From 1a50207f4ea575da2a3e861369227ce9f1d885e7 Mon Sep 17 00:00:00 2001 From: Alexey Lapshin Date: Sun, 26 Feb 2023 18:57:50 +0100 Subject: [PATCH] [DWARFLinker][DWARFv5] Add support for .debug_rnglists. This patch adds support of DWARFv5 .debug_rnglists table. As DWARFLinker resolves relocations, it is able to always use DW_FORM_addr instead of DW_FORM_addrx. DW_FORM_addrx helps to minimize number of relocations, it is also used for split DWARF. Both of these cases are not relevant for the DWARFLinker. Thus, this patch converts all DW_FORM_addrx forms into the DW_FORM_addr. And, as the result, it converts range lists of DW_FORM_rnglistx form into the DW_FORM_sec_offset. For the --update case all DW_FORM_addrx, DW_FORM_rnglistx are preserved as is. Reviewed By: aprantl Differential Revision: https://reviews.llvm.org/D143903 --- llvm/include/llvm/DWARFLinker/DWARFLinker.h | 37 +-- .../llvm/DWARFLinker/DWARFLinkerCompileUnit.h | 18 +- llvm/include/llvm/DWARFLinker/DWARFStreamer.h | 39 ++- llvm/lib/DWARFLinker/DWARFLinker.cpp | 190 ++++++++------- llvm/lib/DWARFLinker/DWARFLinkerCompileUnit.cpp | 8 +- llvm/lib/DWARFLinker/DWARFStreamer.cpp | 116 +++++++-- llvm/test/tools/dsymutil/Inputs/dwarf5-rnglists.o | Bin 0 -> 2220 bytes llvm/test/tools/dsymutil/X86/dwarf5-addrx.test | 68 +++++- llvm/test/tools/dsymutil/X86/dwarf5-rnglists.test | 87 +++++++ .../test/tools/dsymutil/X86/op-convert-offset.test | 8 +- .../tools/llvm-dwarfutil/ELF/X86/dwarf5-addrx.test | 39 ++- .../llvm-dwarfutil/ELF/X86/dwarf5-rnglists.test | 264 +++++++++++++++++++++ .../ELF/X86/warning-skipped-rnglists.test | 54 ----- 13 files changed, 721 insertions(+), 207 deletions(-) create mode 100644 llvm/test/tools/dsymutil/Inputs/dwarf5-rnglists.o create mode 100644 llvm/test/tools/dsymutil/X86/dwarf5-rnglists.test create mode 100644 llvm/test/tools/llvm-dwarfutil/ELF/X86/dwarf5-rnglists.test delete mode 100644 llvm/test/tools/llvm-dwarfutil/ELF/X86/warning-skipped-rnglists.test diff --git a/llvm/include/llvm/DWARFLinker/DWARFLinker.h b/llvm/include/llvm/DWARFLinker/DWARFLinker.h index 30f0c1c..ebfac89 100644 --- a/llvm/include/llvm/DWARFLinker/DWARFLinker.h +++ b/llvm/include/llvm/DWARFLinker/DWARFLinker.h @@ -117,16 +117,23 @@ public: virtual void emitAppleTypes(AccelTable &Table) = 0; - /// Emit piece of .debug_ranges for \p Ranges. + /// Emit debug ranges(.debug_ranges, .debug_rnglists) header. + virtual MCSymbol *emitDwarfDebugRangeListHeader(const CompileUnit &Unit) = 0; + + /// Emit debug ranges(.debug_ranges, .debug_rnglists) fragment. virtual void - emitDwarfDebugRangesTableFragment(const CompileUnit &Unit, - const AddressRanges &LinkedRanges) = 0; + emitDwarfDebugRangeListFragment(const CompileUnit &Unit, + const AddressRanges &LinkedRanges, + PatchLocation Patch) = 0; + + /// Emit debug ranges(.debug_ranges, .debug_rnglists) footer. + virtual void emitDwarfDebugRangeListFooter(const CompileUnit &Unit, + MCSymbol *EndLabel) = 0; - /// 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. - virtual void emitUnitRangesEntries(CompileUnit &Unit, - bool DoRangesSection) = 0; + /// Emit .debug_aranges entries for \p Unit + virtual void + emitDwarfDebugArangesTable(const CompileUnit &Unit, + const AddressRanges &LinkedRanges) = 0; /// Copy the .debug_line over to the updated binary while unobfuscating the /// file names and directories. @@ -189,6 +196,9 @@ public: /// Returns size of generated .debug_ranges section. virtual uint64_t getRangesSectionSize() const = 0; + /// Returns size of generated .debug_rnglists section. + virtual uint64_t getRngListsSectionSize() const = 0; + /// Returns size of generated .debug_info section. virtual uint64_t getDebugInfoSectionSize() const = 0; @@ -724,14 +734,9 @@ private: /// Assign an abbreviation number to \p Abbrev void assignAbbrev(DIEAbbrev &Abbrev); - /// Compute and emit .debug_ranges section for \p Unit, and - /// patch the attributes referencing it. - void patchRangesForUnit(const CompileUnit &Unit, DWARFContext &Dwarf, - const DWARFFile &File) const; - - /// Generate and emit the DW_AT_ranges attribute for a compile_unit if it had - /// one. - void generateUnitRanges(CompileUnit &Unit) const; + /// Compute and emit debug ranges(.debug_aranges, .debug_ranges, + /// .debug_rnglists) for \p Unit, patch the attributes referencing it. + void generateUnitRanges(CompileUnit &Unit, const DWARFFile &File) const; /// Extract the line tables from the original dwarf, extract the relevant /// parts according to the linked function ranges and emit the result in the diff --git a/llvm/include/llvm/DWARFLinker/DWARFLinkerCompileUnit.h b/llvm/include/llvm/DWARFLinker/DWARFLinkerCompileUnit.h index 9c7f24e..39305a3 100644 --- a/llvm/include/llvm/DWARFLinker/DWARFLinkerCompileUnit.h +++ b/llvm/include/llvm/DWARFLinker/DWARFLinkerCompileUnit.h @@ -43,6 +43,8 @@ struct PatchLocation { } }; +using RngListAttributesTy = SmallVector; + /// Stores all information relating to a compile unit, be it in its original /// instance in the object file to its brand new cloned and generated DIE tree. class CompileUnit { @@ -143,14 +145,12 @@ public: uint64_t getHighPc() const { return HighPc; } bool hasLabelAt(uint64_t Addr) const { return Labels.count(Addr); } - std::optional getUnitRangesAttribute() const { - return UnitRangeAttribute; - } - const RangesTy &getFunctionRanges() const { return Ranges; } - const std::vector &getRangesAttributes() const { - return RangeAttributes; + const RngListAttributesTy &getRangesAttributes() { return RangeAttributes; } + + std::optional getUnitRangesAttribute() const { + return UnitRangeAttribute; } const std::vector> & @@ -278,10 +278,10 @@ private: /// The DW_AT_low_pc of each DW_TAG_label. SmallDenseMap Labels; - /// DW_AT_ranges attributes to patch after we have gathered - /// all the unit's function addresses. + /// 'rnglist'(DW_AT_ranges, DW_AT_start_scope) attributes to patch after + /// we have gathered all the unit's function addresses. /// @{ - std::vector RangeAttributes; + RngListAttributesTy RangeAttributes; std::optional UnitRangeAttribute; /// @} diff --git a/llvm/include/llvm/DWARFLinker/DWARFStreamer.h b/llvm/include/llvm/DWARFLinker/DWARFStreamer.h index 24248c8..69d1f93 100644 --- a/llvm/include/llvm/DWARFLinker/DWARFStreamer.h +++ b/llvm/include/llvm/DWARFLinker/DWARFStreamer.h @@ -93,18 +93,28 @@ public: llvm::binaryformat::Swift5ReflectionSectionKind ReflSectionKind, StringRef Buffer, uint32_t Alignment, uint32_t Size); - /// Emit piece of .debug_ranges for \p Ranges. - virtual void - emitDwarfDebugRangesTableFragment(const CompileUnit &Unit, - const AddressRanges &LinkedRanges) override; + /// Emit debug ranges(.debug_ranges, .debug_rnglists) header. + MCSymbol *emitDwarfDebugRangeListHeader(const CompileUnit &Unit) override; - /// 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) override; + /// Emit debug ranges(.debug_ranges, .debug_rnglists) fragment. + void emitDwarfDebugRangeListFragment(const CompileUnit &Unit, + const AddressRanges &LinkedRanges, + PatchLocation Patch) override; + + /// Emit debug ranges(.debug_ranges, .debug_rnglists) footer. + void emitDwarfDebugRangeListFooter(const CompileUnit &Unit, + MCSymbol *EndLabel) override; + + /// Emit .debug_aranges entries for \p Unit + void emitDwarfDebugArangesTable(const CompileUnit &Unit, + const AddressRanges &LinkedRanges) override; uint64_t getRangesSectionSize() const override { return RangesSectionSize; } + uint64_t getRngListsSectionSize() const override { + return RngListsSectionSize; + } + /// Emit the debug_loc contribution for \p Unit by copying the entries from /// \p Dwarf and offsetting them. Update the location attributes to point to /// the new entries. @@ -189,8 +199,16 @@ private: void emitMacroTableImpl(const DWARFDebugMacro *MacroTable, const Offset2UnitMap &UnitMacroMap, OffsetsStringPool &StringPool, uint64_t &OutOffset); - void emitDwarfDebugArangesTable(const CompileUnit &Unit, - const AddressRanges &LinkedRanges); + + /// Emit piece of .debug_ranges for \p LinkedRanges. + void emitDwarfDebugRangesTableFragment(const CompileUnit &Unit, + const AddressRanges &LinkedRanges, + PatchLocation Patch); + + /// Emit piece of .debug_rnglists for \p LinkedRanges. + void emitDwarfDebugRngListsTableFragment(const CompileUnit &Unit, + const AddressRanges &LinkedRanges, + PatchLocation Patch); /// \defgroup MCObjects MC layer objects constructed by the streamer /// @{ @@ -214,6 +232,7 @@ private: std::function Translator; uint64_t RangesSectionSize = 0; + uint64_t RngListsSectionSize = 0; uint64_t LocSectionSize = 0; uint64_t LineSectionSize = 0; uint64_t FrameSectionSize = 0; diff --git a/llvm/lib/DWARFLinker/DWARFLinker.cpp b/llvm/lib/DWARFLinker/DWARFLinker.cpp index abe77ea..7640dfa 100644 --- a/llvm/lib/DWARFLinker/DWARFLinker.cpp +++ b/llvm/lib/DWARFLinker/DWARFLinker.cpp @@ -1203,8 +1203,8 @@ unsigned DWARFLinker::DIECloner::cloneAddressAttribute( dwarf::Form Form = AttrSpec.Form; - // FIXME: Generation of DWARFv5 .debug_addr table is not supported yet. - // Convert attribute into the dwarf::DW_FORM_addr. + // DWARFLinker does not use addrx forms since it generates relocated + // addresses. Replace DW_FORM_addrx with DW_FORM_addr here. if (Form == dwarf::DW_FORM_addrx) Form = dwarf::DW_FORM_addr; @@ -1257,8 +1257,30 @@ unsigned DWARFLinker::DIECloner::cloneScalarAttribute( return AttrSize; } - if (AttrSpec.Attr == dwarf::DW_AT_high_pc && - Die.getTag() == dwarf::DW_TAG_compile_unit) { + [[maybe_unused]] dwarf::Form OriginalForm = AttrSpec.Form; + if (AttrSpec.Form == dwarf::DW_FORM_rnglistx) { + // DWARFLinker does not generate .debug_addr table. Thus we need to change + // all "addrx" related forms to "addr" version. Change DW_FORM_rnglistx + // to DW_FORM_sec_offset here. + std::optional Index = Val.getAsSectionOffset(); + if (!Index) { + Linker.reportWarning("Cannot read the attribute. Dropping.", File, + &InputDIE); + return 0; + } + std::optional Offset = + Unit.getOrigUnit().getRnglistOffset(*Index); + if (!Offset) { + Linker.reportWarning("Cannot read the attribute. Dropping.", File, + &InputDIE); + return 0; + } + + Value = *Offset; + AttrSpec.Form = dwarf::DW_FORM_sec_offset; + AttrSize = Unit.getOrigUnit().getFormParams().getDwarfOffsetByteSize(); + } else if (AttrSpec.Attr == dwarf::DW_AT_high_pc && + Die.getTag() == dwarf::DW_TAG_compile_unit) { std::optional LowPC = Unit.getLowPc(); if (!LowPC) return 0; @@ -1279,11 +1301,11 @@ unsigned DWARFLinker::DIECloner::cloneScalarAttribute( PatchLocation Patch = Die.addValue(DIEAlloc, dwarf::Attribute(AttrSpec.Attr), dwarf::Form(AttrSpec.Form), DIEInteger(Value)); - if (AttrSpec.Attr == dwarf::DW_AT_ranges) { + if (AttrSpec.Attr == dwarf::DW_AT_ranges || + AttrSpec.Attr == dwarf::DW_AT_start_scope) { Unit.noteRangeAttribute(Die, Patch); Info.HasRanges = true; } - // A more generic way to check for location attributes would be // nice, but it's very unlikely that any other attribute needs a // location list. @@ -1294,6 +1316,10 @@ unsigned DWARFLinker::DIECloner::cloneScalarAttribute( } else if (AttrSpec.Attr == dwarf::DW_AT_declaration && Value) Info.IsDeclaration = true; + // check that all dwarf::DW_FORM_rnglistx are handled previously. + assert((Info.HasRanges || (OriginalForm != dwarf::DW_FORM_rnglistx)) && + "Unhandled DW_FORM_rnglistx attribute"); + return AttrSize; } @@ -1343,6 +1369,7 @@ unsigned DWARFLinker::DIECloner::cloneAttribute( case dwarf::DW_FORM_sec_offset: case dwarf::DW_FORM_flag: case dwarf::DW_FORM_flag_present: + case dwarf::DW_FORM_rnglistx: return cloneScalarAttribute(Die, InputDIE, File, Unit, AttrSpec, Val, AttrSize, Info); default: @@ -1412,6 +1439,15 @@ static bool shouldSkipAttribute( case dwarf::DW_AT_high_pc: case dwarf::DW_AT_ranges: return !Update && SkipPC; + case dwarf::DW_AT_addr_base: + // In case !Update the .debug_addr table is not generated/preserved. + return !Update; + case dwarf::DW_AT_rnglists_base: + // In case !Update the .debug_addr table is not generated/preserved. + // Thus instead of DW_FORM_rnglistx the DW_FORM_sec_offset is used. + // Since DW_AT_rnglists_base is used for only DW_FORM_rnglistx the + // DW_AT_rnglists_base is removed. + return !Update; case dwarf::DW_AT_str_offsets_base: // FIXME: Use the string offset table with Dwarf 5. return true; @@ -1612,77 +1648,75 @@ DIE *DWARFLinker::DIECloner::cloneDIE(const DWARFDie &InputDIE, return Die; } -/// Patch the input object file relevant debug_ranges entries -/// and emit them in the output file. Update the relevant attributes +/// Patch the input object file relevant debug_ranges or debug_rnglists +/// entries and emit them in the output file. Update the relevant attributes /// to point at the new entries. -void DWARFLinker::patchRangesForUnit(const CompileUnit &Unit, - DWARFContext &OrigDwarf, +void DWARFLinker::generateUnitRanges(CompileUnit &Unit, const DWARFFile &File) const { - DWARFDebugRangeList RangeList; - const auto &FunctionRanges = Unit.getFunctionRanges(); - unsigned AddressSize = Unit.getOrigUnit().getAddressByteSize(); - DWARFDataExtractor RangeExtractor(OrigDwarf.getDWARFObj(), - OrigDwarf.getDWARFObj().getRangesSection(), - OrigDwarf.isLittleEndian(), AddressSize); - std::optional CachedRange; - DWARFUnit &OrigUnit = Unit.getOrigUnit(); - auto OrigUnitDie = OrigUnit.getUnitDIE(false); - uint64_t UnitBaseAddress = - dwarf::toAddress(OrigUnitDie.find(dwarf::DW_AT_low_pc), 0); - - for (const auto &RangeAttribute : Unit.getRangesAttributes()) { - uint64_t Offset = RangeAttribute.get(); - RangeAttribute.set(TheDwarfEmitter->getRangesSectionSize()); - if (Error E = RangeList.extract(RangeExtractor, &Offset)) { - llvm::consumeError(std::move(E)); - reportWarning("invalid range list ignored.", File); - RangeList.clear(); - } - const auto &Entries = RangeList.getEntries(); - - uint64_t BaseAddress = UnitBaseAddress; - AddressRanges LinkedRanges; - - if (!Entries.empty()) { - for (const auto &Range : Entries) { - if (Range.isBaseAddressSelectionEntry( - Unit.getOrigUnit().getAddressByteSize())) { - BaseAddress = Range.EndAddress; - continue; - } + if (LLVM_UNLIKELY(Options.Update)) + return; - if (!CachedRange || - !CachedRange->Range.contains(Range.StartAddress + BaseAddress)) - CachedRange = FunctionRanges.getRangeThatContains(Range.StartAddress + - BaseAddress); + const auto &FunctionRanges = Unit.getFunctionRanges(); - // All range entries should lie in the function range. - if (!CachedRange) { - reportWarning("inconsistent range data.", File); - continue; + // Build set of linked address ranges for unit function ranges. + AddressRanges LinkedFunctionRanges; + for (const AddressRangeValuePair &Range : FunctionRanges) + LinkedFunctionRanges.insert( + {Range.Range.start() + Range.Value, Range.Range.end() + Range.Value}); + + // Emit LinkedFunctionRanges into .debug_aranges + if (!LinkedFunctionRanges.empty()) + TheDwarfEmitter->emitDwarfDebugArangesTable(Unit, LinkedFunctionRanges); + + RngListAttributesTy AllRngListAttributes = Unit.getRangesAttributes(); + std::optional UnitRngListAttribute = + Unit.getUnitRangesAttribute(); + + if (!AllRngListAttributes.empty() || UnitRngListAttribute) { + std::optional CachedRange; + MCSymbol *EndLabel = TheDwarfEmitter->emitDwarfDebugRangeListHeader(Unit); + + // Read original address ranges, apply relocation value, emit linked address + // ranges. + for (PatchLocation &AttributePatch : AllRngListAttributes) { + // Get ranges from the source DWARF corresponding to the current + // attribute. + AddressRanges LinkedRanges; + if (Expected OriginalRanges = + Unit.getOrigUnit().findRnglistFromOffset(AttributePatch.get())) { + // Apply relocation adjustment. + for (const auto &Range : *OriginalRanges) { + if (!CachedRange || !CachedRange->Range.contains(Range.LowPC)) + CachedRange = FunctionRanges.getRangeThatContains(Range.LowPC); + + // All range entries should lie in the function range. + if (!CachedRange) { + reportWarning("inconsistent range data.", File); + continue; + } + + // Store range for emiting. + LinkedRanges.insert({Range.LowPC + CachedRange->Value, + Range.HighPC + CachedRange->Value}); } - - LinkedRanges.insert( - {Range.StartAddress + BaseAddress + CachedRange->Value, - Range.EndAddress + BaseAddress + CachedRange->Value}); + } else { + llvm::consumeError(OriginalRanges.takeError()); + reportWarning("invalid range list ignored.", File); } + + // Emit linked ranges. + TheDwarfEmitter->emitDwarfDebugRangeListFragment(Unit, LinkedRanges, + AttributePatch); } - TheDwarfEmitter->emitDwarfDebugRangesTableFragment(Unit, LinkedRanges); - } -} + // Emit ranges for Unit AT_ranges attribute. + if (UnitRngListAttribute.has_value()) + TheDwarfEmitter->emitDwarfDebugRangeListFragment( + Unit, LinkedFunctionRanges, *UnitRngListAttribute); -/// 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 { - auto Attr = Unit.getUnitRangesAttribute(); - if (Attr) - Attr->set(TheDwarfEmitter->getRangesSectionSize()); - TheDwarfEmitter->emitUnitRangesEntries(Unit, static_cast(Attr)); + // Emit ranges footer. + TheDwarfEmitter->emitDwarfDebugRangeListFooter(Unit, EndLabel); + } } /// Insert the new line info sequence \p Seq into the current @@ -2265,7 +2299,8 @@ uint64_t DWARFLinker::DIECloner::cloneAllCompileUnits( if (LLVM_UNLIKELY(Linker.Options.Update)) continue; - Linker.patchRangesForUnit(*CurrentUnit, DwarfContext, File); + Linker.generateUnitRanges(*CurrentUnit, File); + auto ProcessExpr = [&](StringRef Bytes, SmallVectorImpl &Buffer) { DWARFUnit &OrigUnit = CurrentUnit->getOrigUnit(); @@ -2287,9 +2322,6 @@ uint64_t DWARFLinker::DIECloner::cloneAllCompileUnits( // Emit all the compile unit's debug information. for (auto &CurrentUnit : CompileUnits) { - if (LLVM_LIKELY(!Linker.Options.Update)) - Linker.generateUnitRanges(*CurrentUnit); - CurrentUnit->fixupForwardReferences(); if (!CurrentUnit->getOutputUnitDIE()) @@ -2384,6 +2416,10 @@ void DWARFLinker::copyInvariantDebugSection(DWARFContext &Dwarf) { Dwarf.getDWARFObj().getFrameSection().Data, "debug_frame"); TheDwarfEmitter->emitSectionContents(Dwarf.getDWARFObj().getArangesSection(), "debug_aranges"); + TheDwarfEmitter->emitSectionContents( + Dwarf.getDWARFObj().getAddrSection().Data, "debug_addr"); + TheDwarfEmitter->emitSectionContents( + Dwarf.getDWARFObj().getRnglistsSection().Data, "debug_rnglists"); } void DWARFLinker::addObjectFile(DWARFFile &File, objFileLoader Loader, @@ -2474,16 +2510,6 @@ Error DWARFLinker::link() { // support or update references to these tables. Thus we report warning // and skip corresponding object file. if (!OptContext.File.Dwarf->getDWARFObj() - .getRnglistsSection() - .Data.empty()) { - reportWarning("'.debug_rnglists' is not currently supported: file " - "will be skipped", - OptContext.File); - OptContext.Skip = true; - continue; - } - - if (!OptContext.File.Dwarf->getDWARFObj() .getLoclistsSection() .Data.empty()) { reportWarning("'.debug_loclists' is not currently supported: file " diff --git a/llvm/lib/DWARFLinker/DWARFLinkerCompileUnit.cpp b/llvm/lib/DWARFLinker/DWARFLinkerCompileUnit.cpp index 6c9e052..870a841 100644 --- a/llvm/lib/DWARFLinker/DWARFLinkerCompileUnit.cpp +++ b/llvm/lib/DWARFLinker/DWARFLinkerCompileUnit.cpp @@ -135,10 +135,12 @@ void CompileUnit::addFunctionRange(uint64_t FuncLowPc, uint64_t FuncHighPc, } void CompileUnit::noteRangeAttribute(const DIE &Die, PatchLocation Attr) { - if (Die.getTag() != dwarf::DW_TAG_compile_unit) - RangeAttributes.push_back(Attr); - else + if (Die.getTag() == dwarf::DW_TAG_compile_unit) { UnitRangeAttribute = Attr; + return; + } + + RangeAttributes.emplace_back(Attr); } void CompileUnit::noteLocationAttribute(PatchLocation Attr, int64_t PcOffset) { diff --git a/llvm/lib/DWARFLinker/DWARFStreamer.cpp b/llvm/lib/DWARFLinker/DWARFStreamer.cpp index a34c407..3af7cde 100644 --- a/llvm/lib/DWARFLinker/DWARFStreamer.cpp +++ b/llvm/lib/DWARFLinker/DWARFStreamer.cpp @@ -108,6 +108,7 @@ bool DwarfStreamer::init(Triple TheTriple, Asm->setDwarfUsesRelocationsAcrossSections(false); RangesSectionSize = 0; + RngListsSectionSize = 0; LocSectionSize = 0; LineSectionSize = 0; FrameSectionSize = 0; @@ -202,6 +203,9 @@ void DwarfStreamer::emitSectionContents(StringRef SecData, StringRef SecName) { .Case("debug_frame", MC->getObjectFileInfo()->getDwarfFrameSection()) .Case("debug_aranges", MC->getObjectFileInfo()->getDwarfARangesSection()) + .Case("debug_addr", MC->getObjectFileInfo()->getDwarfAddrSection()) + .Case("debug_rnglists", + MC->getObjectFileInfo()->getDwarfRnglistsSection()) .Default(nullptr); if (Section) { @@ -363,11 +367,13 @@ void DwarfStreamer::emitDwarfDebugArangesTable( } void DwarfStreamer::emitDwarfDebugRangesTableFragment( - const CompileUnit &Unit, const AddressRanges &LinkedRanges) { - unsigned AddressSize = Unit.getOrigUnit().getAddressByteSize(); + const CompileUnit &Unit, const AddressRanges &LinkedRanges, + PatchLocation Patch) { + Patch.set(RangesSectionSize); // Make .debug_ranges to be current section. MS->switchSection(MC->getObjectFileInfo()->getDwarfRangesSection()); + unsigned AddressSize = Unit.getOrigUnit().getAddressByteSize(); // Emit ranges. uint64_t BaseAddress = 0; @@ -390,27 +396,91 @@ void DwarfStreamer::emitDwarfDebugRangesTableFragment( RangesSectionSize += AddressSize; } -/// 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) { - const RangesTy &FunctionRanges = Unit.getFunctionRanges(); - - // Linked addresses might end up in a different order. - // Build linked address ranges. - AddressRanges LinkedRanges; - for (const AddressRangeValuePair &Range : FunctionRanges) - LinkedRanges.insert( - {Range.Range.start() + Range.Value, Range.Range.end() + Range.Value}); - - if (!FunctionRanges.empty()) - emitDwarfDebugArangesTable(Unit, LinkedRanges); - - if (DoDebugRanges) - emitDwarfDebugRangesTableFragment(Unit, LinkedRanges); +MCSymbol * +DwarfStreamer::emitDwarfDebugRangeListHeader(const CompileUnit &Unit) { + if (Unit.getOrigUnit().getVersion() < 5) + return nullptr; + + // Make .debug_rnglists to be current section. + MS->switchSection(MC->getObjectFileInfo()->getDwarfRnglistsSection()); + + MCSymbol *BeginLabel = Asm->createTempSymbol("Brnglists"); + MCSymbol *EndLabel = Asm->createTempSymbol("Ernglists"); + unsigned AddressSize = Unit.getOrigUnit().getAddressByteSize(); + + // Length + Asm->emitLabelDifference(EndLabel, BeginLabel, sizeof(uint32_t)); + Asm->OutStreamer->emitLabel(BeginLabel); + RngListsSectionSize += sizeof(uint32_t); + + // Version. + MS->emitInt16(5); + RngListsSectionSize += sizeof(uint16_t); + + // Address size. + MS->emitInt8(AddressSize); + RngListsSectionSize++; + + // Seg_size + MS->emitInt8(0); + RngListsSectionSize++; + + // Offset entry count + MS->emitInt32(0); + RngListsSectionSize += sizeof(uint32_t); + + return EndLabel; +} + +void DwarfStreamer::emitDwarfDebugRangeListFragment( + const CompileUnit &Unit, const AddressRanges &LinkedRanges, + PatchLocation Patch) { + if (Unit.getOrigUnit().getVersion() < 5) { + emitDwarfDebugRangesTableFragment(Unit, LinkedRanges, Patch); + return; + } + + emitDwarfDebugRngListsTableFragment(Unit, LinkedRanges, Patch); +} + +void DwarfStreamer::emitDwarfDebugRangeListFooter(const CompileUnit &Unit, + MCSymbol *EndLabel) { + if (Unit.getOrigUnit().getVersion() < 5) + return; + + // Make .debug_rnglists to be current section. + MS->switchSection(MC->getObjectFileInfo()->getDwarfRnglistsSection()); + + if (EndLabel != nullptr) + Asm->OutStreamer->emitLabel(EndLabel); +} + +void DwarfStreamer::emitDwarfDebugRngListsTableFragment( + const CompileUnit &Unit, const AddressRanges &LinkedRanges, + PatchLocation Patch) { + Patch.set(RngListsSectionSize); + + // Make .debug_rnglists to be current section. + MS->switchSection(MC->getObjectFileInfo()->getDwarfRnglistsSection()); + + unsigned AddressSize = Unit.getOrigUnit().getAddressByteSize(); + + for (const AddressRange &Range : LinkedRanges) { + // Emit type of entry. + MS->emitInt8(dwarf::DW_RLE_start_length); + RngListsSectionSize += 1; + + // Emit start address. + MS->emitIntValue(Range.start(), AddressSize); + RngListsSectionSize += AddressSize; + + // Emit length of the range. + RngListsSectionSize += MS->emitSLEB128IntValue(Range.end() - Range.start()); + } + + // Emit the terminator entry. + MS->emitInt8(dwarf::DW_RLE_end_of_list); + RngListsSectionSize += 1; } /// Emit location lists for \p Unit and update attributes to point to the new diff --git a/llvm/test/tools/dsymutil/Inputs/dwarf5-rnglists.o b/llvm/test/tools/dsymutil/Inputs/dwarf5-rnglists.o new file mode 100644 index 0000000000000000000000000000000000000000..8dfd4e774a670d0b9a6d97f92f66bf233213d829 GIT binary patch literal 2220 zcma)6&2Jl35TCbS{z_tpP?D&K7!gAXsvW1PT4+;JXew9gp{nA-rL5NW+A*@7)ZVyO zRYXK2C{#kNIKTm+_EHf1100ch=&?s6PJjfL3W+0ve(;;!*(Nqr@<{XM~CxX6_n9v3$F^}*j$hJMV=LLFTudckkx?_i0 zK@`Sg$mJ-J#y*3#ScGKT6}PlmvpZhfUawX=wteEQ<7ZEX+Z5s)7SEqj-{Sy*4eecc zzH1O~O9DR-IcJKpBm6Q$GsJUBrMBDU^Y_=M@nwUq2ZFvG60hE>u5-#D-e-dMo!}j@ zMA;GlTVK0XYt%d5f9~&?L{Cco??d7>ow8rzV0}fwlQQYSka$j|(&iEd@y-d}oYePF z@XnxLIug zd;mj9;0#dTc^9xb1?Iajl5w9oo`cxGg?!d;K=RDvd~^o9n>aV*-Tq>jw;10M4eh++nW251w%MGVhOLyINr@r1w=kwY5?1A*0@7u5!_7R}b!YdrlM3RLfJn<@tFis7xht z+O;k(Wh$>ZZBpYZlbJB}OnWjlxi|C6`_tolpRziW9!6AKBt3I#;`Qm*5=Rmm-b0^- z<5(hrXE3sg1DB^RP3sxne`%T{k&l}&Nt+71rzVK3gety(|Mp^^H=6JPh++qcqvA&}6%PlN=!cv5)QED{kUg$>bMPmu` zKP!HSK6+Lx?v{SylYzL6`{-%0)TOhedMT9}iA1j8BlvDAm!o1@`x za2qjP;UP$+)IVdREci2EC^P;Sbv2_U&F9q1@Y9}me{#S7@(&_{InUdj+*0E&Wv@fugnQ3qnoDEV@J)geQ;psQ%k?#naa}lWHk-n8NOeo!Cwg~ vT;dx>iA(7~TJo>3QetyAV1EpPrN#Ha5==>6gm_M2YB)?lHh+k0j0gP-uKx)7 literal 0 HcmV?d00001 diff --git a/llvm/test/tools/dsymutil/X86/dwarf5-addrx.test b/llvm/test/tools/dsymutil/X86/dwarf5-addrx.test index 292f760..db7802c 100644 --- a/llvm/test/tools/dsymutil/X86/dwarf5-addrx.test +++ b/llvm/test/tools/dsymutil/X86/dwarf5-addrx.test @@ -1,5 +1,6 @@ ## Test that DWARF5 DW_FORM_addrx is correctly recognized -## and converted into the DW_FORM_addr +## and converted into the DW_FORM_addr or just preserved +## in case --update. ## $ cat dwarf5-addrx.c ## __attribute__ ((optnone)) int foo1 ( ) { @@ -43,14 +44,20 @@ RUN: dsymutil -oso-prepend-path %p/../Inputs %p/../Inputs/private/tmp/dwarf5/dwarf5-addrx.out -o %t.dSYM 2>&1 | FileCheck %s --allow-empty RUN: llvm-dwarfdump --verify %t.dSYM 2>&1 | FileCheck %s -CHECK-NOT: error: RUN: llvm-dwarfdump --verbose %t.dSYM | FileCheck %s --check-prefix DWARF + +RUN: dsymutil --update -oso-prepend-path %p/../Inputs %p/../Inputs/private/tmp/dwarf5/dwarf5-addrx.out -o %t.dSYM 2>&1 | FileCheck %s --allow-empty +RUN: llvm-dwarfdump --verify %t.dSYM 2>&1 | FileCheck %s + +RUN: llvm-dwarfdump --verbose %t.dSYM | FileCheck %s --check-prefix UPDATE-DWARF + +CHECK-NOT: error: + DWARF: DW_TAG_compile_unit DWARF: DW_AT_name [DW_FORM_strp] {{.*}} "dwarf5-addrx.c" DWARF: DW_AT_low_pc [DW_FORM_addr] (0x0000000100000eb0) DWARF: DW_AT_high_pc [DW_FORM_data4] (0x00000103) -DWARF: DW_AT_addr_base [DW_FORM_sec_offset] (0x00000008) DWARF: DW_TAG_subprogram DWARF: DW_AT_low_pc [DW_FORM_addr] (0x0000000100000eb0) DWARF: DW_AT_high_pc [DW_FORM_data4] (0x00000010) @@ -87,3 +94,58 @@ DWARF: DW_TAG_subprogram DWARF: DW_AT_low_pc [DW_FORM_addr] (0x0000000100000f30) DWARF: DW_AT_high_pc [DW_FORM_data4] (0x00000083) DWARF: DW_AT_name [DW_FORM_strp] {{.*}} "main" +DWARF-NOT: .debug_addr contents + +UPDATE-DWARF: DW_TAG_compile_unit +UPDATE-DWARF: DW_AT_name [DW_FORM_strp] {{.*}} "dwarf5-addrx.c" +UPDATE-DWARF: DW_AT_low_pc [DW_FORM_addrx] (indexed (00000000) address = 0x0000000000000000) +UPDATE-DWARF: DW_AT_high_pc [DW_FORM_data4] (0x00000103) +UPDATE-DWARF: DW_TAG_subprogram +UPDATE-DWARF: DW_AT_low_pc [DW_FORM_addrx] (indexed (00000000) address = 0x0000000000000000) +UPDATE-DWARF: DW_AT_high_pc [DW_FORM_data4] (0x00000010) +UPDATE-DWARF: DW_AT_name [DW_FORM_strp] {{.*}} "foo1" +UPDATE-DWARF: DW_TAG_subprogram +UPDATE-DWARF: DW_AT_low_pc [DW_FORM_addrx] (indexed (00000001) address = 0x0000000000000010) +UPDATE-DWARF: DW_AT_high_pc [DW_FORM_data4] (0x00000010) +UPDATE-DWARF: DW_AT_name [DW_FORM_strp] {{.*}} "foo2" +UPDATE-DWARF: DW_TAG_subprogram +UPDATE-DWARF: DW_AT_low_pc [DW_FORM_addrx] (indexed (00000002) address = 0x0000000000000020) +UPDATE-DWARF: DW_AT_high_pc [DW_FORM_data4] (0x00000010) +UPDATE-DWARF: DW_AT_name [DW_FORM_strp] {{.*}} "foo3" +UPDATE-DWARF: DW_TAG_subprogram +UPDATE-DWARF: DW_AT_low_pc [DW_FORM_addrx] (indexed (00000003) address = 0x0000000000000030) +UPDATE-DWARF: DW_AT_high_pc [DW_FORM_data4] (0x00000010) +UPDATE-DWARF: DW_AT_name [DW_FORM_strp] {{.*}} "foo4" +UPDATE-DWARF: DW_TAG_subprogram +UPDATE-DWARF: DW_AT_low_pc [DW_FORM_addrx] (indexed (00000004) address = 0x0000000000000040) +UPDATE-DWARF: DW_AT_high_pc [DW_FORM_data4] (0x00000010) +UPDATE-DWARF: DW_AT_name [DW_FORM_strp] {{.*}} "foo5" +UPDATE-DWARF: DW_TAG_subprogram +UPDATE-DWARF: DW_AT_low_pc [DW_FORM_addrx] (indexed (00000005) address = 0x0000000000000050) +UPDATE-DWARF: DW_AT_high_pc [DW_FORM_data4] (0x00000010) +UPDATE-DWARF: DW_AT_name [DW_FORM_strp] {{.*}} "foo6" +UPDATE-DWARF: DW_TAG_subprogram +UPDATE-DWARF: DW_AT_low_pc [DW_FORM_addrx] (indexed (00000006) address = 0x0000000000000060) +UPDATE-DWARF: DW_AT_high_pc [DW_FORM_data4] (0x00000010) +UPDATE-DWARF: DW_AT_name [DW_FORM_strp] {{.*}} "foo7" +UPDATE-DWARF: DW_TAG_subprogram +UPDATE-DWARF: DW_AT_low_pc [DW_FORM_addrx] (indexed (00000007) address = 0x0000000000000070) +UPDATE-DWARF: DW_AT_high_pc [DW_FORM_data4] (0x00000010) +UPDATE-DWARF: DW_AT_name [DW_FORM_strp] {{.*}} "foo8" +UPDATE-DWARF: DW_TAG_subprogram +UPDATE-DWARF: DW_AT_low_pc [DW_FORM_addrx] (indexed (00000008) address = 0x0000000000000080) +UPDATE-DWARF: DW_AT_high_pc [DW_FORM_data4] (0x00000083) +UPDATE-DWARF: DW_AT_name [DW_FORM_strp] {{.*}} "main" +UPDATE-DWARF: .debug_addr contents: +UPDATE-DWARF: 0x00000000: Address table header: length = 0x0000004c, format = DWARF32, version = 0x0005, addr_size = 0x08, seg_size = 0x00 +UPDATE-DWARF: Addrs: [ +UPDATE-DWARF: 0x0000000000000000 +UPDATE-DWARF: 0x0000000000000010 +UPDATE-DWARF: 0x0000000000000020 +UPDATE-DWARF: 0x0000000000000030 +UPDATE-DWARF: 0x0000000000000040 +UPDATE-DWARF: 0x0000000000000050 +UPDATE-DWARF: 0x0000000000000060 +UPDATE-DWARF: 0x0000000000000070 +UPDATE-DWARF: 0x0000000000000080 +UPDATE-DWARF: ] diff --git a/llvm/test/tools/dsymutil/X86/dwarf5-rnglists.test b/llvm/test/tools/dsymutil/X86/dwarf5-rnglists.test new file mode 100644 index 0000000..e38f6c9 --- /dev/null +++ b/llvm/test/tools/dsymutil/X86/dwarf5-rnglists.test @@ -0,0 +1,87 @@ +## This test checks that .debug_rnglists table correclty handled +## and transformed into the DW_FORM_sec_offset form in case +## --no-update. Or correctly preservedi in --update case. + +## cat dwarf5-rnglists.c +## +## #include +## +## int g1; +## +## int main ( int argv, char** argc ) { +## +## if ( argv > 10 ) { +## volatile int a = 0x4; +## +## if ( g1 ) { +## volatile int b = 0; +## return b; +## } +## +## volatile int c = 7; +## } else if ( g1 ) { +## volatile int a = 0x5; +## } +## +## return 0; +## } + +## $ clang -gdwarf-5 dwarf5-rnglists.c -c -O2 -o dwarf5-rnglists.o +## $ clang -gdwarf-5 dwarf5-rnglists.o -o dwarf5-rnglists + +#RUN: dsymutil -oso-prepend-path %p/../Inputs -y %s -o %t.dSYM +#RUN: llvm-dwarfdump --verify %t.dSYM | FileCheck %s +#RUN: llvm-dwarfdump -a --verbose %t.dSYM | FileCheck %s --check-prefix DWARF-CHECK +# +#RUN: dsymutil --update -oso-prepend-path %p/../Inputs -y %s -o %t.dSYM +#RUN: llvm-dwarfdump --verify %t.dSYM | FileCheck %s +#RUN: llvm-dwarfdump -a --verbose %t.dSYM | FileCheck %s --check-prefix UPD-DWARF-CHECK + +#CHECK: No errors. + +#DWARF-CHECK: DW_TAG_compile_unit +#DWARF-CHECK: DW_TAG_lexical_block +#DWARF-CHECK: DW_AT_ranges [DW_FORM_sec_offset] (0x0000000c +#DWARF-CHECK: [0x0000000100000f79, 0x0000000100000f96) +#DWARF-CHECK: [0x0000000100000fad, 0x0000000100000fb4)) +#DWARF-CHECK-NOT: debug_addr +#DWARF-CHECK: .debug_rnglists contents: +#DWARF-CHECK: 0x00000000: range list header: length = 0x0000001d, format = DWARF32, version = 0x0005, addr_size = 0x08, seg_size = 0x00, offset_entry_count = 0x00000000 +#DWARF-CHECK: ranges: +#DWARF-CHECK: 0x0000000c: [DW_RLE_start_length]: 0x0000000100000f79, 0x000000000000001d => [0x0000000100000f79, 0x0000000100000f96) +#DWARF-CHECK: 0x00000016: [DW_RLE_start_length]: 0x0000000100000fad, 0x0000000000000007 => [0x0000000100000fad, 0x0000000100000fb4) +#DWARF-CHECK: 0x00000020: [DW_RLE_end_of_list ] +#DWARF-CHECK-NOT: debug_addr +# +#UPD-DWARF-CHECK: DW_TAG_compile_unit +#UPD-DWARF-CHECK: DW_TAG_lexical_block +#UPD-DWARF-CHECK: DW_AT_ranges [DW_FORM_rnglistx] (indexed (0x0) rangelist = 0x00000010 +#UPD-DWARF-CHECK: [0x0000000000000009, 0x0000000000000026) +#UPD-DWARF-CHECK: [0x000000000000003d, 0x0000000000000044)) +#UPD-DWARF-CHECK: .debug_addr contents: +#UPD-DWARF-CHECK: 0x00000000: Address table header: length = 0x00000024, format = DWARF32, version = 0x0005, addr_size = 0x08, seg_size = 0x00 +#UPD-DWARF-CHECK: Addrs: [ +#UPD-DWARF-CHECK: 0x0000000000000000 +#UPD-DWARF-CHECK: 0x0000000000000000 +#UPD-DWARF-CHECK: 0x000000000000001c +#UPD-DWARF-CHECK: 0x0000000000000034 +#UPD-DWARF-CHECK: ] + +#UPD-DWARF-CHECK: .debug_rnglists contents: +#UPD-DWARF-CHECK: 0x00000000: range list header: length = 0x00000013, format = DWARF32, version = 0x0005, addr_size = 0x08, seg_size = 0x00, offset_entry_count = 0x00000001 +#UPD-DWARF-CHECK: offsets: [ +#UPD-DWARF-CHECK: 0x00000004 => 0x00000010 +#UPD-DWARF-CHECK: ] +#UPD-DWARF-CHECK: ranges: +#UPD-DWARF-CHECK: 0x00000010: [DW_RLE_offset_pair]: 0x0000000000000009, 0x0000000000000026 => [0x0000000000000009, 0x0000000000000026) +#UPD-DWARF-CHECK: 0x00000013: [DW_RLE_offset_pair]: 0x000000000000003d, 0x0000000000000044 => [0x000000000000003d, 0x0000000000000044) +#UPD-DWARF-CHECK: 0x00000016: [DW_RLE_end_of_list] + +--- +triple: 'x86_64-apple-darwin' +objects: + - filename: 'dwarf5-rnglists.o' + timestamp: 1676048242 + symbols: + - { sym: _main, objAddr: 0x0, binAddr: 0x100000F70, size: 0x48 } + - { sym: _g1, binAddr: 0x100001000, size: 0x0 } diff --git a/llvm/test/tools/dsymutil/X86/op-convert-offset.test b/llvm/test/tools/dsymutil/X86/op-convert-offset.test index e881afa..5694535 100644 --- a/llvm/test/tools/dsymutil/X86/op-convert-offset.test +++ b/llvm/test/tools/dsymutil/X86/op-convert-offset.test @@ -34,12 +34,12 @@ OBJ: DW_AT_location (DW_OP_breg2 RCX+0, DW_OP_constu 0x OBJ: DW_AT_name ("b") OBJ: DW_AT_type (0x000000af "_Bool") -DSYM: 0x00000095: DW_TAG_base_type +DSYM: 0x0000008d: DW_TAG_base_type DSYM: DW_AT_name ("DW_ATE_unsigned_1") DSYM: DW_AT_encoding (DW_ATE_unsigned) DSYM: DW_AT_byte_size (0x01) -DSYM: 0x000000bc: DW_TAG_formal_parameter -DSYM: DW_AT_location (DW_OP_breg2 RCX+0, DW_OP_constu 0xff, DW_OP_and, DW_OP_convert (0x00000095) "DW_ATE_unsigned_1", DW_OP_convert (0x0000009c) "DW_ATE_unsigned_8", DW_OP_stack_value) +DSYM: 0x000000b4: DW_TAG_formal_parameter +DSYM: DW_AT_location (DW_OP_breg2 RCX+0, DW_OP_constu 0xff, DW_OP_and, DW_OP_convert (0x0000008d) "DW_ATE_unsigned_1", DW_OP_convert (0x00000094) "DW_ATE_unsigned_8", DW_OP_stack_value) DSYM: DW_AT_name ("b") -DSYM: DW_AT_type (0x000000da "_Bool") +DSYM: DW_AT_type (0x000000d2 "_Bool") diff --git a/llvm/test/tools/llvm-dwarfutil/ELF/X86/dwarf5-addrx.test b/llvm/test/tools/llvm-dwarfutil/ELF/X86/dwarf5-addrx.test index 20964f9..65e5e81 100644 --- a/llvm/test/tools/llvm-dwarfutil/ELF/X86/dwarf5-addrx.test +++ b/llvm/test/tools/llvm-dwarfutil/ELF/X86/dwarf5-addrx.test @@ -1,11 +1,20 @@ -## Test that DWARF5 DW_FORM_addrx is correctly recognized -## and converted into the DW_FORM_addr +## Test that DWARFv5 DW_FORM_addrx is correctly recognized +## and converted into the DW_FORM_addr in --garbage-collection +## case or correctly preserved in --no-garbage-collection case. # RUN: yaml2obj %s -o %t.o # RUN: llvm-dwarfutil %t.o %t1 # RUN: llvm-dwarfdump -verify %t1 | FileCheck %s # RUN: llvm-dwarfdump -a --verbose %t1 | FileCheck %s --check-prefix DWARF-CHECK +# +# RUN: llvm-dwarfutil --no-garbage-collection %t.o %t1 +# RUN: llvm-dwarfdump -verify %t1 | FileCheck %s +# RUN: llvm-dwarfdump -a --verbose %t1 | FileCheck %s --check-prefix UPD-DWARF-CHECK +# +# RUN: llvm-dwarfutil --no-garbage-collection --build-accelerator=DWARF %t.o %t1 +# RUN: llvm-dwarfdump -verify %t1 | FileCheck %s +# RUN: llvm-dwarfdump -a --verbose %t1 | FileCheck %s --check-prefix UPD-DWARF-CHECK #CHECK: No errors. @@ -13,7 +22,6 @@ #DWARF-CHECK: DW_AT_name [DW_FORM_strp] {{.*}} "CU1" #DWARF-CHECK: DW_AT_low_pc [DW_FORM_addr] (0x0000000000001130) #DWARF-CHECK: DW_AT_high_pc [DW_FORM_data8] (0x0000000000000030) -#DWARF-CHECK: DW_AT_addr_base [DW_FORM_sec_offset] (0x00000008) #DWARF-CHECK: DW_TAG_subprogram #DWARF-CHECK: DW_AT_name [DW_FORM_strp] {{.*}} "foo1" #DWARF-CHECK: DW_AT_low_pc [DW_FORM_addr] (0x0000000000001130) @@ -26,6 +34,31 @@ #DWARF-CHECK: DW_AT_name [DW_FORM_strp] {{.*}} "foo3" #DWARF-CHECK: DW_AT_low_pc [DW_FORM_addr] (0x0000000000001150) #DWARF-CHECK: DW_AT_high_pc [DW_FORM_data8] (0x0000000000000010) +#DWARF-CHECK=NOT: .debug_addr contents: + +#UPD-DWARF-CHECK: DW_TAG_compile_unit +#UPD-DWARF-CHECK: DW_AT_name {{.*}}"CU1" +#UPD-DWARF-CHECK: DW_AT_low_pc [DW_FORM_addrx] (indexed (00000000) address = 0x0000000000001130) +#UPD-DWARF-CHECK: DW_AT_high_pc [DW_FORM_data8] (0x0000000000000030) +#UPD-DWARF-CHECK: DW_TAG_subprogram +#UPD-DWARF-CHECK: DW_AT_name {{.*}}"foo1" +#UPD-DWARF-CHECK: DW_AT_low_pc [DW_FORM_addrx] (indexed (00000000) address = 0x0000000000001130) +#UPD-DWARF-CHECK: DW_AT_high_pc [DW_FORM_data8] (0x0000000000000010) +#UPD-DWARF-CHECK: DW_TAG_subprogram +#UPD-DWARF-CHECK: DW_AT_name {{.*}}"foo2" +#UPD-DWARF-CHECK: DW_AT_low_pc [DW_FORM_addrx] (indexed (00000001) address = 0x0000000000001140) +#UPD-DWARF-CHECK: DW_AT_high_pc [DW_FORM_data8] (0x0000000000000010) +#UPD-DWARF-CHECK: DW_TAG_subprogram +#UPD-DWARF-CHECK: DW_AT_name {{.*}}"foo3" +#UPD-DWARF-CHECK: DW_AT_low_pc [DW_FORM_addrx] (indexed (00000002) address = 0x0000000000001150) +#UPD-DWARF-CHECK: DW_AT_high_pc [DW_FORM_data8] (0x0000000000000010) +#UPD-DWARF-CHECK: .debug_addr contents: +#UPD-DWARF-CHECK: 0x00000000: Address table header: length = 0x0000001c, format = DWARF32, version = 0x0005, addr_size = 0x08, seg_size = 0x00 +#UPD-DWARF-CHECK: Addrs: [ +#UPD-DWARF-CHECK: 0x0000000000001130 +#UPD-DWARF-CHECK: 0x0000000000001140 +#UPD-DWARF-CHECK: 0x0000000000001150 +#UPD-DWARF-CHECK: ] --- !ELF FileHeader: diff --git a/llvm/test/tools/llvm-dwarfutil/ELF/X86/dwarf5-rnglists.test b/llvm/test/tools/llvm-dwarfutil/ELF/X86/dwarf5-rnglists.test new file mode 100644 index 0000000..3a869ef --- /dev/null +++ b/llvm/test/tools/llvm-dwarfutil/ELF/X86/dwarf5-rnglists.test @@ -0,0 +1,264 @@ +## Test that DWARFv5 .debug_rnglists is correctly recognized +## and converted into the DW_FORM_sec_offset form in --garbage-collection +## case or correctly preserved in --no-garbage-collection case. + +# RUN: yaml2obj %s -o %t.o + +# RUN: llvm-dwarfutil %t.o %t1 +# RUN: llvm-dwarfdump -verify %t1 | FileCheck %s +# RUN: llvm-dwarfdump -a --verbose %t1 | FileCheck %s --check-prefix DWARF-CHECK + +# RUN: llvm-dwarfutil --no-garbage-collection %t.o %t1 +# RUN: llvm-dwarfdump -verify %t1 | FileCheck %s +# RUN: llvm-dwarfdump -a --verbose %t1 | FileCheck %s --check-prefix UPD-DWARF-CHECK + +# RUN: llvm-dwarfutil --no-garbage-collection --build-accelerator=DWARF %t.o %t1 +# RUN: llvm-dwarfdump -verify %t1 | FileCheck %s +# RUN: llvm-dwarfdump -a --verbose %t1 | FileCheck %s --check-prefix UPD-DWARF-CHECK + +#CHECK: No errors. + +#DWARF-CHECK: DW_TAG_compile_unit +#DWARF-CHECK: DW_AT_name [DW_FORM_strp] {{.*}} "CU1" +#DWARF-CHECK: DW_AT_low_pc [DW_FORM_addr] (0x0000000000001130) +#DWARF-CHECK: DW_AT_ranges [DW_FORM_sec_offset] (0x[[CURANGE_OFF:[0-9a-f]*]] +#DWARF-CHECK: [0x0000000000001130, 0x0000000000001170)) +#DWARF-CHECK: DW_TAG_subprogram +#DWARF-CHECK: DW_AT_name [DW_FORM_strp] {{.*}} "foo1" +#DWARF-CHECK: DW_AT_low_pc [DW_FORM_addr] (0x0000000000001130) +#DWARF-CHECK: DW_AT_high_pc [DW_FORM_data8] (0x0000000000000010) +#DWARF-CHECK: DW_TAG_lexical_block +#DWARF-CHECK: DW_AT_ranges [DW_FORM_sec_offset] (0x[[F1RANGE_OFF:[0-9a-f]*]] +#DWARF-CHECK: [0x0000000000001130, 0x0000000000001140)) +#DWARF-CHECK: DW_TAG_subprogram +#DWARF-CHECK: DW_AT_name [DW_FORM_strp] {{.*}} "foo2" +#DWARF-CHECK: DW_AT_low_pc [DW_FORM_addr] (0x0000000000001140) +#DWARF-CHECK: DW_AT_high_pc [DW_FORM_data8] (0x0000000000000010) +#DWARF-CHECK: DW_TAG_lexical_block +#DWARF-CHECK: DW_AT_ranges [DW_FORM_sec_offset] (0x[[F2RANGE_OFF:[0-9a-f]*]] +#DWARF-CHECK: [0x0000000000001140, 0x0000000000001150)) +#DWARF-CHECK: DW_TAG_subprogram +#DWARF-CHECK: DW_AT_name [DW_FORM_strp] {{.*}} "foo3" +#DWARF-CHECK: DW_AT_low_pc [DW_FORM_addr] (0x0000000000001150) +#DWARF-CHECK: DW_AT_high_pc [DW_FORM_data8] (0x0000000000000010) +#DWARF-CHECK: DW_TAG_lexical_block +#DWARF-CHECK: DW_AT_ranges [DW_FORM_sec_offset] (0x[[F3RANGE_OFF:[0-9a-f]*]] +#DWARF-CHECK: [0x0000000000001150, 0x0000000000001160)) +#DWARF-CHECK: DW_TAG_subprogram +#DWARF-CHECK: DW_AT_name [DW_FORM_strp] {{.*}} "foo4" +#DWARF-CHECK: DW_AT_low_pc [DW_FORM_addr] (0x0000000000001160) +#DWARF-CHECK: DW_AT_high_pc [DW_FORM_data8] (0x0000000000000010) +#DWARF-CHECK: DW_TAG_lexical_block +#DWARF-CHECK: DW_AT_ranges [DW_FORM_sec_offset] (0x[[F4RANGE_OFF:[0-9a-f]*]] +#DWARF-CHECK: [0x0000000000001160, 0x0000000000001170)) +#DWARF-CHECK-NOT: .debug_addr contents: +#DWARF-CHECK: .debug_aranges contents: +#DWARF-CHECK: Address Range Header: length = 0x0000002c, format = DWARF32, version = 0x0002, cu_offset = 0x00000000, addr_size = 0x08, seg_size = 0x00 +#DWARF-CHECK: [0x0000000000001130, 0x0000000000001170) +#DWARF-CHECK-NOT: .debug_addr contents: +#DWARF-CHECK: .debug_rnglists contents: +#DWARF-CHECK: 0x00000000: range list header: length = 0x00000040, format = DWARF32, version = 0x0005, addr_size = 0x08, seg_size = 0x00, offset_entry_count = 0x00000000 +#DWARF-CHECK: ranges: +#DWARF-CHECK: 0x[[F1RANGE_OFF]]: [DW_RLE_start_length]: 0x0000000000001130, 0x0000000000000010 => [0x0000000000001130, 0x0000000000001140) +#DWARF-CHECK: {{.*}} [DW_RLE_end_of_list ] +#DWARF-CHECK: 0x[[F2RANGE_OFF]]: [DW_RLE_start_length]: 0x0000000000001140, 0x0000000000000010 => [0x0000000000001140, 0x0000000000001150) +#DWARF-CHECK: {{.*}} [DW_RLE_end_of_list ] +#DWARF-CHECK: 0x[[F3RANGE_OFF]]: [DW_RLE_start_length]: 0x0000000000001150, 0x0000000000000010 => [0x0000000000001150, 0x0000000000001160) +#DWARF-CHECK: {{.*}} [DW_RLE_end_of_list ] +#DWARF-CHECK: 0x[[F4RANGE_OFF]]: [DW_RLE_start_length]: 0x0000000000001160, 0x0000000000000010 => [0x0000000000001160, 0x0000000000001170) +#DWARF-CHECK: {{.*}} [DW_RLE_end_of_list ] +#DWARF-CHECK: 0x[[CURANGE_OFF]]: [DW_RLE_start_length]: 0x0000000000001130, 0x0000000000000040 => [0x0000000000001130, 0x0000000000001170) +#DWARF-CHECK: {{.*}} [DW_RLE_end_of_list ] +#DWARF-CHECK-NOT: .debug_addr contents: + +#UPD-DWARF-CHECK: DW_TAG_compile_unit +#UPD-DWARF-CHECK: DW_AT_name {{.*}}"CU1" +#UPD-DWARF-CHECK: DW_AT_low_pc [DW_FORM_addrx] (indexed (00000000) address = 0x0000000000001130) +#UPD-DWARF-CHECK: DW_AT_ranges [DW_FORM_rnglistx] (indexed (0x4) rangelist = 0x0000003e +#UPD-DWARF-CHECK: [0x0000000000001130, 0x0000000000001170)) +#UPD-DWARF-CHECK: DW_TAG_subprogram +#UPD-DWARF-CHECK: DW_AT_name {{.*}}"foo1" +#UPD-DWARF-CHECK: DW_AT_low_pc [DW_FORM_addrx] (indexed (00000000) address = 0x0000000000001130) +#UPD-DWARF-CHECK: DW_AT_high_pc [DW_FORM_data8] (0x0000000000000010) +#UPD-DWARF-CHECK: DW_TAG_lexical_block +#UPD-DWARF-CHECK: DW_AT_ranges [DW_FORM_rnglistx] (indexed (0x0) rangelist = 0x00000020 +#UPD-DWARF-CHECK: [0x0000000000001130, 0x0000000000001140)) +#UPD-DWARF-CHECK: DW_TAG_subprogram +#UPD-DWARF-CHECK: DW_AT_name {{.*}}"foo2" +#UPD-DWARF-CHECK: DW_AT_low_pc [DW_FORM_addrx] (indexed (00000001) address = 0x0000000000001140) +#UPD-DWARF-CHECK: DW_AT_high_pc [DW_FORM_data8] (0x0000000000000010) +#UPD-DWARF-CHECK: DW_TAG_lexical_block +#UPD-DWARF-CHECK: DW_AT_ranges [DW_FORM_rnglistx] (indexed (0x1) rangelist = 0x00000024 +#UPD-DWARF-CHECK: [0x0000000000001140, 0x0000000000001150)) +#UPD-DWARF-CHECK: DW_TAG_subprogram +#UPD-DWARF-CHECK: DW_AT_name {{.*}}"foo3" +#UPD-DWARF-CHECK: DW_AT_low_pc [DW_FORM_addrx] (indexed (00000002) address = 0x0000000000001150) +#UPD-DWARF-CHECK: DW_AT_high_pc [DW_FORM_data8] (0x0000000000000010) +#UPD-DWARF-CHECK: DW_TAG_lexical_block +#UPD-DWARF-CHECK: DW_AT_ranges [DW_FORM_sec_offset] (0x00000028 +#UPD-DWARF-CHECK: [0x0000000000001150, 0x0000000000001160)) +#UPD-DWARF-CHECK: DW_TAG_subprogram +#UPD-DWARF-CHECK: DW_AT_name {{.*}}"foo4" +#UPD-DWARF-CHECK: DW_AT_low_pc [DW_FORM_addrx] (indexed (00000003) address = 0x0000000000001160) +#UPD-DWARF-CHECK: DW_AT_high_pc [DW_FORM_data8] (0x0000000000000010) +#UPD-DWARF-CHECK: DW_TAG_lexical_block +#UPD-DWARF-CHECK: DW_AT_ranges [DW_FORM_sec_offset] (0x00000033 +#UPD-DWARF-CHECK: [0x0000000000001160, 0x0000000000001170)) +#UPD-DWARF-CHECK: .debug_addr contents: +#UPD-DWARF-CHECK: 0x00000000: Address table header: length = 0x00000024, format = DWARF32, version = 0x0005, addr_size = 0x08, seg_size = 0x00 +#UPD-DWARF-CHECK: Addrs: [ +#UPD-DWARF-CHECK: 0x0000000000001130 +#UPD-DWARF-CHECK: 0x0000000000001140 +#UPD-DWARF-CHECK: 0x0000000000001150 +#UPD-DWARF-CHECK: 0x0000000000001160 +#UPD-DWARF-CHECK: ] +#UPD-DWARF-CHECK: .debug_rnglists contents: +#UPD-DWARF-CHECK: 0x00000000: range list header: length = 0x0000003e, format = DWARF32, version = 0x0005, addr_size = 0x08, seg_size = 0x00, offset_entry_count = 0x00000005 +#UPD-DWARF-CHECK: offsets: [ +#UPD-DWARF-CHECK: 0x00000014 => 0x00000020 +#UPD-DWARF-CHECK: 0x00000018 => 0x00000024 +#UPD-DWARF-CHECK: 0x0000001c => 0x00000028 +#UPD-DWARF-CHECK: 0x00000027 => 0x00000033 +#UPD-DWARF-CHECK: 0x00000032 => 0x0000003e +#UPD-DWARF-CHECK: ] +#UPD-DWARF-CHECK: ranges: +#UPD-DWARF-CHECK: 0x00000020: [DW_RLE_startx_length]: 0x0000000000000000, 0x0000000000000010 => [0x0000000000001130, 0x0000000000001140) +#UPD-DWARF-CHECK: 0x00000023: [DW_RLE_end_of_list ] +#UPD-DWARF-CHECK: 0x00000024: [DW_RLE_startx_length]: 0x0000000000000001, 0x0000000000000010 => [0x0000000000001140, 0x0000000000001150) +#UPD-DWARF-CHECK: 0x00000027: [DW_RLE_end_of_list ] +#UPD-DWARF-CHECK: 0x00000028: [DW_RLE_start_length ]: 0x0000000000001150, 0x0000000000000010 => [0x0000000000001150, 0x0000000000001160) +#UPD-DWARF-CHECK: 0x00000032: [DW_RLE_end_of_list ] +#UPD-DWARF-CHECK: 0x00000033: [DW_RLE_start_length ]: 0x0000000000001160, 0x0000000000000010 => [0x0000000000001160, 0x0000000000001170) +#UPD-DWARF-CHECK: 0x0000003d: [DW_RLE_end_of_list ] +#UPD-DWARF-CHECK: 0x0000003e: [DW_RLE_startx_length]: 0x0000000000000000, 0x0000000000000040 => [0x0000000000001130, 0x0000000000001170) +#UPD-DWARF-CHECK: 0x00000041: [DW_RLE_end_of_list ] + +## Following yaml description has Content of the .debug_rnglists exactly like above data ^^^^^^ +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_X86_64 +Sections: + - Name: .text + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] + Address: 0x1130 + Size: 0x70 + - Name: .debug_rnglists + Type: SHT_PROGBITS + Flags: [ ] + Content: "3e000000050008000500000014000000180000001c000000270000003200000003001000030110000750110000000000001000076011000000000000100003004000" +DWARF: + debug_abbrev: + - Table: + - Tag: DW_TAG_compile_unit + Children: DW_CHILDREN_yes + Attributes: + - Attribute: DW_AT_producer + Form: DW_FORM_string + - Attribute: DW_AT_language + Form: DW_FORM_data2 + - Attribute: DW_AT_name + Form: DW_FORM_string + - Attribute: DW_AT_low_pc + Form: DW_FORM_addrx + - Attribute: DW_AT_ranges + Form: DW_FORM_rnglistx + - Attribute: DW_AT_rnglists_base + Form: DW_FORM_sec_offset + - Attribute: DW_AT_addr_base + Form: DW_FORM_sec_offset + - Tag: DW_TAG_subprogram + Children: DW_CHILDREN_yes + Attributes: + - Attribute: DW_AT_name + Form: DW_FORM_string + - Attribute: DW_AT_low_pc + Form: DW_FORM_addrx + - Attribute: DW_AT_high_pc + Form: DW_FORM_data8 + - Attribute: DW_AT_type + Form: DW_FORM_ref4 + - Tag: DW_TAG_lexical_block + Children: DW_CHILDREN_no + Attributes: + - Attribute: DW_AT_ranges + Form: DW_FORM_rnglistx + - Tag: DW_TAG_lexical_block + Children: DW_CHILDREN_no + Attributes: + - Attribute: DW_AT_ranges + Form: DW_FORM_sec_offset + - Tag: DW_TAG_base_type + Children: DW_CHILDREN_no + Attributes: + - Attribute: DW_AT_name + Form: DW_FORM_string + debug_info: + - Version: 5 + UnitType: DW_UT_compile + Entries: + - AbbrCode: 1 + Values: + - CStr: by_hand + - Value: 0x04 + - CStr: CU1 + - Value: 0x0 + - Value: 0x4 + - Value: 0xc + - Value: 0x8 + - AbbrCode: 2 + Values: + - CStr: foo1 + - Value: 0x00 + - Value: 0x10 + - Value: 0x83 + - AbbrCode: 3 + Values: + - Value: 0x00 + - AbbrCode: 0 + - AbbrCode: 2 + Values: + - CStr: foo2 + - Value: 0x01 + - Value: 0x10 + - Value: 0x83 + - AbbrCode: 3 + Values: + - Value: 0x01 + - AbbrCode: 0 + - AbbrCode: 2 + Values: + - CStr: foo3 + - Value: 0x02 + - Value: 0x10 + - Value: 0x83 + - AbbrCode: 4 + Values: + - Value: 0x28 + - AbbrCode: 0 + - AbbrCode: 2 + Values: + - CStr: foo4 + - Value: 0x03 + - Value: 0x10 + - Value: 0x83 + - AbbrCode: 4 + Values: + - Value: 0x33 + - AbbrCode: 0 + - AbbrCode: 5 + Values: + - CStr: int + - AbbrCode: 0 + debug_addr: + - Version: 5 + AddressSize: 0x08 + Entries: + - Address: 0x1130 + - Address: 0x1140 + - Address: 0x1150 + - Address: 0x1160 +... diff --git a/llvm/test/tools/llvm-dwarfutil/ELF/X86/warning-skipped-rnglists.test b/llvm/test/tools/llvm-dwarfutil/ELF/X86/warning-skipped-rnglists.test deleted file mode 100644 index deea90f..0000000 --- a/llvm/test/tools/llvm-dwarfutil/ELF/X86/warning-skipped-rnglists.test +++ /dev/null @@ -1,54 +0,0 @@ -## This test checks the warning message displayed if input file -## contains .debug_rnglists section. - -# RUN: yaml2obj %s -o %t.o - -# RUN: llvm-dwarfutil --garbage-collection %t.o %t1 2>&1 | FileCheck %s -DFILE=%t.o - -# CHECK: [[FILE]]: warning: '.debug_rnglists' is not currently supported: file will be skipped - ---- !ELF -FileHeader: - Class: ELFCLASS64 - Data: ELFDATA2LSB - Type: ET_REL - Machine: EM_X86_64 -Sections: - - Name: .text - Type: SHT_PROGBITS - Flags: [ SHF_ALLOC, SHF_EXECINSTR ] - Address: 0x1000 - AddressAlign: 0x0000000000000010 - Content: "FFFFFFFF" - - Name: .debug_rnglists - Type: SHT_PROGBITS - Flags: [ ] - Content: "0000" -DWARF: - debug_abbrev: - - Table: - - Tag: DW_TAG_compile_unit - Children: DW_CHILDREN_yes - Attributes: - - Attribute: DW_AT_producer - Form: DW_FORM_string - - Attribute: DW_AT_language - Form: DW_FORM_data2 - - Attribute: DW_AT_name - Form: DW_FORM_string - - Attribute: DW_AT_low_pc - Form: DW_FORM_addr - - Attribute: DW_AT_high_pc - Form: DW_FORM_data8 - debug_info: - - Version: 4 - Entries: - - AbbrCode: 1 - Values: - - CStr: by_hand - - Value: 0x04 - - CStr: CU1 - - Value: 0x1000 - - Value: 0x4 - - AbbrCode: 0 -... -- 2.7.4