diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2023-12-09 13:28:42 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2023-12-09 13:28:42 +0000 |
commit | b1c73532ee8997fe5dfbeb7d223027bdf99758a0 (patch) | |
tree | 7d6e51c294ab6719475d660217aa0c0ad0526292 /llvm/lib/DWARFLinker | |
parent | 7fa27ce4a07f19b07799a767fc29416f3b625afb (diff) | |
download | src-b1c73532ee8997fe5dfbeb7d223027bdf99758a0.tar.gz src-b1c73532ee8997fe5dfbeb7d223027bdf99758a0.zip |
Diffstat (limited to 'llvm/lib/DWARFLinker')
-rw-r--r-- | llvm/lib/DWARFLinker/DWARFLinker.cpp | 319 | ||||
-rw-r--r-- | llvm/lib/DWARFLinker/DWARFLinkerCompileUnit.cpp | 2 | ||||
-rw-r--r-- | llvm/lib/DWARFLinker/DWARFStreamer.cpp | 103 |
3 files changed, 222 insertions, 202 deletions
diff --git a/llvm/lib/DWARFLinker/DWARFLinker.cpp b/llvm/lib/DWARFLinker/DWARFLinker.cpp index e6eccb20114a..1a7ea47adc5c 100644 --- a/llvm/lib/DWARFLinker/DWARFLinker.cpp +++ b/llvm/lib/DWARFLinker/DWARFLinker.cpp @@ -15,6 +15,7 @@ #include "llvm/DWARFLinker/DWARFLinkerDeclContext.h" #include "llvm/DWARFLinker/DWARFStreamer.h" #include "llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h" +#include "llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h" #include "llvm/DebugInfo/DWARF/DWARFContext.h" #include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h" #include "llvm/DebugInfo/DWARF/DWARFDebugLine.h" @@ -140,37 +141,6 @@ AddressesMap::~AddressesMap() = default; DwarfEmitter::~DwarfEmitter() = default; -static std::optional<StringRef> StripTemplateParameters(StringRef Name) { - // We are looking for template parameters to strip from Name. e.g. - // - // operator<<B> - // - // We look for > at the end but if it does not contain any < then we - // have something like operator>>. We check for the operator<=> case. - if (!Name.endswith(">") || Name.count("<") == 0 || Name.endswith("<=>")) - return {}; - - // How many < until we have the start of the template parameters. - size_t NumLeftAnglesToSkip = 1; - - // If we have operator<=> then we need to skip its < as well. - NumLeftAnglesToSkip += Name.count("<=>"); - - size_t RightAngleCount = Name.count('>'); - size_t LeftAngleCount = Name.count('<'); - - // If we have more < than > we have operator< or operator<< - // we to account for their < as well. - if (LeftAngleCount > RightAngleCount) - NumLeftAnglesToSkip += LeftAngleCount - RightAngleCount; - - size_t StartOfTemplate = 0; - while (NumLeftAnglesToSkip--) - StartOfTemplate = Name.find('<', StartOfTemplate) + 1; - - return Name.substr(0, StartOfTemplate - 1); -} - bool DWARFLinker::DIECloner::getDIENames(const DWARFDie &Die, AttributesInfo &Info, OffsetsStringPool &StringPool, @@ -207,6 +177,20 @@ static void resolveRelativeObjectPath(SmallVectorImpl<char> &Buf, DWARFDie CU) { sys::path::append(Buf, dwarf::toString(CU.find(dwarf::DW_AT_comp_dir), "")); } +/// Make a best effort to guess the +/// Xcode.app/Contents/Developer/Toolchains/ path from an SDK path. +static SmallString<128> guessToolchainBaseDir(StringRef SysRoot) { + SmallString<128> Result; + // Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk + StringRef Base = sys::path::parent_path(SysRoot); + if (sys::path::filename(Base) != "SDKs") + return Result; + Base = sys::path::parent_path(Base); + Result = Base; + Result += "/Toolchains"; + return Result; +} + /// Collect references to parseable Swift interfaces in imported /// DW_TAG_module blocks. static void analyzeImportedModule( @@ -228,6 +212,11 @@ static void analyzeImportedModule( SysRoot = CU.getSysRoot(); if (!SysRoot.empty() && Path.startswith(SysRoot)) return; + // Don't track interfaces that are part of the toolchain. + // For example: Swift, _Concurrency, ... + SmallString<128> Toolchain = guessToolchainBaseDir(SysRoot); + if (!Toolchain.empty() && Path.startswith(Toolchain)) + return; std::optional<const char *> Name = dwarf::toString(DIE.find(dwarf::DW_AT_name)); if (!Name) @@ -474,8 +463,10 @@ DWARFLinker::getVariableRelocAdjustment(AddressesMap &RelocMgr, const DWARFExpression::Operation &Op = *It; switch (Op.getCode()) { + case dwarf::DW_OP_const2u: case dwarf::DW_OP_const4u: case dwarf::DW_OP_const8u: + case dwarf::DW_OP_const2s: case dwarf::DW_OP_const4s: case dwarf::DW_OP_const8s: if (NextIt == Expression.end() || !isTlsAddressCode(NextIt->getCode())) @@ -1044,32 +1035,45 @@ void DWARFLinker::assignAbbrev(DIEAbbrev &Abbrev) { unsigned DWARFLinker::DIECloner::cloneStringAttribute(DIE &Die, AttributeSpec AttrSpec, const DWARFFormValue &Val, - const DWARFUnit &, + const DWARFUnit &U, AttributesInfo &Info) { std::optional<const char *> String = dwarf::toString(Val); if (!String) return 0; - DwarfStringPoolEntryRef StringEntry; if (AttrSpec.Form == dwarf::DW_FORM_line_strp) { StringEntry = DebugLineStrPool.getEntry(*String); } else { StringEntry = DebugStrPool.getEntry(*String); + if (AttrSpec.Attr == dwarf::DW_AT_APPLE_origin) { + Info.HasAppleOrigin = true; + if (std::optional<StringRef> FileName = + ObjFile.Addresses->getLibraryInstallName()) { + StringEntry = DebugStrPool.getEntry(*FileName); + } + } + // Update attributes info. if (AttrSpec.Attr == dwarf::DW_AT_name) Info.Name = StringEntry; else if (AttrSpec.Attr == dwarf::DW_AT_MIPS_linkage_name || AttrSpec.Attr == dwarf::DW_AT_linkage_name) Info.MangledName = StringEntry; - + if (U.getVersion() >= 5) { + // Switch everything to DW_FORM_strx strings. + auto StringOffsetIndex = + StringOffsetPool.getValueIndex(StringEntry.getOffset()); + return Die + .addValue(DIEAlloc, dwarf::Attribute(AttrSpec.Attr), + dwarf::DW_FORM_strx, DIEInteger(StringOffsetIndex)) + ->sizeOf(U.getFormParams()); + } // Switch everything to out of line strings. AttrSpec.Form = dwarf::DW_FORM_strp; } - Die.addValue(DIEAlloc, dwarf::Attribute(AttrSpec.Attr), AttrSpec.Form, DIEInteger(StringEntry.getOffset())); - return 4; } @@ -1389,7 +1393,7 @@ unsigned DWARFLinker::DIECloner::cloneAddressAttribute( return Unit.getOrigUnit().getAddressByteSize(); } - auto AddrIndex = AddrPool.getAddrIndex(*Addr); + auto AddrIndex = AddrPool.getValueIndex(*Addr); return Die .addValue(DIEAlloc, static_cast<dwarf::Attribute>(AttrSpec.Attr), @@ -1421,6 +1425,17 @@ unsigned DWARFLinker::DIECloner::cloneScalarAttribute( } } + if (AttrSpec.Attr == dwarf::DW_AT_str_offsets_base) { + // DWARFLinker generates common .debug_str_offsets table used for all + // compile units. The offset to the common .debug_str_offsets table is 8 on + // DWARF32. + Info.AttrStrOffsetBaseSeen = true; + return Die + .addValue(DIEAlloc, dwarf::DW_AT_str_offsets_base, + dwarf::DW_FORM_sec_offset, DIEInteger(8)) + ->sizeOf(Unit.getOrigUnit().getFormParams()); + } + if (LLVM_UNLIKELY(Linker.Options.Update)) { if (auto OptionalValue = Val.getAsUnsignedConstant()) Value = *OptionalValue; @@ -1600,51 +1615,25 @@ unsigned DWARFLinker::DIECloner::cloneAttribute( return 0; } -static bool isObjCSelector(StringRef Name) { - return Name.size() > 2 && (Name[0] == '-' || Name[0] == '+') && - (Name[1] == '['); -} - void DWARFLinker::DIECloner::addObjCAccelerator(CompileUnit &Unit, const DIE *Die, DwarfStringPoolEntryRef Name, OffsetsStringPool &StringPool, bool SkipPubSection) { - assert(isObjCSelector(Name.getString()) && "not an objc selector"); - // Objective C method or class function. - // "- [Class(Category) selector :withArg ...]" - StringRef ClassNameStart(Name.getString().drop_front(2)); - size_t FirstSpace = ClassNameStart.find(' '); - if (FirstSpace == StringRef::npos) + std::optional<ObjCSelectorNames> Names = + getObjCNamesIfSelector(Name.getString()); + if (!Names) return; - - StringRef SelectorStart(ClassNameStart.data() + FirstSpace + 1); - if (!SelectorStart.size()) - return; - - StringRef Selector(SelectorStart.data(), SelectorStart.size() - 1); - Unit.addNameAccelerator(Die, StringPool.getEntry(Selector), SkipPubSection); - - // Add an entry for the class name that points to this - // method/class function. - StringRef ClassName(ClassNameStart.data(), FirstSpace); - Unit.addObjCAccelerator(Die, StringPool.getEntry(ClassName), SkipPubSection); - - if (ClassName[ClassName.size() - 1] == ')') { - size_t OpenParens = ClassName.find('('); - if (OpenParens != StringRef::npos) { - StringRef ClassNameNoCategory(ClassName.data(), OpenParens); - Unit.addObjCAccelerator(Die, StringPool.getEntry(ClassNameNoCategory), - SkipPubSection); - - std::string MethodNameNoCategory(Name.getString().data(), OpenParens + 2); - // FIXME: The missing space here may be a bug, but - // dsymutil-classic also does it this way. - MethodNameNoCategory.append(std::string(SelectorStart)); - Unit.addNameAccelerator(Die, StringPool.getEntry(MethodNameNoCategory), - SkipPubSection); - } - } + Unit.addNameAccelerator(Die, StringPool.getEntry(Names->Selector), + SkipPubSection); + Unit.addObjCAccelerator(Die, StringPool.getEntry(Names->ClassName), + SkipPubSection); + if (Names->ClassNameNoCategory) + Unit.addObjCAccelerator( + Die, StringPool.getEntry(*Names->ClassNameNoCategory), SkipPubSection); + if (Names->MethodNameNoCategory) + Unit.addNameAccelerator( + Die, StringPool.getEntry(*Names->MethodNameNoCategory), SkipPubSection); } static bool @@ -1664,9 +1653,6 @@ shouldSkipAttribute(bool Update, // 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; 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. @@ -1679,6 +1665,12 @@ shouldSkipAttribute(bool Update, } } +struct AttributeLinkedOffsetFixup { + int64_t LinkedOffsetFixupVal; + uint64_t InputAttrStartOffset; + uint64_t InputAttrEndOffset; +}; + DIE *DWARFLinker::DIECloner::cloneDIE(const DWARFDie &InputDIE, const DWARFFile &File, CompileUnit &Unit, int64_t PCOffset, uint32_t OutOffset, @@ -1762,6 +1754,9 @@ DIE *DWARFLinker::DIECloner::cloneDIE(const DWARFDie &InputDIE, Flags |= TF_SkipPC; } + std::optional<StringRef> LibraryInstallName = + ObjFile.Addresses->getLibraryInstallName(); + SmallVector<AttributeLinkedOffsetFixup> AttributesFixups; for (const auto &AttrSpec : Abbrev->attributes()) { if (shouldSkipAttribute(Update, AttrSpec, Flags & TF_SkipPC)) { DWARFFormValue::skipValue(AttrSpec.Form, Data, &Offset, @@ -1769,17 +1764,41 @@ DIE *DWARFLinker::DIECloner::cloneDIE(const DWARFDie &InputDIE, continue; } + AttributeLinkedOffsetFixup CurAttrFixup; + CurAttrFixup.InputAttrStartOffset = InputDIE.getOffset() + Offset; + CurAttrFixup.LinkedOffsetFixupVal = + Unit.getStartOffset() + OutOffset - CurAttrFixup.InputAttrStartOffset; + DWARFFormValue Val = AttrSpec.getFormValue(); uint64_t AttrSize = Offset; Val.extractValue(Data, &Offset, U.getFormParams(), &U); + CurAttrFixup.InputAttrEndOffset = InputDIE.getOffset() + Offset; AttrSize = Offset - AttrSize; - OutOffset += cloneAttribute(*Die, InputDIE, File, Unit, Val, AttrSpec, - AttrSize, AttrInfo, IsLittleEndian); + uint64_t FinalAttrSize = + cloneAttribute(*Die, InputDIE, File, Unit, Val, AttrSpec, AttrSize, + AttrInfo, IsLittleEndian); + if (FinalAttrSize != 0 && ObjFile.Addresses->needToSaveValidRelocs()) + AttributesFixups.push_back(CurAttrFixup); + + OutOffset += FinalAttrSize; } - // Look for accelerator entries. uint16_t Tag = InputDIE.getTag(); + // Add the DW_AT_APPLE_origin attribute to Compile Unit die if we have + // an install name and the DWARF doesn't have the attribute yet. + const bool NeedsAppleOrigin = (Tag == dwarf::DW_TAG_compile_unit) && + LibraryInstallName.has_value() && + !AttrInfo.HasAppleOrigin; + if (NeedsAppleOrigin) { + auto StringEntry = DebugStrPool.getEntry(LibraryInstallName.value()); + Die->addValue(DIEAlloc, dwarf::Attribute(dwarf::DW_AT_APPLE_origin), + dwarf::DW_FORM_strp, DIEInteger(StringEntry.getOffset())); + AttrInfo.Name = StringEntry; + OutOffset += 4; + } + + // Look for accelerator entries. // FIXME: This is slightly wrong. An inline_subroutine without a // low_pc, but with AT_ranges might be interesting to get into the // accelerator tables too. For now stick with dsymutil's behavior. @@ -1797,7 +1816,7 @@ DIE *DWARFLinker::DIECloner::cloneDIE(const DWARFDie &InputDIE, Unit.addNameAccelerator(Die, AttrInfo.Name, Tag == dwarf::DW_TAG_inlined_subroutine); } - if (AttrInfo.Name && isObjCSelector(AttrInfo.Name.getString())) + if (AttrInfo.Name) addObjCAccelerator(Unit, Die, AttrInfo.Name, DebugStrPool, /* SkipPubSection =*/true); @@ -1833,6 +1852,14 @@ DIE *DWARFLinker::DIECloner::cloneDIE(const DWARFDie &InputDIE, } } + if (Unit.getOrigUnit().getVersion() >= 5 && !AttrInfo.AttrStrOffsetBaseSeen && + Die->getTag() == dwarf::DW_TAG_compile_unit) { + // No DW_AT_str_offsets_base seen, add it to the DIE. + Die->addValue(DIEAlloc, dwarf::DW_AT_str_offsets_base, + dwarf::DW_FORM_sec_offset, DIEInteger(8)); + OutOffset += 4; + } + DIEAbbrev NewAbbrev = Die->generateAbbrev(); if (HasChildren) NewAbbrev.setChildrenFlag(dwarf::DW_CHILDREN_yes); @@ -1840,8 +1867,19 @@ DIE *DWARFLinker::DIECloner::cloneDIE(const DWARFDie &InputDIE, Linker.assignAbbrev(NewAbbrev); Die->setAbbrevNumber(NewAbbrev.getNumber()); + uint64_t AbbrevNumberSize = getULEB128Size(Die->getAbbrevNumber()); + // Add the size of the abbreviation number to the output offset. - OutOffset += getULEB128Size(Die->getAbbrevNumber()); + OutOffset += AbbrevNumberSize; + + // Update fixups with the size of the abbreviation number + for (AttributeLinkedOffsetFixup &F : AttributesFixups) + F.LinkedOffsetFixupVal += AbbrevNumberSize; + + for (AttributeLinkedOffsetFixup &F : AttributesFixups) + ObjFile.Addresses->updateAndSaveValidRelocs( + Unit.getOrigUnit().getVersion() >= 5, Unit.getOrigUnit().getOffset(), + F.LinkedOffsetFixupVal, F.InputAttrStartOffset, F.InputAttrEndOffset); if (!HasChildren) { // Update our size. @@ -1868,8 +1906,8 @@ DIE *DWARFLinker::DIECloner::cloneDIE(const DWARFDie &InputDIE, /// 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::generateUnitRanges(CompileUnit &Unit, - const DWARFFile &File) const { +void DWARFLinker::generateUnitRanges(CompileUnit &Unit, const DWARFFile &File, + DebugDieValuePool &AddrPool) const { if (LLVM_UNLIKELY(Options.Update)) return; @@ -1922,14 +1960,14 @@ void DWARFLinker::generateUnitRanges(CompileUnit &Unit, } // Emit linked ranges. - TheDwarfEmitter->emitDwarfDebugRangeListFragment(Unit, LinkedRanges, - AttributePatch); + TheDwarfEmitter->emitDwarfDebugRangeListFragment( + Unit, LinkedRanges, AttributePatch, AddrPool); } // Emit ranges for Unit AT_ranges attribute. if (UnitRngListAttribute.has_value()) TheDwarfEmitter->emitDwarfDebugRangeListFragment( - Unit, LinkedFunctionRanges, *UnitRngListAttribute); + Unit, LinkedFunctionRanges, *UnitRngListAttribute, AddrPool); // Emit ranges footer. TheDwarfEmitter->emitDwarfDebugRangeListFooter(Unit, EndLabel); @@ -2011,13 +2049,14 @@ void DWARFLinker::DIECloner::emitDebugAddrSection( if (DwarfVersion < 5) return; - if (AddrPool.Addrs.empty()) + if (AddrPool.DieValues.empty()) return; MCSymbol *EndLabel = Emitter->emitDwarfDebugAddrsHeader(Unit); patchAddrBase(*Unit.getOutputUnitDIE(), DIEInteger(Emitter->getDebugAddrSectionSize())); - Emitter->emitDwarfDebugAddrs(AddrPool.Addrs, Unit.getOrigUnit().getAddressByteSize()); + Emitter->emitDwarfDebugAddrs(AddrPool.DieValues, + Unit.getOrigUnit().getAddressByteSize()); Emitter->emitDwarfDebugAddrsFooter(Unit, EndLabel); } @@ -2571,7 +2610,7 @@ uint64_t DWARFLinker::DIECloner::cloneAllCompileUnits( if (LLVM_UNLIKELY(Linker.Options.Update)) continue; - Linker.generateUnitRanges(*CurrentUnit, File); + Linker.generateUnitRanges(*CurrentUnit, File, AddrPool); auto ProcessExpr = [&](SmallVectorImpl<uint8_t> &SrcBytes, SmallVectorImpl<uint8_t> &OutBytes, @@ -2617,69 +2656,6 @@ uint64_t DWARFLinker::DIECloner::cloneAllCompileUnits( return OutputDebugInfoSize - StartOutputDebugInfoSize; } -bool DWARFLinker::emitPaperTrailWarnings(const DWARFFile &File, - OffsetsStringPool &StringPool) { - - if (File.Warnings.empty()) - return false; - - DIE *CUDie = DIE::get(DIEAlloc, dwarf::DW_TAG_compile_unit); - CUDie->setOffset(11); - StringRef Producer; - StringRef WarningHeader; - - switch (DwarfLinkerClientID) { - case DwarfLinkerClient::Dsymutil: - Producer = StringPool.internString("dsymutil"); - WarningHeader = "dsymutil_warning"; - break; - - default: - Producer = StringPool.internString("dwarfopt"); - WarningHeader = "dwarfopt_warning"; - break; - } - - StringRef FileName = StringPool.internString(File.FileName); - CUDie->addValue(DIEAlloc, dwarf::DW_AT_producer, dwarf::DW_FORM_strp, - DIEInteger(StringPool.getStringOffset(Producer))); - DIEBlock *String = new (DIEAlloc) DIEBlock(); - DIEBlocks.push_back(String); - for (auto &C : FileName) - String->addValue(DIEAlloc, dwarf::Attribute(0), dwarf::DW_FORM_data1, - DIEInteger(C)); - String->addValue(DIEAlloc, dwarf::Attribute(0), dwarf::DW_FORM_data1, - DIEInteger(0)); - - CUDie->addValue(DIEAlloc, dwarf::DW_AT_name, dwarf::DW_FORM_string, String); - for (const auto &Warning : File.Warnings) { - DIE &ConstDie = CUDie->addChild(DIE::get(DIEAlloc, dwarf::DW_TAG_constant)); - ConstDie.addValue(DIEAlloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, - DIEInteger(StringPool.getStringOffset(WarningHeader))); - ConstDie.addValue(DIEAlloc, dwarf::DW_AT_artificial, dwarf::DW_FORM_flag, - DIEInteger(1)); - ConstDie.addValue(DIEAlloc, dwarf::DW_AT_const_value, dwarf::DW_FORM_strp, - DIEInteger(StringPool.getStringOffset(Warning))); - } - unsigned Size = 4 /* FORM_strp */ + FileName.size() + 1 + - File.Warnings.size() * (4 + 1 + 4) + 1 /* End of children */; - DIEAbbrev Abbrev = CUDie->generateAbbrev(); - assignAbbrev(Abbrev); - CUDie->setAbbrevNumber(Abbrev.getNumber()); - Size += getULEB128Size(Abbrev.getNumber()); - // Abbreviation ordering needed for classic compatibility. - for (auto &Child : CUDie->children()) { - Abbrev = Child.generateAbbrev(); - assignAbbrev(Abbrev); - Child.setAbbrevNumber(Abbrev.getNumber()); - Size += getULEB128Size(Abbrev.getNumber()); - } - CUDie->setSize(Size); - TheDwarfEmitter->emitPaperTrailWarningsDie(*CUDie); - - return true; -} - void DWARFLinker::copyInvariantDebugSection(DWARFContext &Dwarf) { TheDwarfEmitter->emitSectionContents(Dwarf.getDWARFObj().getLocSection().Data, "debug_loc"); @@ -2731,6 +2707,7 @@ Error DWARFLinker::link() { // reproducibility. OffsetsStringPool DebugStrPool(StringsTranslator, true); OffsetsStringPool DebugLineStrPool(StringsTranslator, false); + DebugDieValuePool StringOffsetPool; // ODR Contexts for the optimize. DeclContextTree ODRContexts; @@ -2743,9 +2720,6 @@ Error DWARFLinker::link() { outs() << "OBJECT FILE: " << OptContext.File.FileName << "\n"; } - if (emitPaperTrailWarnings(OptContext.File, DebugStrPool)) - continue; - if (!OptContext.File.Dwarf) continue; @@ -2780,12 +2754,12 @@ Error DWARFLinker::link() { continue; } - // In a first phase, just read in the debug info and load all clang modules. + // Clone all the clang modules with requires extracting the DIE units. We + // don't need the full debug info until the Analyze phase. OptContext.CompileUnits.reserve( OptContext.File.Dwarf->getNumCompileUnits()); - for (const auto &CU : OptContext.File.Dwarf->compile_units()) { - auto CUDie = CU->getUnitDIE(false); + auto CUDie = CU->getUnitDIE(/*ExtractUnitDIEOnly=*/true); if (Options.Verbose) { outs() << "Input compilation unit:"; DIDumpOptions DumpOpts; @@ -2797,7 +2771,7 @@ Error DWARFLinker::link() { for (auto &CU : OptContext.ModuleUnits) { if (Error Err = cloneModuleUnit(OptContext, CU, ODRContexts, DebugStrPool, - DebugLineStrPool)) + DebugLineStrPool, StringOffsetPool)) reportWarning(toString(std::move(Err)), CU.File); } } @@ -2826,9 +2800,9 @@ Error DWARFLinker::link() { return; for (const auto &CU : Context.File.Dwarf->compile_units()) { - // The !isClangModuleRef condition effectively skips over fully resolved - // skeleton units. - auto CUDie = CU->getUnitDIE(); + // Previously we only extracted the unit DIEs. We need the full debug info + // now. + auto CUDie = CU->getUnitDIE(/*ExtractUnitDIEOnly=*/false); std::string PCMFile = getPCMFile(CUDie, Options.ObjectPrefixMap); if (!CUDie || LLVM_UNLIKELY(Options.Update) || @@ -2894,7 +2868,7 @@ Error DWARFLinker::link() { SizeByObject[OptContext.File.FileName].Output = DIECloner(*this, TheDwarfEmitter.get(), OptContext.File, DIEAlloc, OptContext.CompileUnits, Options.Update, DebugStrPool, - DebugLineStrPool) + DebugLineStrPool, StringOffsetPool) .cloneAllCompileUnits(*OptContext.File.Dwarf, OptContext.File, OptContext.File.Dwarf->isLittleEndian()); } @@ -2911,6 +2885,8 @@ Error DWARFLinker::link() { if (TheDwarfEmitter != nullptr) { TheDwarfEmitter->emitAbbrevs(Abbreviations, Options.TargetDWARFVersion); TheDwarfEmitter->emitStrings(DebugStrPool); + TheDwarfEmitter->emitStringOffsets(StringOffsetPool.DieValues, + Options.TargetDWARFVersion); TheDwarfEmitter->emitLineStrings(DebugLineStrPool); for (AccelTableKind TableKind : Options.AccelTables) { switch (TableKind) { @@ -3027,6 +3003,7 @@ Error DWARFLinker::cloneModuleUnit(LinkContext &Context, RefModuleUnit &Unit, DeclContextTree &ODRContexts, OffsetsStringPool &DebugStrPool, OffsetsStringPool &DebugLineStrPool, + DebugDieValuePool &StringOffsetPool, unsigned Indent) { assert(Unit.Unit.get() != nullptr); @@ -3053,7 +3030,7 @@ Error DWARFLinker::cloneModuleUnit(LinkContext &Context, RefModuleUnit &Unit, CompileUnits.emplace_back(std::move(Unit.Unit)); assert(TheDwarfEmitter); DIECloner(*this, TheDwarfEmitter.get(), Unit.File, DIEAlloc, CompileUnits, - Options.Update, DebugStrPool, DebugLineStrPool) + Options.Update, DebugStrPool, DebugLineStrPool, StringOffsetPool) .cloneAllCompileUnits(*Unit.File.Dwarf, Unit.File, Unit.File.Dwarf->isLittleEndian()); return Error::success(); @@ -3062,11 +3039,13 @@ Error DWARFLinker::cloneModuleUnit(LinkContext &Context, RefModuleUnit &Unit, void DWARFLinker::verifyInput(const DWARFFile &File) { assert(File.Dwarf); - raw_ostream &os = Options.Verbose ? errs() : nulls(); + + std::string Buffer; + raw_string_ostream OS(Buffer); DIDumpOptions DumpOpts; - if (!File.Dwarf->verify(os, DumpOpts.noImplicitRecursion())) { + if (!File.Dwarf->verify(OS, DumpOpts.noImplicitRecursion())) { if (Options.InputVerificationHandler) - Options.InputVerificationHandler(File); + Options.InputVerificationHandler(File, OS.str()); } } diff --git a/llvm/lib/DWARFLinker/DWARFLinkerCompileUnit.cpp b/llvm/lib/DWARFLinker/DWARFLinkerCompileUnit.cpp index add0d94da73f..06559bc38c86 100644 --- a/llvm/lib/DWARFLinker/DWARFLinkerCompileUnit.cpp +++ b/llvm/lib/DWARFLinker/DWARFLinkerCompileUnit.cpp @@ -97,8 +97,10 @@ void CompileUnit::markEverythingAsKept() { ++NextIt; switch (It->getCode()) { + case dwarf::DW_OP_const2u: case dwarf::DW_OP_const4u: case dwarf::DW_OP_const8u: + case dwarf::DW_OP_const2s: case dwarf::DW_OP_const4s: case dwarf::DW_OP_const8s: if (NextIt == Expression.end() || diff --git a/llvm/lib/DWARFLinker/DWARFStreamer.cpp b/llvm/lib/DWARFLinker/DWARFStreamer.cpp index fbd89dcf1ca1..cd649c328ed9 100644 --- a/llvm/lib/DWARFLinker/DWARFStreamer.cpp +++ b/llvm/lib/DWARFLinker/DWARFStreamer.cpp @@ -234,18 +234,6 @@ void DwarfStreamer::emitSectionContents(StringRef SecData, StringRef SecName) { } } -/// Emit DIE containing warnings. -void DwarfStreamer::emitPaperTrailWarningsDie(DIE &Die) { - switchToDebugInfoSection(/* Version */ 2); - auto &Asm = getAsmPrinter(); - Asm.emitInt32(11 + Die.getSize() - 4); - Asm.emitInt16(2); - Asm.emitInt32(0); - Asm.emitInt8(MC->getTargetTriple().isArch64Bit() ? 8 : 4); - DebugInfoSectionSize += 11; - emitDIE(Die); -} - /// Emit the debug_str section stored in \p Pool. void DwarfStreamer::emitStrings(const NonRelocatableStringpool &Pool) { Asm->OutStreamer->switchSection(MOFI->getDwarfStrSection()); @@ -258,6 +246,39 @@ void DwarfStreamer::emitStrings(const NonRelocatableStringpool &Pool) { } } +/// Emit the debug string offset table described by \p StringOffsets into the +/// .debug_str_offsets table. +void DwarfStreamer::emitStringOffsets( + const SmallVector<uint64_t> &StringOffsets, uint16_t TargetDWARFVersion) { + + if (TargetDWARFVersion < 5 || StringOffsets.empty()) + return; + + Asm->OutStreamer->switchSection(MOFI->getDwarfStrOffSection()); + + MCSymbol *BeginLabel = Asm->createTempSymbol("Bdebugstroff"); + MCSymbol *EndLabel = Asm->createTempSymbol("Edebugstroff"); + + // Length. + Asm->emitLabelDifference(EndLabel, BeginLabel, sizeof(uint32_t)); + Asm->OutStreamer->emitLabel(BeginLabel); + StrOffsetSectionSize += sizeof(uint32_t); + + // Version. + MS->emitInt16(5); + StrOffsetSectionSize += sizeof(uint16_t); + + // Padding. + MS->emitInt16(0); + StrOffsetSectionSize += sizeof(uint16_t); + + for (auto Off : StringOffsets) { + Asm->OutStreamer->emitInt32(Off); + StrOffsetSectionSize += sizeof(uint32_t); + } + Asm->OutStreamer->emitLabel(EndLabel); +} + /// Emit the debug_line_str section stored in \p Pool. void DwarfStreamer::emitLineStrings(const NonRelocatableStringpool &Pool) { Asm->OutStreamer->switchSection(MOFI->getDwarfLineStrSection()); @@ -270,14 +291,13 @@ void DwarfStreamer::emitLineStrings(const NonRelocatableStringpool &Pool) { } } -void DwarfStreamer::emitDebugNames( - AccelTable<DWARF5AccelTableStaticData> &Table) { +void DwarfStreamer::emitDebugNames(DWARF5AccelTable &Table) { if (EmittedUnits.empty()) return; // Build up data structures needed to emit this section. - std::vector<MCSymbol *> CompUnits; - DenseMap<unsigned, size_t> UniqueIdToCuMap; + std::vector<std::variant<MCSymbol *, uint64_t>> CompUnits; + DenseMap<unsigned, unsigned> UniqueIdToCuMap; unsigned Id = 0; for (auto &CU : EmittedUnits) { CompUnits.push_back(CU.LabelBegin); @@ -286,10 +306,19 @@ void DwarfStreamer::emitDebugNames( } Asm->OutStreamer->switchSection(MOFI->getDwarfDebugNamesSection()); + dwarf::Form Form = DIEInteger::BestForm(/*IsSigned*/ false, + (uint64_t)UniqueIdToCuMap.size() - 1); + /// llvm-dwarfutil doesn't support type units + .debug_names right now. + // FIXME: add support for type units + .debug_names. For now the behavior is + // unsuported. emitDWARF5AccelTable( Asm.get(), Table, CompUnits, - [&UniqueIdToCuMap](const DWARF5AccelTableStaticData &Entry) { - return UniqueIdToCuMap[Entry.getCUIndex()]; + [&](const DWARF5AccelTableData &Entry) + -> std::optional<DWARF5AccelTable::UnitIndexAndEncoding> { + if (UniqueIdToCuMap.size() > 1) + return {{UniqueIdToCuMap[Entry.getUnitID()], + {dwarf::DW_IDX_compile_unit, Form}}}; + return std::nullopt; }); } @@ -455,13 +484,13 @@ DwarfStreamer::emitDwarfDebugRangeListHeader(const CompileUnit &Unit) { void DwarfStreamer::emitDwarfDebugRangeListFragment( const CompileUnit &Unit, const AddressRanges &LinkedRanges, - PatchLocation Patch) { + PatchLocation Patch, DebugDieValuePool &AddrPool) { if (Unit.getOrigUnit().getVersion() < 5) { emitDwarfDebugRangesTableFragment(Unit, LinkedRanges, Patch); return; } - emitDwarfDebugRngListsTableFragment(Unit, LinkedRanges, Patch); + emitDwarfDebugRngListsTableFragment(Unit, LinkedRanges, Patch, AddrPool); } void DwarfStreamer::emitDwarfDebugRangeListFooter(const CompileUnit &Unit, @@ -478,25 +507,35 @@ void DwarfStreamer::emitDwarfDebugRangeListFooter(const CompileUnit &Unit, void DwarfStreamer::emitDwarfDebugRngListsTableFragment( const CompileUnit &Unit, const AddressRanges &LinkedRanges, - PatchLocation Patch) { + PatchLocation Patch, DebugDieValuePool &AddrPool) { Patch.set(RngListsSectionSize); // Make .debug_rnglists to be current section. MS->switchSection(MC->getObjectFileInfo()->getDwarfRnglistsSection()); - - unsigned AddressSize = Unit.getOrigUnit().getAddressByteSize(); + std::optional<uint64_t> BaseAddress; for (const AddressRange &Range : LinkedRanges) { + + if (!BaseAddress) { + BaseAddress = Range.start(); + + // Emit base address. + MS->emitInt8(dwarf::DW_RLE_base_addressx); + RngListsSectionSize += 1; + RngListsSectionSize += + MS->emitULEB128IntValue(AddrPool.getValueIndex(*BaseAddress)); + } + // Emit type of entry. - MS->emitInt8(dwarf::DW_RLE_start_length); + MS->emitInt8(dwarf::DW_RLE_offset_pair); RngListsSectionSize += 1; - // Emit start address. - MS->emitIntValue(Range.start(), AddressSize); - RngListsSectionSize += AddressSize; + // Emit start offset relative to base address. + RngListsSectionSize += + MS->emitULEB128IntValue(Range.start() - *BaseAddress); - // Emit length of the range. - RngListsSectionSize += MS->emitULEB128IntValue(Range.end() - Range.start()); + // Emit end offset relative to base address. + RngListsSectionSize += MS->emitULEB128IntValue(Range.end() - *BaseAddress); } // Emit the terminator entry. @@ -544,7 +583,7 @@ MCSymbol *DwarfStreamer::emitDwarfDebugLocListHeader(const CompileUnit &Unit) { void DwarfStreamer::emitDwarfDebugLocListFragment( const CompileUnit &Unit, const DWARFLocationExpressionsVector &LinkedLocationExpression, - PatchLocation Patch, DebugAddrPool &AddrPool) { + PatchLocation Patch, DebugDieValuePool &AddrPool) { if (Unit.getOrigUnit().getVersion() < 5) { emitDwarfDebugLocTableFragment(Unit, LinkedLocationExpression, Patch); return; @@ -662,7 +701,7 @@ void DwarfStreamer::emitDwarfDebugAddrsFooter(const CompileUnit &Unit, void DwarfStreamer::emitDwarfDebugLocListsTableFragment( const CompileUnit &Unit, const DWARFLocationExpressionsVector &LinkedLocationExpression, - PatchLocation Patch, DebugAddrPool &AddrPool) { + PatchLocation Patch, DebugDieValuePool &AddrPool) { Patch.set(LocListsSectionSize); // Make .debug_loclists the current section. @@ -681,7 +720,7 @@ void DwarfStreamer::emitDwarfDebugLocListsTableFragment( MS->emitInt8(dwarf::DW_LLE_base_addressx); LocListsSectionSize += 1; LocListsSectionSize += - MS->emitULEB128IntValue(AddrPool.getAddrIndex(*BaseAddress)); + MS->emitULEB128IntValue(AddrPool.getValueIndex(*BaseAddress)); } // Emit type of entry. |