diff options
author | Greg Clayton <gclayton@apple.com> | 2011-06-29 22:09:02 +0000 |
---|---|---|
committer | Greg Clayton <gclayton@apple.com> | 2011-06-29 22:09:02 +0000 |
commit | dea8cb4fe314fb772706e033e50c3258210007f5 (patch) | |
tree | f48ad3ccc7229cc40cccc815e20e1b64fd8c01ea /lldb/source/Core | |
parent | 1c2d4f2feaf680df14b0a6a2f23e2d96589ac598 (diff) | |
download | bcm5719-llvm-dea8cb4fe314fb772706e033e50c3258210007f5.tar.gz bcm5719-llvm-dea8cb4fe314fb772706e033e50c3258210007f5.zip |
Added support for finding and global variables in the SBTarget and SBModule
level in the public API.
Also modified the ValueObject values to be able to display global variables
without having a valid running process. The globals will read themselves from
the object file section data if there is no process, and from the process if
there is one.
Also fixed an issue where modifications for dynamic types could cause child
values of ValueObjects to not show up if the value was unable to evaluate
itself (children of NULL pointer objects).
llvm-svn: 134102
Diffstat (limited to 'lldb/source/Core')
-rw-r--r-- | lldb/source/Core/Value.cpp | 78 | ||||
-rw-r--r-- | lldb/source/Core/ValueObject.cpp | 190 | ||||
-rw-r--r-- | lldb/source/Core/ValueObjectList.cpp | 10 | ||||
-rw-r--r-- | lldb/source/Core/ValueObjectVariable.cpp | 2 |
4 files changed, 167 insertions, 113 deletions
diff --git a/lldb/source/Core/Value.cpp b/lldb/source/Core/Value.cpp index 2d8ac9147ce..2ba490ebb0a 100644 --- a/lldb/source/Core/Value.cpp +++ b/lldb/source/Core/Value.cpp @@ -516,6 +516,7 @@ Value::GetValueAsData (ExecutionContext *exe_ctx, clang::ASTContext *ast_context Error error; lldb::addr_t address = LLDB_INVALID_ADDRESS; AddressType address_type = eAddressTypeFile; + Address file_so_addr; switch (m_value_type) { default: @@ -541,11 +542,11 @@ Value::GetValueAsData (ExecutionContext *exe_ctx, clang::ASTContext *ast_context case eValueTypeLoadAddress: if (exe_ctx == NULL) { - error.SetErrorString ("can't read memory (no execution context)"); + error.SetErrorString ("can't read load address (no execution context)"); } else if (exe_ctx->process == NULL) { - error.SetErrorString ("can't read memory (invalid process)"); + error.SetErrorString ("can't read load address (invalid process)"); } else { @@ -557,6 +558,15 @@ Value::GetValueAsData (ExecutionContext *exe_ctx, clang::ASTContext *ast_context break; case eValueTypeFileAddress: + if (exe_ctx == NULL) + { + error.SetErrorString ("can't read file address (no execution context)"); + } + else if (exe_ctx->target == NULL) + { + error.SetErrorString ("can't read file address (invalid target)"); + } + else { // The only thing we can currently lock down to a module so that // we can resolve a file address, is a variable. @@ -564,9 +574,10 @@ Value::GetValueAsData (ExecutionContext *exe_ctx, clang::ASTContext *ast_context if (GetVariable()) { - lldb::addr_t file_addr = m_value.ULongLong(LLDB_INVALID_ADDRESS); - if (file_addr != LLDB_INVALID_ADDRESS) + address = m_value.ULongLong(LLDB_INVALID_ADDRESS); + if (address != LLDB_INVALID_ADDRESS) { + bool resolved = false; SymbolContext var_sc; variable->CalculateSymbolContext(&var_sc); if (var_sc.module_sp) @@ -574,31 +585,46 @@ Value::GetValueAsData (ExecutionContext *exe_ctx, clang::ASTContext *ast_context ObjectFile *objfile = var_sc.module_sp->GetObjectFile(); if (objfile) { - Address so_addr(file_addr, objfile->GetSectionList()); - address = so_addr.GetLoadAddress (exe_ctx->target); - if (address != LLDB_INVALID_ADDRESS) + Address so_addr(address, objfile->GetSectionList()); + addr_t load_address = so_addr.GetLoadAddress (exe_ctx->target); + if (load_address != LLDB_INVALID_ADDRESS) { + resolved = true; + address = load_address; address_type = eAddressTypeLoad; data.SetByteOrder(exe_ctx->target->GetArchitecture().GetByteOrder()); data.SetAddressByteSize(exe_ctx->target->GetArchitecture().GetAddressByteSize()); } else { - data.SetByteOrder(objfile->GetByteOrder()); - data.SetAddressByteSize(objfile->GetAddressByteSize()); + if (so_addr.IsSectionOffset()) + { + resolved = true; + file_so_addr = so_addr; + data.SetByteOrder(objfile->GetByteOrder()); + data.SetAddressByteSize(objfile->GetAddressByteSize()); + } } } - if (address_type == eAddressTypeFile) - error.SetErrorStringWithFormat ("%s is not loaded.\n", var_sc.module_sp->GetFileSpec().GetFilename().AsCString()); } - else + if (!resolved) { - error.SetErrorStringWithFormat ("unable to resolve the module for file address 0x%llx for variable '%s'", file_addr, variable->GetName().AsCString("")); + if (var_sc.module_sp) + error.SetErrorStringWithFormat ("unable to resolve the module for file address 0x%llx for variable '%s' in %s%s%s", + address, + variable->GetName().AsCString(""), + var_sc.module_sp->GetFileSpec().GetDirectory().GetCString(), + var_sc.module_sp->GetFileSpec().GetDirectory() ? "/" : "", + var_sc.module_sp->GetFileSpec().GetFilename().GetCString()); + else + error.SetErrorStringWithFormat ("unable to resolve the module for file address 0x%llx for variable '%s'", + address, + variable->GetName().AsCString("")); } } else { - error.SetErrorString ("Invalid file address."); + error.SetErrorString ("invalid file address"); } } else @@ -651,14 +677,28 @@ Value::GetValueAsData (ExecutionContext *exe_ctx, clang::ASTContext *ast_context // The address is an address in this process, so just copy it memcpy (dst, (uint8_t*)NULL + address, byte_size); } - else if (address_type == eAddressTypeLoad) + else if ((address_type == eAddressTypeLoad) || (address_type == eAddressTypeFile)) { - if (exe_ctx->process->ReadMemory(address, dst, byte_size, error) != byte_size) + if (file_so_addr.IsValid()) { - if (error.Success()) - error.SetErrorStringWithFormat("read %u bytes of memory from 0x%llx failed", (uint64_t)address, byte_size); - else + // We have a file address that we were able to translate into a + // section offset address so we might be able to read this from + // the object files if we don't have a live process. Lets always + // try and read from the process if we have one though since we + // want to read the actual value by setting "prefer_file_cache" + // to false. + const bool prefer_file_cache = false; + if (exe_ctx->target->ReadMemory(file_so_addr, prefer_file_cache, dst, byte_size, error) != byte_size) + { + error.SetErrorStringWithFormat("read memory from 0x%llx failed", (uint64_t)address); + } + } + else + { + if (exe_ctx->process->ReadMemory(address, dst, byte_size, error) != byte_size) + { error.SetErrorStringWithFormat("read memory from 0x%llx failed", (uint64_t)address); + } } } else diff --git a/lldb/source/Core/ValueObject.cpp b/lldb/source/Core/ValueObject.cpp index 6471972ad99..c4bfc3c126c 100644 --- a/lldb/source/Core/ValueObject.cpp +++ b/lldb/source/Core/ValueObject.cpp @@ -285,21 +285,21 @@ ValueObjectSP ValueObject::GetChildAtIndex (uint32_t idx, bool can_create) { ValueObjectSP child_sp; - if (UpdateValueIfNeeded()) + // We may need to update our value if we are dynamic + if (IsPossibleDynamicType ()) + UpdateValueIfNeeded(); + if (idx < GetNumChildren()) { - if (idx < GetNumChildren()) + // Check if we have already made the child value object? + if (can_create && m_children[idx] == NULL) { - // Check if we have already made the child value object? - if (can_create && m_children[idx] == NULL) - { - // No we haven't created the child at this index, so lets have our - // subclass do it and cache the result for quick future access. - m_children[idx] = CreateChildAtIndex (idx, false, 0); - } - - if (m_children[idx] != NULL) - return m_children[idx]->GetSP(); + // No we haven't created the child at this index, so lets have our + // subclass do it and cache the result for quick future access. + m_children[idx] = CreateChildAtIndex (idx, false, 0); } + + if (m_children[idx] != NULL) + return m_children[idx]->GetSP(); } return child_sp; } @@ -322,36 +322,37 @@ ValueObject::GetChildMemberWithName (const ConstString &name, bool can_create) // need a vector of indexes that can get us down to the correct child ValueObjectSP child_sp; - if (UpdateValueIfNeeded()) + // We may need to update our value if we are dynamic + if (IsPossibleDynamicType ()) + UpdateValueIfNeeded(); + + std::vector<uint32_t> child_indexes; + clang::ASTContext *clang_ast = GetClangAST(); + void *clang_type = GetClangType(); + bool omit_empty_base_classes = true; + const size_t num_child_indexes = ClangASTContext::GetIndexOfChildMemberWithName (clang_ast, + clang_type, + name.GetCString(), + omit_empty_base_classes, + child_indexes); + if (num_child_indexes > 0) { - std::vector<uint32_t> child_indexes; - clang::ASTContext *clang_ast = GetClangAST(); - void *clang_type = GetClangType(); - bool omit_empty_base_classes = true; - const size_t num_child_indexes = ClangASTContext::GetIndexOfChildMemberWithName (clang_ast, - clang_type, - name.GetCString(), - omit_empty_base_classes, - child_indexes); - if (num_child_indexes > 0) - { - std::vector<uint32_t>::const_iterator pos = child_indexes.begin (); - std::vector<uint32_t>::const_iterator end = child_indexes.end (); + std::vector<uint32_t>::const_iterator pos = child_indexes.begin (); + std::vector<uint32_t>::const_iterator end = child_indexes.end (); - child_sp = GetChildAtIndex(*pos, can_create); - for (++pos; pos != end; ++pos) + child_sp = GetChildAtIndex(*pos, can_create); + for (++pos; pos != end; ++pos) + { + if (child_sp) { - if (child_sp) - { - ValueObjectSP new_child_sp(child_sp->GetChildAtIndex (*pos, can_create)); - child_sp = new_child_sp; - } - else - { - child_sp.reset(); - } - + ValueObjectSP new_child_sp(child_sp->GetChildAtIndex (*pos, can_create)); + child_sp = new_child_sp; } + else + { + child_sp.reset(); + } + } } return child_sp; @@ -391,62 +392,59 @@ ValueObject::CreateChildAtIndex (uint32_t idx, bool synthetic_array_member, int3 { ValueObject *valobj = NULL; - if (UpdateValueIfNeeded()) - { - bool omit_empty_base_classes = true; - - std::string child_name_str; - uint32_t child_byte_size = 0; - int32_t child_byte_offset = 0; - uint32_t child_bitfield_bit_size = 0; - uint32_t child_bitfield_bit_offset = 0; - bool child_is_base_class = false; - bool child_is_deref_of_parent = false; - - const bool transparent_pointers = synthetic_array_member == false; - clang::ASTContext *clang_ast = GetClangAST(); - clang_type_t clang_type = GetClangType(); - clang_type_t child_clang_type; - - ExecutionContext exe_ctx; - GetExecutionContextScope()->CalculateExecutionContext (exe_ctx); - - child_clang_type = ClangASTContext::GetChildClangTypeAtIndex (&exe_ctx, - clang_ast, - GetName().GetCString(), - clang_type, - idx, - transparent_pointers, - omit_empty_base_classes, - child_name_str, - child_byte_size, - child_byte_offset, - child_bitfield_bit_size, - child_bitfield_bit_offset, - child_is_base_class, - child_is_deref_of_parent); - if (child_clang_type && child_byte_size) - { - if (synthetic_index) - child_byte_offset += child_byte_size * synthetic_index; - - ConstString child_name; - if (!child_name_str.empty()) - child_name.SetCString (child_name_str.c_str()); + bool omit_empty_base_classes = true; - valobj = new ValueObjectChild (*this, - clang_ast, - child_clang_type, - child_name, - child_byte_size, - child_byte_offset, - child_bitfield_bit_size, - child_bitfield_bit_offset, - child_is_base_class, - child_is_deref_of_parent); - if (m_pointers_point_to_load_addrs) - valobj->SetPointersPointToLoadAddrs (m_pointers_point_to_load_addrs); - } + std::string child_name_str; + uint32_t child_byte_size = 0; + int32_t child_byte_offset = 0; + uint32_t child_bitfield_bit_size = 0; + uint32_t child_bitfield_bit_offset = 0; + bool child_is_base_class = false; + bool child_is_deref_of_parent = false; + + const bool transparent_pointers = synthetic_array_member == false; + clang::ASTContext *clang_ast = GetClangAST(); + clang_type_t clang_type = GetClangType(); + clang_type_t child_clang_type; + + ExecutionContext exe_ctx; + GetExecutionContextScope()->CalculateExecutionContext (exe_ctx); + + child_clang_type = ClangASTContext::GetChildClangTypeAtIndex (&exe_ctx, + clang_ast, + GetName().GetCString(), + clang_type, + idx, + transparent_pointers, + omit_empty_base_classes, + child_name_str, + child_byte_size, + child_byte_offset, + child_bitfield_bit_size, + child_bitfield_bit_offset, + child_is_base_class, + child_is_deref_of_parent); + if (child_clang_type && child_byte_size) + { + if (synthetic_index) + child_byte_offset += child_byte_size * synthetic_index; + + ConstString child_name; + if (!child_name_str.empty()) + child_name.SetCString (child_name_str.c_str()); + + valobj = new ValueObjectChild (*this, + clang_ast, + child_clang_type, + child_name, + child_byte_size, + child_byte_offset, + child_bitfield_bit_size, + child_bitfield_bit_offset, + child_is_base_class, + child_is_deref_of_parent); + if (m_pointers_point_to_load_addrs) + valobj->SetPointersPointToLoadAddrs (m_pointers_point_to_load_addrs); } return valobj; @@ -994,6 +992,12 @@ ValueObject::IsPossibleCPlusPlusDynamicType () return ClangASTContext::IsPossibleCPlusPlusDynamicType (GetClangAST (), GetClangType()); } +bool +ValueObject::IsPossibleDynamicType () +{ + return ClangASTContext::IsPossibleDynamicType (GetClangAST (), GetClangType()); +} + ValueObjectSP ValueObject::GetSyntheticArrayMemberFromPointer (int32_t index, bool can_create) { diff --git a/lldb/source/Core/ValueObjectList.cpp b/lldb/source/Core/ValueObjectList.cpp index 8913d4da18d..f732a698ee5 100644 --- a/lldb/source/Core/ValueObjectList.cpp +++ b/lldb/source/Core/ValueObjectList.cpp @@ -51,6 +51,16 @@ ValueObjectList::Append (const ValueObjectSP &val_obj_sp) m_value_objects.push_back(val_obj_sp); } +void +ValueObjectList::Append (const ValueObjectList &valobj_list) +{ + std::copy(valobj_list.m_value_objects.begin(), // source begin + valobj_list.m_value_objects.end(), // source end + back_inserter(m_value_objects)); // destination + +} + + uint32_t ValueObjectList::GetSize() const { diff --git a/lldb/source/Core/ValueObjectVariable.cpp b/lldb/source/Core/ValueObjectVariable.cpp index e2a281b7f95..79692a023a8 100644 --- a/lldb/source/Core/ValueObjectVariable.cpp +++ b/lldb/source/Core/ValueObjectVariable.cpp @@ -169,7 +169,7 @@ ValueObjectVariable::UpdateValue () // 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 && exe_ctx.process) + if (value_type == Value::eValueTypeFileAddress && exe_ctx.process && exe_ctx.process->IsAlive()) { lldb::addr_t file_addr = m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS); if (file_addr != LLDB_INVALID_ADDRESS) |