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:
parent
6eece29d8f
commit
2501e5e2ea
|
@ -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
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue