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 (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 90 Error 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 DIEs 96 // 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 121 Error DwarfUnit::emitDebugLine(const Triple &TargetTriple, 122 const DWARFDebugLine::LineTable &OutLineTable) { 123 DebugLineSectionEmitter DebugLineEmitter(TargetTriple, *this); 124 125 return DebugLineEmitter.emit(OutLineTable); 126 } 127 128 Error 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 \p 171 /// Unit into \p Sec. The data is provided in \p Info. 172 std::optional<uint64_t> 173 DwarfUnit::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()); // Length 180 LengthOffset = OutSection.OS.tell(); 181 182 OutSection.emitIntVal(dwarf::DW_PUBNAMES_VERSION, 2); // Version 183 184 OutSection.notePatch(DebugOffsetPatch{ 185 OutSection.OS.tell(), 186 &getOrCreateSectionDescriptor(DebugSectionKind::DebugInfo)}); 187 OutSection.emitOffset(0xBADDEF); // Unit offset 188 189 OutSection.emitIntVal(getUnitSize(), 4); // Size 190 } 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. 200 void 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