1 //===- DWARFEmitterImpl.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 "DWARFEmitterImpl.h" 10 #include "DWARFLinkerCompileUnit.h" 11 #include "llvm/MC/MCAsmBackend.h" 12 #include "llvm/MC/MCCodeEmitter.h" 13 #include "llvm/MC/MCObjectWriter.h" 14 #include "llvm/MC/MCSubtargetInfo.h" 15 #include "llvm/MC/MCTargetOptions.h" 16 #include "llvm/MC/MCTargetOptionsCommandFlags.h" 17 #include "llvm/MC/TargetRegistry.h" 18 #include "llvm/Support/FormattedStream.h" 19 20 using namespace llvm; 21 using namespace dwarf_linker; 22 using namespace dwarf_linker::parallel; 23 24 Error DwarfEmitterImpl::init(Triple TheTriple, 25 StringRef Swift5ReflectionSegmentName) { 26 std::string ErrorStr; 27 std::string TripleName; 28 29 // Get the target. 30 const Target *TheTarget = 31 TargetRegistry::lookupTarget(TripleName, TheTriple, ErrorStr); 32 if (!TheTarget) 33 return createStringError(std::errc::invalid_argument, ErrorStr.c_str()); 34 TripleName = TheTriple.getTriple(); 35 36 // Create all the MC Objects. 37 MRI.reset(TheTarget->createMCRegInfo(TripleName)); 38 if (!MRI) 39 return createStringError(std::errc::invalid_argument, 40 "no register info for target %s", 41 TripleName.c_str()); 42 43 MCTargetOptions MCOptions = mc::InitMCTargetOptionsFromFlags(); 44 MAI.reset(TheTarget->createMCAsmInfo(*MRI, TripleName, MCOptions)); 45 if (!MAI) 46 return createStringError(std::errc::invalid_argument, 47 "no asm info for target %s", TripleName.c_str()); 48 49 MSTI.reset(TheTarget->createMCSubtargetInfo(TripleName, "", "")); 50 if (!MSTI) 51 return createStringError(std::errc::invalid_argument, 52 "no subtarget info for target %s", 53 TripleName.c_str()); 54 55 MC.reset(new MCContext(TheTriple, MAI.get(), MRI.get(), MSTI.get(), nullptr, 56 nullptr, true, Swift5ReflectionSegmentName)); 57 MOFI.reset(TheTarget->createMCObjectFileInfo(*MC, /*PIC=*/false, false)); 58 MC->setObjectFileInfo(MOFI.get()); 59 60 MAB = TheTarget->createMCAsmBackend(*MSTI, *MRI, MCOptions); 61 if (!MAB) 62 return createStringError(std::errc::invalid_argument, 63 "no asm backend for target %s", 64 TripleName.c_str()); 65 66 MII.reset(TheTarget->createMCInstrInfo()); 67 if (!MII) 68 return createStringError(std::errc::invalid_argument, 69 "no instr info info for target %s", 70 TripleName.c_str()); 71 72 MCE = TheTarget->createMCCodeEmitter(*MII, *MC); 73 if (!MCE) 74 return createStringError(std::errc::invalid_argument, 75 "no code emitter for target %s", 76 TripleName.c_str()); 77 78 switch (OutFileType) { 79 case DWARFLinker::OutputFileType::Assembly: { 80 MIP = TheTarget->createMCInstPrinter(TheTriple, MAI->getAssemblerDialect(), 81 *MAI, *MII, *MRI); 82 MS = TheTarget->createAsmStreamer( 83 *MC, std::make_unique<formatted_raw_ostream>(OutFile), true, true, MIP, 84 std::unique_ptr<MCCodeEmitter>(MCE), std::unique_ptr<MCAsmBackend>(MAB), 85 true); 86 break; 87 } 88 case DWARFLinker::OutputFileType::Object: { 89 MS = TheTarget->createMCObjectStreamer( 90 TheTriple, *MC, std::unique_ptr<MCAsmBackend>(MAB), 91 MAB->createObjectWriter(OutFile), std::unique_ptr<MCCodeEmitter>(MCE), 92 *MSTI, MCOptions.MCRelaxAll, MCOptions.MCIncrementalLinkerCompatible, 93 /*DWARFMustBeAtTheEnd*/ false); 94 break; 95 } 96 } 97 98 if (!MS) 99 return createStringError(std::errc::invalid_argument, 100 "no object streamer for target %s", 101 TripleName.c_str()); 102 103 // Finally create the AsmPrinter we'll use to emit the DIEs. 104 TM.reset(TheTarget->createTargetMachine(TripleName, "", "", TargetOptions(), 105 std::nullopt)); 106 if (!TM) 107 return createStringError(std::errc::invalid_argument, 108 "no target machine for target %s", 109 TripleName.c_str()); 110 111 Asm.reset(TheTarget->createAsmPrinter(*TM, std::unique_ptr<MCStreamer>(MS))); 112 if (!Asm) 113 return createStringError(std::errc::invalid_argument, 114 "no asm printer for target %s", 115 TripleName.c_str()); 116 Asm->setDwarfUsesRelocationsAcrossSections(false); 117 118 DebugInfoSectionSize = 0; 119 120 return Error::success(); 121 } 122 123 void DwarfEmitterImpl::emitSwiftAST(StringRef Buffer) { 124 MCSection *SwiftASTSection = MOFI->getDwarfSwiftASTSection(); 125 SwiftASTSection->setAlignment(Align(32)); 126 MS->switchSection(SwiftASTSection); 127 MS->emitBytes(Buffer); 128 } 129 130 /// Emit the swift reflection section stored in \p Buffer. 131 void DwarfEmitterImpl::emitSwiftReflectionSection( 132 llvm::binaryformat::Swift5ReflectionSectionKind ReflSectionKind, 133 StringRef Buffer, uint32_t Alignment, uint32_t) { 134 MCSection *ReflectionSection = 135 MOFI->getSwift5ReflectionSection(ReflSectionKind); 136 if (ReflectionSection == nullptr) 137 return; 138 ReflectionSection->setAlignment(Align(Alignment)); 139 MS->switchSection(ReflectionSection); 140 MS->emitBytes(Buffer); 141 } 142 143 void DwarfEmitterImpl::emitSectionContents(StringRef SecData, 144 StringRef SecName) { 145 if (SecData.empty()) 146 return; 147 148 if (MCSection *Section = switchSection(SecName)) { 149 MS->switchSection(Section); 150 151 MS->emitBytes(SecData); 152 } 153 } 154 155 MCSection *DwarfEmitterImpl::switchSection(StringRef SecName) { 156 return StringSwitch<MCSection *>(SecName) 157 .Case("debug_info", MC->getObjectFileInfo()->getDwarfInfoSection()) 158 .Case("debug_abbrev", MC->getObjectFileInfo()->getDwarfAbbrevSection()) 159 .Case("debug_line", MC->getObjectFileInfo()->getDwarfLineSection()) 160 .Case("debug_loc", MC->getObjectFileInfo()->getDwarfLocSection()) 161 .Case("debug_ranges", MC->getObjectFileInfo()->getDwarfRangesSection()) 162 .Case("debug_frame", MC->getObjectFileInfo()->getDwarfFrameSection()) 163 .Case("debug_aranges", MC->getObjectFileInfo()->getDwarfARangesSection()) 164 .Case("debug_rnglists", 165 MC->getObjectFileInfo()->getDwarfRnglistsSection()) 166 .Case("debug_loclists", 167 MC->getObjectFileInfo()->getDwarfLoclistsSection()) 168 .Case("debug_macro", MC->getObjectFileInfo()->getDwarfMacroSection()) 169 .Case("debug_macinfo", MC->getObjectFileInfo()->getDwarfMacinfoSection()) 170 .Case("debug_addr", MC->getObjectFileInfo()->getDwarfAddrSection()) 171 .Case("debug_str", MC->getObjectFileInfo()->getDwarfStrSection()) 172 .Case("debug_line_str", MC->getObjectFileInfo()->getDwarfLineStrSection()) 173 .Case("debug_str_offsets", 174 MC->getObjectFileInfo()->getDwarfStrOffSection()) 175 .Case("debug_pubnames", 176 MC->getObjectFileInfo()->getDwarfPubNamesSection()) 177 .Case("debug_pubtypes", 178 MC->getObjectFileInfo()->getDwarfPubTypesSection()) 179 .Case("debug_names", MC->getObjectFileInfo()->getDwarfDebugNamesSection()) 180 .Case("apple_names", MC->getObjectFileInfo()->getDwarfAccelNamesSection()) 181 .Case("apple_namespac", 182 MC->getObjectFileInfo()->getDwarfAccelNamespaceSection()) 183 .Case("apple_objc", MC->getObjectFileInfo()->getDwarfAccelObjCSection()) 184 .Case("apple_types", MC->getObjectFileInfo()->getDwarfAccelTypesSection()) 185 186 .Default(nullptr); 187 } 188 189 void DwarfEmitterImpl::emitAbbrevs( 190 const SmallVector<std::unique_ptr<DIEAbbrev>> &Abbrevs, 191 unsigned DwarfVersion) { 192 MS->switchSection(MOFI->getDwarfAbbrevSection()); 193 MC->setDwarfVersion(DwarfVersion); 194 Asm->emitDwarfAbbrevs(Abbrevs); 195 } 196 197 void DwarfEmitterImpl::emitCompileUnitHeader(DwarfUnit &Unit) { 198 MS->switchSection(MOFI->getDwarfInfoSection()); 199 MC->setDwarfVersion(Unit.getVersion()); 200 201 // Emit size of content not including length itself. The size has already 202 // been computed in CompileUnit::computeOffsets(). Subtract 4 to that size to 203 // account for the length field. 204 Asm->emitInt32(Unit.getUnitSize() - 4); 205 Asm->emitInt16(Unit.getVersion()); 206 207 if (Unit.getVersion() >= 5) { 208 Asm->emitInt8(dwarf::DW_UT_compile); 209 Asm->emitInt8(Unit.getFormParams().AddrSize); 210 // Proper offset to the abbreviations table will be set later. 211 Asm->emitInt32(0); 212 DebugInfoSectionSize += 12; 213 } else { 214 // Proper offset to the abbreviations table will be set later. 215 Asm->emitInt32(0); 216 Asm->emitInt8(Unit.getFormParams().AddrSize); 217 DebugInfoSectionSize += 11; 218 } 219 } 220 221 void DwarfEmitterImpl::emitDIE(DIE &Die) { 222 MS->switchSection(MOFI->getDwarfInfoSection()); 223 Asm->emitDwarfDIE(Die); 224 DebugInfoSectionSize += Die.getSize(); 225 } 226 227 void DwarfEmitterImpl::emitDebugNames(DWARF5AccelTable &Table, 228 DebugNamesUnitsOffsets &CUOffsets, 229 CompUnitIDToIdx &CUidToIdx) { 230 if (CUOffsets.empty()) 231 return; 232 233 Asm->OutStreamer->switchSection(MOFI->getDwarfDebugNamesSection()); 234 dwarf::Form Form = 235 DIEInteger::BestForm(/*IsSigned*/ false, (uint64_t)CUidToIdx.size() - 1); 236 // FIXME: add support for type units + .debug_names. For now the behavior is 237 // unsuported. 238 emitDWARF5AccelTable( 239 Asm.get(), Table, CUOffsets, 240 [&](const DWARF5AccelTableData &Entry) 241 -> std::optional<DWARF5AccelTable::UnitIndexAndEncoding> { 242 if (CUidToIdx.size() > 1) 243 return {{CUidToIdx[Entry.getUnitID()], 244 {dwarf::DW_IDX_compile_unit, Form}}}; 245 return std::nullopt; 246 }); 247 } 248 249 void DwarfEmitterImpl::emitAppleNamespaces( 250 AccelTable<AppleAccelTableStaticOffsetData> &Table) { 251 Asm->OutStreamer->switchSection(MOFI->getDwarfAccelNamespaceSection()); 252 auto *SectionBegin = Asm->createTempSymbol("namespac_begin"); 253 Asm->OutStreamer->emitLabel(SectionBegin); 254 emitAppleAccelTable(Asm.get(), Table, "namespac", SectionBegin); 255 } 256 257 void DwarfEmitterImpl::emitAppleNames( 258 AccelTable<AppleAccelTableStaticOffsetData> &Table) { 259 Asm->OutStreamer->switchSection(MOFI->getDwarfAccelNamesSection()); 260 auto *SectionBegin = Asm->createTempSymbol("names_begin"); 261 Asm->OutStreamer->emitLabel(SectionBegin); 262 emitAppleAccelTable(Asm.get(), Table, "names", SectionBegin); 263 } 264 265 void DwarfEmitterImpl::emitAppleObjc( 266 AccelTable<AppleAccelTableStaticOffsetData> &Table) { 267 Asm->OutStreamer->switchSection(MOFI->getDwarfAccelObjCSection()); 268 auto *SectionBegin = Asm->createTempSymbol("objc_begin"); 269 Asm->OutStreamer->emitLabel(SectionBegin); 270 emitAppleAccelTable(Asm.get(), Table, "objc", SectionBegin); 271 } 272 273 void DwarfEmitterImpl::emitAppleTypes( 274 AccelTable<AppleAccelTableStaticTypeData> &Table) { 275 Asm->OutStreamer->switchSection(MOFI->getDwarfAccelTypesSection()); 276 auto *SectionBegin = Asm->createTempSymbol("types_begin"); 277 Asm->OutStreamer->emitLabel(SectionBegin); 278 emitAppleAccelTable(Asm.get(), Table, "types", SectionBegin); 279 } 280