247 lines · cpp
1//===- DWARFLinkerUnit.cpp ------------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "DWARFLinkerUnit.h"10#include "DWARFEmitterImpl.h"11#include "DebugLineSectionEmitter.h"12 13using namespace llvm;14using namespace dwarf_linker;15using namespace dwarf_linker::parallel;16 17void DwarfUnit::assignAbbrev(DIEAbbrev &Abbrev) {18 // Check the set for priors.19 FoldingSetNodeID ID;20 Abbrev.Profile(ID);21 void *InsertToken;22 23 DIEAbbrev *InSet = AbbreviationsSet.FindNodeOrInsertPos(ID, InsertToken);24 // If it's newly added.25 if (InSet) {26 // Assign existing abbreviation number.27 Abbrev.setNumber(InSet->getNumber());28 } else {29 // Add to abbreviation list.30 Abbreviations.push_back(31 std::make_unique<DIEAbbrev>(Abbrev.getTag(), Abbrev.hasChildren()));32 for (const auto &Attr : Abbrev.getData())33 Abbreviations.back()->AddAttribute(Attr);34 AbbreviationsSet.InsertNode(Abbreviations.back().get(), InsertToken);35 // Assign the unique abbreviation number.36 Abbrev.setNumber(Abbreviations.size());37 Abbreviations.back()->setNumber(Abbreviations.size());38 }39}40 41Error DwarfUnit::emitAbbreviations() {42 const std::vector<std::unique_ptr<DIEAbbrev>> &Abbrevs = getAbbreviations();43 if (Abbrevs.empty())44 return Error::success();45 46 SectionDescriptor &AbbrevSection =47 getOrCreateSectionDescriptor(DebugSectionKind::DebugAbbrev);48 49 // For each abbreviation.50 for (const auto &Abbrev : Abbrevs)51 emitDwarfAbbrevEntry(*Abbrev, AbbrevSection);52 53 // Mark end of abbreviations.54 encodeULEB128(0, AbbrevSection.OS);55 56 return Error::success();57}58 59void DwarfUnit::emitDwarfAbbrevEntry(const DIEAbbrev &Abbrev,60 SectionDescriptor &AbbrevSection) {61 // Emit the abbreviations code (base 1 index.)62 encodeULEB128(Abbrev.getNumber(), AbbrevSection.OS);63 64 // Emit the abbreviations data.65 // Emit its Dwarf tag type.66 encodeULEB128(Abbrev.getTag(), AbbrevSection.OS);67 68 // Emit whether it has children DIEs.69 encodeULEB128((unsigned)Abbrev.hasChildren(), AbbrevSection.OS);70 71 // For each attribute description.72 const SmallVectorImpl<DIEAbbrevData> &Data = Abbrev.getData();73 for (const DIEAbbrevData &AttrData : Data) {74 // Emit attribute type.75 encodeULEB128(AttrData.getAttribute(), AbbrevSection.OS);76 77 // Emit form type.78 encodeULEB128(AttrData.getForm(), AbbrevSection.OS);79 80 // Emit value for DW_FORM_implicit_const.81 if (AttrData.getForm() == dwarf::DW_FORM_implicit_const)82 encodeSLEB128(AttrData.getValue(), AbbrevSection.OS);83 }84 85 // Mark end of abbreviation.86 encodeULEB128(0, AbbrevSection.OS);87 encodeULEB128(0, AbbrevSection.OS);88}89 90Error DwarfUnit::emitDebugInfo(const Triple &TargetTriple) {91 DIE *OutUnitDIE = getOutUnitDIE();92 if (OutUnitDIE == nullptr)93 return Error::success();94 95 // FIXME: Remove dependence on DwarfEmitterImpl/AsmPrinter and emit DIEs96 // directly.97 98 SectionDescriptor &OutSection =99 getOrCreateSectionDescriptor(DebugSectionKind::DebugInfo);100 DwarfEmitterImpl Emitter(DWARFLinker::OutputFileType::Object, OutSection.OS);101 if (Error Err = Emitter.init(TargetTriple, "__DWARF"))102 return Err;103 104 // Emit compile unit header.105 Emitter.emitCompileUnitHeader(*this);106 size_t OffsetToAbbreviationTableOffset =107 (getFormParams().Version >= 5) ? 8 : 6;108 OutSection.notePatch(DebugOffsetPatch{109 OffsetToAbbreviationTableOffset,110 &getOrCreateSectionDescriptor(DebugSectionKind::DebugAbbrev)});111 112 // Emit DIEs.113 Emitter.emitDIE(*OutUnitDIE);114 Emitter.finish();115 116 // Set start offset ans size for .debug_info section.117 OutSection.setSizesForSectionCreatedByAsmPrinter();118 return Error::success();119}120 121Error DwarfUnit::emitDebugLine(const Triple &TargetTriple,122 const DWARFDebugLine::LineTable &OutLineTable) {123 DebugLineSectionEmitter DebugLineEmitter(TargetTriple, *this);124 125 return DebugLineEmitter.emit(OutLineTable);126}127 128Error DwarfUnit::emitDebugStringOffsetSection() {129 if (getVersion() < 5)130 return Error::success();131 132 if (DebugStringIndexMap.empty())133 return Error::success();134 135 SectionDescriptor &OutDebugStrOffsetsSection =136 getOrCreateSectionDescriptor(DebugSectionKind::DebugStrOffsets);137 138 // Emit section header.139 140 // Emit length.141 OutDebugStrOffsetsSection.emitUnitLength(0xBADDEF);142 uint64_t OffsetAfterSectionLength = OutDebugStrOffsetsSection.OS.tell();143 144 // Emit version.145 OutDebugStrOffsetsSection.emitIntVal(5, 2);146 147 // Emit padding.148 OutDebugStrOffsetsSection.emitIntVal(0, 2);149 150 // Emit index to offset map.151 for (const StringEntry *String : DebugStringIndexMap.getValues()) {152 // Note patch for string offset value.153 OutDebugStrOffsetsSection.notePatch(154 DebugStrPatch{{OutDebugStrOffsetsSection.OS.tell()}, String});155 156 // Emit placeholder for offset value.157 OutDebugStrOffsetsSection.emitOffset(0xBADDEF);158 }159 160 // Patch section length.161 OutDebugStrOffsetsSection.apply(162 OffsetAfterSectionLength -163 OutDebugStrOffsetsSection.getFormParams().getDwarfOffsetByteSize(),164 dwarf::DW_FORM_sec_offset,165 OutDebugStrOffsetsSection.OS.tell() - OffsetAfterSectionLength);166 167 return Error::success();168}169 170/// Emit the pubnames or pubtypes section contribution for \p171/// Unit into \p Sec. The data is provided in \p Info.172std::optional<uint64_t>173DwarfUnit::emitPubAcceleratorEntry(SectionDescriptor &OutSection,174 const DwarfUnit::AccelInfo &Info,175 std::optional<uint64_t> LengthOffset) {176 if (!LengthOffset) {177 // Emit the header.178 OutSection.emitIntVal(0xBADDEF,179 getFormParams().getDwarfOffsetByteSize()); // Length180 LengthOffset = OutSection.OS.tell();181 182 OutSection.emitIntVal(dwarf::DW_PUBNAMES_VERSION, 2); // Version183 184 OutSection.notePatch(DebugOffsetPatch{185 OutSection.OS.tell(),186 &getOrCreateSectionDescriptor(DebugSectionKind::DebugInfo)});187 OutSection.emitOffset(0xBADDEF); // Unit offset188 189 OutSection.emitIntVal(getUnitSize(), 4); // Size190 }191 OutSection.emitOffset(Info.OutOffset);192 193 // Emit the string itself.194 OutSection.emitInplaceString(Info.String->first());195 196 return LengthOffset;197}198 199/// Emit .debug_pubnames and .debug_pubtypes for \p Unit.200void DwarfUnit::emitPubAccelerators() {201 std::optional<uint64_t> NamesLengthOffset;202 std::optional<uint64_t> TypesLengthOffset;203 204 forEachAcceleratorRecord([&](const DwarfUnit::AccelInfo &Info) {205 if (Info.AvoidForPubSections)206 return;207 208 switch (Info.Type) {209 case DwarfUnit::AccelType::Name: {210 NamesLengthOffset = emitPubAcceleratorEntry(211 getOrCreateSectionDescriptor(DebugSectionKind::DebugPubNames), Info,212 NamesLengthOffset);213 } break;214 case DwarfUnit::AccelType::Type: {215 TypesLengthOffset = emitPubAcceleratorEntry(216 getOrCreateSectionDescriptor(DebugSectionKind::DebugPubTypes), Info,217 TypesLengthOffset);218 } break;219 default: {220 // Nothing to do.221 } break;222 }223 });224 225 if (NamesLengthOffset) {226 SectionDescriptor &OutSection =227 getOrCreateSectionDescriptor(DebugSectionKind::DebugPubNames);228 OutSection.emitIntVal(0, 4); // End marker.229 230 OutSection.apply(*NamesLengthOffset -231 OutSection.getFormParams().getDwarfOffsetByteSize(),232 dwarf::DW_FORM_sec_offset,233 OutSection.OS.tell() - *NamesLengthOffset);234 }235 236 if (TypesLengthOffset) {237 SectionDescriptor &OutSection =238 getOrCreateSectionDescriptor(DebugSectionKind::DebugPubTypes);239 OutSection.emitIntVal(0, 4); // End marker.240 241 OutSection.apply(*TypesLengthOffset -242 OutSection.getFormParams().getDwarfOffsetByteSize(),243 dwarf::DW_FORM_sec_offset,244 OutSection.OS.tell() - *TypesLengthOffset);245 }246}247