diff options
Diffstat (limited to 'contrib/llvm-project/llvm/lib/DWARFLinkerParallel/DWARFLinkerUnit.cpp')
-rw-r--r-- | contrib/llvm-project/llvm/lib/DWARFLinkerParallel/DWARFLinkerUnit.cpp | 250 |
1 files changed, 250 insertions, 0 deletions
diff --git a/contrib/llvm-project/llvm/lib/DWARFLinkerParallel/DWARFLinkerUnit.cpp b/contrib/llvm-project/llvm/lib/DWARFLinkerParallel/DWARFLinkerUnit.cpp new file mode 100644 index 000000000000..b1da1900d65e --- /dev/null +++ b/contrib/llvm-project/llvm/lib/DWARFLinkerParallel/DWARFLinkerUnit.cpp @@ -0,0 +1,250 @@ +//===- DWARFLinkerUnit.cpp ------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "DWARFLinkerUnit.h" +#include "DWARFEmitterImpl.h" +#include "DebugLineSectionEmitter.h" + +namespace llvm { +namespace dwarflinker_parallel { + +void DwarfUnit::assignAbbrev(DIEAbbrev &Abbrev) { + // Check the set for priors. + FoldingSetNodeID ID; + Abbrev.Profile(ID); + void *InsertToken; + + DIEAbbrev *InSet = AbbreviationsSet.FindNodeOrInsertPos(ID, InsertToken); + // If it's newly added. + if (InSet) { + // Assign existing abbreviation number. + Abbrev.setNumber(InSet->getNumber()); + } else { + // Add to abbreviation list. + Abbreviations.push_back( + std::make_unique<DIEAbbrev>(Abbrev.getTag(), Abbrev.hasChildren())); + for (const auto &Attr : Abbrev.getData()) + Abbreviations.back()->AddAttribute(Attr); + AbbreviationsSet.InsertNode(Abbreviations.back().get(), InsertToken); + // Assign the unique abbreviation number. + Abbrev.setNumber(Abbreviations.size()); + Abbreviations.back()->setNumber(Abbreviations.size()); + } +} + +Error DwarfUnit::emitAbbreviations() { + const std::vector<std::unique_ptr<DIEAbbrev>> &Abbrevs = getAbbreviations(); + if (Abbrevs.empty()) + return Error::success(); + + SectionDescriptor &AbbrevSection = + getOrCreateSectionDescriptor(DebugSectionKind::DebugAbbrev); + + // For each abbreviation. + for (const auto &Abbrev : Abbrevs) + emitDwarfAbbrevEntry(*Abbrev, AbbrevSection); + + // Mark end of abbreviations. + encodeULEB128(0, AbbrevSection.OS); + + return Error::success(); +} + +void DwarfUnit::emitDwarfAbbrevEntry(const DIEAbbrev &Abbrev, + SectionDescriptor &AbbrevSection) { + // Emit the abbreviations code (base 1 index.) + encodeULEB128(Abbrev.getNumber(), AbbrevSection.OS); + + // Emit the abbreviations data. + // Emit its Dwarf tag type. + encodeULEB128(Abbrev.getTag(), AbbrevSection.OS); + + // Emit whether it has children DIEs. + encodeULEB128((unsigned)Abbrev.hasChildren(), AbbrevSection.OS); + + // For each attribute description. + const SmallVectorImpl<DIEAbbrevData> &Data = Abbrev.getData(); + for (unsigned i = 0, N = Data.size(); i < N; ++i) { + const DIEAbbrevData &AttrData = Data[i]; + + // Emit attribute type. + encodeULEB128(AttrData.getAttribute(), AbbrevSection.OS); + + // Emit form type. + encodeULEB128(AttrData.getForm(), AbbrevSection.OS); + + // Emit value for DW_FORM_implicit_const. + if (AttrData.getForm() == dwarf::DW_FORM_implicit_const) + encodeSLEB128(AttrData.getValue(), AbbrevSection.OS); + } + + // Mark end of abbreviation. + encodeULEB128(0, AbbrevSection.OS); + encodeULEB128(0, AbbrevSection.OS); +} + +Error DwarfUnit::emitDebugInfo(const Triple &TargetTriple) { + DIE *OutUnitDIE = getOutUnitDIE(); + if (OutUnitDIE == nullptr) + return Error::success(); + + // FIXME: Remove dependence on DwarfEmitterImpl/AsmPrinter and emit DIEs + // directly. + + SectionDescriptor &OutSection = + getOrCreateSectionDescriptor(DebugSectionKind::DebugInfo); + DwarfEmitterImpl Emitter(DWARFLinker::OutputFileType::Object, OutSection.OS); + if (Error Err = Emitter.init(TargetTriple, "__DWARF")) + return Err; + + // Emit compile unit header. + Emitter.emitCompileUnitHeader(*this); + size_t OffsetToAbbreviationTableOffset = + (getFormParams().Version >= 5) ? 8 : 6; + OutSection.notePatch(DebugOffsetPatch{ + OffsetToAbbreviationTableOffset, + &getOrCreateSectionDescriptor(DebugSectionKind::DebugAbbrev)}); + + // Emit DIEs. + Emitter.emitDIE(*OutUnitDIE); + Emitter.finish(); + + // Set start offset ans size for .debug_info section. + OutSection.setSizesForSectionCreatedByAsmPrinter(); + return Error::success(); +} + +Error DwarfUnit::emitDebugLine(const Triple &TargetTriple, + const DWARFDebugLine::LineTable &OutLineTable) { + DebugLineSectionEmitter DebugLineEmitter(TargetTriple, *this); + + return DebugLineEmitter.emit(OutLineTable); +} + +Error DwarfUnit::emitDebugStringOffsetSection() { + if (getVersion() < 5) + return Error::success(); + + if (DebugStringIndexMap.empty()) + return Error::success(); + + SectionDescriptor &OutDebugStrOffsetsSection = + getOrCreateSectionDescriptor(DebugSectionKind::DebugStrOffsets); + + // Emit section header. + + // Emit length. + OutDebugStrOffsetsSection.emitUnitLength(0xBADDEF); + uint64_t OffsetAfterSectionLength = OutDebugStrOffsetsSection.OS.tell(); + + // Emit version. + OutDebugStrOffsetsSection.emitIntVal(5, 2); + + // Emit padding. + OutDebugStrOffsetsSection.emitIntVal(0, 2); + + // Emit index to offset map. + for (const StringEntry *String : DebugStringIndexMap.getValues()) { + // Note patch for string offset value. + OutDebugStrOffsetsSection.notePatch( + DebugStrPatch{{OutDebugStrOffsetsSection.OS.tell()}, String}); + + // Emit placeholder for offset value. + OutDebugStrOffsetsSection.emitOffset(0xBADDEF); + } + + // Patch section length. + OutDebugStrOffsetsSection.apply( + OffsetAfterSectionLength - + OutDebugStrOffsetsSection.getFormParams().getDwarfOffsetByteSize(), + dwarf::DW_FORM_sec_offset, + OutDebugStrOffsetsSection.OS.tell() - OffsetAfterSectionLength); + + return Error::success(); +} + +/// Emit the pubnames or pubtypes section contribution for \p +/// Unit into \p Sec. The data is provided in \p Info. +std::optional<uint64_t> +DwarfUnit::emitPubAcceleratorEntry(SectionDescriptor &OutSection, + const DwarfUnit::AccelInfo &Info, + std::optional<uint64_t> LengthOffset) { + if (!LengthOffset) { + // Emit the header. + OutSection.emitIntVal(0xBADDEF, + getFormParams().getDwarfOffsetByteSize()); // Length + LengthOffset = OutSection.OS.tell(); + + OutSection.emitIntVal(dwarf::DW_PUBNAMES_VERSION, 2); // Version + + OutSection.notePatch(DebugOffsetPatch{ + OutSection.OS.tell(), + &getOrCreateSectionDescriptor(DebugSectionKind::DebugInfo)}); + OutSection.emitOffset(0xBADDEF); // Unit offset + + OutSection.emitIntVal(getUnitSize(), 4); // Size + } + OutSection.emitOffset(Info.OutOffset); + + // Emit the string itself. + OutSection.emitInplaceString(Info.String->first()); + + return LengthOffset; +} + +/// Emit .debug_pubnames and .debug_pubtypes for \p Unit. +void DwarfUnit::emitPubAccelerators() { + std::optional<uint64_t> NamesLengthOffset; + std::optional<uint64_t> TypesLengthOffset; + + forEachAcceleratorRecord([&](const DwarfUnit::AccelInfo &Info) { + if (Info.AvoidForPubSections) + return; + + switch (Info.Type) { + case DwarfUnit::AccelType::Name: { + NamesLengthOffset = emitPubAcceleratorEntry( + getOrCreateSectionDescriptor(DebugSectionKind::DebugPubNames), Info, + NamesLengthOffset); + } break; + case DwarfUnit::AccelType::Type: { + TypesLengthOffset = emitPubAcceleratorEntry( + getOrCreateSectionDescriptor(DebugSectionKind::DebugPubTypes), Info, + TypesLengthOffset); + } break; + default: { + // Nothing to do. + } break; + } + }); + + if (NamesLengthOffset) { + SectionDescriptor &OutSection = + getOrCreateSectionDescriptor(DebugSectionKind::DebugPubNames); + OutSection.emitIntVal(0, 4); // End marker. + + OutSection.apply(*NamesLengthOffset - + OutSection.getFormParams().getDwarfOffsetByteSize(), + dwarf::DW_FORM_sec_offset, + OutSection.OS.tell() - *NamesLengthOffset); + } + + if (TypesLengthOffset) { + SectionDescriptor &OutSection = + getOrCreateSectionDescriptor(DebugSectionKind::DebugPubTypes); + OutSection.emitIntVal(0, 4); // End marker. + + OutSection.apply(*TypesLengthOffset - + OutSection.getFormParams().getDwarfOffsetByteSize(), + dwarf::DW_FORM_sec_offset, + OutSection.OS.tell() - *TypesLengthOffset); + } +} + +} // end of namespace dwarflinker_parallel +} // end of namespace llvm |