diff --git a/lld/ELF/Config.h b/lld/ELF/Config.h index 83f293ab2ce57..33bfa42b0fcbf 100644 --- a/lld/ELF/Config.h +++ b/lld/ELF/Config.h @@ -229,6 +229,7 @@ struct Config { bool cref; llvm::SmallVector, 0> deadRelocInNonAlloc; + bool debugNames; bool demangle = true; bool dependentLibraries; bool disableVerify; diff --git a/lld/ELF/DWARF.cpp b/lld/ELF/DWARF.cpp index ac28aa8c7ca6e..5d58e0c60a952 100644 --- a/lld/ELF/DWARF.cpp +++ b/lld/ELF/DWARF.cpp @@ -40,6 +40,7 @@ template LLDDwarfObj::LLDDwarfObj(ObjFile *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 ada38a043bc22..64c25c706c343 100644 --- a/lld/ELF/DWARF.h +++ b/lld/ELF/DWARF.h @@ -62,6 +62,9 @@ template 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 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 86cc09621a912..5fffdc51f34dd 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 c5e95d0d25c1a..d470646ed0eee 100644 --- a/lld/ELF/Options.td +++ b/lld/ELF/Options.td @@ -153,6 +153,10 @@ def : Flag<["--"], "no-color-diagnostics">, Alias, 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 0d7f393a9f3f4..7b9ada40c0f67 100644 --- a/lld/ELF/SyntheticSections.cpp +++ b/lld/ELF/SyntheticSections.cpp @@ -30,15 +30,19 @@ #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" #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" #include "llvm/Support/TimeProfiler.h" +#include #include using namespace llvm; @@ -2711,6 +2715,606 @@ static uint32_t computeGdbHash(StringRef s) { return h; } +// 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; +} + +static Expected +readEntry(uint64_t &offset, const DWARFDebugNames::NameIndex &ni, + uint64_t entriesBase, DWARFDataExtractor &namesExtractor, + const LLDDWARFSection &namesSec) { + auto ie = makeThreadLocal(); + ie->poolOffset = offset; + Error err = Error::success(); + uint64_t ulebVal = namesExtractor.getULEB128(&offset, &err); + if (err) + return createStringError(inconvertibleErrorCode(), + "invalid abbrev code: %s", + toString(std::move(err)).c_str()); + if (!isUInt<32>(ulebVal)) + return createStringError(inconvertibleErrorCode(), + "abbrev code too large for DWARF32: %" PRIu64, + ulebVal); + ie->abbrevCode = static_cast(ulebVal); + auto it = ni.getAbbrevs().find_as(ie->abbrevCode); + if (it == ni.getAbbrevs().end()) + return createStringError(inconvertibleErrorCode(), + "abbrev code not found in abbrev table: %" PRIu32, + ie->abbrevCode); + + DebugNamesBaseSection::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 = entriesBase + attr.attrValue; + } else if (a.Form != DW_FORM_flag_present) + return createStringError(inconvertibleErrorCode(), + "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: + return createStringError( + inconvertibleErrorCode(), + "unrecognized form encoding %d in abbrev table", a.Form); + } + } + if (err) + return createStringError(inconvertibleErrorCode(), + "error while reading attributes: %s", + toString(std::move(err)).c_str()); + if (a.Index == DW_IDX_compile_unit) + cuAttr = attr; + else if (a.Form != DW_FORM_flag_present) + ie->attrValues.push_back(attr); + } + // Canonicalize abbrev by placing the CU/TU index at the end. + ie->attrValues.push_back(cuAttr); + return ie; +} + +void DebugNamesBaseSection::parseDebugNames( + InputChunk &inputChunk, OutputChunk &chunk, + DWARFDataExtractor &namesExtractor, DataExtractor &strExtractor, + function_ref( + uint32_t numCus, const DWARFDebugNames::Header &, + const DWARFDebugNames::DWARFDebugNamesOffsets &)> + readOffsets) { + const LLDDWARFSection &namesSec = inputChunk.section; + DenseMap offsetMap; + // Number of CUs seen in previous NameIndex sections within current chunk. + uint32_t numCus = 0; + 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(": found DWARF64, which is currently unsupported")); + return; + } + if (nd.hdr.Version != 5) { + errorOrWarn(toString(namesSec.sec) + Twine(": unsupported version: ") + + Twine(nd.hdr.Version)); + return; + } + uint32_t dwarfSize = dwarf::getDwarfOffsetByteSize(DwarfFormat::DWARF32); + DWARFDebugNames::DWARFDebugNamesOffsets locs = ni.getOffsets(); + if (locs.EntriesBase > namesExtractor.getData().size()) { + errorOrWarn(toString(namesSec.sec) + + Twine(": entry pool start is beyond end of section")); + return; + } + + SmallVector entryOffsets = readOffsets(numCus, 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. + uint64_t offset = locs.EntriesBase + entryOffsets[i]; + while (offset < namesSec.Data.size() && namesSec.Data[offset] != 0) { + // Read & store all entries (for the same string). + Expected ieOrErr = + readEntry(offset, ni, locs.EntriesBase, namesExtractor, namesSec); + if (!ieOrErr) { + errorOrWarn(toString(namesSec.sec) + ": " + + toString(ieOrErr.takeError())); + return; + } + ne.indexEntries.push_back(std::move(*ieOrErr)); + } + if (offset >= namesSec.Data.size()) + errorOrWarn(toString(namesSec.sec) + + Twine(": index entry is out of bounds")); + + for (IndexEntry &ie : ne.entries()) + offsetMap[ie.poolOffset] = &ie; + } + + // 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); + numCus += nd.hdr.CompUnitCount; + } +} + +// 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 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 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; + // TODO: We don't handle type units yet, so LocalTypeUnitCount & + // ForeignTypeUnitCount are left as 0. + if (nd.hdr.LocalTypeUnitCount || nd.hdr.ForeignTypeUnitCount) + warn(toString(inputChunk.section.sec) + + Twine(": type units are not implemented")); + // 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) { + // 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(); + } + } + } + + // 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 abbrevSet; + // Determine the form for the DW_IDX_compile_unit attributes in the merged + // index. The input form may not be big enough for all CU indices. + 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 'parseDebugNames'. + 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 + 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 + // code mapping. + FoldingSetNodeID id; + abbrev.Profile(id); + 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 = + new (abbrevAlloc.Allocate()) Abbrev(std::move(abbrev)); + abbrevSet.InsertNode(abbrev2, insertPos); + abbrevTable.push_back(abbrev2); + newCode = abbrevTable.size(); + abbrev2->code = newCode; + } + inputChunk.nameData[i].abbrevCodeMap[oldAbbrev.Code] = newCode; + } + } + } + + // 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); + } + os.write("\0", 2); // attribute specification end + } + os.write(0); // abbrev table end + hdr.AbbrevTableSize = abbrevTableBuf.size(); +} + +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 DebugNamesBaseSection::computeEntryPool( + MutableArrayRef inputChunks) { + TimeTraceScope timeScope("Merge .debug_names", "entry pool"); + // 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(config->threadCount, numShards)); + const size_t shift = 32 - countr_zero(numShards); + const uint8_t cuAttrSize = getMergedCuCountForm(hdr.CompUnitCount).first; + DenseMap maps[numShards]; + + parallelFor(0, concurrency, [&](size_t threadId) { + for (auto i : seq(numChunks)) { + InputChunk &inputChunk = inputChunks[i]; + 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. + for (NameEntry &ne : nd.nameEntries) { + auto shardId = ne.hashValue >> shift; + if ((shardId & (concurrency - 1)) != threadId) + continue; + + 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) to have correct merged offset value and size. + auto &back = ie.attrValues.back(); + back.attrValue += inputChunk.baseCuIdx + j; + back.attrSize = cuAttrSize; + } + + 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(std::move(ne.indexEntries)); + } + } + } + }); + + // Compute entry offsets in parallel. 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 + } + 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; + } + }); + + // 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 (const auto &[a, v] : zip_equal(abbrev->attributes, ie.attrValues)) + if (a.Index == DW_IDX_parent && a.Form == DW_FORM_ref4) + v.attrValue = ie.parentEntry->poolOffset; + } + } + }); + + // Return (entry pool size, number of entries). + uint32_t num = 0; + for (auto &map : maps) + num += map.size(); + return {offsets[numShards - 1], num}; +} + +void DebugNamesBaseSection::init( + function_ref parseFile) { + TimeTraceScope timeScope("Merge .debug_names"); + // Collect and remove input .debug_names sections. Save InputSection pointers + // to relocate string offsets in `writeTo`. + SetVector files; + for (InputSectionBase *s : ctx.inputSections) { + InputSection *isec = dyn_cast(s); + if (!isec) + continue; + if (!(s->flags & SHF_ALLOC) && s->name == ".debug_names") { + s->markDead(); + inputSections.push_back(isec); + files.insert(isec->file); + } + } + + // 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(files.size()); + MutableArrayRef inputChunks(inputChunksPtr.get(), files.size()); + numChunks = files.size(); + chunks = std::make_unique(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 DebugNamesSection::DebugNamesSection() { + init([](InputFile *f, InputChunk &inputChunk, OutputChunk &chunk) { + auto *file = cast>(f); + DWARFContext dwarf(std::make_unique>(file)); + auto &dobj = static_cast &>(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))); + } + parseDebugNames( + inputChunk, chunk, namesExtractor, strExtractor, + [&chunk, namesData = dobj.getNamesSection().Data.data()]( + uint32_t numCus, const DWARFDebugNames::Header &hdr, + const DWARFDebugNames::DWARFDebugNamesOffsets &locs) { + // Read CU offsets, which are relocated by .debug_info + X + // relocations. Record the section offset to be relocated by + // `finalizeContents`. + chunk.compUnits.resize_for_overwrite(numCus + hdr.CompUnitCount); + for (auto i : seq(hdr.CompUnitCount)) + chunk.compUnits[numCus + i] = locs.CUsBase + i * 4; + + // Read entry offsets. + const char *p = namesData + locs.EntryOffsetsBase; + SmallVector entryOffsets; + entryOffsets.resize_for_overwrite(hdr.NameCount); + for (uint32_t &offset : entryOffsets) + offset = endian::readNext(p); + return entryOffsets; + }); + }); +} + +template +template +void DebugNamesSection::getNameRelocs( + InputSection *sec, ArrayRef rels, + DenseMap &relocs) { + for (const RelTy &rel : rels) { + Symbol &sym = sec->file->getRelocTargetSym(rel); + relocs[rel.r_offset] = sym.getVA(getAddend(rel)); + } +} + +template void DebugNamesSection::finalizeContents() { + // Get relocations of .debug_names sections. + auto relocs = std::make_unique[]>(numChunks); + parallelFor(0, numChunks, [&](size_t i) { + InputSection *sec = inputSections[i]; + auto rels = sec->template relsOrRelas(); + if (rels.areRelocsRel()) + getNameRelocs(sec, rels.rels, relocs.get()[i]); + else + getNameRelocs(sec, rels.relas, relocs.get()[i]); + + // Relocate CU offsets with .debug_info + X relocations. + OutputChunk &chunk = chunks.get()[i]; + for (auto [j, cuOffset] : enumerate(chunk.compUnits)) + cuOffset = relocs.get()[i].lookup(cuOffset); + }); + + // Relocate string offsets in the name table with .debug_str + X relocations. + parallelForEach(nameVecs, [&](auto &nameVec) { + for (NameEntry &ne : nameVec) + ne.stringOffset = relocs.get()[ne.chunkIdx].lookup(ne.stringOffset); + }); +} + +template void DebugNamesSection::writeTo(uint8_t *buf) { + [[maybe_unused]] const uint8_t *const beginBuf = buf; + // Write the header. + endian::writeNext(buf, hdr.UnitLength); + endian::writeNext(buf, hdr.Version); + buf += 2; // padding + endian::writeNext(buf, hdr.CompUnitCount); + endian::writeNext(buf, hdr.LocalTypeUnitCount); + endian::writeNext(buf, hdr.ForeignTypeUnitCount); + endian::writeNext(buf, hdr.BucketCount); + endian::writeNext(buf, hdr.NameCount); + endian::writeNext(buf, hdr.AbbrevTableSize); + endian::writeNext(buf, + hdr.AugmentationStringSize); + memcpy(buf, hdr.AugmentationString.c_str(), hdr.AugmentationString.size()); + buf += hdr.AugmentationStringSize; + + // Write the CU list. + for (auto &chunk : getChunks()) + for (uint32_t cuOffset : chunk.compUnits) + endian::writeNext(buf, cuOffset); + + // TODO: Write the local TU list, then the foreign TU list.. + + // Write the hash lookup table. + SmallVector, 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 &bucket : buckets) { + if (!bucket.empty()) + endian::write32(buf, bucketIdx); + buf += 4; + bucketIdx += bucket.size(); + } + // Write the hashes. + for (const SmallVector &bucket : buckets) + for (const NameEntry *e : bucket) + endian::writeNext(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 &bucket : buckets) + for (const NameEntry *ne : bucket) + endian::writeNext(buf, ne->stringOffset); + + // Then write the entry offsets. + for (const SmallVector &bucket : buckets) + for (const NameEntry *ne : bucket) + endian::writeNext(buf, ne->entryOffset); + + // Write the abbrev table. + buf = llvm::copy(abbrevTableBuf, buf); + + // 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) { + // Write all the entries for the string. + 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::writeNext(buf, value.attrValue); + break; + case 4: + endian::writeNext(buf, value.attrValue); + break; + default: + llvm_unreachable("invalid attrSize"); + } + } + } + ++buf; // index entry sentinel + } + } + assert(uint64_t(buf - beginBuf) == size); +} + GdbIndexSection::GdbIndexSection() : SyntheticSection(0, SHT_PROGBITS, 1, ".gdb_index") {} @@ -3863,6 +4467,7 @@ void InStruct::reset() { ppc32Got2.reset(); ibtPlt.reset(); relaPlt.reset(); + debugNames.reset(); gdbIndex.reset(); shStrTab.reset(); strTab.reset(); @@ -4272,6 +4877,11 @@ template void elf::createSyntheticSections() { if (config->andFeatures || !ctx.aarch64PauthAbiCoreInfo.empty()) add(*make()); + if (config->debugNames) { + in.debugNames = std::make_unique>(); + add(*in.debugNames); + } + if (config->gdbIndex) { in.gdbIndex = GdbIndexSection::create(); add(*in.gdbIndex); diff --git a/lld/ELF/SyntheticSections.h b/lld/ELF/SyntheticSections.h index 759b78668f546..995fd4b344b07 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,134 @@ class RelroPaddingSection final : public SyntheticSection { void writeTo(uint8_t *buf) override {} }; +// 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: + struct Abbrev : llvm::FoldingSetNode { + uint32_t code; + uint32_t tag; + SmallVector attributes; + + void Profile(llvm::FoldingSetNodeID &id) const; + }; + + struct AttrValue { + uint32_t attrValue; + uint8_t attrSize; + }; + + struct IndexEntry { + uint32_t abbrevCode; + uint32_t poolOffset; + union { + uint64_t parentOffset = 0; + IndexEntry *parentEntry; + }; + SmallVector attrValues; + }; + + struct NameEntry { + const char *name; + uint32_t hashValue; + uint32_t stringOffset; + uint32_t entryOffset; + // Used to relocate `stringOffset` in the merged section. + uint32_t chunkIdx; + SmallVector indexEntries; + + llvm::iterator_range< + llvm::pointee_iterator::iterator>> + entries() { + return llvm::make_pointee_range(indexEntries); + } + }; + + // 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 abbrevCodeMap; + SmallVector nameEntries; + }; + + // 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; + SmallVector nameData; + std::optional llvmDebugNames; + }; + + struct OutputChunk { + // Pointer to the .debug_info section that contains compile units, used to + // compute the relocated CU offsets. + InputSection *infoSec; + // This initially holds section offsets. After relocation, the section + // offsets are changed to CU offsets relative the the output section. + SmallVector compUnits; + }; + + DebugNamesBaseSection(); + size_t getSize() const override { return size; } + bool isNeeded() const override { return numChunks > 0; } + +protected: + void init(llvm::function_ref); + static void + parseDebugNames(InputChunk &inputChunk, OutputChunk &chunk, + llvm::DWARFDataExtractor &namesExtractor, + llvm::DataExtractor &strExtractor, + llvm::function_ref( + uint32_t numCUs, const llvm::DWARFDebugNames::Header &hdr, + const llvm::DWARFDebugNames::DWARFDebugNamesOffsets &)> + readOffsets); + void computeHdrAndAbbrevTable(MutableArrayRef inputChunks); + std::pair + computeEntryPool(MutableArrayRef inputChunks); + + // Input .debug_names sections for relocating string offsets in the name table + // in `finalizeContents`. + SmallVector inputSections; + + llvm::DWARFDebugNames::Header hdr; + size_t numChunks; + std::unique_ptr chunks; + llvm::SpecificBumpPtrAllocator abbrevAlloc; + SmallVector abbrevTable; + SmallVector abbrevTableBuf; + + ArrayRef getChunks() const { + return ArrayRef(chunks.get(), numChunks); + } + + // Sharded name entries that will be used to compute bucket_count and the + // count name table. + static constexpr size_t numShards = 32; + SmallVector nameVecs[numShards]; +}; + +// Complement DebugNamesBaseSection for ELFT-aware code: reading offsets, +// relocating string offsets, and writeTo. +template +class DebugNamesSection final : public DebugNamesBaseSection { +public: + DebugNamesSection(); + void finalizeContents() override; + void writeTo(uint8_t *buf) override; + + template + void getNameRelocs(InputSection *sec, ArrayRef rels, + llvm::DenseMap &relocs); + +private: + static void readOffsets(InputChunk &inputChunk, OutputChunk &chunk, + llvm::DWARFDataExtractor &namesExtractor, + llvm::DataExtractor &strExtractor); +}; + class GdbIndexSection final : public SyntheticSection { public: struct AddressEntry { @@ -1364,6 +1496,7 @@ struct InStruct { std::unique_ptr ibtPlt; std::unique_ptr relaPlt; // Non-SHF_ALLOC sections + std::unique_ptr debugNames; std::unique_ptr gdbIndex; std::unique_ptr shStrTab; std::unique_ptr strTab; diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp index d2a9e872dab91..240c16a4d8f69 100644 --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -1957,6 +1957,7 @@ template void Writer::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 bf0c8e55d103e..a7ed49726fd99 100644 --- a/lld/docs/ReleaseNotes.rst +++ b/lld/docs/ReleaseNotes.rst @@ -32,6 +32,9 @@ ELF Improvements * ``GNU_PROPERTY_AARCH64_FEATURE_PAUTH`` notes, ``R_AARCH64_AUTH_ABS64`` and ``R_AARCH64_AUTH_RELATIVE`` relocations are now supported. (`#72714 `_) +* ``--debug-names`` is added to create a merged ``.debug_names`` index + from input ``.debug_names`` sections. Type units are not handled yet. + (`#86508 `_) Breaking changes ---------------- diff --git a/lld/docs/ld.lld.1 b/lld/docs/ld.lld.1 index e0316730f442e..ba8ce8f784759 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-a.s b/lld/test/ELF/Inputs/debug-names-a.s new file mode 100644 index 0000000000000..0adc520e765ca --- /dev/null +++ b/lld/test/ELF/Inputs/debug-names-a.s @@ -0,0 +1,239 @@ +.ifdef GEN +#--- a.cc +struct t1 {}; +extern "C" void _start(t1) {} +#--- gen +clang --target=x86_64-linux -S -g -gpubnames a.cc -o - +.endif + .text + .file "a.cc" + .globl _start # -- Begin function _start + .p2align 4, 0x90 + .type _start,@function +_start: # @_start +.Lfunc_begin0: + .file 0 "/proc/self/cwd" "a.cc" md5 0x6835f89a7d36054002b51e54e47d852e + .loc 0 2 0 # a.cc:2:0 + .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: + .loc 0 2 29 prologue_end epilogue_begin # a.cc:2:29 + popq %rbp + .cfi_def_cfa %rsp, 8 + retq +.Ltmp1: +.Lfunc_end0: + .size _start, .Lfunc_end0-_start + .cfi_endproc + # -- End function + .section .debug_abbrev,"",@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 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 0 # EOM(3) + .section .debug_info,"",@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:0x34 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:0x16 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 + # DW_AT_external + .byte 3 # Abbrev [3] 0x2e: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 57 # DW_AT_type + .byte 0 # End Of Children Mark + .byte 4 # Abbrev [4] 0x39:0x6 DW_TAG_structure_type + .byte 5 # DW_AT_calling_convention + .byte 4 # 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,"",@progbits + .long 24 # Length of String Offsets Set + .short 5 + .short 0 +.Lstr_offsets_base0: + .section .debug_str,"MS",@progbits,1 +.Linfo_string0: + .byte 0 # string offset=0 +.Linfo_string1: + .asciz "a.cc" # string offset=1 +.Linfo_string2: + .asciz "/proc/self/cwd" # string offset=6 +.Linfo_string3: + .asciz "_start" # string offset=21 +.Linfo_string4: + .asciz "t1" # string offset=28 + .section .debug_str_offsets,"",@progbits + .long .Linfo_string0 + .long .Linfo_string1 + .long .Linfo_string2 + .long .Linfo_string3 + .long .Linfo_string4 + .section .debug_addr,"",@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,"",@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 0 # Bucket 1 + .long 5863786 # Hash in Bucket 0 + .long -304389582 # Hash in Bucket 0 + .long .Linfo_string4 # String in Bucket 0: t1 + .long .Linfo_string3 # String in Bucket 0: _start + .long .Lnames1-.Lnames_entries0 # Offset in Bucket 0 + .long .Lnames0-.Lnames_entries0 # Offset in Bucket 0 +.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 0 # End of abbrev list +.Lnames_abbrev_end0: +.Lnames_entries0: +.Lnames1: +.L1: + .byte 1 # Abbreviation code + .long 57 # DW_IDX_die_offset + .byte 0 # DW_IDX_parent + # End of list: t1 +.Lnames0: +.L0: + .byte 2 # Abbreviation code + .long 35 # DW_IDX_die_offset + .byte 0 # DW_IDX_parent + # End of list: _start + .p2align 2, 0x0 +.Lnames_end0: + .section ".note.GNU-stack","",@progbits + .addrsig + .section .debug_line,"",@progbits +.Lline_table_start0: diff --git a/lld/test/ELF/Inputs/debug-names-b.s b/lld/test/ELF/Inputs/debug-names-b.s new file mode 100644 index 0000000000000..2e3996742020b --- /dev/null +++ b/lld/test/ELF/Inputs/debug-names-b.s @@ -0,0 +1,358 @@ +.ifdef GEN +#--- b.cc +struct t1 { }; +namespace ns { +struct t2 {}; +} +int main() { t1 v1; ns::t2 v2; } +#--- gen +clang --target=x86_64-linux -S -g -gpubnames b.cc -o - +.endif + .text + .file "b.cc" + .globl main # -- Begin function main + .p2align 4, 0x90 + .type main,@function +main: # @main +.Lfunc_begin0: + .file 0 "/proc/self/cwd" "b.cc" md5 0xcb70125759dcd65dfed077164397a2f4 + .loc 0 5 0 # b.cc:5:0 + .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: + .loc 0 5 32 prologue_end # b.cc:5:32 + xorl %eax, %eax + .loc 0 5 32 epilogue_begin is_stmt 0 # b.cc:5:32 + popq %rbp + .cfi_def_cfa %rsp, 8 + retq +.Ltmp1: +.Lfunc_end0: + .size main, .Lfunc_end0-main + .cfi_endproc + # -- End function + .section .debug_abbrev,"",@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 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 3 # 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 19 # DW_FORM_ref4 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 4 # 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 5 # 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 6 # Abbreviation Code + .byte 57 # DW_TAG_namespace + .byte 1 # DW_CHILDREN_yes + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 0 # EOM(3) + .section .debug_info,"",@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:0x51 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:0x26 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 5 # DW_AT_decl_line + .long 73 # 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 5 # DW_AT_decl_line + .long 77 # DW_AT_type + .byte 3 # Abbrev [3] 0x3d:0xb DW_TAG_variable + .byte 2 # DW_AT_location + .byte 145 + .byte 126 + .byte 7 # DW_AT_name + .byte 0 # DW_AT_decl_file + .byte 5 # DW_AT_decl_line + .long 85 # DW_AT_type + .byte 0 # End Of Children Mark + .byte 4 # Abbrev [4] 0x49: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] 0x4d: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 6 # Abbrev [6] 0x53:0x9 DW_TAG_namespace + .byte 8 # DW_AT_name + .byte 5 # Abbrev [5] 0x55:0x6 DW_TAG_structure_type + .byte 5 # DW_AT_calling_convention + .byte 9 # DW_AT_name + .byte 1 # DW_AT_byte_size + .byte 0 # DW_AT_decl_file + .byte 3 # DW_AT_decl_line + .byte 0 # End Of Children Mark + .byte 0 # End Of Children Mark +.Ldebug_info_end0: + .section .debug_str_offsets,"",@progbits + .long 44 # Length of String Offsets Set + .short 5 + .short 0 +.Lstr_offsets_base0: + .section .debug_str,"MS",@progbits,1 +.Linfo_string0: + .byte 0 # string offset=0 +.Linfo_string1: + .asciz "b.cc" # string offset=1 +.Linfo_string2: + .asciz "/proc/self/cwd" # string offset=6 +.Linfo_string3: + .asciz "main" # string offset=21 +.Linfo_string4: + .asciz "int" # string offset=26 +.Linfo_string5: + .asciz "v1" # string offset=30 +.Linfo_string6: + .asciz "t1" # string offset=33 +.Linfo_string7: + .asciz "v2" # string offset=36 +.Linfo_string8: + .asciz "ns" # string offset=39 +.Linfo_string9: + .asciz "t2" # string offset=42 + .section .debug_str_offsets,"",@progbits + .long .Linfo_string0 + .long .Linfo_string1 + .long .Linfo_string2 + .long .Linfo_string3 + .long .Linfo_string4 + .long .Linfo_string5 + .long .Linfo_string6 + .long .Linfo_string7 + .long .Linfo_string8 + .long .Linfo_string9 + .section .debug_addr,"",@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,"",@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 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 0 # Bucket 0 + .long 1 # Bucket 1 + .long 3 # Bucket 2 + .long 4 # Bucket 3 + .long 5 # Bucket 4 + .long 5863786 # Hash in Bucket 1 + .long 2090499946 # Hash in Bucket 1 + .long 5863787 # Hash in Bucket 2 + .long 193495088 # Hash in Bucket 3 + .long 5863654 # Hash in Bucket 4 + .long .Linfo_string6 # String in Bucket 1: t1 + .long .Linfo_string3 # String in Bucket 1: main + .long .Linfo_string9 # String in Bucket 2: t2 + .long .Linfo_string4 # String in Bucket 3: int + .long .Linfo_string8 # String in Bucket 4: ns + .long .Lnames2-.Lnames_entries0 # Offset in Bucket 1 + .long .Lnames0-.Lnames_entries0 # Offset in Bucket 1 + .long .Lnames4-.Lnames_entries0 # Offset in Bucket 2 + .long .Lnames1-.Lnames_entries0 # Offset in Bucket 3 + .long .Lnames3-.Lnames_entries0 # Offset in Bucket 4 +.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 19 # DW_TAG_structure_type + .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 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 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 0 # End of abbrev list +.Lnames_abbrev_end0: +.Lnames_entries0: +.Lnames2: +.L4: + .byte 1 # Abbreviation code + .long 77 # 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 +.Lnames4: +.L3: + .byte 3 # Abbreviation code + .long 85 # DW_IDX_die_offset + .long .L1-.Lnames_entries0 # DW_IDX_parent + .byte 0 # End of list: t2 +.Lnames1: +.L0: + .byte 4 # Abbreviation code + .long 73 # DW_IDX_die_offset + .byte 0 # DW_IDX_parent + # End of list: int +.Lnames3: +.L1: + .byte 5 # Abbreviation code + .long 83 # DW_IDX_die_offset + .byte 0 # DW_IDX_parent + # End of list: ns + .p2align 2, 0x0 +.Lnames_end0: + .section ".note.GNU-stack","",@progbits + .addrsig + .section .debug_line,"",@progbits +.Lline_table_start0: diff --git a/lld/test/ELF/debug-names-bad.s b/lld/test/ELF/debug-names-bad.s new file mode 100644 index 0000000000000..69a7f753e971a --- /dev/null +++ b/lld/test/ELF/debug-names-bad.s @@ -0,0 +1,97 @@ +# REQUIRES: x86 +# RUN: rm -rf %t && mkdir %t && cd %t + +## Test errors in the header. +# RUN: sed '/Header: version/s/5/4/' %S/Inputs/debug-names-a.s > bad-version.s +# RUN: llvm-mc -filetype=obj -triple=x86_64 bad-version.s -o bad-version.o +# RUN: not ld.lld --debug-names bad-version.o 2>&1 | FileCheck %s --check-prefix=BAD-VERSION --implicit-check-not=error: + +# BAD-VERSION: error: bad-version.o:(.debug_names): unsupported version: 4 + +# RUN: sed '/Header: name count/s/[0-9]/4/' %S/Inputs/debug-names-a.s > bad-name-count.s +# RUN: llvm-mc -filetype=obj -triple=x86_64 bad-name-count.s -o bad-name-count.o +# RUN: not ld.lld --debug-names bad-name-count.o 2>&1 | FileCheck %s --check-prefix=BAD-NAME-COUNT --implicit-check-not=error: + +## Test errors in offsets. +# BAD-NAME-COUNT: error: bad-name-count.o:(.debug_names): Section too small: cannot read abbreviations. + +# RUN: sed '/Offset in Bucket/s/long/byte/' %S/Inputs/debug-names-a.s > entry-offset-in-byte.s +# RUN: llvm-mc -filetype=obj -triple=x86_64 entry-offset-in-byte.s -o entry-offset-in-byte.o +# RUN: not ld.lld --debug-names entry-offset-in-byte.o 2>&1 | FileCheck %s --check-prefix=ENTRY-OFFSET-IN-BYTE --implicit-check-not=error: + +# ENTRY-OFFSET-IN-BYTE-COUNT-2: error: entry-offset-in-byte.o:(.debug_names): index entry is out of bounds + +## Test errors in the abbrev table. +# RUN: sed -E '/DW_IDX_parent/{n;s/[0-9]+.*DW_FORM_flag_present/16/}' %S/Inputs/debug-names-a.s > bad-parent-form.s +# RUN: llvm-mc -filetype=obj -triple=x86_64 bad-parent-form.s -o bad-parent-form.o +# RUN: not ld.lld --debug-names bad-parent-form.o 2>&1 | FileCheck %s --check-prefix=BAD-PARENT-FORM --implicit-check-not=error: + +# BAD-PARENT-FORM: error: bad-parent-form.o:(.debug_names): invalid form for DW_IDX_parent + +# RUN: sed -E '/DW_IDX_die_offset/{n;s/[0-9]+.*DW_FORM_ref4/16/}' %S/Inputs/debug-names-a.s > bad-die-form.s +# RUN: llvm-mc -filetype=obj -triple=x86_64 bad-die-form.s -o bad-die-form.o +# RUN: not ld.lld --debug-names bad-die-form.o 2>&1 | FileCheck %s --check-prefix=BAD-DIE-FORM --implicit-check-not=error: + +# BAD-DIE-FORM: error: bad-die-form.o:(.debug_names): unrecognized form encoding 16 in abbrev table + +## Test errors in the entry pool. +# RUN: sed -E '/Lnames.:/{n;n;s/[0-9]+/3/}' %S/Inputs/debug-names-a.s > bad-abbrev-code.s +# RUN: llvm-mc -filetype=obj -triple=x86_64 bad-abbrev-code.s -o bad-abbrev-code.o +# RUN: not ld.lld --debug-names bad-abbrev-code.o 2>&1 | FileCheck %s --check-prefix=BAD-ABBREV-CODE --implicit-check-not=error: +# RUN: ld.lld --debug-names bad-abbrev-code.o -o bad-abbrev-code --noinhibit-exec +# RUN: llvm-dwarfdump --debug-names bad-abbrev-code | FileCheck %s --check-prefix=BAD-ABBREV-CODE-DWARF + +# BAD-ABBREV-CODE: error: bad-abbrev-code.o:(.debug_names): abbrev code not found in abbrev table: 3 + +# BAD-ABBREV-CODE-DWARF: Abbreviations [ +# BAD-ABBREV-CODE-DWARF-NEXT: Abbreviation 0x1 { +# BAD-ABBREV-CODE-DWARF-NEXT: Tag: DW_TAG_subprogram +# BAD-ABBREV-CODE-DWARF-NEXT: DW_IDX_die_offset: DW_FORM_ref4 +# BAD-ABBREV-CODE-DWARF-NEXT: DW_IDX_parent: DW_FORM_flag_present +# BAD-ABBREV-CODE-DWARF-NEXT: DW_IDX_compile_unit: DW_FORM_data1 +# BAD-ABBREV-CODE-DWARF-NEXT: } +# BAD-ABBREV-CODE-DWARF-NEXT: Abbreviation 0x2 { +# BAD-ABBREV-CODE-DWARF-NEXT: Tag: DW_TAG_structure_type +# BAD-ABBREV-CODE-DWARF-NEXT: DW_IDX_die_offset: DW_FORM_ref4 +# BAD-ABBREV-CODE-DWARF-NEXT: DW_IDX_parent: DW_FORM_flag_present +# BAD-ABBREV-CODE-DWARF-NEXT: DW_IDX_compile_unit: DW_FORM_data1 +# BAD-ABBREV-CODE-DWARF-NEXT: } +# BAD-ABBREV-CODE-DWARF-NEXT: ] +# BAD-ABBREV-CODE-DWARF: Bucket 0 +# BAD-ABBREV-CODE-DWARF-NOT: Entry + +# RUN: sed -E '/Lnames0:/{n;n;n;s/.*DW_IDX_die_offset.*//}' %S/Inputs/debug-names-a.s > missing-die-offset0.s +# RUN: llvm-mc -filetype=obj -triple=x86_64 missing-die-offset0.s -o missing-die-offset0.o +# RUN: ld.lld --debug-names missing-die-offset0.o --noinhibit-exec -o missing-die-offset0 2>&1 | FileCheck %s --check-prefix=MISSING-DIE-OFFSET0 + +# MISSING-DIE-OFFSET0: warning: missing-die-offset0.o:(.debug_names): index entry is out of bounds + +# RUN: sed -E '/Lnames1:/{n;n;n;s/.*DW_IDX_die_offset.*//}' %S/Inputs/debug-names-a.s > missing-die-offset1.s +# RUN: llvm-mc -filetype=obj -triple=x86_64 missing-die-offset1.s -o missing-die-offset1.o +# RUN: ld.lld --debug-names missing-die-offset1.o -o missing-die-offset1 +# RUN: llvm-dwarfdump --debug-names missing-die-offset1 | FileCheck %s --check-prefix=MISSING-DIE-OFFSET1 + +# MISSING-DIE-OFFSET1: Bucket 0 [ +# MISSING-DIE-OFFSET1-NEXT: Name 1 { +# MISSING-DIE-OFFSET1-NEXT: Hash: 0x59796A +# MISSING-DIE-OFFSET1-NEXT: String: {{.*}} "t1" +# MISSING-DIE-OFFSET1-NEXT: Entry @ 0x65 { +# MISSING-DIE-OFFSET1-NEXT: Abbrev: 0x2 +# MISSING-DIE-OFFSET1-NEXT: Tag: DW_TAG_structure_type +# MISSING-DIE-OFFSET1-NEXT: DW_IDX_die_offset: 0x00230200 +# MISSING-DIE-OFFSET1-NEXT: DW_IDX_parent: +# MISSING-DIE-OFFSET1-NEXT: DW_IDX_compile_unit: 0x00 +# MISSING-DIE-OFFSET1-NEXT: } +# MISSING-DIE-OFFSET1-NEXT: } +# MISSING-DIE-OFFSET1-NEXT: Name 2 { +# MISSING-DIE-OFFSET1-NEXT: Hash: 0xEDDB6232 +# MISSING-DIE-OFFSET1-NEXT: String: {{.*}} "_start" +# MISSING-DIE-OFFSET1-NEXT: Entry @ 0x6c { +# MISSING-DIE-OFFSET1-NEXT: Abbrev: 0x1 +# MISSING-DIE-OFFSET1-NEXT: Tag: DW_TAG_subprogram +# MISSING-DIE-OFFSET1-NEXT: DW_IDX_die_offset: 0x00000023 +# MISSING-DIE-OFFSET1-NEXT: DW_IDX_parent: +# MISSING-DIE-OFFSET1-NEXT: DW_IDX_compile_unit: 0x00 +# MISSING-DIE-OFFSET1-NEXT: } +# MISSING-DIE-OFFSET1-NEXT: } +# MISSING-DIE-OFFSET1-NEXT: ] diff --git a/lld/test/ELF/debug-names-die-offset-form-flag-present.s b/lld/test/ELF/debug-names-die-offset-form-flag-present.s new file mode 100644 index 0000000000000..1674498df7e30 --- /dev/null +++ b/lld/test/ELF/debug-names-die-offset-form-flag-present.s @@ -0,0 +1,152 @@ +# This file was generated by: +# 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 a.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 --implicit-check-not=error: %s + +# CHECK: error: [[FILE]]:(.debug_names): unrecognized form encoding 25 in abbrev table + + .text + .globl main # -- Begin function main + .p2align 4, 0x90 + .type main,@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,"",@progbits + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 0 # EOM(3) + .section .debug_info,"",@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,"",@progbits + .long 36 # Length of String Offsets Set + .short 5 + .short 0 +.Lstr_offsets_base0: + .section .debug_str,"MS",@progbits,1 +.Linfo_string0: + .asciz "clang version 19.0.0git (git@github.com:llvm/llvm-project.git 53b14cd9ce2b57da73d173fc876d2e9e199f5640)" # string offset=0 +.Linfo_string1: + .asciz "a.cpp" # string offset=104 +.Linfo_string2: + .asciz "/proc/self/cwd" # string offset=110 +.Linfo_string3: + .asciz "main" # string offset=125 +.Linfo_string4: + .asciz "int" # string offset=130 +.Linfo_string5: + .asciz "argc" # string offset=134 +.Linfo_string6: + .asciz "argv" # string offset=139 +.Linfo_string7: + .asciz "char" # string offset=144 +.Laddr_table_base0: + .quad .Lfunc_begin0 +.Ldebug_addr_end0: + .section .debug_names,"",@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@github.com:llvm/llvm-project.git 53b14cd9ce2b57da73d173fc876d2e9e199f5640)" + .section ".note.GNU-stack","",@progbits + .addrsig + .section .debug_line,"",@progbits +.Lline_table_start0: diff --git a/lld/test/ELF/debug-names-different-aug-string.s b/lld/test/ELF/debug-names-different-aug-string.s new file mode 100644 index 0000000000000..eb0c3fadf8a30 --- /dev/null +++ b/lld/test/ELF/debug-names-different-aug-string.s @@ -0,0 +1,14 @@ +# REQUIRES: x86 +# RUN: rm -rf %t && mkdir %t && cd %t +# RUN: sed 's/LLVM0700/LLVM9999/' %S/Inputs/debug-names-a.s | llvm-mc -filetype=obj -triple=x86_64 -o a.o +# RUN: llvm-mc -filetype=obj -triple=x86_64 %S/Inputs/debug-names-b.s -o b.o +# 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: +# DWARF: Name Index @ 0x0 { +# DWARF-NEXT: Header { +# DWARF-NEXT: Length: +# DWARF-NEXT: Format: DWARF32 +# DWARF-NEXT: Version: 5 +# DWARF: Augmentation: '' diff --git a/lld/test/ELF/debug-names-dwarf64.s b/lld/test/ELF/debug-names-dwarf64.s new file mode 100644 index 0000000000000..8261e9e2d01c7 --- /dev/null +++ b/lld/test/ELF/debug-names-dwarf64.s @@ -0,0 +1,250 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t.o +# RUN: not ld.lld --debug-names %t.o -o /dev/null 2>&1 | \ +# RUN: FileCheck -DFILE=%t.o --implicit-check-not=error: %s + +# CHECK: error: [[FILE]]:(.debug_names): found DWARF64, which is currently unsupported + +.ifdef GEN +//--- a.cc +struct t1 {}; +extern "C" void _start(t1) {} +//--- gen +clang --target=x86_64-linux -S -g -gpubnames -gdwarf64 a.cc -o - +.endif + .text + .file "a.cc" + .globl _start # -- Begin function _start + .p2align 4, 0x90 + .type _start,@function +_start: # @_start +.Lfunc_begin0: + .file 0 "/proc/self/cwd" "a.cc" md5 0x6835f89a7d36054002b51e54e47d852e + .loc 0 2 0 # a.cc:2:0 + .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: + .loc 0 2 29 prologue_end epilogue_begin # a.cc:2:29 + popq %rbp + .cfi_def_cfa %rsp, 8 + retq +.Ltmp1: +.Lfunc_end0: + .size _start, .Lfunc_end0-_start + .cfi_endproc + # -- End function + .section .debug_abbrev,"",@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 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 0 # EOM(3) + .section .debug_info,"",@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 + .byte 1 # Abbrev [1] 0x18:0x40 DW_TAG_compile_unit + .byte 0 # DW_AT_producer + .short 33 # DW_AT_language + .byte 1 # DW_AT_name + .quad .Lstr_offsets_base0 # DW_AT_str_offsets_base + .quad .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 + .quad .Laddr_table_base0 # DW_AT_addr_base + .byte 2 # Abbrev [2] 0x3b:0x16 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 + # DW_AT_external + .byte 3 # Abbrev [3] 0x46: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 81 # DW_AT_type + .byte 0 # End Of Children Mark + .byte 4 # Abbrev [4] 0x51:0x6 DW_TAG_structure_type + .byte 5 # DW_AT_calling_convention + .byte 4 # 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,"",@progbits + .long 4294967295 # DWARF64 Mark + .quad 44 # Length of String Offsets Set + .short 5 + .short 0 +.Lstr_offsets_base0: + .section .debug_str,"MS",@progbits,1 +.Linfo_string0: + .byte 0 # string offset=0 +.Linfo_string1: + .asciz "a.cc" # string offset=1 +.Linfo_string2: + .asciz "/proc/self/cwd" # string offset=6 +.Linfo_string3: + .asciz "_start" # string offset=21 +.Linfo_string4: + .asciz "t1" # string offset=28 + .section .debug_str_offsets,"",@progbits + .quad .Linfo_string0 + .quad .Linfo_string1 + .quad .Linfo_string2 + .quad .Linfo_string3 + .quad .Linfo_string4 + .section .debug_addr,"",@progbits + .long 4294967295 # DWARF64 Mark + .quad .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,"",@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 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 + .quad .Lcu_begin0 # Compilation unit 0 + .long 1 # Bucket 0 + .long 0 # Bucket 1 + .long 5863786 # Hash in Bucket 0 + .long -304389582 # Hash in Bucket 0 + .quad .Linfo_string4 # String in Bucket 0: t1 + .quad .Linfo_string3 # String in Bucket 0: _start + .quad .Lnames1-.Lnames_entries0 # Offset in Bucket 0 + .quad .Lnames0-.Lnames_entries0 # Offset in Bucket 0 +.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 0 # End of abbrev list +.Lnames_abbrev_end0: +.Lnames_entries0: +.Lnames1: +.L1: + .byte 1 # Abbreviation code + .long 81 # DW_IDX_die_offset + .byte 0 # DW_IDX_parent + # End of list: t1 +.Lnames0: +.L0: + .byte 2 # Abbreviation code + .long 59 # DW_IDX_die_offset + .byte 0 # DW_IDX_parent + # End of list: _start + .p2align 2, 0x0 +.Lnames_end0: + .section ".note.GNU-stack","",@progbits + .addrsig + .section .debug_line,"",@progbits +.Lline_table_start0: 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 0000000000000..7140157b01d84 --- /dev/null +++ b/lld/test/ELF/debug-names-missing-parent.s @@ -0,0 +1,234 @@ +# REQUIRES: x86 +## Test clang-17-generated DW_TAG_subprogram, which do not contain DW_IDX_parent +## attributes. + +# RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t.o +# RUN: ld.lld --debug-names %t.o -o %t +# RUN: llvm-dwarfdump --debug-info --debug-names %t | FileCheck %s --check-prefix=DWARF + +# DWARF: 0x00000023: DW_TAG_namespace +# DWARF: 0x00000025: DW_TAG_subprogram + +# DWARF: String: {{.*}} "fa" +# DWARF-NEXT: Entry @ 0x71 { +# DWARF-NEXT: Abbrev: 0x1 +# DWARF-NEXT: Tag: DW_TAG_subprogram +# DWARF-NEXT: DW_IDX_die_offset: 0x00000025 +# DWARF-NEXT: DW_IDX_compile_unit: 0x00 +# DWARF-NEXT: } +# DWARF: String: {{.*}} "ns" +# DWARF-NEXT: Entry @ 0x78 { +# DWARF-NEXT: Abbrev: 0x2 +# DWARF-NEXT: Tag: DW_TAG_namespace +# DWARF-NEXT: DW_IDX_die_offset: 0x00000023 +# DWARF-NEXT: DW_IDX_compile_unit: 0x00 +# DWARF-NEXT: } + +.ifdef GEN +//--- a.cc +namespace ns { +void fa() {} +} +//--- gen +clang-17 --target=x86_64-linux -S -O1 -g -gpubnames a.cc -o - +.endif + .text + .file "a.cc" + .globl _ZN2ns2faEv # -- Begin function _ZN2ns2faEv + .p2align 4, 0x90 + .type _ZN2ns2faEv,@function +_ZN2ns2faEv: # @_ZN2ns2faEv +.Lfunc_begin0: + .file 0 "/proc/self/cwd" "a.cc" md5 0xb3281d5b5a0b2997d7d59d49bc912274 + .cfi_startproc +# %bb.0: + .loc 0 2 12 prologue_end # a.cc:2:12 + retq +.Ltmp0: +.Lfunc_end0: + .size _ZN2ns2faEv, .Lfunc_end0-_ZN2ns2faEv + .cfi_endproc + # -- End function + .section .debug_abbrev,"",@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 57 # DW_TAG_namespace + .byte 1 # DW_CHILDREN_yes + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 3 # 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 122 # DW_AT_call_all_calls + .byte 25 # DW_FORM_flag_present + .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,"",@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:0x27 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:0xf DW_TAG_namespace + .byte 3 # DW_AT_name + .byte 3 # Abbrev [3] 0x25: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 87 + # DW_AT_call_all_calls + .byte 4 # DW_AT_linkage_name + .byte 5 # DW_AT_name + .byte 0 # DW_AT_decl_file + .byte 2 # DW_AT_decl_line + # DW_AT_external + .byte 0 # End Of Children Mark + .byte 0 # End Of Children Mark +.Ldebug_info_end0: + .section .debug_str_offsets,"",@progbits + .long 28 # Length of String Offsets Set + .short 5 + .short 0 +.Lstr_offsets_base0: + .section .debug_str,"MS",@progbits,1 +.Linfo_string0: + .byte 0 # string offset=0 +.Linfo_string1: + .asciz "a.cc" # string offset=1 +.Linfo_string2: + .asciz "/proc/self/cwd" # string offset=6 +.Linfo_string3: + .asciz "ns" # string offset=21 +.Linfo_string4: + .asciz "fa" # string offset=24 +.Linfo_string5: + .asciz "_ZN2ns2faEv" # string offset=27 + .section .debug_str_offsets,"",@progbits + .long .Linfo_string0 + .long .Linfo_string1 + .long .Linfo_string2 + .long .Linfo_string3 + .long .Linfo_string5 + .long .Linfo_string4 + .section .debug_addr,"",@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,"",@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 5863372 # Hash in Bucket 1 + .long 5863654 # Hash in Bucket 1 + .long -1413999533 # Hash in Bucket 2 + .long .Linfo_string4 # String in Bucket 1: fa + .long .Linfo_string3 # String in Bucket 1: ns + .long .Linfo_string5 # String in Bucket 2: _ZN2ns2faEv + .long .Lnames1-.Lnames_entries0 # Offset in Bucket 1 + .long .Lnames0-.Lnames_entries0 # Offset in Bucket 1 + .long .Lnames2-.Lnames_entries0 # Offset in Bucket 2 +.Lnames_abbrev_start0: + .byte 46 # 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 57 # Abbrev code + .byte 57 # DW_TAG_namespace + .byte 3 # DW_IDX_die_offset + .byte 19 # DW_FORM_ref4 + .byte 0 # End of abbrev + .byte 0 # End of abbrev + .byte 0 # End of abbrev list +.Lnames_abbrev_end0: +.Lnames_entries0: +.Lnames1: + .byte 46 # Abbreviation code + .long 37 # DW_IDX_die_offset + .byte 0 # End of list: fa +.Lnames0: + .byte 57 # Abbreviation code + .long 35 # DW_IDX_die_offset + .byte 0 # End of list: ns +.Lnames2: + .byte 46 # Abbreviation code + .long 37 # DW_IDX_die_offset + .byte 0 # End of list: _ZN2ns2faEv + .p2align 2, 0x0 +.Lnames_end0: + .section ".note.GNU-stack","",@progbits + .addrsig + .section .debug_line,"",@progbits +.Lline_table_start0: 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 0000000000000..78fcdc227ef25 --- /dev/null +++ b/lld/test/ELF/debug-names-multi-cus.s @@ -0,0 +1,789 @@ +# REQUIRES: x86 +## Test name indexes that contain multiple CU offsets due to LTO. + +# RUN: rm -rf %t && split-file %s %t && cd %t +# RUN: llvm-mc -filetype=obj -triple=x86_64 %S/Inputs/debug-names-a.s -o a.o +# RUN: llvm-mc -filetype=obj -triple=x86_64 bcd.s -o bcd.o +# RUN: llvm-mc -filetype=obj -triple=x86_64 ef.s -o ef.o +# RUN: ld.lld --debug-names a.o bcd.o ef.o -o out +# RUN: llvm-dwarfdump --debug-info --debug-names out | FileCheck %s --check-prefix=DWARF + +## Place the multiple CU offsets in the second name index in an input file. +# RUN: ld.lld -r a.o bcd.o -o abcd.o +# RUN: ld.lld --debug-names abcd.o ef.o -o out +# RUN: llvm-dwarfdump --debug-info --debug-names out | FileCheck %s --check-prefix=DWARF + +# DWARF: [[CU0:0x[^:]+]]: Compile Unit +# DWARF: [[CU1:0x[^:]+]]: Compile Unit +# DWARF: [[CU2:0x[^:]+]]: Compile Unit +# DWARF: [[CU3:0x[^:]+]]: Compile Unit +# DWARF: [[CU4:0x[^:]+]]: Compile Unit +# DWARF: [[CU5:0x[^:]+]]: Compile Unit +# DWARF: Compilation Unit offsets [ +# DWARF-NEXT: CU[0]: [[CU0]] +# DWARF-NEXT: CU[1]: [[CU1]] +# DWARF-NEXT: CU[2]: [[CU2]] +# DWARF-NEXT: CU[3]: [[CU3]] +# DWARF-NEXT: CU[4]: [[CU4]] +# DWARF-NEXT: CU[5]: [[CU5]] +# DWARF-NEXT: ] +# DWARF: String: {{.*}} "vc" +# DWARF: DW_IDX_compile_unit: 0x02 +# DWARF: String: {{.*}} "vd" +# DWARF: DW_IDX_die_offset: +# DWARF-SAME: 0x00000020 +# DWARF: DW_IDX_compile_unit: +# DWARF-SAME: 0x03 +# DWARF: String: {{.*}} "ve" +# DWARF: DW_IDX_die_offset: +# DWARF-SAME: 0x0000001e +# DWARF: DW_IDX_compile_unit: +# DWARF-SAME: 0x04 +# DWARF: String: {{.*}} "vf" +# DWARF: DW_IDX_compile_unit: +# DWARF-SAME: 0x05 +# DWARF: String: {{.*}} "vb" +# DWARF: DW_IDX_compile_unit: +# DWARF-SAME: 0x01 + +.ifdef GEN +#--- b.cc +[[gnu::used]] int vb; +#--- c.cc +[[gnu::used]] int vc; +#--- d.cc +namespace ns { +[[gnu::used]] int vd; +} + +//--- e.cc +[[gnu::used]] int ve; +//--- f.cc +namespace ns { +[[gnu::used]] int vf; +} + +#--- gen +clang --target=x86_64-linux -O1 -g -gpubnames -flto b.cc c.cc d.cc -nostdlib -fuse-ld=lld -Wl,--lto-emit-asm +echo '#--- bcd.s' +cat a.out.lto.s +clang --target=x86_64-linux -O1 -g -gpubnames -flto e.cc f.cc -nostdlib -fuse-ld=lld -Wl,--lto-emit-asm +echo '#--- ef.s' +cat a.out.lto.s +.endif +#--- bcd.s + .text + .file "ld-temp.o" + .file 1 "/proc/self/cwd" "b.cc" md5 0x78dad32a49063326a4de543198e54944 + .file 2 "/proc/self/cwd" "c.cc" md5 0x7a0f7bf2cb0ec8c297f794908d91ab1b + .file 3 "/proc/self/cwd" "d.cc" md5 0xf7e2af89615ce48bf9a98fdae55ab5ad + .type vb,@object # @vb + .section .bss.vb,"aw",@nobits + .globl vb + .p2align 2, 0x0 +vb: + .long 0 # 0x0 + .size vb, 4 + + .type vc,@object # @vc + .section .bss.vc,"aw",@nobits + .globl vc + .p2align 2, 0x0 +vc: + .long 0 # 0x0 + .size vc, 4 + + .type _ZN2ns2vdE,@object # @_ZN2ns2vdE + .section .bss._ZN2ns2vdE,"aw",@nobits + .globl _ZN2ns2vdE + .p2align 2, 0x0 +_ZN2ns2vdE: + .long 0 # 0x0 + .size _ZN2ns2vdE, 4 + + .section .debug_abbrev,"",@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 115 # DW_AT_addr_base + .byte 23 # DW_FORM_sec_offset + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 2 # Abbreviation Code + .byte 52 # DW_TAG_variable + .byte 0 # DW_CHILDREN_no + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 63 # DW_AT_external + .byte 25 # DW_FORM_flag_present + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 2 # DW_AT_location + .byte 24 # DW_FORM_exprloc + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 3 # 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 4 # Abbreviation Code + .byte 52 # DW_TAG_variable + .byte 0 # DW_CHILDREN_no + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 73 # DW_AT_type + .byte 16 # DW_FORM_ref_addr + .byte 63 # DW_AT_external + .byte 25 # DW_FORM_flag_present + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 2 # DW_AT_location + .byte 24 # DW_FORM_exprloc + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 5 # Abbreviation Code + .byte 57 # DW_TAG_namespace + .byte 1 # DW_CHILDREN_yes + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 6 # Abbreviation Code + .byte 52 # DW_TAG_variable + .byte 0 # DW_CHILDREN_no + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 73 # DW_AT_type + .byte 16 # DW_FORM_ref_addr + .byte 63 # DW_AT_external + .byte 25 # DW_FORM_flag_present + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 2 # DW_AT_location + .byte 24 # DW_FORM_exprloc + .byte 110 # DW_AT_linkage_name + .byte 37 # DW_FORM_strx1 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 0 # EOM(3) + .section .debug_info,"",@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:0x22 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 + .long .Laddr_table_base0 # DW_AT_addr_base + .byte 2 # Abbrev [2] 0x1e:0xb DW_TAG_variable + .byte 3 # DW_AT_name + .long 41 # DW_AT_type + # DW_AT_external + .byte 1 # DW_AT_decl_file + .byte 1 # DW_AT_decl_line + .byte 2 # DW_AT_location + .byte 161 + .byte 0 + .byte 3 # Abbrev [3] 0x29:0x4 DW_TAG_base_type + .byte 4 # DW_AT_name + .byte 5 # DW_AT_encoding + .byte 4 # DW_AT_byte_size + .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:0x1e DW_TAG_compile_unit + .byte 0 # DW_AT_producer + .short 33 # DW_AT_language + .byte 5 # 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 + .long .Laddr_table_base0 # DW_AT_addr_base + .byte 4 # Abbrev [4] 0x1e:0xb DW_TAG_variable + .byte 6 # DW_AT_name + .long .debug_info+41 # DW_AT_type + # DW_AT_external + .byte 2 # DW_AT_decl_file + .byte 1 # DW_AT_decl_line + .byte 2 # DW_AT_location + .byte 161 + .byte 1 + .byte 0 # End Of Children Mark +.Ldebug_info_end1: +.Lcu_begin2: + .long .Ldebug_info_end2-.Ldebug_info_start2 # Length of Unit +.Ldebug_info_start2: + .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:0x22 DW_TAG_compile_unit + .byte 0 # DW_AT_producer + .short 33 # DW_AT_language + .byte 7 # 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 + .long .Laddr_table_base0 # DW_AT_addr_base + .byte 5 # Abbrev [5] 0x1e:0xf DW_TAG_namespace + .byte 8 # DW_AT_name + .byte 6 # Abbrev [6] 0x20:0xc DW_TAG_variable + .byte 9 # DW_AT_name + .long .debug_info+41 # DW_AT_type + # DW_AT_external + .byte 3 # DW_AT_decl_file + .byte 2 # DW_AT_decl_line + .byte 2 # DW_AT_location + .byte 161 + .byte 2 + .byte 10 # DW_AT_linkage_name + .byte 0 # End Of Children Mark + .byte 0 # End Of Children Mark +.Ldebug_info_end2: + .section .debug_str_offsets,"",@progbits + .long 48 # Length of String Offsets Set + .short 5 + .short 0 +.Lstr_offsets_base0: + .section .debug_str,"MS",@progbits,1 +.Linfo_string0: + .byte 0 # string offset=0 +.Linfo_string1: + .asciz "b.cc" # string offset=1 +.Linfo_string2: + .asciz "/proc/self/cwd" # string offset=6 +.Linfo_string3: + .asciz "vb" # string offset=21 +.Linfo_string4: + .asciz "int" # string offset=24 +.Linfo_string5: + .asciz "c.cc" # string offset=28 +.Linfo_string6: + .asciz "vc" # string offset=33 +.Linfo_string7: + .asciz "d.cc" # string offset=36 +.Linfo_string8: + .asciz "ns" # string offset=41 +.Linfo_string9: + .asciz "vd" # string offset=44 +.Linfo_string10: + .asciz "_ZN2ns2vdE" # string offset=47 + .section .debug_str_offsets,"",@progbits + .long .Linfo_string0 + .long .Linfo_string1 + .long .Linfo_string2 + .long .Linfo_string3 + .long .Linfo_string4 + .long .Linfo_string5 + .long .Linfo_string6 + .long .Linfo_string7 + .long .Linfo_string8 + .long .Linfo_string9 + .long .Linfo_string10 + .section .debug_addr,"",@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 vb + .quad vc + .quad _ZN2ns2vdE +.Ldebug_addr_end0: + .section .debug_names,"",@progbits + .long .Lnames_end0-.Lnames_start0 # Header: unit length +.Lnames_start0: + .short 5 # Header: version + .short 0 # Header: padding + .long 3 # 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 .Lcu_begin1 # Compilation unit 1 + .long .Lcu_begin2 # Compilation unit 2 + .long 1 # Bucket 0 + .long 2 # Bucket 1 + .long 3 # Bucket 2 + .long 0 # Bucket 3 + .long 4 # Bucket 4 + .long 6 # Bucket 5 + .long 5863902 # Hash in Bucket 0 + .long 5863903 # Hash in Bucket 1 + .long 193495088 # Hash in Bucket 2 + .long 5863654 # Hash in Bucket 4 + .long -823734096 # Hash in Bucket 4 + .long 5863901 # Hash in Bucket 5 + .long .Linfo_string6 # String in Bucket 0: vc + .long .Linfo_string9 # String in Bucket 1: vd + .long .Linfo_string4 # String in Bucket 2: int + .long .Linfo_string8 # String in Bucket 4: ns + .long .Linfo_string10 # String in Bucket 4: _ZN2ns2vdE + .long .Linfo_string3 # String in Bucket 5: vb + .long .Lnames2-.Lnames_entries0 # Offset in Bucket 0 + .long .Lnames4-.Lnames_entries0 # Offset in Bucket 1 + .long .Lnames0-.Lnames_entries0 # Offset in Bucket 2 + .long .Lnames3-.Lnames_entries0 # Offset in Bucket 4 + .long .Lnames5-.Lnames_entries0 # Offset in Bucket 4 + .long .Lnames1-.Lnames_entries0 # Offset in Bucket 5 +.Lnames_abbrev_start0: + .byte 1 # Abbrev code + .byte 52 # DW_TAG_variable + .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 52 # DW_TAG_variable + .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 19 # DW_FORM_ref4 + .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 4 # Abbrev code + .byte 57 # DW_TAG_namespace + .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: +.Lnames2: +.L0: + .byte 1 # Abbreviation code + .byte 1 # DW_IDX_compile_unit + .long 30 # DW_IDX_die_offset + .byte 0 # DW_IDX_parent + # End of list: vc +.Lnames4: +.L4: + .byte 2 # Abbreviation code + .byte 2 # DW_IDX_compile_unit + .long 32 # DW_IDX_die_offset + .long .L2-.Lnames_entries0 # DW_IDX_parent + .byte 0 # End of list: vd +.Lnames0: +.L3: + .byte 3 # Abbreviation code + .byte 0 # DW_IDX_compile_unit + .long 41 # DW_IDX_die_offset + .byte 0 # DW_IDX_parent + # End of list: int +.Lnames3: +.L2: + .byte 4 # Abbreviation code + .byte 2 # DW_IDX_compile_unit + .long 30 # DW_IDX_die_offset + .byte 0 # DW_IDX_parent + # End of list: ns +.Lnames5: + .byte 2 # Abbreviation code + .byte 2 # DW_IDX_compile_unit + .long 32 # DW_IDX_die_offset + .long .L2-.Lnames_entries0 # DW_IDX_parent + .byte 0 # End of list: _ZN2ns2vdE +.Lnames1: +.L1: + .byte 1 # Abbreviation code + .byte 0 # DW_IDX_compile_unit + .long 30 # DW_IDX_die_offset + .byte 0 # DW_IDX_parent + # End of list: vb + .p2align 2, 0x0 +.Lnames_end0: + .section ".note.GNU-stack","",@progbits + .addrsig + .addrsig_sym vb + .addrsig_sym vc + .addrsig_sym _ZN2ns2vdE + .section .debug_line,"",@progbits +.Lline_table_start0: +#--- ef.s + .text + .file "ld-temp.o" + .file 1 "/proc/self/cwd" "e.cc" md5 0xa8d6c645998197bd15436f2a351ebd6a + .file 2 "/proc/self/cwd" "f.cc" md5 0x6ec1ec6b7f003f84cb0bf3409e65b085 + .type ve,@object # @ve + .section .bss.ve,"aw",@nobits + .globl ve + .p2align 2, 0x0 +ve: + .long 0 # 0x0 + .size ve, 4 + + .type _ZN2ns2vfE,@object # @_ZN2ns2vfE + .section .bss._ZN2ns2vfE,"aw",@nobits + .globl _ZN2ns2vfE + .p2align 2, 0x0 +_ZN2ns2vfE: + .long 0 # 0x0 + .size _ZN2ns2vfE, 4 + + .section .debug_abbrev,"",@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 115 # DW_AT_addr_base + .byte 23 # DW_FORM_sec_offset + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 2 # Abbreviation Code + .byte 52 # DW_TAG_variable + .byte 0 # DW_CHILDREN_no + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 63 # DW_AT_external + .byte 25 # DW_FORM_flag_present + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 2 # DW_AT_location + .byte 24 # DW_FORM_exprloc + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 3 # 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 4 # Abbreviation Code + .byte 57 # DW_TAG_namespace + .byte 1 # DW_CHILDREN_yes + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 5 # Abbreviation Code + .byte 52 # DW_TAG_variable + .byte 0 # DW_CHILDREN_no + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 73 # DW_AT_type + .byte 16 # DW_FORM_ref_addr + .byte 63 # DW_AT_external + .byte 25 # DW_FORM_flag_present + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 2 # DW_AT_location + .byte 24 # DW_FORM_exprloc + .byte 110 # DW_AT_linkage_name + .byte 37 # DW_FORM_strx1 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 0 # EOM(3) + .section .debug_info,"",@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:0x22 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 + .long .Laddr_table_base0 # DW_AT_addr_base + .byte 2 # Abbrev [2] 0x1e:0xb DW_TAG_variable + .byte 3 # DW_AT_name + .long 41 # DW_AT_type + # DW_AT_external + .byte 1 # DW_AT_decl_file + .byte 1 # DW_AT_decl_line + .byte 2 # DW_AT_location + .byte 161 + .byte 0 + .byte 3 # Abbrev [3] 0x29:0x4 DW_TAG_base_type + .byte 4 # DW_AT_name + .byte 5 # DW_AT_encoding + .byte 4 # DW_AT_byte_size + .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:0x22 DW_TAG_compile_unit + .byte 0 # DW_AT_producer + .short 33 # DW_AT_language + .byte 5 # 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 + .long .Laddr_table_base0 # DW_AT_addr_base + .byte 4 # Abbrev [4] 0x1e:0xf DW_TAG_namespace + .byte 6 # DW_AT_name + .byte 5 # Abbrev [5] 0x20:0xc DW_TAG_variable + .byte 7 # DW_AT_name + .long .debug_info+41 # DW_AT_type + # DW_AT_external + .byte 2 # DW_AT_decl_file + .byte 2 # DW_AT_decl_line + .byte 2 # DW_AT_location + .byte 161 + .byte 1 + .byte 8 # DW_AT_linkage_name + .byte 0 # End Of Children Mark + .byte 0 # End Of Children Mark +.Ldebug_info_end1: + .section .debug_str_offsets,"",@progbits + .long 40 # Length of String Offsets Set + .short 5 + .short 0 +.Lstr_offsets_base0: + .section .debug_str,"MS",@progbits,1 +.Linfo_string0: + .byte 0 # string offset=0 +.Linfo_string1: + .asciz "e.cc" # string offset=1 +.Linfo_string2: + .asciz "/proc/self/cwd" # string offset=6 +.Linfo_string3: + .asciz "ve" # string offset=21 +.Linfo_string4: + .asciz "int" # string offset=24 +.Linfo_string5: + .asciz "f.cc" # string offset=28 +.Linfo_string6: + .asciz "ns" # string offset=33 +.Linfo_string7: + .asciz "vf" # string offset=36 +.Linfo_string8: + .asciz "_ZN2ns2vfE" # string offset=39 + .section .debug_str_offsets,"",@progbits + .long .Linfo_string0 + .long .Linfo_string1 + .long .Linfo_string2 + .long .Linfo_string3 + .long .Linfo_string4 + .long .Linfo_string5 + .long .Linfo_string6 + .long .Linfo_string7 + .long .Linfo_string8 + .section .debug_addr,"",@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 ve + .quad _ZN2ns2vfE +.Ldebug_addr_end0: + .section .debug_names,"",@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 1 # Bucket 0 + .long 2 # Bucket 1 + .long 0 # Bucket 2 + .long 3 # Bucket 3 + .long 4 # Bucket 4 + .long 5863905 # Hash in Bucket 0 + .long -823734030 # Hash in Bucket 1 + .long 193495088 # Hash in Bucket 3 + .long 5863654 # Hash in Bucket 4 + .long 5863904 # Hash in Bucket 4 + .long .Linfo_string7 # String in Bucket 0: vf + .long .Linfo_string8 # String in Bucket 1: _ZN2ns2vfE + .long .Linfo_string4 # String in Bucket 3: int + .long .Linfo_string6 # String in Bucket 4: ns + .long .Linfo_string3 # String in Bucket 4: ve + .long .Lnames3-.Lnames_entries0 # Offset in Bucket 0 + .long .Lnames4-.Lnames_entries0 # Offset in Bucket 1 + .long .Lnames0-.Lnames_entries0 # Offset in Bucket 3 + .long .Lnames2-.Lnames_entries0 # Offset in Bucket 4 + .long .Lnames1-.Lnames_entries0 # Offset in Bucket 4 +.Lnames_abbrev_start0: + .byte 1 # Abbrev code + .byte 52 # DW_TAG_variable + .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 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 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 57 # DW_TAG_namespace + .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 4 # Abbrev code + .byte 52 # DW_TAG_variable + .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: +.Lnames3: +.L2: + .byte 1 # Abbreviation code + .byte 1 # DW_IDX_compile_unit + .long 32 # DW_IDX_die_offset + .long .L0-.Lnames_entries0 # DW_IDX_parent + .byte 0 # End of list: vf +.Lnames4: + .byte 1 # Abbreviation code + .byte 1 # DW_IDX_compile_unit + .long 32 # DW_IDX_die_offset + .long .L0-.Lnames_entries0 # DW_IDX_parent + .byte 0 # End of list: _ZN2ns2vfE +.Lnames0: +.L3: + .byte 2 # Abbreviation code + .byte 0 # DW_IDX_compile_unit + .long 41 # DW_IDX_die_offset + .byte 0 # DW_IDX_parent + # End of list: int +.Lnames2: +.L0: + .byte 3 # Abbreviation code + .byte 1 # DW_IDX_compile_unit + .long 30 # DW_IDX_die_offset + .byte 0 # DW_IDX_parent + # End of list: ns +.Lnames1: +.L1: + .byte 4 # Abbreviation code + .byte 0 # DW_IDX_compile_unit + .long 30 # DW_IDX_die_offset + .byte 0 # DW_IDX_parent + # End of list: ve + .p2align 2, 0x0 +.Lnames_end0: + .section ".note.GNU-stack","",@progbits + .addrsig + .addrsig_sym ve + .addrsig_sym _ZN2ns2vfE + .section .debug_line,"",@progbits +.Lline_table_start0: diff --git a/lld/test/ELF/debug-names-nonames.s b/lld/test/ELF/debug-names-nonames.s new file mode 100644 index 0000000000000..54b7c864fa825 --- /dev/null +++ b/lld/test/ELF/debug-names-nonames.s @@ -0,0 +1,33 @@ +# REQUIRES: x86 +# RUN: rm -rf %t && mkdir %t && cd %t +# RUN: llvm-mc -filetype=obj -triple=x86_64 %S/Inputs/debug-names-a.s -o a.o +# RUN: echo '.globl foo; foo:' | llvm-mc -filetype=obj -triple=x86_64 - -o b0.o + +# RUN: ld.lld --debug-names a.o b0.o -o out0 +# RUN: llvm-dwarfdump -debug-names out0 | FileCheck %s --check-prefix=DWARF + +# DWARF: .debug_names contents: +# DWARF-NEXT: Name Index @ 0x0 { +# DWARF-NEXT: Header { +# DWARF-NEXT: Length: 0x6F +# 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: 2 +# DWARF-NEXT: Name count: 2 +# DWARF-NEXT: Abbreviations table size: 0x15 +# DWARF-NEXT: Augmentation: 'LLVM0700' +# DWARF-NEXT: } +# DWARF-NEXT: Compilation Unit offsets [ +# DWARF-NEXT: CU[0]: 0x00000000 +# DWARF-NEXT: ] + +## Test both files without .debug_names. +# RUN: echo '.globl _start; _start:' | llvm-mc -filetype=obj -triple=x86_64 - -o a0.o +# RUN: ld.lld --debug-names a0.o b0.o -o out1 +# RUN: llvm-readelf -SW out1 | FileCheck %s --check-prefix=ELF + +# ELF: Name Type Address Off Size ES Flg Lk Inf Al +# ELF-NOT: .debug_names 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 0000000000000..64551aa02e59f --- /dev/null +++ b/lld/test/ELF/debug-names-parent-idx.s @@ -0,0 +1,746 @@ +# debug-names-parent-idx.s generated with: + +# clang++ -g -O0 -gpubnames -fdebug-compilation-dir='/proc/self/cwd' -S \ +# a.cpp -o a.s + +# foo.h contents: + +# int foo(); + +# struct foo { +# int x; +# char y; +# struct foo *foo_ptr; +# }; + +# namespace parent_test { +# int foo(); +# } + +# a.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: 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 a.o b.o -o out + +# RUN: llvm-dwarfdump -debug-names out | FileCheck %s --check-prefix=DWARF + +# 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: 0x00000174 "_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: 0x00000160 "_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: +# 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: 0x00000093 "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: +# 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: +# 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: 0x0000007d "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: +# DWARF-NEXT: DW_IDX_compile_unit: 0x00 +# DWARF-NEXT: } +# DWARF-NEXT: } +# DWARF-NEXT: Name 5 { +# DWARF-NEXT: Hash: 0xB887389 +# DWARF-NEXT: String: 0x00000097 "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: +# 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: +# 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: +# 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: 0x0000008e "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: +# 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: 0x00000168 "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: +# DWARF-NEXT: DW_IDX_compile_unit: 0x01 +# DWARF-NEXT: } +# DWARF-NEXT: } +# DWARF-NEXT: Name 8 { +# DWARF-NEXT: Hash: 0x51007E98 +# DWARF-NEXT: String: 0x00000081 "_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: +# DWARF-NEXT: DW_IDX_compile_unit: 0x00 +# DWARF-NEXT: } +# DWARF-NEXT: } +# DWARF-NEXT: Name 9 { +# DWARF-NEXT: Hash: 0x7C952063 +# DWARF-NEXT: String: 0x0000009f "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: +# 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: +# DWARF-NEXT: DW_IDX_compile_unit: 0x01 +# DWARF-NEXT: } +# DWARF-NEXT: } +# DWARF-NEXT: ] + +#--- a.s + .text + .globl _Z3barR3fooi # -- Begin function _Z3barR3fooi + .p2align 4, 0x90 + .type _Z3barR3fooi,@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,@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@PLT + movl %eax, -36(%rbp) + movl -36(%rbp), %esi + leaq -32(%rbp), %rdi + callq _Z3barR3fooi + callq _ZN11parent_test3fooEv@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,"",@progbits + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 0 # EOM(3) + .section .debug_info,"",@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,"",@progbits + .long 72 # Length of String Offsets Set + .short 5 + .short 0 +.Lstr_offsets_base0: + .section .debug_str,"MS",@progbits,1 +.Linfo_string0: + .asciz "clang version 19.0.0git (git@github.com:llvm/llvm-project.git 53b14cd9ce2b57da73d173fc876d2e9e199f5640)" # string offset=0 +.Linfo_string1: + .asciz "a.cpp" # string offset=104 +.Linfo_string2: + .asciz "/proc/self/cwd" # string offset=110 +.Linfo_string3: + .asciz "bar" # string offset=125 +.Linfo_string4: + .asciz "_Z3barR3fooi" # string offset=129 +.Linfo_string5: + .asciz "main" # string offset=142 +.Linfo_string6: + .asciz "int" # string offset=147 +.Linfo_string7: + .asciz "foo" # string offset=151 +.Linfo_string8: + .asciz "x" # string offset=155 +.Linfo_string9: + .asciz "y" # string offset=157 +.Linfo_string10: + .asciz "char" # string offset=159 +.Linfo_string11: + .asciz "foo_ptr" # string offset=164 +.Linfo_string12: + .asciz "junk" # string offset=172 +.Linfo_string13: + .asciz "argc" # string offset=177 +.Linfo_string14: + .asciz "argv" # string offset=182 +.Linfo_string15: + .asciz "my_struct" # string offset=187 +.Linfo_string16: + .asciz "junk2" # string offset=197 +.Laddr_table_base0: + .quad .Lfunc_begin0 + .quad .Lfunc_begin1 +.Ldebug_addr_end0: + .section .debug_names,"",@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@github.com:llvm/llvm-project.git 53b14cd9ce2b57da73d173fc876d2e9e199f5640)" + .section ".note.GNU-stack","",@progbits + .addrsig + .addrsig_sym _Z3barR3fooi + .addrsig_sym _Z3foov + .addrsig_sym _ZN11parent_test3fooEv + .section .debug_line,"",@progbits +.Lline_table_start0: + +#--- b.s +# Generated with: + +# clang++ -g -O0 -gpubnames -fdebug-compilation-dir='/proc/self/cwd' -S \ +# b.cpp -o b.s + +# foo.h contents: + +# int foo(); + +#struct foo { +# int x; +# char y; +# struct foo *foo_ptr; +# }; + +# namespace parent_test { +# int foo(); +# } + +# b.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,@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,@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,"",@progbits + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 0 # EOM(3) + .section .debug_info,"",@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,"",@progbits + .long 56 # Length of String Offsets Set + .short 5 + .short 0 +.Lstr_offsets_base0: + .section .debug_str,"MS",@progbits,1 +.Linfo_string0: + .asciz "clang version 19.0.0git (git@github.com:llvm/llvm-project.git 53b14cd9ce2b57da73d173fc876d2e9e199f5640)" # string offset=0 +.Linfo_string1: + .asciz "b.cpp" # string offset=104 +.Linfo_string2: + .asciz "/proc/self/cwd" # string offset=110 +.Linfo_string3: + .asciz "int" # string offset=125 +.Linfo_string4: + .asciz "foo" # string offset=129 +.Linfo_string5: + .asciz "_Z3foov" # string offset=133 +.Linfo_string6: + .asciz "parent_test" # string offset=141 +.Linfo_string7: + .asciz "_ZN11parent_test3fooEv" # string offset=153 +.Linfo_string8: + .asciz "struct2" # string offset=176 +.Linfo_string9: + .asciz "x" # string offset=184 +.Linfo_string10: + .asciz "y" # string offset=186 +.Linfo_string11: + .asciz "char" # string offset=188 +.Linfo_string12: + .asciz "foo_ptr" # string offset=193 +.Laddr_table_base0: + .quad .Lfunc_begin0 + .quad .Lfunc_begin1 +.Ldebug_addr_end0: + .section .debug_names,"",@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@github.com:llvm/llvm-project.git 53b14cd9ce2b57da73d173fc876d2e9e199f5640)" + .section ".note.GNU-stack","",@progbits + .addrsig + .section .debug_line,"",@progbits +.Lline_table_start0: diff --git a/lld/test/ELF/debug-names-type-units.s b/lld/test/ELF/debug-names-type-units.s new file mode 100644 index 0000000000000..dda065b238d85 --- /dev/null +++ b/lld/test/ELF/debug-names-type-units.s @@ -0,0 +1,895 @@ +# REQUIRES: x86 +# RUN: rm -rf %t && split-file %s %t && cd %t +# RUN: llvm-mc -filetype=obj -triple=x86_64 a.tu.s -o a.tu.o +# RUN: llvm-mc -filetype=obj -triple=x86_64 a.foreign-tu.s -o a.foreign-tu.o +# RUN: llvm-mc -filetype=obj -triple=x86_64 b.s -o b.o + +# RUN: ld.lld --debug-names a.tu.o b.o -o out0 2>&1 | FileCheck --check-prefix=WARN %s +# RUN: llvm-dwarfdump --debug-names out0 | FileCheck --check-prefix=DWARF %s + +# WARN: warning: a.tu.o:(.debug_names): type units are not implemented + +# DWARF: CU count: 2 +# DWARF-NEXT: Local TU count: 0 +# DWARF-NEXT: Foreign TU count: 0 +# DWARF: Compilation Unit offsets [ +# DWARF-NEXT: CU[0]: +# DWARF-SAME: 0x0000002a +# DWARF-NEXT: CU[1]: +# DWARF-SAME: 0x0000006a +# DWARF-NEXT: ] +# DWARF: String: {{.*}} "t1" +# DWARF-NEXT: Entry @ 0x8f { +# DWARF-NEXT: Abbrev: 0x2 +# DWARF-NEXT: Tag: DW_TAG_structure_type +# DWARF-NEXT: DW_IDX_type_unit: 0x00 +# DWARF-NEXT: DW_IDX_die_offset: 0x00000023 +# DWARF-NEXT: DW_IDX_parent: +# DWARF-NEXT: DW_IDX_compile_unit: 0x00 +# DWARF-NEXT: } +# DWARF-NEXT: Entry @ 0x96 { +# DWARF-NEXT: Abbrev: 0x1 +# DWARF-NEXT: Tag: DW_TAG_structure_type +# DWARF-NEXT: DW_IDX_die_offset: 0x00000036 +# DWARF-NEXT: DW_IDX_parent: +# DWARF-NEXT: DW_IDX_compile_unit: 0x00 +# DWARF-NEXT: } +# DWARF-NEXT: Entry @ 0x9c { +# DWARF-NEXT: Abbrev: 0x1 +# DWARF-NEXT: Tag: DW_TAG_structure_type +# DWARF-NEXT: DW_IDX_die_offset: 0x00000029 +# DWARF-NEXT: DW_IDX_parent: +# DWARF-NEXT: DW_IDX_compile_unit: 0x01 +# DWARF-NEXT: } + +# RUN: ld.lld --debug-names a.foreign-tu.o b.o -o out1 2>&1 | FileCheck %s --check-prefix=WARN2 +# RUN: llvm-dwarfdump --debug-names out1 | FileCheck --check-prefix=DWARF2 %s + +# WARN2: warning: a.foreign-tu.o:(.debug_names): type units are not implemented + +# DWARF2: CU count: 2 +# DWARF2-NEXT: Local TU count: 0 +# DWARF2-NEXT: Foreign TU count: 0 +# DWARF2: Compilation Unit offsets [ +# DWARF2-NEXT: CU[0]: +# DWARF2-SAME: 0x00000000 +# DWARF2-NEXT: CU[1]: +# DWARF2-SAME: 0x00000028 +# DWARF2-NEXT: ] + +.ifdef GEN +#--- a.cc +struct t1 {}; +extern "C" void _start(t1) {} +#--- b.cc +struct t1 { } vb; +#--- gen +echo '#--- a.tu.s' +clang --target=x86_64-linux -S -O1 -g -gpubnames -fdebug-types-section a.cc -o - +echo '#--- a.foreign-tu.s' +clang --target=x86_64-linux -S -O1 -g -gpubnames -fdebug-types-section -gsplit-dwarf a.cc -o - +echo '#--- b.s' +clang --target=x86_64-linux -S -O1 -g -gpubnames b.cc -o - +.endif +#--- a.tu.s + .text + .file "a.cc" + .globl _start # -- Begin function _start + .p2align 4, 0x90 + .type _start,@function +_start: # @_start +.Lfunc_begin0: + .file 0 "/proc/self/cwd" "a.cc" md5 0x6835f89a7d36054002b51e54e47d852e + .cfi_startproc +# %bb.0: # %entry + .loc 0 2 29 prologue_end # a.cc:2:29 + retq +.Ltmp0: +.Lfunc_end0: + .size _start, .Lfunc_end0-_start + .cfi_endproc + # -- End function + .section .debug_info,"G",@progbits,14297044602779165170,comdat +.Ltu_begin0: + .long .Ldebug_info_end0-.Ldebug_info_start0 # Length of Unit +.Ldebug_info_start0: + .short 5 # DWARF version number + .byte 2 # DWARF Unit Type + .byte 8 # Address Size (in bytes) + .long .debug_abbrev # Offset Into Abbrev. Section + .quad -4149699470930386446 # Type Signature + .long 35 # Type DIE Offset + .byte 1 # Abbrev [1] 0x18:0x12 DW_TAG_type_unit + .short 33 # DW_AT_language + .long .Lline_table_start0 # DW_AT_stmt_list + .long .Lstr_offsets_base0 # DW_AT_str_offsets_base + .byte 2 # Abbrev [2] 0x23:0x6 DW_TAG_structure_type + .byte 5 # DW_AT_calling_convention + .byte 4 # 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_abbrev,"",@progbits + .byte 1 # Abbreviation Code + .byte 65 # DW_TAG_type_unit + .byte 1 # DW_CHILDREN_yes + .byte 19 # DW_AT_language + .byte 5 # DW_FORM_data2 + .byte 16 # DW_AT_stmt_list + .byte 23 # DW_FORM_sec_offset + .byte 114 # DW_AT_str_offsets_base + .byte 23 # DW_FORM_sec_offset + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 2 # 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 3 # 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 4 # 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 122 # DW_AT_call_all_calls + .byte 25 # DW_FORM_flag_present + .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 5 # Abbreviation Code + .byte 5 # DW_TAG_formal_parameter + .byte 0 # DW_CHILDREN_no + .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 6 # Abbreviation Code + .byte 19 # DW_TAG_structure_type + .byte 0 # DW_CHILDREN_no + .byte 60 # DW_AT_declaration + .byte 25 # DW_FORM_flag_present + .byte 105 # DW_AT_signature + .byte 32 # DW_FORM_ref_sig8 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 0 # EOM(3) + .section .debug_info,"",@progbits +.Lcu_begin0: + .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 3 # Abbrev [3] 0xc:0x34 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 4 # Abbrev [4] 0x23:0x13 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 87 + # DW_AT_call_all_calls + .byte 3 # DW_AT_name + .byte 0 # DW_AT_decl_file + .byte 2 # DW_AT_decl_line + # DW_AT_external + .byte 5 # Abbrev [5] 0x2e:0x7 DW_TAG_formal_parameter + .byte 0 # DW_AT_decl_file + .byte 2 # DW_AT_decl_line + .long 54 # DW_AT_type + .byte 0 # End Of Children Mark + .byte 6 # Abbrev [6] 0x36:0x9 DW_TAG_structure_type + # DW_AT_declaration + .quad -4149699470930386446 # DW_AT_signature + .byte 0 # End Of Children Mark +.Ldebug_info_end1: + .section .debug_str_offsets,"",@progbits + .long 24 # Length of String Offsets Set + .short 5 + .short 0 +.Lstr_offsets_base0: + .section .debug_str,"MS",@progbits,1 +.Linfo_string0: + .byte 0 # string offset=0 +.Linfo_string1: + .asciz "a.cc" # string offset=1 +.Linfo_string2: + .asciz "/proc/self/cwd" # string offset=6 +.Linfo_string3: + .asciz "_start" # string offset=21 +.Linfo_string4: + .asciz "t1" # string offset=28 + .section .debug_str_offsets,"",@progbits + .long .Linfo_string0 + .long .Linfo_string1 + .long .Linfo_string2 + .long .Linfo_string3 + .long .Linfo_string4 + .section .debug_addr,"",@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,"",@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 1 # 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 .Ltu_begin0 # Type unit 0 + .long 1 # Bucket 0 + .long 0 # Bucket 1 + .long 5863786 # Hash in Bucket 0 + .long -304389582 # Hash in Bucket 0 + .long .Linfo_string4 # String in Bucket 0: t1 + .long .Linfo_string3 # String in Bucket 0: _start + .long .Lnames1-.Lnames_entries0 # Offset in Bucket 0 + .long .Lnames0-.Lnames_entries0 # Offset in Bucket 0 +.Lnames_abbrev_start0: + .byte 1 # Abbrev code + .byte 19 # DW_TAG_structure_type + .byte 2 # DW_IDX_type_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 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 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: +.Lnames1: +.L1: + .byte 1 # Abbreviation code + .byte 0 # DW_IDX_type_unit + .long 35 # DW_IDX_die_offset +.L0: # DW_IDX_parent + .byte 2 # Abbreviation code + .long 54 # DW_IDX_die_offset + .byte 0 # DW_IDX_parent + # End of list: t1 +.Lnames0: + .byte 3 # Abbreviation code + .long 35 # DW_IDX_die_offset + .byte 0 # DW_IDX_parent + # End of list: _start + .p2align 2, 0x0 +.Lnames_end0: + .section ".note.GNU-stack","",@progbits + .addrsig + .section .debug_line,"",@progbits +.Lline_table_start0: +#--- a.foreign-tu.s + .text + .file "a.cc" + .globl _start # -- Begin function _start + .p2align 4, 0x90 + .type _start,@function +_start: # @_start +.Lfunc_begin0: + .file 0 "/proc/self/cwd" "a.cc" md5 0x6835f89a7d36054002b51e54e47d852e + .cfi_startproc +# %bb.0: # %entry + .loc 0 2 29 prologue_end # a.cc:2:29 + retq +.Ltmp0: +.Lfunc_end0: + .size _start, .Lfunc_end0-_start + .cfi_endproc + # -- End function + .section .debug_info.dwo,"e",@progbits + .long .Ldebug_info_dwo_end0-.Ldebug_info_dwo_start0 # Length of Unit +.Ldebug_info_dwo_start0: + .short 5 # DWARF version number + .byte 6 # DWARF Unit Type + .byte 8 # Address Size (in bytes) + .long 0 # Offset Into Abbrev. Section + .quad -4149699470930386446 # Type Signature + .long 33 # Type DIE Offset + .byte 1 # Abbrev [1] 0x18:0x10 DW_TAG_type_unit + .short 33 # DW_AT_language + .byte 1 # DW_AT_comp_dir + .byte 2 # DW_AT_dwo_name + .long 0 # DW_AT_stmt_list + .byte 2 # Abbrev [2] 0x21:0x6 DW_TAG_structure_type + .byte 5 # DW_AT_calling_convention + .byte 3 # 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_dwo_end0: + .section .debug_abbrev,"",@progbits + .byte 1 # Abbreviation Code + .byte 74 # DW_TAG_skeleton_unit + .byte 0 # DW_CHILDREN_no + .byte 16 # DW_AT_stmt_list + .byte 23 # DW_FORM_sec_offset + .byte 114 # DW_AT_str_offsets_base + .byte 23 # DW_FORM_sec_offset + .byte 27 # DW_AT_comp_dir + .byte 37 # DW_FORM_strx1 + .byte 118 # DW_AT_dwo_name + .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 0 # EOM(3) + .section .debug_info,"",@progbits +.Lcu_begin0: + .long .Ldebug_info_end0-.Ldebug_info_start0 # Length of Unit +.Ldebug_info_start0: + .short 5 # DWARF version number + .byte 4 # DWARF Unit Type + .byte 8 # Address Size (in bytes) + .long .debug_abbrev # Offset Into Abbrev. Section + .quad -2763464185488304260 + .byte 1 # Abbrev [1] 0x14:0x14 DW_TAG_skeleton_unit + .long .Lline_table_start0 # DW_AT_stmt_list + .long .Lstr_offsets_base0 # DW_AT_str_offsets_base + .byte 0 # DW_AT_comp_dir + .byte 1 # DW_AT_dwo_name + .byte 0 # DW_AT_low_pc + .long .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc + .long .Laddr_table_base0 # DW_AT_addr_base +.Ldebug_info_end0: + .section .debug_str_offsets,"",@progbits + .long 12 # Length of String Offsets Set + .short 5 + .short 0 +.Lstr_offsets_base0: + .section .debug_str,"MS",@progbits,1 +.Lskel_string0: + .asciz "/proc/self/cwd" # string offset=0 +.Lskel_string1: + .asciz "_start" # string offset=15 +.Lskel_string2: + .asciz "t1" # string offset=22 +.Lskel_string3: + .asciz "a.dwo" # string offset=25 + .section .debug_str_offsets,"",@progbits + .long .Lskel_string0 + .long .Lskel_string3 + .section .debug_str_offsets.dwo,"e",@progbits + .long 28 # Length of String Offsets Set + .short 5 + .short 0 + .section .debug_str.dwo,"eMS",@progbits,1 +.Linfo_string0: + .asciz "_start" # string offset=0 +.Linfo_string1: + .asciz "/proc/self/cwd" # string offset=7 +.Linfo_string2: + .asciz "a.dwo" # string offset=22 +.Linfo_string3: + .asciz "t1" # string offset=28 +.Linfo_string4: + .byte 0 # string offset=31 +.Linfo_string5: + .asciz "a.cc" # string offset=32 + .section .debug_str_offsets.dwo,"e",@progbits + .long 0 + .long 7 + .long 22 + .long 28 + .long 31 + .long 32 + .section .debug_info.dwo,"e",@progbits + .long .Ldebug_info_dwo_end1-.Ldebug_info_dwo_start1 # Length of Unit +.Ldebug_info_dwo_start1: + .short 5 # DWARF version number + .byte 5 # DWARF Unit Type + .byte 8 # Address Size (in bytes) + .long 0 # Offset Into Abbrev. Section + .quad -2763464185488304260 + .byte 3 # Abbrev [3] 0x14:0x23 DW_TAG_compile_unit + .byte 4 # DW_AT_producer + .short 33 # DW_AT_language + .byte 5 # DW_AT_name + .byte 2 # DW_AT_dwo_name + .byte 4 # Abbrev [4] 0x1a:0x13 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 87 + # DW_AT_call_all_calls + .byte 0 # DW_AT_name + .byte 0 # DW_AT_decl_file + .byte 2 # DW_AT_decl_line + # DW_AT_external + .byte 5 # Abbrev [5] 0x25:0x7 DW_TAG_formal_parameter + .byte 0 # DW_AT_decl_file + .byte 2 # DW_AT_decl_line + .long 45 # DW_AT_type + .byte 0 # End Of Children Mark + .byte 6 # Abbrev [6] 0x2d:0x9 DW_TAG_structure_type + # DW_AT_declaration + .quad -4149699470930386446 # DW_AT_signature + .byte 0 # End Of Children Mark +.Ldebug_info_dwo_end1: + .section .debug_abbrev.dwo,"e",@progbits + .byte 1 # Abbreviation Code + .byte 65 # DW_TAG_type_unit + .byte 1 # DW_CHILDREN_yes + .byte 19 # DW_AT_language + .byte 5 # DW_FORM_data2 + .byte 27 # DW_AT_comp_dir + .byte 37 # DW_FORM_strx1 + .byte 118 # DW_AT_dwo_name + .byte 37 # DW_FORM_strx1 + .byte 16 # DW_AT_stmt_list + .byte 23 # DW_FORM_sec_offset + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 2 # 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 3 # 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 118 # DW_AT_dwo_name + .byte 37 # DW_FORM_strx1 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 4 # 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 122 # DW_AT_call_all_calls + .byte 25 # DW_FORM_flag_present + .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 5 # Abbreviation Code + .byte 5 # DW_TAG_formal_parameter + .byte 0 # DW_CHILDREN_no + .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 6 # Abbreviation Code + .byte 19 # DW_TAG_structure_type + .byte 0 # DW_CHILDREN_no + .byte 60 # DW_AT_declaration + .byte 25 # DW_FORM_flag_present + .byte 105 # DW_AT_signature + .byte 32 # DW_FORM_ref_sig8 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 0 # EOM(3) + .section .debug_line.dwo,"e",@progbits +.Ltmp1: + .long .Ldebug_line_end0-.Ldebug_line_start0 # unit length +.Ldebug_line_start0: + .short 5 + .byte 8 + .byte 0 + .long .Lprologue_end0-.Lprologue_start0 +.Lprologue_start0: + .byte 1 + .byte 1 + .byte 1 + .byte -5 + .byte 14 + .byte 1 + .byte 1 + .byte 1 + .byte 8 + .byte 1 + .ascii "/proc/self/cwd" + .byte 0 + .byte 3 + .byte 1 + .byte 8 + .byte 2 + .byte 15 + .byte 5 + .byte 30 + .byte 1 + .ascii "a.cc" + .byte 0 + .byte 0 + .byte 0x68, 0x35, 0xf8, 0x9a + .byte 0x7d, 0x36, 0x05, 0x40 + .byte 0x02, 0xb5, 0x1e, 0x54 + .byte 0xe4, 0x7d, 0x85, 0x2e +.Lprologue_end0: +.Ldebug_line_end0: + .section .debug_addr,"",@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,"",@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 1 # 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 + .quad -4149699470930386446 # Type unit 0 + .long 1 # Bucket 0 + .long 0 # Bucket 1 + .long 5863786 # Hash in Bucket 0 + .long -304389582 # Hash in Bucket 0 + .long .Lskel_string2 # String in Bucket 0: t1 + .long .Lskel_string1 # String in Bucket 0: _start + .long .Lnames1-.Lnames_entries0 # Offset in Bucket 0 + .long .Lnames0-.Lnames_entries0 # Offset in Bucket 0 +.Lnames_abbrev_start0: + .byte 1 # Abbrev code + .byte 19 # DW_TAG_structure_type + .byte 2 # DW_IDX_type_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 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 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: +.Lnames1: +.L2: + .byte 1 # Abbreviation code + .byte 0 # DW_IDX_type_unit + .long 33 # DW_IDX_die_offset +.L1: # DW_IDX_parent + .byte 2 # Abbreviation code + .long 45 # DW_IDX_die_offset + .byte 0 # DW_IDX_parent + # End of list: t1 +.Lnames0: +.L0: + .byte 3 # Abbreviation code + .long 26 # DW_IDX_die_offset + .byte 0 # DW_IDX_parent + # End of list: _start + .p2align 2, 0x0 +.Lnames_end0: + .section ".note.GNU-stack","",@progbits + .addrsig + .section .debug_line,"",@progbits +.Lline_table_start0: +#--- b.s + .text + .file "b.cc" + .file 0 "/proc/self/cwd" "b.cc" md5 0xe69190c4224a66c796605e3a1324674b + .type vb,@object # @vb + .bss + .globl vb +vb: + .zero 1 + .size vb, 1 + + .section .debug_abbrev,"",@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 115 # DW_AT_addr_base + .byte 23 # DW_FORM_sec_offset + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 2 # Abbreviation Code + .byte 52 # DW_TAG_variable + .byte 0 # DW_CHILDREN_no + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 63 # DW_AT_external + .byte 25 # DW_FORM_flag_present + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 2 # DW_AT_location + .byte 24 # DW_FORM_exprloc + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 3 # 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 0 # EOM(3) + .section .debug_info,"",@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 + .long .Laddr_table_base0 # DW_AT_addr_base + .byte 2 # Abbrev [2] 0x1e:0xb DW_TAG_variable + .byte 3 # DW_AT_name + .long 41 # DW_AT_type + # DW_AT_external + .byte 0 # DW_AT_decl_file + .byte 1 # DW_AT_decl_line + .byte 2 # DW_AT_location + .byte 161 + .byte 0 + .byte 3 # Abbrev [3] 0x29:0x6 DW_TAG_structure_type + .byte 5 # DW_AT_calling_convention + .byte 4 # 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,"",@progbits + .long 24 # Length of String Offsets Set + .short 5 + .short 0 +.Lstr_offsets_base0: + .section .debug_str,"MS",@progbits,1 +.Linfo_string0: + .byte 0 # string offset=0 +.Linfo_string1: + .asciz "b.cc" # string offset=1 +.Linfo_string2: + .asciz "/proc/self/cwd" # string offset=6 +.Linfo_string3: + .asciz "vb" # string offset=21 +.Linfo_string4: + .asciz "t1" # string offset=24 + .section .debug_str_offsets,"",@progbits + .long .Linfo_string0 + .long .Linfo_string1 + .long .Linfo_string2 + .long .Linfo_string3 + .long .Linfo_string4 + .section .debug_addr,"",@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 vb +.Ldebug_addr_end0: + .section .debug_names,"",@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 5863786 # Hash in Bucket 0 + .long 5863901 # Hash in Bucket 1 + .long .Linfo_string4 # String in Bucket 0: t1 + .long .Linfo_string3 # String in Bucket 1: vb + .long .Lnames0-.Lnames_entries0 # Offset in Bucket 0 + .long .Lnames1-.Lnames_entries0 # Offset in Bucket 1 +.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 52 # DW_TAG_variable + .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 41 # DW_IDX_die_offset + .byte 0 # DW_IDX_parent + # End of list: t1 +.Lnames1: +.L0: + .byte 2 # Abbreviation code + .long 30 # DW_IDX_die_offset + .byte 0 # DW_IDX_parent + # End of list: vb + .p2align 2, 0x0 +.Lnames_end0: + .section ".note.GNU-stack","",@progbits + .addrsig + .section .debug_line,"",@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 0000000000000..888dd9007ed12 --- /dev/null +++ b/lld/test/ELF/debug-names.s @@ -0,0 +1,430 @@ +# debug-names.s was generated with: + +# - clang++ -g -O0 -gpubnames -fdebug-compilation-dir='/proc/self/cwd' \ +# -S a.cpp -o a.s + +# a.cpp contents: + +# struct t1 { }; +# void f1(t1) { } + +# 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 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 0000000000000000 [[#%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 + +## Test we can handle concatenated .debug_names. +# RUN: ld.lld -r a.o b.o -o ab.o +# RUN: ld.lld --debug-names ab.o -o out1 +# RUN: llvm-dwarfdump -debug-names out1 | FileCheck %s --check-prefix=DWARF + +# READELF: Name Type Address Off Size ES Flg Lk Inf Al +# READELF: .debug_names PROGBITS 0000000000000000 [[#%x,]] 0000cc 00 0 0 4 + +## Test we can handle compressed input and --compress-debug-sections compresses output .debug_names. +# RUN: %if zlib %{ llvm-objcopy --compress-debug-sections=zlib a.o a.zlib.o %} +# RUN: %if zlib %{ ld.lld --debug-names --compress-debug-sections=zlib a.zlib.o b.o -o out.zlib %} +# RUN: %if zlib %{ llvm-readelf -S out.zlib | FileCheck %s --check-prefix=READELF-ZLIB %} +# RUN: %if zlib %{ llvm-objcopy --decompress-debug-sections out.zlib out.zlib.de %} +# RUN: %if zlib %{ llvm-dwarfdump -debug-names out.zlib.de | FileCheck %s --check-prefix=DWARF %} + +# READELF-ZLIB: Name Type Address Off Size ES Flg Lk Inf Al +# READELF-ZLIB: .debug_names PROGBITS 0000000000000000 [[#%x,]] [[#%x,]] 00 C 0 0 1 + +# 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: 0x00000089 "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: +# 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: +# DWARF-NEXT: DW_IDX_compile_unit: 0x01 +# DWARF-NEXT: } +# DWARF-NEXT: } +# DWARF-NEXT: Name 2 { +# DWARF-NEXT: Hash: 0x5355B2BE +# DWARF-NEXT: String: 0x00000080 "_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: +# 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: +# 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: +# 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: 0x0000007d "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: +# DWARF-NEXT: DW_IDX_compile_unit: 0x00 +# DWARF-NEXT: } +# DWARF-NEXT: } +# DWARF-NEXT: ] + +#--- a.s + .text + .globl _Z2f12t1 # -- Begin function _Z2f12t1 + .p2align 4, 0x90 + .type _Z2f12t1,@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,"",@progbits + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 0 # EOM(3) + .section .debug_info,"",@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,"",@progbits + .long 28 # Length of String Offsets Set + .short 5 + .short 0 +.Lstr_offsets_base0: + .section .debug_str,"MS",@progbits,1 +.Linfo_string0: + .asciz "clang version 19.0.0git (git@github.com:llvm/llvm-project.git 53b14cd9ce2b57da73d173fc876d2e9e199f5640)" # 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 "t1" # string offset=137 +.Laddr_table_base0: + .quad .Lfunc_begin0 +.Ldebug_addr_end0: + .section .debug_names,"",@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@github.com:llvm/llvm-project.git 53b14cd9ce2b57da73d173fc876d2e9e199f5640)" + .section ".note.GNU-stack","",@progbits + .addrsig + .section .debug_line,"",@progbits +.Lline_table_start0: + +#--- b.s +# Generated with: +# - clang++ -g -O0 -gpubnames -fdebug-compilation-dir='/proc/self/cwd' \ +# -S b.cpp -o b.s + +# b.cpp contents: + +# struct t1 { }; +# int main() { +# t1 v1; +# } +# + + .text + .globl main # -- Begin function main + .p2align 4, 0x90 + .type main,@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,"",@progbits + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 0 # EOM(3) + .section .debug_info,"",@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,"",@progbits + .long 32 # Length of String Offsets Set + .short 5 + .short 0 +.Lstr_offsets_base0: + .section .debug_str,"MS",@progbits,1 +.Linfo_string0: + .asciz "clang version 19.0.0git (git@github.com:llvm/llvm-project.git 53b14cd9ce2b57da73d173fc876d2e9e199f5640)" # string offset=0 +.Linfo_string1: + .asciz "b.cpp" # string offset=104 +.Linfo_string2: + .asciz "/proc/self/cwd" # string offset=110 +.Linfo_string3: + .asciz "main" # string offset=125 +.Linfo_string4: + .asciz "int" # string offset=130 +.Linfo_string5: + .asciz "v1" # string offset=134 +.Linfo_string6: + .asciz "t1" # string offset=137 +.Laddr_table_base0: + .quad .Lfunc_begin0 +.Ldebug_addr_end0: + .section .debug_names,"",@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@github.com:llvm/llvm-project.git 53b14cd9ce2b57da73d173fc876d2e9e199f5640)" + .section ".note.GNU-stack","",@progbits + .addrsig + .section .debug_line,"",@progbits +.Lline_table_start0: diff --git a/lld/test/ELF/driver.test b/lld/test/ELF/driver.test index 49deb902aa0fd..45d73607c8ac6 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 diff --git a/lld/test/ELF/ppc32-debug-names.s b/lld/test/ELF/ppc32-debug-names.s new file mode 100644 index 0000000000000..3fc93ec86693f --- /dev/null +++ b/lld/test/ELF/ppc32-debug-names.s @@ -0,0 +1,418 @@ +# ppc32-debug-names.s was generated with: + +# clang++ --target=powerpc -g -gpubnames \ +# -fdebug-compilation-dir='/self/proc/cwd' -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: 0x00000089 "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: +# 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: +# DWARF-NEXT: DW_IDX_compile_unit: 0x01 +# DWARF-NEXT: } +# DWARF-NEXT: } +# DWARF-NEXT: Name 2 { +# DWARF-NEXT: Hash: 0x5355B2BE +# DWARF-NEXT: String: 0x00000080 "_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: +# DWARF-NEXT: DW_IDX_compile_unit: 0x00 +# DWARF-NEXT: } +# DWARF-NEXT: } +# DWARF-NEXT: Name 3 { +# DWARF-NEXT: Hash: 0x7C9A7F6A +# DWARF-NEXT: String: 0x0000010d "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: +# 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: 0x00000112 "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: +# 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: 0x0000007d "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: +# 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,@function +_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 + .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,"",@progbits + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 0 # EOM(3) + .section .debug_info,"",@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,"",@progbits + .long 28 # Length of String Offsets Set + .short 5 + .short 0 +.Lstr_offsets_base0: + .section .debug_str,"MS",@progbits,1 +.Linfo_string0: + .asciz "clang version 19.0.0git (git@github.com:llvm/llvm-project.git 53b14cd9ce2b57da73d173fc876d2e9e199f5640)" # 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 "t1" # string offset=137 +.Laddr_table_base0: + .long .Lfunc_begin0 +.Ldebug_addr_end0: + .section .debug_names,"",@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@github.com:llvm/llvm-project.git 53b14cd9ce2b57da73d173fc876d2e9e199f5640)" + .section ".note.GNU-stack","",@progbits + .addrsig + .section .debug_line,"",@progbits +.Lline_table_start0: + +#--- b.s +# Generated with: +# - clang++ --target=powerpc -g -O0 -gpubnames \ +# -fdebug-compilation-dir='/self/proc/cwd' -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,@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,"",@progbits + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 0 # EOM(3) + .section .debug_info,"",@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,"",@progbits + .long 32 # Length of String Offsets Set + .short 5 + .short 0 +.Lstr_offsets_base0: + .section .debug_str,"MS",@progbits,1 +.Linfo_string0: + .asciz "clang version 19.0.0git (git@github.com:llvm/llvm-project.git 53b14cd9ce2b57da73d173fc876d2e9e199f5640)" # string offset=0 +.Linfo_string1: + .asciz "b.cpp" # string offset=104 +.Linfo_string2: + .asciz "/proc/self/cwd" # string offset=110 +.Linfo_string3: + .asciz "main" # string offset=125 +.Linfo_string4: + .asciz "int" # string offset=130 +.Linfo_string5: + .asciz "v1" # string offset=134 +.Linfo_string6: + .asciz "t1" # string offset=137 +.Laddr_table_base0: + .long .Lfunc_begin0 +.Ldebug_addr_end0: + .section .debug_names,"",@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@github.com:llvm/llvm-project.git 53b14cd9ce2b57da73d173fc876d2e9e199f5640)" + .section ".note.GNU-stack","",@progbits + .addrsig + .section .debug_line,"",@progbits +.Lline_table_start0: