forked from OSchip/llvm-project
[LLDB] Dump valid ranges of variables
This allows `image lookup -a ... -v` to print variables only if the given address is covered by the valid ranges of the variables. Since variables created in dwarf plugin always has empty scope range, print the variable if it has empty scope. Differential Revision: https://reviews.llvm.org/D119963
This commit is contained in:
parent
c33dbc2a2d
commit
15983c28aa
|
@ -229,6 +229,14 @@ public:
|
|||
/// \param[in] fallback_style
|
||||
/// The display style for the address.
|
||||
///
|
||||
/// \param[in] addr_byte_size
|
||||
/// The address byte size for the address.
|
||||
///
|
||||
/// \param[in] all_ranges
|
||||
/// If true, dump all valid ranges and value ranges for the variable that
|
||||
/// contains the address, otherwise dumping the range that contains the
|
||||
/// address.
|
||||
///
|
||||
/// \return
|
||||
/// Returns \b true if the address was able to be displayed.
|
||||
/// File and load addresses may be unresolved and it may not be
|
||||
|
@ -238,7 +246,8 @@ public:
|
|||
/// \see Address::DumpStyle
|
||||
bool Dump(Stream *s, ExecutionContextScope *exe_scope, DumpStyle style,
|
||||
DumpStyle fallback_style = DumpStyleInvalid,
|
||||
uint32_t addr_byte_size = UINT32_MAX) const;
|
||||
uint32_t addr_byte_size = UINT32_MAX,
|
||||
bool all_ranges = false) const;
|
||||
|
||||
AddressClass GetAddressClass() const;
|
||||
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include "lldb/Utility/Scalar.h"
|
||||
#include "lldb/Utility/Status.h"
|
||||
#include "lldb/lldb-private.h"
|
||||
#include "llvm/DebugInfo/DWARF/DWARFLocationExpression.h"
|
||||
#include <functional>
|
||||
|
||||
class DWARFUnit;
|
||||
|
@ -55,18 +56,10 @@ public:
|
|||
/// \param[in] level
|
||||
/// The level of verbosity to use.
|
||||
///
|
||||
/// \param[in] location_list_base_addr
|
||||
/// If this is a location list based expression, this is the
|
||||
/// address of the object that owns it. NOTE: this value is
|
||||
/// different from the DWARF version of the location list base
|
||||
/// address which is compile unit relative. This base address
|
||||
/// is the address of the object that owns the location list.
|
||||
///
|
||||
/// \param[in] abi
|
||||
/// An optional ABI plug-in that can be used to resolve register
|
||||
/// names.
|
||||
void GetDescription(Stream *s, lldb::DescriptionLevel level,
|
||||
lldb::addr_t location_list_base_addr, ABI *abi) const;
|
||||
void GetDescription(Stream *s, lldb::DescriptionLevel level, ABI *abi) const;
|
||||
|
||||
/// Return true if the location expression contains data
|
||||
bool IsValid() const;
|
||||
|
@ -217,6 +210,13 @@ public:
|
|||
lldb::addr_t func_load_addr, lldb::addr_t address,
|
||||
ABI *abi);
|
||||
|
||||
bool DumpLocations(Stream *s, lldb::DescriptionLevel level,
|
||||
lldb::addr_t func_load_addr, lldb::addr_t addr, ABI *abi);
|
||||
|
||||
bool GetLocationExpressions(
|
||||
lldb::addr_t load_function_start,
|
||||
llvm::function_ref<bool(llvm::DWARFLocationExpression)> callback) const;
|
||||
|
||||
bool MatchesOperand(StackFrame &frame, const Instruction::Operand &op);
|
||||
|
||||
llvm::Optional<DataExtractor>
|
||||
|
|
|
@ -77,7 +77,9 @@ public:
|
|||
|
||||
const DWARFExpression &LocationExpression() const { return m_location; }
|
||||
|
||||
bool DumpLocationForAddress(Stream *s, const Address &address);
|
||||
// When given invalid address, it dumps all locations. Otherwise it only dumps
|
||||
// the location that contains this address.
|
||||
bool DumpLocations(Stream *s, const Address &address);
|
||||
|
||||
size_t MemorySize() const;
|
||||
|
||||
|
|
|
@ -50,6 +50,7 @@
|
|||
#include "lldb/Utility/LLDBLog.h"
|
||||
#include "lldb/Utility/State.h"
|
||||
#include "lldb/Utility/Timer.h"
|
||||
#include "lldb/lldb-private-enumerations.h"
|
||||
|
||||
#include "llvm/ADT/ScopeExit.h"
|
||||
#include "llvm/Support/FileSystem.h"
|
||||
|
@ -1429,7 +1430,8 @@ static bool DumpModuleSymbolFile(Stream &strm, Module *module) {
|
|||
}
|
||||
|
||||
static void DumpAddress(ExecutionContextScope *exe_scope,
|
||||
const Address &so_addr, bool verbose, Stream &strm) {
|
||||
const Address &so_addr, bool verbose, bool all_ranges,
|
||||
Stream &strm) {
|
||||
strm.IndentMore();
|
||||
strm.Indent(" Address: ");
|
||||
so_addr.Dump(&strm, exe_scope, Address::DumpStyleModuleWithFileAddress);
|
||||
|
@ -1444,7 +1446,8 @@ static void DumpAddress(ExecutionContextScope *exe_scope,
|
|||
// Print out detailed address information when verbose is enabled
|
||||
if (verbose) {
|
||||
strm.EOL();
|
||||
so_addr.Dump(&strm, exe_scope, Address::DumpStyleDetailedSymbolContext);
|
||||
so_addr.Dump(&strm, exe_scope, Address::DumpStyleDetailedSymbolContext,
|
||||
Address::DumpStyleInvalid, UINT32_MAX, all_ranges);
|
||||
}
|
||||
strm.IndentLess();
|
||||
}
|
||||
|
@ -1452,7 +1455,7 @@ static void DumpAddress(ExecutionContextScope *exe_scope,
|
|||
static bool LookupAddressInModule(CommandInterpreter &interpreter, Stream &strm,
|
||||
Module *module, uint32_t resolve_mask,
|
||||
lldb::addr_t raw_addr, lldb::addr_t offset,
|
||||
bool verbose) {
|
||||
bool verbose, bool all_ranges) {
|
||||
if (module) {
|
||||
lldb::addr_t addr = raw_addr - offset;
|
||||
Address so_addr;
|
||||
|
@ -1470,7 +1473,7 @@ static bool LookupAddressInModule(CommandInterpreter &interpreter, Stream &strm,
|
|||
|
||||
ExecutionContextScope *exe_scope =
|
||||
interpreter.GetExecutionContext().GetBestExecutionContextScope();
|
||||
DumpAddress(exe_scope, so_addr, verbose, strm);
|
||||
DumpAddress(exe_scope, so_addr, verbose, all_ranges, strm);
|
||||
// strm.IndentMore();
|
||||
// strm.Indent (" Address: ");
|
||||
// so_addr.Dump (&strm, exe_scope,
|
||||
|
@ -1502,7 +1505,7 @@ static bool LookupAddressInModule(CommandInterpreter &interpreter, Stream &strm,
|
|||
static uint32_t LookupSymbolInModule(CommandInterpreter &interpreter,
|
||||
Stream &strm, Module *module,
|
||||
const char *name, bool name_is_regex,
|
||||
bool verbose) {
|
||||
bool verbose, bool all_ranges) {
|
||||
if (!module)
|
||||
return 0;
|
||||
|
||||
|
@ -1535,7 +1538,7 @@ static uint32_t LookupSymbolInModule(CommandInterpreter &interpreter,
|
|||
if (symbol && symbol->ValueIsAddress()) {
|
||||
DumpAddress(
|
||||
interpreter.GetExecutionContext().GetBestExecutionContextScope(),
|
||||
symbol->GetAddressRef(), verbose, strm);
|
||||
symbol->GetAddressRef(), verbose, all_ranges, strm);
|
||||
}
|
||||
}
|
||||
strm.IndentLess();
|
||||
|
@ -1545,7 +1548,7 @@ static uint32_t LookupSymbolInModule(CommandInterpreter &interpreter,
|
|||
|
||||
static void DumpSymbolContextList(ExecutionContextScope *exe_scope,
|
||||
Stream &strm, SymbolContextList &sc_list,
|
||||
bool verbose) {
|
||||
bool verbose, bool all_ranges) {
|
||||
strm.IndentMore();
|
||||
|
||||
const uint32_t num_matches = sc_list.GetSize();
|
||||
|
@ -1557,7 +1560,7 @@ static void DumpSymbolContextList(ExecutionContextScope *exe_scope,
|
|||
|
||||
sc.GetAddressRange(eSymbolContextEverything, 0, true, range);
|
||||
|
||||
DumpAddress(exe_scope, range.GetBaseAddress(), verbose, strm);
|
||||
DumpAddress(exe_scope, range.GetBaseAddress(), verbose, all_ranges, strm);
|
||||
}
|
||||
}
|
||||
strm.IndentLess();
|
||||
|
@ -1567,7 +1570,7 @@ static size_t LookupFunctionInModule(CommandInterpreter &interpreter,
|
|||
Stream &strm, Module *module,
|
||||
const char *name, bool name_is_regex,
|
||||
const ModuleFunctionSearchOptions &options,
|
||||
bool verbose) {
|
||||
bool verbose, bool all_ranges) {
|
||||
if (module && name && name[0]) {
|
||||
SymbolContextList sc_list;
|
||||
size_t num_matches = 0;
|
||||
|
@ -1588,7 +1591,7 @@ static size_t LookupFunctionInModule(CommandInterpreter &interpreter,
|
|||
strm.PutCString(":\n");
|
||||
DumpSymbolContextList(
|
||||
interpreter.GetExecutionContext().GetBestExecutionContextScope(),
|
||||
strm, sc_list, verbose);
|
||||
strm, sc_list, verbose, all_ranges);
|
||||
}
|
||||
return num_matches;
|
||||
}
|
||||
|
@ -1693,7 +1696,7 @@ static uint32_t LookupFileAndLineInModule(CommandInterpreter &interpreter,
|
|||
Stream &strm, Module *module,
|
||||
const FileSpec &file_spec,
|
||||
uint32_t line, bool check_inlines,
|
||||
bool verbose) {
|
||||
bool verbose, bool all_ranges) {
|
||||
if (module && file_spec) {
|
||||
SymbolContextList sc_list;
|
||||
const uint32_t num_matches = module->ResolveSymbolContextsForFileSpec(
|
||||
|
@ -1710,7 +1713,7 @@ static uint32_t LookupFileAndLineInModule(CommandInterpreter &interpreter,
|
|||
strm.PutCString(":\n");
|
||||
DumpSymbolContextList(
|
||||
interpreter.GetExecutionContext().GetBestExecutionContextScope(),
|
||||
strm, sc_list, verbose);
|
||||
strm, sc_list, verbose, all_ranges);
|
||||
return num_matches;
|
||||
}
|
||||
}
|
||||
|
@ -3598,6 +3601,10 @@ public:
|
|||
case 'r':
|
||||
m_use_regex = true;
|
||||
break;
|
||||
|
||||
case '\x01':
|
||||
m_all_ranges = true;
|
||||
break;
|
||||
default:
|
||||
llvm_unreachable("Unimplemented option");
|
||||
}
|
||||
|
@ -3614,6 +3621,7 @@ public:
|
|||
m_line_number = 0;
|
||||
m_use_regex = false;
|
||||
m_include_inlines = true;
|
||||
m_all_ranges = false;
|
||||
m_verbose = false;
|
||||
m_print_all = false;
|
||||
}
|
||||
|
@ -3632,6 +3640,7 @@ public:
|
|||
bool m_use_regex; // Name lookups in m_str are regular expressions.
|
||||
bool m_include_inlines; // Check for inline entries when looking up by
|
||||
// file/line.
|
||||
bool m_all_ranges; // Print all ranges or single range.
|
||||
bool m_verbose; // Enable verbose lookup info
|
||||
bool m_print_all; // Print all matches, even in cases where there's a best
|
||||
// match.
|
||||
|
@ -3714,7 +3723,8 @@ public:
|
|||
(m_options.m_verbose
|
||||
? static_cast<int>(eSymbolContextVariable)
|
||||
: 0),
|
||||
m_options.m_addr, m_options.m_offset, m_options.m_verbose)) {
|
||||
m_options.m_addr, m_options.m_offset, m_options.m_verbose,
|
||||
m_options.m_all_ranges)) {
|
||||
result.SetStatus(eReturnStatusSuccessFinishResult);
|
||||
return true;
|
||||
}
|
||||
|
@ -3725,7 +3735,8 @@ public:
|
|||
if (!m_options.m_str.empty()) {
|
||||
if (LookupSymbolInModule(m_interpreter, result.GetOutputStream(),
|
||||
module, m_options.m_str.c_str(),
|
||||
m_options.m_use_regex, m_options.m_verbose)) {
|
||||
m_options.m_use_regex, m_options.m_verbose,
|
||||
m_options.m_all_ranges)) {
|
||||
result.SetStatus(eReturnStatusSuccessFinishResult);
|
||||
return true;
|
||||
}
|
||||
|
@ -3737,7 +3748,8 @@ public:
|
|||
if (LookupFileAndLineInModule(
|
||||
m_interpreter, result.GetOutputStream(), module,
|
||||
m_options.m_file, m_options.m_line_number,
|
||||
m_options.m_include_inlines, m_options.m_verbose)) {
|
||||
m_options.m_include_inlines, m_options.m_verbose,
|
||||
m_options.m_all_ranges)) {
|
||||
result.SetStatus(eReturnStatusSuccessFinishResult);
|
||||
return true;
|
||||
}
|
||||
|
@ -3755,7 +3767,8 @@ public:
|
|||
if (LookupFunctionInModule(m_interpreter, result.GetOutputStream(),
|
||||
module, m_options.m_str.c_str(),
|
||||
m_options.m_use_regex, function_options,
|
||||
m_options.m_verbose)) {
|
||||
m_options.m_verbose,
|
||||
m_options.m_all_ranges)) {
|
||||
result.SetStatus(eReturnStatusSuccessFinishResult);
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -957,6 +957,9 @@ let Command = "target modules lookup" in {
|
|||
def target_modules_lookup_type : Option<"type", "t">, Group<6>, Arg<"Name">,
|
||||
Required, Desc<"Lookup a type by name in the debug symbols in one or more "
|
||||
"target modules.">;
|
||||
def target_modules_lookup_variables_ranges : Option<"show-variable-ranges",
|
||||
"\\x01">, GroupRange<1, 6>, Desc<"Dump valid ranges of variables (must be "
|
||||
"used in conjunction with --verbose">;
|
||||
def target_modules_lookup_verbose : Option<"verbose", "v">,
|
||||
Desc<"Enable verbose lookup information.">;
|
||||
def target_modules_lookup_all : Option<"all", "A">, Desc<"Print all matches, "
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include "lldb/Symbol/Type.h"
|
||||
#include "lldb/Symbol/Variable.h"
|
||||
#include "lldb/Symbol/VariableList.h"
|
||||
#include "lldb/Target/ABI.h"
|
||||
#include "lldb/Target/ExecutionContext.h"
|
||||
#include "lldb/Target/ExecutionContextScope.h"
|
||||
#include "lldb/Target/Process.h"
|
||||
|
@ -403,7 +404,8 @@ bool Address::GetDescription(Stream &s, Target &target,
|
|||
}
|
||||
|
||||
bool Address::Dump(Stream *s, ExecutionContextScope *exe_scope, DumpStyle style,
|
||||
DumpStyle fallback_style, uint32_t addr_size) const {
|
||||
DumpStyle fallback_style, uint32_t addr_size,
|
||||
bool all_ranges) const {
|
||||
// If the section was nullptr, only load address is going to work unless we
|
||||
// are trying to deref a pointer
|
||||
SectionSP section_sp(GetSection());
|
||||
|
@ -720,27 +722,42 @@ bool Address::Dump(Stream *s, ExecutionContextScope *exe_scope, DumpStyle style,
|
|||
bool get_parent_variables = true;
|
||||
bool stop_if_block_is_inlined_function = false;
|
||||
VariableList variable_list;
|
||||
sc.block->AppendVariables(can_create, get_parent_variables,
|
||||
stop_if_block_is_inlined_function,
|
||||
[](Variable *) { return true; },
|
||||
&variable_list);
|
||||
|
||||
addr_t file_addr = GetFileAddress();
|
||||
sc.block->AppendVariables(
|
||||
can_create, get_parent_variables,
|
||||
stop_if_block_is_inlined_function,
|
||||
[&](Variable *var) {
|
||||
return var && var->LocationIsValidForAddress(*this);
|
||||
},
|
||||
&variable_list);
|
||||
ABISP abi =
|
||||
ABI::FindPlugin(ProcessSP(), module_sp->GetArchitecture());
|
||||
for (const VariableSP &var_sp : variable_list) {
|
||||
if (var_sp && var_sp->LocationIsValidForAddress(*this)) {
|
||||
s->Indent();
|
||||
s->Printf(" Variable: id = {0x%8.8" PRIx64 "}, name = \"%s\"",
|
||||
var_sp->GetID(), var_sp->GetName().GetCString());
|
||||
Type *type = var_sp->GetType();
|
||||
if (type)
|
||||
s->Printf(", type = \"%s\"", type->GetName().GetCString());
|
||||
else
|
||||
s->PutCString(", type = <unknown>");
|
||||
s->PutCString(", location = ");
|
||||
var_sp->DumpLocationForAddress(s, *this);
|
||||
s->PutCString(", decl = ");
|
||||
var_sp->GetDeclaration().DumpStopContext(s, false);
|
||||
s->EOL();
|
||||
}
|
||||
s->Indent();
|
||||
s->Printf(" Variable: id = {0x%8.8" PRIx64 "}, name = \"%s\"",
|
||||
var_sp->GetID(), var_sp->GetName().GetCString());
|
||||
Type *type = var_sp->GetType();
|
||||
if (type)
|
||||
s->Printf(", type = \"%s\"", type->GetName().GetCString());
|
||||
else
|
||||
s->PutCString(", type = <unknown>");
|
||||
s->PutCString(", valid ranges = ");
|
||||
if (var_sp->GetScopeRange().IsEmpty())
|
||||
s->PutCString("<block>");
|
||||
else if (all_ranges) {
|
||||
for (auto range : var_sp->GetScopeRange())
|
||||
DumpAddressRange(s->AsRawOstream(), range.GetRangeBase(),
|
||||
range.GetRangeEnd(), addr_size);
|
||||
} else if (auto *range =
|
||||
var_sp->GetScopeRange().FindEntryThatContains(
|
||||
file_addr))
|
||||
DumpAddressRange(s->AsRawOstream(), range->GetRangeBase(),
|
||||
range->GetRangeEnd(), addr_size);
|
||||
s->PutCString(", location = ");
|
||||
var_sp->DumpLocations(s, all_ranges ? LLDB_INVALID_ADDRESS : *this);
|
||||
s->PutCString(", decl = ");
|
||||
var_sp->GetDeclaration().DumpStopContext(s, false);
|
||||
s->EOL();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -129,7 +129,6 @@ private:
|
|||
}
|
||||
|
||||
void DWARFExpression::GetDescription(Stream *s, lldb::DescriptionLevel level,
|
||||
addr_t location_list_base_addr,
|
||||
ABI *abi) const {
|
||||
if (IsLocationList()) {
|
||||
// We have a location list
|
||||
|
@ -2673,14 +2672,50 @@ static DataExtractor ToDataExtractor(const llvm::DWARFLocationExpression &loc,
|
|||
return DataExtractor(buffer_sp, byte_order, addr_size);
|
||||
}
|
||||
|
||||
llvm::Optional<DataExtractor>
|
||||
DWARFExpression::GetLocationExpression(addr_t load_function_start,
|
||||
addr_t addr) const {
|
||||
bool DWARFExpression::DumpLocations(Stream *s, lldb::DescriptionLevel level,
|
||||
addr_t load_function_start, addr_t addr,
|
||||
ABI *abi) {
|
||||
if (!IsLocationList()) {
|
||||
DumpLocation(s, m_data, level, abi);
|
||||
return true;
|
||||
}
|
||||
bool dump_all = addr == LLDB_INVALID_ADDRESS;
|
||||
llvm::ListSeparator separator;
|
||||
auto callback = [&](llvm::DWARFLocationExpression loc) -> bool {
|
||||
if (loc.Range &&
|
||||
(dump_all || (loc.Range->LowPC <= addr && addr < loc.Range->HighPC))) {
|
||||
uint32_t addr_size = m_data.GetAddressByteSize();
|
||||
DataExtractor data = ToDataExtractor(loc, m_data.GetByteOrder(),
|
||||
m_data.GetAddressByteSize());
|
||||
s->AsRawOstream() << separator;
|
||||
s->PutCString("[");
|
||||
s->AsRawOstream() << llvm::format_hex(loc.Range->LowPC,
|
||||
2 + 2 * addr_size);
|
||||
s->PutCString(", ");
|
||||
s->AsRawOstream() << llvm::format_hex(loc.Range->HighPC,
|
||||
2 + 2 * addr_size);
|
||||
s->PutCString(") -> ");
|
||||
DumpLocation(s, data, level, abi);
|
||||
return dump_all;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
if (!GetLocationExpressions(load_function_start, callback))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DWARFExpression::GetLocationExpressions(
|
||||
addr_t load_function_start,
|
||||
llvm::function_ref<bool(llvm::DWARFLocationExpression)> callback) const {
|
||||
if (load_function_start == LLDB_INVALID_ADDRESS)
|
||||
return false;
|
||||
|
||||
Log *log = GetLog(LLDBLog::Expressions);
|
||||
|
||||
std::unique_ptr<llvm::DWARFLocationTable> loctable_up =
|
||||
m_dwarf_cu->GetLocationTable(m_data);
|
||||
llvm::Optional<DataExtractor> result;
|
||||
|
||||
uint64_t offset = 0;
|
||||
auto lookup_addr =
|
||||
[&](uint32_t index) -> llvm::Optional<llvm::object::SectionedAddress> {
|
||||
|
@ -2700,19 +2735,32 @@ DWARFExpression::GetLocationExpression(addr_t load_function_start,
|
|||
addr_t slide = load_function_start - m_loclist_addresses->func_file_addr;
|
||||
loc->Range->LowPC += slide;
|
||||
loc->Range->HighPC += slide;
|
||||
|
||||
if (loc->Range->LowPC <= addr && addr < loc->Range->HighPC)
|
||||
result = ToDataExtractor(*loc, m_data.GetByteOrder(),
|
||||
m_data.GetAddressByteSize());
|
||||
}
|
||||
return !result;
|
||||
return callback(*loc);
|
||||
};
|
||||
llvm::Error E = loctable_up->visitAbsoluteLocationList(
|
||||
llvm::Error error = loctable_up->visitAbsoluteLocationList(
|
||||
offset, llvm::object::SectionedAddress{m_loclist_addresses->cu_file_addr},
|
||||
lookup_addr, process_list);
|
||||
if (E)
|
||||
LLDB_LOG_ERROR(log, std::move(E), "{0}");
|
||||
return result;
|
||||
if (error) {
|
||||
LLDB_LOG_ERROR(log, std::move(error), "{0}");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
llvm::Optional<DataExtractor>
|
||||
DWARFExpression::GetLocationExpression(addr_t load_function_start,
|
||||
addr_t addr) const {
|
||||
llvm::Optional<DataExtractor> data;
|
||||
auto callback = [&](llvm::DWARFLocationExpression loc) {
|
||||
if (loc.Range && loc.Range->LowPC <= addr && addr < loc.Range->HighPC) {
|
||||
data = ToDataExtractor(loc, m_data.GetByteOrder(),
|
||||
m_data.GetAddressByteSize());
|
||||
}
|
||||
return !data;
|
||||
};
|
||||
GetLocationExpressions(load_function_start, callback);
|
||||
return data;
|
||||
}
|
||||
|
||||
bool DWARFExpression::MatchesOperand(StackFrame &frame,
|
||||
|
@ -2738,7 +2786,8 @@ bool DWARFExpression::MatchesOperand(StackFrame &frame,
|
|||
addr_t pc = frame.GetFrameCodeAddress().GetLoadAddress(
|
||||
frame.CalculateTarget().get());
|
||||
|
||||
if (llvm::Optional<DataExtractor> expr = GetLocationExpression(load_function_start, pc))
|
||||
if (llvm::Optional<DataExtractor> expr =
|
||||
GetLocationExpression(load_function_start, pc))
|
||||
opcodes = std::move(*expr);
|
||||
else
|
||||
return false;
|
||||
|
|
|
@ -3923,7 +3923,7 @@ SymbolFileDWARF::CollectCallEdges(ModuleSP module, DWARFDIE function_die) {
|
|||
if (log) {
|
||||
StreamString call_target_desc;
|
||||
call_target->GetDescription(&call_target_desc, eDescriptionLevelBrief,
|
||||
LLDB_INVALID_ADDRESS, nullptr);
|
||||
nullptr);
|
||||
LLDB_LOG(log, "CollectCallEdges: Found indirect call target: {0}",
|
||||
call_target_desc.GetString());
|
||||
}
|
||||
|
@ -3936,11 +3936,9 @@ SymbolFileDWARF::CollectCallEdges(ModuleSP module, DWARFDIE function_die) {
|
|||
for (const CallSiteParameter ¶m : parameters) {
|
||||
StreamString callee_loc_desc, caller_loc_desc;
|
||||
param.LocationInCallee.GetDescription(&callee_loc_desc,
|
||||
eDescriptionLevelBrief,
|
||||
LLDB_INVALID_ADDRESS, nullptr);
|
||||
eDescriptionLevelBrief, nullptr);
|
||||
param.LocationInCaller.GetDescription(&caller_loc_desc,
|
||||
eDescriptionLevelBrief,
|
||||
LLDB_INVALID_ADDRESS, nullptr);
|
||||
eDescriptionLevelBrief, nullptr);
|
||||
LLDB_LOG(log, "CollectCallEdges: \tparam: {0} => {1}",
|
||||
callee_loc_desc.GetString(), caller_loc_desc.GetString());
|
||||
}
|
||||
|
|
|
@ -147,23 +147,13 @@ void Variable::Dump(Stream *s, bool show_context) const {
|
|||
|
||||
if (m_location.IsValid()) {
|
||||
s->PutCString(", location = ");
|
||||
lldb::addr_t loclist_base_addr = LLDB_INVALID_ADDRESS;
|
||||
if (m_location.IsLocationList()) {
|
||||
SymbolContext variable_sc;
|
||||
m_owner_scope->CalculateSymbolContext(&variable_sc);
|
||||
if (variable_sc.function)
|
||||
loclist_base_addr = variable_sc.function->GetAddressRange()
|
||||
.GetBaseAddress()
|
||||
.GetFileAddress();
|
||||
}
|
||||
ABISP abi;
|
||||
if (m_owner_scope) {
|
||||
ModuleSP module_sp(m_owner_scope->CalculateSymbolContextModule());
|
||||
if (module_sp)
|
||||
abi = ABI::FindPlugin(ProcessSP(), module_sp->GetArchitecture());
|
||||
}
|
||||
m_location.GetDescription(s, lldb::eDescriptionLevelBrief,
|
||||
loclist_base_addr, abi.get());
|
||||
m_location.GetDescription(s, lldb::eDescriptionLevelBrief, abi.get());
|
||||
}
|
||||
|
||||
if (m_external)
|
||||
|
@ -445,36 +435,25 @@ Status Variable::GetValuesForVariableExpressionPath(
|
|||
return error;
|
||||
}
|
||||
|
||||
bool Variable::DumpLocationForAddress(Stream *s, const Address &address) {
|
||||
// Be sure to resolve the address to section offset prior to calling this
|
||||
// function.
|
||||
if (address.IsSectionOffset()) {
|
||||
SymbolContext sc;
|
||||
CalculateSymbolContext(&sc);
|
||||
if (sc.module_sp == address.GetModule()) {
|
||||
ABISP abi;
|
||||
if (m_owner_scope) {
|
||||
ModuleSP module_sp(m_owner_scope->CalculateSymbolContextModule());
|
||||
if (module_sp)
|
||||
abi = ABI::FindPlugin(ProcessSP(), module_sp->GetArchitecture());
|
||||
}
|
||||
bool Variable::DumpLocations(Stream *s, const Address &address) {
|
||||
SymbolContext sc;
|
||||
CalculateSymbolContext(&sc);
|
||||
ABISP abi;
|
||||
if (m_owner_scope) {
|
||||
ModuleSP module_sp(m_owner_scope->CalculateSymbolContextModule());
|
||||
if (module_sp)
|
||||
abi = ABI::FindPlugin(ProcessSP(), module_sp->GetArchitecture());
|
||||
}
|
||||
|
||||
const addr_t file_addr = address.GetFileAddress();
|
||||
if (sc.function) {
|
||||
if (sc.function->GetAddressRange().ContainsFileAddress(address)) {
|
||||
addr_t loclist_base_file_addr =
|
||||
sc.function->GetAddressRange().GetBaseAddress().GetFileAddress();
|
||||
if (loclist_base_file_addr == LLDB_INVALID_ADDRESS)
|
||||
return false;
|
||||
return m_location.DumpLocationForAddress(s, eDescriptionLevelBrief,
|
||||
loclist_base_file_addr,
|
||||
file_addr, abi.get());
|
||||
}
|
||||
}
|
||||
return m_location.DumpLocationForAddress(s, eDescriptionLevelBrief,
|
||||
LLDB_INVALID_ADDRESS, file_addr,
|
||||
abi.get());
|
||||
}
|
||||
const addr_t file_addr = address.GetFileAddress();
|
||||
if (sc.function) {
|
||||
addr_t loclist_base_file_addr =
|
||||
sc.function->GetAddressRange().GetBaseAddress().GetFileAddress();
|
||||
if (loclist_base_file_addr == LLDB_INVALID_ADDRESS)
|
||||
return false;
|
||||
return m_location.DumpLocations(s, eDescriptionLevelBrief,
|
||||
loclist_base_file_addr, file_addr,
|
||||
abi.get());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
# RUN: %lldb %t -o "image lookup -v -s lookup_loclists" -o exit | FileCheck %s
|
||||
|
||||
# CHECK-LABEL: image lookup -v -s lookup_loclists
|
||||
# CHECK: Variable: {{.*}}, name = "x0", type = "int", location = DW_OP_reg0 RAX,
|
||||
# CHECK: Variable: {{.*}}, name = "x0", type = "int", valid ranges = <block>, location = [0x0000000000000000, 0x0000000000000003) -> DW_OP_reg0 RAX,
|
||||
# CHECK-NOT: Variable:
|
||||
|
||||
loclists:
|
||||
|
|
|
@ -8,18 +8,30 @@
|
|||
# RUN: %lldb %t -o "image lookup -v -a 0" -o "image lookup -v -a 2" \
|
||||
# RUN: -o "image dump symfile" -o exit | FileCheck %s
|
||||
|
||||
# RUN: %lldb %t -o "image lookup -v -a 0 -show-variable-ranges" -o \
|
||||
# RUN: "image lookup -v -a 2 -show-variable-ranges" \
|
||||
# RUN: -o exit | FileCheck %s --check-prefix=ALL-RANGES
|
||||
|
||||
# RUN: llvm-mc -triple=x86_64-pc-linux -filetype=obj %s --defsym LOCLISTS=0 > %t
|
||||
# RUN: %lldb %t -o "image lookup -v -a 0" -o "image lookup -v -a 2" \
|
||||
# RUN: -o "image dump symfile" -o exit | FileCheck %s --check-prefix=CHECK --check-prefix=LOCLISTS
|
||||
|
||||
# ALL-RANGES-LABEL: image lookup -v -a 0 -show-variable-ranges
|
||||
# ALL-RANGES: Variable: id = {{.*}}, name = "x0", type = "int", valid ranges = <block>, location = [0x0000000000000000, 0x0000000000000001) -> DW_OP_reg5 RDI, [0x0000000000000001, 0x0000000000000006) -> DW_OP_reg0 RAX
|
||||
# ALL-RANGES: Variable: id = {{.*}}, name = "x1", type = "int", valid ranges = <block>, location = <empty>
|
||||
# ALL-RANGES-LABEL: image lookup -v -a 2 -show-variable-ranges
|
||||
# ALL-RANGES: Variable: id = {{.*}}, name = "x0", type = "int", valid ranges = <block>, location = [0x0000000000000000, 0x0000000000000001) -> DW_OP_reg5 RDI, [0x0000000000000001, 0x0000000000000006) -> DW_OP_reg0 RAX
|
||||
# ALL-RANGES: Variable: id = {{.*}}, name = "x1", type = "int", valid ranges = <block>, location = <empty>
|
||||
# ALL-RANGES: Variable: id = {{.*}}, name = "x3", type = "int", valid ranges = <block>, location = [0x0000000000000002, 0x0000000000000003) -> DW_OP_reg1 RDX
|
||||
|
||||
# CHECK-LABEL: image lookup -v -a 0
|
||||
# CHECK: Variable: {{.*}}, name = "x0", type = "int", location = DW_OP_reg5 RDI,
|
||||
# CHECK: Variable: {{.*}}, name = "x1", type = "int", location = <empty>,
|
||||
# CHECK: Variable: {{.*}}, name = "x0", type = "int", valid ranges = <block>, location = [0x0000000000000000, 0x0000000000000001) -> DW_OP_reg5 RDI
|
||||
# CHECK: Variable: {{.*}}, name = "x1", type = "int", valid ranges = <block>, location = <empty>,
|
||||
|
||||
# CHECK-LABEL: image lookup -v -a 2
|
||||
# CHECK: Variable: {{.*}}, name = "x0", type = "int", location = DW_OP_reg0 RAX,
|
||||
# CHECK: Variable: {{.*}}, name = "x1", type = "int", location = <empty>,
|
||||
# CHECK: Variable: {{.*}}, name = "x3", type = "int", location = DW_OP_reg1 RDX,
|
||||
# CHECK: Variable: {{.*}}, name = "x0", type = "int", valid ranges = <block>, location = [0x0000000000000001, 0x0000000000000006) -> DW_OP_reg0 RAX
|
||||
# CHECK: Variable: {{.*}}, name = "x1", type = "int", valid ranges = <block>, location = <empty>,
|
||||
# CHECK: Variable: {{.*}}, name = "x3", type = "int", valid ranges = <block>, location = [0x0000000000000002, 0x0000000000000003) -> DW_OP_reg1 RDX
|
||||
|
||||
# CHECK-LABEL: image dump symfile
|
||||
# CHECK: CompileUnit{0x00000000}
|
||||
|
|
|
@ -7,10 +7,10 @@
|
|||
|
||||
|
||||
# CHECK-LABEL: image lookup -v -s loc
|
||||
# CHECK: Variable: {{.*}}, name = "x0", type = "int", location = DW_OP_reg5 RDI,
|
||||
# CHECK: Variable: {{.*}}, name = "x0", type = "int", valid ranges = <block>, location = [0x0000000000000000, 0x0000000000000001) -> DW_OP_reg5 RDI,
|
||||
|
||||
# CHECK-LABEL: image lookup -v -s loclists
|
||||
# CHECK: Variable: {{.*}}, name = "x1", type = "int", location = DW_OP_reg0 RAX,
|
||||
# CHECK: Variable: {{.*}}, name = "x1", type = "int", valid ranges = <block>, location = [0x0000000000000001, 0x0000000000000002) -> DW_OP_reg0 RAX,
|
||||
|
||||
|
||||
loc:
|
||||
|
|
|
@ -3,8 +3,8 @@
|
|||
# RUN: %lldb debug_loclists-dwo.o -o "image lookup -v -s lookup_loclists" -o exit | FileCheck %s
|
||||
|
||||
# CHECK-LABEL: image lookup -v -s lookup_loclists
|
||||
# CHECK: Variable: {{.*}}, name = "x0", type = "int", location = DW_OP_reg0 RAX,
|
||||
# CHECK: Variable: {{.*}}, name = "x1", type = "int", location = DW_OP_reg1 RDX,
|
||||
# CHECK: Variable: {{.*}}, name = "x0", type = "int", valid ranges = <block>, location = [0x0000000000000000, 0x0000000000000003) -> DW_OP_reg0 RAX,
|
||||
# CHECK: Variable: {{.*}}, name = "x1", type = "int", valid ranges = <block>, location = [0x0000000000000002, 0x0000000000000004) -> DW_OP_reg1 RDX,
|
||||
|
||||
loclists:
|
||||
nop
|
||||
|
|
|
@ -6,8 +6,8 @@
|
|||
# RUN: %lldb %t -o "image lookup -v -s lookup_loclists" -o exit | FileCheck %s
|
||||
|
||||
# CHECK-LABEL: image lookup -v -s lookup_loclists
|
||||
# CHECK: Variable: id = {{.*}}, name = "x0", type = "int", location = DW_OP_reg0 RAX,
|
||||
# CHECK: Variable: id = {{.*}}, name = "x1", type = "int", location = DW_OP_reg1 RDX,
|
||||
# CHECK: Variable: id = {{.*}}, name = "x0", type = "int", valid ranges = <block>, location = [0x0000000000000000, 0x0000000000000003) -> DW_OP_reg0 RAX,
|
||||
# CHECK: Variable: id = {{.*}}, name = "x1", type = "int", valid ranges = <block>, location = [0x0000000000000002, 0x0000000000000004) -> DW_OP_reg1 RDX,
|
||||
|
||||
## This part is kept in both the main and the dwp file to be able to reference the offsets.
|
||||
loclists:
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
# CHECK-LABEL: image lookup -v -n F1
|
||||
# CHECK: CompileUnit: id = {0x00000001}, file = "1.c", language = "<not loaded>"
|
||||
# CHECK: Function: {{.*}}, name = "F1", range = [0x0000000000000001-0x0000000000000002)
|
||||
# CHECK: Variable: {{.*}}, name = "x", type = "int", location = DW_OP_reg1 RDX
|
||||
# CHECK: Variable: {{.*}}, name = "x", type = "int", valid ranges = <block>, location = [0x0000000000000001, 0x0000000000000002) -> DW_OP_reg1 RDX
|
||||
|
||||
# SYMBOLS: Compile units:
|
||||
# SYMBOLS-NEXT: CompileUnit{0x00000000}, language = "<not loaded>", file = '0.c'
|
||||
|
|
|
@ -14,35 +14,35 @@
|
|||
# at the inlined function entry.
|
||||
image lookup -v -s break_at_inlined_f_in_main
|
||||
# CHECK-LABEL: image lookup -v -s break_at_inlined_f_in_main
|
||||
# CHECK: name = "unused1", type = "void *", location = <empty>
|
||||
# CHECK: name = "used", type = "int", location = DW_OP_consts +42
|
||||
# CHECK: name = "unused2", type = "int", location = <empty>
|
||||
# CHECK: name = "partial", type = "int", location = DW_OP_reg4 RSI
|
||||
# CHECK: name = "unused3", type = "int", location = <empty>
|
||||
# CHECK: name = "unused1", type = "void *", valid ranges = <block>, location = <empty>
|
||||
# CHECK: name = "used", type = "int", valid ranges = <block>, location = [0x0000000000000011, 0x0000000000000014) -> DW_OP_consts +42
|
||||
# CHECK: name = "unused2", type = "int", valid ranges = <block>, location = <empty>
|
||||
# CHECK: name = "partial", type = "int", valid ranges = <block>, location = [0x0000000000000011, 0x0000000000000019) -> DW_OP_reg4 RSI
|
||||
# CHECK: name = "unused3", type = "int", valid ranges = <block>, location = <empty>
|
||||
|
||||
# Show variables outsid of the live range of the 'partial' parameter
|
||||
# and verify that the output is as expected.
|
||||
image lookup -v -s break_at_inlined_f_in_main_between_printfs
|
||||
# CHECK-LABEL: image lookup -v -s break_at_inlined_f_in_main_between_printfs
|
||||
# CHECK: name = "unused1", type = "void *", location = <empty>
|
||||
# CHECK: name = "used", type = "int", location = DW_OP_reg3 RBX
|
||||
# CHECK: name = "unused2", type = "int", location = <empty>
|
||||
# CHECK: name = "unused1", type = "void *", valid ranges = <block>, location = <empty>
|
||||
# CHECK: name = "used", type = "int", valid ranges = <block>, location = [0x0000000000000014, 0x000000000000001e) -> DW_OP_reg3 RBX
|
||||
# CHECK: name = "unused2", type = "int", valid ranges = <block>, location = <empty>
|
||||
# Note: image lookup does not show variables outside of their
|
||||
# location, so |partial| is missing here.
|
||||
# CHECK-NOT: partial
|
||||
# CHECK: name = "unused3", type = "int", location = <empty>
|
||||
# CHECK: name = "unused3", type = "int", valid ranges = <block>, location = <empty>
|
||||
|
||||
# Check that we show parameters even if all of them are compiled away.
|
||||
image lookup -v -s break_at_inlined_g_in_main
|
||||
# CHECK-LABEL: image lookup -v -s break_at_inlined_g_in_main
|
||||
# CHECK: name = "unused", type = "int", location = <empty>
|
||||
# CHECK: name = "unused", type = "int", valid ranges = <block>, location = <empty>
|
||||
|
||||
# Check that even the other inlined instance of f displays the correct
|
||||
# parameters.
|
||||
image lookup -v -s break_at_inlined_f_in_other
|
||||
# CHECK-LABEL: image lookup -v -s break_at_inlined_f_in_other
|
||||
# CHECK: name = "unused1", type = "void *", location = <empty>
|
||||
# CHECK: name = "used", type = "int", location = DW_OP_consts +1
|
||||
# CHECK: name = "unused2", type = "int", location = <empty>
|
||||
# CHECK: name = "partial", type = "int", location = DW_OP_consts +2
|
||||
# CHECK: name = "unused3", type = "int", location = <empty>
|
||||
# CHECK: name = "unused1", type = "void *", valid ranges = <block>, location = <empty>
|
||||
# CHECK: name = "used", type = "int", valid ranges = <block>, location = [0x0000000000000001, 0x000000000000000b) -> DW_OP_consts +1
|
||||
# CHECK: name = "unused2", type = "int", valid ranges = <block>, location = <empty>
|
||||
# CHECK: name = "partial", type = "int", valid ranges = <block>, location = [0x0000000000000001, 0x0000000000000006) -> DW_OP_consts +2
|
||||
# CHECK: name = "unused3", type = "int", valid ranges = <block>, location = <empty>
|
||||
|
|
Loading…
Reference in New Issue