This is an archive of the discontinued LLVM Phabricator instance.

[LLDB] - Add support for DW_RLE_base_address and DW_RLE_offset_pair entries (.debug_rnglists)
ClosedPublic

Authored by grimar on Oct 11 2018, 7:54 AM.

Diff Detail

Repository
rL LLVM

Event Timeline

grimar created this revision.Oct 11 2018, 7:54 AM

See inlined comments.

source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.cpp
150–151 ↗(On Diff #169211)

Might be nice to not push a base address entry and store the base address locally and fixup any DW_RLE_offset_pair entries on the fly?

source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.h
51–55 ↗(On Diff #169211)

Do we really need to store all this? Can't we just convert to address ranges on the fly in DWARFDebugRngLists::Extract? With the current DW_RLE_base_address and DW_RLE_offset_pair stuff we can store the base address locally inside the DWARFDebugRngLists::Extract function and skip pushing an entry for it and then convert any DW_RLE_offset_pair stuff into addresses by adding the base address before pushing the range. Or will this be required to support other opcodes?

grimar added inline comments.Oct 12 2018, 3:40 AM
source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.h
51–55 ↗(On Diff #169211)

I think we can not do that in DWARFDebugRngLists::Extract because we should take
in account that we can have multiple CU with different address bases.

Example:
https://github.com/llvm-mirror/lldb/blob/master/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp#L1069
In this code dwarf2Data->DebugRanges() call Extract which extracts all ranges from .debug_range section.
But at the moment of extraction, it does not know the base address for a given CU and that is why code calls
range.Slide after that I believe.

Here is an example I have in mind for this patch. The executable below contains 2 CUs and 2 contibution in .debug_rnglists (one for each CU)

.debug_info contents:
0x00000000: Compile Unit: length = 0x000000ac version = 0x0005 unit_type = DW_UT_compile abbr_offset = 0x0000 addr_size = 0x08 (next unit at 0x000000b0)

0x0000000c: DW_TAG_compile_unit [1] *
...
              DW_AT_low_pc [DW_FORM_addr]	(0x0000000000400520)
              DW_AT_high_pc [DW_FORM_data4]	(0x00000034)
              DW_AT_rnglists_base [DW_FORM_sec_offset]	(0x0000000c)

...
0x000000b0: Compile Unit: length = 0x000000a1 version = 0x0005 unit_type = DW_UT_compile abbr_offset = 0x00ad addr_size = 0x08 (next unit at 0x00000155)

0x000000bc: DW_TAG_compile_unit [1] *
....
              DW_AT_low_pc [DW_FORM_addr]	(0x0000000000400560)
              DW_AT_high_pc [DW_FORM_data4]	(0x00000027)
              DW_AT_rnglists_base [DW_FORM_sec_offset]	(0x0000001f)
.debug_rnglists contents:
0x00000000: range list header: length = 0x0000000f, version = 0x0005, addr_size = 0x08, seg_size = 0x00, offset_entry_count = 0x00000000
ranges:
0x0000000c: [DW_RLE_offset_pair]:  0x0000000000000005, 0x0000000000000012 => [0x0000000000000005, 0x0000000000000012)
0x0000000f: [DW_RLE_offset_pair]:  0x0000000000000017, 0x000000000000001d => [0x0000000000000017, 0x000000000000001d)
0x00000012: [DW_RLE_end_of_list]
0x00000013: range list header: length = 0x0000000f, version = 0x0005, addr_size = 0x08, seg_size = 0x00, offset_entry_count = 0x00000000
ranges:
0x0000001f: [DW_RLE_offset_pair]:  0x0000000000000005, 0x0000000000000012 => [0x0000000000000005, 0x0000000000000012)
0x00000022: [DW_RLE_offset_pair]:  0x0000000000000017, 0x000000000000001d => [0x0000000000000017, 0x000000000000001d)
0x00000025: [DW_RLE_end_of_list]

With that, it seems we want to parse the .debug_rnglists section once, but for each CU we have different contribution offset (DW_AT_rnglists_base) and the different base address (DW_AT_low_pc), so I think should fix up the ranges parsed independently.
That is why I had to store RngListEntry list and doing the fixup in FindRanges.

As an improvement we might want to cache the result returned by FindRanges somehow I think, so for further calls of FindRanges
for a given CU we would not need to do a fixup and can just return the ranges list built earlier.

grimar updated this revision to Diff 170050.Oct 18 2018, 1:42 AM
  • Rebased, resolved conflicts.
clayborg accepted this revision.Oct 23 2018, 9:31 AM
This revision is now accepted and ready to land.Oct 23 2018, 9:31 AM
This revision was automatically updated to reflect the committed changes.

It looks like this might have broken the bots, could you please take a look?

http://green.lab.llvm.org/green/view/LLDB/job/lldb-cmake/11671/consoleFull#434797663d489585b-5106-414a-ac11-3ff90657619c

******************** TEST 'lldb :: Breakpoint/debug_rnglist_rlestartend.test' FAILED ********************
Script:
--
: 'RUN: at line 1';   /Users/buildslave/jenkins/workspace/lldb-cmake/lldb-build/bin/yaml2obj /Users/buildslave/jenkins/workspace/lldb-cmake/llvm/tools/lldb/lit/Breakpoint/Inputs/debug_rnglist_rlestartend.yaml > /Users/buildslave/jenkins/workspace/lldb-cmake/lldb-build/tools/lldb/lit/Breakpoint/Output/debug_rnglist_rlestartend.test.tmptest
: 'RUN: at line 2';   /Users/buildslave/jenkins/workspace/lldb-cmake/lldb-build/bin/lldb-test breakpoints /Users/buildslave/jenkins/workspace/lldb-cmake/lldb-build/tools/lldb/lit/Breakpoint/Output/debug_rnglist_rlestartend.test.tmptest /Users/buildslave/jenkins/workspace/lldb-cmake/llvm/tools/lldb/lit/Breakpoint/debug_rnglist_rlestartend.test | /Users/buildslave/jenkins/workspace/lldb-cmake/lldb-build/bin/FileCheck /Users/buildslave/jenkins/workspace/lldb-cmake/llvm/tools/lldb/lit/Breakpoint/debug_rnglist_rlestartend.test
--
Exit Code: 2

Command Output (stderr):
--
unexpected encoding
UNREACHABLE executed at /Users/buildslave/jenkins/workspace/lldb-cmake/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.cpp:202!
0  lldb-test                0x0000000105a27d65 llvm::sys::PrintStackTrace(llvm::raw_ostream&) + 37
1  lldb-test                0x0000000105a26c96 llvm::sys::RunSignalHandlers() + 198
2  lldb-test                0x0000000105a283c8 SignalHandler(int) + 264
3  libsystem_platform.dylib 0x00007fff78d08f5a _sigtramp + 26
4  libsystem_platform.dylib 0x00007ffeea2c9da8 _sigtramp + 1901858408
5  libsystem_c.dylib        0x00007fff78aa61ae abort + 127
6  lldb-test                0x000000010599797c llvm::llvm_unreachable_internal(char const*, char const*, unsigned int) + 540
7  lldb-test                0x0000000105eaeba9 DWARFDebugRngLists::FindRanges(DWARFUnit const*, unsigned int, lldb_private::RangeArray<unsigned long long, unsigned long long, 2u>&) const + 457
8  lldb-test                0x0000000105ea9dcc DWARFDebugInfoEntry::GetAttributeAddressRanges(SymbolFileDWARF*, DWARFUnit const*, lldb_private::RangeArray<unsigned long long, unsigned long long, 2u>&, bool, bool) const + 140
9  lldb-test                0x0000000105eb4114 DWARFUnit::BuildAddressRangeTable(SymbolFileDWARF*, DWARFDebugAranges*) + 116
10 lldb-test                0x0000000105ea6bd1 DWARFDebugInfo::GetCompileUnitAranges() + 1025
11 lldb-test                0x0000000105ec4c0f SymbolFileDWARF::ResolveSymbolContext(lldb_private::Address const&, unsigned int, lldb_private::SymbolContext&) + 255
12 lldb-test                0x0000000105ba76bf lldb_private::SymbolVendor::ResolveSymbolContext(lldb_private::Address const&, unsigned int, lldb_private::SymbolContext&) + 95
13 lldb-test                0x0000000105a8305b lldb_private::Module::ResolveSymbolContextForAddress(lldb_private::Address const&, unsigned int, lldb_private::SymbolContext&, bool) + 459
14 lldb-test                0x0000000105a49b3d lldb_private::Address::CalculateSymbolContext(lldb_private::SymbolContext*, unsigned int) const + 205
15 lldb-test                0x0000000105a33e67 lldb_private::BreakpointLocation::GetDescription(lldb_private::Stream*, lldb::DescriptionLevel) + 279
16 lldb-test                0x0000000105a2e591 lldb_private::Breakpoint::GetDescription(lldb_private::Stream*, lldb::DescriptionLevel, bool) + 849
17 lldb-test                0x000000010713ba1a CommandObjectBreakpointSet::DoExecute(lldb_private::Args&, lldb_private::CommandReturnObject&) + 3082
18 lldb-test                0x0000000105b2daa2 lldb_private::CommandObjectParsed::Execute(char const*, lldb_private::CommandReturnObject&) + 418
19 lldb-test                0x0000000105b26485 lldb_private::CommandInterpreter::HandleCommand(char const*, lldb_private::LazyBool, lldb_private::CommandReturnObject&, lldb_private::ExecutionContext*, bool, bool) + 2869
20 lldb-test                0x0000000105b2eb31 lldb_private::CommandObjectRegexCommand::DoExecute(llvm::StringRef, lldb_private::CommandReturnObject&) + 849
21 lldb-test                0x0000000105b2dcd6 lldb_private::CommandObjectRaw::Execute(char const*, lldb_private::CommandReturnObject&) + 470
22 lldb-test                0x0000000105b26485 lldb_private::CommandInterpreter::HandleCommand(char const*, lldb_private::LazyBool, lldb_private::CommandReturnObject&, lldb_private::ExecutionContext*, bool, bool) + 2869
23 lldb-test                0x000000010593c474 main + 1716
24 libdyld.dylib            0x00007fff789fa015 start + 1
25 libdyld.dylib            0x0000000000000004 start + 2271240176
Stack dump:
0.	Program arguments: /Users/buildslave/jenkins/workspace/lldb-cmake/lldb-build/bin/lldb-test breakpoints /Users/buildslave/jenkins/workspace/lldb-cmake/lldb-build/tools/lldb/lit/Breakpoint/Output/debug_rnglist_rlestartend.test.tmptest /Users/buildslave/jenkins/workspace/lldb-cmake/llvm/tools/lldb/lit/Breakpoint/debug_rnglist_rlestartend.test 
1.	HandleCommand(command = "b main")
2.	HandleCommand(command = "breakpoint set --name 'main'")
FileCheck error: '-' is empty.
FileCheck command line:  /Users/buildslave/jenkins/workspace/lldb-cmake/lldb-build/bin/FileCheck /Users/buildslave/jenkins/workspace/lldb-cmake/llvm/tools/lldb/lit/Breakpoint/debug_rnglist_rlestartend.test

--