1 //===- DWARFDebugFrame.h - Parsing of .debug_frame ------------------------===//
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/DebugInfo/DWARF/DWARFDebugFrame.h"
10 #include "llvm/ADT/DenseMap.h"
11 #include "llvm/ADT/Optional.h"
12 #include "llvm/ADT/StringExtras.h"
13 #include "llvm/ADT/StringRef.h"
14 #include "llvm/BinaryFormat/Dwarf.h"
15 #include "llvm/MC/MCRegisterInfo.h"
16 #include "llvm/Support/Casting.h"
17 #include "llvm/Support/Compiler.h"
18 #include "llvm/Support/DataExtractor.h"
19 #include "llvm/Support/Errc.h"
20 #include "llvm/Support/ErrorHandling.h"
21 #include "llvm/Support/Format.h"
22 #include "llvm/Support/raw_ostream.h"
23 #include <algorithm>
24 #include <cassert>
25 #include <cinttypes>
26 #include <cstdint>
27 #include <string>
28 #include <vector>
29
30 using namespace llvm;
31 using namespace dwarf;
32
printRegister(raw_ostream & OS,const MCRegisterInfo * MRI,bool IsEH,unsigned RegNum)33 static void printRegister(raw_ostream &OS, const MCRegisterInfo *MRI, bool IsEH,
34 unsigned RegNum) {
35 if (MRI) {
36 if (Optional<unsigned> LLVMRegNum = MRI->getLLVMRegNum(RegNum, IsEH)) {
37 if (const char *RegName = MRI->getName(*LLVMRegNum)) {
38 OS << RegName;
39 return;
40 }
41 }
42 }
43 OS << "reg" << RegNum;
44 }
45
46 // See DWARF standard v3, section 7.23
47 const uint8_t DWARF_CFI_PRIMARY_OPCODE_MASK = 0xc0;
48 const uint8_t DWARF_CFI_PRIMARY_OPERAND_MASK = 0x3f;
49
parse(DWARFDataExtractor Data,uint64_t * Offset,uint64_t EndOffset)50 Error CFIProgram::parse(DWARFDataExtractor Data, uint64_t *Offset,
51 uint64_t EndOffset) {
52 DataExtractor::Cursor C(*Offset);
53 while (C && C.tell() < EndOffset) {
54 uint8_t Opcode = Data.getRelocatedValue(C, 1);
55 if (!C)
56 break;
57
58 // Some instructions have a primary opcode encoded in the top bits.
59 if (uint8_t Primary = Opcode & DWARF_CFI_PRIMARY_OPCODE_MASK) {
60 // If it's a primary opcode, the first operand is encoded in the bottom
61 // bits of the opcode itself.
62 uint64_t Op1 = Opcode & DWARF_CFI_PRIMARY_OPERAND_MASK;
63 switch (Primary) {
64 case DW_CFA_advance_loc:
65 case DW_CFA_restore:
66 addInstruction(Primary, Op1);
67 break;
68 case DW_CFA_offset:
69 addInstruction(Primary, Op1, Data.getULEB128(C));
70 break;
71 default:
72 llvm_unreachable("invalid primary CFI opcode");
73 }
74 continue;
75 }
76
77 // Extended opcode - its value is Opcode itself.
78 switch (Opcode) {
79 default:
80 return createStringError(errc::illegal_byte_sequence,
81 "invalid extended CFI opcode 0x%" PRIx8, Opcode);
82 case DW_CFA_nop:
83 case DW_CFA_remember_state:
84 case DW_CFA_restore_state:
85 case DW_CFA_GNU_window_save:
86 // No operands
87 addInstruction(Opcode);
88 break;
89 case DW_CFA_set_loc:
90 // Operands: Address
91 addInstruction(Opcode, Data.getRelocatedAddress(C));
92 break;
93 case DW_CFA_advance_loc1:
94 // Operands: 1-byte delta
95 addInstruction(Opcode, Data.getRelocatedValue(C, 1));
96 break;
97 case DW_CFA_advance_loc2:
98 // Operands: 2-byte delta
99 addInstruction(Opcode, Data.getRelocatedValue(C, 2));
100 break;
101 case DW_CFA_advance_loc4:
102 // Operands: 4-byte delta
103 addInstruction(Opcode, Data.getRelocatedValue(C, 4));
104 break;
105 case DW_CFA_restore_extended:
106 case DW_CFA_undefined:
107 case DW_CFA_same_value:
108 case DW_CFA_def_cfa_register:
109 case DW_CFA_def_cfa_offset:
110 case DW_CFA_GNU_args_size:
111 // Operands: ULEB128
112 addInstruction(Opcode, Data.getULEB128(C));
113 break;
114 case DW_CFA_def_cfa_offset_sf:
115 // Operands: SLEB128
116 addInstruction(Opcode, Data.getSLEB128(C));
117 break;
118 case DW_CFA_offset_extended:
119 case DW_CFA_register:
120 case DW_CFA_def_cfa:
121 case DW_CFA_val_offset: {
122 // Operands: ULEB128, ULEB128
123 // Note: We can not embed getULEB128 directly into function
124 // argument list. getULEB128 changes Offset and order of evaluation
125 // for arguments is unspecified.
126 uint64_t op1 = Data.getULEB128(C);
127 uint64_t op2 = Data.getULEB128(C);
128 addInstruction(Opcode, op1, op2);
129 break;
130 }
131 case DW_CFA_offset_extended_sf:
132 case DW_CFA_def_cfa_sf:
133 case DW_CFA_val_offset_sf: {
134 // Operands: ULEB128, SLEB128
135 // Note: see comment for the previous case
136 uint64_t op1 = Data.getULEB128(C);
137 uint64_t op2 = (uint64_t)Data.getSLEB128(C);
138 addInstruction(Opcode, op1, op2);
139 break;
140 }
141 case DW_CFA_def_cfa_expression: {
142 uint64_t ExprLength = Data.getULEB128(C);
143 addInstruction(Opcode, 0);
144 StringRef Expression = Data.getBytes(C, ExprLength);
145
146 DataExtractor Extractor(Expression, Data.isLittleEndian(),
147 Data.getAddressSize());
148 // Note. We do not pass the DWARF format to DWARFExpression, because
149 // DW_OP_call_ref, the only operation which depends on the format, is
150 // prohibited in call frame instructions, see sec. 6.4.2 in DWARFv5.
151 Instructions.back().Expression =
152 DWARFExpression(Extractor, Data.getAddressSize());
153 break;
154 }
155 case DW_CFA_expression:
156 case DW_CFA_val_expression: {
157 uint64_t RegNum = Data.getULEB128(C);
158 addInstruction(Opcode, RegNum, 0);
159
160 uint64_t BlockLength = Data.getULEB128(C);
161 StringRef Expression = Data.getBytes(C, BlockLength);
162 DataExtractor Extractor(Expression, Data.isLittleEndian(),
163 Data.getAddressSize());
164 // Note. We do not pass the DWARF format to DWARFExpression, because
165 // DW_OP_call_ref, the only operation which depends on the format, is
166 // prohibited in call frame instructions, see sec. 6.4.2 in DWARFv5.
167 Instructions.back().Expression =
168 DWARFExpression(Extractor, Data.getAddressSize());
169 break;
170 }
171 }
172 }
173
174 *Offset = C.tell();
175 return C.takeError();
176 }
177
178 namespace {
179
180
181 } // end anonymous namespace
182
getOperandTypes()183 ArrayRef<CFIProgram::OperandType[2]> CFIProgram::getOperandTypes() {
184 static OperandType OpTypes[DW_CFA_restore+1][2];
185 static bool Initialized = false;
186 if (Initialized) {
187 return ArrayRef<OperandType[2]>(&OpTypes[0], DW_CFA_restore+1);
188 }
189 Initialized = true;
190
191 #define DECLARE_OP2(OP, OPTYPE0, OPTYPE1) \
192 do { \
193 OpTypes[OP][0] = OPTYPE0; \
194 OpTypes[OP][1] = OPTYPE1; \
195 } while (false)
196 #define DECLARE_OP1(OP, OPTYPE0) DECLARE_OP2(OP, OPTYPE0, OT_None)
197 #define DECLARE_OP0(OP) DECLARE_OP1(OP, OT_None)
198
199 DECLARE_OP1(DW_CFA_set_loc, OT_Address);
200 DECLARE_OP1(DW_CFA_advance_loc, OT_FactoredCodeOffset);
201 DECLARE_OP1(DW_CFA_advance_loc1, OT_FactoredCodeOffset);
202 DECLARE_OP1(DW_CFA_advance_loc2, OT_FactoredCodeOffset);
203 DECLARE_OP1(DW_CFA_advance_loc4, OT_FactoredCodeOffset);
204 DECLARE_OP1(DW_CFA_MIPS_advance_loc8, OT_FactoredCodeOffset);
205 DECLARE_OP2(DW_CFA_def_cfa, OT_Register, OT_Offset);
206 DECLARE_OP2(DW_CFA_def_cfa_sf, OT_Register, OT_SignedFactDataOffset);
207 DECLARE_OP1(DW_CFA_def_cfa_register, OT_Register);
208 DECLARE_OP1(DW_CFA_def_cfa_offset, OT_Offset);
209 DECLARE_OP1(DW_CFA_def_cfa_offset_sf, OT_SignedFactDataOffset);
210 DECLARE_OP1(DW_CFA_def_cfa_expression, OT_Expression);
211 DECLARE_OP1(DW_CFA_undefined, OT_Register);
212 DECLARE_OP1(DW_CFA_same_value, OT_Register);
213 DECLARE_OP2(DW_CFA_offset, OT_Register, OT_UnsignedFactDataOffset);
214 DECLARE_OP2(DW_CFA_offset_extended, OT_Register, OT_UnsignedFactDataOffset);
215 DECLARE_OP2(DW_CFA_offset_extended_sf, OT_Register, OT_SignedFactDataOffset);
216 DECLARE_OP2(DW_CFA_val_offset, OT_Register, OT_UnsignedFactDataOffset);
217 DECLARE_OP2(DW_CFA_val_offset_sf, OT_Register, OT_SignedFactDataOffset);
218 DECLARE_OP2(DW_CFA_register, OT_Register, OT_Register);
219 DECLARE_OP2(DW_CFA_expression, OT_Register, OT_Expression);
220 DECLARE_OP2(DW_CFA_val_expression, OT_Register, OT_Expression);
221 DECLARE_OP1(DW_CFA_restore, OT_Register);
222 DECLARE_OP1(DW_CFA_restore_extended, OT_Register);
223 DECLARE_OP0(DW_CFA_remember_state);
224 DECLARE_OP0(DW_CFA_restore_state);
225 DECLARE_OP0(DW_CFA_GNU_window_save);
226 DECLARE_OP1(DW_CFA_GNU_args_size, OT_Offset);
227 DECLARE_OP0(DW_CFA_nop);
228
229 #undef DECLARE_OP0
230 #undef DECLARE_OP1
231 #undef DECLARE_OP2
232
233 return ArrayRef<OperandType[2]>(&OpTypes[0], DW_CFA_restore+1);
234 }
235
236 /// Print \p Opcode's operand number \p OperandIdx which has value \p Operand.
printOperand(raw_ostream & OS,DIDumpOptions DumpOpts,const MCRegisterInfo * MRI,bool IsEH,const Instruction & Instr,unsigned OperandIdx,uint64_t Operand) const237 void CFIProgram::printOperand(raw_ostream &OS, DIDumpOptions DumpOpts,
238 const MCRegisterInfo *MRI, bool IsEH,
239 const Instruction &Instr, unsigned OperandIdx,
240 uint64_t Operand) const {
241 assert(OperandIdx < 2);
242 uint8_t Opcode = Instr.Opcode;
243 OperandType Type = getOperandTypes()[Opcode][OperandIdx];
244
245 switch (Type) {
246 case OT_Unset: {
247 OS << " Unsupported " << (OperandIdx ? "second" : "first") << " operand to";
248 auto OpcodeName = CallFrameString(Opcode, Arch);
249 if (!OpcodeName.empty())
250 OS << " " << OpcodeName;
251 else
252 OS << format(" Opcode %x", Opcode);
253 break;
254 }
255 case OT_None:
256 break;
257 case OT_Address:
258 OS << format(" %" PRIx64, Operand);
259 break;
260 case OT_Offset:
261 // The offsets are all encoded in a unsigned form, but in practice
262 // consumers use them signed. It's most certainly legacy due to
263 // the lack of signed variants in the first Dwarf standards.
264 OS << format(" %+" PRId64, int64_t(Operand));
265 break;
266 case OT_FactoredCodeOffset: // Always Unsigned
267 if (CodeAlignmentFactor)
268 OS << format(" %" PRId64, Operand * CodeAlignmentFactor);
269 else
270 OS << format(" %" PRId64 "*code_alignment_factor" , Operand);
271 break;
272 case OT_SignedFactDataOffset:
273 if (DataAlignmentFactor)
274 OS << format(" %" PRId64, int64_t(Operand) * DataAlignmentFactor);
275 else
276 OS << format(" %" PRId64 "*data_alignment_factor" , int64_t(Operand));
277 break;
278 case OT_UnsignedFactDataOffset:
279 if (DataAlignmentFactor)
280 OS << format(" %" PRId64, Operand * DataAlignmentFactor);
281 else
282 OS << format(" %" PRId64 "*data_alignment_factor" , Operand);
283 break;
284 case OT_Register:
285 OS << ' ';
286 printRegister(OS, MRI, IsEH, Operand);
287 break;
288 case OT_Expression:
289 assert(Instr.Expression && "missing DWARFExpression object");
290 OS << " ";
291 Instr.Expression->print(OS, DumpOpts, MRI, nullptr, IsEH);
292 break;
293 }
294 }
295
dump(raw_ostream & OS,DIDumpOptions DumpOpts,const MCRegisterInfo * MRI,bool IsEH,unsigned IndentLevel) const296 void CFIProgram::dump(raw_ostream &OS, DIDumpOptions DumpOpts,
297 const MCRegisterInfo *MRI, bool IsEH,
298 unsigned IndentLevel) const {
299 for (const auto &Instr : Instructions) {
300 uint8_t Opcode = Instr.Opcode;
301 if (Opcode & DWARF_CFI_PRIMARY_OPCODE_MASK)
302 Opcode &= DWARF_CFI_PRIMARY_OPCODE_MASK;
303 OS.indent(2 * IndentLevel);
304 OS << CallFrameString(Opcode, Arch) << ":";
305 for (unsigned i = 0; i < Instr.Ops.size(); ++i)
306 printOperand(OS, DumpOpts, MRI, IsEH, Instr, i, Instr.Ops[i]);
307 OS << '\n';
308 }
309 }
310
311 // Returns the CIE identifier to be used by the requested format.
312 // CIE ids for .debug_frame sections are defined in Section 7.24 of DWARFv5.
313 // For CIE ID in .eh_frame sections see
314 // https://refspecs.linuxfoundation.org/LSB_5.0.0/LSB-Core-generic/LSB-Core-generic/ehframechpt.html
getCIEId(bool IsDWARF64,bool IsEH)315 constexpr uint64_t getCIEId(bool IsDWARF64, bool IsEH) {
316 if (IsEH)
317 return 0;
318 if (IsDWARF64)
319 return DW64_CIE_ID;
320 return DW_CIE_ID;
321 }
322
dump(raw_ostream & OS,DIDumpOptions DumpOpts,const MCRegisterInfo * MRI,bool IsEH) const323 void CIE::dump(raw_ostream &OS, DIDumpOptions DumpOpts,
324 const MCRegisterInfo *MRI, bool IsEH) const {
325 // A CIE with a zero length is a terminator entry in the .eh_frame section.
326 if (IsEH && Length == 0) {
327 OS << format("%08" PRIx64, Offset) << " ZERO terminator\n";
328 return;
329 }
330
331 OS << format("%08" PRIx64, Offset)
332 << format(" %0*" PRIx64, IsDWARF64 ? 16 : 8, Length)
333 << format(" %0*" PRIx64, IsDWARF64 && !IsEH ? 16 : 8,
334 getCIEId(IsDWARF64, IsEH))
335 << " CIE\n"
336 << " Format: " << FormatString(IsDWARF64) << "\n"
337 << format(" Version: %d\n", Version)
338 << " Augmentation: \"" << Augmentation << "\"\n";
339 if (Version >= 4) {
340 OS << format(" Address size: %u\n", (uint32_t)AddressSize);
341 OS << format(" Segment desc size: %u\n",
342 (uint32_t)SegmentDescriptorSize);
343 }
344 OS << format(" Code alignment factor: %u\n", (uint32_t)CodeAlignmentFactor);
345 OS << format(" Data alignment factor: %d\n", (int32_t)DataAlignmentFactor);
346 OS << format(" Return address column: %d\n", (int32_t)ReturnAddressRegister);
347 if (Personality)
348 OS << format(" Personality Address: %016" PRIx64 "\n", *Personality);
349 if (!AugmentationData.empty()) {
350 OS << " Augmentation data: ";
351 for (uint8_t Byte : AugmentationData)
352 OS << ' ' << hexdigit(Byte >> 4) << hexdigit(Byte & 0xf);
353 OS << "\n";
354 }
355 OS << "\n";
356 CFIs.dump(OS, DumpOpts, MRI, IsEH);
357 OS << "\n";
358 }
359
dump(raw_ostream & OS,DIDumpOptions DumpOpts,const MCRegisterInfo * MRI,bool IsEH) const360 void FDE::dump(raw_ostream &OS, DIDumpOptions DumpOpts,
361 const MCRegisterInfo *MRI, bool IsEH) const {
362 OS << format("%08" PRIx64, Offset)
363 << format(" %0*" PRIx64, IsDWARF64 ? 16 : 8, Length)
364 << format(" %0*" PRIx64, IsDWARF64 && !IsEH ? 16 : 8, CIEPointer)
365 << " FDE cie=";
366 if (LinkedCIE)
367 OS << format("%08" PRIx64, LinkedCIE->getOffset());
368 else
369 OS << "<invalid offset>";
370 OS << format(" pc=%08" PRIx64 "...%08" PRIx64 "\n", InitialLocation,
371 InitialLocation + AddressRange);
372 OS << " Format: " << FormatString(IsDWARF64) << "\n";
373 if (LSDAAddress)
374 OS << format(" LSDA Address: %016" PRIx64 "\n", *LSDAAddress);
375 CFIs.dump(OS, DumpOpts, MRI, IsEH);
376 OS << "\n";
377 }
378
DWARFDebugFrame(Triple::ArchType Arch,bool IsEH,uint64_t EHFrameAddress)379 DWARFDebugFrame::DWARFDebugFrame(Triple::ArchType Arch,
380 bool IsEH, uint64_t EHFrameAddress)
381 : Arch(Arch), IsEH(IsEH), EHFrameAddress(EHFrameAddress) {}
382
383 DWARFDebugFrame::~DWARFDebugFrame() = default;
384
dumpDataAux(DataExtractor Data,uint64_t Offset,int Length)385 static void LLVM_ATTRIBUTE_UNUSED dumpDataAux(DataExtractor Data,
386 uint64_t Offset, int Length) {
387 errs() << "DUMP: ";
388 for (int i = 0; i < Length; ++i) {
389 uint8_t c = Data.getU8(&Offset);
390 errs().write_hex(c); errs() << " ";
391 }
392 errs() << "\n";
393 }
394
parse(DWARFDataExtractor Data)395 Error DWARFDebugFrame::parse(DWARFDataExtractor Data) {
396 uint64_t Offset = 0;
397 DenseMap<uint64_t, CIE *> CIEs;
398
399 while (Data.isValidOffset(Offset)) {
400 uint64_t StartOffset = Offset;
401
402 uint64_t Length;
403 DwarfFormat Format;
404 std::tie(Length, Format) = Data.getInitialLength(&Offset);
405 bool IsDWARF64 = Format == DWARF64;
406
407 // If the Length is 0, then this CIE is a terminator. We add it because some
408 // dumper tools might need it to print something special for such entries
409 // (e.g. llvm-objdump --dwarf=frames prints "ZERO terminator").
410 if (Length == 0) {
411 auto Cie = std::make_unique<CIE>(
412 IsDWARF64, StartOffset, 0, 0, SmallString<8>(), 0, 0, 0, 0, 0,
413 SmallString<8>(), 0, 0, None, None, Arch);
414 CIEs[StartOffset] = Cie.get();
415 Entries.push_back(std::move(Cie));
416 break;
417 }
418
419 // At this point, Offset points to the next field after Length.
420 // Length is the structure size excluding itself. Compute an offset one
421 // past the end of the structure (needed to know how many instructions to
422 // read).
423 uint64_t StartStructureOffset = Offset;
424 uint64_t EndStructureOffset = Offset + Length;
425
426 // The Id field's size depends on the DWARF format
427 Error Err = Error::success();
428 uint64_t Id = Data.getRelocatedValue((IsDWARF64 && !IsEH) ? 8 : 4, &Offset,
429 /*SectionIndex=*/nullptr, &Err);
430 if (Err)
431 return Err;
432
433 if (Id == getCIEId(IsDWARF64, IsEH)) {
434 uint8_t Version = Data.getU8(&Offset);
435 const char *Augmentation = Data.getCStr(&Offset);
436 StringRef AugmentationString(Augmentation ? Augmentation : "");
437 // TODO: we should provide a way to report a warning and continue dumping.
438 if (IsEH && Version != 1)
439 return createStringError(errc::not_supported,
440 "unsupported CIE version: %" PRIu8, Version);
441
442 uint8_t AddressSize = Version < 4 ? Data.getAddressSize() :
443 Data.getU8(&Offset);
444 Data.setAddressSize(AddressSize);
445 uint8_t SegmentDescriptorSize = Version < 4 ? 0 : Data.getU8(&Offset);
446 uint64_t CodeAlignmentFactor = Data.getULEB128(&Offset);
447 int64_t DataAlignmentFactor = Data.getSLEB128(&Offset);
448 uint64_t ReturnAddressRegister =
449 Version == 1 ? Data.getU8(&Offset) : Data.getULEB128(&Offset);
450
451 // Parse the augmentation data for EH CIEs
452 StringRef AugmentationData("");
453 uint32_t FDEPointerEncoding = DW_EH_PE_absptr;
454 uint32_t LSDAPointerEncoding = DW_EH_PE_omit;
455 Optional<uint64_t> Personality;
456 Optional<uint32_t> PersonalityEncoding;
457 if (IsEH) {
458 Optional<uint64_t> AugmentationLength;
459 uint64_t StartAugmentationOffset;
460 uint64_t EndAugmentationOffset;
461
462 // Walk the augmentation string to get all the augmentation data.
463 for (unsigned i = 0, e = AugmentationString.size(); i != e; ++i) {
464 switch (AugmentationString[i]) {
465 default:
466 return createStringError(
467 errc::invalid_argument,
468 "unknown augmentation character in entry at 0x%" PRIx64,
469 StartOffset);
470 case 'L':
471 LSDAPointerEncoding = Data.getU8(&Offset);
472 break;
473 case 'P': {
474 if (Personality)
475 return createStringError(
476 errc::invalid_argument,
477 "duplicate personality in entry at 0x%" PRIx64, StartOffset);
478 PersonalityEncoding = Data.getU8(&Offset);
479 Personality = Data.getEncodedPointer(
480 &Offset, *PersonalityEncoding,
481 EHFrameAddress ? EHFrameAddress + Offset : 0);
482 break;
483 }
484 case 'R':
485 FDEPointerEncoding = Data.getU8(&Offset);
486 break;
487 case 'S':
488 // Current frame is a signal trampoline.
489 break;
490 case 'z':
491 if (i)
492 return createStringError(
493 errc::invalid_argument,
494 "'z' must be the first character at 0x%" PRIx64, StartOffset);
495 // Parse the augmentation length first. We only parse it if
496 // the string contains a 'z'.
497 AugmentationLength = Data.getULEB128(&Offset);
498 StartAugmentationOffset = Offset;
499 EndAugmentationOffset = Offset + *AugmentationLength;
500 break;
501 case 'B':
502 // B-Key is used for signing functions associated with this
503 // augmentation string
504 break;
505 }
506 }
507
508 if (AugmentationLength.hasValue()) {
509 if (Offset != EndAugmentationOffset)
510 return createStringError(errc::invalid_argument,
511 "parsing augmentation data at 0x%" PRIx64
512 " failed",
513 StartOffset);
514 AugmentationData = Data.getData().slice(StartAugmentationOffset,
515 EndAugmentationOffset);
516 }
517 }
518
519 auto Cie = std::make_unique<CIE>(
520 IsDWARF64, StartOffset, Length, Version, AugmentationString,
521 AddressSize, SegmentDescriptorSize, CodeAlignmentFactor,
522 DataAlignmentFactor, ReturnAddressRegister, AugmentationData,
523 FDEPointerEncoding, LSDAPointerEncoding, Personality,
524 PersonalityEncoding, Arch);
525 CIEs[StartOffset] = Cie.get();
526 Entries.emplace_back(std::move(Cie));
527 } else {
528 // FDE
529 uint64_t CIEPointer = Id;
530 uint64_t InitialLocation = 0;
531 uint64_t AddressRange = 0;
532 Optional<uint64_t> LSDAAddress;
533 CIE *Cie = CIEs[IsEH ? (StartStructureOffset - CIEPointer) : CIEPointer];
534
535 if (IsEH) {
536 // The address size is encoded in the CIE we reference.
537 if (!Cie)
538 return createStringError(errc::invalid_argument,
539 "parsing FDE data at 0x%" PRIx64
540 " failed due to missing CIE",
541 StartOffset);
542 if (auto Val =
543 Data.getEncodedPointer(&Offset, Cie->getFDEPointerEncoding(),
544 EHFrameAddress + Offset)) {
545 InitialLocation = *Val;
546 }
547 if (auto Val = Data.getEncodedPointer(
548 &Offset, Cie->getFDEPointerEncoding(), 0)) {
549 AddressRange = *Val;
550 }
551
552 StringRef AugmentationString = Cie->getAugmentationString();
553 if (!AugmentationString.empty()) {
554 // Parse the augmentation length and data for this FDE.
555 uint64_t AugmentationLength = Data.getULEB128(&Offset);
556
557 uint64_t EndAugmentationOffset = Offset + AugmentationLength;
558
559 // Decode the LSDA if the CIE augmentation string said we should.
560 if (Cie->getLSDAPointerEncoding() != DW_EH_PE_omit) {
561 LSDAAddress = Data.getEncodedPointer(
562 &Offset, Cie->getLSDAPointerEncoding(),
563 EHFrameAddress ? Offset + EHFrameAddress : 0);
564 }
565
566 if (Offset != EndAugmentationOffset)
567 return createStringError(errc::invalid_argument,
568 "parsing augmentation data at 0x%" PRIx64
569 " failed",
570 StartOffset);
571 }
572 } else {
573 InitialLocation = Data.getRelocatedAddress(&Offset);
574 AddressRange = Data.getRelocatedAddress(&Offset);
575 }
576
577 Entries.emplace_back(new FDE(IsDWARF64, StartOffset, Length, CIEPointer,
578 InitialLocation, AddressRange, Cie,
579 LSDAAddress, Arch));
580 }
581
582 if (Error E =
583 Entries.back()->cfis().parse(Data, &Offset, EndStructureOffset))
584 return E;
585
586 if (Offset != EndStructureOffset)
587 return createStringError(
588 errc::invalid_argument,
589 "parsing entry instructions at 0x%" PRIx64 " failed", StartOffset);
590 }
591
592 return Error::success();
593 }
594
getEntryAtOffset(uint64_t Offset) const595 FrameEntry *DWARFDebugFrame::getEntryAtOffset(uint64_t Offset) const {
596 auto It = partition_point(Entries, [=](const std::unique_ptr<FrameEntry> &E) {
597 return E->getOffset() < Offset;
598 });
599 if (It != Entries.end() && (*It)->getOffset() == Offset)
600 return It->get();
601 return nullptr;
602 }
603
dump(raw_ostream & OS,DIDumpOptions DumpOpts,const MCRegisterInfo * MRI,Optional<uint64_t> Offset) const604 void DWARFDebugFrame::dump(raw_ostream &OS, DIDumpOptions DumpOpts,
605 const MCRegisterInfo *MRI,
606 Optional<uint64_t> Offset) const {
607 if (Offset) {
608 if (auto *Entry = getEntryAtOffset(*Offset))
609 Entry->dump(OS, DumpOpts, MRI, IsEH);
610 return;
611 }
612
613 OS << "\n";
614 for (const auto &Entry : Entries)
615 Entry->dump(OS, DumpOpts, MRI, IsEH);
616 }
617