[ORC] Add std::tuple support to SimplePackedSerialization.
[llvm-project.git] / llvm / lib / DebugInfo / DWARF / DWARFDebugFrame.cpp
blob92a461dbd9411648d415cb324f123607c1d29304
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 //===----------------------------------------------------------------------===//
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>
28 using namespace llvm;
29 using namespace dwarf;
31 static void printRegister(raw_ostream &OS, const MCRegisterInfo *MRI, bool IsEH,
32 unsigned RegNum) {
33 if (MRI) {
34 if (Optional<unsigned> LLVMRegNum = MRI->getLLVMRegNum(RegNum, IsEH)) {
35 if (const char *RegName = MRI->getName(*LLVMRegNum)) {
36 OS << RegName;
37 return;
41 OS << "reg" << RegNum;
44 UnwindLocation UnwindLocation::createUnspecified() { return {Unspecified}; }
46 UnwindLocation UnwindLocation::createUndefined() { return {Undefined}; }
48 UnwindLocation UnwindLocation::createSame() { return {Same}; }
50 UnwindLocation UnwindLocation::createIsConstant(int32_t Value) {
51 return {Constant, InvalidRegisterNumber, Value, None, false};
54 UnwindLocation UnwindLocation::createIsCFAPlusOffset(int32_t Offset) {
55 return {CFAPlusOffset, InvalidRegisterNumber, Offset, None, false};
58 UnwindLocation UnwindLocation::createAtCFAPlusOffset(int32_t Offset) {
59 return {CFAPlusOffset, InvalidRegisterNumber, Offset, None, true};
62 UnwindLocation
63 UnwindLocation::createIsRegisterPlusOffset(uint32_t RegNum, int32_t Offset,
64 Optional<uint32_t> AddrSpace) {
65 return {RegPlusOffset, RegNum, Offset, AddrSpace, false};
68 UnwindLocation
69 UnwindLocation::createAtRegisterPlusOffset(uint32_t RegNum, int32_t Offset,
70 Optional<uint32_t> AddrSpace) {
71 return {RegPlusOffset, RegNum, Offset, AddrSpace, true};
74 UnwindLocation UnwindLocation::createIsDWARFExpression(DWARFExpression Expr) {
75 return {Expr, false};
78 UnwindLocation UnwindLocation::createAtDWARFExpression(DWARFExpression Expr) {
79 return {Expr, true};
82 void UnwindLocation::dump(raw_ostream &OS, const MCRegisterInfo *MRI,
83 bool IsEH) const {
84 if (Dereference)
85 OS << '[';
86 switch (Kind) {
87 case Unspecified:
88 OS << "unspecified";
89 break;
90 case Undefined:
91 OS << "undefined";
92 break;
93 case Same:
94 OS << "same";
95 break;
96 case CFAPlusOffset:
97 OS << "CFA";
98 if (Offset == 0)
99 break;
100 if (Offset > 0)
101 OS << "+";
102 OS << Offset;
103 break;
104 case RegPlusOffset:
105 printRegister(OS, MRI, IsEH, RegNum);
106 if (Offset == 0 && !AddrSpace)
107 break;
108 if (Offset >= 0)
109 OS << "+";
110 OS << Offset;
111 if (AddrSpace)
112 OS << " in addrspace" << *AddrSpace;
113 break;
114 case DWARFExpr:
115 Expr->print(OS, DIDumpOptions(), MRI, nullptr, IsEH);
116 break;
117 case Constant:
118 OS << Offset;
119 break;
121 if (Dereference)
122 OS << ']';
125 raw_ostream &llvm::dwarf::operator<<(raw_ostream &OS,
126 const UnwindLocation &UL) {
127 UL.dump(OS, nullptr, false);
128 return OS;
131 bool UnwindLocation::operator==(const UnwindLocation &RHS) const {
132 if (Kind != RHS.Kind)
133 return false;
134 switch (Kind) {
135 case Unspecified:
136 case Undefined:
137 case Same:
138 return true;
139 case CFAPlusOffset:
140 return Offset == RHS.Offset && Dereference == RHS.Dereference;
141 case RegPlusOffset:
142 return RegNum == RHS.RegNum && Offset == RHS.Offset &&
143 Dereference == RHS.Dereference;
144 case DWARFExpr:
145 return *Expr == *RHS.Expr && Dereference == RHS.Dereference;
146 case Constant:
147 return Offset == RHS.Offset;
149 return false;
152 void RegisterLocations::dump(raw_ostream &OS, const MCRegisterInfo *MRI,
153 bool IsEH) const {
154 bool First = true;
155 for (const auto &RegLocPair : Locations) {
156 if (First)
157 First = false;
158 else
159 OS << ", ";
160 printRegister(OS, MRI, IsEH, RegLocPair.first);
161 OS << '=';
162 RegLocPair.second.dump(OS, MRI, IsEH);
166 raw_ostream &llvm::dwarf::operator<<(raw_ostream &OS,
167 const RegisterLocations &RL) {
168 RL.dump(OS, nullptr, false);
169 return OS;
172 void UnwindRow::dump(raw_ostream &OS, const MCRegisterInfo *MRI, bool IsEH,
173 unsigned IndentLevel) const {
174 OS.indent(2 * IndentLevel);
175 if (hasAddress())
176 OS << format("0x%" PRIx64 ": ", *Address);
177 OS << "CFA=";
178 CFAValue.dump(OS, MRI, IsEH);
179 if (RegLocs.hasLocations()) {
180 OS << ": ";
181 RegLocs.dump(OS, MRI, IsEH);
183 OS << "\n";
186 raw_ostream &llvm::dwarf::operator<<(raw_ostream &OS, const UnwindRow &Row) {
187 Row.dump(OS, nullptr, false, 0);
188 return OS;
191 void UnwindTable::dump(raw_ostream &OS, const MCRegisterInfo *MRI, bool IsEH,
192 unsigned IndentLevel) const {
193 for (const UnwindRow &Row : Rows)
194 Row.dump(OS, MRI, IsEH, IndentLevel);
197 raw_ostream &llvm::dwarf::operator<<(raw_ostream &OS, const UnwindTable &Rows) {
198 Rows.dump(OS, nullptr, false, 0);
199 return OS;
202 Expected<UnwindTable> UnwindTable::create(const FDE *Fde) {
203 const CIE *Cie = Fde->getLinkedCIE();
204 if (Cie == nullptr)
205 return createStringError(errc::invalid_argument,
206 "unable to get CIE for FDE at offset 0x%" PRIx64,
207 Fde->getOffset());
209 // Rows will be empty if there are no CFI instructions.
210 if (Cie->cfis().empty() && Fde->cfis().empty())
211 return UnwindTable();
213 UnwindTable UT;
214 UnwindRow Row;
215 Row.setAddress(Fde->getInitialLocation());
216 UT.EndAddress = Fde->getInitialLocation() + Fde->getAddressRange();
217 if (Error CieError = UT.parseRows(Cie->cfis(), Row, nullptr))
218 return std::move(CieError);
219 // We need to save the initial locations of registers from the CIE parsing
220 // in case we run into DW_CFA_restore or DW_CFA_restore_extended opcodes.
221 const RegisterLocations InitialLocs = Row.getRegisterLocations();
222 if (Error FdeError = UT.parseRows(Fde->cfis(), Row, &InitialLocs))
223 return std::move(FdeError);
224 // May be all the CFI instructions were DW_CFA_nop amd Row becomes empty.
225 // Do not add that to the unwind table.
226 if (Row.getRegisterLocations().hasLocations() ||
227 Row.getCFAValue().getLocation() != UnwindLocation::Unspecified)
228 UT.Rows.push_back(Row);
229 return UT;
232 Expected<UnwindTable> UnwindTable::create(const CIE *Cie) {
233 // Rows will be empty if there are no CFI instructions.
234 if (Cie->cfis().empty())
235 return UnwindTable();
237 UnwindTable UT;
238 UnwindRow Row;
239 if (Error CieError = UT.parseRows(Cie->cfis(), Row, nullptr))
240 return std::move(CieError);
241 // May be all the CFI instructions were DW_CFA_nop amd Row becomes empty.
242 // Do not add that to the unwind table.
243 if (Row.getRegisterLocations().hasLocations() ||
244 Row.getCFAValue().getLocation() != UnwindLocation::Unspecified)
245 UT.Rows.push_back(Row);
246 return UT;
249 // See DWARF standard v3, section 7.23
250 const uint8_t DWARF_CFI_PRIMARY_OPCODE_MASK = 0xc0;
251 const uint8_t DWARF_CFI_PRIMARY_OPERAND_MASK = 0x3f;
253 Error CFIProgram::parse(DWARFDataExtractor Data, uint64_t *Offset,
254 uint64_t EndOffset) {
255 DataExtractor::Cursor C(*Offset);
256 while (C && C.tell() < EndOffset) {
257 uint8_t Opcode = Data.getRelocatedValue(C, 1);
258 if (!C)
259 break;
261 // Some instructions have a primary opcode encoded in the top bits.
262 if (uint8_t Primary = Opcode & DWARF_CFI_PRIMARY_OPCODE_MASK) {
263 // If it's a primary opcode, the first operand is encoded in the bottom
264 // bits of the opcode itself.
265 uint64_t Op1 = Opcode & DWARF_CFI_PRIMARY_OPERAND_MASK;
266 switch (Primary) {
267 case DW_CFA_advance_loc:
268 case DW_CFA_restore:
269 addInstruction(Primary, Op1);
270 break;
271 case DW_CFA_offset:
272 addInstruction(Primary, Op1, Data.getULEB128(C));
273 break;
274 default:
275 llvm_unreachable("invalid primary CFI opcode");
277 continue;
280 // Extended opcode - its value is Opcode itself.
281 switch (Opcode) {
282 default:
283 return createStringError(errc::illegal_byte_sequence,
284 "invalid extended CFI opcode 0x%" PRIx8, Opcode);
285 case DW_CFA_nop:
286 case DW_CFA_remember_state:
287 case DW_CFA_restore_state:
288 case DW_CFA_GNU_window_save:
289 // No operands
290 addInstruction(Opcode);
291 break;
292 case DW_CFA_set_loc:
293 // Operands: Address
294 addInstruction(Opcode, Data.getRelocatedAddress(C));
295 break;
296 case DW_CFA_advance_loc1:
297 // Operands: 1-byte delta
298 addInstruction(Opcode, Data.getRelocatedValue(C, 1));
299 break;
300 case DW_CFA_advance_loc2:
301 // Operands: 2-byte delta
302 addInstruction(Opcode, Data.getRelocatedValue(C, 2));
303 break;
304 case DW_CFA_advance_loc4:
305 // Operands: 4-byte delta
306 addInstruction(Opcode, Data.getRelocatedValue(C, 4));
307 break;
308 case DW_CFA_restore_extended:
309 case DW_CFA_undefined:
310 case DW_CFA_same_value:
311 case DW_CFA_def_cfa_register:
312 case DW_CFA_def_cfa_offset:
313 case DW_CFA_GNU_args_size:
314 // Operands: ULEB128
315 addInstruction(Opcode, Data.getULEB128(C));
316 break;
317 case DW_CFA_def_cfa_offset_sf:
318 // Operands: SLEB128
319 addInstruction(Opcode, Data.getSLEB128(C));
320 break;
321 case DW_CFA_LLVM_def_aspace_cfa:
322 case DW_CFA_LLVM_def_aspace_cfa_sf: {
323 auto RegNum = Data.getULEB128(C);
324 auto CfaOffset = Opcode == DW_CFA_LLVM_def_aspace_cfa
325 ? Data.getULEB128(C)
326 : Data.getSLEB128(C);
327 auto AddressSpace = Data.getULEB128(C);
328 addInstruction(Opcode, RegNum, CfaOffset, AddressSpace);
329 break;
331 case DW_CFA_offset_extended:
332 case DW_CFA_register:
333 case DW_CFA_def_cfa:
334 case DW_CFA_val_offset: {
335 // Operands: ULEB128, ULEB128
336 // Note: We can not embed getULEB128 directly into function
337 // argument list. getULEB128 changes Offset and order of evaluation
338 // for arguments is unspecified.
339 uint64_t op1 = Data.getULEB128(C);
340 uint64_t op2 = Data.getULEB128(C);
341 addInstruction(Opcode, op1, op2);
342 break;
344 case DW_CFA_offset_extended_sf:
345 case DW_CFA_def_cfa_sf:
346 case DW_CFA_val_offset_sf: {
347 // Operands: ULEB128, SLEB128
348 // Note: see comment for the previous case
349 uint64_t op1 = Data.getULEB128(C);
350 uint64_t op2 = (uint64_t)Data.getSLEB128(C);
351 addInstruction(Opcode, op1, op2);
352 break;
354 case DW_CFA_def_cfa_expression: {
355 uint64_t ExprLength = Data.getULEB128(C);
356 addInstruction(Opcode, 0);
357 StringRef Expression = Data.getBytes(C, ExprLength);
359 DataExtractor Extractor(Expression, Data.isLittleEndian(),
360 Data.getAddressSize());
361 // Note. We do not pass the DWARF format to DWARFExpression, because
362 // DW_OP_call_ref, the only operation which depends on the format, is
363 // prohibited in call frame instructions, see sec. 6.4.2 in DWARFv5.
364 Instructions.back().Expression =
365 DWARFExpression(Extractor, Data.getAddressSize());
366 break;
368 case DW_CFA_expression:
369 case DW_CFA_val_expression: {
370 uint64_t RegNum = Data.getULEB128(C);
371 addInstruction(Opcode, RegNum, 0);
373 uint64_t BlockLength = Data.getULEB128(C);
374 StringRef Expression = Data.getBytes(C, BlockLength);
375 DataExtractor Extractor(Expression, Data.isLittleEndian(),
376 Data.getAddressSize());
377 // Note. We do not pass the DWARF format to DWARFExpression, because
378 // DW_OP_call_ref, the only operation which depends on the format, is
379 // prohibited in call frame instructions, see sec. 6.4.2 in DWARFv5.
380 Instructions.back().Expression =
381 DWARFExpression(Extractor, Data.getAddressSize());
382 break;
387 *Offset = C.tell();
388 return C.takeError();
391 StringRef CFIProgram::callFrameString(unsigned Opcode) const {
392 return dwarf::CallFrameString(Opcode, Arch);
395 const char *CFIProgram::operandTypeString(CFIProgram::OperandType OT) {
396 #define ENUM_TO_CSTR(e) \
397 case e: \
398 return #e;
399 switch (OT) {
400 ENUM_TO_CSTR(OT_Unset);
401 ENUM_TO_CSTR(OT_None);
402 ENUM_TO_CSTR(OT_Address);
403 ENUM_TO_CSTR(OT_Offset);
404 ENUM_TO_CSTR(OT_FactoredCodeOffset);
405 ENUM_TO_CSTR(OT_SignedFactDataOffset);
406 ENUM_TO_CSTR(OT_UnsignedFactDataOffset);
407 ENUM_TO_CSTR(OT_Register);
408 ENUM_TO_CSTR(OT_AddressSpace);
409 ENUM_TO_CSTR(OT_Expression);
411 return "<unknown CFIProgram::OperandType>";
414 llvm::Expected<uint64_t>
415 CFIProgram::Instruction::getOperandAsUnsigned(const CFIProgram &CFIP,
416 uint32_t OperandIdx) const {
417 if (OperandIdx >= MaxOperands)
418 return createStringError(errc::invalid_argument,
419 "operand index %" PRIu32 " is not valid",
420 OperandIdx);
421 OperandType Type = CFIP.getOperandTypes()[Opcode][OperandIdx];
422 uint64_t Operand = Ops[OperandIdx];
423 switch (Type) {
424 case OT_Unset:
425 case OT_None:
426 case OT_Expression:
427 return createStringError(errc::invalid_argument,
428 "op[%" PRIu32 "] has type %s which has no value",
429 OperandIdx, CFIProgram::operandTypeString(Type));
431 case OT_Offset:
432 case OT_SignedFactDataOffset:
433 case OT_UnsignedFactDataOffset:
434 return createStringError(
435 errc::invalid_argument,
436 "op[%" PRIu32 "] has OperandType OT_Offset which produces a signed "
437 "result, call getOperandAsSigned instead",
438 OperandIdx);
440 case OT_Address:
441 case OT_Register:
442 case OT_AddressSpace:
443 return Operand;
445 case OT_FactoredCodeOffset: {
446 const uint64_t CodeAlignmentFactor = CFIP.codeAlign();
447 if (CodeAlignmentFactor == 0)
448 return createStringError(
449 errc::invalid_argument,
450 "op[%" PRIu32 "] has type OT_FactoredCodeOffset but code alignment "
451 "is zero",
452 OperandIdx);
453 return Operand * CodeAlignmentFactor;
456 llvm_unreachable("invalid operand type");
459 llvm::Expected<int64_t>
460 CFIProgram::Instruction::getOperandAsSigned(const CFIProgram &CFIP,
461 uint32_t OperandIdx) const {
462 if (OperandIdx >= MaxOperands)
463 return createStringError(errc::invalid_argument,
464 "operand index %" PRIu32 " is not valid",
465 OperandIdx);
466 OperandType Type = CFIP.getOperandTypes()[Opcode][OperandIdx];
467 uint64_t Operand = Ops[OperandIdx];
468 switch (Type) {
469 case OT_Unset:
470 case OT_None:
471 case OT_Expression:
472 return createStringError(errc::invalid_argument,
473 "op[%" PRIu32 "] has type %s which has no value",
474 OperandIdx, CFIProgram::operandTypeString(Type));
476 case OT_Address:
477 case OT_Register:
478 case OT_AddressSpace:
479 return createStringError(
480 errc::invalid_argument,
481 "op[%" PRIu32 "] has OperandType %s which produces an unsigned result, "
482 "call getOperandAsUnsigned instead",
483 OperandIdx, CFIProgram::operandTypeString(Type));
485 case OT_Offset:
486 return (int64_t)Operand;
488 case OT_FactoredCodeOffset:
489 case OT_SignedFactDataOffset: {
490 const int64_t DataAlignmentFactor = CFIP.dataAlign();
491 if (DataAlignmentFactor == 0)
492 return createStringError(errc::invalid_argument,
493 "op[%" PRIu32 "] has type %s but data "
494 "alignment is zero",
495 OperandIdx, CFIProgram::operandTypeString(Type));
496 return int64_t(Operand) * DataAlignmentFactor;
499 case OT_UnsignedFactDataOffset: {
500 const int64_t DataAlignmentFactor = CFIP.dataAlign();
501 if (DataAlignmentFactor == 0)
502 return createStringError(errc::invalid_argument,
503 "op[%" PRIu32
504 "] has type OT_UnsignedFactDataOffset but data "
505 "alignment is zero",
506 OperandIdx);
507 return Operand * DataAlignmentFactor;
510 llvm_unreachable("invalid operand type");
513 Error UnwindTable::parseRows(const CFIProgram &CFIP, UnwindRow &Row,
514 const RegisterLocations *InitialLocs) {
515 std::vector<RegisterLocations> RegisterStates;
516 for (const CFIProgram::Instruction &Inst : CFIP) {
517 switch (Inst.Opcode) {
518 case dwarf::DW_CFA_set_loc: {
519 // The DW_CFA_set_loc instruction takes a single operand that
520 // represents a target address. The required action is to create a new
521 // table row using the specified address as the location. All other
522 // values in the new row are initially identical to the current row.
523 // The new location value is always greater than the current one. If
524 // the segment_size field of this FDE's CIE is non- zero, the initial
525 // location is preceded by a segment selector of the given length
526 llvm::Expected<uint64_t> NewAddress = Inst.getOperandAsUnsigned(CFIP, 0);
527 if (!NewAddress)
528 return NewAddress.takeError();
529 if (*NewAddress <= Row.getAddress())
530 return createStringError(
531 errc::invalid_argument,
532 "%s with adrress 0x%" PRIx64 " which must be greater than the "
533 "current row address 0x%" PRIx64,
534 CFIP.callFrameString(Inst.Opcode).str().c_str(), *NewAddress,
535 Row.getAddress());
536 Rows.push_back(Row);
537 Row.setAddress(*NewAddress);
538 break;
541 case dwarf::DW_CFA_advance_loc:
542 case dwarf::DW_CFA_advance_loc1:
543 case dwarf::DW_CFA_advance_loc2:
544 case dwarf::DW_CFA_advance_loc4: {
545 // The DW_CFA_advance instruction takes a single operand that
546 // represents a constant delta. The required action is to create a new
547 // table row with a location value that is computed by taking the
548 // current entry’s location value and adding the value of delta *
549 // code_alignment_factor. All other values in the new row are initially
550 // identical to the current row.
551 Rows.push_back(Row);
552 llvm::Expected<uint64_t> Offset = Inst.getOperandAsUnsigned(CFIP, 0);
553 if (!Offset)
554 return Offset.takeError();
555 Row.slideAddress(*Offset);
556 break;
559 case dwarf::DW_CFA_restore:
560 case dwarf::DW_CFA_restore_extended: {
561 // The DW_CFA_restore instruction takes a single operand (encoded with
562 // the opcode) that represents a register number. The required action
563 // is to change the rule for the indicated register to the rule
564 // assigned it by the initial_instructions in the CIE.
565 if (InitialLocs == nullptr)
566 return createStringError(
567 errc::invalid_argument, "%s encountered while parsing a CIE",
568 CFIP.callFrameString(Inst.Opcode).str().c_str());
569 llvm::Expected<uint64_t> RegNum = Inst.getOperandAsUnsigned(CFIP, 0);
570 if (!RegNum)
571 return RegNum.takeError();
572 if (Optional<UnwindLocation> O =
573 InitialLocs->getRegisterLocation(*RegNum))
574 Row.getRegisterLocations().setRegisterLocation(*RegNum, *O);
575 else
576 Row.getRegisterLocations().removeRegisterLocation(*RegNum);
577 break;
580 case dwarf::DW_CFA_offset:
581 case dwarf::DW_CFA_offset_extended:
582 case dwarf::DW_CFA_offset_extended_sf: {
583 llvm::Expected<uint64_t> RegNum = Inst.getOperandAsUnsigned(CFIP, 0);
584 if (!RegNum)
585 return RegNum.takeError();
586 llvm::Expected<int64_t> Offset = Inst.getOperandAsSigned(CFIP, 1);
587 if (!Offset)
588 return Offset.takeError();
589 Row.getRegisterLocations().setRegisterLocation(
590 *RegNum, UnwindLocation::createAtCFAPlusOffset(*Offset));
591 break;
594 case dwarf::DW_CFA_nop:
595 break;
597 case dwarf::DW_CFA_remember_state:
598 RegisterStates.push_back(Row.getRegisterLocations());
599 break;
601 case dwarf::DW_CFA_restore_state:
602 if (RegisterStates.empty())
603 return createStringError(errc::invalid_argument,
604 "DW_CFA_restore_state without a matching "
605 "previous DW_CFA_remember_state");
606 Row.getRegisterLocations() = RegisterStates.back();
607 RegisterStates.pop_back();
608 break;
610 case dwarf::DW_CFA_GNU_window_save:
611 switch (CFIP.triple()) {
612 case Triple::aarch64:
613 case Triple::aarch64_be:
614 case Triple::aarch64_32: {
615 // DW_CFA_GNU_window_save is used for different things on different
616 // architectures. For aarch64 it is known as
617 // DW_CFA_AARCH64_negate_ra_state. The action is to toggle the
618 // value of the return address state between 1 and 0. If there is
619 // no rule for the AARCH64_DWARF_PAUTH_RA_STATE register, then it
620 // should be initially set to 1.
621 constexpr uint32_t AArch64DWARFPAuthRaState = 34;
622 auto LRLoc = Row.getRegisterLocations().getRegisterLocation(
623 AArch64DWARFPAuthRaState);
624 if (LRLoc) {
625 if (LRLoc->getLocation() == UnwindLocation::Constant) {
626 // Toggle the constant value from 0 to 1 or 1 to 0.
627 LRLoc->setConstant(LRLoc->getConstant() ^ 1);
628 } else {
629 return createStringError(
630 errc::invalid_argument,
631 "%s encountered when existing rule for this register is not "
632 "a constant",
633 CFIP.callFrameString(Inst.Opcode).str().c_str());
635 } else {
636 Row.getRegisterLocations().setRegisterLocation(
637 AArch64DWARFPAuthRaState, UnwindLocation::createIsConstant(1));
639 break;
642 case Triple::sparc:
643 case Triple::sparcv9:
644 case Triple::sparcel:
645 for (uint32_t RegNum = 16; RegNum < 32; ++RegNum) {
646 Row.getRegisterLocations().setRegisterLocation(
647 RegNum, UnwindLocation::createAtCFAPlusOffset((RegNum - 16) * 8));
649 break;
651 default: {
652 return createStringError(
653 errc::not_supported,
654 "DW_CFA opcode %#x is not supported for architecture %s",
655 Inst.Opcode, Triple::getArchTypeName(CFIP.triple()).str().c_str());
657 break;
660 break;
662 case dwarf::DW_CFA_undefined: {
663 llvm::Expected<uint64_t> RegNum = Inst.getOperandAsUnsigned(CFIP, 0);
664 if (!RegNum)
665 return RegNum.takeError();
666 Row.getRegisterLocations().setRegisterLocation(
667 *RegNum, UnwindLocation::createUndefined());
668 break;
671 case dwarf::DW_CFA_same_value: {
672 llvm::Expected<uint64_t> RegNum = Inst.getOperandAsUnsigned(CFIP, 0);
673 if (!RegNum)
674 return RegNum.takeError();
675 Row.getRegisterLocations().setRegisterLocation(
676 *RegNum, UnwindLocation::createSame());
677 break;
680 case dwarf::DW_CFA_GNU_args_size:
681 break;
683 case dwarf::DW_CFA_register: {
684 llvm::Expected<uint64_t> RegNum = Inst.getOperandAsUnsigned(CFIP, 0);
685 if (!RegNum)
686 return RegNum.takeError();
687 llvm::Expected<uint64_t> NewRegNum = Inst.getOperandAsUnsigned(CFIP, 1);
688 if (!NewRegNum)
689 return NewRegNum.takeError();
690 Row.getRegisterLocations().setRegisterLocation(
691 *RegNum, UnwindLocation::createIsRegisterPlusOffset(*NewRegNum, 0));
692 break;
695 case dwarf::DW_CFA_val_offset:
696 case dwarf::DW_CFA_val_offset_sf: {
697 llvm::Expected<uint64_t> RegNum = Inst.getOperandAsUnsigned(CFIP, 0);
698 if (!RegNum)
699 return RegNum.takeError();
700 llvm::Expected<int64_t> Offset = Inst.getOperandAsSigned(CFIP, 1);
701 if (!Offset)
702 return Offset.takeError();
703 Row.getRegisterLocations().setRegisterLocation(
704 *RegNum, UnwindLocation::createIsCFAPlusOffset(*Offset));
705 break;
708 case dwarf::DW_CFA_expression: {
709 llvm::Expected<uint64_t> RegNum = Inst.getOperandAsUnsigned(CFIP, 0);
710 if (!RegNum)
711 return RegNum.takeError();
712 Row.getRegisterLocations().setRegisterLocation(
713 *RegNum, UnwindLocation::createAtDWARFExpression(*Inst.Expression));
714 break;
717 case dwarf::DW_CFA_val_expression: {
718 llvm::Expected<uint64_t> RegNum = Inst.getOperandAsUnsigned(CFIP, 0);
719 if (!RegNum)
720 return RegNum.takeError();
721 Row.getRegisterLocations().setRegisterLocation(
722 *RegNum, UnwindLocation::createIsDWARFExpression(*Inst.Expression));
723 break;
726 case dwarf::DW_CFA_def_cfa_register: {
727 llvm::Expected<uint64_t> RegNum = Inst.getOperandAsUnsigned(CFIP, 0);
728 if (!RegNum)
729 return RegNum.takeError();
730 if (Row.getCFAValue().getLocation() != UnwindLocation::RegPlusOffset)
731 Row.getCFAValue() =
732 UnwindLocation::createIsRegisterPlusOffset(*RegNum, 0);
733 else
734 Row.getCFAValue().setRegister(*RegNum);
735 break;
738 case dwarf::DW_CFA_def_cfa_offset:
739 case dwarf::DW_CFA_def_cfa_offset_sf: {
740 llvm::Expected<int64_t> Offset = Inst.getOperandAsSigned(CFIP, 0);
741 if (!Offset)
742 return Offset.takeError();
743 if (Row.getCFAValue().getLocation() != UnwindLocation::RegPlusOffset) {
744 return createStringError(
745 errc::invalid_argument,
746 "%s found when CFA rule was not RegPlusOffset",
747 CFIP.callFrameString(Inst.Opcode).str().c_str());
749 Row.getCFAValue().setOffset(*Offset);
750 break;
753 case dwarf::DW_CFA_def_cfa:
754 case dwarf::DW_CFA_def_cfa_sf: {
755 llvm::Expected<uint64_t> RegNum = Inst.getOperandAsUnsigned(CFIP, 0);
756 if (!RegNum)
757 return RegNum.takeError();
758 llvm::Expected<int64_t> Offset = Inst.getOperandAsSigned(CFIP, 1);
759 if (!Offset)
760 return Offset.takeError();
761 Row.getCFAValue() =
762 UnwindLocation::createIsRegisterPlusOffset(*RegNum, *Offset);
763 break;
766 case dwarf::DW_CFA_LLVM_def_aspace_cfa:
767 case dwarf::DW_CFA_LLVM_def_aspace_cfa_sf: {
768 llvm::Expected<uint64_t> RegNum = Inst.getOperandAsUnsigned(CFIP, 0);
769 if (!RegNum)
770 return RegNum.takeError();
771 llvm::Expected<int64_t> Offset = Inst.getOperandAsSigned(CFIP, 1);
772 if (!Offset)
773 return Offset.takeError();
774 llvm::Expected<uint32_t> CFAAddrSpace =
775 Inst.getOperandAsUnsigned(CFIP, 2);
776 if (!CFAAddrSpace)
777 return CFAAddrSpace.takeError();
778 Row.getCFAValue() = UnwindLocation::createIsRegisterPlusOffset(
779 *RegNum, *Offset, *CFAAddrSpace);
780 break;
783 case dwarf::DW_CFA_def_cfa_expression:
784 Row.getCFAValue() =
785 UnwindLocation::createIsDWARFExpression(*Inst.Expression);
786 break;
789 return Error::success();
792 ArrayRef<CFIProgram::OperandType[CFIProgram::MaxOperands]>
793 CFIProgram::getOperandTypes() {
794 static OperandType OpTypes[DW_CFA_restore + 1][MaxOperands];
795 static bool Initialized = false;
796 if (Initialized) {
797 return ArrayRef<OperandType[MaxOperands]>(&OpTypes[0], DW_CFA_restore + 1);
799 Initialized = true;
801 #define DECLARE_OP3(OP, OPTYPE0, OPTYPE1, OPTYPE2) \
802 do { \
803 OpTypes[OP][0] = OPTYPE0; \
804 OpTypes[OP][1] = OPTYPE1; \
805 OpTypes[OP][2] = OPTYPE2; \
806 } while (false)
807 #define DECLARE_OP2(OP, OPTYPE0, OPTYPE1) \
808 DECLARE_OP3(OP, OPTYPE0, OPTYPE1, OT_None)
809 #define DECLARE_OP1(OP, OPTYPE0) DECLARE_OP2(OP, OPTYPE0, OT_None)
810 #define DECLARE_OP0(OP) DECLARE_OP1(OP, OT_None)
812 DECLARE_OP1(DW_CFA_set_loc, OT_Address);
813 DECLARE_OP1(DW_CFA_advance_loc, OT_FactoredCodeOffset);
814 DECLARE_OP1(DW_CFA_advance_loc1, OT_FactoredCodeOffset);
815 DECLARE_OP1(DW_CFA_advance_loc2, OT_FactoredCodeOffset);
816 DECLARE_OP1(DW_CFA_advance_loc4, OT_FactoredCodeOffset);
817 DECLARE_OP1(DW_CFA_MIPS_advance_loc8, OT_FactoredCodeOffset);
818 DECLARE_OP2(DW_CFA_def_cfa, OT_Register, OT_Offset);
819 DECLARE_OP2(DW_CFA_def_cfa_sf, OT_Register, OT_SignedFactDataOffset);
820 DECLARE_OP1(DW_CFA_def_cfa_register, OT_Register);
821 DECLARE_OP3(DW_CFA_LLVM_def_aspace_cfa, OT_Register, OT_Offset,
822 OT_AddressSpace);
823 DECLARE_OP3(DW_CFA_LLVM_def_aspace_cfa_sf, OT_Register,
824 OT_SignedFactDataOffset, OT_AddressSpace);
825 DECLARE_OP1(DW_CFA_def_cfa_offset, OT_Offset);
826 DECLARE_OP1(DW_CFA_def_cfa_offset_sf, OT_SignedFactDataOffset);
827 DECLARE_OP1(DW_CFA_def_cfa_expression, OT_Expression);
828 DECLARE_OP1(DW_CFA_undefined, OT_Register);
829 DECLARE_OP1(DW_CFA_same_value, OT_Register);
830 DECLARE_OP2(DW_CFA_offset, OT_Register, OT_UnsignedFactDataOffset);
831 DECLARE_OP2(DW_CFA_offset_extended, OT_Register, OT_UnsignedFactDataOffset);
832 DECLARE_OP2(DW_CFA_offset_extended_sf, OT_Register, OT_SignedFactDataOffset);
833 DECLARE_OP2(DW_CFA_val_offset, OT_Register, OT_UnsignedFactDataOffset);
834 DECLARE_OP2(DW_CFA_val_offset_sf, OT_Register, OT_SignedFactDataOffset);
835 DECLARE_OP2(DW_CFA_register, OT_Register, OT_Register);
836 DECLARE_OP2(DW_CFA_expression, OT_Register, OT_Expression);
837 DECLARE_OP2(DW_CFA_val_expression, OT_Register, OT_Expression);
838 DECLARE_OP1(DW_CFA_restore, OT_Register);
839 DECLARE_OP1(DW_CFA_restore_extended, OT_Register);
840 DECLARE_OP0(DW_CFA_remember_state);
841 DECLARE_OP0(DW_CFA_restore_state);
842 DECLARE_OP0(DW_CFA_GNU_window_save);
843 DECLARE_OP1(DW_CFA_GNU_args_size, OT_Offset);
844 DECLARE_OP0(DW_CFA_nop);
846 #undef DECLARE_OP0
847 #undef DECLARE_OP1
848 #undef DECLARE_OP2
850 return ArrayRef<OperandType[MaxOperands]>(&OpTypes[0], DW_CFA_restore + 1);
853 /// Print \p Opcode's operand number \p OperandIdx which has value \p Operand.
854 void CFIProgram::printOperand(raw_ostream &OS, DIDumpOptions DumpOpts,
855 const MCRegisterInfo *MRI, bool IsEH,
856 const Instruction &Instr, unsigned OperandIdx,
857 uint64_t Operand) const {
858 assert(OperandIdx < MaxOperands);
859 uint8_t Opcode = Instr.Opcode;
860 OperandType Type = getOperandTypes()[Opcode][OperandIdx];
862 switch (Type) {
863 case OT_Unset: {
864 OS << " Unsupported " << (OperandIdx ? "second" : "first") << " operand to";
865 auto OpcodeName = callFrameString(Opcode);
866 if (!OpcodeName.empty())
867 OS << " " << OpcodeName;
868 else
869 OS << format(" Opcode %x", Opcode);
870 break;
872 case OT_None:
873 break;
874 case OT_Address:
875 OS << format(" %" PRIx64, Operand);
876 break;
877 case OT_Offset:
878 // The offsets are all encoded in a unsigned form, but in practice
879 // consumers use them signed. It's most certainly legacy due to
880 // the lack of signed variants in the first Dwarf standards.
881 OS << format(" %+" PRId64, int64_t(Operand));
882 break;
883 case OT_FactoredCodeOffset: // Always Unsigned
884 if (CodeAlignmentFactor)
885 OS << format(" %" PRId64, Operand * CodeAlignmentFactor);
886 else
887 OS << format(" %" PRId64 "*code_alignment_factor" , Operand);
888 break;
889 case OT_SignedFactDataOffset:
890 if (DataAlignmentFactor)
891 OS << format(" %" PRId64, int64_t(Operand) * DataAlignmentFactor);
892 else
893 OS << format(" %" PRId64 "*data_alignment_factor" , int64_t(Operand));
894 break;
895 case OT_UnsignedFactDataOffset:
896 if (DataAlignmentFactor)
897 OS << format(" %" PRId64, Operand * DataAlignmentFactor);
898 else
899 OS << format(" %" PRId64 "*data_alignment_factor" , Operand);
900 break;
901 case OT_Register:
902 OS << ' ';
903 printRegister(OS, MRI, IsEH, Operand);
904 break;
905 case OT_AddressSpace:
906 OS << format(" in addrspace%" PRId64, Operand);
907 break;
908 case OT_Expression:
909 assert(Instr.Expression && "missing DWARFExpression object");
910 OS << " ";
911 Instr.Expression->print(OS, DumpOpts, MRI, nullptr, IsEH);
912 break;
916 void CFIProgram::dump(raw_ostream &OS, DIDumpOptions DumpOpts,
917 const MCRegisterInfo *MRI, bool IsEH,
918 unsigned IndentLevel) const {
919 for (const auto &Instr : Instructions) {
920 uint8_t Opcode = Instr.Opcode;
921 OS.indent(2 * IndentLevel);
922 OS << callFrameString(Opcode) << ":";
923 for (unsigned i = 0; i < Instr.Ops.size(); ++i)
924 printOperand(OS, DumpOpts, MRI, IsEH, Instr, i, Instr.Ops[i]);
925 OS << '\n';
929 // Returns the CIE identifier to be used by the requested format.
930 // CIE ids for .debug_frame sections are defined in Section 7.24 of DWARFv5.
931 // For CIE ID in .eh_frame sections see
932 // https://refspecs.linuxfoundation.org/LSB_5.0.0/LSB-Core-generic/LSB-Core-generic/ehframechpt.html
933 constexpr uint64_t getCIEId(bool IsDWARF64, bool IsEH) {
934 if (IsEH)
935 return 0;
936 if (IsDWARF64)
937 return DW64_CIE_ID;
938 return DW_CIE_ID;
941 void CIE::dump(raw_ostream &OS, DIDumpOptions DumpOpts,
942 const MCRegisterInfo *MRI, bool IsEH) const {
943 // A CIE with a zero length is a terminator entry in the .eh_frame section.
944 if (IsEH && Length == 0) {
945 OS << format("%08" PRIx64, Offset) << " ZERO terminator\n";
946 return;
949 OS << format("%08" PRIx64, Offset)
950 << format(" %0*" PRIx64, IsDWARF64 ? 16 : 8, Length)
951 << format(" %0*" PRIx64, IsDWARF64 && !IsEH ? 16 : 8,
952 getCIEId(IsDWARF64, IsEH))
953 << " CIE\n"
954 << " Format: " << FormatString(IsDWARF64) << "\n";
955 if (IsEH && Version != 1)
956 OS << "WARNING: unsupported CIE version\n";
957 OS << format(" Version: %d\n", Version)
958 << " Augmentation: \"" << Augmentation << "\"\n";
959 if (Version >= 4) {
960 OS << format(" Address size: %u\n", (uint32_t)AddressSize);
961 OS << format(" Segment desc size: %u\n",
962 (uint32_t)SegmentDescriptorSize);
964 OS << format(" Code alignment factor: %u\n", (uint32_t)CodeAlignmentFactor);
965 OS << format(" Data alignment factor: %d\n", (int32_t)DataAlignmentFactor);
966 OS << format(" Return address column: %d\n", (int32_t)ReturnAddressRegister);
967 if (Personality)
968 OS << format(" Personality Address: %016" PRIx64 "\n", *Personality);
969 if (!AugmentationData.empty()) {
970 OS << " Augmentation data: ";
971 for (uint8_t Byte : AugmentationData)
972 OS << ' ' << hexdigit(Byte >> 4) << hexdigit(Byte & 0xf);
973 OS << "\n";
975 OS << "\n";
976 CFIs.dump(OS, DumpOpts, MRI, IsEH);
977 OS << "\n";
979 if (Expected<UnwindTable> RowsOrErr = UnwindTable::create(this))
980 RowsOrErr->dump(OS, MRI, IsEH, 1);
981 else {
982 DumpOpts.RecoverableErrorHandler(joinErrors(
983 createStringError(errc::invalid_argument,
984 "decoding the CIE opcodes into rows failed"),
985 RowsOrErr.takeError()));
987 OS << "\n";
990 void FDE::dump(raw_ostream &OS, DIDumpOptions DumpOpts,
991 const MCRegisterInfo *MRI, bool IsEH) const {
992 OS << format("%08" PRIx64, Offset)
993 << format(" %0*" PRIx64, IsDWARF64 ? 16 : 8, Length)
994 << format(" %0*" PRIx64, IsDWARF64 && !IsEH ? 16 : 8, CIEPointer)
995 << " FDE cie=";
996 if (LinkedCIE)
997 OS << format("%08" PRIx64, LinkedCIE->getOffset());
998 else
999 OS << "<invalid offset>";
1000 OS << format(" pc=%08" PRIx64 "...%08" PRIx64 "\n", InitialLocation,
1001 InitialLocation + AddressRange);
1002 OS << " Format: " << FormatString(IsDWARF64) << "\n";
1003 if (LSDAAddress)
1004 OS << format(" LSDA Address: %016" PRIx64 "\n", *LSDAAddress);
1005 CFIs.dump(OS, DumpOpts, MRI, IsEH);
1006 OS << "\n";
1008 if (Expected<UnwindTable> RowsOrErr = UnwindTable::create(this))
1009 RowsOrErr->dump(OS, MRI, IsEH, 1);
1010 else {
1011 DumpOpts.RecoverableErrorHandler(joinErrors(
1012 createStringError(errc::invalid_argument,
1013 "decoding the FDE opcodes into rows failed"),
1014 RowsOrErr.takeError()));
1016 OS << "\n";
1019 DWARFDebugFrame::DWARFDebugFrame(Triple::ArchType Arch,
1020 bool IsEH, uint64_t EHFrameAddress)
1021 : Arch(Arch), IsEH(IsEH), EHFrameAddress(EHFrameAddress) {}
1023 DWARFDebugFrame::~DWARFDebugFrame() = default;
1025 static void LLVM_ATTRIBUTE_UNUSED dumpDataAux(DataExtractor Data,
1026 uint64_t Offset, int Length) {
1027 errs() << "DUMP: ";
1028 for (int i = 0; i < Length; ++i) {
1029 uint8_t c = Data.getU8(&Offset);
1030 errs().write_hex(c); errs() << " ";
1032 errs() << "\n";
1035 Error DWARFDebugFrame::parse(DWARFDataExtractor Data) {
1036 uint64_t Offset = 0;
1037 DenseMap<uint64_t, CIE *> CIEs;
1039 while (Data.isValidOffset(Offset)) {
1040 uint64_t StartOffset = Offset;
1042 uint64_t Length;
1043 DwarfFormat Format;
1044 std::tie(Length, Format) = Data.getInitialLength(&Offset);
1045 bool IsDWARF64 = Format == DWARF64;
1047 // If the Length is 0, then this CIE is a terminator. We add it because some
1048 // dumper tools might need it to print something special for such entries
1049 // (e.g. llvm-objdump --dwarf=frames prints "ZERO terminator").
1050 if (Length == 0) {
1051 auto Cie = std::make_unique<CIE>(
1052 IsDWARF64, StartOffset, 0, 0, SmallString<8>(), 0, 0, 0, 0, 0,
1053 SmallString<8>(), 0, 0, None, None, Arch);
1054 CIEs[StartOffset] = Cie.get();
1055 Entries.push_back(std::move(Cie));
1056 break;
1059 // At this point, Offset points to the next field after Length.
1060 // Length is the structure size excluding itself. Compute an offset one
1061 // past the end of the structure (needed to know how many instructions to
1062 // read).
1063 uint64_t StartStructureOffset = Offset;
1064 uint64_t EndStructureOffset = Offset + Length;
1066 // The Id field's size depends on the DWARF format
1067 Error Err = Error::success();
1068 uint64_t Id = Data.getRelocatedValue((IsDWARF64 && !IsEH) ? 8 : 4, &Offset,
1069 /*SectionIndex=*/nullptr, &Err);
1070 if (Err)
1071 return Err;
1073 if (Id == getCIEId(IsDWARF64, IsEH)) {
1074 uint8_t Version = Data.getU8(&Offset);
1075 const char *Augmentation = Data.getCStr(&Offset);
1076 StringRef AugmentationString(Augmentation ? Augmentation : "");
1077 uint8_t AddressSize = Version < 4 ? Data.getAddressSize() :
1078 Data.getU8(&Offset);
1079 Data.setAddressSize(AddressSize);
1080 uint8_t SegmentDescriptorSize = Version < 4 ? 0 : Data.getU8(&Offset);
1081 uint64_t CodeAlignmentFactor = Data.getULEB128(&Offset);
1082 int64_t DataAlignmentFactor = Data.getSLEB128(&Offset);
1083 uint64_t ReturnAddressRegister =
1084 Version == 1 ? Data.getU8(&Offset) : Data.getULEB128(&Offset);
1086 // Parse the augmentation data for EH CIEs
1087 StringRef AugmentationData("");
1088 uint32_t FDEPointerEncoding = DW_EH_PE_absptr;
1089 uint32_t LSDAPointerEncoding = DW_EH_PE_omit;
1090 Optional<uint64_t> Personality;
1091 Optional<uint32_t> PersonalityEncoding;
1092 if (IsEH) {
1093 Optional<uint64_t> AugmentationLength;
1094 uint64_t StartAugmentationOffset;
1095 uint64_t EndAugmentationOffset;
1097 // Walk the augmentation string to get all the augmentation data.
1098 for (unsigned i = 0, e = AugmentationString.size(); i != e; ++i) {
1099 switch (AugmentationString[i]) {
1100 default:
1101 return createStringError(
1102 errc::invalid_argument,
1103 "unknown augmentation character in entry at 0x%" PRIx64,
1104 StartOffset);
1105 case 'L':
1106 LSDAPointerEncoding = Data.getU8(&Offset);
1107 break;
1108 case 'P': {
1109 if (Personality)
1110 return createStringError(
1111 errc::invalid_argument,
1112 "duplicate personality in entry at 0x%" PRIx64, StartOffset);
1113 PersonalityEncoding = Data.getU8(&Offset);
1114 Personality = Data.getEncodedPointer(
1115 &Offset, *PersonalityEncoding,
1116 EHFrameAddress ? EHFrameAddress + Offset : 0);
1117 break;
1119 case 'R':
1120 FDEPointerEncoding = Data.getU8(&Offset);
1121 break;
1122 case 'S':
1123 // Current frame is a signal trampoline.
1124 break;
1125 case 'z':
1126 if (i)
1127 return createStringError(
1128 errc::invalid_argument,
1129 "'z' must be the first character at 0x%" PRIx64, StartOffset);
1130 // Parse the augmentation length first. We only parse it if
1131 // the string contains a 'z'.
1132 AugmentationLength = Data.getULEB128(&Offset);
1133 StartAugmentationOffset = Offset;
1134 EndAugmentationOffset = Offset + *AugmentationLength;
1135 break;
1136 case 'B':
1137 // B-Key is used for signing functions associated with this
1138 // augmentation string
1139 break;
1143 if (AugmentationLength.hasValue()) {
1144 if (Offset != EndAugmentationOffset)
1145 return createStringError(errc::invalid_argument,
1146 "parsing augmentation data at 0x%" PRIx64
1147 " failed",
1148 StartOffset);
1149 AugmentationData = Data.getData().slice(StartAugmentationOffset,
1150 EndAugmentationOffset);
1154 auto Cie = std::make_unique<CIE>(
1155 IsDWARF64, StartOffset, Length, Version, AugmentationString,
1156 AddressSize, SegmentDescriptorSize, CodeAlignmentFactor,
1157 DataAlignmentFactor, ReturnAddressRegister, AugmentationData,
1158 FDEPointerEncoding, LSDAPointerEncoding, Personality,
1159 PersonalityEncoding, Arch);
1160 CIEs[StartOffset] = Cie.get();
1161 Entries.emplace_back(std::move(Cie));
1162 } else {
1163 // FDE
1164 uint64_t CIEPointer = Id;
1165 uint64_t InitialLocation = 0;
1166 uint64_t AddressRange = 0;
1167 Optional<uint64_t> LSDAAddress;
1168 CIE *Cie = CIEs[IsEH ? (StartStructureOffset - CIEPointer) : CIEPointer];
1170 if (IsEH) {
1171 // The address size is encoded in the CIE we reference.
1172 if (!Cie)
1173 return createStringError(errc::invalid_argument,
1174 "parsing FDE data at 0x%" PRIx64
1175 " failed due to missing CIE",
1176 StartOffset);
1177 if (auto Val =
1178 Data.getEncodedPointer(&Offset, Cie->getFDEPointerEncoding(),
1179 EHFrameAddress + Offset)) {
1180 InitialLocation = *Val;
1182 if (auto Val = Data.getEncodedPointer(
1183 &Offset, Cie->getFDEPointerEncoding(), 0)) {
1184 AddressRange = *Val;
1187 StringRef AugmentationString = Cie->getAugmentationString();
1188 if (!AugmentationString.empty()) {
1189 // Parse the augmentation length and data for this FDE.
1190 uint64_t AugmentationLength = Data.getULEB128(&Offset);
1192 uint64_t EndAugmentationOffset = Offset + AugmentationLength;
1194 // Decode the LSDA if the CIE augmentation string said we should.
1195 if (Cie->getLSDAPointerEncoding() != DW_EH_PE_omit) {
1196 LSDAAddress = Data.getEncodedPointer(
1197 &Offset, Cie->getLSDAPointerEncoding(),
1198 EHFrameAddress ? Offset + EHFrameAddress : 0);
1201 if (Offset != EndAugmentationOffset)
1202 return createStringError(errc::invalid_argument,
1203 "parsing augmentation data at 0x%" PRIx64
1204 " failed",
1205 StartOffset);
1207 } else {
1208 InitialLocation = Data.getRelocatedAddress(&Offset);
1209 AddressRange = Data.getRelocatedAddress(&Offset);
1212 Entries.emplace_back(new FDE(IsDWARF64, StartOffset, Length, CIEPointer,
1213 InitialLocation, AddressRange, Cie,
1214 LSDAAddress, Arch));
1217 if (Error E =
1218 Entries.back()->cfis().parse(Data, &Offset, EndStructureOffset))
1219 return E;
1221 if (Offset != EndStructureOffset)
1222 return createStringError(
1223 errc::invalid_argument,
1224 "parsing entry instructions at 0x%" PRIx64 " failed", StartOffset);
1227 return Error::success();
1230 FrameEntry *DWARFDebugFrame::getEntryAtOffset(uint64_t Offset) const {
1231 auto It = partition_point(Entries, [=](const std::unique_ptr<FrameEntry> &E) {
1232 return E->getOffset() < Offset;
1234 if (It != Entries.end() && (*It)->getOffset() == Offset)
1235 return It->get();
1236 return nullptr;
1239 void DWARFDebugFrame::dump(raw_ostream &OS, DIDumpOptions DumpOpts,
1240 const MCRegisterInfo *MRI,
1241 Optional<uint64_t> Offset) const {
1242 if (Offset) {
1243 if (auto *Entry = getEntryAtOffset(*Offset))
1244 Entry->dump(OS, DumpOpts, MRI, IsEH);
1245 return;
1248 OS << "\n";
1249 for (const auto &Entry : Entries)
1250 Entry->dump(OS, DumpOpts, MRI, IsEH);