diff options
Diffstat (limited to 'lldb/source/Core/ValueObjectVariable.cpp')
-rw-r--r-- | lldb/source/Core/ValueObjectVariable.cpp | 674 |
1 files changed, 304 insertions, 370 deletions
diff --git a/lldb/source/Core/ValueObjectVariable.cpp b/lldb/source/Core/ValueObjectVariable.cpp index a29d858d169..f0695d85ac2 100644 --- a/lldb/source/Core/ValueObjectVariable.cpp +++ b/lldb/source/Core/ValueObjectVariable.cpp @@ -7,7 +7,6 @@ // //===----------------------------------------------------------------------===// - #include "lldb/Core/ValueObjectVariable.h" // C Includes @@ -16,8 +15,8 @@ // Project includes #include "lldb/Core/Module.h" #include "lldb/Core/RegisterValue.h" -#include "lldb/Core/ValueObjectList.h" #include "lldb/Core/Value.h" +#include "lldb/Core/ValueObjectList.h" #include "lldb/Symbol/Function.h" #include "lldb/Symbol/ObjectFile.h" @@ -32,422 +31,357 @@ #include "lldb/Target/Target.h" #include "lldb/Target/Thread.h" - using namespace lldb_private; lldb::ValueObjectSP -ValueObjectVariable::Create (ExecutionContextScope *exe_scope, const lldb::VariableSP &var_sp) -{ - return (new ValueObjectVariable (exe_scope, var_sp))->GetSP(); +ValueObjectVariable::Create(ExecutionContextScope *exe_scope, + const lldb::VariableSP &var_sp) { + return (new ValueObjectVariable(exe_scope, var_sp))->GetSP(); } -ValueObjectVariable::ValueObjectVariable (ExecutionContextScope *exe_scope, const lldb::VariableSP &var_sp) : - ValueObject(exe_scope), - m_variable_sp(var_sp) -{ - // Do not attempt to construct one of these objects with no variable! - assert (m_variable_sp.get() != NULL); - m_name = var_sp->GetName(); +ValueObjectVariable::ValueObjectVariable(ExecutionContextScope *exe_scope, + const lldb::VariableSP &var_sp) + : ValueObject(exe_scope), m_variable_sp(var_sp) { + // Do not attempt to construct one of these objects with no variable! + assert(m_variable_sp.get() != NULL); + m_name = var_sp->GetName(); } -ValueObjectVariable::~ValueObjectVariable() -{ -} +ValueObjectVariable::~ValueObjectVariable() {} -CompilerType -ValueObjectVariable::GetCompilerTypeImpl () -{ - Type *var_type = m_variable_sp->GetType(); - if (var_type) - return var_type->GetForwardCompilerType (); - return CompilerType(); +CompilerType ValueObjectVariable::GetCompilerTypeImpl() { + Type *var_type = m_variable_sp->GetType(); + if (var_type) + return var_type->GetForwardCompilerType(); + return CompilerType(); } -ConstString -ValueObjectVariable::GetTypeName() -{ - Type * var_type = m_variable_sp->GetType(); - if (var_type) - return var_type->GetName(); - return ConstString(); +ConstString ValueObjectVariable::GetTypeName() { + Type *var_type = m_variable_sp->GetType(); + if (var_type) + return var_type->GetName(); + return ConstString(); } -ConstString -ValueObjectVariable::GetDisplayTypeName() -{ - Type * var_type = m_variable_sp->GetType(); - if (var_type) - return var_type->GetForwardCompilerType ().GetDisplayTypeName(); - return ConstString(); +ConstString ValueObjectVariable::GetDisplayTypeName() { + Type *var_type = m_variable_sp->GetType(); + if (var_type) + return var_type->GetForwardCompilerType().GetDisplayTypeName(); + return ConstString(); } -ConstString -ValueObjectVariable::GetQualifiedTypeName() -{ - Type * var_type = m_variable_sp->GetType(); - if (var_type) - return var_type->GetQualifiedName(); - return ConstString(); +ConstString ValueObjectVariable::GetQualifiedTypeName() { + Type *var_type = m_variable_sp->GetType(); + if (var_type) + return var_type->GetQualifiedName(); + return ConstString(); } -size_t -ValueObjectVariable::CalculateNumChildren(uint32_t max) -{ - CompilerType type(GetCompilerType()); - - if (!type.IsValid()) - return 0; - - const bool omit_empty_base_classes = true; - auto child_count = type.GetNumChildren(omit_empty_base_classes); - return child_count <= max ? child_count : max; +size_t ValueObjectVariable::CalculateNumChildren(uint32_t max) { + CompilerType type(GetCompilerType()); + + if (!type.IsValid()) + return 0; + + const bool omit_empty_base_classes = true; + auto child_count = type.GetNumChildren(omit_empty_base_classes); + return child_count <= max ? child_count : max; } -uint64_t -ValueObjectVariable::GetByteSize() -{ - ExecutionContext exe_ctx(GetExecutionContextRef()); - - CompilerType type(GetCompilerType()); - - if (!type.IsValid()) - return 0; - - return type.GetByteSize(exe_ctx.GetBestExecutionContextScope()); +uint64_t ValueObjectVariable::GetByteSize() { + ExecutionContext exe_ctx(GetExecutionContextRef()); + + CompilerType type(GetCompilerType()); + + if (!type.IsValid()) + return 0; + + return type.GetByteSize(exe_ctx.GetBestExecutionContextScope()); } -lldb::ValueType -ValueObjectVariable::GetValueType() const -{ - if (m_variable_sp) - return m_variable_sp->GetScope(); - return lldb::eValueTypeInvalid; +lldb::ValueType ValueObjectVariable::GetValueType() const { + if (m_variable_sp) + return m_variable_sp->GetScope(); + return lldb::eValueTypeInvalid; } -bool -ValueObjectVariable::UpdateValue () -{ - SetValueIsValid (false); - m_error.Clear(); - - Variable *variable = m_variable_sp.get(); - DWARFExpression &expr = variable->LocationExpression(); - - if (variable->GetLocationIsConstantValueData()) - { - // expr doesn't contain DWARF bytes, it contains the constant variable - // value bytes themselves... - if (expr.GetExpressionData(m_data)) - m_value.SetContext(Value::eContextTypeVariable, variable); - else - m_error.SetErrorString ("empty constant data"); - // constant bytes can't be edited - sorry - m_resolved_value.SetContext(Value::eContextTypeInvalid, NULL); - } - else - { - lldb::addr_t loclist_base_load_addr = LLDB_INVALID_ADDRESS; - ExecutionContext exe_ctx (GetExecutionContextRef()); - - Target *target = exe_ctx.GetTargetPtr(); - if (target) - { - m_data.SetByteOrder(target->GetArchitecture().GetByteOrder()); - m_data.SetAddressByteSize(target->GetArchitecture().GetAddressByteSize()); - } +bool ValueObjectVariable::UpdateValue() { + SetValueIsValid(false); + m_error.Clear(); - if (expr.IsLocationList()) - { - SymbolContext sc; - variable->CalculateSymbolContext (&sc); - if (sc.function) - loclist_base_load_addr = sc.function->GetAddressRange().GetBaseAddress().GetLoadAddress (target); - } - Value old_value(m_value); - if (expr.Evaluate (&exe_ctx, - nullptr, - nullptr, - nullptr, - loclist_base_load_addr, - nullptr, - nullptr, - m_value, - &m_error)) - { - m_resolved_value = m_value; - m_value.SetContext(Value::eContextTypeVariable, variable); - - CompilerType compiler_type = GetCompilerType(); - if (compiler_type.IsValid()) - m_value.SetCompilerType(compiler_type); - - Value::ValueType value_type = m_value.GetValueType(); - - Process *process = exe_ctx.GetProcessPtr(); - const bool process_is_alive = process && process->IsAlive(); - const uint32_t type_info = compiler_type.GetTypeInfo(); - const bool is_pointer_or_ref = (type_info & (lldb::eTypeIsPointer | lldb::eTypeIsReference)) != 0; - - switch (value_type) - { - case Value::eValueTypeFileAddress: - // If this type is a pointer, then its children will be considered load addresses - // if the pointer or reference is dereferenced, but only if the process is alive. - // - // There could be global variables like in the following code: - // struct LinkedListNode { Foo* foo; LinkedListNode* next; }; - // Foo g_foo1; - // Foo g_foo2; - // LinkedListNode g_second_node = { &g_foo2, NULL }; - // LinkedListNode g_first_node = { &g_foo1, &g_second_node }; - // - // When we aren't running, we should be able to look at these variables using - // the "target variable" command. Children of the "g_first_node" always will - // be of the same address type as the parent. But children of the "next" member of - // LinkedListNode will become load addresses if we have a live process, or remain - // what a file address if it what a file address. - if (process_is_alive && is_pointer_or_ref) - SetAddressTypeOfChildren(eAddressTypeLoad); - else - SetAddressTypeOfChildren(eAddressTypeFile); - break; - case Value::eValueTypeHostAddress: - // Same as above for load addresses, except children of pointer or refs are always - // load addresses. Host addresses are used to store freeze dried variables. If this - // type is a struct, the entire struct contents will be copied into the heap of the - // LLDB process, but we do not currrently follow any pointers. - if (is_pointer_or_ref) - SetAddressTypeOfChildren(eAddressTypeLoad); - else - SetAddressTypeOfChildren(eAddressTypeHost); - break; - case Value::eValueTypeLoadAddress: - case Value::eValueTypeScalar: - case Value::eValueTypeVector: - SetAddressTypeOfChildren(eAddressTypeLoad); - break; - } + Variable *variable = m_variable_sp.get(); + DWARFExpression &expr = variable->LocationExpression(); - switch (value_type) - { - case Value::eValueTypeVector: - // fall through - case Value::eValueTypeScalar: - // The variable value is in the Scalar value inside the m_value. - // We can point our m_data right to it. - m_error = m_value.GetValueAsData (&exe_ctx, m_data, 0, GetModule().get()); - break; - - case Value::eValueTypeFileAddress: - case Value::eValueTypeLoadAddress: - case Value::eValueTypeHostAddress: - // The DWARF expression result was an address in the inferior - // process. If this variable is an aggregate type, we just need - // the address as the main value as all child variable objects - // will rely upon this location and add an offset and then read - // their own values as needed. If this variable is a simple - // type, we read all data for it into m_data. - // Make sure this type has a value before we try and read it - - // If we have a file address, convert it to a load address if we can. - if (value_type == Value::eValueTypeFileAddress && process_is_alive) - { - lldb::addr_t file_addr = m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS); - if (file_addr != LLDB_INVALID_ADDRESS) - { - SymbolContext var_sc; - variable->CalculateSymbolContext(&var_sc); - if (var_sc.module_sp) - { - ObjectFile *objfile = var_sc.module_sp->GetObjectFile(); - if (objfile) - { - Address so_addr(file_addr, objfile->GetSectionList()); - lldb::addr_t load_addr = so_addr.GetLoadAddress (target); - if (load_addr != LLDB_INVALID_ADDRESS) - { - m_value.SetValueType(Value::eValueTypeLoadAddress); - m_value.GetScalar() = load_addr; - } - } - } - } - } + if (variable->GetLocationIsConstantValueData()) { + // expr doesn't contain DWARF bytes, it contains the constant variable + // value bytes themselves... + if (expr.GetExpressionData(m_data)) + m_value.SetContext(Value::eContextTypeVariable, variable); + else + m_error.SetErrorString("empty constant data"); + // constant bytes can't be edited - sorry + m_resolved_value.SetContext(Value::eContextTypeInvalid, NULL); + } else { + lldb::addr_t loclist_base_load_addr = LLDB_INVALID_ADDRESS; + ExecutionContext exe_ctx(GetExecutionContextRef()); - if (!CanProvideValue()) - { - // this value object represents an aggregate type whose - // children have values, but this object does not. So we - // say we are changed if our location has changed. - SetValueDidChange (value_type != old_value.GetValueType() || m_value.GetScalar() != old_value.GetScalar()); - } - else - { - // Copy the Value and set the context to use our Variable - // so it can extract read its value into m_data appropriately - Value value(m_value); - value.SetContext(Value::eContextTypeVariable, variable); - m_error = value.GetValueAsData(&exe_ctx, m_data, 0, GetModule().get()); - - SetValueDidChange (value_type != old_value.GetValueType() || m_value.GetScalar() != old_value.GetScalar()); + Target *target = exe_ctx.GetTargetPtr(); + if (target) { + m_data.SetByteOrder(target->GetArchitecture().GetByteOrder()); + m_data.SetAddressByteSize(target->GetArchitecture().GetAddressByteSize()); + } + + if (expr.IsLocationList()) { + SymbolContext sc; + variable->CalculateSymbolContext(&sc); + if (sc.function) + loclist_base_load_addr = + sc.function->GetAddressRange().GetBaseAddress().GetLoadAddress( + target); + } + Value old_value(m_value); + if (expr.Evaluate(&exe_ctx, nullptr, nullptr, nullptr, + loclist_base_load_addr, nullptr, nullptr, m_value, + &m_error)) { + m_resolved_value = m_value; + m_value.SetContext(Value::eContextTypeVariable, variable); + + CompilerType compiler_type = GetCompilerType(); + if (compiler_type.IsValid()) + m_value.SetCompilerType(compiler_type); + + Value::ValueType value_type = m_value.GetValueType(); + + Process *process = exe_ctx.GetProcessPtr(); + const bool process_is_alive = process && process->IsAlive(); + const uint32_t type_info = compiler_type.GetTypeInfo(); + const bool is_pointer_or_ref = + (type_info & (lldb::eTypeIsPointer | lldb::eTypeIsReference)) != 0; + + switch (value_type) { + case Value::eValueTypeFileAddress: + // If this type is a pointer, then its children will be considered load + // addresses + // if the pointer or reference is dereferenced, but only if the process + // is alive. + // + // There could be global variables like in the following code: + // struct LinkedListNode { Foo* foo; LinkedListNode* next; }; + // Foo g_foo1; + // Foo g_foo2; + // LinkedListNode g_second_node = { &g_foo2, NULL }; + // LinkedListNode g_first_node = { &g_foo1, &g_second_node }; + // + // When we aren't running, we should be able to look at these variables + // using + // the "target variable" command. Children of the "g_first_node" always + // will + // be of the same address type as the parent. But children of the "next" + // member of + // LinkedListNode will become load addresses if we have a live process, + // or remain + // what a file address if it what a file address. + if (process_is_alive && is_pointer_or_ref) + SetAddressTypeOfChildren(eAddressTypeLoad); + else + SetAddressTypeOfChildren(eAddressTypeFile); + break; + case Value::eValueTypeHostAddress: + // Same as above for load addresses, except children of pointer or refs + // are always + // load addresses. Host addresses are used to store freeze dried + // variables. If this + // type is a struct, the entire struct contents will be copied into the + // heap of the + // LLDB process, but we do not currrently follow any pointers. + if (is_pointer_or_ref) + SetAddressTypeOfChildren(eAddressTypeLoad); + else + SetAddressTypeOfChildren(eAddressTypeHost); + break; + case Value::eValueTypeLoadAddress: + case Value::eValueTypeScalar: + case Value::eValueTypeVector: + SetAddressTypeOfChildren(eAddressTypeLoad); + break; + } + + switch (value_type) { + case Value::eValueTypeVector: + // fall through + case Value::eValueTypeScalar: + // The variable value is in the Scalar value inside the m_value. + // We can point our m_data right to it. + m_error = + m_value.GetValueAsData(&exe_ctx, m_data, 0, GetModule().get()); + break; + + case Value::eValueTypeFileAddress: + case Value::eValueTypeLoadAddress: + case Value::eValueTypeHostAddress: + // The DWARF expression result was an address in the inferior + // process. If this variable is an aggregate type, we just need + // the address as the main value as all child variable objects + // will rely upon this location and add an offset and then read + // their own values as needed. If this variable is a simple + // type, we read all data for it into m_data. + // Make sure this type has a value before we try and read it + + // If we have a file address, convert it to a load address if we can. + if (value_type == Value::eValueTypeFileAddress && process_is_alive) { + lldb::addr_t file_addr = + m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS); + if (file_addr != LLDB_INVALID_ADDRESS) { + SymbolContext var_sc; + variable->CalculateSymbolContext(&var_sc); + if (var_sc.module_sp) { + ObjectFile *objfile = var_sc.module_sp->GetObjectFile(); + if (objfile) { + Address so_addr(file_addr, objfile->GetSectionList()); + lldb::addr_t load_addr = so_addr.GetLoadAddress(target); + if (load_addr != LLDB_INVALID_ADDRESS) { + m_value.SetValueType(Value::eValueTypeLoadAddress); + m_value.GetScalar() = load_addr; } - break; + } } - - SetValueIsValid (m_error.Success()); + } } - else - { - // could not find location, won't allow editing - m_resolved_value.SetContext(Value::eContextTypeInvalid, NULL); + + if (!CanProvideValue()) { + // this value object represents an aggregate type whose + // children have values, but this object does not. So we + // say we are changed if our location has changed. + SetValueDidChange(value_type != old_value.GetValueType() || + m_value.GetScalar() != old_value.GetScalar()); + } else { + // Copy the Value and set the context to use our Variable + // so it can extract read its value into m_data appropriately + Value value(m_value); + value.SetContext(Value::eContextTypeVariable, variable); + m_error = + value.GetValueAsData(&exe_ctx, m_data, 0, GetModule().get()); + + SetValueDidChange(value_type != old_value.GetValueType() || + m_value.GetScalar() != old_value.GetScalar()); } + break; + } + + SetValueIsValid(m_error.Success()); + } else { + // could not find location, won't allow editing + m_resolved_value.SetContext(Value::eContextTypeInvalid, NULL); } - return m_error.Success(); + } + return m_error.Success(); } - - -bool -ValueObjectVariable::IsInScope () -{ - const ExecutionContextRef &exe_ctx_ref = GetExecutionContextRef(); - if (exe_ctx_ref.HasFrameRef()) - { - ExecutionContext exe_ctx (exe_ctx_ref); - StackFrame *frame = exe_ctx.GetFramePtr(); - if (frame) - { - return m_variable_sp->IsInScope (frame); - } - else - { - // This ValueObject had a frame at one time, but now we - // can't locate it, so return false since we probably aren't - // in scope. - return false; - } +bool ValueObjectVariable::IsInScope() { + const ExecutionContextRef &exe_ctx_ref = GetExecutionContextRef(); + if (exe_ctx_ref.HasFrameRef()) { + ExecutionContext exe_ctx(exe_ctx_ref); + StackFrame *frame = exe_ctx.GetFramePtr(); + if (frame) { + return m_variable_sp->IsInScope(frame); + } else { + // This ValueObject had a frame at one time, but now we + // can't locate it, so return false since we probably aren't + // in scope. + return false; } - // We have a variable that wasn't tied to a frame, which - // means it is a global and is always in scope. - return true; - + } + // We have a variable that wasn't tied to a frame, which + // means it is a global and is always in scope. + return true; } -lldb::ModuleSP -ValueObjectVariable::GetModule() -{ - if (m_variable_sp) - { - SymbolContextScope *sc_scope = m_variable_sp->GetSymbolContextScope(); - if (sc_scope) - { - return sc_scope->CalculateSymbolContextModule(); - } +lldb::ModuleSP ValueObjectVariable::GetModule() { + if (m_variable_sp) { + SymbolContextScope *sc_scope = m_variable_sp->GetSymbolContextScope(); + if (sc_scope) { + return sc_scope->CalculateSymbolContextModule(); } - return lldb::ModuleSP(); + } + return lldb::ModuleSP(); } -SymbolContextScope * -ValueObjectVariable::GetSymbolContextScope() -{ - if (m_variable_sp) - return m_variable_sp->GetSymbolContextScope(); - return NULL; +SymbolContextScope *ValueObjectVariable::GetSymbolContextScope() { + if (m_variable_sp) + return m_variable_sp->GetSymbolContextScope(); + return NULL; } -bool -ValueObjectVariable::GetDeclaration (Declaration &decl) -{ - if (m_variable_sp) - { - decl = m_variable_sp->GetDeclaration(); - return true; - } - return false; +bool ValueObjectVariable::GetDeclaration(Declaration &decl) { + if (m_variable_sp) { + decl = m_variable_sp->GetDeclaration(); + return true; + } + return false; } -const char * -ValueObjectVariable::GetLocationAsCString () -{ - if (m_resolved_value.GetContextType() == Value::eContextTypeRegisterInfo) - return GetLocationAsCStringImpl(m_resolved_value, - m_data); - else - return ValueObject::GetLocationAsCString(); +const char *ValueObjectVariable::GetLocationAsCString() { + if (m_resolved_value.GetContextType() == Value::eContextTypeRegisterInfo) + return GetLocationAsCStringImpl(m_resolved_value, m_data); + else + return ValueObject::GetLocationAsCString(); } -bool -ValueObjectVariable::SetValueFromCString (const char *value_str, Error& error) -{ - if (!UpdateValueIfNeeded()) - { - error.SetErrorString("unable to update value before writing"); - return false; +bool ValueObjectVariable::SetValueFromCString(const char *value_str, + Error &error) { + if (!UpdateValueIfNeeded()) { + error.SetErrorString("unable to update value before writing"); + return false; + } + + if (m_resolved_value.GetContextType() == Value::eContextTypeRegisterInfo) { + RegisterInfo *reg_info = m_resolved_value.GetRegisterInfo(); + ExecutionContext exe_ctx(GetExecutionContextRef()); + RegisterContext *reg_ctx = exe_ctx.GetRegisterContext(); + RegisterValue reg_value; + if (!reg_info || !reg_ctx) { + error.SetErrorString("unable to retrieve register info"); + return false; } - - if (m_resolved_value.GetContextType() == Value::eContextTypeRegisterInfo) - { - RegisterInfo *reg_info = m_resolved_value.GetRegisterInfo(); - ExecutionContext exe_ctx(GetExecutionContextRef()); - RegisterContext *reg_ctx = exe_ctx.GetRegisterContext(); - RegisterValue reg_value; - if (!reg_info || !reg_ctx) - { - error.SetErrorString("unable to retrieve register info"); - return false; - } - error = reg_value.SetValueFromCString(reg_info, value_str); - if (error.Fail()) - return false; - if (reg_ctx->WriteRegister (reg_info, reg_value)) - { - SetNeedsUpdate(); - return true; - } - else - { - error.SetErrorString("unable to write back to register"); - return false; - } + error = reg_value.SetValueFromCString(reg_info, value_str); + if (error.Fail()) + return false; + if (reg_ctx->WriteRegister(reg_info, reg_value)) { + SetNeedsUpdate(); + return true; + } else { + error.SetErrorString("unable to write back to register"); + return false; } - else - return ValueObject::SetValueFromCString(value_str, error); + } else + return ValueObject::SetValueFromCString(value_str, error); } -bool -ValueObjectVariable::SetData (DataExtractor &data, Error &error) -{ - if (!UpdateValueIfNeeded()) - { - error.SetErrorString("unable to update value before writing"); - return false; +bool ValueObjectVariable::SetData(DataExtractor &data, Error &error) { + if (!UpdateValueIfNeeded()) { + error.SetErrorString("unable to update value before writing"); + return false; + } + + if (m_resolved_value.GetContextType() == Value::eContextTypeRegisterInfo) { + RegisterInfo *reg_info = m_resolved_value.GetRegisterInfo(); + ExecutionContext exe_ctx(GetExecutionContextRef()); + RegisterContext *reg_ctx = exe_ctx.GetRegisterContext(); + RegisterValue reg_value; + if (!reg_info || !reg_ctx) { + error.SetErrorString("unable to retrieve register info"); + return false; } - - if (m_resolved_value.GetContextType() == Value::eContextTypeRegisterInfo) - { - RegisterInfo *reg_info = m_resolved_value.GetRegisterInfo(); - ExecutionContext exe_ctx(GetExecutionContextRef()); - RegisterContext *reg_ctx = exe_ctx.GetRegisterContext(); - RegisterValue reg_value; - if (!reg_info || !reg_ctx) - { - error.SetErrorString("unable to retrieve register info"); - return false; - } - error = reg_value.SetValueFromData(reg_info, data, 0, true); - if (error.Fail()) - return false; - if (reg_ctx->WriteRegister (reg_info, reg_value)) - { - SetNeedsUpdate(); - return true; - } - else - { - error.SetErrorString("unable to write back to register"); - return false; - } + error = reg_value.SetValueFromData(reg_info, data, 0, true); + if (error.Fail()) + return false; + if (reg_ctx->WriteRegister(reg_info, reg_value)) { + SetNeedsUpdate(); + return true; + } else { + error.SetErrorString("unable to write back to register"); + return false; } - else - return ValueObject::SetData(data, error); + } else + return ValueObject::SetData(data, error); } |