1 | //===- DwarfStreamer.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 "llvm/DWARFLinker/Classic/DWARFStreamer.h" |
10 | #include "llvm/CodeGen/NonRelocatableStringpool.h" |
11 | #include "llvm/DWARFLinker/Classic/DWARFLinkerCompileUnit.h" |
12 | #include "llvm/DebugInfo/DWARF/DWARFContext.h" |
13 | #include "llvm/DebugInfo/DWARF/DWARFDebugMacro.h" |
14 | #include "llvm/MC/MCAsmBackend.h" |
15 | #include "llvm/MC/MCCodeEmitter.h" |
16 | #include "llvm/MC/MCDwarf.h" |
17 | #include "llvm/MC/MCObjectWriter.h" |
18 | #include "llvm/MC/MCSection.h" |
19 | #include "llvm/MC/MCStreamer.h" |
20 | #include "llvm/MC/MCSubtargetInfo.h" |
21 | #include "llvm/MC/MCTargetOptions.h" |
22 | #include "llvm/MC/MCTargetOptionsCommandFlags.h" |
23 | #include "llvm/MC/TargetRegistry.h" |
24 | #include "llvm/Support/FormatVariadic.h" |
25 | #include "llvm/Support/LEB128.h" |
26 | #include "llvm/Target/TargetOptions.h" |
27 | #include "llvm/TargetParser/Triple.h" |
28 | |
29 | using namespace llvm; |
30 | using namespace dwarf_linker; |
31 | using namespace dwarf_linker::classic; |
32 | |
33 | Expected<std::unique_ptr<DwarfStreamer>> DwarfStreamer::createStreamer( |
34 | const Triple &TheTriple, DWARFLinkerBase::OutputFileType FileType, |
35 | raw_pwrite_stream &OutFile, DWARFLinkerBase::MessageHandlerTy Warning) { |
36 | std::unique_ptr<DwarfStreamer> Streamer = |
37 | std::make_unique<DwarfStreamer>(args&: FileType, args&: OutFile, args&: Warning); |
38 | if (Error Err = Streamer->init(TheTriple, Swift5ReflectionSegmentName: "__DWARF" )) |
39 | return std::move(Err); |
40 | |
41 | return std::move(Streamer); |
42 | } |
43 | |
44 | Error DwarfStreamer::init(Triple TheTriple, |
45 | StringRef Swift5ReflectionSegmentName) { |
46 | std::string ErrorStr; |
47 | std::string TripleName; |
48 | |
49 | // Get the target. |
50 | const Target *TheTarget = |
51 | TargetRegistry::lookupTarget(ArchName: TripleName, TheTriple, Error&: ErrorStr); |
52 | if (!TheTarget) |
53 | return createStringError(EC: std::errc::invalid_argument, Fmt: ErrorStr.c_str()); |
54 | |
55 | TripleName = TheTriple.getTriple(); |
56 | |
57 | // Create all the MC Objects. |
58 | MRI.reset(p: TheTarget->createMCRegInfo(TT: TripleName)); |
59 | if (!MRI) |
60 | return createStringError(EC: std::errc::invalid_argument, |
61 | Fmt: "no register info for target %s" , |
62 | Vals: TripleName.c_str()); |
63 | |
64 | MCTargetOptions MCOptions = mc::InitMCTargetOptionsFromFlags(); |
65 | MAI.reset(p: TheTarget->createMCAsmInfo(MRI: *MRI, TheTriple: TripleName, Options: MCOptions)); |
66 | if (!MAI) |
67 | return createStringError(EC: std::errc::invalid_argument, |
68 | Fmt: "no asm info for target %s" , Vals: TripleName.c_str()); |
69 | |
70 | MSTI.reset(p: TheTarget->createMCSubtargetInfo(TheTriple: TripleName, CPU: "" , Features: "" )); |
71 | if (!MSTI) |
72 | return createStringError(EC: std::errc::invalid_argument, |
73 | Fmt: "no subtarget info for target %s" , |
74 | Vals: TripleName.c_str()); |
75 | |
76 | MC.reset(p: new MCContext(TheTriple, MAI.get(), MRI.get(), MSTI.get(), nullptr, |
77 | nullptr, true, Swift5ReflectionSegmentName)); |
78 | MOFI.reset(p: TheTarget->createMCObjectFileInfo(Ctx&: *MC, /*PIC=*/false, LargeCodeModel: false)); |
79 | MC->setObjectFileInfo(MOFI.get()); |
80 | |
81 | MAB = TheTarget->createMCAsmBackend(STI: *MSTI, MRI: *MRI, Options: MCOptions); |
82 | if (!MAB) |
83 | return createStringError(EC: std::errc::invalid_argument, |
84 | Fmt: "no asm backend for target %s" , |
85 | Vals: TripleName.c_str()); |
86 | |
87 | MII.reset(p: TheTarget->createMCInstrInfo()); |
88 | if (!MII) |
89 | return createStringError(EC: std::errc::invalid_argument, |
90 | Fmt: "no instr info info for target %s" , |
91 | Vals: TripleName.c_str()); |
92 | |
93 | MCE = TheTarget->createMCCodeEmitter(II: *MII, Ctx&: *MC); |
94 | if (!MCE) |
95 | return createStringError(EC: std::errc::invalid_argument, |
96 | Fmt: "no code emitter for target %s" , |
97 | Vals: TripleName.c_str()); |
98 | |
99 | switch (OutFileType) { |
100 | case DWARFLinker::OutputFileType::Assembly: { |
101 | MIP = TheTarget->createMCInstPrinter(T: TheTriple, SyntaxVariant: MAI->getAssemblerDialect(), |
102 | MAI: *MAI, MII: *MII, MRI: *MRI); |
103 | MS = TheTarget->createAsmStreamer( |
104 | Ctx&: *MC, OS: std::make_unique<formatted_raw_ostream>(args&: OutFile), IsVerboseAsm: true, UseDwarfDirectory: true, InstPrint: MIP, |
105 | CE: std::unique_ptr<MCCodeEmitter>(MCE), TAB: std::unique_ptr<MCAsmBackend>(MAB), |
106 | ShowInst: true); |
107 | break; |
108 | } |
109 | case DWARFLinker::OutputFileType::Object: { |
110 | MS = TheTarget->createMCObjectStreamer( |
111 | T: TheTriple, Ctx&: *MC, TAB: std::unique_ptr<MCAsmBackend>(MAB), |
112 | OW: MAB->createObjectWriter(OS&: OutFile), Emitter: std::unique_ptr<MCCodeEmitter>(MCE), |
113 | STI: *MSTI, RelaxAll: MCOptions.MCRelaxAll, IncrementalLinkerCompatible: MCOptions.MCIncrementalLinkerCompatible, |
114 | /*DWARFMustBeAtTheEnd*/ false); |
115 | break; |
116 | } |
117 | } |
118 | |
119 | if (!MS) |
120 | return createStringError(EC: std::errc::invalid_argument, |
121 | Fmt: "no object streamer for target %s" , |
122 | Vals: TripleName.c_str()); |
123 | |
124 | // Finally create the AsmPrinter we'll use to emit the DIEs. |
125 | TM.reset(p: TheTarget->createTargetMachine(TT: TripleName, CPU: "" , Features: "" , Options: TargetOptions(), |
126 | RM: std::nullopt)); |
127 | if (!TM) |
128 | return createStringError(EC: std::errc::invalid_argument, |
129 | Fmt: "no target machine for target %s" , |
130 | Vals: TripleName.c_str()); |
131 | |
132 | Asm.reset(p: TheTarget->createAsmPrinter(TM&: *TM, Streamer: std::unique_ptr<MCStreamer>(MS))); |
133 | if (!Asm) |
134 | return createStringError(EC: std::errc::invalid_argument, |
135 | Fmt: "no asm printer for target %s" , |
136 | Vals: TripleName.c_str()); |
137 | Asm->setDwarfUsesRelocationsAcrossSections(false); |
138 | |
139 | RangesSectionSize = 0; |
140 | RngListsSectionSize = 0; |
141 | LocSectionSize = 0; |
142 | LocListsSectionSize = 0; |
143 | LineSectionSize = 0; |
144 | FrameSectionSize = 0; |
145 | DebugInfoSectionSize = 0; |
146 | MacInfoSectionSize = 0; |
147 | MacroSectionSize = 0; |
148 | |
149 | return Error::success(); |
150 | } |
151 | |
152 | void DwarfStreamer::finish() { MS->finish(); } |
153 | |
154 | void DwarfStreamer::switchToDebugInfoSection(unsigned DwarfVersion) { |
155 | MS->switchSection(Section: MOFI->getDwarfInfoSection()); |
156 | MC->setDwarfVersion(DwarfVersion); |
157 | } |
158 | |
159 | /// Emit the compilation unit header for \p Unit in the debug_info section. |
160 | /// |
161 | /// A Dwarf 4 section header is encoded as: |
162 | /// uint32_t Unit length (omitting this field) |
163 | /// uint16_t Version |
164 | /// uint32_t Abbreviation table offset |
165 | /// uint8_t Address size |
166 | /// Leading to a total of 11 bytes. |
167 | /// |
168 | /// A Dwarf 5 section header is encoded as: |
169 | /// uint32_t Unit length (omitting this field) |
170 | /// uint16_t Version |
171 | /// uint8_t Unit type |
172 | /// uint8_t Address size |
173 | /// uint32_t Abbreviation table offset |
174 | /// Leading to a total of 12 bytes. |
175 | void DwarfStreamer::(CompileUnit &Unit, |
176 | unsigned DwarfVersion) { |
177 | switchToDebugInfoSection(DwarfVersion); |
178 | |
179 | /// The start of the unit within its section. |
180 | Unit.setLabelBegin(Asm->createTempSymbol(Name: "cu_begin" )); |
181 | Asm->OutStreamer->emitLabel(Symbol: Unit.getLabelBegin()); |
182 | |
183 | // Emit size of content not including length itself. The size has already |
184 | // been computed in CompileUnit::computeOffsets(). Subtract 4 to that size to |
185 | // account for the length field. |
186 | Asm->emitInt32(Value: Unit.getNextUnitOffset() - Unit.getStartOffset() - 4); |
187 | Asm->emitInt16(Value: DwarfVersion); |
188 | |
189 | if (DwarfVersion >= 5) { |
190 | Asm->emitInt8(Value: dwarf::DW_UT_compile); |
191 | Asm->emitInt8(Value: Unit.getOrigUnit().getAddressByteSize()); |
192 | // We share one abbreviations table across all units so it's always at the |
193 | // start of the section. |
194 | Asm->emitInt32(Value: 0); |
195 | DebugInfoSectionSize += 12; |
196 | } else { |
197 | // We share one abbreviations table across all units so it's always at the |
198 | // start of the section. |
199 | Asm->emitInt32(Value: 0); |
200 | Asm->emitInt8(Value: Unit.getOrigUnit().getAddressByteSize()); |
201 | DebugInfoSectionSize += 11; |
202 | } |
203 | |
204 | // Remember this CU. |
205 | EmittedUnits.push_back(x: {.ID: Unit.getUniqueID(), .LabelBegin: Unit.getLabelBegin()}); |
206 | } |
207 | |
208 | /// Emit the \p Abbrevs array as the shared abbreviation table |
209 | /// for the linked Dwarf file. |
210 | void DwarfStreamer::emitAbbrevs( |
211 | const std::vector<std::unique_ptr<DIEAbbrev>> &Abbrevs, |
212 | unsigned DwarfVersion) { |
213 | MS->switchSection(Section: MOFI->getDwarfAbbrevSection()); |
214 | MC->setDwarfVersion(DwarfVersion); |
215 | Asm->emitDwarfAbbrevs(Abbrevs); |
216 | } |
217 | |
218 | /// Recursively emit the DIE tree rooted at \p Die. |
219 | void DwarfStreamer::emitDIE(DIE &Die) { |
220 | MS->switchSection(Section: MOFI->getDwarfInfoSection()); |
221 | Asm->emitDwarfDIE(Die); |
222 | DebugInfoSectionSize += Die.getSize(); |
223 | } |
224 | |
225 | /// Emit contents of section SecName From Obj. |
226 | void DwarfStreamer::emitSectionContents(StringRef SecData, |
227 | DebugSectionKind SecKind) { |
228 | if (SecData.empty()) |
229 | return; |
230 | |
231 | if (MCSection *Section = getMCSection(SecKind)) { |
232 | MS->switchSection(Section); |
233 | |
234 | MS->emitBytes(Data: SecData); |
235 | } |
236 | } |
237 | |
238 | MCSection *DwarfStreamer::getMCSection(DebugSectionKind SecKind) { |
239 | switch (SecKind) { |
240 | case DebugSectionKind::DebugInfo: |
241 | return MC->getObjectFileInfo()->getDwarfInfoSection(); |
242 | case DebugSectionKind::DebugLine: |
243 | return MC->getObjectFileInfo()->getDwarfLineSection(); |
244 | case DebugSectionKind::DebugFrame: |
245 | return MC->getObjectFileInfo()->getDwarfFrameSection(); |
246 | case DebugSectionKind::DebugRange: |
247 | return MC->getObjectFileInfo()->getDwarfRangesSection(); |
248 | case DebugSectionKind::DebugRngLists: |
249 | return MC->getObjectFileInfo()->getDwarfRnglistsSection(); |
250 | case DebugSectionKind::DebugLoc: |
251 | return MC->getObjectFileInfo()->getDwarfLocSection(); |
252 | case DebugSectionKind::DebugLocLists: |
253 | return MC->getObjectFileInfo()->getDwarfLoclistsSection(); |
254 | case DebugSectionKind::DebugARanges: |
255 | return MC->getObjectFileInfo()->getDwarfARangesSection(); |
256 | case DebugSectionKind::DebugAbbrev: |
257 | return MC->getObjectFileInfo()->getDwarfAbbrevSection(); |
258 | case DebugSectionKind::DebugMacinfo: |
259 | return MC->getObjectFileInfo()->getDwarfMacinfoSection(); |
260 | case DebugSectionKind::DebugMacro: |
261 | return MC->getObjectFileInfo()->getDwarfMacroSection(); |
262 | case DebugSectionKind::DebugAddr: |
263 | return MC->getObjectFileInfo()->getDwarfAddrSection(); |
264 | case DebugSectionKind::DebugStr: |
265 | return MC->getObjectFileInfo()->getDwarfStrSection(); |
266 | case DebugSectionKind::DebugLineStr: |
267 | return MC->getObjectFileInfo()->getDwarfLineStrSection(); |
268 | case DebugSectionKind::DebugStrOffsets: |
269 | return MC->getObjectFileInfo()->getDwarfStrOffSection(); |
270 | case DebugSectionKind::DebugPubNames: |
271 | return MC->getObjectFileInfo()->getDwarfPubNamesSection(); |
272 | case DebugSectionKind::DebugPubTypes: |
273 | return MC->getObjectFileInfo()->getDwarfPubTypesSection(); |
274 | case DebugSectionKind::DebugNames: |
275 | return MC->getObjectFileInfo()->getDwarfDebugNamesSection(); |
276 | case DebugSectionKind::AppleNames: |
277 | return MC->getObjectFileInfo()->getDwarfAccelNamesSection(); |
278 | case DebugSectionKind::AppleNamespaces: |
279 | return MC->getObjectFileInfo()->getDwarfAccelNamespaceSection(); |
280 | case DebugSectionKind::AppleObjC: |
281 | return MC->getObjectFileInfo()->getDwarfAccelObjCSection(); |
282 | case DebugSectionKind::AppleTypes: |
283 | return MC->getObjectFileInfo()->getDwarfAccelTypesSection(); |
284 | case DebugSectionKind::NumberOfEnumEntries: |
285 | llvm_unreachable("Unknown DebugSectionKind value" ); |
286 | break; |
287 | } |
288 | |
289 | return nullptr; |
290 | } |
291 | |
292 | /// Emit the debug_str section stored in \p Pool. |
293 | void DwarfStreamer::emitStrings(const NonRelocatableStringpool &Pool) { |
294 | Asm->OutStreamer->switchSection(Section: MOFI->getDwarfStrSection()); |
295 | std::vector<DwarfStringPoolEntryRef> Entries = Pool.getEntriesForEmission(); |
296 | for (auto Entry : Entries) { |
297 | // Emit the string itself. |
298 | Asm->OutStreamer->emitBytes(Data: Entry.getString()); |
299 | // Emit a null terminator. |
300 | Asm->emitInt8(Value: 0); |
301 | } |
302 | } |
303 | |
304 | /// Emit the debug string offset table described by \p StringOffsets into the |
305 | /// .debug_str_offsets table. |
306 | void DwarfStreamer::emitStringOffsets( |
307 | const SmallVector<uint64_t> &StringOffsets, uint16_t TargetDWARFVersion) { |
308 | |
309 | if (TargetDWARFVersion < 5 || StringOffsets.empty()) |
310 | return; |
311 | |
312 | Asm->OutStreamer->switchSection(Section: MOFI->getDwarfStrOffSection()); |
313 | |
314 | MCSymbol *BeginLabel = Asm->createTempSymbol(Name: "Bdebugstroff" ); |
315 | MCSymbol *EndLabel = Asm->createTempSymbol(Name: "Edebugstroff" ); |
316 | |
317 | // Length. |
318 | Asm->emitLabelDifference(Hi: EndLabel, Lo: BeginLabel, Size: sizeof(uint32_t)); |
319 | Asm->OutStreamer->emitLabel(Symbol: BeginLabel); |
320 | StrOffsetSectionSize += sizeof(uint32_t); |
321 | |
322 | // Version. |
323 | MS->emitInt16(Value: 5); |
324 | StrOffsetSectionSize += sizeof(uint16_t); |
325 | |
326 | // Padding. |
327 | MS->emitInt16(Value: 0); |
328 | StrOffsetSectionSize += sizeof(uint16_t); |
329 | |
330 | for (auto Off : StringOffsets) { |
331 | Asm->OutStreamer->emitInt32(Value: Off); |
332 | StrOffsetSectionSize += sizeof(uint32_t); |
333 | } |
334 | Asm->OutStreamer->emitLabel(Symbol: EndLabel); |
335 | } |
336 | |
337 | /// Emit the debug_line_str section stored in \p Pool. |
338 | void DwarfStreamer::emitLineStrings(const NonRelocatableStringpool &Pool) { |
339 | Asm->OutStreamer->switchSection(Section: MOFI->getDwarfLineStrSection()); |
340 | std::vector<DwarfStringPoolEntryRef> Entries = Pool.getEntriesForEmission(); |
341 | for (auto Entry : Entries) { |
342 | // Emit the string itself. |
343 | Asm->OutStreamer->emitBytes(Data: Entry.getString()); |
344 | // Emit a null terminator. |
345 | Asm->emitInt8(Value: 0); |
346 | } |
347 | } |
348 | |
349 | void DwarfStreamer::emitDebugNames(DWARF5AccelTable &Table) { |
350 | if (EmittedUnits.empty()) |
351 | return; |
352 | |
353 | // Build up data structures needed to emit this section. |
354 | std::vector<std::variant<MCSymbol *, uint64_t>> CompUnits; |
355 | DenseMap<unsigned, unsigned> UniqueIdToCuMap; |
356 | unsigned Id = 0; |
357 | for (auto &CU : EmittedUnits) { |
358 | CompUnits.push_back(x: CU.LabelBegin); |
359 | // We might be omitting CUs, so we need to remap them. |
360 | UniqueIdToCuMap[CU.ID] = Id++; |
361 | } |
362 | |
363 | Asm->OutStreamer->switchSection(Section: MOFI->getDwarfDebugNamesSection()); |
364 | dwarf::Form Form = DIEInteger::BestForm(/*IsSigned*/ false, |
365 | Int: (uint64_t)UniqueIdToCuMap.size() - 1); |
366 | /// llvm-dwarfutil doesn't support type units + .debug_names right now. |
367 | // FIXME: add support for type units + .debug_names. For now the behavior is |
368 | // unsuported. |
369 | emitDWARF5AccelTable( |
370 | Asm: Asm.get(), Contents&: Table, CUs: CompUnits, |
371 | getIndexForEntry: [&](const DWARF5AccelTableData &Entry) |
372 | -> std::optional<DWARF5AccelTable::UnitIndexAndEncoding> { |
373 | if (UniqueIdToCuMap.size() > 1) |
374 | return {{.Index: UniqueIdToCuMap[Entry.getUnitID()], |
375 | .Encoding: {.Index: dwarf::DW_IDX_compile_unit, .Form: Form}}}; |
376 | return std::nullopt; |
377 | }); |
378 | } |
379 | |
380 | void DwarfStreamer::emitAppleNamespaces( |
381 | AccelTable<AppleAccelTableStaticOffsetData> &Table) { |
382 | Asm->OutStreamer->switchSection(Section: MOFI->getDwarfAccelNamespaceSection()); |
383 | auto *SectionBegin = Asm->createTempSymbol(Name: "namespac_begin" ); |
384 | Asm->OutStreamer->emitLabel(Symbol: SectionBegin); |
385 | emitAppleAccelTable(Asm: Asm.get(), Contents&: Table, Prefix: "namespac" , SecBegin: SectionBegin); |
386 | } |
387 | |
388 | void DwarfStreamer::emitAppleNames( |
389 | AccelTable<AppleAccelTableStaticOffsetData> &Table) { |
390 | Asm->OutStreamer->switchSection(Section: MOFI->getDwarfAccelNamesSection()); |
391 | auto *SectionBegin = Asm->createTempSymbol(Name: "names_begin" ); |
392 | Asm->OutStreamer->emitLabel(Symbol: SectionBegin); |
393 | emitAppleAccelTable(Asm: Asm.get(), Contents&: Table, Prefix: "names" , SecBegin: SectionBegin); |
394 | } |
395 | |
396 | void DwarfStreamer::emitAppleObjc( |
397 | AccelTable<AppleAccelTableStaticOffsetData> &Table) { |
398 | Asm->OutStreamer->switchSection(Section: MOFI->getDwarfAccelObjCSection()); |
399 | auto *SectionBegin = Asm->createTempSymbol(Name: "objc_begin" ); |
400 | Asm->OutStreamer->emitLabel(Symbol: SectionBegin); |
401 | emitAppleAccelTable(Asm: Asm.get(), Contents&: Table, Prefix: "objc" , SecBegin: SectionBegin); |
402 | } |
403 | |
404 | void DwarfStreamer::emitAppleTypes( |
405 | AccelTable<AppleAccelTableStaticTypeData> &Table) { |
406 | Asm->OutStreamer->switchSection(Section: MOFI->getDwarfAccelTypesSection()); |
407 | auto *SectionBegin = Asm->createTempSymbol(Name: "types_begin" ); |
408 | Asm->OutStreamer->emitLabel(Symbol: SectionBegin); |
409 | emitAppleAccelTable(Asm: Asm.get(), Contents&: Table, Prefix: "types" , SecBegin: SectionBegin); |
410 | } |
411 | |
412 | /// Emit the swift_ast section stored in \p Buffers. |
413 | void DwarfStreamer::emitSwiftAST(StringRef Buffer) { |
414 | MCSection *SwiftASTSection = MOFI->getDwarfSwiftASTSection(); |
415 | SwiftASTSection->setAlignment(Align(32)); |
416 | MS->switchSection(Section: SwiftASTSection); |
417 | MS->emitBytes(Data: Buffer); |
418 | } |
419 | |
420 | void DwarfStreamer::emitSwiftReflectionSection( |
421 | llvm::binaryformat::Swift5ReflectionSectionKind ReflSectionKind, |
422 | StringRef Buffer, uint32_t Alignment, uint32_t Size) { |
423 | MCSection *ReflectionSection = |
424 | MOFI->getSwift5ReflectionSection(ReflSectionKind); |
425 | if (ReflectionSection == nullptr) |
426 | return; |
427 | ReflectionSection->setAlignment(Align(Alignment)); |
428 | MS->switchSection(Section: ReflectionSection); |
429 | MS->emitBytes(Data: Buffer); |
430 | } |
431 | |
432 | void DwarfStreamer::emitDwarfDebugArangesTable( |
433 | const CompileUnit &Unit, const AddressRanges &LinkedRanges) { |
434 | unsigned AddressSize = Unit.getOrigUnit().getAddressByteSize(); |
435 | |
436 | // Make .debug_aranges to be current section. |
437 | MS->switchSection(Section: MC->getObjectFileInfo()->getDwarfARangesSection()); |
438 | |
439 | // Emit Header. |
440 | MCSymbol *BeginLabel = Asm->createTempSymbol(Name: "Barange" ); |
441 | MCSymbol *EndLabel = Asm->createTempSymbol(Name: "Earange" ); |
442 | |
443 | unsigned = |
444 | sizeof(int32_t) + // Size of contents (w/o this field |
445 | sizeof(int16_t) + // DWARF ARange version number |
446 | sizeof(int32_t) + // Offset of CU in the .debug_info section |
447 | sizeof(int8_t) + // Pointer Size (in bytes) |
448 | sizeof(int8_t); // Segment Size (in bytes) |
449 | |
450 | unsigned TupleSize = AddressSize * 2; |
451 | unsigned Padding = offsetToAlignment(Value: HeaderSize, Alignment: Align(TupleSize)); |
452 | |
453 | Asm->emitLabelDifference(Hi: EndLabel, Lo: BeginLabel, Size: 4); // Arange length |
454 | Asm->OutStreamer->emitLabel(Symbol: BeginLabel); |
455 | Asm->emitInt16(Value: dwarf::DW_ARANGES_VERSION); // Version number |
456 | Asm->emitInt32(Value: Unit.getStartOffset()); // Corresponding unit's offset |
457 | Asm->emitInt8(Value: AddressSize); // Address size |
458 | Asm->emitInt8(Value: 0); // Segment size |
459 | |
460 | Asm->OutStreamer->emitFill(NumBytes: Padding, FillValue: 0x0); |
461 | |
462 | // Emit linked ranges. |
463 | for (const AddressRange &Range : LinkedRanges) { |
464 | MS->emitIntValue(Value: Range.start(), Size: AddressSize); |
465 | MS->emitIntValue(Value: Range.end() - Range.start(), Size: AddressSize); |
466 | } |
467 | |
468 | // Emit terminator. |
469 | Asm->OutStreamer->emitIntValue(Value: 0, Size: AddressSize); |
470 | Asm->OutStreamer->emitIntValue(Value: 0, Size: AddressSize); |
471 | Asm->OutStreamer->emitLabel(Symbol: EndLabel); |
472 | } |
473 | |
474 | void DwarfStreamer::emitDwarfDebugRangesTableFragment( |
475 | const CompileUnit &Unit, const AddressRanges &LinkedRanges, |
476 | PatchLocation Patch) { |
477 | Patch.set(RangesSectionSize); |
478 | |
479 | // Make .debug_ranges to be current section. |
480 | MS->switchSection(Section: MC->getObjectFileInfo()->getDwarfRangesSection()); |
481 | unsigned AddressSize = Unit.getOrigUnit().getAddressByteSize(); |
482 | |
483 | // Emit ranges. |
484 | uint64_t BaseAddress = 0; |
485 | if (std::optional<uint64_t> LowPC = Unit.getLowPc()) |
486 | BaseAddress = *LowPC; |
487 | |
488 | for (const AddressRange &Range : LinkedRanges) { |
489 | MS->emitIntValue(Value: Range.start() - BaseAddress, Size: AddressSize); |
490 | MS->emitIntValue(Value: Range.end() - BaseAddress, Size: AddressSize); |
491 | |
492 | RangesSectionSize += AddressSize; |
493 | RangesSectionSize += AddressSize; |
494 | } |
495 | |
496 | // Add the terminator entry. |
497 | MS->emitIntValue(Value: 0, Size: AddressSize); |
498 | MS->emitIntValue(Value: 0, Size: AddressSize); |
499 | |
500 | RangesSectionSize += AddressSize; |
501 | RangesSectionSize += AddressSize; |
502 | } |
503 | |
504 | MCSymbol * |
505 | DwarfStreamer::(const CompileUnit &Unit) { |
506 | if (Unit.getOrigUnit().getVersion() < 5) |
507 | return nullptr; |
508 | |
509 | // Make .debug_rnglists to be current section. |
510 | MS->switchSection(Section: MC->getObjectFileInfo()->getDwarfRnglistsSection()); |
511 | |
512 | MCSymbol *BeginLabel = Asm->createTempSymbol(Name: "Brnglists" ); |
513 | MCSymbol *EndLabel = Asm->createTempSymbol(Name: "Ernglists" ); |
514 | unsigned AddressSize = Unit.getOrigUnit().getAddressByteSize(); |
515 | |
516 | // Length |
517 | Asm->emitLabelDifference(Hi: EndLabel, Lo: BeginLabel, Size: sizeof(uint32_t)); |
518 | Asm->OutStreamer->emitLabel(Symbol: BeginLabel); |
519 | RngListsSectionSize += sizeof(uint32_t); |
520 | |
521 | // Version. |
522 | MS->emitInt16(Value: 5); |
523 | RngListsSectionSize += sizeof(uint16_t); |
524 | |
525 | // Address size. |
526 | MS->emitInt8(Value: AddressSize); |
527 | RngListsSectionSize++; |
528 | |
529 | // Seg_size |
530 | MS->emitInt8(Value: 0); |
531 | RngListsSectionSize++; |
532 | |
533 | // Offset entry count |
534 | MS->emitInt32(Value: 0); |
535 | RngListsSectionSize += sizeof(uint32_t); |
536 | |
537 | return EndLabel; |
538 | } |
539 | |
540 | void DwarfStreamer::emitDwarfDebugRangeListFragment( |
541 | const CompileUnit &Unit, const AddressRanges &LinkedRanges, |
542 | PatchLocation Patch, DebugDieValuePool &AddrPool) { |
543 | if (Unit.getOrigUnit().getVersion() < 5) { |
544 | emitDwarfDebugRangesTableFragment(Unit, LinkedRanges, Patch); |
545 | return; |
546 | } |
547 | |
548 | emitDwarfDebugRngListsTableFragment(Unit, LinkedRanges, Patch, AddrPool); |
549 | } |
550 | |
551 | void DwarfStreamer::(const CompileUnit &Unit, |
552 | MCSymbol *EndLabel) { |
553 | if (Unit.getOrigUnit().getVersion() < 5) |
554 | return; |
555 | |
556 | // Make .debug_rnglists to be current section. |
557 | MS->switchSection(Section: MC->getObjectFileInfo()->getDwarfRnglistsSection()); |
558 | |
559 | if (EndLabel != nullptr) |
560 | Asm->OutStreamer->emitLabel(Symbol: EndLabel); |
561 | } |
562 | |
563 | void DwarfStreamer::emitDwarfDebugRngListsTableFragment( |
564 | const CompileUnit &Unit, const AddressRanges &LinkedRanges, |
565 | PatchLocation Patch, DebugDieValuePool &AddrPool) { |
566 | Patch.set(RngListsSectionSize); |
567 | |
568 | // Make .debug_rnglists to be current section. |
569 | MS->switchSection(Section: MC->getObjectFileInfo()->getDwarfRnglistsSection()); |
570 | std::optional<uint64_t> BaseAddress; |
571 | |
572 | for (const AddressRange &Range : LinkedRanges) { |
573 | |
574 | if (!BaseAddress) { |
575 | BaseAddress = Range.start(); |
576 | |
577 | // Emit base address. |
578 | MS->emitInt8(Value: dwarf::DW_RLE_base_addressx); |
579 | RngListsSectionSize += 1; |
580 | RngListsSectionSize += |
581 | MS->emitULEB128IntValue(Value: AddrPool.getValueIndex(Value: *BaseAddress)); |
582 | } |
583 | |
584 | // Emit type of entry. |
585 | MS->emitInt8(Value: dwarf::DW_RLE_offset_pair); |
586 | RngListsSectionSize += 1; |
587 | |
588 | // Emit start offset relative to base address. |
589 | RngListsSectionSize += |
590 | MS->emitULEB128IntValue(Value: Range.start() - *BaseAddress); |
591 | |
592 | // Emit end offset relative to base address. |
593 | RngListsSectionSize += MS->emitULEB128IntValue(Value: Range.end() - *BaseAddress); |
594 | } |
595 | |
596 | // Emit the terminator entry. |
597 | MS->emitInt8(Value: dwarf::DW_RLE_end_of_list); |
598 | RngListsSectionSize += 1; |
599 | } |
600 | |
601 | /// Emit debug locations(.debug_loc, .debug_loclists) header. |
602 | MCSymbol *DwarfStreamer::(const CompileUnit &Unit) { |
603 | if (Unit.getOrigUnit().getVersion() < 5) |
604 | return nullptr; |
605 | |
606 | // Make .debug_loclists the current section. |
607 | MS->switchSection(Section: MC->getObjectFileInfo()->getDwarfLoclistsSection()); |
608 | |
609 | MCSymbol *BeginLabel = Asm->createTempSymbol(Name: "Bloclists" ); |
610 | MCSymbol *EndLabel = Asm->createTempSymbol(Name: "Eloclists" ); |
611 | unsigned AddressSize = Unit.getOrigUnit().getAddressByteSize(); |
612 | |
613 | // Length |
614 | Asm->emitLabelDifference(Hi: EndLabel, Lo: BeginLabel, Size: sizeof(uint32_t)); |
615 | Asm->OutStreamer->emitLabel(Symbol: BeginLabel); |
616 | LocListsSectionSize += sizeof(uint32_t); |
617 | |
618 | // Version. |
619 | MS->emitInt16(Value: 5); |
620 | LocListsSectionSize += sizeof(uint16_t); |
621 | |
622 | // Address size. |
623 | MS->emitInt8(Value: AddressSize); |
624 | LocListsSectionSize++; |
625 | |
626 | // Seg_size |
627 | MS->emitInt8(Value: 0); |
628 | LocListsSectionSize++; |
629 | |
630 | // Offset entry count |
631 | MS->emitInt32(Value: 0); |
632 | LocListsSectionSize += sizeof(uint32_t); |
633 | |
634 | return EndLabel; |
635 | } |
636 | |
637 | /// Emit debug locations(.debug_loc, .debug_loclists) fragment. |
638 | void DwarfStreamer::emitDwarfDebugLocListFragment( |
639 | const CompileUnit &Unit, |
640 | const DWARFLocationExpressionsVector &LinkedLocationExpression, |
641 | PatchLocation Patch, DebugDieValuePool &AddrPool) { |
642 | if (Unit.getOrigUnit().getVersion() < 5) { |
643 | emitDwarfDebugLocTableFragment(Unit, LinkedLocationExpression, Patch); |
644 | return; |
645 | } |
646 | |
647 | emitDwarfDebugLocListsTableFragment(Unit, LinkedLocationExpression, Patch, |
648 | AddrPool); |
649 | } |
650 | |
651 | /// Emit debug locations(.debug_loc, .debug_loclists) footer. |
652 | void DwarfStreamer::(const CompileUnit &Unit, |
653 | MCSymbol *EndLabel) { |
654 | if (Unit.getOrigUnit().getVersion() < 5) |
655 | return; |
656 | |
657 | // Make .debug_loclists the current section. |
658 | MS->switchSection(Section: MC->getObjectFileInfo()->getDwarfLoclistsSection()); |
659 | |
660 | if (EndLabel != nullptr) |
661 | Asm->OutStreamer->emitLabel(Symbol: EndLabel); |
662 | } |
663 | |
664 | /// Emit piece of .debug_loc for \p LinkedLocationExpression. |
665 | void DwarfStreamer::emitDwarfDebugLocTableFragment( |
666 | const CompileUnit &Unit, |
667 | const DWARFLocationExpressionsVector &LinkedLocationExpression, |
668 | PatchLocation Patch) { |
669 | Patch.set(LocSectionSize); |
670 | |
671 | // Make .debug_loc to be current section. |
672 | MS->switchSection(Section: MC->getObjectFileInfo()->getDwarfLocSection()); |
673 | unsigned AddressSize = Unit.getOrigUnit().getAddressByteSize(); |
674 | |
675 | // Emit ranges. |
676 | uint64_t BaseAddress = 0; |
677 | if (std::optional<uint64_t> LowPC = Unit.getLowPc()) |
678 | BaseAddress = *LowPC; |
679 | |
680 | for (const DWARFLocationExpression &LocExpression : |
681 | LinkedLocationExpression) { |
682 | if (LocExpression.Range) { |
683 | MS->emitIntValue(Value: LocExpression.Range->LowPC - BaseAddress, Size: AddressSize); |
684 | MS->emitIntValue(Value: LocExpression.Range->HighPC - BaseAddress, Size: AddressSize); |
685 | |
686 | LocSectionSize += AddressSize; |
687 | LocSectionSize += AddressSize; |
688 | } |
689 | |
690 | Asm->OutStreamer->emitIntValue(Value: LocExpression.Expr.size(), Size: 2); |
691 | Asm->OutStreamer->emitBytes(Data: StringRef( |
692 | (const char *)LocExpression.Expr.data(), LocExpression.Expr.size())); |
693 | LocSectionSize += LocExpression.Expr.size() + 2; |
694 | } |
695 | |
696 | // Add the terminator entry. |
697 | MS->emitIntValue(Value: 0, Size: AddressSize); |
698 | MS->emitIntValue(Value: 0, Size: AddressSize); |
699 | |
700 | LocSectionSize += AddressSize; |
701 | LocSectionSize += AddressSize; |
702 | } |
703 | |
704 | /// Emit .debug_addr header. |
705 | MCSymbol *DwarfStreamer::(const CompileUnit &Unit) { |
706 | |
707 | // Make .debug_addr the current section. |
708 | MS->switchSection(Section: MC->getObjectFileInfo()->getDwarfAddrSection()); |
709 | |
710 | MCSymbol *BeginLabel = Asm->createTempSymbol(Name: "Bdebugaddr" ); |
711 | MCSymbol *EndLabel = Asm->createTempSymbol(Name: "Edebugaddr" ); |
712 | unsigned AddrSize = Unit.getOrigUnit().getAddressByteSize(); |
713 | |
714 | // Emit length. |
715 | Asm->emitLabelDifference(Hi: EndLabel, Lo: BeginLabel, Size: sizeof(uint32_t)); |
716 | Asm->OutStreamer->emitLabel(Symbol: BeginLabel); |
717 | AddrSectionSize += sizeof(uint32_t); |
718 | |
719 | // Emit version. |
720 | Asm->emitInt16(Value: 5); |
721 | AddrSectionSize += 2; |
722 | |
723 | // Emit address size. |
724 | Asm->emitInt8(Value: AddrSize); |
725 | AddrSectionSize += 1; |
726 | |
727 | // Emit segment size. |
728 | Asm->emitInt8(Value: 0); |
729 | AddrSectionSize += 1; |
730 | |
731 | return EndLabel; |
732 | } |
733 | |
734 | /// Emit the .debug_addr addresses stored in \p Addrs. |
735 | void DwarfStreamer::emitDwarfDebugAddrs(const SmallVector<uint64_t> &Addrs, |
736 | uint8_t AddrSize) { |
737 | Asm->OutStreamer->switchSection(Section: MOFI->getDwarfAddrSection()); |
738 | for (auto Addr : Addrs) { |
739 | Asm->OutStreamer->emitIntValue(Value: Addr, Size: AddrSize); |
740 | AddrSectionSize += AddrSize; |
741 | } |
742 | } |
743 | |
744 | /// Emit .debug_addr footer. |
745 | void DwarfStreamer::(const CompileUnit &Unit, |
746 | MCSymbol *EndLabel) { |
747 | |
748 | // Make .debug_addr the current section. |
749 | MS->switchSection(Section: MC->getObjectFileInfo()->getDwarfAddrSection()); |
750 | |
751 | if (EndLabel != nullptr) |
752 | Asm->OutStreamer->emitLabel(Symbol: EndLabel); |
753 | } |
754 | |
755 | /// Emit piece of .debug_loclists for \p LinkedLocationExpression. |
756 | void DwarfStreamer::emitDwarfDebugLocListsTableFragment( |
757 | const CompileUnit &Unit, |
758 | const DWARFLocationExpressionsVector &LinkedLocationExpression, |
759 | PatchLocation Patch, DebugDieValuePool &AddrPool) { |
760 | Patch.set(LocListsSectionSize); |
761 | |
762 | // Make .debug_loclists the current section. |
763 | MS->switchSection(Section: MC->getObjectFileInfo()->getDwarfLoclistsSection()); |
764 | std::optional<uint64_t> BaseAddress; |
765 | |
766 | for (const DWARFLocationExpression &LocExpression : |
767 | LinkedLocationExpression) { |
768 | if (LocExpression.Range) { |
769 | |
770 | if (!BaseAddress) { |
771 | |
772 | BaseAddress = LocExpression.Range->LowPC; |
773 | |
774 | // Emit base address. |
775 | MS->emitInt8(Value: dwarf::DW_LLE_base_addressx); |
776 | LocListsSectionSize += 1; |
777 | LocListsSectionSize += |
778 | MS->emitULEB128IntValue(Value: AddrPool.getValueIndex(Value: *BaseAddress)); |
779 | } |
780 | |
781 | // Emit type of entry. |
782 | MS->emitInt8(Value: dwarf::DW_LLE_offset_pair); |
783 | LocListsSectionSize += 1; |
784 | |
785 | // Emit start offset relative to base address. |
786 | LocListsSectionSize += |
787 | MS->emitULEB128IntValue(Value: LocExpression.Range->LowPC - *BaseAddress); |
788 | |
789 | // Emit end offset relative to base address. |
790 | LocListsSectionSize += |
791 | MS->emitULEB128IntValue(Value: LocExpression.Range->HighPC - *BaseAddress); |
792 | } else { |
793 | // Emit type of entry. |
794 | MS->emitInt8(Value: dwarf::DW_LLE_default_location); |
795 | LocListsSectionSize += 1; |
796 | } |
797 | |
798 | LocListsSectionSize += MS->emitULEB128IntValue(Value: LocExpression.Expr.size()); |
799 | Asm->OutStreamer->emitBytes(Data: StringRef( |
800 | (const char *)LocExpression.Expr.data(), LocExpression.Expr.size())); |
801 | LocListsSectionSize += LocExpression.Expr.size(); |
802 | } |
803 | |
804 | // Emit the terminator entry. |
805 | MS->emitInt8(Value: dwarf::DW_LLE_end_of_list); |
806 | LocListsSectionSize += 1; |
807 | } |
808 | |
809 | void DwarfStreamer::emitLineTableForUnit( |
810 | const DWARFDebugLine::LineTable &LineTable, const CompileUnit &Unit, |
811 | OffsetsStringPool &DebugStrPool, OffsetsStringPool &DebugLineStrPool) { |
812 | // Switch to the section where the table will be emitted into. |
813 | MS->switchSection(Section: MC->getObjectFileInfo()->getDwarfLineSection()); |
814 | |
815 | MCSymbol *LineStartSym = MC->createTempSymbol(); |
816 | MCSymbol *LineEndSym = MC->createTempSymbol(); |
817 | |
818 | // unit_length. |
819 | if (LineTable.Prologue.FormParams.Format == dwarf::DwarfFormat::DWARF64) { |
820 | MS->emitInt32(Value: dwarf::DW_LENGTH_DWARF64); |
821 | LineSectionSize += 4; |
822 | } |
823 | emitLabelDifference(Hi: LineEndSym, Lo: LineStartSym, |
824 | Format: LineTable.Prologue.FormParams.Format, SectionSize&: LineSectionSize); |
825 | Asm->OutStreamer->emitLabel(Symbol: LineStartSym); |
826 | |
827 | // Emit prologue. |
828 | emitLineTablePrologue(P: LineTable.Prologue, DebugStrPool, DebugLineStrPool); |
829 | |
830 | // Emit rows. |
831 | emitLineTableRows(LineTable, LineEndSym, |
832 | AddressByteSize: Unit.getOrigUnit().getAddressByteSize()); |
833 | } |
834 | |
835 | void DwarfStreamer::emitLineTablePrologue(const DWARFDebugLine::Prologue &P, |
836 | OffsetsStringPool &DebugStrPool, |
837 | OffsetsStringPool &DebugLineStrPool) { |
838 | MCSymbol *PrologueStartSym = MC->createTempSymbol(); |
839 | MCSymbol *PrologueEndSym = MC->createTempSymbol(); |
840 | |
841 | // version (uhalf). |
842 | MS->emitInt16(Value: P.getVersion()); |
843 | LineSectionSize += 2; |
844 | if (P.getVersion() == 5) { |
845 | // address_size (ubyte). |
846 | MS->emitInt8(Value: P.getAddressSize()); |
847 | LineSectionSize += 1; |
848 | |
849 | // segment_selector_size (ubyte). |
850 | MS->emitInt8(Value: P.SegSelectorSize); |
851 | LineSectionSize += 1; |
852 | } |
853 | |
854 | // header_length. |
855 | emitLabelDifference(Hi: PrologueEndSym, Lo: PrologueStartSym, Format: P.FormParams.Format, |
856 | SectionSize&: LineSectionSize); |
857 | |
858 | Asm->OutStreamer->emitLabel(Symbol: PrologueStartSym); |
859 | emitLineTableProloguePayload(P, DebugStrPool, DebugLineStrPool); |
860 | Asm->OutStreamer->emitLabel(Symbol: PrologueEndSym); |
861 | } |
862 | |
863 | void DwarfStreamer::emitLineTablePrologueV2IncludeAndFileTable( |
864 | const DWARFDebugLine::Prologue &P, OffsetsStringPool &DebugStrPool, |
865 | OffsetsStringPool &DebugLineStrPool) { |
866 | // include_directories (sequence of path names). |
867 | for (const DWARFFormValue &Include : P.IncludeDirectories) |
868 | emitLineTableString(P, String: Include, DebugStrPool, DebugLineStrPool); |
869 | // The last entry is followed by a single null byte. |
870 | MS->emitInt8(Value: 0); |
871 | LineSectionSize += 1; |
872 | |
873 | // file_names (sequence of file entries). |
874 | for (const DWARFDebugLine::FileNameEntry &File : P.FileNames) { |
875 | // A null-terminated string containing the full or relative path name of a |
876 | // source file. |
877 | emitLineTableString(P, String: File.Name, DebugStrPool, DebugLineStrPool); |
878 | // An unsigned LEB128 number representing the directory index of a directory |
879 | // in the include_directories section. |
880 | LineSectionSize += MS->emitULEB128IntValue(Value: File.DirIdx); |
881 | // An unsigned LEB128 number representing the (implementation-defined) time |
882 | // of last modification for the file, or 0 if not available. |
883 | LineSectionSize += MS->emitULEB128IntValue(Value: File.ModTime); |
884 | // An unsigned LEB128 number representing the length in bytes of the file, |
885 | // or 0 if not available. |
886 | LineSectionSize += MS->emitULEB128IntValue(Value: File.Length); |
887 | } |
888 | // The last entry is followed by a single null byte. |
889 | MS->emitInt8(Value: 0); |
890 | LineSectionSize += 1; |
891 | } |
892 | |
893 | void DwarfStreamer::emitLineTablePrologueV5IncludeAndFileTable( |
894 | const DWARFDebugLine::Prologue &P, OffsetsStringPool &DebugStrPool, |
895 | OffsetsStringPool &DebugLineStrPool) { |
896 | if (P.IncludeDirectories.empty()) { |
897 | // directory_entry_format_count(ubyte). |
898 | MS->emitInt8(Value: 0); |
899 | LineSectionSize += 1; |
900 | } else { |
901 | // directory_entry_format_count(ubyte). |
902 | MS->emitInt8(Value: 1); |
903 | LineSectionSize += 1; |
904 | |
905 | // directory_entry_format (sequence of ULEB128 pairs). |
906 | LineSectionSize += MS->emitULEB128IntValue(Value: dwarf::DW_LNCT_path); |
907 | LineSectionSize += |
908 | MS->emitULEB128IntValue(Value: P.IncludeDirectories[0].getForm()); |
909 | } |
910 | |
911 | // directories_count (ULEB128). |
912 | LineSectionSize += MS->emitULEB128IntValue(Value: P.IncludeDirectories.size()); |
913 | // directories (sequence of directory names). |
914 | for (auto Include : P.IncludeDirectories) |
915 | emitLineTableString(P, String: Include, DebugStrPool, DebugLineStrPool); |
916 | |
917 | bool HasChecksums = P.ContentTypes.HasMD5; |
918 | bool HasInlineSources = P.ContentTypes.HasSource; |
919 | |
920 | if (P.FileNames.empty()) { |
921 | // file_name_entry_format_count (ubyte). |
922 | MS->emitInt8(Value: 0); |
923 | LineSectionSize += 1; |
924 | } else { |
925 | // file_name_entry_format_count (ubyte). |
926 | MS->emitInt8(Value: 2 + (HasChecksums ? 1 : 0) + (HasInlineSources ? 1 : 0)); |
927 | LineSectionSize += 1; |
928 | |
929 | // file_name_entry_format (sequence of ULEB128 pairs). |
930 | auto StrForm = P.FileNames[0].Name.getForm(); |
931 | LineSectionSize += MS->emitULEB128IntValue(Value: dwarf::DW_LNCT_path); |
932 | LineSectionSize += MS->emitULEB128IntValue(Value: StrForm); |
933 | |
934 | LineSectionSize += MS->emitULEB128IntValue(Value: dwarf::DW_LNCT_directory_index); |
935 | LineSectionSize += MS->emitULEB128IntValue(Value: dwarf::DW_FORM_data1); |
936 | |
937 | if (HasChecksums) { |
938 | LineSectionSize += MS->emitULEB128IntValue(Value: dwarf::DW_LNCT_MD5); |
939 | LineSectionSize += MS->emitULEB128IntValue(Value: dwarf::DW_FORM_data16); |
940 | } |
941 | |
942 | if (HasInlineSources) { |
943 | LineSectionSize += MS->emitULEB128IntValue(Value: dwarf::DW_LNCT_LLVM_source); |
944 | LineSectionSize += MS->emitULEB128IntValue(Value: StrForm); |
945 | } |
946 | } |
947 | |
948 | // file_names_count (ULEB128). |
949 | LineSectionSize += MS->emitULEB128IntValue(Value: P.FileNames.size()); |
950 | |
951 | // file_names (sequence of file name entries). |
952 | for (auto File : P.FileNames) { |
953 | emitLineTableString(P, String: File.Name, DebugStrPool, DebugLineStrPool); |
954 | MS->emitInt8(Value: File.DirIdx); |
955 | LineSectionSize += 1; |
956 | if (HasChecksums) { |
957 | MS->emitBinaryData( |
958 | Data: StringRef(reinterpret_cast<const char *>(File.Checksum.data()), |
959 | File.Checksum.size())); |
960 | LineSectionSize += File.Checksum.size(); |
961 | } |
962 | if (HasInlineSources) |
963 | emitLineTableString(P, String: File.Source, DebugStrPool, DebugLineStrPool); |
964 | } |
965 | } |
966 | |
967 | void DwarfStreamer::emitLineTableString(const DWARFDebugLine::Prologue &P, |
968 | const DWARFFormValue &String, |
969 | OffsetsStringPool &DebugStrPool, |
970 | OffsetsStringPool &DebugLineStrPool) { |
971 | std::optional<const char *> StringVal = dwarf::toString(V: String); |
972 | if (!StringVal) { |
973 | warn(Warning: "Cann't read string from line table." ); |
974 | return; |
975 | } |
976 | |
977 | switch (String.getForm()) { |
978 | case dwarf::DW_FORM_string: { |
979 | StringRef Str = *StringVal; |
980 | Asm->OutStreamer->emitBytes(Data: Str.data()); |
981 | Asm->emitInt8(Value: 0); |
982 | LineSectionSize += Str.size() + 1; |
983 | } break; |
984 | case dwarf::DW_FORM_strp: |
985 | case dwarf::DW_FORM_line_strp: { |
986 | DwarfStringPoolEntryRef StringRef = |
987 | String.getForm() == dwarf::DW_FORM_strp |
988 | ? DebugStrPool.getEntry(S: *StringVal) |
989 | : DebugLineStrPool.getEntry(S: *StringVal); |
990 | |
991 | emitIntOffset(Offset: StringRef.getOffset(), Format: P.FormParams.Format, SectionSize&: LineSectionSize); |
992 | } break; |
993 | default: |
994 | warn(Warning: "Unsupported string form inside line table." ); |
995 | break; |
996 | }; |
997 | } |
998 | |
999 | void DwarfStreamer::emitLineTableProloguePayload( |
1000 | const DWARFDebugLine::Prologue &P, OffsetsStringPool &DebugStrPool, |
1001 | OffsetsStringPool &DebugLineStrPool) { |
1002 | // minimum_instruction_length (ubyte). |
1003 | MS->emitInt8(Value: P.MinInstLength); |
1004 | LineSectionSize += 1; |
1005 | if (P.FormParams.Version >= 4) { |
1006 | // maximum_operations_per_instruction (ubyte). |
1007 | MS->emitInt8(Value: P.MaxOpsPerInst); |
1008 | LineSectionSize += 1; |
1009 | } |
1010 | // default_is_stmt (ubyte). |
1011 | MS->emitInt8(Value: P.DefaultIsStmt); |
1012 | LineSectionSize += 1; |
1013 | // line_base (sbyte). |
1014 | MS->emitInt8(Value: P.LineBase); |
1015 | LineSectionSize += 1; |
1016 | // line_range (ubyte). |
1017 | MS->emitInt8(Value: P.LineRange); |
1018 | LineSectionSize += 1; |
1019 | // opcode_base (ubyte). |
1020 | MS->emitInt8(Value: P.OpcodeBase); |
1021 | LineSectionSize += 1; |
1022 | |
1023 | // standard_opcode_lengths (array of ubyte). |
1024 | for (auto Length : P.StandardOpcodeLengths) { |
1025 | MS->emitInt8(Value: Length); |
1026 | LineSectionSize += 1; |
1027 | } |
1028 | |
1029 | if (P.FormParams.Version < 5) |
1030 | emitLineTablePrologueV2IncludeAndFileTable(P, DebugStrPool, |
1031 | DebugLineStrPool); |
1032 | else |
1033 | emitLineTablePrologueV5IncludeAndFileTable(P, DebugStrPool, |
1034 | DebugLineStrPool); |
1035 | } |
1036 | |
1037 | void DwarfStreamer::emitLineTableRows( |
1038 | const DWARFDebugLine::LineTable &LineTable, MCSymbol *LineEndSym, |
1039 | unsigned AddressByteSize) { |
1040 | |
1041 | MCDwarfLineTableParams Params; |
1042 | Params.DWARF2LineOpcodeBase = LineTable.Prologue.OpcodeBase; |
1043 | Params.DWARF2LineBase = LineTable.Prologue.LineBase; |
1044 | Params.DWARF2LineRange = LineTable.Prologue.LineRange; |
1045 | |
1046 | SmallString<128> EncodingBuffer; |
1047 | |
1048 | if (LineTable.Rows.empty()) { |
1049 | // We only have the dummy entry, dsymutil emits an entry with a 0 |
1050 | // address in that case. |
1051 | MCDwarfLineAddr::encode(Context&: *MC, Params, LineDelta: std::numeric_limits<int64_t>::max(), AddrDelta: 0, |
1052 | OS&: EncodingBuffer); |
1053 | MS->emitBytes(Data: EncodingBuffer); |
1054 | LineSectionSize += EncodingBuffer.size(); |
1055 | MS->emitLabel(Symbol: LineEndSym); |
1056 | return; |
1057 | } |
1058 | |
1059 | // Line table state machine fields |
1060 | unsigned FileNum = 1; |
1061 | unsigned LastLine = 1; |
1062 | unsigned Column = 0; |
1063 | unsigned IsStatement = 1; |
1064 | unsigned Isa = 0; |
1065 | uint64_t Address = -1ULL; |
1066 | |
1067 | unsigned RowsSinceLastSequence = 0; |
1068 | |
1069 | for (const DWARFDebugLine::Row &Row : LineTable.Rows) { |
1070 | int64_t AddressDelta; |
1071 | if (Address == -1ULL) { |
1072 | MS->emitIntValue(Value: dwarf::DW_LNS_extended_op, Size: 1); |
1073 | MS->emitULEB128IntValue(Value: AddressByteSize + 1); |
1074 | MS->emitIntValue(Value: dwarf::DW_LNE_set_address, Size: 1); |
1075 | MS->emitIntValue(Value: Row.Address.Address, Size: AddressByteSize); |
1076 | LineSectionSize += |
1077 | 2 + AddressByteSize + getULEB128Size(Value: AddressByteSize + 1); |
1078 | AddressDelta = 0; |
1079 | } else { |
1080 | AddressDelta = |
1081 | (Row.Address.Address - Address) / LineTable.Prologue.MinInstLength; |
1082 | } |
1083 | |
1084 | // FIXME: code copied and transformed from MCDwarf.cpp::EmitDwarfLineTable. |
1085 | // We should find a way to share this code, but the current compatibility |
1086 | // requirement with classic dsymutil makes it hard. Revisit that once this |
1087 | // requirement is dropped. |
1088 | |
1089 | if (FileNum != Row.File) { |
1090 | FileNum = Row.File; |
1091 | MS->emitIntValue(Value: dwarf::DW_LNS_set_file, Size: 1); |
1092 | MS->emitULEB128IntValue(Value: FileNum); |
1093 | LineSectionSize += 1 + getULEB128Size(Value: FileNum); |
1094 | } |
1095 | if (Column != Row.Column) { |
1096 | Column = Row.Column; |
1097 | MS->emitIntValue(Value: dwarf::DW_LNS_set_column, Size: 1); |
1098 | MS->emitULEB128IntValue(Value: Column); |
1099 | LineSectionSize += 1 + getULEB128Size(Value: Column); |
1100 | } |
1101 | |
1102 | // FIXME: We should handle the discriminator here, but dsymutil doesn't |
1103 | // consider it, thus ignore it for now. |
1104 | |
1105 | if (Isa != Row.Isa) { |
1106 | Isa = Row.Isa; |
1107 | MS->emitIntValue(Value: dwarf::DW_LNS_set_isa, Size: 1); |
1108 | MS->emitULEB128IntValue(Value: Isa); |
1109 | LineSectionSize += 1 + getULEB128Size(Value: Isa); |
1110 | } |
1111 | if (IsStatement != Row.IsStmt) { |
1112 | IsStatement = Row.IsStmt; |
1113 | MS->emitIntValue(Value: dwarf::DW_LNS_negate_stmt, Size: 1); |
1114 | LineSectionSize += 1; |
1115 | } |
1116 | if (Row.BasicBlock) { |
1117 | MS->emitIntValue(Value: dwarf::DW_LNS_set_basic_block, Size: 1); |
1118 | LineSectionSize += 1; |
1119 | } |
1120 | |
1121 | if (Row.PrologueEnd) { |
1122 | MS->emitIntValue(Value: dwarf::DW_LNS_set_prologue_end, Size: 1); |
1123 | LineSectionSize += 1; |
1124 | } |
1125 | |
1126 | if (Row.EpilogueBegin) { |
1127 | MS->emitIntValue(Value: dwarf::DW_LNS_set_epilogue_begin, Size: 1); |
1128 | LineSectionSize += 1; |
1129 | } |
1130 | |
1131 | int64_t LineDelta = int64_t(Row.Line) - LastLine; |
1132 | if (!Row.EndSequence) { |
1133 | MCDwarfLineAddr::encode(Context&: *MC, Params, LineDelta, AddrDelta: AddressDelta, |
1134 | OS&: EncodingBuffer); |
1135 | MS->emitBytes(Data: EncodingBuffer); |
1136 | LineSectionSize += EncodingBuffer.size(); |
1137 | EncodingBuffer.resize(N: 0); |
1138 | Address = Row.Address.Address; |
1139 | LastLine = Row.Line; |
1140 | RowsSinceLastSequence++; |
1141 | } else { |
1142 | if (LineDelta) { |
1143 | MS->emitIntValue(Value: dwarf::DW_LNS_advance_line, Size: 1); |
1144 | MS->emitSLEB128IntValue(Value: LineDelta); |
1145 | LineSectionSize += 1 + getSLEB128Size(Value: LineDelta); |
1146 | } |
1147 | if (AddressDelta) { |
1148 | MS->emitIntValue(Value: dwarf::DW_LNS_advance_pc, Size: 1); |
1149 | MS->emitULEB128IntValue(Value: AddressDelta); |
1150 | LineSectionSize += 1 + getULEB128Size(Value: AddressDelta); |
1151 | } |
1152 | MCDwarfLineAddr::encode(Context&: *MC, Params, LineDelta: std::numeric_limits<int64_t>::max(), |
1153 | AddrDelta: 0, OS&: EncodingBuffer); |
1154 | MS->emitBytes(Data: EncodingBuffer); |
1155 | LineSectionSize += EncodingBuffer.size(); |
1156 | EncodingBuffer.resize(N: 0); |
1157 | Address = -1ULL; |
1158 | LastLine = FileNum = IsStatement = 1; |
1159 | RowsSinceLastSequence = Column = Isa = 0; |
1160 | } |
1161 | } |
1162 | |
1163 | if (RowsSinceLastSequence) { |
1164 | MCDwarfLineAddr::encode(Context&: *MC, Params, LineDelta: std::numeric_limits<int64_t>::max(), AddrDelta: 0, |
1165 | OS&: EncodingBuffer); |
1166 | MS->emitBytes(Data: EncodingBuffer); |
1167 | LineSectionSize += EncodingBuffer.size(); |
1168 | EncodingBuffer.resize(N: 0); |
1169 | } |
1170 | |
1171 | MS->emitLabel(Symbol: LineEndSym); |
1172 | } |
1173 | |
1174 | void DwarfStreamer::emitIntOffset(uint64_t Offset, dwarf::DwarfFormat Format, |
1175 | uint64_t &SectionSize) { |
1176 | uint8_t Size = dwarf::getDwarfOffsetByteSize(Format); |
1177 | MS->emitIntValue(Value: Offset, Size); |
1178 | SectionSize += Size; |
1179 | } |
1180 | |
1181 | void DwarfStreamer::emitLabelDifference(const MCSymbol *Hi, const MCSymbol *Lo, |
1182 | dwarf::DwarfFormat Format, |
1183 | uint64_t &SectionSize) { |
1184 | uint8_t Size = dwarf::getDwarfOffsetByteSize(Format); |
1185 | Asm->emitLabelDifference(Hi, Lo, Size); |
1186 | SectionSize += Size; |
1187 | } |
1188 | |
1189 | /// Emit the pubnames or pubtypes section contribution for \p |
1190 | /// Unit into \p Sec. The data is provided in \p Names. |
1191 | void DwarfStreamer::emitPubSectionForUnit( |
1192 | MCSection *Sec, StringRef SecName, const CompileUnit &Unit, |
1193 | const std::vector<CompileUnit::AccelInfo> &Names) { |
1194 | if (Names.empty()) |
1195 | return; |
1196 | |
1197 | // Start the dwarf pubnames section. |
1198 | Asm->OutStreamer->switchSection(Section: Sec); |
1199 | MCSymbol *BeginLabel = Asm->createTempSymbol(Name: "pub" + SecName + "_begin" ); |
1200 | MCSymbol *EndLabel = Asm->createTempSymbol(Name: "pub" + SecName + "_end" ); |
1201 | |
1202 | bool = false; |
1203 | // Emit the pubnames for this compilation unit. |
1204 | for (const auto &Name : Names) { |
1205 | if (Name.SkipPubSection) |
1206 | continue; |
1207 | |
1208 | if (!HeaderEmitted) { |
1209 | // Emit the header. |
1210 | Asm->emitLabelDifference(Hi: EndLabel, Lo: BeginLabel, Size: 4); // Length |
1211 | Asm->OutStreamer->emitLabel(Symbol: BeginLabel); |
1212 | Asm->emitInt16(Value: dwarf::DW_PUBNAMES_VERSION); // Version |
1213 | Asm->emitInt32(Value: Unit.getStartOffset()); // Unit offset |
1214 | Asm->emitInt32(Value: Unit.getNextUnitOffset() - Unit.getStartOffset()); // Size |
1215 | HeaderEmitted = true; |
1216 | } |
1217 | Asm->emitInt32(Value: Name.Die->getOffset()); |
1218 | |
1219 | // Emit the string itself. |
1220 | Asm->OutStreamer->emitBytes(Data: Name.Name.getString()); |
1221 | // Emit a null terminator. |
1222 | Asm->emitInt8(Value: 0); |
1223 | } |
1224 | |
1225 | if (!HeaderEmitted) |
1226 | return; |
1227 | Asm->emitInt32(Value: 0); // End marker. |
1228 | Asm->OutStreamer->emitLabel(Symbol: EndLabel); |
1229 | } |
1230 | |
1231 | /// Emit .debug_pubnames for \p Unit. |
1232 | void DwarfStreamer::emitPubNamesForUnit(const CompileUnit &Unit) { |
1233 | emitPubSectionForUnit(Sec: MC->getObjectFileInfo()->getDwarfPubNamesSection(), |
1234 | SecName: "names" , Unit, Names: Unit.getPubnames()); |
1235 | } |
1236 | |
1237 | /// Emit .debug_pubtypes for \p Unit. |
1238 | void DwarfStreamer::emitPubTypesForUnit(const CompileUnit &Unit) { |
1239 | emitPubSectionForUnit(Sec: MC->getObjectFileInfo()->getDwarfPubTypesSection(), |
1240 | SecName: "types" , Unit, Names: Unit.getPubtypes()); |
1241 | } |
1242 | |
1243 | /// Emit a CIE into the debug_frame section. |
1244 | void DwarfStreamer::emitCIE(StringRef CIEBytes) { |
1245 | MS->switchSection(Section: MC->getObjectFileInfo()->getDwarfFrameSection()); |
1246 | |
1247 | MS->emitBytes(Data: CIEBytes); |
1248 | FrameSectionSize += CIEBytes.size(); |
1249 | } |
1250 | |
1251 | /// Emit a FDE into the debug_frame section. \p FDEBytes |
1252 | /// contains the FDE data without the length, CIE offset and address |
1253 | /// which will be replaced with the parameter values. |
1254 | void DwarfStreamer::emitFDE(uint32_t CIEOffset, uint32_t AddrSize, |
1255 | uint64_t Address, StringRef FDEBytes) { |
1256 | MS->switchSection(Section: MC->getObjectFileInfo()->getDwarfFrameSection()); |
1257 | |
1258 | MS->emitIntValue(Value: FDEBytes.size() + 4 + AddrSize, Size: 4); |
1259 | MS->emitIntValue(Value: CIEOffset, Size: 4); |
1260 | MS->emitIntValue(Value: Address, Size: AddrSize); |
1261 | MS->emitBytes(Data: FDEBytes); |
1262 | FrameSectionSize += FDEBytes.size() + 8 + AddrSize; |
1263 | } |
1264 | |
1265 | void DwarfStreamer::emitMacroTables(DWARFContext *Context, |
1266 | const Offset2UnitMap &UnitMacroMap, |
1267 | OffsetsStringPool &StringPool) { |
1268 | assert(Context != nullptr && "Empty DWARF context" ); |
1269 | |
1270 | // Check for .debug_macinfo table. |
1271 | if (const DWARFDebugMacro *Table = Context->getDebugMacinfo()) { |
1272 | MS->switchSection(Section: MC->getObjectFileInfo()->getDwarfMacinfoSection()); |
1273 | emitMacroTableImpl(MacroTable: Table, UnitMacroMap, StringPool, OutOffset&: MacInfoSectionSize); |
1274 | } |
1275 | |
1276 | // Check for .debug_macro table. |
1277 | if (const DWARFDebugMacro *Table = Context->getDebugMacro()) { |
1278 | MS->switchSection(Section: MC->getObjectFileInfo()->getDwarfMacroSection()); |
1279 | emitMacroTableImpl(MacroTable: Table, UnitMacroMap, StringPool, OutOffset&: MacroSectionSize); |
1280 | } |
1281 | } |
1282 | |
1283 | void DwarfStreamer::emitMacroTableImpl(const DWARFDebugMacro *MacroTable, |
1284 | const Offset2UnitMap &UnitMacroMap, |
1285 | OffsetsStringPool &StringPool, |
1286 | uint64_t &OutOffset) { |
1287 | bool DefAttributeIsReported = false; |
1288 | bool UndefAttributeIsReported = false; |
1289 | bool ImportAttributeIsReported = false; |
1290 | for (const DWARFDebugMacro::MacroList &List : MacroTable->MacroLists) { |
1291 | Offset2UnitMap::const_iterator UnitIt = UnitMacroMap.find(Val: List.Offset); |
1292 | if (UnitIt == UnitMacroMap.end()) { |
1293 | warn(Warning: formatv( |
1294 | Fmt: "couldn`t find compile unit for the macro table with offset = {0:x}" , |
1295 | Vals: List.Offset)); |
1296 | continue; |
1297 | } |
1298 | |
1299 | // Skip macro table if the unit was not cloned. |
1300 | DIE *OutputUnitDIE = UnitIt->second->getOutputUnitDIE(); |
1301 | if (OutputUnitDIE == nullptr) |
1302 | continue; |
1303 | |
1304 | // Update macro attribute of cloned compile unit with the proper offset to |
1305 | // the macro table. |
1306 | bool = false; |
1307 | for (auto &V : OutputUnitDIE->values()) { |
1308 | if (V.getAttribute() == dwarf::DW_AT_macro_info) { |
1309 | V = DIEValue(V.getAttribute(), V.getForm(), DIEInteger(OutOffset)); |
1310 | break; |
1311 | } else if (V.getAttribute() == dwarf::DW_AT_macros) { |
1312 | hasDWARFv5Header = true; |
1313 | V = DIEValue(V.getAttribute(), V.getForm(), DIEInteger(OutOffset)); |
1314 | break; |
1315 | } |
1316 | } |
1317 | |
1318 | // Write DWARFv5 header. |
1319 | if (hasDWARFv5Header) { |
1320 | // Write header version. |
1321 | MS->emitIntValue(Value: List.Header.Version, Size: sizeof(List.Header.Version)); |
1322 | OutOffset += sizeof(List.Header.Version); |
1323 | |
1324 | uint8_t Flags = List.Header.Flags; |
1325 | |
1326 | // Check for OPCODE_OPERANDS_TABLE. |
1327 | if (Flags & |
1328 | DWARFDebugMacro::HeaderFlagMask::MACRO_OPCODE_OPERANDS_TABLE) { |
1329 | Flags &= ~DWARFDebugMacro::HeaderFlagMask::MACRO_OPCODE_OPERANDS_TABLE; |
1330 | warn(Warning: "opcode_operands_table is not supported yet." ); |
1331 | } |
1332 | |
1333 | // Check for DEBUG_LINE_OFFSET. |
1334 | std::optional<uint64_t> StmtListOffset; |
1335 | if (Flags & DWARFDebugMacro::HeaderFlagMask::MACRO_DEBUG_LINE_OFFSET) { |
1336 | // Get offset to the line table from the cloned compile unit. |
1337 | for (auto &V : OutputUnitDIE->values()) { |
1338 | if (V.getAttribute() == dwarf::DW_AT_stmt_list) { |
1339 | StmtListOffset = V.getDIEInteger().getValue(); |
1340 | break; |
1341 | } |
1342 | } |
1343 | |
1344 | if (!StmtListOffset) { |
1345 | Flags &= ~DWARFDebugMacro::HeaderFlagMask::MACRO_DEBUG_LINE_OFFSET; |
1346 | warn(Warning: "couldn`t find line table for macro table." ); |
1347 | } |
1348 | } |
1349 | |
1350 | // Write flags. |
1351 | MS->emitIntValue(Value: Flags, Size: sizeof(Flags)); |
1352 | OutOffset += sizeof(Flags); |
1353 | |
1354 | // Write offset to line table. |
1355 | if (StmtListOffset) { |
1356 | MS->emitIntValue(Value: *StmtListOffset, Size: List.Header.getOffsetByteSize()); |
1357 | OutOffset += List.Header.getOffsetByteSize(); |
1358 | } |
1359 | } |
1360 | |
1361 | // Write macro entries. |
1362 | for (const DWARFDebugMacro::Entry &MacroEntry : List.Macros) { |
1363 | if (MacroEntry.Type == 0) { |
1364 | OutOffset += MS->emitULEB128IntValue(Value: MacroEntry.Type); |
1365 | continue; |
1366 | } |
1367 | |
1368 | uint8_t MacroType = MacroEntry.Type; |
1369 | switch (MacroType) { |
1370 | default: { |
1371 | bool HasVendorSpecificExtension = |
1372 | (!hasDWARFv5Header && MacroType == dwarf::DW_MACINFO_vendor_ext) || |
1373 | (hasDWARFv5Header && (MacroType >= dwarf::DW_MACRO_lo_user && |
1374 | MacroType <= dwarf::DW_MACRO_hi_user)); |
1375 | |
1376 | if (HasVendorSpecificExtension) { |
1377 | // Write macinfo type. |
1378 | MS->emitIntValue(Value: MacroType, Size: 1); |
1379 | OutOffset++; |
1380 | |
1381 | // Write vendor extension constant. |
1382 | OutOffset += MS->emitULEB128IntValue(Value: MacroEntry.ExtConstant); |
1383 | |
1384 | // Write vendor extension string. |
1385 | StringRef String = MacroEntry.ExtStr; |
1386 | MS->emitBytes(Data: String); |
1387 | MS->emitIntValue(Value: 0, Size: 1); |
1388 | OutOffset += String.size() + 1; |
1389 | } else |
1390 | warn(Warning: "unknown macro type. skip." ); |
1391 | } break; |
1392 | // debug_macro and debug_macinfo share some common encodings. |
1393 | // DW_MACRO_define == DW_MACINFO_define |
1394 | // DW_MACRO_undef == DW_MACINFO_undef |
1395 | // DW_MACRO_start_file == DW_MACINFO_start_file |
1396 | // DW_MACRO_end_file == DW_MACINFO_end_file |
1397 | // For readibility/uniformity we are using DW_MACRO_*. |
1398 | case dwarf::DW_MACRO_define: |
1399 | case dwarf::DW_MACRO_undef: { |
1400 | // Write macinfo type. |
1401 | MS->emitIntValue(Value: MacroType, Size: 1); |
1402 | OutOffset++; |
1403 | |
1404 | // Write source line. |
1405 | OutOffset += MS->emitULEB128IntValue(Value: MacroEntry.Line); |
1406 | |
1407 | // Write macro string. |
1408 | StringRef String = MacroEntry.MacroStr; |
1409 | MS->emitBytes(Data: String); |
1410 | MS->emitIntValue(Value: 0, Size: 1); |
1411 | OutOffset += String.size() + 1; |
1412 | } break; |
1413 | case dwarf::DW_MACRO_define_strp: |
1414 | case dwarf::DW_MACRO_undef_strp: |
1415 | case dwarf::DW_MACRO_define_strx: |
1416 | case dwarf::DW_MACRO_undef_strx: { |
1417 | assert(UnitIt->second->getOrigUnit().getVersion() >= 5); |
1418 | |
1419 | // DW_MACRO_*_strx forms are not supported currently. |
1420 | // Convert to *_strp. |
1421 | switch (MacroType) { |
1422 | case dwarf::DW_MACRO_define_strx: { |
1423 | MacroType = dwarf::DW_MACRO_define_strp; |
1424 | if (!DefAttributeIsReported) { |
1425 | warn(Warning: "DW_MACRO_define_strx unsupported yet. Convert to " |
1426 | "DW_MACRO_define_strp." ); |
1427 | DefAttributeIsReported = true; |
1428 | } |
1429 | } break; |
1430 | case dwarf::DW_MACRO_undef_strx: { |
1431 | MacroType = dwarf::DW_MACRO_undef_strp; |
1432 | if (!UndefAttributeIsReported) { |
1433 | warn(Warning: "DW_MACRO_undef_strx unsupported yet. Convert to " |
1434 | "DW_MACRO_undef_strp." ); |
1435 | UndefAttributeIsReported = true; |
1436 | } |
1437 | } break; |
1438 | default: |
1439 | // Nothing to do. |
1440 | break; |
1441 | } |
1442 | |
1443 | // Write macinfo type. |
1444 | MS->emitIntValue(Value: MacroType, Size: 1); |
1445 | OutOffset++; |
1446 | |
1447 | // Write source line. |
1448 | OutOffset += MS->emitULEB128IntValue(Value: MacroEntry.Line); |
1449 | |
1450 | // Write macro string. |
1451 | DwarfStringPoolEntryRef EntryRef = |
1452 | StringPool.getEntry(S: MacroEntry.MacroStr); |
1453 | MS->emitIntValue(Value: EntryRef.getOffset(), Size: List.Header.getOffsetByteSize()); |
1454 | OutOffset += List.Header.getOffsetByteSize(); |
1455 | break; |
1456 | } |
1457 | case dwarf::DW_MACRO_start_file: { |
1458 | // Write macinfo type. |
1459 | MS->emitIntValue(Value: MacroType, Size: 1); |
1460 | OutOffset++; |
1461 | // Write source line. |
1462 | OutOffset += MS->emitULEB128IntValue(Value: MacroEntry.Line); |
1463 | // Write source file id. |
1464 | OutOffset += MS->emitULEB128IntValue(Value: MacroEntry.File); |
1465 | } break; |
1466 | case dwarf::DW_MACRO_end_file: { |
1467 | // Write macinfo type. |
1468 | MS->emitIntValue(Value: MacroType, Size: 1); |
1469 | OutOffset++; |
1470 | } break; |
1471 | case dwarf::DW_MACRO_import: |
1472 | case dwarf::DW_MACRO_import_sup: { |
1473 | if (!ImportAttributeIsReported) { |
1474 | warn(Warning: "DW_MACRO_import and DW_MACRO_import_sup are unsupported yet. " |
1475 | "remove." ); |
1476 | ImportAttributeIsReported = true; |
1477 | } |
1478 | } break; |
1479 | } |
1480 | } |
1481 | } |
1482 | } |
1483 | |