This revision was automatically updated to reflect the committed changes.
Closed by commit rG15983c28aa81: [LLDB] Dump valid ranges of variables
(authored by zequanwu).
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D119963/new/
https://reviews.llvm.org/D119963
Files:
lldb/include/lldb/Core/Address.h
lldb/include/lldb/Expression/DWARFExpression.h
lldb/include/lldb/Symbol/Variable.h
lldb/source/Commands/CommandObjectTarget.cpp
lldb/source/Commands/Options.td
lldb/source/Core/Address.cpp
lldb/source/Expression/DWARFExpression.cpp
lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
lldb/source/Symbol/Variable.cpp
lldb/test/Shell/SymbolFile/DWARF/x86/DW_AT_loclists_base.s
lldb/test/Shell/SymbolFile/DWARF/x86/debug_loc.s
lldb/test/Shell/SymbolFile/DWARF/x86/debug_loc_and_loclists.s
lldb/test/Shell/SymbolFile/DWARF/x86/debug_loclists-dwo.s
lldb/test/Shell/SymbolFile/DWARF/x86/debug_loclists-dwp.s
lldb/test/Shell/SymbolFile/DWARF/x86/dwp.s
lldb/test/Shell/SymbolFile/DWARF/x86/unused-inlined-params.test
Index: lldb/test/Shell/SymbolFile/DWARF/x86/unused-inlined-params.test
===================================================================
--- lldb/test/Shell/SymbolFile/DWARF/x86/unused-inlined-params.test
+++ lldb/test/Shell/SymbolFile/DWARF/x86/unused-inlined-params.test
@@ -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>
Index: lldb/test/Shell/SymbolFile/DWARF/x86/dwp.s
===================================================================
--- lldb/test/Shell/SymbolFile/DWARF/x86/dwp.s
+++ lldb/test/Shell/SymbolFile/DWARF/x86/dwp.s
@@ -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'
Index: lldb/test/Shell/SymbolFile/DWARF/x86/debug_loclists-dwp.s
===================================================================
--- lldb/test/Shell/SymbolFile/DWARF/x86/debug_loclists-dwp.s
+++ lldb/test/Shell/SymbolFile/DWARF/x86/debug_loclists-dwp.s
@@ -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:
Index: lldb/test/Shell/SymbolFile/DWARF/x86/debug_loclists-dwo.s
===================================================================
--- lldb/test/Shell/SymbolFile/DWARF/x86/debug_loclists-dwo.s
+++ lldb/test/Shell/SymbolFile/DWARF/x86/debug_loclists-dwo.s
@@ -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
Index: lldb/test/Shell/SymbolFile/DWARF/x86/debug_loc_and_loclists.s
===================================================================
--- lldb/test/Shell/SymbolFile/DWARF/x86/debug_loc_and_loclists.s
+++ lldb/test/Shell/SymbolFile/DWARF/x86/debug_loc_and_loclists.s
@@ -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:
Index: lldb/test/Shell/SymbolFile/DWARF/x86/debug_loc.s
===================================================================
--- lldb/test/Shell/SymbolFile/DWARF/x86/debug_loc.s
+++ lldb/test/Shell/SymbolFile/DWARF/x86/debug_loc.s
@@ -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}
Index: lldb/test/Shell/SymbolFile/DWARF/x86/DW_AT_loclists_base.s
===================================================================
--- lldb/test/Shell/SymbolFile/DWARF/x86/DW_AT_loclists_base.s
+++ lldb/test/Shell/SymbolFile/DWARF/x86/DW_AT_loclists_base.s
@@ -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:
Index: lldb/source/Symbol/Variable.cpp
===================================================================
--- lldb/source/Symbol/Variable.cpp
+++ lldb/source/Symbol/Variable.cpp
@@ -147,23 +147,13 @@
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 @@
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;
}
Index: lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
===================================================================
--- lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
+++ lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
@@ -3923,7 +3923,7 @@
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 @@
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());
}
Index: lldb/source/Expression/DWARFExpression.cpp
===================================================================
--- lldb/source/Expression/DWARFExpression.cpp
+++ lldb/source/Expression/DWARFExpression.cpp
@@ -129,7 +129,6 @@
}
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 @@
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 @@
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 @@
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;
Index: lldb/source/Core/Address.cpp
===================================================================
--- lldb/source/Core/Address.cpp
+++ lldb/source/Core/Address.cpp
@@ -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::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 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();
}
}
}
Index: lldb/source/Commands/Options.td
===================================================================
--- lldb/source/Commands/Options.td
+++ lldb/source/Commands/Options.td
@@ -957,6 +957,9 @@
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, "
Index: lldb/source/Commands/CommandObjectTarget.cpp
===================================================================
--- lldb/source/Commands/CommandObjectTarget.cpp
+++ lldb/source/Commands/CommandObjectTarget.cpp
@@ -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 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 @@
// 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 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 @@
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 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 @@
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 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 @@
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 @@
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 @@
strm.PutCString(":\n");
DumpSymbolContextList(
interpreter.GetExecutionContext().GetBestExecutionContextScope(),
- strm, sc_list, verbose);
+ strm, sc_list, verbose, all_ranges);
}
return num_matches;
}
@@ -1693,7 +1696,7 @@
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 @@
strm.PutCString(":\n");
DumpSymbolContextList(
interpreter.GetExecutionContext().GetBestExecutionContextScope(),
- strm, sc_list, verbose);
+ strm, sc_list, verbose, all_ranges);
return num_matches;
}
}
@@ -3598,6 +3601,10 @@
case 'r':
m_use_regex = true;
break;
+
+ case '\x01':
+ m_all_ranges = true;
+ break;
default:
llvm_unreachable("Unimplemented option");
}
@@ -3614,6 +3621,7 @@
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 @@
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 @@
(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 @@
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 @@
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 @@
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;
}
Index: lldb/include/lldb/Symbol/Variable.h
===================================================================
--- lldb/include/lldb/Symbol/Variable.h
+++ lldb/include/lldb/Symbol/Variable.h
@@ -77,7 +77,9 @@
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;
Index: lldb/include/lldb/Expression/DWARFExpression.h
===================================================================
--- lldb/include/lldb/Expression/DWARFExpression.h
+++ lldb/include/lldb/Expression/DWARFExpression.h
@@ -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 @@
/// \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 @@
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>
Index: lldb/include/lldb/Core/Address.h
===================================================================
--- lldb/include/lldb/Core/Address.h
+++ lldb/include/lldb/Core/Address.h
@@ -229,6 +229,14 @@
/// \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 @@
/// \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;
_______________________________________________
lldb-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits