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-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "DWARFLinkerUnit.h" 10 #include "DWARFEmitterImpl.h" 11 #include "DebugLineSectionEmitter.h" 12 13 using namespace llvm; 14 using namespace dwarf_linker; 15 using namespace dwarf_linker::parallel; 16 17 void 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 41 Error 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 59 void 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 (unsigned i = 0, N = Data.size(); i < N; ++i) { 74 const DIEAbbrevData &AttrData = Data[i]; 75 76 // Emit attribute type. 77 encodeULEB128(AttrData.getAttribute(), AbbrevSection.OS); 78 79 // Emit form type. 80 encodeULEB128(AttrData.getForm(), AbbrevSection.OS); 81 82 // Emit value for DW_FORM_implicit_const. 83 if (AttrData.getForm() == dwarf::DW_FORM_implicit_const) 84 encodeSLEB128(AttrData.getValue(), AbbrevSection.OS); 85 } 86 87 // Mark end of abbreviation. 88 encodeULEB128(0, AbbrevSection.OS); 89 encodeULEB128(0, AbbrevSection.OS); 90 } 91 92 Error DwarfUnit::emitDebugInfo(const Triple &TargetTriple) { 93 DIE *OutUnitDIE = getOutUnitDIE(); 94 if (OutUnitDIE == nullptr) 95 return Error::success(); 96 97 // FIXME: Remove dependence on DwarfEmitterImpl/AsmPrinter and emit DIEs 98 // directly. 99 100 SectionDescriptor &OutSection = 101 getOrCreateSectionDescriptor(DebugSectionKind::DebugInfo); 102 DwarfEmitterImpl Emitter(DWARFLinker::OutputFileType::Object, OutSection.OS); 103 if (Error Err = Emitter.init(TargetTriple, "__DWARF")) 104 return Err; 105 106 // Emit compile unit header. 107 Emitter.emitCompileUnitHeader(*this); 108 size_t OffsetToAbbreviationTableOffset = 109 (getFormParams().Version >= 5) ? 8 : 6; 110 OutSection.notePatch(DebugOffsetPatch{ 111 OffsetToAbbreviationTableOffset, 112 &getOrCreateSectionDescriptor(DebugSectionKind::DebugAbbrev)}); 113 114 // Emit DIEs. 115 Emitter.emitDIE(*OutUnitDIE); 116 Emitter.finish(); 117 118 // Set start offset ans size for .debug_info section. 119 OutSection.setSizesForSectionCreatedByAsmPrinter(); 120 return Error::success(); 121 } 122 123 Error DwarfUnit::emitDebugLine(const Triple &TargetTriple, 124 const DWARFDebugLine::LineTable &OutLineTable) { 125 DebugLineSectionEmitter DebugLineEmitter(TargetTriple, *this); 126 127 return DebugLineEmitter.emit(OutLineTable); 128 } 129 130 Error DwarfUnit::emitDebugStringOffsetSection() { 131 if (getVersion() < 5) 132 return Error::success(); 133 134 if (DebugStringIndexMap.empty()) 135 return Error::success(); 136 137 SectionDescriptor &OutDebugStrOffsetsSection = 138 getOrCreateSectionDescriptor(DebugSectionKind::DebugStrOffsets); 139 140 // Emit section header. 141 142 // Emit length. 143 OutDebugStrOffsetsSection.emitUnitLength(0xBADDEF); 144 uint64_t OffsetAfterSectionLength = OutDebugStrOffsetsSection.OS.tell(); 145 146 // Emit version. 147 OutDebugStrOffsetsSection.emitIntVal(5, 2); 148 149 // Emit padding. 150 OutDebugStrOffsetsSection.emitIntVal(0, 2); 151 152 // Emit index to offset map. 153 for (const StringEntry *String : DebugStringIndexMap.getValues()) { 154 // Note patch for string offset value. 155 OutDebugStrOffsetsSection.notePatch( 156 DebugStrPatch{{OutDebugStrOffsetsSection.OS.tell()}, String}); 157 158 // Emit placeholder for offset value. 159 OutDebugStrOffsetsSection.emitOffset(0xBADDEF); 160 } 161 162 // Patch section length. 163 OutDebugStrOffsetsSection.apply( 164 OffsetAfterSectionLength - 165 OutDebugStrOffsetsSection.getFormParams().getDwarfOffsetByteSize(), 166 dwarf::DW_FORM_sec_offset, 167 OutDebugStrOffsetsSection.OS.tell() - OffsetAfterSectionLength); 168 169 return Error::success(); 170 } 171 172 /// Emit the pubnames or pubtypes section contribution for \p 173 /// Unit into \p Sec. The data is provided in \p Info. 174 std::optional<uint64_t> 175 DwarfUnit::emitPubAcceleratorEntry(SectionDescriptor &OutSection, 176 const DwarfUnit::AccelInfo &Info, 177 std::optional<uint64_t> LengthOffset) { 178 if (!LengthOffset) { 179 // Emit the header. 180 OutSection.emitIntVal(0xBADDEF, 181 getFormParams().getDwarfOffsetByteSize()); // Length 182 LengthOffset = OutSection.OS.tell(); 183 184 OutSection.emitIntVal(dwarf::DW_PUBNAMES_VERSION, 2); // Version 185 186 OutSection.notePatch(DebugOffsetPatch{ 187 OutSection.OS.tell(), 188 &getOrCreateSectionDescriptor(DebugSectionKind::DebugInfo)}); 189 OutSection.emitOffset(0xBADDEF); // Unit offset 190 191 OutSection.emitIntVal(getUnitSize(), 4); // Size 192 } 193 OutSection.emitOffset(Info.OutOffset); 194 195 // Emit the string itself. 196 OutSection.emitInplaceString(Info.String->first()); 197 198 return LengthOffset; 199 } 200 201 /// Emit .debug_pubnames and .debug_pubtypes for \p Unit. 202 void DwarfUnit::emitPubAccelerators() { 203 std::optional<uint64_t> NamesLengthOffset; 204 std::optional<uint64_t> TypesLengthOffset; 205 206 forEachAcceleratorRecord([&](const DwarfUnit::AccelInfo &Info) { 207 if (Info.AvoidForPubSections) 208 return; 209 210 switch (Info.Type) { 211 case DwarfUnit::AccelType::Name: { 212 NamesLengthOffset = emitPubAcceleratorEntry( 213 getOrCreateSectionDescriptor(DebugSectionKind::DebugPubNames), Info, 214 NamesLengthOffset); 215 } break; 216 case DwarfUnit::AccelType::Type: { 217 TypesLengthOffset = emitPubAcceleratorEntry( 218 getOrCreateSectionDescriptor(DebugSectionKind::DebugPubTypes), Info, 219 TypesLengthOffset); 220 } break; 221 default: { 222 // Nothing to do. 223 } break; 224 } 225 }); 226 227 if (NamesLengthOffset) { 228 SectionDescriptor &OutSection = 229 getOrCreateSectionDescriptor(DebugSectionKind::DebugPubNames); 230 OutSection.emitIntVal(0, 4); // End marker. 231 232 OutSection.apply(*NamesLengthOffset - 233 OutSection.getFormParams().getDwarfOffsetByteSize(), 234 dwarf::DW_FORM_sec_offset, 235 OutSection.OS.tell() - *NamesLengthOffset); 236 } 237 238 if (TypesLengthOffset) { 239 SectionDescriptor &OutSection = 240 getOrCreateSectionDescriptor(DebugSectionKind::DebugPubTypes); 241 OutSection.emitIntVal(0, 4); // End marker. 242 243 OutSection.apply(*TypesLengthOffset - 244 OutSection.getFormParams().getDwarfOffsetByteSize(), 245 dwarf::DW_FORM_sec_offset, 246 OutSection.OS.tell() - *TypesLengthOffset); 247 } 248 } 249