PageRenderTime 56ms CodeModel.GetById 34ms app.highlight 19ms RepoModel.GetById 1ms app.codeStats 0ms

/source/Core/ValueObjectVariable.cpp

https://gitlab.com/jorjpimm/lldb
C++ | 413 lines | 328 code | 47 blank | 38 comment | 56 complexity | a2dea6e48c128bd2171cc50d411c49ac MD5 | raw file
  1//===-- ValueObjectVariable.cpp ---------------------------------*- C++ -*-===//
  2//
  3//                     The LLVM Compiler Infrastructure
  4//
  5// This file is distributed under the University of Illinois Open Source
  6// License. See LICENSE.TXT for details.
  7//
  8//===----------------------------------------------------------------------===//
  9
 10
 11#include "lldb/Core/ValueObjectVariable.h"
 12
 13// C Includes
 14// C++ Includes
 15// Other libraries and framework includes
 16// Project includes
 17#include "lldb/Core/Module.h"
 18#include "lldb/Core/RegisterValue.h"
 19#include "lldb/Core/ValueObjectList.h"
 20#include "lldb/Core/Value.h"
 21
 22#include "lldb/Symbol/Function.h"
 23#include "lldb/Symbol/ObjectFile.h"
 24#include "lldb/Symbol/SymbolContext.h"
 25#include "lldb/Symbol/SymbolContextScope.h"
 26#include "lldb/Symbol/Type.h"
 27#include "lldb/Symbol/Variable.h"
 28
 29#include "lldb/Target/ExecutionContext.h"
 30#include "lldb/Target/Process.h"
 31#include "lldb/Target/RegisterContext.h"
 32#include "lldb/Target/Target.h"
 33#include "lldb/Target/Thread.h"
 34
 35
 36using namespace lldb_private;
 37
 38lldb::ValueObjectSP
 39ValueObjectVariable::Create (ExecutionContextScope *exe_scope, const lldb::VariableSP &var_sp)
 40{
 41    return (new ValueObjectVariable (exe_scope, var_sp))->GetSP();
 42}
 43
 44ValueObjectVariable::ValueObjectVariable (ExecutionContextScope *exe_scope, const lldb::VariableSP &var_sp) :
 45    ValueObject(exe_scope),
 46    m_variable_sp(var_sp)
 47{
 48    // Do not attempt to construct one of these objects with no variable!
 49    assert (m_variable_sp.get() != NULL);
 50    m_name = var_sp->GetName();
 51}
 52
 53ValueObjectVariable::~ValueObjectVariable()
 54{
 55}
 56
 57ClangASTType
 58ValueObjectVariable::GetClangTypeImpl ()
 59{
 60    Type *var_type = m_variable_sp->GetType();
 61    if (var_type)
 62        return var_type->GetClangForwardType();
 63    return ClangASTType();
 64}
 65
 66ConstString
 67ValueObjectVariable::GetTypeName()
 68{
 69    Type * var_type = m_variable_sp->GetType();
 70    if (var_type)
 71        return var_type->GetName();
 72    return ConstString();
 73}
 74
 75ConstString
 76ValueObjectVariable::GetDisplayTypeName()
 77{
 78    Type * var_type = m_variable_sp->GetType();
 79    if (var_type)
 80        return var_type->GetClangForwardType().GetDisplayTypeName();
 81    return ConstString();
 82}
 83
 84ConstString
 85ValueObjectVariable::GetQualifiedTypeName()
 86{
 87    Type * var_type = m_variable_sp->GetType();
 88    if (var_type)
 89        return var_type->GetQualifiedName();
 90    return ConstString();
 91}
 92
 93size_t
 94ValueObjectVariable::CalculateNumChildren()
 95{    
 96    ClangASTType type(GetClangType());
 97    
 98    if (!type.IsValid())
 99        return 0;
100    
101    const bool omit_empty_base_classes = true;
102    return type.GetNumChildren(omit_empty_base_classes);
103}
104
105uint64_t
106ValueObjectVariable::GetByteSize()
107{
108    ClangASTType type(GetClangType());
109    
110    if (!type.IsValid())
111        return 0;
112    
113    return type.GetByteSize();
114}
115
116lldb::ValueType
117ValueObjectVariable::GetValueType() const
118{
119    if (m_variable_sp)
120        return m_variable_sp->GetScope();
121    return lldb::eValueTypeInvalid;
122}
123
124bool
125ValueObjectVariable::UpdateValue ()
126{
127    SetValueIsValid (false);
128    m_error.Clear();
129
130    Variable *variable = m_variable_sp.get();
131    DWARFExpression &expr = variable->LocationExpression();
132    
133    if (variable->GetLocationIsConstantValueData())
134    {
135        // expr doesn't contain DWARF bytes, it contains the constant variable
136        // value bytes themselves...
137        if (expr.GetExpressionData(m_data))
138            m_value.SetContext(Value::eContextTypeVariable, variable);
139        else
140            m_error.SetErrorString ("empty constant data");
141        // constant bytes can't be edited - sorry
142        m_resolved_value.SetContext(Value::eContextTypeInvalid, NULL);
143    }
144    else
145    {
146        lldb::addr_t loclist_base_load_addr = LLDB_INVALID_ADDRESS;
147        ExecutionContext exe_ctx (GetExecutionContextRef());
148        
149        Target *target = exe_ctx.GetTargetPtr();
150        if (target)
151        {
152            m_data.SetByteOrder(target->GetArchitecture().GetByteOrder());
153            m_data.SetAddressByteSize(target->GetArchitecture().GetAddressByteSize());
154        }
155
156        if (expr.IsLocationList())
157        {
158            SymbolContext sc;
159            variable->CalculateSymbolContext (&sc);
160            if (sc.function)
161                loclist_base_load_addr = sc.function->GetAddressRange().GetBaseAddress().GetLoadAddress (target);
162        }
163        Value old_value(m_value);
164        if (expr.Evaluate (&exe_ctx, NULL, NULL, NULL, loclist_base_load_addr, NULL, m_value, &m_error))
165        {
166            m_resolved_value = m_value;
167            m_value.SetContext(Value::eContextTypeVariable, variable);
168            
169            ClangASTType clang_type = GetClangType();
170            if (clang_type.IsValid())
171                m_value.SetClangType(clang_type);
172
173            Value::ValueType value_type = m_value.GetValueType();
174            
175            switch (value_type)
176            {
177                case Value::eValueTypeFileAddress:
178                    SetAddressTypeOfChildren(eAddressTypeFile);
179                    break;
180                case Value::eValueTypeHostAddress:
181                    SetAddressTypeOfChildren(eAddressTypeHost);
182                    break;
183                case Value::eValueTypeLoadAddress:
184                case Value::eValueTypeScalar:
185                case Value::eValueTypeVector:
186                    SetAddressTypeOfChildren(eAddressTypeLoad);
187                    break;
188            }
189
190            switch (value_type)
191            {
192            case Value::eValueTypeVector:
193                    // fall through
194            case Value::eValueTypeScalar:
195                // The variable value is in the Scalar value inside the m_value.
196                // We can point our m_data right to it.
197                m_error = m_value.GetValueAsData (&exe_ctx, m_data, 0, GetModule().get());
198                break;
199
200            case Value::eValueTypeFileAddress:
201            case Value::eValueTypeLoadAddress:
202            case Value::eValueTypeHostAddress:
203                // The DWARF expression result was an address in the inferior
204                // process. If this variable is an aggregate type, we just need
205                // the address as the main value as all child variable objects
206                // will rely upon this location and add an offset and then read
207                // their own values as needed. If this variable is a simple
208                // type, we read all data for it into m_data.
209                // Make sure this type has a value before we try and read it
210
211                // If we have a file address, convert it to a load address if we can.
212                Process *process = exe_ctx.GetProcessPtr();
213                if (value_type == Value::eValueTypeFileAddress && process && process->IsAlive())
214                {
215                    lldb::addr_t file_addr = m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS);
216                    if (file_addr != LLDB_INVALID_ADDRESS)
217                    {
218                        SymbolContext var_sc;
219                        variable->CalculateSymbolContext(&var_sc);
220                        if (var_sc.module_sp)
221                        {
222                            ObjectFile *objfile = var_sc.module_sp->GetObjectFile();
223                            if (objfile)
224                            {
225                                Address so_addr(file_addr, objfile->GetSectionList());
226                                lldb::addr_t load_addr = so_addr.GetLoadAddress (target);
227                                if (load_addr != LLDB_INVALID_ADDRESS)
228                                {
229                                    m_value.SetValueType(Value::eValueTypeLoadAddress);
230                                    m_value.GetScalar() = load_addr;
231                                }
232                            }
233                        }
234                    }
235                }
236
237                if (!CanProvideValue())
238                {
239                    // this value object represents an aggregate type whose
240                    // children have values, but this object does not. So we
241                    // say we are changed if our location has changed.
242                    SetValueDidChange (value_type != old_value.GetValueType() || m_value.GetScalar() != old_value.GetScalar());
243                }
244                else
245                {
246                    // Copy the Value and set the context to use our Variable
247                    // so it can extract read its value into m_data appropriately
248                    Value value(m_value);
249                    value.SetContext(Value::eContextTypeVariable, variable);
250                    m_error = value.GetValueAsData(&exe_ctx, m_data, 0, GetModule().get());
251                    
252                    SetValueDidChange (value_type != old_value.GetValueType() || m_value.GetScalar() != old_value.GetScalar());
253                }
254                break;
255            }
256
257            SetValueIsValid (m_error.Success());
258        }
259        else
260        {
261            // could not find location, won't allow editing
262            m_resolved_value.SetContext(Value::eContextTypeInvalid, NULL);
263        }
264    }
265    return m_error.Success();
266}
267
268
269
270bool
271ValueObjectVariable::IsInScope ()
272{
273    const ExecutionContextRef &exe_ctx_ref = GetExecutionContextRef();
274    if (exe_ctx_ref.HasFrameRef())
275    {
276        ExecutionContext exe_ctx (exe_ctx_ref);
277        StackFrame *frame = exe_ctx.GetFramePtr();
278        if (frame)
279        {
280            return m_variable_sp->IsInScope (frame);
281        }
282        else
283        {
284            // This ValueObject had a frame at one time, but now we
285            // can't locate it, so return false since we probably aren't
286            // in scope.
287            return false;
288        }
289    }
290    // We have a variable that wasn't tied to a frame, which
291    // means it is a global and is always in scope.
292    return true;
293         
294}
295
296lldb::ModuleSP
297ValueObjectVariable::GetModule()
298{
299    if (m_variable_sp)
300    {
301        SymbolContextScope *sc_scope = m_variable_sp->GetSymbolContextScope();
302        if (sc_scope)
303        {
304            return sc_scope->CalculateSymbolContextModule();
305        }
306    }
307    return lldb::ModuleSP();
308}
309
310SymbolContextScope *
311ValueObjectVariable::GetSymbolContextScope()
312{
313    if (m_variable_sp)
314        return m_variable_sp->GetSymbolContextScope();
315    return NULL;
316}
317
318bool
319ValueObjectVariable::GetDeclaration (Declaration &decl)
320{
321    if (m_variable_sp)
322    {
323        decl = m_variable_sp->GetDeclaration();
324        return true;
325    }
326    return false;
327}
328
329const char *
330ValueObjectVariable::GetLocationAsCString ()
331{
332    if (m_resolved_value.GetContextType() == Value::eContextTypeRegisterInfo)
333        return GetLocationAsCStringImpl(m_resolved_value,
334                                        m_data);
335    else
336        return ValueObject::GetLocationAsCString();
337}
338
339bool
340ValueObjectVariable::SetValueFromCString (const char *value_str, Error& error)
341{
342    if (!UpdateValueIfNeeded())
343    {
344        error.SetErrorString("unable to update value before writing");
345        return false;
346    }
347    
348    if (m_resolved_value.GetContextType() == Value::eContextTypeRegisterInfo)
349    {
350        RegisterInfo *reg_info = m_resolved_value.GetRegisterInfo();
351        ExecutionContext exe_ctx(GetExecutionContextRef());
352        RegisterContext *reg_ctx = exe_ctx.GetRegisterContext();
353        RegisterValue reg_value;
354        if (!reg_info || !reg_ctx)
355        {
356            error.SetErrorString("unable to retrieve register info");
357            return false;
358        }
359        error = reg_value.SetValueFromCString(reg_info, value_str);
360        if (error.Fail())
361            return false;
362        if (reg_ctx->WriteRegister (reg_info, reg_value))
363        {
364            SetNeedsUpdate();
365            return true;
366        }
367        else
368        {
369            error.SetErrorString("unable to write back to register");
370            return false;
371        }
372    }
373    else
374        return ValueObject::SetValueFromCString(value_str, error);
375}
376
377bool
378ValueObjectVariable::SetData (DataExtractor &data, Error &error)
379{
380    if (!UpdateValueIfNeeded())
381    {
382        error.SetErrorString("unable to update value before writing");
383        return false;
384    }
385    
386    if (m_resolved_value.GetContextType() == Value::eContextTypeRegisterInfo)
387    {
388        RegisterInfo *reg_info = m_resolved_value.GetRegisterInfo();
389        ExecutionContext exe_ctx(GetExecutionContextRef());
390        RegisterContext *reg_ctx = exe_ctx.GetRegisterContext();
391        RegisterValue reg_value;
392        if (!reg_info || !reg_ctx)
393        {
394            error.SetErrorString("unable to retrieve register info");
395            return false;
396        }
397        error = reg_value.SetValueFromData(reg_info, data, 0, true);
398        if (error.Fail())
399            return false;
400        if (reg_ctx->WriteRegister (reg_info, reg_value))
401        {
402            SetNeedsUpdate();
403            return true;
404        }
405        else
406        {
407            error.SetErrorString("unable to write back to register");
408            return false;
409        }
410    }
411    else
412        return ValueObject::SetData(data, error);
413}