diff --git a/llvm/include/llvm/DWARFLinker/DWARFLinker.h b/llvm/include/llvm/DWARFLinker/DWARFLinker.h --- a/llvm/include/llvm/DWARFLinker/DWARFLinker.h +++ b/llvm/include/llvm/DWARFLinker/DWARFLinker.h @@ -117,19 +117,32 @@ virtual void emitAppleTypes(AccelTable &Table) = 0; - /// Emit debug ranges(.debug_ranges, .debug_rnglists) header. + /// Emit debug ranges (.debug_ranges, .debug_rnglists) header. virtual MCSymbol *emitDwarfDebugRangeListHeader(const CompileUnit &Unit) = 0; - /// Emit debug ranges(.debug_ranges, .debug_rnglists) fragment. + /// Emit debug ranges (.debug_ranges, .debug_rnglists) fragment. virtual void emitDwarfDebugRangeListFragment(const CompileUnit &Unit, const AddressRanges &LinkedRanges, PatchLocation Patch) = 0; - /// Emit debug ranges(.debug_ranges, .debug_rnglists) footer. + /// Emit debug ranges (.debug_ranges, .debug_rnglists) footer. virtual void emitDwarfDebugRangeListFooter(const CompileUnit &Unit, MCSymbol *EndLabel) = 0; + /// Emit debug locations (.debug_loc, .debug_loclists) header. + virtual MCSymbol *emitDwarfDebugLocListHeader(const CompileUnit &Unit) = 0; + + /// Emit debug locations (.debug_loc, .debug_loclists) fragment. + virtual void emitDwarfDebugLocListFragment( + const CompileUnit &Unit, + const DWARFLocationExpressionsVector &LinkedLocationExpression, + PatchLocation Patch) = 0; + + /// Emit debug locations (.debug_loc, .debug_loclists) footer. + virtual void emitDwarfDebugLocListFooter(const CompileUnit &Unit, + MCSymbol *EndLabel) = 0; + /// Emit .debug_aranges entries for \p Unit virtual void emitDwarfDebugArangesTable(const CompileUnit &Unit, @@ -159,14 +172,6 @@ virtual void emitFDE(uint32_t CIEOffset, uint32_t AddreSize, uint64_t Address, StringRef Bytes) = 0; - /// 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. - virtual void emitLocationsForUnit( - const CompileUnit &Unit, DWARFContext &Dwarf, - std::function &)> - ProcessExpr) = 0; - /// Emit the compilation unit header for \p Unit in the /// .debug_info section. /// @@ -207,6 +212,9 @@ /// Returns size of generated .debug_macro section. virtual uint64_t getDebugMacroSectionSize() const = 0; + + /// Returns size of generated .debug_loclists section. + virtual uint64_t getLocListsSectionSize() const = 0; }; using UnitListTy = std::vector>; @@ -738,6 +746,14 @@ /// .debug_rnglists) for \p Unit, patch the attributes referencing it. void generateUnitRanges(CompileUnit &Unit, const DWARFFile &File) const; + using ExpressionHandlerRef = function_ref &, + SmallVectorImpl &)>; + + /// Compute and emit debug locations (.debug_loc, .debug_loclists) + /// for \p Unit, patch the attributes referencing it. + void generateUnitLocations(CompileUnit &Unit, const DWARFFile &File, + ExpressionHandlerRef ExprHandler) 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 /// .debug_line section. diff --git a/llvm/include/llvm/DWARFLinker/DWARFLinkerCompileUnit.h b/llvm/include/llvm/DWARFLinker/DWARFLinkerCompileUnit.h --- a/llvm/include/llvm/DWARFLinker/DWARFLinkerCompileUnit.h +++ b/llvm/include/llvm/DWARFLinker/DWARFLinkerCompileUnit.h @@ -44,6 +44,7 @@ }; using RngListAttributesTy = SmallVector; +using LocListAttributesTy = 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. @@ -153,8 +154,7 @@ return UnitRangeAttribute; } - const std::vector> & - getLocationAttributes() const { + const LocListAttributesTy &getLocationAttributes() const { return LocationAttributes; } @@ -289,7 +289,7 @@ /// original debug_loc section to the liked one. They are stored /// along with the PC offset that is to be applied to their /// function's address. - std::vector> LocationAttributes; + LocListAttributesTy LocationAttributes; /// Accelerator entries for the unit, both for the pub* /// sections and the apple* ones. diff --git a/llvm/include/llvm/DWARFLinker/DWARFStreamer.h b/llvm/include/llvm/DWARFLinker/DWARFStreamer.h --- a/llvm/include/llvm/DWARFLinker/DWARFStreamer.h +++ b/llvm/include/llvm/DWARFLinker/DWARFStreamer.h @@ -105,6 +105,19 @@ void emitDwarfDebugRangeListFooter(const CompileUnit &Unit, MCSymbol *EndLabel) override; + /// Emit debug locations(.debug_loc, .debug_loclists) header. + MCSymbol *emitDwarfDebugLocListHeader(const CompileUnit &Unit) override; + + /// Emit debug ranges(.debug_loc, .debug_loclists) fragment. + void emitDwarfDebugLocListFragment( + const CompileUnit &Unit, + const DWARFLocationExpressionsVector &LinkedLocationExpression, + PatchLocation Patch) override; + + /// Emit debug ranges(.debug_loc, .debug_loclists) footer. + void emitDwarfDebugLocListFooter(const CompileUnit &Unit, + MCSymbol *EndLabel) override; + /// Emit .debug_aranges entries for \p Unit void emitDwarfDebugArangesTable(const CompileUnit &Unit, const AddressRanges &LinkedRanges) override; @@ -115,14 +128,6 @@ 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. - void emitLocationsForUnit( - const CompileUnit &Unit, DWARFContext &Dwarf, - std::function &)> ProcessExpr) - override; - /// Emit the line table described in \p Rows into the debug_line section. void emitLineTableForUnit(MCDwarfLineTableParams Params, StringRef PrologueBytes, unsigned MinInstLength, @@ -181,6 +186,10 @@ return MacroSectionSize; } + uint64_t getLocListsSectionSize() const override { + return LocListsSectionSize; + } + void emitMacroTables(DWARFContext *Context, const Offset2UnitMap &UnitMacroMap, OffsetsStringPool &StringPool) override; @@ -210,6 +219,18 @@ const AddressRanges &LinkedRanges, PatchLocation Patch); + /// Emit piece of .debug_loc for \p LinkedRanges. + void emitDwarfDebugLocTableFragment( + const CompileUnit &Unit, + const DWARFLocationExpressionsVector &LinkedLocationExpression, + PatchLocation Patch); + + /// Emit piece of .debug_loclists for \p LinkedRanges. + void emitDwarfDebugLocListsTableFragment( + const CompileUnit &Unit, + const DWARFLocationExpressionsVector &LinkedLocationExpression, + PatchLocation Patch); + /// \defgroup MCObjects MC layer objects constructed by the streamer /// @{ std::unique_ptr MRI; @@ -234,6 +255,7 @@ uint64_t RangesSectionSize = 0; uint64_t RngListsSectionSize = 0; uint64_t LocSectionSize = 0; + uint64_t LocListsSectionSize = 0; uint64_t LineSectionSize = 0; uint64_t FrameSectionSize = 0; uint64_t DebugInfoSectionSize = 0; diff --git a/llvm/lib/DWARFLinker/DWARFLinker.cpp b/llvm/lib/DWARFLinker/DWARFLinker.cpp --- a/llvm/lib/DWARFLinker/DWARFLinker.cpp +++ b/llvm/lib/DWARFLinker/DWARFLinker.cpp @@ -1261,8 +1261,13 @@ } if (AttrSpec.Attr == dwarf::DW_AT_declaration && Value) Info.IsDeclaration = true; - Die.addValue(DIEAlloc, dwarf::Attribute(AttrSpec.Attr), - dwarf::Form(AttrSpec.Form), DIEInteger(Value)); + + if (AttrSpec.Form == dwarf::DW_FORM_loclistx) + Die.addValue(DIEAlloc, dwarf::Attribute(AttrSpec.Attr), + dwarf::Form(AttrSpec.Form), DIELocList(Value)); + else + Die.addValue(DIEAlloc, dwarf::Attribute(AttrSpec.Attr), + dwarf::Form(AttrSpec.Form), DIEInteger(Value)); return AttrSize; } @@ -1285,6 +1290,27 @@ return 0; } + Value = *Offset; + AttrSpec.Form = dwarf::DW_FORM_sec_offset; + AttrSize = Unit.getOrigUnit().getFormParams().getDwarfOffsetByteSize(); + } else if (AttrSpec.Form == dwarf::DW_FORM_loclistx) { + // DWARFLinker does not generate .debug_addr table. Thus we need to change + // all "addrx" related forms to "addr" version. Change DW_FORM_loclistx + // 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().getLoclistOffset(*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(); @@ -1307,6 +1333,7 @@ &InputDIE); return 0; } + PatchLocation Patch = Die.addValue(DIEAlloc, dwarf::Attribute(AttrSpec.Attr), dwarf::Form(AttrSpec.Form), DIEInteger(Value)); @@ -1314,13 +1341,10 @@ 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. - // FIXME: use DWARFAttribute::mayHaveLocationDescription(). - else if (AttrSpec.Attr == dwarf::DW_AT_location || - AttrSpec.Attr == dwarf::DW_AT_frame_base) { + } else if (DWARFAttribute::mayHaveLocationList(AttrSpec.Attr) && + dwarf::doesFormBelongToClass(AttrSpec.Form, + DWARFFormValue::FC_SectionOffset, + Unit.getOrigUnit().getVersion())) { Unit.noteLocationAttribute(Patch, Info.PCOffset); } else if (AttrSpec.Attr == dwarf::DW_AT_declaration && Value) Info.IsDeclaration = true; @@ -1383,6 +1407,7 @@ case dwarf::DW_FORM_flag: case dwarf::DW_FORM_flag_present: case dwarf::DW_FORM_rnglistx: + case dwarf::DW_FORM_loclistx: return cloneScalarAttribute(Die, InputDIE, File, Unit, AttrSpec, Val, AttrSize, Info); default: @@ -1464,6 +1489,12 @@ case dwarf::DW_AT_str_offsets_base: // FIXME: Use the string offset table with Dwarf 5. return true; + case dwarf::DW_AT_loclists_base: + // In case !Update the .debug_addr table is not generated/preserved. + // Thus instead of DW_FORM_loclistx the DW_FORM_sec_offset is used. + // Since DW_AT_loclists_base is used for only DW_FORM_loclistx the + // DW_AT_loclists_base is removed. + return !Update; case dwarf::DW_AT_location: case dwarf::DW_AT_frame_base: // FIXME: for some reason dsymutil-classic keeps the location attributes @@ -1732,6 +1763,61 @@ } } +void DWARFLinker::generateUnitLocations( + CompileUnit &Unit, const DWARFFile &File, + ExpressionHandlerRef ExprHandler) const { + if (LLVM_UNLIKELY(Options.Update)) + return; + + const LocListAttributesTy &AllLocListAttributes = + Unit.getLocationAttributes(); + + if (AllLocListAttributes.empty()) + return; + + // Emit locations list table header. + MCSymbol *EndLabel = TheDwarfEmitter->emitDwarfDebugLocListHeader(Unit); + + for (auto &CurLocAttr : AllLocListAttributes) { + // Get location expressions vector corresponding to the current attribute + // from the source DWARF. + Expected OriginalLocations = + Unit.getOrigUnit().findLoclistFromOffset((CurLocAttr.first).get()); + + if (!OriginalLocations) { + llvm::consumeError(OriginalLocations.takeError()); + reportWarning("Invalid location attribute ignored.", File); + continue; + } + + DWARFLocationExpressionsVector LinkedLocationExpressions; + for (DWARFLocationExpression &CurExpression : *OriginalLocations) { + + DWARFLocationExpression LinkedExpression; + + if (CurExpression.Range) { + // Relocate address range. + LinkedExpression.Range = { + CurExpression.Range->LowPC + CurLocAttr.second, + CurExpression.Range->HighPC + CurLocAttr.second}; + } + + // Clone expression. + LinkedExpression.Expr.reserve(CurExpression.Expr.size()); + ExprHandler(CurExpression.Expr, LinkedExpression.Expr); + + LinkedLocationExpressions.push_back(LinkedExpression); + } + + // Emit locations list table fragment corresponding to the CurLocAttr. + TheDwarfEmitter->emitDwarfDebugLocListFragment( + Unit, LinkedLocationExpressions, CurLocAttr.first); + } + + // Emit locations list table footer. + TheDwarfEmitter->emitDwarfDebugLocListFooter(Unit, EndLabel); +} + /// Insert the new line info sequence \p Seq into the current /// set of already linked line info \p Rows. static void insertLineSequence(std::vector &Seq, @@ -2314,17 +2400,17 @@ Linker.generateUnitRanges(*CurrentUnit, File); - auto ProcessExpr = [&](StringRef Bytes, - SmallVectorImpl &Buffer) { + auto ProcessExpr = [&](SmallVectorImpl &SrcBytes, + SmallVectorImpl &OutBytes) { DWARFUnit &OrigUnit = CurrentUnit->getOrigUnit(); - DataExtractor Data(Bytes, IsLittleEndian, + DataExtractor Data(SrcBytes, IsLittleEndian, OrigUnit.getAddressByteSize()); cloneExpression(Data, DWARFExpression(Data, OrigUnit.getAddressByteSize(), OrigUnit.getFormParams().Format), - File, *CurrentUnit, Buffer); + File, *CurrentUnit, OutBytes); }; - Emitter->emitLocationsForUnit(*CurrentUnit, DwarfContext, ProcessExpr); + Linker.generateUnitLocations(*CurrentUnit, File, ProcessExpr); } } @@ -2433,6 +2519,8 @@ Dwarf.getDWARFObj().getAddrSection().Data, "debug_addr"); TheDwarfEmitter->emitSectionContents( Dwarf.getDWARFObj().getRnglistsSection().Data, "debug_rnglists"); + TheDwarfEmitter->emitSectionContents( + Dwarf.getDWARFObj().getLoclistsSection().Data, "debug_loclists"); } void DWARFLinker::addObjectFile(DWARFFile &File, objFileLoader Loader, @@ -2518,20 +2606,6 @@ continue; } - // Check for unsupported sections. Following sections can be referenced - // from .debug_info section. Current DWARFLinker implementation does not - // support or update references to these tables. Thus we report warning - // and skip corresponding object file. - if (!OptContext.File.Dwarf->getDWARFObj() - .getLoclistsSection() - .Data.empty()) { - reportWarning("'.debug_loclists' is not currently supported: file " - "will be skipped", - OptContext.File); - OptContext.Skip = true; - continue; - } - // In a first phase, just read in the debug info and load all clang modules. OptContext.CompileUnits.reserve( OptContext.File.Dwarf->getNumCompileUnits()); diff --git a/llvm/lib/DWARFLinker/DWARFStreamer.cpp b/llvm/lib/DWARFLinker/DWARFStreamer.cpp --- a/llvm/lib/DWARFLinker/DWARFStreamer.cpp +++ b/llvm/lib/DWARFLinker/DWARFStreamer.cpp @@ -110,6 +110,7 @@ RangesSectionSize = 0; RngListsSectionSize = 0; LocSectionSize = 0; + LocListsSectionSize = 0; LineSectionSize = 0; FrameSectionSize = 0; DebugInfoSectionSize = 0; @@ -206,6 +207,8 @@ .Case("debug_addr", MC->getObjectFileInfo()->getDwarfAddrSection()) .Case("debug_rnglists", MC->getObjectFileInfo()->getDwarfRnglistsSection()) + .Case("debug_loclists", + MC->getObjectFileInfo()->getDwarfLoclistsSection()) .Default(nullptr); if (Section) { @@ -483,73 +486,149 @@ RngListsSectionSize += 1; } -/// Emit location lists for \p Unit and update attributes to point to the new -/// entries. -void DwarfStreamer::emitLocationsForUnit( - const CompileUnit &Unit, DWARFContext &Dwarf, - std::function &)> ProcessExpr) { - const auto &Attributes = Unit.getLocationAttributes(); +/// Emit debug locations(.debug_loc, .debug_loclists) header. +MCSymbol *DwarfStreamer::emitDwarfDebugLocListHeader(const CompileUnit &Unit) { + if (Unit.getOrigUnit().getVersion() < 5) + return nullptr; + + // Make .debug_loclists the current section. + MS->switchSection(MC->getObjectFileInfo()->getDwarfLoclistsSection()); + + MCSymbol *BeginLabel = Asm->createTempSymbol("Bloclists"); + MCSymbol *EndLabel = Asm->createTempSymbol("Eloclists"); + unsigned AddressSize = Unit.getOrigUnit().getAddressByteSize(); + + // Length + Asm->emitLabelDifference(EndLabel, BeginLabel, sizeof(uint32_t)); + Asm->OutStreamer->emitLabel(BeginLabel); + LocListsSectionSize += sizeof(uint32_t); + + // Version. + MS->emitInt16(5); + LocListsSectionSize += sizeof(uint16_t); + + // Address size. + MS->emitInt8(AddressSize); + LocListsSectionSize++; + + // Seg_size + MS->emitInt8(0); + LocListsSectionSize++; - if (Attributes.empty()) + // Offset entry count + MS->emitInt32(0); + LocListsSectionSize += sizeof(uint32_t); + + return EndLabel; +} + +/// Emit debug locations(.debug_loc, .debug_loclists) fragment. +void DwarfStreamer::emitDwarfDebugLocListFragment( + const CompileUnit &Unit, + const DWARFLocationExpressionsVector &LinkedLocationExpression, + PatchLocation Patch) { + if (Unit.getOrigUnit().getVersion() < 5) { + emitDwarfDebugLocTableFragment(Unit, LinkedLocationExpression, Patch); return; + } - MS->switchSection(MC->getObjectFileInfo()->getDwarfLocSection()); + emitDwarfDebugLocListsTableFragment(Unit, LinkedLocationExpression, Patch); +} + +/// Emit debug locations(.debug_loc, .debug_loclists) footer. +void DwarfStreamer::emitDwarfDebugLocListFooter(const CompileUnit &Unit, + MCSymbol *EndLabel) { + if (Unit.getOrigUnit().getVersion() < 5) + return; + + // Make .debug_loclists the current section. + MS->switchSection(MC->getObjectFileInfo()->getDwarfLoclistsSection()); + + if (EndLabel != nullptr) + Asm->OutStreamer->emitLabel(EndLabel); +} +/// Emit piece of .debug_loc for \p LinkedLocationExpression. +void DwarfStreamer::emitDwarfDebugLocTableFragment( + const CompileUnit &Unit, + const DWARFLocationExpressionsVector &LinkedLocationExpression, + PatchLocation Patch) { + Patch.set(LocSectionSize); + + // Make .debug_loc to be current section. + MS->switchSection(MC->getObjectFileInfo()->getDwarfLocSection()); unsigned AddressSize = Unit.getOrigUnit().getAddressByteSize(); - uint64_t BaseAddressMarker = (AddressSize == 8) - ? std::numeric_limits::max() - : std::numeric_limits::max(); - const DWARFSection &InputSec = Dwarf.getDWARFObj().getLocSection(); - DataExtractor Data(InputSec.Data, Dwarf.isLittleEndian(), AddressSize); - DWARFUnit &OrigUnit = Unit.getOrigUnit(); - auto OrigUnitDie = OrigUnit.getUnitDIE(false); - int64_t UnitPcOffset = 0; - if (auto OrigLowPc = - dwarf::toAddress(OrigUnitDie.find(dwarf::DW_AT_low_pc))) { - assert(Unit.getLowPc()); - UnitPcOffset = int64_t(*OrigLowPc) - *Unit.getLowPc(); + + // Emit ranges. + uint64_t BaseAddress = 0; + if (std::optional LowPC = Unit.getLowPc()) + BaseAddress = *LowPC; + + for (const DWARFLocationExpression &LocExpression : + LinkedLocationExpression) { + if (LocExpression.Range) { + MS->emitIntValue(LocExpression.Range->LowPC - BaseAddress, AddressSize); + MS->emitIntValue(LocExpression.Range->HighPC - BaseAddress, AddressSize); + + LocSectionSize += AddressSize; + LocSectionSize += AddressSize; + } + + Asm->OutStreamer->emitIntValue(LocExpression.Expr.size(), 2); + Asm->OutStreamer->emitBytes(StringRef( + (const char *)LocExpression.Expr.data(), LocExpression.Expr.size())); + LocSectionSize += LocExpression.Expr.size() + 2; } - SmallVector Buffer; - for (const auto &Attr : Attributes) { - uint64_t Offset = Attr.first.get(); - Attr.first.set(LocSectionSize); - // This is the quantity to add to the old location address to get - // the correct address for the new one. - int64_t LocPcOffset = Attr.second + UnitPcOffset; - while (Data.isValidOffset(Offset)) { - uint64_t Low = Data.getUnsigned(&Offset, AddressSize); - uint64_t High = Data.getUnsigned(&Offset, AddressSize); - LocSectionSize += 2 * AddressSize; - // End of list entry. - if (Low == 0 && High == 0) { - Asm->OutStreamer->emitIntValue(0, AddressSize); - Asm->OutStreamer->emitIntValue(0, AddressSize); - break; - } - // Base address selection entry. - if (Low == BaseAddressMarker) { - Asm->OutStreamer->emitIntValue(BaseAddressMarker, AddressSize); - Asm->OutStreamer->emitIntValue(High + Attr.second, AddressSize); - LocPcOffset = 0; - continue; - } - // Location list entry. - Asm->OutStreamer->emitIntValue(Low + LocPcOffset, AddressSize); - Asm->OutStreamer->emitIntValue(High + LocPcOffset, AddressSize); - uint64_t Length = Data.getU16(&Offset); - Asm->OutStreamer->emitIntValue(Length, 2); - // Copy the bytes into to the buffer, process them, emit them. - Buffer.reserve(Length); - Buffer.resize(0); - StringRef Input = InputSec.Data.substr(Offset, Length); - ProcessExpr(Input, Buffer); - Asm->OutStreamer->emitBytes( - StringRef((const char *)Buffer.data(), Length)); - Offset += Length; - LocSectionSize += Length + 2; + // Add the terminator entry. + MS->emitIntValue(0, AddressSize); + MS->emitIntValue(0, AddressSize); + + LocSectionSize += AddressSize; + LocSectionSize += AddressSize; +} + +/// Emit piece of .debug_loclists for \p LinkedLocationExpression. +void DwarfStreamer::emitDwarfDebugLocListsTableFragment( + const CompileUnit &Unit, + const DWARFLocationExpressionsVector &LinkedLocationExpression, + PatchLocation Patch) { + Patch.set(LocListsSectionSize); + + // Make .debug_loclists the current section. + MS->switchSection(MC->getObjectFileInfo()->getDwarfLoclistsSection()); + + unsigned AddressSize = Unit.getOrigUnit().getAddressByteSize(); + + for (const DWARFLocationExpression &LocExpression : + LinkedLocationExpression) { + if (LocExpression.Range) { + // Emit type of entry. + MS->emitInt8(dwarf::DW_LLE_start_length); + LocListsSectionSize += 1; + + // Emit start address. + MS->emitIntValue(LocExpression.Range->LowPC, AddressSize); + LocListsSectionSize += AddressSize; + + // Emit length of the range. + LocListsSectionSize += MS->emitSLEB128IntValue( + LocExpression.Range->HighPC - LocExpression.Range->LowPC); + } else { + // Emit type of entry. + MS->emitInt8(dwarf::DW_LLE_default_location); + LocListsSectionSize += 1; } + + LocListsSectionSize += MS->emitULEB128IntValue(LocExpression.Expr.size()); + Asm->OutStreamer->emitBytes(StringRef( + (const char *)LocExpression.Expr.data(), LocExpression.Expr.size())); + LocListsSectionSize += LocExpression.Expr.size(); } + + // Emit the terminator entry. + MS->emitInt8(dwarf::DW_LLE_end_of_list); + LocListsSectionSize += 1; } void DwarfStreamer::emitLineTableForUnit(MCDwarfLineTableParams Params, diff --git a/llvm/test/tools/dsymutil/Inputs/dwarf5-loclists.o b/llvm/test/tools/dsymutil/Inputs/dwarf5-loclists.o new file mode 100644 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 GIT binary patch literal 0 Hc$@ +## +## int main ( int argv, char** argc ) { +## printf ("\n argv %d", argv ); +## argv++; +## printf ("\n argv %d", argv ); +## argv++; +## printf ("\n argv %d", &argv ); +## return 0; +## } + +## $ clang -gdwarf-5 dwarf5-loclists.c -c -O2 -o dwarf5-rnglists.o + +#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_formal_parameter +#DWARF-CHECK: DW_AT_name {{.*}} "dwarf5-loclists.c" +#DWARF-CHECK-NOT: DW_AT_loclists_base +#DWARF-CHECK: DW_TAG_formal_parameter +#DWARF-CHECK: DW_AT_location [DW_FORM_sec_offset] (0x0000000c: +#DWARF-CHECK: [0x0000000100000f70, 0x0000000100000f87): DW_OP_reg5 RDI +#DWARF-CHECK: [0x0000000100000f87, 0x0000000100000f93): DW_OP_reg3 RBX +#DWARF-CHECK: [0x0000000100000f93, 0x0000000100000f9d): DW_OP_reg4 RSI +#DWARF-CHECK: [0x0000000100000fa0, 0x0000000100000fa3): DW_OP_reg3 RBX +#DWARF-CHECK: [0x0000000100000fa3, 0x0000000100000fbc): DW_OP_breg6 RBP-20) +#DWARF-CHECK: DW_AT_name {{.*}} "argv" +#DWARF-CHECK: DW_TAG_formal_parameter +#DWARF-CHECK: DW_AT_location [DW_FORM_sec_offset] (0x0000004a: +#DWARF-CHECK: [0x0000000100000f70, 0x0000000100000f89): DW_OP_reg4 RSI +#DWARF-CHECK: [0x0000000100000f89, 0x0000000100000fbc): DW_OP_entry_value(DW_OP_reg4 RSI), DW_OP_stack_value) +#DWARF-CHECK: DW_AT_name {{.*}} "argc" +#DWARF-CHECK: .debug_loclists contents: +#DWARF-CHECK: 0x00000000: locations list header: length = 0x00000062, format = DWARF32, version = 0x0005, addr_size = 0x08, seg_size = 0x00, offset_entry_count = 0x00000000 +#DWARF-CHECK: 0x0000000c: +#DWARF-CHECK: DW_LLE_start_length (0x0000000100000f70, 0x0000000000000017) +#DWARF-CHECK: => [0x0000000100000f70, 0x0000000100000f87): DW_OP_reg5 RDI +#DWARF-CHECK: DW_LLE_start_length (0x0000000100000f87, 0x000000000000000c) +#DWARF-CHECK: => [0x0000000100000f87, 0x0000000100000f93): DW_OP_reg3 RBX +#DWARF-CHECK: DW_LLE_start_length (0x0000000100000f93, 0x000000000000000a) +#DWARF-CHECK: => [0x0000000100000f93, 0x0000000100000f9d): DW_OP_reg4 RSI +#DWARF-CHECK: DW_LLE_start_length (0x0000000100000fa0, 0x0000000000000003) +#DWARF-CHECK: => [0x0000000100000fa0, 0x0000000100000fa3): DW_OP_reg3 RBX +#DWARF-CHECK: DW_LLE_start_length (0x0000000100000fa3, 0x0000000000000019) +#DWARF-CHECK: => [0x0000000100000fa3, 0x0000000100000fbc): DW_OP_breg6 RBP-20 +#DWARF-CHECK: DW_LLE_end_of_list () +#DWARF-CHECK: 0x0000004a: +#DWARF-CHECK: DW_LLE_start_length (0x0000000100000f70, 0x0000000000000019) +#DWARF-CHECK: => [0x0000000100000f70, 0x0000000100000f89): DW_OP_reg4 RSI +#DWARF-CHECK: DW_LLE_start_length (0x0000000100000f89, 0x0000000000000033) +#DWARF-CHECK: => [0x0000000100000f89, 0x0000000100000fbc): DW_OP_entry_value(DW_OP_reg4 RSI), DW_OP_stack_value +#DWARF-CHECK: DW_LLE_end_of_list () + +#UPD-DWARF-CHECK: DW_TAG_compile_unit +#UPD-DWARF-CHECK: DW_AT_name {{.*}} "dwarf5-loclists.c" +#UPD-DWARF-CHECK: DW_AT_loclists_base [DW_FORM_sec_offset] (0x0000000c) +#UPD-DWARF-CHECK: DW_TAG_formal_parameter [8] (0x00000058) +#UPD-DWARF-CHECK: DW_AT_location [DW_FORM_loclistx] (indexed (0x0) loclist = 0x00000014: +#UPD-DWARF-CHECK: [0x0000000000000000, 0x0000000000000017): DW_OP_reg5 RDI +#UPD-DWARF-CHECK: [0x0000000000000017, 0x0000000000000023): DW_OP_reg3 RBX +#UPD-DWARF-CHECK: [0x0000000000000023, 0x000000000000002d): DW_OP_reg4 RSI +#UPD-DWARF-CHECK: [0x0000000000000030, 0x0000000000000033): DW_OP_reg3 RBX +#UPD-DWARF-CHECK: [0x0000000000000033, 0x000000000000004c): DW_OP_breg6 RBP-20) +#UPD-DWARF-CHECK: DW_AT_name {{.*}} "argv" +#UPD-DWARF-CHECK: DW_TAG_formal_parameter [8] (0x00000058) +#UPD-DWARF-CHECK: DW_AT_location [DW_FORM_loclistx] (indexed (0x1) loclist = 0x0000002f: +#UPD-DWARF-CHECK: [0x0000000000000000, 0x0000000000000019): DW_OP_reg4 RSI +#UPD-DWARF-CHECK: [0x0000000000000019, 0x000000000000004c): DW_OP_entry_value(DW_OP_reg4 RSI), DW_OP_stack_value) +#UPD-DWARF-CHECK: DW_AT_name {{.*}} "argc" +#UPD-DWARF-CHECK: .debug_loclists contents: +#UPD-DWARF-CHECK: 0x00000000: locations list header: length = 0x00000039, format = DWARF32, version = 0x0005, addr_size = 0x08, seg_size = 0x00, offset_entry_count = 0x00000002 +#UPD-DWARF-CHECK: offsets: [ +#UPD-DWARF-CHECK: 0x00000008 => 0x00000014 +#UPD-DWARF-CHECK: 0x00000023 => 0x0000002f +#UPD-DWARF-CHECK: ] +#UPD-DWARF-CHECK: 0x00000014: +#UPD-DWARF-CHECK: DW_LLE_offset_pair (0x0000000000000000, 0x0000000000000017): DW_OP_reg5 RDI +#UPD-DWARF-CHECK: DW_LLE_offset_pair (0x0000000000000017, 0x0000000000000023): DW_OP_reg3 RBX +#UPD-DWARF-CHECK: DW_LLE_offset_pair (0x0000000000000023, 0x000000000000002d): DW_OP_reg4 RSI +#UPD-DWARF-CHECK: DW_LLE_offset_pair (0x0000000000000030, 0x0000000000000033): DW_OP_reg3 RBX +#UPD-DWARF-CHECK: DW_LLE_offset_pair (0x0000000000000033, 0x000000000000004c): DW_OP_breg6 RBP-20 +#UPD-DWARF-CHECK: DW_LLE_end_of_list () +#UPD-DWARF-CHECK: 0x0000002f: +#UPD-DWARF-CHECK: DW_LLE_offset_pair (0x0000000000000000, 0x0000000000000019): DW_OP_reg4 RSI +#UPD-DWARF-CHECK: DW_LLE_offset_pair (0x0000000000000019, 0x000000000000004c): DW_OP_entry_value(DW_OP_reg4 RSI), DW_OP_stack_value +#UPD-DWARF-CHECK: DW_LLE_end_of_list () + +--- +triple: 'x86_64-apple-darwin' +objects: + - filename: 'dwarf5-loclists.o' + timestamp: 1676048242 + symbols: + - { sym: _main, objAddr: 0x0, binAddr: 0x100000F70, size: 0x48 } + - { sym: _g1, binAddr: 0x100001000, size: 0x0 } diff --git a/llvm/test/tools/llvm-dwarfutil/ELF/X86/dwarf5-loclists.test b/llvm/test/tools/llvm-dwarfutil/ELF/X86/dwarf5-loclists.test new file mode 100644 --- /dev/null +++ b/llvm/test/tools/llvm-dwarfutil/ELF/X86/dwarf5-loclists.test @@ -0,0 +1,201 @@ +## Test that DWARFv5 .debug_loclists 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 {{.*}}"CU1" +#DWARF-CHECK-NOT: DW_AT_loclists_base +#DWARF-CHECK: DW_TAG_variable +#DWARF-CHECK: DW_AT_name {{.*}}"var1" +#DWARF-CHECK: DW_AT_location [DW_FORM_sec_offset] (0x0000000c: +#DWARF-CHECK: [0x0000000000001130, 0x0000000000001140): DW_OP_reg5 RDI) +#DWARF-CHECK: DW_AT_name {{.*}}"var2" +#DWARF-CHECK: DW_AT_location [DW_FORM_sec_offset] (0x00000019: +#DWARF-CHECK: : DW_OP_reg5 RDI) +#DWARF-CHECK: DW_TAG_variable +#DWARF-CHECK: DW_AT_name {{.*}}"var3" +#DWARF-CHECK: DW_AT_location [DW_FORM_sec_offset] (0x0000001d: +#DWARF-CHECK: [0x0000000000001140, 0x0000000000001150): DW_OP_reg5 RDI +#DWARF-CHECK: [0x0000000000001160, 0x0000000000001170): DW_OP_reg6 RBP) + +#UPD-DWARF-CHECK: DW_TAG_compile_unit +#UPD-DWARF-CHECK: DW_AT_name {{.*}}"CU1" +#UPD-DWARF-CHECK: DW_AT_loclists_base [DW_FORM_sec_offset] (0x0000000c) +#UPD-DWARF-CHECK: DW_TAG_variable +#UPD-DWARF-CHECK: DW_AT_name {{.*}}"var1" +#UPD-DWARF-CHECK: DW_AT_location [DW_FORM_loclistx] (indexed (0x0) loclist = 0x00000018: +#UPD-DWARF-CHECK: [0x0000000000001130, 0x0000000000001140): DW_OP_reg5 RDI) +#UPD-DWARF-CHECK: DW_TAG_variable +#UPD-DWARF-CHECK: DW_AT_name {{.*}}"var2" +#UPD-DWARF-CHECK: DW_AT_location [DW_FORM_loclistx] (indexed (0x1) loclist = 0x0000001e: +#UPD-DWARF-CHECK: : DW_OP_reg5 RDI) +#UPD-DWARF-CHECK: DW_TAG_variable +#UPD-DWARF-CHECK: DW_AT_name {{.*}}"var3" +#UPD-DWARF-CHECK: DW_AT_location [DW_FORM_loclistx] (indexed (0x2) loclist = 0x00000022: +#UPD-DWARF-CHECK: [0x0000000000001140, 0x0000000000001150): DW_OP_reg5 RDI +#UPD-DWARF-CHECK: [0x0000000000001160, 0x0000000000001170): DW_OP_reg6 RBP) + +## Following yaml description has Content of the .debug_rnglists exactly like following data vvvvvvvvvvv +## .debug_rnglists contents: +## 0x00000000: range list header: length = 0x0000003e, format = DWARF32, version = 0x0005, addr_size = 0x08, seg_size = 0x00, offset_entry_count = 0x00000005 +## offsets: [ +## 0x00000014 => 0x00000020 +## 0x00000018 => 0x00000024 +## 0x0000001c => 0x00000028 +## 0x00000027 => 0x00000033 +## 0x00000032 => 0x0000003e +## ] +## ranges: +## 0x00000020: [DW_RLE_startx_length]: 0x0000000000000000, 0x0000000000000010 => [0x0000000000001130, 0x0000000000001140) +## 0x00000023: [DW_RLE_end_of_list ] +## 0x00000024: [DW_RLE_startx_length]: 0x0000000000000001, 0x0000000000000010 => [0x0000000000001140, 0x0000000000001150) +## 0x00000027: [DW_RLE_end_of_list ] +## 0x00000028: [DW_RLE_start_length ]: 0x0000000000001150, 0x0000000000000010 => [0x0000000000001150, 0x0000000000001160) +## 0x00000032: [DW_RLE_end_of_list ] +## 0x00000033: [DW_RLE_start_length ]: 0x0000000000001160, 0x0000000000000010 => [0x0000000000001160, 0x0000000000001170) +## 0x0000003d: [DW_RLE_end_of_list ] +## 0x0000003e: [DW_RLE_startx_length]: 0x0000000000000000, 0x0000000000000040 => [0x0000000000001130, 0x0000000000001170) +## 0x00000041: [DW_RLE_end_of_list ] + + +## Following yaml description has Content of the .debug_loclists exactly like following data vvvvvvvvvvv +## .debug_loclists contents: +## 0x00000000: locations list header: length = 0x00000029, format = DWARF32, version = 0x0005, addr_size = 0x08, seg_size = 0x00, offset_entry_count = 0x00000003 +## offsets: [ +## 0x0000000c => 0x00000018 +## 0x00000012 => 0x0000001e +## 0x00000016 => 0x00000022 +## ] +## 0x00000018: +## DW_LLE_startx_length (0x0000000000000000, 0x0000000000000010): DW_OP_reg5 RDI +## DW_LLE_end_of_list () +## +## 0x0000001e: +## DW_LLE_default_location() +## => : DW_OP_reg5 RDI +## DW_LLE_end_of_list () +## +## 0x00000022: +## DW_LLE_startx_length (0x0000000000000001, 0x0000000000000010): DW_OP_reg5 RDI +## DW_LLE_startx_length (0x0000000000000003, 0x0000000000000010): DW_OP_reg6 RBP +## DW_LLE_end_of_list () + +--- !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" + - Name: .debug_loclists + Type: SHT_PROGBITS + Flags: [ ] + Content: "2900000005000800030000000c0000001200000016000000030010015500050155000301100155030310015600" +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_loclists_base + Form: DW_FORM_sec_offset + - Attribute: DW_AT_addr_base + Form: DW_FORM_sec_offset + - Tag: DW_TAG_base_type + Children: DW_CHILDREN_no + Attributes: + - Attribute: DW_AT_name + Form: DW_FORM_string + - Tag: DW_TAG_variable + Children: DW_CHILDREN_no + Attributes: + - Attribute: DW_AT_name + Form: DW_FORM_string + - Attribute: DW_AT_const_value + Form: DW_FORM_data4 + - Attribute: DW_AT_type + Form: DW_FORM_ref_addr + - Attribute: DW_AT_location + Form: DW_FORM_loclistx + 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: 0xc + - Value: 0x8 + - AbbrCode: 2 + Values: + - CStr: int + - AbbrCode: 3 + Values: + - CStr: var1 + - Value: 0x00000000 + - Value: 0x00000029 + - Value: 0x0 + - AbbrCode: 3 + Values: + - CStr: var2 + - Value: 0x00000000 + - Value: 0x00000029 + - Value: 0x1 + - AbbrCode: 3 + Values: + - CStr: var3 + - Value: 0x00000000 + - Value: 0x00000029 + - Value: 0x2 + - 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-loclists.test b/llvm/test/tools/llvm-dwarfutil/ELF/X86/warning-skipped-loclists.test deleted file mode 100644 --- a/llvm/test/tools/llvm-dwarfutil/ELF/X86/warning-skipped-loclists.test +++ /dev/null @@ -1,54 +0,0 @@ -## This test checks the warning message displayed if input file -## contains .debug_loclists 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_loclists' 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_loclists - Type: SHT_PROGBITS - Flags: [ ] - Content: "0000000000000000000000" -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 -...