aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/DWARFLinker
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2023-12-09 13:28:42 +0000
committerDimitry Andric <dim@FreeBSD.org>2023-12-09 13:28:42 +0000
commitb1c73532ee8997fe5dfbeb7d223027bdf99758a0 (patch)
tree7d6e51c294ab6719475d660217aa0c0ad0526292 /llvm/lib/DWARFLinker
parent7fa27ce4a07f19b07799a767fc29416f3b625afb (diff)
downloadsrc-b1c73532ee8997fe5dfbeb7d223027bdf99758a0.tar.gz
src-b1c73532ee8997fe5dfbeb7d223027bdf99758a0.zip
Diffstat (limited to 'llvm/lib/DWARFLinker')
-rw-r--r--llvm/lib/DWARFLinker/DWARFLinker.cpp319
-rw-r--r--llvm/lib/DWARFLinker/DWARFLinkerCompileUnit.cpp2
-rw-r--r--llvm/lib/DWARFLinker/DWARFStreamer.cpp103
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.