[lld] [lld][ELF] Implement merged .debug_names section (PR #88092)
Fangrui Song via llvm-commits
llvm-commits at lists.llvm.org
Mon Apr 15 14:05:58 PDT 2024
https://github.com/MaskRay updated https://github.com/llvm/llvm-project/pull/88092
>From 6a046c3a67c284a6e3f1634dc92e0c528bf9409c Mon Sep 17 00:00:00 2001
From: Caroline Tice <cmtice at google.com>
Date: Mon, 25 Mar 2024 00:00:27 -0700
Subject: [PATCH 01/23] [lld][ELF] Implement merged .debug_names section.
Update LLD to be able to generate a single merged .debug_names section (rather
than a set of appended sections). Option is controlled by a new flag, --debug-names.
Does not handle type units yet (coming soon).
---
lld/ELF/Config.h | 1 +
lld/ELF/DWARF.cpp | 1 +
lld/ELF/DWARF.h | 4 +
lld/ELF/Driver.cpp | 3 +
lld/ELF/Options.td | 4 +
lld/ELF/SyntheticSections.cpp | 758 ++++++++++++++++++
lld/ELF/SyntheticSections.h | 134 ++++
lld/docs/ld.lld.1 | 4 +
lld/test/ELF/Inputs/debug-names-2.s | 191 +++++
.../ELF/Inputs/debug-names-parent-idx-2.s | 347 ++++++++
lld/test/ELF/debug-names-bad-aug-string.s | 189 +++++
lld/test/ELF/debug-names-bad-die-idx-sizes.s | 151 ++++
lld/test/ELF/debug-names-bad-name-count.s | 154 ++++
lld/test/ELF/debug-names-bad-offsets-sizes.s | 153 ++++
lld/test/ELF/debug-names-bad-version.s | 173 ++++
lld/test/ELF/debug-names-invalid-attribute.s | 179 +++++
lld/test/ELF/debug-names-parent-idx.s | 549 +++++++++++++
lld/test/ELF/debug-names.s | 294 +++++++
18 files changed, 3289 insertions(+)
create mode 100644 lld/test/ELF/Inputs/debug-names-2.s
create mode 100644 lld/test/ELF/Inputs/debug-names-parent-idx-2.s
create mode 100644 lld/test/ELF/debug-names-bad-aug-string.s
create mode 100644 lld/test/ELF/debug-names-bad-die-idx-sizes.s
create mode 100644 lld/test/ELF/debug-names-bad-name-count.s
create mode 100644 lld/test/ELF/debug-names-bad-offsets-sizes.s
create mode 100644 lld/test/ELF/debug-names-bad-version.s
create mode 100644 lld/test/ELF/debug-names-invalid-attribute.s
create mode 100644 lld/test/ELF/debug-names-parent-idx.s
create mode 100644 lld/test/ELF/debug-names.s
diff --git a/lld/ELF/Config.h b/lld/ELF/Config.h
index 83f293ab2ce578..33bfa42b0fcbf0 100644
--- a/lld/ELF/Config.h
+++ b/lld/ELF/Config.h
@@ -229,6 +229,7 @@ struct Config {
bool cref;
llvm::SmallVector<std::pair<llvm::GlobPattern, uint64_t>, 0>
deadRelocInNonAlloc;
+ bool debugNames;
bool demangle = true;
bool dependentLibraries;
bool disableVerify;
diff --git a/lld/ELF/DWARF.cpp b/lld/ELF/DWARF.cpp
index ac28aa8c7ca6e0..5d58e0c60a952e 100644
--- a/lld/ELF/DWARF.cpp
+++ b/lld/ELF/DWARF.cpp
@@ -40,6 +40,7 @@ template <class ELFT> LLDDwarfObj<ELFT>::LLDDwarfObj(ObjFile<ELFT> *obj) {
.Case(".debug_gnu_pubtypes", &gnuPubtypesSection)
.Case(".debug_line", &lineSection)
.Case(".debug_loclists", &loclistsSection)
+ .Case(".debug_names", &namesSection)
.Case(".debug_ranges", &rangesSection)
.Case(".debug_rnglists", &rnglistsSection)
.Case(".debug_str_offsets", &strOffsetsSection)
diff --git a/lld/ELF/DWARF.h b/lld/ELF/DWARF.h
index ada38a043bc22a..64c25c706c3437 100644
--- a/lld/ELF/DWARF.h
+++ b/lld/ELF/DWARF.h
@@ -62,6 +62,9 @@ template <class ELFT> class LLDDwarfObj final : public llvm::DWARFObject {
const LLDDWARFSection &getGnuPubtypesSection() const override {
return gnuPubtypesSection;
}
+ const LLDDWARFSection &getNamesSection() const override {
+ return namesSection;
+ }
StringRef getFileName() const override { return ""; }
StringRef getAbbrevSection() const override { return abbrevSection; }
@@ -87,6 +90,7 @@ template <class ELFT> class LLDDwarfObj final : public llvm::DWARFObject {
LLDDWARFSection infoSection;
LLDDWARFSection lineSection;
LLDDWARFSection loclistsSection;
+ LLDDWARFSection namesSection;
LLDDWARFSection rangesSection;
LLDDWARFSection rnglistsSection;
LLDDWARFSection strOffsetsSection;
diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp
index 86cc09621a9129..5fffdc51f34ddf 100644
--- a/lld/ELF/Driver.cpp
+++ b/lld/ELF/Driver.cpp
@@ -442,6 +442,8 @@ static void checkOptions() {
error("-r and -pie may not be used together");
if (config->exportDynamic)
error("-r and --export-dynamic may not be used together");
+ if (config->debugNames)
+ error("-r and --debug-names may not be used together");
}
if (config->executeOnly) {
@@ -1234,6 +1236,7 @@ static void readConfigs(opt::InputArgList &args) {
config->cref = args.hasArg(OPT_cref);
config->optimizeBBJumps =
args.hasFlag(OPT_optimize_bb_jumps, OPT_no_optimize_bb_jumps, false);
+ config->debugNames = args.hasFlag(OPT_debug_names, OPT_no_debug_names, false);
config->demangle = args.hasFlag(OPT_demangle, OPT_no_demangle, true);
config->dependencyFile = args.getLastArgValue(OPT_dependency_file);
config->dependentLibraries = args.hasFlag(OPT_dependent_libraries, OPT_no_dependent_libraries, true);
diff --git a/lld/ELF/Options.td b/lld/ELF/Options.td
index c5e95d0d25c1ae..d470646ed0eeef 100644
--- a/lld/ELF/Options.td
+++ b/lld/ELF/Options.td
@@ -153,6 +153,10 @@ def : Flag<["--"], "no-color-diagnostics">, Alias<color_diagnostics>, AliasArgs<
def cref: FF<"cref">,
HelpText<"Output cross reference table. If -Map is specified, print to the map file">;
+defm debug_names: BB<"debug-names",
+ "Generate a merged .debug_names section",
+ "Do not generate a merged .debug_names section (default)">;
+
defm demangle: B<"demangle",
"Demangle symbol names (default)",
"Do not demangle symbol names">;
diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp
index 0d7f393a9f3f4d..d440410faa54f4 100644
--- a/lld/ELF/SyntheticSections.cpp
+++ b/lld/ELF/SyntheticSections.cpp
@@ -14,6 +14,7 @@
//===----------------------------------------------------------------------===//
#include "SyntheticSections.h"
+
#include "Config.h"
#include "DWARF.h"
#include "EhFrame.h"
@@ -34,7 +35,9 @@
#include "llvm/ADT/StringExtras.h"
#include "llvm/BinaryFormat/Dwarf.h"
#include "llvm/BinaryFormat/ELF.h"
+#include "llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h"
#include "llvm/DebugInfo/DWARF/DWARFDebugPubTable.h"
+#include "llvm/Support/DJB.h"
#include "llvm/Support/Endian.h"
#include "llvm/Support/LEB128.h"
#include "llvm/Support/Parallel.h"
@@ -2711,6 +2714,759 @@ static uint32_t computeGdbHash(StringRef s) {
return h;
}
+DebugNamesSection::DebugNamesSection()
+ : SyntheticSection(0, SHT_PROGBITS, 1, ".debug_names") {}
+
+template <class ELFT, class RelTy>
+void DebugNamesSection::getNameRelocsImpl(
+ InputSection *sec, ArrayRef<RelTy> rels,
+ llvm::DenseMap<uint32_t, uint32_t> &relocs) {
+ for (auto &rel : rels) {
+ Symbol &sym = sec->getFile<ELFT>()->getRelocTargetSym(rel);
+ relocs[rel.r_offset] = sym.getVA(getAddend<ELFT>(rel));
+ }
+}
+
+template <class ELFT>
+void DebugNamesSection::getNameRelocs(
+ InputSectionBase *base, llvm::DenseMap<uint32_t, uint32_t> &relocs) {
+ auto *sec = cast<InputSection>(base);
+ const RelsOrRelas<ELFT> rels = sec->template relsOrRelas<ELFT>();
+ if (rels.areRelocsRel())
+ getNameRelocsImpl<ELFT>(sec, rels.rels, relocs);
+ else
+ getNameRelocsImpl<ELFT>(sec, rels.relas, relocs);
+}
+
+void DebugNamesSection::writeTo(uint8_t *buf) { invokeELFT(writeToImpl, buf); }
+
+template <class ELFT> void DebugNamesSection::writeToImpl(uint8_t *buf) {
+ SmallVector<uint32_t, 0> mergedCuOffsets;
+ SmallVector<uint32_t, 0> mergedTuOffsets;
+ llvm::DenseMap<uint32_t, uint32_t> strOffsets;
+ SmallVector<llvm::DenseMap<uint32_t, uint32_t>, 0> chunksRelocs;
+ chunksRelocs.reserve(numChunks);
+
+ for (size_t i = 0; i < numChunks; ++i) {
+ DebugNamesOutputChunk &chunk = outputChunks[i];
+ InputSectionBase *base = inputDebugNamesSections[i];
+ llvm::DenseMap<uint32_t, uint32_t> relocs;
+ getNameRelocs<ELFT>(base, relocs);
+ chunksRelocs.push_back(std::move(relocs));
+
+ // Update CuOffsets list with new data
+ for (uint32_t cuOffset : chunk.compilationUnits)
+ mergedCuOffsets.push_back(chunk.sec->outSecOff + cuOffset);
+
+ // TODO: Update TuOffsets list with new data
+ }
+
+ // Update the entries with the relocated string offsets.
+ for (auto &stringEntry : mergedEntries) {
+ uint32_t oldOffset = stringEntry.stringOffsetOffset;
+ uint32_t idx = stringEntry.chunkIdx;
+ stringEntry.relocatedEntryOffset = chunksRelocs[idx][oldOffset];
+ }
+
+ // Write out bytes for merged section.
+
+ // Write the header.
+ endian::write32<ELFT::Endianness>(buf + 0, mergedHdr.UnitLength);
+ endian::write16<ELFT::Endianness>(buf + 4, mergedHdr.Version);
+ endian::write32<ELFT::Endianness>(buf + 8, mergedHdr.CompUnitCount);
+ endian::write32<ELFT::Endianness>(buf + 12,
+ mergedHdr.LocalTypeUnitCount);
+ endian::write32<ELFT::Endianness>(buf + 16,
+ mergedHdr.ForeignTypeUnitCount);
+ endian::write32<ELFT::Endianness>(buf + 20, mergedHdr.BucketCount);
+ endian::write32<ELFT::Endianness>(buf + 24, mergedHdr.NameCount);
+ endian::write32<ELFT::Endianness>(buf + 28, mergedHdr.AbbrevTableSize);
+ endian::write32<ELFT::Endianness>(buf + 32,
+ mergedHdr.AugmentationStringSize);
+ buf += 36;
+ memcpy(buf, mergedHdr.AugmentationString.c_str(), 8);
+ buf += 8;
+
+ // Write the CU list.
+ for (uint32_t offset : mergedCuOffsets) {
+ endian::write32<ELFT::Endianness>(buf + 0, offset);
+ buf += 4;
+ }
+
+ // Write the local TU list.
+ // TODO: Fix this, once we get everything working without TUs.
+ if (mergedHdr.LocalTypeUnitCount != 0)
+ warn(".debug_names: type units are not handled in merged index");
+
+ // Write the foreign TU list.
+ // Currently LLVM does not emit foreign type units, so there should
+ // be nothing here to emit.
+ // TODO: Fix this, once we get everything working wtihout TUs.
+ if (mergedHdr.ForeignTypeUnitCount != 0)
+ warn(".debug_names: type units are not handled in merged index");
+
+ // Write the hash table.
+ // ... Write the buckets
+ uint32_t idx = 1;
+ for (const auto &bucket : bucketList) {
+ if (!bucket.empty())
+ endian::write32<ELFT::Endianness>(buf + 0, idx);
+ idx += bucket.size();
+ buf += 4;
+ }
+
+ // ...Write the hashes
+ for (const auto &bucket : bucketList) {
+ for (const auto &entry : bucket) {
+ uint32_t hashValue = entry->hashValue;
+ endian::write32<ELFT::Endianness>(buf + 0, hashValue);
+ buf += 4;
+ }
+ }
+
+ // Write the string offsets.
+ for (const auto &entry : mergedEntries) {
+ endian::write32<ELFT::Endianness>(buf + 0,
+ entry.relocatedEntryOffset);
+ buf += 4;
+ }
+
+ // Write the entry offsets.
+ for (const auto &entry : mergedEntries) {
+ endian::write32<ELFT::Endianness>(buf + 0, entry.entryOffset);
+ buf += 4;
+ }
+
+ // Write the abbrev table.
+ for (const auto *abbrev : mergedAbbrevTable) {
+ size_t uleb_size = encodeULEB128(abbrev->code, buf);
+ buf += uleb_size;
+ uleb_size = encodeULEB128(abbrev->tag, buf);
+ buf += uleb_size;
+ for (auto attr : abbrev->attributes) {
+ uleb_size = encodeULEB128(attr.Index, buf);
+ buf += uleb_size;
+ uleb_size = encodeULEB128(attr.Form, buf);
+ buf += uleb_size;
+ }
+ endian::write16<ELFT::Endianness>(buf + 0, 0); // attribute sentinels.
+ buf += 2;
+ }
+ *buf++ = 0; // abbrev table sentinel
+
+ // Write the entry pool.
+ for (const auto &stringEntry : mergedEntries) {
+ // Write all the entries for the string.
+ size_t uleb_size;
+ for (const auto &entry : stringEntry.indexEntries) {
+ uleb_size = encodeULEB128(entry->abbrevCode, buf);
+ buf += uleb_size;
+ for (const auto &value : entry->attrValues) {
+ if (value.attrSize > 0) {
+ endian::write32<ELFT::Endianness>(buf + 0, value.attrValue);
+ buf += value.attrSize;
+ }
+ }
+ }
+ *buf++ = 0; // Entry sentinel
+ }
+}
+
+bool DebugNamesSection::isNeeded() const { return numChunks > 0; }
+
+template <class ELFT>
+static void
+readCompileUnitOffsets(struct DebugNamesSection::DebugNamesSectionData &secData,
+ DebugNamesSection::DebugNamesInputChunk &inputChunk,
+ DebugNamesSection::DebugNamesOutputChunk &outputChunk,
+ llvm::DWARFDataExtractor &namesExtractor) {
+ uint64_t offset = secData.locs.CUsBase;
+ uint64_t *offsetPtr = &offset;
+ for (size_t i = 0; i < secData.hdr.CompUnitCount; ++i) {
+ llvm::Error err = llvm::Error::success();
+ uint32_t value = namesExtractor.getU32(offsetPtr, &err);
+ if (err)
+ errorOrWarn(toString(inputChunk.namesSection->sec) +
+ ": error reading CU offsets: " + toString(std::move(err)));
+ else
+ outputChunk.compilationUnits.push_back(value);
+ }
+}
+
+template <class ELFT>
+static void
+readEntryOffsets(struct DebugNamesSection::DebugNamesSectionData &secData,
+ DebugNamesSection::DebugNamesInputChunk &chunk,
+ llvm::DWARFDataExtractor &namesExtractor) {
+ secData.entryOffsets = std::make_unique<uint32_t[]>(secData.hdr.NameCount);
+ if (secData.locs.EntryOffsetsBase >= namesExtractor.getData().size())
+ errorOrWarn(toString(chunk.namesSection->sec) +
+ ": invalid entry offsets input");
+
+ uint64_t offset = secData.locs.EntryOffsetsBase;
+ uint64_t *offsetPtr = &offset;
+ for (size_t i = 0; i < secData.hdr.NameCount; ++i) {
+ llvm::Error err = llvm::Error::success();
+ uint32_t value = namesExtractor.getU32(offsetPtr, &err);
+ if (err)
+ errorOrWarn(toString(chunk.namesSection->sec) +
+ ": error reading entry offsets: " + toString(std::move(err)));
+ else
+ secData.entryOffsets.get()[i] = value;
+ }
+}
+
+template <class ELFT>
+static void readAttributeValues(
+ SmallVector<DebugNamesSection::AttrValueData, 3> &values,
+ DebugNamesSection::DebugNamesInputChunk &chunk, uint64_t &offset,
+ struct DebugNamesSection::DebugNamesSectionData &secData,
+ int32_t &parentOffset, llvm::DWARFDataExtractor &namesExtractor,
+ const llvm::DWARFDebugNames::Abbrev &abbrev) {
+ const LLDDWARFSection &namesSection = *chunk.namesSection;
+ uint64_t *offsetPtr = &offset;
+ DebugNamesSection::AttrValueData cuOrTuAttr = {0, 0};
+ for (auto attr : abbrev.Attributes) {
+ llvm::Error err = llvm::Error::success();
+ DebugNamesSection::AttrValueData newAttr;
+ uint32_t value;
+ switch (attr.Form) {
+ case DW_FORM_flag_present: {
+ // Currently only DW_IDX_parent attributes (in .debug_names) can
+ // have this form. This form does not have a real value (nothing is
+ // emitted for it).
+ break;
+ }
+ case DW_FORM_data1:
+ case DW_FORM_ref1: {
+ newAttr.attrValue = namesExtractor.getU8(offsetPtr, &err);
+ newAttr.attrSize = 1;
+ break;
+ }
+ case DW_FORM_data2:
+ case DW_FORM_ref2: {
+ value = namesExtractor.getU16(offsetPtr, &err);
+ newAttr.attrValue = value;
+ newAttr.attrSize = 2;
+ break;
+ }
+ case DW_FORM_data4:
+ case DW_FORM_ref4: {
+ value = namesExtractor.getU32(offsetPtr, &err);
+ newAttr.attrValue = value;
+ newAttr.attrSize = 4;
+ if (attr.Index == dwarf::DW_IDX_parent)
+ parentOffset = value + secData.locs.EntriesBase;
+ break;
+ }
+ case DW_FORM_data8:
+ case DW_FORM_ref8:
+ case DW_FORM_ref_sig8: {
+ value = namesExtractor.getU64(offsetPtr, &err);
+ newAttr.attrValue = value;
+ newAttr.attrSize = 8;
+ break;
+ }
+ default: {
+ errorOrWarn(toString(namesSection.sec) +
+ Twine(": unrecognized form encoding ") + Twine(attr.Form) +
+ " in .debug_names abbrev table");
+ break;
+ }
+ }
+ if (err)
+ errorOrWarn(
+ toString(namesSection.sec) +
+ ": error while reading attributes: " + toString(std::move(err)));
+ if (attr.Index == DW_IDX_compile_unit || attr.Index == DW_IDX_type_unit)
+ // Save it to put it at the end of the attributes list.
+ cuOrTuAttr = newAttr;
+ else if (attr.Form != DW_FORM_flag_present)
+ values.push_back(newAttr);
+ }
+
+ // Make sure the CU or TU index attribute is the last one in the list.
+ values.push_back(cuOrTuAttr);
+}
+
+template <class ELFT>
+static void readEntry(DebugNamesSection::NamedEntry &stringEntry,
+ DebugNamesSection::DebugNamesInputChunk &chunk,
+ DebugNamesSection::DebugNamesSectionData &secData,
+ llvm::DWARFDataExtractor &namesExtractor,
+ const llvm::DWARFDebugNames::NameIndex &ni) {
+ std::unique_ptr<LLDDWARFSection> &namesSection = chunk.namesSection;
+ uint64_t offset = stringEntry.entryOffset;
+ // Each entry ends with a zero 'sentinel' value
+ while (offset < namesSection->Data.size() &&
+ namesSection->Data[offset] != 0) {
+ // Read & store all entries (for the same string)
+ auto entry = std::make_unique<DebugNamesSection::IndexEntry>();
+ entry->poolOffset = offset;
+ llvm::Error err = llvm::Error::success();
+ uint64_t ulebValue = namesExtractor.getULEB128(&offset, &err);
+ if (err)
+ errorOrWarn(toString(chunk.namesSection->sec) +
+ ": error reading entry: " + toString(std::move(err)));
+ entry->abbrevCode = static_cast<uint32_t>(ulebValue);
+ const auto &abbrevs = ni.getAbbrevs();
+ auto abbrevIt = abbrevs.find_as(entry->abbrevCode);
+ if (abbrevIt != abbrevs.end()) {
+ const llvm::DWARFDebugNames::Abbrev &abbrev = *abbrevIt;
+ readAttributeValues<ELFT>(entry->attrValues, chunk, offset, secData,
+ entry->parentOffset, namesExtractor, abbrev);
+ stringEntry.indexEntries.push_back(std::move(entry));
+ }
+ }
+ if (offset >= namesSection->Data.size())
+ errorOrWarn(toString(chunk.namesSection->sec) +
+ ": encountered unexpected end of section while reading entry");
+}
+
+template <class ELFT>
+static void
+readEntries(struct DebugNamesSection::DebugNamesSectionData &secData,
+ DebugNamesSection::DebugNamesInputChunk &chunk,
+ llvm::DWARFDataExtractor &namesExtractor,
+ llvm::DataExtractor &strExtractor,
+ const llvm::DWARFDebugNames::NameIndex &ni) {
+ // Temporary map from entry offsets to address (pointer) of entry with that
+ // offset; used to find parent entries quickly.
+ DenseMap<uint32_t, DebugNamesSection::IndexEntry *> offsetMap;
+ // Reserve sizes for this chunk's hashes & namedEntries.
+ chunk.hashValues.reserve(secData.hdr.NameCount);
+ secData.namedEntries.reserve(secData.hdr.NameCount);
+ // Calculate the Entry Offsets, create initial records.
+ for (uint32_t i = 0; i < secData.hdr.NameCount; ++i) {
+ // Get string value
+ DebugNamesSection::NamedEntry stringEntry;
+ stringEntry.entryOffset =
+ secData.locs.EntriesBase + secData.entryOffsets[i];
+ uint64_t strOffsetOffset =
+ secData.locs.StringOffsetsBase + i * secData.dwarfSize;
+ stringEntry.stringOffsetOffset = strOffsetOffset;
+ uint64_t strOffset =
+ namesExtractor.getRelocatedValue(secData.dwarfSize, &strOffsetOffset);
+ StringRef name = strExtractor.getCStrRef(&strOffset);
+ stringEntry.name = name.data();
+ // Calculate hash
+ stringEntry.hashValue = caseFoldingDjbHash(name);
+ chunk.hashValues.push_back(stringEntry.hashValue);
+ // Read String Entry
+ readEntry<ELFT>(stringEntry, chunk, secData, namesExtractor, ni);
+ // Add index entries & offsets to our temporary map
+ for (const auto &entry : stringEntry.indexEntries)
+ offsetMap[entry->poolOffset] = entry.get();
+ secData.namedEntries.push_back(std::move(stringEntry));
+ }
+ // Find/assign pointers to any 'real' parent entries (needed to find correct
+ // parent entry offsets in merged data).
+ for (auto &stringEntry : secData.namedEntries)
+ for (auto &entry : stringEntry.indexEntries)
+ if (entry->parentOffset != -1)
+ entry->parentEntry = offsetMap[entry->parentOffset];
+}
+
+static uint16_t computeDebugNamesHeaderSize() {
+ // Size of the .debug_names section header, in bytes, for DWARF32:
+ uint16_t size = /* unit length */ 4 +
+ /* version */ 2 +
+ /* padding */ 2 +
+ /* CU count */ 4 +
+ /* TU count */ 4 +
+ /* Foreign TU count */ 4 +
+ /* Bucket Count */ 4 +
+ /* Name Count */ 4 +
+ /* Abbrev table size */ 4 +
+ /* Augmentation string size */ 4 +
+ /* augmentation string */ 8;
+ return size;
+}
+
+template <class ELFT>
+static void collectDebugNamesSectionData(
+ DebugNamesSection::DebugNamesInputChunk &chunk,
+ DebugNamesSection::DebugNamesOutputChunk &outputChunk,
+ llvm::DWARFDataExtractor &namesExtractor,
+ llvm::DataExtractor &strExtractor) {
+ for (const auto &ni : *chunk.debugNamesData) {
+ DebugNamesSection::DebugNamesSectionData secData;
+ secData.hdr = ni.getHeader();
+ if (secData.hdr.Format != DwarfFormat::DWARF32)
+ errorOrWarn(toString(chunk.namesSection->sec) + ": unsupported DWARF64");
+ secData.dwarfSize = dwarf::getDwarfOffsetByteSize(DwarfFormat::DWARF32);
+ secData.hdrSize = computeDebugNamesHeaderSize();
+ if (secData.hdr.Version != 5)
+ errorOrWarn(toString(chunk.namesSection->sec) + ": unsupported version");
+ secData.locs = findDebugNamesOffsets(secData.hdrSize, secData.hdr);
+ readCompileUnitOffsets<ELFT>(secData, chunk, outputChunk, namesExtractor);
+ readEntryOffsets<ELFT>(secData, chunk, namesExtractor);
+ readEntries<ELFT>(secData, chunk, namesExtractor, strExtractor, ni);
+ chunk.sectionsData.push_back(std::move(secData));
+ }
+}
+
+void DebugNamesSection::collectMergedCounts(
+ MutableArrayRef<DebugNamesInputChunk> &inputChunks) {
+ SmallVector<uint32_t, 0> tmpMergedCuOffsets;
+
+ mergedHdr.CompUnitCount = 0;
+ mergedHdr.LocalTypeUnitCount = 0;
+ mergedHdr.ForeignTypeUnitCount = 0;
+ mergedHdr.Version = 5;
+ mergedHdr.Format = DwarfFormat::DWARF32;
+ mergedHdr.AugmentationStringSize = 0;
+
+ for (size_t i = 0; i < numChunks; ++i) {
+ DebugNamesInputChunk &inputChunk = inputChunks[i];
+ DebugNamesOutputChunk &outputChunk = outputChunks[i];
+ inputChunk.baseCuOffsetIdx = tmpMergedCuOffsets.size();
+ for (uint32_t cuOffset : outputChunk.compilationUnits)
+ tmpMergedCuOffsets.push_back(outputChunk.sec->outSecOff + cuOffset);
+ for (const DebugNamesSectionData &data : inputChunk.sectionsData) {
+ mergedHdr.CompUnitCount += data.hdr.CompUnitCount;
+ mergedHdr.LocalTypeUnitCount += data.hdr.LocalTypeUnitCount;
+ mergedHdr.ForeignTypeUnitCount += data.hdr.ForeignTypeUnitCount;
+ // Set & check the Augmentation String.
+ if (mergedHdr.AugmentationStringSize == 0) {
+ mergedHdr.AugmentationStringSize = data.hdr.AugmentationStringSize;
+ mergedHdr.AugmentationString = data.hdr.AugmentationString;
+ } else if ((mergedHdr.AugmentationStringSize !=
+ data.hdr.AugmentationStringSize) ||
+ (mergedHdr.AugmentationString !=
+ data.hdr.AugmentationString)) {
+ // There are conflicting augmentation strings, so it's best for the
+ // merged index to not use an augmentation string.
+ StringRef emptyString = " ";
+ mergedHdr.AugmentationStringSize = 8;
+ mergedHdr.AugmentationString = emptyString;
+ }
+ }
+ }
+}
+
+void DebugNamesSection::Abbrev::Profile(llvm::FoldingSetNodeID &id) const {
+ id.AddInteger(tag);
+ for (const DWARFDebugNames::AttributeEncoding &attr : attributes) {
+ id.AddInteger(attr.Index);
+ id.AddInteger(attr.Form);
+ }
+}
+
+std::pair<uint8_t, dwarf::Form> DebugNamesSection::getMergedCuSizeData() {
+ // Once we've merged all the CU offsets into a single list, the original
+ // DWARF form/size (often 1 byte) may be too small to hold indices to all
+ // the offsets. Here we calculate what the right form/size needs to be for
+ // the merged index.
+ uint8_t size;
+ dwarf::Form form;
+ // TODO: Investigate possibly using llvm::DIEInteger::BestForm here
+ if (mergedHdr.CompUnitCount > 0xffffffff) {
+ form = DW_FORM_data8;
+ size = 8;
+ } else if (mergedHdr.CompUnitCount > 0xffff) {
+ form = DW_FORM_data4;
+ size = 4;
+ } else if (mergedHdr.CompUnitCount > 0xff) {
+ form = DW_FORM_data2;
+ size = 2;
+ } else {
+ form = DW_FORM_data1;
+ size = 1;
+ }
+
+ return {size, form};
+}
+
+void DebugNamesSection::getMergedAbbrevTable(
+ MutableArrayRef<DebugNamesInputChunk> &inputChunks) {
+ MapVector<uint64_t, Abbrev> abbrevMap;
+ FoldingSet<DebugNamesSection::Abbrev> AbbreviationsSet;
+
+ // Need to determine what size form is needed for the DW_IDX_compile_unit
+ // attributes in the merged index. Will need to update the abbrevs to use
+ // the right form.
+ dwarf::Form compileUnitAttrForm = getMergedCuSizeData().second;
+
+ for (DebugNamesInputChunk &chunk : inputChunks) {
+ for (const auto &ni : *chunk.debugNamesData) {
+ const auto &abbrevs = ni.getAbbrevs();
+ for (const DWARFDebugNames::Abbrev &abbrev : abbrevs) {
+ // Create canonicalized abbrev.
+ DebugNamesSection::Abbrev newAbbrev;
+ DWARFDebugNames::AttributeEncoding cuOrTuAttr(DW_IDX_compile_unit,
+ compileUnitAttrForm);
+ newAbbrev.code = abbrev.Code;
+ newAbbrev.tag = abbrev.Tag;
+ for (const auto attr : abbrev.Attributes) {
+ DWARFDebugNames::AttributeEncoding newAttr(attr.Index, attr.Form);
+ if (attr.Index == DW_IDX_compile_unit ||
+ attr.Index == DW_IDX_type_unit)
+ // Save it, to put it at the end.
+ cuOrTuAttr.Index = newAttr.Index;
+ else
+ newAbbrev.attributes.push_back(newAttr);
+ }
+ // Put the CU/TU index at the end of the attributes list.
+ newAbbrev.attributes.push_back(cuOrTuAttr);
+
+ // Next, check our abbreviations set to see if we've already seen the
+ // identical abbreviation.
+ uint32_t oldCode = newAbbrev.code;
+ uint32_t newCode;
+ FoldingSetNodeID id;
+ newAbbrev.Profile(id);
+ void *insertPos;
+ if (Abbrev *Existing =
+ AbbreviationsSet.FindNodeOrInsertPos(id, insertPos)) {
+ // Found it; we've already seen an identical abbreviation.
+ newCode = Existing->code;
+ } else {
+ // Didn't find it.
+ Abbrev *newAbbrev2 = new (Alloc) Abbrev(std::move(newAbbrev));
+ AbbreviationsSet.InsertNode(newAbbrev2, insertPos);
+ newCode = mergedAbbrevTable.size() + 1;
+ newAbbrev2->code = newCode;
+ mergedAbbrevTable.push_back(newAbbrev2);
+ }
+ chunk.abbrevCodeMap[oldCode] = newCode;
+ }
+ }
+ }
+
+ // Calculate the merged abbrev table size.
+ mergedHdr.AbbrevTableSize = 0;
+ for (Abbrev *a : mergedAbbrevTable) {
+ mergedHdr.AbbrevTableSize += getULEB128Size(a->code);
+ mergedHdr.AbbrevTableSize += getULEB128Size(a->tag);
+ for (const auto &attr : a->attributes) {
+ mergedHdr.AbbrevTableSize += getULEB128Size(attr.Index);
+ mergedHdr.AbbrevTableSize += getULEB128Size(attr.Form);
+ }
+ mergedHdr.AbbrevTableSize += 2; // attribute index & form sentinels
+ }
+ ++mergedHdr.AbbrevTableSize; // abbrev table sentinel
+}
+
+void DebugNamesSection::getMergedSymbols(
+ MutableArrayRef<DebugNamesInputChunk> &inputChunks) {
+ // The number of symbols (& abbrevs) we will handle is very large; will use
+ // multi-threading to speed it up.
+ constexpr size_t numShards = 32;
+ const size_t concurrency =
+ llvm::bit_floor(std::min<size_t>(config->threadCount, numShards));
+ const size_t shift = 32 - llvm::countr_zero(numShards);
+
+ struct ShardData {
+ // Map to uniquify symbols by name
+ MapVector<CachedHashStringRef, NamedEntry> nameMap;
+ };
+
+ // Need to determine what size is needed for the DW_IDX_compile_unit
+ // attributes in the merged index. Will need to update the indexEntries
+ // to use the right size.
+ uint8_t compileUnitAttrSize = getMergedCuSizeData().first;
+
+ auto shardsPtr = std::make_unique<ShardData[]>(numShards);
+ MutableArrayRef<ShardData> shards(shardsPtr.get(), numShards);
+
+ parallelFor(0, concurrency, [&](size_t threadId) {
+ for (size_t i = 0; i < numChunks; ++i) {
+ DebugNamesInputChunk &chunk = inputChunks[i];
+ for (auto &secData : chunk.sectionsData) {
+ // Deduplicate the NamedEntry records (based on the string/name),
+ // using a map from string/name to NamedEntry records.
+ // Note there is a twist: If there is already a record for the current
+ // 'string' in the nameMap, we append all the indexEntries from the
+ // current record to the record that's in the nameMap. I.e. we
+ // deduplicate the *strings* but we keep all the IndexEntry records
+ // (moving them to the appropriate 'kept' NamedEntry record).
+ for (auto &stringEntry : secData.namedEntries) {
+ size_t shardId = stringEntry.hashValue >> shift;
+ if ((shardId & (concurrency - 1)) != threadId)
+ continue;
+
+ auto &shard = shards[shardId];
+ stringEntry.chunkIdx = i;
+ for (auto &entry : stringEntry.indexEntries) {
+ // The DW_IDX_compile_unit is always the last attribute (we set it
+ // up that way when we read/created the attributes). We need to
+ // update the index value to use the correct merged offset, and we
+ // need to fix the size of the index attribute.
+ uint8_t endPos = entry->attrValues.size() - 1;
+ entry->attrValues[endPos].attrValue += chunk.baseCuOffsetIdx;
+ entry->attrValues[endPos].attrSize = compileUnitAttrSize;
+ // Update the entry's abbrev code to match the merged
+ // abbreviations.
+ entry->abbrevCode = chunk.abbrevCodeMap[entry->abbrevCode];
+ }
+
+ CachedHashStringRef cachedHashName(stringEntry.name);
+ auto [it, inserted] =
+ shard.nameMap.try_emplace(cachedHashName, std::move(stringEntry));
+ if (!inserted) {
+ // Found the string already; don't add to map, but append
+ // entry/entries for it to existing map entry.
+ NamedEntry &found = it->second;
+ // Append the entries...
+ for (auto &entry : stringEntry.indexEntries)
+ found.indexEntries.push_back(std::move(entry));
+ }
+ }
+ }
+ }
+ });
+
+ // Combined the shared symbols into mergedEntries
+ for (auto &shard : shards)
+ for (auto &mapEntry : shard.nameMap)
+ mergedEntries.push_back(std::move(mapEntry.second));
+ mergedHdr.NameCount = mergedEntries.size();
+}
+
+void DebugNamesSection::computeUniqueHashes(
+ MutableArrayRef<DebugNamesInputChunk> &chunks) {
+ SmallVector<uint32_t, 0> uniques;
+ for (const auto &chunk : chunks)
+ uniques.append(chunk.hashValues);
+ llvm::sort(uniques);
+ mergedHdr.BucketCount = dwarf::getDebugNamesBucketCount(llvm::unique(uniques) - uniques.begin());
+}
+
+void DebugNamesSection::generateBuckets() {
+ bucketList.resize(mergedHdr.BucketCount);
+ for (auto &entry : mergedEntries) {
+ uint32_t bucketIdx = entry.hashValue % mergedHdr.BucketCount;
+ bucketList[bucketIdx].push_back(&entry);
+ }
+
+ // Sort the contents of the buckets by hash value so that the hash collisions
+ // end up together.
+ for (auto &bucket : bucketList)
+ llvm::stable_sort(bucket, [](NamedEntry *lhs, NamedEntry *rhs) {
+ return lhs->hashValue < rhs->hashValue;
+ });
+}
+
+void DebugNamesSection::calculateEntriesSizeAndOffsets() {
+ uint32_t offset = 0;
+ for (DebugNamesSection::NamedEntry &stringEntry : mergedEntries) {
+ stringEntry.entryOffset = offset;
+ for (auto &entry : stringEntry.indexEntries) {
+ uint32_t entrySize = 0;
+ entry->poolOffset = offset;
+ uint32_t ulebSize = getULEB128Size(entry->abbrevCode);
+ entrySize += ulebSize;
+ for (const auto &attr : entry->attrValues)
+ entrySize += attr.attrSize;
+ offset += entrySize;
+ }
+ // Add in sentinel size
+ ++offset;
+ }
+ mergedTotalEntriesSize = offset;
+}
+
+void DebugNamesSection::updateParentIndexEntries() {
+ for (DebugNamesSection::NamedEntry &stringEntry : mergedEntries) {
+ for (auto &childEntry : stringEntry.indexEntries) {
+ if (!childEntry->parentEntry)
+ continue;
+
+ // Abbrevs are indexed starting at 1; vector starts at 0. (abbrevCode
+ // corresponds to position in the merged table vector).
+ const Abbrev *abbrev = mergedAbbrevTable[childEntry->abbrevCode - 1];
+
+ // Found the abbrev. Find the index for the DW_IDX_parent attribute
+ // (in the abbrev) and update that value in the entry with the
+ // correct parent offset (in the merged entry pool).
+ for (size_t idx = 0, size = abbrev->attributes.size(); idx < size;
+ ++idx) {
+ auto attr = abbrev->attributes[idx];
+ if (attr.Index == DW_IDX_parent && attr.Form == DW_FORM_ref4)
+ childEntry->attrValues[idx].attrValue =
+ childEntry->parentEntry->poolOffset;
+ }
+ }
+ }
+}
+
+uint64_t DebugNamesSection::calculateMergedSectionSize() {
+ uint32_t hdrSize = computeDebugNamesHeaderSize();
+ mergedOffsets = findDebugNamesOffsets(hdrSize, mergedHdr);
+ // Add in the size for all the Entries, and make it 4-byte aligned.
+ mergedHdr.UnitLength =
+ alignTo(mergedOffsets.EntriesBase + mergedTotalEntriesSize, 4);
+ // Add in the first 4 bytes, whichs print out the length of the section.
+ return mergedHdr.UnitLength + 4;
+}
+
+template <class ELFT> DebugNamesSection *DebugNamesSection::create() {
+ llvm::TimeTraceScope timeScope("Create merged .debug_names");
+ SetVector<InputFile *> files;
+ SmallVector<InputSectionBase *, 0> sections;
+ for (InputSectionBase *s : ctx.inputSections) {
+ InputSection *isec = dyn_cast<InputSection>(s);
+ if (!isec)
+ continue;
+ // Mark original sections as dead, but save links to them for calculating
+ // relocations later.
+ if (s->name == ".debug_names") {
+ s->markDead();
+ sections.push_back(s);
+ files.insert(isec->file);
+ }
+ }
+ auto inputChunksPtr = std::make_unique<DebugNamesInputChunk[]>(files.size());
+ MutableArrayRef<DebugNamesInputChunk> inputChunks(inputChunksPtr.get(),
+ files.size());
+ auto outputChunks = std::make_unique<DebugNamesOutputChunk[]>(files.size());
+ parallelFor(0, files.size(), [&](size_t i) {
+ ObjFile<ELFT> *file = cast<ObjFile<ELFT>>(files[i]);
+ auto dwarfCtx = std::make_unique<DWARFContext>(
+ std::make_unique<LLDDwarfObj<ELFT>>(file));
+ auto &dobj =
+ static_cast<const LLDDwarfObj<ELFT> &>(dwarfCtx->getDWARFObj());
+
+ // Extract llvm::DWARFDebugNames data from the .debug_names section. The
+ // .debug_names section needs the .debug_str section, to get the actual
+ // symbol names.
+ const StringRef &strSection = dobj.getStrSection();
+ const LLDDWARFSection &namesSection = dobj.getNamesSection();
+ llvm::DWARFDataExtractor namesExtractor(dobj, namesSection, config->isLE,
+ config->wordsize);
+ llvm::DataExtractor strExtractor(strSection, config->isLE,
+ config->wordsize);
+ inputChunks[i].debugNamesData =
+ std::make_unique<DWARFDebugNames>(namesExtractor, strExtractor);
+ inputChunks[i].namesSection =
+ std::make_unique<LLDDWARFSection>(namesSection);
+ if (llvm::Error E = inputChunks[i].debugNamesData->extract()) {
+ // Report an error here. We were unable to extract the data.
+ errorOrWarn(toString(dobj.getNamesSection().sec) + ": " +
+ toString(std::move(E)));
+ }
+ outputChunks[i].sec = dobj.getInfoSection();
+ collectDebugNamesSectionData<ELFT>(inputChunks[i], outputChunks[i],
+ namesExtractor, strExtractor);
+ });
+
+ auto *ret = make<DebugNamesSection>();
+ ret->addSections(sections);
+ ret->outputChunks = std::move(outputChunks);
+ ret->numChunks = files.size();
+ ret->collectMergedCounts(inputChunks);
+ ret->getMergedAbbrevTable(inputChunks);
+ ret->getMergedSymbols(inputChunks);
+ ret->computeUniqueHashes(inputChunks);
+ inputChunksPtr.reset();
+ ret->generateBuckets();
+ ret->calculateEntriesSizeAndOffsets();
+ ret->updateParentIndexEntries();
+ ret->sectionSize = ret->calculateMergedSectionSize();
+ return ret;
+}
+
GdbIndexSection::GdbIndexSection()
: SyntheticSection(0, SHT_PROGBITS, 1, ".gdb_index") {}
@@ -4272,6 +5028,8 @@ template <class ELFT> void elf::createSyntheticSections() {
if (config->andFeatures || !ctx.aarch64PauthAbiCoreInfo.empty())
add(*make<GnuPropertySection>());
+ if (config->debugNames)
+ add(*DebugNamesSection::create<ELFT>());
if (config->gdbIndex) {
in.gdbIndex = GdbIndexSection::create<ELFT>();
add(*in.gdbIndex);
diff --git a/lld/ELF/SyntheticSections.h b/lld/ELF/SyntheticSections.h
index 759b78668f5462..e0b01831edaa77 100644
--- a/lld/ELF/SyntheticSections.h
+++ b/lld/ELF/SyntheticSections.h
@@ -21,13 +21,17 @@
#define LLD_ELF_SYNTHETIC_SECTIONS_H
#include "Config.h"
+#include "DWARF.h"
#include "InputSection.h"
#include "Symbols.h"
#include "llvm/ADT/DenseSet.h"
+#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/MapVector.h"
#include "llvm/ADT/STLFunctionalExtras.h"
#include "llvm/BinaryFormat/ELF.h"
+#include "llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h"
#include "llvm/MC/StringTableBuilder.h"
+#include "llvm/Support/Allocator.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/Endian.h"
#include "llvm/Support/Parallel.h"
@@ -789,6 +793,136 @@ class RelroPaddingSection final : public SyntheticSection {
void writeTo(uint8_t *buf) override {}
};
+class DebugNamesSection final : public SyntheticSection {
+ // N.B. Everything in this class assumes that we are using DWARF32.
+ // If we move to DWARF64, most of this data will need to be re-sized,
+ // and the code that handles or manipulates it will need to be updated
+ // accordingly.
+
+public:
+ DebugNamesSection();
+ template <typename ELFT> static DebugNamesSection *create();
+ void writeTo(uint8_t *buf) override;
+ size_t getSize() const override { return sectionSize; }
+ bool isNeeded() const override;
+
+ void addSections(SmallVector<InputSectionBase *, 0> sec_list) {
+ inputDebugNamesSections = sec_list;
+ }
+
+ template <class ELFT> void writeToImpl(uint8_t *buf);
+
+ template <class ELFT, class RelTy>
+ void getNameRelocsImpl(InputSection *sec, ArrayRef<RelTy> rels,
+ llvm::DenseMap<uint32_t, uint32_t> &relocs);
+
+ template <class ELFT>
+ void getNameRelocs(InputSectionBase *base,
+ llvm::DenseMap<uint32_t, uint32_t> &relocs);
+
+ template <class ELFT>
+ void endianWrite(uint8_t size, uint8_t *buf_start, uint32_t offset,
+ uint32_t data);
+
+ struct Abbrev : public llvm::FoldingSetNode {
+ uint32_t code;
+ uint32_t tag;
+ SmallVector<llvm::DWARFDebugNames::AttributeEncoding, 2> attributes;
+
+ void Profile(llvm::FoldingSetNodeID &id) const;
+ };
+
+ struct AttrValueData {
+ uint32_t attrValue;
+ uint8_t attrSize;
+ };
+
+ struct IndexEntry {
+ uint32_t abbrevCode;
+ uint32_t poolOffset;
+ union {
+ int32_t parentOffset = -1;
+ IndexEntry *parentEntry;
+ };
+ SmallVector<AttrValueData, 3> attrValues;
+ };
+
+ struct NamedEntry {
+ const char *name;
+ uint32_t hashValue;
+ uint32_t stringOffsetOffset;
+ uint32_t entryOffset;
+ uint32_t relocatedEntryOffset;
+ // The index of the chunk that 'name' points into, for looking up
+ // relocation data for this string.
+ uint32_t chunkIdx;
+ SmallVector<std::unique_ptr<IndexEntry>, 0> indexEntries;
+ };
+
+ struct SectionOffsetLocs {
+ uint64_t stringOffsetsBase;
+ uint64_t entryOffsetsBase;
+ uint64_t entriesBase;
+ };
+
+ struct DebugNamesSectionData {
+ llvm::DWARFDebugNames::Header hdr;
+ llvm::DWARFDebugNames::DWARFDebugNamesOffsets locs;
+ SmallVector<uint32_t, 0> tuOffsets;
+ SmallVector<Abbrev, 0> abbrevTable;
+ std::unique_ptr<uint32_t[]> entryOffsets;
+ SmallVector<NamedEntry, 0> namedEntries;
+ uint16_t dwarfSize;
+ uint16_t hdrSize;
+ };
+
+ // Per-file data used, while reading in the data, to generate the merged
+ // section information.
+ struct DebugNamesInputChunk {
+ uint32_t baseCuOffsetIdx;
+ std::unique_ptr<llvm::DWARFDebugNames> debugNamesData;
+ std::unique_ptr<LLDDWARFSection> namesSection;
+ SmallVector<DebugNamesSectionData, 0> sectionsData;
+ SmallVector<uint32_t, 0> hashValues;
+ llvm::DenseMap<uint32_t, uint32_t> abbrevCodeMap;
+ };
+
+ // Per-file data needed for correctly writing out the .debug_names section.
+ struct DebugNamesOutputChunk {
+ // Pointer to .debug_info section for this chunk/file, used for
+ // calculating correct relocated CU offsets in the merged index.
+ InputSection *sec;
+ SmallVector<uint32_t, 0> compilationUnits;
+ SmallVector<uint32_t, 0> typeUnits;
+ };
+
+ void collectMergedCounts(MutableArrayRef<DebugNamesInputChunk> &inputChunks);
+ std::pair<uint8_t, llvm::dwarf::Form> getMergedCuSizeData();
+ void getMergedAbbrevTable(MutableArrayRef<DebugNamesInputChunk> &inputChunks);
+ void getMergedSymbols(MutableArrayRef<DebugNamesInputChunk> &inputChunks);
+ void computeUniqueHashes(MutableArrayRef<DebugNamesInputChunk> &inputChunks);
+ void generateBuckets();
+ void calculateEntriesSizeAndOffsets();
+ void updateParentIndexEntries();
+ uint64_t calculateMergedSectionSize();
+
+ llvm::BumpPtrAllocator Alloc;
+
+private:
+ size_t sectionSize;
+ uint32_t mergedTotalEntriesSize;
+ uint32_t numChunks;
+ llvm::DWARFDebugNames::DWARFDebugNamesOffsets mergedOffsets;
+ std::unique_ptr<DebugNamesOutputChunk[]> outputChunks;
+ // Pointers to the original .debug_names sections; used for find the correct'
+ // string relocation values when writing out the merged index.
+ SmallVector<InputSectionBase *, 0> inputDebugNamesSections;
+ llvm::DWARFDebugNames::Header mergedHdr;
+ SmallVector<Abbrev *, 0> mergedAbbrevTable;
+ SmallVector<NamedEntry, 0> mergedEntries;
+ SmallVector<SmallVector<NamedEntry *, 0>, 0> bucketList;
+};
+
class GdbIndexSection final : public SyntheticSection {
public:
struct AddressEntry {
diff --git a/lld/docs/ld.lld.1 b/lld/docs/ld.lld.1
index e0316730f442ed..ba8ce8f784759a 100644
--- a/lld/docs/ld.lld.1
+++ b/lld/docs/ld.lld.1
@@ -172,6 +172,10 @@ This is like a generalized
Output cross reference table. If
.Fl Map
is specified, print to the map file.
+.It Fl -debug-names
+Generate a merged
+.Li .debug_names
+section.
.It Fl -defsym Ns = Ns Ar symbol Ns = Ns Ar expression
Define a symbol alias.
.Ar expression
diff --git a/lld/test/ELF/Inputs/debug-names-2.s b/lld/test/ELF/Inputs/debug-names-2.s
new file mode 100644
index 00000000000000..586788653dcc72
--- /dev/null
+++ b/lld/test/ELF/Inputs/debug-names-2.s
@@ -0,0 +1,191 @@
+#-- input file: debug-names-2.cpp
+## Generated with:
+##
+## - clang++ -g -O0 -gpubnames -fdebug-compilation-dir='debug-names-test' \
+## -S debug-names-2.cpp -o debug-names-2.s
+##
+## debug-names-2.cpp contents:
+##
+## struct t1 { };
+## int main() {
+## t1 v1;
+## }
+##
+ .text
+ .globl main # -- Begin function main
+ .p2align 4, 0x90
+ .type main, at function
+main: # @main
+.Lfunc_begin0:
+ .cfi_startproc
+# %bb.0: # %entry
+ pushq %rbp
+ .cfi_def_cfa_offset 16
+ .cfi_offset %rbp, -16
+ movq %rsp, %rbp
+ .cfi_def_cfa_register %rbp
+.Ltmp0:
+ xorl %eax, %eax
+ popq %rbp
+ .cfi_def_cfa %rsp, 8
+ retq
+.Ltmp1:
+.Lfunc_end0:
+ .size main, .Lfunc_end0-main
+ .cfi_endproc
+ # -- End function
+ .section .debug_abbrev,"", at progbits
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 0 # EOM(3)
+ .section .debug_info,"", at progbits
+.Lcu_begin0:
+ .long .Ldebug_info_end0-.Ldebug_info_start0 # Length of Unit
+.Ldebug_info_start0:
+ .short 5 # DWARF version number
+ .byte 1 # DWARF Unit Type
+ .byte 8 # Address Size (in bytes)
+ .long .debug_abbrev # Offset Into Abbrev. Section
+ .byte 1 # Abbrev [1] 0xc:0x3d DW_TAG_compile_unit
+ .byte 0 # DW_AT_producer
+ .short 33 # DW_AT_language
+ .byte 1 # DW_AT_name
+ .long .Lstr_offsets_base0 # DW_AT_str_offsets_base
+ .long .Lline_table_start0 # DW_AT_stmt_list
+ .byte 2 # DW_AT_comp_dir
+ .byte 0 # DW_AT_low_pc
+ .long .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc
+ .long .Laddr_table_base0 # DW_AT_addr_base
+ .byte 2 # Abbrev [2] 0x23:0x1b DW_TAG_subprogram
+ .byte 0 # DW_AT_low_pc
+ .long .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc
+ .byte 1 # DW_AT_frame_base
+ .byte 86
+ .byte 3 # DW_AT_name
+ .byte 0 # DW_AT_decl_file
+ .byte 2 # DW_AT_decl_line
+ .long 62 # DW_AT_type
+ # DW_AT_external
+ .byte 3 # Abbrev [3] 0x32:0xb DW_TAG_variable
+ .byte 2 # DW_AT_location
+ .byte 145
+ .byte 127
+ .byte 5 # DW_AT_name
+ .byte 0 # DW_AT_decl_file
+ .byte 3 # DW_AT_decl_line
+ .long 66 # DW_AT_type
+ .byte 0 # End Of Children Mark
+ .byte 4 # Abbrev [4] 0x3e:0x4 DW_TAG_base_type
+ .byte 4 # DW_AT_name
+ .byte 5 # DW_AT_encoding
+ .byte 4 # DW_AT_byte_size
+ .byte 5 # Abbrev [5] 0x42:0x6 DW_TAG_structure_type
+ .byte 5 # DW_AT_calling_convention
+ .byte 6 # DW_AT_name
+ .byte 1 # DW_AT_byte_size
+ .byte 0 # DW_AT_decl_file
+ .byte 1 # DW_AT_decl_line
+ .byte 0 # End Of Children Mark
+.Ldebug_info_end0:
+ .section .debug_str_offsets,"", at progbits
+ .long 32 # Length of String Offsets Set
+ .short 5
+ .short 0
+.Lstr_offsets_base0:
+ .section .debug_str,"MS", at progbits,1
+.Linfo_string0:
+ .asciz "clang version 19.0.0git (git at github.com:llvm/llvm-project.git 4df364bc93af49ae413ec1ae8328f34ac70730c4)" # string offset=0
+.Linfo_string1:
+ .asciz "debug-names-2.cpp" # string offset=104
+.Linfo_string2:
+ .asciz "debug-names-test" # string offset=122
+.Linfo_string3:
+ .asciz "main" # string offset=139
+.Linfo_string4:
+ .asciz "int" # string offset=144
+.Linfo_string5:
+ .asciz "v1" # string offset=148
+.Linfo_string6:
+ .asciz "t1" # string offset=151
+.Laddr_table_base0:
+ .quad .Lfunc_begin0
+.Ldebug_addr_end0:
+ .section .debug_names,"", at progbits
+ .long .Lnames_end0-.Lnames_start0 # Header: unit length
+.Lnames_start0:
+ .short 5 # Header: version
+ .short 0 # Header: padding
+ .long 1 # Header: compilation unit count
+ .long 0 # Header: local type unit count
+ .long 0 # Header: foreign type unit count
+ .long 3 # Header: bucket count
+ .long 3 # Header: name count
+ .long .Lnames_abbrev_end0-.Lnames_abbrev_start0 # Header: abbreviation table size
+ .long 8 # Header: augmentation string size
+ .ascii "LLVM0700" # Header: augmentation string
+ .long .Lcu_begin0 # Compilation unit 0
+ .long 0 # Bucket 0
+ .long 1 # Bucket 1
+ .long 3 # Bucket 2
+ .long 5863786 # Hash in Bucket 1
+ .long 2090499946 # Hash in Bucket 1
+ .long 193495088 # Hash in Bucket 2
+ .long .Linfo_string6 # String in Bucket 1: t1
+ .long .Linfo_string3 # String in Bucket 1: main
+ .long .Linfo_string4 # String in Bucket 2: int
+ .long .Lnames2-.Lnames_entries0 # Offset in Bucket 1
+ .long .Lnames0-.Lnames_entries0 # Offset in Bucket 1
+ .long .Lnames1-.Lnames_entries0 # Offset in Bucket 2
+.Lnames_abbrev_start0:
+ .byte 1 # Abbrev code
+ .byte 19 # DW_TAG_structure_type
+ .byte 3 # DW_IDX_die_offset
+ .byte 19 # DW_FORM_ref4
+ .byte 4 # DW_IDX_parent
+ .byte 25 # DW_FORM_flag_present
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev
+ .byte 2 # Abbrev code
+ .byte 46 # DW_TAG_subprogram
+ .byte 3 # DW_IDX_die_offset
+ .byte 19 # DW_FORM_ref4
+ .byte 4 # DW_IDX_parent
+ .byte 25 # DW_FORM_flag_present
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev
+ .byte 3 # Abbrev code
+ .byte 36 # DW_TAG_base_type
+ .byte 3 # DW_IDX_die_offset
+ .byte 19 # DW_FORM_ref4
+ .byte 4 # DW_IDX_parent
+ .byte 25 # DW_FORM_flag_present
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev list
+.Lnames_abbrev_end0:
+.Lnames_entries0:
+.Lnames2:
+.L1:
+ .byte 1 # Abbreviation code
+ .long 66 # DW_IDX_die_offset
+ .byte 0 # DW_IDX_parent
+ # End of list: t1
+.Lnames0:
+.L2:
+ .byte 2 # Abbreviation code
+ .long 35 # DW_IDX_die_offset
+ .byte 0 # DW_IDX_parent
+ # End of list: main
+.Lnames1:
+.L0:
+ .byte 3 # Abbreviation code
+ .long 62 # DW_IDX_die_offset
+ .byte 0 # DW_IDX_parent
+ # End of list: int
+ .p2align 2, 0x0
+.Lnames_end0:
+ .ident "clang version 19.0.0git (git at github.com:llvm/llvm-project.git 4df364bc93af49ae413ec1ae8328f34ac70730c4)"
+ .section ".note.GNU-stack","", at progbits
+ .addrsig
+ .section .debug_line,"", at progbits
+.Lline_table_start0:
diff --git a/lld/test/ELF/Inputs/debug-names-parent-idx-2.s b/lld/test/ELF/Inputs/debug-names-parent-idx-2.s
new file mode 100644
index 00000000000000..7eedaaee549450
--- /dev/null
+++ b/lld/test/ELF/Inputs/debug-names-parent-idx-2.s
@@ -0,0 +1,347 @@
+#-- input file: debug-names-parent-idx-2.cpp
+## Generated with:
+##
+## - clang++ -g -O0 -gpubnames -fdebug-compilation-dir='parent-idx-test' \
+## -S debug-names-parent-idx-2.cpp -o debug-names-parent-idx-2.s
+##
+## foo.h contents:
+##
+## int foo();
+##
+## struct foo {
+## int x;
+## char y;
+## struct foo *foo_ptr;
+## };
+##
+## namespace parent_test {
+## int foo();
+## }
+##
+## debug-names-parent-index-2.cpp contents:
+##
+## #include "foo.h"
+## int foo () {
+## struct foo struct2;
+## struct2.x = 1024;
+## struct2.y = 'r';
+## struct2.foo_ptr = nullptr;
+## return struct2.x * (int) struct2.y;
+## }
+##
+## namespace parent_test {
+## int foo () {
+## return 25;
+## }
+## }
+##
+ .text
+ .globl _Z3foov # -- Begin function _Z3foov
+ .p2align 4, 0x90
+ .type _Z3foov, at function
+_Z3foov: # @_Z3foov
+.Lfunc_begin0:
+ .cfi_startproc
+# %bb.0: # %entry
+ pushq %rbp
+ .cfi_def_cfa_offset 16
+ .cfi_offset %rbp, -16
+ movq %rsp, %rbp
+ .cfi_def_cfa_register %rbp
+.Ltmp0:
+ movl $1024, -16(%rbp) # imm = 0x400
+ movb $114, -12(%rbp)
+ movq $0, -8(%rbp)
+ movl -16(%rbp), %eax
+ movsbl -12(%rbp), %ecx
+ imull %ecx, %eax
+ popq %rbp
+ .cfi_def_cfa %rsp, 8
+ retq
+.Ltmp1:
+.Lfunc_end0:
+ .size _Z3foov, .Lfunc_end0-_Z3foov
+ .cfi_endproc
+ # -- End function
+ .globl _ZN11parent_test3fooEv # -- Begin function _ZN11parent_test3fooEv
+ .p2align 4, 0x90
+ .type _ZN11parent_test3fooEv, at function
+_ZN11parent_test3fooEv: # @_ZN11parent_test3fooEv
+.Lfunc_begin1:
+ .cfi_startproc
+# %bb.0: # %entry
+ pushq %rbp
+ .cfi_def_cfa_offset 16
+ .cfi_offset %rbp, -16
+ movq %rsp, %rbp
+ .cfi_def_cfa_register %rbp
+.Ltmp2:
+ movl $25, %eax
+ popq %rbp
+ .cfi_def_cfa %rsp, 8
+ retq
+.Ltmp3:
+.Lfunc_end1:
+ .size _ZN11parent_test3fooEv, .Lfunc_end1-_ZN11parent_test3fooEv
+ .cfi_endproc
+ # -- End function
+ .section .debug_abbrev,"", at progbits
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 0 # EOM(3)
+ .section .debug_info,"", at progbits
+.Lcu_begin0:
+ .long .Ldebug_info_end0-.Ldebug_info_start0 # Length of Unit
+.Ldebug_info_start0:
+ .short 5 # DWARF version number
+ .byte 1 # DWARF Unit Type
+ .byte 8 # Address Size (in bytes)
+ .long .debug_abbrev # Offset Into Abbrev. Section
+ .byte 1 # Abbrev [1] 0xc:0x76 DW_TAG_compile_unit
+ .byte 0 # DW_AT_producer
+ .short 33 # DW_AT_language
+ .byte 1 # DW_AT_name
+ .long .Lstr_offsets_base0 # DW_AT_str_offsets_base
+ .long .Lline_table_start0 # DW_AT_stmt_list
+ .byte 2 # DW_AT_comp_dir
+ .byte 0 # DW_AT_low_pc
+ .long .Lfunc_end1-.Lfunc_begin0 # DW_AT_high_pc
+ .long .Laddr_table_base0 # DW_AT_addr_base
+ .byte 2 # Abbrev [2] 0x23:0x4 DW_TAG_base_type
+ .byte 3 # DW_AT_name
+ .byte 5 # DW_AT_encoding
+ .byte 4 # DW_AT_byte_size
+ .byte 3 # Abbrev [3] 0x27:0x1c DW_TAG_subprogram
+ .byte 0 # DW_AT_low_pc
+ .long .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc
+ .byte 1 # DW_AT_frame_base
+ .byte 86
+ .byte 5 # DW_AT_linkage_name
+ .byte 6 # DW_AT_name
+ .byte 0 # DW_AT_decl_file
+ .byte 4 # DW_AT_decl_line
+ .long 35 # DW_AT_type
+ # DW_AT_external
+ .byte 4 # Abbrev [4] 0x37:0xb DW_TAG_variable
+ .byte 2 # DW_AT_location
+ .byte 145
+ .byte 112
+ .byte 8 # DW_AT_name
+ .byte 0 # DW_AT_decl_file
+ .byte 5 # DW_AT_decl_line
+ .long 86 # DW_AT_type
+ .byte 0 # End Of Children Mark
+ .byte 5 # Abbrev [5] 0x43:0x13 DW_TAG_namespace
+ .byte 4 # DW_AT_name
+ .byte 6 # Abbrev [6] 0x45:0x10 DW_TAG_subprogram
+ .byte 1 # DW_AT_low_pc
+ .long .Lfunc_end1-.Lfunc_begin1 # DW_AT_high_pc
+ .byte 1 # DW_AT_frame_base
+ .byte 86
+ .byte 7 # DW_AT_linkage_name
+ .byte 6 # DW_AT_name
+ .byte 0 # DW_AT_decl_file
+ .byte 16 # DW_AT_decl_line
+ .long 35 # DW_AT_type
+ # DW_AT_external
+ .byte 0 # End Of Children Mark
+ .byte 7 # Abbrev [7] 0x56:0x22 DW_TAG_structure_type
+ .byte 5 # DW_AT_calling_convention
+ .byte 6 # DW_AT_name
+ .byte 16 # DW_AT_byte_size
+ .byte 1 # DW_AT_decl_file
+ .byte 4 # DW_AT_decl_line
+ .byte 8 # Abbrev [8] 0x5c:0x9 DW_TAG_member
+ .byte 9 # DW_AT_name
+ .long 35 # DW_AT_type
+ .byte 1 # DW_AT_decl_file
+ .byte 5 # DW_AT_decl_line
+ .byte 0 # DW_AT_data_member_location
+ .byte 8 # Abbrev [8] 0x65:0x9 DW_TAG_member
+ .byte 10 # DW_AT_name
+ .long 120 # DW_AT_type
+ .byte 1 # DW_AT_decl_file
+ .byte 6 # DW_AT_decl_line
+ .byte 4 # DW_AT_data_member_location
+ .byte 8 # Abbrev [8] 0x6e:0x9 DW_TAG_member
+ .byte 12 # DW_AT_name
+ .long 124 # DW_AT_type
+ .byte 1 # DW_AT_decl_file
+ .byte 7 # DW_AT_decl_line
+ .byte 8 # DW_AT_data_member_location
+ .byte 0 # End Of Children Mark
+ .byte 2 # Abbrev [2] 0x78:0x4 DW_TAG_base_type
+ .byte 11 # DW_AT_name
+ .byte 6 # DW_AT_encoding
+ .byte 1 # DW_AT_byte_size
+ .byte 9 # Abbrev [9] 0x7c:0x5 DW_TAG_pointer_type
+ .long 86 # DW_AT_type
+ .byte 0 # End Of Children Mark
+.Ldebug_info_end0:
+ .section .debug_str_offsets,"", at progbits
+ .long 56 # Length of String Offsets Set
+ .short 5
+ .short 0
+.Lstr_offsets_base0:
+ .section .debug_str,"MS", at progbits,1
+.Linfo_string0:
+ .asciz "clang version 19.0.0git (git at github.com:llvm/llvm-project.git 4df364bc93af49ae413ec1ae8328f34ac70730c4)" # string offset=0
+.Linfo_string1:
+ .asciz "debug-names-parent-idx-2.cpp" # string offset=104
+.Linfo_string2:
+ .asciz "parent-idx-test" # string offset=133
+.Linfo_string3:
+ .asciz "int" # string offset=149
+.Linfo_string4:
+ .asciz "foo" # string offset=153
+.Linfo_string5:
+ .asciz "_Z3foov" # string offset=157
+.Linfo_string6:
+ .asciz "parent_test" # string offset=165
+.Linfo_string7:
+ .asciz "_ZN11parent_test3fooEv" # string offset=177
+.Linfo_string8:
+ .asciz "struct2" # string offset=200
+.Linfo_string9:
+ .asciz "x" # string offset=208
+.Linfo_string10:
+ .asciz "y" # string offset=210
+.Linfo_string11:
+ .asciz "char" # string offset=212
+.Linfo_string12:
+ .asciz "foo_ptr" # string offset=217
+.Laddr_table_base0:
+ .quad .Lfunc_begin0
+ .quad .Lfunc_begin1
+.Ldebug_addr_end0:
+ .section .debug_names,"", at progbits
+ .long .Lnames_end0-.Lnames_start0 # Header: unit length
+.Lnames_start0:
+ .short 5 # Header: version
+ .short 0 # Header: padding
+ .long 1 # Header: compilation unit count
+ .long 0 # Header: local type unit count
+ .long 0 # Header: foreign type unit count
+ .long 6 # Header: bucket count
+ .long 6 # Header: name count
+ .long .Lnames_abbrev_end0-.Lnames_abbrev_start0 # Header: abbreviation table size
+ .long 8 # Header: augmentation string size
+ .ascii "LLVM0700" # Header: augmentation string
+ .long .Lcu_begin0 # Compilation unit 0
+ .long 0 # Bucket 0
+ .long 1 # Bucket 1
+ .long 3 # Bucket 2
+ .long 5 # Bucket 3
+ .long 0 # Bucket 4
+ .long 6 # Bucket 5
+ .long -1451972055 # Hash in Bucket 1
+ .long -1257882357 # Hash in Bucket 1
+ .long 175265198 # Hash in Bucket 2
+ .long 193495088 # Hash in Bucket 2
+ .long 193491849 # Hash in Bucket 3
+ .long 2090147939 # Hash in Bucket 5
+ .long .Linfo_string7 # String in Bucket 1: _ZN11parent_test3fooEv
+ .long .Linfo_string5 # String in Bucket 1: _Z3foov
+ .long .Linfo_string6 # String in Bucket 2: parent_test
+ .long .Linfo_string3 # String in Bucket 2: int
+ .long .Linfo_string4 # String in Bucket 3: foo
+ .long .Linfo_string11 # String in Bucket 5: char
+ .long .Lnames4-.Lnames_entries0 # Offset in Bucket 1
+ .long .Lnames2-.Lnames_entries0 # Offset in Bucket 1
+ .long .Lnames3-.Lnames_entries0 # Offset in Bucket 2
+ .long .Lnames0-.Lnames_entries0 # Offset in Bucket 2
+ .long .Lnames1-.Lnames_entries0 # Offset in Bucket 3
+ .long .Lnames5-.Lnames_entries0 # Offset in Bucket 5
+.Lnames_abbrev_start0:
+ .byte 1 # Abbrev code
+ .byte 46 # DW_TAG_subprogram
+ .byte 3 # DW_IDX_die_offset
+ .byte 19 # DW_FORM_ref4
+ .byte 4 # DW_IDX_parent
+ .byte 19 # DW_FORM_ref4
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev
+ .byte 2 # Abbrev code
+ .byte 46 # DW_TAG_subprogram
+ .byte 3 # DW_IDX_die_offset
+ .byte 19 # DW_FORM_ref4
+ .byte 4 # DW_IDX_parent
+ .byte 25 # DW_FORM_flag_present
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev
+ .byte 3 # Abbrev code
+ .byte 57 # DW_TAG_namespace
+ .byte 3 # DW_IDX_die_offset
+ .byte 19 # DW_FORM_ref4
+ .byte 4 # DW_IDX_parent
+ .byte 25 # DW_FORM_flag_present
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev
+ .byte 4 # Abbrev code
+ .byte 36 # DW_TAG_base_type
+ .byte 3 # DW_IDX_die_offset
+ .byte 19 # DW_FORM_ref4
+ .byte 4 # DW_IDX_parent
+ .byte 25 # DW_FORM_flag_present
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev
+ .byte 5 # Abbrev code
+ .byte 19 # DW_TAG_structure_type
+ .byte 3 # DW_IDX_die_offset
+ .byte 19 # DW_FORM_ref4
+ .byte 4 # DW_IDX_parent
+ .byte 25 # DW_FORM_flag_present
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev list
+.Lnames_abbrev_end0:
+.Lnames_entries0:
+.Lnames4:
+.L3:
+ .byte 1 # Abbreviation code
+ .long 69 # DW_IDX_die_offset
+ .long .L5-.Lnames_entries0 # DW_IDX_parent
+ .byte 0 # End of list: _ZN11parent_test3fooEv
+.Lnames2:
+.L0:
+ .byte 2 # Abbreviation code
+ .long 39 # DW_IDX_die_offset
+ .byte 0 # DW_IDX_parent
+ # End of list: _Z3foov
+.Lnames3:
+.L5:
+ .byte 3 # Abbreviation code
+ .long 67 # DW_IDX_die_offset
+ .byte 0 # DW_IDX_parent
+ # End of list: parent_test
+.Lnames0:
+.L2:
+ .byte 4 # Abbreviation code
+ .long 35 # DW_IDX_die_offset
+ .byte 0 # DW_IDX_parent
+ # End of list: int
+.Lnames1:
+ .byte 2 # Abbreviation code
+ .long 39 # DW_IDX_die_offset
+ .byte 1 # DW_IDX_parent
+ # Abbreviation code
+ .long 69 # DW_IDX_die_offset
+ .long .L5-.Lnames_entries0 # DW_IDX_parent
+.L4:
+ .byte 5 # Abbreviation code
+ .long 86 # DW_IDX_die_offset
+ .byte 0 # DW_IDX_parent
+ # End of list: foo
+.Lnames5:
+.L1:
+ .byte 4 # Abbreviation code
+ .long 120 # DW_IDX_die_offset
+ .byte 0 # DW_IDX_parent
+ # End of list: char
+ .p2align 2, 0x0
+.Lnames_end0:
+ .ident "clang version 19.0.0git (git at github.com:llvm/llvm-project.git 4df364bc93af49ae413ec1ae8328f34ac70730c4)"
+ .section ".note.GNU-stack","", at progbits
+ .addrsig
+ .section .debug_line,"", at progbits
+.Lline_table_start0:
diff --git a/lld/test/ELF/debug-names-bad-aug-string.s b/lld/test/ELF/debug-names-bad-aug-string.s
new file mode 100644
index 00000000000000..edf79f0fde5773
--- /dev/null
+++ b/lld/test/ELF/debug-names-bad-aug-string.s
@@ -0,0 +1,189 @@
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t1.o
+# RUN: llvm-mc -filetype=obj -triple=x86_64 %p/Inputs/debug-names-2.s -o %t2
+# RUN: ld.lld --debug-names %t1.o %t2.o -o %t
+
+# RUN: llvm-dwarfdump -debug-names %t | FileCheck %s --check-prefix=DWARF
+
+# DWARF: .debug_names contents:
+# DWARF: Name Index @ 0x0 {
+# DWARF-NEXT: Header {
+# DWARF-NEXT: Length: 0xCC
+# DWARF-NEXT: Format: DWARF32
+# DWARF-NEXT: Version: 5
+# DWARF-NEXT: CU count: 2
+# DWARF-NEXT: Local TU count: 0
+# DWARF-NEXT: Foreign TU count: 0
+# DWARF-NEXT: Bucket count: 5
+# DWARF-NEXT: Name count: 5
+# DWARF-NEXT: Abbreviations table size: 0x1F
+# DWARF-NEXT: Augmentation: ' '
+# DWARF: Compilation Unit offsets [
+# DWARF-NEXT: CU[0]: 0x00000000
+# DWARF-NEXT: CU[1]: 0x00000041
+
+##
+## This file was generated by copying debug-names.s and manually
+## editing the 'Header: augmentation string' in the .debug_names section.
+##
+ .text
+ .globl _Z2f12t1 # -- Begin function _Z2f12t1
+ .p2align 4, 0x90
+ .type _Z2f12t1, at function
+_Z2f12t1: # @_Z2f12t1
+.Lfunc_begin0:
+ .cfi_startproc
+# %bb.0: # %entry
+ pushq %rbp
+ .cfi_def_cfa_offset 16
+ .cfi_offset %rbp, -16
+ movq %rsp, %rbp
+ .cfi_def_cfa_register %rbp
+.Ltmp0:
+ popq %rbp
+ .cfi_def_cfa %rsp, 8
+ retq
+.Ltmp1:
+.Lfunc_end0:
+ .size _Z2f12t1, .Lfunc_end0-_Z2f12t1
+ .cfi_endproc
+ # -- End function
+ .section .debug_abbrev,"", at progbits
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 0 # EOM(3)
+ .section .debug_info,"", at progbits
+.Lcu_begin0:
+ .long .Ldebug_info_end0-.Ldebug_info_start0 # Length of Unit
+.Ldebug_info_start0:
+ .short 5 # DWARF version number
+ .byte 1 # DWARF Unit Type
+ .byte 8 # Address Size (in bytes)
+ .long .debug_abbrev # Offset Into Abbrev. Section
+ .byte 1 # Abbrev [1] 0xc:0x35 DW_TAG_compile_unit
+ .byte 0 # DW_AT_producer
+ .short 33 # DW_AT_language
+ .byte 1 # DW_AT_name
+ .long .Lstr_offsets_base0 # DW_AT_str_offsets_base
+ .long .Lline_table_start0 # DW_AT_stmt_list
+ .byte 2 # DW_AT_comp_dir
+ .byte 0 # DW_AT_low_pc
+ .long .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc
+ .long .Laddr_table_base0 # DW_AT_addr_base
+ .byte 2 # Abbrev [2] 0x23:0x17 DW_TAG_subprogram
+ .byte 0 # DW_AT_low_pc
+ .long .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc
+ .byte 1 # DW_AT_frame_base
+ .byte 86
+ .byte 3 # DW_AT_linkage_name
+ .byte 4 # DW_AT_name
+ .byte 0 # DW_AT_decl_file
+ .byte 2 # DW_AT_decl_line
+ # DW_AT_external
+ .byte 3 # Abbrev [3] 0x2f:0xa DW_TAG_formal_parameter
+ .byte 2 # DW_AT_location
+ .byte 145
+ .byte 127
+ .byte 0 # DW_AT_decl_file
+ .byte 2 # DW_AT_decl_line
+ .long 58 # DW_AT_type
+ .byte 0 # End Of Children Mark
+ .byte 4 # Abbrev [4] 0x3a:0x6 DW_TAG_structure_type
+ .byte 5 # DW_AT_calling_convention
+ .byte 5 # DW_AT_name
+ .byte 1 # DW_AT_byte_size
+ .byte 0 # DW_AT_decl_file
+ .byte 1 # DW_AT_decl_line
+ .byte 0 # End Of Children Mark
+.Ldebug_info_end0:
+ .section .debug_str_offsets,"", at progbits
+ .long 28 # Length of String Offsets Set
+ .short 5
+ .short 0
+.Lstr_offsets_base0:
+ .section .debug_str,"MS", at progbits,1
+.Linfo_string0:
+ .asciz "clang version 19.0.0git (git at github.com:llvm/llvm-project.git 4df364bc93af49ae413ec1ae8328f34ac70730c4)" # string offset=0
+.Linfo_string1:
+ .asciz "debug-names.cpp" # string offset=104
+.Linfo_string2:
+ .asciz "debug-names-test" # string offset=120
+.Linfo_string3:
+ .asciz "f1" # string offset=137
+.Linfo_string4:
+ .asciz "_Z2f12t1" # string offset=140
+.Linfo_string5:
+ .asciz "t1" # string offset=149
+.Laddr_table_base0:
+ .quad .Lfunc_begin0
+.Ldebug_addr_end0:
+ .section .debug_names,"", at progbits
+ .long .Lnames_end0-.Lnames_start0 # Header: unit length
+.Lnames_start0:
+ .short 5 # Header: version
+ .short 0 # Header: padding
+ .long 1 # Header: compilation unit count
+ .long 0 # Header: local type unit count
+ .long 0 # Header: foreign type unit count
+ .long 3 # Header: bucket count
+ .long 3 # Header: name count
+ .long .Lnames_abbrev_end0-.Lnames_abbrev_start0 # Header: abbreviation table size
+ .long 8 # Header: augmentation string size
+ .ascii "JUNK1234" # Header: augmentation string
+ .long .Lcu_begin0 # Compilation unit 0
+ .long 0 # Bucket 0
+ .long 1 # Bucket 1
+ .long 3 # Bucket 2
+ .long 5863324 # Hash in Bucket 1
+ .long 5863786 # Hash in Bucket 1
+ .long 1398125246 # Hash in Bucket 2
+ .long .Linfo_string3 # String in Bucket 1: f1
+ .long .Linfo_string5 # String in Bucket 1: t1
+ .long .Linfo_string4 # String in Bucket 2: _Z2f12t1
+ .long .Lnames0-.Lnames_entries0 # Offset in Bucket 1
+ .long .Lnames2-.Lnames_entries0 # Offset in Bucket 1
+ .long .Lnames1-.Lnames_entries0 # Offset in Bucket 2
+.Lnames_abbrev_start0:
+ .byte 1 # Abbrev code
+ .byte 46 # DW_TAG_subprogram
+ .byte 3 # DW_IDX_die_offset
+ .byte 19 # DW_FORM_ref4
+ .byte 4 # DW_IDX_parent
+ .byte 25 # DW_FORM_flag_present
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev
+ .byte 2 # Abbrev code
+ .byte 19 # DW_TAG_structure_type
+ .byte 3 # DW_IDX_die_offset
+ .byte 19 # DW_FORM_ref4
+ .byte 4 # DW_IDX_parent
+ .byte 25 # DW_FORM_flag_present
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev list
+.Lnames_abbrev_end0:
+.Lnames_entries0:
+.Lnames0:
+.L1:
+ .byte 1 # Abbreviation code
+ .long 35 # DW_IDX_die_offset
+ .byte 0 # DW_IDX_parent
+ # End of list: f1
+.Lnames2:
+.L0:
+ .byte 2 # Abbreviation code
+ .long 58 # DW_IDX_die_offset
+ .byte 0 # DW_IDX_parent
+ # End of list: t1
+.Lnames1:
+ .byte 1 # Abbreviation code
+ .long 35 # DW_IDX_die_offset
+ .byte 0 # DW_IDX_parent
+ # End of list: _Z2f12t1
+ .p2align 2, 0x0
+.Lnames_end0:
+ .ident "clang version 19.0.0git (git at github.com:llvm/llvm-project.git 4df364bc93af49ae413ec1ae8328f34ac70730c4)"
+ .section ".note.GNU-stack","", at progbits
+ .addrsig
+ .section .debug_line,"", at progbits
+.Lline_table_start0:
diff --git a/lld/test/ELF/debug-names-bad-die-idx-sizes.s b/lld/test/ELF/debug-names-bad-die-idx-sizes.s
new file mode 100644
index 00000000000000..2da278a8dd5b7c
--- /dev/null
+++ b/lld/test/ELF/debug-names-bad-die-idx-sizes.s
@@ -0,0 +1,151 @@
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t1.o
+#
+# RUN: not ld.lld --debug-names %t1.o -o /dev/null 2>&1 | FileCheck %s
+#
+# CHECK: error: {{.*}}:(.debug_names): encountered unexpected end of section while reading entry
+
+## This file was generated by first compiling main.cpp:
+## clang++ -g -O0 -S -gpubnames -fdebug-compilation-dir='debug-names-test' \
+## main.cpp
+##
+## Then manually edit the .debug_names section. In the entries, change the
+## size of the DW_IDX_die_offset from '.long' to '.byte'.
+##
+## main.cpp:
+## int main (int argc, char **argv) { }
+##
+ .text
+ .globl main # -- Begin function main
+ .p2align 4, 0x90
+ .type main, at function
+main: # @main
+.Lfunc_begin0:
+ .cfi_startproc
+# %bb.0: # %entry
+ pushq %rbp
+ .cfi_def_cfa_offset 16
+ .cfi_offset %rbp, -16
+ movq %rsp, %rbp
+ .cfi_def_cfa_register %rbp
+ movl %edi, -4(%rbp)
+ movq %rsi, -16(%rbp)
+.Ltmp0:
+ xorl %eax, %eax
+ popq %rbp
+ .cfi_def_cfa %rsp, 8
+ retq
+.Ltmp1:
+.Lfunc_end0:
+ .size main, .Lfunc_end0-main
+ .cfi_endproc
+ # -- End function
+ .section .debug_abbrev,"", at progbits
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 0 # EOM(3)
+ .section .debug_info,"", at progbits
+.Lcu_begin0:
+ .long .Ldebug_info_end0-.Ldebug_info_start0 # Length of Unit
+.Ldebug_info_start0:
+ .short 5 # DWARF version number
+ .byte 1 # DWARF Unit Type
+ .byte 8 # Address Size (in bytes)
+ .long .debug_abbrev # Offset Into Abbrev. Section
+.Ldebug_info_end0:
+ .section .debug_str_offsets,"", at progbits
+ .long 36 # Length of String Offsets Set
+ .short 5
+ .short 0
+.Lstr_offsets_base0:
+ .section .debug_str,"MS", at progbits,1
+.Linfo_string0:
+ .asciz "clang version 19.0.0git (git at github.com:llvm/llvm-project.git d33d5630b281debe6eabd67e323bcf767340fb6a)" # string offset=0
+.Linfo_string1:
+ .asciz "main.cpp" # string offset=104
+.Linfo_string2:
+ .asciz "debug-names-test" # string offset=113
+.Linfo_string3:
+ .asciz "main" # string offset=130
+.Linfo_string4:
+ .asciz "int" # string offset=135
+.Linfo_string5:
+ .asciz "argc" # string offset=139
+.Linfo_string6:
+ .asciz "argv" # string offset=144
+.Linfo_string7:
+ .asciz "char" # string offset=149
+.Laddr_table_base0:
+ .quad .Lfunc_begin0
+.Ldebug_addr_end0:
+ .section .debug_names,"", at progbits
+ .long .Lnames_end0-.Lnames_start0 # Header: unit length
+.Lnames_start0:
+ .short 5 # Header: version
+ .short 0 # Header: padding
+ .long 1 # Header: compilation unit count
+ .long 0 # Header: local type unit count
+ .long 0 # Header: foreign type unit count
+ .long 3 # Header: bucket count
+ .long 3 # Header: name count
+ .long .Lnames_abbrev_end0-.Lnames_abbrev_start0 # Header: abbreviation table size
+ .long 8 # Header: augmentation string size
+ .ascii "LLVM0700" # Header: augmentation string
+ .long .Lcu_begin0 # Compilation unit 0
+ .long 0 # Bucket 0
+ .long 1 # Bucket 1
+ .long 2 # Bucket 2
+ .long 2090499946 # Hash in Bucket 1
+ .long 193495088 # Hash in Bucket 2
+ .long 2090147939 # Hash in Bucket 2
+ .long .Linfo_string3 # String in Bucket 1: main
+ .long .Linfo_string4 # String in Bucket 2: int
+ .long .Linfo_string7 # String in Bucket 2: char
+ .long .Lnames0-.Lnames_entries0 # Offset in Bucket 1
+ .long .Lnames1-.Lnames_entries0 # Offset in Bucket 2
+ .long .Lnames2-.Lnames_entries0 # Offset in Bucket 2
+.Lnames_abbrev_start0:
+ .byte 1 # Abbrev code
+ .byte 46 # DW_TAG_subprogram
+ .byte 3 # DW_IDX_die_offset
+ .byte 19 # DW_FORM_ref4
+ .byte 4 # DW_IDX_parent
+ .byte 25 # DW_FORM_flag_present
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev
+ .byte 2 # Abbrev code
+ .byte 36 # DW_TAG_base_type
+ .byte 3 # DW_IDX_die_offset
+ .byte 19 # DW_FORM_ref4
+ .byte 4 # DW_IDX_parent
+ .byte 25 # DW_FORM_flag_present
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev list
+.Lnames_abbrev_end0:
+.Lnames_entries0:
+.Lnames0:
+.L1:
+ .byte 1 # Abbreviation code
+ .byte 35 # DW_IDX_die_offset
+ .byte 0 # DW_IDX_parent
+ # End of list: main
+.Lnames1:
+.L0:
+ .byte 2 # Abbreviation code
+ .byte 73 # DW_IDX_die_offset
+ .byte 0 # DW_IDX_parent
+ # End of list: int
+.Lnames2:
+.L2:
+ .byte 2 # Abbreviation code
+ .byte 87 # DW_IDX_die_offset
+ .byte 0 # DW_IDX_parent
+ # End of list: char
+ .p2align 2, 0x0
+.Lnames_end0:
+ .ident "clang version 19.0.0git (git at github.com:llvm/llvm-project.git d33d5630b281debe6eabd67e323bcf767340fb6a)"
+ .section ".note.GNU-stack","", at progbits
+ .addrsig
+ .section .debug_line,"", at progbits
+.Lline_table_start0:
diff --git a/lld/test/ELF/debug-names-bad-name-count.s b/lld/test/ELF/debug-names-bad-name-count.s
new file mode 100644
index 00000000000000..4acfa182b11a91
--- /dev/null
+++ b/lld/test/ELF/debug-names-bad-name-count.s
@@ -0,0 +1,154 @@
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t1.o
+#
+# RUN: not ld.lld --debug-names %t1.o -o /dev/null 2>&1 | FileCheck %s
+#
+# CHECK: error: {{.*}}:(.debug_names): encountered unexpected end of section while reading entry
+# CHECK: error: {{.*}}:(.debug_names): encountered unexpected end of section while reading entry
+# CHECK: error: {{.*}}:(.debug_names): encountered unexpected end of section while reading entry
+# CHECK: error: {{.*}}:(.debug_names): encountered unexpected end of section while reading entry
+
+## This file was generated by first compiling main.cpp:
+## clang++ -g -O0 -S -gpubnames -fdebug-compilation-dir='debug-names-test' \
+## main.cpp
+##
+## Then manually edit .debug_names section: change value for
+## 'Header: name count' from 3 to 4.
+##
+## main.cpp:
+## int main (int argc, char **argv) { }
+##
+ .text
+ .globl main # -- Begin function main
+ .p2align 4, 0x90
+ .type main, at function
+main: # @main
+.Lfunc_begin0:
+ .cfi_startproc
+# %bb.0: # %entry
+ pushq %rbp
+ .cfi_def_cfa_offset 16
+ .cfi_offset %rbp, -16
+ movq %rsp, %rbp
+ .cfi_def_cfa_register %rbp
+ movl %edi, -4(%rbp)
+ movq %rsi, -16(%rbp)
+.Ltmp0:
+ xorl %eax, %eax
+ popq %rbp
+ .cfi_def_cfa %rsp, 8
+ retq
+.Ltmp1:
+.Lfunc_end0:
+ .size main, .Lfunc_end0-main
+ .cfi_endproc
+ # -- End function
+ .section .debug_abbrev,"", at progbits
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 0 # EOM(3)
+ .section .debug_info,"", at progbits
+.Lcu_begin0:
+ .long .Ldebug_info_end0-.Ldebug_info_start0 # Length of Unit
+.Ldebug_info_start0:
+ .short 5 # DWARF version number
+ .byte 1 # DWARF Unit Type
+ .byte 8 # Address Size (in bytes)
+ .long .debug_abbrev # Offset Into Abbrev. Section
+.Ldebug_info_end0:
+ .section .debug_str_offsets,"", at progbits
+ .long 36 # Length of String Offsets Set
+ .short 5
+ .short 0
+.Lstr_offsets_base0:
+ .section .debug_str,"MS", at progbits,1
+.Linfo_string0:
+ .asciz "clang version 19.0.0git (git at github.com:llvm/llvm-project.git d33d5630b281debe6eabd67e323bcf767340fb6a)" # string offset=0
+.Linfo_string1:
+ .asciz "main.cpp" # string offset=104
+.Linfo_string2:
+ .asciz "debug-names-test" # string offset=113
+.Linfo_string3:
+ .asciz "main" # string offset=130
+.Linfo_string4:
+ .asciz "int" # string offset=135
+.Linfo_string5:
+ .asciz "argc" # string offset=139
+.Linfo_string6:
+ .asciz "argv" # string offset=144
+.Linfo_string7:
+ .asciz "char" # string offset=149
+.Laddr_table_base0:
+ .quad .Lfunc_begin0
+.Ldebug_addr_end0:
+ .section .debug_names,"", at progbits
+ .long .Lnames_end0-.Lnames_start0 # Header: unit length
+.Lnames_start0:
+ .short 5 # Header: version
+ .short 0 # Header: padding
+ .long 1 # Header: compilation unit count
+ .long 0 # Header: local type unit count
+ .long 0 # Header: foreign type unit count
+ .long 3 # Header: bucket count
+ .long 4 # Header: name count
+ .long .Lnames_abbrev_end0-.Lnames_abbrev_start0 # Header: abbreviation table size
+ .long 8 # Header: augmentation string size
+ .ascii "LLVM0700" # Header: augmentation string
+ .long .Lcu_begin0 # Compilation unit 0
+ .long 0 # Bucket 0
+ .long 1 # Bucket 1
+ .long 2 # Bucket 2
+ .long 2090499946 # Hash in Bucket 1
+ .long 193495088 # Hash in Bucket 2
+ .long 2090147939 # Hash in Bucket 2
+ .long .Linfo_string3 # String in Bucket 1: main
+ .long .Linfo_string4 # String in Bucket 2: int
+ .long .Linfo_string7 # String in Bucket 2: char
+ .long .Lnames0-.Lnames_entries0 # Offset in Bucket 1
+ .long .Lnames1-.Lnames_entries0 # Offset in Bucket 2
+ .long .Lnames2-.Lnames_entries0 # Offset in Bucket 2
+.Lnames_abbrev_start0:
+ .byte 1 # Abbrev code
+ .byte 46 # DW_TAG_subprogram
+ .byte 3 # DW_IDX_die_offset
+ .byte 19 # DW_FORM_ref4
+ .byte 4 # DW_IDX_parent
+ .byte 25 # DW_FORM_flag_present
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev
+ .byte 2 # Abbrev code
+ .byte 36 # DW_TAG_base_type
+ .byte 3 # DW_IDX_die_offset
+ .byte 19 # DW_FORM_ref4
+ .byte 4 # DW_IDX_parent
+ .byte 25 # DW_FORM_flag_present
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev list
+.Lnames_abbrev_end0:
+.Lnames_entries0:
+.Lnames0:
+.L1:
+ .byte 1 # Abbreviation code
+ .long 35 # DW_IDX_die_offset
+ .byte 0 # DW_IDX_parent
+ # End of list: main
+.Lnames1:
+.L0:
+ .byte 2 # Abbreviation code
+ .long 73 # DW_IDX_die_offset
+ .byte 0 # DW_IDX_parent
+ # End of list: int
+.Lnames2:
+.L2:
+ .byte 2 # Abbreviation code
+ .long 87 # DW_IDX_die_offset
+ .byte 0 # DW_IDX_parent
+ # End of list: char
+ .p2align 2, 0x0
+.Lnames_end0:
+ .ident "clang version 19.0.0git (git at github.com:llvm/llvm-project.git d33d5630b281debe6eabd67e323bcf767340fb6a)"
+ .section ".note.GNU-stack","", at progbits
+ .addrsig
+ .section .debug_line,"", at progbits
+.Lline_table_start0:
diff --git a/lld/test/ELF/debug-names-bad-offsets-sizes.s b/lld/test/ELF/debug-names-bad-offsets-sizes.s
new file mode 100644
index 00000000000000..e11d19a9bf579c
--- /dev/null
+++ b/lld/test/ELF/debug-names-bad-offsets-sizes.s
@@ -0,0 +1,153 @@
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t1.o
+#
+# RUN: not ld.lld --debug-names %t1.o -o /dev/null 2>&1 | FileCheck %s
+#
+# CHECK: error: {{.*}}:(.debug_names): encountered unexpected end of section while reading entry
+# CHECK: error: {{.*}}:(.debug_names): encountered unexpected end of section while reading entry
+# CHECK: error: {{.*}}:(.debug_names): encountered unexpected end of section while reading entry
+
+## This file was generated by first compiling main.cpp:
+## clang++ -g -O0 -S -gpubnames -fdebug-compilation-dir='debug-names-test' \
+## main.cpp
+##
+## Then manually edit .debug_names section. Change the sizes of
+## 'Offset in Bucket' values from '.long' to '.byte'.
+##
+## main.cpp:
+## int main (int argc, char **argv) { }
+##
+ .text
+ .globl main # -- Begin function main
+ .p2align 4, 0x90
+ .type main, at function
+main: # @main
+.Lfunc_begin0:
+ .cfi_startproc
+# %bb.0: # %entry
+ pushq %rbp
+ .cfi_def_cfa_offset 16
+ .cfi_offset %rbp, -16
+ movq %rsp, %rbp
+ .cfi_def_cfa_register %rbp
+ movl %edi, -4(%rbp)
+ movq %rsi, -16(%rbp)
+.Ltmp0:
+ xorl %eax, %eax
+ popq %rbp
+ .cfi_def_cfa %rsp, 8
+ retq
+.Ltmp1:
+.Lfunc_end0:
+ .size main, .Lfunc_end0-main
+ .cfi_endproc
+ # -- End function
+ .section .debug_abbrev,"", at progbits
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 0 # EOM(3)
+ .section .debug_info,"", at progbits
+.Lcu_begin0:
+ .long .Ldebug_info_end0-.Ldebug_info_start0 # Length of Unit
+.Ldebug_info_start0:
+ .short 5 # DWARF version number
+ .byte 1 # DWARF Unit Type
+ .byte 8 # Address Size (in bytes)
+ .long .debug_abbrev # Offset Into Abbrev. Section
+.Ldebug_info_end0:
+ .section .debug_str_offsets,"", at progbits
+ .long 36 # Length of String Offsets Set
+ .short 5
+ .short 0
+.Lstr_offsets_base0:
+ .section .debug_str,"MS", at progbits,1
+.Linfo_string0:
+ .asciz "clang version 19.0.0git (git at github.com:llvm/llvm-project.git d33d5630b281debe6eabd67e323bcf767340fb6a)" # string offset=0
+.Linfo_string1:
+ .asciz "main.cpp" # string offset=104
+.Linfo_string2:
+ .asciz "debug-names-test" # string offset=113
+.Linfo_string3:
+ .asciz "main" # string offset=130
+.Linfo_string4:
+ .asciz "int" # string offset=135
+.Linfo_string5:
+ .asciz "argc" # string offset=139
+.Linfo_string6:
+ .asciz "argv" # string offset=144
+.Linfo_string7:
+ .asciz "char" # string offset=149
+.Laddr_table_base0:
+ .quad .Lfunc_begin0
+.Ldebug_addr_end0:
+ .section .debug_names,"", at progbits
+ .long .Lnames_end0-.Lnames_start0 # Header: unit length
+.Lnames_start0:
+ .short 5 # Header: version
+ .short 0 # Header: padding
+ .long 1 # Header: compilation unit count
+ .long 0 # Header: local type unit count
+ .long 0 # Header: foreign type unit count
+ .long 3 # Header: bucket count
+ .long 3 # Header: name count
+ .long .Lnames_abbrev_end0-.Lnames_abbrev_start0 # Header: abbreviation table size
+ .long 8 # Header: augmentation string size
+ .ascii "LLVM0700" # Header: augmentation string
+ .long .Lcu_begin0 # Compilation unit 0
+ .long 0 # Bucket 0
+ .long 1 # Bucket 1
+ .long 2 # Bucket 2
+ .long 2090499946 # Hash in Bucket 1
+ .long 193495088 # Hash in Bucket 2
+ .long 2090147939 # Hash in Bucket 2
+ .long .Linfo_string3 # String in Bucket 1: main
+ .long .Linfo_string4 # String in Bucket 2: int
+ .long .Linfo_string7 # String in Bucket 2: char
+ .byte .Lnames0-.Lnames_entries0 # Offset in Bucket 1
+ .byte .Lnames1-.Lnames_entries0 # Offset in Bucket 2
+ .byte .Lnames2-.Lnames_entries0 # Offset in Bucket 2
+.Lnames_abbrev_start0:
+ .byte 1 # Abbrev code
+ .byte 46 # DW_TAG_subprogram
+ .byte 3 # DW_IDX_die_offset
+ .byte 19 # DW_FORM_ref4
+ .byte 4 # DW_IDX_parent
+ .byte 25 # DW_FORM_flag_present
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev
+ .byte 2 # Abbrev code
+ .byte 36 # DW_TAG_base_type
+ .byte 3 # DW_IDX_die_offset
+ .byte 19 # DW_FORM_ref4
+ .byte 4 # DW_IDX_parent
+ .byte 25 # DW_FORM_flag_present
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev list
+.Lnames_abbrev_end0:
+.Lnames_entries0:
+.Lnames0:
+.L1:
+ .byte 1 # Abbreviation code
+ .long 35 # DW_IDX_die_offset
+ .byte 0 # DW_IDX_parent
+ # End of list: main
+.Lnames1:
+.L0:
+ .byte 2 # Abbreviation code
+ .long 73 # DW_IDX_die_offset
+ .byte 0 # DW_IDX_parent
+ # End of list: int
+.Lnames2:
+.L2:
+ .byte 2 # Abbreviation code
+ .long 87 # DW_IDX_die_offset
+ .byte 0 # DW_IDX_parent
+ # End of list: char
+ .p2align 2, 0x0
+.Lnames_end0:
+ .ident "clang version 19.0.0git (git at github.com:llvm/llvm-project.git d33d5630b281debe6eabd67e323bcf767340fb6a)"
+ .section ".note.GNU-stack","", at progbits
+ .addrsig
+ .section .debug_line,"", at progbits
+.Lline_table_start0:
diff --git a/lld/test/ELF/debug-names-bad-version.s b/lld/test/ELF/debug-names-bad-version.s
new file mode 100644
index 00000000000000..f3914670af94a5
--- /dev/null
+++ b/lld/test/ELF/debug-names-bad-version.s
@@ -0,0 +1,173 @@
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t1.o
+# RUN: llvm-mc -filetype=obj -triple=x86_64 %p/Inputs/debug-names-2.s -o %t2
+#
+# RUN: not ld.lld --debug-names %t1.o %t2.o -o /dev/null 2>&1 | FileCheck %s
+#
+# CHECK: error: {{.*}}:(.debug_names): unsupported version
+##
+## This file was generated by copying debug-names.s and manually
+## editing the 'Header: version' in the .debug_names section (changed it from
+## 5 to 4).
+
+ .text
+ .globl _Z2f12t1 # -- Begin function _Z2f12t1
+ .p2align 4, 0x90
+ .type _Z2f12t1, at function
+_Z2f12t1: # @_Z2f12t1
+.Lfunc_begin0:
+ .cfi_startproc
+# %bb.0: # %entry
+ pushq %rbp
+ .cfi_def_cfa_offset 16
+ .cfi_offset %rbp, -16
+ movq %rsp, %rbp
+ .cfi_def_cfa_register %rbp
+.Ltmp0:
+ popq %rbp
+ .cfi_def_cfa %rsp, 8
+ retq
+.Ltmp1:
+.Lfunc_end0:
+ .size _Z2f12t1, .Lfunc_end0-_Z2f12t1
+ .cfi_endproc
+ # -- End function
+ .section .debug_abbrev,"", at progbits
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 0 # EOM(3)
+ .section .debug_info,"", at progbits
+.Lcu_begin0:
+ .long .Ldebug_info_end0-.Ldebug_info_start0 # Length of Unit
+.Ldebug_info_start0:
+ .short 5 # DWARF version number
+ .byte 1 # DWARF Unit Type
+ .byte 8 # Address Size (in bytes)
+ .long .debug_abbrev # Offset Into Abbrev. Section
+ .byte 1 # Abbrev [1] 0xc:0x35 DW_TAG_compile_unit
+ .byte 0 # DW_AT_producer
+ .short 33 # DW_AT_language
+ .byte 1 # DW_AT_name
+ .long .Lstr_offsets_base0 # DW_AT_str_offsets_base
+ .long .Lline_table_start0 # DW_AT_stmt_list
+ .byte 2 # DW_AT_comp_dir
+ .byte 0 # DW_AT_low_pc
+ .long .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc
+ .long .Laddr_table_base0 # DW_AT_addr_base
+ .byte 2 # Abbrev [2] 0x23:0x17 DW_TAG_subprogram
+ .byte 0 # DW_AT_low_pc
+ .long .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc
+ .byte 1 # DW_AT_frame_base
+ .byte 86
+ .byte 3 # DW_AT_linkage_name
+ .byte 4 # DW_AT_name
+ .byte 0 # DW_AT_decl_file
+ .byte 2 # DW_AT_decl_line
+ # DW_AT_external
+ .byte 3 # Abbrev [3] 0x2f:0xa DW_TAG_formal_parameter
+ .byte 2 # DW_AT_location
+ .byte 145
+ .byte 127
+ .byte 0 # DW_AT_decl_file
+ .byte 2 # DW_AT_decl_line
+ .long 58 # DW_AT_type
+ .byte 0 # End Of Children Mark
+ .byte 4 # Abbrev [4] 0x3a:0x6 DW_TAG_structure_type
+ .byte 5 # DW_AT_calling_convention
+ .byte 5 # DW_AT_name
+ .byte 1 # DW_AT_byte_size
+ .byte 0 # DW_AT_decl_file
+ .byte 1 # DW_AT_decl_line
+ .byte 0 # End Of Children Mark
+.Ldebug_info_end0:
+ .section .debug_str_offsets,"", at progbits
+ .long 28 # Length of String Offsets Set
+ .short 5
+ .short 0
+.Lstr_offsets_base0:
+ .section .debug_str,"MS", at progbits,1
+.Linfo_string0:
+ .asciz "clang version 19.0.0git (git at github.com:llvm/llvm-project.git 4df364bc93af49ae413ec1ae8328f34ac70730c4)" # string offset=0
+.Linfo_string1:
+ .asciz "debug-names.cpp" # string offset=104
+.Linfo_string2:
+ .asciz "debug-names-test" # string offset=120
+.Linfo_string3:
+ .asciz "f1" # string offset=137
+.Linfo_string4:
+ .asciz "_Z2f12t1" # string offset=140
+.Linfo_string5:
+ .asciz "t1" # string offset=149
+.Laddr_table_base0:
+ .quad .Lfunc_begin0
+.Ldebug_addr_end0:
+ .section .debug_names,"", at progbits
+ .long .Lnames_end0-.Lnames_start0 # Header: unit length
+.Lnames_start0:
+ .short 4 # Header: version
+ .short 0 # Header: padding
+ .long 1 # Header: compilation unit count
+ .long 0 # Header: local type unit count
+ .long 0 # Header: foreign type unit count
+ .long 3 # Header: bucket count
+ .long 3 # Header: name count
+ .long .Lnames_abbrev_end0-.Lnames_abbrev_start0 # Header: abbreviation table size
+ .long 8 # Header: augmentation string size
+ .ascii "LLVM0700" # Header: augmentation string
+ .long .Lcu_begin0 # Compilation unit 0
+ .long 0 # Bucket 0
+ .long 1 # Bucket 1
+ .long 3 # Bucket 2
+ .long 5863324 # Hash in Bucket 1
+ .long 5863786 # Hash in Bucket 1
+ .long 1398125246 # Hash in Bucket 2
+ .long .Linfo_string3 # String in Bucket 1: f1
+ .long .Linfo_string5 # String in Bucket 1: t1
+ .long .Linfo_string4 # String in Bucket 2: _Z2f12t1
+ .long .Lnames0-.Lnames_entries0 # Offset in Bucket 1
+ .long .Lnames2-.Lnames_entries0 # Offset in Bucket 1
+ .long .Lnames1-.Lnames_entries0 # Offset in Bucket 2
+.Lnames_abbrev_start0:
+ .byte 1 # Abbrev code
+ .byte 46 # DW_TAG_subprogram
+ .byte 3 # DW_IDX_die_offset
+ .byte 19 # DW_FORM_ref4
+ .byte 4 # DW_IDX_parent
+ .byte 25 # DW_FORM_flag_present
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev
+ .byte 2 # Abbrev code
+ .byte 19 # DW_TAG_structure_type
+ .byte 3 # DW_IDX_die_offset
+ .byte 19 # DW_FORM_ref4
+ .byte 4 # DW_IDX_parent
+ .byte 25 # DW_FORM_flag_present
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev list
+.Lnames_abbrev_end0:
+.Lnames_entries0:
+.Lnames0:
+.L1:
+ .byte 1 # Abbreviation code
+ .long 35 # DW_IDX_die_offset
+ .byte 0 # DW_IDX_parent
+ # End of list: f1
+.Lnames2:
+.L0:
+ .byte 2 # Abbreviation code
+ .long 58 # DW_IDX_die_offset
+ .byte 0 # DW_IDX_parent
+ # End of list: t1
+.Lnames1:
+ .byte 1 # Abbreviation code
+ .long 35 # DW_IDX_die_offset
+ .byte 0 # DW_IDX_parent
+ # End of list: _Z2f12t1
+ .p2align 2, 0x0
+.Lnames_end0:
+ .ident "clang version 19.0.0git (git at github.com:llvm/llvm-project.git 4df364bc93af49ae413ec1ae8328f34ac70730c4)"
+ .section ".note.GNU-stack","", at progbits
+ .addrsig
+ .section .debug_line,"", at progbits
+.Lline_table_start0:
diff --git a/lld/test/ELF/debug-names-invalid-attribute.s b/lld/test/ELF/debug-names-invalid-attribute.s
new file mode 100644
index 00000000000000..9b1a915d81f882
--- /dev/null
+++ b/lld/test/ELF/debug-names-invalid-attribute.s
@@ -0,0 +1,179 @@
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t1.o
+#
+# RUN: not ld.lld --debug-names %t1.o -o /dev/null 2>&1 | FileCheck %s
+#
+# CHECK: error: {{.*}}:(.debug_names): unrecognized form encoding 16 in .debug_names abbrev table
+##
+## Generated by copying debug-names.s and manually editing it to make some
+## of the abbrev attributes invalid.
+
+ .text
+ .globl _Z2f12t1 # -- Begin function _Z2f12t1
+ .p2align 4, 0x90
+ .type _Z2f12t1, at function
+_Z2f12t1: # @_Z2f12t1
+.Lfunc_begin0:
+ .cfi_startproc
+# %bb.0: # %entry
+ pushq %rbp
+ .cfi_def_cfa_offset 16
+ .cfi_offset %rbp, -16
+ movq %rsp, %rbp
+ .cfi_def_cfa_register %rbp
+.Ltmp0:
+ popq %rbp
+ .cfi_def_cfa %rsp, 8
+ retq
+.Ltmp1:
+.Lfunc_end0:
+ .size _Z2f12t1, .Lfunc_end0-_Z2f12t1
+ .cfi_endproc
+ # -- End function
+ .section .debug_abbrev,"", at progbits
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 0 # EOM(3)
+ .section .debug_info,"", at progbits
+.Lcu_begin0:
+ .long .Ldebug_info_end0-.Ldebug_info_start0 # Length of Unit
+.Ldebug_info_start0:
+ .short 5 # DWARF version number
+ .byte 1 # DWARF Unit Type
+ .byte 8 # Address Size (in bytes)
+ .long .debug_abbrev # Offset Into Abbrev. Section
+ .byte 1 # Abbrev [1] 0xc:0x35 DW_TAG_compile_unit
+ .byte 0 # DW_AT_producer
+ .short 33 # DW_AT_language
+ .byte 1 # DW_AT_name
+ .long .Lstr_offsets_base0 # DW_AT_str_offsets_base
+ .long .Lline_table_start0 # DW_AT_stmt_list
+ .byte 2 # DW_AT_comp_dir
+ .byte 0 # DW_AT_low_pc
+ .long .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc
+ .long .Laddr_table_base0 # DW_AT_addr_base
+ .byte 2 # Abbrev [2] 0x23:0x17 DW_TAG_subprogram
+ .byte 0 # DW_AT_low_pc
+ .long .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc
+ .byte 1 # DW_AT_frame_base
+ .byte 86
+ .byte 3 # DW_AT_linkage_name
+ .byte 4 # DW_AT_name
+ .byte 0 # DW_AT_decl_file
+ .byte 2 # DW_AT_decl_line
+ # DW_AT_external
+ .byte 3 # Abbrev [3] 0x2f:0xa DW_TAG_formal_parameter
+ .byte 2 # DW_AT_location
+ .byte 145
+ .byte 127
+ .byte 0 # DW_AT_decl_file
+ .byte 2 # DW_AT_decl_line
+ .long 58 # DW_AT_type
+ .byte 0 # End Of Children Mark
+ .byte 4 # Abbrev [4] 0x3a:0x6 DW_TAG_structure_type
+ .byte 5 # DW_AT_calling_convention
+ .byte 5 # DW_AT_name
+ .byte 1 # DW_AT_byte_size
+ .byte 0 # DW_AT_decl_file
+ .byte 1 # DW_AT_decl_line
+ .byte 0 # End Of Children Mark
+.Ldebug_info_end0:
+ .section .debug_str_offsets,"", at progbits
+ .long 28 # Length of String Offsets Set
+ .short 5
+ .short 0
+.Lstr_offsets_base0:
+ .section .debug_str,"MS", at progbits,1
+.Linfo_string0:
+ .asciz "clang version 19.0.0git (git at github.com:llvm/llvm-project.git 4df364bc93af49ae413ec1ae8328f34ac70730c4)" # string offset=0
+.Linfo_string1:
+ .asciz "debug-names.cpp" # string offset=104
+.Linfo_string2:
+ .asciz "debug-names-test" # string offset=120
+.Linfo_string3:
+ .asciz "f1" # string offset=137
+.Linfo_string4:
+ .asciz "_Z2f12t1" # string offset=140
+.Linfo_string5:
+ .asciz "t1" # string offset=149
+.Laddr_table_base0:
+ .quad .Lfunc_begin0
+.Ldebug_addr_end0:
+ .section .debug_names,"", at progbits
+ .long .Lnames_end0-.Lnames_start0 # Header: unit length
+.Lnames_start0:
+ .short 5 # Header: version
+ .short 0 # Header: padding
+ .long 1 # Header: compilation unit count
+ .long 0 # Header: local type unit count
+ .long 0 # Header: foreign type unit count
+ .long 3 # Header: bucket count
+ .long 3 # Header: name count
+ .long .Lnames_abbrev_end0-.Lnames_abbrev_start0 # Header: abbreviation table size
+ .long 8 # Header: augmentation string size
+ .ascii "LLVM0700" # Header: augmentation string
+ .long .Lcu_begin0 # Compilation unit 0
+ .long 0 # Bucket 0
+ .long 1 # Bucket 1
+ .long 3 # Bucket 2
+ .long 5863324 # Hash in Bucket 1
+ .long 5863786 # Hash in Bucket 1
+ .long 1398125246 # Hash in Bucket 2
+ .long .Linfo_string3 # String in Bucket 1: f1
+ .long .Linfo_string5 # String in Bucket 1: t1
+ .long .Linfo_string4 # String in Bucket 2: _Z2f12t1
+ .long .Lnames0-.Lnames_entries0 # Offset in Bucket 1
+ .long .Lnames2-.Lnames_entries0 # Offset in Bucket 1
+ .long .Lnames1-.Lnames_entries0 # Offset in Bucket 2
+.Lnames_abbrev_start0:
+ .byte 1 # Abbrev code
+ .byte 46 # DW_TAG_subprogram
+ .byte 3 # DW_IDX_die_offset
+ .byte 19 # DW_FORM_ref4
+ .byte 4 # DW_IDX_parent
+ .byte 25 # DW_FORM_flag_present
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev
+ .byte 2 # Abbrev code
+ .byte 19 # DW_TAG_structure_type
+ .byte 3 # DW_IDX_die_offset
+ .byte 19 # DW_FORM_ref4
+ .byte 4 # DW_IDX_parent
+ .byte 25 # DW_FORM_flag_present
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev
+ .byte 3 # Abbrev code
+ .byte 19 # DW_TAG_structure_type
+ .byte 3 # DW_IDX_die_offset
+ .byte 16 # DW_FORM_ref_addr
+ .byte 7 # DW_IDX_unknown
+ .byte 25 # DW_FORM_flag_present
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev list
+.Lnames_abbrev_end0:
+.Lnames_entries0:
+.Lnames0:
+.L1:
+ .byte 1 # Abbreviation code
+ .long 35 # DW_IDX_die_offset
+ .byte 0 # DW_IDX_parent
+ # End of list: f1
+.Lnames2:
+.L0:
+ .byte 2 # Abbreviation code
+ .long 58 # DW_IDX_die_offset
+ .byte 0 # DW_IDX_parent
+ # End of list: t1
+.Lnames1:
+ .byte 3 # Abbreviation code
+ .long 35 # DW_IDX_die_offset
+ .byte 0 # DW_IDX_parent
+ # End of list: _Z2f12t1
+ .p2align 2, 0x0
+.Lnames_end0:
+ .ident "clang version 19.0.0git (git at github.com:llvm/llvm-project.git 4df364bc93af49ae413ec1ae8328f34ac70730c4)"
+ .section ".note.GNU-stack","", at progbits
+ .addrsig
+ .section .debug_line,"", at progbits
+.Lline_table_start0:
diff --git a/lld/test/ELF/debug-names-parent-idx.s b/lld/test/ELF/debug-names-parent-idx.s
new file mode 100644
index 00000000000000..a4e8682cd9ee58
--- /dev/null
+++ b/lld/test/ELF/debug-names-parent-idx.s
@@ -0,0 +1,549 @@
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t1.o
+# RUN: llvm-mc -filetype=obj -triple=x86_64 %p/Inputs/debug-names-parent-idx-2.s -o %t2.o
+# RUN: ld.lld --debug-names %t1.o %t2.o -o %t
+
+# RUN: llvm-dwarfdump -debug-names %t | FileCheck %s --check-prefix=DWARF
+
+# DWARF: .debug_names contents:
+# DWARF: Name Index @ 0x0 {
+# DWARF-NEXT: Header {
+# DWARF-NEXT: Length: 0x15C
+# DWARF-NEXT: Format: DWARF32
+# DWARF-NEXT: Version: 5
+# DWARF-NEXT: CU count: 2
+# DWARF-NEXT: Local TU count: 0
+# DWARF-NEXT: Foreign TU count: 0
+# DWARF-NEXT: Bucket count: 9
+# DWARF-NEXT: Name count: 9
+# DWARF-NEXT: Abbreviations table size: 0x33
+# DWARF-NEXT: Augmentation: 'LLVM0700'
+# DWARF: Compilation Unit offsets [
+# DWARF-NEXT: CU[0]: 0x00000000
+# DWARF-NEXT: CU[1]: 0x000000cc
+# DWARF: Abbreviations [
+# DWARF-NEXT: Abbreviation 0x1 {
+# DWARF-NEXT: Tag: DW_TAG_base_type
+# DWARF-NEXT: DW_IDX_die_offset: DW_FORM_ref4
+# DWARF-NEXT: DW_IDX_parent: DW_FORM_flag_present
+# DWARF-NEXT: DW_IDX_compile_unit: DW_FORM_data1
+# DWARF: Abbreviation 0x2 {
+# DWARF-NEXT: Tag: DW_TAG_subprogram
+# DWARF-NEXT: DW_IDX_die_offset: DW_FORM_ref4
+# DWARF-NEXT: DW_IDX_parent: DW_FORM_flag_present
+# DWARF-NEXT: DW_IDX_compile_unit: DW_FORM_data1
+# DWARF: Abbreviation 0x3 {
+# DWARF-NEXT: Tag: DW_TAG_structure_type
+# DWARF-NEXT: DW_IDX_die_offset: DW_FORM_ref4
+# DWARF-NEXT: DW_IDX_parent: DW_FORM_flag_present
+# DWARF-NEXT: DW_IDX_compile_unit: DW_FORM_data1
+# DWARF: Abbreviation 0x4 {
+# DWARF-NEXT: Tag: DW_TAG_subprogram
+# DWARF-NEXT: DW_IDX_die_offset: DW_FORM_ref4
+# DWARF-NEXT: DW_IDX_parent: DW_FORM_ref4
+# DWARF-NEXT: DW_IDX_compile_unit: DW_FORM_data1
+# DWARF: Abbreviation 0x5 {
+# DWARF-NEXT: Tag: DW_TAG_namespace
+# DWARF-NEXT: DW_IDX_die_offset: DW_FORM_ref4
+# DWARF-NEXT: DW_IDX_parent: DW_FORM_flag_present
+# DWARF-NEXT: DW_IDX_compile_unit: DW_FORM_data1
+# DWARF: String: 0x00000093 "bar"
+# DWARF-NEXT: Entry @ 0xf7 {
+# DWARF-NEXT: Abbrev: 0x2
+# DWARF-NEXT: Tag: DW_TAG_subprogram
+# DWARF-NEXT: DW_IDX_die_offset: 0x00000023
+# DWARF-NEXT: DW_IDX_parent: <parent not indexed>
+# DWARF-NEXT: DW_IDX_compile_unit: 0x00
+# DWARF: String: 0x000000a9 "int"
+# DWARF-NEXT: Entry @ 0xfe {
+# DWARF-NEXT: Abbrev: 0x1
+# DWARF-NEXT: Tag: DW_TAG_base_type
+# DWARF-NEXT: DW_IDX_die_offset: 0x0000008d
+# DWARF-NEXT: DW_IDX_parent: <parent not indexed>
+# DWARF-NEXT: DW_IDX_compile_unit: 0x00
+# DWARF-NEXT: }
+# DWARF-NEXT: Entry @ 0x104 {
+# DWARF-NEXT: Abbrev: 0x1
+# DWARF-NEXT: Tag: DW_TAG_base_type
+# DWARF-NEXT: DW_IDX_die_offset: 0x00000023
+# DWARF-NEXT: DW_IDX_parent: <parent not indexed>
+# DWARF-NEXT: DW_IDX_compile_unit: 0x01
+# DWARF: String: 0x000000ad "foo"
+# DWARF-NEXT: Entry @ 0x10b {
+# DWARF-NEXT: Abbrev: 0x3
+# DWARF-NEXT: Tag: DW_TAG_structure_type
+# DWARF-NEXT: DW_IDX_die_offset: 0x00000096
+# DWARF-NEXT: DW_IDX_parent: <parent not indexed>
+# DWARF-NEXT: DW_IDX_compile_unit: 0x00
+# DWARF-NEXT: }
+# DWARF-NEXT: Entry @ 0x111 {
+# DWARF-NEXT: Abbrev: 0x2
+# DWARF-NEXT: Tag: DW_TAG_subprogram
+# DWARF-NEXT: DW_IDX_die_offset: 0x00000027
+# DWARF-NEXT: DW_IDX_parent: <parent not indexed>
+# DWARF-NEXT: DW_IDX_compile_unit: 0x01
+# DWARF-NEXT: }
+# DWARF-NEXT: Entry @ 0x117 {
+# DWARF-NEXT: Abbrev: 0x4
+# DWARF-NEXT: Tag: DW_TAG_subprogram
+# DWARF-NEXT: DW_IDX_die_offset: 0x00000045
+# DWARF-NEXT: DW_IDX_parent: Entry @ 0x128
+# DWARF-NEXT: DW_IDX_compile_unit: 0x01
+# DWARF-NEXT: }
+# DWARF-NEXT: Entry @ 0x121 {
+# DWARF-NEXT: Abbrev: 0x3
+# DWARF-NEXT: Tag: DW_TAG_structure_type
+# DWARF-NEXT: DW_IDX_die_offset: 0x00000056
+# DWARF-NEXT: DW_IDX_parent: <parent not indexed>
+# DWARF-NEXT: DW_IDX_compile_unit: 0x01
+# DWARF: String: 0x00000196 "parent_test"
+# DWARF-NEXT: Entry @ 0x128 {
+# DWARF-NEXT: Abbrev: 0x5
+# DWARF-NEXT: Tag: DW_TAG_namespace
+# DWARF-NEXT: DW_IDX_die_offset: 0x00000043
+# DWARF-NEXT: DW_IDX_parent: <parent not indexed>
+# DWARF-NEXT: DW_IDX_compile_unit: 0x01
+# DWARF: String: 0x00000097 "_Z3barR3fooi"
+# DWARF-NEXT: Entry @ 0x12f {
+# DWARF-NEXT: Abbrev: 0x2
+# DWARF-NEXT: Tag: DW_TAG_subprogram
+# DWARF-NEXT: DW_IDX_die_offset: 0x00000023
+# DWARF-NEXT: DW_IDX_parent: <parent not indexed>
+# DWARF-NEXT: DW_IDX_compile_unit: 0x00
+# DWARF: String: 0x000000a4 "main"
+# DWARF-NEXT: Entry @ 0x136 {
+# DWARF-NEXT: Abbrev: 0x2
+# DWARF-NEXT: Tag: DW_TAG_subprogram
+# DWARF-NEXT: DW_IDX_die_offset: 0x00000046
+# DWARF-NEXT: DW_IDX_parent: <parent not indexed>
+# DWARF-NEXT: DW_IDX_compile_unit: 0x00
+# DWARF: String: 0x000000b5 "char"
+# DWARF-NEXT: Entry @ 0x13d {
+# DWARF-NEXT: Abbrev: 0x1
+# DWARF-NEXT: Tag: DW_TAG_base_type
+# DWARF-NEXT: DW_IDX_die_offset: 0x000000b8
+# DWARF-NEXT: DW_IDX_parent: <parent not indexed>
+# DWARF-NEXT: DW_IDX_compile_unit: 0x00
+# DWARF-NEXT: }
+# DWARF-NEXT: Entry @ 0x143 {
+# DWARF-NEXT: Abbrev: 0x1
+# DWARF-NEXT: Tag: DW_TAG_base_type
+# DWARF-NEXT: DW_IDX_die_offset: 0x00000078
+# DWARF-NEXT: DW_IDX_parent: <parent not indexed>
+# DWARF-NEXT: DW_IDX_compile_unit: 0x01
+# DWARF: String: 0x000001a2 "_ZN11parent_test3fooEv"
+# DWARF-NEXT: Entry @ 0x14a {
+# DWARF-NEXT: Abbrev: 0x4
+# DWARF-NEXT: Tag: DW_TAG_subprogram
+# DWARF-NEXT: DW_IDX_die_offset: 0x00000045
+# DWARF-NEXT: DW_IDX_parent: Entry @ 0x128
+# DWARF-NEXT: DW_IDX_compile_unit: 0x01
+# DWARF: String: 0x0000018e "_Z3foov"
+# DWARF-NEXT: Entry @ 0x155 {
+# DWARF-NEXT: Abbrev: 0x2
+# DWARF-NEXT: Tag: DW_TAG_subprogram
+# DWARF-NEXT: DW_IDX_die_offset: 0x00000027
+# DWARF-NEXT: DW_IDX_parent: <parent not indexed>
+# DWARF-NEXT: DW_IDX_compile_unit: 0x01
+
+#-- input file: debug-names-parent-idx.cpp
+## Generated with:
+##
+## - clang++ -g -O0 -gpubnames -fdebug-compilation-dir='parent-idx-test' \
+## -S debug-names-parent-idx.cpp -o debug-names-parent-idx.s
+##
+## foo.h contents:
+##
+## int foo();
+##
+## struct foo {
+## int x;
+## char y;
+## struct foo *foo_ptr;
+## };
+##
+## namespace parent_test {
+## int foo();
+## }
+##
+## debug-names-parent-idx.cpp contents:
+##
+## #include "foo.h"
+## void bar (struct foo &foo, int junk) {
+## foo.x = foo.x * junk;
+## }
+## int main (int argc, char** argv) {
+## struct foo my_struct;
+## my_struct.x = 10;
+## my_struct.y = 'q';
+## my_struct.foo_ptr = nullptr;
+## int junk = foo();
+## bar(my_struct, junk);
+## int junk2 = parent_test::foo();
+## return 0;
+## }
+##
+ .text
+ .globl _Z3barR3fooi # -- Begin function _Z3barR3fooi
+ .p2align 4, 0x90
+ .type _Z3barR3fooi, at function
+_Z3barR3fooi: # @_Z3barR3fooi
+.Lfunc_begin0:
+ .cfi_startproc
+# %bb.0: # %entry
+ pushq %rbp
+ .cfi_def_cfa_offset 16
+ .cfi_offset %rbp, -16
+ movq %rsp, %rbp
+ .cfi_def_cfa_register %rbp
+ movq %rdi, -8(%rbp)
+ movl %esi, -12(%rbp)
+.Ltmp0:
+ movq -8(%rbp), %rax
+ movl (%rax), %ecx
+ imull -12(%rbp), %ecx
+ movq -8(%rbp), %rax
+ movl %ecx, (%rax)
+ popq %rbp
+ .cfi_def_cfa %rsp, 8
+ retq
+.Ltmp1:
+.Lfunc_end0:
+ .size _Z3barR3fooi, .Lfunc_end0-_Z3barR3fooi
+ .cfi_endproc
+ # -- End function
+ .globl main # -- Begin function main
+ .p2align 4, 0x90
+ .type main, at function
+main: # @main
+.Lfunc_begin1:
+ .cfi_startproc
+# %bb.0: # %entry
+ pushq %rbp
+ .cfi_def_cfa_offset 16
+ .cfi_offset %rbp, -16
+ movq %rsp, %rbp
+ .cfi_def_cfa_register %rbp
+ subq $48, %rsp
+ movl $0, -4(%rbp)
+ movl %edi, -8(%rbp)
+ movq %rsi, -16(%rbp)
+.Ltmp2:
+ movl $10, -32(%rbp)
+ movb $113, -28(%rbp)
+ movq $0, -24(%rbp)
+ callq _Z3foov at PLT
+ movl %eax, -36(%rbp)
+ movl -36(%rbp), %esi
+ leaq -32(%rbp), %rdi
+ callq _Z3barR3fooi
+ callq _ZN11parent_test3fooEv at PLT
+ movl %eax, -40(%rbp)
+ xorl %eax, %eax
+ addq $48, %rsp
+ popq %rbp
+ .cfi_def_cfa %rsp, 8
+ retq
+.Ltmp3:
+.Lfunc_end1:
+ .size main, .Lfunc_end1-main
+ .cfi_endproc
+ # -- End function
+ .section .debug_abbrev,"", at progbits
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 0 # EOM(3)
+ .section .debug_info,"", at progbits
+.Lcu_begin0:
+ .long .Ldebug_info_end0-.Ldebug_info_start0 # Length of Unit
+.Ldebug_info_start0:
+ .short 5 # DWARF version number
+ .byte 1 # DWARF Unit Type
+ .byte 8 # Address Size (in bytes)
+ .long .debug_abbrev # Offset Into Abbrev. Section
+ .byte 1 # Abbrev [1] 0xc:0xc0 DW_TAG_compile_unit
+ .byte 0 # DW_AT_producer
+ .short 33 # DW_AT_language
+ .byte 1 # DW_AT_name
+ .long .Lstr_offsets_base0 # DW_AT_str_offsets_base
+ .long .Lline_table_start0 # DW_AT_stmt_list
+ .byte 2 # DW_AT_comp_dir
+ .byte 0 # DW_AT_low_pc
+ .long .Lfunc_end1-.Lfunc_begin0 # DW_AT_high_pc
+ .long .Laddr_table_base0 # DW_AT_addr_base
+ .byte 2 # Abbrev [2] 0x23:0x23 DW_TAG_subprogram
+ .byte 0 # DW_AT_low_pc
+ .long .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc
+ .byte 1 # DW_AT_frame_base
+ .byte 86
+ .byte 3 # DW_AT_linkage_name
+ .byte 4 # DW_AT_name
+ .byte 0 # DW_AT_decl_file
+ .byte 3 # DW_AT_decl_line
+ # DW_AT_external
+ .byte 3 # Abbrev [3] 0x2f:0xb DW_TAG_formal_parameter
+ .byte 2 # DW_AT_location
+ .byte 145
+ .byte 120
+ .byte 7 # DW_AT_name
+ .byte 0 # DW_AT_decl_file
+ .byte 3 # DW_AT_decl_line
+ .long 145 # DW_AT_type
+ .byte 3 # Abbrev [3] 0x3a:0xb DW_TAG_formal_parameter
+ .byte 2 # DW_AT_location
+ .byte 145
+ .byte 116
+ .byte 12 # DW_AT_name
+ .byte 0 # DW_AT_decl_file
+ .byte 3 # DW_AT_decl_line
+ .long 141 # DW_AT_type
+ .byte 0 # End Of Children Mark
+ .byte 4 # Abbrev [4] 0x46:0x47 DW_TAG_subprogram
+ .byte 1 # DW_AT_low_pc
+ .long .Lfunc_end1-.Lfunc_begin1 # DW_AT_high_pc
+ .byte 1 # DW_AT_frame_base
+ .byte 86
+ .byte 5 # DW_AT_name
+ .byte 0 # DW_AT_decl_file
+ .byte 7 # DW_AT_decl_line
+ .long 141 # DW_AT_type
+ # DW_AT_external
+ .byte 3 # Abbrev [3] 0x55:0xb DW_TAG_formal_parameter
+ .byte 2 # DW_AT_location
+ .byte 145
+ .byte 120
+ .byte 13 # DW_AT_name
+ .byte 0 # DW_AT_decl_file
+ .byte 7 # DW_AT_decl_line
+ .long 141 # DW_AT_type
+ .byte 3 # Abbrev [3] 0x60:0xb DW_TAG_formal_parameter
+ .byte 2 # DW_AT_location
+ .byte 145
+ .byte 112
+ .byte 14 # DW_AT_name
+ .byte 0 # DW_AT_decl_file
+ .byte 7 # DW_AT_decl_line
+ .long 193 # DW_AT_type
+ .byte 5 # Abbrev [5] 0x6b:0xb DW_TAG_variable
+ .byte 2 # DW_AT_location
+ .byte 145
+ .byte 96
+ .byte 15 # DW_AT_name
+ .byte 0 # DW_AT_decl_file
+ .byte 9 # DW_AT_decl_line
+ .long 150 # DW_AT_type
+ .byte 5 # Abbrev [5] 0x76:0xb DW_TAG_variable
+ .byte 2 # DW_AT_location
+ .byte 145
+ .byte 92
+ .byte 12 # DW_AT_name
+ .byte 0 # DW_AT_decl_file
+ .byte 14 # DW_AT_decl_line
+ .long 141 # DW_AT_type
+ .byte 5 # Abbrev [5] 0x81:0xb DW_TAG_variable
+ .byte 2 # DW_AT_location
+ .byte 145
+ .byte 88
+ .byte 16 # DW_AT_name
+ .byte 0 # DW_AT_decl_file
+ .byte 16 # DW_AT_decl_line
+ .long 141 # DW_AT_type
+ .byte 0 # End Of Children Mark
+ .byte 6 # Abbrev [6] 0x8d:0x4 DW_TAG_base_type
+ .byte 6 # DW_AT_name
+ .byte 5 # DW_AT_encoding
+ .byte 4 # DW_AT_byte_size
+ .byte 7 # Abbrev [7] 0x91:0x5 DW_TAG_reference_type
+ .long 150 # DW_AT_type
+ .byte 8 # Abbrev [8] 0x96:0x22 DW_TAG_structure_type
+ .byte 5 # DW_AT_calling_convention
+ .byte 7 # DW_AT_name
+ .byte 16 # DW_AT_byte_size
+ .byte 1 # DW_AT_decl_file
+ .byte 4 # DW_AT_decl_line
+ .byte 9 # Abbrev [9] 0x9c:0x9 DW_TAG_member
+ .byte 8 # DW_AT_name
+ .long 141 # DW_AT_type
+ .byte 1 # DW_AT_decl_file
+ .byte 5 # DW_AT_decl_line
+ .byte 0 # DW_AT_data_member_location
+ .byte 9 # Abbrev [9] 0xa5:0x9 DW_TAG_member
+ .byte 9 # DW_AT_name
+ .long 184 # DW_AT_type
+ .byte 1 # DW_AT_decl_file
+ .byte 6 # DW_AT_decl_line
+ .byte 4 # DW_AT_data_member_location
+ .byte 9 # Abbrev [9] 0xae:0x9 DW_TAG_member
+ .byte 11 # DW_AT_name
+ .long 188 # DW_AT_type
+ .byte 1 # DW_AT_decl_file
+ .byte 7 # DW_AT_decl_line
+ .byte 8 # DW_AT_data_member_location
+ .byte 0 # End Of Children Mark
+ .byte 6 # Abbrev [6] 0xb8:0x4 DW_TAG_base_type
+ .byte 10 # DW_AT_name
+ .byte 6 # DW_AT_encoding
+ .byte 1 # DW_AT_byte_size
+ .byte 10 # Abbrev [10] 0xbc:0x5 DW_TAG_pointer_type
+ .long 150 # DW_AT_type
+ .byte 10 # Abbrev [10] 0xc1:0x5 DW_TAG_pointer_type
+ .long 198 # DW_AT_type
+ .byte 10 # Abbrev [10] 0xc6:0x5 DW_TAG_pointer_type
+ .long 184 # DW_AT_type
+ .byte 0 # End Of Children Mark
+.Ldebug_info_end0:
+ .section .debug_str_offsets,"", at progbits
+ .long 72 # Length of String Offsets Set
+ .short 5
+ .short 0
+.Lstr_offsets_base0:
+ .section .debug_str,"MS", at progbits,1
+.Linfo_string0:
+ .asciz "clang version 19.0.0git (git at github.com:llvm/llvm-project.git 4df364bc93af49ae413ec1ae8328f34ac70730c4)" # string offset=0
+.Linfo_string1:
+ .asciz "debug-names-parent-idx.cpp" # string offset=104
+.Linfo_string2:
+ .asciz "parent-idx-test" # string offset=131
+.Linfo_string3:
+ .asciz "bar" # string offset=147
+.Linfo_string4:
+ .asciz "_Z3barR3fooi" # string offset=151
+.Linfo_string5:
+ .asciz "main" # string offset=164
+.Linfo_string6:
+ .asciz "int" # string offset=169
+.Linfo_string7:
+ .asciz "foo" # string offset=173
+.Linfo_string8:
+ .asciz "x" # string offset=177
+.Linfo_string9:
+ .asciz "y" # string offset=179
+.Linfo_string10:
+ .asciz "char" # string offset=181
+.Linfo_string11:
+ .asciz "foo_ptr" # string offset=186
+.Linfo_string12:
+ .asciz "junk" # string offset=194
+.Linfo_string13:
+ .asciz "argc" # string offset=199
+.Linfo_string14:
+ .asciz "argv" # string offset=204
+.Linfo_string15:
+ .asciz "my_struct" # string offset=209
+.Linfo_string16:
+ .asciz "junk2" # string offset=219
+.Laddr_table_base0:
+ .quad .Lfunc_begin0
+ .quad .Lfunc_begin1
+.Ldebug_addr_end0:
+ .section .debug_names,"", at progbits
+ .long .Lnames_end0-.Lnames_start0 # Header: unit length
+.Lnames_start0:
+ .short 5 # Header: version
+ .short 0 # Header: padding
+ .long 1 # Header: compilation unit count
+ .long 0 # Header: local type unit count
+ .long 0 # Header: foreign type unit count
+ .long 6 # Header: bucket count
+ .long 6 # Header: name count
+ .long .Lnames_abbrev_end0-.Lnames_abbrev_start0 # Header: abbreviation table size
+ .long 8 # Header: augmentation string size
+ .ascii "LLVM0700" # Header: augmentation string
+ .long .Lcu_begin0 # Compilation unit 0
+ .long 1 # Bucket 0
+ .long 0 # Bucket 1
+ .long 2 # Bucket 2
+ .long 4 # Bucket 3
+ .long 5 # Bucket 4
+ .long 6 # Bucket 5
+ .long 193487034 # Hash in Bucket 0
+ .long 193495088 # Hash in Bucket 2
+ .long 1358986904 # Hash in Bucket 2
+ .long 193491849 # Hash in Bucket 3
+ .long 2090499946 # Hash in Bucket 4
+ .long 2090147939 # Hash in Bucket 5
+ .long .Linfo_string3 # String in Bucket 0: bar
+ .long .Linfo_string6 # String in Bucket 2: int
+ .long .Linfo_string4 # String in Bucket 2: _Z3barR3fooi
+ .long .Linfo_string7 # String in Bucket 3: foo
+ .long .Linfo_string5 # String in Bucket 4: main
+ .long .Linfo_string10 # String in Bucket 5: char
+ .long .Lnames0-.Lnames_entries0 # Offset in Bucket 0
+ .long .Lnames3-.Lnames_entries0 # Offset in Bucket 2
+ .long .Lnames1-.Lnames_entries0 # Offset in Bucket 2
+ .long .Lnames4-.Lnames_entries0 # Offset in Bucket 3
+ .long .Lnames2-.Lnames_entries0 # Offset in Bucket 4
+ .long .Lnames5-.Lnames_entries0 # Offset in Bucket 5
+.Lnames_abbrev_start0:
+ .byte 1 # Abbrev code
+ .byte 46 # DW_TAG_subprogram
+ .byte 3 # DW_IDX_die_offset
+ .byte 19 # DW_FORM_ref4
+ .byte 4 # DW_IDX_parent
+ .byte 25 # DW_FORM_flag_present
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev
+ .byte 2 # Abbrev code
+ .byte 36 # DW_TAG_base_type
+ .byte 3 # DW_IDX_die_offset
+ .byte 19 # DW_FORM_ref4
+ .byte 4 # DW_IDX_parent
+ .byte 25 # DW_FORM_flag_present
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev
+ .byte 3 # Abbrev code
+ .byte 19 # DW_TAG_structure_type
+ .byte 3 # DW_IDX_die_offset
+ .byte 19 # DW_FORM_ref4
+ .byte 4 # DW_IDX_parent
+ .byte 25 # DW_FORM_flag_present
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev list
+.Lnames_abbrev_end0:
+.Lnames_entries0:
+.Lnames0:
+.L2:
+ .byte 1 # Abbreviation code
+ .long 35 # DW_IDX_die_offset
+ .byte 0 # DW_IDX_parent
+ # End of list: bar
+.Lnames3:
+.L1:
+ .byte 2 # Abbreviation code
+ .long 141 # DW_IDX_die_offset
+ .byte 0 # DW_IDX_parent
+ # End of list: int
+.Lnames1:
+ .byte 1 # Abbreviation code
+ .long 35 # DW_IDX_die_offset
+ .byte 0 # DW_IDX_parent
+ # End of list: _Z3barR3fooi
+.Lnames4:
+.L4:
+ .byte 3 # Abbreviation code
+ .long 150 # DW_IDX_die_offset
+ .byte 0 # DW_IDX_parent
+ # End of list: foo
+.Lnames2:
+.L0:
+ .byte 1 # Abbreviation code
+ .long 70 # DW_IDX_die_offset
+ .byte 0 # DW_IDX_parent
+ # End of list: main
+.Lnames5:
+.L3:
+ .byte 2 # Abbreviation code
+ .long 184 # DW_IDX_die_offset
+ .byte 0 # DW_IDX_parent
+ # End of list: char
+ .p2align 2, 0x0
+.Lnames_end0:
+ .ident "clang version 19.0.0git (git at github.com:llvm/llvm-project.git 4df364bc93af49ae413ec1ae8328f34ac70730c4)"
+ .section ".note.GNU-stack","", at progbits
+ .addrsig
+ .addrsig_sym _Z3barR3fooi
+ .addrsig_sym _Z3foov
+ .addrsig_sym _ZN11parent_test3fooEv
+ .section .debug_line,"", at progbits
+.Lline_table_start0:
diff --git a/lld/test/ELF/debug-names.s b/lld/test/ELF/debug-names.s
new file mode 100644
index 00000000000000..ce013303f65f67
--- /dev/null
+++ b/lld/test/ELF/debug-names.s
@@ -0,0 +1,294 @@
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t1.o
+# RUN: llvm-mc -filetype=obj -triple=x86_64 %p/Inputs/debug-names-2.s -o %t2.o
+# RUN: ld.lld --debug-names %t1.o %t2.o -o %t
+
+# RUN: llvm-objdump -d %t | FileCheck %s --check-prefix=DISASM
+# RUN: llvm-dwarfdump -debug-names %t | FileCheck %s --check-prefix=DWARF
+# RUN: llvm-readelf -SW %t | FileCheck %s --check-prefix=READELF
+
+# DISASM: Disassembly of section .text:
+# DISASM-EMPTY:
+# DISASM: <_Z2f12t1>:
+# DISASM-CHECK: 201180: 55 pushq %rbp
+# DISASM-CHECK: 201181: 48 89 e5 movq %rsp, %rbp
+# DISASM-CHECK: 201184: 5d popq %rbp
+# DISASM-CHECK: 201185: c3 retq
+# DISASM-CHECK: 201186: cc int3
+# DISASM-CHECK: 201187: cc int3
+# DISASM-CHECK: 201188: cc int3
+# DISASM-CHECK: 201189: cc int3
+# DISASM-CHECK: 20118a: cc int3
+# DISASM-CHECK: 20118b: cc int3
+# DISASM-CHECK: 20118c: cc int3
+# DISASM-CHECK: 20118d: cc int3
+# DISASM-CHECK: 20118e: cc int3
+# DISASM-CHECK: 20118f: cc int3
+# DISASM: <main>:
+# DISASM-CHECK: 201190: 55 pushq %rbp
+# DISASM-CHECK: 201191: 48 89 e5 movq %rsp, %rbp
+# DISASM-CHECK: 201194: 31 c0 xorl %eax, %eax
+# DISASM-CHECK: 201196: 5d popq %rbp
+# DISASM-CHECK: 201197: c3 retq
+
+# DWARF: .debug_names contents:
+# DWARF: Name Index @ 0x0 {
+# DWARF-NEXT: Header {
+# DWARF-NEXT: Length: 0xCC
+# DWARF-NEXT: Format: DWARF32
+# DWARF-NEXT: Version: 5
+# DWARF-NEXT: CU count: 2
+# DWARF-NEXT: Local TU count: 0
+# DWARF-NEXT: Foreign TU count: 0
+# DWARF-NEXT: Bucket count: 5
+# DWARF-NEXT: Name count: 5
+# DWARF-NEXT: Abbreviations table size: 0x1F
+# DWARF-NEXT: Augmentation: 'LLVM0700'
+# DWARF: Compilation Unit offsets [
+# DWARF-NEXT: CU[0]: 0x00000000
+# DWARF-NEXT: CU[1]: 0x00000041
+# DWARF: Abbreviations [
+# DWARF-NEXT: Abbreviation 0x1 {
+# DWARF: Tag: DW_TAG_structure_type
+# DWARF-NEXT: DW_IDX_die_offset: DW_FORM_ref4
+# DWARF-NEXT: DW_IDX_parent: DW_FORM_flag_present
+# DWARF-NEXT: DW_IDX_compile_unit: DW_FORM_data1
+# DWARF: Abbreviation 0x2 {
+# DWARF-NEXT: Tag: DW_TAG_subprogram
+# DWARF-NEXT: DW_IDX_die_offset: DW_FORM_ref4
+# DWARF-NEXT: DW_IDX_parent: DW_FORM_flag_present
+# DWARF-NEXT: DW_IDX_compile_unit: DW_FORM_data1
+# DWARF: Abbreviation 0x3 {
+# DWARF-NEXT: Tag: DW_TAG_base_type
+# DWARF-NEXT: DW_IDX_die_offset: DW_FORM_ref4
+# DWARF-NEXT: DW_IDX_parent: DW_FORM_flag_present
+# DWARF-NEXT: DW_IDX_compile_unit: DW_FORM_data1
+# DWARF: Bucket 0 [
+# DWARF: Bucket 1 [
+# DWARF: String: 0x00000089 "f1"
+# DWARF-NEXT: Entry @ 0xa3 {
+# DWARF-NEXT: Abbrev: 0x2
+# DWARF-NEXT: Tag: DW_TAG_subprogram
+# DWARF-NEXT: DW_IDX_die_offset: 0x00000023
+# DWARF-NEXT: DW_IDX_parent: <parent not indexed>
+# DWARF-NEXT: DW_IDX_compile_unit: 0x00
+# DWARF: String: 0x00000095 "t1"
+# DWARF-NEXT: Entry @ 0xaa {
+# DWARF-NEXT: Abbrev: 0x1
+# DWARF-NEXT: Tag: DW_TAG_structure_type
+# DWARF-NEXT: DW_IDX_die_offset: 0x0000003a
+# DWARF-NEXT: DW_IDX_parent: <parent not indexed>
+# DWARF-NEXT: DW_IDX_compile_unit: 0x00
+# DWARF-NEXT: }
+# DWARF-NEXT: Entry @ 0xb0 {
+# DWARF-NEXT: Abbrev: 0x1
+# DWARF-NEXT: Tag: DW_TAG_structure_type
+# DWARF-NEXT: DW_IDX_die_offset: 0x00000042
+# DWARF-NEXT: DW_IDX_parent: <parent not indexed>
+# DWARF-NEXT: DW_IDX_compile_unit: 0x01
+# DWARF: String: 0x00000130 "int"
+# DWARF-NEXT: Entry @ 0xb7 {
+# DWARF-NEXT: Abbrev: 0x3
+# DWARF-NEXT: Tag: DW_TAG_base_type
+# DWARF-NEXT: DW_IDX_die_offset: 0x0000003e
+# DWARF-NEXT: DW_IDX_parent: <parent not indexed>
+# DWARF-NEXT: DW_IDX_compile_unit: 0x01
+# DWARF: Bucket 2 [
+# DWARF: Bucket 3 [
+# DWARF: String: 0x0000008c "_Z2f12t1"
+# DWARF-NEXT: Entry @ 0xbe {
+# DWARF-NEXT: Abbrev: 0x2
+# DWARF-NEXT: Tag: DW_TAG_subprogram
+# DWARF-NEXT: DW_IDX_die_offset: 0x00000023
+# DWARF-NEXT: DW_IDX_parent: <parent not indexed>
+# DWARF-NEXT: DW_IDX_compile_unit: 0x00
+# DWARF: Bucket 4 [
+# DWARF: String: 0x0000012b "main"
+# DWARF-NEXT: Entry @ 0xc5 {
+# DWARF-NEXT: Abbrev: 0x2
+# DWARF-NEXT: Tag: DW_TAG_subprogram
+# DWARF-NEXT: DW_IDX_die_offset: 0x00000023
+# DWARF-NEXT: DW_IDX_parent: <parent not indexed>
+# DWARF-NEXT: DW_IDX_compile_unit: 0x01
+
+# READELF: .debug_names PROGBITS 0000000000000000 0003eb 0000d0
+
+# RUN: ld.lld --debug-names --no-debug-names %t1.o %t2.o -o %t
+# RUN: llvm-readelf -SW %t | FileCheck %s --check-prefix=NO_DBG_NAMES
+
+
+# NO_DBG_NAMES: .debug_names PROGBITS 0000000000000000 00037c 000110
+
+#-- input file: debug-names.cpp
+## Generated with:
+##
+## - clang++ -g -O0 -gpubnames -fdebug-compilation-dir='debug-names-test' \
+## -S debug-names.cpp -o debug-names.s
+##
+## debug-names.cpp contents:
+##
+## struct t1 { };
+## void f1(t1) { }
+##
+##
+ .text
+ .globl _Z2f12t1 # -- Begin function _Z2f12t1
+ .p2align 4, 0x90
+ .type _Z2f12t1, at function
+_Z2f12t1: # @_Z2f12t1
+.Lfunc_begin0:
+ .cfi_startproc
+# %bb.0: # %entry
+ pushq %rbp
+ .cfi_def_cfa_offset 16
+ .cfi_offset %rbp, -16
+ movq %rsp, %rbp
+ .cfi_def_cfa_register %rbp
+.Ltmp0:
+ popq %rbp
+ .cfi_def_cfa %rsp, 8
+ retq
+.Ltmp1:
+.Lfunc_end0:
+ .size _Z2f12t1, .Lfunc_end0-_Z2f12t1
+ .cfi_endproc
+ # -- End function
+ .section .debug_abbrev,"", at progbits
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 0 # EOM(3)
+ .section .debug_info,"", at progbits
+.Lcu_begin0:
+ .long .Ldebug_info_end0-.Ldebug_info_start0 # Length of Unit
+.Ldebug_info_start0:
+ .short 5 # DWARF version number
+ .byte 1 # DWARF Unit Type
+ .byte 8 # Address Size (in bytes)
+ .long .debug_abbrev # Offset Into Abbrev. Section
+ .byte 1 # Abbrev [1] 0xc:0x35 DW_TAG_compile_unit
+ .byte 0 # DW_AT_producer
+ .short 33 # DW_AT_language
+ .byte 1 # DW_AT_name
+ .long .Lstr_offsets_base0 # DW_AT_str_offsets_base
+ .long .Lline_table_start0 # DW_AT_stmt_list
+ .byte 2 # DW_AT_comp_dir
+ .byte 0 # DW_AT_low_pc
+ .long .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc
+ .long .Laddr_table_base0 # DW_AT_addr_base
+ .byte 2 # Abbrev [2] 0x23:0x17 DW_TAG_subprogram
+ .byte 0 # DW_AT_low_pc
+ .long .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc
+ .byte 1 # DW_AT_frame_base
+ .byte 86
+ .byte 3 # DW_AT_linkage_name
+ .byte 4 # DW_AT_name
+ .byte 0 # DW_AT_decl_file
+ .byte 2 # DW_AT_decl_line
+ # DW_AT_external
+ .byte 3 # Abbrev [3] 0x2f:0xa DW_TAG_formal_parameter
+ .byte 2 # DW_AT_location
+ .byte 145
+ .byte 127
+ .byte 0 # DW_AT_decl_file
+ .byte 2 # DW_AT_decl_line
+ .long 58 # DW_AT_type
+ .byte 0 # End Of Children Mark
+ .byte 4 # Abbrev [4] 0x3a:0x6 DW_TAG_structure_type
+ .byte 5 # DW_AT_calling_convention
+ .byte 5 # DW_AT_name
+ .byte 1 # DW_AT_byte_size
+ .byte 0 # DW_AT_decl_file
+ .byte 1 # DW_AT_decl_line
+ .byte 0 # End Of Children Mark
+.Ldebug_info_end0:
+ .section .debug_str_offsets,"", at progbits
+ .long 28 # Length of String Offsets Set
+ .short 5
+ .short 0
+.Lstr_offsets_base0:
+ .section .debug_str,"MS", at progbits,1
+.Linfo_string0:
+ .asciz "clang version 19.0.0git (git at github.com:llvm/llvm-project.git 4df364bc93af49ae413ec1ae8328f34ac70730c4)" # string offset=0
+.Linfo_string1:
+ .asciz "debug-names.cpp" # string offset=104
+.Linfo_string2:
+ .asciz "debug-names-test" # string offset=120
+.Linfo_string3:
+ .asciz "f1" # string offset=137
+.Linfo_string4:
+ .asciz "_Z2f12t1" # string offset=140
+.Linfo_string5:
+ .asciz "t1" # string offset=149
+.Laddr_table_base0:
+ .quad .Lfunc_begin0
+.Ldebug_addr_end0:
+ .section .debug_names,"", at progbits
+ .long .Lnames_end0-.Lnames_start0 # Header: unit length
+.Lnames_start0:
+ .short 5 # Header: version
+ .short 0 # Header: padding
+ .long 1 # Header: compilation unit count
+ .long 0 # Header: local type unit count
+ .long 0 # Header: foreign type unit count
+ .long 3 # Header: bucket count
+ .long 3 # Header: name count
+ .long .Lnames_abbrev_end0-.Lnames_abbrev_start0 # Header: abbreviation table size
+ .long 8 # Header: augmentation string size
+ .ascii "LLVM0700" # Header: augmentation string
+ .long .Lcu_begin0 # Compilation unit 0
+ .long 0 # Bucket 0
+ .long 1 # Bucket 1
+ .long 3 # Bucket 2
+ .long 5863324 # Hash in Bucket 1
+ .long 5863786 # Hash in Bucket 1
+ .long 1398125246 # Hash in Bucket 2
+ .long .Linfo_string3 # String in Bucket 1: f1
+ .long .Linfo_string5 # String in Bucket 1: t1
+ .long .Linfo_string4 # String in Bucket 2: _Z2f12t1
+ .long .Lnames0-.Lnames_entries0 # Offset in Bucket 1
+ .long .Lnames2-.Lnames_entries0 # Offset in Bucket 1
+ .long .Lnames1-.Lnames_entries0 # Offset in Bucket 2
+.Lnames_abbrev_start0:
+ .byte 1 # Abbrev code
+ .byte 46 # DW_TAG_subprogram
+ .byte 3 # DW_IDX_die_offset
+ .byte 19 # DW_FORM_ref4
+ .byte 4 # DW_IDX_parent
+ .byte 25 # DW_FORM_flag_present
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev
+ .byte 2 # Abbrev code
+ .byte 19 # DW_TAG_structure_type
+ .byte 3 # DW_IDX_die_offset
+ .byte 19 # DW_FORM_ref4
+ .byte 4 # DW_IDX_parent
+ .byte 25 # DW_FORM_flag_present
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev list
+.Lnames_abbrev_end0:
+.Lnames_entries0:
+.Lnames0:
+.L1:
+ .byte 1 # Abbreviation code
+ .long 35 # DW_IDX_die_offset
+ .byte 0 # DW_IDX_parent
+ # End of list: f1
+.Lnames2:
+.L0:
+ .byte 2 # Abbreviation code
+ .long 58 # DW_IDX_die_offset
+ .byte 0 # DW_IDX_parent
+ # End of list: t1
+.Lnames1:
+ .byte 1 # Abbreviation code
+ .long 35 # DW_IDX_die_offset
+ .byte 0 # DW_IDX_parent
+ # End of list: _Z2f12t1
+ .p2align 2, 0x0
+.Lnames_end0:
+ .ident "clang version 19.0.0git (git at github.com:llvm/llvm-project.git 4df364bc93af49ae413ec1ae8328f34ac70730c4)"
+ .section ".note.GNU-stack","", at progbits
+ .addrsig
+ .section .debug_line,"", at progbits
+.Lline_table_start0:
>From 46339e6451baeb8d582226cfc206bbe76d597035 Mon Sep 17 00:00:00 2001
From: Caroline Tice <cmtice at google.com>
Date: Mon, 25 Mar 2024 19:48:29 -0700
Subject: [PATCH 02/23] [lld][ELF] Implement merged .debug_names section.
Fix two typos in test cases.
---
lld/test/ELF/debug-names-bad-aug-string.s | 2 +-
lld/test/ELF/debug-names-bad-version.s | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/lld/test/ELF/debug-names-bad-aug-string.s b/lld/test/ELF/debug-names-bad-aug-string.s
index edf79f0fde5773..ec1651362497e6 100644
--- a/lld/test/ELF/debug-names-bad-aug-string.s
+++ b/lld/test/ELF/debug-names-bad-aug-string.s
@@ -1,6 +1,6 @@
# REQUIRES: x86
# RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t1.o
-# RUN: llvm-mc -filetype=obj -triple=x86_64 %p/Inputs/debug-names-2.s -o %t2
+# RUN: llvm-mc -filetype=obj -triple=x86_64 %p/Inputs/debug-names-2.s -o %t2.o
# RUN: ld.lld --debug-names %t1.o %t2.o -o %t
# RUN: llvm-dwarfdump -debug-names %t | FileCheck %s --check-prefix=DWARF
diff --git a/lld/test/ELF/debug-names-bad-version.s b/lld/test/ELF/debug-names-bad-version.s
index f3914670af94a5..bf1855151c20da 100644
--- a/lld/test/ELF/debug-names-bad-version.s
+++ b/lld/test/ELF/debug-names-bad-version.s
@@ -1,6 +1,6 @@
# REQUIRES: x86
# RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t1.o
-# RUN: llvm-mc -filetype=obj -triple=x86_64 %p/Inputs/debug-names-2.s -o %t2
+# RUN: llvm-mc -filetype=obj -triple=x86_64 %p/Inputs/debug-names-2.s -o %t2.o
#
# RUN: not ld.lld --debug-names %t1.o %t2.o -o /dev/null 2>&1 | FileCheck %s
#
>From a90417463d3819c3c7bc5b10b7fc3e36caf48dc9 Mon Sep 17 00:00:00 2001
From: Caroline Tice <cmtice at google.com>
Date: Mon, 25 Mar 2024 23:38:38 -0700
Subject: [PATCH 03/23] [lld][ELF] Implement merged .debug_names section.
Clean up some error checking and reporting, and add some new tests.
---
lld/ELF/SyntheticSections.cpp | 52 +++---
lld/test/ELF/debug-names-dwarf64.s | 151 +++++++++++++++++
.../ELF/debug-names-invalid-abbrev-code.s | 151 +++++++++++++++++
.../ELF/debug-names-invalid-attribute-2.s | 150 +++++++++++++++++
.../ELF/debug-names-invalid-attribute-3.s | 154 ++++++++++++++++++
lld/test/ELF/debug-names-invalid-parent-idx.s | 153 +++++++++++++++++
6 files changed, 788 insertions(+), 23 deletions(-)
create mode 100644 lld/test/ELF/debug-names-dwarf64.s
create mode 100644 lld/test/ELF/debug-names-invalid-abbrev-code.s
create mode 100644 lld/test/ELF/debug-names-invalid-attribute-2.s
create mode 100644 lld/test/ELF/debug-names-invalid-attribute-3.s
create mode 100644 lld/test/ELF/debug-names-invalid-parent-idx.s
diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp
index d440410faa54f4..bc3083141f7665 100644
--- a/lld/ELF/SyntheticSections.cpp
+++ b/lld/ELF/SyntheticSections.cpp
@@ -2877,42 +2877,36 @@ bool DebugNamesSection::isNeeded() const { return numChunks > 0; }
template <class ELFT>
static void
readCompileUnitOffsets(struct DebugNamesSection::DebugNamesSectionData &secData,
- DebugNamesSection::DebugNamesInputChunk &inputChunk,
DebugNamesSection::DebugNamesOutputChunk &outputChunk,
llvm::DWARFDataExtractor &namesExtractor) {
uint64_t offset = secData.locs.CUsBase;
uint64_t *offsetPtr = &offset;
for (size_t i = 0; i < secData.hdr.CompUnitCount; ++i) {
llvm::Error err = llvm::Error::success();
+ // This call to namesExtractor can't fail; if there were a problem with the
+ // input, it would have been caught in the call to NamesIndex::extract, in
+ // DebugNamesSection::create.
uint32_t value = namesExtractor.getU32(offsetPtr, &err);
- if (err)
- errorOrWarn(toString(inputChunk.namesSection->sec) +
- ": error reading CU offsets: " + toString(std::move(err)));
- else
- outputChunk.compilationUnits.push_back(value);
+ llvm::cantFail(std::move(err));
+ outputChunk.compilationUnits.push_back(value);
}
}
template <class ELFT>
static void
readEntryOffsets(struct DebugNamesSection::DebugNamesSectionData &secData,
- DebugNamesSection::DebugNamesInputChunk &chunk,
llvm::DWARFDataExtractor &namesExtractor) {
secData.entryOffsets = std::make_unique<uint32_t[]>(secData.hdr.NameCount);
- if (secData.locs.EntryOffsetsBase >= namesExtractor.getData().size())
- errorOrWarn(toString(chunk.namesSection->sec) +
- ": invalid entry offsets input");
-
uint64_t offset = secData.locs.EntryOffsetsBase;
uint64_t *offsetPtr = &offset;
for (size_t i = 0; i < secData.hdr.NameCount; ++i) {
llvm::Error err = llvm::Error::success();
+ // This call to namesExtractor can't fail; if there were a problem with the
+ // input, it would have been caught in the call to NamesIndex::extract, in
+ // DebugNamesSection::create.
uint32_t value = namesExtractor.getU32(offsetPtr, &err);
- if (err)
- errorOrWarn(toString(chunk.namesSection->sec) +
- ": error reading entry offsets: " + toString(std::move(err)));
- else
- secData.entryOffsets.get()[i] = value;
+ llvm::cantFail(std::move(err));
+ secData.entryOffsets.get()[i] = value;
}
}
@@ -2930,11 +2924,17 @@ static void readAttributeValues(
llvm::Error err = llvm::Error::success();
DebugNamesSection::AttrValueData newAttr;
uint32_t value;
+ if (attr.Index == DW_IDX_parent &&
+ attr.Form != DW_FORM_flag_present &&
+ attr.Form != DW_FORM_ref4)
+ errorOrWarn(toString(namesSection.sec) + ": invalid form for DW_IDX_parent");
switch (attr.Form) {
case DW_FORM_flag_present: {
// Currently only DW_IDX_parent attributes (in .debug_names) can
// have this form. This form does not have a real value (nothing is
// emitted for it).
+ if (attr.Index != DW_IDX_parent)
+ errorOrWarn(toString(namesSection.sec) + ": invalid form for attribute");
break;
}
case DW_FORM_data1:
@@ -3004,10 +3004,11 @@ static void readEntry(DebugNamesSection::NamedEntry &stringEntry,
auto entry = std::make_unique<DebugNamesSection::IndexEntry>();
entry->poolOffset = offset;
llvm::Error err = llvm::Error::success();
+ // This call to namesExtractor can't fail; if there were a problem with the
+ // input, it would have been caught in the call to NamesIndex::extract, in
+ // DebugNamesSection::create.
uint64_t ulebValue = namesExtractor.getULEB128(&offset, &err);
- if (err)
- errorOrWarn(toString(chunk.namesSection->sec) +
- ": error reading entry: " + toString(std::move(err)));
+ llvm::cantFail(std::move(err));
entry->abbrevCode = static_cast<uint32_t>(ulebValue);
const auto &abbrevs = ni.getAbbrevs();
auto abbrevIt = abbrevs.find_as(entry->abbrevCode);
@@ -3016,7 +3017,9 @@ static void readEntry(DebugNamesSection::NamedEntry &stringEntry,
readAttributeValues<ELFT>(entry->attrValues, chunk, offset, secData,
entry->parentOffset, namesExtractor, abbrev);
stringEntry.indexEntries.push_back(std::move(entry));
- }
+ } else
+ errorOrWarn(toString(chunk.namesSection->sec) +
+ ": invalid abbrev code in entry");
}
if (offset >= namesSection->Data.size())
errorOrWarn(toString(chunk.namesSection->sec) +
@@ -3092,15 +3095,18 @@ static void collectDebugNamesSectionData(
for (const auto &ni : *chunk.debugNamesData) {
DebugNamesSection::DebugNamesSectionData secData;
secData.hdr = ni.getHeader();
- if (secData.hdr.Format != DwarfFormat::DWARF32)
+ if (secData.hdr.Format != DwarfFormat::DWARF32) {
errorOrWarn(toString(chunk.namesSection->sec) + ": unsupported DWARF64");
+ // Don't try to continue; we can't parse DWARF64 at the moment.
+ return;
+ }
secData.dwarfSize = dwarf::getDwarfOffsetByteSize(DwarfFormat::DWARF32);
secData.hdrSize = computeDebugNamesHeaderSize();
if (secData.hdr.Version != 5)
errorOrWarn(toString(chunk.namesSection->sec) + ": unsupported version");
secData.locs = findDebugNamesOffsets(secData.hdrSize, secData.hdr);
- readCompileUnitOffsets<ELFT>(secData, chunk, outputChunk, namesExtractor);
- readEntryOffsets<ELFT>(secData, chunk, namesExtractor);
+ readCompileUnitOffsets<ELFT>(secData, outputChunk, namesExtractor);
+ readEntryOffsets<ELFT>(secData, namesExtractor);
readEntries<ELFT>(secData, chunk, namesExtractor, strExtractor, ni);
chunk.sectionsData.push_back(std::move(secData));
}
diff --git a/lld/test/ELF/debug-names-dwarf64.s b/lld/test/ELF/debug-names-dwarf64.s
new file mode 100644
index 00000000000000..4391142c5558c2
--- /dev/null
+++ b/lld/test/ELF/debug-names-dwarf64.s
@@ -0,0 +1,151 @@
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t1.o
+#
+# RUN: not ld.lld --debug-names %t1.o -o /dev/null 2>&1 | FileCheck %s
+#
+# CHECK: error: {{.*}}(.debug_names): unsupported DWARF64
+##
+## This file was generated by:
+## clang++ -g -O0 -S -fdebug-compilation-dir='debug-names-test' \
+## -gdwarf64 -gpubnames main.cpp
+##
+## main.cpp
+## int main (int argc, char **argv) { }
+##
+ .text
+ .globl main # -- Begin function main
+ .p2align 4, 0x90
+ .type main, at function
+main: # @main
+.Lfunc_begin0:
+ .cfi_startproc
+# %bb.0: # %entry
+ pushq %rbp
+ .cfi_def_cfa_offset 16
+ .cfi_offset %rbp, -16
+ movq %rsp, %rbp
+ .cfi_def_cfa_register %rbp
+ movl %edi, -4(%rbp)
+ movq %rsi, -16(%rbp)
+.Ltmp0:
+ xorl %eax, %eax
+ popq %rbp
+ .cfi_def_cfa %rsp, 8
+ retq
+.Ltmp1:
+.Lfunc_end0:
+ .size main, .Lfunc_end0-main
+ .cfi_endproc
+ # -- End function
+ .section .debug_abbrev,"", at progbits
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 0 # EOM(3)
+ .section .debug_info,"", at progbits
+.Lcu_begin0:
+ .long 4294967295 # DWARF64 Mark
+ .quad .Ldebug_info_end0-.Ldebug_info_start0 # Length of Unit
+.Ldebug_info_start0:
+ .short 5 # DWARF version number
+ .byte 1 # DWARF Unit Type
+ .byte 8 # Address Size (in bytes)
+ .quad .debug_abbrev # Offset Into Abbrev. Section
+.Ldebug_info_end0:
+ .section .debug_str_offsets,"", at progbits
+ .long 4294967295 # DWARF64 Mark
+ .quad 68 # Length of String Offsets Set
+ .short 5
+ .short 0
+.Lstr_offsets_base0:
+ .section .debug_str,"MS", at progbits,1
+.Linfo_string0:
+ .asciz "clang version 19.0.0git (git at github.com:llvm/llvm-project.git 9b37e60051f362e8e22c88785239fd5dfbfdf105)" # string offset=0
+.Linfo_string1:
+ .asciz "main.cpp" # string offset=104
+.Linfo_string2:
+ .asciz "debug-names-test" # string offset=113
+.Linfo_string3:
+ .asciz "main" # string offset=130
+.Linfo_string4:
+ .asciz "int" # string offset=135
+.Linfo_string5:
+ .asciz "argc" # string offset=139
+.Linfo_string6:
+ .asciz "argv" # string offset=144
+.Linfo_string7:
+ .asciz "char" # string offset=149
+.Laddr_table_base0:
+ .quad .Lfunc_begin0
+.Ldebug_addr_end0:
+ .section .debug_names,"", at progbits
+ .long 4294967295 # DWARF64 Mark
+ .quad .Lnames_end0-.Lnames_start0 # Header: unit length
+.Lnames_start0:
+ .short 5 # Header: version
+ .short 0 # Header: padding
+ .long 1 # Header: compilation unit count
+ .long 0 # Header: local type unit count
+ .long 0 # Header: foreign type unit count
+ .long 3 # Header: bucket count
+ .long 3 # Header: name count
+ .long .Lnames_abbrev_end0-.Lnames_abbrev_start0 # Header: abbreviation table size
+ .long 8 # Header: augmentation string size
+ .ascii "LLVM0700" # Header: augmentation string
+ .quad .Lcu_begin0 # Compilation unit 0
+ .long 0 # Bucket 0
+ .long 1 # Bucket 1
+ .long 2 # Bucket 2
+ .long 2090499946 # Hash in Bucket 1
+ .long 193495088 # Hash in Bucket 2
+ .long 2090147939 # Hash in Bucket 2
+ .quad .Linfo_string3 # String in Bucket 1: main
+ .quad .Linfo_string4 # String in Bucket 2: int
+ .quad .Linfo_string7 # String in Bucket 2: char
+ .quad .Lnames0-.Lnames_entries0 # Offset in Bucket 1
+ .quad .Lnames1-.Lnames_entries0 # Offset in Bucket 2
+ .quad .Lnames2-.Lnames_entries0 # Offset in Bucket 2
+.Lnames_abbrev_start0:
+ .byte 1 # Abbrev code
+ .byte 46 # DW_TAG_subprogram
+ .byte 3 # DW_IDX_die_offset
+ .byte 19 # DW_FORM_ref4
+ .byte 4 # DW_IDX_parent
+ .byte 25 # DW_FORM_flag_present
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev
+ .byte 2 # Abbrev code
+ .byte 36 # DW_TAG_base_type
+ .byte 3 # DW_IDX_die_offset
+ .byte 19 # DW_FORM_ref4
+ .byte 4 # DW_IDX_parent
+ .byte 25 # DW_FORM_flag_present
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev list
+.Lnames_abbrev_end0:
+.Lnames_entries0:
+.Lnames0:
+.L2:
+ .byte 1 # Abbreviation code
+ .long 59 # DW_IDX_die_offset
+ .byte 0 # DW_IDX_parent
+ # End of list: main
+.Lnames1:
+.L1:
+ .byte 2 # Abbreviation code
+ .long 97 # DW_IDX_die_offset
+ .byte 0 # DW_IDX_parent
+ # End of list: int
+.Lnames2:
+.L0:
+ .byte 2 # Abbreviation code
+ .long 111 # DW_IDX_die_offset
+ .byte 0 # DW_IDX_parent
+ # End of list: char
+ .p2align 2, 0x0
+.Lnames_end0:
+ .ident "clang version 19.0.0git (git at github.com:llvm/llvm-project.git 9b37e60051f362e8e22c88785239fd5dfbfdf105)"
+ .section ".note.GNU-stack","", at progbits
+ .addrsig
+ .section .debug_line,"", at progbits
+.Lline_table_start0:
diff --git a/lld/test/ELF/debug-names-invalid-abbrev-code.s b/lld/test/ELF/debug-names-invalid-abbrev-code.s
new file mode 100644
index 00000000000000..14970e0d10433c
--- /dev/null
+++ b/lld/test/ELF/debug-names-invalid-abbrev-code.s
@@ -0,0 +1,151 @@
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t1.o
+#
+# RUN: not ld.lld --debug-names %t1.o -o /dev/null 2>&1 | FileCheck %s
+#
+# CHECK: error: {{.*}}(.debug_names): invalid abbrev code in entry
+# CHECK: error: {{.*}}(.debug_names): invalid abbrev code in entry
+##
+## This file was generated by:
+## clang++ -g -O0 -S -fdebug-compilation-dir='debug-names-test' \
+## -gpubnames main.cpp
+##
+## Then manually changing an abbrev code.
+##
+## main.cpp
+## int main (int argc, char **argv) { }
+##
+ .text
+ .globl main # -- Begin function main
+ .p2align 4, 0x90
+ .type main, at function
+main: # @main
+.Lfunc_begin0:
+ .cfi_startproc
+# %bb.0: # %entry
+ pushq %rbp
+ .cfi_def_cfa_offset 16
+ .cfi_offset %rbp, -16
+ movq %rsp, %rbp
+ .cfi_def_cfa_register %rbp
+ movl %edi, -4(%rbp)
+ movq %rsi, -16(%rbp)
+.Ltmp0:
+ xorl %eax, %eax
+ popq %rbp
+ .cfi_def_cfa %rsp, 8
+ retq
+.Ltmp1:
+.Lfunc_end0:
+ .size main, .Lfunc_end0-main
+ .cfi_endproc
+ # -- End function
+ .section .debug_abbrev,"", at progbits
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 0 # EOM(3)
+ .section .debug_info,"", at progbits
+.Lcu_begin0:
+ .long .Ldebug_info_end0-.Ldebug_info_start0 # Length of Unit
+.Ldebug_info_start0:
+ .short 5 # DWARF version number
+ .byte 1 # DWARF Unit Type
+ .byte 8 # Address Size (in bytes)
+ .long .debug_abbrev # Offset Into Abbrev. Section
+.Ldebug_info_end0:
+ .section .debug_str_offsets,"", at progbits
+ .long 36 # Length of String Offsets Set
+ .short 5
+ .short 0
+.Lstr_offsets_base0:
+ .section .debug_str,"MS", at progbits,1
+.Linfo_string0:
+ .asciz "clang version 19.0.0git (git at github.com:llvm/llvm-project.git d33d5630b281debe6eabd67e323bcf767340fb6a)" # string offset=0
+.Linfo_string1:
+ .asciz "main.cpp" # string offset=104
+.Linfo_string2:
+ .asciz "debug-names-test" # string offset=113
+.Linfo_string3:
+ .asciz "main" # string offset=130
+.Linfo_string4:
+ .asciz "int" # string offset=135
+.Linfo_string5:
+ .asciz "argc" # string offset=139
+.Linfo_string6:
+ .asciz "argv" # string offset=144
+.Linfo_string7:
+ .asciz "char" # string offset=149
+.Laddr_table_base0:
+ .quad .Lfunc_begin0
+.Ldebug_addr_end0:
+ .section .debug_names,"", at progbits
+ .long .Lnames_end0-.Lnames_start0 # Header: unit length
+.Lnames_start0:
+ .short 5 # Header: version
+ .short 0 # Header: padding
+ .long 1 # Header: compilation unit count
+ .long 0 # Header: local type unit count
+ .long 0 # Header: foreign type unit count
+ .long 3 # Header: bucket count
+ .long 3 # Header: name count
+ .long .Lnames_abbrev_end0-.Lnames_abbrev_start0 # Header: abbreviation table size
+ .long 8 # Header: augmentation string size
+ .ascii "LLVM0700" # Header: augmentation string
+ .long .Lcu_begin0 # Compilation unit 0
+ .long 0 # Bucket 0
+ .long 1 # Bucket 1
+ .long 2 # Bucket 2
+ .long 2090499946 # Hash in Bucket 1
+ .long 193495088 # Hash in Bucket 2
+ .long 2090147939 # Hash in Bucket 2
+ .long .Linfo_string3 # String in Bucket 1: main
+ .long .Linfo_string4 # String in Bucket 2: int
+ .long .Linfo_string7 # String in Bucket 2: char
+ .long .Lnames0-.Lnames_entries0 # Offset in Bucket 1
+ .long .Lnames1-.Lnames_entries0 # Offset in Bucket 2
+ .long .Lnames2-.Lnames_entries0 # Offset in Bucket 2
+.Lnames_abbrev_start0:
+ .byte 1 # Abbrev code
+ .byte 46 # DW_TAG_subprogram
+ .byte 3 # DW_IDX_die_offset
+ .byte 19 # DW_FORM_ref4
+ .byte 4 # DW_IDX_parent
+ .byte 25 # DW_FORM_flag_present
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev
+ .byte 2 # Abbrev code
+ .byte 36 # DW_TAG_base_type
+ .byte 3 # DW_IDX_die_offset
+ .byte 19 # DW_FORM_ref4
+ .byte 4 # DW_IDX_parent
+ .byte 25 # DW_FORM_flag_present
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev list
+.Lnames_abbrev_end0:
+.Lnames_entries0:
+.Lnames0:
+.L1:
+ .byte 1 # Abbreviation code
+ .long 35 # DW_IDX_die_offset
+ .byte 0 # DW_IDX_parent
+ # End of list: main
+.Lnames1:
+.L0:
+ .byte 3 # Abbreviation code
+ .long 73 # DW_IDX_die_offset
+ .byte 0 # DW_IDX_parent
+ # End of list: int
+.Lnames2:
+.L2:
+ .byte 2 # Abbreviation code
+ .long 87 # DW_IDX_die_offset
+ .byte 0 # DW_IDX_parent
+ # End of list: char
+ .p2align 2, 0x0
+.Lnames_end0:
+ .ident "clang version 19.0.0git (git at github.com:llvm/llvm-project.git d33d5630b281debe6eabd67e323bcf767340fb6a)"
+ .section ".note.GNU-stack","", at progbits
+ .addrsig
+ .section .debug_line,"", at progbits
+.Lline_table_start0:
diff --git a/lld/test/ELF/debug-names-invalid-attribute-2.s b/lld/test/ELF/debug-names-invalid-attribute-2.s
new file mode 100644
index 00000000000000..44e74911bd0353
--- /dev/null
+++ b/lld/test/ELF/debug-names-invalid-attribute-2.s
@@ -0,0 +1,150 @@
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t1.o
+#
+# RUN: not ld.lld --debug-names %t1.o -o /dev/null 2>&1 | FileCheck %s
+#
+# CHECK: error: {{.*}}(.debug_names): error while reading attributes: unexpected end of data at offset 0x80 while reading [0x7e, 0x82)
+##
+## This file was generated by:
+## clang++ -g -O0 -S -fdebug-compilation-dir='debug-names-test' \
+## -gpubnames main.cpp
+##
+## Then manually editing .debug_names section, commenting out a
+## DW_IDX_die_offset in an entry.
+##
+## main.cpp
+## int main (int argc, char **argv) { }
+##
+ .text
+ .globl main # -- Begin function main
+ .p2align 4, 0x90
+ .type main, at function
+main: # @main
+.Lfunc_begin0:
+ .cfi_startproc
+# %bb.0: # %entry
+ pushq %rbp
+ .cfi_def_cfa_offset 16
+ .cfi_offset %rbp, -16
+ movq %rsp, %rbp
+ .cfi_def_cfa_register %rbp
+ movl %edi, -4(%rbp)
+ movq %rsi, -16(%rbp)
+.Ltmp0:
+ xorl %eax, %eax
+ popq %rbp
+ .cfi_def_cfa %rsp, 8
+ retq
+.Ltmp1:
+.Lfunc_end0:
+ .size main, .Lfunc_end0-main
+ .cfi_endproc
+ # -- End function
+ .section .debug_abbrev,"", at progbits
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 0 # EOM(3)
+ .section .debug_info,"", at progbits
+.Lcu_begin0:
+ .long .Ldebug_info_end0-.Ldebug_info_start0 # Length of Unit
+.Ldebug_info_start0:
+ .short 5 # DWARF version number
+ .byte 1 # DWARF Unit Type
+ .byte 8 # Address Size (in bytes)
+ .long .debug_abbrev # Offset Into Abbrev. Section
+.Ldebug_info_end0:
+ .section .debug_str_offsets,"", at progbits
+ .long 36 # Length of String Offsets Set
+ .short 5
+ .short 0
+.Lstr_offsets_base0:
+ .section .debug_str,"MS", at progbits,1
+.Linfo_string0:
+ .asciz "clang version 19.0.0git (git at github.com:llvm/llvm-project.git d33d5630b281debe6eabd67e323bcf767340fb6a)" # string offset=0
+.Linfo_string1:
+ .asciz "main.cpp" # string offset=104
+.Linfo_string2:
+ .asciz "debug-names-test" # string offset=113
+.Linfo_string3:
+ .asciz "main" # string offset=130
+.Linfo_string4:
+ .asciz "int" # string offset=135
+.Linfo_string5:
+ .asciz "argc" # string offset=139
+.Linfo_string6:
+ .asciz "argv" # string offset=144
+.Linfo_string7:
+ .asciz "char" # string offset=149
+.Laddr_table_base0:
+ .quad .Lfunc_begin0
+.Ldebug_addr_end0:
+ .section .debug_names,"", at progbits
+ .long .Lnames_end0-.Lnames_start0 # Header: unit length
+.Lnames_start0:
+ .short 5 # Header: version
+ .short 0 # Header: padding
+ .long 1 # Header: compilation unit count
+ .long 0 # Header: local type unit count
+ .long 0 # Header: foreign type unit count
+ .long 3 # Header: bucket count
+ .long 3 # Header: name count
+ .long .Lnames_abbrev_end0-.Lnames_abbrev_start0 # Header: abbreviation table size
+ .long 8 # Header: augmentation string size
+ .ascii "LLVM0700" # Header: augmentation string
+ .long .Lcu_begin0 # Compilation unit 0
+ .long 0 # Bucket 0
+ .long 1 # Bucket 1
+ .long 2 # Bucket 2
+ .long 2090499946 # Hash in Bucket 1
+ .long 193495088 # Hash in Bucket 2
+ .long 2090147939 # Hash in Bucket 2
+ .long .Linfo_string3 # String in Bucket 1: main
+ .long .Linfo_string4 # String in Bucket 2: int
+ .long .Linfo_string7 # String in Bucket 2: char
+ .long .Lnames0-.Lnames_entries0 # Offset in Bucket 1
+ .long .Lnames1-.Lnames_entries0 # Offset in Bucket 2
+ .long .Lnames2-.Lnames_entries0 # Offset in Bucket 2
+.Lnames_abbrev_start0:
+ .byte 1 # Abbrev code
+ .byte 46 # DW_TAG_subprogram
+ .byte 3 # DW_IDX_die_offset
+ .byte 19 # DW_FORM_ref4
+ .byte 4 # DW_IDX_parent
+ .byte 25 # DW_FORM_flag_present
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev
+ .byte 2 # Abbrev code
+ .byte 36 # DW_TAG_base_type
+ .byte 3 # DW_IDX_die_offset
+ .byte 19 # DW_FORM_ref4
+ .byte 4 # DW_IDX_parent
+ .byte 25 # DW_FORM_flag_present
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev list
+.Lnames_abbrev_end0:
+.Lnames_entries0:
+.Lnames0:
+.L1:
+ .byte 1 # Abbreviation code
+ .long 35 # DW_IDX_die_offset
+ .byte 0 # DW_IDX_parent
+ # End of list: main
+.Lnames1:
+.L0:
+ .byte 2 # Abbreviation code
+ .long 73 # DW_IDX_die_offset
+ .byte 0 # DW_IDX_parent
+ # End of list: int
+.Lnames2:
+.L2:
+ .byte 2 # Abbreviation code
+# .long 87 # DW_IDX_die_offset
+ # End of list: char
+ .p2align 2, 0x0
+.Lnames_end0:
+ .ident "clang version 19.0.0git (git at github.com:llvm/llvm-project.git d33d5630b281debe6eabd67e323bcf767340fb6a)"
+ .section ".note.GNU-stack","", at progbits
+ .addrsig
+ .section .debug_line,"", at progbits
+.Lline_table_start0:
diff --git a/lld/test/ELF/debug-names-invalid-attribute-3.s b/lld/test/ELF/debug-names-invalid-attribute-3.s
new file mode 100644
index 00000000000000..1e6ea8074975f5
--- /dev/null
+++ b/lld/test/ELF/debug-names-invalid-attribute-3.s
@@ -0,0 +1,154 @@
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t1.o
+#
+# RUN: not ld.lld --debug-names %t1.o -o /dev/null 2>&1 | FileCheck %s
+#
+# CHECK: error: {{.*}}(.debug_names): invalid form for attribute
+##
+## This file was generated by:
+## clang++ -g -O0 -S -fdebug-compilation-dir='debug-names-test' \
+## -gpubnames main.cpp
+##
+##
+## Then manually changing the first .debug_names abbrev, so that the
+## DW_IDX_die_offset uses DW_FORM_flag_present (invalid) & the DW_IDX_parent
+## uses DW_FORM_ref4. Also updated the sizes of the values in the entry
+## that uses the abbrev, to match the sizes of the forms.
+##
+## main.cpp
+## int main (int argc, char **argv) { }
+##
+ .text
+ .globl main # -- Begin function main
+ .p2align 4, 0x90
+ .type main, at function
+main: # @main
+.Lfunc_begin0:
+ .cfi_startproc
+# %bb.0: # %entry
+ pushq %rbp
+ .cfi_def_cfa_offset 16
+ .cfi_offset %rbp, -16
+ movq %rsp, %rbp
+ .cfi_def_cfa_register %rbp
+ movl %edi, -4(%rbp)
+ movq %rsi, -16(%rbp)
+.Ltmp0:
+ xorl %eax, %eax
+ popq %rbp
+ .cfi_def_cfa %rsp, 8
+ retq
+.Ltmp1:
+.Lfunc_end0:
+ .size main, .Lfunc_end0-main
+ .cfi_endproc
+ # -- End function
+ .section .debug_abbrev,"", at progbits
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 0 # EOM(3)
+ .section .debug_info,"", at progbits
+.Lcu_begin0:
+ .long .Ldebug_info_end0-.Ldebug_info_start0 # Length of Unit
+.Ldebug_info_start0:
+ .short 5 # DWARF version number
+ .byte 1 # DWARF Unit Type
+ .byte 8 # Address Size (in bytes)
+ .long .debug_abbrev # Offset Into Abbrev. Section
+.Ldebug_info_end0:
+ .section .debug_str_offsets,"", at progbits
+ .long 36 # Length of String Offsets Set
+ .short 5
+ .short 0
+.Lstr_offsets_base0:
+ .section .debug_str,"MS", at progbits,1
+.Linfo_string0:
+ .asciz "clang version 19.0.0git (git at github.com:llvm/llvm-project.git d33d5630b281debe6eabd67e323bcf767340fb6a)" # string offset=0
+.Linfo_string1:
+ .asciz "main.cpp" # string offset=104
+.Linfo_string2:
+ .asciz "debug-names-test" # string offset=113
+.Linfo_string3:
+ .asciz "main" # string offset=130
+.Linfo_string4:
+ .asciz "int" # string offset=135
+.Linfo_string5:
+ .asciz "argc" # string offset=139
+.Linfo_string6:
+ .asciz "argv" # string offset=144
+.Linfo_string7:
+ .asciz "char" # string offset=149
+.Laddr_table_base0:
+ .quad .Lfunc_begin0
+.Ldebug_addr_end0:
+ .section .debug_names,"", at progbits
+ .long .Lnames_end0-.Lnames_start0 # Header: unit length
+.Lnames_start0:
+ .short 5 # Header: version
+ .short 0 # Header: padding
+ .long 1 # Header: compilation unit count
+ .long 0 # Header: local type unit count
+ .long 0 # Header: foreign type unit count
+ .long 3 # Header: bucket count
+ .long 3 # Header: name count
+ .long .Lnames_abbrev_end0-.Lnames_abbrev_start0 # Header: abbreviation table size
+ .long 8 # Header: augmentation string size
+ .ascii "LLVM0700" # Header: augmentation string
+ .long .Lcu_begin0 # Compilation unit 0
+ .long 0 # Bucket 0
+ .long 1 # Bucket 1
+ .long 2 # Bucket 2
+ .long 2090499946 # Hash in Bucket 1
+ .long 193495088 # Hash in Bucket 2
+ .long 2090147939 # Hash in Bucket 2
+ .long .Linfo_string3 # String in Bucket 1: main
+ .long .Linfo_string4 # String in Bucket 2: int
+ .long .Linfo_string7 # String in Bucket 2: char
+ .long .Lnames0-.Lnames_entries0 # Offset in Bucket 1
+ .long .Lnames1-.Lnames_entries0 # Offset in Bucket 2
+ .long .Lnames2-.Lnames_entries0 # Offset in Bucket 2
+.Lnames_abbrev_start0:
+ .byte 1 # Abbrev code
+ .byte 46 # DW_TAG_subprogram
+ .byte 3 # DW_IDX_die_offset
+ .byte 25 # DW_FORM_flag_present
+ .byte 4 # DW_IDX_parent
+ .byte 19 # DW_FORM_ref4
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev
+ .byte 2 # Abbrev code
+ .byte 36 # DW_TAG_base_type
+ .byte 3 # DW_IDX_die_offset
+ .byte 19 # DW_FORM_ref4
+ .byte 4 # DW_IDX_parent
+ .byte 25 # DW_FORM_flag_present
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev list
+.Lnames_abbrev_end0:
+.Lnames_entries0:
+.Lnames0:
+.L1:
+ .byte 1 # Abbreviation code
+ .byte 35 # DW_IDX_die_offset
+ .long 0 # DW_IDX_parent
+ # End of list: main
+.Lnames1:
+.L0:
+ .byte 2 # Abbreviation code
+ .long 73 # DW_IDX_die_offset
+ .byte 0 # DW_IDX_parent
+ # End of list: int
+.Lnames2:
+.L2:
+ .byte 2 # Abbreviation code
+ .long 87 # DW_IDX_die_offset
+ .byte 0 # DW_IDX_parent
+ # End of list: char
+ .p2align 2, 0x0
+.Lnames_end0:
+ .ident "clang version 19.0.0git (git at github.com:llvm/llvm-project.git d33d5630b281debe6eabd67e323bcf767340fb6a)"
+ .section ".note.GNU-stack","", at progbits
+ .addrsig
+ .section .debug_line,"", at progbits
+.Lline_table_start0:
diff --git a/lld/test/ELF/debug-names-invalid-parent-idx.s b/lld/test/ELF/debug-names-invalid-parent-idx.s
new file mode 100644
index 00000000000000..be5df8b155250e
--- /dev/null
+++ b/lld/test/ELF/debug-names-invalid-parent-idx.s
@@ -0,0 +1,153 @@
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t1.o
+#
+# RUN: not ld.lld --debug-names %t1.o -o /dev/null 2>&1 | FileCheck %s
+#
+# CHECK: error: {{.*}}(.debug_names): invalid form for DW_IDX_parent
+# CHECK: error: {{.*}}(.debug_names): invalid form for DW_IDX_parent
+# CHECK: error: {{.*}}(.debug_names): invalid form for DW_IDX_parent
+##
+## This file was generated by:
+## clang++ -g -O0 -S -fdebug-compilation-dir='debug-names-test' \
+## -gpubnames main.cpp
+##
+## Then manually editing .debug_names section, changing the form for a
+## DW_IDX_parent from DW_FORM_flag_present to DW_FORM_ref1 (invalid).
+##
+## main.cpp
+## int main (int argc, char **argv) { }
+##
+ .text
+ .globl main # -- Begin function main
+ .p2align 4, 0x90
+ .type main, at function
+main: # @main
+.Lfunc_begin0:
+ .cfi_startproc
+# %bb.0: # %entry
+ pushq %rbp
+ .cfi_def_cfa_offset 16
+ .cfi_offset %rbp, -16
+ movq %rsp, %rbp
+ .cfi_def_cfa_register %rbp
+ movl %edi, -4(%rbp)
+ movq %rsi, -16(%rbp)
+.Ltmp0:
+ xorl %eax, %eax
+ popq %rbp
+ .cfi_def_cfa %rsp, 8
+ retq
+.Ltmp1:
+.Lfunc_end0:
+ .size main, .Lfunc_end0-main
+ .cfi_endproc
+ # -- End function
+ .section .debug_abbrev,"", at progbits
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 0 # EOM(3)
+ .section .debug_info,"", at progbits
+.Lcu_begin0:
+ .long .Ldebug_info_end0-.Ldebug_info_start0 # Length of Unit
+.Ldebug_info_start0:
+ .short 5 # DWARF version number
+ .byte 1 # DWARF Unit Type
+ .byte 8 # Address Size (in bytes)
+ .long .debug_abbrev # Offset Into Abbrev. Section
+.Ldebug_info_end0:
+ .section .debug_str_offsets,"", at progbits
+ .long 36 # Length of String Offsets Set
+ .short 5
+ .short 0
+.Lstr_offsets_base0:
+ .section .debug_str,"MS", at progbits,1
+.Linfo_string0:
+ .asciz "clang version 19.0.0git (git at github.com:llvm/llvm-project.git d33d5630b281debe6eabd67e323bcf767340fb6a)" # string offset=0
+.Linfo_string1:
+ .asciz "main.cpp" # string offset=104
+.Linfo_string2:
+ .asciz "debug-names-test" # string offset=113
+.Linfo_string3:
+ .asciz "main" # string offset=130
+.Linfo_string4:
+ .asciz "int" # string offset=135
+.Linfo_string5:
+ .asciz "argc" # string offset=139
+.Linfo_string6:
+ .asciz "argv" # string offset=144
+.Linfo_string7:
+ .asciz "char" # string offset=149
+.Laddr_table_base0:
+ .quad .Lfunc_begin0
+.Ldebug_addr_end0:
+ .section .debug_names,"", at progbits
+ .long .Lnames_end0-.Lnames_start0 # Header: unit length
+.Lnames_start0:
+ .short 5 # Header: version
+ .short 0 # Header: padding
+ .long 1 # Header: compilation unit count
+ .long 0 # Header: local type unit count
+ .long 0 # Header: foreign type unit count
+ .long 3 # Header: bucket count
+ .long 3 # Header: name count
+ .long .Lnames_abbrev_end0-.Lnames_abbrev_start0 # Header: abbreviation table size
+ .long 8 # Header: augmentation string size
+ .ascii "LLVM0700" # Header: augmentation string
+ .long .Lcu_begin0 # Compilation unit 0
+ .long 0 # Bucket 0
+ .long 1 # Bucket 1
+ .long 2 # Bucket 2
+ .long 2090499946 # Hash in Bucket 1
+ .long 193495088 # Hash in Bucket 2
+ .long 2090147939 # Hash in Bucket 2
+ .long .Linfo_string3 # String in Bucket 1: main
+ .long .Linfo_string4 # String in Bucket 2: int
+ .long .Linfo_string7 # String in Bucket 2: char
+ .long .Lnames0-.Lnames_entries0 # Offset in Bucket 1
+ .long .Lnames1-.Lnames_entries0 # Offset in Bucket 2
+ .long .Lnames2-.Lnames_entries0 # Offset in Bucket 2
+.Lnames_abbrev_start0:
+ .byte 1 # Abbrev code
+ .byte 46 # DW_TAG_subprogram
+ .byte 3 # DW_IDX_die_offset
+ .byte 19 # DW_FORM_ref4
+ .byte 4 # DW_IDX_parent
+ .byte 25 # DW_FORM_flag_present
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev
+ .byte 2 # Abbrev code
+ .byte 36 # DW_TAG_base_type
+ .byte 3 # DW_IDX_die_offset
+ .byte 19 # DW_FORM_ref4
+ .byte 4 # DW_IDX_parent
+ .byte 17 # DW_FORM_ref1
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev list
+.Lnames_abbrev_end0:
+.Lnames_entries0:
+.Lnames0:
+.L1:
+ .byte 1 # Abbreviation code
+ .long 35 # DW_IDX_die_offset
+ .byte 0 # DW_IDX_parent
+ # End of list: main
+.Lnames1:
+.L0:
+ .byte 2 # Abbreviation code
+ .long 73 # DW_IDX_die_offset
+ .byte 0 # DW_IDX_parent
+ # End of list: int
+.Lnames2:
+.L2:
+ .byte 2 # Abbreviation code
+ .long 87 # DW_IDX_die_offset
+ .byte 0 # DW_IDX_parent
+ # End of list: char
+ .p2align 2, 0x0
+.Lnames_end0:
+ .ident "clang version 19.0.0git (git at github.com:llvm/llvm-project.git d33d5630b281debe6eabd67e323bcf767340fb6a)"
+ .section ".note.GNU-stack","", at progbits
+ .addrsig
+ .section .debug_line,"", at progbits
+.Lline_table_start0:
>From 5b7ff5b5cd5c137d29d467aebfa2615ac25c00df Mon Sep 17 00:00:00 2001
From: Caroline Tice <cmtice at google.com>
Date: Tue, 26 Mar 2024 22:48:27 -0700
Subject: [PATCH 04/23] [lld][ELF] Implement merged .debug_names section.
Update and fix debug-names* tests. Make entire DebugNamesSection
a template <class ELFT> section. Fix formatting and other
review comments.
---
lld/ELF/SyntheticSections.cpp | 238 +++++----
lld/ELF/SyntheticSections.h | 17 +-
lld/test/ELF/Inputs/debug-names-2.s | 45 +-
.../ELF/Inputs/debug-names-parent-idx-2.s | 98 +---
lld/test/ELF/debug-names-bad-aug-string.s | 84 +--
lld/test/ELF/debug-names-bad-die-idx-sizes.s | 32 +-
lld/test/ELF/debug-names-bad-name-count.s | 39 +-
lld/test/ELF/debug-names-bad-offsets-sizes.s | 37 +-
lld/test/ELF/debug-names-bad-version.s | 21 +-
lld/test/ELF/debug-names-dwarf64.s | 28 +-
.../ELF/debug-names-invalid-abbrev-code.s | 34 +-
.../ELF/debug-names-invalid-attribute-2.s | 34 +-
.../ELF/debug-names-invalid-attribute-3.s | 39 +-
lld/test/ELF/debug-names-invalid-attribute.s | 53 +-
lld/test/ELF/debug-names-invalid-flags.s | 148 ++++++
lld/test/ELF/debug-names-invalid-parent-idx.s | 38 +-
lld/test/ELF/debug-names-parent-idx.s | 496 +++++++-----------
lld/test/ELF/debug-names.s | 263 ++++------
18 files changed, 752 insertions(+), 992 deletions(-)
create mode 100644 lld/test/ELF/debug-names-invalid-flags.s
diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp
index bc3083141f7665..776bf719a01d77 100644
--- a/lld/ELF/SyntheticSections.cpp
+++ b/lld/ELF/SyntheticSections.cpp
@@ -2714,13 +2714,15 @@ static uint32_t computeGdbHash(StringRef s) {
return h;
}
-DebugNamesSection::DebugNamesSection()
+template <class ELFT>
+DebugNamesSection<ELFT>::DebugNamesSection()
: SyntheticSection(0, SHT_PROGBITS, 1, ".debug_names") {}
-template <class ELFT, class RelTy>
-void DebugNamesSection::getNameRelocsImpl(
+template <class ELFT>
+template <class RelTy>
+void DebugNamesSection<ELFT>::getNameRelocsImpl(
InputSection *sec, ArrayRef<RelTy> rels,
- llvm::DenseMap<uint32_t, uint32_t> &relocs) {
+ DenseMap<uint32_t, uint32_t> &relocs) {
for (auto &rel : rels) {
Symbol &sym = sec->getFile<ELFT>()->getRelocTargetSym(rel);
relocs[rel.r_offset] = sym.getVA(getAddend<ELFT>(rel));
@@ -2728,31 +2730,28 @@ void DebugNamesSection::getNameRelocsImpl(
}
template <class ELFT>
-void DebugNamesSection::getNameRelocs(
- InputSectionBase *base, llvm::DenseMap<uint32_t, uint32_t> &relocs) {
+void DebugNamesSection<ELFT>::getNameRelocs(
+ InputSectionBase *base, DenseMap<uint32_t, uint32_t> &relocs) {
auto *sec = cast<InputSection>(base);
const RelsOrRelas<ELFT> rels = sec->template relsOrRelas<ELFT>();
if (rels.areRelocsRel())
- getNameRelocsImpl<ELFT>(sec, rels.rels, relocs);
+ getNameRelocsImpl(sec, rels.rels, relocs);
else
- getNameRelocsImpl<ELFT>(sec, rels.relas, relocs);
+ getNameRelocsImpl(sec, rels.relas, relocs);
}
-void DebugNamesSection::writeTo(uint8_t *buf) { invokeELFT(writeToImpl, buf); }
-
-template <class ELFT> void DebugNamesSection::writeToImpl(uint8_t *buf) {
+template <class ELFT> void DebugNamesSection<ELFT>::writeTo(uint8_t *buf) {
SmallVector<uint32_t, 0> mergedCuOffsets;
SmallVector<uint32_t, 0> mergedTuOffsets;
- llvm::DenseMap<uint32_t, uint32_t> strOffsets;
- SmallVector<llvm::DenseMap<uint32_t, uint32_t>, 0> chunksRelocs;
+ DenseMap<uint32_t, uint32_t> strOffsets;
+ SmallVector<DenseMap<uint32_t, uint32_t>, 0> chunksRelocs;
chunksRelocs.reserve(numChunks);
for (size_t i = 0; i < numChunks; ++i) {
DebugNamesOutputChunk &chunk = outputChunks[i];
InputSectionBase *base = inputDebugNamesSections[i];
- llvm::DenseMap<uint32_t, uint32_t> relocs;
- getNameRelocs<ELFT>(base, relocs);
- chunksRelocs.push_back(std::move(relocs));
+ DenseMap<uint32_t, uint32_t> &relocs = chunksRelocs.emplace_back();
+ getNameRelocs(base, relocs);
// Update CuOffsets list with new data
for (uint32_t cuOffset : chunk.compilationUnits)
@@ -2839,15 +2838,11 @@ template <class ELFT> void DebugNamesSection::writeToImpl(uint8_t *buf) {
// Write the abbrev table.
for (const auto *abbrev : mergedAbbrevTable) {
- size_t uleb_size = encodeULEB128(abbrev->code, buf);
- buf += uleb_size;
- uleb_size = encodeULEB128(abbrev->tag, buf);
- buf += uleb_size;
+ buf += encodeULEB128(abbrev->code, buf);
+ buf += encodeULEB128(abbrev->tag, buf);
for (auto attr : abbrev->attributes) {
- uleb_size = encodeULEB128(attr.Index, buf);
- buf += uleb_size;
- uleb_size = encodeULEB128(attr.Form, buf);
- buf += uleb_size;
+ buf += encodeULEB128(attr.Index, buf);
+ buf += encodeULEB128(attr.Form, buf);
}
endian::write16<ELFT::Endianness>(buf + 0, 0); // attribute sentinels.
buf += 2;
@@ -2857,10 +2852,8 @@ template <class ELFT> void DebugNamesSection::writeToImpl(uint8_t *buf) {
// Write the entry pool.
for (const auto &stringEntry : mergedEntries) {
// Write all the entries for the string.
- size_t uleb_size;
for (const auto &entry : stringEntry.indexEntries) {
- uleb_size = encodeULEB128(entry->abbrevCode, buf);
- buf += uleb_size;
+ buf += encodeULEB128(entry->abbrevCode, buf);
for (const auto &value : entry->attrValues) {
if (value.attrSize > 0) {
endian::write32<ELFT::Endianness>(buf + 0, value.attrValue);
@@ -2872,69 +2865,74 @@ template <class ELFT> void DebugNamesSection::writeToImpl(uint8_t *buf) {
}
}
-bool DebugNamesSection::isNeeded() const { return numChunks > 0; }
+template <class ELFT> bool DebugNamesSection<ELFT>::isNeeded() const {
+ return numChunks > 0;
+}
template <class ELFT>
-static void
-readCompileUnitOffsets(struct DebugNamesSection::DebugNamesSectionData &secData,
- DebugNamesSection::DebugNamesOutputChunk &outputChunk,
- llvm::DWARFDataExtractor &namesExtractor) {
+static void readCompileUnitOffsets(
+ typename DebugNamesSection<ELFT>::DebugNamesSectionData &secData,
+ typename DebugNamesSection<ELFT>::DebugNamesOutputChunk &outputChunk,
+ DWARFDataExtractor &namesExtractor) {
uint64_t offset = secData.locs.CUsBase;
uint64_t *offsetPtr = &offset;
for (size_t i = 0; i < secData.hdr.CompUnitCount; ++i) {
- llvm::Error err = llvm::Error::success();
+ Error err = Error::success();
// This call to namesExtractor can't fail; if there were a problem with the
// input, it would have been caught in the call to NamesIndex::extract, in
// DebugNamesSection::create.
uint32_t value = namesExtractor.getU32(offsetPtr, &err);
- llvm::cantFail(std::move(err));
+ cantFail(std::move(err));
outputChunk.compilationUnits.push_back(value);
}
}
template <class ELFT>
-static void
-readEntryOffsets(struct DebugNamesSection::DebugNamesSectionData &secData,
- llvm::DWARFDataExtractor &namesExtractor) {
+static void readEntryOffsets(
+ typename DebugNamesSection<ELFT>::DebugNamesSectionData &secData,
+ DWARFDataExtractor &namesExtractor) {
secData.entryOffsets = std::make_unique<uint32_t[]>(secData.hdr.NameCount);
uint64_t offset = secData.locs.EntryOffsetsBase;
uint64_t *offsetPtr = &offset;
for (size_t i = 0; i < secData.hdr.NameCount; ++i) {
- llvm::Error err = llvm::Error::success();
+ Error err = Error::success();
// This call to namesExtractor can't fail; if there were a problem with the
// input, it would have been caught in the call to NamesIndex::extract, in
// DebugNamesSection::create.
uint32_t value = namesExtractor.getU32(offsetPtr, &err);
- llvm::cantFail(std::move(err));
+ cantFail(std::move(err));
secData.entryOffsets.get()[i] = value;
}
}
template <class ELFT>
static void readAttributeValues(
- SmallVector<DebugNamesSection::AttrValueData, 3> &values,
- DebugNamesSection::DebugNamesInputChunk &chunk, uint64_t &offset,
- struct DebugNamesSection::DebugNamesSectionData &secData,
- int32_t &parentOffset, llvm::DWARFDataExtractor &namesExtractor,
- const llvm::DWARFDebugNames::Abbrev &abbrev) {
+ SmallVector<typename DebugNamesSection<ELFT>::AttrValueData, 3> &values,
+ typename DebugNamesSection<ELFT>::DebugNamesInputChunk &chunk,
+ uint64_t &offset,
+ typename DebugNamesSection<ELFT>::DebugNamesSectionData &secData,
+ int32_t &parentOffset, DWARFDataExtractor &namesExtractor,
+ const DWARFDebugNames::Abbrev &abbrev) {
const LLDDWARFSection &namesSection = *chunk.namesSection;
uint64_t *offsetPtr = &offset;
- DebugNamesSection::AttrValueData cuOrTuAttr = {0, 0};
+ typename DebugNamesSection<ELFT>::AttrValueData cuOrTuAttr = {0, 0};
for (auto attr : abbrev.Attributes) {
- llvm::Error err = llvm::Error::success();
- DebugNamesSection::AttrValueData newAttr;
+ Error err = Error::success();
+ typename DebugNamesSection<ELFT>::AttrValueData newAttr;
uint32_t value;
if (attr.Index == DW_IDX_parent &&
attr.Form != DW_FORM_flag_present &&
attr.Form != DW_FORM_ref4)
- errorOrWarn(toString(namesSection.sec) + ": invalid form for DW_IDX_parent");
+ errorOrWarn(toString(namesSection.sec) +
+ Twine(": invalid form for DW_IDX_parent"));
switch (attr.Form) {
case DW_FORM_flag_present: {
// Currently only DW_IDX_parent attributes (in .debug_names) can
// have this form. This form does not have a real value (nothing is
// emitted for it).
if (attr.Index != DW_IDX_parent)
- errorOrWarn(toString(namesSection.sec) + ": invalid form for attribute");
+ errorOrWarn(toString(namesSection.sec) +
+ Twine(": invalid form for attribute"));
break;
}
case DW_FORM_data1:
@@ -2970,14 +2968,14 @@ static void readAttributeValues(
default: {
errorOrWarn(toString(namesSection.sec) +
Twine(": unrecognized form encoding ") + Twine(attr.Form) +
- " in .debug_names abbrev table");
+ Twine(" in .debug_names abbrev table"));
break;
}
}
if (err)
- errorOrWarn(
- toString(namesSection.sec) +
- ": error while reading attributes: " + toString(std::move(err)));
+ errorOrWarn(toString(namesSection.sec) +
+ Twine(": error while reading attributes: ") +
+ toString(std::move(err)));
if (attr.Index == DW_IDX_compile_unit || attr.Index == DW_IDX_type_unit)
// Save it to put it at the end of the attributes list.
cuOrTuAttr = newAttr;
@@ -2990,59 +2988,61 @@ static void readAttributeValues(
}
template <class ELFT>
-static void readEntry(DebugNamesSection::NamedEntry &stringEntry,
- DebugNamesSection::DebugNamesInputChunk &chunk,
- DebugNamesSection::DebugNamesSectionData &secData,
- llvm::DWARFDataExtractor &namesExtractor,
- const llvm::DWARFDebugNames::NameIndex &ni) {
+static void
+readEntry(typename DebugNamesSection<ELFT>::NamedEntry &stringEntry,
+ typename DebugNamesSection<ELFT>::DebugNamesInputChunk &chunk,
+ typename DebugNamesSection<ELFT>::DebugNamesSectionData &secData,
+ DWARFDataExtractor &namesExtractor,
+ const DWARFDebugNames::NameIndex &ni) {
std::unique_ptr<LLDDWARFSection> &namesSection = chunk.namesSection;
uint64_t offset = stringEntry.entryOffset;
// Each entry ends with a zero 'sentinel' value
while (offset < namesSection->Data.size() &&
namesSection->Data[offset] != 0) {
// Read & store all entries (for the same string)
- auto entry = std::make_unique<DebugNamesSection::IndexEntry>();
+ auto entry =
+ std::make_unique<typename DebugNamesSection<ELFT>::IndexEntry>();
entry->poolOffset = offset;
- llvm::Error err = llvm::Error::success();
+ Error err = Error::success();
// This call to namesExtractor can't fail; if there were a problem with the
// input, it would have been caught in the call to NamesIndex::extract, in
// DebugNamesSection::create.
uint64_t ulebValue = namesExtractor.getULEB128(&offset, &err);
- llvm::cantFail(std::move(err));
+ cantFail(std::move(err));
entry->abbrevCode = static_cast<uint32_t>(ulebValue);
const auto &abbrevs = ni.getAbbrevs();
auto abbrevIt = abbrevs.find_as(entry->abbrevCode);
if (abbrevIt != abbrevs.end()) {
- const llvm::DWARFDebugNames::Abbrev &abbrev = *abbrevIt;
+ const DWARFDebugNames::Abbrev &abbrev = *abbrevIt;
readAttributeValues<ELFT>(entry->attrValues, chunk, offset, secData,
entry->parentOffset, namesExtractor, abbrev);
stringEntry.indexEntries.push_back(std::move(entry));
} else
errorOrWarn(toString(chunk.namesSection->sec) +
- ": invalid abbrev code in entry");
+ Twine(": invalid abbrev code in entry"));
}
if (offset >= namesSection->Data.size())
- errorOrWarn(toString(chunk.namesSection->sec) +
- ": encountered unexpected end of section while reading entry");
+ errorOrWarn(
+ toString(chunk.namesSection->sec) +
+ Twine(": encountered unexpected end of section while reading entry"));
}
template <class ELFT>
static void
-readEntries(struct DebugNamesSection::DebugNamesSectionData &secData,
- DebugNamesSection::DebugNamesInputChunk &chunk,
- llvm::DWARFDataExtractor &namesExtractor,
- llvm::DataExtractor &strExtractor,
- const llvm::DWARFDebugNames::NameIndex &ni) {
+readEntries(typename DebugNamesSection<ELFT>::DebugNamesSectionData &secData,
+ typename DebugNamesSection<ELFT>::DebugNamesInputChunk &chunk,
+ DWARFDataExtractor &namesExtractor, DataExtractor &strExtractor,
+ const DWARFDebugNames::NameIndex &ni) {
// Temporary map from entry offsets to address (pointer) of entry with that
// offset; used to find parent entries quickly.
- DenseMap<uint32_t, DebugNamesSection::IndexEntry *> offsetMap;
+ DenseMap<uint32_t, typename DebugNamesSection<ELFT>::IndexEntry *> offsetMap;
// Reserve sizes for this chunk's hashes & namedEntries.
chunk.hashValues.reserve(secData.hdr.NameCount);
secData.namedEntries.reserve(secData.hdr.NameCount);
// Calculate the Entry Offsets, create initial records.
for (uint32_t i = 0; i < secData.hdr.NameCount; ++i) {
// Get string value
- DebugNamesSection::NamedEntry stringEntry;
+ typename DebugNamesSection<ELFT>::NamedEntry stringEntry;
stringEntry.entryOffset =
secData.locs.EntriesBase + secData.entryOffsets[i];
uint64_t strOffsetOffset =
@@ -3088,22 +3088,23 @@ static uint16_t computeDebugNamesHeaderSize() {
template <class ELFT>
static void collectDebugNamesSectionData(
- DebugNamesSection::DebugNamesInputChunk &chunk,
- DebugNamesSection::DebugNamesOutputChunk &outputChunk,
- llvm::DWARFDataExtractor &namesExtractor,
- llvm::DataExtractor &strExtractor) {
+ typename DebugNamesSection<ELFT>::DebugNamesInputChunk &chunk,
+ typename DebugNamesSection<ELFT>::DebugNamesOutputChunk &outputChunk,
+ DWARFDataExtractor &namesExtractor, DataExtractor &strExtractor) {
for (const auto &ni : *chunk.debugNamesData) {
- DebugNamesSection::DebugNamesSectionData secData;
+ typename DebugNamesSection<ELFT>::DebugNamesSectionData secData;
secData.hdr = ni.getHeader();
if (secData.hdr.Format != DwarfFormat::DWARF32) {
- errorOrWarn(toString(chunk.namesSection->sec) + ": unsupported DWARF64");
+ errorOrWarn(toString(chunk.namesSection->sec) +
+ Twine(": unsupported DWARF64"));
// Don't try to continue; we can't parse DWARF64 at the moment.
return;
}
secData.dwarfSize = dwarf::getDwarfOffsetByteSize(DwarfFormat::DWARF32);
secData.hdrSize = computeDebugNamesHeaderSize();
if (secData.hdr.Version != 5)
- errorOrWarn(toString(chunk.namesSection->sec) + ": unsupported version");
+ errorOrWarn(toString(chunk.namesSection->sec) +
+ Twine(": unsupported version"));
secData.locs = findDebugNamesOffsets(secData.hdrSize, secData.hdr);
readCompileUnitOffsets<ELFT>(secData, outputChunk, namesExtractor);
readEntryOffsets<ELFT>(secData, namesExtractor);
@@ -3112,10 +3113,10 @@ static void collectDebugNamesSectionData(
}
}
-void DebugNamesSection::collectMergedCounts(
+template <class ELFT>
+void DebugNamesSection<ELFT>::collectMergedCounts(
MutableArrayRef<DebugNamesInputChunk> &inputChunks) {
SmallVector<uint32_t, 0> tmpMergedCuOffsets;
-
mergedHdr.CompUnitCount = 0;
mergedHdr.LocalTypeUnitCount = 0;
mergedHdr.ForeignTypeUnitCount = 0;
@@ -3143,15 +3144,15 @@ void DebugNamesSection::collectMergedCounts(
data.hdr.AugmentationString)) {
// There are conflicting augmentation strings, so it's best for the
// merged index to not use an augmentation string.
- StringRef emptyString = " ";
mergedHdr.AugmentationStringSize = 8;
- mergedHdr.AugmentationString = emptyString;
+ mergedHdr.AugmentationString = " ";
}
}
}
}
-void DebugNamesSection::Abbrev::Profile(llvm::FoldingSetNodeID &id) const {
+template <class ELFT>
+void DebugNamesSection<ELFT>::Abbrev::Profile(FoldingSetNodeID &id) const {
id.AddInteger(tag);
for (const DWARFDebugNames::AttributeEncoding &attr : attributes) {
id.AddInteger(attr.Index);
@@ -3159,14 +3160,15 @@ void DebugNamesSection::Abbrev::Profile(llvm::FoldingSetNodeID &id) const {
}
}
-std::pair<uint8_t, dwarf::Form> DebugNamesSection::getMergedCuSizeData() {
+template <class ELFT>
+std::pair<uint8_t, dwarf::Form> DebugNamesSection<ELFT>::getMergedCuSizeData() {
// Once we've merged all the CU offsets into a single list, the original
// DWARF form/size (often 1 byte) may be too small to hold indices to all
// the offsets. Here we calculate what the right form/size needs to be for
// the merged index.
uint8_t size;
dwarf::Form form;
- // TODO: Investigate possibly using llvm::DIEInteger::BestForm here
+ // TODO: Investigate possibly using DIEInteger::BestForm here
if (mergedHdr.CompUnitCount > 0xffffffff) {
form = DW_FORM_data8;
size = 8;
@@ -3184,10 +3186,11 @@ std::pair<uint8_t, dwarf::Form> DebugNamesSection::getMergedCuSizeData() {
return {size, form};
}
-void DebugNamesSection::getMergedAbbrevTable(
+template <class ELFT>
+void DebugNamesSection<ELFT>::getMergedAbbrevTable(
MutableArrayRef<DebugNamesInputChunk> &inputChunks) {
MapVector<uint64_t, Abbrev> abbrevMap;
- FoldingSet<DebugNamesSection::Abbrev> AbbreviationsSet;
+ FoldingSet<Abbrev> AbbreviationsSet;
// Need to determine what size form is needed for the DW_IDX_compile_unit
// attributes in the merged index. Will need to update the abbrevs to use
@@ -3199,7 +3202,7 @@ void DebugNamesSection::getMergedAbbrevTable(
const auto &abbrevs = ni.getAbbrevs();
for (const DWARFDebugNames::Abbrev &abbrev : abbrevs) {
// Create canonicalized abbrev.
- DebugNamesSection::Abbrev newAbbrev;
+ Abbrev newAbbrev;
DWARFDebugNames::AttributeEncoding cuOrTuAttr(DW_IDX_compile_unit,
compileUnitAttrForm);
newAbbrev.code = abbrev.Code;
@@ -3254,14 +3257,15 @@ void DebugNamesSection::getMergedAbbrevTable(
++mergedHdr.AbbrevTableSize; // abbrev table sentinel
}
-void DebugNamesSection::getMergedSymbols(
+template <class ELFT>
+void DebugNamesSection<ELFT>::getMergedSymbols(
MutableArrayRef<DebugNamesInputChunk> &inputChunks) {
// The number of symbols (& abbrevs) we will handle is very large; will use
// multi-threading to speed it up.
constexpr size_t numShards = 32;
const size_t concurrency =
- llvm::bit_floor(std::min<size_t>(config->threadCount, numShards));
- const size_t shift = 32 - llvm::countr_zero(numShards);
+ bit_floor(std::min<size_t>(config->threadCount, numShards));
+ const size_t shift = 32 - countr_zero(numShards);
struct ShardData {
// Map to uniquify symbols by name
@@ -3330,7 +3334,8 @@ void DebugNamesSection::getMergedSymbols(
mergedHdr.NameCount = mergedEntries.size();
}
-void DebugNamesSection::computeUniqueHashes(
+template <class ELFT>
+void DebugNamesSection<ELFT>::computeUniqueHashes(
MutableArrayRef<DebugNamesInputChunk> &chunks) {
SmallVector<uint32_t, 0> uniques;
for (const auto &chunk : chunks)
@@ -3339,7 +3344,7 @@ void DebugNamesSection::computeUniqueHashes(
mergedHdr.BucketCount = dwarf::getDebugNamesBucketCount(llvm::unique(uniques) - uniques.begin());
}
-void DebugNamesSection::generateBuckets() {
+template <class ELFT> void DebugNamesSection<ELFT>::generateBuckets() {
bucketList.resize(mergedHdr.BucketCount);
for (auto &entry : mergedEntries) {
uint32_t bucketIdx = entry.hashValue % mergedHdr.BucketCount;
@@ -3349,20 +3354,20 @@ void DebugNamesSection::generateBuckets() {
// Sort the contents of the buckets by hash value so that the hash collisions
// end up together.
for (auto &bucket : bucketList)
- llvm::stable_sort(bucket, [](NamedEntry *lhs, NamedEntry *rhs) {
+ stable_sort(bucket, [](NamedEntry *lhs, NamedEntry *rhs) {
return lhs->hashValue < rhs->hashValue;
});
}
-void DebugNamesSection::calculateEntriesSizeAndOffsets() {
+template <class ELFT>
+void DebugNamesSection<ELFT>::calculateEntriesSizeAndOffsets() {
uint32_t offset = 0;
- for (DebugNamesSection::NamedEntry &stringEntry : mergedEntries) {
+ for (NamedEntry &stringEntry : mergedEntries) {
stringEntry.entryOffset = offset;
for (auto &entry : stringEntry.indexEntries) {
uint32_t entrySize = 0;
entry->poolOffset = offset;
- uint32_t ulebSize = getULEB128Size(entry->abbrevCode);
- entrySize += ulebSize;
+ entrySize += getULEB128Size(entry->abbrevCode);
for (const auto &attr : entry->attrValues)
entrySize += attr.attrSize;
offset += entrySize;
@@ -3373,8 +3378,8 @@ void DebugNamesSection::calculateEntriesSizeAndOffsets() {
mergedTotalEntriesSize = offset;
}
-void DebugNamesSection::updateParentIndexEntries() {
- for (DebugNamesSection::NamedEntry &stringEntry : mergedEntries) {
+template <class ELFT> void DebugNamesSection<ELFT>::updateParentIndexEntries() {
+ for (NamedEntry &stringEntry : mergedEntries) {
for (auto &childEntry : stringEntry.indexEntries) {
if (!childEntry->parentEntry)
continue;
@@ -3397,7 +3402,8 @@ void DebugNamesSection::updateParentIndexEntries() {
}
}
-uint64_t DebugNamesSection::calculateMergedSectionSize() {
+template <class ELFT>
+uint64_t DebugNamesSection<ELFT>::calculateMergedSectionSize() {
uint32_t hdrSize = computeDebugNamesHeaderSize();
mergedOffsets = findDebugNamesOffsets(hdrSize, mergedHdr);
// Add in the size for all the Entries, and make it 4-byte aligned.
@@ -3407,8 +3413,9 @@ uint64_t DebugNamesSection::calculateMergedSectionSize() {
return mergedHdr.UnitLength + 4;
}
-template <class ELFT> DebugNamesSection *DebugNamesSection::create() {
- llvm::TimeTraceScope timeScope("Create merged .debug_names");
+template <class ELFT>
+DebugNamesSection<ELFT> *DebugNamesSection<ELFT>::create() {
+ TimeTraceScope timeScope("Create merged .debug_names");
SetVector<InputFile *> files;
SmallVector<InputSectionBase *, 0> sections;
for (InputSectionBase *s : ctx.inputSections) {
@@ -3428,28 +3435,26 @@ template <class ELFT> DebugNamesSection *DebugNamesSection::create() {
files.size());
auto outputChunks = std::make_unique<DebugNamesOutputChunk[]>(files.size());
parallelFor(0, files.size(), [&](size_t i) {
- ObjFile<ELFT> *file = cast<ObjFile<ELFT>>(files[i]);
+ auto *file = cast<ObjFile<ELFT>>(files[i]);
auto dwarfCtx = std::make_unique<DWARFContext>(
std::make_unique<LLDDwarfObj<ELFT>>(file));
auto &dobj =
static_cast<const LLDDwarfObj<ELFT> &>(dwarfCtx->getDWARFObj());
- // Extract llvm::DWARFDebugNames data from the .debug_names section. The
+ // Extract DWARFDebugNames data from the .debug_names section. The
// .debug_names section needs the .debug_str section, to get the actual
// symbol names.
- const StringRef &strSection = dobj.getStrSection();
+ const StringRef strSection = dobj.getStrSection();
const LLDDWARFSection &namesSection = dobj.getNamesSection();
- llvm::DWARFDataExtractor namesExtractor(dobj, namesSection, config->isLE,
- config->wordsize);
- llvm::DataExtractor strExtractor(strSection, config->isLE,
- config->wordsize);
+ DWARFDataExtractor namesExtractor(dobj, namesSection, config->isLE,
+ config->wordsize);
+ DataExtractor strExtractor(strSection, config->isLE, config->wordsize);
inputChunks[i].debugNamesData =
std::make_unique<DWARFDebugNames>(namesExtractor, strExtractor);
inputChunks[i].namesSection =
std::make_unique<LLDDWARFSection>(namesSection);
- if (llvm::Error E = inputChunks[i].debugNamesData->extract()) {
- // Report an error here. We were unable to extract the data.
- errorOrWarn(toString(dobj.getNamesSection().sec) + ": " +
+ if (Error E = inputChunks[i].debugNamesData->extract()) {
+ errorOrWarn(toString(dobj.getNamesSection().sec) + Twine(": ") +
toString(std::move(E)));
}
outputChunks[i].sec = dobj.getInfoSection();
@@ -3458,13 +3463,14 @@ template <class ELFT> DebugNamesSection *DebugNamesSection::create() {
});
auto *ret = make<DebugNamesSection>();
- ret->addSections(sections);
+ ret->inputDebugNamesSections = sections;
ret->outputChunks = std::move(outputChunks);
ret->numChunks = files.size();
ret->collectMergedCounts(inputChunks);
ret->getMergedAbbrevTable(inputChunks);
ret->getMergedSymbols(inputChunks);
ret->computeUniqueHashes(inputChunks);
+ // inputChunks are needed any more. Reset now to save memory.
inputChunksPtr.reset();
ret->generateBuckets();
ret->calculateEntriesSizeAndOffsets();
@@ -5035,7 +5041,7 @@ template <class ELFT> void elf::createSyntheticSections() {
add(*make<GnuPropertySection>());
if (config->debugNames)
- add(*DebugNamesSection::create<ELFT>());
+ add(*DebugNamesSection<ELFT>::create());
if (config->gdbIndex) {
in.gdbIndex = GdbIndexSection::create<ELFT>();
add(*in.gdbIndex);
diff --git a/lld/ELF/SyntheticSections.h b/lld/ELF/SyntheticSections.h
index e0b01831edaa77..24ffdb3db4946b 100644
--- a/lld/ELF/SyntheticSections.h
+++ b/lld/ELF/SyntheticSections.h
@@ -793,7 +793,7 @@ class RelroPaddingSection final : public SyntheticSection {
void writeTo(uint8_t *buf) override {}
};
-class DebugNamesSection final : public SyntheticSection {
+template <class ELFT> class DebugNamesSection final : public SyntheticSection {
// N.B. Everything in this class assumes that we are using DWARF32.
// If we move to DWARF64, most of this data will need to be re-sized,
// and the code that handles or manipulates it will need to be updated
@@ -801,29 +801,18 @@ class DebugNamesSection final : public SyntheticSection {
public:
DebugNamesSection();
- template <typename ELFT> static DebugNamesSection *create();
+ static DebugNamesSection *create();
void writeTo(uint8_t *buf) override;
size_t getSize() const override { return sectionSize; }
bool isNeeded() const override;
- void addSections(SmallVector<InputSectionBase *, 0> sec_list) {
- inputDebugNamesSections = sec_list;
- }
-
- template <class ELFT> void writeToImpl(uint8_t *buf);
-
- template <class ELFT, class RelTy>
+ template <class RelTy>
void getNameRelocsImpl(InputSection *sec, ArrayRef<RelTy> rels,
llvm::DenseMap<uint32_t, uint32_t> &relocs);
- template <class ELFT>
void getNameRelocs(InputSectionBase *base,
llvm::DenseMap<uint32_t, uint32_t> &relocs);
- template <class ELFT>
- void endianWrite(uint8_t size, uint8_t *buf_start, uint32_t offset,
- uint32_t data);
-
struct Abbrev : public llvm::FoldingSetNode {
uint32_t code;
uint32_t tag;
diff --git a/lld/test/ELF/Inputs/debug-names-2.s b/lld/test/ELF/Inputs/debug-names-2.s
index 586788653dcc72..83ddbd2050d40b 100644
--- a/lld/test/ELF/Inputs/debug-names-2.s
+++ b/lld/test/ELF/Inputs/debug-names-2.s
@@ -1,11 +1,10 @@
#-- input file: debug-names-2.cpp
## Generated with:
-##
## - clang++ -g -O0 -gpubnames -fdebug-compilation-dir='debug-names-test' \
## -S debug-names-2.cpp -o debug-names-2.s
-##
+
## debug-names-2.cpp contents:
-##
+
## struct t1 { };
## int main() {
## t1 v1;
@@ -46,46 +45,6 @@ main: # @main
.byte 1 # DWARF Unit Type
.byte 8 # Address Size (in bytes)
.long .debug_abbrev # Offset Into Abbrev. Section
- .byte 1 # Abbrev [1] 0xc:0x3d DW_TAG_compile_unit
- .byte 0 # DW_AT_producer
- .short 33 # DW_AT_language
- .byte 1 # DW_AT_name
- .long .Lstr_offsets_base0 # DW_AT_str_offsets_base
- .long .Lline_table_start0 # DW_AT_stmt_list
- .byte 2 # DW_AT_comp_dir
- .byte 0 # DW_AT_low_pc
- .long .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc
- .long .Laddr_table_base0 # DW_AT_addr_base
- .byte 2 # Abbrev [2] 0x23:0x1b DW_TAG_subprogram
- .byte 0 # DW_AT_low_pc
- .long .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc
- .byte 1 # DW_AT_frame_base
- .byte 86
- .byte 3 # DW_AT_name
- .byte 0 # DW_AT_decl_file
- .byte 2 # DW_AT_decl_line
- .long 62 # DW_AT_type
- # DW_AT_external
- .byte 3 # Abbrev [3] 0x32:0xb DW_TAG_variable
- .byte 2 # DW_AT_location
- .byte 145
- .byte 127
- .byte 5 # DW_AT_name
- .byte 0 # DW_AT_decl_file
- .byte 3 # DW_AT_decl_line
- .long 66 # DW_AT_type
- .byte 0 # End Of Children Mark
- .byte 4 # Abbrev [4] 0x3e:0x4 DW_TAG_base_type
- .byte 4 # DW_AT_name
- .byte 5 # DW_AT_encoding
- .byte 4 # DW_AT_byte_size
- .byte 5 # Abbrev [5] 0x42:0x6 DW_TAG_structure_type
- .byte 5 # DW_AT_calling_convention
- .byte 6 # DW_AT_name
- .byte 1 # DW_AT_byte_size
- .byte 0 # DW_AT_decl_file
- .byte 1 # DW_AT_decl_line
- .byte 0 # End Of Children Mark
.Ldebug_info_end0:
.section .debug_str_offsets,"", at progbits
.long 32 # Length of String Offsets Set
diff --git a/lld/test/ELF/Inputs/debug-names-parent-idx-2.s b/lld/test/ELF/Inputs/debug-names-parent-idx-2.s
index 7eedaaee549450..ebd93c01d85189 100644
--- a/lld/test/ELF/Inputs/debug-names-parent-idx-2.s
+++ b/lld/test/ELF/Inputs/debug-names-parent-idx-2.s
@@ -1,25 +1,25 @@
#-- input file: debug-names-parent-idx-2.cpp
## Generated with:
-##
+
## - clang++ -g -O0 -gpubnames -fdebug-compilation-dir='parent-idx-test' \
## -S debug-names-parent-idx-2.cpp -o debug-names-parent-idx-2.s
-##
+
## foo.h contents:
-##
+
## int foo();
-##
+
## struct foo {
## int x;
## char y;
## struct foo *foo_ptr;
## };
-##
+
## namespace parent_test {
## int foo();
## }
-##
+
## debug-names-parent-index-2.cpp contents:
-##
+
## #include "foo.h"
## int foo () {
## struct foo struct2;
@@ -28,13 +28,13 @@
## struct2.foo_ptr = nullptr;
## return struct2.x * (int) struct2.y;
## }
-##
+
## namespace parent_test {
## int foo () {
## return 25;
## }
## }
-##
+
.text
.globl _Z3foov # -- Begin function _Z3foov
.p2align 4, 0x90
@@ -97,86 +97,6 @@ _ZN11parent_test3fooEv: # @_ZN11parent_test3fooEv
.byte 1 # DWARF Unit Type
.byte 8 # Address Size (in bytes)
.long .debug_abbrev # Offset Into Abbrev. Section
- .byte 1 # Abbrev [1] 0xc:0x76 DW_TAG_compile_unit
- .byte 0 # DW_AT_producer
- .short 33 # DW_AT_language
- .byte 1 # DW_AT_name
- .long .Lstr_offsets_base0 # DW_AT_str_offsets_base
- .long .Lline_table_start0 # DW_AT_stmt_list
- .byte 2 # DW_AT_comp_dir
- .byte 0 # DW_AT_low_pc
- .long .Lfunc_end1-.Lfunc_begin0 # DW_AT_high_pc
- .long .Laddr_table_base0 # DW_AT_addr_base
- .byte 2 # Abbrev [2] 0x23:0x4 DW_TAG_base_type
- .byte 3 # DW_AT_name
- .byte 5 # DW_AT_encoding
- .byte 4 # DW_AT_byte_size
- .byte 3 # Abbrev [3] 0x27:0x1c DW_TAG_subprogram
- .byte 0 # DW_AT_low_pc
- .long .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc
- .byte 1 # DW_AT_frame_base
- .byte 86
- .byte 5 # DW_AT_linkage_name
- .byte 6 # DW_AT_name
- .byte 0 # DW_AT_decl_file
- .byte 4 # DW_AT_decl_line
- .long 35 # DW_AT_type
- # DW_AT_external
- .byte 4 # Abbrev [4] 0x37:0xb DW_TAG_variable
- .byte 2 # DW_AT_location
- .byte 145
- .byte 112
- .byte 8 # DW_AT_name
- .byte 0 # DW_AT_decl_file
- .byte 5 # DW_AT_decl_line
- .long 86 # DW_AT_type
- .byte 0 # End Of Children Mark
- .byte 5 # Abbrev [5] 0x43:0x13 DW_TAG_namespace
- .byte 4 # DW_AT_name
- .byte 6 # Abbrev [6] 0x45:0x10 DW_TAG_subprogram
- .byte 1 # DW_AT_low_pc
- .long .Lfunc_end1-.Lfunc_begin1 # DW_AT_high_pc
- .byte 1 # DW_AT_frame_base
- .byte 86
- .byte 7 # DW_AT_linkage_name
- .byte 6 # DW_AT_name
- .byte 0 # DW_AT_decl_file
- .byte 16 # DW_AT_decl_line
- .long 35 # DW_AT_type
- # DW_AT_external
- .byte 0 # End Of Children Mark
- .byte 7 # Abbrev [7] 0x56:0x22 DW_TAG_structure_type
- .byte 5 # DW_AT_calling_convention
- .byte 6 # DW_AT_name
- .byte 16 # DW_AT_byte_size
- .byte 1 # DW_AT_decl_file
- .byte 4 # DW_AT_decl_line
- .byte 8 # Abbrev [8] 0x5c:0x9 DW_TAG_member
- .byte 9 # DW_AT_name
- .long 35 # DW_AT_type
- .byte 1 # DW_AT_decl_file
- .byte 5 # DW_AT_decl_line
- .byte 0 # DW_AT_data_member_location
- .byte 8 # Abbrev [8] 0x65:0x9 DW_TAG_member
- .byte 10 # DW_AT_name
- .long 120 # DW_AT_type
- .byte 1 # DW_AT_decl_file
- .byte 6 # DW_AT_decl_line
- .byte 4 # DW_AT_data_member_location
- .byte 8 # Abbrev [8] 0x6e:0x9 DW_TAG_member
- .byte 12 # DW_AT_name
- .long 124 # DW_AT_type
- .byte 1 # DW_AT_decl_file
- .byte 7 # DW_AT_decl_line
- .byte 8 # DW_AT_data_member_location
- .byte 0 # End Of Children Mark
- .byte 2 # Abbrev [2] 0x78:0x4 DW_TAG_base_type
- .byte 11 # DW_AT_name
- .byte 6 # DW_AT_encoding
- .byte 1 # DW_AT_byte_size
- .byte 9 # Abbrev [9] 0x7c:0x5 DW_TAG_pointer_type
- .long 86 # DW_AT_type
- .byte 0 # End Of Children Mark
.Ldebug_info_end0:
.section .debug_str_offsets,"", at progbits
.long 56 # Length of String Offsets Set
diff --git a/lld/test/ELF/debug-names-bad-aug-string.s b/lld/test/ELF/debug-names-bad-aug-string.s
index ec1651362497e6..0c4f625fad7c18 100644
--- a/lld/test/ELF/debug-names-bad-aug-string.s
+++ b/lld/test/ELF/debug-names-bad-aug-string.s
@@ -1,31 +1,30 @@
-# REQUIRES: x86
-# RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t1.o
-# RUN: llvm-mc -filetype=obj -triple=x86_64 %p/Inputs/debug-names-2.s -o %t2.o
-# RUN: ld.lld --debug-names %t1.o %t2.o -o %t
+// This file was generated by copying debug-names.s and manually
+// editing the 'Header: augmentation string' in the .debug_names section.
-# RUN: llvm-dwarfdump -debug-names %t | FileCheck %s --check-prefix=DWARF
+// REQUIRES: x86
+// RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t1.o
+// RUN: llvm-mc -filetype=obj -triple=x86_64 %p/Inputs/debug-names-2.s -o %t2.o
+// RUN: ld.lld --debug-names %t1.o %t2.o -o %t
-# DWARF: .debug_names contents:
-# DWARF: Name Index @ 0x0 {
-# DWARF-NEXT: Header {
-# DWARF-NEXT: Length: 0xCC
-# DWARF-NEXT: Format: DWARF32
-# DWARF-NEXT: Version: 5
-# DWARF-NEXT: CU count: 2
-# DWARF-NEXT: Local TU count: 0
-# DWARF-NEXT: Foreign TU count: 0
-# DWARF-NEXT: Bucket count: 5
-# DWARF-NEXT: Name count: 5
-# DWARF-NEXT: Abbreviations table size: 0x1F
-# DWARF-NEXT: Augmentation: ' '
-# DWARF: Compilation Unit offsets [
-# DWARF-NEXT: CU[0]: 0x00000000
-# DWARF-NEXT: CU[1]: 0x00000041
+// RUN: llvm-dwarfdump -debug-names %t \
+// RUN: | FileCheck -DFILE=%t1.o -DFILE=%t2.o %s --check-prefix=DWARF
-##
-## This file was generated by copying debug-names.s and manually
-## editing the 'Header: augmentation string' in the .debug_names section.
-##
+// DWARF: .debug_names contents:
+// DWARF: Name Index @ 0x0 {
+// DWARF-NEXT: Header {
+// DWARF-NEXT: Length: 0xCC
+// DWARF-NEXT: Format: DWARF32
+// DWARF-NEXT: Version: 5
+// DWARF-NEXT: CU count: 2
+// DWARF-NEXT: Local TU count: 0
+// DWARF-NEXT: Foreign TU count: 0
+// DWARF-NEXT: Bucket count: 5
+// DWARF-NEXT: Name count: 5
+// DWARF-NEXT: Abbreviations table size: 0x1F
+// DWARF-NEXT: Augmentation: ' '
+// DWARF: Compilation Unit offsets [
+// DWARF-NEXT: CU[0]: 0x00000000
+// DWARF-NEXT: CU[1]: 0x0000000c
.text
.globl _Z2f12t1 # -- Begin function _Z2f12t1
.p2align 4, 0x90
@@ -60,41 +59,6 @@ _Z2f12t1: # @_Z2f12t1
.byte 1 # DWARF Unit Type
.byte 8 # Address Size (in bytes)
.long .debug_abbrev # Offset Into Abbrev. Section
- .byte 1 # Abbrev [1] 0xc:0x35 DW_TAG_compile_unit
- .byte 0 # DW_AT_producer
- .short 33 # DW_AT_language
- .byte 1 # DW_AT_name
- .long .Lstr_offsets_base0 # DW_AT_str_offsets_base
- .long .Lline_table_start0 # DW_AT_stmt_list
- .byte 2 # DW_AT_comp_dir
- .byte 0 # DW_AT_low_pc
- .long .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc
- .long .Laddr_table_base0 # DW_AT_addr_base
- .byte 2 # Abbrev [2] 0x23:0x17 DW_TAG_subprogram
- .byte 0 # DW_AT_low_pc
- .long .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc
- .byte 1 # DW_AT_frame_base
- .byte 86
- .byte 3 # DW_AT_linkage_name
- .byte 4 # DW_AT_name
- .byte 0 # DW_AT_decl_file
- .byte 2 # DW_AT_decl_line
- # DW_AT_external
- .byte 3 # Abbrev [3] 0x2f:0xa DW_TAG_formal_parameter
- .byte 2 # DW_AT_location
- .byte 145
- .byte 127
- .byte 0 # DW_AT_decl_file
- .byte 2 # DW_AT_decl_line
- .long 58 # DW_AT_type
- .byte 0 # End Of Children Mark
- .byte 4 # Abbrev [4] 0x3a:0x6 DW_TAG_structure_type
- .byte 5 # DW_AT_calling_convention
- .byte 5 # DW_AT_name
- .byte 1 # DW_AT_byte_size
- .byte 0 # DW_AT_decl_file
- .byte 1 # DW_AT_decl_line
- .byte 0 # End Of Children Mark
.Ldebug_info_end0:
.section .debug_str_offsets,"", at progbits
.long 28 # Length of String Offsets Set
diff --git a/lld/test/ELF/debug-names-bad-die-idx-sizes.s b/lld/test/ELF/debug-names-bad-die-idx-sizes.s
index 2da278a8dd5b7c..e73d013f3b0edb 100644
--- a/lld/test/ELF/debug-names-bad-die-idx-sizes.s
+++ b/lld/test/ELF/debug-names-bad-die-idx-sizes.s
@@ -1,20 +1,20 @@
-# REQUIRES: x86
-# RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t1.o
-#
-# RUN: not ld.lld --debug-names %t1.o -o /dev/null 2>&1 | FileCheck %s
-#
-# CHECK: error: {{.*}}:(.debug_names): encountered unexpected end of section while reading entry
+// This file was generated by first compiling main.cpp:
+// clang++ -g -O0 -S -gpubnames -fdebug-compilation-dir='debug-names-test' \
+// main.cpp
+// Then manually edit the .debug_names section. In the entries, change the
+// size of the DW_IDX_die_offset from '.long' to '.byte'.
+
+// Contents of main.cpp:
+// int main (int argc, char **argv) { }
+
+// REQUIRES: x86
+// RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t1.o
+
+// RUN: not ld.lld --debug-names %t1.o -o /dev/null 2>&1 \
+// RUN: | FileCheck -DFILE=%t1.o %s
+
+// CHECK: error: {{.*}}:(.debug_names): encountered unexpected end of section while reading entry
-## This file was generated by first compiling main.cpp:
-## clang++ -g -O0 -S -gpubnames -fdebug-compilation-dir='debug-names-test' \
-## main.cpp
-##
-## Then manually edit the .debug_names section. In the entries, change the
-## size of the DW_IDX_die_offset from '.long' to '.byte'.
-##
-## main.cpp:
-## int main (int argc, char **argv) { }
-##
.text
.globl main # -- Begin function main
.p2align 4, 0x90
diff --git a/lld/test/ELF/debug-names-bad-name-count.s b/lld/test/ELF/debug-names-bad-name-count.s
index 4acfa182b11a91..cda4484b0e4c67 100644
--- a/lld/test/ELF/debug-names-bad-name-count.s
+++ b/lld/test/ELF/debug-names-bad-name-count.s
@@ -1,23 +1,24 @@
-# REQUIRES: x86
-# RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t1.o
-#
-# RUN: not ld.lld --debug-names %t1.o -o /dev/null 2>&1 | FileCheck %s
-#
-# CHECK: error: {{.*}}:(.debug_names): encountered unexpected end of section while reading entry
-# CHECK: error: {{.*}}:(.debug_names): encountered unexpected end of section while reading entry
-# CHECK: error: {{.*}}:(.debug_names): encountered unexpected end of section while reading entry
-# CHECK: error: {{.*}}:(.debug_names): encountered unexpected end of section while reading entry
+// REQUIRES: x86
+// RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t1.o
+
+// RUN: not ld.lld --debug-names %t1.o -o /dev/null 2>&1 \
+// RUN: FileCheck -DFILE=%t1.o %s
+
+// CHECK: error: {{.*}}:(.debug_names): encountered unexpected end of section while reading entry
+// CHECK: error: {{.*}}:(.debug_names): encountered unexpected end of section while reading entry
+// CHECK: error: {{.*}}:(.debug_names): encountered unexpected end of section while reading entry
+// CHECK: error: {{.*}}:(.debug_names): encountered unexpected end of section while reading entry
+
+// This file was generated by first compiling main.cpp:
+// clang++ -g -O0 -S -gpubnames -fdebug-compilation-dir='debug-names-test' \
+// main.cpp
+
+// Then manually edit .debug_names section: change value for
+// 'Header: name count' from 3 to 4.
+
+// Contents of main.cpp:
+// int main (int argc, char **argv) { }
-## This file was generated by first compiling main.cpp:
-## clang++ -g -O0 -S -gpubnames -fdebug-compilation-dir='debug-names-test' \
-## main.cpp
-##
-## Then manually edit .debug_names section: change value for
-## 'Header: name count' from 3 to 4.
-##
-## main.cpp:
-## int main (int argc, char **argv) { }
-##
.text
.globl main # -- Begin function main
.p2align 4, 0x90
diff --git a/lld/test/ELF/debug-names-bad-offsets-sizes.s b/lld/test/ELF/debug-names-bad-offsets-sizes.s
index e11d19a9bf579c..3e7f36b2e2175e 100644
--- a/lld/test/ELF/debug-names-bad-offsets-sizes.s
+++ b/lld/test/ELF/debug-names-bad-offsets-sizes.s
@@ -1,22 +1,23 @@
-# REQUIRES: x86
-# RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t1.o
-#
-# RUN: not ld.lld --debug-names %t1.o -o /dev/null 2>&1 | FileCheck %s
-#
-# CHECK: error: {{.*}}:(.debug_names): encountered unexpected end of section while reading entry
-# CHECK: error: {{.*}}:(.debug_names): encountered unexpected end of section while reading entry
-# CHECK: error: {{.*}}:(.debug_names): encountered unexpected end of section while reading entry
+// This file was generated by first compiling main.cpp:
+// clang++ -g -O0 -S -gpubnames -fdebug-compilation-dir='debug-names-test' \
+// main.cpp
+
+// Then manually edit .debug_names section. Change the sizes of
+// 'Offset in Bucket' values from '.long' to '.byte'.
+
+// Contentsof main.cpp:
+// int main (int argc, char **argv) { }
+
+// REQUIRES: x86
+// RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t1.o
+
+// RUN: not ld.lld --debug-names %t1.o -o /dev/null 2>&1 \
+// RUN: | FileCheck -DFILE=%t1.o %s
+
+// CHECK: error: {{.*}}:(.debug_names): encountered unexpected end of section while reading entry
+// CHECK: error: {{.*}}:(.debug_names): encountered unexpected end of section while reading entry
+// CHECK: error: {{.*}}:(.debug_names): encountered unexpected end of section while reading entry
-## This file was generated by first compiling main.cpp:
-## clang++ -g -O0 -S -gpubnames -fdebug-compilation-dir='debug-names-test' \
-## main.cpp
-##
-## Then manually edit .debug_names section. Change the sizes of
-## 'Offset in Bucket' values from '.long' to '.byte'.
-##
-## main.cpp:
-## int main (int argc, char **argv) { }
-##
.text
.globl main # -- Begin function main
.p2align 4, 0x90
diff --git a/lld/test/ELF/debug-names-bad-version.s b/lld/test/ELF/debug-names-bad-version.s
index bf1855151c20da..6a299805ca090f 100644
--- a/lld/test/ELF/debug-names-bad-version.s
+++ b/lld/test/ELF/debug-names-bad-version.s
@@ -1,15 +1,14 @@
-# REQUIRES: x86
-# RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t1.o
-# RUN: llvm-mc -filetype=obj -triple=x86_64 %p/Inputs/debug-names-2.s -o %t2.o
-#
-# RUN: not ld.lld --debug-names %t1.o %t2.o -o /dev/null 2>&1 | FileCheck %s
-#
-# CHECK: error: {{.*}}:(.debug_names): unsupported version
-##
-## This file was generated by copying debug-names.s and manually
-## editing the 'Header: version' in the .debug_names section (changed it from
-## 5 to 4).
+// This file was generated by copying debug-names.s and manually
+// editing the 'Header: version' in the .debug_names section (changed it from
+// 5 to 4).
+// REQUIRES: x86
+// RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t1.o
+// RUN: llvm-mc -filetype=obj -triple=x86_64 %p/Inputs/debug-names-2.s -o %t2.o
+// RUN: not ld.lld --debug-names %t1.o %t2.o -o /dev/null 2>&1 | FileCheck %s
+
+// CHECK: error: {{.*}}:(.debug_names): unsupported version
+
.text
.globl _Z2f12t1 # -- Begin function _Z2f12t1
.p2align 4, 0x90
diff --git a/lld/test/ELF/debug-names-dwarf64.s b/lld/test/ELF/debug-names-dwarf64.s
index 4391142c5558c2..790f2ddeba3972 100644
--- a/lld/test/ELF/debug-names-dwarf64.s
+++ b/lld/test/ELF/debug-names-dwarf64.s
@@ -1,17 +1,17 @@
-# REQUIRES: x86
-# RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t1.o
-#
-# RUN: not ld.lld --debug-names %t1.o -o /dev/null 2>&1 | FileCheck %s
-#
-# CHECK: error: {{.*}}(.debug_names): unsupported DWARF64
-##
-## This file was generated by:
-## clang++ -g -O0 -S -fdebug-compilation-dir='debug-names-test' \
-## -gdwarf64 -gpubnames main.cpp
-##
-## main.cpp
-## int main (int argc, char **argv) { }
-##
+// This file was generated by:
+// clang++ -g -O0 -S -fdebug-compilation-dir='debug-names-test' \
+// -gdwarf64 -gpubnames main.cpp
+
+// Contents of main.cpp
+// int main (int argc, char **argv) { }
+
+// REQUIRES: x86
+// RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t1.o
+// RUN: not ld.lld --debug-names %t1.o -o /dev/null 2>&1 \
+// RUN: | FileCheck -DFILE=%t1.o %s
+
+// CHECK: error: {{.*}}(.debug_names): unsupported DWARF64
+
.text
.globl main # -- Begin function main
.p2align 4, 0x90
diff --git a/lld/test/ELF/debug-names-invalid-abbrev-code.s b/lld/test/ELF/debug-names-invalid-abbrev-code.s
index 14970e0d10433c..54c0105ae56b5e 100644
--- a/lld/test/ELF/debug-names-invalid-abbrev-code.s
+++ b/lld/test/ELF/debug-names-invalid-abbrev-code.s
@@ -1,20 +1,20 @@
-# REQUIRES: x86
-# RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t1.o
-#
-# RUN: not ld.lld --debug-names %t1.o -o /dev/null 2>&1 | FileCheck %s
-#
-# CHECK: error: {{.*}}(.debug_names): invalid abbrev code in entry
-# CHECK: error: {{.*}}(.debug_names): invalid abbrev code in entry
-##
-## This file was generated by:
-## clang++ -g -O0 -S -fdebug-compilation-dir='debug-names-test' \
-## -gpubnames main.cpp
-##
-## Then manually changing an abbrev code.
-##
-## main.cpp
-## int main (int argc, char **argv) { }
-##
+// This file was generated by:
+// clang++ -g -O0 -S -fdebug-compilation-dir='debug-names-test' \
+// -gpubnames main.cpp
+
+// Then manually changing an abbrev code.
+
+// Contents of main.cpp
+// int main (int argc, char **argv) { }
+
+// REQUIRES: x86
+// RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t1.o
+// RUN: not ld.lld --debug-names %t1.o -o /dev/null 2>&1 \
+// RUN: | FileCheck -DFILE=%t1.o %s
+
+// CHECK: error: {{.*}}(.debug_names): invalid abbrev code in entry
+// CHECK: error: {{.*}}(.debug_names): invalid abbrev code in entry
+
.text
.globl main # -- Begin function main
.p2align 4, 0x90
diff --git a/lld/test/ELF/debug-names-invalid-attribute-2.s b/lld/test/ELF/debug-names-invalid-attribute-2.s
index 44e74911bd0353..16706f0054c312 100644
--- a/lld/test/ELF/debug-names-invalid-attribute-2.s
+++ b/lld/test/ELF/debug-names-invalid-attribute-2.s
@@ -1,20 +1,20 @@
-# REQUIRES: x86
-# RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t1.o
-#
-# RUN: not ld.lld --debug-names %t1.o -o /dev/null 2>&1 | FileCheck %s
-#
-# CHECK: error: {{.*}}(.debug_names): error while reading attributes: unexpected end of data at offset 0x80 while reading [0x7e, 0x82)
-##
-## This file was generated by:
-## clang++ -g -O0 -S -fdebug-compilation-dir='debug-names-test' \
-## -gpubnames main.cpp
-##
-## Then manually editing .debug_names section, commenting out a
-## DW_IDX_die_offset in an entry.
-##
-## main.cpp
-## int main (int argc, char **argv) { }
-##
+// This file was generated by:
+// clang++ -g -O0 -S -fdebug-compilation-dir='debug-names-test' \
+// -gpubnames main.cpp
+
+// Then manually editing .debug_names section, commenting out a
+// DW_IDX_die_offset in an entry.
+
+// Contents of main.cpp
+// int main (int argc, char **argv) { }
+
+// REQUIRES: x86
+// RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t1.o
+// RUN: not ld.lld --debug-names %t1.o -o /dev/null 2>&1 \
+// RUN: | FileCheck -DFILE=%t1.o %s
+
+// CHECK: error: {{.*}}(.debug_names): error while reading attributes: unexpected end of data at offset 0x80 while reading [0x7e, 0x82)
+
.text
.globl main # -- Begin function main
.p2align 4, 0x90
diff --git a/lld/test/ELF/debug-names-invalid-attribute-3.s b/lld/test/ELF/debug-names-invalid-attribute-3.s
index 1e6ea8074975f5..9b99cbe87d5a0e 100644
--- a/lld/test/ELF/debug-names-invalid-attribute-3.s
+++ b/lld/test/ELF/debug-names-invalid-attribute-3.s
@@ -1,23 +1,22 @@
-# REQUIRES: x86
-# RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t1.o
-#
-# RUN: not ld.lld --debug-names %t1.o -o /dev/null 2>&1 | FileCheck %s
-#
-# CHECK: error: {{.*}}(.debug_names): invalid form for attribute
-##
-## This file was generated by:
-## clang++ -g -O0 -S -fdebug-compilation-dir='debug-names-test' \
-## -gpubnames main.cpp
-##
-##
-## Then manually changing the first .debug_names abbrev, so that the
-## DW_IDX_die_offset uses DW_FORM_flag_present (invalid) & the DW_IDX_parent
-## uses DW_FORM_ref4. Also updated the sizes of the values in the entry
-## that uses the abbrev, to match the sizes of the forms.
-##
-## main.cpp
-## int main (int argc, char **argv) { }
-##
+// This file was generated by:
+// clang++ -g -O0 -S -fdebug-compilation-dir='debug-names-test' \
+// -gpubnames main.cpp
+
+// Then manually changing the first .debug_names abbrev, so that the
+// DW_IDX_die_offset uses DW_FORM_flag_present (invalid) & the DW_IDX_parent
+// uses DW_FORM_ref4. Also updated the sizes of the values in the entry
+// that uses the abbrev, to match the sizes of the forms.
+
+// Contents of main.cpp
+// int main (int argc, char **argv) { }
+
+// REQUIRES: x86
+// RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t1.o
+// RUN: not ld.lld --debug-names %t1.o -o /dev/null 2>&1 \
+// RUN: | FileCheck -DFILE=%t1.o %s
+
+// CHECK: error: {{.*}}(.debug_names): invalid form for attribute
+
.text
.globl main # -- Begin function main
.p2align 4, 0x90
diff --git a/lld/test/ELF/debug-names-invalid-attribute.s b/lld/test/ELF/debug-names-invalid-attribute.s
index 9b1a915d81f882..303337c0295da7 100644
--- a/lld/test/ELF/debug-names-invalid-attribute.s
+++ b/lld/test/ELF/debug-names-invalid-attribute.s
@@ -1,13 +1,13 @@
-# REQUIRES: x86
-# RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t1.o
-#
-# RUN: not ld.lld --debug-names %t1.o -o /dev/null 2>&1 | FileCheck %s
-#
-# CHECK: error: {{.*}}:(.debug_names): unrecognized form encoding 16 in .debug_names abbrev table
-##
-## Generated by copying debug-names.s and manually editing it to make some
-## of the abbrev attributes invalid.
+// Generated by copying debug-names.s and manually editing it to make some
+// of the abbrev attributes invalid.
+// REQUIRES: x86
+// RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t1.o
+// RUN: not ld.lld --debug-names %t1.o -o /dev/null 2>&1 \
+// RUN: | FileCheck -DFILE=%t1.o %s
+
+// CHECK: error: {{.*}}:(.debug_names): unrecognized form encoding 16 in .debug_names abbrev table
+
.text
.globl _Z2f12t1 # -- Begin function _Z2f12t1
.p2align 4, 0x90
@@ -42,41 +42,6 @@ _Z2f12t1: # @_Z2f12t1
.byte 1 # DWARF Unit Type
.byte 8 # Address Size (in bytes)
.long .debug_abbrev # Offset Into Abbrev. Section
- .byte 1 # Abbrev [1] 0xc:0x35 DW_TAG_compile_unit
- .byte 0 # DW_AT_producer
- .short 33 # DW_AT_language
- .byte 1 # DW_AT_name
- .long .Lstr_offsets_base0 # DW_AT_str_offsets_base
- .long .Lline_table_start0 # DW_AT_stmt_list
- .byte 2 # DW_AT_comp_dir
- .byte 0 # DW_AT_low_pc
- .long .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc
- .long .Laddr_table_base0 # DW_AT_addr_base
- .byte 2 # Abbrev [2] 0x23:0x17 DW_TAG_subprogram
- .byte 0 # DW_AT_low_pc
- .long .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc
- .byte 1 # DW_AT_frame_base
- .byte 86
- .byte 3 # DW_AT_linkage_name
- .byte 4 # DW_AT_name
- .byte 0 # DW_AT_decl_file
- .byte 2 # DW_AT_decl_line
- # DW_AT_external
- .byte 3 # Abbrev [3] 0x2f:0xa DW_TAG_formal_parameter
- .byte 2 # DW_AT_location
- .byte 145
- .byte 127
- .byte 0 # DW_AT_decl_file
- .byte 2 # DW_AT_decl_line
- .long 58 # DW_AT_type
- .byte 0 # End Of Children Mark
- .byte 4 # Abbrev [4] 0x3a:0x6 DW_TAG_structure_type
- .byte 5 # DW_AT_calling_convention
- .byte 5 # DW_AT_name
- .byte 1 # DW_AT_byte_size
- .byte 0 # DW_AT_decl_file
- .byte 1 # DW_AT_decl_line
- .byte 0 # End Of Children Mark
.Ldebug_info_end0:
.section .debug_str_offsets,"", at progbits
.long 28 # Length of String Offsets Set
diff --git a/lld/test/ELF/debug-names-invalid-flags.s b/lld/test/ELF/debug-names-invalid-flags.s
new file mode 100644
index 00000000000000..96cd4da243b688
--- /dev/null
+++ b/lld/test/ELF/debug-names-invalid-flags.s
@@ -0,0 +1,148 @@
+// This file was generated by:
+// clang++ -g -O0 -S -fdebug-compilation-dir='debug-names-test' \
+// -gpubnames main.cpp
+
+// Contents of main.cpp
+// int main (int argc, char **argv) { }
+
+// REQUIRES: x86
+// RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t1.o
+// RUN: not ld.lld --debug-names -r %t1.o -o /dev/null 2>&1 \
+// RUN: | FileCheck -DFILE=%t1.o %s
+
+// CHECK: error: -r and --debug-names may not be used together
+
+ .text
+ .globl main # -- Begin function main
+ .p2align 4, 0x90
+ .type main, at function
+main: # @main
+.Lfunc_begin0:
+ .cfi_startproc
+# %bb.0: # %entry
+ pushq %rbp
+ .cfi_def_cfa_offset 16
+ .cfi_offset %rbp, -16
+ movq %rsp, %rbp
+ .cfi_def_cfa_register %rbp
+ movl %edi, -4(%rbp)
+ movq %rsi, -16(%rbp)
+.Ltmp0:
+ xorl %eax, %eax
+ popq %rbp
+ .cfi_def_cfa %rsp, 8
+ retq
+.Ltmp1:
+.Lfunc_end0:
+ .size main, .Lfunc_end0-main
+ .cfi_endproc
+ # -- End function
+ .section .debug_abbrev,"", at progbits
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 0 # EOM(3)
+ .section .debug_info,"", at progbits
+.Lcu_begin0:
+ .long .Ldebug_info_end0-.Ldebug_info_start0 # Length of Unit
+.Ldebug_info_start0:
+ .short 5 # DWARF version number
+ .byte 1 # DWARF Unit Type
+ .byte 8 # Address Size (in bytes)
+ .long .debug_abbrev # Offset Into Abbrev. Section
+.Ldebug_info_end0:
+ .section .debug_str_offsets,"", at progbits
+ .long 36 # Length of String Offsets Set
+ .short 5
+ .short 0
+.Lstr_offsets_base0:
+ .section .debug_str,"MS", at progbits,1
+.Linfo_string0:
+ .asciz "clang version 19.0.0git (git at github.com:llvm/llvm-project.git d33d5630b281debe6eabd67e323bcf767340fb6a)" # string offset=0
+.Linfo_string1:
+ .asciz "main.cpp" # string offset=104
+.Linfo_string2:
+ .asciz "debug-names-test" # string offset=113
+.Linfo_string3:
+ .asciz "main" # string offset=130
+.Linfo_string4:
+ .asciz "int" # string offset=135
+.Linfo_string5:
+ .asciz "argc" # string offset=139
+.Linfo_string6:
+ .asciz "argv" # string offset=144
+.Linfo_string7:
+ .asciz "char" # string offset=149
+.Laddr_table_base0:
+ .quad .Lfunc_begin0
+.Ldebug_addr_end0:
+ .section .debug_names,"", at progbits
+ .long .Lnames_end0-.Lnames_start0 # Header: unit length
+.Lnames_start0:
+ .short 5 # Header: version
+ .short 0 # Header: padding
+ .long 1 # Header: compilation unit count
+ .long 0 # Header: local type unit count
+ .long 0 # Header: foreign type unit count
+ .long 3 # Header: bucket count
+ .long 3 # Header: name count
+ .long .Lnames_abbrev_end0-.Lnames_abbrev_start0 # Header: abbreviation table size
+ .long 8 # Header: augmentation string size
+ .ascii "LLVM0700" # Header: augmentation string
+ .long .Lcu_begin0 # Compilation unit 0
+ .long 0 # Bucket 0
+ .long 1 # Bucket 1
+ .long 2 # Bucket 2
+ .long 2090499946 # Hash in Bucket 1
+ .long 193495088 # Hash in Bucket 2
+ .long 2090147939 # Hash in Bucket 2
+ .long .Linfo_string3 # String in Bucket 1: main
+ .long .Linfo_string4 # String in Bucket 2: int
+ .long .Linfo_string7 # String in Bucket 2: char
+ .long .Lnames0-.Lnames_entries0 # Offset in Bucket 1
+ .long .Lnames1-.Lnames_entries0 # Offset in Bucket 2
+ .long .Lnames2-.Lnames_entries0 # Offset in Bucket 2
+.Lnames_abbrev_start0:
+ .byte 1 # Abbrev code
+ .byte 46 # DW_TAG_subprogram
+ .byte 3 # DW_IDX_die_offset
+ .byte 19 # DW_FORM_ref4
+ .byte 4 # DW_IDX_parent
+ .byte 25 # DW_FORM_flag_present
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev
+ .byte 2 # Abbrev code
+ .byte 36 # DW_TAG_base_type
+ .byte 3 # DW_IDX_die_offset
+ .byte 19 # DW_FORM_ref4
+ .byte 4 # DW_IDX_parent
+ .byte 25 # DW_FORM_flag_present
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev list
+.Lnames_abbrev_end0:
+.Lnames_entries0:
+.Lnames0:
+.L1:
+ .byte 1 # Abbreviation code
+ .long 35 # DW_IDX_die_offset
+ .byte 0 # DW_IDX_parent
+ # End of list: main
+.Lnames1:
+.L0:
+ .byte 2 # Abbreviation code
+ .long 73 # DW_IDX_die_offset
+ .byte 0 # DW_IDX_parent
+ # End of list: int
+.Lnames2:
+.L2:
+ .byte 2 # Abbreviation code
+ .long 87 # DW_IDX_die_offset
+ .byte 0 # DW_IDX_parent
+ # End of list: char
+ .p2align 2, 0x0
+.Lnames_end0:
+ .ident "clang version 19.0.0git (git at github.com:llvm/llvm-project.git d33d5630b281debe6eabd67e323bcf767340fb6a)"
+ .section ".note.GNU-stack","", at progbits
+ .addrsig
+ .section .debug_line,"", at progbits
+.Lline_table_start0:
diff --git a/lld/test/ELF/debug-names-invalid-parent-idx.s b/lld/test/ELF/debug-names-invalid-parent-idx.s
index be5df8b155250e..698183880445a6 100644
--- a/lld/test/ELF/debug-names-invalid-parent-idx.s
+++ b/lld/test/ELF/debug-names-invalid-parent-idx.s
@@ -1,22 +1,22 @@
-# REQUIRES: x86
-# RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t1.o
-#
-# RUN: not ld.lld --debug-names %t1.o -o /dev/null 2>&1 | FileCheck %s
-#
-# CHECK: error: {{.*}}(.debug_names): invalid form for DW_IDX_parent
-# CHECK: error: {{.*}}(.debug_names): invalid form for DW_IDX_parent
-# CHECK: error: {{.*}}(.debug_names): invalid form for DW_IDX_parent
-##
-## This file was generated by:
-## clang++ -g -O0 -S -fdebug-compilation-dir='debug-names-test' \
-## -gpubnames main.cpp
-##
-## Then manually editing .debug_names section, changing the form for a
-## DW_IDX_parent from DW_FORM_flag_present to DW_FORM_ref1 (invalid).
-##
-## main.cpp
-## int main (int argc, char **argv) { }
-##
+// This file was generated by:
+// clang++ -g -O0 -S -fdebug-compilation-dir='debug-names-test' \
+// -gpubnames main.cpp
+
+// Then manually editing .debug_names section, changing the form for a
+// DW_IDX_parent from DW_FORM_flag_present to DW_FORM_ref1 (invalid).
+
+// Contents of main.cpp
+// int main (int argc, char **argv) { }
+
+// REQUIRES: x86
+// RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t1.o
+// RUN: not ld.lld --debug-names %t1.o -o /dev/null 2>&1 \
+// RUN: | FileCheck -DFILE=%t1.o %s
+
+// CHECK: error: {{.*}}(.debug_names): invalid form for DW_IDX_parent
+// CHECK: error: {{.*}}(.debug_names): invalid form for DW_IDX_parent
+// CHECK: error: {{.*}}(.debug_names): invalid form for DW_IDX_parent
+
.text
.globl main # -- Begin function main
.p2align 4, 0x90
diff --git a/lld/test/ELF/debug-names-parent-idx.s b/lld/test/ELF/debug-names-parent-idx.s
index a4e8682cd9ee58..cda9203fd21670 100644
--- a/lld/test/ELF/debug-names-parent-idx.s
+++ b/lld/test/ELF/debug-names-parent-idx.s
@@ -1,188 +1,188 @@
-# REQUIRES: x86
-# RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t1.o
-# RUN: llvm-mc -filetype=obj -triple=x86_64 %p/Inputs/debug-names-parent-idx-2.s -o %t2.o
-# RUN: ld.lld --debug-names %t1.o %t2.o -o %t
+// Generated with:
-# RUN: llvm-dwarfdump -debug-names %t | FileCheck %s --check-prefix=DWARF
+// - clang++ -g -O0 -gpubnames -fdebug-compilation-dir='parent-idx-test' \
+// -S debug-names-parent-idx.cpp -o debug-names-parent-idx.s
+
+// foo.h contents:
+
+// int foo();
+
+// struct foo {
+// int x;
+// char y;
+// struct foo *foo_ptr;
+// };
+
+// namespace parent_test {
+// int foo();
+// }
+
+// debug-names-parent-idx.cpp contents:
+
+// #include "foo.h"
+// void bar (struct foo &foo, int junk) {
+// foo.x = foo.x * junk;
+// }
+// int main (int argc, char** argv) {
+// struct foo my_struct;
+// my_struct.x = 10;
+// my_struct.y = 'q';
+// my_struct.foo_ptr = nullptr;
+// int junk = foo();
+// bar(my_struct, junk);
+// int junk2 = parent_test::foo();
+// return 0;
+// }
+
+// REQUIRES: x86
+// RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t1.o
+// RUN: llvm-mc -filetype=obj -triple=x86_64 %p/Inputs/debug-names-parent-idx-2.s -o %t2.o
+// RUN: ld.lld --debug-names %t1.o %t2.o -o %t
+
+// RUN: llvm-dwarfdump -debug-names %t \
+// RUN: | FileCheck -DFILE=%t1.o -DFILE=%t2.o %s --check-prefix=DWARF
+
+// DWARF: .debug_names contents:
+// DWARF: Name Index @ 0x0 {
+// DWARF-NEXT: Header {
+// DWARF-NEXT: Length: 0x15C
+// DWARF-NEXT: Format: DWARF32
+// DWARF-NEXT: Version: 5
+// DWARF-NEXT: CU count: 2
+// DWARF-NEXT: Local TU count: 0
+// DWARF-NEXT: Foreign TU count: 0
+// DWARF-NEXT: Bucket count: 9
+// DWARF-NEXT: Name count: 9
+// DWARF-NEXT: Abbreviations table size: 0x33
+// DWARF-NEXT: Augmentation: 'LLVM0700'
+// DWARF: Compilation Unit offsets [
+// DWARF-NEXT: CU[0]: 0x00000000
+// DWARF-NEXT: CU[1]: 0x0000000c
+// DWARF: Abbreviations [
+// DWARF-NEXT: Abbreviation 0x1 {
+// DWARF-NEXT: Tag: DW_TAG_base_type
+// DWARF-NEXT: DW_IDX_die_offset: DW_FORM_ref4
+// DWARF-NEXT: DW_IDX_parent: DW_FORM_flag_present
+// DWARF-NEXT: DW_IDX_compile_unit: DW_FORM_data1
+// DWARF: Abbreviation 0x2 {
+// DWARF-NEXT: Tag: DW_TAG_subprogram
+// DWARF-NEXT: DW_IDX_die_offset: DW_FORM_ref4
+// DWARF-NEXT: DW_IDX_parent: DW_FORM_flag_present
+// DWARF-NEXT: DW_IDX_compile_unit: DW_FORM_data1
+// DWARF: Abbreviation 0x3 {
+// DWARF-NEXT: Tag: DW_TAG_structure_type
+// DWARF-NEXT: DW_IDX_die_offset: DW_FORM_ref4
+// DWARF-NEXT: DW_IDX_parent: DW_FORM_flag_present
+// DWARF-NEXT: DW_IDX_compile_unit: DW_FORM_data1
+// DWARF: Abbreviation 0x4 {
+// DWARF-NEXT: Tag: DW_TAG_subprogram
+// DWARF-NEXT: DW_IDX_die_offset: DW_FORM_ref4
+// DWARF-NEXT: DW_IDX_parent: DW_FORM_ref4
+// DWARF-NEXT: DW_IDX_compile_unit: DW_FORM_data1
+// DWARF: Abbreviation 0x5 {
+// DWARF-NEXT: Tag: DW_TAG_namespace
+// DWARF-NEXT: DW_IDX_die_offset: DW_FORM_ref4
+// DWARF-NEXT: DW_IDX_parent: DW_FORM_flag_present
+// DWARF-NEXT: DW_IDX_compile_unit: DW_FORM_data1
+// DWARF: String: 0x00000093 "bar"
+// DWARF-NEXT: Entry @ 0xf7 {
+// DWARF-NEXT: Abbrev: 0x2
+// DWARF-NEXT: Tag: DW_TAG_subprogram
+// DWARF-NEXT: DW_IDX_die_offset: 0x00000023
+// DWARF-NEXT: DW_IDX_parent: <parent not indexed>
+// DWARF-NEXT: DW_IDX_compile_unit: 0x00
+// DWARF: String: 0x000000a9 "int"
+// DWARF-NEXT: Entry @ 0xfe {
+// DWARF-NEXT: Abbrev: 0x1
+// DWARF-NEXT: Tag: DW_TAG_base_type
+// DWARF-NEXT: DW_IDX_die_offset: 0x0000008d
+// DWARF-NEXT: DW_IDX_parent: <parent not indexed>
+// DWARF-NEXT: DW_IDX_compile_unit: 0x00
+// DWARF-NEXT: }
+// DWARF-NEXT: Entry @ 0x104 {
+// DWARF-NEXT: Abbrev: 0x1
+// DWARF-NEXT: Tag: DW_TAG_base_type
+// DWARF-NEXT: DW_IDX_die_offset: 0x00000023
+// DWARF-NEXT: DW_IDX_parent: <parent not indexed>
+// DWARF-NEXT: DW_IDX_compile_unit: 0x01
+// DWARF: String: 0x000000ad "foo"
+// DWARF-NEXT: Entry @ 0x10b {
+// DWARF-NEXT: Abbrev: 0x3
+// DWARF-NEXT: Tag: DW_TAG_structure_type
+// DWARF-NEXT: DW_IDX_die_offset: 0x00000096
+// DWARF-NEXT: DW_IDX_parent: <parent not indexed>
+// DWARF-NEXT: DW_IDX_compile_unit: 0x00
+// DWARF-NEXT: }
+// DWARF-NEXT: Entry @ 0x111 {
+// DWARF-NEXT: Abbrev: 0x2
+// DWARF-NEXT: Tag: DW_TAG_subprogram
+// DWARF-NEXT: DW_IDX_die_offset: 0x00000027
+// DWARF-NEXT: DW_IDX_parent: <parent not indexed>
+// DWARF-NEXT: DW_IDX_compile_unit: 0x01
+// DWARF-NEXT: }
+// DWARF-NEXT: Entry @ 0x117 {
+// DWARF-NEXT: Abbrev: 0x4
+// DWARF-NEXT: Tag: DW_TAG_subprogram
+// DWARF-NEXT: DW_IDX_die_offset: 0x00000045
+// DWARF-NEXT: DW_IDX_parent: Entry @ 0x128
+// DWARF-NEXT: DW_IDX_compile_unit: 0x01
+// DWARF-NEXT: }
+// DWARF-NEXT: Entry @ 0x121 {
+// DWARF-NEXT: Abbrev: 0x3
+// DWARF-NEXT: Tag: DW_TAG_structure_type
+// DWARF-NEXT: DW_IDX_die_offset: 0x00000056
+// DWARF-NEXT: DW_IDX_parent: <parent not indexed>
+// DWARF-NEXT: DW_IDX_compile_unit: 0x01
+// DWARF: String: 0x00000196 "parent_test"
+// DWARF-NEXT: Entry @ 0x128 {
+// DWARF-NEXT: Abbrev: 0x5
+// DWARF-NEXT: Tag: DW_TAG_namespace
+// DWARF-NEXT: DW_IDX_die_offset: 0x00000043
+// DWARF-NEXT: DW_IDX_parent: <parent not indexed>
+// DWARF-NEXT: DW_IDX_compile_unit: 0x01
+// DWARF: String: 0x00000097 "_Z3barR3fooi"
+// DWARF-NEXT: Entry @ 0x12f {
+// DWARF-NEXT: Abbrev: 0x2
+// DWARF-NEXT: Tag: DW_TAG_subprogram
+// DWARF-NEXT: DW_IDX_die_offset: 0x00000023
+// DWARF-NEXT: DW_IDX_parent: <parent not indexed>
+// DWARF-NEXT: DW_IDX_compile_unit: 0x00
+// DWARF: String: 0x000000a4 "main"
+// DWARF-NEXT: Entry @ 0x136 {
+// DWARF-NEXT: Abbrev: 0x2
+// DWARF-NEXT: Tag: DW_TAG_subprogram
+// DWARF-NEXT: DW_IDX_die_offset: 0x00000046
+// DWARF-NEXT: DW_IDX_parent: <parent not indexed>
+// DWARF-NEXT: DW_IDX_compile_unit: 0x00
+// DWARF: String: 0x000000b5 "char"
+// DWARF-NEXT: Entry @ 0x13d {
+// DWARF-NEXT: Abbrev: 0x1
+// DWARF-NEXT: Tag: DW_TAG_base_type
+// DWARF-NEXT: DW_IDX_die_offset: 0x000000b8
+// DWARF-NEXT: DW_IDX_parent: <parent not indexed>
+// DWARF-NEXT: DW_IDX_compile_unit: 0x00
+// DWARF-NEXT: }
+// DWARF-NEXT: Entry @ 0x143 {
+// DWARF-NEXT: Abbrev: 0x1
+// DWARF-NEXT: Tag: DW_TAG_base_type
+// DWARF-NEXT: DW_IDX_die_offset: 0x00000078
+// DWARF-NEXT: DW_IDX_parent: <parent not indexed>
+// DWARF-NEXT: DW_IDX_compile_unit: 0x01
+// DWARF: String: 0x000001a2 "_ZN11parent_test3fooEv"
+// DWARF-NEXT: Entry @ 0x14a {
+// DWARF-NEXT: Abbrev: 0x4
+// DWARF-NEXT: Tag: DW_TAG_subprogram
+// DWARF-NEXT: DW_IDX_die_offset: 0x00000045
+// DWARF-NEXT: DW_IDX_parent: Entry @ 0x128
+// DWARF-NEXT: DW_IDX_compile_unit: 0x01
+// DWARF: String: 0x0000018e "_Z3foov"
+// DWARF-NEXT: Entry @ 0x155 {
+// DWARF-NEXT: Abbrev: 0x2
+// DWARF-NEXT: Tag: DW_TAG_subprogram
+// DWARF-NEXT: DW_IDX_die_offset: 0x00000027
+// DWARF-NEXT: DW_IDX_parent: <parent not indexed>
+// DWARF-NEXT: DW_IDX_compile_unit: 0x01
-# DWARF: .debug_names contents:
-# DWARF: Name Index @ 0x0 {
-# DWARF-NEXT: Header {
-# DWARF-NEXT: Length: 0x15C
-# DWARF-NEXT: Format: DWARF32
-# DWARF-NEXT: Version: 5
-# DWARF-NEXT: CU count: 2
-# DWARF-NEXT: Local TU count: 0
-# DWARF-NEXT: Foreign TU count: 0
-# DWARF-NEXT: Bucket count: 9
-# DWARF-NEXT: Name count: 9
-# DWARF-NEXT: Abbreviations table size: 0x33
-# DWARF-NEXT: Augmentation: 'LLVM0700'
-# DWARF: Compilation Unit offsets [
-# DWARF-NEXT: CU[0]: 0x00000000
-# DWARF-NEXT: CU[1]: 0x000000cc
-# DWARF: Abbreviations [
-# DWARF-NEXT: Abbreviation 0x1 {
-# DWARF-NEXT: Tag: DW_TAG_base_type
-# DWARF-NEXT: DW_IDX_die_offset: DW_FORM_ref4
-# DWARF-NEXT: DW_IDX_parent: DW_FORM_flag_present
-# DWARF-NEXT: DW_IDX_compile_unit: DW_FORM_data1
-# DWARF: Abbreviation 0x2 {
-# DWARF-NEXT: Tag: DW_TAG_subprogram
-# DWARF-NEXT: DW_IDX_die_offset: DW_FORM_ref4
-# DWARF-NEXT: DW_IDX_parent: DW_FORM_flag_present
-# DWARF-NEXT: DW_IDX_compile_unit: DW_FORM_data1
-# DWARF: Abbreviation 0x3 {
-# DWARF-NEXT: Tag: DW_TAG_structure_type
-# DWARF-NEXT: DW_IDX_die_offset: DW_FORM_ref4
-# DWARF-NEXT: DW_IDX_parent: DW_FORM_flag_present
-# DWARF-NEXT: DW_IDX_compile_unit: DW_FORM_data1
-# DWARF: Abbreviation 0x4 {
-# DWARF-NEXT: Tag: DW_TAG_subprogram
-# DWARF-NEXT: DW_IDX_die_offset: DW_FORM_ref4
-# DWARF-NEXT: DW_IDX_parent: DW_FORM_ref4
-# DWARF-NEXT: DW_IDX_compile_unit: DW_FORM_data1
-# DWARF: Abbreviation 0x5 {
-# DWARF-NEXT: Tag: DW_TAG_namespace
-# DWARF-NEXT: DW_IDX_die_offset: DW_FORM_ref4
-# DWARF-NEXT: DW_IDX_parent: DW_FORM_flag_present
-# DWARF-NEXT: DW_IDX_compile_unit: DW_FORM_data1
-# DWARF: String: 0x00000093 "bar"
-# DWARF-NEXT: Entry @ 0xf7 {
-# DWARF-NEXT: Abbrev: 0x2
-# DWARF-NEXT: Tag: DW_TAG_subprogram
-# DWARF-NEXT: DW_IDX_die_offset: 0x00000023
-# DWARF-NEXT: DW_IDX_parent: <parent not indexed>
-# DWARF-NEXT: DW_IDX_compile_unit: 0x00
-# DWARF: String: 0x000000a9 "int"
-# DWARF-NEXT: Entry @ 0xfe {
-# DWARF-NEXT: Abbrev: 0x1
-# DWARF-NEXT: Tag: DW_TAG_base_type
-# DWARF-NEXT: DW_IDX_die_offset: 0x0000008d
-# DWARF-NEXT: DW_IDX_parent: <parent not indexed>
-# DWARF-NEXT: DW_IDX_compile_unit: 0x00
-# DWARF-NEXT: }
-# DWARF-NEXT: Entry @ 0x104 {
-# DWARF-NEXT: Abbrev: 0x1
-# DWARF-NEXT: Tag: DW_TAG_base_type
-# DWARF-NEXT: DW_IDX_die_offset: 0x00000023
-# DWARF-NEXT: DW_IDX_parent: <parent not indexed>
-# DWARF-NEXT: DW_IDX_compile_unit: 0x01
-# DWARF: String: 0x000000ad "foo"
-# DWARF-NEXT: Entry @ 0x10b {
-# DWARF-NEXT: Abbrev: 0x3
-# DWARF-NEXT: Tag: DW_TAG_structure_type
-# DWARF-NEXT: DW_IDX_die_offset: 0x00000096
-# DWARF-NEXT: DW_IDX_parent: <parent not indexed>
-# DWARF-NEXT: DW_IDX_compile_unit: 0x00
-# DWARF-NEXT: }
-# DWARF-NEXT: Entry @ 0x111 {
-# DWARF-NEXT: Abbrev: 0x2
-# DWARF-NEXT: Tag: DW_TAG_subprogram
-# DWARF-NEXT: DW_IDX_die_offset: 0x00000027
-# DWARF-NEXT: DW_IDX_parent: <parent not indexed>
-# DWARF-NEXT: DW_IDX_compile_unit: 0x01
-# DWARF-NEXT: }
-# DWARF-NEXT: Entry @ 0x117 {
-# DWARF-NEXT: Abbrev: 0x4
-# DWARF-NEXT: Tag: DW_TAG_subprogram
-# DWARF-NEXT: DW_IDX_die_offset: 0x00000045
-# DWARF-NEXT: DW_IDX_parent: Entry @ 0x128
-# DWARF-NEXT: DW_IDX_compile_unit: 0x01
-# DWARF-NEXT: }
-# DWARF-NEXT: Entry @ 0x121 {
-# DWARF-NEXT: Abbrev: 0x3
-# DWARF-NEXT: Tag: DW_TAG_structure_type
-# DWARF-NEXT: DW_IDX_die_offset: 0x00000056
-# DWARF-NEXT: DW_IDX_parent: <parent not indexed>
-# DWARF-NEXT: DW_IDX_compile_unit: 0x01
-# DWARF: String: 0x00000196 "parent_test"
-# DWARF-NEXT: Entry @ 0x128 {
-# DWARF-NEXT: Abbrev: 0x5
-# DWARF-NEXT: Tag: DW_TAG_namespace
-# DWARF-NEXT: DW_IDX_die_offset: 0x00000043
-# DWARF-NEXT: DW_IDX_parent: <parent not indexed>
-# DWARF-NEXT: DW_IDX_compile_unit: 0x01
-# DWARF: String: 0x00000097 "_Z3barR3fooi"
-# DWARF-NEXT: Entry @ 0x12f {
-# DWARF-NEXT: Abbrev: 0x2
-# DWARF-NEXT: Tag: DW_TAG_subprogram
-# DWARF-NEXT: DW_IDX_die_offset: 0x00000023
-# DWARF-NEXT: DW_IDX_parent: <parent not indexed>
-# DWARF-NEXT: DW_IDX_compile_unit: 0x00
-# DWARF: String: 0x000000a4 "main"
-# DWARF-NEXT: Entry @ 0x136 {
-# DWARF-NEXT: Abbrev: 0x2
-# DWARF-NEXT: Tag: DW_TAG_subprogram
-# DWARF-NEXT: DW_IDX_die_offset: 0x00000046
-# DWARF-NEXT: DW_IDX_parent: <parent not indexed>
-# DWARF-NEXT: DW_IDX_compile_unit: 0x00
-# DWARF: String: 0x000000b5 "char"
-# DWARF-NEXT: Entry @ 0x13d {
-# DWARF-NEXT: Abbrev: 0x1
-# DWARF-NEXT: Tag: DW_TAG_base_type
-# DWARF-NEXT: DW_IDX_die_offset: 0x000000b8
-# DWARF-NEXT: DW_IDX_parent: <parent not indexed>
-# DWARF-NEXT: DW_IDX_compile_unit: 0x00
-# DWARF-NEXT: }
-# DWARF-NEXT: Entry @ 0x143 {
-# DWARF-NEXT: Abbrev: 0x1
-# DWARF-NEXT: Tag: DW_TAG_base_type
-# DWARF-NEXT: DW_IDX_die_offset: 0x00000078
-# DWARF-NEXT: DW_IDX_parent: <parent not indexed>
-# DWARF-NEXT: DW_IDX_compile_unit: 0x01
-# DWARF: String: 0x000001a2 "_ZN11parent_test3fooEv"
-# DWARF-NEXT: Entry @ 0x14a {
-# DWARF-NEXT: Abbrev: 0x4
-# DWARF-NEXT: Tag: DW_TAG_subprogram
-# DWARF-NEXT: DW_IDX_die_offset: 0x00000045
-# DWARF-NEXT: DW_IDX_parent: Entry @ 0x128
-# DWARF-NEXT: DW_IDX_compile_unit: 0x01
-# DWARF: String: 0x0000018e "_Z3foov"
-# DWARF-NEXT: Entry @ 0x155 {
-# DWARF-NEXT: Abbrev: 0x2
-# DWARF-NEXT: Tag: DW_TAG_subprogram
-# DWARF-NEXT: DW_IDX_die_offset: 0x00000027
-# DWARF-NEXT: DW_IDX_parent: <parent not indexed>
-# DWARF-NEXT: DW_IDX_compile_unit: 0x01
-
-#-- input file: debug-names-parent-idx.cpp
-## Generated with:
-##
-## - clang++ -g -O0 -gpubnames -fdebug-compilation-dir='parent-idx-test' \
-## -S debug-names-parent-idx.cpp -o debug-names-parent-idx.s
-##
-## foo.h contents:
-##
-## int foo();
-##
-## struct foo {
-## int x;
-## char y;
-## struct foo *foo_ptr;
-## };
-##
-## namespace parent_test {
-## int foo();
-## }
-##
-## debug-names-parent-idx.cpp contents:
-##
-## #include "foo.h"
-## void bar (struct foo &foo, int junk) {
-## foo.x = foo.x * junk;
-## }
-## int main (int argc, char** argv) {
-## struct foo my_struct;
-## my_struct.x = 10;
-## my_struct.y = 'q';
-## my_struct.foo_ptr = nullptr;
-## int junk = foo();
-## bar(my_struct, junk);
-## int junk2 = parent_test::foo();
-## return 0;
-## }
-##
.text
.globl _Z3barR3fooi # -- Begin function _Z3barR3fooi
.p2align 4, 0x90
@@ -261,136 +261,6 @@ main: # @main
.byte 1 # DWARF Unit Type
.byte 8 # Address Size (in bytes)
.long .debug_abbrev # Offset Into Abbrev. Section
- .byte 1 # Abbrev [1] 0xc:0xc0 DW_TAG_compile_unit
- .byte 0 # DW_AT_producer
- .short 33 # DW_AT_language
- .byte 1 # DW_AT_name
- .long .Lstr_offsets_base0 # DW_AT_str_offsets_base
- .long .Lline_table_start0 # DW_AT_stmt_list
- .byte 2 # DW_AT_comp_dir
- .byte 0 # DW_AT_low_pc
- .long .Lfunc_end1-.Lfunc_begin0 # DW_AT_high_pc
- .long .Laddr_table_base0 # DW_AT_addr_base
- .byte 2 # Abbrev [2] 0x23:0x23 DW_TAG_subprogram
- .byte 0 # DW_AT_low_pc
- .long .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc
- .byte 1 # DW_AT_frame_base
- .byte 86
- .byte 3 # DW_AT_linkage_name
- .byte 4 # DW_AT_name
- .byte 0 # DW_AT_decl_file
- .byte 3 # DW_AT_decl_line
- # DW_AT_external
- .byte 3 # Abbrev [3] 0x2f:0xb DW_TAG_formal_parameter
- .byte 2 # DW_AT_location
- .byte 145
- .byte 120
- .byte 7 # DW_AT_name
- .byte 0 # DW_AT_decl_file
- .byte 3 # DW_AT_decl_line
- .long 145 # DW_AT_type
- .byte 3 # Abbrev [3] 0x3a:0xb DW_TAG_formal_parameter
- .byte 2 # DW_AT_location
- .byte 145
- .byte 116
- .byte 12 # DW_AT_name
- .byte 0 # DW_AT_decl_file
- .byte 3 # DW_AT_decl_line
- .long 141 # DW_AT_type
- .byte 0 # End Of Children Mark
- .byte 4 # Abbrev [4] 0x46:0x47 DW_TAG_subprogram
- .byte 1 # DW_AT_low_pc
- .long .Lfunc_end1-.Lfunc_begin1 # DW_AT_high_pc
- .byte 1 # DW_AT_frame_base
- .byte 86
- .byte 5 # DW_AT_name
- .byte 0 # DW_AT_decl_file
- .byte 7 # DW_AT_decl_line
- .long 141 # DW_AT_type
- # DW_AT_external
- .byte 3 # Abbrev [3] 0x55:0xb DW_TAG_formal_parameter
- .byte 2 # DW_AT_location
- .byte 145
- .byte 120
- .byte 13 # DW_AT_name
- .byte 0 # DW_AT_decl_file
- .byte 7 # DW_AT_decl_line
- .long 141 # DW_AT_type
- .byte 3 # Abbrev [3] 0x60:0xb DW_TAG_formal_parameter
- .byte 2 # DW_AT_location
- .byte 145
- .byte 112
- .byte 14 # DW_AT_name
- .byte 0 # DW_AT_decl_file
- .byte 7 # DW_AT_decl_line
- .long 193 # DW_AT_type
- .byte 5 # Abbrev [5] 0x6b:0xb DW_TAG_variable
- .byte 2 # DW_AT_location
- .byte 145
- .byte 96
- .byte 15 # DW_AT_name
- .byte 0 # DW_AT_decl_file
- .byte 9 # DW_AT_decl_line
- .long 150 # DW_AT_type
- .byte 5 # Abbrev [5] 0x76:0xb DW_TAG_variable
- .byte 2 # DW_AT_location
- .byte 145
- .byte 92
- .byte 12 # DW_AT_name
- .byte 0 # DW_AT_decl_file
- .byte 14 # DW_AT_decl_line
- .long 141 # DW_AT_type
- .byte 5 # Abbrev [5] 0x81:0xb DW_TAG_variable
- .byte 2 # DW_AT_location
- .byte 145
- .byte 88
- .byte 16 # DW_AT_name
- .byte 0 # DW_AT_decl_file
- .byte 16 # DW_AT_decl_line
- .long 141 # DW_AT_type
- .byte 0 # End Of Children Mark
- .byte 6 # Abbrev [6] 0x8d:0x4 DW_TAG_base_type
- .byte 6 # DW_AT_name
- .byte 5 # DW_AT_encoding
- .byte 4 # DW_AT_byte_size
- .byte 7 # Abbrev [7] 0x91:0x5 DW_TAG_reference_type
- .long 150 # DW_AT_type
- .byte 8 # Abbrev [8] 0x96:0x22 DW_TAG_structure_type
- .byte 5 # DW_AT_calling_convention
- .byte 7 # DW_AT_name
- .byte 16 # DW_AT_byte_size
- .byte 1 # DW_AT_decl_file
- .byte 4 # DW_AT_decl_line
- .byte 9 # Abbrev [9] 0x9c:0x9 DW_TAG_member
- .byte 8 # DW_AT_name
- .long 141 # DW_AT_type
- .byte 1 # DW_AT_decl_file
- .byte 5 # DW_AT_decl_line
- .byte 0 # DW_AT_data_member_location
- .byte 9 # Abbrev [9] 0xa5:0x9 DW_TAG_member
- .byte 9 # DW_AT_name
- .long 184 # DW_AT_type
- .byte 1 # DW_AT_decl_file
- .byte 6 # DW_AT_decl_line
- .byte 4 # DW_AT_data_member_location
- .byte 9 # Abbrev [9] 0xae:0x9 DW_TAG_member
- .byte 11 # DW_AT_name
- .long 188 # DW_AT_type
- .byte 1 # DW_AT_decl_file
- .byte 7 # DW_AT_decl_line
- .byte 8 # DW_AT_data_member_location
- .byte 0 # End Of Children Mark
- .byte 6 # Abbrev [6] 0xb8:0x4 DW_TAG_base_type
- .byte 10 # DW_AT_name
- .byte 6 # DW_AT_encoding
- .byte 1 # DW_AT_byte_size
- .byte 10 # Abbrev [10] 0xbc:0x5 DW_TAG_pointer_type
- .long 150 # DW_AT_type
- .byte 10 # Abbrev [10] 0xc1:0x5 DW_TAG_pointer_type
- .long 198 # DW_AT_type
- .byte 10 # Abbrev [10] 0xc6:0x5 DW_TAG_pointer_type
- .long 184 # DW_AT_type
- .byte 0 # End Of Children Mark
.Ldebug_info_end0:
.section .debug_str_offsets,"", at progbits
.long 72 # Length of String Offsets Set
diff --git a/lld/test/ELF/debug-names.s b/lld/test/ELF/debug-names.s
index ce013303f65f67..ca6d32998542b5 100644
--- a/lld/test/ELF/debug-names.s
+++ b/lld/test/ELF/debug-names.s
@@ -1,136 +1,110 @@
-# REQUIRES: x86
-# RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t1.o
-# RUN: llvm-mc -filetype=obj -triple=x86_64 %p/Inputs/debug-names-2.s -o %t2.o
-# RUN: ld.lld --debug-names %t1.o %t2.o -o %t
+// Generated with:
-# RUN: llvm-objdump -d %t | FileCheck %s --check-prefix=DISASM
-# RUN: llvm-dwarfdump -debug-names %t | FileCheck %s --check-prefix=DWARF
-# RUN: llvm-readelf -SW %t | FileCheck %s --check-prefix=READELF
-
-# DISASM: Disassembly of section .text:
-# DISASM-EMPTY:
-# DISASM: <_Z2f12t1>:
-# DISASM-CHECK: 201180: 55 pushq %rbp
-# DISASM-CHECK: 201181: 48 89 e5 movq %rsp, %rbp
-# DISASM-CHECK: 201184: 5d popq %rbp
-# DISASM-CHECK: 201185: c3 retq
-# DISASM-CHECK: 201186: cc int3
-# DISASM-CHECK: 201187: cc int3
-# DISASM-CHECK: 201188: cc int3
-# DISASM-CHECK: 201189: cc int3
-# DISASM-CHECK: 20118a: cc int3
-# DISASM-CHECK: 20118b: cc int3
-# DISASM-CHECK: 20118c: cc int3
-# DISASM-CHECK: 20118d: cc int3
-# DISASM-CHECK: 20118e: cc int3
-# DISASM-CHECK: 20118f: cc int3
-# DISASM: <main>:
-# DISASM-CHECK: 201190: 55 pushq %rbp
-# DISASM-CHECK: 201191: 48 89 e5 movq %rsp, %rbp
-# DISASM-CHECK: 201194: 31 c0 xorl %eax, %eax
-# DISASM-CHECK: 201196: 5d popq %rbp
-# DISASM-CHECK: 201197: c3 retq
+// - clang++ -g -O0 -gpubnames -fdebug-compilation-dir='debug-names-test' \
+// -S debug-names.cpp -o debug-names.s
-# DWARF: .debug_names contents:
-# DWARF: Name Index @ 0x0 {
-# DWARF-NEXT: Header {
-# DWARF-NEXT: Length: 0xCC
-# DWARF-NEXT: Format: DWARF32
-# DWARF-NEXT: Version: 5
-# DWARF-NEXT: CU count: 2
-# DWARF-NEXT: Local TU count: 0
-# DWARF-NEXT: Foreign TU count: 0
-# DWARF-NEXT: Bucket count: 5
-# DWARF-NEXT: Name count: 5
-# DWARF-NEXT: Abbreviations table size: 0x1F
-# DWARF-NEXT: Augmentation: 'LLVM0700'
-# DWARF: Compilation Unit offsets [
-# DWARF-NEXT: CU[0]: 0x00000000
-# DWARF-NEXT: CU[1]: 0x00000041
-# DWARF: Abbreviations [
-# DWARF-NEXT: Abbreviation 0x1 {
-# DWARF: Tag: DW_TAG_structure_type
-# DWARF-NEXT: DW_IDX_die_offset: DW_FORM_ref4
-# DWARF-NEXT: DW_IDX_parent: DW_FORM_flag_present
-# DWARF-NEXT: DW_IDX_compile_unit: DW_FORM_data1
-# DWARF: Abbreviation 0x2 {
-# DWARF-NEXT: Tag: DW_TAG_subprogram
-# DWARF-NEXT: DW_IDX_die_offset: DW_FORM_ref4
-# DWARF-NEXT: DW_IDX_parent: DW_FORM_flag_present
-# DWARF-NEXT: DW_IDX_compile_unit: DW_FORM_data1
-# DWARF: Abbreviation 0x3 {
-# DWARF-NEXT: Tag: DW_TAG_base_type
-# DWARF-NEXT: DW_IDX_die_offset: DW_FORM_ref4
-# DWARF-NEXT: DW_IDX_parent: DW_FORM_flag_present
-# DWARF-NEXT: DW_IDX_compile_unit: DW_FORM_data1
-# DWARF: Bucket 0 [
-# DWARF: Bucket 1 [
-# DWARF: String: 0x00000089 "f1"
-# DWARF-NEXT: Entry @ 0xa3 {
-# DWARF-NEXT: Abbrev: 0x2
-# DWARF-NEXT: Tag: DW_TAG_subprogram
-# DWARF-NEXT: DW_IDX_die_offset: 0x00000023
-# DWARF-NEXT: DW_IDX_parent: <parent not indexed>
-# DWARF-NEXT: DW_IDX_compile_unit: 0x00
-# DWARF: String: 0x00000095 "t1"
-# DWARF-NEXT: Entry @ 0xaa {
-# DWARF-NEXT: Abbrev: 0x1
-# DWARF-NEXT: Tag: DW_TAG_structure_type
-# DWARF-NEXT: DW_IDX_die_offset: 0x0000003a
-# DWARF-NEXT: DW_IDX_parent: <parent not indexed>
-# DWARF-NEXT: DW_IDX_compile_unit: 0x00
-# DWARF-NEXT: }
-# DWARF-NEXT: Entry @ 0xb0 {
-# DWARF-NEXT: Abbrev: 0x1
-# DWARF-NEXT: Tag: DW_TAG_structure_type
-# DWARF-NEXT: DW_IDX_die_offset: 0x00000042
-# DWARF-NEXT: DW_IDX_parent: <parent not indexed>
-# DWARF-NEXT: DW_IDX_compile_unit: 0x01
-# DWARF: String: 0x00000130 "int"
-# DWARF-NEXT: Entry @ 0xb7 {
-# DWARF-NEXT: Abbrev: 0x3
-# DWARF-NEXT: Tag: DW_TAG_base_type
-# DWARF-NEXT: DW_IDX_die_offset: 0x0000003e
-# DWARF-NEXT: DW_IDX_parent: <parent not indexed>
-# DWARF-NEXT: DW_IDX_compile_unit: 0x01
-# DWARF: Bucket 2 [
-# DWARF: Bucket 3 [
-# DWARF: String: 0x0000008c "_Z2f12t1"
-# DWARF-NEXT: Entry @ 0xbe {
-# DWARF-NEXT: Abbrev: 0x2
-# DWARF-NEXT: Tag: DW_TAG_subprogram
-# DWARF-NEXT: DW_IDX_die_offset: 0x00000023
-# DWARF-NEXT: DW_IDX_parent: <parent not indexed>
-# DWARF-NEXT: DW_IDX_compile_unit: 0x00
-# DWARF: Bucket 4 [
-# DWARF: String: 0x0000012b "main"
-# DWARF-NEXT: Entry @ 0xc5 {
-# DWARF-NEXT: Abbrev: 0x2
-# DWARF-NEXT: Tag: DW_TAG_subprogram
-# DWARF-NEXT: DW_IDX_die_offset: 0x00000023
-# DWARF-NEXT: DW_IDX_parent: <parent not indexed>
-# DWARF-NEXT: DW_IDX_compile_unit: 0x01
+// debug-names.cpp contents:
-# READELF: .debug_names PROGBITS 0000000000000000 0003eb 0000d0
+// struct t1 { };
+// void f1(t1) { }
-# RUN: ld.lld --debug-names --no-debug-names %t1.o %t2.o -o %t
-# RUN: llvm-readelf -SW %t | FileCheck %s --check-prefix=NO_DBG_NAMES
-
+// REQUIRES: x86
+// RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t1.o
+// RUN: llvm-mc -filetype=obj -triple=x86_64 %p/Inputs/debug-names-2.s -o %t2.o
-# NO_DBG_NAMES: .debug_names PROGBITS 0000000000000000 00037c 000110
+// RUN: ld.lld --debug-names --no-debug-names %t1.o %t2.o -o %t
+// RUN: llvm-readelf -SW %t | FileCheck %s --check-prefix=NO_DBG_NAMES
-#-- input file: debug-names.cpp
-## Generated with:
-##
-## - clang++ -g -O0 -gpubnames -fdebug-compilation-dir='debug-names-test' \
-## -S debug-names.cpp -o debug-names.s
-##
-## debug-names.cpp contents:
-##
-## struct t1 { };
-## void f1(t1) { }
-##
-##
+// NO_DBG_NAMES: .debug_names PROGBITS 0000000000000000 [[#%x,]] 000110
+
+// RUN: ld.lld --debug-names %t1.o %t2.o -o %t
+
+// RUN: llvm-dwarfdump -debug-names %t | FileCheck %s --check-prefix=DWARF
+// RUN: llvm-readelf -SW %t \
+// RUN: | FileCheck -DFILE=%t1.o -DFILE=%t2.o %s --check-prefix=READELF
+
+// READELF: .debug_names PROGBITS 0000000000000000 [[#%x,]] 0000d0
+
+// DWARF: .debug_names contents:
+// DWARF: Name Index @ 0x0 {
+// DWARF-NEXT: Header {
+// DWARF-NEXT: Length: 0xCC
+// DWARF-NEXT: Format: DWARF32
+// DWARF-NEXT: Version: 5
+// DWARF-NEXT: CU count: 2
+// DWARF-NEXT: Local TU count: 0
+// DWARF-NEXT: Foreign TU count: 0
+// DWARF-NEXT: Bucket count: 5
+// DWARF-NEXT: Name count: 5
+// DWARF-NEXT: Abbreviations table size: 0x1F
+// DWARF-NEXT: Augmentation: 'LLVM0700'
+// DWARF: Compilation Unit offsets [
+// DWARF-NEXT: CU[0]: 0x00000000
+// DWARF-NEXT: CU[1]: 0x0000000c
+// DWARF: Abbreviations [
+// DWARF-NEXT: Abbreviation 0x1 {
+// DWARF: Tag: DW_TAG_structure_type
+// DWARF-NEXT: DW_IDX_die_offset: DW_FORM_ref4
+// DWARF-NEXT: DW_IDX_parent: DW_FORM_flag_present
+// DWARF-NEXT: DW_IDX_compile_unit: DW_FORM_data1
+// DWARF: Abbreviation 0x2 {
+// DWARF-NEXT: Tag: DW_TAG_subprogram
+// DWARF-NEXT: DW_IDX_die_offset: DW_FORM_ref4
+// DWARF-NEXT: DW_IDX_parent: DW_FORM_flag_present
+// DWARF-NEXT: DW_IDX_compile_unit: DW_FORM_data1
+// DWARF: Abbreviation 0x3 {
+// DWARF-NEXT: Tag: DW_TAG_base_type
+// DWARF-NEXT: DW_IDX_die_offset: DW_FORM_ref4
+// DWARF-NEXT: DW_IDX_parent: DW_FORM_flag_present
+// DWARF-NEXT: DW_IDX_compile_unit: DW_FORM_data1
+// DWARF: Bucket 0 [
+// DWARF: Bucket 1 [
+// DWARF: String: 0x00000089 "f1"
+// DWARF-NEXT: Entry @ 0xa3 {
+// DWARF-NEXT: Abbrev: 0x2
+// DWARF-NEXT: Tag: DW_TAG_subprogram
+// DWARF-NEXT: DW_IDX_die_offset: 0x00000023
+// DWARF-NEXT: DW_IDX_parent: <parent not indexed>
+// DWARF-NEXT: DW_IDX_compile_unit: 0x00
+// DWARF: String: 0x00000095 "t1"
+// DWARF-NEXT: Entry @ 0xaa {
+// DWARF-NEXT: Abbrev: 0x1
+// DWARF-NEXT: Tag: DW_TAG_structure_type
+// DWARF-NEXT: DW_IDX_die_offset: 0x0000003a
+// DWARF-NEXT: DW_IDX_parent: <parent not indexed>
+// DWARF-NEXT: DW_IDX_compile_unit: 0x00
+// DWARF-NEXT: }
+// DWARF-NEXT: Entry @ 0xb0 {
+// DWARF-NEXT: Abbrev: 0x1
+// DWARF-NEXT: Tag: DW_TAG_structure_type
+// DWARF-NEXT: DW_IDX_die_offset: 0x00000042
+// DWARF-NEXT: DW_IDX_parent: <parent not indexed>
+// DWARF-NEXT: DW_IDX_compile_unit: 0x01
+// DWARF: String: 0x00000130 "int"
+// DWARF-NEXT: Entry @ 0xb7 {
+// DWARF-NEXT: Abbrev: 0x3
+// DWARF-NEXT: Tag: DW_TAG_base_type
+// DWARF-NEXT: DW_IDX_die_offset: 0x0000003e
+// DWARF-NEXT: DW_IDX_parent: <parent not indexed>
+// DWARF-NEXT: DW_IDX_compile_unit: 0x01
+// DWARF: Bucket 2 [
+// DWARF: Bucket 3 [
+// DWARF: String: 0x0000008c "_Z2f12t1"
+// DWARF-NEXT: Entry @ 0xbe {
+// DWARF-NEXT: Abbrev: 0x2
+// DWARF-NEXT: Tag: DW_TAG_subprogram
+// DWARF-NEXT: DW_IDX_die_offset: 0x00000023
+// DWARF-NEXT: DW_IDX_parent: <parent not indexed>
+// DWARF-NEXT: DW_IDX_compile_unit: 0x00
+// DWARF: Bucket 4 [
+// DWARF: String: 0x0000012b "main"
+// DWARF-NEXT: Entry @ 0xc5 {
+// DWARF-NEXT: Abbrev: 0x2
+// DWARF-NEXT: Tag: DW_TAG_subprogram
+// DWARF-NEXT: DW_IDX_die_offset: 0x00000023
+// DWARF-NEXT: DW_IDX_parent: <parent not indexed>
+// DWARF-NEXT: DW_IDX_compile_unit: 0x01
+
.text
.globl _Z2f12t1 # -- Begin function _Z2f12t1
.p2align 4, 0x90
@@ -165,41 +139,6 @@ _Z2f12t1: # @_Z2f12t1
.byte 1 # DWARF Unit Type
.byte 8 # Address Size (in bytes)
.long .debug_abbrev # Offset Into Abbrev. Section
- .byte 1 # Abbrev [1] 0xc:0x35 DW_TAG_compile_unit
- .byte 0 # DW_AT_producer
- .short 33 # DW_AT_language
- .byte 1 # DW_AT_name
- .long .Lstr_offsets_base0 # DW_AT_str_offsets_base
- .long .Lline_table_start0 # DW_AT_stmt_list
- .byte 2 # DW_AT_comp_dir
- .byte 0 # DW_AT_low_pc
- .long .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc
- .long .Laddr_table_base0 # DW_AT_addr_base
- .byte 2 # Abbrev [2] 0x23:0x17 DW_TAG_subprogram
- .byte 0 # DW_AT_low_pc
- .long .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc
- .byte 1 # DW_AT_frame_base
- .byte 86
- .byte 3 # DW_AT_linkage_name
- .byte 4 # DW_AT_name
- .byte 0 # DW_AT_decl_file
- .byte 2 # DW_AT_decl_line
- # DW_AT_external
- .byte 3 # Abbrev [3] 0x2f:0xa DW_TAG_formal_parameter
- .byte 2 # DW_AT_location
- .byte 145
- .byte 127
- .byte 0 # DW_AT_decl_file
- .byte 2 # DW_AT_decl_line
- .long 58 # DW_AT_type
- .byte 0 # End Of Children Mark
- .byte 4 # Abbrev [4] 0x3a:0x6 DW_TAG_structure_type
- .byte 5 # DW_AT_calling_convention
- .byte 5 # DW_AT_name
- .byte 1 # DW_AT_byte_size
- .byte 0 # DW_AT_decl_file
- .byte 1 # DW_AT_decl_line
- .byte 0 # End Of Children Mark
.Ldebug_info_end0:
.section .debug_str_offsets,"", at progbits
.long 28 # Length of String Offsets Set
>From 932aa047c913d620e2eb49b9e6c94deee2b5c4c5 Mon Sep 17 00:00:00 2001
From: Caroline Tice <cmtice at google.com>
Date: Tue, 26 Mar 2024 23:04:50 -0700
Subject: [PATCH 05/23] [lld][ELF] Implement merged .debug_names section.
Fix code formatting issue.
---
lld/ELF/SyntheticSections.cpp | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp
index 776bf719a01d77..389fda9bf436b2 100644
--- a/lld/ELF/SyntheticSections.cpp
+++ b/lld/ELF/SyntheticSections.cpp
@@ -2920,8 +2920,7 @@ static void readAttributeValues(
Error err = Error::success();
typename DebugNamesSection<ELFT>::AttrValueData newAttr;
uint32_t value;
- if (attr.Index == DW_IDX_parent &&
- attr.Form != DW_FORM_flag_present &&
+ if (attr.Index == DW_IDX_parent && attr.Form != DW_FORM_flag_present &&
attr.Form != DW_FORM_ref4)
errorOrWarn(toString(namesSection.sec) +
Twine(": invalid form for DW_IDX_parent"));
>From 2723b34681b6058be0419fb0252dcc97abbf7474 Mon Sep 17 00:00:00 2001
From: Caroline Tice <cmtice at google.com>
Date: Wed, 27 Mar 2024 00:28:52 -0700
Subject: [PATCH 06/23] [lld][ELF] Implement merged .debug_names section
Update for-loop to make sure unnecessary evaluations/calculations are
not performed on condition checks.
---
lld/ELF/SyntheticSections.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp
index 389fda9bf436b2..28efc126df86dd 100644
--- a/lld/ELF/SyntheticSections.cpp
+++ b/lld/ELF/SyntheticSections.cpp
@@ -3039,7 +3039,7 @@ readEntries(typename DebugNamesSection<ELFT>::DebugNamesSectionData &secData,
chunk.hashValues.reserve(secData.hdr.NameCount);
secData.namedEntries.reserve(secData.hdr.NameCount);
// Calculate the Entry Offsets, create initial records.
- for (uint32_t i = 0; i < secData.hdr.NameCount; ++i) {
+ for (uint32_t i = 0, e = secData.hdr.NameCount; i != e; ++i) {
// Get string value
typename DebugNamesSection<ELFT>::NamedEntry stringEntry;
stringEntry.entryOffset =
>From 64e666a208b0786ef97706262177290d6e0638d7 Mon Sep 17 00:00:00 2001
From: Caroline Tice <cmtice at google.com>
Date: Wed, 27 Mar 2024 07:52:09 -0700
Subject: [PATCH 07/23] [lld][ELF] Implement merged .debug_names section.
Move '-r' and '--debug-names' test to driver.test; remove
debug-names-invalid-flags.s test.
---
lld/test/ELF/debug-names-invalid-flags.s | 148 -----------------------
1 file changed, 148 deletions(-)
delete mode 100644 lld/test/ELF/debug-names-invalid-flags.s
diff --git a/lld/test/ELF/debug-names-invalid-flags.s b/lld/test/ELF/debug-names-invalid-flags.s
deleted file mode 100644
index 96cd4da243b688..00000000000000
--- a/lld/test/ELF/debug-names-invalid-flags.s
+++ /dev/null
@@ -1,148 +0,0 @@
-// This file was generated by:
-// clang++ -g -O0 -S -fdebug-compilation-dir='debug-names-test' \
-// -gpubnames main.cpp
-
-// Contents of main.cpp
-// int main (int argc, char **argv) { }
-
-// REQUIRES: x86
-// RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t1.o
-// RUN: not ld.lld --debug-names -r %t1.o -o /dev/null 2>&1 \
-// RUN: | FileCheck -DFILE=%t1.o %s
-
-// CHECK: error: -r and --debug-names may not be used together
-
- .text
- .globl main # -- Begin function main
- .p2align 4, 0x90
- .type main, at function
-main: # @main
-.Lfunc_begin0:
- .cfi_startproc
-# %bb.0: # %entry
- pushq %rbp
- .cfi_def_cfa_offset 16
- .cfi_offset %rbp, -16
- movq %rsp, %rbp
- .cfi_def_cfa_register %rbp
- movl %edi, -4(%rbp)
- movq %rsi, -16(%rbp)
-.Ltmp0:
- xorl %eax, %eax
- popq %rbp
- .cfi_def_cfa %rsp, 8
- retq
-.Ltmp1:
-.Lfunc_end0:
- .size main, .Lfunc_end0-main
- .cfi_endproc
- # -- End function
- .section .debug_abbrev,"", at progbits
- .byte 0 # EOM(1)
- .byte 0 # EOM(2)
- .byte 0 # EOM(3)
- .section .debug_info,"", at progbits
-.Lcu_begin0:
- .long .Ldebug_info_end0-.Ldebug_info_start0 # Length of Unit
-.Ldebug_info_start0:
- .short 5 # DWARF version number
- .byte 1 # DWARF Unit Type
- .byte 8 # Address Size (in bytes)
- .long .debug_abbrev # Offset Into Abbrev. Section
-.Ldebug_info_end0:
- .section .debug_str_offsets,"", at progbits
- .long 36 # Length of String Offsets Set
- .short 5
- .short 0
-.Lstr_offsets_base0:
- .section .debug_str,"MS", at progbits,1
-.Linfo_string0:
- .asciz "clang version 19.0.0git (git at github.com:llvm/llvm-project.git d33d5630b281debe6eabd67e323bcf767340fb6a)" # string offset=0
-.Linfo_string1:
- .asciz "main.cpp" # string offset=104
-.Linfo_string2:
- .asciz "debug-names-test" # string offset=113
-.Linfo_string3:
- .asciz "main" # string offset=130
-.Linfo_string4:
- .asciz "int" # string offset=135
-.Linfo_string5:
- .asciz "argc" # string offset=139
-.Linfo_string6:
- .asciz "argv" # string offset=144
-.Linfo_string7:
- .asciz "char" # string offset=149
-.Laddr_table_base0:
- .quad .Lfunc_begin0
-.Ldebug_addr_end0:
- .section .debug_names,"", at progbits
- .long .Lnames_end0-.Lnames_start0 # Header: unit length
-.Lnames_start0:
- .short 5 # Header: version
- .short 0 # Header: padding
- .long 1 # Header: compilation unit count
- .long 0 # Header: local type unit count
- .long 0 # Header: foreign type unit count
- .long 3 # Header: bucket count
- .long 3 # Header: name count
- .long .Lnames_abbrev_end0-.Lnames_abbrev_start0 # Header: abbreviation table size
- .long 8 # Header: augmentation string size
- .ascii "LLVM0700" # Header: augmentation string
- .long .Lcu_begin0 # Compilation unit 0
- .long 0 # Bucket 0
- .long 1 # Bucket 1
- .long 2 # Bucket 2
- .long 2090499946 # Hash in Bucket 1
- .long 193495088 # Hash in Bucket 2
- .long 2090147939 # Hash in Bucket 2
- .long .Linfo_string3 # String in Bucket 1: main
- .long .Linfo_string4 # String in Bucket 2: int
- .long .Linfo_string7 # String in Bucket 2: char
- .long .Lnames0-.Lnames_entries0 # Offset in Bucket 1
- .long .Lnames1-.Lnames_entries0 # Offset in Bucket 2
- .long .Lnames2-.Lnames_entries0 # Offset in Bucket 2
-.Lnames_abbrev_start0:
- .byte 1 # Abbrev code
- .byte 46 # DW_TAG_subprogram
- .byte 3 # DW_IDX_die_offset
- .byte 19 # DW_FORM_ref4
- .byte 4 # DW_IDX_parent
- .byte 25 # DW_FORM_flag_present
- .byte 0 # End of abbrev
- .byte 0 # End of abbrev
- .byte 2 # Abbrev code
- .byte 36 # DW_TAG_base_type
- .byte 3 # DW_IDX_die_offset
- .byte 19 # DW_FORM_ref4
- .byte 4 # DW_IDX_parent
- .byte 25 # DW_FORM_flag_present
- .byte 0 # End of abbrev
- .byte 0 # End of abbrev
- .byte 0 # End of abbrev list
-.Lnames_abbrev_end0:
-.Lnames_entries0:
-.Lnames0:
-.L1:
- .byte 1 # Abbreviation code
- .long 35 # DW_IDX_die_offset
- .byte 0 # DW_IDX_parent
- # End of list: main
-.Lnames1:
-.L0:
- .byte 2 # Abbreviation code
- .long 73 # DW_IDX_die_offset
- .byte 0 # DW_IDX_parent
- # End of list: int
-.Lnames2:
-.L2:
- .byte 2 # Abbreviation code
- .long 87 # DW_IDX_die_offset
- .byte 0 # DW_IDX_parent
- # End of list: char
- .p2align 2, 0x0
-.Lnames_end0:
- .ident "clang version 19.0.0git (git at github.com:llvm/llvm-project.git d33d5630b281debe6eabd67e323bcf767340fb6a)"
- .section ".note.GNU-stack","", at progbits
- .addrsig
- .section .debug_line,"", at progbits
-.Lline_table_start0:
>From 28444182704374a45a3684b5e958540953cae6de Mon Sep 17 00:00:00 2001
From: Caroline Tice <cmtice at google.com>
Date: Fri, 29 Mar 2024 07:33:14 -0700
Subject: [PATCH 08/23] [lld][ELF] Implement merged .debug_names section.
Address various review comments.
---
lld/ELF/SyntheticSections.cpp | 65 +++++++++++++++--------------------
lld/ELF/SyntheticSections.h | 4 +--
2 files changed, 29 insertions(+), 40 deletions(-)
diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp
index 28efc126df86dd..32eb19568f6159 100644
--- a/lld/ELF/SyntheticSections.cpp
+++ b/lld/ELF/SyntheticSections.cpp
@@ -2747,7 +2747,7 @@ template <class ELFT> void DebugNamesSection<ELFT>::writeTo(uint8_t *buf) {
SmallVector<DenseMap<uint32_t, uint32_t>, 0> chunksRelocs;
chunksRelocs.reserve(numChunks);
- for (size_t i = 0; i < numChunks; ++i) {
+ for (size_t i = 0, e = numChunks; i != e; ++i) {
DebugNamesOutputChunk &chunk = outputChunks[i];
InputSectionBase *base = inputDebugNamesSections[i];
DenseMap<uint32_t, uint32_t> &relocs = chunksRelocs.emplace_back();
@@ -2798,9 +2798,7 @@ template <class ELFT> void DebugNamesSection<ELFT>::writeTo(uint8_t *buf) {
warn(".debug_names: type units are not handled in merged index");
// Write the foreign TU list.
- // Currently LLVM does not emit foreign type units, so there should
- // be nothing here to emit.
- // TODO: Fix this, once we get everything working wtihout TUs.
+ // TODO: Fix this, once we get everything working without TUs.
if (mergedHdr.ForeignTypeUnitCount != 0)
warn(".debug_names: type units are not handled in merged index");
@@ -2855,10 +2853,8 @@ template <class ELFT> void DebugNamesSection<ELFT>::writeTo(uint8_t *buf) {
for (const auto &entry : stringEntry.indexEntries) {
buf += encodeULEB128(entry->abbrevCode, buf);
for (const auto &value : entry->attrValues) {
- if (value.attrSize > 0) {
- endian::write32<ELFT::Endianness>(buf + 0, value.attrValue);
- buf += value.attrSize;
- }
+ endian::write32<ELFT::Endianness>(buf + 0, value.attrValue);
+ buf += value.attrSize;
}
}
*buf++ = 0; // Entry sentinel
@@ -2876,33 +2872,26 @@ static void readCompileUnitOffsets(
DWARFDataExtractor &namesExtractor) {
uint64_t offset = secData.locs.CUsBase;
uint64_t *offsetPtr = &offset;
- for (size_t i = 0; i < secData.hdr.CompUnitCount; ++i) {
- Error err = Error::success();
- // This call to namesExtractor can't fail; if there were a problem with the
- // input, it would have been caught in the call to NamesIndex::extract, in
- // DebugNamesSection::create.
- uint32_t value = namesExtractor.getU32(offsetPtr, &err);
- cantFail(std::move(err));
- outputChunk.compilationUnits.push_back(value);
- }
+ outputChunk.compilationUnits.resize(secData.hdr.CompUnitCount);
+ uint32_t *bufferPtr =
+ namesExtractor.getU32(offsetPtr, outputChunk.compilationUnits.begin(),
+ secData.hdr.CompUnitCount);
+ if (!bufferPtr)
+ errorOrWarn(toString(outputChunk.sec) +
+ Twine(": error while reading CU offsets"));
}
template <class ELFT>
static void readEntryOffsets(
typename DebugNamesSection<ELFT>::DebugNamesSectionData &secData,
DWARFDataExtractor &namesExtractor) {
- secData.entryOffsets = std::make_unique<uint32_t[]>(secData.hdr.NameCount);
+ secData.entryOffsets.resize(secData.hdr.NameCount);
uint64_t offset = secData.locs.EntryOffsetsBase;
uint64_t *offsetPtr = &offset;
- for (size_t i = 0; i < secData.hdr.NameCount; ++i) {
- Error err = Error::success();
- // This call to namesExtractor can't fail; if there were a problem with the
- // input, it would have been caught in the call to NamesIndex::extract, in
- // DebugNamesSection::create.
- uint32_t value = namesExtractor.getU32(offsetPtr, &err);
- cantFail(std::move(err));
- secData.entryOffsets.get()[i] = value;
- }
+ uint32_t *bufferPtr = namesExtractor.getU32(
+ offsetPtr, secData.entryOffsets.begin(), secData.hdr.NameCount);
+ if (!bufferPtr)
+ errorOrWarn(Twine(": error while reading entry offsets"));
}
template <class ELFT>
@@ -2975,7 +2964,7 @@ static void readAttributeValues(
errorOrWarn(toString(namesSection.sec) +
Twine(": error while reading attributes: ") +
toString(std::move(err)));
- if (attr.Index == DW_IDX_compile_unit || attr.Index == DW_IDX_type_unit)
+ if (attr.Index == DW_IDX_compile_unit)
// Save it to put it at the end of the attributes list.
cuOrTuAttr = newAttr;
else if (attr.Form != DW_FORM_flag_present)
@@ -3090,8 +3079,9 @@ static void collectDebugNamesSectionData(
typename DebugNamesSection<ELFT>::DebugNamesInputChunk &chunk,
typename DebugNamesSection<ELFT>::DebugNamesOutputChunk &outputChunk,
DWARFDataExtractor &namesExtractor, DataExtractor &strExtractor) {
- for (const auto &ni : *chunk.debugNamesData) {
- typename DebugNamesSection<ELFT>::DebugNamesSectionData secData;
+ for (const DWARFDebugNames::NameIndex &ni : *chunk.debugNamesData) {
+ typename DebugNamesSection<ELFT>::DebugNamesSectionData &secData =
+ chunk.sectionsData.emplace_back();
secData.hdr = ni.getHeader();
if (secData.hdr.Format != DwarfFormat::DWARF32) {
errorOrWarn(toString(chunk.namesSection->sec) +
@@ -3108,7 +3098,6 @@ static void collectDebugNamesSectionData(
readCompileUnitOffsets<ELFT>(secData, outputChunk, namesExtractor);
readEntryOffsets<ELFT>(secData, namesExtractor);
readEntries<ELFT>(secData, chunk, namesExtractor, strExtractor, ni);
- chunk.sectionsData.push_back(std::move(secData));
}
}
@@ -3123,7 +3112,7 @@ void DebugNamesSection<ELFT>::collectMergedCounts(
mergedHdr.Format = DwarfFormat::DWARF32;
mergedHdr.AugmentationStringSize = 0;
- for (size_t i = 0; i < numChunks; ++i) {
+ for (size_t i = 0, e = numChunks; i != e; ++i) {
DebugNamesInputChunk &inputChunk = inputChunks[i];
DebugNamesOutputChunk &outputChunk = outputChunks[i];
inputChunk.baseCuOffsetIdx = tmpMergedCuOffsets.size();
@@ -3197,7 +3186,7 @@ void DebugNamesSection<ELFT>::getMergedAbbrevTable(
dwarf::Form compileUnitAttrForm = getMergedCuSizeData().second;
for (DebugNamesInputChunk &chunk : inputChunks) {
- for (const auto &ni : *chunk.debugNamesData) {
+ for (const DWARFDebugNames::NameIndex &ni : *chunk.debugNamesData) {
const auto &abbrevs = ni.getAbbrevs();
for (const DWARFDebugNames::Abbrev &abbrev : abbrevs) {
// Create canonicalized abbrev.
@@ -3208,8 +3197,7 @@ void DebugNamesSection<ELFT>::getMergedAbbrevTable(
newAbbrev.tag = abbrev.Tag;
for (const auto attr : abbrev.Attributes) {
DWARFDebugNames::AttributeEncoding newAttr(attr.Index, attr.Form);
- if (attr.Index == DW_IDX_compile_unit ||
- attr.Index == DW_IDX_type_unit)
+ if (attr.Index == DW_IDX_compile_unit)
// Save it, to put it at the end.
cuOrTuAttr.Index = newAttr.Index;
else
@@ -3231,7 +3219,8 @@ void DebugNamesSection<ELFT>::getMergedAbbrevTable(
newCode = Existing->code;
} else {
// Didn't find it.
- Abbrev *newAbbrev2 = new (Alloc) Abbrev(std::move(newAbbrev));
+ Abbrev *newAbbrev2 =
+ new (abbrevAlloc.Allocate()) Abbrev(std::move(newAbbrev));
AbbreviationsSet.InsertNode(newAbbrev2, insertPos);
newCode = mergedAbbrevTable.size() + 1;
newAbbrev2->code = newCode;
@@ -3280,7 +3269,7 @@ void DebugNamesSection<ELFT>::getMergedSymbols(
MutableArrayRef<ShardData> shards(shardsPtr.get(), numShards);
parallelFor(0, concurrency, [&](size_t threadId) {
- for (size_t i = 0; i < numChunks; ++i) {
+ for (size_t i = 0, e = numChunks; i != e; ++i) {
DebugNamesInputChunk &chunk = inputChunks[i];
for (auto &secData : chunk.sectionsData) {
// Deduplicate the NamedEntry records (based on the string/name),
@@ -3390,7 +3379,7 @@ template <class ELFT> void DebugNamesSection<ELFT>::updateParentIndexEntries() {
// Found the abbrev. Find the index for the DW_IDX_parent attribute
// (in the abbrev) and update that value in the entry with the
// correct parent offset (in the merged entry pool).
- for (size_t idx = 0, size = abbrev->attributes.size(); idx < size;
+ for (size_t idx = 0, size = abbrev->attributes.size(); idx != size;
++idx) {
auto attr = abbrev->attributes[idx];
if (attr.Index == DW_IDX_parent && attr.Form == DW_FORM_ref4)
diff --git a/lld/ELF/SyntheticSections.h b/lld/ELF/SyntheticSections.h
index 24ffdb3db4946b..297f2ca6e27d85 100644
--- a/lld/ELF/SyntheticSections.h
+++ b/lld/ELF/SyntheticSections.h
@@ -859,7 +859,7 @@ template <class ELFT> class DebugNamesSection final : public SyntheticSection {
llvm::DWARFDebugNames::DWARFDebugNamesOffsets locs;
SmallVector<uint32_t, 0> tuOffsets;
SmallVector<Abbrev, 0> abbrevTable;
- std::unique_ptr<uint32_t[]> entryOffsets;
+ SmallVector<uint32_t, 0> entryOffsets;
SmallVector<NamedEntry, 0> namedEntries;
uint16_t dwarfSize;
uint16_t hdrSize;
@@ -895,7 +895,7 @@ template <class ELFT> class DebugNamesSection final : public SyntheticSection {
void updateParentIndexEntries();
uint64_t calculateMergedSectionSize();
- llvm::BumpPtrAllocator Alloc;
+ llvm::SpecificBumpPtrAllocator<Abbrev> abbrevAlloc;
private:
size_t sectionSize;
>From c17e68b9981182b26e7f1edf3b8d02be76110b5d Mon Sep 17 00:00:00 2001
From: Caroline Tice <cmtice at google.com>
Date: Fri, 29 Mar 2024 07:36:10 -0700
Subject: [PATCH 09/23] [lld][ELF] Implement merged .debug_names section.
Fix comment,
---
lld/ELF/SyntheticSections.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp
index 32eb19568f6159..7db2524597cc6d 100644
--- a/lld/ELF/SyntheticSections.cpp
+++ b/lld/ELF/SyntheticSections.cpp
@@ -3458,7 +3458,7 @@ DebugNamesSection<ELFT> *DebugNamesSection<ELFT>::create() {
ret->getMergedAbbrevTable(inputChunks);
ret->getMergedSymbols(inputChunks);
ret->computeUniqueHashes(inputChunks);
- // inputChunks are needed any more. Reset now to save memory.
+ // inputChunks are not needed any more. Reset now to save memory.
inputChunksPtr.reset();
ret->generateBuckets();
ret->calculateEntriesSizeAndOffsets();
>From c4d7537e1a6c4e20d781a5227865f0ea7ddb8485 Mon Sep 17 00:00:00 2001
From: Caroline Tice <cmtice at google.com>
Date: Fri, 29 Mar 2024 09:08:28 -0700
Subject: [PATCH 10/23] [lld][ELF] Implement merged .debug_names section.
Replace "ELFT::TargetEndianness" with "ELFT::Endianness"
---
lld/ELF/SyntheticSections.cpp | 12 ++++--------
1 file changed, 4 insertions(+), 8 deletions(-)
diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp
index 7db2524597cc6d..3ae8e1f97c5c1a 100644
--- a/lld/ELF/SyntheticSections.cpp
+++ b/lld/ELF/SyntheticSections.cpp
@@ -2773,15 +2773,12 @@ template <class ELFT> void DebugNamesSection<ELFT>::writeTo(uint8_t *buf) {
endian::write32<ELFT::Endianness>(buf + 0, mergedHdr.UnitLength);
endian::write16<ELFT::Endianness>(buf + 4, mergedHdr.Version);
endian::write32<ELFT::Endianness>(buf + 8, mergedHdr.CompUnitCount);
- endian::write32<ELFT::Endianness>(buf + 12,
- mergedHdr.LocalTypeUnitCount);
- endian::write32<ELFT::Endianness>(buf + 16,
- mergedHdr.ForeignTypeUnitCount);
+ endian::write32<ELFT::Endianness>(buf + 12, mergedHdr.LocalTypeUnitCount);
+ endian::write32<ELFT::Endianness>(buf + 16, mergedHdr.ForeignTypeUnitCount);
endian::write32<ELFT::Endianness>(buf + 20, mergedHdr.BucketCount);
endian::write32<ELFT::Endianness>(buf + 24, mergedHdr.NameCount);
endian::write32<ELFT::Endianness>(buf + 28, mergedHdr.AbbrevTableSize);
- endian::write32<ELFT::Endianness>(buf + 32,
- mergedHdr.AugmentationStringSize);
+ endian::write32<ELFT::Endianness>(buf + 32, mergedHdr.AugmentationStringSize);
buf += 36;
memcpy(buf, mergedHdr.AugmentationString.c_str(), 8);
buf += 8;
@@ -2823,8 +2820,7 @@ template <class ELFT> void DebugNamesSection<ELFT>::writeTo(uint8_t *buf) {
// Write the string offsets.
for (const auto &entry : mergedEntries) {
- endian::write32<ELFT::Endianness>(buf + 0,
- entry.relocatedEntryOffset);
+ endian::write32<ELFT::Endianness>(buf + 0, entry.relocatedEntryOffset);
buf += 4;
}
>From 06171a85f7e1d896f247d7f168d07308cab7bfad Mon Sep 17 00:00:00 2001
From: Caroline Tice <cmtice at google.com>
Date: Fri, 29 Mar 2024 15:32:40 -0700
Subject: [PATCH 11/23] [lld][ELF] Implement merged .debug_names section.
Set augmentation string size from the augmentation string (for error
handling case).
---
lld/ELF/SyntheticSections.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp
index 3ae8e1f97c5c1a..0a56a6fb888f40 100644
--- a/lld/ELF/SyntheticSections.cpp
+++ b/lld/ELF/SyntheticSections.cpp
@@ -3128,8 +3128,8 @@ void DebugNamesSection<ELFT>::collectMergedCounts(
data.hdr.AugmentationString)) {
// There are conflicting augmentation strings, so it's best for the
// merged index to not use an augmentation string.
- mergedHdr.AugmentationStringSize = 8;
mergedHdr.AugmentationString = " ";
+ mergedHdr.AugmentationStringSize = mergedHdr.AugmentationString.size();
}
}
}
>From 11898cac5255897fd94ed73b1d75c6bbe9d9bc67 Mon Sep 17 00:00:00 2001
From: Caroline Tice <cmtice at google.com>
Date: Mon, 1 Apr 2024 21:58:31 -0700
Subject: [PATCH 12/23] [lld][ELF] Implement merged .debug_names section.
Update debug-names*.s tests, to use split file format rather than
multiple files.
Reduce the use of 'auto' in DebugNamesSection work, replacing it with
actual type names. Use UINT*_MAXINT rather than constant values.
---
lld/ELF/SyntheticSections.cpp | 43 ++++++++++++++++++-----------------
1 file changed, 22 insertions(+), 21 deletions(-)
diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp
index 0a56a6fb888f40..c87b29e34f69de 100644
--- a/lld/ELF/SyntheticSections.cpp
+++ b/lld/ELF/SyntheticSections.cpp
@@ -2761,7 +2761,7 @@ template <class ELFT> void DebugNamesSection<ELFT>::writeTo(uint8_t *buf) {
}
// Update the entries with the relocated string offsets.
- for (auto &stringEntry : mergedEntries) {
+ for (NamedEntry &stringEntry : mergedEntries) {
uint32_t oldOffset = stringEntry.stringOffsetOffset;
uint32_t idx = stringEntry.chunkIdx;
stringEntry.relocatedEntryOffset = chunksRelocs[idx][oldOffset];
@@ -2802,7 +2802,7 @@ template <class ELFT> void DebugNamesSection<ELFT>::writeTo(uint8_t *buf) {
// Write the hash table.
// ... Write the buckets
uint32_t idx = 1;
- for (const auto &bucket : bucketList) {
+ for (const SmallVector<NamedEntry *, 0> &bucket : bucketList) {
if (!bucket.empty())
endian::write32<ELFT::Endianness>(buf + 0, idx);
idx += bucket.size();
@@ -2819,7 +2819,7 @@ template <class ELFT> void DebugNamesSection<ELFT>::writeTo(uint8_t *buf) {
}
// Write the string offsets.
- for (const auto &entry : mergedEntries) {
+ for (const NamedEntry &entry : mergedEntries) {
endian::write32<ELFT::Endianness>(buf + 0, entry.relocatedEntryOffset);
buf += 4;
}
@@ -2831,10 +2831,10 @@ template <class ELFT> void DebugNamesSection<ELFT>::writeTo(uint8_t *buf) {
}
// Write the abbrev table.
- for (const auto *abbrev : mergedAbbrevTable) {
+ for (const Abbrev *abbrev : mergedAbbrevTable) {
buf += encodeULEB128(abbrev->code, buf);
buf += encodeULEB128(abbrev->tag, buf);
- for (auto attr : abbrev->attributes) {
+ for (DWARFDebugNames::AttributeEncoding attr : abbrev->attributes) {
buf += encodeULEB128(attr.Index, buf);
buf += encodeULEB128(attr.Form, buf);
}
@@ -2846,7 +2846,7 @@ template <class ELFT> void DebugNamesSection<ELFT>::writeTo(uint8_t *buf) {
// Write the entry pool.
for (const auto &stringEntry : mergedEntries) {
// Write all the entries for the string.
- for (const auto &entry : stringEntry.indexEntries) {
+ for (const std::unique_ptr<IndexEntry> &entry : stringEntry.indexEntries) {
buf += encodeULEB128(entry->abbrevCode, buf);
for (const auto &value : entry->attrValues) {
endian::write32<ELFT::Endianness>(buf + 0, value.attrValue);
@@ -2901,7 +2901,7 @@ static void readAttributeValues(
const LLDDWARFSection &namesSection = *chunk.namesSection;
uint64_t *offsetPtr = &offset;
typename DebugNamesSection<ELFT>::AttrValueData cuOrTuAttr = {0, 0};
- for (auto attr : abbrev.Attributes) {
+ for (DWARFDebugNames::AttributeEncoding attr : abbrev.Attributes) {
Error err = Error::success();
typename DebugNamesSection<ELFT>::AttrValueData newAttr;
uint32_t value;
@@ -3153,13 +3153,13 @@ std::pair<uint8_t, dwarf::Form> DebugNamesSection<ELFT>::getMergedCuSizeData() {
uint8_t size;
dwarf::Form form;
// TODO: Investigate possibly using DIEInteger::BestForm here
- if (mergedHdr.CompUnitCount > 0xffffffff) {
+ if (mergedHdr.CompUnitCount > UINT32_MAX) {
form = DW_FORM_data8;
size = 8;
- } else if (mergedHdr.CompUnitCount > 0xffff) {
+ } else if (mergedHdr.CompUnitCount > UINT16_MAX) {
form = DW_FORM_data4;
size = 4;
- } else if (mergedHdr.CompUnitCount > 0xff) {
+ } else if (mergedHdr.CompUnitCount > UINT8_MAX) {
form = DW_FORM_data2;
size = 2;
} else {
@@ -3191,7 +3191,8 @@ void DebugNamesSection<ELFT>::getMergedAbbrevTable(
compileUnitAttrForm);
newAbbrev.code = abbrev.Code;
newAbbrev.tag = abbrev.Tag;
- for (const auto attr : abbrev.Attributes) {
+ for (const DWARFDebugNames::AttributeEncoding attr :
+ abbrev.Attributes) {
DWARFDebugNames::AttributeEncoding newAttr(attr.Index, attr.Form);
if (attr.Index == DW_IDX_compile_unit)
// Save it, to put it at the end.
@@ -3232,7 +3233,7 @@ void DebugNamesSection<ELFT>::getMergedAbbrevTable(
for (Abbrev *a : mergedAbbrevTable) {
mergedHdr.AbbrevTableSize += getULEB128Size(a->code);
mergedHdr.AbbrevTableSize += getULEB128Size(a->tag);
- for (const auto &attr : a->attributes) {
+ for (const DWARFDebugNames::AttributeEncoding &attr : a->attributes) {
mergedHdr.AbbrevTableSize += getULEB128Size(attr.Index);
mergedHdr.AbbrevTableSize += getULEB128Size(attr.Form);
}
@@ -3267,7 +3268,7 @@ void DebugNamesSection<ELFT>::getMergedSymbols(
parallelFor(0, concurrency, [&](size_t threadId) {
for (size_t i = 0, e = numChunks; i != e; ++i) {
DebugNamesInputChunk &chunk = inputChunks[i];
- for (auto &secData : chunk.sectionsData) {
+ for (DebugNamesSectionData &secData : chunk.sectionsData) {
// Deduplicate the NamedEntry records (based on the string/name),
// using a map from string/name to NamedEntry records.
// Note there is a twist: If there is already a record for the current
@@ -3275,14 +3276,14 @@ void DebugNamesSection<ELFT>::getMergedSymbols(
// current record to the record that's in the nameMap. I.e. we
// deduplicate the *strings* but we keep all the IndexEntry records
// (moving them to the appropriate 'kept' NamedEntry record).
- for (auto &stringEntry : secData.namedEntries) {
+ for (NamedEntry &stringEntry : secData.namedEntries) {
size_t shardId = stringEntry.hashValue >> shift;
if ((shardId & (concurrency - 1)) != threadId)
continue;
auto &shard = shards[shardId];
stringEntry.chunkIdx = i;
- for (auto &entry : stringEntry.indexEntries) {
+ for (std::unique_ptr<IndexEntry> &entry : stringEntry.indexEntries) {
// The DW_IDX_compile_unit is always the last attribute (we set it
// up that way when we read/created the attributes). We need to
// update the index value to use the correct merged offset, and we
@@ -3312,7 +3313,7 @@ void DebugNamesSection<ELFT>::getMergedSymbols(
});
// Combined the shared symbols into mergedEntries
- for (auto &shard : shards)
+ for (ShardData &shard : shards)
for (auto &mapEntry : shard.nameMap)
mergedEntries.push_back(std::move(mapEntry.second));
mergedHdr.NameCount = mergedEntries.size();
@@ -3330,14 +3331,14 @@ void DebugNamesSection<ELFT>::computeUniqueHashes(
template <class ELFT> void DebugNamesSection<ELFT>::generateBuckets() {
bucketList.resize(mergedHdr.BucketCount);
- for (auto &entry : mergedEntries) {
+ for (NamedEntry &entry : mergedEntries) {
uint32_t bucketIdx = entry.hashValue % mergedHdr.BucketCount;
bucketList[bucketIdx].push_back(&entry);
}
// Sort the contents of the buckets by hash value so that the hash collisions
// end up together.
- for (auto &bucket : bucketList)
+ for (SmallVector<NamedEntry *, 0> &bucket : bucketList)
stable_sort(bucket, [](NamedEntry *lhs, NamedEntry *rhs) {
return lhs->hashValue < rhs->hashValue;
});
@@ -3348,7 +3349,7 @@ void DebugNamesSection<ELFT>::calculateEntriesSizeAndOffsets() {
uint32_t offset = 0;
for (NamedEntry &stringEntry : mergedEntries) {
stringEntry.entryOffset = offset;
- for (auto &entry : stringEntry.indexEntries) {
+ for (std::unique_ptr<IndexEntry> &entry : stringEntry.indexEntries) {
uint32_t entrySize = 0;
entry->poolOffset = offset;
entrySize += getULEB128Size(entry->abbrevCode);
@@ -3364,7 +3365,7 @@ void DebugNamesSection<ELFT>::calculateEntriesSizeAndOffsets() {
template <class ELFT> void DebugNamesSection<ELFT>::updateParentIndexEntries() {
for (NamedEntry &stringEntry : mergedEntries) {
- for (auto &childEntry : stringEntry.indexEntries) {
+ for (std::unique_ptr<IndexEntry> &childEntry : stringEntry.indexEntries) {
if (!childEntry->parentEntry)
continue;
@@ -3377,7 +3378,7 @@ template <class ELFT> void DebugNamesSection<ELFT>::updateParentIndexEntries() {
// correct parent offset (in the merged entry pool).
for (size_t idx = 0, size = abbrev->attributes.size(); idx != size;
++idx) {
- auto attr = abbrev->attributes[idx];
+ DWARFDebugNames::AttributeEncoding attr = abbrev->attributes[idx];
if (attr.Index == DW_IDX_parent && attr.Form == DW_FORM_ref4)
childEntry->attrValues[idx].attrValue =
childEntry->parentEntry->poolOffset;
>From c8b69048ce6d0aa8da4756c9c86a988a8d46e385 Mon Sep 17 00:00:00 2001
From: Caroline Tice <cmtice at google.com>
Date: Mon, 1 Apr 2024 22:19:18 -0700
Subject: [PATCH 13/23] [lld][ELF] Implement merged .debug_names section.
Update tests to up split-file instead of multiple files.
---
lld/test/ELF/Inputs/debug-names-2.s | 150 ---------
.../ELF/Inputs/debug-names-parent-idx-2.s | 267 ----------------
lld/test/ELF/debug-names-bad-aug-string.s | 169 ++++++++++-
lld/test/ELF/debug-names-bad-version.s | 165 +++++++++-
lld/test/ELF/debug-names-parent-idx.s | 286 +++++++++++++++++-
lld/test/ELF/debug-names.s | 178 ++++++++++-
6 files changed, 774 insertions(+), 441 deletions(-)
delete mode 100644 lld/test/ELF/Inputs/debug-names-2.s
delete mode 100644 lld/test/ELF/Inputs/debug-names-parent-idx-2.s
diff --git a/lld/test/ELF/Inputs/debug-names-2.s b/lld/test/ELF/Inputs/debug-names-2.s
deleted file mode 100644
index 83ddbd2050d40b..00000000000000
--- a/lld/test/ELF/Inputs/debug-names-2.s
+++ /dev/null
@@ -1,150 +0,0 @@
-#-- input file: debug-names-2.cpp
-## Generated with:
-## - clang++ -g -O0 -gpubnames -fdebug-compilation-dir='debug-names-test' \
-## -S debug-names-2.cpp -o debug-names-2.s
-
-## debug-names-2.cpp contents:
-
-## struct t1 { };
-## int main() {
-## t1 v1;
-## }
-##
- .text
- .globl main # -- Begin function main
- .p2align 4, 0x90
- .type main, at function
-main: # @main
-.Lfunc_begin0:
- .cfi_startproc
-# %bb.0: # %entry
- pushq %rbp
- .cfi_def_cfa_offset 16
- .cfi_offset %rbp, -16
- movq %rsp, %rbp
- .cfi_def_cfa_register %rbp
-.Ltmp0:
- xorl %eax, %eax
- popq %rbp
- .cfi_def_cfa %rsp, 8
- retq
-.Ltmp1:
-.Lfunc_end0:
- .size main, .Lfunc_end0-main
- .cfi_endproc
- # -- End function
- .section .debug_abbrev,"", at progbits
- .byte 0 # EOM(1)
- .byte 0 # EOM(2)
- .byte 0 # EOM(3)
- .section .debug_info,"", at progbits
-.Lcu_begin0:
- .long .Ldebug_info_end0-.Ldebug_info_start0 # Length of Unit
-.Ldebug_info_start0:
- .short 5 # DWARF version number
- .byte 1 # DWARF Unit Type
- .byte 8 # Address Size (in bytes)
- .long .debug_abbrev # Offset Into Abbrev. Section
-.Ldebug_info_end0:
- .section .debug_str_offsets,"", at progbits
- .long 32 # Length of String Offsets Set
- .short 5
- .short 0
-.Lstr_offsets_base0:
- .section .debug_str,"MS", at progbits,1
-.Linfo_string0:
- .asciz "clang version 19.0.0git (git at github.com:llvm/llvm-project.git 4df364bc93af49ae413ec1ae8328f34ac70730c4)" # string offset=0
-.Linfo_string1:
- .asciz "debug-names-2.cpp" # string offset=104
-.Linfo_string2:
- .asciz "debug-names-test" # string offset=122
-.Linfo_string3:
- .asciz "main" # string offset=139
-.Linfo_string4:
- .asciz "int" # string offset=144
-.Linfo_string5:
- .asciz "v1" # string offset=148
-.Linfo_string6:
- .asciz "t1" # string offset=151
-.Laddr_table_base0:
- .quad .Lfunc_begin0
-.Ldebug_addr_end0:
- .section .debug_names,"", at progbits
- .long .Lnames_end0-.Lnames_start0 # Header: unit length
-.Lnames_start0:
- .short 5 # Header: version
- .short 0 # Header: padding
- .long 1 # Header: compilation unit count
- .long 0 # Header: local type unit count
- .long 0 # Header: foreign type unit count
- .long 3 # Header: bucket count
- .long 3 # Header: name count
- .long .Lnames_abbrev_end0-.Lnames_abbrev_start0 # Header: abbreviation table size
- .long 8 # Header: augmentation string size
- .ascii "LLVM0700" # Header: augmentation string
- .long .Lcu_begin0 # Compilation unit 0
- .long 0 # Bucket 0
- .long 1 # Bucket 1
- .long 3 # Bucket 2
- .long 5863786 # Hash in Bucket 1
- .long 2090499946 # Hash in Bucket 1
- .long 193495088 # Hash in Bucket 2
- .long .Linfo_string6 # String in Bucket 1: t1
- .long .Linfo_string3 # String in Bucket 1: main
- .long .Linfo_string4 # String in Bucket 2: int
- .long .Lnames2-.Lnames_entries0 # Offset in Bucket 1
- .long .Lnames0-.Lnames_entries0 # Offset in Bucket 1
- .long .Lnames1-.Lnames_entries0 # Offset in Bucket 2
-.Lnames_abbrev_start0:
- .byte 1 # Abbrev code
- .byte 19 # DW_TAG_structure_type
- .byte 3 # DW_IDX_die_offset
- .byte 19 # DW_FORM_ref4
- .byte 4 # DW_IDX_parent
- .byte 25 # DW_FORM_flag_present
- .byte 0 # End of abbrev
- .byte 0 # End of abbrev
- .byte 2 # Abbrev code
- .byte 46 # DW_TAG_subprogram
- .byte 3 # DW_IDX_die_offset
- .byte 19 # DW_FORM_ref4
- .byte 4 # DW_IDX_parent
- .byte 25 # DW_FORM_flag_present
- .byte 0 # End of abbrev
- .byte 0 # End of abbrev
- .byte 3 # Abbrev code
- .byte 36 # DW_TAG_base_type
- .byte 3 # DW_IDX_die_offset
- .byte 19 # DW_FORM_ref4
- .byte 4 # DW_IDX_parent
- .byte 25 # DW_FORM_flag_present
- .byte 0 # End of abbrev
- .byte 0 # End of abbrev
- .byte 0 # End of abbrev list
-.Lnames_abbrev_end0:
-.Lnames_entries0:
-.Lnames2:
-.L1:
- .byte 1 # Abbreviation code
- .long 66 # DW_IDX_die_offset
- .byte 0 # DW_IDX_parent
- # End of list: t1
-.Lnames0:
-.L2:
- .byte 2 # Abbreviation code
- .long 35 # DW_IDX_die_offset
- .byte 0 # DW_IDX_parent
- # End of list: main
-.Lnames1:
-.L0:
- .byte 3 # Abbreviation code
- .long 62 # DW_IDX_die_offset
- .byte 0 # DW_IDX_parent
- # End of list: int
- .p2align 2, 0x0
-.Lnames_end0:
- .ident "clang version 19.0.0git (git at github.com:llvm/llvm-project.git 4df364bc93af49ae413ec1ae8328f34ac70730c4)"
- .section ".note.GNU-stack","", at progbits
- .addrsig
- .section .debug_line,"", at progbits
-.Lline_table_start0:
diff --git a/lld/test/ELF/Inputs/debug-names-parent-idx-2.s b/lld/test/ELF/Inputs/debug-names-parent-idx-2.s
deleted file mode 100644
index ebd93c01d85189..00000000000000
--- a/lld/test/ELF/Inputs/debug-names-parent-idx-2.s
+++ /dev/null
@@ -1,267 +0,0 @@
-#-- input file: debug-names-parent-idx-2.cpp
-## Generated with:
-
-## - clang++ -g -O0 -gpubnames -fdebug-compilation-dir='parent-idx-test' \
-## -S debug-names-parent-idx-2.cpp -o debug-names-parent-idx-2.s
-
-## foo.h contents:
-
-## int foo();
-
-## struct foo {
-## int x;
-## char y;
-## struct foo *foo_ptr;
-## };
-
-## namespace parent_test {
-## int foo();
-## }
-
-## debug-names-parent-index-2.cpp contents:
-
-## #include "foo.h"
-## int foo () {
-## struct foo struct2;
-## struct2.x = 1024;
-## struct2.y = 'r';
-## struct2.foo_ptr = nullptr;
-## return struct2.x * (int) struct2.y;
-## }
-
-## namespace parent_test {
-## int foo () {
-## return 25;
-## }
-## }
-
- .text
- .globl _Z3foov # -- Begin function _Z3foov
- .p2align 4, 0x90
- .type _Z3foov, at function
-_Z3foov: # @_Z3foov
-.Lfunc_begin0:
- .cfi_startproc
-# %bb.0: # %entry
- pushq %rbp
- .cfi_def_cfa_offset 16
- .cfi_offset %rbp, -16
- movq %rsp, %rbp
- .cfi_def_cfa_register %rbp
-.Ltmp0:
- movl $1024, -16(%rbp) # imm = 0x400
- movb $114, -12(%rbp)
- movq $0, -8(%rbp)
- movl -16(%rbp), %eax
- movsbl -12(%rbp), %ecx
- imull %ecx, %eax
- popq %rbp
- .cfi_def_cfa %rsp, 8
- retq
-.Ltmp1:
-.Lfunc_end0:
- .size _Z3foov, .Lfunc_end0-_Z3foov
- .cfi_endproc
- # -- End function
- .globl _ZN11parent_test3fooEv # -- Begin function _ZN11parent_test3fooEv
- .p2align 4, 0x90
- .type _ZN11parent_test3fooEv, at function
-_ZN11parent_test3fooEv: # @_ZN11parent_test3fooEv
-.Lfunc_begin1:
- .cfi_startproc
-# %bb.0: # %entry
- pushq %rbp
- .cfi_def_cfa_offset 16
- .cfi_offset %rbp, -16
- movq %rsp, %rbp
- .cfi_def_cfa_register %rbp
-.Ltmp2:
- movl $25, %eax
- popq %rbp
- .cfi_def_cfa %rsp, 8
- retq
-.Ltmp3:
-.Lfunc_end1:
- .size _ZN11parent_test3fooEv, .Lfunc_end1-_ZN11parent_test3fooEv
- .cfi_endproc
- # -- End function
- .section .debug_abbrev,"", at progbits
- .byte 0 # EOM(1)
- .byte 0 # EOM(2)
- .byte 0 # EOM(3)
- .section .debug_info,"", at progbits
-.Lcu_begin0:
- .long .Ldebug_info_end0-.Ldebug_info_start0 # Length of Unit
-.Ldebug_info_start0:
- .short 5 # DWARF version number
- .byte 1 # DWARF Unit Type
- .byte 8 # Address Size (in bytes)
- .long .debug_abbrev # Offset Into Abbrev. Section
-.Ldebug_info_end0:
- .section .debug_str_offsets,"", at progbits
- .long 56 # Length of String Offsets Set
- .short 5
- .short 0
-.Lstr_offsets_base0:
- .section .debug_str,"MS", at progbits,1
-.Linfo_string0:
- .asciz "clang version 19.0.0git (git at github.com:llvm/llvm-project.git 4df364bc93af49ae413ec1ae8328f34ac70730c4)" # string offset=0
-.Linfo_string1:
- .asciz "debug-names-parent-idx-2.cpp" # string offset=104
-.Linfo_string2:
- .asciz "parent-idx-test" # string offset=133
-.Linfo_string3:
- .asciz "int" # string offset=149
-.Linfo_string4:
- .asciz "foo" # string offset=153
-.Linfo_string5:
- .asciz "_Z3foov" # string offset=157
-.Linfo_string6:
- .asciz "parent_test" # string offset=165
-.Linfo_string7:
- .asciz "_ZN11parent_test3fooEv" # string offset=177
-.Linfo_string8:
- .asciz "struct2" # string offset=200
-.Linfo_string9:
- .asciz "x" # string offset=208
-.Linfo_string10:
- .asciz "y" # string offset=210
-.Linfo_string11:
- .asciz "char" # string offset=212
-.Linfo_string12:
- .asciz "foo_ptr" # string offset=217
-.Laddr_table_base0:
- .quad .Lfunc_begin0
- .quad .Lfunc_begin1
-.Ldebug_addr_end0:
- .section .debug_names,"", at progbits
- .long .Lnames_end0-.Lnames_start0 # Header: unit length
-.Lnames_start0:
- .short 5 # Header: version
- .short 0 # Header: padding
- .long 1 # Header: compilation unit count
- .long 0 # Header: local type unit count
- .long 0 # Header: foreign type unit count
- .long 6 # Header: bucket count
- .long 6 # Header: name count
- .long .Lnames_abbrev_end0-.Lnames_abbrev_start0 # Header: abbreviation table size
- .long 8 # Header: augmentation string size
- .ascii "LLVM0700" # Header: augmentation string
- .long .Lcu_begin0 # Compilation unit 0
- .long 0 # Bucket 0
- .long 1 # Bucket 1
- .long 3 # Bucket 2
- .long 5 # Bucket 3
- .long 0 # Bucket 4
- .long 6 # Bucket 5
- .long -1451972055 # Hash in Bucket 1
- .long -1257882357 # Hash in Bucket 1
- .long 175265198 # Hash in Bucket 2
- .long 193495088 # Hash in Bucket 2
- .long 193491849 # Hash in Bucket 3
- .long 2090147939 # Hash in Bucket 5
- .long .Linfo_string7 # String in Bucket 1: _ZN11parent_test3fooEv
- .long .Linfo_string5 # String in Bucket 1: _Z3foov
- .long .Linfo_string6 # String in Bucket 2: parent_test
- .long .Linfo_string3 # String in Bucket 2: int
- .long .Linfo_string4 # String in Bucket 3: foo
- .long .Linfo_string11 # String in Bucket 5: char
- .long .Lnames4-.Lnames_entries0 # Offset in Bucket 1
- .long .Lnames2-.Lnames_entries0 # Offset in Bucket 1
- .long .Lnames3-.Lnames_entries0 # Offset in Bucket 2
- .long .Lnames0-.Lnames_entries0 # Offset in Bucket 2
- .long .Lnames1-.Lnames_entries0 # Offset in Bucket 3
- .long .Lnames5-.Lnames_entries0 # Offset in Bucket 5
-.Lnames_abbrev_start0:
- .byte 1 # Abbrev code
- .byte 46 # DW_TAG_subprogram
- .byte 3 # DW_IDX_die_offset
- .byte 19 # DW_FORM_ref4
- .byte 4 # DW_IDX_parent
- .byte 19 # DW_FORM_ref4
- .byte 0 # End of abbrev
- .byte 0 # End of abbrev
- .byte 2 # Abbrev code
- .byte 46 # DW_TAG_subprogram
- .byte 3 # DW_IDX_die_offset
- .byte 19 # DW_FORM_ref4
- .byte 4 # DW_IDX_parent
- .byte 25 # DW_FORM_flag_present
- .byte 0 # End of abbrev
- .byte 0 # End of abbrev
- .byte 3 # Abbrev code
- .byte 57 # DW_TAG_namespace
- .byte 3 # DW_IDX_die_offset
- .byte 19 # DW_FORM_ref4
- .byte 4 # DW_IDX_parent
- .byte 25 # DW_FORM_flag_present
- .byte 0 # End of abbrev
- .byte 0 # End of abbrev
- .byte 4 # Abbrev code
- .byte 36 # DW_TAG_base_type
- .byte 3 # DW_IDX_die_offset
- .byte 19 # DW_FORM_ref4
- .byte 4 # DW_IDX_parent
- .byte 25 # DW_FORM_flag_present
- .byte 0 # End of abbrev
- .byte 0 # End of abbrev
- .byte 5 # Abbrev code
- .byte 19 # DW_TAG_structure_type
- .byte 3 # DW_IDX_die_offset
- .byte 19 # DW_FORM_ref4
- .byte 4 # DW_IDX_parent
- .byte 25 # DW_FORM_flag_present
- .byte 0 # End of abbrev
- .byte 0 # End of abbrev
- .byte 0 # End of abbrev list
-.Lnames_abbrev_end0:
-.Lnames_entries0:
-.Lnames4:
-.L3:
- .byte 1 # Abbreviation code
- .long 69 # DW_IDX_die_offset
- .long .L5-.Lnames_entries0 # DW_IDX_parent
- .byte 0 # End of list: _ZN11parent_test3fooEv
-.Lnames2:
-.L0:
- .byte 2 # Abbreviation code
- .long 39 # DW_IDX_die_offset
- .byte 0 # DW_IDX_parent
- # End of list: _Z3foov
-.Lnames3:
-.L5:
- .byte 3 # Abbreviation code
- .long 67 # DW_IDX_die_offset
- .byte 0 # DW_IDX_parent
- # End of list: parent_test
-.Lnames0:
-.L2:
- .byte 4 # Abbreviation code
- .long 35 # DW_IDX_die_offset
- .byte 0 # DW_IDX_parent
- # End of list: int
-.Lnames1:
- .byte 2 # Abbreviation code
- .long 39 # DW_IDX_die_offset
- .byte 1 # DW_IDX_parent
- # Abbreviation code
- .long 69 # DW_IDX_die_offset
- .long .L5-.Lnames_entries0 # DW_IDX_parent
-.L4:
- .byte 5 # Abbreviation code
- .long 86 # DW_IDX_die_offset
- .byte 0 # DW_IDX_parent
- # End of list: foo
-.Lnames5:
-.L1:
- .byte 4 # Abbreviation code
- .long 120 # DW_IDX_die_offset
- .byte 0 # DW_IDX_parent
- # End of list: char
- .p2align 2, 0x0
-.Lnames_end0:
- .ident "clang version 19.0.0git (git at github.com:llvm/llvm-project.git 4df364bc93af49ae413ec1ae8328f34ac70730c4)"
- .section ".note.GNU-stack","", at progbits
- .addrsig
- .section .debug_line,"", at progbits
-.Lline_table_start0:
diff --git a/lld/test/ELF/debug-names-bad-aug-string.s b/lld/test/ELF/debug-names-bad-aug-string.s
index 0c4f625fad7c18..bf46f4ccef03db 100644
--- a/lld/test/ELF/debug-names-bad-aug-string.s
+++ b/lld/test/ELF/debug-names-bad-aug-string.s
@@ -2,12 +2,17 @@
// editing the 'Header: augmentation string' in the .debug_names section.
// REQUIRES: x86
-// RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t1.o
-// RUN: llvm-mc -filetype=obj -triple=x86_64 %p/Inputs/debug-names-2.s -o %t2.o
-// RUN: ld.lld --debug-names %t1.o %t2.o -o %t
+// RUN: rm -rf %t && split-file %s %t
+// RUN: llvm-mc -filetype=obj -triple=x86_64 %t/debug-names-bad-aug-string.s \
+// RUN: -o %t/debug-names-bad-aug-string.o
+// RUN: llvm-mc -filetype=obj -triple=x86_64 %t/debug-names-2.s \
+// RUN: -o %t/debug-names-2.o
+// RUN: ld.lld --debug-names %t/debug-names-bad-aug-string.o \
+// RUN: %t/debug-names-2.o -o %t/debug-names-bad-aug-string
-// RUN: llvm-dwarfdump -debug-names %t \
-// RUN: | FileCheck -DFILE=%t1.o -DFILE=%t2.o %s --check-prefix=DWARF
+// RUN: llvm-dwarfdump -debug-names %t/debug-names-bad-aug-string \
+// RUN: | FileCheck -DFILE=%t/debug-names-bad-aug-string.o \
+// RUN: -DFILE=%t/debug-names-2.o %s --check-prefix=DWARF
// DWARF: .debug_names contents:
// DWARF: Name Index @ 0x0 {
@@ -25,6 +30,8 @@
// DWARF: Compilation Unit offsets [
// DWARF-NEXT: CU[0]: 0x00000000
// DWARF-NEXT: CU[1]: 0x0000000c
+
+#--- debug-names-bad-aug-string.s
.text
.globl _Z2f12t1 # -- Begin function _Z2f12t1
.p2align 4, 0x90
@@ -151,3 +158,155 @@ _Z2f12t1: # @_Z2f12t1
.addrsig
.section .debug_line,"", at progbits
.Lline_table_start0:
+
+#--- debug-names-2.s
+// input file: debug-names-2.cpp
+// Generated with:
+// - clang++ -g -O0 -gpubnames -fdebug-compilation-dir='debug-names-test' \
+// -S debug-names-2.cpp -o debug-names-2.s
+
+// debug-names-2.cpp contents:
+
+// struct t1 { };
+// int main() {
+// t1 v1;
+// }
+//
+ .text
+ .globl main # -- Begin function main
+ .p2align 4, 0x90
+ .type main, at function
+main: # @main
+.Lfunc_begin0:
+ .cfi_startproc
+# %bb.0: # %entry
+ pushq %rbp
+ .cfi_def_cfa_offset 16
+ .cfi_offset %rbp, -16
+ movq %rsp, %rbp
+ .cfi_def_cfa_register %rbp
+.Ltmp0:
+ xorl %eax, %eax
+ popq %rbp
+ .cfi_def_cfa %rsp, 8
+ retq
+.Ltmp1:
+.Lfunc_end0:
+ .size main, .Lfunc_end0-main
+ .cfi_endproc
+ # -- End function
+ .section .debug_abbrev,"", at progbits
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 0 # EOM(3)
+ .section .debug_info,"", at progbits
+.Lcu_begin0:
+ .long .Ldebug_info_end0-.Ldebug_info_start0 # Length of Unit
+.Ldebug_info_start0:
+ .short 5 # DWARF version number
+ .byte 1 # DWARF Unit Type
+ .byte 8 # Address Size (in bytes)
+ .long .debug_abbrev # Offset Into Abbrev. Section
+.Ldebug_info_end0:
+ .section .debug_str_offsets,"", at progbits
+ .long 32 # Length of String Offsets Set
+ .short 5
+ .short 0
+.Lstr_offsets_base0:
+ .section .debug_str,"MS", at progbits,1
+.Linfo_string0:
+ .asciz "clang version 19.0.0git (git at github.com:llvm/llvm-project.git 4df364bc93af49ae413ec1ae8328f34ac70730c4)" # string offset=0
+.Linfo_string1:
+ .asciz "debug-names-2.cpp" # string offset=104
+.Linfo_string2:
+ .asciz "debug-names-test" # string offset=122
+.Linfo_string3:
+ .asciz "main" # string offset=139
+.Linfo_string4:
+ .asciz "int" # string offset=144
+.Linfo_string5:
+ .asciz "v1" # string offset=148
+.Linfo_string6:
+ .asciz "t1" # string offset=151
+.Laddr_table_base0:
+ .quad .Lfunc_begin0
+.Ldebug_addr_end0:
+ .section .debug_names,"", at progbits
+ .long .Lnames_end0-.Lnames_start0 # Header: unit length
+.Lnames_start0:
+ .short 5 # Header: version
+ .short 0 # Header: padding
+ .long 1 # Header: compilation unit count
+ .long 0 # Header: local type unit count
+ .long 0 # Header: foreign type unit count
+ .long 3 # Header: bucket count
+ .long 3 # Header: name count
+ .long .Lnames_abbrev_end0-.Lnames_abbrev_start0 # Header: abbreviation table size
+ .long 8 # Header: augmentation string size
+ .ascii "LLVM0700" # Header: augmentation string
+ .long .Lcu_begin0 # Compilation unit 0
+ .long 0 # Bucket 0
+ .long 1 # Bucket 1
+ .long 3 # Bucket 2
+ .long 5863786 # Hash in Bucket 1
+ .long 2090499946 # Hash in Bucket 1
+ .long 193495088 # Hash in Bucket 2
+ .long .Linfo_string6 # String in Bucket 1: t1
+ .long .Linfo_string3 # String in Bucket 1: main
+ .long .Linfo_string4 # String in Bucket 2: int
+ .long .Lnames2-.Lnames_entries0 # Offset in Bucket 1
+ .long .Lnames0-.Lnames_entries0 # Offset in Bucket 1
+ .long .Lnames1-.Lnames_entries0 # Offset in Bucket 2
+.Lnames_abbrev_start0:
+ .byte 1 # Abbrev code
+ .byte 19 # DW_TAG_structure_type
+ .byte 3 # DW_IDX_die_offset
+ .byte 19 # DW_FORM_ref4
+ .byte 4 # DW_IDX_parent
+ .byte 25 # DW_FORM_flag_present
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev
+ .byte 2 # Abbrev code
+ .byte 46 # DW_TAG_subprogram
+ .byte 3 # DW_IDX_die_offset
+ .byte 19 # DW_FORM_ref4
+ .byte 4 # DW_IDX_parent
+ .byte 25 # DW_FORM_flag_present
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev
+ .byte 3 # Abbrev code
+ .byte 36 # DW_TAG_base_type
+ .byte 3 # DW_IDX_die_offset
+ .byte 19 # DW_FORM_ref4
+ .byte 4 # DW_IDX_parent
+ .byte 25 # DW_FORM_flag_present
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev list
+.Lnames_abbrev_end0:
+.Lnames_entries0:
+.Lnames2:
+.L1:
+ .byte 1 # Abbreviation code
+ .long 66 # DW_IDX_die_offset
+ .byte 0 # DW_IDX_parent
+ # End of list: t1
+.Lnames0:
+.L2:
+ .byte 2 # Abbreviation code
+ .long 35 # DW_IDX_die_offset
+ .byte 0 # DW_IDX_parent
+ # End of list: main
+.Lnames1:
+.L0:
+ .byte 3 # Abbreviation code
+ .long 62 # DW_IDX_die_offset
+ .byte 0 # DW_IDX_parent
+ # End of list: int
+ .p2align 2, 0x0
+.Lnames_end0:
+ .ident "clang version 19.0.0git (git at github.com:llvm/llvm-project.git 4df364bc93af49ae413ec1ae8328f34ac70730c4)"
+ .section ".note.GNU-stack","", at progbits
+ .addrsig
+ .section .debug_line,"", at progbits
+.Lline_table_start0:
diff --git a/lld/test/ELF/debug-names-bad-version.s b/lld/test/ELF/debug-names-bad-version.s
index 6a299805ca090f..eda1eaa03039bf 100644
--- a/lld/test/ELF/debug-names-bad-version.s
+++ b/lld/test/ELF/debug-names-bad-version.s
@@ -3,12 +3,17 @@
// 5 to 4).
// REQUIRES: x86
-// RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t1.o
-// RUN: llvm-mc -filetype=obj -triple=x86_64 %p/Inputs/debug-names-2.s -o %t2.o
-// RUN: not ld.lld --debug-names %t1.o %t2.o -o /dev/null 2>&1 | FileCheck %s
+// RUN: rm -rf %t && split-file %s %t
+// RUN: llvm-mc -filetype=obj -triple=x86_64 %t/debug-names-bad-version.s \
+// RUN: -o %t/debug-names-bad-version.o
+// RUN: llvm-mc -filetype=obj -triple=x86_64 %t/debug-names-2.s \
+// RUN: -o %t/debug-names-2.o
+// RUN: not ld.lld --debug-names %t/debug-names-bad-version.o \
+// RUN: %t/debug-names-2.o -o /dev/null 2>&1 | FileCheck %s
// CHECK: error: {{.*}}:(.debug_names): unsupported version
-
+
+#--- debug-names-bad-version.s
.text
.globl _Z2f12t1 # -- Begin function _Z2f12t1
.p2align 4, 0x90
@@ -170,3 +175,155 @@ _Z2f12t1: # @_Z2f12t1
.addrsig
.section .debug_line,"", at progbits
.Lline_table_start0:
+
+#--- debug-names-2.s
+// input file: debug-names-2.cpp
+// Generated with:
+// - clang++ -g -O0 -gpubnames -fdebug-compilation-dir='debug-names-test' \
+// -S debug-names-2.cpp -o debug-names-2.s
+
+// debug-names-2.cpp contents:
+
+// struct t1 { };
+// int main() {
+// t1 v1;
+// }
+//
+ .text
+ .globl main # -- Begin function main
+ .p2align 4, 0x90
+ .type main, at function
+main: # @main
+.Lfunc_begin0:
+ .cfi_startproc
+# %bb.0: # %entry
+ pushq %rbp
+ .cfi_def_cfa_offset 16
+ .cfi_offset %rbp, -16
+ movq %rsp, %rbp
+ .cfi_def_cfa_register %rbp
+.Ltmp0:
+ xorl %eax, %eax
+ popq %rbp
+ .cfi_def_cfa %rsp, 8
+ retq
+.Ltmp1:
+.Lfunc_end0:
+ .size main, .Lfunc_end0-main
+ .cfi_endproc
+ # -- End function
+ .section .debug_abbrev,"", at progbits
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 0 # EOM(3)
+ .section .debug_info,"", at progbits
+.Lcu_begin0:
+ .long .Ldebug_info_end0-.Ldebug_info_start0 # Length of Unit
+.Ldebug_info_start0:
+ .short 5 # DWARF version number
+ .byte 1 # DWARF Unit Type
+ .byte 8 # Address Size (in bytes)
+ .long .debug_abbrev # Offset Into Abbrev. Section
+.Ldebug_info_end0:
+ .section .debug_str_offsets,"", at progbits
+ .long 32 # Length of String Offsets Set
+ .short 5
+ .short 0
+.Lstr_offsets_base0:
+ .section .debug_str,"MS", at progbits,1
+.Linfo_string0:
+ .asciz "clang version 19.0.0git (git at github.com:llvm/llvm-project.git 4df364bc93af49ae413ec1ae8328f34ac70730c4)" # string offset=0
+.Linfo_string1:
+ .asciz "debug-names-2.cpp" # string offset=104
+.Linfo_string2:
+ .asciz "debug-names-test" # string offset=122
+.Linfo_string3:
+ .asciz "main" # string offset=139
+.Linfo_string4:
+ .asciz "int" # string offset=144
+.Linfo_string5:
+ .asciz "v1" # string offset=148
+.Linfo_string6:
+ .asciz "t1" # string offset=151
+.Laddr_table_base0:
+ .quad .Lfunc_begin0
+.Ldebug_addr_end0:
+ .section .debug_names,"", at progbits
+ .long .Lnames_end0-.Lnames_start0 # Header: unit length
+.Lnames_start0:
+ .short 5 # Header: version
+ .short 0 # Header: padding
+ .long 1 # Header: compilation unit count
+ .long 0 # Header: local type unit count
+ .long 0 # Header: foreign type unit count
+ .long 3 # Header: bucket count
+ .long 3 # Header: name count
+ .long .Lnames_abbrev_end0-.Lnames_abbrev_start0 # Header: abbreviation table size
+ .long 8 # Header: augmentation string size
+ .ascii "LLVM0700" # Header: augmentation string
+ .long .Lcu_begin0 # Compilation unit 0
+ .long 0 # Bucket 0
+ .long 1 # Bucket 1
+ .long 3 # Bucket 2
+ .long 5863786 # Hash in Bucket 1
+ .long 2090499946 # Hash in Bucket 1
+ .long 193495088 # Hash in Bucket 2
+ .long .Linfo_string6 # String in Bucket 1: t1
+ .long .Linfo_string3 # String in Bucket 1: main
+ .long .Linfo_string4 # String in Bucket 2: int
+ .long .Lnames2-.Lnames_entries0 # Offset in Bucket 1
+ .long .Lnames0-.Lnames_entries0 # Offset in Bucket 1
+ .long .Lnames1-.Lnames_entries0 # Offset in Bucket 2
+.Lnames_abbrev_start0:
+ .byte 1 # Abbrev code
+ .byte 19 # DW_TAG_structure_type
+ .byte 3 # DW_IDX_die_offset
+ .byte 19 # DW_FORM_ref4
+ .byte 4 # DW_IDX_parent
+ .byte 25 # DW_FORM_flag_present
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev
+ .byte 2 # Abbrev code
+ .byte 46 # DW_TAG_subprogram
+ .byte 3 # DW_IDX_die_offset
+ .byte 19 # DW_FORM_ref4
+ .byte 4 # DW_IDX_parent
+ .byte 25 # DW_FORM_flag_present
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev
+ .byte 3 # Abbrev code
+ .byte 36 # DW_TAG_base_type
+ .byte 3 # DW_IDX_die_offset
+ .byte 19 # DW_FORM_ref4
+ .byte 4 # DW_IDX_parent
+ .byte 25 # DW_FORM_flag_present
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev list
+.Lnames_abbrev_end0:
+.Lnames_entries0:
+.Lnames2:
+.L1:
+ .byte 1 # Abbreviation code
+ .long 66 # DW_IDX_die_offset
+ .byte 0 # DW_IDX_parent
+ # End of list: t1
+.Lnames0:
+.L2:
+ .byte 2 # Abbreviation code
+ .long 35 # DW_IDX_die_offset
+ .byte 0 # DW_IDX_parent
+ # End of list: main
+.Lnames1:
+.L0:
+ .byte 3 # Abbreviation code
+ .long 62 # DW_IDX_die_offset
+ .byte 0 # DW_IDX_parent
+ # End of list: int
+ .p2align 2, 0x0
+.Lnames_end0:
+ .ident "clang version 19.0.0git (git at github.com:llvm/llvm-project.git 4df364bc93af49ae413ec1ae8328f34ac70730c4)"
+ .section ".note.GNU-stack","", at progbits
+ .addrsig
+ .section .debug_line,"", at progbits
+.Lline_table_start0:
diff --git a/lld/test/ELF/debug-names-parent-idx.s b/lld/test/ELF/debug-names-parent-idx.s
index cda9203fd21670..b44455bb498ef8 100644
--- a/lld/test/ELF/debug-names-parent-idx.s
+++ b/lld/test/ELF/debug-names-parent-idx.s
@@ -1,4 +1,4 @@
-// Generated with:
+// debug-names-parent-idx.s generated with:
// - clang++ -g -O0 -gpubnames -fdebug-compilation-dir='parent-idx-test' \
// -S debug-names-parent-idx.cpp -o debug-names-parent-idx.s
@@ -35,12 +35,17 @@
// }
// REQUIRES: x86
-// RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t1.o
-// RUN: llvm-mc -filetype=obj -triple=x86_64 %p/Inputs/debug-names-parent-idx-2.s -o %t2.o
-// RUN: ld.lld --debug-names %t1.o %t2.o -o %t
+// RUN: rm -rf %t && split-file %s %t
+// RUN: llvm-mc -filetype=obj -triple=x86_64 %t/debug-names-parent-idx.s \
+// RUN: -o %t/debug-names-parent-idx.o
+// RUN: llvm-mc -filetype=obj -triple=x86_64 %t/debug-names-parent-idx-2.s \
+// RUN: -o %t/debug-names-parent-idx-2.o
+// RUN: ld.lld --debug-names %t/debug-names-parent-idx.o \
+// RUN: %t/debug-names-parent-idx-2.o -o %t/debug-names-parent-idx
-// RUN: llvm-dwarfdump -debug-names %t \
-// RUN: | FileCheck -DFILE=%t1.o -DFILE=%t2.o %s --check-prefix=DWARF
+// RUN: llvm-dwarfdump -debug-names %t/debug-names-parent-idx \
+// RUN: | FileCheck -DFILE=%t/debug-names-parent-idx.o \
+// RUN: -DFILE=%t/debug-names-parent-idx-2.o %s --check-prefix=DWARF
// DWARF: .debug_names contents:
// DWARF: Name Index @ 0x0 {
@@ -183,6 +188,7 @@
// DWARF-NEXT: DW_IDX_parent: <parent not indexed>
// DWARF-NEXT: DW_IDX_compile_unit: 0x01
+#--- debug-names-parent-idx.s
.text
.globl _Z3barR3fooi # -- Begin function _Z3barR3fooi
.p2align 4, 0x90
@@ -417,3 +423,271 @@ main: # @main
.addrsig_sym _ZN11parent_test3fooEv
.section .debug_line,"", at progbits
.Lline_table_start0:
+
+#--- debug-names-parent-idx-2.s
+// Generated with:
+
+// - clang++ -g -O0 -gpubnames -fdebug-compilation-dir='parent-idx-test' \
+// -S debug-names-parent-idx-2.cpp -o debug-names-parent-idx-2.s
+
+// foo.h contents:
+
+// int foo();
+
+//struct foo {
+// int x;
+// char y;
+// struct foo *foo_ptr;
+// };
+
+// namespace parent_test {
+// int foo();
+// }
+
+// debug-names-parent-index-2.cpp contents:
+
+// #include "foo.h"
+// int foo () {
+// struct foo struct2;
+// struct2.x = 1024;
+// struct2.y = 'r';
+// struct2.foo_ptr = nullptr;
+// return struct2.x * (int) struct2.y;
+// }
+
+// namespace parent_test {
+// int foo () {
+// return 25;
+// }
+// }
+
+ .text
+ .globl _Z3foov # -- Begin function _Z3foov
+ .p2align 4, 0x90
+ .type _Z3foov, at function
+_Z3foov: # @_Z3foov
+.Lfunc_begin0:
+ .cfi_startproc
+# %bb.0: # %entry
+ pushq %rbp
+ .cfi_def_cfa_offset 16
+ .cfi_offset %rbp, -16
+ movq %rsp, %rbp
+ .cfi_def_cfa_register %rbp
+.Ltmp0:
+ movl $1024, -16(%rbp) # imm = 0x400
+ movb $114, -12(%rbp)
+ movq $0, -8(%rbp)
+ movl -16(%rbp), %eax
+ movsbl -12(%rbp), %ecx
+ imull %ecx, %eax
+ popq %rbp
+ .cfi_def_cfa %rsp, 8
+ retq
+.Ltmp1:
+.Lfunc_end0:
+ .size _Z3foov, .Lfunc_end0-_Z3foov
+ .cfi_endproc
+ # -- End function
+ .globl _ZN11parent_test3fooEv # -- Begin function _ZN11parent_test3fooEv
+ .p2align 4, 0x90
+ .type _ZN11parent_test3fooEv, at function
+_ZN11parent_test3fooEv: # @_ZN11parent_test3fooEv
+.Lfunc_begin1:
+ .cfi_startproc
+# %bb.0: # %entry
+ pushq %rbp
+ .cfi_def_cfa_offset 16
+ .cfi_offset %rbp, -16
+ movq %rsp, %rbp
+ .cfi_def_cfa_register %rbp
+.Ltmp2:
+ movl $25, %eax
+ popq %rbp
+ .cfi_def_cfa %rsp, 8
+ retq
+.Ltmp3:
+.Lfunc_end1:
+ .size _ZN11parent_test3fooEv, .Lfunc_end1-_ZN11parent_test3fooEv
+ .cfi_endproc
+ # -- End function
+ .section .debug_abbrev,"", at progbits
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 0 # EOM(3)
+ .section .debug_info,"", at progbits
+.Lcu_begin0:
+ .long .Ldebug_info_end0-.Ldebug_info_start0 # Length of Unit
+.Ldebug_info_start0:
+ .short 5 # DWARF version number
+ .byte 1 # DWARF Unit Type
+ .byte 8 # Address Size (in bytes)
+ .long .debug_abbrev # Offset Into Abbrev. Section
+.Ldebug_info_end0:
+ .section .debug_str_offsets,"", at progbits
+ .long 56 # Length of String Offsets Set
+ .short 5
+ .short 0
+.Lstr_offsets_base0:
+ .section .debug_str,"MS", at progbits,1
+.Linfo_string0:
+ .asciz "clang version 19.0.0git (git at github.com:llvm/llvm-project.git 4df364bc93af49ae413ec1ae8328f34ac70730c4)" # string offset=0
+.Linfo_string1:
+ .asciz "debug-names-parent-idx-2.cpp" # string offset=104
+.Linfo_string2:
+ .asciz "parent-idx-test" # string offset=133
+.Linfo_string3:
+ .asciz "int" # string offset=149
+.Linfo_string4:
+ .asciz "foo" # string offset=153
+.Linfo_string5:
+ .asciz "_Z3foov" # string offset=157
+.Linfo_string6:
+ .asciz "parent_test" # string offset=165
+.Linfo_string7:
+ .asciz "_ZN11parent_test3fooEv" # string offset=177
+.Linfo_string8:
+ .asciz "struct2" # string offset=200
+.Linfo_string9:
+ .asciz "x" # string offset=208
+.Linfo_string10:
+ .asciz "y" # string offset=210
+.Linfo_string11:
+ .asciz "char" # string offset=212
+.Linfo_string12:
+ .asciz "foo_ptr" # string offset=217
+.Laddr_table_base0:
+ .quad .Lfunc_begin0
+ .quad .Lfunc_begin1
+.Ldebug_addr_end0:
+ .section .debug_names,"", at progbits
+ .long .Lnames_end0-.Lnames_start0 # Header: unit length
+.Lnames_start0:
+ .short 5 # Header: version
+ .short 0 # Header: padding
+ .long 1 # Header: compilation unit count
+ .long 0 # Header: local type unit count
+ .long 0 # Header: foreign type unit count
+ .long 6 # Header: bucket count
+ .long 6 # Header: name count
+ .long .Lnames_abbrev_end0-.Lnames_abbrev_start0 # Header: abbreviation table size
+ .long 8 # Header: augmentation string size
+ .ascii "LLVM0700" # Header: augmentation string
+ .long .Lcu_begin0 # Compilation unit 0
+ .long 0 # Bucket 0
+ .long 1 # Bucket 1
+ .long 3 # Bucket 2
+ .long 5 # Bucket 3
+ .long 0 # Bucket 4
+ .long 6 # Bucket 5
+ .long -1451972055 # Hash in Bucket 1
+ .long -1257882357 # Hash in Bucket 1
+ .long 175265198 # Hash in Bucket 2
+ .long 193495088 # Hash in Bucket 2
+ .long 193491849 # Hash in Bucket 3
+ .long 2090147939 # Hash in Bucket 5
+ .long .Linfo_string7 # String in Bucket 1: _ZN11parent_test3fooEv
+ .long .Linfo_string5 # String in Bucket 1: _Z3foov
+ .long .Linfo_string6 # String in Bucket 2: parent_test
+ .long .Linfo_string3 # String in Bucket 2: int
+ .long .Linfo_string4 # String in Bucket 3: foo
+ .long .Linfo_string11 # String in Bucket 5: char
+ .long .Lnames4-.Lnames_entries0 # Offset in Bucket 1
+ .long .Lnames2-.Lnames_entries0 # Offset in Bucket 1
+ .long .Lnames3-.Lnames_entries0 # Offset in Bucket 2
+ .long .Lnames0-.Lnames_entries0 # Offset in Bucket 2
+ .long .Lnames1-.Lnames_entries0 # Offset in Bucket 3
+ .long .Lnames5-.Lnames_entries0 # Offset in Bucket 5
+.Lnames_abbrev_start0:
+ .byte 1 # Abbrev code
+ .byte 46 # DW_TAG_subprogram
+ .byte 3 # DW_IDX_die_offset
+ .byte 19 # DW_FORM_ref4
+ .byte 4 # DW_IDX_parent
+ .byte 19 # DW_FORM_ref4
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev
+ .byte 2 # Abbrev code
+ .byte 46 # DW_TAG_subprogram
+ .byte 3 # DW_IDX_die_offset
+ .byte 19 # DW_FORM_ref4
+ .byte 4 # DW_IDX_parent
+ .byte 25 # DW_FORM_flag_present
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev
+ .byte 3 # Abbrev code
+ .byte 57 # DW_TAG_namespace
+ .byte 3 # DW_IDX_die_offset
+ .byte 19 # DW_FORM_ref4
+ .byte 4 # DW_IDX_parent
+ .byte 25 # DW_FORM_flag_present
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev
+ .byte 4 # Abbrev code
+ .byte 36 # DW_TAG_base_type
+ .byte 3 # DW_IDX_die_offset
+ .byte 19 # DW_FORM_ref4
+ .byte 4 # DW_IDX_parent
+ .byte 25 # DW_FORM_flag_present
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev
+ .byte 5 # Abbrev code
+ .byte 19 # DW_TAG_structure_type
+ .byte 3 # DW_IDX_die_offset
+ .byte 19 # DW_FORM_ref4
+ .byte 4 # DW_IDX_parent
+ .byte 25 # DW_FORM_flag_present
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev list
+.Lnames_abbrev_end0:
+.Lnames_entries0:
+.Lnames4:
+.L3:
+ .byte 1 # Abbreviation code
+ .long 69 # DW_IDX_die_offset
+ .long .L5-.Lnames_entries0 # DW_IDX_parent
+ .byte 0 # End of list: _ZN11parent_test3fooEv
+.Lnames2:
+.L0:
+ .byte 2 # Abbreviation code
+ .long 39 # DW_IDX_die_offset
+ .byte 0 # DW_IDX_parent
+ # End of list: _Z3foov
+.Lnames3:
+.L5:
+ .byte 3 # Abbreviation code
+ .long 67 # DW_IDX_die_offset
+ .byte 0 # DW_IDX_parent
+ # End of list: parent_test
+.Lnames0:
+.L2:
+ .byte 4 # Abbreviation code
+ .long 35 # DW_IDX_die_offset
+ .byte 0 # DW_IDX_parent
+ # End of list: int
+.Lnames1:
+ .byte 2 # Abbreviation code
+ .long 39 # DW_IDX_die_offset
+ .byte 1 # DW_IDX_parent
+ # Abbreviation code
+ .long 69 # DW_IDX_die_offset
+ .long .L5-.Lnames_entries0 # DW_IDX_parent
+.L4:
+ .byte 5 # Abbreviation code
+ .long 86 # DW_IDX_die_offset
+ .byte 0 # DW_IDX_parent
+ # End of list: foo
+.Lnames5:
+.L1:
+ .byte 4 # Abbreviation code
+ .long 120 # DW_IDX_die_offset
+ .byte 0 # DW_IDX_parent
+ # End of list: char
+ .p2align 2, 0x0
+.Lnames_end0:
+ .ident "clang version 19.0.0git (git at github.com:llvm/llvm-project.git 4df364bc93af49ae413ec1ae8328f34ac70730c4)"
+ .section ".note.GNU-stack","", at progbits
+ .addrsig
+ .section .debug_line,"", at progbits
+.Lline_table_start0:
diff --git a/lld/test/ELF/debug-names.s b/lld/test/ELF/debug-names.s
index ca6d32998542b5..baadadd98ebf4f 100644
--- a/lld/test/ELF/debug-names.s
+++ b/lld/test/ELF/debug-names.s
@@ -1,4 +1,4 @@
-// Generated with:
+// debug_names.s was gGenerated with:
// - clang++ -g -O0 -gpubnames -fdebug-compilation-dir='debug-names-test' \
// -S debug-names.cpp -o debug-names.s
@@ -9,19 +9,27 @@
// void f1(t1) { }
// REQUIRES: x86
-// RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t1.o
-// RUN: llvm-mc -filetype=obj -triple=x86_64 %p/Inputs/debug-names-2.s -o %t2.o
+// RUN: rm -rf %t && split-file %s %t
+// RUN: llvm-mc -filetype=obj -triple=x86_64 %t/debug-names.s \
+// RUN: -o %t/debug-names.o
+// RUN: llvm-mc -filetype=obj -triple=x86_64 %t/debug-names-2.s \
+// RUN: -o %t/debug-names-2.o
-// RUN: ld.lld --debug-names --no-debug-names %t1.o %t2.o -o %t
-// RUN: llvm-readelf -SW %t | FileCheck %s --check-prefix=NO_DBG_NAMES
+// RUN: ld.lld --debug-names --no-debug-names %t/debug-names.o \
+// RUN: %t/debug-names-2.o -o %t/debug-names
+// RUN: llvm-readelf -SW %t/debug-names \
+// RUN: | FileCheck %s --check-prefix=NO_DBG_NAMES
// NO_DBG_NAMES: .debug_names PROGBITS 0000000000000000 [[#%x,]] 000110
-// RUN: ld.lld --debug-names %t1.o %t2.o -o %t
+// RUN: ld.lld --debug-names %t/debug-names.o %t/debug-names-2.o \
+// RUN: -o %t/debug-names
-// RUN: llvm-dwarfdump -debug-names %t | FileCheck %s --check-prefix=DWARF
-// RUN: llvm-readelf -SW %t \
-// RUN: | FileCheck -DFILE=%t1.o -DFILE=%t2.o %s --check-prefix=READELF
+// RUN: llvm-dwarfdump -debug-names %t/debug-names \
+// RUN: | FileCheck %s --check-prefix=DWARF
+// RUN: llvm-readelf -SW %t/debug-names \
+// RUN: | FileCheck -DFILE=%t/debug-names.o \
+// RUN: -DFILE=%t/debug-names-2.o %s --check-prefix=READELF
// READELF: .debug_names PROGBITS 0000000000000000 [[#%x,]] 0000d0
@@ -105,6 +113,7 @@
// DWARF-NEXT: DW_IDX_parent: <parent not indexed>
// DWARF-NEXT: DW_IDX_compile_unit: 0x01
+#--- debug-names.s
.text
.globl _Z2f12t1 # -- Begin function _Z2f12t1
.p2align 4, 0x90
@@ -231,3 +240,154 @@ _Z2f12t1: # @_Z2f12t1
.addrsig
.section .debug_line,"", at progbits
.Lline_table_start0:
+
+#--- debug-names-2.s
+// Generated with:
+// - clang++ -g -O0 -gpubnames -fdebug-compilation-dir='debug-names-test' \
+// -S debug-names-2.cpp -o debug-names-2.s
+
+// debug-names-2.cpp contents:
+
+// struct t1 { };
+// int main() {
+// t1 v1;
+// }
+//
+ .text
+ .globl main # -- Begin function main
+ .p2align 4, 0x90
+ .type main, at function
+main: # @main
+.Lfunc_begin0:
+ .cfi_startproc
+# %bb.0: # %entry
+ pushq %rbp
+ .cfi_def_cfa_offset 16
+ .cfi_offset %rbp, -16
+ movq %rsp, %rbp
+ .cfi_def_cfa_register %rbp
+.Ltmp0:
+ xorl %eax, %eax
+ popq %rbp
+ .cfi_def_cfa %rsp, 8
+ retq
+.Ltmp1:
+.Lfunc_end0:
+ .size main, .Lfunc_end0-main
+ .cfi_endproc
+ # -- End function
+ .section .debug_abbrev,"", at progbits
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 0 # EOM(3)
+ .section .debug_info,"", at progbits
+.Lcu_begin0:
+ .long .Ldebug_info_end0-.Ldebug_info_start0 # Length of Unit
+.Ldebug_info_start0:
+ .short 5 # DWARF version number
+ .byte 1 # DWARF Unit Type
+ .byte 8 # Address Size (in bytes)
+ .long .debug_abbrev # Offset Into Abbrev. Section
+.Ldebug_info_end0:
+ .section .debug_str_offsets,"", at progbits
+ .long 32 # Length of String Offsets Set
+ .short 5
+ .short 0
+.Lstr_offsets_base0:
+ .section .debug_str,"MS", at progbits,1
+.Linfo_string0:
+ .asciz "clang version 19.0.0git (git at github.com:llvm/llvm-project.git 4df364bc93af49ae413ec1ae8328f34ac70730c4)" # string offset=0
+.Linfo_string1:
+ .asciz "debug-names-2.cpp" # string offset=104
+.Linfo_string2:
+ .asciz "debug-names-test" # string offset=122
+.Linfo_string3:
+ .asciz "main" # string offset=139
+.Linfo_string4:
+ .asciz "int" # string offset=144
+.Linfo_string5:
+ .asciz "v1" # string offset=148
+.Linfo_string6:
+ .asciz "t1" # string offset=151
+.Laddr_table_base0:
+ .quad .Lfunc_begin0
+.Ldebug_addr_end0:
+ .section .debug_names,"", at progbits
+ .long .Lnames_end0-.Lnames_start0 # Header: unit length
+.Lnames_start0:
+ .short 5 # Header: version
+ .short 0 # Header: padding
+ .long 1 # Header: compilation unit count
+ .long 0 # Header: local type unit count
+ .long 0 # Header: foreign type unit count
+ .long 3 # Header: bucket count
+ .long 3 # Header: name count
+ .long .Lnames_abbrev_end0-.Lnames_abbrev_start0 # Header: abbreviation table size
+ .long 8 # Header: augmentation string size
+ .ascii "LLVM0700" # Header: augmentation string
+ .long .Lcu_begin0 # Compilation unit 0
+ .long 0 # Bucket 0
+ .long 1 # Bucket 1
+ .long 3 # Bucket 2
+ .long 5863786 # Hash in Bucket 1
+ .long 2090499946 # Hash in Bucket 1
+ .long 193495088 # Hash in Bucket 2
+ .long .Linfo_string6 # String in Bucket 1: t1
+ .long .Linfo_string3 # String in Bucket 1: main
+ .long .Linfo_string4 # String in Bucket 2: int
+ .long .Lnames2-.Lnames_entries0 # Offset in Bucket 1
+ .long .Lnames0-.Lnames_entries0 # Offset in Bucket 1
+ .long .Lnames1-.Lnames_entries0 # Offset in Bucket 2
+.Lnames_abbrev_start0:
+ .byte 1 # Abbrev code
+ .byte 19 # DW_TAG_structure_type
+ .byte 3 # DW_IDX_die_offset
+ .byte 19 # DW_FORM_ref4
+ .byte 4 # DW_IDX_parent
+ .byte 25 # DW_FORM_flag_present
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev
+ .byte 2 # Abbrev code
+ .byte 46 # DW_TAG_subprogram
+ .byte 3 # DW_IDX_die_offset
+ .byte 19 # DW_FORM_ref4
+ .byte 4 # DW_IDX_parent
+ .byte 25 # DW_FORM_flag_present
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev
+ .byte 3 # Abbrev code
+ .byte 36 # DW_TAG_base_type
+ .byte 3 # DW_IDX_die_offset
+ .byte 19 # DW_FORM_ref4
+ .byte 4 # DW_IDX_parent
+ .byte 25 # DW_FORM_flag_present
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev list
+.Lnames_abbrev_end0:
+.Lnames_entries0:
+.Lnames2:
+.L1:
+ .byte 1 # Abbreviation code
+ .long 66 # DW_IDX_die_offset
+ .byte 0 # DW_IDX_parent
+ # End of list: t1
+.Lnames0:
+.L2:
+ .byte 2 # Abbreviation code
+ .long 35 # DW_IDX_die_offset
+ .byte 0 # DW_IDX_parent
+ # End of list: main
+.Lnames1:
+.L0:
+ .byte 3 # Abbreviation code
+ .long 62 # DW_IDX_die_offset
+ .byte 0 # DW_IDX_parent
+ # End of list: int
+ .p2align 2, 0x0
+.Lnames_end0:
+ .ident "clang version 19.0.0git (git at github.com:llvm/llvm-project.git 4df364bc93af49ae413ec1ae8328f34ac70730c4)"
+ .section ".note.GNU-stack","", at progbits
+ .addrsig
+ .section .debug_line,"", at progbits
+.Lline_table_start0:
>From e4442221c8c8197e5970b92fc86c8cf7517f319b Mon Sep 17 00:00:00 2001
From: Fangrui Song <i at maskray.me>
Date: Sun, 7 Apr 2024 12:41:58 -0700
Subject: [PATCH 14/23] Simplify and optimize .debug_names and removed dead TU
code
[ELF] Add --debug-names to create merged .debug_names
`clang -g -gpubnames` (with optional -gsplit-dwarf) creates the
`.debug_names` section ("per-CU" index). By default lld concatenates
input `.debug_names` sections into an output `.debug_names` section.
LLDB can consume the concatenated section but the lookup performance is
not good.
This patch adds --debug-names to create a per-module index by combining
the per-CU indexes into a single index that covers the entire load
module. The produced `.debug_names` is a replacement for `.gdb_index`.
Type units (-fdebug-types-section) are not handled yet.
Co-authored-by: Fangrui Song <i at maskray.me>
---
lld/ELF/SyntheticSections.cpp | 1211 +++++++----------
lld/ELF/SyntheticSections.h | 160 +--
lld/ELF/Writer.cpp | 1 +
lld/docs/ReleaseNotes.rst | 2 +
lld/test/ELF/debug-names-bad-aug-string.s | 78 +-
lld/test/ELF/debug-names-bad-die-idx-sizes.s | 25 +-
lld/test/ELF/debug-names-bad-name-count.s | 30 +-
lld/test/ELF/debug-names-bad-offsets-sizes.s | 28 +-
lld/test/ELF/debug-names-bad-version.s | 45 +-
lld/test/ELF/debug-names-dwarf64.s | 20 +-
.../ELF/debug-names-invalid-abbrev-code.s | 23 +-
.../ELF/debug-names-invalid-attribute-2.s | 24 +-
.../ELF/debug-names-invalid-attribute-3.s | 28 +-
lld/test/ELF/debug-names-invalid-attribute.s | 14 +-
lld/test/ELF/debug-names-invalid-parent-idx.s | 27 +-
lld/test/ELF/debug-names-parent-idx.s | 468 ++++---
lld/test/ELF/debug-names.s | 251 ++--
lld/test/ELF/driver.test | 3 +-
18 files changed, 1171 insertions(+), 1267 deletions(-)
diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp
index c87b29e34f69de..be307f1b001f31 100644
--- a/lld/ELF/SyntheticSections.cpp
+++ b/lld/ELF/SyntheticSections.cpp
@@ -14,7 +14,6 @@
//===----------------------------------------------------------------------===//
#include "SyntheticSections.h"
-
#include "Config.h"
#include "DWARF.h"
#include "EhFrame.h"
@@ -31,6 +30,7 @@
#include "lld/Common/Strings.h"
#include "lld/Common/Version.h"
#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/Sequence.h"
#include "llvm/ADT/SetOperations.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/BinaryFormat/Dwarf.h"
@@ -2714,754 +2714,584 @@ static uint32_t computeGdbHash(StringRef s) {
return h;
}
-template <class ELFT>
-DebugNamesSection<ELFT>::DebugNamesSection()
- : SyntheticSection(0, SHT_PROGBITS, 1, ".debug_names") {}
-
-template <class ELFT>
-template <class RelTy>
-void DebugNamesSection<ELFT>::getNameRelocsImpl(
- InputSection *sec, ArrayRef<RelTy> rels,
- DenseMap<uint32_t, uint32_t> &relocs) {
- for (auto &rel : rels) {
- Symbol &sym = sec->getFile<ELFT>()->getRelocTargetSym(rel);
- relocs[rel.r_offset] = sym.getVA(getAddend<ELFT>(rel));
- }
-}
-
-template <class ELFT>
-void DebugNamesSection<ELFT>::getNameRelocs(
- InputSectionBase *base, DenseMap<uint32_t, uint32_t> &relocs) {
- auto *sec = cast<InputSection>(base);
- const RelsOrRelas<ELFT> rels = sec->template relsOrRelas<ELFT>();
- if (rels.areRelocsRel())
- getNameRelocsImpl(sec, rels.rels, relocs);
- else
- getNameRelocsImpl(sec, rels.relas, relocs);
-}
-
-template <class ELFT> void DebugNamesSection<ELFT>::writeTo(uint8_t *buf) {
- SmallVector<uint32_t, 0> mergedCuOffsets;
- SmallVector<uint32_t, 0> mergedTuOffsets;
- DenseMap<uint32_t, uint32_t> strOffsets;
- SmallVector<DenseMap<uint32_t, uint32_t>, 0> chunksRelocs;
- chunksRelocs.reserve(numChunks);
-
- for (size_t i = 0, e = numChunks; i != e; ++i) {
- DebugNamesOutputChunk &chunk = outputChunks[i];
- InputSectionBase *base = inputDebugNamesSections[i];
- DenseMap<uint32_t, uint32_t> &relocs = chunksRelocs.emplace_back();
- getNameRelocs(base, relocs);
-
- // Update CuOffsets list with new data
- for (uint32_t cuOffset : chunk.compilationUnits)
- mergedCuOffsets.push_back(chunk.sec->outSecOff + cuOffset);
-
- // TODO: Update TuOffsets list with new data
- }
-
- // Update the entries with the relocated string offsets.
- for (NamedEntry &stringEntry : mergedEntries) {
- uint32_t oldOffset = stringEntry.stringOffsetOffset;
- uint32_t idx = stringEntry.chunkIdx;
- stringEntry.relocatedEntryOffset = chunksRelocs[idx][oldOffset];
- }
-
- // Write out bytes for merged section.
-
- // Write the header.
- endian::write32<ELFT::Endianness>(buf + 0, mergedHdr.UnitLength);
- endian::write16<ELFT::Endianness>(buf + 4, mergedHdr.Version);
- endian::write32<ELFT::Endianness>(buf + 8, mergedHdr.CompUnitCount);
- endian::write32<ELFT::Endianness>(buf + 12, mergedHdr.LocalTypeUnitCount);
- endian::write32<ELFT::Endianness>(buf + 16, mergedHdr.ForeignTypeUnitCount);
- endian::write32<ELFT::Endianness>(buf + 20, mergedHdr.BucketCount);
- endian::write32<ELFT::Endianness>(buf + 24, mergedHdr.NameCount);
- endian::write32<ELFT::Endianness>(buf + 28, mergedHdr.AbbrevTableSize);
- endian::write32<ELFT::Endianness>(buf + 32, mergedHdr.AugmentationStringSize);
- buf += 36;
- memcpy(buf, mergedHdr.AugmentationString.c_str(), 8);
- buf += 8;
-
- // Write the CU list.
- for (uint32_t offset : mergedCuOffsets) {
- endian::write32<ELFT::Endianness>(buf + 0, offset);
- buf += 4;
- }
-
- // Write the local TU list.
- // TODO: Fix this, once we get everything working without TUs.
- if (mergedHdr.LocalTypeUnitCount != 0)
- warn(".debug_names: type units are not handled in merged index");
-
- // Write the foreign TU list.
- // TODO: Fix this, once we get everything working without TUs.
- if (mergedHdr.ForeignTypeUnitCount != 0)
- warn(".debug_names: type units are not handled in merged index");
-
- // Write the hash table.
- // ... Write the buckets
- uint32_t idx = 1;
- for (const SmallVector<NamedEntry *, 0> &bucket : bucketList) {
- if (!bucket.empty())
- endian::write32<ELFT::Endianness>(buf + 0, idx);
- idx += bucket.size();
- buf += 4;
- }
-
- // ...Write the hashes
- for (const auto &bucket : bucketList) {
- for (const auto &entry : bucket) {
- uint32_t hashValue = entry->hashValue;
- endian::write32<ELFT::Endianness>(buf + 0, hashValue);
- buf += 4;
- }
- }
-
- // Write the string offsets.
- for (const NamedEntry &entry : mergedEntries) {
- endian::write32<ELFT::Endianness>(buf + 0, entry.relocatedEntryOffset);
- buf += 4;
- }
-
- // Write the entry offsets.
- for (const auto &entry : mergedEntries) {
- endian::write32<ELFT::Endianness>(buf + 0, entry.entryOffset);
- buf += 4;
- }
-
- // Write the abbrev table.
- for (const Abbrev *abbrev : mergedAbbrevTable) {
- buf += encodeULEB128(abbrev->code, buf);
- buf += encodeULEB128(abbrev->tag, buf);
- for (DWARFDebugNames::AttributeEncoding attr : abbrev->attributes) {
- buf += encodeULEB128(attr.Index, buf);
- buf += encodeULEB128(attr.Form, buf);
- }
- endian::write16<ELFT::Endianness>(buf + 0, 0); // attribute sentinels.
- buf += 2;
- }
- *buf++ = 0; // abbrev table sentinel
-
- // Write the entry pool.
- for (const auto &stringEntry : mergedEntries) {
- // Write all the entries for the string.
- for (const std::unique_ptr<IndexEntry> &entry : stringEntry.indexEntries) {
- buf += encodeULEB128(entry->abbrevCode, buf);
- for (const auto &value : entry->attrValues) {
- endian::write32<ELFT::Endianness>(buf + 0, value.attrValue);
- buf += value.attrSize;
- }
- }
- *buf++ = 0; // Entry sentinel
- }
-}
-
-template <class ELFT> bool DebugNamesSection<ELFT>::isNeeded() const {
- return numChunks > 0;
-}
-
-template <class ELFT>
-static void readCompileUnitOffsets(
- typename DebugNamesSection<ELFT>::DebugNamesSectionData &secData,
- typename DebugNamesSection<ELFT>::DebugNamesOutputChunk &outputChunk,
- DWARFDataExtractor &namesExtractor) {
- uint64_t offset = secData.locs.CUsBase;
- uint64_t *offsetPtr = &offset;
- outputChunk.compilationUnits.resize(secData.hdr.CompUnitCount);
- uint32_t *bufferPtr =
- namesExtractor.getU32(offsetPtr, outputChunk.compilationUnits.begin(),
- secData.hdr.CompUnitCount);
- if (!bufferPtr)
- errorOrWarn(toString(outputChunk.sec) +
- Twine(": error while reading CU offsets"));
-}
-
-template <class ELFT>
-static void readEntryOffsets(
- typename DebugNamesSection<ELFT>::DebugNamesSectionData &secData,
- DWARFDataExtractor &namesExtractor) {
- secData.entryOffsets.resize(secData.hdr.NameCount);
- uint64_t offset = secData.locs.EntryOffsetsBase;
- uint64_t *offsetPtr = &offset;
- uint32_t *bufferPtr = namesExtractor.getU32(
- offsetPtr, secData.entryOffsets.begin(), secData.hdr.NameCount);
- if (!bufferPtr)
- errorOrWarn(Twine(": error while reading entry offsets"));
-}
-
-template <class ELFT>
-static void readAttributeValues(
- SmallVector<typename DebugNamesSection<ELFT>::AttrValueData, 3> &values,
- typename DebugNamesSection<ELFT>::DebugNamesInputChunk &chunk,
- uint64_t &offset,
- typename DebugNamesSection<ELFT>::DebugNamesSectionData &secData,
- int32_t &parentOffset, DWARFDataExtractor &namesExtractor,
- const DWARFDebugNames::Abbrev &abbrev) {
- const LLDDWARFSection &namesSection = *chunk.namesSection;
- uint64_t *offsetPtr = &offset;
- typename DebugNamesSection<ELFT>::AttrValueData cuOrTuAttr = {0, 0};
- for (DWARFDebugNames::AttributeEncoding attr : abbrev.Attributes) {
- Error err = Error::success();
- typename DebugNamesSection<ELFT>::AttrValueData newAttr;
- uint32_t value;
- if (attr.Index == DW_IDX_parent && attr.Form != DW_FORM_flag_present &&
- attr.Form != DW_FORM_ref4)
- errorOrWarn(toString(namesSection.sec) +
- Twine(": invalid form for DW_IDX_parent"));
- switch (attr.Form) {
- case DW_FORM_flag_present: {
- // Currently only DW_IDX_parent attributes (in .debug_names) can
- // have this form. This form does not have a real value (nothing is
- // emitted for it).
- if (attr.Index != DW_IDX_parent)
- errorOrWarn(toString(namesSection.sec) +
- Twine(": invalid form for attribute"));
- break;
- }
- case DW_FORM_data1:
- case DW_FORM_ref1: {
- newAttr.attrValue = namesExtractor.getU8(offsetPtr, &err);
- newAttr.attrSize = 1;
- break;
- }
- case DW_FORM_data2:
- case DW_FORM_ref2: {
- value = namesExtractor.getU16(offsetPtr, &err);
- newAttr.attrValue = value;
- newAttr.attrSize = 2;
- break;
- }
- case DW_FORM_data4:
- case DW_FORM_ref4: {
- value = namesExtractor.getU32(offsetPtr, &err);
- newAttr.attrValue = value;
- newAttr.attrSize = 4;
- if (attr.Index == dwarf::DW_IDX_parent)
- parentOffset = value + secData.locs.EntriesBase;
- break;
- }
- case DW_FORM_data8:
- case DW_FORM_ref8:
- case DW_FORM_ref_sig8: {
- value = namesExtractor.getU64(offsetPtr, &err);
- newAttr.attrValue = value;
- newAttr.attrSize = 8;
- break;
+// 4-byte alignment ensures that values in the hash lookup table and the name
+// table are aligned.
+DebugNamesBaseSection::DebugNamesBaseSection()
+ : SyntheticSection(0, SHT_PROGBITS, 4, ".debug_names") {}
+
+// Get the size of the .debug_names section header in bytes for DWARF32:
+static uint32_t getDebugNamesHeaderSize(uint32_t augmentationStringSize) {
+ return /* unit length */ 4 +
+ /* version */ 2 +
+ /* padding */ 2 +
+ /* CU count */ 4 +
+ /* TU count */ 4 +
+ /* Foreign TU count */ 4 +
+ /* Bucket Count */ 4 +
+ /* Name Count */ 4 +
+ /* Abbrev table size */ 4 +
+ /* Augmentation string size */ 4 +
+ /* Augmentation string */ augmentationStringSize;
+}
+
+void DebugNamesBaseSection::parseDebugNames(
+ InputChunk &inputChunk, OutputChunk &chunk,
+ DWARFDataExtractor &namesExtractor, DataExtractor &strExtractor,
+ function_ref<SmallVector<uint32_t, 0>(
+ const DWARFDebugNames::Header &,
+ const DWARFDebugNames::DWARFDebugNamesOffsets &)>
+ readOffsets) {
+ const LLDDWARFSection namesSec = inputChunk.section;
+ DenseMap<uint32_t, IndexEntry *> offsetMap;
+ for (const DWARFDebugNames::NameIndex &ni : *inputChunk.llvmDebugNames) {
+ NameData &nd = inputChunk.nameData.emplace_back();
+ nd.hdr = ni.getHeader();
+ if (nd.hdr.Format != DwarfFormat::DWARF32) {
+ errorOrWarn(toString(namesSec.sec) + Twine(": unsupported DWARF64"));
+ return;
}
- default: {
- errorOrWarn(toString(namesSection.sec) +
- Twine(": unrecognized form encoding ") + Twine(attr.Form) +
- Twine(" in .debug_names abbrev table"));
- break;
+ if (nd.hdr.Version != 5) {
+ errorOrWarn(toString(namesSec.sec) + Twine(": unsupported version ") +
+ Twine(nd.hdr.Version));
+ return;
}
+ const uint32_t dwarfSize =
+ dwarf::getDwarfOffsetByteSize(DwarfFormat::DWARF32);
+ const uint32_t hdrSize =
+ getDebugNamesHeaderSize(nd.hdr.AugmentationStringSize);
+ auto locs = findDebugNamesOffsets(hdrSize, nd.hdr);
+ if (locs.EntriesBase > namesExtractor.getData().size()) {
+ errorOrWarn(toString(namesSec.sec) +
+ Twine(": index entry is out of bounds"));
+ return;
}
- if (err)
- errorOrWarn(toString(namesSection.sec) +
- Twine(": error while reading attributes: ") +
- toString(std::move(err)));
- if (attr.Index == DW_IDX_compile_unit)
- // Save it to put it at the end of the attributes list.
- cuOrTuAttr = newAttr;
- else if (attr.Form != DW_FORM_flag_present)
- values.push_back(newAttr);
- }
- // Make sure the CU or TU index attribute is the last one in the list.
- values.push_back(cuOrTuAttr);
-}
+ SmallVector<uint32_t, 0> entryOffsets = readOffsets(nd.hdr, locs);
+
+ // Read the entry pool.
+ offsetMap.clear();
+ nd.nameEntries.resize(nd.hdr.NameCount);
+ for (auto i : seq(nd.hdr.NameCount)) {
+ NameEntry &ne = nd.nameEntries[i];
+ uint64_t strOffset = locs.StringOffsetsBase + i * dwarfSize;
+ ne.stringOffset = strOffset;
+ uint64_t strp = namesExtractor.getRelocatedValue(dwarfSize, &strOffset);
+ StringRef name = strExtractor.getCStrRef(&strp);
+ ne.name = name.data();
+ ne.hashValue = caseFoldingDjbHash(name);
+
+ // Read a series of index entries that end with abbreviation code 0.
+ const char *errMsg = nullptr;
+ uint64_t offset = locs.EntriesBase + entryOffsets[i];
+ while (offset < namesSec.Data.size() && namesSec.Data[offset] != 0) {
+ auto ie = makeThreadLocal<IndexEntry>();
+ ie->poolOffset = offset;
+ Error err = Error::success();
+ ie->abbrevCode =
+ static_cast<uint32_t>(namesExtractor.getULEB128(&offset, &err));
+ if (err) {
+ consumeError(std::move(err));
+ errMsg = ": invalid abbrev code in entry";
+ break;
+ }
+ auto it = ni.getAbbrevs().find_as(ie->abbrevCode);
+ if (it == ni.getAbbrevs().end()) {
+ errMsg = ": invalid abbrev code in entry";
+ break;
+ }
-template <class ELFT>
-static void
-readEntry(typename DebugNamesSection<ELFT>::NamedEntry &stringEntry,
- typename DebugNamesSection<ELFT>::DebugNamesInputChunk &chunk,
- typename DebugNamesSection<ELFT>::DebugNamesSectionData &secData,
- DWARFDataExtractor &namesExtractor,
- const DWARFDebugNames::NameIndex &ni) {
- std::unique_ptr<LLDDWARFSection> &namesSection = chunk.namesSection;
- uint64_t offset = stringEntry.entryOffset;
- // Each entry ends with a zero 'sentinel' value
- while (offset < namesSection->Data.size() &&
- namesSection->Data[offset] != 0) {
- // Read & store all entries (for the same string)
- auto entry =
- std::make_unique<typename DebugNamesSection<ELFT>::IndexEntry>();
- entry->poolOffset = offset;
- Error err = Error::success();
- // This call to namesExtractor can't fail; if there were a problem with the
- // input, it would have been caught in the call to NamesIndex::extract, in
- // DebugNamesSection::create.
- uint64_t ulebValue = namesExtractor.getULEB128(&offset, &err);
- cantFail(std::move(err));
- entry->abbrevCode = static_cast<uint32_t>(ulebValue);
- const auto &abbrevs = ni.getAbbrevs();
- auto abbrevIt = abbrevs.find_as(entry->abbrevCode);
- if (abbrevIt != abbrevs.end()) {
- const DWARFDebugNames::Abbrev &abbrev = *abbrevIt;
- readAttributeValues<ELFT>(entry->attrValues, chunk, offset, secData,
- entry->parentOffset, namesExtractor, abbrev);
- stringEntry.indexEntries.push_back(std::move(entry));
- } else
- errorOrWarn(toString(chunk.namesSection->sec) +
- Twine(": invalid abbrev code in entry"));
- }
- if (offset >= namesSection->Data.size())
- errorOrWarn(
- toString(chunk.namesSection->sec) +
- Twine(": encountered unexpected end of section while reading entry"));
-}
+ AttrValue attr, cuAttr = {0, 0};
+ for (DWARFDebugNames::AttributeEncoding a : it->Attributes) {
+ if (a.Index == dwarf::DW_IDX_parent) {
+ if (a.Form == dwarf::DW_FORM_ref4) {
+ attr.attrValue = namesExtractor.getU32(&offset, &err);
+ attr.attrSize = 4;
+ ie->parentOffset = locs.EntriesBase + attr.attrValue;
+ } else if (a.Form != DW_FORM_flag_present) {
+ errMsg = ": invalid form for DW_IDX_parent";
+ }
+ } else {
+ switch (a.Form) {
+ case DW_FORM_data1:
+ case DW_FORM_ref1: {
+ attr.attrValue = namesExtractor.getU8(&offset, &err);
+ attr.attrSize = 1;
+ break;
+ }
+ case DW_FORM_data2:
+ case DW_FORM_ref2: {
+ attr.attrValue = namesExtractor.getU16(&offset, &err);
+ attr.attrSize = 2;
+ break;
+ }
+ case DW_FORM_data4:
+ case DW_FORM_ref4: {
+ attr.attrValue = namesExtractor.getU32(&offset, &err);
+ attr.attrSize = 4;
+ break;
+ }
+ default:
+ errorOrWarn(toString(namesSec.sec) +
+ Twine(": unrecognized form encoding ") +
+ Twine(a.Form) + Twine(" in abbrev table"));
+ return;
+ }
+ }
+ if (err) {
+ errorOrWarn(toString(namesSec.sec) +
+ Twine(": error while reading attributes: ") +
+ toString(std::move(err)));
+ return;
+ }
+ if (a.Index == DW_IDX_compile_unit)
+ cuAttr = attr;
+ else if (a.Form != DW_FORM_flag_present)
+ ie->attrValues.push_back(attr);
+ }
-template <class ELFT>
-static void
-readEntries(typename DebugNamesSection<ELFT>::DebugNamesSectionData &secData,
- typename DebugNamesSection<ELFT>::DebugNamesInputChunk &chunk,
- DWARFDataExtractor &namesExtractor, DataExtractor &strExtractor,
- const DWARFDebugNames::NameIndex &ni) {
- // Temporary map from entry offsets to address (pointer) of entry with that
- // offset; used to find parent entries quickly.
- DenseMap<uint32_t, typename DebugNamesSection<ELFT>::IndexEntry *> offsetMap;
- // Reserve sizes for this chunk's hashes & namedEntries.
- chunk.hashValues.reserve(secData.hdr.NameCount);
- secData.namedEntries.reserve(secData.hdr.NameCount);
- // Calculate the Entry Offsets, create initial records.
- for (uint32_t i = 0, e = secData.hdr.NameCount; i != e; ++i) {
- // Get string value
- typename DebugNamesSection<ELFT>::NamedEntry stringEntry;
- stringEntry.entryOffset =
- secData.locs.EntriesBase + secData.entryOffsets[i];
- uint64_t strOffsetOffset =
- secData.locs.StringOffsetsBase + i * secData.dwarfSize;
- stringEntry.stringOffsetOffset = strOffsetOffset;
- uint64_t strOffset =
- namesExtractor.getRelocatedValue(secData.dwarfSize, &strOffsetOffset);
- StringRef name = strExtractor.getCStrRef(&strOffset);
- stringEntry.name = name.data();
- // Calculate hash
- stringEntry.hashValue = caseFoldingDjbHash(name);
- chunk.hashValues.push_back(stringEntry.hashValue);
- // Read String Entry
- readEntry<ELFT>(stringEntry, chunk, secData, namesExtractor, ni);
- // Add index entries & offsets to our temporary map
- for (const auto &entry : stringEntry.indexEntries)
- offsetMap[entry->poolOffset] = entry.get();
- secData.namedEntries.push_back(std::move(stringEntry));
- }
- // Find/assign pointers to any 'real' parent entries (needed to find correct
- // parent entry offsets in merged data).
- for (auto &stringEntry : secData.namedEntries)
- for (auto &entry : stringEntry.indexEntries)
- if (entry->parentOffset != -1)
- entry->parentEntry = offsetMap[entry->parentOffset];
-}
-
-static uint16_t computeDebugNamesHeaderSize() {
- // Size of the .debug_names section header, in bytes, for DWARF32:
- uint16_t size = /* unit length */ 4 +
- /* version */ 2 +
- /* padding */ 2 +
- /* CU count */ 4 +
- /* TU count */ 4 +
- /* Foreign TU count */ 4 +
- /* Bucket Count */ 4 +
- /* Name Count */ 4 +
- /* Abbrev table size */ 4 +
- /* Augmentation string size */ 4 +
- /* augmentation string */ 8;
- return size;
-}
+ // Canonicalize abbrev by placing the CU/TU index at the end.
+ ie->attrValues.push_back(cuAttr);
+ ne.indexEntries.push_back(std::move(ie));
+ }
+ if (offset >= namesSec.Data.size())
+ errMsg = ": index entry is out of bounds";
+ if (errMsg)
+ errorOrWarn(toString(namesSec.sec) + Twine(errMsg));
-template <class ELFT>
-static void collectDebugNamesSectionData(
- typename DebugNamesSection<ELFT>::DebugNamesInputChunk &chunk,
- typename DebugNamesSection<ELFT>::DebugNamesOutputChunk &outputChunk,
- DWARFDataExtractor &namesExtractor, DataExtractor &strExtractor) {
- for (const DWARFDebugNames::NameIndex &ni : *chunk.debugNamesData) {
- typename DebugNamesSection<ELFT>::DebugNamesSectionData &secData =
- chunk.sectionsData.emplace_back();
- secData.hdr = ni.getHeader();
- if (secData.hdr.Format != DwarfFormat::DWARF32) {
- errorOrWarn(toString(chunk.namesSection->sec) +
- Twine(": unsupported DWARF64"));
- // Don't try to continue; we can't parse DWARF64 at the moment.
- return;
+ for (IndexEntry &ie : ne.entries())
+ offsetMap[ie.poolOffset] = &ie;
}
- secData.dwarfSize = dwarf::getDwarfOffsetByteSize(DwarfFormat::DWARF32);
- secData.hdrSize = computeDebugNamesHeaderSize();
- if (secData.hdr.Version != 5)
- errorOrWarn(toString(chunk.namesSection->sec) +
- Twine(": unsupported version"));
- secData.locs = findDebugNamesOffsets(secData.hdrSize, secData.hdr);
- readCompileUnitOffsets<ELFT>(secData, outputChunk, namesExtractor);
- readEntryOffsets<ELFT>(secData, namesExtractor);
- readEntries<ELFT>(secData, chunk, namesExtractor, strExtractor, ni);
- }
-}
-template <class ELFT>
-void DebugNamesSection<ELFT>::collectMergedCounts(
- MutableArrayRef<DebugNamesInputChunk> &inputChunks) {
- SmallVector<uint32_t, 0> tmpMergedCuOffsets;
- mergedHdr.CompUnitCount = 0;
- mergedHdr.LocalTypeUnitCount = 0;
- mergedHdr.ForeignTypeUnitCount = 0;
- mergedHdr.Version = 5;
- mergedHdr.Format = DwarfFormat::DWARF32;
- mergedHdr.AugmentationStringSize = 0;
-
- for (size_t i = 0, e = numChunks; i != e; ++i) {
- DebugNamesInputChunk &inputChunk = inputChunks[i];
- DebugNamesOutputChunk &outputChunk = outputChunks[i];
- inputChunk.baseCuOffsetIdx = tmpMergedCuOffsets.size();
- for (uint32_t cuOffset : outputChunk.compilationUnits)
- tmpMergedCuOffsets.push_back(outputChunk.sec->outSecOff + cuOffset);
- for (const DebugNamesSectionData &data : inputChunk.sectionsData) {
- mergedHdr.CompUnitCount += data.hdr.CompUnitCount;
- mergedHdr.LocalTypeUnitCount += data.hdr.LocalTypeUnitCount;
- mergedHdr.ForeignTypeUnitCount += data.hdr.ForeignTypeUnitCount;
- // Set & check the Augmentation String.
- if (mergedHdr.AugmentationStringSize == 0) {
- mergedHdr.AugmentationStringSize = data.hdr.AugmentationStringSize;
- mergedHdr.AugmentationString = data.hdr.AugmentationString;
- } else if ((mergedHdr.AugmentationStringSize !=
- data.hdr.AugmentationStringSize) ||
- (mergedHdr.AugmentationString !=
- data.hdr.AugmentationString)) {
- // There are conflicting augmentation strings, so it's best for the
- // merged index to not use an augmentation string.
- mergedHdr.AugmentationString = " ";
- mergedHdr.AugmentationStringSize = mergedHdr.AugmentationString.size();
+ // Assign parent pointers, which will be used to update DW_IDX_parent index
+ // attributes. Note: offsetMap[0] does not exist, so parentOffset == 0 will
+ // get parentEntry == null as well.
+ for (NameEntry &ne : nd.nameEntries)
+ for (IndexEntry &ie : ne.entries())
+ ie.parentEntry = offsetMap.lookup(ie.parentOffset);
+ }
+}
+
+// Compute the form for output DW_IDX_compile_unit attributes similar to
+// DIEInteger::BestForm. The input forms (often DW_FORM_data1) may not hold all
+// CU indices.
+std::pair<uint8_t, dwarf::Form> static getMergedCuCountForm(
+ uint32_t compUnitCount) {
+ if (compUnitCount > UINT16_MAX)
+ return {4, DW_FORM_data4};
+ if (compUnitCount > UINT8_MAX)
+ return {2, DW_FORM_data2};
+ return {1, DW_FORM_data1};
+}
+
+void DebugNamesBaseSection::computeHdrAndAbbrevTable(
+ MutableArrayRef<InputChunk> inputChunks) {
+ TimeTraceScope timeScope("Merge .debug_names", "hdr and abbrev table");
+ size_t numCu = 0;
+ hdr.Format = DwarfFormat::DWARF32;
+ hdr.Version = 5;
+ hdr.CompUnitCount = 0;
+ hdr.LocalTypeUnitCount = 0;
+ hdr.ForeignTypeUnitCount = 0;
+ hdr.AugmentationStringSize = 0;
+
+ // Compute CU and TU counts.
+ for (auto i : seq(numChunks)) {
+ InputChunk &inputChunk = inputChunks[i];
+ inputChunk.baseCuIdx = numCu;
+ numCu += chunks[i].compUnits.size();
+ for (const NameData &nd : inputChunk.nameData) {
+ hdr.CompUnitCount += nd.hdr.CompUnitCount;
+ hdr.LocalTypeUnitCount += nd.hdr.LocalTypeUnitCount;
+ hdr.ForeignTypeUnitCount += nd.hdr.ForeignTypeUnitCount;
+ // If augmentation strings are not identical, use an empty string.
+ if (i == 0) {
+ hdr.AugmentationStringSize = nd.hdr.AugmentationStringSize;
+ hdr.AugmentationString = nd.hdr.AugmentationString;
+ } else if (hdr.AugmentationString != nd.hdr.AugmentationString) {
+ hdr.AugmentationStringSize = 0;
+ hdr.AugmentationString.clear();
}
}
}
-}
-
-template <class ELFT>
-void DebugNamesSection<ELFT>::Abbrev::Profile(FoldingSetNodeID &id) const {
- id.AddInteger(tag);
- for (const DWARFDebugNames::AttributeEncoding &attr : attributes) {
- id.AddInteger(attr.Index);
- id.AddInteger(attr.Form);
- }
-}
-
-template <class ELFT>
-std::pair<uint8_t, dwarf::Form> DebugNamesSection<ELFT>::getMergedCuSizeData() {
- // Once we've merged all the CU offsets into a single list, the original
- // DWARF form/size (often 1 byte) may be too small to hold indices to all
- // the offsets. Here we calculate what the right form/size needs to be for
- // the merged index.
- uint8_t size;
- dwarf::Form form;
- // TODO: Investigate possibly using DIEInteger::BestForm here
- if (mergedHdr.CompUnitCount > UINT32_MAX) {
- form = DW_FORM_data8;
- size = 8;
- } else if (mergedHdr.CompUnitCount > UINT16_MAX) {
- form = DW_FORM_data4;
- size = 4;
- } else if (mergedHdr.CompUnitCount > UINT8_MAX) {
- form = DW_FORM_data2;
- size = 2;
- } else {
- form = DW_FORM_data1;
- size = 1;
- }
-
- return {size, form};
-}
-template <class ELFT>
-void DebugNamesSection<ELFT>::getMergedAbbrevTable(
- MutableArrayRef<DebugNamesInputChunk> &inputChunks) {
- MapVector<uint64_t, Abbrev> abbrevMap;
- FoldingSet<Abbrev> AbbreviationsSet;
-
- // Need to determine what size form is needed for the DW_IDX_compile_unit
- // attributes in the merged index. Will need to update the abbrevs to use
- // the right form.
- dwarf::Form compileUnitAttrForm = getMergedCuSizeData().second;
-
- for (DebugNamesInputChunk &chunk : inputChunks) {
- for (const DWARFDebugNames::NameIndex &ni : *chunk.debugNamesData) {
- const auto &abbrevs = ni.getAbbrevs();
- for (const DWARFDebugNames::Abbrev &abbrev : abbrevs) {
- // Create canonicalized abbrev.
- Abbrev newAbbrev;
- DWARFDebugNames::AttributeEncoding cuOrTuAttr(DW_IDX_compile_unit,
- compileUnitAttrForm);
- newAbbrev.code = abbrev.Code;
- newAbbrev.tag = abbrev.Tag;
- for (const DWARFDebugNames::AttributeEncoding attr :
- abbrev.Attributes) {
- DWARFDebugNames::AttributeEncoding newAttr(attr.Index, attr.Form);
- if (attr.Index == DW_IDX_compile_unit)
- // Save it, to put it at the end.
- cuOrTuAttr.Index = newAttr.Index;
+ // Uniquify input abbrev tables and compute mapping from old abbrev code to
+ // new abbrev code.
+ FoldingSet<Abbrev> abbrevSet;
+ // Determine the form for the DW_IDX_compile_unit attributes in the merged
+ // index. The input form may not encode all possible CU indices.
+ const dwarf::Form cuAttrForm = getMergedCuCountForm(hdr.CompUnitCount).second;
+ for (InputChunk &inputChunk : inputChunks) {
+ for (auto [i, ni] : enumerate(*inputChunk.llvmDebugNames)) {
+ for (const DWARFDebugNames::Abbrev &oldAbbrev : ni.getAbbrevs()) {
+ // Canonicalize abbrev by placing the CU/TU index at the end,
+ // similar to `DebugNamesBaseSection::parse`.
+ Abbrev abbrev;
+ DWARFDebugNames::AttributeEncoding cuAttr(DW_IDX_compile_unit,
+ cuAttrForm);
+ abbrev.code = oldAbbrev.Code;
+ abbrev.tag = oldAbbrev.Tag;
+ for (DWARFDebugNames::AttributeEncoding a : oldAbbrev.Attributes) {
+ if (a.Index == DW_IDX_compile_unit)
+ cuAttr.Index = a.Index;
else
- newAbbrev.attributes.push_back(newAttr);
+ abbrev.attributes.push_back({a.Index, a.Form});
}
- // Put the CU/TU index at the end of the attributes list.
- newAbbrev.attributes.push_back(cuOrTuAttr);
+ abbrev.attributes.push_back(cuAttr);
- // Next, check our abbreviations set to see if we've already seen the
- // identical abbreviation.
- uint32_t oldCode = newAbbrev.code;
- uint32_t newCode;
+ // Profile the abbrev, get or assign a new code, then record the abbrev
+ // code mapping.
FoldingSetNodeID id;
- newAbbrev.Profile(id);
+ abbrev.Profile(id);
+ uint32_t newCode;
void *insertPos;
- if (Abbrev *Existing =
- AbbreviationsSet.FindNodeOrInsertPos(id, insertPos)) {
- // Found it; we've already seen an identical abbreviation.
- newCode = Existing->code;
+ if (Abbrev *existing = abbrevSet.FindNodeOrInsertPos(id, insertPos)) {
+ newCode = existing->code;
} else {
- // Didn't find it.
- Abbrev *newAbbrev2 =
- new (abbrevAlloc.Allocate()) Abbrev(std::move(newAbbrev));
- AbbreviationsSet.InsertNode(newAbbrev2, insertPos);
- newCode = mergedAbbrevTable.size() + 1;
- newAbbrev2->code = newCode;
- mergedAbbrevTable.push_back(newAbbrev2);
+ Abbrev *abbrev2 =
+ new (abbrevAlloc.Allocate()) Abbrev(std::move(abbrev));
+ abbrevSet.InsertNode(abbrev2, insertPos);
+ abbrevTable.push_back(abbrev2);
+ newCode = abbrevTable.size();
+ abbrev2->code = newCode;
}
- chunk.abbrevCodeMap[oldCode] = newCode;
+ inputChunk.nameData[i].abbrevCodeMap[oldAbbrev.Code] = newCode;
}
}
}
- // Calculate the merged abbrev table size.
- mergedHdr.AbbrevTableSize = 0;
- for (Abbrev *a : mergedAbbrevTable) {
- mergedHdr.AbbrevTableSize += getULEB128Size(a->code);
- mergedHdr.AbbrevTableSize += getULEB128Size(a->tag);
- for (const DWARFDebugNames::AttributeEncoding &attr : a->attributes) {
- mergedHdr.AbbrevTableSize += getULEB128Size(attr.Index);
- mergedHdr.AbbrevTableSize += getULEB128Size(attr.Form);
+ // Compute the merged abbrev table.
+ raw_svector_ostream os(abbrevTableBuf);
+ for (Abbrev *abbrev : abbrevTable) {
+ encodeULEB128(abbrev->code, os);
+ encodeULEB128(abbrev->tag, os);
+ for (DWARFDebugNames::AttributeEncoding a : abbrev->attributes) {
+ encodeULEB128(a.Index, os);
+ encodeULEB128(a.Form, os);
}
- mergedHdr.AbbrevTableSize += 2; // attribute index & form sentinels
+ os.write("\0", 2); // attribute specification end
}
- ++mergedHdr.AbbrevTableSize; // abbrev table sentinel
+ os.write(0); // abbrev table end
+ hdr.AbbrevTableSize = abbrevTableBuf.size();
}
-template <class ELFT>
-void DebugNamesSection<ELFT>::getMergedSymbols(
- MutableArrayRef<DebugNamesInputChunk> &inputChunks) {
- // The number of symbols (& abbrevs) we will handle is very large; will use
- // multi-threading to speed it up.
- constexpr size_t numShards = 32;
+void DebugNamesBaseSection::Abbrev::Profile(FoldingSetNodeID &id) const {
+ id.AddInteger(tag);
+ for (const DWARFDebugNames::AttributeEncoding &attr : attributes) {
+ id.AddInteger(attr.Index);
+ id.AddInteger(attr.Form);
+ }
+}
+
+std::pair<uint32_t, uint32_t> DebugNamesBaseSection::computeEntryPool(
+ MutableArrayRef<InputChunk> inputChunks) {
+ TimeTraceScope timeScope("Merge .debug_names", "entry pool");
+ // Collect the compilation units for each unique name. Speed it up using
+ // multi-threading as the number of symbols can be in the order of millions.
const size_t concurrency =
bit_floor(std::min<size_t>(config->threadCount, numShards));
const size_t shift = 32 - countr_zero(numShards);
-
- struct ShardData {
- // Map to uniquify symbols by name
- MapVector<CachedHashStringRef, NamedEntry> nameMap;
- };
-
- // Need to determine what size is needed for the DW_IDX_compile_unit
- // attributes in the merged index. Will need to update the indexEntries
- // to use the right size.
- uint8_t compileUnitAttrSize = getMergedCuSizeData().first;
-
- auto shardsPtr = std::make_unique<ShardData[]>(numShards);
- MutableArrayRef<ShardData> shards(shardsPtr.get(), numShards);
-
+ const uint8_t cuAttrSize = getMergedCuCountForm(hdr.CompUnitCount).first;
+ DenseMap<CachedHashStringRef, size_t> maps[numShards];
parallelFor(0, concurrency, [&](size_t threadId) {
- for (size_t i = 0, e = numChunks; i != e; ++i) {
- DebugNamesInputChunk &chunk = inputChunks[i];
- for (DebugNamesSectionData &secData : chunk.sectionsData) {
- // Deduplicate the NamedEntry records (based on the string/name),
- // using a map from string/name to NamedEntry records.
- // Note there is a twist: If there is already a record for the current
- // 'string' in the nameMap, we append all the indexEntries from the
- // current record to the record that's in the nameMap. I.e. we
- // deduplicate the *strings* but we keep all the IndexEntry records
- // (moving them to the appropriate 'kept' NamedEntry record).
- for (NamedEntry &stringEntry : secData.namedEntries) {
- size_t shardId = stringEntry.hashValue >> shift;
+ for (auto i : seq(numChunks)) {
+ InputChunk &inputChunk = inputChunks[i];
+ for (NameData &nd : inputChunk.nameData) {
+ for (NameEntry &ne : nd.nameEntries) {
+ auto shardId = ne.hashValue >> shift;
if ((shardId & (concurrency - 1)) != threadId)
continue;
- auto &shard = shards[shardId];
- stringEntry.chunkIdx = i;
- for (std::unique_ptr<IndexEntry> &entry : stringEntry.indexEntries) {
- // The DW_IDX_compile_unit is always the last attribute (we set it
- // up that way when we read/created the attributes). We need to
- // update the index value to use the correct merged offset, and we
- // need to fix the size of the index attribute.
- uint8_t endPos = entry->attrValues.size() - 1;
- entry->attrValues[endPos].attrValue += chunk.baseCuOffsetIdx;
- entry->attrValues[endPos].attrSize = compileUnitAttrSize;
- // Update the entry's abbrev code to match the merged
- // abbreviations.
- entry->abbrevCode = chunk.abbrevCodeMap[entry->abbrevCode];
+ ne.chunkIdx = i;
+ for (IndexEntry &ie : ne.entries()) {
+ ie.abbrevCode = nd.abbrevCodeMap[ie.abbrevCode];
+ // Update the DW_IDX_compile_unit attribute (the last one after
+ // canonicalization).
+ auto &back = ie.attrValues.back();
+ back.attrValue += inputChunk.baseCuIdx;
+ back.attrSize = cuAttrSize;
}
- CachedHashStringRef cachedHashName(stringEntry.name);
- auto [it, inserted] =
- shard.nameMap.try_emplace(cachedHashName, std::move(stringEntry));
- if (!inserted) {
- // Found the string already; don't add to map, but append
- // entry/entries for it to existing map entry.
- NamedEntry &found = it->second;
- // Append the entries...
- for (auto &entry : stringEntry.indexEntries)
- found.indexEntries.push_back(std::move(entry));
- }
+ auto &nameVec = nameVecs[shardId];
+ auto [it, inserted] = maps[shardId].try_emplace(
+ CachedHashStringRef(ne.name, ne.hashValue), nameVec.size());
+ if (inserted)
+ nameVec.push_back(std::move(ne));
+ else
+ nameVec[it->second].indexEntries.append(ne.indexEntries);
}
}
}
});
- // Combined the shared symbols into mergedEntries
- for (ShardData &shard : shards)
- for (auto &mapEntry : shard.nameMap)
- mergedEntries.push_back(std::move(mapEntry.second));
- mergedHdr.NameCount = mergedEntries.size();
-}
-
-template <class ELFT>
-void DebugNamesSection<ELFT>::computeUniqueHashes(
- MutableArrayRef<DebugNamesInputChunk> &chunks) {
- SmallVector<uint32_t, 0> uniques;
- for (const auto &chunk : chunks)
- uniques.append(chunk.hashValues);
- llvm::sort(uniques);
- mergedHdr.BucketCount = dwarf::getDebugNamesBucketCount(llvm::unique(uniques) - uniques.begin());
-}
-
-template <class ELFT> void DebugNamesSection<ELFT>::generateBuckets() {
- bucketList.resize(mergedHdr.BucketCount);
- for (NamedEntry &entry : mergedEntries) {
- uint32_t bucketIdx = entry.hashValue % mergedHdr.BucketCount;
- bucketList[bucketIdx].push_back(&entry);
- }
-
- // Sort the contents of the buckets by hash value so that the hash collisions
- // end up together.
- for (SmallVector<NamedEntry *, 0> &bucket : bucketList)
- stable_sort(bucket, [](NamedEntry *lhs, NamedEntry *rhs) {
- return lhs->hashValue < rhs->hashValue;
- });
-}
-
-template <class ELFT>
-void DebugNamesSection<ELFT>::calculateEntriesSizeAndOffsets() {
- uint32_t offset = 0;
- for (NamedEntry &stringEntry : mergedEntries) {
- stringEntry.entryOffset = offset;
- for (std::unique_ptr<IndexEntry> &entry : stringEntry.indexEntries) {
- uint32_t entrySize = 0;
- entry->poolOffset = offset;
- entrySize += getULEB128Size(entry->abbrevCode);
- for (const auto &attr : entry->attrValues)
- entrySize += attr.attrSize;
- offset += entrySize;
+ // Compute entry offsets parallelly. First, compute offsets relative to the
+ // current shard.
+ uint32_t offsets[numShards];
+ parallelFor(0, numShards, [&](size_t shard) {
+ uint32_t offset = 0;
+ for (NameEntry &ne : nameVecs[shard]) {
+ ne.entryOffset = offset;
+ for (IndexEntry &ie : ne.entries()) {
+ ie.poolOffset = offset;
+ offset += getULEB128Size(ie.abbrevCode);
+ for (AttrValue value : ie.attrValues)
+ offset += value.attrSize;
+ }
+ ++offset; // index entry sentinel
}
- // Add in sentinel size
- ++offset;
- }
- mergedTotalEntriesSize = offset;
-}
-
-template <class ELFT> void DebugNamesSection<ELFT>::updateParentIndexEntries() {
- for (NamedEntry &stringEntry : mergedEntries) {
- for (std::unique_ptr<IndexEntry> &childEntry : stringEntry.indexEntries) {
- if (!childEntry->parentEntry)
- continue;
+ offsets[shard] = offset;
+ });
+ // Then add shard offsets.
+ std::partial_sum(offsets, std::end(offsets), offsets);
+ parallelFor(1, numShards, [&](size_t shard) {
+ uint32_t offset = offsets[shard - 1];
+ for (NameEntry &ne : nameVecs[shard]) {
+ ne.entryOffset += offset;
+ for (IndexEntry &ie : ne.entries())
+ ie.poolOffset += offset;
+ }
+ });
- // Abbrevs are indexed starting at 1; vector starts at 0. (abbrevCode
- // corresponds to position in the merged table vector).
- const Abbrev *abbrev = mergedAbbrevTable[childEntry->abbrevCode - 1];
-
- // Found the abbrev. Find the index for the DW_IDX_parent attribute
- // (in the abbrev) and update that value in the entry with the
- // correct parent offset (in the merged entry pool).
- for (size_t idx = 0, size = abbrev->attributes.size(); idx != size;
- ++idx) {
- DWARFDebugNames::AttributeEncoding attr = abbrev->attributes[idx];
- if (attr.Index == DW_IDX_parent && attr.Form == DW_FORM_ref4)
- childEntry->attrValues[idx].attrValue =
- childEntry->parentEntry->poolOffset;
+ // Update DW_IDX_parent attributes that use DW_FORM_ref4.
+ parallelFor(0, numShards, [&](size_t shard) {
+ for (NameEntry &ne : nameVecs[shard]) {
+ for (IndexEntry &ie : ne.entries()) {
+ if (!ie.parentEntry)
+ continue;
+ const Abbrev *abbrev = abbrevTable[ie.abbrevCode - 1];
+ for (auto i : seq(abbrev->attributes.size())) {
+ DWARFDebugNames::AttributeEncoding a = abbrev->attributes[i];
+ if (a.Index == DW_IDX_parent && a.Form == DW_FORM_ref4)
+ ie.attrValues[i].attrValue = ie.parentEntry->poolOffset;
+ }
}
}
- }
-}
+ });
-template <class ELFT>
-uint64_t DebugNamesSection<ELFT>::calculateMergedSectionSize() {
- uint32_t hdrSize = computeDebugNamesHeaderSize();
- mergedOffsets = findDebugNamesOffsets(hdrSize, mergedHdr);
- // Add in the size for all the Entries, and make it 4-byte aligned.
- mergedHdr.UnitLength =
- alignTo(mergedOffsets.EntriesBase + mergedTotalEntriesSize, 4);
- // Add in the first 4 bytes, whichs print out the length of the section.
- return mergedHdr.UnitLength + 4;
+ // Return (entry pool size, number of entries).
+ uint32_t num = 0;
+ for (auto &map : maps)
+ num += map.size();
+ return {offsets[numShards - 1], num};
}
-template <class ELFT>
-DebugNamesSection<ELFT> *DebugNamesSection<ELFT>::create() {
- TimeTraceScope timeScope("Create merged .debug_names");
+void DebugNamesBaseSection::init(
+ function_ref<void(InputFile *, InputChunk &, OutputChunk &)> parseFile) {
+ TimeTraceScope timeScope("Merge .debug_names");
+ // Collect and remove input .debug_names sections. Save InputSection pointers
+ // to relocate string offsets in `writeTo`.
SetVector<InputFile *> files;
- SmallVector<InputSectionBase *, 0> sections;
for (InputSectionBase *s : ctx.inputSections) {
InputSection *isec = dyn_cast<InputSection>(s);
if (!isec)
continue;
- // Mark original sections as dead, but save links to them for calculating
- // relocations later.
- if (s->name == ".debug_names") {
+ if (!(s->flags & SHF_ALLOC) && s->name == ".debug_names") {
s->markDead();
- sections.push_back(s);
+ inputSections.push_back(isec);
files.insert(isec->file);
}
}
- auto inputChunksPtr = std::make_unique<DebugNamesInputChunk[]>(files.size());
- MutableArrayRef<DebugNamesInputChunk> inputChunks(inputChunksPtr.get(),
- files.size());
- auto outputChunks = std::make_unique<DebugNamesOutputChunk[]>(files.size());
- parallelFor(0, files.size(), [&](size_t i) {
- auto *file = cast<ObjFile<ELFT>>(files[i]);
- auto dwarfCtx = std::make_unique<DWARFContext>(
- std::make_unique<LLDDwarfObj<ELFT>>(file));
- auto &dobj =
- static_cast<const LLDDwarfObj<ELFT> &>(dwarfCtx->getDWARFObj());
-
- // Extract DWARFDebugNames data from the .debug_names section. The
- // .debug_names section needs the .debug_str section, to get the actual
- // symbol names.
- const StringRef strSection = dobj.getStrSection();
- const LLDDWARFSection &namesSection = dobj.getNamesSection();
- DWARFDataExtractor namesExtractor(dobj, namesSection, config->isLE,
- config->wordsize);
- DataExtractor strExtractor(strSection, config->isLE, config->wordsize);
- inputChunks[i].debugNamesData =
- std::make_unique<DWARFDebugNames>(namesExtractor, strExtractor);
- inputChunks[i].namesSection =
- std::make_unique<LLDDWARFSection>(namesSection);
- if (Error E = inputChunks[i].debugNamesData->extract()) {
+
+ // Parse input .debug_names sections and extract InputChunk and OutputChunk
+ // data. OutputChunk contains CU information, which will be needed by
+ // `writeTo`.
+ auto inputChunksPtr = std::make_unique<InputChunk[]>(files.size());
+ MutableArrayRef<InputChunk> inputChunks(inputChunksPtr.get(), files.size());
+ numChunks = files.size();
+ chunks = std::make_unique<OutputChunk[]>(files.size());
+ {
+ TimeTraceScope timeScope("Merge .debug_names", "parse");
+ parallelFor(0, files.size(), [&](size_t i) {
+ parseFile(files[i], inputChunks[i], chunks[i]);
+ });
+ }
+
+ // Compute section header (except unit_length), abbrev table, and entry pool.
+ computeHdrAndAbbrevTable(inputChunks);
+ uint32_t entryPoolSize;
+ std::tie(entryPoolSize, hdr.NameCount) = computeEntryPool(inputChunks);
+ hdr.BucketCount = dwarf::getDebugNamesBucketCount(hdr.NameCount);
+
+ // Compute the section size. Subtract 4 to get the unit_length for DWARF32.
+ uint32_t hdrSize = getDebugNamesHeaderSize(hdr.AugmentationStringSize);
+ size = findDebugNamesOffsets(hdrSize, hdr).EntriesBase + entryPoolSize;
+ hdr.UnitLength = size - 4;
+}
+
+template <class ELFT> DebugNamesSection<ELFT>::DebugNamesSection() {
+ init([](InputFile *f, InputChunk &inputChunk, OutputChunk &chunk) {
+ auto *file = cast<ObjFile<ELFT>>(f);
+ DWARFContext dwarf(std::make_unique<LLDDwarfObj<ELFT>>(file));
+ auto &dobj = static_cast<const LLDDwarfObj<ELFT> &>(dwarf.getDWARFObj());
+ chunk.infoSec = dobj.getInfoSection();
+ DWARFDataExtractor namesExtractor(dobj, dobj.getNamesSection(),
+ ELFT::Endianness == endianness::little,
+ ELFT::Is64Bits ? 8 : 4);
+ // .debug_str is needed to get symbol names from string offsets.
+ DataExtractor strExtractor(dobj.getStrSection(),
+ ELFT::Endianness == endianness::little,
+ ELFT::Is64Bits ? 8 : 4);
+ inputChunk.section = dobj.getNamesSection();
+
+ inputChunk.llvmDebugNames.emplace(namesExtractor, strExtractor);
+ if (Error e = inputChunk.llvmDebugNames->extract()) {
errorOrWarn(toString(dobj.getNamesSection().sec) + Twine(": ") +
- toString(std::move(E)));
+ toString(std::move(e)));
}
- outputChunks[i].sec = dobj.getInfoSection();
- collectDebugNamesSectionData<ELFT>(inputChunks[i], outputChunks[i],
- namesExtractor, strExtractor);
+ parseDebugNames(
+ inputChunk, chunk, namesExtractor, strExtractor,
+ [&chunk, namesData = dobj.getNamesSection().Data.data()](
+ const DWARFDebugNames::Header &hdr,
+ const DWARFDebugNames::DWARFDebugNamesOffsets &locs) {
+ // Read CU offsets.
+ const char *p = namesData + locs.CUsBase;
+ chunk.compUnits.resize_for_overwrite(hdr.CompUnitCount);
+ for (auto i : seq(hdr.CompUnitCount))
+ chunk.compUnits[i] =
+ endian::readNext<uint32_t, ELFT::Endianness, unaligned>(p);
+
+ // Read entry offsets.
+ p = namesData + locs.EntryOffsetsBase;
+ SmallVector<uint32_t, 0> entryOffsets;
+ entryOffsets.resize_for_overwrite(hdr.NameCount);
+ for (auto i : seq(hdr.NameCount))
+ entryOffsets[i] =
+ endian::readNext<uint32_t, ELFT::Endianness, unaligned>(p);
+ return entryOffsets;
+ });
});
+}
- auto *ret = make<DebugNamesSection>();
- ret->inputDebugNamesSections = sections;
- ret->outputChunks = std::move(outputChunks);
- ret->numChunks = files.size();
- ret->collectMergedCounts(inputChunks);
- ret->getMergedAbbrevTable(inputChunks);
- ret->getMergedSymbols(inputChunks);
- ret->computeUniqueHashes(inputChunks);
- // inputChunks are not needed any more. Reset now to save memory.
- inputChunksPtr.reset();
- ret->generateBuckets();
- ret->calculateEntriesSizeAndOffsets();
- ret->updateParentIndexEntries();
- ret->sectionSize = ret->calculateMergedSectionSize();
- return ret;
+template <class ELFT>
+template <class RelTy>
+void DebugNamesSection<ELFT>::getNameRelocs(
+ InputSection *sec, ArrayRef<RelTy> rels,
+ DenseMap<uint32_t, uint32_t> &relocs) {
+ for (const RelTy &rel : rels) {
+ Symbol &sym = sec->file->getRelocTargetSym(rel);
+ relocs[rel.r_offset] = sym.getVA(getAddend<ELFT>(rel));
+ }
+}
+
+template <class ELFT> void DebugNamesSection<ELFT>::finalizeContents() {
+ // Get relocations of .debug_names sections.
+ auto relocs = std::make_unique<DenseMap<uint32_t, uint32_t>[]>(numChunks);
+ parallelFor(0, numChunks, [&](size_t i) {
+ InputSection *sec = inputSections[i];
+ auto rels = sec->template relsOrRelas<ELFT>();
+ if (rels.areRelocsRel())
+ getNameRelocs(sec, rels.rels, relocs.get()[i]);
+ else
+ getNameRelocs(sec, rels.relas, relocs.get()[i]);
+ });
+
+ // Relocate string offsets in the name table.
+ parallelForEach(nameVecs, [&](auto &nameVec) {
+ for (NameEntry &ne : nameVec)
+ ne.stringOffset = relocs.get()[ne.chunkIdx][ne.stringOffset];
+ });
+}
+
+template <class ELFT> void DebugNamesSection<ELFT>::writeTo(uint8_t *buf) {
+ [[maybe_unused]] uint8_t *oldBuf = buf;
+ // Write the header.
+ endian::write32<ELFT::Endianness>(buf + 0, hdr.UnitLength);
+ endian::write16<ELFT::Endianness>(buf + 4, hdr.Version);
+ endian::write32<ELFT::Endianness>(buf + 8, hdr.CompUnitCount);
+ endian::write32<ELFT::Endianness>(buf + 12, hdr.LocalTypeUnitCount);
+ endian::write32<ELFT::Endianness>(buf + 16, hdr.ForeignTypeUnitCount);
+ endian::write32<ELFT::Endianness>(buf + 20, hdr.BucketCount);
+ endian::write32<ELFT::Endianness>(buf + 24, hdr.NameCount);
+ endian::write32<ELFT::Endianness>(buf + 28, hdr.AbbrevTableSize);
+ endian::write32<ELFT::Endianness>(buf + 32, hdr.AugmentationStringSize);
+ buf += 36;
+ memcpy(buf, hdr.AugmentationString.c_str(), hdr.AugmentationString.size());
+ buf += hdr.AugmentationStringSize;
+
+ // Write the CU list.
+ for (auto i : seq(numChunks)) {
+ OutputChunk &chunk = chunks[i];
+ for (uint32_t cuOffset : chunk.compUnits) {
+ endian::write32<ELFT::Endianness>(buf,
+ chunk.infoSec->outSecOff + cuOffset);
+ buf += 4;
+ }
+ }
+
+ if (hdr.LocalTypeUnitCount || hdr.ForeignTypeUnitCount)
+ warn(".debug_names: type units are not implemented");
+
+ // Write the hash lookup table.
+ SmallVector<SmallVector<NameEntry *, 0>, 0> buckets(hdr.BucketCount);
+ // Symbols enter into a bucket whose index is the hash modulo bucket_count.
+ for (auto &nameVec : nameVecs)
+ for (NameEntry &ne : nameVec)
+ buckets[ne.hashValue % hdr.BucketCount].push_back(&ne);
+
+ // Write buckets (accumulated bucket counts).
+ uint32_t bucketIdx = 1;
+ for (const SmallVector<NameEntry *, 0> &bucket : buckets) {
+ if (!bucket.empty())
+ endian::write32<ELFT::Endianness>(buf, bucketIdx);
+ buf += 4;
+ bucketIdx += bucket.size();
+ }
+ // Write the hashes.
+ for (const SmallVector<NameEntry *, 0> &bucket : buckets) {
+ for (const NameEntry *e : bucket) {
+ endian::write32<ELFT::Endianness>(buf, e->hashValue);
+ buf += 4;
+ }
+ }
+
+ // Write the name table. The name entries are ordered by bucket_idx and
+ // correspond one-to-one with the hash lookup table.
+ //
+ // First, write the relocated string offsets.
+ for (const SmallVector<NameEntry *, 0> &bucket : buckets) {
+ for (const NameEntry *ne : bucket) {
+ endian::write32<ELFT::Endianness>(buf, ne->stringOffset);
+ buf += 4;
+ }
+ }
+ // Then write the entry offsets.
+ for (const SmallVector<NameEntry *, 0> &bucket : buckets) {
+ for (const NameEntry *ne : bucket) {
+ endian::write32<ELFT::Endianness>(buf, ne->entryOffset);
+ buf += 4;
+ }
+ }
+
+ // Write the abbrev table.
+ memcpy(buf, abbrevTableBuf.data(), abbrevTableBuf.size());
+ buf += abbrevTableBuf.size();
+
+ // Write the entry pool. Unlike the name table, the name entries follow the
+ // nameVecs order computed by `computeEntryPool`.
+ for (auto &nameVec : nameVecs) {
+ for (NameEntry &ne : nameVec) {
+ for (const IndexEntry &ie : ne.entries()) {
+ buf += encodeULEB128(ie.abbrevCode, buf);
+ for (AttrValue value : ie.attrValues) {
+ switch (value.attrSize) {
+ case 1:
+ *buf = value.attrValue;
+ break;
+ case 2:
+ endian::write16<ELFT::Endianness>(buf, value.attrValue);
+ break;
+ case 4:
+ endian::write32<ELFT::Endianness>(buf, value.attrValue);
+ break;
+ default:
+ llvm_unreachable("invalid attrSize");
+ }
+ buf += value.attrSize;
+ }
+ }
+ ++buf; // index entry sentinel
+ }
+ }
+ assert(uint64_t(buf - oldBuf) == size);
}
GdbIndexSection::GdbIndexSection()
@@ -4616,6 +4446,7 @@ void InStruct::reset() {
ppc32Got2.reset();
ibtPlt.reset();
relaPlt.reset();
+ debugNames.reset();
gdbIndex.reset();
shStrTab.reset();
strTab.reset();
@@ -5025,8 +4856,10 @@ template <class ELFT> void elf::createSyntheticSections() {
if (config->andFeatures || !ctx.aarch64PauthAbiCoreInfo.empty())
add(*make<GnuPropertySection>());
- if (config->debugNames)
- add(*DebugNamesSection<ELFT>::create());
+ if (config->debugNames) {
+ in.debugNames = std::make_unique<DebugNamesSection<ELFT>>();
+ add(*in.debugNames);
+ }
if (config->gdbIndex) {
in.gdbIndex = GdbIndexSection::create<ELFT>();
add(*in.gdbIndex);
diff --git a/lld/ELF/SyntheticSections.h b/lld/ELF/SyntheticSections.h
index 297f2ca6e27d85..2d37cbdefb4ade 100644
--- a/lld/ELF/SyntheticSections.h
+++ b/lld/ELF/SyntheticSections.h
@@ -793,27 +793,11 @@ class RelroPaddingSection final : public SyntheticSection {
void writeTo(uint8_t *buf) override {}
};
-template <class ELFT> class DebugNamesSection final : public SyntheticSection {
- // N.B. Everything in this class assumes that we are using DWARF32.
- // If we move to DWARF64, most of this data will need to be re-sized,
- // and the code that handles or manipulates it will need to be updated
- // accordingly.
-
+// Used by the merged DWARF32 .debug_names (a per-module index). If we
+// move to DWARF64, most of this data will need to be re-sized.
+class DebugNamesBaseSection : public SyntheticSection {
public:
- DebugNamesSection();
- static DebugNamesSection *create();
- void writeTo(uint8_t *buf) override;
- size_t getSize() const override { return sectionSize; }
- bool isNeeded() const override;
-
- template <class RelTy>
- void getNameRelocsImpl(InputSection *sec, ArrayRef<RelTy> rels,
- llvm::DenseMap<uint32_t, uint32_t> &relocs);
-
- void getNameRelocs(InputSectionBase *base,
- llvm::DenseMap<uint32_t, uint32_t> &relocs);
-
- struct Abbrev : public llvm::FoldingSetNode {
+ struct Abbrev : llvm::FoldingSetNode {
uint32_t code;
uint32_t tag;
SmallVector<llvm::DWARFDebugNames::AttributeEncoding, 2> attributes;
@@ -821,7 +805,7 @@ template <class ELFT> class DebugNamesSection final : public SyntheticSection {
void Profile(llvm::FoldingSetNodeID &id) const;
};
- struct AttrValueData {
+ struct AttrValue {
uint32_t attrValue;
uint8_t attrSize;
};
@@ -830,86 +814,103 @@ template <class ELFT> class DebugNamesSection final : public SyntheticSection {
uint32_t abbrevCode;
uint32_t poolOffset;
union {
- int32_t parentOffset = -1;
+ uint64_t parentOffset = 0;
IndexEntry *parentEntry;
};
- SmallVector<AttrValueData, 3> attrValues;
+ SmallVector<AttrValue, 3> attrValues;
};
- struct NamedEntry {
+ struct NameEntry {
const char *name;
uint32_t hashValue;
- uint32_t stringOffsetOffset;
+ uint32_t stringOffset;
uint32_t entryOffset;
- uint32_t relocatedEntryOffset;
- // The index of the chunk that 'name' points into, for looking up
- // relocation data for this string.
+ // Used to relocate `stringOffset` in the merged section.
uint32_t chunkIdx;
- SmallVector<std::unique_ptr<IndexEntry>, 0> indexEntries;
- };
+ SmallVector<IndexEntry *, 0> indexEntries;
- struct SectionOffsetLocs {
- uint64_t stringOffsetsBase;
- uint64_t entryOffsetsBase;
- uint64_t entriesBase;
+ llvm::iterator_range<
+ llvm::pointee_iterator<typename SmallVector<IndexEntry *, 0>::iterator>>
+ entries() {
+ return llvm::make_pointee_range(indexEntries);
+ }
};
- struct DebugNamesSectionData {
+ // One name index described by an input .debug_names section. An InputChunk
+ // typically contains one single name index.
+ struct NameData {
llvm::DWARFDebugNames::Header hdr;
- llvm::DWARFDebugNames::DWARFDebugNamesOffsets locs;
- SmallVector<uint32_t, 0> tuOffsets;
- SmallVector<Abbrev, 0> abbrevTable;
- SmallVector<uint32_t, 0> entryOffsets;
- SmallVector<NamedEntry, 0> namedEntries;
- uint16_t dwarfSize;
- uint16_t hdrSize;
+ llvm::DenseMap<uint32_t, uint32_t> abbrevCodeMap;
+ SmallVector<NameEntry, 0> nameEntries;
};
- // Per-file data used, while reading in the data, to generate the merged
- // section information.
- struct DebugNamesInputChunk {
- uint32_t baseCuOffsetIdx;
- std::unique_ptr<llvm::DWARFDebugNames> debugNamesData;
- std::unique_ptr<LLDDWARFSection> namesSection;
- SmallVector<DebugNamesSectionData, 0> sectionsData;
- SmallVector<uint32_t, 0> hashValues;
- llvm::DenseMap<uint32_t, uint32_t> abbrevCodeMap;
+ // InputChunk and OutputChunk hold per-file contribution to the merged index.
+ // InputChunk instances will be discarded after `create` completes.
+ struct InputChunk {
+ uint32_t baseCuIdx;
+ LLDDWARFSection section;
+ SmallVector<NameData, 0> nameData;
+ std::optional<llvm::DWARFDebugNames> llvmDebugNames;
};
- // Per-file data needed for correctly writing out the .debug_names section.
- struct DebugNamesOutputChunk {
- // Pointer to .debug_info section for this chunk/file, used for
- // calculating correct relocated CU offsets in the merged index.
- InputSection *sec;
- SmallVector<uint32_t, 0> compilationUnits;
- SmallVector<uint32_t, 0> typeUnits;
+ struct OutputChunk {
+ // Pointer to the .debug_info section that contains compile units, used to
+ // compute the relocated CU offsets.
+ InputSection *infoSec;
+ SmallVector<uint32_t, 0> compUnits;
};
- void collectMergedCounts(MutableArrayRef<DebugNamesInputChunk> &inputChunks);
- std::pair<uint8_t, llvm::dwarf::Form> getMergedCuSizeData();
- void getMergedAbbrevTable(MutableArrayRef<DebugNamesInputChunk> &inputChunks);
- void getMergedSymbols(MutableArrayRef<DebugNamesInputChunk> &inputChunks);
- void computeUniqueHashes(MutableArrayRef<DebugNamesInputChunk> &inputChunks);
- void generateBuckets();
- void calculateEntriesSizeAndOffsets();
- void updateParentIndexEntries();
- uint64_t calculateMergedSectionSize();
+ DebugNamesBaseSection();
+ size_t getSize() const override { return size; }
+ bool isNeeded() const override { return numChunks > 0; }
+protected:
+ void init(llvm::function_ref<void(InputFile *, InputChunk &, OutputChunk &)>);
+ static void
+ parseDebugNames(InputChunk &inputChunk, OutputChunk &chunk,
+ llvm::DWARFDataExtractor &namesExtractor,
+ llvm::DataExtractor &strExtractor,
+ llvm::function_ref<SmallVector<uint32_t, 0>(
+ const llvm::DWARFDebugNames::Header &hdr,
+ const llvm::DWARFDebugNames::DWARFDebugNamesOffsets &)>
+ readOffsets);
+ void computeHdrAndAbbrevTable(MutableArrayRef<InputChunk>);
+ std::pair<uint32_t, uint32_t> computeEntryPool(MutableArrayRef<InputChunk>);
+
+ // Input .debug_names sections for relocating string offsets in the name table
+ // in finalizeContents.
+ SmallVector<InputSection *, 0> inputSections;
+
+ llvm::DWARFDebugNames::Header hdr;
+ size_t numChunks;
+ std::unique_ptr<OutputChunk[]> chunks;
llvm::SpecificBumpPtrAllocator<Abbrev> abbrevAlloc;
+ SmallVector<Abbrev *, 0> abbrevTable;
+ SmallVector<char, 0> abbrevTableBuf;
+
+ // Sharded name entries that will be used to compute bucket_count and the
+ // count name table.
+ static constexpr size_t numShards = 32;
+ SmallVector<NameEntry, 0> nameVecs[numShards];
+};
+
+// Complement DebugNamesBaseSection for ELFT-aware code: reading offsets,
+// relocating string offsets, and writeTo.
+template <class ELFT>
+class DebugNamesSection final : public DebugNamesBaseSection {
+public:
+ DebugNamesSection();
+ void finalizeContents() override;
+ void writeTo(uint8_t *buf) override;
+
+ template <class RelTy>
+ void getNameRelocs(InputSection *sec, ArrayRef<RelTy> rels,
+ llvm::DenseMap<uint32_t, uint32_t> &relocs);
private:
- size_t sectionSize;
- uint32_t mergedTotalEntriesSize;
- uint32_t numChunks;
- llvm::DWARFDebugNames::DWARFDebugNamesOffsets mergedOffsets;
- std::unique_ptr<DebugNamesOutputChunk[]> outputChunks;
- // Pointers to the original .debug_names sections; used for find the correct'
- // string relocation values when writing out the merged index.
- SmallVector<InputSectionBase *, 0> inputDebugNamesSections;
- llvm::DWARFDebugNames::Header mergedHdr;
- SmallVector<Abbrev *, 0> mergedAbbrevTable;
- SmallVector<NamedEntry, 0> mergedEntries;
- SmallVector<SmallVector<NamedEntry *, 0>, 0> bucketList;
+ static void readOffsets(InputChunk &inputChunk, OutputChunk &chunk,
+ llvm::DWARFDataExtractor &namesExtractor,
+ llvm::DataExtractor &strExtractor);
};
class GdbIndexSection final : public SyntheticSection {
@@ -1487,6 +1488,7 @@ struct InStruct {
std::unique_ptr<IBTPltSection> ibtPlt;
std::unique_ptr<RelocationBaseSection> relaPlt;
// Non-SHF_ALLOC sections
+ std::unique_ptr<SyntheticSection> debugNames;
std::unique_ptr<GdbIndexSection> gdbIndex;
std::unique_ptr<StringTableSection> shStrTab;
std::unique_ptr<StringTableSection> strTab;
diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp
index d2a9e872dab91e..240c16a4d8f69b 100644
--- a/lld/ELF/Writer.cpp
+++ b/lld/ELF/Writer.cpp
@@ -1957,6 +1957,7 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() {
// finalizeAddressDependentContent may have added local symbols to the
// static symbol table.
finalizeSynthetic(in.symTab.get());
+ finalizeSynthetic(in.debugNames.get());
finalizeSynthetic(in.ppc64LongBranchTarget.get());
finalizeSynthetic(in.armCmseSGSection.get());
}
diff --git a/lld/docs/ReleaseNotes.rst b/lld/docs/ReleaseNotes.rst
index bf0c8e55d103e8..8efe877caf6aa4 100644
--- a/lld/docs/ReleaseNotes.rst
+++ b/lld/docs/ReleaseNotes.rst
@@ -32,6 +32,8 @@ ELF Improvements
* ``GNU_PROPERTY_AARCH64_FEATURE_PAUTH`` notes, ``R_AARCH64_AUTH_ABS64`` and
``R_AARCH64_AUTH_RELATIVE`` relocations are now supported.
(`#72714 <https://github.com/llvm/llvm-project/pull/72714>`_)
+* ``--debug-names`` is added to create a merged ``.debug_names`` index
+ from input ``.debug_names`` sections.
Breaking changes
----------------
diff --git a/lld/test/ELF/debug-names-bad-aug-string.s b/lld/test/ELF/debug-names-bad-aug-string.s
index bf46f4ccef03db..1cf81cfef94dfc 100644
--- a/lld/test/ELF/debug-names-bad-aug-string.s
+++ b/lld/test/ELF/debug-names-bad-aug-string.s
@@ -1,37 +1,31 @@
-// This file was generated by copying debug-names.s and manually
-// editing the 'Header: augmentation string' in the .debug_names section.
+# This file was generated by copying debug-names.s and manually
+# editing the 'Header: augmentation string' in the .debug_names section.
-// REQUIRES: x86
-// RUN: rm -rf %t && split-file %s %t
-// RUN: llvm-mc -filetype=obj -triple=x86_64 %t/debug-names-bad-aug-string.s \
-// RUN: -o %t/debug-names-bad-aug-string.o
-// RUN: llvm-mc -filetype=obj -triple=x86_64 %t/debug-names-2.s \
-// RUN: -o %t/debug-names-2.o
-// RUN: ld.lld --debug-names %t/debug-names-bad-aug-string.o \
-// RUN: %t/debug-names-2.o -o %t/debug-names-bad-aug-string
+# REQUIRES: x86
+# RUN: rm -rf %t && split-file %s %t && cd %t
+# RUN: llvm-mc -filetype=obj -triple=x86_64 bad-aug-string.s -o bad-aug-string.o
+# RUN: llvm-mc -filetype=obj -triple=x86_64 b.s -o b.o
+# RUN: ld.lld --debug-names bad-aug-string.o b.o -o out
+# RUN: llvm-dwarfdump -debug-names out | FileCheck %s --check-prefix=DWARF
-// RUN: llvm-dwarfdump -debug-names %t/debug-names-bad-aug-string \
-// RUN: | FileCheck -DFILE=%t/debug-names-bad-aug-string.o \
-// RUN: -DFILE=%t/debug-names-2.o %s --check-prefix=DWARF
-
-// DWARF: .debug_names contents:
-// DWARF: Name Index @ 0x0 {
-// DWARF-NEXT: Header {
-// DWARF-NEXT: Length: 0xCC
-// DWARF-NEXT: Format: DWARF32
-// DWARF-NEXT: Version: 5
-// DWARF-NEXT: CU count: 2
-// DWARF-NEXT: Local TU count: 0
-// DWARF-NEXT: Foreign TU count: 0
-// DWARF-NEXT: Bucket count: 5
-// DWARF-NEXT: Name count: 5
-// DWARF-NEXT: Abbreviations table size: 0x1F
-// DWARF-NEXT: Augmentation: ' '
-// DWARF: Compilation Unit offsets [
-// DWARF-NEXT: CU[0]: 0x00000000
-// DWARF-NEXT: CU[1]: 0x0000000c
+# DWARF: .debug_names contents:
+# DWARF: Name Index @ 0x0 {
+# DWARF-NEXT: Header {
+# DWARF-NEXT: Length: 0xC0
+# DWARF-NEXT: Format: DWARF32
+# DWARF-NEXT: Version: 5
+# DWARF-NEXT: CU count: 2
+# DWARF-NEXT: Local TU count: 0
+# DWARF-NEXT: Foreign TU count: 0
+# DWARF-NEXT: Bucket count: 5
+# DWARF-NEXT: Name count: 5
+# DWARF-NEXT: Abbreviations table size: 0x1F
+# DWARF-NEXT: Augmentation: ''
+# DWARF: Compilation Unit offsets [
+# DWARF-NEXT: CU[0]: 0x00000000
+# DWARF-NEXT: CU[1]: 0x0000000c
-#--- debug-names-bad-aug-string.s
+#--- bad-aug-string.s
.text
.globl _Z2f12t1 # -- Begin function _Z2f12t1
.p2align 4, 0x90
@@ -159,19 +153,19 @@ _Z2f12t1: # @_Z2f12t1
.section .debug_line,"", at progbits
.Lline_table_start0:
-#--- debug-names-2.s
-// input file: debug-names-2.cpp
-// Generated with:
-// - clang++ -g -O0 -gpubnames -fdebug-compilation-dir='debug-names-test' \
-// -S debug-names-2.cpp -o debug-names-2.s
+#--- b.s
+# input file: debug-names-2.cpp
+# Generated with:
+# - clang++ -g -O0 -gpubnames -fdebug-compilation-dir='debug-names-test' \
+# -S debug-names-2.cpp -o b.s
-// debug-names-2.cpp contents:
+# debug-names-2.cpp contents:
-// struct t1 { };
-// int main() {
-// t1 v1;
-// }
-//
+# struct t1 { };
+# int main() {
+# t1 v1;
+# }
+#
.text
.globl main # -- Begin function main
.p2align 4, 0x90
diff --git a/lld/test/ELF/debug-names-bad-die-idx-sizes.s b/lld/test/ELF/debug-names-bad-die-idx-sizes.s
index e73d013f3b0edb..25a14d2e7a1912 100644
--- a/lld/test/ELF/debug-names-bad-die-idx-sizes.s
+++ b/lld/test/ELF/debug-names-bad-die-idx-sizes.s
@@ -1,19 +1,18 @@
-// This file was generated by first compiling main.cpp:
-// clang++ -g -O0 -S -gpubnames -fdebug-compilation-dir='debug-names-test' \
-// main.cpp
-// Then manually edit the .debug_names section. In the entries, change the
-// size of the DW_IDX_die_offset from '.long' to '.byte'.
+# This file was generated by first compiling main.cpp:
+# clang++ -g -O0 -S -gpubnames -fdebug-compilation-dir='debug-names-test' \
+# main.cpp
+# Then manually edit the .debug_names section. In the entries, change the
+# size of the DW_IDX_die_offset from '.long' to '.byte'.
-// Contents of main.cpp:
-// int main (int argc, char **argv) { }
+# Contents of main.cpp:
+# int main (int argc, char **argv) { }
-// REQUIRES: x86
-// RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t1.o
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t1.o
+# RUN: not ld.lld --debug-names %t1.o -o /dev/null 2>&1 \
+# RUN: | FileCheck -DFILE=%t1.o --implicit-check-not=error: %s
-// RUN: not ld.lld --debug-names %t1.o -o /dev/null 2>&1 \
-// RUN: | FileCheck -DFILE=%t1.o %s
-
-// CHECK: error: {{.*}}:(.debug_names): encountered unexpected end of section while reading entry
+# CHECK: error: [[FILE]]:(.debug_names): index entry is out of bounds
.text
.globl main # -- Begin function main
diff --git a/lld/test/ELF/debug-names-bad-name-count.s b/lld/test/ELF/debug-names-bad-name-count.s
index cda4484b0e4c67..3410949b62fcd1 100644
--- a/lld/test/ELF/debug-names-bad-name-count.s
+++ b/lld/test/ELF/debug-names-bad-name-count.s
@@ -1,23 +1,23 @@
-// REQUIRES: x86
-// RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t1.o
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t1.o
-// RUN: not ld.lld --debug-names %t1.o -o /dev/null 2>&1 \
-// RUN: FileCheck -DFILE=%t1.o %s
+# RUN: not ld.lld --debug-names %t1.o -o /dev/null 2>&1 \
+# RUN: FileCheck -DFILE=%t1.o --implicit-check-not=error: %s
-// CHECK: error: {{.*}}:(.debug_names): encountered unexpected end of section while reading entry
-// CHECK: error: {{.*}}:(.debug_names): encountered unexpected end of section while reading entry
-// CHECK: error: {{.*}}:(.debug_names): encountered unexpected end of section while reading entry
-// CHECK: error: {{.*}}:(.debug_names): encountered unexpected end of section while reading entry
+# CHECK: error: [[FILE]]:(.debug_names): index entry is out of bounds
+# CHECK: error: [[FILE]]:(.debug_names): index entry is out of bounds
+# CHECK: error: [[FILE]]:(.debug_names): index entry is out of bounds
+# CHECK: error: [[FILE]]:(.debug_names): index entry is out of bounds
-// This file was generated by first compiling main.cpp:
-// clang++ -g -O0 -S -gpubnames -fdebug-compilation-dir='debug-names-test' \
-// main.cpp
+# This file was generated by first compiling main.cpp:
+# clang++ -g -O0 -S -gpubnames -fdebug-compilation-dir='debug-names-test' \
+# main.cpp
-// Then manually edit .debug_names section: change value for
-// 'Header: name count' from 3 to 4.
+# Then manually edit .debug_names section: change value for
+# 'Header: name count' from 3 to 4.
-// Contents of main.cpp:
-// int main (int argc, char **argv) { }
+# Contents of main.cpp:
+# int main (int argc, char **argv) { }
.text
.globl main # -- Begin function main
diff --git a/lld/test/ELF/debug-names-bad-offsets-sizes.s b/lld/test/ELF/debug-names-bad-offsets-sizes.s
index 3e7f36b2e2175e..e5b4570b216513 100644
--- a/lld/test/ELF/debug-names-bad-offsets-sizes.s
+++ b/lld/test/ELF/debug-names-bad-offsets-sizes.s
@@ -1,22 +1,22 @@
-// This file was generated by first compiling main.cpp:
-// clang++ -g -O0 -S -gpubnames -fdebug-compilation-dir='debug-names-test' \
-// main.cpp
+# This file was generated by first compiling main.cpp:
+# clang++ -g -O0 -S -gpubnames -fdebug-compilation-dir='debug-names-test' \
+# main.cpp
-// Then manually edit .debug_names section. Change the sizes of
-// 'Offset in Bucket' values from '.long' to '.byte'.
+# Then manually edit .debug_names section. Change the sizes of
+# 'Offset in Bucket' values from '.long' to '.byte'.
-// Contentsof main.cpp:
-// int main (int argc, char **argv) { }
+# Contentsof main.cpp:
+# int main (int argc, char **argv) { }
-// REQUIRES: x86
-// RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t1.o
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t1.o
-// RUN: not ld.lld --debug-names %t1.o -o /dev/null 2>&1 \
-// RUN: | FileCheck -DFILE=%t1.o %s
+# RUN: not ld.lld --debug-names %t1.o -o /dev/null 2>&1 \
+# RUN: | FileCheck -DFILE=%t1.o --implicit-check-not=error: %s
-// CHECK: error: {{.*}}:(.debug_names): encountered unexpected end of section while reading entry
-// CHECK: error: {{.*}}:(.debug_names): encountered unexpected end of section while reading entry
-// CHECK: error: {{.*}}:(.debug_names): encountered unexpected end of section while reading entry
+# CHECK: error: [[FILE]]:(.debug_names): index entry is out of bounds
+# CHECK-NEXT: error: [[FILE]]:(.debug_names): index entry is out of bounds
+# CHECK-NEXT: error: [[FILE]]:(.debug_names): index entry is out of bounds
.text
.globl main # -- Begin function main
diff --git a/lld/test/ELF/debug-names-bad-version.s b/lld/test/ELF/debug-names-bad-version.s
index eda1eaa03039bf..ac7d6853bfa623 100644
--- a/lld/test/ELF/debug-names-bad-version.s
+++ b/lld/test/ELF/debug-names-bad-version.s
@@ -1,19 +1,16 @@
-// This file was generated by copying debug-names.s and manually
-// editing the 'Header: version' in the .debug_names section (changed it from
-// 5 to 4).
+# This file was generated by copying debug-names.s and manually
+# editing the 'Header: version' in the .debug_names section (changed it from
+# 5 to 4).
-// REQUIRES: x86
-// RUN: rm -rf %t && split-file %s %t
-// RUN: llvm-mc -filetype=obj -triple=x86_64 %t/debug-names-bad-version.s \
-// RUN: -o %t/debug-names-bad-version.o
-// RUN: llvm-mc -filetype=obj -triple=x86_64 %t/debug-names-2.s \
-// RUN: -o %t/debug-names-2.o
-// RUN: not ld.lld --debug-names %t/debug-names-bad-version.o \
-// RUN: %t/debug-names-2.o -o /dev/null 2>&1 | FileCheck %s
+# REQUIRES: x86
+# RUN: rm -rf %t && split-file %s %t && cd %t
+# RUN: llvm-mc -filetype=obj -triple=x86_64 bad-version.s -o bad-version.o
+# RUN: llvm-mc -filetype=obj -triple=x86_64 b.s -o b.o
+# RUN: not ld.lld --debug-names bad-version.o b.o 2>&1 | FileCheck %s --implicit-check-not=error:
-// CHECK: error: {{.*}}:(.debug_names): unsupported version
+# CHECK: error: bad-version.o:(.debug_names): unsupported version 4
-#--- debug-names-bad-version.s
+#--- bad-version.s
.text
.globl _Z2f12t1 # -- Begin function _Z2f12t1
.p2align 4, 0x90
@@ -176,19 +173,19 @@ _Z2f12t1: # @_Z2f12t1
.section .debug_line,"", at progbits
.Lline_table_start0:
-#--- debug-names-2.s
-// input file: debug-names-2.cpp
-// Generated with:
-// - clang++ -g -O0 -gpubnames -fdebug-compilation-dir='debug-names-test' \
-// -S debug-names-2.cpp -o debug-names-2.s
+#--- b.s
+# input file: debug-names-2.cpp
+# Generated with:
+# - clang++ -g -O0 -gpubnames -fdebug-compilation-dir='debug-names-test' \
+# -S debug-names-2.cpp -o b.s
-// debug-names-2.cpp contents:
+# debug-names-2.cpp contents:
-// struct t1 { };
-// int main() {
-// t1 v1;
-// }
-//
+# struct t1 { };
+# int main() {
+# t1 v1;
+# }
+#
.text
.globl main # -- Begin function main
.p2align 4, 0x90
diff --git a/lld/test/ELF/debug-names-dwarf64.s b/lld/test/ELF/debug-names-dwarf64.s
index 790f2ddeba3972..515ea67945e616 100644
--- a/lld/test/ELF/debug-names-dwarf64.s
+++ b/lld/test/ELF/debug-names-dwarf64.s
@@ -1,16 +1,16 @@
-// This file was generated by:
-// clang++ -g -O0 -S -fdebug-compilation-dir='debug-names-test' \
-// -gdwarf64 -gpubnames main.cpp
+# This file was generated by:
+# clang++ -g -O0 -S -fdebug-compilation-dir='debug-names-test' \
+# -gdwarf64 -gpubnames main.cpp
-// Contents of main.cpp
-// int main (int argc, char **argv) { }
+# Contents of main.cpp
+# int main (int argc, char **argv) { }
-// REQUIRES: x86
-// RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t1.o
-// RUN: not ld.lld --debug-names %t1.o -o /dev/null 2>&1 \
-// RUN: | FileCheck -DFILE=%t1.o %s
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t1.o
+# RUN: not ld.lld --debug-names %t1.o -o /dev/null 2>&1 \
+# RUN: | FileCheck -DFILE=%t1.o --implicit-check-not=error: %s
-// CHECK: error: {{.*}}(.debug_names): unsupported DWARF64
+# CHECK: error: [[FILE]]:(.debug_names): unsupported DWARF64
.text
.globl main # -- Begin function main
diff --git a/lld/test/ELF/debug-names-invalid-abbrev-code.s b/lld/test/ELF/debug-names-invalid-abbrev-code.s
index 54c0105ae56b5e..65d7f50f02d372 100644
--- a/lld/test/ELF/debug-names-invalid-abbrev-code.s
+++ b/lld/test/ELF/debug-names-invalid-abbrev-code.s
@@ -1,19 +1,18 @@
-// This file was generated by:
-// clang++ -g -O0 -S -fdebug-compilation-dir='debug-names-test' \
-// -gpubnames main.cpp
+# This file was generated by:
+# clang++ -g -O0 -S -fdebug-compilation-dir='debug-names-test' \
+# -gpubnames main.cpp
-// Then manually changing an abbrev code.
+# Then manually changing an abbrev code.
-// Contents of main.cpp
-// int main (int argc, char **argv) { }
+# Contents of main.cpp
+# int main (int argc, char **argv) { }
-// REQUIRES: x86
-// RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t1.o
-// RUN: not ld.lld --debug-names %t1.o -o /dev/null 2>&1 \
-// RUN: | FileCheck -DFILE=%t1.o %s
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t1.o
+# RUN: not ld.lld --debug-names %t1.o -o /dev/null 2>&1 \
+# RUN: | FileCheck -DFILE=%t1.o --implicit-check-not=error: %s
-// CHECK: error: {{.*}}(.debug_names): invalid abbrev code in entry
-// CHECK: error: {{.*}}(.debug_names): invalid abbrev code in entry
+# CHECK: error: [[FILE]]:(.debug_names): invalid abbrev code in entry
.text
.globl main # -- Begin function main
diff --git a/lld/test/ELF/debug-names-invalid-attribute-2.s b/lld/test/ELF/debug-names-invalid-attribute-2.s
index 16706f0054c312..fbed524ef29f83 100644
--- a/lld/test/ELF/debug-names-invalid-attribute-2.s
+++ b/lld/test/ELF/debug-names-invalid-attribute-2.s
@@ -1,19 +1,19 @@
-// This file was generated by:
-// clang++ -g -O0 -S -fdebug-compilation-dir='debug-names-test' \
-// -gpubnames main.cpp
+# This file was generated by:
+# clang++ -g -O0 -S -fdebug-compilation-dir='debug-names-test' \
+# -gpubnames main.cpp
-// Then manually editing .debug_names section, commenting out a
-// DW_IDX_die_offset in an entry.
+# Then manually editing .debug_names section, commenting out a
+# DW_IDX_die_offset in an entry.
-// Contents of main.cpp
-// int main (int argc, char **argv) { }
+# Contents of main.cpp
+# int main (int argc, char **argv) { }
-// REQUIRES: x86
-// RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t1.o
-// RUN: not ld.lld --debug-names %t1.o -o /dev/null 2>&1 \
-// RUN: | FileCheck -DFILE=%t1.o %s
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t1.o
+# RUN: not ld.lld --debug-names %t1.o -o /dev/null 2>&1 \
+# RUN: | FileCheck -DFILE=%t1.o --implicit-check-not=error: %s
-// CHECK: error: {{.*}}(.debug_names): error while reading attributes: unexpected end of data at offset 0x80 while reading [0x7e, 0x82)
+# CHECK: error: [[FILE]]:(.debug_names): error while reading attributes: unexpected end of data at offset 0x80 while reading [0x7e, 0x82)
.text
.globl main # -- Begin function main
diff --git a/lld/test/ELF/debug-names-invalid-attribute-3.s b/lld/test/ELF/debug-names-invalid-attribute-3.s
index 9b99cbe87d5a0e..465f0a92064b4c 100644
--- a/lld/test/ELF/debug-names-invalid-attribute-3.s
+++ b/lld/test/ELF/debug-names-invalid-attribute-3.s
@@ -1,21 +1,21 @@
-// This file was generated by:
-// clang++ -g -O0 -S -fdebug-compilation-dir='debug-names-test' \
-// -gpubnames main.cpp
+# This file was generated by:
+# clang++ -g -O0 -S -fdebug-compilation-dir='debug-names-test' \
+# -gpubnames main.cpp
-// Then manually changing the first .debug_names abbrev, so that the
-// DW_IDX_die_offset uses DW_FORM_flag_present (invalid) & the DW_IDX_parent
-// uses DW_FORM_ref4. Also updated the sizes of the values in the entry
-// that uses the abbrev, to match the sizes of the forms.
+# Then manually changing the first .debug_names abbrev, so that the
+# DW_IDX_die_offset uses DW_FORM_flag_present (invalid) & the DW_IDX_parent
+# uses DW_FORM_ref4. Also updated the sizes of the values in the entry
+# that uses the abbrev, to match the sizes of the forms.
-// Contents of main.cpp
-// int main (int argc, char **argv) { }
+# Contents of main.cpp
+# int main (int argc, char **argv) { }
-// REQUIRES: x86
-// RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t1.o
-// RUN: not ld.lld --debug-names %t1.o -o /dev/null 2>&1 \
-// RUN: | FileCheck -DFILE=%t1.o %s
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t1.o
+# RUN: not ld.lld --debug-names %t1.o -o /dev/null 2>&1 \
+# RUN: | FileCheck -DFILE=%t1.o --implicit-check-not=error: %s
-// CHECK: error: {{.*}}(.debug_names): invalid form for attribute
+# CHECK: error: [[FILE]]:(.debug_names): unrecognized form encoding 25 in abbrev table
.text
.globl main # -- Begin function main
diff --git a/lld/test/ELF/debug-names-invalid-attribute.s b/lld/test/ELF/debug-names-invalid-attribute.s
index 303337c0295da7..19de19c313bcfe 100644
--- a/lld/test/ELF/debug-names-invalid-attribute.s
+++ b/lld/test/ELF/debug-names-invalid-attribute.s
@@ -1,12 +1,12 @@
-// Generated by copying debug-names.s and manually editing it to make some
-// of the abbrev attributes invalid.
+# Generated by copying debug-names.s and manually editing it to make some
+# of the abbrev attributes invalid.
-// REQUIRES: x86
-// RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t1.o
-// RUN: not ld.lld --debug-names %t1.o -o /dev/null 2>&1 \
-// RUN: | FileCheck -DFILE=%t1.o %s
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t1.o
+# RUN: not ld.lld --debug-names %t1.o -o /dev/null 2>&1 \
+# RUN: | FileCheck -DFILE=%t1.o --implicit-check-not=error: %s
-// CHECK: error: {{.*}}:(.debug_names): unrecognized form encoding 16 in .debug_names abbrev table
+# CHECK: error: [[FILE]]:(.debug_names): unrecognized form encoding 16 in abbrev table
.text
.globl _Z2f12t1 # -- Begin function _Z2f12t1
diff --git a/lld/test/ELF/debug-names-invalid-parent-idx.s b/lld/test/ELF/debug-names-invalid-parent-idx.s
index 698183880445a6..01e62fb99586a2 100644
--- a/lld/test/ELF/debug-names-invalid-parent-idx.s
+++ b/lld/test/ELF/debug-names-invalid-parent-idx.s
@@ -1,21 +1,20 @@
-// This file was generated by:
-// clang++ -g -O0 -S -fdebug-compilation-dir='debug-names-test' \
-// -gpubnames main.cpp
+# This file was generated by:
+# clang++ -g -O0 -S -fdebug-compilation-dir='debug-names-test' \
+# -gpubnames main.cpp
-// Then manually editing .debug_names section, changing the form for a
-// DW_IDX_parent from DW_FORM_flag_present to DW_FORM_ref1 (invalid).
+# Then manually editing .debug_names section, changing the form for a
+# DW_IDX_parent from DW_FORM_flag_present to DW_FORM_ref1 (invalid).
-// Contents of main.cpp
-// int main (int argc, char **argv) { }
+# Contents of main.cpp
+# int main (int argc, char **argv) { }
-// REQUIRES: x86
-// RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t1.o
-// RUN: not ld.lld --debug-names %t1.o -o /dev/null 2>&1 \
-// RUN: | FileCheck -DFILE=%t1.o %s
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t1.o
+# RUN: not ld.lld --debug-names %t1.o -o /dev/null 2>&1 \
+# RUN: | FileCheck -DFILE=%t1.o --implicit-check-not=error: %s
-// CHECK: error: {{.*}}(.debug_names): invalid form for DW_IDX_parent
-// CHECK: error: {{.*}}(.debug_names): invalid form for DW_IDX_parent
-// CHECK: error: {{.*}}(.debug_names): invalid form for DW_IDX_parent
+# CHECK: error: [[FILE]]:(.debug_names): invalid form for DW_IDX_parent
+# CHECK: error: [[FILE]]:(.debug_names): invalid form for DW_IDX_parent
.text
.globl main # -- Begin function main
diff --git a/lld/test/ELF/debug-names-parent-idx.s b/lld/test/ELF/debug-names-parent-idx.s
index b44455bb498ef8..22e382e45c9a10 100644
--- a/lld/test/ELF/debug-names-parent-idx.s
+++ b/lld/test/ELF/debug-names-parent-idx.s
@@ -1,192 +1,248 @@
-// debug-names-parent-idx.s generated with:
+# debug-names-parent-idx.s generated with:
-// - clang++ -g -O0 -gpubnames -fdebug-compilation-dir='parent-idx-test' \
-// -S debug-names-parent-idx.cpp -o debug-names-parent-idx.s
+# - clang++ -g -O0 -gpubnames -fdebug-compilation-dir='parent-idx-test' \
+# -S debug-names-parent-idx.cpp -o debug-names-parent-idx.s
-// foo.h contents:
+# foo.h contents:
-// int foo();
+# int foo();
-// struct foo {
-// int x;
-// char y;
-// struct foo *foo_ptr;
-// };
+# struct foo {
+# int x;
+# char y;
+# struct foo *foo_ptr;
+# };
-// namespace parent_test {
-// int foo();
-// }
+# namespace parent_test {
+# int foo();
+# }
-// debug-names-parent-idx.cpp contents:
+# debug-names-parent-idx.cpp contents:
-// #include "foo.h"
-// void bar (struct foo &foo, int junk) {
-// foo.x = foo.x * junk;
-// }
-// int main (int argc, char** argv) {
-// struct foo my_struct;
-// my_struct.x = 10;
-// my_struct.y = 'q';
-// my_struct.foo_ptr = nullptr;
-// int junk = foo();
-// bar(my_struct, junk);
-// int junk2 = parent_test::foo();
-// return 0;
-// }
+# #include "foo.h"
+# void bar (struct foo &foo, int junk) {
+# foo.x = foo.x * junk;
+# }
+# int main (int argc, char** argv) {
+# struct foo my_struct;
+# my_struct.x = 10;
+# my_struct.y = 'q';
+# my_struct.foo_ptr = nullptr;
+# int junk = foo();
+# bar(my_struct, junk);
+# int junk2 = parent_test::foo();
+# return 0;
+# }
-// REQUIRES: x86
-// RUN: rm -rf %t && split-file %s %t
-// RUN: llvm-mc -filetype=obj -triple=x86_64 %t/debug-names-parent-idx.s \
-// RUN: -o %t/debug-names-parent-idx.o
-// RUN: llvm-mc -filetype=obj -triple=x86_64 %t/debug-names-parent-idx-2.s \
-// RUN: -o %t/debug-names-parent-idx-2.o
-// RUN: ld.lld --debug-names %t/debug-names-parent-idx.o \
-// RUN: %t/debug-names-parent-idx-2.o -o %t/debug-names-parent-idx
+# REQUIRES: x86
+# RUN: rm -rf %t && split-file %s %t && cd %t
+# RUN: llvm-mc -filetype=obj -triple=x86_64 debug-names-parent-idx.s \
+# RUN: -o debug-names-parent-idx.o
+# RUN: llvm-mc -filetype=obj -triple=x86_64 debug-names-parent-idx-2.s \
+# RUN: -o debug-names-parent-idx-2.o
+# RUN: ld.lld --debug-names debug-names-parent-idx.o \
+# RUN: debug-names-parent-idx-2.o -o debug-names-parent-idx
-// RUN: llvm-dwarfdump -debug-names %t/debug-names-parent-idx \
-// RUN: | FileCheck -DFILE=%t/debug-names-parent-idx.o \
-// RUN: -DFILE=%t/debug-names-parent-idx-2.o %s --check-prefix=DWARF
+# RUN: llvm-dwarfdump -debug-names debug-names-parent-idx | FileCheck %s --check-prefix=DWARF
-// DWARF: .debug_names contents:
-// DWARF: Name Index @ 0x0 {
-// DWARF-NEXT: Header {
-// DWARF-NEXT: Length: 0x15C
-// DWARF-NEXT: Format: DWARF32
-// DWARF-NEXT: Version: 5
-// DWARF-NEXT: CU count: 2
-// DWARF-NEXT: Local TU count: 0
-// DWARF-NEXT: Foreign TU count: 0
-// DWARF-NEXT: Bucket count: 9
-// DWARF-NEXT: Name count: 9
-// DWARF-NEXT: Abbreviations table size: 0x33
-// DWARF-NEXT: Augmentation: 'LLVM0700'
-// DWARF: Compilation Unit offsets [
-// DWARF-NEXT: CU[0]: 0x00000000
-// DWARF-NEXT: CU[1]: 0x0000000c
-// DWARF: Abbreviations [
-// DWARF-NEXT: Abbreviation 0x1 {
-// DWARF-NEXT: Tag: DW_TAG_base_type
-// DWARF-NEXT: DW_IDX_die_offset: DW_FORM_ref4
-// DWARF-NEXT: DW_IDX_parent: DW_FORM_flag_present
-// DWARF-NEXT: DW_IDX_compile_unit: DW_FORM_data1
-// DWARF: Abbreviation 0x2 {
-// DWARF-NEXT: Tag: DW_TAG_subprogram
-// DWARF-NEXT: DW_IDX_die_offset: DW_FORM_ref4
-// DWARF-NEXT: DW_IDX_parent: DW_FORM_flag_present
-// DWARF-NEXT: DW_IDX_compile_unit: DW_FORM_data1
-// DWARF: Abbreviation 0x3 {
-// DWARF-NEXT: Tag: DW_TAG_structure_type
-// DWARF-NEXT: DW_IDX_die_offset: DW_FORM_ref4
-// DWARF-NEXT: DW_IDX_parent: DW_FORM_flag_present
-// DWARF-NEXT: DW_IDX_compile_unit: DW_FORM_data1
-// DWARF: Abbreviation 0x4 {
-// DWARF-NEXT: Tag: DW_TAG_subprogram
-// DWARF-NEXT: DW_IDX_die_offset: DW_FORM_ref4
-// DWARF-NEXT: DW_IDX_parent: DW_FORM_ref4
-// DWARF-NEXT: DW_IDX_compile_unit: DW_FORM_data1
-// DWARF: Abbreviation 0x5 {
-// DWARF-NEXT: Tag: DW_TAG_namespace
-// DWARF-NEXT: DW_IDX_die_offset: DW_FORM_ref4
-// DWARF-NEXT: DW_IDX_parent: DW_FORM_flag_present
-// DWARF-NEXT: DW_IDX_compile_unit: DW_FORM_data1
-// DWARF: String: 0x00000093 "bar"
-// DWARF-NEXT: Entry @ 0xf7 {
-// DWARF-NEXT: Abbrev: 0x2
-// DWARF-NEXT: Tag: DW_TAG_subprogram
-// DWARF-NEXT: DW_IDX_die_offset: 0x00000023
-// DWARF-NEXT: DW_IDX_parent: <parent not indexed>
-// DWARF-NEXT: DW_IDX_compile_unit: 0x00
-// DWARF: String: 0x000000a9 "int"
-// DWARF-NEXT: Entry @ 0xfe {
-// DWARF-NEXT: Abbrev: 0x1
-// DWARF-NEXT: Tag: DW_TAG_base_type
-// DWARF-NEXT: DW_IDX_die_offset: 0x0000008d
-// DWARF-NEXT: DW_IDX_parent: <parent not indexed>
-// DWARF-NEXT: DW_IDX_compile_unit: 0x00
-// DWARF-NEXT: }
-// DWARF-NEXT: Entry @ 0x104 {
-// DWARF-NEXT: Abbrev: 0x1
-// DWARF-NEXT: Tag: DW_TAG_base_type
-// DWARF-NEXT: DW_IDX_die_offset: 0x00000023
-// DWARF-NEXT: DW_IDX_parent: <parent not indexed>
-// DWARF-NEXT: DW_IDX_compile_unit: 0x01
-// DWARF: String: 0x000000ad "foo"
-// DWARF-NEXT: Entry @ 0x10b {
-// DWARF-NEXT: Abbrev: 0x3
-// DWARF-NEXT: Tag: DW_TAG_structure_type
-// DWARF-NEXT: DW_IDX_die_offset: 0x00000096
-// DWARF-NEXT: DW_IDX_parent: <parent not indexed>
-// DWARF-NEXT: DW_IDX_compile_unit: 0x00
-// DWARF-NEXT: }
-// DWARF-NEXT: Entry @ 0x111 {
-// DWARF-NEXT: Abbrev: 0x2
-// DWARF-NEXT: Tag: DW_TAG_subprogram
-// DWARF-NEXT: DW_IDX_die_offset: 0x00000027
-// DWARF-NEXT: DW_IDX_parent: <parent not indexed>
-// DWARF-NEXT: DW_IDX_compile_unit: 0x01
-// DWARF-NEXT: }
-// DWARF-NEXT: Entry @ 0x117 {
-// DWARF-NEXT: Abbrev: 0x4
-// DWARF-NEXT: Tag: DW_TAG_subprogram
-// DWARF-NEXT: DW_IDX_die_offset: 0x00000045
-// DWARF-NEXT: DW_IDX_parent: Entry @ 0x128
-// DWARF-NEXT: DW_IDX_compile_unit: 0x01
-// DWARF-NEXT: }
-// DWARF-NEXT: Entry @ 0x121 {
-// DWARF-NEXT: Abbrev: 0x3
-// DWARF-NEXT: Tag: DW_TAG_structure_type
-// DWARF-NEXT: DW_IDX_die_offset: 0x00000056
-// DWARF-NEXT: DW_IDX_parent: <parent not indexed>
-// DWARF-NEXT: DW_IDX_compile_unit: 0x01
-// DWARF: String: 0x00000196 "parent_test"
-// DWARF-NEXT: Entry @ 0x128 {
-// DWARF-NEXT: Abbrev: 0x5
-// DWARF-NEXT: Tag: DW_TAG_namespace
-// DWARF-NEXT: DW_IDX_die_offset: 0x00000043
-// DWARF-NEXT: DW_IDX_parent: <parent not indexed>
-// DWARF-NEXT: DW_IDX_compile_unit: 0x01
-// DWARF: String: 0x00000097 "_Z3barR3fooi"
-// DWARF-NEXT: Entry @ 0x12f {
-// DWARF-NEXT: Abbrev: 0x2
-// DWARF-NEXT: Tag: DW_TAG_subprogram
-// DWARF-NEXT: DW_IDX_die_offset: 0x00000023
-// DWARF-NEXT: DW_IDX_parent: <parent not indexed>
-// DWARF-NEXT: DW_IDX_compile_unit: 0x00
-// DWARF: String: 0x000000a4 "main"
-// DWARF-NEXT: Entry @ 0x136 {
-// DWARF-NEXT: Abbrev: 0x2
-// DWARF-NEXT: Tag: DW_TAG_subprogram
-// DWARF-NEXT: DW_IDX_die_offset: 0x00000046
-// DWARF-NEXT: DW_IDX_parent: <parent not indexed>
-// DWARF-NEXT: DW_IDX_compile_unit: 0x00
-// DWARF: String: 0x000000b5 "char"
-// DWARF-NEXT: Entry @ 0x13d {
-// DWARF-NEXT: Abbrev: 0x1
-// DWARF-NEXT: Tag: DW_TAG_base_type
-// DWARF-NEXT: DW_IDX_die_offset: 0x000000b8
-// DWARF-NEXT: DW_IDX_parent: <parent not indexed>
-// DWARF-NEXT: DW_IDX_compile_unit: 0x00
-// DWARF-NEXT: }
-// DWARF-NEXT: Entry @ 0x143 {
-// DWARF-NEXT: Abbrev: 0x1
-// DWARF-NEXT: Tag: DW_TAG_base_type
-// DWARF-NEXT: DW_IDX_die_offset: 0x00000078
-// DWARF-NEXT: DW_IDX_parent: <parent not indexed>
-// DWARF-NEXT: DW_IDX_compile_unit: 0x01
-// DWARF: String: 0x000001a2 "_ZN11parent_test3fooEv"
-// DWARF-NEXT: Entry @ 0x14a {
-// DWARF-NEXT: Abbrev: 0x4
-// DWARF-NEXT: Tag: DW_TAG_subprogram
-// DWARF-NEXT: DW_IDX_die_offset: 0x00000045
-// DWARF-NEXT: DW_IDX_parent: Entry @ 0x128
-// DWARF-NEXT: DW_IDX_compile_unit: 0x01
-// DWARF: String: 0x0000018e "_Z3foov"
-// DWARF-NEXT: Entry @ 0x155 {
-// DWARF-NEXT: Abbrev: 0x2
-// DWARF-NEXT: Tag: DW_TAG_subprogram
-// DWARF-NEXT: DW_IDX_die_offset: 0x00000027
-// DWARF-NEXT: DW_IDX_parent: <parent not indexed>
-// DWARF-NEXT: DW_IDX_compile_unit: 0x01
+# DWARF: .debug_names contents:
+# DWARF: Name Index @ 0x0 {
+# DWARF-NEXT: Header {
+# DWARF-NEXT: Length: 0x158
+# DWARF-NEXT: Format: DWARF32
+# DWARF-NEXT: Version: 5
+# DWARF-NEXT: CU count: 2
+# DWARF-NEXT: Local TU count: 0
+# DWARF-NEXT: Foreign TU count: 0
+# DWARF-NEXT: Bucket count: 9
+# DWARF-NEXT: Name count: 9
+# DWARF-NEXT: Abbreviations table size: 0x33
+# DWARF-NEXT: Augmentation: 'LLVM0700'
+# DWARF: Compilation Unit offsets [
+# DWARF-NEXT: CU[0]: 0x00000000
+# DWARF-NEXT: CU[1]: 0x0000000c
+# DWARF: Abbreviations [
+# DWARF-NEXT: Abbreviation 0x1 {
+# DWARF-NEXT: Tag: DW_TAG_base_type
+# DWARF-NEXT: DW_IDX_die_offset: DW_FORM_ref4
+# DWARF-NEXT: DW_IDX_parent: DW_FORM_flag_present
+# DWARF-NEXT: DW_IDX_compile_unit: DW_FORM_data1
+# DWARF: Abbreviation 0x2 {
+# DWARF-NEXT: Tag: DW_TAG_subprogram
+# DWARF-NEXT: DW_IDX_die_offset: DW_FORM_ref4
+# DWARF-NEXT: DW_IDX_parent: DW_FORM_flag_present
+# DWARF-NEXT: DW_IDX_compile_unit: DW_FORM_data1
+# DWARF: Abbreviation 0x3 {
+# DWARF-NEXT: Tag: DW_TAG_structure_type
+# DWARF-NEXT: DW_IDX_die_offset: DW_FORM_ref4
+# DWARF-NEXT: DW_IDX_parent: DW_FORM_flag_present
+# DWARF-NEXT: DW_IDX_compile_unit: DW_FORM_data1
+# DWARF: Abbreviation 0x4 {
+# DWARF-NEXT: Tag: DW_TAG_subprogram
+# DWARF-NEXT: DW_IDX_die_offset: DW_FORM_ref4
+# DWARF-NEXT: DW_IDX_parent: DW_FORM_ref4
+# DWARF-NEXT: DW_IDX_compile_unit: DW_FORM_data1
+# DWARF: Abbreviation 0x5 {
+# DWARF-NEXT: Tag: DW_TAG_namespace
+# DWARF-NEXT: DW_IDX_die_offset: DW_FORM_ref4
+# DWARF-NEXT: DW_IDX_parent: DW_FORM_flag_present
+# DWARF-NEXT: DW_IDX_compile_unit: DW_FORM_data1
+# DWARF: Bucket 0 [
+# DWARF-NEXT: EMPTY
+# DWARF-NEXT: ]
+# DWARF-NEXT: Bucket 1 [
+# DWARF-NEXT: Name 1 {
+# DWARF-NEXT: Hash: 0xA974AA29
+# DWARF-NEXT: String: 0x000001a2 "_ZN11parent_test3fooEv"
+# DWARF-NEXT: Entry @ 0x14a {
+# DWARF-NEXT: Abbrev: 0x4
+# DWARF-NEXT: Tag: DW_TAG_subprogram
+# DWARF-NEXT: DW_IDX_die_offset: 0x00000045
+# DWARF-NEXT: DW_IDX_parent: Entry @ 0x128
+# DWARF-NEXT: DW_IDX_compile_unit: 0x01
+# DWARF-NEXT: }
+# DWARF-NEXT: }
+# DWARF-NEXT: Name 2 {
+# DWARF-NEXT: Hash: 0xB5063D0B
+# DWARF-NEXT: String: 0x0000018e "_Z3foov"
+# DWARF-NEXT: Entry @ 0x155 {
+# DWARF-NEXT: Abbrev: 0x2
+# DWARF-NEXT: Tag: DW_TAG_subprogram
+# DWARF-NEXT: DW_IDX_die_offset: 0x00000027
+# DWARF-NEXT: DW_IDX_parent: <parent not indexed>
+# DWARF-NEXT: DW_IDX_compile_unit: 0x01
+# DWARF-NEXT: }
+# DWARF-NEXT: }
+# DWARF-NEXT: ]
+# DWARF-NEXT: Bucket 2 [
+# DWARF-NEXT: Name 3 {
+# DWARF-NEXT: Hash: 0xB888030
+# DWARF-NEXT: String: 0x000000a9 "int"
+# DWARF-NEXT: Entry @ 0xfe {
+# DWARF-NEXT: Abbrev: 0x1
+# DWARF-NEXT: Tag: DW_TAG_base_type
+# DWARF-NEXT: DW_IDX_die_offset: 0x0000008d
+# DWARF-NEXT: DW_IDX_parent: <parent not indexed>
+# DWARF-NEXT: DW_IDX_compile_unit: 0x00
+# DWARF-NEXT: }
+# DWARF-NEXT: Entry @ 0x104 {
+# DWARF-NEXT: Abbrev: 0x1
+# DWARF-NEXT: Tag: DW_TAG_base_type
+# DWARF-NEXT: DW_IDX_die_offset: 0x00000023
+# DWARF-NEXT: DW_IDX_parent: <parent not indexed>
+# DWARF-NEXT: DW_IDX_compile_unit: 0x01
+# DWARF-NEXT: }
+# DWARF-NEXT: }
+# DWARF-NEXT: ]
+# DWARF-NEXT: Bucket 3 [
+# DWARF-NEXT: Name 4 {
+# DWARF-NEXT: Hash: 0xB8860BA
+# DWARF-NEXT: String: 0x00000093 "bar"
+# DWARF-NEXT: Entry @ 0xf7 {
+# DWARF-NEXT: Abbrev: 0x2
+# DWARF-NEXT: Tag: DW_TAG_subprogram
+# DWARF-NEXT: DW_IDX_die_offset: 0x00000023
+# DWARF-NEXT: DW_IDX_parent: <parent not indexed>
+# DWARF-NEXT: DW_IDX_compile_unit: 0x00
+# DWARF-NEXT: }
+# DWARF-NEXT: }
+# DWARF-NEXT: Name 5 {
+# DWARF-NEXT: Hash: 0xB887389
+# DWARF-NEXT: String: 0x000000ad "foo"
+# DWARF-NEXT: Entry @ 0x10b {
+# DWARF-NEXT: Abbrev: 0x3
+# DWARF-NEXT: Tag: DW_TAG_structure_type
+# DWARF-NEXT: DW_IDX_die_offset: 0x00000096
+# DWARF-NEXT: DW_IDX_parent: <parent not indexed>
+# DWARF-NEXT: DW_IDX_compile_unit: 0x00
+# DWARF-NEXT: }
+# DWARF-NEXT: Entry @ 0x111 {
+# DWARF-NEXT: Abbrev: 0x2
+# DWARF-NEXT: Tag: DW_TAG_subprogram
+# DWARF-NEXT: DW_IDX_die_offset: 0x00000027
+# DWARF-NEXT: DW_IDX_parent: <parent not indexed>
+# DWARF-NEXT: DW_IDX_compile_unit: 0x01
+# DWARF-NEXT: }
+# DWARF-NEXT: Entry @ 0x117 {
+# DWARF-NEXT: Abbrev: 0x4
+# DWARF-NEXT: Tag: DW_TAG_subprogram
+# DWARF-NEXT: DW_IDX_die_offset: 0x00000045
+# DWARF-NEXT: DW_IDX_parent: Entry @ 0x128
+# DWARF-NEXT: DW_IDX_compile_unit: 0x01
+# DWARF-NEXT: }
+# DWARF-NEXT: Entry @ 0x121 {
+# DWARF-NEXT: Abbrev: 0x3
+# DWARF-NEXT: Tag: DW_TAG_structure_type
+# DWARF-NEXT: DW_IDX_die_offset: 0x00000056
+# DWARF-NEXT: DW_IDX_parent: <parent not indexed>
+# DWARF-NEXT: DW_IDX_compile_unit: 0x01
+# DWARF-NEXT: }
+# DWARF-NEXT: }
+# DWARF-NEXT: ]
+# DWARF-NEXT: Bucket 4 [
+# DWARF-NEXT: EMPTY
+# DWARF-NEXT: ]
+# DWARF-NEXT: Bucket 5 [
+# DWARF-NEXT: EMPTY
+# DWARF-NEXT: ]
+# DWARF-NEXT: Bucket 6 [
+# DWARF-NEXT: EMPTY
+# DWARF-NEXT: ]
+# DWARF-NEXT: Bucket 7 [
+# DWARF-NEXT: Name 6 {
+# DWARF-NEXT: Hash: 0x7C9A7F6A
+# DWARF-NEXT: String: 0x000000a4 "main"
+# DWARF-NEXT: Entry @ 0x136 {
+# DWARF-NEXT: Abbrev: 0x2
+# DWARF-NEXT: Tag: DW_TAG_subprogram
+# DWARF-NEXT: DW_IDX_die_offset: 0x00000046
+# DWARF-NEXT: DW_IDX_parent: <parent not indexed>
+# DWARF-NEXT: DW_IDX_compile_unit: 0x00
+# DWARF-NEXT: }
+# DWARF-NEXT: }
+# DWARF-NEXT: ]
+# DWARF-NEXT: Bucket 8 [
+# DWARF-NEXT: Name 7 {
+# DWARF-NEXT: Hash: 0xA7255AE
+# DWARF-NEXT: String: 0x00000196 "parent_test"
+# DWARF-NEXT: Entry @ 0x128 {
+# DWARF-NEXT: Abbrev: 0x5
+# DWARF-NEXT: Tag: DW_TAG_namespace
+# DWARF-NEXT: DW_IDX_die_offset: 0x00000043
+# DWARF-NEXT: DW_IDX_parent: <parent not indexed>
+# DWARF-NEXT: DW_IDX_compile_unit: 0x01
+# DWARF-NEXT: }
+# DWARF-NEXT: }
+# DWARF-NEXT: Name 8 {
+# DWARF-NEXT: Hash: 0x51007E98
+# DWARF-NEXT: String: 0x00000097 "_Z3barR3fooi"
+# DWARF-NEXT: Entry @ 0x12f {
+# DWARF-NEXT: Abbrev: 0x2
+# DWARF-NEXT: Tag: DW_TAG_subprogram
+# DWARF-NEXT: DW_IDX_die_offset: 0x00000023
+# DWARF-NEXT: DW_IDX_parent: <parent not indexed>
+# DWARF-NEXT: DW_IDX_compile_unit: 0x00
+# DWARF-NEXT: }
+# DWARF-NEXT: }
+# DWARF-NEXT: Name 9 {
+# DWARF-NEXT: Hash: 0x7C952063
+# DWARF-NEXT: String: 0x000000b5 "char"
+# DWARF-NEXT: Entry @ 0x13d {
+# DWARF-NEXT: Abbrev: 0x1
+# DWARF-NEXT: Tag: DW_TAG_base_type
+# DWARF-NEXT: DW_IDX_die_offset: 0x000000b8
+# DWARF-NEXT: DW_IDX_parent: <parent not indexed>
+# DWARF-NEXT: DW_IDX_compile_unit: 0x00
+# DWARF-NEXT: }
+# DWARF-NEXT: Entry @ 0x143 {
+# DWARF-NEXT: Abbrev: 0x1
+# DWARF-NEXT: Tag: DW_TAG_base_type
+# DWARF-NEXT: DW_IDX_die_offset: 0x00000078
+# DWARF-NEXT: DW_IDX_parent: <parent not indexed>
+# DWARF-NEXT: DW_IDX_compile_unit: 0x01
+# DWARF-NEXT: }
+# DWARF-NEXT: }
+# DWARF-NEXT: ]
#--- debug-names-parent-idx.s
.text
@@ -425,41 +481,41 @@ main: # @main
.Lline_table_start0:
#--- debug-names-parent-idx-2.s
-// Generated with:
+# Generated with:
-// - clang++ -g -O0 -gpubnames -fdebug-compilation-dir='parent-idx-test' \
-// -S debug-names-parent-idx-2.cpp -o debug-names-parent-idx-2.s
+# - clang++ -g -O0 -gpubnames -fdebug-compilation-dir='parent-idx-test' \
+# -S debug-names-parent-idx-2.cpp -o debug-names-parent-idx-2.s
-// foo.h contents:
+# foo.h contents:
-// int foo();
+# int foo();
-//struct foo {
-// int x;
-// char y;
-// struct foo *foo_ptr;
-// };
+#struct foo {
+# int x;
+# char y;
+# struct foo *foo_ptr;
+# };
-// namespace parent_test {
-// int foo();
-// }
+# namespace parent_test {
+# int foo();
+# }
-// debug-names-parent-index-2.cpp contents:
+# debug-names-parent-index-2.cpp contents:
-// #include "foo.h"
-// int foo () {
-// struct foo struct2;
-// struct2.x = 1024;
-// struct2.y = 'r';
-// struct2.foo_ptr = nullptr;
-// return struct2.x * (int) struct2.y;
-// }
+# #include "foo.h"
+# int foo () {
+# struct foo struct2;
+# struct2.x = 1024;
+# struct2.y = 'r';
+# struct2.foo_ptr = nullptr;
+# return struct2.x * (int) struct2.y;
+# }
-// namespace parent_test {
-// int foo () {
-// return 25;
-// }
-// }
+# namespace parent_test {
+# int foo () {
+# return 25;
+# }
+# }
.text
.globl _Z3foov # -- Begin function _Z3foov
diff --git a/lld/test/ELF/debug-names.s b/lld/test/ELF/debug-names.s
index baadadd98ebf4f..442653386977dc 100644
--- a/lld/test/ELF/debug-names.s
+++ b/lld/test/ELF/debug-names.s
@@ -1,119 +1,140 @@
-// debug_names.s was gGenerated with:
+# debug_names.s was gGenerated with:
-// - clang++ -g -O0 -gpubnames -fdebug-compilation-dir='debug-names-test' \
-// -S debug-names.cpp -o debug-names.s
+# - clang++ -g -O0 -gpubnames -fdebug-compilation-dir='debug-names-test' \
+# -S debug-names.cpp -o a.s
-// debug-names.cpp contents:
+# debug-names.cpp contents:
-// struct t1 { };
-// void f1(t1) { }
+# struct t1 { };
+# void f1(t1) { }
-// REQUIRES: x86
-// RUN: rm -rf %t && split-file %s %t
-// RUN: llvm-mc -filetype=obj -triple=x86_64 %t/debug-names.s \
-// RUN: -o %t/debug-names.o
-// RUN: llvm-mc -filetype=obj -triple=x86_64 %t/debug-names-2.s \
-// RUN: -o %t/debug-names-2.o
+# REQUIRES: x86
+# RUN: rm -rf %t && split-file %s %t && cd %t
+# RUN: llvm-mc -filetype=obj -triple=x86_64 a.s -o a.o
+# RUN: llvm-mc -filetype=obj -triple=x86_64 b.s -o b.o
-// RUN: ld.lld --debug-names --no-debug-names %t/debug-names.o \
-// RUN: %t/debug-names-2.o -o %t/debug-names
-// RUN: llvm-readelf -SW %t/debug-names \
-// RUN: | FileCheck %s --check-prefix=NO_DBG_NAMES
+# RUN: ld.lld --debug-names --no-debug-names a.o b.o -o out0
+# RUN: llvm-readelf -SW out0 | FileCheck %s --check-prefix=NO_MERGE
-// NO_DBG_NAMES: .debug_names PROGBITS 0000000000000000 [[#%x,]] 000110
+# NO_MERGE: Name Type Address Off Size ES Flg Lk Inf Al
+# NO_MERGE: .debug_names PROGBITS 0000000000000000 [[#%x,]] 000110 00 0 0 4
-// RUN: ld.lld --debug-names %t/debug-names.o %t/debug-names-2.o \
-// RUN: -o %t/debug-names
+# RUN: ld.lld --debug-names a.o b.o -o out
-// RUN: llvm-dwarfdump -debug-names %t/debug-names \
-// RUN: | FileCheck %s --check-prefix=DWARF
-// RUN: llvm-readelf -SW %t/debug-names \
-// RUN: | FileCheck -DFILE=%t/debug-names.o \
-// RUN: -DFILE=%t/debug-names-2.o %s --check-prefix=READELF
+# RUN: llvm-dwarfdump -debug-names out | FileCheck %s --check-prefix=DWARF
+# RUN: llvm-readelf -SW out | FileCheck %s --check-prefix=READELF
-// READELF: .debug_names PROGBITS 0000000000000000 [[#%x,]] 0000d0
+# READELF: Name Type Address Off Size ES Flg Lk Inf Al
+# READELF: .debug_names PROGBITS 0000000000000000 [[#%x,]] 0000cc 00 0 0 4
-// DWARF: .debug_names contents:
-// DWARF: Name Index @ 0x0 {
-// DWARF-NEXT: Header {
-// DWARF-NEXT: Length: 0xCC
-// DWARF-NEXT: Format: DWARF32
-// DWARF-NEXT: Version: 5
-// DWARF-NEXT: CU count: 2
-// DWARF-NEXT: Local TU count: 0
-// DWARF-NEXT: Foreign TU count: 0
-// DWARF-NEXT: Bucket count: 5
-// DWARF-NEXT: Name count: 5
-// DWARF-NEXT: Abbreviations table size: 0x1F
-// DWARF-NEXT: Augmentation: 'LLVM0700'
-// DWARF: Compilation Unit offsets [
-// DWARF-NEXT: CU[0]: 0x00000000
-// DWARF-NEXT: CU[1]: 0x0000000c
-// DWARF: Abbreviations [
-// DWARF-NEXT: Abbreviation 0x1 {
-// DWARF: Tag: DW_TAG_structure_type
-// DWARF-NEXT: DW_IDX_die_offset: DW_FORM_ref4
-// DWARF-NEXT: DW_IDX_parent: DW_FORM_flag_present
-// DWARF-NEXT: DW_IDX_compile_unit: DW_FORM_data1
-// DWARF: Abbreviation 0x2 {
-// DWARF-NEXT: Tag: DW_TAG_subprogram
-// DWARF-NEXT: DW_IDX_die_offset: DW_FORM_ref4
-// DWARF-NEXT: DW_IDX_parent: DW_FORM_flag_present
-// DWARF-NEXT: DW_IDX_compile_unit: DW_FORM_data1
-// DWARF: Abbreviation 0x3 {
-// DWARF-NEXT: Tag: DW_TAG_base_type
-// DWARF-NEXT: DW_IDX_die_offset: DW_FORM_ref4
-// DWARF-NEXT: DW_IDX_parent: DW_FORM_flag_present
-// DWARF-NEXT: DW_IDX_compile_unit: DW_FORM_data1
-// DWARF: Bucket 0 [
-// DWARF: Bucket 1 [
-// DWARF: String: 0x00000089 "f1"
-// DWARF-NEXT: Entry @ 0xa3 {
-// DWARF-NEXT: Abbrev: 0x2
-// DWARF-NEXT: Tag: DW_TAG_subprogram
-// DWARF-NEXT: DW_IDX_die_offset: 0x00000023
-// DWARF-NEXT: DW_IDX_parent: <parent not indexed>
-// DWARF-NEXT: DW_IDX_compile_unit: 0x00
-// DWARF: String: 0x00000095 "t1"
-// DWARF-NEXT: Entry @ 0xaa {
-// DWARF-NEXT: Abbrev: 0x1
-// DWARF-NEXT: Tag: DW_TAG_structure_type
-// DWARF-NEXT: DW_IDX_die_offset: 0x0000003a
-// DWARF-NEXT: DW_IDX_parent: <parent not indexed>
-// DWARF-NEXT: DW_IDX_compile_unit: 0x00
-// DWARF-NEXT: }
-// DWARF-NEXT: Entry @ 0xb0 {
-// DWARF-NEXT: Abbrev: 0x1
-// DWARF-NEXT: Tag: DW_TAG_structure_type
-// DWARF-NEXT: DW_IDX_die_offset: 0x00000042
-// DWARF-NEXT: DW_IDX_parent: <parent not indexed>
-// DWARF-NEXT: DW_IDX_compile_unit: 0x01
-// DWARF: String: 0x00000130 "int"
-// DWARF-NEXT: Entry @ 0xb7 {
-// DWARF-NEXT: Abbrev: 0x3
-// DWARF-NEXT: Tag: DW_TAG_base_type
-// DWARF-NEXT: DW_IDX_die_offset: 0x0000003e
-// DWARF-NEXT: DW_IDX_parent: <parent not indexed>
-// DWARF-NEXT: DW_IDX_compile_unit: 0x01
-// DWARF: Bucket 2 [
-// DWARF: Bucket 3 [
-// DWARF: String: 0x0000008c "_Z2f12t1"
-// DWARF-NEXT: Entry @ 0xbe {
-// DWARF-NEXT: Abbrev: 0x2
-// DWARF-NEXT: Tag: DW_TAG_subprogram
-// DWARF-NEXT: DW_IDX_die_offset: 0x00000023
-// DWARF-NEXT: DW_IDX_parent: <parent not indexed>
-// DWARF-NEXT: DW_IDX_compile_unit: 0x00
-// DWARF: Bucket 4 [
-// DWARF: String: 0x0000012b "main"
-// DWARF-NEXT: Entry @ 0xc5 {
-// DWARF-NEXT: Abbrev: 0x2
-// DWARF-NEXT: Tag: DW_TAG_subprogram
-// DWARF-NEXT: DW_IDX_die_offset: 0x00000023
-// DWARF-NEXT: DW_IDX_parent: <parent not indexed>
-// DWARF-NEXT: DW_IDX_compile_unit: 0x01
+# DWARF: .debug_names contents:
+# DWARF: Name Index @ 0x0 {
+# DWARF-NEXT: Header {
+# DWARF-NEXT: Length: 0xC8
+# DWARF-NEXT: Format: DWARF32
+# DWARF-NEXT: Version: 5
+# DWARF-NEXT: CU count: 2
+# DWARF-NEXT: Local TU count: 0
+# DWARF-NEXT: Foreign TU count: 0
+# DWARF-NEXT: Bucket count: 5
+# DWARF-NEXT: Name count: 5
+# DWARF-NEXT: Abbreviations table size: 0x1F
+# DWARF-NEXT: Augmentation: 'LLVM0700'
+# DWARF: Compilation Unit offsets [
+# DWARF-NEXT: CU[0]: 0x00000000
+# DWARF-NEXT: CU[1]: 0x0000000c
+# DWARF: Abbreviations [
+# DWARF-NEXT: Abbreviation 0x1 {
+# DWARF: Tag: DW_TAG_structure_type
+# DWARF-NEXT: DW_IDX_die_offset: DW_FORM_ref4
+# DWARF-NEXT: DW_IDX_parent: DW_FORM_flag_present
+# DWARF-NEXT: DW_IDX_compile_unit: DW_FORM_data1
+# DWARF: Abbreviation 0x2 {
+# DWARF-NEXT: Tag: DW_TAG_subprogram
+# DWARF-NEXT: DW_IDX_die_offset: DW_FORM_ref4
+# DWARF-NEXT: DW_IDX_parent: DW_FORM_flag_present
+# DWARF-NEXT: DW_IDX_compile_unit: DW_FORM_data1
+# DWARF: Abbreviation 0x3 {
+# DWARF-NEXT: Tag: DW_TAG_base_type
+# DWARF-NEXT: DW_IDX_die_offset: DW_FORM_ref4
+# DWARF-NEXT: DW_IDX_parent: DW_FORM_flag_present
+# DWARF-NEXT: DW_IDX_compile_unit: DW_FORM_data1
+# DWARF: Bucket 0 [
+# DWARF-NEXT: EMPTY
+# DWARF-NEXT: ]
+# DWARF-NEXT: Bucket 1 [
+# DWARF-NEXT: Name 1 {
+# DWARF-NEXT: Hash: 0x59796A
+# DWARF-NEXT: String: 0x00000095 "t1"
+# DWARF-NEXT: Entry @ 0xaa {
+# DWARF-NEXT: Abbrev: 0x1
+# DWARF-NEXT: Tag: DW_TAG_structure_type
+# DWARF-NEXT: DW_IDX_die_offset: 0x0000003a
+# DWARF-NEXT: DW_IDX_parent: <parent not indexed>
+# DWARF-NEXT: DW_IDX_compile_unit: 0x00
+# DWARF-NEXT: }
+# DWARF-NEXT: Entry @ 0xb0 {
+# DWARF-NEXT: Abbrev: 0x1
+# DWARF-NEXT: Tag: DW_TAG_structure_type
+# DWARF-NEXT: DW_IDX_die_offset: 0x00000042
+# DWARF-NEXT: DW_IDX_parent: <parent not indexed>
+# DWARF-NEXT: DW_IDX_compile_unit: 0x01
+# DWARF-NEXT: }
+# DWARF-NEXT: }
+# DWARF-NEXT: Name 2 {
+# DWARF-NEXT: Hash: 0x5355B2BE
+# DWARF-NEXT: String: 0x0000008c "_Z2f12t1"
+# DWARF-NEXT: Entry @ 0xbe {
+# DWARF-NEXT: Abbrev: 0x2
+# DWARF-NEXT: Tag: DW_TAG_subprogram
+# DWARF-NEXT: DW_IDX_die_offset: 0x00000023
+# DWARF-NEXT: DW_IDX_parent: <parent not indexed>
+# DWARF-NEXT: DW_IDX_compile_unit: 0x00
+# DWARF-NEXT: }
+# DWARF-NEXT: }
+# DWARF-NEXT: Name 3 {
+# DWARF-NEXT: Hash: 0x7C9A7F6A
+# DWARF-NEXT: String: 0x0000012b "main"
+# DWARF-NEXT: Entry @ 0xc5 {
+# DWARF-NEXT: Abbrev: 0x2
+# DWARF-NEXT: Tag: DW_TAG_subprogram
+# DWARF-NEXT: DW_IDX_die_offset: 0x00000023
+# DWARF-NEXT: DW_IDX_parent: <parent not indexed>
+# DWARF-NEXT: DW_IDX_compile_unit: 0x01
+# DWARF-NEXT: }
+# DWARF-NEXT: }
+# DWARF-NEXT: ]
+# DWARF-NEXT: Bucket 2 [
+# DWARF-NEXT: EMPTY
+# DWARF-NEXT: ]
+# DWARF-NEXT: Bucket 3 [
+# DWARF-NEXT: Name 4 {
+# DWARF-NEXT: Hash: 0xB888030
+# DWARF-NEXT: String: 0x00000130 "int"
+# DWARF-NEXT: Entry @ 0xb7 {
+# DWARF-NEXT: Abbrev: 0x3
+# DWARF-NEXT: Tag: DW_TAG_base_type
+# DWARF-NEXT: DW_IDX_die_offset: 0x0000003e
+# DWARF-NEXT: DW_IDX_parent: <parent not indexed>
+# DWARF-NEXT: DW_IDX_compile_unit: 0x01
+# DWARF-NEXT: }
+# DWARF-NEXT: }
+# DWARF-NEXT: ]
+# DWARF-NEXT: Bucket 4 [
+# DWARF-NEXT: Name 5 {
+# DWARF-NEXT: Hash: 0x59779C
+# DWARF-NEXT: String: 0x00000089 "f1"
+# DWARF-NEXT: Entry @ 0xa3 {
+# DWARF-NEXT: Abbrev: 0x2
+# DWARF-NEXT: Tag: DW_TAG_subprogram
+# DWARF-NEXT: DW_IDX_die_offset: 0x00000023
+# DWARF-NEXT: DW_IDX_parent: <parent not indexed>
+# DWARF-NEXT: DW_IDX_compile_unit: 0x00
+# DWARF-NEXT: }
+# DWARF-NEXT: }
+# DWARF-NEXT: ]
-#--- debug-names.s
+#--- a.s
.text
.globl _Z2f12t1 # -- Begin function _Z2f12t1
.p2align 4, 0x90
@@ -241,18 +262,18 @@ _Z2f12t1: # @_Z2f12t1
.section .debug_line,"", at progbits
.Lline_table_start0:
-#--- debug-names-2.s
-// Generated with:
-// - clang++ -g -O0 -gpubnames -fdebug-compilation-dir='debug-names-test' \
-// -S debug-names-2.cpp -o debug-names-2.s
+#--- b.s
+# Generated with:
+# - clang++ -g -O0 -gpubnames -fdebug-compilation-dir='debug-names-test' \
+# -S debug-names-2.cpp -o b.s
-// debug-names-2.cpp contents:
+# debug-names-2.cpp contents:
-// struct t1 { };
-// int main() {
-// t1 v1;
-// }
-//
+# struct t1 { };
+# int main() {
+# t1 v1;
+# }
+#
.text
.globl main # -- Begin function main
.p2align 4, 0x90
diff --git a/lld/test/ELF/driver.test b/lld/test/ELF/driver.test
index 49deb902aa0fd8..45d73607c8ac66 100644
--- a/lld/test/ELF/driver.test
+++ b/lld/test/ELF/driver.test
@@ -30,9 +30,10 @@
# ERR2: error: -r and -pie may not be used together
# ERR2: error: -r and --export-dynamic may not be used together
-# RUN: not ld.lld -r --icf=all --gdb-index %t -o /dev/null 2>&1 | FileCheck -check-prefix=ERR4 %s
+# RUN: not ld.lld -r --icf=all --gdb-index --debug-names %t -o /dev/null 2>&1 | FileCheck -check-prefix=ERR4 %s
# ERR4: error: -r and --gdb-index may not be used together
# ERR4: error: -r and --icf may not be used together
+# ERR4: error: -r and --debug-names may not be used together
# RUN: not ld.lld -shared -pie %t -o /dev/null 2>&1 | FileCheck -check-prefix=ERR7 %s
# ERR7: error: -shared and -pie may not be used together
>From 53b14cd9ce2b57da73d173fc876d2e9e199f5640 Mon Sep 17 00:00:00 2001
From: Caroline Tice <cmtice at google.com>
Date: Wed, 10 Apr 2024 23:33:53 -0700
Subject: [PATCH 15/23] [lld][ELF] Implement merged .debug_names section.
Migrate updates & fixes from maskray's lld-debug-names branch.
---
lld/ELF/SyntheticSections.cpp | 47 +++++++++++++++++++++++++----------
lld/ELF/SyntheticSections.h | 16 ++++++------
2 files changed, 43 insertions(+), 20 deletions(-)
diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp
index be307f1b001f31..3a71f8dd01cc60 100644
--- a/lld/ELF/SyntheticSections.cpp
+++ b/lld/ELF/SyntheticSections.cpp
@@ -2784,6 +2784,7 @@ void DebugNamesBaseSection::parseDebugNames(
const char *errMsg = nullptr;
uint64_t offset = locs.EntriesBase + entryOffsets[i];
while (offset < namesSec.Data.size() && namesSec.Data[offset] != 0) {
+ // Read & store all entries (for the same string).
auto ie = makeThreadLocal<IndexEntry>();
ie->poolOffset = offset;
Error err = Error::success();
@@ -2871,9 +2872,9 @@ void DebugNamesBaseSection::parseDebugNames(
}
}
-// Compute the form for output DW_IDX_compile_unit attributes similar to
-// DIEInteger::BestForm. The input forms (often DW_FORM_data1) may not hold all
-// CU indices.
+// Compute the form for output DW_IDX_compile_unit attributes, similar to
+// DIEInteger::BestForm. The input form (often DW_FORM_data1) may not hold all
+// the merged CU indices.
std::pair<uint8_t, dwarf::Form> static getMergedCuCountForm(
uint32_t compUnitCount) {
if (compUnitCount > UINT16_MAX)
@@ -2908,23 +2909,26 @@ void DebugNamesBaseSection::computeHdrAndAbbrevTable(
hdr.AugmentationStringSize = nd.hdr.AugmentationStringSize;
hdr.AugmentationString = nd.hdr.AugmentationString;
} else if (hdr.AugmentationString != nd.hdr.AugmentationString) {
+ // There are conflicting augmentation strings, so it's best for the
+ // merged index to not use an augmentation string.
hdr.AugmentationStringSize = 0;
hdr.AugmentationString.clear();
}
}
}
- // Uniquify input abbrev tables and compute mapping from old abbrev code to
- // new abbrev code.
+ // Create the merged abbrev table, uniquifyinng the input abbrev tables and
+ // computing mapping from old (per-cu) abbrev codes to new (merged) abbrev
+ // codes.
FoldingSet<Abbrev> abbrevSet;
// Determine the form for the DW_IDX_compile_unit attributes in the merged
- // index. The input form may not encode all possible CU indices.
+ // index. The input form may not be big enough for all CU indices.
const dwarf::Form cuAttrForm = getMergedCuCountForm(hdr.CompUnitCount).second;
for (InputChunk &inputChunk : inputChunks) {
for (auto [i, ni] : enumerate(*inputChunk.llvmDebugNames)) {
for (const DWARFDebugNames::Abbrev &oldAbbrev : ni.getAbbrevs()) {
// Canonicalize abbrev by placing the CU/TU index at the end,
- // similar to `DebugNamesBaseSection::parse`.
+ // similar to 'parseDebugNames'.
Abbrev abbrev;
DWARFDebugNames::AttributeEncoding cuAttr(DW_IDX_compile_unit,
cuAttrForm);
@@ -2936,6 +2940,7 @@ void DebugNamesBaseSection::computeHdrAndAbbrevTable(
else
abbrev.attributes.push_back({a.Index, a.Form});
}
+ // Put the CU/TU index at the end of the attributes list.
abbrev.attributes.push_back(cuAttr);
// Profile the abbrev, get or assign a new code, then record the abbrev
@@ -2945,6 +2950,7 @@ void DebugNamesBaseSection::computeHdrAndAbbrevTable(
uint32_t newCode;
void *insertPos;
if (Abbrev *existing = abbrevSet.FindNodeOrInsertPos(id, insertPos)) {
+ // Found it; we've already seen an identical abbreviation.
newCode = existing->code;
} else {
Abbrev *abbrev2 =
@@ -2985,17 +2991,22 @@ void DebugNamesBaseSection::Abbrev::Profile(FoldingSetNodeID &id) const {
std::pair<uint32_t, uint32_t> DebugNamesBaseSection::computeEntryPool(
MutableArrayRef<InputChunk> inputChunks) {
TimeTraceScope timeScope("Merge .debug_names", "entry pool");
- // Collect the compilation units for each unique name. Speed it up using
- // multi-threading as the number of symbols can be in the order of millions.
+ // Collect and de-duplicate all the names (preserving all the entries).
+ // Speed it up using multithreading, as the number of symbols can be in the
+ // order of millions.
const size_t concurrency =
bit_floor(std::min<size_t>(config->threadCount, numShards));
const size_t shift = 32 - countr_zero(numShards);
const uint8_t cuAttrSize = getMergedCuCountForm(hdr.CompUnitCount).first;
DenseMap<CachedHashStringRef, size_t> maps[numShards];
+
parallelFor(0, concurrency, [&](size_t threadId) {
for (auto i : seq(numChunks)) {
InputChunk &inputChunk = inputChunks[i];
for (NameData &nd : inputChunk.nameData) {
+ // Deduplicate the NameEntry records (based on the string/name),
+ // appending all IndexEntries from duplicate NameEntry records to
+ // the single preserved copy.
for (NameEntry &ne : nd.nameEntries) {
auto shardId = ne.hashValue >> shift;
if ((shardId & (concurrency - 1)) != threadId)
@@ -3003,9 +3014,11 @@ std::pair<uint32_t, uint32_t> DebugNamesBaseSection::computeEntryPool(
ne.chunkIdx = i;
for (IndexEntry &ie : ne.entries()) {
+ // Update the IndexEntry's abbrev code to match the merged
+ // abbreviations.
ie.abbrevCode = nd.abbrevCodeMap[ie.abbrevCode];
// Update the DW_IDX_compile_unit attribute (the last one after
- // canonicalization).
+ // canonicalization) to have correct merged offset value and size.
auto &back = ie.attrValues.back();
back.attrValue += inputChunk.baseCuIdx;
back.attrSize = cuAttrSize;
@@ -3017,13 +3030,13 @@ std::pair<uint32_t, uint32_t> DebugNamesBaseSection::computeEntryPool(
if (inserted)
nameVec.push_back(std::move(ne));
else
- nameVec[it->second].indexEntries.append(ne.indexEntries);
+ nameVec[it->second].indexEntries.append(std::move(ne.indexEntries));
}
}
}
});
- // Compute entry offsets parallelly. First, compute offsets relative to the
+ // Compute entry offsets in parallel. First, comptute offsets relative to the
// current shard.
uint32_t offsets[numShards];
parallelFor(0, numShards, [&](size_t shard) {
@@ -3051,12 +3064,15 @@ std::pair<uint32_t, uint32_t> DebugNamesBaseSection::computeEntryPool(
}
});
- // Update DW_IDX_parent attributes that use DW_FORM_ref4.
+ // Update the DW_IDX_parent entries that refer to real parents (have
+ // DW_FORM_ref4).
parallelFor(0, numShards, [&](size_t shard) {
for (NameEntry &ne : nameVecs[shard]) {
for (IndexEntry &ie : ne.entries()) {
if (!ie.parentEntry)
continue;
+ // Abbrevs are indexed starting at 1; vector starts at 0. (abbrevCode
+ // corresponds to position in the merged table vector).
const Abbrev *abbrev = abbrevTable[ie.abbrevCode - 1];
for (auto i : seq(abbrev->attributes.size())) {
DWARFDebugNames::AttributeEncoding a = abbrev->attributes[i];
@@ -3217,6 +3233,8 @@ template <class ELFT> void DebugNamesSection<ELFT>::writeTo(uint8_t *buf) {
}
}
+ // Write the local TU list, then the foreign TU list..
+ // TODO: Fix this, once we get everything working without TUs.
if (hdr.LocalTypeUnitCount || hdr.ForeignTypeUnitCount)
warn(".debug_names: type units are not implemented");
@@ -3253,6 +3271,7 @@ template <class ELFT> void DebugNamesSection<ELFT>::writeTo(uint8_t *buf) {
buf += 4;
}
}
+
// Then write the entry offsets.
for (const SmallVector<NameEntry *, 0> &bucket : buckets) {
for (const NameEntry *ne : bucket) {
@@ -3269,6 +3288,7 @@ template <class ELFT> void DebugNamesSection<ELFT>::writeTo(uint8_t *buf) {
// nameVecs order computed by `computeEntryPool`.
for (auto &nameVec : nameVecs) {
for (NameEntry &ne : nameVec) {
+ // Write all the entries for the string.
for (const IndexEntry &ie : ne.entries()) {
buf += encodeULEB128(ie.abbrevCode, buf);
for (AttrValue value : ie.attrValues) {
@@ -4860,6 +4880,7 @@ template <class ELFT> void elf::createSyntheticSections() {
in.debugNames = std::make_unique<DebugNamesSection<ELFT>>();
add(*in.debugNames);
}
+
if (config->gdbIndex) {
in.gdbIndex = GdbIndexSection::create<ELFT>();
add(*in.gdbIndex);
diff --git a/lld/ELF/SyntheticSections.h b/lld/ELF/SyntheticSections.h
index 2d37cbdefb4ade..3b813600721496 100644
--- a/lld/ELF/SyntheticSections.h
+++ b/lld/ELF/SyntheticSections.h
@@ -836,16 +836,17 @@ class DebugNamesBaseSection : public SyntheticSection {
}
};
- // One name index described by an input .debug_names section. An InputChunk
- // typically contains one single name index.
+ // The contents of one input .debug_names section. An InputChunk
+ // typically contains one NameData, but might contain more, especially
+ // in LTO builds.
struct NameData {
llvm::DWARFDebugNames::Header hdr;
llvm::DenseMap<uint32_t, uint32_t> abbrevCodeMap;
SmallVector<NameEntry, 0> nameEntries;
};
- // InputChunk and OutputChunk hold per-file contribution to the merged index.
- // InputChunk instances will be discarded after `create` completes.
+ // InputChunk and OutputChunk hold per-file contributions to the merged index.
+ // InputChunk instances will be discarded after `init` completes.
struct InputChunk {
uint32_t baseCuIdx;
LLDDWARFSection section;
@@ -874,11 +875,12 @@ class DebugNamesBaseSection : public SyntheticSection {
const llvm::DWARFDebugNames::Header &hdr,
const llvm::DWARFDebugNames::DWARFDebugNamesOffsets &)>
readOffsets);
- void computeHdrAndAbbrevTable(MutableArrayRef<InputChunk>);
- std::pair<uint32_t, uint32_t> computeEntryPool(MutableArrayRef<InputChunk>);
+ void computeHdrAndAbbrevTable(MutableArrayRef<InputChunk> inputChunks);
+ std::pair<uint32_t, uint32_t>
+ computeEntryPool(MutableArrayRef<InputChunk> inputChunks);
// Input .debug_names sections for relocating string offsets in the name table
- // in finalizeContents.
+ // in `finalizeContents`.
SmallVector<InputSection *, 0> inputSections;
llvm::DWARFDebugNames::Header hdr;
>From b5732b011503f464514f01c0df9e24b351598c09 Mon Sep 17 00:00:00 2001
From: Caroline Tice <cmtice at google.com>
Date: Sun, 14 Apr 2024 10:07:17 -0700
Subject: [PATCH 16/23] [lld][ELF] Properly handle multiple (appended) indices
within single .o
Current implementation does not properly handle reading multiple
(appended) .debug_names sections withih the same input .o file. This updates
the code that reads from the .debug_nemes section to add in the proper
offset when there are multiple appended .debug_names (could be generated
by LTO, e.g.).
---
lld/ELF/SyntheticSections.cpp | 33 +++++++++++++++++++++++----------
lld/ELF/SyntheticSections.h | 2 ++
2 files changed, 25 insertions(+), 10 deletions(-)
diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp
index 3a71f8dd01cc60..12acbcc9a842ac 100644
--- a/lld/ELF/SyntheticSections.cpp
+++ b/lld/ELF/SyntheticSections.cpp
@@ -2738,11 +2738,18 @@ void DebugNamesBaseSection::parseDebugNames(
InputChunk &inputChunk, OutputChunk &chunk,
DWARFDataExtractor &namesExtractor, DataExtractor &strExtractor,
function_ref<SmallVector<uint32_t, 0>(
+ uint32_t numCus,
+ uint32_t niOffset,
const DWARFDebugNames::Header &,
const DWARFDebugNames::DWARFDebugNamesOffsets &)>
readOffsets) {
const LLDDWARFSection namesSec = inputChunk.section;
DenseMap<uint32_t, IndexEntry *> offsetMap;
+ // Number of CUs seen in previous NameIndex sections within current chunk.
+ uint32_t numCus = 0;
+ // Offset of current NameIndex section from start of .debug_names section in
+ // current chunk.
+ uint32_t niOffset = 0;
for (const DWARFDebugNames::NameIndex &ni : *inputChunk.llvmDebugNames) {
NameData &nd = inputChunk.nameData.emplace_back();
nd.hdr = ni.getHeader();
@@ -2760,20 +2767,21 @@ void DebugNamesBaseSection::parseDebugNames(
const uint32_t hdrSize =
getDebugNamesHeaderSize(nd.hdr.AugmentationStringSize);
auto locs = findDebugNamesOffsets(hdrSize, nd.hdr);
- if (locs.EntriesBase > namesExtractor.getData().size()) {
+ if (locs.EntriesBase + niOffset > namesExtractor.getData().size()) {
errorOrWarn(toString(namesSec.sec) +
Twine(": index entry is out of bounds"));
return;
}
- SmallVector<uint32_t, 0> entryOffsets = readOffsets(nd.hdr, locs);
+ SmallVector<uint32_t, 0> entryOffsets = readOffsets(numCus, niOffset,
+ nd.hdr, locs);
// Read the entry pool.
offsetMap.clear();
nd.nameEntries.resize(nd.hdr.NameCount);
for (auto i : seq(nd.hdr.NameCount)) {
NameEntry &ne = nd.nameEntries[i];
- uint64_t strOffset = locs.StringOffsetsBase + i * dwarfSize;
+ uint64_t strOffset = locs.StringOffsetsBase + niOffset + i * dwarfSize;
ne.stringOffset = strOffset;
uint64_t strp = namesExtractor.getRelocatedValue(dwarfSize, &strOffset);
StringRef name = strExtractor.getCStrRef(&strp);
@@ -2782,7 +2790,7 @@ void DebugNamesBaseSection::parseDebugNames(
// Read a series of index entries that end with abbreviation code 0.
const char *errMsg = nullptr;
- uint64_t offset = locs.EntriesBase + entryOffsets[i];
+ uint64_t offset = locs.EntriesBase + niOffset + entryOffsets[i];
while (offset < namesSec.Data.size() && namesSec.Data[offset] != 0) {
// Read & store all entries (for the same string).
auto ie = makeThreadLocal<IndexEntry>();
@@ -2869,6 +2877,8 @@ void DebugNamesBaseSection::parseDebugNames(
for (NameEntry &ne : nd.nameEntries)
for (IndexEntry &ie : ne.entries())
ie.parentEntry = offsetMap.lookup(ie.parentOffset);
+ numCus += nd.hdr.CompUnitCount;
+ niOffset += nd.hdr.UnitLength + 4;
}
}
@@ -3003,7 +3013,8 @@ std::pair<uint32_t, uint32_t> DebugNamesBaseSection::computeEntryPool(
parallelFor(0, concurrency, [&](size_t threadId) {
for (auto i : seq(numChunks)) {
InputChunk &inputChunk = inputChunks[i];
- for (NameData &nd : inputChunk.nameData) {
+ for (auto j : seq(inputChunk.nameData.size())) {
+ NameData &nd = inputChunk.nameData[j];
// Deduplicate the NameEntry records (based on the string/name),
// appending all IndexEntries from duplicate NameEntry records to
// the single preserved copy.
@@ -3020,7 +3031,7 @@ std::pair<uint32_t, uint32_t> DebugNamesBaseSection::computeEntryPool(
// Update the DW_IDX_compile_unit attribute (the last one after
// canonicalization) to have correct merged offset value and size.
auto &back = ie.attrValues.back();
- back.attrValue += inputChunk.baseCuIdx;
+ back.attrValue += inputChunk.baseCuIdx + j;
back.attrSize = cuAttrSize;
}
@@ -3156,17 +3167,19 @@ template <class ELFT> DebugNamesSection<ELFT>::DebugNamesSection() {
parseDebugNames(
inputChunk, chunk, namesExtractor, strExtractor,
[&chunk, namesData = dobj.getNamesSection().Data.data()](
+ uint32_t numCus,
+ uint32_t niOffset,
const DWARFDebugNames::Header &hdr,
const DWARFDebugNames::DWARFDebugNamesOffsets &locs) {
// Read CU offsets.
- const char *p = namesData + locs.CUsBase;
- chunk.compUnits.resize_for_overwrite(hdr.CompUnitCount);
+ const char *p = namesData + niOffset + locs.CUsBase;
+ chunk.compUnits.resize_for_overwrite(numCus + hdr.CompUnitCount);
for (auto i : seq(hdr.CompUnitCount))
- chunk.compUnits[i] =
+ chunk.compUnits[i + numCus] =
endian::readNext<uint32_t, ELFT::Endianness, unaligned>(p);
// Read entry offsets.
- p = namesData + locs.EntryOffsetsBase;
+ p = namesData + niOffset + locs.EntryOffsetsBase;
SmallVector<uint32_t, 0> entryOffsets;
entryOffsets.resize_for_overwrite(hdr.NameCount);
for (auto i : seq(hdr.NameCount))
diff --git a/lld/ELF/SyntheticSections.h b/lld/ELF/SyntheticSections.h
index 3b813600721496..f15658e779bc20 100644
--- a/lld/ELF/SyntheticSections.h
+++ b/lld/ELF/SyntheticSections.h
@@ -872,6 +872,8 @@ class DebugNamesBaseSection : public SyntheticSection {
llvm::DWARFDataExtractor &namesExtractor,
llvm::DataExtractor &strExtractor,
llvm::function_ref<SmallVector<uint32_t, 0>(
+ uint32_t numCUs,
+ uint32_t niOffset,
const llvm::DWARFDebugNames::Header &hdr,
const llvm::DWARFDebugNames::DWARFDebugNamesOffsets &)>
readOffsets);
>From 5b4566d6a3ca317d923647778e7a150df821be21 Mon Sep 17 00:00:00 2001
From: Caroline Tice <cmtice at google.com>
Date: Sun, 14 Apr 2024 13:16:06 -0700
Subject: [PATCH 17/23] [lld][ELF] Add & update tests:
New tests:
- ppc-debug-names.s : Tests .debug_names merging for big endiamn & 32-bit
- debug-names-missing-parent.s: Tests .debug_names merging works when a
DW_IDX_parent attribute is missing.
Updated debug-names-bad-die-idx-sizes.s & debug-names-bad-name-count.s:
- Added tests with --noinhibit_execc to generate warnings & not die
Fixed names of source files in debug_names.s & the new/updated tests.
---
lld/test/ELF/debug-names-bad-die-idx-sizes.s | 32 +-
lld/test/ELF/debug-names-bad-name-count.s | 21 +-
lld/test/ELF/debug-names-missing-parent.s | 223 ++++++++++
lld/test/ELF/debug-names.s | 50 +--
lld/test/ELF/ppc32-debug-names.s | 417 +++++++++++++++++++
5 files changed, 698 insertions(+), 45 deletions(-)
create mode 100644 lld/test/ELF/debug-names-missing-parent.s
create mode 100644 lld/test/ELF/ppc32-debug-names.s
diff --git a/lld/test/ELF/debug-names-bad-die-idx-sizes.s b/lld/test/ELF/debug-names-bad-die-idx-sizes.s
index 25a14d2e7a1912..850629b3086603 100644
--- a/lld/test/ELF/debug-names-bad-die-idx-sizes.s
+++ b/lld/test/ELF/debug-names-bad-die-idx-sizes.s
@@ -1,10 +1,10 @@
-# This file was generated by first compiling main.cpp:
-# clang++ -g -O0 -S -gpubnames -fdebug-compilation-dir='debug-names-test' \
-# main.cpp
+# This file was generated by first compiling a.cpp:
+# clang++ -g -O0 -S -gpubnames -fdebug-compilation-dir='/proc/self/cwd' a.cpp
+
# Then manually edit the .debug_names section. In the entries, change the
# size of the DW_IDX_die_offset from '.long' to '.byte'.
-# Contents of main.cpp:
+# Contents of a.cpp:
# int main (int argc, char **argv) { }
# REQUIRES: x86
@@ -14,6 +14,12 @@
# CHECK: error: [[FILE]]:(.debug_names): index entry is out of bounds
+# RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t1.o
+# RUN: ld.lld --debug-names --noinhibit-exec %t1.o -o /dev/null 2>&1 \
+# RUN: | FileCheck -DFILE=%t1.o %s --check-prefix=WARN
+
+# WARN: warning: [[FILE]]:(.debug_names): index entry is out of bounds
+
.text
.globl main # -- Begin function main
.p2align 4, 0x90
@@ -59,21 +65,21 @@ main: # @main
.Lstr_offsets_base0:
.section .debug_str,"MS", at progbits,1
.Linfo_string0:
- .asciz "clang version 19.0.0git (git at github.com:llvm/llvm-project.git d33d5630b281debe6eabd67e323bcf767340fb6a)" # string offset=0
+ .asciz "clang version 19.0.0git (git at github.com:llvm/llvm-project.git 53b14cd9ce2b57da73d173fc876d2e9e199f5640)" # string offset=0
.Linfo_string1:
- .asciz "main.cpp" # string offset=104
+ .asciz "a.cpp" # string offset=104
.Linfo_string2:
- .asciz "debug-names-test" # string offset=113
+ .asciz "/proc/self/cwd" # string offset=110
.Linfo_string3:
- .asciz "main" # string offset=130
+ .asciz "main" # string offset=125
.Linfo_string4:
- .asciz "int" # string offset=135
+ .asciz "int" # string offset=130
.Linfo_string5:
- .asciz "argc" # string offset=139
+ .asciz "argc" # string offset=134
.Linfo_string6:
- .asciz "argv" # string offset=144
+ .asciz "argv" # string offset=139
.Linfo_string7:
- .asciz "char" # string offset=149
+ .asciz "char" # string offset=144
.Laddr_table_base0:
.quad .Lfunc_begin0
.Ldebug_addr_end0:
@@ -143,7 +149,7 @@ main: # @main
# End of list: char
.p2align 2, 0x0
.Lnames_end0:
- .ident "clang version 19.0.0git (git at github.com:llvm/llvm-project.git d33d5630b281debe6eabd67e323bcf767340fb6a)"
+ .ident "clang version 19.0.0git (git at github.com:llvm/llvm-project.git 53b14cd9ce2b57da73d173fc876d2e9e199f5640)"
.section ".note.GNU-stack","", at progbits
.addrsig
.section .debug_line,"", at progbits
diff --git a/lld/test/ELF/debug-names-bad-name-count.s b/lld/test/ELF/debug-names-bad-name-count.s
index 3410949b62fcd1..f660bc0512cc6f 100644
--- a/lld/test/ELF/debug-names-bad-name-count.s
+++ b/lld/test/ELF/debug-names-bad-name-count.s
@@ -1,22 +1,29 @@
# REQUIRES: x86
# RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t1.o
-
+
# RUN: not ld.lld --debug-names %t1.o -o /dev/null 2>&1 \
-# RUN: FileCheck -DFILE=%t1.o --implicit-check-not=error: %s
-
+# RUN: | FileCheck -DFILE=%t1.o --implicit-check-not=error: %s
+
# CHECK: error: [[FILE]]:(.debug_names): index entry is out of bounds
# CHECK: error: [[FILE]]:(.debug_names): index entry is out of bounds
# CHECK: error: [[FILE]]:(.debug_names): index entry is out of bounds
# CHECK: error: [[FILE]]:(.debug_names): index entry is out of bounds
-# This file was generated by first compiling main.cpp:
-# clang++ -g -O0 -S -gpubnames -fdebug-compilation-dir='debug-names-test' \
-# main.cpp
+# RUN: ld.lld --noinhibit-exec --debug-names %t1.o -o /dev/null 2>&1 \
+# RUN: | FileCheck -DFILE=%t1.o %s --check-prefix=WARN
+
+# WARN: warning: [[FILE]]:(.debug_names): index entry is out of bounds
+# WARN: warning: [[FILE]]:(.debug_names): index entry is out of bounds
+# WARN: warning: [[FILE]]:(.debug_names): index entry is out of bounds
+# WARN: warning: [[FILE]]:(.debug_names): index entry is out of bounds
+
+# This file was generated by first compiling a.cpp:
+# clang++ -g -O0 -S -gpubnames -fdebug-compilation-dir='/proc/self/cwd' a.cpp
# Then manually edit .debug_names section: change value for
# 'Header: name count' from 3 to 4.
-# Contents of main.cpp:
+# Contents of a.cpp:
# int main (int argc, char **argv) { }
.text
diff --git a/lld/test/ELF/debug-names-missing-parent.s b/lld/test/ELF/debug-names-missing-parent.s
new file mode 100644
index 00000000000000..5c7e0ad839a00e
--- /dev/null
+++ b/lld/test/ELF/debug-names-missing-parent.s
@@ -0,0 +1,223 @@
+# debug-names-missing-parent was generated with
+
+# clang++ -g -O0 -S -fdebug-compilation-dir='debug-names-test' \
+# -gpubnames a.cpp
+
+# a.cpp contents:
+
+# int main (int argc, char **argv) { }
+
+# Then manually edit the .s file:
+# - Remove DW_IDX_parent & DW_FORM_flag_present from DW_TAG_subprogram abbrev
+# - Remove DW_IDX_parent value from entry for 'main'
+
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t1.o
+# RUN: ld.lld --debug-names %t1.o -o %t
+# RUN: llvm-dwarfdump --debug-names %t | FileCheck %s --check-prefix=DWARF
+
+# DWARF: .debug_names contents:
+# DWARF: Name Index @ 0x0 {
+# DWARF-NEXT: Header {
+# DWARF-NEXT: Length: 0x8A
+# DWARF-NEXT: Format: DWARF32
+# DWARF-NEXT: Version: 5
+# DWARF-NEXT: CU count: 1
+# DWARF-NEXT: Local TU count: 0
+# DWARF-NEXT: Foreign TU count: 0
+# DWARF-NEXT: Bucket count: 3
+# DWARF-NEXT: Name count: 3
+# DWARF-NEXT: Abbreviations table size: 0x13
+# DWARF-NEXT: Augmentation: 'LLVM0700'
+# DWARF: Compilation Unit offsets [
+# DWARF-NEXT: CU[0]: 0x00000000
+# DWARF: Abbreviations [
+# DWARF-NEXT: Abbreviation 0x1 {
+# DWARF: Tag: DW_TAG_base_type
+# DWARF-NEXT: DW_IDX_die_offset: DW_FORM_ref4
+# DWARF-NEXT: DW_IDX_parent: DW_FORM_flag_present
+# DWARF-NEXT: DW_IDX_compile_unit: DW_FORM_data1
+# DWARF: Abbreviation 0x2 {
+# DWARF-NEXT: Tag: DW_TAG_subprogram
+# DWARF-NEXT: DW_IDX_die_offset: DW_FORM_ref4
+# DWARF-NEXT: DW_IDX_compile_unit: DW_FORM_data1
+# DWARF: Bucket 0 [
+# DWARF-NEXT: EMPTY
+# DWARF-NEXT: ]
+# DWARF-NEXT: Bucket 1 [
+# DWARF-NEXT: Name 1 {
+# DWARF-NEXT: Hash: 0x7C9A7F6A
+# DWARF-NEXT: String: 0x0000007f "main"
+# DWARF-NEXT: Entry @ 0x7a {
+# DWARF-NEXT: Abbrev: 0x2
+# DWARF-NEXT: Tag: DW_TAG_subprogram
+# DWARF-NEXT: DW_IDX_die_offset: 0x00000023
+# DWARF-NEXT: DW_IDX_compile_unit: 0x00
+# DWARF-NEXT: }
+# DWARF-NEXT: Entry @ 0x80 {
+# DWARF-NEXT: Abbrev: 0x1
+# DWARF-NEXT: Tag: DW_TAG_base_type
+# DWARF-NEXT: DW_IDX_die_offset: 0x00000049
+# DWARF-NEXT: DW_IDX_parent: <parent not indexed>
+# DWARF-NEXT: DW_IDX_compile_unit: 0x00
+# DWARF-NEXT: }
+# DWARF-NEXT: }
+# DWARF-NEXT: ]
+# DWARF-NEXT: Bucket 2 [
+# DWARF-NEXT: Name 2 {
+# DWARF-NEXT: Hash: 0xB888030
+# DWARF-NEXT: String: 0x00000084 "int"
+# DWARF-NEXT: Entry @ 0x73 {
+# DWARF-NEXT: Abbrev: 0x1
+# DWARF-NEXT: Tag: DW_TAG_base_type
+# DWARF-NEXT: DW_IDX_die_offset: 0x00000049
+# DWARF-NEXT: DW_IDX_parent: <parent not indexed>
+# DWARF-NEXT: DW_IDX_compile_unit: 0x00
+# DWARF-NEXT: }
+# DWARF-NEXT: }
+# DWARF-NEXT: Name 3 {
+# DWARF-NEXT: Hash: 0x7C952063
+# DWARF-NEXT: String: 0x00000092 "char"
+# DWARF-NEXT: Entry @ 0x87 {
+# DWARF-NEXT: Abbrev: 0x1
+# DWARF-NEXT: Tag: DW_TAG_base_type
+# DWARF-NEXT: DW_IDX_die_offset: 0x00000057
+# DWARF-NEXT: DW_IDX_parent: <parent not indexed>
+# DWARF-NEXT: DW_IDX_compile_unit: 0x00
+# DWARF-NEXT: }
+# DWARF-NEXT: }
+# DWARF-NEXT: ]
+
+# --- a.s
+
+ .text
+ .globl main # -- Begin function main
+ .p2align 4, 0x90
+ .type main, at function
+main: # @main
+.Lfunc_begin0:
+ .cfi_startproc
+# %bb.0: # %entry
+ pushq %rbp
+ .cfi_def_cfa_offset 16
+ .cfi_offset %rbp, -16
+ movq %rsp, %rbp
+ .cfi_def_cfa_register %rbp
+ movl %edi, -4(%rbp)
+ movq %rsi, -16(%rbp)
+.Ltmp0:
+ xorl %eax, %eax
+ popq %rbp
+ .cfi_def_cfa %rsp, 8
+ retq
+.Ltmp1:
+.Lfunc_end0:
+ .size main, .Lfunc_end0-main
+ .cfi_endproc
+ # -- End function
+ .section .debug_abbrev,"", at progbits
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 0 # EOM(3)
+ .section .debug_info,"", at progbits
+.Lcu_begin0:
+ .long .Ldebug_info_end0-.Ldebug_info_start0 # Length of Unit
+.Ldebug_info_start0:
+ .short 5 # DWARF version number
+ .byte 1 # DWARF Unit Type
+ .byte 8 # Address Size (in bytes)
+ .long .debug_abbrev # Offset Into Abbrev. Section
+.Ldebug_info_end0:
+ .section .debug_str_offsets,"", at progbits
+ .long 36 # Length of String Offsets Set
+ .short 5
+ .short 0
+.Lstr_offsets_base0:
+ .section .debug_str,"MS", at progbits,1
+.Linfo_string0:
+ .asciz "clang version 19.0.0git (git at github.com:llvm/llvm-project.git 53b14cd9ce2b57da73d173fc876d2e9e199f5640)" # string offset=0
+.Linfo_string1:
+ .asciz "a.cpp" # string offset=104
+.Linfo_string2:
+ .asciz "debug-names-test" # string offset=110
+.Linfo_string3:
+ .asciz "main" # string offset=127
+.Linfo_string4:
+ .asciz "int" # string offset=132
+.Linfo_string5:
+ .asciz "argc" # string offset=136
+.Linfo_string6:
+ .asciz "argv" # string offset=141
+.Linfo_string7:
+ .asciz "char" # string offset=146
+.Laddr_table_base0:
+ .quad .Lfunc_begin0
+.Ldebug_addr_end0:
+ .section .debug_names,"", at progbits
+ .long .Lnames_end0-.Lnames_start0 # Header: unit length
+.Lnames_start0:
+ .short 5 # Header: version
+ .short 0 # Header: padding
+ .long 1 # Header: compilation unit count
+ .long 0 # Header: local type unit count
+ .long 0 # Header: foreign type unit count
+ .long 3 # Header: bucket count
+ .long 3 # Header: name count
+ .long .Lnames_abbrev_end0-.Lnames_abbrev_start0 # Header: abbreviation table size
+ .long 8 # Header: augmentation string size
+ .ascii "LLVM0700" # Header: augmentation string
+ .long .Lcu_begin0 # Compilation unit 0
+ .long 0 # Bucket 0
+ .long 1 # Bucket 1
+ .long 2 # Bucket 2
+ .long 2090499946 # Hash in Bucket 1
+ .long 193495088 # Hash in Bucket 2
+ .long 2090147939 # Hash in Bucket 2
+ .long .Linfo_string3 # String in Bucket 1: main
+ .long .Linfo_string4 # String in Bucket 2: int
+ .long .Linfo_string7 # String in Bucket 2: char
+ .long .Lnames0-.Lnames_entries0 # Offset in Bucket 1
+ .long .Lnames1-.Lnames_entries0 # Offset in Bucket 2
+ .long .Lnames2-.Lnames_entries0 # Offset in Bucket 2
+.Lnames_abbrev_start0:
+ .byte 1 # Abbrev code
+ .byte 46 # DW_TAG_subprogram
+ .byte 3 # DW_IDX_die_offset
+ .byte 19 # DW_FORM_ref4
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev
+ .byte 2 # Abbrev code
+ .byte 36 # DW_TAG_base_type
+ .byte 3 # DW_IDX_die_offset
+ .byte 19 # DW_FORM_ref4
+ .byte 4 # DW_IDX_parent
+ .byte 25 # DW_FORM_flag_present
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev list
+.Lnames_abbrev_end0:
+.Lnames_entries0:
+.Lnames0:
+.L1:
+ .byte 1 # Abbreviation code
+ .long 35 # DW_IDX_die_offset
+ # End of list: main
+.Lnames1:
+.L0:
+ .byte 2 # Abbreviation code
+ .long 73 # DW_IDX_die_offset
+ .byte 0 # DW_IDX_parent
+ # End of list: int
+.Lnames2:
+.L2:
+ .byte 2 # Abbreviation code
+ .long 87 # DW_IDX_die_offset
+ .byte 0 # DW_IDX_parent
+ # End of list: char
+ .p2align 2, 0x0
+.Lnames_end0:
+ .ident "clang version 19.0.0git (git at github.com:llvm/llvm-project.git 53b14cd9ce2b57da73d173fc876d2e9e199f5640)"
+ .section ".note.GNU-stack","", at progbits
+ .addrsig
+ .section .debug_line,"", at progbits
+.Lline_table_start0:
diff --git a/lld/test/ELF/debug-names.s b/lld/test/ELF/debug-names.s
index 442653386977dc..eb35281a224f0d 100644
--- a/lld/test/ELF/debug-names.s
+++ b/lld/test/ELF/debug-names.s
@@ -1,9 +1,9 @@
-# debug_names.s was gGenerated with:
+# debug-names.s was generated with:
# - clang++ -g -O0 -gpubnames -fdebug-compilation-dir='debug-names-test' \
-# -S debug-names.cpp -o a.s
+# -S a.cpp -o a.s
-# debug-names.cpp contents:
+# a.cpp contents:
# struct t1 { };
# void f1(t1) { }
@@ -65,7 +65,7 @@
# DWARF-NEXT: Bucket 1 [
# DWARF-NEXT: Name 1 {
# DWARF-NEXT: Hash: 0x59796A
-# DWARF-NEXT: String: 0x00000095 "t1"
+# DWARF-NEXT: String: 0x0000008b "t1"
# DWARF-NEXT: Entry @ 0xaa {
# DWARF-NEXT: Abbrev: 0x1
# DWARF-NEXT: Tag: DW_TAG_structure_type
@@ -83,7 +83,7 @@
# DWARF-NEXT: }
# DWARF-NEXT: Name 2 {
# DWARF-NEXT: Hash: 0x5355B2BE
-# DWARF-NEXT: String: 0x0000008c "_Z2f12t1"
+# DWARF-NEXT: String: 0x00000082 "_Z2f12t1"
# DWARF-NEXT: Entry @ 0xbe {
# DWARF-NEXT: Abbrev: 0x2
# DWARF-NEXT: Tag: DW_TAG_subprogram
@@ -94,7 +94,7 @@
# DWARF-NEXT: }
# DWARF-NEXT: Name 3 {
# DWARF-NEXT: Hash: 0x7C9A7F6A
-# DWARF-NEXT: String: 0x0000012b "main"
+# DWARF-NEXT: String: 0x00000115 "main"
# DWARF-NEXT: Entry @ 0xc5 {
# DWARF-NEXT: Abbrev: 0x2
# DWARF-NEXT: Tag: DW_TAG_subprogram
@@ -110,7 +110,7 @@
# DWARF-NEXT: Bucket 3 [
# DWARF-NEXT: Name 4 {
# DWARF-NEXT: Hash: 0xB888030
-# DWARF-NEXT: String: 0x00000130 "int"
+# DWARF-NEXT: String: 0x0000011a "int"
# DWARF-NEXT: Entry @ 0xb7 {
# DWARF-NEXT: Abbrev: 0x3
# DWARF-NEXT: Tag: DW_TAG_base_type
@@ -123,7 +123,7 @@
# DWARF-NEXT: Bucket 4 [
# DWARF-NEXT: Name 5 {
# DWARF-NEXT: Hash: 0x59779C
-# DWARF-NEXT: String: 0x00000089 "f1"
+# DWARF-NEXT: String: 0x0000007f "f1"
# DWARF-NEXT: Entry @ 0xa3 {
# DWARF-NEXT: Abbrev: 0x2
# DWARF-NEXT: Tag: DW_TAG_subprogram
@@ -177,17 +177,17 @@ _Z2f12t1: # @_Z2f12t1
.Lstr_offsets_base0:
.section .debug_str,"MS", at progbits,1
.Linfo_string0:
- .asciz "clang version 19.0.0git (git at github.com:llvm/llvm-project.git 4df364bc93af49ae413ec1ae8328f34ac70730c4)" # string offset=0
+ .asciz "clang version 19.0.0git (git at github.com:llvm/llvm-project.git 53b14cd9ce2b57da73d173fc876d2e9e199f5640)" # string offset=0
.Linfo_string1:
- .asciz "debug-names.cpp" # string offset=104
+ .asciz "a.cpp" # string offset=104
.Linfo_string2:
- .asciz "debug-names-test" # string offset=120
+ .asciz "debug-names-test" # string offset=110
.Linfo_string3:
- .asciz "f1" # string offset=137
+ .asciz "f1" # string offset=127
.Linfo_string4:
- .asciz "_Z2f12t1" # string offset=140
+ .asciz "_Z2f12t1" # string offset=130
.Linfo_string5:
- .asciz "t1" # string offset=149
+ .asciz "t1" # string offset=139
.Laddr_table_base0:
.quad .Lfunc_begin0
.Ldebug_addr_end0:
@@ -256,7 +256,7 @@ _Z2f12t1: # @_Z2f12t1
# End of list: _Z2f12t1
.p2align 2, 0x0
.Lnames_end0:
- .ident "clang version 19.0.0git (git at github.com:llvm/llvm-project.git 4df364bc93af49ae413ec1ae8328f34ac70730c4)"
+ .ident "clang version 19.0.0git (git at github.com:llvm/llvm-project.git 53b14cd9ce2b57da73d173fc876d2e9e199f5640)"
.section ".note.GNU-stack","", at progbits
.addrsig
.section .debug_line,"", at progbits
@@ -265,9 +265,9 @@ _Z2f12t1: # @_Z2f12t1
#--- b.s
# Generated with:
# - clang++ -g -O0 -gpubnames -fdebug-compilation-dir='debug-names-test' \
-# -S debug-names-2.cpp -o b.s
+# -S b.cpp -o b.s
-# debug-names-2.cpp contents:
+# b.cpp contents:
# struct t1 { };
# int main() {
@@ -317,19 +317,19 @@ main: # @main
.Lstr_offsets_base0:
.section .debug_str,"MS", at progbits,1
.Linfo_string0:
- .asciz "clang version 19.0.0git (git at github.com:llvm/llvm-project.git 4df364bc93af49ae413ec1ae8328f34ac70730c4)" # string offset=0
+ .asciz "clang version 19.0.0git (git at github.com:llvm/llvm-project.git 53b14cd9ce2b57da73d173fc876d2e9e199f5640)" # string offset=0
.Linfo_string1:
- .asciz "debug-names-2.cpp" # string offset=104
+ .asciz "b.cpp" # string offset=104
.Linfo_string2:
- .asciz "debug-names-test" # string offset=122
+ .asciz "debug-names-test" # string offset=110
.Linfo_string3:
- .asciz "main" # string offset=139
+ .asciz "main" # string offset=127
.Linfo_string4:
- .asciz "int" # string offset=144
+ .asciz "int" # string offset=132
.Linfo_string5:
- .asciz "v1" # string offset=148
+ .asciz "v1" # string offset=136
.Linfo_string6:
- .asciz "t1" # string offset=151
+ .asciz "t1" # string offset=139
.Laddr_table_base0:
.quad .Lfunc_begin0
.Ldebug_addr_end0:
@@ -407,7 +407,7 @@ main: # @main
# End of list: int
.p2align 2, 0x0
.Lnames_end0:
- .ident "clang version 19.0.0git (git at github.com:llvm/llvm-project.git 4df364bc93af49ae413ec1ae8328f34ac70730c4)"
+ .ident "clang version 19.0.0git (git at github.com:llvm/llvm-project.git 53b14cd9ce2b57da73d173fc876d2e9e199f5640)"
.section ".note.GNU-stack","", at progbits
.addrsig
.section .debug_line,"", at progbits
diff --git a/lld/test/ELF/ppc32-debug-names.s b/lld/test/ELF/ppc32-debug-names.s
new file mode 100644
index 00000000000000..40d7cc5b4fa2f7
--- /dev/null
+++ b/lld/test/ELF/ppc32-debug-names.s
@@ -0,0 +1,417 @@
+# ppc-debug-names.s was generated with:
+
+# - clang++ --target=powerpc -g -O0 -gpubnames \
+# -fdebug-compilation-dir='debug-names-test' -S a.cpp -o a.s
+
+# a.cpp contents:
+
+# struct t1 { };
+# void f1(t1) { }
+
+# REQUIRES: ppc
+# RUN: rm -rf %t && split-file %s %t && cd %t
+# RUN: llvm-mc -filetype=obj -triple=powerpc a.s -o a.o
+# RUN: llvm-mc -filetype=obj -triple=powerpc b.s -o b.o
+
+# RUN: ld.lld --debug-names --no-debug-names a.o b.o -o out0
+# RUN: llvm-readelf -SW out0 | FileCheck %s --check-prefix=NO_MERGE
+
+# NO_MERGE: Name Type Address Off Size ES Flg Lk Inf Al
+# NO_MERGE: .debug_names PROGBITS 00000000 [[#%x,]] 000110 00 0 0 4
+
+# RUN: ld.lld --debug-names a.o b.o -o out
+
+# RUN: llvm-dwarfdump -debug-names out | FileCheck %s --check-prefix=DWARF
+# RUN: llvm-readelf -SW out | FileCheck %s --check-prefix=READELF
+
+# READELF: Name Type Address Off Size ES Flg Lk Inf Al
+# READELF: .debug_names PROGBITS 00000000 [[#%x,]] 0000cc 00 0 0 4
+
+# DWARF: file format elf32-powerpc
+# DWARF: .debug_names contents:
+# DWARF: Name Index @ 0x0 {
+# DWARF-NEXT: Header {
+# DWARF-NEXT: Length: 0xC8
+# DWARF-NEXT: Format: DWARF32
+# DWARF-NEXT: Version: 5
+# DWARF-NEXT: CU count: 2
+# DWARF-NEXT: Local TU count: 0
+# DWARF-NEXT: Foreign TU count: 0
+# DWARF-NEXT: Bucket count: 5
+# DWARF-NEXT: Name count: 5
+# DWARF-NEXT: Abbreviations table size: 0x1F
+# DWARF-NEXT: Augmentation: 'LLVM0700'
+# DWARF: Compilation Unit offsets [
+# DWARF-NEXT: CU[0]: 0x00000000
+# DWARF-NEXT: CU[1]: 0x0000000c
+# DWARF: Abbreviations [
+# DWARF-NEXT: Abbreviation 0x1 {
+# DWARF: Tag: DW_TAG_structure_type
+# DWARF-NEXT: DW_IDX_die_offset: DW_FORM_ref4
+# DWARF-NEXT: DW_IDX_parent: DW_FORM_flag_present
+# DWARF-NEXT: DW_IDX_compile_unit: DW_FORM_data1
+# DWARF: Abbreviation 0x2 {
+# DWARF-NEXT: Tag: DW_TAG_subprogram
+# DWARF-NEXT: DW_IDX_die_offset: DW_FORM_ref4
+# DWARF-NEXT: DW_IDX_parent: DW_FORM_flag_present
+# DWARF-NEXT: DW_IDX_compile_unit: DW_FORM_data1
+# DWARF: Abbreviation 0x3 {
+# DWARF-NEXT: Tag: DW_TAG_base_type
+# DWARF-NEXT: DW_IDX_die_offset: DW_FORM_ref4
+# DWARF-NEXT: DW_IDX_parent: DW_FORM_flag_present
+# DWARF-NEXT: DW_IDX_compile_unit: DW_FORM_data1
+# DWARF: Bucket 0 [
+# DWARF-NEXT: EMPTY
+# DWARF-NEXT: ]
+# DWARF-NEXT: Bucket 1 [
+# DWARF-NEXT: Name 1 {
+# DWARF-NEXT: Hash: 0x59796A
+# DWARF-NEXT: String: 0x0000008b "t1"
+# DWARF-NEXT: Entry @ 0xaa {
+# DWARF-NEXT: Abbrev: 0x1
+# DWARF-NEXT: Tag: DW_TAG_structure_type
+# DWARF-NEXT: DW_IDX_die_offset: 0x0000003a
+# DWARF-NEXT: DW_IDX_parent: <parent not indexed>
+# DWARF-NEXT: DW_IDX_compile_unit: 0x00
+# DWARF-NEXT: }
+# DWARF-NEXT: Entry @ 0xb0 {
+# DWARF-NEXT: Abbrev: 0x1
+# DWARF-NEXT: Tag: DW_TAG_structure_type
+# DWARF-NEXT: DW_IDX_die_offset: 0x00000042
+# DWARF-NEXT: DW_IDX_parent: <parent not indexed>
+# DWARF-NEXT: DW_IDX_compile_unit: 0x01
+# DWARF-NEXT: }
+# DWARF-NEXT: }
+# DWARF-NEXT: Name 2 {
+# DWARF-NEXT: Hash: 0x5355B2BE
+# DWARF-NEXT: String: 0x00000082 "_Z2f12t1"
+# DWARF-NEXT: Entry @ 0xbe {
+# DWARF-NEXT: Abbrev: 0x2
+# DWARF-NEXT: Tag: DW_TAG_subprogram
+# DWARF-NEXT: DW_IDX_die_offset: 0x00000023
+# DWARF-NEXT: DW_IDX_parent: <parent not indexed>
+# DWARF-NEXT: DW_IDX_compile_unit: 0x00
+# DWARF-NEXT: }
+# DWARF-NEXT: }
+# DWARF-NEXT: Name 3 {
+# DWARF-NEXT: Hash: 0x7C9A7F6A
+# DWARF-NEXT: String: 0x00000111 "main"
+# DWARF-NEXT: Entry @ 0xc5 {
+# DWARF-NEXT: Abbrev: 0x2
+# DWARF-NEXT: Tag: DW_TAG_subprogram
+# DWARF-NEXT: DW_IDX_die_offset: 0x00000023
+# DWARF-NEXT: DW_IDX_parent: <parent not indexed>
+# DWARF-NEXT: DW_IDX_compile_unit: 0x01
+# DWARF-NEXT: }
+# DWARF-NEXT: }
+# DWARF-NEXT: ]
+# DWARF-NEXT: Bucket 2 [
+# DWARF-NEXT: EMPTY
+# DWARF-NEXT: ]
+# DWARF-NEXT: Bucket 3 [
+# DWARF-NEXT: Name 4 {
+# DWARF-NEXT: Hash: 0xB888030
+# DWARF-NEXT: String: 0x00000116 "int"
+# DWARF-NEXT: Entry @ 0xb7 {
+# DWARF-NEXT: Abbrev: 0x3
+# DWARF-NEXT: Tag: DW_TAG_base_type
+# DWARF-NEXT: DW_IDX_die_offset: 0x0000003e
+# DWARF-NEXT: DW_IDX_parent: <parent not indexed>
+# DWARF-NEXT: DW_IDX_compile_unit: 0x01
+# DWARF-NEXT: }
+# DWARF-NEXT: }
+# DWARF-NEXT: ]
+# DWARF-NEXT: Bucket 4 [
+# DWARF-NEXT: Name 5 {
+# DWARF-NEXT: Hash: 0x59779C
+# DWARF-NEXT: String: 0x0000007f "f1"
+# DWARF-NEXT: Entry @ 0xa3 {
+# DWARF-NEXT: Abbrev: 0x2
+# DWARF-NEXT: Tag: DW_TAG_subprogram
+# DWARF-NEXT: DW_IDX_die_offset: 0x00000023
+# DWARF-NEXT: DW_IDX_parent: <parent not indexed>
+# DWARF-NEXT: DW_IDX_compile_unit: 0x00
+# DWARF-NEXT: }
+# DWARF-NEXT: }
+# DWARF-NEXT: ]
+
+#--- a.s
+ .text
+ .globl _Z2f12t1 # -- Begin function _Z2f12t1
+ .p2align 2
+ .type _Z2f12t1, at function
+_Z2f12t1: # @_Z2f12t1
+.Lfunc_begin0:
+ .cfi_startproc
+# %bb.0: # %entry
+ stwu 1, -16(1)
+ stw 31, 12(1)
+ .cfi_def_cfa_offset 16
+ .cfi_offset r31, -4
+ mr 31, 1
+ .cfi_def_cfa_register r31
+.Ltmp0:
+ lwz 31, 12(1)
+ addi 1, 1, 16
+ blr
+.Ltmp1:
+.Lfunc_end0:
+ .size _Z2f12t1, .Lfunc_end0-.Lfunc_begin0
+ .cfi_endproc
+ # -- End function
+ .section .debug_abbrev,"", at progbits
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 0 # EOM(3)
+ .section .debug_info,"", at progbits
+.Lcu_begin0:
+ .long .Ldebug_info_end0-.Ldebug_info_start0 # Length of Unit
+.Ldebug_info_start0:
+ .short 5 # DWARF version number
+ .byte 1 # DWARF Unit Type
+ .byte 4 # Address Size (in bytes)
+ .long .debug_abbrev # Offset Into Abbrev. Section
+.Ldebug_info_end0:
+ .section .debug_str_offsets,"", at progbits
+ .long 28 # Length of String Offsets Set
+ .short 5
+ .short 0
+.Lstr_offsets_base0:
+ .section .debug_str,"MS", at progbits,1
+.Linfo_string0:
+ .asciz "clang version 19.0.0git (git at github.com:llvm/llvm-project.git 53b14cd9ce2b57da73d173fc876d2e9e199f5640)" # string offset=0
+.Linfo_string1:
+ .asciz "a.cpp" # string offset=104
+.Linfo_string2:
+ .asciz "debug-names-test" # string offset=110
+.Linfo_string3:
+ .asciz "f1" # string offset=127
+.Linfo_string4:
+ .asciz "_Z2f12t1" # string offset=130
+.Linfo_string5:
+ .asciz "t1" # string offset=139
+.Laddr_table_base0:
+ .long .Lfunc_begin0
+.Ldebug_addr_end0:
+ .section .debug_names,"", at progbits
+ .long .Lnames_end0-.Lnames_start0 # Header: unit length
+.Lnames_start0:
+ .short 5 # Header: version
+ .short 0 # Header: padding
+ .long 1 # Header: compilation unit count
+ .long 0 # Header: local type unit count
+ .long 0 # Header: foreign type unit count
+ .long 3 # Header: bucket count
+ .long 3 # Header: name count
+ .long .Lnames_abbrev_end0-.Lnames_abbrev_start0 # Header: abbreviation table size
+ .long 8 # Header: augmentation string size
+ .ascii "LLVM0700" # Header: augmentation string
+ .long .Lcu_begin0 # Compilation unit 0
+ .long 0 # Bucket 0
+ .long 1 # Bucket 1
+ .long 3 # Bucket 2
+ .long 5863324 # Hash in Bucket 1
+ .long 5863786 # Hash in Bucket 1
+ .long 1398125246 # Hash in Bucket 2
+ .long .Linfo_string3 # String in Bucket 1: f1
+ .long .Linfo_string5 # String in Bucket 1: t1
+ .long .Linfo_string4 # String in Bucket 2: _Z2f12t1
+ .long .Lnames0-.Lnames_entries0 # Offset in Bucket 1
+ .long .Lnames2-.Lnames_entries0 # Offset in Bucket 1
+ .long .Lnames1-.Lnames_entries0 # Offset in Bucket 2
+.Lnames_abbrev_start0:
+ .byte 1 # Abbrev code
+ .byte 46 # DW_TAG_subprogram
+ .byte 3 # DW_IDX_die_offset
+ .byte 19 # DW_FORM_ref4
+ .byte 4 # DW_IDX_parent
+ .byte 25 # DW_FORM_flag_present
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev
+ .byte 2 # Abbrev code
+ .byte 19 # DW_TAG_structure_type
+ .byte 3 # DW_IDX_die_offset
+ .byte 19 # DW_FORM_ref4
+ .byte 4 # DW_IDX_parent
+ .byte 25 # DW_FORM_flag_present
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev list
+.Lnames_abbrev_end0:
+.Lnames_entries0:
+.Lnames0:
+.L1:
+ .byte 1 # Abbreviation code
+ .long 35 # DW_IDX_die_offset
+ .byte 0 # DW_IDX_parent
+ # End of list: f1
+.Lnames2:
+.L0:
+ .byte 2 # Abbreviation code
+ .long 58 # DW_IDX_die_offset
+ .byte 0 # DW_IDX_parent
+ # End of list: t1
+.Lnames1:
+ .byte 1 # Abbreviation code
+ .long 35 # DW_IDX_die_offset
+ .byte 0 # DW_IDX_parent
+ # End of list: _Z2f12t1
+ .p2align 2, 0x0
+.Lnames_end0:
+ .ident "clang version 19.0.0git (git at github.com:llvm/llvm-project.git 53b14cd9ce2b57da73d173fc876d2e9e199f5640)"
+ .section ".note.GNU-stack","", at progbits
+ .addrsig
+ .section .debug_line,"", at progbits
+.Lline_table_start0:
+
+#--- b.s
+# Generated with:
+# - clang++ --target=powerpc -g -O0 -gpubnames \
+# -fdebug-compilation-dir='debug-names-test' -S b.cpp -o b.s
+
+# b.cpp contents:
+
+# struct t1 { };
+# int main() {
+# t1 v1;
+# }
+#
+ .text
+ .globl main # -- Begin function main
+ .p2align 2
+ .type main, at function
+main: # @main
+.Lfunc_begin0:
+ .cfi_startproc
+# %bb.0: # %entry
+ stwu 1, -16(1)
+ stw 31, 12(1)
+ .cfi_def_cfa_offset 16
+ .cfi_offset r31, -4
+ mr 31, 1
+ .cfi_def_cfa_register r31
+ li 3, 0
+.Ltmp0:
+ lwz 31, 12(1)
+ addi 1, 1, 16
+ blr
+.Ltmp1:
+.Lfunc_end0:
+ .size main, .Lfunc_end0-.Lfunc_begin0
+ .cfi_endproc
+ # -- End function
+ .section .debug_abbrev,"", at progbits
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 0 # EOM(3)
+ .section .debug_info,"", at progbits
+.Lcu_begin0:
+ .long .Ldebug_info_end0-.Ldebug_info_start0 # Length of Unit
+.Ldebug_info_start0:
+ .short 5 # DWARF version number
+ .byte 1 # DWARF Unit Type
+ .byte 4 # Address Size (in bytes)
+ .long .debug_abbrev # Offset Into Abbrev. Section
+.Ldebug_info_end0:
+ .section .debug_str_offsets,"", at progbits
+ .long 32 # Length of String Offsets Set
+ .short 5
+ .short 0
+.Lstr_offsets_base0:
+ .section .debug_str,"MS", at progbits,1
+.Linfo_string0:
+ .asciz "clang version 19.0.0git (git at github.com:llvm/llvm-project.git 53b14cd9ce2b57da73d173fc876d2e9e199f5640)" # string offset=0
+.Linfo_string1:
+ .asciz "b.cpp" # string offset=104
+.Linfo_string2:
+ .asciz "debug-names-test" # string offset=110
+.Linfo_string3:
+ .asciz "main" # string offset=127
+.Linfo_string4:
+ .asciz "int" # string offset=132
+.Linfo_string5:
+ .asciz "v1" # string offset=136
+.Linfo_string6:
+ .asciz "t1" # string offset=139
+.Laddr_table_base0:
+ .long .Lfunc_begin0
+.Ldebug_addr_end0:
+ .section .debug_names,"", at progbits
+ .long .Lnames_end0-.Lnames_start0 # Header: unit length
+.Lnames_start0:
+ .short 5 # Header: version
+ .short 0 # Header: padding
+ .long 1 # Header: compilation unit count
+ .long 0 # Header: local type unit count
+ .long 0 # Header: foreign type unit count
+ .long 3 # Header: bucket count
+ .long 3 # Header: name count
+ .long .Lnames_abbrev_end0-.Lnames_abbrev_start0 # Header: abbreviation table size
+ .long 8 # Header: augmentation string size
+ .ascii "LLVM0700" # Header: augmentation string
+ .long .Lcu_begin0 # Compilation unit 0
+ .long 0 # Bucket 0
+ .long 1 # Bucket 1
+ .long 3 # Bucket 2
+ .long 5863786 # Hash in Bucket 1
+ .long 2090499946 # Hash in Bucket 1
+ .long 193495088 # Hash in Bucket 2
+ .long .Linfo_string6 # String in Bucket 1: t1
+ .long .Linfo_string3 # String in Bucket 1: main
+ .long .Linfo_string4 # String in Bucket 2: int
+ .long .Lnames2-.Lnames_entries0 # Offset in Bucket 1
+ .long .Lnames0-.Lnames_entries0 # Offset in Bucket 1
+ .long .Lnames1-.Lnames_entries0 # Offset in Bucket 2
+.Lnames_abbrev_start0:
+ .byte 1 # Abbrev code
+ .byte 19 # DW_TAG_structure_type
+ .byte 3 # DW_IDX_die_offset
+ .byte 19 # DW_FORM_ref4
+ .byte 4 # DW_IDX_parent
+ .byte 25 # DW_FORM_flag_present
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev
+ .byte 2 # Abbrev code
+ .byte 46 # DW_TAG_subprogram
+ .byte 3 # DW_IDX_die_offset
+ .byte 19 # DW_FORM_ref4
+ .byte 4 # DW_IDX_parent
+ .byte 25 # DW_FORM_flag_present
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev
+ .byte 3 # Abbrev code
+ .byte 36 # DW_TAG_base_type
+ .byte 3 # DW_IDX_die_offset
+ .byte 19 # DW_FORM_ref4
+ .byte 4 # DW_IDX_parent
+ .byte 25 # DW_FORM_flag_present
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev list
+.Lnames_abbrev_end0:
+.Lnames_entries0:
+.Lnames2:
+.L1:
+ .byte 1 # Abbreviation code
+ .long 66 # DW_IDX_die_offset
+ .byte 0 # DW_IDX_parent
+ # End of list: t1
+.Lnames0:
+.L2:
+ .byte 2 # Abbreviation code
+ .long 35 # DW_IDX_die_offset
+ .byte 0 # DW_IDX_parent
+ # End of list: main
+.Lnames1:
+.L0:
+ .byte 3 # Abbreviation code
+ .long 62 # DW_IDX_die_offset
+ .byte 0 # DW_IDX_parent
+ # End of list: int
+ .p2align 2, 0x0
+.Lnames_end0:
+ .ident "clang version 19.0.0git (git at github.com:llvm/llvm-project.git 53b14cd9ce2b57da73d173fc876d2e9e199f5640)"
+ .section ".note.GNU-stack","", at progbits
+ .addrsig
+ .section .debug_line,"", at progbits
+.Lline_table_start0:
>From 8d712883000fef2d21832c1d600e64da4fc19548 Mon Sep 17 00:00:00 2001
From: Caroline Tice <cmtice at google.com>
Date: Sun, 14 Apr 2024 13:37:38 -0700
Subject: [PATCH 18/23] [lld][ELF] Fix clang-format issues.
Fix clang-format issues.
---
lld/ELF/SyntheticSections.cpp | 11 ++++-------
lld/ELF/SyntheticSections.h | 3 +--
2 files changed, 5 insertions(+), 9 deletions(-)
diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp
index 12acbcc9a842ac..910ace1c757b43 100644
--- a/lld/ELF/SyntheticSections.cpp
+++ b/lld/ELF/SyntheticSections.cpp
@@ -2738,9 +2738,7 @@ void DebugNamesBaseSection::parseDebugNames(
InputChunk &inputChunk, OutputChunk &chunk,
DWARFDataExtractor &namesExtractor, DataExtractor &strExtractor,
function_ref<SmallVector<uint32_t, 0>(
- uint32_t numCus,
- uint32_t niOffset,
- const DWARFDebugNames::Header &,
+ uint32_t numCus, uint32_t niOffset, const DWARFDebugNames::Header &,
const DWARFDebugNames::DWARFDebugNamesOffsets &)>
readOffsets) {
const LLDDWARFSection namesSec = inputChunk.section;
@@ -2773,8 +2771,8 @@ void DebugNamesBaseSection::parseDebugNames(
return;
}
- SmallVector<uint32_t, 0> entryOffsets = readOffsets(numCus, niOffset,
- nd.hdr, locs);
+ SmallVector<uint32_t, 0> entryOffsets =
+ readOffsets(numCus, niOffset, nd.hdr, locs);
// Read the entry pool.
offsetMap.clear();
@@ -3167,8 +3165,7 @@ template <class ELFT> DebugNamesSection<ELFT>::DebugNamesSection() {
parseDebugNames(
inputChunk, chunk, namesExtractor, strExtractor,
[&chunk, namesData = dobj.getNamesSection().Data.data()](
- uint32_t numCus,
- uint32_t niOffset,
+ uint32_t numCus, uint32_t niOffset,
const DWARFDebugNames::Header &hdr,
const DWARFDebugNames::DWARFDebugNamesOffsets &locs) {
// Read CU offsets.
diff --git a/lld/ELF/SyntheticSections.h b/lld/ELF/SyntheticSections.h
index f15658e779bc20..534fac005e0b8b 100644
--- a/lld/ELF/SyntheticSections.h
+++ b/lld/ELF/SyntheticSections.h
@@ -872,8 +872,7 @@ class DebugNamesBaseSection : public SyntheticSection {
llvm::DWARFDataExtractor &namesExtractor,
llvm::DataExtractor &strExtractor,
llvm::function_ref<SmallVector<uint32_t, 0>(
- uint32_t numCUs,
- uint32_t niOffset,
+ uint32_t numCUs, uint32_t niOffset,
const llvm::DWARFDebugNames::Header &hdr,
const llvm::DWARFDebugNames::DWARFDebugNamesOffsets &)>
readOffsets);
>From 7607c4d40149128f848055613edf9c3cf9ae890d Mon Sep 17 00:00:00 2001
From: Caroline Tice <cmtice at google.com>
Date: Sun, 14 Apr 2024 16:29:47 -0700
Subject: [PATCH 19/23] [lld][ELF] Clean up file & directory names in tests.
Shorten file names to a.cpp, b.cpp, etc.
Replace debug-names-test directory with /proc/self/cwd.
---
lld/test/ELF/debug-names-bad-aug-string.s | 45 ++++----
lld/test/ELF/debug-names-bad-name-count.s | 18 +--
lld/test/ELF/debug-names-bad-offsets-sizes.s | 25 ++--
lld/test/ELF/debug-names-bad-version.s | 85 ++++----------
lld/test/ELF/debug-names-dwarf64.s | 24 ++--
.../ELF/debug-names-invalid-abbrev-code.s | 23 ++--
.../ELF/debug-names-invalid-attribute-2.s | 23 ++--
.../ELF/debug-names-invalid-attribute-3.s | 23 ++--
lld/test/ELF/debug-names-invalid-attribute.s | 16 +--
lld/test/ELF/debug-names-invalid-parent-idx.s | 25 ++--
lld/test/ELF/debug-names-missing-parent.s | 21 ++--
lld/test/ELF/debug-names-parent-idx.s | 109 +++++++++---------
lld/test/ELF/debug-names.s | 35 +++---
lld/test/ELF/ppc32-debug-names.s | 33 +++---
14 files changed, 233 insertions(+), 272 deletions(-)
diff --git a/lld/test/ELF/debug-names-bad-aug-string.s b/lld/test/ELF/debug-names-bad-aug-string.s
index 1cf81cfef94dfc..62ed64aa5b5703 100644
--- a/lld/test/ELF/debug-names-bad-aug-string.s
+++ b/lld/test/ELF/debug-names-bad-aug-string.s
@@ -3,9 +3,9 @@
# REQUIRES: x86
# RUN: rm -rf %t && split-file %s %t && cd %t
-# RUN: llvm-mc -filetype=obj -triple=x86_64 bad-aug-string.s -o bad-aug-string.o
+# RUN: llvm-mc -filetype=obj -triple=x86_64 a.s -o a.o
# RUN: llvm-mc -filetype=obj -triple=x86_64 b.s -o b.o
-# RUN: ld.lld --debug-names bad-aug-string.o b.o -o out
+# RUN: ld.lld --debug-names a.o b.o -o out
# RUN: llvm-dwarfdump -debug-names out | FileCheck %s --check-prefix=DWARF
# DWARF: .debug_names contents:
@@ -24,8 +24,8 @@
# DWARF: Compilation Unit offsets [
# DWARF-NEXT: CU[0]: 0x00000000
# DWARF-NEXT: CU[1]: 0x0000000c
-
-#--- bad-aug-string.s
+
+#--- a.s
.text
.globl _Z2f12t1 # -- Begin function _Z2f12t1
.p2align 4, 0x90
@@ -68,17 +68,17 @@ _Z2f12t1: # @_Z2f12t1
.Lstr_offsets_base0:
.section .debug_str,"MS", at progbits,1
.Linfo_string0:
- .asciz "clang version 19.0.0git (git at github.com:llvm/llvm-project.git 4df364bc93af49ae413ec1ae8328f34ac70730c4)" # string offset=0
+ .asciz "clang version 19.0.0git (git at github.com:llvm/llvm-project.git 53b14cd9ce2b57da73d173fc876d2e9e199f5640)" # string offset=0
.Linfo_string1:
- .asciz "debug-names.cpp" # string offset=104
+ .asciz "a.cpp" # string offset=104
.Linfo_string2:
- .asciz "debug-names-test" # string offset=120
+ .asciz "/proc/self/cwd" # string offset=110
.Linfo_string3:
- .asciz "f1" # string offset=137
+ .asciz "f1" # string offset=125
.Linfo_string4:
- .asciz "_Z2f12t1" # string offset=140
+ .asciz "_Z2f12t1" # string offset=128
.Linfo_string5:
- .asciz "t1" # string offset=149
+ .asciz "t1" # string offset=137
.Laddr_table_base0:
.quad .Lfunc_begin0
.Ldebug_addr_end0:
@@ -147,19 +147,18 @@ _Z2f12t1: # @_Z2f12t1
# End of list: _Z2f12t1
.p2align 2, 0x0
.Lnames_end0:
- .ident "clang version 19.0.0git (git at github.com:llvm/llvm-project.git 4df364bc93af49ae413ec1ae8328f34ac70730c4)"
+ .ident "clang version 19.0.0git (git at github.com:llvm/llvm-project.git 53b14cd9ce2b57da73d173fc876d2e9e199f5640)"
.section ".note.GNU-stack","", at progbits
.addrsig
.section .debug_line,"", at progbits
.Lline_table_start0:
#--- b.s
-# input file: debug-names-2.cpp
# Generated with:
-# - clang++ -g -O0 -gpubnames -fdebug-compilation-dir='debug-names-test' \
-# -S debug-names-2.cpp -o b.s
+# - clang++ -g -O0 -gpubnames -fdebug-compilation-dir='/proc/self/cwdt' \
+# -S b.cpp -o b.s
-# debug-names-2.cpp contents:
+# b.cpp contents:
# struct t1 { };
# int main() {
@@ -209,19 +208,19 @@ main: # @main
.Lstr_offsets_base0:
.section .debug_str,"MS", at progbits,1
.Linfo_string0:
- .asciz "clang version 19.0.0git (git at github.com:llvm/llvm-project.git 4df364bc93af49ae413ec1ae8328f34ac70730c4)" # string offset=0
+ .asciz "clang version 19.0.0git (git at github.com:llvm/llvm-project.git 53b14cd9ce2b57da73d173fc876d2e9e199f5640)" # string offset=0
.Linfo_string1:
- .asciz "debug-names-2.cpp" # string offset=104
+ .asciz "b.cpp" # string offset=104
.Linfo_string2:
- .asciz "debug-names-test" # string offset=122
+ .asciz "/proc/self/cwd" # string offset=110
.Linfo_string3:
- .asciz "main" # string offset=139
+ .asciz "main" # string offset=125
.Linfo_string4:
- .asciz "int" # string offset=144
+ .asciz "int" # string offset=130
.Linfo_string5:
- .asciz "v1" # string offset=148
+ .asciz "v1" # string offset=134
.Linfo_string6:
- .asciz "t1" # string offset=151
+ .asciz "t1" # string offset=137
.Laddr_table_base0:
.quad .Lfunc_begin0
.Ldebug_addr_end0:
@@ -299,7 +298,7 @@ main: # @main
# End of list: int
.p2align 2, 0x0
.Lnames_end0:
- .ident "clang version 19.0.0git (git at github.com:llvm/llvm-project.git 4df364bc93af49ae413ec1ae8328f34ac70730c4)"
+ .ident "clang version 19.0.0git (git at github.com:llvm/llvm-project.git 53b14cd9ce2b57da73d173fc876d2e9e199f5640)"
.section ".note.GNU-stack","", at progbits
.addrsig
.section .debug_line,"", at progbits
diff --git a/lld/test/ELF/debug-names-bad-name-count.s b/lld/test/ELF/debug-names-bad-name-count.s
index f660bc0512cc6f..11a418177e1c16 100644
--- a/lld/test/ELF/debug-names-bad-name-count.s
+++ b/lld/test/ELF/debug-names-bad-name-count.s
@@ -71,21 +71,21 @@ main: # @main
.Lstr_offsets_base0:
.section .debug_str,"MS", at progbits,1
.Linfo_string0:
- .asciz "clang version 19.0.0git (git at github.com:llvm/llvm-project.git d33d5630b281debe6eabd67e323bcf767340fb6a)" # string offset=0
+ .asciz "clang version 19.0.0git (git at github.com:llvm/llvm-project.git 53b14cd9ce2b57da73d173fc876d2e9e199f5640)" # string offset=0
.Linfo_string1:
- .asciz "main.cpp" # string offset=104
+ .asciz "a.cpp" # string offset=104
.Linfo_string2:
- .asciz "debug-names-test" # string offset=113
+ .asciz "/proc/self/cwd" # string offset=110
.Linfo_string3:
- .asciz "main" # string offset=130
+ .asciz "main" # string offset=125
.Linfo_string4:
- .asciz "int" # string offset=135
+ .asciz "int" # string offset=130
.Linfo_string5:
- .asciz "argc" # string offset=139
+ .asciz "argc" # string offset=134
.Linfo_string6:
- .asciz "argv" # string offset=144
+ .asciz "argv" # string offset=139
.Linfo_string7:
- .asciz "char" # string offset=149
+ .asciz "char" # string offset=144
.Laddr_table_base0:
.quad .Lfunc_begin0
.Ldebug_addr_end0:
@@ -155,7 +155,7 @@ main: # @main
# End of list: char
.p2align 2, 0x0
.Lnames_end0:
- .ident "clang version 19.0.0git (git at github.com:llvm/llvm-project.git d33d5630b281debe6eabd67e323bcf767340fb6a)"
+ .ident "clang version 19.0.0git (git at github.com:llvm/llvm-project.git 53b14cd9ce2b57da73d173fc876d2e9e199f5640)"
.section ".note.GNU-stack","", at progbits
.addrsig
.section .debug_line,"", at progbits
diff --git a/lld/test/ELF/debug-names-bad-offsets-sizes.s b/lld/test/ELF/debug-names-bad-offsets-sizes.s
index e5b4570b216513..e70a6215f3c874 100644
--- a/lld/test/ELF/debug-names-bad-offsets-sizes.s
+++ b/lld/test/ELF/debug-names-bad-offsets-sizes.s
@@ -1,11 +1,10 @@
-# This file was generated by first compiling main.cpp:
-# clang++ -g -O0 -S -gpubnames -fdebug-compilation-dir='debug-names-test' \
-# main.cpp
+# This file was generated by first compiling a.cpp:
+# clang++ -g -O0 -S -gpubnames -fdebug-compilation-dir='/proc/self/cwd' a.cpp
# Then manually edit .debug_names section. Change the sizes of
# 'Offset in Bucket' values from '.long' to '.byte'.
-# Contentsof main.cpp:
+# Contents of a.cpp:
# int main (int argc, char **argv) { }
# REQUIRES: x86
@@ -63,21 +62,21 @@ main: # @main
.Lstr_offsets_base0:
.section .debug_str,"MS", at progbits,1
.Linfo_string0:
- .asciz "clang version 19.0.0git (git at github.com:llvm/llvm-project.git d33d5630b281debe6eabd67e323bcf767340fb6a)" # string offset=0
+ .asciz "clang version 19.0.0git (git at github.com:llvm/llvm-project.git 53b14cd9ce2b57da73d173fc876d2e9e199f5640)" # string offset=0
.Linfo_string1:
- .asciz "main.cpp" # string offset=104
+ .asciz "a.cpp" # string offset=104
.Linfo_string2:
- .asciz "debug-names-test" # string offset=113
+ .asciz "/proc/self/cwd" # string offset=110
.Linfo_string3:
- .asciz "main" # string offset=130
+ .asciz "main" # string offset=125
.Linfo_string4:
- .asciz "int" # string offset=135
+ .asciz "int" # string offset=130
.Linfo_string5:
- .asciz "argc" # string offset=139
+ .asciz "argc" # string offset=134
.Linfo_string6:
- .asciz "argv" # string offset=144
+ .asciz "argv" # string offset=139
.Linfo_string7:
- .asciz "char" # string offset=149
+ .asciz "char" # string offset=144
.Laddr_table_base0:
.quad .Lfunc_begin0
.Ldebug_addr_end0:
@@ -147,7 +146,7 @@ main: # @main
# End of list: char
.p2align 2, 0x0
.Lnames_end0:
- .ident "clang version 19.0.0git (git at github.com:llvm/llvm-project.git d33d5630b281debe6eabd67e323bcf767340fb6a)"
+ .ident "clang version 19.0.0git (git at github.com:llvm/llvm-project.git 53b14cd9ce2b57da73d173fc876d2e9e199f5640)"
.section ".note.GNU-stack","", at progbits
.addrsig
.section .debug_line,"", at progbits
diff --git a/lld/test/ELF/debug-names-bad-version.s b/lld/test/ELF/debug-names-bad-version.s
index ac7d6853bfa623..6f6ff2d507a9b2 100644
--- a/lld/test/ELF/debug-names-bad-version.s
+++ b/lld/test/ELF/debug-names-bad-version.s
@@ -4,13 +4,14 @@
# REQUIRES: x86
# RUN: rm -rf %t && split-file %s %t && cd %t
-# RUN: llvm-mc -filetype=obj -triple=x86_64 bad-version.s -o bad-version.o
+# RUN: llvm-mc -filetype=obj -triple=x86_64 a.s -o a.o
# RUN: llvm-mc -filetype=obj -triple=x86_64 b.s -o b.o
-# RUN: not ld.lld --debug-names bad-version.o b.o 2>&1 | FileCheck %s --implicit-check-not=error:
+# RUN: not ld.lld --debug-names a.o b.o 2>&1 \
+# RUN: | FileCheck -DFILE=a.o %s --implicit-check-not=error:
-# CHECK: error: bad-version.o:(.debug_names): unsupported version 4
-
-#--- bad-version.s
+# CHECK: error: [[FILE]]:(.debug_names): unsupported version 4
+
+#--- a.s
.text
.globl _Z2f12t1 # -- Begin function _Z2f12t1
.p2align 4, 0x90
@@ -45,41 +46,6 @@ _Z2f12t1: # @_Z2f12t1
.byte 1 # DWARF Unit Type
.byte 8 # Address Size (in bytes)
.long .debug_abbrev # Offset Into Abbrev. Section
- .byte 1 # Abbrev [1] 0xc:0x35 DW_TAG_compile_unit
- .byte 0 # DW_AT_producer
- .short 33 # DW_AT_language
- .byte 1 # DW_AT_name
- .long .Lstr_offsets_base0 # DW_AT_str_offsets_base
- .long .Lline_table_start0 # DW_AT_stmt_list
- .byte 2 # DW_AT_comp_dir
- .byte 0 # DW_AT_low_pc
- .long .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc
- .long .Laddr_table_base0 # DW_AT_addr_base
- .byte 2 # Abbrev [2] 0x23:0x17 DW_TAG_subprogram
- .byte 0 # DW_AT_low_pc
- .long .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc
- .byte 1 # DW_AT_frame_base
- .byte 86
- .byte 3 # DW_AT_linkage_name
- .byte 4 # DW_AT_name
- .byte 0 # DW_AT_decl_file
- .byte 2 # DW_AT_decl_line
- # DW_AT_external
- .byte 3 # Abbrev [3] 0x2f:0xa DW_TAG_formal_parameter
- .byte 2 # DW_AT_location
- .byte 145
- .byte 127
- .byte 0 # DW_AT_decl_file
- .byte 2 # DW_AT_decl_line
- .long 58 # DW_AT_type
- .byte 0 # End Of Children Mark
- .byte 4 # Abbrev [4] 0x3a:0x6 DW_TAG_structure_type
- .byte 5 # DW_AT_calling_convention
- .byte 5 # DW_AT_name
- .byte 1 # DW_AT_byte_size
- .byte 0 # DW_AT_decl_file
- .byte 1 # DW_AT_decl_line
- .byte 0 # End Of Children Mark
.Ldebug_info_end0:
.section .debug_str_offsets,"", at progbits
.long 28 # Length of String Offsets Set
@@ -88,17 +54,17 @@ _Z2f12t1: # @_Z2f12t1
.Lstr_offsets_base0:
.section .debug_str,"MS", at progbits,1
.Linfo_string0:
- .asciz "clang version 19.0.0git (git at github.com:llvm/llvm-project.git 4df364bc93af49ae413ec1ae8328f34ac70730c4)" # string offset=0
+ .asciz "clang version 19.0.0git (git at github.com:llvm/llvm-project.git 53b14cd9ce2b57da73d173fc876d2e9e199f5640)" # string offset=0
.Linfo_string1:
- .asciz "debug-names.cpp" # string offset=104
+ .asciz "a.cpp" # string offset=104
.Linfo_string2:
- .asciz "debug-names-test" # string offset=120
+ .asciz "/proc/self/cwd" # string offset=110
.Linfo_string3:
- .asciz "f1" # string offset=137
+ .asciz "f1" # string offset=125
.Linfo_string4:
- .asciz "_Z2f12t1" # string offset=140
+ .asciz "_Z2f12t1" # string offset=128
.Linfo_string5:
- .asciz "t1" # string offset=149
+ .asciz "t1" # string offset=137
.Laddr_table_base0:
.quad .Lfunc_begin0
.Ldebug_addr_end0:
@@ -167,19 +133,18 @@ _Z2f12t1: # @_Z2f12t1
# End of list: _Z2f12t1
.p2align 2, 0x0
.Lnames_end0:
- .ident "clang version 19.0.0git (git at github.com:llvm/llvm-project.git 4df364bc93af49ae413ec1ae8328f34ac70730c4)"
+ .ident "clang version 19.0.0git (git at github.com:llvm/llvm-project.git 53b14cd9ce2b57da73d173fc876d2e9e199f5640)"
.section ".note.GNU-stack","", at progbits
.addrsig
.section .debug_line,"", at progbits
.Lline_table_start0:
#--- b.s
-# input file: debug-names-2.cpp
# Generated with:
-# - clang++ -g -O0 -gpubnames -fdebug-compilation-dir='debug-names-test' \
-# -S debug-names-2.cpp -o b.s
+# - clang++ -g -O0 -gpubnames -fdebug-compilation-dir='/proc/self/cwd' \
+# -S b.cpp -o b.s
-# debug-names-2.cpp contents:
+# b.cpp contents:
# struct t1 { };
# int main() {
@@ -217,7 +182,7 @@ main: # @main
.Lcu_begin0:
.long .Ldebug_info_end0-.Ldebug_info_start0 # Length of Unit
.Ldebug_info_start0:
- .short 5 # DWARF version number
+ .short 4 # DWARF version number
.byte 1 # DWARF Unit Type
.byte 8 # Address Size (in bytes)
.long .debug_abbrev # Offset Into Abbrev. Section
@@ -229,19 +194,19 @@ main: # @main
.Lstr_offsets_base0:
.section .debug_str,"MS", at progbits,1
.Linfo_string0:
- .asciz "clang version 19.0.0git (git at github.com:llvm/llvm-project.git 4df364bc93af49ae413ec1ae8328f34ac70730c4)" # string offset=0
+ .asciz "clang version 19.0.0git (git at github.com:llvm/llvm-project.git 53b14cd9ce2b57da73d173fc876d2e9e199f5640)" # string offset=0
.Linfo_string1:
- .asciz "debug-names-2.cpp" # string offset=104
+ .asciz "b.cpp" # string offset=104
.Linfo_string2:
- .asciz "debug-names-test" # string offset=122
+ .asciz "/proc/self/cwd" # string offset=110
.Linfo_string3:
- .asciz "main" # string offset=139
+ .asciz "main" # string offset=125
.Linfo_string4:
- .asciz "int" # string offset=144
+ .asciz "int" # string offset=130
.Linfo_string5:
- .asciz "v1" # string offset=148
+ .asciz "v1" # string offset=134
.Linfo_string6:
- .asciz "t1" # string offset=151
+ .asciz "t1" # string offset=137
.Laddr_table_base0:
.quad .Lfunc_begin0
.Ldebug_addr_end0:
@@ -319,7 +284,7 @@ main: # @main
# End of list: int
.p2align 2, 0x0
.Lnames_end0:
- .ident "clang version 19.0.0git (git at github.com:llvm/llvm-project.git 4df364bc93af49ae413ec1ae8328f34ac70730c4)"
+ .ident "clang version 19.0.0git (git at github.com:llvm/llvm-project.git 53b14cd9ce2b57da73d173fc876d2e9e199f5640)"
.section ".note.GNU-stack","", at progbits
.addrsig
.section .debug_line,"", at progbits
diff --git a/lld/test/ELF/debug-names-dwarf64.s b/lld/test/ELF/debug-names-dwarf64.s
index 515ea67945e616..310e9379bf9aed 100644
--- a/lld/test/ELF/debug-names-dwarf64.s
+++ b/lld/test/ELF/debug-names-dwarf64.s
@@ -1,8 +1,8 @@
# This file was generated by:
-# clang++ -g -O0 -S -fdebug-compilation-dir='debug-names-test' \
-# -gdwarf64 -gpubnames main.cpp
+# clang++ -g -O0 -S -fdebug-compilation-dir='/proc/self/cwd' \
+# -gdwarf64 -gpubnames a.cpp
-# Contents of main.cpp
+# Contents of a.cpp
# int main (int argc, char **argv) { }
# REQUIRES: x86
@@ -59,21 +59,21 @@ main: # @main
.Lstr_offsets_base0:
.section .debug_str,"MS", at progbits,1
.Linfo_string0:
- .asciz "clang version 19.0.0git (git at github.com:llvm/llvm-project.git 9b37e60051f362e8e22c88785239fd5dfbfdf105)" # string offset=0
+ .asciz "clang version 19.0.0git (git at github.com:llvm/llvm-project.git 53b14cd9ce2b57da73d173fc876d2e9e199f5640)" # string offset=0
.Linfo_string1:
- .asciz "main.cpp" # string offset=104
+ .asciz "a.cpp" # string offset=104
.Linfo_string2:
- .asciz "debug-names-test" # string offset=113
+ .asciz "/proc/self/cwd" # string offset=110
.Linfo_string3:
- .asciz "main" # string offset=130
+ .asciz "main" # string offset=125
.Linfo_string4:
- .asciz "int" # string offset=135
+ .asciz "int" # string offset=130
.Linfo_string5:
- .asciz "argc" # string offset=139
+ .asciz "argc" # string offset=134
.Linfo_string6:
- .asciz "argv" # string offset=144
+ .asciz "argv" # string offset=139
.Linfo_string7:
- .asciz "char" # string offset=149
+ .asciz "char" # string offset=144
.Laddr_table_base0:
.quad .Lfunc_begin0
.Ldebug_addr_end0:
@@ -144,7 +144,7 @@ main: # @main
# End of list: char
.p2align 2, 0x0
.Lnames_end0:
- .ident "clang version 19.0.0git (git at github.com:llvm/llvm-project.git 9b37e60051f362e8e22c88785239fd5dfbfdf105)"
+ .ident "clang version 19.0.0git (git at github.com:llvm/llvm-project.git 53b14cd9ce2b57da73d173fc876d2e9e199f5640)"
.section ".note.GNU-stack","", at progbits
.addrsig
.section .debug_line,"", at progbits
diff --git a/lld/test/ELF/debug-names-invalid-abbrev-code.s b/lld/test/ELF/debug-names-invalid-abbrev-code.s
index 65d7f50f02d372..5290eb86e276d2 100644
--- a/lld/test/ELF/debug-names-invalid-abbrev-code.s
+++ b/lld/test/ELF/debug-names-invalid-abbrev-code.s
@@ -1,10 +1,9 @@
# This file was generated by:
-# clang++ -g -O0 -S -fdebug-compilation-dir='debug-names-test' \
-# -gpubnames main.cpp
+# clang++ -g -O0 -S -fdebug-compilation-dir='/proc/self/cwd' -gpubnames a.cpp
# Then manually changing an abbrev code.
-# Contents of main.cpp
+# Contents of a.cpp
# int main (int argc, char **argv) { }
# REQUIRES: x86
@@ -59,21 +58,21 @@ main: # @main
.Lstr_offsets_base0:
.section .debug_str,"MS", at progbits,1
.Linfo_string0:
- .asciz "clang version 19.0.0git (git at github.com:llvm/llvm-project.git d33d5630b281debe6eabd67e323bcf767340fb6a)" # string offset=0
+ .asciz "clang version 19.0.0git (git at github.com:llvm/llvm-project.git 53b14cd9ce2b57da73d173fc876d2e9e199f5640)" # string offset=0
.Linfo_string1:
- .asciz "main.cpp" # string offset=104
+ .asciz "a.cpp" # string offset=104
.Linfo_string2:
- .asciz "debug-names-test" # string offset=113
+ .asciz "/proc/self/cwd" # string offset=110
.Linfo_string3:
- .asciz "main" # string offset=130
+ .asciz "main" # string offset=125
.Linfo_string4:
- .asciz "int" # string offset=135
+ .asciz "int" # string offset=130
.Linfo_string5:
- .asciz "argc" # string offset=139
+ .asciz "argc" # string offset=134
.Linfo_string6:
- .asciz "argv" # string offset=144
+ .asciz "argv" # string offset=139
.Linfo_string7:
- .asciz "char" # string offset=149
+ .asciz "char" # string offset=144
.Laddr_table_base0:
.quad .Lfunc_begin0
.Ldebug_addr_end0:
@@ -143,7 +142,7 @@ main: # @main
# End of list: char
.p2align 2, 0x0
.Lnames_end0:
- .ident "clang version 19.0.0git (git at github.com:llvm/llvm-project.git d33d5630b281debe6eabd67e323bcf767340fb6a)"
+ .ident "clang version 19.0.0git (git at github.com:llvm/llvm-project.git 53b14cd9ce2b57da73d173fc876d2e9e199f5640)"
.section ".note.GNU-stack","", at progbits
.addrsig
.section .debug_line,"", at progbits
diff --git a/lld/test/ELF/debug-names-invalid-attribute-2.s b/lld/test/ELF/debug-names-invalid-attribute-2.s
index fbed524ef29f83..6ea8c5e1e3f693 100644
--- a/lld/test/ELF/debug-names-invalid-attribute-2.s
+++ b/lld/test/ELF/debug-names-invalid-attribute-2.s
@@ -1,11 +1,10 @@
# This file was generated by:
-# clang++ -g -O0 -S -fdebug-compilation-dir='debug-names-test' \
-# -gpubnames main.cpp
+# clang++ -g -O0 -S -fdebug-compilation-dir='/proc/self/cwd' -gpubnames a.cpp
# Then manually editing .debug_names section, commenting out a
# DW_IDX_die_offset in an entry.
-# Contents of main.cpp
+# Contents of a.cpp
# int main (int argc, char **argv) { }
# REQUIRES: x86
@@ -60,21 +59,21 @@ main: # @main
.Lstr_offsets_base0:
.section .debug_str,"MS", at progbits,1
.Linfo_string0:
- .asciz "clang version 19.0.0git (git at github.com:llvm/llvm-project.git d33d5630b281debe6eabd67e323bcf767340fb6a)" # string offset=0
+ .asciz "clang version 19.0.0git (git at github.com:llvm/llvm-project.git 53b14cd9ce2b57da73d173fc876d2e9e199f5640)" # string offset=0
.Linfo_string1:
- .asciz "main.cpp" # string offset=104
+ .asciz "a.cpp" # string offset=104
.Linfo_string2:
- .asciz "debug-names-test" # string offset=113
+ .asciz "/proc/self/cwd" # string offset=110
.Linfo_string3:
- .asciz "main" # string offset=130
+ .asciz "main" # string offset=125
.Linfo_string4:
- .asciz "int" # string offset=135
+ .asciz "int" # string offset=130
.Linfo_string5:
- .asciz "argc" # string offset=139
+ .asciz "argc" # string offset=134
.Linfo_string6:
- .asciz "argv" # string offset=144
+ .asciz "argv" # string offset=139
.Linfo_string7:
- .asciz "char" # string offset=149
+ .asciz "char" # string offset=144
.Laddr_table_base0:
.quad .Lfunc_begin0
.Ldebug_addr_end0:
@@ -143,7 +142,7 @@ main: # @main
# End of list: char
.p2align 2, 0x0
.Lnames_end0:
- .ident "clang version 19.0.0git (git at github.com:llvm/llvm-project.git d33d5630b281debe6eabd67e323bcf767340fb6a)"
+ .ident "clang version 19.0.0git (git at github.com:llvm/llvm-project.git 53b14cd9ce2b57da73d173fc876d2e9e199f5640)"
.section ".note.GNU-stack","", at progbits
.addrsig
.section .debug_line,"", at progbits
diff --git a/lld/test/ELF/debug-names-invalid-attribute-3.s b/lld/test/ELF/debug-names-invalid-attribute-3.s
index 465f0a92064b4c..1674498df7e30f 100644
--- a/lld/test/ELF/debug-names-invalid-attribute-3.s
+++ b/lld/test/ELF/debug-names-invalid-attribute-3.s
@@ -1,13 +1,12 @@
# This file was generated by:
-# clang++ -g -O0 -S -fdebug-compilation-dir='debug-names-test' \
-# -gpubnames main.cpp
+# clang++ -g -O0 -S -fdebug-compilation-dir='/proc/self/cwd' -gpubnames a.cpp
# Then manually changing the first .debug_names abbrev, so that the
# DW_IDX_die_offset uses DW_FORM_flag_present (invalid) & the DW_IDX_parent
# uses DW_FORM_ref4. Also updated the sizes of the values in the entry
# that uses the abbrev, to match the sizes of the forms.
-# Contents of main.cpp
+# Contents of a.cpp
# int main (int argc, char **argv) { }
# REQUIRES: x86
@@ -62,21 +61,21 @@ main: # @main
.Lstr_offsets_base0:
.section .debug_str,"MS", at progbits,1
.Linfo_string0:
- .asciz "clang version 19.0.0git (git at github.com:llvm/llvm-project.git d33d5630b281debe6eabd67e323bcf767340fb6a)" # string offset=0
+ .asciz "clang version 19.0.0git (git at github.com:llvm/llvm-project.git 53b14cd9ce2b57da73d173fc876d2e9e199f5640)" # string offset=0
.Linfo_string1:
- .asciz "main.cpp" # string offset=104
+ .asciz "a.cpp" # string offset=104
.Linfo_string2:
- .asciz "debug-names-test" # string offset=113
+ .asciz "/proc/self/cwd" # string offset=110
.Linfo_string3:
- .asciz "main" # string offset=130
+ .asciz "main" # string offset=125
.Linfo_string4:
- .asciz "int" # string offset=135
+ .asciz "int" # string offset=130
.Linfo_string5:
- .asciz "argc" # string offset=139
+ .asciz "argc" # string offset=134
.Linfo_string6:
- .asciz "argv" # string offset=144
+ .asciz "argv" # string offset=139
.Linfo_string7:
- .asciz "char" # string offset=149
+ .asciz "char" # string offset=144
.Laddr_table_base0:
.quad .Lfunc_begin0
.Ldebug_addr_end0:
@@ -146,7 +145,7 @@ main: # @main
# End of list: char
.p2align 2, 0x0
.Lnames_end0:
- .ident "clang version 19.0.0git (git at github.com:llvm/llvm-project.git d33d5630b281debe6eabd67e323bcf767340fb6a)"
+ .ident "clang version 19.0.0git (git at github.com:llvm/llvm-project.git 53b14cd9ce2b57da73d173fc876d2e9e199f5640)"
.section ".note.GNU-stack","", at progbits
.addrsig
.section .debug_line,"", at progbits
diff --git a/lld/test/ELF/debug-names-invalid-attribute.s b/lld/test/ELF/debug-names-invalid-attribute.s
index 19de19c313bcfe..52b9c6f7ade95e 100644
--- a/lld/test/ELF/debug-names-invalid-attribute.s
+++ b/lld/test/ELF/debug-names-invalid-attribute.s
@@ -1,4 +1,4 @@
-# Generated by copying debug-names.s and manually editing it to make some
+# Generated by copying a.s from debug-names.s and manually editing it to make some
# of the abbrev attributes invalid.
# REQUIRES: x86
@@ -50,17 +50,17 @@ _Z2f12t1: # @_Z2f12t1
.Lstr_offsets_base0:
.section .debug_str,"MS", at progbits,1
.Linfo_string0:
- .asciz "clang version 19.0.0git (git at github.com:llvm/llvm-project.git 4df364bc93af49ae413ec1ae8328f34ac70730c4)" # string offset=0
+ .asciz "clang version 19.0.0git (git at github.com:llvm/llvm-project.git 53b14cd9ce2b57da73d173fc876d2e9e199f5640)" # string offset=0
.Linfo_string1:
- .asciz "debug-names.cpp" # string offset=104
+ .asciz "a.cpp" # string offset=104
.Linfo_string2:
- .asciz "debug-names-test" # string offset=120
+ .asciz "/proc/self/cwd" # string offset=110
.Linfo_string3:
- .asciz "f1" # string offset=137
+ .asciz "f1" # string offset=125
.Linfo_string4:
- .asciz "_Z2f12t1" # string offset=140
+ .asciz "_Z2f12t1" # string offset=128
.Linfo_string5:
- .asciz "t1" # string offset=149
+ .asciz "t1" # string offset=137
.Laddr_table_base0:
.quad .Lfunc_begin0
.Ldebug_addr_end0:
@@ -137,7 +137,7 @@ _Z2f12t1: # @_Z2f12t1
# End of list: _Z2f12t1
.p2align 2, 0x0
.Lnames_end0:
- .ident "clang version 19.0.0git (git at github.com:llvm/llvm-project.git 4df364bc93af49ae413ec1ae8328f34ac70730c4)"
+ .ident "clang version 19.0.0git (git at github.com:llvm/llvm-project.git 53b14cd9ce2b57da73d173fc876d2e9e199f5640)"
.section ".note.GNU-stack","", at progbits
.addrsig
.section .debug_line,"", at progbits
diff --git a/lld/test/ELF/debug-names-invalid-parent-idx.s b/lld/test/ELF/debug-names-invalid-parent-idx.s
index 01e62fb99586a2..5db11ee10b32ea 100644
--- a/lld/test/ELF/debug-names-invalid-parent-idx.s
+++ b/lld/test/ELF/debug-names-invalid-parent-idx.s
@@ -1,11 +1,11 @@
# This file was generated by:
-# clang++ -g -O0 -S -fdebug-compilation-dir='debug-names-test' \
-# -gpubnames main.cpp
+# clang++ -g -O0 -S -fdebug-compilation-dir='/proc/self/cwd' \
+# -gpubnames a.cpp
# Then manually editing .debug_names section, changing the form for a
# DW_IDX_parent from DW_FORM_flag_present to DW_FORM_ref1 (invalid).
-# Contents of main.cpp
+# Contents of a.cpp
# int main (int argc, char **argv) { }
# REQUIRES: x86
@@ -22,6 +22,7 @@
.type main, at function
main: # @main
.Lfunc_begin0:
+ .file 0 "/proc/self/cwd" "a.cpp" md5 0xb5f4ba9cf33ca376f9981b3284aa785f
.cfi_startproc
# %bb.0: # %entry
pushq %rbp
@@ -61,21 +62,21 @@ main: # @main
.Lstr_offsets_base0:
.section .debug_str,"MS", at progbits,1
.Linfo_string0:
- .asciz "clang version 19.0.0git (git at github.com:llvm/llvm-project.git d33d5630b281debe6eabd67e323bcf767340fb6a)" # string offset=0
+ .asciz "clang version 19.0.0git (git at github.com:llvm/llvm-project.git 53b14cd9ce2b57da73d173fc876d2e9e199f5640)" # string offset=0
.Linfo_string1:
- .asciz "main.cpp" # string offset=104
+ .asciz "a.cpp" # string offset=104
.Linfo_string2:
- .asciz "debug-names-test" # string offset=113
+ .asciz "/proc/self/cwd" # string offset=110
.Linfo_string3:
- .asciz "main" # string offset=130
+ .asciz "main" # string offset=125
.Linfo_string4:
- .asciz "int" # string offset=135
+ .asciz "int" # string offset=130
.Linfo_string5:
- .asciz "argc" # string offset=139
+ .asciz "argc" # string offset=134
.Linfo_string6:
- .asciz "argv" # string offset=144
+ .asciz "argv" # string offset=139
.Linfo_string7:
- .asciz "char" # string offset=149
+ .asciz "char" # string offset=144
.Laddr_table_base0:
.quad .Lfunc_begin0
.Ldebug_addr_end0:
@@ -145,7 +146,7 @@ main: # @main
# End of list: char
.p2align 2, 0x0
.Lnames_end0:
- .ident "clang version 19.0.0git (git at github.com:llvm/llvm-project.git d33d5630b281debe6eabd67e323bcf767340fb6a)"
+ .ident "clang version 19.0.0git (git at github.com:llvm/llvm-project.git 53b14cd9ce2b57da73d173fc876d2e9e199f5640)"
.section ".note.GNU-stack","", at progbits
.addrsig
.section .debug_line,"", at progbits
diff --git a/lld/test/ELF/debug-names-missing-parent.s b/lld/test/ELF/debug-names-missing-parent.s
index 5c7e0ad839a00e..480d047504934a 100644
--- a/lld/test/ELF/debug-names-missing-parent.s
+++ b/lld/test/ELF/debug-names-missing-parent.s
@@ -1,6 +1,6 @@
# debug-names-missing-parent was generated with
-# clang++ -g -O0 -S -fdebug-compilation-dir='debug-names-test' \
+# clang++ -g -O0 -S -fdebug-compilation-dir='/proc/self/cwd' \
# -gpubnames a.cpp
# a.cpp contents:
@@ -47,7 +47,7 @@
# DWARF-NEXT: Bucket 1 [
# DWARF-NEXT: Name 1 {
# DWARF-NEXT: Hash: 0x7C9A7F6A
-# DWARF-NEXT: String: 0x0000007f "main"
+# DWARF-NEXT: String: 0x0000007d "main"
# DWARF-NEXT: Entry @ 0x7a {
# DWARF-NEXT: Abbrev: 0x2
# DWARF-NEXT: Tag: DW_TAG_subprogram
@@ -66,7 +66,7 @@
# DWARF-NEXT: Bucket 2 [
# DWARF-NEXT: Name 2 {
# DWARF-NEXT: Hash: 0xB888030
-# DWARF-NEXT: String: 0x00000084 "int"
+# DWARF-NEXT: String: 0x00000082 "int"
# DWARF-NEXT: Entry @ 0x73 {
# DWARF-NEXT: Abbrev: 0x1
# DWARF-NEXT: Tag: DW_TAG_base_type
@@ -77,7 +77,7 @@
# DWARF-NEXT: }
# DWARF-NEXT: Name 3 {
# DWARF-NEXT: Hash: 0x7C952063
-# DWARF-NEXT: String: 0x00000092 "char"
+# DWARF-NEXT: String: 0x0000008b "char"
# DWARF-NEXT: Entry @ 0x87 {
# DWARF-NEXT: Abbrev: 0x1
# DWARF-NEXT: Tag: DW_TAG_base_type
@@ -139,17 +139,18 @@ main: # @main
.Linfo_string1:
.asciz "a.cpp" # string offset=104
.Linfo_string2:
- .asciz "debug-names-test" # string offset=110
+ .asciz "/proc/self/cwd" # string offset=110
.Linfo_string3:
- .asciz "main" # string offset=127
+ .asciz "main" # string offset=125
.Linfo_string4:
- .asciz "int" # string offset=132
+ .asciz "int" # string offset=130
.Linfo_string5:
- .asciz "argc" # string offset=136
+ .asciz "argc" # string offset=134
.Linfo_string6:
- .asciz "argv" # string offset=141
+ .asciz "argv" # string offset=139
.Linfo_string7:
- .asciz "char" # string offset=146
+ .asciz "char" # string offset=144
+ .section .debug_str_offsets,"", at progbits
.Laddr_table_base0:
.quad .Lfunc_begin0
.Ldebug_addr_end0:
diff --git a/lld/test/ELF/debug-names-parent-idx.s b/lld/test/ELF/debug-names-parent-idx.s
index 22e382e45c9a10..64551aa02e59f5 100644
--- a/lld/test/ELF/debug-names-parent-idx.s
+++ b/lld/test/ELF/debug-names-parent-idx.s
@@ -1,7 +1,7 @@
# debug-names-parent-idx.s generated with:
-# - clang++ -g -O0 -gpubnames -fdebug-compilation-dir='parent-idx-test' \
-# -S debug-names-parent-idx.cpp -o debug-names-parent-idx.s
+# clang++ -g -O0 -gpubnames -fdebug-compilation-dir='/proc/self/cwd' -S \
+# a.cpp -o a.s
# foo.h contents:
@@ -17,7 +17,7 @@
# int foo();
# }
-# debug-names-parent-idx.cpp contents:
+# a.cpp contents:
# #include "foo.h"
# void bar (struct foo &foo, int junk) {
@@ -36,14 +36,11 @@
# REQUIRES: x86
# RUN: rm -rf %t && split-file %s %t && cd %t
-# RUN: llvm-mc -filetype=obj -triple=x86_64 debug-names-parent-idx.s \
-# RUN: -o debug-names-parent-idx.o
-# RUN: llvm-mc -filetype=obj -triple=x86_64 debug-names-parent-idx-2.s \
-# RUN: -o debug-names-parent-idx-2.o
-# RUN: ld.lld --debug-names debug-names-parent-idx.o \
-# RUN: debug-names-parent-idx-2.o -o debug-names-parent-idx
+# RUN: llvm-mc -filetype=obj -triple=x86_64 a.s -o a.o
+# RUN: llvm-mc -filetype=obj -triple=x86_64 b.s -o b.o
+# RUN: ld.lld --debug-names a.o b.o -o out
-# RUN: llvm-dwarfdump -debug-names debug-names-parent-idx | FileCheck %s --check-prefix=DWARF
+# RUN: llvm-dwarfdump -debug-names out | FileCheck %s --check-prefix=DWARF
# DWARF: .debug_names contents:
# DWARF: Name Index @ 0x0 {
@@ -93,7 +90,7 @@
# DWARF-NEXT: Bucket 1 [
# DWARF-NEXT: Name 1 {
# DWARF-NEXT: Hash: 0xA974AA29
-# DWARF-NEXT: String: 0x000001a2 "_ZN11parent_test3fooEv"
+# DWARF-NEXT: String: 0x00000174 "_ZN11parent_test3fooEv"
# DWARF-NEXT: Entry @ 0x14a {
# DWARF-NEXT: Abbrev: 0x4
# DWARF-NEXT: Tag: DW_TAG_subprogram
@@ -104,7 +101,7 @@
# DWARF-NEXT: }
# DWARF-NEXT: Name 2 {
# DWARF-NEXT: Hash: 0xB5063D0B
-# DWARF-NEXT: String: 0x0000018e "_Z3foov"
+# DWARF-NEXT: String: 0x00000160 "_Z3foov"
# DWARF-NEXT: Entry @ 0x155 {
# DWARF-NEXT: Abbrev: 0x2
# DWARF-NEXT: Tag: DW_TAG_subprogram
@@ -117,7 +114,7 @@
# DWARF-NEXT: Bucket 2 [
# DWARF-NEXT: Name 3 {
# DWARF-NEXT: Hash: 0xB888030
-# DWARF-NEXT: String: 0x000000a9 "int"
+# DWARF-NEXT: String: 0x00000093 "int"
# DWARF-NEXT: Entry @ 0xfe {
# DWARF-NEXT: Abbrev: 0x1
# DWARF-NEXT: Tag: DW_TAG_base_type
@@ -137,7 +134,7 @@
# DWARF-NEXT: Bucket 3 [
# DWARF-NEXT: Name 4 {
# DWARF-NEXT: Hash: 0xB8860BA
-# DWARF-NEXT: String: 0x00000093 "bar"
+# DWARF-NEXT: String: 0x0000007d "bar"
# DWARF-NEXT: Entry @ 0xf7 {
# DWARF-NEXT: Abbrev: 0x2
# DWARF-NEXT: Tag: DW_TAG_subprogram
@@ -148,7 +145,7 @@
# DWARF-NEXT: }
# DWARF-NEXT: Name 5 {
# DWARF-NEXT: Hash: 0xB887389
-# DWARF-NEXT: String: 0x000000ad "foo"
+# DWARF-NEXT: String: 0x00000097 "foo"
# DWARF-NEXT: Entry @ 0x10b {
# DWARF-NEXT: Abbrev: 0x3
# DWARF-NEXT: Tag: DW_TAG_structure_type
@@ -191,7 +188,7 @@
# DWARF-NEXT: Bucket 7 [
# DWARF-NEXT: Name 6 {
# DWARF-NEXT: Hash: 0x7C9A7F6A
-# DWARF-NEXT: String: 0x000000a4 "main"
+# DWARF-NEXT: String: 0x0000008e "main"
# DWARF-NEXT: Entry @ 0x136 {
# DWARF-NEXT: Abbrev: 0x2
# DWARF-NEXT: Tag: DW_TAG_subprogram
@@ -204,7 +201,7 @@
# DWARF-NEXT: Bucket 8 [
# DWARF-NEXT: Name 7 {
# DWARF-NEXT: Hash: 0xA7255AE
-# DWARF-NEXT: String: 0x00000196 "parent_test"
+# DWARF-NEXT: String: 0x00000168 "parent_test"
# DWARF-NEXT: Entry @ 0x128 {
# DWARF-NEXT: Abbrev: 0x5
# DWARF-NEXT: Tag: DW_TAG_namespace
@@ -215,7 +212,7 @@
# DWARF-NEXT: }
# DWARF-NEXT: Name 8 {
# DWARF-NEXT: Hash: 0x51007E98
-# DWARF-NEXT: String: 0x00000097 "_Z3barR3fooi"
+# DWARF-NEXT: String: 0x00000081 "_Z3barR3fooi"
# DWARF-NEXT: Entry @ 0x12f {
# DWARF-NEXT: Abbrev: 0x2
# DWARF-NEXT: Tag: DW_TAG_subprogram
@@ -226,7 +223,7 @@
# DWARF-NEXT: }
# DWARF-NEXT: Name 9 {
# DWARF-NEXT: Hash: 0x7C952063
-# DWARF-NEXT: String: 0x000000b5 "char"
+# DWARF-NEXT: String: 0x0000009f "char"
# DWARF-NEXT: Entry @ 0x13d {
# DWARF-NEXT: Abbrev: 0x1
# DWARF-NEXT: Tag: DW_TAG_base_type
@@ -244,7 +241,7 @@
# DWARF-NEXT: }
# DWARF-NEXT: ]
-#--- debug-names-parent-idx.s
+#--- a.s
.text
.globl _Z3barR3fooi # -- Begin function _Z3barR3fooi
.p2align 4, 0x90
@@ -331,39 +328,39 @@ main: # @main
.Lstr_offsets_base0:
.section .debug_str,"MS", at progbits,1
.Linfo_string0:
- .asciz "clang version 19.0.0git (git at github.com:llvm/llvm-project.git 4df364bc93af49ae413ec1ae8328f34ac70730c4)" # string offset=0
+ .asciz "clang version 19.0.0git (git at github.com:llvm/llvm-project.git 53b14cd9ce2b57da73d173fc876d2e9e199f5640)" # string offset=0
.Linfo_string1:
- .asciz "debug-names-parent-idx.cpp" # string offset=104
+ .asciz "a.cpp" # string offset=104
.Linfo_string2:
- .asciz "parent-idx-test" # string offset=131
+ .asciz "/proc/self/cwd" # string offset=110
.Linfo_string3:
- .asciz "bar" # string offset=147
+ .asciz "bar" # string offset=125
.Linfo_string4:
- .asciz "_Z3barR3fooi" # string offset=151
+ .asciz "_Z3barR3fooi" # string offset=129
.Linfo_string5:
- .asciz "main" # string offset=164
+ .asciz "main" # string offset=142
.Linfo_string6:
- .asciz "int" # string offset=169
+ .asciz "int" # string offset=147
.Linfo_string7:
- .asciz "foo" # string offset=173
+ .asciz "foo" # string offset=151
.Linfo_string8:
- .asciz "x" # string offset=177
+ .asciz "x" # string offset=155
.Linfo_string9:
- .asciz "y" # string offset=179
+ .asciz "y" # string offset=157
.Linfo_string10:
- .asciz "char" # string offset=181
+ .asciz "char" # string offset=159
.Linfo_string11:
- .asciz "foo_ptr" # string offset=186
+ .asciz "foo_ptr" # string offset=164
.Linfo_string12:
- .asciz "junk" # string offset=194
+ .asciz "junk" # string offset=172
.Linfo_string13:
- .asciz "argc" # string offset=199
+ .asciz "argc" # string offset=177
.Linfo_string14:
- .asciz "argv" # string offset=204
+ .asciz "argv" # string offset=182
.Linfo_string15:
- .asciz "my_struct" # string offset=209
+ .asciz "my_struct" # string offset=187
.Linfo_string16:
- .asciz "junk2" # string offset=219
+ .asciz "junk2" # string offset=197
.Laddr_table_base0:
.quad .Lfunc_begin0
.quad .Lfunc_begin1
@@ -471,7 +468,7 @@ main: # @main
# End of list: char
.p2align 2, 0x0
.Lnames_end0:
- .ident "clang version 19.0.0git (git at github.com:llvm/llvm-project.git 4df364bc93af49ae413ec1ae8328f34ac70730c4)"
+ .ident "clang version 19.0.0git (git at github.com:llvm/llvm-project.git 53b14cd9ce2b57da73d173fc876d2e9e199f5640)"
.section ".note.GNU-stack","", at progbits
.addrsig
.addrsig_sym _Z3barR3fooi
@@ -480,11 +477,11 @@ main: # @main
.section .debug_line,"", at progbits
.Lline_table_start0:
-#--- debug-names-parent-idx-2.s
+#--- b.s
# Generated with:
-# - clang++ -g -O0 -gpubnames -fdebug-compilation-dir='parent-idx-test' \
-# -S debug-names-parent-idx-2.cpp -o debug-names-parent-idx-2.s
+# clang++ -g -O0 -gpubnames -fdebug-compilation-dir='/proc/self/cwd' -S \
+# b.cpp -o b.s
# foo.h contents:
@@ -500,7 +497,7 @@ main: # @main
# int foo();
# }
-# debug-names-parent-index-2.cpp contents:
+# b.cpp contents:
# #include "foo.h"
# int foo () {
@@ -587,31 +584,31 @@ _ZN11parent_test3fooEv: # @_ZN11parent_test3fooEv
.Lstr_offsets_base0:
.section .debug_str,"MS", at progbits,1
.Linfo_string0:
- .asciz "clang version 19.0.0git (git at github.com:llvm/llvm-project.git 4df364bc93af49ae413ec1ae8328f34ac70730c4)" # string offset=0
+ .asciz "clang version 19.0.0git (git at github.com:llvm/llvm-project.git 53b14cd9ce2b57da73d173fc876d2e9e199f5640)" # string offset=0
.Linfo_string1:
- .asciz "debug-names-parent-idx-2.cpp" # string offset=104
+ .asciz "b.cpp" # string offset=104
.Linfo_string2:
- .asciz "parent-idx-test" # string offset=133
+ .asciz "/proc/self/cwd" # string offset=110
.Linfo_string3:
- .asciz "int" # string offset=149
+ .asciz "int" # string offset=125
.Linfo_string4:
- .asciz "foo" # string offset=153
+ .asciz "foo" # string offset=129
.Linfo_string5:
- .asciz "_Z3foov" # string offset=157
+ .asciz "_Z3foov" # string offset=133
.Linfo_string6:
- .asciz "parent_test" # string offset=165
+ .asciz "parent_test" # string offset=141
.Linfo_string7:
- .asciz "_ZN11parent_test3fooEv" # string offset=177
+ .asciz "_ZN11parent_test3fooEv" # string offset=153
.Linfo_string8:
- .asciz "struct2" # string offset=200
+ .asciz "struct2" # string offset=176
.Linfo_string9:
- .asciz "x" # string offset=208
+ .asciz "x" # string offset=184
.Linfo_string10:
- .asciz "y" # string offset=210
+ .asciz "y" # string offset=186
.Linfo_string11:
- .asciz "char" # string offset=212
+ .asciz "char" # string offset=188
.Linfo_string12:
- .asciz "foo_ptr" # string offset=217
+ .asciz "foo_ptr" # string offset=193
.Laddr_table_base0:
.quad .Lfunc_begin0
.quad .Lfunc_begin1
@@ -742,7 +739,7 @@ _ZN11parent_test3fooEv: # @_ZN11parent_test3fooEv
# End of list: char
.p2align 2, 0x0
.Lnames_end0:
- .ident "clang version 19.0.0git (git at github.com:llvm/llvm-project.git 4df364bc93af49ae413ec1ae8328f34ac70730c4)"
+ .ident "clang version 19.0.0git (git at github.com:llvm/llvm-project.git 53b14cd9ce2b57da73d173fc876d2e9e199f5640)"
.section ".note.GNU-stack","", at progbits
.addrsig
.section .debug_line,"", at progbits
diff --git a/lld/test/ELF/debug-names.s b/lld/test/ELF/debug-names.s
index eb35281a224f0d..4ca2cb1eabefae 100644
--- a/lld/test/ELF/debug-names.s
+++ b/lld/test/ELF/debug-names.s
@@ -1,7 +1,7 @@
# debug-names.s was generated with:
-# - clang++ -g -O0 -gpubnames -fdebug-compilation-dir='debug-names-test' \
-# -S a.cpp -o a.s
+# - clang++ -g -O0 -gpubnames -fdebug-compilation-dir='/proc/self/cwd' \
+# -S a.cpp -o a.s
# a.cpp contents:
@@ -65,7 +65,7 @@
# DWARF-NEXT: Bucket 1 [
# DWARF-NEXT: Name 1 {
# DWARF-NEXT: Hash: 0x59796A
-# DWARF-NEXT: String: 0x0000008b "t1"
+# DWARF-NEXT: String: 0x00000089 "t1"
# DWARF-NEXT: Entry @ 0xaa {
# DWARF-NEXT: Abbrev: 0x1
# DWARF-NEXT: Tag: DW_TAG_structure_type
@@ -83,7 +83,7 @@
# DWARF-NEXT: }
# DWARF-NEXT: Name 2 {
# DWARF-NEXT: Hash: 0x5355B2BE
-# DWARF-NEXT: String: 0x00000082 "_Z2f12t1"
+# DWARF-NEXT: String: 0x00000080 "_Z2f12t1"
# DWARF-NEXT: Entry @ 0xbe {
# DWARF-NEXT: Abbrev: 0x2
# DWARF-NEXT: Tag: DW_TAG_subprogram
@@ -94,7 +94,7 @@
# DWARF-NEXT: }
# DWARF-NEXT: Name 3 {
# DWARF-NEXT: Hash: 0x7C9A7F6A
-# DWARF-NEXT: String: 0x00000115 "main"
+# DWARF-NEXT: String: 0x00000111 "main"
# DWARF-NEXT: Entry @ 0xc5 {
# DWARF-NEXT: Abbrev: 0x2
# DWARF-NEXT: Tag: DW_TAG_subprogram
@@ -110,7 +110,7 @@
# DWARF-NEXT: Bucket 3 [
# DWARF-NEXT: Name 4 {
# DWARF-NEXT: Hash: 0xB888030
-# DWARF-NEXT: String: 0x0000011a "int"
+# DWARF-NEXT: String: 0x00000116 "int"
# DWARF-NEXT: Entry @ 0xb7 {
# DWARF-NEXT: Abbrev: 0x3
# DWARF-NEXT: Tag: DW_TAG_base_type
@@ -123,7 +123,7 @@
# DWARF-NEXT: Bucket 4 [
# DWARF-NEXT: Name 5 {
# DWARF-NEXT: Hash: 0x59779C
-# DWARF-NEXT: String: 0x0000007f "f1"
+# DWARF-NEXT: String: 0x0000007d "f1"
# DWARF-NEXT: Entry @ 0xa3 {
# DWARF-NEXT: Abbrev: 0x2
# DWARF-NEXT: Tag: DW_TAG_subprogram
@@ -181,13 +181,13 @@ _Z2f12t1: # @_Z2f12t1
.Linfo_string1:
.asciz "a.cpp" # string offset=104
.Linfo_string2:
- .asciz "debug-names-test" # string offset=110
+ .asciz "/proc/self/cwd" # string offset=110
.Linfo_string3:
- .asciz "f1" # string offset=127
+ .asciz "f1" # string offset=125
.Linfo_string4:
- .asciz "_Z2f12t1" # string offset=130
+ .asciz "_Z2f12t1" # string offset=128
.Linfo_string5:
- .asciz "t1" # string offset=139
+ .asciz "t1" # string offset=137
.Laddr_table_base0:
.quad .Lfunc_begin0
.Ldebug_addr_end0:
@@ -264,7 +264,7 @@ _Z2f12t1: # @_Z2f12t1
#--- b.s
# Generated with:
-# - clang++ -g -O0 -gpubnames -fdebug-compilation-dir='debug-names-test' \
+# - clang++ -g -O0 -gpubnames -fdebug-compilation-dir='/proc/self/cwd' \
# -S b.cpp -o b.s
# b.cpp contents:
@@ -274,6 +274,7 @@ _Z2f12t1: # @_Z2f12t1
# t1 v1;
# }
#
+
.text
.globl main # -- Begin function main
.p2align 4, 0x90
@@ -321,15 +322,15 @@ main: # @main
.Linfo_string1:
.asciz "b.cpp" # string offset=104
.Linfo_string2:
- .asciz "debug-names-test" # string offset=110
+ .asciz "/proc/self/cwd" # string offset=110
.Linfo_string3:
- .asciz "main" # string offset=127
+ .asciz "main" # string offset=125
.Linfo_string4:
- .asciz "int" # string offset=132
+ .asciz "int" # string offset=130
.Linfo_string5:
- .asciz "v1" # string offset=136
+ .asciz "v1" # string offset=134
.Linfo_string6:
- .asciz "t1" # string offset=139
+ .asciz "t1" # string offset=137
.Laddr_table_base0:
.quad .Lfunc_begin0
.Ldebug_addr_end0:
diff --git a/lld/test/ELF/ppc32-debug-names.s b/lld/test/ELF/ppc32-debug-names.s
index 40d7cc5b4fa2f7..f091f961588d0c 100644
--- a/lld/test/ELF/ppc32-debug-names.s
+++ b/lld/test/ELF/ppc32-debug-names.s
@@ -1,7 +1,7 @@
# ppc-debug-names.s was generated with:
# - clang++ --target=powerpc -g -O0 -gpubnames \
-# -fdebug-compilation-dir='debug-names-test' -S a.cpp -o a.s
+# -fdebug-compilation-dir='/self/proc/cwd' -S a.cpp -o a.s
# a.cpp contents:
@@ -66,7 +66,7 @@
# DWARF-NEXT: Bucket 1 [
# DWARF-NEXT: Name 1 {
# DWARF-NEXT: Hash: 0x59796A
-# DWARF-NEXT: String: 0x0000008b "t1"
+# DWARF-NEXT: String: 0x00000089 "t1"
# DWARF-NEXT: Entry @ 0xaa {
# DWARF-NEXT: Abbrev: 0x1
# DWARF-NEXT: Tag: DW_TAG_structure_type
@@ -84,7 +84,7 @@
# DWARF-NEXT: }
# DWARF-NEXT: Name 2 {
# DWARF-NEXT: Hash: 0x5355B2BE
-# DWARF-NEXT: String: 0x00000082 "_Z2f12t1"
+# DWARF-NEXT: String: 0x00000080 "_Z2f12t1"
# DWARF-NEXT: Entry @ 0xbe {
# DWARF-NEXT: Abbrev: 0x2
# DWARF-NEXT: Tag: DW_TAG_subprogram
@@ -95,7 +95,7 @@
# DWARF-NEXT: }
# DWARF-NEXT: Name 3 {
# DWARF-NEXT: Hash: 0x7C9A7F6A
-# DWARF-NEXT: String: 0x00000111 "main"
+# DWARF-NEXT: String: 0x0000010d "main"
# DWARF-NEXT: Entry @ 0xc5 {
# DWARF-NEXT: Abbrev: 0x2
# DWARF-NEXT: Tag: DW_TAG_subprogram
@@ -111,7 +111,7 @@
# DWARF-NEXT: Bucket 3 [
# DWARF-NEXT: Name 4 {
# DWARF-NEXT: Hash: 0xB888030
-# DWARF-NEXT: String: 0x00000116 "int"
+# DWARF-NEXT: String: 0x00000112 "int"
# DWARF-NEXT: Entry @ 0xb7 {
# DWARF-NEXT: Abbrev: 0x3
# DWARF-NEXT: Tag: DW_TAG_base_type
@@ -124,7 +124,7 @@
# DWARF-NEXT: Bucket 4 [
# DWARF-NEXT: Name 5 {
# DWARF-NEXT: Hash: 0x59779C
-# DWARF-NEXT: String: 0x0000007f "f1"
+# DWARF-NEXT: String: 0x0000007d "f1"
# DWARF-NEXT: Entry @ 0xa3 {
# DWARF-NEXT: Abbrev: 0x2
# DWARF-NEXT: Tag: DW_TAG_subprogram
@@ -144,6 +144,7 @@ _Z2f12t1: # @_Z2f12t1
.Lfunc_begin0:
.cfi_startproc
# %bb.0: # %entry
+ #DEBUG_VALUE: f1: <- [$r3+0]
stwu 1, -16(1)
stw 31, 12(1)
.cfi_def_cfa_offset 16
@@ -183,13 +184,13 @@ _Z2f12t1: # @_Z2f12t1
.Linfo_string1:
.asciz "a.cpp" # string offset=104
.Linfo_string2:
- .asciz "debug-names-test" # string offset=110
+ .asciz "/proc/self/cwd" # string offset=110
.Linfo_string3:
- .asciz "f1" # string offset=127
+ .asciz "f1" # string offset=125
.Linfo_string4:
- .asciz "_Z2f12t1" # string offset=130
+ .asciz "_Z2f12t1" # string offset=128
.Linfo_string5:
- .asciz "t1" # string offset=139
+ .asciz "t1" # string offset=137
.Laddr_table_base0:
.long .Lfunc_begin0
.Ldebug_addr_end0:
@@ -267,7 +268,7 @@ _Z2f12t1: # @_Z2f12t1
#--- b.s
# Generated with:
# - clang++ --target=powerpc -g -O0 -gpubnames \
-# -fdebug-compilation-dir='debug-names-test' -S b.cpp -o b.s
+# -fdebug-compilation-dir='/self/proc/cwd' -S b.cpp -o b.s
# b.cpp contents:
@@ -324,15 +325,15 @@ main: # @main
.Linfo_string1:
.asciz "b.cpp" # string offset=104
.Linfo_string2:
- .asciz "debug-names-test" # string offset=110
+ .asciz "/proc/self/cwd" # string offset=110
.Linfo_string3:
- .asciz "main" # string offset=127
+ .asciz "main" # string offset=125
.Linfo_string4:
- .asciz "int" # string offset=132
+ .asciz "int" # string offset=130
.Linfo_string5:
- .asciz "v1" # string offset=136
+ .asciz "v1" # string offset=134
.Linfo_string6:
- .asciz "t1" # string offset=139
+ .asciz "t1" # string offset=137
.Laddr_table_base0:
.long .Lfunc_begin0
.Ldebug_addr_end0:
>From 3721df40d983e3a9ba8bdd35796e556001461290 Mon Sep 17 00:00:00 2001
From: Caroline Tice <cmtice at google.com>
Date: Mon, 15 Apr 2024 00:54:03 -0700
Subject: [PATCH 20/23] [lld][ELF] Add test for CompUnit > 1
Add code to update CU offsets correctly when there are multiple CUs
within one .o file. Also add test for this.
---
lld/ELF/SyntheticSections.cpp | 34 ++
lld/ELF/SyntheticSections.h | 2 +
lld/test/ELF/debug-names-multi-cus.s | 645 +++++++++++++++++++++++++++
3 files changed, 681 insertions(+)
create mode 100644 lld/test/ELF/debug-names-multi-cus.s
diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp
index 910ace1c757b43..b69cc4cd967d5c 100644
--- a/lld/ELF/SyntheticSections.cpp
+++ b/lld/ELF/SyntheticSections.cpp
@@ -3217,6 +3217,38 @@ template <class ELFT> void DebugNamesSection<ELFT>::finalizeContents() {
});
}
+template <class ELFT>
+void DebugNamesSection<ELFT>::updateMultiCuOffsets(OutputChunk &chunk) {
+ // Find the .debug_info section data for this chunk.
+ auto *file = cast<ObjFile<ELFT>>(chunk.infoSec->file);
+ DWARFContext dwarf(std::make_unique<LLDDwarfObj<ELFT>>(file));
+ auto &dobj = static_cast<const LLDDwarfObj<ELFT> &>(dwarf.getDWARFObj());
+ InputSection *infoSec = dobj.getInfoSection();
+ auto infoData = toStringRef(infoSec->contentMaybeDecompress());
+ const char *p = infoData.data();
+
+ // Skim through the CUs reading the unit lengths & types to find correct
+ // starting offsets for CUs (before relocation).
+ uint32_t nextCu = 0;
+ for (size_t i = 1, end = chunk.compUnits.size(); i < end; ++i) {
+ // First CU offset for each new (appended) .debug_names section starts at
+ // zero.
+ if (chunk.compUnits[i] == 0) {
+ // Skip to start of next CU and read the type & size.
+ p = infoData.data() + nextCu;
+ uint32_t unit_length =
+ endian::readNext<uint32_t, ELFT::Endianness, unaligned>(p);
+ [[maybe_unused]] uint16_t version =
+ endian::readNext<uint16_t, ELFT::Endianness, unaligned>(p);
+ uint8_t unitType =
+ endian::readNext<uint8_t, ELFT::Endianness, unaligned>(p);
+ if (unitType == dwarf::DW_UT_compile)
+ nextCu += unit_length + 4;
+ }
+ chunk.compUnits[i] += nextCu;
+ }
+}
+
template <class ELFT> void DebugNamesSection<ELFT>::writeTo(uint8_t *buf) {
[[maybe_unused]] uint8_t *oldBuf = buf;
// Write the header.
@@ -3236,6 +3268,8 @@ template <class ELFT> void DebugNamesSection<ELFT>::writeTo(uint8_t *buf) {
// Write the CU list.
for (auto i : seq(numChunks)) {
OutputChunk &chunk = chunks[i];
+ if (chunk.compUnits.size() > 1)
+ updateMultiCuOffsets(chunk);
for (uint32_t cuOffset : chunk.compUnits) {
endian::write32<ELFT::Endianness>(buf,
chunk.infoSec->outSecOff + cuOffset);
diff --git a/lld/ELF/SyntheticSections.h b/lld/ELF/SyntheticSections.h
index 534fac005e0b8b..cbf16c4011388b 100644
--- a/lld/ELF/SyntheticSections.h
+++ b/lld/ELF/SyntheticSections.h
@@ -910,6 +910,8 @@ class DebugNamesSection final : public DebugNamesBaseSection {
void getNameRelocs(InputSection *sec, ArrayRef<RelTy> rels,
llvm::DenseMap<uint32_t, uint32_t> &relocs);
+ void updateMultiCuOffsets(OutputChunk &chunk);
+
private:
static void readOffsets(InputChunk &inputChunk, OutputChunk &chunk,
llvm::DWARFDataExtractor &namesExtractor,
diff --git a/lld/test/ELF/debug-names-multi-cus.s b/lld/test/ELF/debug-names-multi-cus.s
new file mode 100644
index 00000000000000..bc79a783f61dd7
--- /dev/null
+++ b/lld/test/ELF/debug-names-multi-cus.s
@@ -0,0 +1,645 @@
+# ab.s was generated by:
+
+# clang++ a.cpp -gpubnames a.cpp -g -emit-llvm -c \
+# -fdebug-compilation-dir='/proc/self/cwd
+# clang++ b.cpp -gpubnames b.cpp -g -emit-llvm -c \
+# -fdebug-compilation-dir='/proc/self/cwd
+# llvm-link a.bc b.bc -o ab.bc
+# clang++ ab.bc -S -o ab.s
+
+# a.cpp contains:
+# struct t1 { };
+# void f1(t1) { }
+
+# b.cpp contains:
+# struct t1 { };
+# int main() {
+# t1 v1;
+# }
+
+
+# REQUIRES: x86
+# RUN: rm -rf %t && split-file %s %t && cd %t
+# RUN: llvm-mc -filetype=obj -triple=x86_64 ab.s -o ab.o
+# RUN: llvm-mc -filetype=obj -triple=x86_64 c.s -o c.o
+# RUN: ld.lld --debug-names ab.o c.o -o out
+# RUN: llvm-dwarfdump --debug-names out \
+# RUN: | FileCheck -DFILE=a.o %s --check-prefix=DWARF
+
+# DWARF: Compilation Unit offsets [
+# DWARF-NEXT: CU[0]: 0x00000000
+# DWARF-NEXT: CU[1]: 0x00000041
+# DWARF-NEXT: CU[2]: 0x00000084
+# DWARF-NEXT: ]
+
+# RUN: ld.lld --debug-names c.o ab.o -o out2
+# RUN: llvm-dwarfdump --debug-names out2 \
+# RUN: | FileCheck -DFILE=a.o %s --check-prefix=DWARF2
+
+# DWARF2: Compilation Unit offsets [
+# DWARF2-NEXT: CU[0]: 0x00000000
+# DWARF2-NEXT: CU[1]: 0x00000030
+# DWARF2-NEXT: CU[2]: 0x00000071
+# DWARF2-NEXT: ]
+
+#--- ab.s
+ .text
+ .globl _Z2f12t1 # -- Begin function _Z2f12t1
+ .p2align 4, 0x90
+ .type _Z2f12t1, at function
+_Z2f12t1: # @_Z2f12t1
+.Lfunc_begin0:
+ .cfi_startproc
+# %bb.0: # %entry
+ pushq %rbp
+ .cfi_def_cfa_offset 16
+ .cfi_offset %rbp, -16
+ movq %rsp, %rbp
+ .cfi_def_cfa_register %rbp
+.Ltmp0:
+ popq %rbp
+ .cfi_def_cfa %rsp, 8
+ retq
+.Ltmp1:
+.Lfunc_end0:
+ .size _Z2f12t1, .Lfunc_end0-_Z2f12t1
+ .cfi_endproc
+ # -- End function
+ .globl main # -- Begin function main
+ .p2align 4, 0x90
+ .type main, at function
+main: # @main
+.Lfunc_begin1:
+ .cfi_startproc
+# %bb.0: # %entry
+ pushq %rbp
+ .cfi_def_cfa_offset 16
+ .cfi_offset %rbp, -16
+ movq %rsp, %rbp
+ .cfi_def_cfa_register %rbp
+.Ltmp2:
+ xorl %eax, %eax
+ popq %rbp
+ .cfi_def_cfa %rsp, 8
+ retq
+.Ltmp3:
+.Lfunc_end1:
+ .size main, .Lfunc_end1-main
+ .cfi_endproc
+ # -- End function
+ .section .debug_abbrev,"", at progbits
+ .byte 1 # Abbreviation Code
+ .byte 17 # DW_TAG_compile_unit
+ .byte 1 # DW_CHILDREN_yes
+ .byte 37 # DW_AT_producer
+ .byte 37 # DW_FORM_strx1
+ .byte 19 # DW_AT_language
+ .byte 5 # DW_FORM_data2
+ .byte 3 # DW_AT_name
+ .byte 37 # DW_FORM_strx1
+ .byte 114 # DW_AT_str_offsets_base
+ .byte 23 # DW_FORM_sec_offset
+ .byte 16 # DW_AT_stmt_list
+ .byte 23 # DW_FORM_sec_offset
+ .byte 27 # DW_AT_comp_dir
+ .byte 37 # DW_FORM_strx1
+ .byte 17 # DW_AT_low_pc
+ .byte 27 # DW_FORM_addrx
+ .byte 18 # DW_AT_high_pc
+ .byte 6 # DW_FORM_data4
+ .byte 115 # DW_AT_addr_base
+ .byte 23 # DW_FORM_sec_offset
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 2 # Abbreviation Code
+ .byte 46 # DW_TAG_subprogram
+ .byte 1 # DW_CHILDREN_yes
+ .byte 17 # DW_AT_low_pc
+ .byte 27 # DW_FORM_addrx
+ .byte 18 # DW_AT_high_pc
+ .byte 6 # DW_FORM_data4
+ .byte 64 # DW_AT_frame_base
+ .byte 24 # DW_FORM_exprloc
+ .byte 110 # DW_AT_linkage_name
+ .byte 37 # DW_FORM_strx1
+ .byte 3 # DW_AT_name
+ .byte 37 # DW_FORM_strx1
+ .byte 58 # DW_AT_decl_file
+ .byte 11 # DW_FORM_data1
+ .byte 59 # DW_AT_decl_line
+ .byte 11 # DW_FORM_data1
+ .byte 63 # DW_AT_external
+ .byte 25 # DW_FORM_flag_present
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 3 # Abbreviation Code
+ .byte 5 # DW_TAG_formal_parameter
+ .byte 0 # DW_CHILDREN_no
+ .byte 2 # DW_AT_location
+ .byte 24 # DW_FORM_exprloc
+ .byte 58 # DW_AT_decl_file
+ .byte 11 # DW_FORM_data1
+ .byte 59 # DW_AT_decl_line
+ .byte 11 # DW_FORM_data1
+ .byte 73 # DW_AT_type
+ .byte 19 # DW_FORM_ref4
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 4 # Abbreviation Code
+ .byte 19 # DW_TAG_structure_type
+ .byte 0 # DW_CHILDREN_no
+ .byte 54 # DW_AT_calling_convention
+ .byte 11 # DW_FORM_data1
+ .byte 3 # DW_AT_name
+ .byte 37 # DW_FORM_strx1
+ .byte 11 # DW_AT_byte_size
+ .byte 11 # DW_FORM_data1
+ .byte 58 # DW_AT_decl_file
+ .byte 11 # DW_FORM_data1
+ .byte 59 # DW_AT_decl_line
+ .byte 11 # DW_FORM_data1
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 5 # Abbreviation Code
+ .byte 46 # DW_TAG_subprogram
+ .byte 1 # DW_CHILDREN_yes
+ .byte 17 # DW_AT_low_pc
+ .byte 27 # DW_FORM_addrx
+ .byte 18 # DW_AT_high_pc
+ .byte 6 # DW_FORM_data4
+ .byte 64 # DW_AT_frame_base
+ .byte 24 # DW_FORM_exprloc
+ .byte 3 # DW_AT_name
+ .byte 37 # DW_FORM_strx1
+ .byte 58 # DW_AT_decl_file
+ .byte 11 # DW_FORM_data1
+ .byte 59 # DW_AT_decl_line
+ .byte 11 # DW_FORM_data1
+ .byte 73 # DW_AT_type
+ .byte 19 # DW_FORM_ref4
+ .byte 63 # DW_AT_external
+ .byte 25 # DW_FORM_flag_present
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 6 # Abbreviation Code
+ .byte 52 # DW_TAG_variable
+ .byte 0 # DW_CHILDREN_no
+ .byte 2 # DW_AT_location
+ .byte 24 # DW_FORM_exprloc
+ .byte 3 # DW_AT_name
+ .byte 37 # DW_FORM_strx1
+ .byte 58 # DW_AT_decl_file
+ .byte 11 # DW_FORM_data1
+ .byte 59 # DW_AT_decl_line
+ .byte 11 # DW_FORM_data1
+ .byte 73 # DW_AT_type
+ .byte 16 # DW_FORM_ref_addr
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 7 # Abbreviation Code
+ .byte 36 # DW_TAG_base_type
+ .byte 0 # DW_CHILDREN_no
+ .byte 3 # DW_AT_name
+ .byte 37 # DW_FORM_strx1
+ .byte 62 # DW_AT_encoding
+ .byte 11 # DW_FORM_data1
+ .byte 11 # DW_AT_byte_size
+ .byte 11 # DW_FORM_data1
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 0 # EOM(3)
+ .section .debug_info,"", at progbits
+.Lcu_begin0:
+ .long .Ldebug_info_end0-.Ldebug_info_start0 # Length of Unit
+.Ldebug_info_start0:
+ .short 5 # DWARF version number
+ .byte 1 # DWARF Unit Type
+ .byte 8 # Address Size (in bytes)
+ .long .debug_abbrev # Offset Into Abbrev. Section
+ .byte 1 # Abbrev [1] 0xc:0x35 DW_TAG_compile_unit
+ .byte 0 # DW_AT_producer
+ .short 33 # DW_AT_language
+ .byte 1 # DW_AT_name
+ .long .Lstr_offsets_base0 # DW_AT_str_offsets_base
+ .long .Lline_table_start0 # DW_AT_stmt_list
+ .byte 2 # DW_AT_comp_dir
+ .byte 0 # DW_AT_low_pc
+ .long .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc
+ .long .Laddr_table_base0 # DW_AT_addr_base
+ .byte 2 # Abbrev [2] 0x23:0x17 DW_TAG_subprogram
+ .byte 0 # DW_AT_low_pc
+ .long .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc
+ .byte 1 # DW_AT_frame_base
+ .byte 86
+ .byte 4 # DW_AT_linkage_name
+ .byte 5 # DW_AT_name
+ .byte 1 # DW_AT_decl_file
+ .byte 2 # DW_AT_decl_line
+ # DW_AT_external
+ .byte 3 # Abbrev [3] 0x2f:0xa DW_TAG_formal_parameter
+ .byte 2 # DW_AT_location
+ .byte 145
+ .byte 127
+ .byte 1 # DW_AT_decl_file
+ .byte 2 # DW_AT_decl_line
+ .long 58 # DW_AT_type
+ .byte 0 # End Of Children Mark
+ .byte 4 # Abbrev [4] 0x3a:0x6 DW_TAG_structure_type
+ .byte 5 # DW_AT_calling_convention
+ .byte 8 # DW_AT_name
+ .byte 1 # DW_AT_byte_size
+ .byte 1 # DW_AT_decl_file
+ .byte 1 # DW_AT_decl_line
+ .byte 0 # End Of Children Mark
+.Ldebug_info_end0:
+.Lcu_begin1:
+ .long .Ldebug_info_end1-.Ldebug_info_start1 # Length of Unit
+.Ldebug_info_start1:
+ .short 5 # DWARF version number
+ .byte 1 # DWARF Unit Type
+ .byte 8 # Address Size (in bytes)
+ .long .debug_abbrev # Offset Into Abbrev. Section
+ .byte 1 # Abbrev [1] 0xc:0x37 DW_TAG_compile_unit
+ .byte 0 # DW_AT_producer
+ .short 33 # DW_AT_language
+ .byte 3 # DW_AT_name
+ .long .Lstr_offsets_base0 # DW_AT_str_offsets_base
+ .long .Lline_table_start0 # DW_AT_stmt_list
+ .byte 2 # DW_AT_comp_dir
+ .byte 1 # DW_AT_low_pc
+ .long .Lfunc_end1-.Lfunc_begin1 # DW_AT_high_pc
+ .long .Laddr_table_base0 # DW_AT_addr_base
+ .byte 5 # Abbrev [5] 0x23:0x1b DW_TAG_subprogram
+ .byte 1 # DW_AT_low_pc
+ .long .Lfunc_end1-.Lfunc_begin1 # DW_AT_high_pc
+ .byte 1 # DW_AT_frame_base
+ .byte 86
+ .byte 6 # DW_AT_name
+ .byte 2 # DW_AT_decl_file
+ .byte 2 # DW_AT_decl_line
+ .long 62 # DW_AT_type
+ # DW_AT_external
+ .byte 6 # Abbrev [6] 0x32:0xb DW_TAG_variable
+ .byte 2 # DW_AT_location
+ .byte 145
+ .byte 127
+ .byte 9 # DW_AT_name
+ .byte 2 # DW_AT_decl_file
+ .byte 3 # DW_AT_decl_line
+ .long .debug_info+58 # DW_AT_type
+ .byte 0 # End Of Children Mark
+ .byte 7 # Abbrev [7] 0x3e:0x4 DW_TAG_base_type
+ .byte 7 # DW_AT_name
+ .byte 5 # DW_AT_encoding
+ .byte 4 # DW_AT_byte_size
+ .byte 0 # End Of Children Mark
+.Ldebug_info_end1:
+ .section .debug_str_offsets,"", at progbits
+ .long 44 # Length of String Offsets Set
+ .short 5
+ .short 0
+.Lstr_offsets_base0:
+ .section .debug_str,"MS", at progbits,1
+.Linfo_string0:
+ .asciz "clang version 19.0.0git (git at github.com:llvm/llvm-project.git 7607c4d40149128f848055613edf9c3cf9ae890d)" # string offset=0
+.Linfo_string1:
+ .asciz "a.cpp" # string offset=104
+.Linfo_string2:
+ .asciz "/proc/self/cwd" # string offset=110
+.Linfo_string3:
+ .asciz "f1" # string offset=125
+.Linfo_string4:
+ .asciz "_Z2f12t1" # string offset=128
+.Linfo_string5:
+ .asciz "b.cpp" # string offset=137
+.Linfo_string6:
+ .asciz "main" # string offset=143
+.Linfo_string7:
+ .asciz "int" # string offset=148
+.Linfo_string8:
+ .asciz "t1" # string offset=152
+.Linfo_string9:
+ .asciz "v1" # string offset=155
+ .section .debug_str_offsets,"", at progbits
+ .long .Linfo_string0
+ .long .Linfo_string1
+ .long .Linfo_string2
+ .long .Linfo_string5
+ .long .Linfo_string4
+ .long .Linfo_string3
+ .long .Linfo_string6
+ .long .Linfo_string7
+ .long .Linfo_string8
+ .long .Linfo_string9
+ .section .debug_addr,"", at progbits
+ .long .Ldebug_addr_end0-.Ldebug_addr_start0 # Length of contribution
+.Ldebug_addr_start0:
+ .short 5 # DWARF version number
+ .byte 8 # Address size
+ .byte 0 # Segment selector size
+.Laddr_table_base0:
+ .quad .Lfunc_begin0
+ .quad .Lfunc_begin1
+.Ldebug_addr_end0:
+ .section .debug_names,"", at progbits
+ .long .Lnames_end0-.Lnames_start0 # Header: unit length
+.Lnames_start0:
+ .short 5 # Header: version
+ .short 0 # Header: padding
+ .long 2 # Header: compilation unit count
+ .long 0 # Header: local type unit count
+ .long 0 # Header: foreign type unit count
+ .long 5 # Header: bucket count
+ .long 5 # Header: name count
+ .long .Lnames_abbrev_end0-.Lnames_abbrev_start0 # Header: abbreviation table size
+ .long 8 # Header: augmentation string size
+ .ascii "LLVM0700" # Header: augmentation string
+ .long .Lcu_begin0 # Compilation unit 0
+ .long .Lcu_begin1 # Compilation unit 1
+ .long 0 # Bucket 0
+ .long 1 # Bucket 1
+ .long 0 # Bucket 2
+ .long 4 # Bucket 3
+ .long 5 # Bucket 4
+ .long 5863786 # Hash in Bucket 1
+ .long 1398125246 # Hash in Bucket 1
+ .long 2090499946 # Hash in Bucket 1
+ .long 193495088 # Hash in Bucket 3
+ .long 5863324 # Hash in Bucket 4
+ .long .Linfo_string8 # String in Bucket 1: t1
+ .long .Linfo_string4 # String in Bucket 1: _Z2f12t1
+ .long .Linfo_string6 # String in Bucket 1: main
+ .long .Linfo_string7 # String in Bucket 3: int
+ .long .Linfo_string3 # String in Bucket 4: f1
+ .long .Lnames4-.Lnames_entries0 # Offset in Bucket 1
+ .long .Lnames1-.Lnames_entries0 # Offset in Bucket 1
+ .long .Lnames2-.Lnames_entries0 # Offset in Bucket 1
+ .long .Lnames3-.Lnames_entries0 # Offset in Bucket 3
+ .long .Lnames0-.Lnames_entries0 # Offset in Bucket 4
+.Lnames_abbrev_start0:
+ .byte 1 # Abbrev code
+ .byte 19 # DW_TAG_structure_type
+ .byte 1 # DW_IDX_compile_unit
+ .byte 11 # DW_FORM_data1
+ .byte 3 # DW_IDX_die_offset
+ .byte 19 # DW_FORM_ref4
+ .byte 4 # DW_IDX_parent
+ .byte 25 # DW_FORM_flag_present
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev
+ .byte 2 # Abbrev code
+ .byte 46 # DW_TAG_subprogram
+ .byte 1 # DW_IDX_compile_unit
+ .byte 11 # DW_FORM_data1
+ .byte 3 # DW_IDX_die_offset
+ .byte 19 # DW_FORM_ref4
+ .byte 4 # DW_IDX_parent
+ .byte 25 # DW_FORM_flag_present
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev
+ .byte 3 # Abbrev code
+ .byte 36 # DW_TAG_base_type
+ .byte 1 # DW_IDX_compile_unit
+ .byte 11 # DW_FORM_data1
+ .byte 3 # DW_IDX_die_offset
+ .byte 19 # DW_FORM_ref4
+ .byte 4 # DW_IDX_parent
+ .byte 25 # DW_FORM_flag_present
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev list
+.Lnames_abbrev_end0:
+.Lnames_entries0:
+.Lnames4:
+.L0:
+ .byte 1 # Abbreviation code
+ .byte 0 # DW_IDX_compile_unit
+ .long 58 # DW_IDX_die_offset
+ .byte 0 # DW_IDX_parent
+ # End of list: t1
+.Lnames1:
+.L3:
+ .byte 2 # Abbreviation code
+ .byte 0 # DW_IDX_compile_unit
+ .long 35 # DW_IDX_die_offset
+ .byte 0 # DW_IDX_parent
+ # End of list: _Z2f12t1
+.Lnames2:
+.L2:
+ .byte 2 # Abbreviation code
+ .byte 1 # DW_IDX_compile_unit
+ .long 35 # DW_IDX_die_offset
+ .byte 0 # DW_IDX_parent
+ # End of list: main
+.Lnames3:
+.L1:
+ .byte 3 # Abbreviation code
+ .byte 1 # DW_IDX_compile_unit
+ .long 62 # DW_IDX_die_offset
+ .byte 0 # DW_IDX_parent
+ # End of list: int
+.Lnames0:
+ .byte 2 # Abbreviation code
+ .byte 0 # DW_IDX_compile_unit
+ .long 35 # DW_IDX_die_offset
+ .byte 0 # DW_IDX_parent
+ # End of list: f1
+ .p2align 2, 0x0
+.Lnames_end0:
+ .ident "clang version 19.0.0git (git at github.com:llvm/llvm-project.git 7607c4d40149128f848055613edf9c3cf9ae890d)"
+ .ident "clang version 19.0.0git (git at github.com:llvm/llvm-project.git 7607c4d40149128f848055613edf9c3cf9ae890d)"
+ .section ".note.GNU-stack","", at progbits
+ .addrsig
+ .section .debug_line,"", at progbits
+.Lline_table_start0:
+
+#--- c.s
+# Generated with:
+# - clang++ -g -gpubnames -fdebug-compilation-dir='/proc/self/cwd' \
+# -S c.cpp -o c.s
+
+# c.cpp contents:
+
+# void null() { }
+
+ .text
+ .globl _Z4nullv # -- Begin function _Z4nullv
+ .p2align 4, 0x90
+ .type _Z4nullv, at function
+_Z4nullv: # @_Z4nullv
+.Lfunc_begin0:
+ .cfi_startproc
+# %bb.0: # %entry
+ pushq %rbp
+ .cfi_def_cfa_offset 16
+ .cfi_offset %rbp, -16
+ movq %rsp, %rbp
+ .cfi_def_cfa_register %rbp
+.Ltmp0:
+ popq %rbp
+ .cfi_def_cfa %rsp, 8
+ retq
+.Ltmp1:
+.Lfunc_end0:
+ .size _Z4nullv, .Lfunc_end0-_Z4nullv
+ .cfi_endproc
+ # -- End function
+ .section .debug_abbrev,"", at progbits
+ .byte 1 # Abbreviation Code
+ .byte 17 # DW_TAG_compile_unit
+ .byte 1 # DW_CHILDREN_yes
+ .byte 37 # DW_AT_producer
+ .byte 37 # DW_FORM_strx1
+ .byte 19 # DW_AT_language
+ .byte 5 # DW_FORM_data2
+ .byte 3 # DW_AT_name
+ .byte 37 # DW_FORM_strx1
+ .byte 114 # DW_AT_str_offsets_base
+ .byte 23 # DW_FORM_sec_offset
+ .byte 16 # DW_AT_stmt_list
+ .byte 23 # DW_FORM_sec_offset
+ .byte 27 # DW_AT_comp_dir
+ .byte 37 # DW_FORM_strx1
+ .byte 17 # DW_AT_low_pc
+ .byte 27 # DW_FORM_addrx
+ .byte 18 # DW_AT_high_pc
+ .byte 6 # DW_FORM_data4
+ .byte 115 # DW_AT_addr_base
+ .byte 23 # DW_FORM_sec_offset
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 2 # Abbreviation Code
+ .byte 46 # DW_TAG_subprogram
+ .byte 0 # DW_CHILDREN_no
+ .byte 17 # DW_AT_low_pc
+ .byte 27 # DW_FORM_addrx
+ .byte 18 # DW_AT_high_pc
+ .byte 6 # DW_FORM_data4
+ .byte 64 # DW_AT_frame_base
+ .byte 24 # DW_FORM_exprloc
+ .byte 110 # DW_AT_linkage_name
+ .byte 37 # DW_FORM_strx1
+ .byte 3 # DW_AT_name
+ .byte 37 # DW_FORM_strx1
+ .byte 58 # DW_AT_decl_file
+ .byte 11 # DW_FORM_data1
+ .byte 59 # DW_AT_decl_line
+ .byte 11 # DW_FORM_data1
+ .byte 63 # DW_AT_external
+ .byte 25 # DW_FORM_flag_present
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 0 # EOM(3)
+ .section .debug_info,"", at progbits
+.Lcu_begin0:
+ .long .Ldebug_info_end0-.Ldebug_info_start0 # Length of Unit
+.Ldebug_info_start0:
+ .short 5 # DWARF version number
+ .byte 1 # DWARF Unit Type
+ .byte 8 # Address Size (in bytes)
+ .long .debug_abbrev # Offset Into Abbrev. Section
+ .byte 1 # Abbrev [1] 0xc:0x24 DW_TAG_compile_unit
+ .byte 0 # DW_AT_producer
+ .short 33 # DW_AT_language
+ .byte 1 # DW_AT_name
+ .long .Lstr_offsets_base0 # DW_AT_str_offsets_base
+ .long .Lline_table_start0 # DW_AT_stmt_list
+ .byte 2 # DW_AT_comp_dir
+ .byte 0 # DW_AT_low_pc
+ .long .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc
+ .long .Laddr_table_base0 # DW_AT_addr_base
+ .byte 2 # Abbrev [2] 0x23:0xc DW_TAG_subprogram
+ .byte 0 # DW_AT_low_pc
+ .long .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc
+ .byte 1 # DW_AT_frame_base
+ .byte 86
+ .byte 3 # DW_AT_linkage_name
+ .byte 4 # DW_AT_name
+ .byte 0 # DW_AT_decl_file
+ .byte 1 # DW_AT_decl_line
+ # DW_AT_external
+ .byte 0 # End Of Children Mark
+.Ldebug_info_end0:
+ .section .debug_str_offsets,"", at progbits
+ .long 24 # Length of String Offsets Set
+ .short 5
+ .short 0
+.Lstr_offsets_base0:
+ .section .debug_str,"MS", at progbits,1
+.Linfo_string0:
+ .asciz "clang version 19.0.0git (git at github.com:llvm/llvm-project.git 7607c4d40149128f848055613edf9c3cf9ae890d)" # string offset=0
+.Linfo_string1:
+ .asciz "c.cpp" # string offset=104
+.Linfo_string2:
+ .asciz "/proc/self/cwd" # string offset=110
+.Linfo_string3:
+ .asciz "null" # string offset=125
+.Linfo_string4:
+ .asciz "_Z4nullv" # string offset=130
+ .section .debug_str_offsets,"", at progbits
+ .long .Linfo_string0
+ .long .Linfo_string1
+ .long .Linfo_string2
+ .long .Linfo_string4
+ .long .Linfo_string3
+ .section .debug_addr,"", at progbits
+ .long .Ldebug_addr_end0-.Ldebug_addr_start0 # Length of contribution
+.Ldebug_addr_start0:
+ .short 5 # DWARF version number
+ .byte 8 # Address size
+ .byte 0 # Segment selector size
+.Laddr_table_base0:
+ .quad .Lfunc_begin0
+.Ldebug_addr_end0:
+ .section .debug_names,"", at progbits
+ .long .Lnames_end0-.Lnames_start0 # Header: unit length
+.Lnames_start0:
+ .short 5 # Header: version
+ .short 0 # Header: padding
+ .long 1 # Header: compilation unit count
+ .long 0 # Header: local type unit count
+ .long 0 # Header: foreign type unit count
+ .long 2 # Header: bucket count
+ .long 2 # Header: name count
+ .long .Lnames_abbrev_end0-.Lnames_abbrev_start0 # Header: abbreviation table size
+ .long 8 # Header: augmentation string size
+ .ascii "LLVM0700" # Header: augmentation string
+ .long .Lcu_begin0 # Compilation unit 0
+ .long 1 # Bucket 0
+ .long 2 # Bucket 1
+ .long 2090557760 # Hash in Bucket 0
+ .long 1488390083 # Hash in Bucket 1
+ .long .Linfo_string3 # String in Bucket 0: null
+ .long .Linfo_string4 # String in Bucket 1: _Z4nullv
+ .long .Lnames0-.Lnames_entries0 # Offset in Bucket 0
+ .long .Lnames1-.Lnames_entries0 # Offset in Bucket 1
+.Lnames_abbrev_start0:
+ .byte 1 # Abbrev code
+ .byte 46 # DW_TAG_subprogram
+ .byte 3 # DW_IDX_die_offset
+ .byte 19 # DW_FORM_ref4
+ .byte 4 # DW_IDX_parent
+ .byte 25 # DW_FORM_flag_present
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev list
+.Lnames_abbrev_end0:
+.Lnames_entries0:
+.Lnames0:
+.L0:
+ .byte 1 # Abbreviation code
+ .long 35 # DW_IDX_die_offset
+ .byte 0 # DW_IDX_parent
+ # End of list: null
+.Lnames1:
+ .byte 1 # Abbreviation code
+ .long 35 # DW_IDX_die_offset
+ .byte 0 # DW_IDX_parent
+ # End of list: _Z4nullv
+ .p2align 2, 0x0
+.Lnames_end0:
+ .ident "clang version 19.0.0git (git at github.com:llvm/llvm-project.git 7607c4d40149128f848055613edf9c3cf9ae890d)"
+ .section ".note.GNU-stack","", at progbits
+ .addrsig
+ .section .debug_line,"", at progbits
+.Lline_table_start0:
>From 174fa5bef6ea85dc68ce75da927c5ef723d1566d Mon Sep 17 00:00:00 2001
From: Caroline Tice <cmtice at google.com>
Date: Mon, 15 Apr 2024 10:33:31 -0700
Subject: [PATCH 21/23] [lld][ELF] Clean up updateMultiCuOffset.
Use the existing .debug_info section pointer in chunk, rather than
rebuilding it.
---
lld/ELF/SyntheticSections.cpp | 9 +--------
1 file changed, 1 insertion(+), 8 deletions(-)
diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp
index b69cc4cd967d5c..3f7931c4d24862 100644
--- a/lld/ELF/SyntheticSections.cpp
+++ b/lld/ELF/SyntheticSections.cpp
@@ -3219,20 +3219,13 @@ template <class ELFT> void DebugNamesSection<ELFT>::finalizeContents() {
template <class ELFT>
void DebugNamesSection<ELFT>::updateMultiCuOffsets(OutputChunk &chunk) {
- // Find the .debug_info section data for this chunk.
- auto *file = cast<ObjFile<ELFT>>(chunk.infoSec->file);
- DWARFContext dwarf(std::make_unique<LLDDwarfObj<ELFT>>(file));
- auto &dobj = static_cast<const LLDDwarfObj<ELFT> &>(dwarf.getDWARFObj());
- InputSection *infoSec = dobj.getInfoSection();
- auto infoData = toStringRef(infoSec->contentMaybeDecompress());
+ auto infoData = toStringRef(chunk.infoSec->contentMaybeDecompress());
const char *p = infoData.data();
// Skim through the CUs reading the unit lengths & types to find correct
// starting offsets for CUs (before relocation).
uint32_t nextCu = 0;
for (size_t i = 1, end = chunk.compUnits.size(); i < end; ++i) {
- // First CU offset for each new (appended) .debug_names section starts at
- // zero.
if (chunk.compUnits[i] == 0) {
// Skip to start of next CU and read the type & size.
p = infoData.data() + nextCu;
>From d81d3598e589b24443eca55e53b140040e67862d Mon Sep 17 00:00:00 2001
From: Fangrui Song <i at maskray.me>
Date: Mon, 15 Apr 2024 13:03:30 -0700
Subject: [PATCH 22/23] writeTo: Use endian::writeNext and rename oldBuf
---
lld/ELF/SyntheticSections.cpp | 64 +++++++++++++++--------------------
1 file changed, 27 insertions(+), 37 deletions(-)
diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp
index 3f7931c4d24862..dd07236aef29fc 100644
--- a/lld/ELF/SyntheticSections.cpp
+++ b/lld/ELF/SyntheticSections.cpp
@@ -3243,18 +3243,19 @@ void DebugNamesSection<ELFT>::updateMultiCuOffsets(OutputChunk &chunk) {
}
template <class ELFT> void DebugNamesSection<ELFT>::writeTo(uint8_t *buf) {
- [[maybe_unused]] uint8_t *oldBuf = buf;
+ [[maybe_unused]] const uint8_t *const beginBuf = buf;
// Write the header.
- endian::write32<ELFT::Endianness>(buf + 0, hdr.UnitLength);
- endian::write16<ELFT::Endianness>(buf + 4, hdr.Version);
- endian::write32<ELFT::Endianness>(buf + 8, hdr.CompUnitCount);
- endian::write32<ELFT::Endianness>(buf + 12, hdr.LocalTypeUnitCount);
- endian::write32<ELFT::Endianness>(buf + 16, hdr.ForeignTypeUnitCount);
- endian::write32<ELFT::Endianness>(buf + 20, hdr.BucketCount);
- endian::write32<ELFT::Endianness>(buf + 24, hdr.NameCount);
- endian::write32<ELFT::Endianness>(buf + 28, hdr.AbbrevTableSize);
- endian::write32<ELFT::Endianness>(buf + 32, hdr.AugmentationStringSize);
- buf += 36;
+ endian::writeNext<uint32_t, ELFT::Endianness>(buf, hdr.UnitLength);
+ endian::writeNext<uint16_t, ELFT::Endianness>(buf, hdr.Version);
+ buf += 2; // padding
+ endian::writeNext<uint32_t, ELFT::Endianness>(buf, hdr.CompUnitCount);
+ endian::writeNext<uint32_t, ELFT::Endianness>(buf, hdr.LocalTypeUnitCount);
+ endian::writeNext<uint32_t, ELFT::Endianness>(buf, hdr.ForeignTypeUnitCount);
+ endian::writeNext<uint32_t, ELFT::Endianness>(buf, hdr.BucketCount);
+ endian::writeNext<uint32_t, ELFT::Endianness>(buf, hdr.NameCount);
+ endian::writeNext<uint32_t, ELFT::Endianness>(buf, hdr.AbbrevTableSize);
+ endian::writeNext<uint32_t, ELFT::Endianness>(buf,
+ hdr.AugmentationStringSize);
memcpy(buf, hdr.AugmentationString.c_str(), hdr.AugmentationString.size());
buf += hdr.AugmentationStringSize;
@@ -3264,9 +3265,8 @@ template <class ELFT> void DebugNamesSection<ELFT>::writeTo(uint8_t *buf) {
if (chunk.compUnits.size() > 1)
updateMultiCuOffsets(chunk);
for (uint32_t cuOffset : chunk.compUnits) {
- endian::write32<ELFT::Endianness>(buf,
- chunk.infoSec->outSecOff + cuOffset);
- buf += 4;
+ endian::writeNext<uint32_t, ELFT::Endianness>(
+ buf, chunk.infoSec->outSecOff + cuOffset);
}
}
@@ -3291,31 +3291,22 @@ template <class ELFT> void DebugNamesSection<ELFT>::writeTo(uint8_t *buf) {
bucketIdx += bucket.size();
}
// Write the hashes.
- for (const SmallVector<NameEntry *, 0> &bucket : buckets) {
- for (const NameEntry *e : bucket) {
- endian::write32<ELFT::Endianness>(buf, e->hashValue);
- buf += 4;
- }
- }
+ for (const SmallVector<NameEntry *, 0> &bucket : buckets)
+ for (const NameEntry *e : bucket)
+ endian::writeNext<uint32_t, ELFT::Endianness>(buf, e->hashValue);
// Write the name table. The name entries are ordered by bucket_idx and
// correspond one-to-one with the hash lookup table.
//
// First, write the relocated string offsets.
- for (const SmallVector<NameEntry *, 0> &bucket : buckets) {
- for (const NameEntry *ne : bucket) {
- endian::write32<ELFT::Endianness>(buf, ne->stringOffset);
- buf += 4;
- }
- }
+ for (const SmallVector<NameEntry *, 0> &bucket : buckets)
+ for (const NameEntry *ne : bucket)
+ endian::writeNext<uint32_t, ELFT::Endianness>(buf, ne->stringOffset);
// Then write the entry offsets.
- for (const SmallVector<NameEntry *, 0> &bucket : buckets) {
- for (const NameEntry *ne : bucket) {
- endian::write32<ELFT::Endianness>(buf, ne->entryOffset);
- buf += 4;
- }
- }
+ for (const SmallVector<NameEntry *, 0> &bucket : buckets)
+ for (const NameEntry *ne : bucket)
+ endian::writeNext<uint32_t, ELFT::Endianness>(buf, ne->entryOffset);
// Write the abbrev table.
memcpy(buf, abbrevTableBuf.data(), abbrevTableBuf.size());
@@ -3331,24 +3322,23 @@ template <class ELFT> void DebugNamesSection<ELFT>::writeTo(uint8_t *buf) {
for (AttrValue value : ie.attrValues) {
switch (value.attrSize) {
case 1:
- *buf = value.attrValue;
+ *buf++ = value.attrValue;
break;
case 2:
- endian::write16<ELFT::Endianness>(buf, value.attrValue);
+ endian::writeNext<uint16_t, ELFT::Endianness>(buf, value.attrValue);
break;
case 4:
- endian::write32<ELFT::Endianness>(buf, value.attrValue);
+ endian::writeNext<uint32_t, ELFT::Endianness>(buf, value.attrValue);
break;
default:
llvm_unreachable("invalid attrSize");
}
- buf += value.attrSize;
}
}
++buf; // index entry sentinel
}
}
- assert(uint64_t(buf - oldBuf) == size);
+ assert(uint64_t(buf - beginBuf) == size);
}
GdbIndexSection::GdbIndexSection()
>From a81528642d1c7df57db4f82f6d06ba686e9a3a46 Mon Sep 17 00:00:00 2001
From: Fangrui Song <i at maskray.me>
Date: Mon, 15 Apr 2024 13:28:31 -0700
Subject: [PATCH 23/23] Fix CU list offsets when there are 3+ CUs in one
relocatable file
---
lld/ELF/SyntheticSections.cpp | 38 +++++++----------------------------
lld/ELF/SyntheticSections.h | 3 +--
2 files changed, 8 insertions(+), 33 deletions(-)
diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp
index dd07236aef29fc..89d3967eed1de5 100644
--- a/lld/ELF/SyntheticSections.cpp
+++ b/lld/ELF/SyntheticSections.cpp
@@ -3170,6 +3170,7 @@ template <class ELFT> DebugNamesSection<ELFT>::DebugNamesSection() {
const DWARFDebugNames::DWARFDebugNamesOffsets &locs) {
// Read CU offsets.
const char *p = namesData + niOffset + locs.CUsBase;
+ chunk.cusBase = niOffset + locs.CUsBase;
chunk.compUnits.resize_for_overwrite(numCus + hdr.CompUnitCount);
for (auto i : seq(hdr.CompUnitCount))
chunk.compUnits[i + numCus] =
@@ -3208,6 +3209,10 @@ template <class ELFT> void DebugNamesSection<ELFT>::finalizeContents() {
getNameRelocs(sec, rels.rels, relocs.get()[i]);
else
getNameRelocs(sec, rels.relas, relocs.get()[i]);
+
+ OutputChunk &chunk = chunks.get()[i];
+ for (auto [j, cuOffset] : enumerate(chunk.compUnits))
+ cuOffset = relocs.get()[i].lookup(chunk.cusBase + j * 4);
});
// Relocate string offsets in the name table.
@@ -3217,31 +3222,6 @@ template <class ELFT> void DebugNamesSection<ELFT>::finalizeContents() {
});
}
-template <class ELFT>
-void DebugNamesSection<ELFT>::updateMultiCuOffsets(OutputChunk &chunk) {
- auto infoData = toStringRef(chunk.infoSec->contentMaybeDecompress());
- const char *p = infoData.data();
-
- // Skim through the CUs reading the unit lengths & types to find correct
- // starting offsets for CUs (before relocation).
- uint32_t nextCu = 0;
- for (size_t i = 1, end = chunk.compUnits.size(); i < end; ++i) {
- if (chunk.compUnits[i] == 0) {
- // Skip to start of next CU and read the type & size.
- p = infoData.data() + nextCu;
- uint32_t unit_length =
- endian::readNext<uint32_t, ELFT::Endianness, unaligned>(p);
- [[maybe_unused]] uint16_t version =
- endian::readNext<uint16_t, ELFT::Endianness, unaligned>(p);
- uint8_t unitType =
- endian::readNext<uint8_t, ELFT::Endianness, unaligned>(p);
- if (unitType == dwarf::DW_UT_compile)
- nextCu += unit_length + 4;
- }
- chunk.compUnits[i] += nextCu;
- }
-}
-
template <class ELFT> void DebugNamesSection<ELFT>::writeTo(uint8_t *buf) {
[[maybe_unused]] const uint8_t *const beginBuf = buf;
// Write the header.
@@ -3262,12 +3242,8 @@ template <class ELFT> void DebugNamesSection<ELFT>::writeTo(uint8_t *buf) {
// Write the CU list.
for (auto i : seq(numChunks)) {
OutputChunk &chunk = chunks[i];
- if (chunk.compUnits.size() > 1)
- updateMultiCuOffsets(chunk);
- for (uint32_t cuOffset : chunk.compUnits) {
- endian::writeNext<uint32_t, ELFT::Endianness>(
- buf, chunk.infoSec->outSecOff + cuOffset);
- }
+ for (uint32_t cuOffset : chunk.compUnits)
+ endian::writeNext<uint32_t, ELFT::Endianness>(buf, cuOffset);
}
// Write the local TU list, then the foreign TU list..
diff --git a/lld/ELF/SyntheticSections.h b/lld/ELF/SyntheticSections.h
index cbf16c4011388b..e3946ba0ae8f54 100644
--- a/lld/ELF/SyntheticSections.h
+++ b/lld/ELF/SyntheticSections.h
@@ -858,6 +858,7 @@ class DebugNamesBaseSection : public SyntheticSection {
// Pointer to the .debug_info section that contains compile units, used to
// compute the relocated CU offsets.
InputSection *infoSec;
+ uint32_t cusBase;
SmallVector<uint32_t, 0> compUnits;
};
@@ -910,8 +911,6 @@ class DebugNamesSection final : public DebugNamesBaseSection {
void getNameRelocs(InputSection *sec, ArrayRef<RelTy> rels,
llvm::DenseMap<uint32_t, uint32_t> &relocs);
- void updateMultiCuOffsets(OutputChunk &chunk);
-
private:
static void readOffsets(InputChunk &inputChunk, OutputChunk &chunk,
llvm::DWARFDataExtractor &namesExtractor,
More information about the llvm-commits
mailing list