Modified LLDB to be able to lookup global variables by address.

This is done by adding a "Variable *" to SymbolContext and allowing SymbolFile::ResolveSymbolContext() so if an address is resolved into a symbol context, we can include the global or static variable for that address.

This means you can now find global variables that are merged globals when doing a "image lookup --verbose --address 0x1230000". Previously we would resolve a symbol and show "_MergedGlobals123 + 1234". But now we can show the global variable name.

The eSymbolContextEverything purposely does not include the new eSymbolContextVariable in its lookup since stack frame code does many lookups and we don't want it triggering the global variable lookups.

<rdar://problem/18945678> 

llvm-svn: 226084
This commit is contained in:
Greg Clayton 2015-01-15 02:59:20 +00:00
parent 6eece29d8f
commit 2501e5e2ea
8 changed files with 156 additions and 16 deletions

View File

@ -347,6 +347,7 @@ public:
Block * block; ///< The Block for a given query
LineEntry line_entry; ///< The LineEntry for a given query
Symbol * symbol; ///< The Symbol for a given query
Variable * variable; ///< The global variable matching the given query
};

View File

@ -290,7 +290,11 @@ namespace lldb {
eSymbolContextBlock = (1u << 4), ///< Set when the deepest \a block is requested from a query, or was located in query results
eSymbolContextLineEntry = (1u << 5), ///< Set when \a line_entry is requested from a query, or was located in query results
eSymbolContextSymbol = (1u << 6), ///< Set when \a symbol is requested from a query, or was located in query results
eSymbolContextEverything = ((eSymbolContextSymbol << 1) - 1u) ///< Indicates to try and lookup everything up during a query.
eSymbolContextEverything = ((eSymbolContextSymbol << 1) - 1u), ///< Indicates to try and lookup everything up during a routine symbol context query.
eSymbolContextVariable = (1u << 7) ///< Set when \a global or static variable is requested from a query, or was located in query results.
///< eSymbolContextVariable is potentially expensive to lookup so it isn't included in
///< eSymbolContextEverything which stops it from being used during frame PC lookups and
///< many other potential address to symbol context lookups.
} SymbolContextItem;
typedef enum Permissions

View File

@ -4078,7 +4078,7 @@ public:
if (LookupAddressInModule (m_interpreter,
result.GetOutputStream(),
module,
eSymbolContextEverything,
eSymbolContextEverything | (m_options.m_verbose ? eSymbolContextVariable : 0),
m_options.m_addr,
m_options.m_offset,
m_options.m_verbose))

View File

@ -654,7 +654,7 @@ Address::Dump (Stream *s, ExecutionContextScope *exe_scope, DumpStyle style, Dum
if (module_sp)
{
SymbolContext sc;
module_sp->ResolveSymbolContextForAddress(*this, eSymbolContextEverything, sc);
module_sp->ResolveSymbolContextForAddress(*this, eSymbolContextEverything | eSymbolContextVariable, sc);
if (sc.function || sc.symbol)
{
bool show_stop_context = true;
@ -712,7 +712,7 @@ Address::Dump (Stream *s, ExecutionContextScope *exe_scope, DumpStyle style, Dum
if (module_sp)
{
SymbolContext sc;
module_sp->ResolveSymbolContextForAddress(*this, eSymbolContextEverything, sc);
module_sp->ResolveSymbolContextForAddress(*this, eSymbolContextEverything | eSymbolContextVariable, sc);
if (sc.symbol)
{
// If we have just a symbol make sure it is in the same section

View File

@ -2786,6 +2786,59 @@ SymbolFileDWARF::GetFunction (DWARFCompileUnit* dwarf_cu, const DWARFDebugInfoEn
return false;
}
SymbolFileDWARF::GlobalVariableMap &
SymbolFileDWARF::GetGlobalAranges()
{
if (!m_global_aranges_ap)
{
m_global_aranges_ap.reset (new GlobalVariableMap());
ModuleSP module_sp = GetObjectFile()->GetModule();
if (module_sp)
{
const size_t num_cus = module_sp->GetNumCompileUnits();
for (size_t i = 0; i < num_cus; ++i)
{
CompUnitSP cu_sp = module_sp->GetCompileUnitAtIndex(i);
if (cu_sp)
{
VariableListSP globals_sp = cu_sp->GetVariableList(true);
if (globals_sp)
{
const size_t num_globals = globals_sp->GetSize();
for (size_t g = 0; g < num_globals; ++g)
{
VariableSP var_sp = globals_sp->GetVariableAtIndex(g);
if (var_sp && !var_sp->GetLocationIsConstantValueData())
{
const DWARFExpression &location = var_sp->LocationExpression();
Value location_result;
Error error;
if (location.Evaluate(NULL, NULL, NULL, LLDB_INVALID_ADDRESS, NULL, location_result, &error))
{
if (location_result.GetValueType() == Value::eValueTypeFileAddress)
{
lldb::addr_t file_addr = location_result.GetScalar().ULongLong();
lldb::addr_t byte_size = 1;
if (var_sp->GetType())
byte_size = var_sp->GetType()->GetByteSize();
m_global_aranges_ap->Append(GlobalVariableMap::Entry(file_addr, byte_size, var_sp.get()));
}
}
}
}
}
}
}
}
m_global_aranges_ap->Sort();
}
return *m_global_aranges_ap;
}
uint32_t
SymbolFileDWARF::ResolveSymbolContext (const Address& so_addr, uint32_t resolve_scope, SymbolContext& sc)
{
@ -2794,10 +2847,11 @@ SymbolFileDWARF::ResolveSymbolContext (const Address& so_addr, uint32_t resolve_
static_cast<void*>(so_addr.GetSection().get()),
so_addr.GetOffset(), resolve_scope);
uint32_t resolved = 0;
if (resolve_scope & ( eSymbolContextCompUnit |
eSymbolContextFunction |
eSymbolContextBlock |
eSymbolContextLineEntry))
if (resolve_scope & ( eSymbolContextCompUnit |
eSymbolContextFunction |
eSymbolContextBlock |
eSymbolContextLineEntry |
eSymbolContextVariable ))
{
lldb::addr_t file_vm_addr = so_addr.GetFileAddress();
@ -2805,7 +2859,30 @@ SymbolFileDWARF::ResolveSymbolContext (const Address& so_addr, uint32_t resolve_
if (debug_info)
{
const dw_offset_t cu_offset = debug_info->GetCompileUnitAranges().FindAddress(file_vm_addr);
if (cu_offset != DW_INVALID_OFFSET)
if (cu_offset == DW_INVALID_OFFSET)
{
// Global variables are not in the compile unit address ranges. The only way to
// currently find global variables is to iterate over the .debug_pubnames or the
// __apple_names table and find all items in there that point to DW_TAG_variable
// DIEs and then find the address that matches.
if (resolve_scope & eSymbolContextVariable)
{
GlobalVariableMap &map = GetGlobalAranges();
const GlobalVariableMap::Entry *entry = map.FindEntryThatContains(file_vm_addr);
if (entry && entry->data)
{
Variable *variable = entry->data;
SymbolContextScope *scc = variable->GetSymbolContextScope();
if (scc)
{
scc->CalculateSymbolContext(&sc);
sc.variable = variable;
}
return sc.GetResolvedMask();
}
}
}
else
{
uint32_t cu_idx = DW_INVALID_INDEX;
DWARFCompileUnit* dwarf_cu = debug_info->GetCompileUnit(cu_offset, &cu_idx).get();

View File

@ -29,6 +29,7 @@
#include "lldb/Core/ConstString.h"
#include "lldb/Core/dwarf.h"
#include "lldb/Core/Flags.h"
#include "lldb/Core/RangeMap.h"
#include "lldb/Core/UniqueCStringMap.h"
#include "lldb/Symbol/ClangASTContext.h"
#include "lldb/Symbol/SymbolFile.h"
@ -557,6 +558,11 @@ protected:
uint32_t type_mask,
TypeSet &type_set);
typedef lldb_private::RangeDataVector<lldb::addr_t, lldb::addr_t, lldb_private::Variable *> GlobalVariableMap;
GlobalVariableMap &
GetGlobalAranges();
lldb::ModuleWP m_debug_map_module_wp;
SymbolFileDWARFDebugMap * m_debug_map_symfile;
clang::TranslationUnitDecl * m_clang_tu_decl;
@ -584,6 +590,7 @@ protected:
std::unique_ptr<DWARFMappedHash::MemoryTable> m_apple_types_ap;
std::unique_ptr<DWARFMappedHash::MemoryTable> m_apple_namespaces_ap;
std::unique_ptr<DWARFMappedHash::MemoryTable> m_apple_objc_ap;
std::unique_ptr<GlobalVariableMap> m_global_aranges_ap;
NameToDIE m_function_basename_index; // All concrete functions
NameToDIE m_function_fullname_index; // All concrete functions
NameToDIE m_function_method_index; // All inlined functions

View File

@ -21,6 +21,7 @@
#include "lldb/Symbol/Symbol.h"
#include "lldb/Symbol/SymbolFile.h"
#include "lldb/Symbol/SymbolVendor.h"
#include "lldb/Symbol/Variable.h"
#include "lldb/Target/Target.h"
using namespace lldb;
@ -33,7 +34,8 @@ SymbolContext::SymbolContext() :
function (nullptr),
block (nullptr),
line_entry (),
symbol (nullptr)
symbol (nullptr),
variable (nullptr)
{
}
@ -44,7 +46,8 @@ SymbolContext::SymbolContext(const ModuleSP& m, CompileUnit *cu, Function *f, Bl
function (f),
block (b),
line_entry (),
symbol (s)
symbol (s),
variable (nullptr)
{
if (le)
line_entry = *le;
@ -57,7 +60,8 @@ SymbolContext::SymbolContext(const TargetSP &t, const ModuleSP& m, CompileUnit *
function (f),
block (b),
line_entry (),
symbol (s)
symbol (s),
variable (nullptr)
{
if (le)
line_entry = *le;
@ -70,7 +74,8 @@ SymbolContext::SymbolContext(const SymbolContext& rhs) :
function (rhs.function),
block (rhs.block),
line_entry (rhs.line_entry),
symbol (rhs.symbol)
symbol (rhs.symbol),
variable (rhs.variable)
{
}
@ -82,7 +87,8 @@ SymbolContext::SymbolContext (SymbolContextScope *sc_scope) :
function (nullptr),
block (nullptr),
line_entry (),
symbol (nullptr)
symbol (nullptr),
variable (nullptr)
{
sc_scope->CalculateSymbolContext (this);
}
@ -103,6 +109,7 @@ SymbolContext::operator= (const SymbolContext& rhs)
block = rhs.block;
line_entry = rhs.line_entry;
symbol = rhs.symbol;
variable = rhs.variable;
}
return *this;
}
@ -118,6 +125,7 @@ SymbolContext::Clear(bool clear_target)
block = nullptr;
line_entry.Clear();
symbol = nullptr;
variable = nullptr;
}
bool
@ -309,6 +317,37 @@ SymbolContext::GetDescription(Stream *s, lldb::DescriptionLevel level, Target *t
symbol->GetDescription(s, level, target);
s->EOL();
}
if (variable != nullptr)
{
s->Indent(" Variable: ");
s->Printf("id = {0x%8.8" PRIx64 "}, ", variable->GetID());
switch (variable->GetScope())
{
case eValueTypeVariableGlobal:
s->PutCString("kind = global, ");
break;
case eValueTypeVariableStatic:
s->PutCString("kind = static, ");
break;
case eValueTypeVariableArgument:
s->PutCString("kind = argument, ");
break;
case eValueTypeVariableLocal:
s->PutCString("kind = local, ");
break;
default:
break;
}
s->Printf ("name = \"%s\"\n", variable->GetName().GetCString());
}
}
uint32_t
@ -322,6 +361,7 @@ SymbolContext::GetResolvedMask () const
if (block) resolved_mask |= eSymbolContextBlock;
if (line_entry.IsValid()) resolved_mask |= eSymbolContextLineEntry;
if (symbol) resolved_mask |= eSymbolContextSymbol;
if (variable) resolved_mask |= eSymbolContextVariable;
return resolved_mask;
}
@ -377,6 +417,12 @@ SymbolContext::Dump(Stream *s, Target *target) const
if (symbol != nullptr && symbol->GetMangled())
*s << ' ' << symbol->GetMangled().GetName().AsCString();
s->EOL();
*s << "Variable = " << (void *)variable;
if (variable != nullptr)
{
*s << " {0x" << variable->GetID() << "} " << variable->GetType()->GetName();
s->EOL();
}
s->IndentLess();
s->IndentLess();
}
@ -389,7 +435,8 @@ lldb_private::operator== (const SymbolContext& lhs, const SymbolContext& rhs)
&& lhs.module_sp.get() == rhs.module_sp.get()
&& lhs.comp_unit == rhs.comp_unit
&& lhs.target_sp.get() == rhs.target_sp.get()
&& LineEntry::Compare(lhs.line_entry, rhs.line_entry) == 0;
&& LineEntry::Compare(lhs.line_entry, rhs.line_entry) == 0
&& lhs.variable == rhs.variable;
}
bool
@ -400,7 +447,8 @@ lldb_private::operator!= (const SymbolContext& lhs, const SymbolContext& rhs)
|| lhs.module_sp.get() != rhs.module_sp.get()
|| lhs.comp_unit != rhs.comp_unit
|| lhs.target_sp.get() != rhs.target_sp.get()
|| LineEntry::Compare(lhs.line_entry, rhs.line_entry) != 0;
|| LineEntry::Compare(lhs.line_entry, rhs.line_entry) != 0
|| lhs.variable != rhs.variable;
}
bool

View File

@ -203,7 +203,10 @@ void
Variable::CalculateSymbolContext (SymbolContext *sc)
{
if (m_owner_scope)
{
m_owner_scope->CalculateSymbolContext(sc);
sc->variable = this;
}
else
sc->Clear(false);
}