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