From 9786d3d019f1486d209af67bd18adfc8971a116e Mon Sep 17 00:00:00 2001 From: Frederic Riss Date: Sat, 14 Mar 2015 03:46:51 +0000 Subject: [PATCH] [dsymutil] Generate debug_aranges section. This actually shares most of its implementation with the generation of the debug_ranges (the absence of 'a' is not a typo) contribution for the unit's DW_AT_ranges attribute. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@232246 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../tools/dsymutil/X86/basic-linking-x86.test | 10 +++ .../X86/basic-lto-dw4-linking-x86.test | 8 ++ .../dsymutil/X86/basic-lto-linking-x86.test | 8 ++ tools/dsymutil/DwarfLinker.cpp | 86 +++++++++++++++---- 4 files changed, 93 insertions(+), 19 deletions(-) diff --git a/test/tools/dsymutil/X86/basic-linking-x86.test b/test/tools/dsymutil/X86/basic-linking-x86.test index 1dae3d34197..7958d83c7e2 100644 --- a/test/tools/dsymutil/X86/basic-linking-x86.test +++ b/test/tools/dsymutil/X86/basic-linking-x86.test @@ -129,3 +129,13 @@ CHECK: DW_AT_frame_base [DW_FORM_block1] (<0x01> 56 ) CHECK: NULL +CHECK:.debug_aranges contents: +CHECK-NEXT:Address Range Header: length = 0x0000002c, version = 0x0002, cu_offset = 0x00000000, addr_size = 0x08, seg_size = 0x00 +CHECK-NEXT:[0x0000000100000ea0 - 0x0000000100000ec4) +CHECK-NEXT:Address Range Header: length = 0x0000003c, version = 0x0002, cu_offset = 0x00000081, addr_size = 0x08, seg_size = 0x00 +CHECK-NEXT:[0x0000000100000ed0 - 0x0000000100000f19) +CHECK-NEXT:[0x0000000100000f20 - 0x0000000100000f37) +CHECK-NEXT:Address Range Header: length = 0x0000003c, version = 0x0002, cu_offset = 0x00000126, addr_size = 0x08, seg_size = 0x00 +CHECK-NEXT:[0x0000000100000f40 - 0x0000000100000f84) +CHECK-NEXT:[0x0000000100000f90 - 0x0000000100000fa9) + diff --git a/test/tools/dsymutil/X86/basic-lto-dw4-linking-x86.test b/test/tools/dsymutil/X86/basic-lto-dw4-linking-x86.test index 094000aafd5..40b578ad865 100644 --- a/test/tools/dsymutil/X86/basic-lto-dw4-linking-x86.test +++ b/test/tools/dsymutil/X86/basic-lto-dw4-linking-x86.test @@ -105,3 +105,11 @@ CHECK: [0x0000000100000f9f - 0x0000000100000fa7)) CHECK: NULL CHECK: NULL + +CHECK: .debug_aranges contents: +CHECK-NEXT: Address Range Header: length = 0x0000002c, version = 0x0002, cu_offset = 0x00000000, addr_size = 0x08, seg_size = 0x00 +CHECK-NEXT: [0x0000000100000f40 - 0x0000000100000f4b) +CHECK-NEXT: Address Range Header: length = 0x0000002c, version = 0x0002, cu_offset = 0x00000077, addr_size = 0x08, seg_size = 0x00 +CHECK-NEXT: [0x0000000100000f50 - 0x0000000100000f87) +CHECK-NEXT: Address Range Header: length = 0x0000002c, version = 0x0002, cu_offset = 0x0000011b, addr_size = 0x08, seg_size = 0x00 +CHECK-NEXT: [0x0000000100000f90 - 0x0000000100000fb4) diff --git a/test/tools/dsymutil/X86/basic-lto-linking-x86.test b/test/tools/dsymutil/X86/basic-lto-linking-x86.test index 5322bde92d9..8db5bc54c66 100644 --- a/test/tools/dsymutil/X86/basic-lto-linking-x86.test +++ b/test/tools/dsymutil/X86/basic-lto-linking-x86.test @@ -119,3 +119,11 @@ CHECK: DW_TAG_subprogram [11] CHECK: DW_AT_name [DW_FORM_strp] ( .debug_str[0x0000008a] = "inc") CHECK: DW_AT_type [DW_FORM_ref_addr] (0x0000000000000063) CHECK: NULL + +CHECK: .debug_aranges contents: +CHECK-NEXT: Address Range Header: length = 0x0000002c, version = 0x0002, cu_offset = 0x00000000, addr_size = 0x08, seg_size = 0x00 +CHECK-NEXT: [0x0000000100000f40 - 0x0000000100000f4b) +CHECK-NEXT: Address Range Header: length = 0x0000002c, version = 0x0002, cu_offset = 0x00000081, addr_size = 0x08, seg_size = 0x00 +CHECK-NEXT: [0x0000000100000f50 - 0x0000000100000f89) +CHECK-NEXT: Address Range Header: length = 0x0000002c, version = 0x0002, cu_offset = 0x0000013a, addr_size = 0x08, seg_size = 0x00 +CHECK-NEXT: [0x0000000100000f90 - 0x0000000100000fb4) diff --git a/tools/dsymutil/DwarfLinker.cpp b/tools/dsymutil/DwarfLinker.cpp index 4a474057824..295e6160fd3 100644 --- a/tools/dsymutil/DwarfLinker.cpp +++ b/tools/dsymutil/DwarfLinker.cpp @@ -361,8 +361,10 @@ public: const std::vector &Entries, unsigned AddressSize); - /// \brief Emit debug_ranges entries for a DW_TAG_compile_unit's DW_AT_ranges. - void emitUnitRangesEntries(CompileUnit &Unit); + /// \brief Emit debug_aranges entries for \p Unit and if \p + /// DoRangesSection is true, also emit the debug_ranges entries for + /// the DW_TAG_compile_unit's DW_AT_ranges attribute. + void emitUnitRangesEntries(CompileUnit &Unit, bool DoRangesSection); uint32_t getRangesSectionSize() const { return RangesSectionSize; } }; @@ -532,14 +534,13 @@ void DwarfStreamer::emitRangesEntries( RangesSectionSize += 2 * AddressSize; } -/// \brief Emit the debug_range contents for a compile_unit level -/// DW_AT_ranges attribute. Just aggregate all the ranges gathered -/// inside that unit. -void DwarfStreamer::emitUnitRangesEntries(CompileUnit &Unit) { - MS->SwitchSection(MC->getObjectFileInfo()->getDwarfRangesSection()); - - // Offset each range by the right amount. - int64_t PcOffset = -Unit.getLowPc(); +/// \brief Emit the debug_aranges contribution of a unit and +/// if \p DoDebugRanges is true the debug_range contents for a +/// compile_unit level DW_AT_ranges attribute (Which are basically the +/// same thing with a different base address). +/// Just aggregate all the ranges gathered inside that unit. +void DwarfStreamer::emitUnitRangesEntries(CompileUnit &Unit, + bool DoDebugRanges) { unsigned AddressSize = Unit.getOrigUnit().getAddressByteSize(); // Gather the ranges in a vector, so that we can simplify them. The // IntervalMap will have coalesced the non-linked ranges, but here @@ -548,19 +549,65 @@ void DwarfStreamer::emitUnitRangesEntries(CompileUnit &Unit) { const auto &FunctionRanges = Unit.getFunctionRanges(); for (auto Range = FunctionRanges.begin(), End = FunctionRanges.end(); Range != End; ++Range) - Ranges.push_back(std::make_pair(Range.start() + Range.value() + PcOffset, - Range.stop() + Range.value() + PcOffset)); + Ranges.push_back(std::make_pair(Range.start() + Range.value(), + Range.stop() + Range.value())); // The object addresses where sorted, but again, the linked // addresses might end up in a different order. std::sort(Ranges.begin(), Ranges.end()); + if (!Ranges.empty()) { + MS->SwitchSection(MC->getObjectFileInfo()->getDwarfARangesSection()); + + MCSymbol *BeginLabel = Asm->GetTempSymbol("Barange", Unit.getUniqueID()); + MCSymbol *EndLabel = Asm->GetTempSymbol("Earange", Unit.getUniqueID()); + + unsigned HeaderSize = + sizeof(int32_t) + // Size of contents (w/o this field + sizeof(int16_t) + // DWARF ARange version number + sizeof(int32_t) + // Offset of CU in the .debug_info section + sizeof(int8_t) + // Pointer Size (in bytes) + sizeof(int8_t); // Segment Size (in bytes) + + unsigned TupleSize = AddressSize * 2; + unsigned Padding = OffsetToAlignment(HeaderSize, TupleSize); + + Asm->EmitLabelDifference(EndLabel, BeginLabel, 4); // Arange length + Asm->OutStreamer.EmitLabel(BeginLabel); + Asm->EmitInt16(dwarf::DW_ARANGES_VERSION); // Version number + Asm->EmitInt32(Unit.getStartOffset()); // Corresponding unit's offset + Asm->EmitInt8(AddressSize); // Address size + Asm->EmitInt8(0); // Segment size + + Asm->OutStreamer.EmitFill(Padding, 0x0); + + for (auto Range = Ranges.begin(), End = Ranges.end(); Range != End; + ++Range) { + uint64_t RangeStart = Range->first; + MS->EmitIntValue(RangeStart, AddressSize); + while ((Range + 1) != End && Range->second == (Range + 1)->first) + ++Range; + MS->EmitIntValue(Range->second - RangeStart, AddressSize); + } + + // Emit terminator + Asm->OutStreamer.EmitIntValue(0, AddressSize); + Asm->OutStreamer.EmitIntValue(0, AddressSize); + Asm->OutStreamer.EmitLabel(EndLabel); + } + + if (!DoDebugRanges) + return; + + MS->SwitchSection(MC->getObjectFileInfo()->getDwarfRangesSection()); + // Offset each range by the right amount. + int64_t PcOffset = -Unit.getLowPc(); // Emit coalesced ranges. for (auto Range = Ranges.begin(), End = Ranges.end(); Range != End; ++Range) { - MS->EmitIntValue(Range->first, AddressSize); + MS->EmitIntValue(Range->first + PcOffset, AddressSize); while (Range + 1 != End && Range->second == (Range + 1)->first) ++Range; - MS->EmitIntValue(Range->second, AddressSize); + MS->EmitIntValue(Range->second + PcOffset, AddressSize); RangesSectionSize += 2 * AddressSize; } @@ -1707,16 +1754,17 @@ void DwarfLinker::patchRangesForUnit(const CompileUnit &Unit, } } -/// \brief Generate the debug_ranges entries for \p Unit's -/// DW_AT_ranges attribute if there is one. +/// \brief Generate the debug_aranges entries for \p Unit and if the +/// unit has a DW_AT_ranges attribute, also emit the debug_ranges +/// contribution for this attribute. /// FIXME: this could actually be done right in patchRangesForUnit, /// but for the sake of initial bit-for-bit compatibility with legacy /// dsymutil, we have to do it in a delayed pass. void DwarfLinker::generateUnitRanges(CompileUnit &Unit) const { - if (DIEInteger *Attr = Unit.getUnitRangesAttribute()) { + DIEInteger *Attr = Unit.getUnitRangesAttribute(); + if (Attr) Attr->setValue(Streamer->getRangesSectionSize()); - Streamer->emitUnitRangesEntries(Unit); - } + Streamer->emitUnitRangesEntries(Unit, Attr != nullptr); } bool DwarfLinker::link(const DebugMap &Map) { -- 2.34.1