diff --git a/lldb/include/lldb/Core/Address.h b/lldb/include/lldb/Core/Address.h --- a/lldb/include/lldb/Core/Address.h +++ b/lldb/include/lldb/Core/Address.h @@ -238,7 +238,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 print_var_ranges = false) const; AddressClass GetAddressClass() const; diff --git a/lldb/source/Commands/CommandObjectTarget.cpp b/lldb/source/Commands/CommandObjectTarget.cpp --- a/lldb/source/Commands/CommandObjectTarget.cpp +++ b/lldb/source/Commands/CommandObjectTarget.cpp @@ -1429,7 +1429,8 @@ } static void DumpAddress(ExecutionContextScope *exe_scope, - const Address &so_addr, bool verbose, Stream &strm) { + const Address &so_addr, bool verbose, + bool print_var_ranges, Stream &strm) { strm.IndentMore(); strm.Indent(" Address: "); so_addr.Dump(&strm, exe_scope, Address::DumpStyleModuleWithFileAddress); @@ -1444,7 +1445,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, print_var_ranges); } strm.IndentLess(); } @@ -1452,7 +1454,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 print_var_ranges) { if (module) { lldb::addr_t addr = raw_addr - offset; Address so_addr; @@ -1470,7 +1472,7 @@ ExecutionContextScope *exe_scope = interpreter.GetExecutionContext().GetBestExecutionContextScope(); - DumpAddress(exe_scope, so_addr, verbose, strm); + DumpAddress(exe_scope, so_addr, verbose, print_var_ranges, strm); // strm.IndentMore(); // strm.Indent (" Address: "); // so_addr.Dump (&strm, exe_scope, @@ -1502,7 +1504,7 @@ static uint32_t LookupSymbolInModule(CommandInterpreter &interpreter, Stream &strm, Module *module, const char *name, bool name_is_regex, - bool verbose) { + bool verbose, bool print_var_ranges) { if (!module) return 0; @@ -1535,7 +1537,7 @@ if (symbol && symbol->ValueIsAddress()) { DumpAddress( interpreter.GetExecutionContext().GetBestExecutionContextScope(), - symbol->GetAddressRef(), verbose, strm); + symbol->GetAddressRef(), verbose, print_var_ranges, strm); } } strm.IndentLess(); @@ -1545,7 +1547,7 @@ static void DumpSymbolContextList(ExecutionContextScope *exe_scope, Stream &strm, SymbolContextList &sc_list, - bool verbose) { + bool verbose, bool print_var_ranges) { strm.IndentMore(); const uint32_t num_matches = sc_list.GetSize(); @@ -1557,7 +1559,8 @@ sc.GetAddressRange(eSymbolContextEverything, 0, true, range); - DumpAddress(exe_scope, range.GetBaseAddress(), verbose, strm); + DumpAddress(exe_scope, range.GetBaseAddress(), verbose, print_var_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 print_var_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, print_var_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 print_var_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, print_var_ranges); return num_matches; } } @@ -3598,6 +3601,9 @@ case 'r': m_use_regex = true; break; + case 'R': + m_var_ranges = true; + break; default: llvm_unreachable("Unimplemented option"); } @@ -3614,6 +3620,7 @@ m_line_number = 0; m_use_regex = false; m_include_inlines = true; + m_var_ranges = false; m_verbose = false; m_print_all = false; } @@ -3632,6 +3639,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_var_ranges; // Print the valid ranges of variables. 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 +3722,8 @@ (m_options.m_verbose ? static_cast(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_var_ranges)) { result.SetStatus(eReturnStatusSuccessFinishResult); return true; } @@ -3725,7 +3734,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_var_ranges)) { result.SetStatus(eReturnStatusSuccessFinishResult); return true; } @@ -3737,7 +3747,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_var_ranges)) { result.SetStatus(eReturnStatusSuccessFinishResult); return true; } @@ -3755,7 +3766,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_var_ranges)) { result.SetStatus(eReturnStatusSuccessFinishResult); return true; } diff --git a/lldb/source/Commands/Options.td b/lldb/source/Commands/Options.td --- a/lldb/source/Commands/Options.td +++ b/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-variables-ranges", + "R">, 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, " diff --git a/lldb/source/Core/Address.cpp b/lldb/source/Core/Address.cpp --- a/lldb/source/Core/Address.cpp +++ b/lldb/source/Core/Address.cpp @@ -403,7 +403,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 print_var_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,10 +721,18 @@ 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, + [&file_addr](Variable *var) { + // Variables created from Dwarf always have empty scope range. + if (var->GetScopeRange().IsEmpty()) + return true; + return var->GetScopeRange().FindEntryThatContains(file_addr) != + nullptr; + }, + &variable_list); for (const VariableSP &var_sp : variable_list) { if (var_sp && var_sp->LocationIsValidForAddress(*this)) { @@ -739,6 +748,18 @@ var_sp->DumpLocationForAddress(s, *this); s->PutCString(", decl = "); var_sp->GetDeclaration().DumpStopContext(s, false); + if (print_var_ranges) { + s->PutCString(", valid ranges ="); + for (auto range : var_sp->GetScopeRange()) { + s->PutCString(" ["); + s->AsRawOstream() << llvm::format_hex(range.GetRangeBase(), + 2 + 2 * addr_size); + s->PutCString("-"); + s->AsRawOstream() << llvm::format_hex(range.GetRangeEnd(), + 2 + 2 * addr_size); + s->PutCString(")"); + } + } s->EOL(); } } diff --git a/lldb/test/Shell/SymbolFile/DWARF/x86/debug_loc.s b/lldb/test/Shell/SymbolFile/DWARF/x86/debug_loc.s --- a/lldb/test/Shell/SymbolFile/DWARF/x86/debug_loc.s +++ b/lldb/test/Shell/SymbolFile/DWARF/x86/debug_loc.s @@ -5,21 +5,21 @@ # UNSUPPORTED: lldb-repro # RUN: llvm-mc -triple=x86_64-pc-linux -filetype=obj %s --defsym LOC=0 > %t -# RUN: %lldb %t -o "image lookup -v -a 0" -o "image lookup -v -a 2" \ +# RUN: %lldb %t -o "image lookup -v -a 0 -R" -o "image lookup -v -a 2 -R" \ # RUN: -o "image dump symfile" -o exit | FileCheck %s # 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: %lldb %t -o "image lookup -v -a 0 -R" -o "image lookup -v -a 2 -R" \ # RUN: -o "image dump symfile" -o exit | FileCheck %s --check-prefix=CHECK --check-prefix=LOCLISTS -# 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 = , +# CHECK-LABEL: image lookup -v -a 0 -R +# CHECK: Variable: {{.*}}, name = "x0", type = "int", location = DW_OP_reg5 RDI, decl = , valid ranges = +# CHECK: Variable: {{.*}}, name = "x1", type = "int", location = , decl = , valid ranges = -# 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 = , -# CHECK: Variable: {{.*}}, name = "x3", type = "int", location = DW_OP_reg1 RDX, +# CHECK-LABEL: image lookup -v -a 2 -R +# CHECK: Variable: {{.*}}, name = "x0", type = "int", location = DW_OP_reg0 RAX, decl = , valid ranges = +# CHECK: Variable: {{.*}}, name = "x1", type = "int", location = , decl = , valid ranges = +# CHECK: Variable: {{.*}}, name = "x3", type = "int", location = DW_OP_reg1 RDX, decl = , valid ranges = # CHECK-LABEL: image dump symfile # CHECK: CompileUnit{0x00000000}