1 //===- DWARFDebugFrame.h - Parsing of .debug_frame ------------------------===//
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
7 //===----------------------------------------------------------------------===//
9 #include "llvm/DebugInfo/DWARF/DWARFDebugFrame.h"
10 #include "llvm/ADT/DenseMap.h"
11 #include "llvm/ADT/StringExtras.h"
12 #include "llvm/ADT/StringRef.h"
13 #include "llvm/BinaryFormat/Dwarf.h"
14 #include "llvm/DebugInfo/DIContext.h"
15 #include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h"
16 #include "llvm/Support/Compiler.h"
17 #include "llvm/Support/DataExtractor.h"
18 #include "llvm/Support/Errc.h"
19 #include "llvm/Support/ErrorHandling.h"
20 #include "llvm/Support/Format.h"
21 #include "llvm/Support/raw_ostream.h"
28 using namespace dwarf
;
30 static void printRegister(raw_ostream
&OS
, DIDumpOptions DumpOpts
,
32 if (DumpOpts
.GetNameForDWARFReg
) {
33 auto RegName
= DumpOpts
.GetNameForDWARFReg(RegNum
, DumpOpts
.IsEH
);
34 if (!RegName
.empty()) {
39 OS
<< "reg" << RegNum
;
42 UnwindLocation
UnwindLocation::createUnspecified() { return {Unspecified
}; }
44 UnwindLocation
UnwindLocation::createUndefined() { return {Undefined
}; }
46 UnwindLocation
UnwindLocation::createSame() { return {Same
}; }
48 UnwindLocation
UnwindLocation::createIsConstant(int32_t Value
) {
49 return {Constant
, InvalidRegisterNumber
, Value
, std::nullopt
, false};
52 UnwindLocation
UnwindLocation::createIsCFAPlusOffset(int32_t Offset
) {
53 return {CFAPlusOffset
, InvalidRegisterNumber
, Offset
, std::nullopt
, false};
56 UnwindLocation
UnwindLocation::createAtCFAPlusOffset(int32_t Offset
) {
57 return {CFAPlusOffset
, InvalidRegisterNumber
, Offset
, std::nullopt
, true};
61 UnwindLocation::createIsRegisterPlusOffset(uint32_t RegNum
, int32_t Offset
,
62 std::optional
<uint32_t> AddrSpace
) {
63 return {RegPlusOffset
, RegNum
, Offset
, AddrSpace
, false};
67 UnwindLocation::createAtRegisterPlusOffset(uint32_t RegNum
, int32_t Offset
,
68 std::optional
<uint32_t> AddrSpace
) {
69 return {RegPlusOffset
, RegNum
, Offset
, AddrSpace
, true};
72 UnwindLocation
UnwindLocation::createIsDWARFExpression(DWARFExpression Expr
) {
76 UnwindLocation
UnwindLocation::createAtDWARFExpression(DWARFExpression Expr
) {
80 void UnwindLocation::dump(raw_ostream
&OS
, DIDumpOptions DumpOpts
) const {
102 printRegister(OS
, DumpOpts
, RegNum
);
103 if (Offset
== 0 && !AddrSpace
)
109 OS
<< " in addrspace" << *AddrSpace
;
112 Expr
->print(OS
, DumpOpts
, nullptr);
123 raw_ostream
&llvm::dwarf::operator<<(raw_ostream
&OS
,
124 const UnwindLocation
&UL
) {
125 auto DumpOpts
= DIDumpOptions();
126 UL
.dump(OS
, DumpOpts
);
130 bool UnwindLocation::operator==(const UnwindLocation
&RHS
) const {
131 if (Kind
!= RHS
.Kind
)
139 return Offset
== RHS
.Offset
&& Dereference
== RHS
.Dereference
;
141 return RegNum
== RHS
.RegNum
&& Offset
== RHS
.Offset
&&
142 Dereference
== RHS
.Dereference
;
144 return *Expr
== *RHS
.Expr
&& Dereference
== RHS
.Dereference
;
146 return Offset
== RHS
.Offset
;
151 void RegisterLocations::dump(raw_ostream
&OS
, DIDumpOptions DumpOpts
) const {
153 for (const auto &RegLocPair
: Locations
) {
158 printRegister(OS
, DumpOpts
, RegLocPair
.first
);
160 RegLocPair
.second
.dump(OS
, DumpOpts
);
164 raw_ostream
&llvm::dwarf::operator<<(raw_ostream
&OS
,
165 const RegisterLocations
&RL
) {
166 auto DumpOpts
= DIDumpOptions();
167 RL
.dump(OS
, DumpOpts
);
171 void UnwindRow::dump(raw_ostream
&OS
, DIDumpOptions DumpOpts
,
172 unsigned IndentLevel
) const {
173 OS
.indent(2 * IndentLevel
);
175 OS
<< format("0x%" PRIx64
": ", *Address
);
177 CFAValue
.dump(OS
, DumpOpts
);
178 if (RegLocs
.hasLocations()) {
180 RegLocs
.dump(OS
, DumpOpts
);
185 raw_ostream
&llvm::dwarf::operator<<(raw_ostream
&OS
, const UnwindRow
&Row
) {
186 auto DumpOpts
= DIDumpOptions();
187 Row
.dump(OS
, DumpOpts
, 0);
191 void UnwindTable::dump(raw_ostream
&OS
, DIDumpOptions DumpOpts
,
192 unsigned IndentLevel
) const {
193 for (const UnwindRow
&Row
: Rows
)
194 Row
.dump(OS
, DumpOpts
, IndentLevel
);
197 raw_ostream
&llvm::dwarf::operator<<(raw_ostream
&OS
, const UnwindTable
&Rows
) {
198 auto DumpOpts
= DIDumpOptions();
199 Rows
.dump(OS
, DumpOpts
, 0);
203 Expected
<UnwindTable
> UnwindTable::create(const FDE
*Fde
) {
204 const CIE
*Cie
= Fde
->getLinkedCIE();
206 return createStringError(errc::invalid_argument
,
207 "unable to get CIE for FDE at offset 0x%" PRIx64
,
210 // Rows will be empty if there are no CFI instructions.
211 if (Cie
->cfis().empty() && Fde
->cfis().empty())
212 return UnwindTable();
216 Row
.setAddress(Fde
->getInitialLocation());
217 UT
.EndAddress
= Fde
->getInitialLocation() + Fde
->getAddressRange();
218 if (Error CieError
= UT
.parseRows(Cie
->cfis(), Row
, nullptr))
219 return std::move(CieError
);
220 // We need to save the initial locations of registers from the CIE parsing
221 // in case we run into DW_CFA_restore or DW_CFA_restore_extended opcodes.
222 const RegisterLocations InitialLocs
= Row
.getRegisterLocations();
223 if (Error FdeError
= UT
.parseRows(Fde
->cfis(), Row
, &InitialLocs
))
224 return std::move(FdeError
);
225 // May be all the CFI instructions were DW_CFA_nop amd Row becomes empty.
226 // Do not add that to the unwind table.
227 if (Row
.getRegisterLocations().hasLocations() ||
228 Row
.getCFAValue().getLocation() != UnwindLocation::Unspecified
)
229 UT
.Rows
.push_back(Row
);
233 Expected
<UnwindTable
> UnwindTable::create(const CIE
*Cie
) {
234 // Rows will be empty if there are no CFI instructions.
235 if (Cie
->cfis().empty())
236 return UnwindTable();
240 if (Error CieError
= UT
.parseRows(Cie
->cfis(), Row
, nullptr))
241 return std::move(CieError
);
242 // May be all the CFI instructions were DW_CFA_nop amd Row becomes empty.
243 // Do not add that to the unwind table.
244 if (Row
.getRegisterLocations().hasLocations() ||
245 Row
.getCFAValue().getLocation() != UnwindLocation::Unspecified
)
246 UT
.Rows
.push_back(Row
);
250 // See DWARF standard v3, section 7.23
251 const uint8_t DWARF_CFI_PRIMARY_OPCODE_MASK
= 0xc0;
252 const uint8_t DWARF_CFI_PRIMARY_OPERAND_MASK
= 0x3f;
254 Error
CFIProgram::parse(DWARFDataExtractor Data
, uint64_t *Offset
,
255 uint64_t EndOffset
) {
256 DataExtractor::Cursor
C(*Offset
);
257 while (C
&& C
.tell() < EndOffset
) {
258 uint8_t Opcode
= Data
.getRelocatedValue(C
, 1);
262 // Some instructions have a primary opcode encoded in the top bits.
263 if (uint8_t Primary
= Opcode
& DWARF_CFI_PRIMARY_OPCODE_MASK
) {
264 // If it's a primary opcode, the first operand is encoded in the bottom
265 // bits of the opcode itself.
266 uint64_t Op1
= Opcode
& DWARF_CFI_PRIMARY_OPERAND_MASK
;
268 case DW_CFA_advance_loc
:
270 addInstruction(Primary
, Op1
);
273 addInstruction(Primary
, Op1
, Data
.getULEB128(C
));
276 llvm_unreachable("invalid primary CFI opcode");
281 // Extended opcode - its value is Opcode itself.
284 return createStringError(errc::illegal_byte_sequence
,
285 "invalid extended CFI opcode 0x%" PRIx8
, Opcode
);
287 case DW_CFA_remember_state
:
288 case DW_CFA_restore_state
:
289 case DW_CFA_GNU_window_save
:
290 case DW_CFA_AARCH64_negate_ra_state_with_pc
:
292 addInstruction(Opcode
);
296 addInstruction(Opcode
, Data
.getRelocatedAddress(C
));
298 case DW_CFA_advance_loc1
:
299 // Operands: 1-byte delta
300 addInstruction(Opcode
, Data
.getRelocatedValue(C
, 1));
302 case DW_CFA_advance_loc2
:
303 // Operands: 2-byte delta
304 addInstruction(Opcode
, Data
.getRelocatedValue(C
, 2));
306 case DW_CFA_advance_loc4
:
307 // Operands: 4-byte delta
308 addInstruction(Opcode
, Data
.getRelocatedValue(C
, 4));
310 case DW_CFA_restore_extended
:
311 case DW_CFA_undefined
:
312 case DW_CFA_same_value
:
313 case DW_CFA_def_cfa_register
:
314 case DW_CFA_def_cfa_offset
:
315 case DW_CFA_GNU_args_size
:
317 addInstruction(Opcode
, Data
.getULEB128(C
));
319 case DW_CFA_def_cfa_offset_sf
:
321 addInstruction(Opcode
, Data
.getSLEB128(C
));
323 case DW_CFA_LLVM_def_aspace_cfa
:
324 case DW_CFA_LLVM_def_aspace_cfa_sf
: {
325 auto RegNum
= Data
.getULEB128(C
);
326 auto CfaOffset
= Opcode
== DW_CFA_LLVM_def_aspace_cfa
328 : Data
.getSLEB128(C
);
329 auto AddressSpace
= Data
.getULEB128(C
);
330 addInstruction(Opcode
, RegNum
, CfaOffset
, AddressSpace
);
333 case DW_CFA_offset_extended
:
334 case DW_CFA_register
:
336 case DW_CFA_val_offset
: {
337 // Operands: ULEB128, ULEB128
338 // Note: We can not embed getULEB128 directly into function
339 // argument list. getULEB128 changes Offset and order of evaluation
340 // for arguments is unspecified.
341 uint64_t op1
= Data
.getULEB128(C
);
342 uint64_t op2
= Data
.getULEB128(C
);
343 addInstruction(Opcode
, op1
, op2
);
346 case DW_CFA_offset_extended_sf
:
347 case DW_CFA_def_cfa_sf
:
348 case DW_CFA_val_offset_sf
: {
349 // Operands: ULEB128, SLEB128
350 // Note: see comment for the previous case
351 uint64_t op1
= Data
.getULEB128(C
);
352 uint64_t op2
= (uint64_t)Data
.getSLEB128(C
);
353 addInstruction(Opcode
, op1
, op2
);
356 case DW_CFA_def_cfa_expression
: {
357 uint64_t ExprLength
= Data
.getULEB128(C
);
358 addInstruction(Opcode
, 0);
359 StringRef Expression
= Data
.getBytes(C
, ExprLength
);
361 DataExtractor
Extractor(Expression
, Data
.isLittleEndian(),
362 Data
.getAddressSize());
363 // Note. We do not pass the DWARF format to DWARFExpression, because
364 // DW_OP_call_ref, the only operation which depends on the format, is
365 // prohibited in call frame instructions, see sec. 6.4.2 in DWARFv5.
366 Instructions
.back().Expression
=
367 DWARFExpression(Extractor
, Data
.getAddressSize());
370 case DW_CFA_expression
:
371 case DW_CFA_val_expression
: {
372 uint64_t RegNum
= Data
.getULEB128(C
);
373 addInstruction(Opcode
, RegNum
, 0);
375 uint64_t BlockLength
= Data
.getULEB128(C
);
376 StringRef Expression
= Data
.getBytes(C
, BlockLength
);
377 DataExtractor
Extractor(Expression
, Data
.isLittleEndian(),
378 Data
.getAddressSize());
379 // Note. We do not pass the DWARF format to DWARFExpression, because
380 // DW_OP_call_ref, the only operation which depends on the format, is
381 // prohibited in call frame instructions, see sec. 6.4.2 in DWARFv5.
382 Instructions
.back().Expression
=
383 DWARFExpression(Extractor
, Data
.getAddressSize());
390 return C
.takeError();
393 StringRef
CFIProgram::callFrameString(unsigned Opcode
) const {
394 return dwarf::CallFrameString(Opcode
, Arch
);
397 const char *CFIProgram::operandTypeString(CFIProgram::OperandType OT
) {
398 #define ENUM_TO_CSTR(e) \
402 ENUM_TO_CSTR(OT_Unset
);
403 ENUM_TO_CSTR(OT_None
);
404 ENUM_TO_CSTR(OT_Address
);
405 ENUM_TO_CSTR(OT_Offset
);
406 ENUM_TO_CSTR(OT_FactoredCodeOffset
);
407 ENUM_TO_CSTR(OT_SignedFactDataOffset
);
408 ENUM_TO_CSTR(OT_UnsignedFactDataOffset
);
409 ENUM_TO_CSTR(OT_Register
);
410 ENUM_TO_CSTR(OT_AddressSpace
);
411 ENUM_TO_CSTR(OT_Expression
);
413 return "<unknown CFIProgram::OperandType>";
416 llvm::Expected
<uint64_t>
417 CFIProgram::Instruction::getOperandAsUnsigned(const CFIProgram
&CFIP
,
418 uint32_t OperandIdx
) const {
419 if (OperandIdx
>= MaxOperands
)
420 return createStringError(errc::invalid_argument
,
421 "operand index %" PRIu32
" is not valid",
423 OperandType Type
= CFIP
.getOperandTypes()[Opcode
][OperandIdx
];
424 uint64_t Operand
= Ops
[OperandIdx
];
429 return createStringError(errc::invalid_argument
,
430 "op[%" PRIu32
"] has type %s which has no value",
431 OperandIdx
, CFIProgram::operandTypeString(Type
));
434 case OT_SignedFactDataOffset
:
435 case OT_UnsignedFactDataOffset
:
436 return createStringError(
437 errc::invalid_argument
,
438 "op[%" PRIu32
"] has OperandType OT_Offset which produces a signed "
439 "result, call getOperandAsSigned instead",
444 case OT_AddressSpace
:
447 case OT_FactoredCodeOffset
: {
448 const uint64_t CodeAlignmentFactor
= CFIP
.codeAlign();
449 if (CodeAlignmentFactor
== 0)
450 return createStringError(
451 errc::invalid_argument
,
452 "op[%" PRIu32
"] has type OT_FactoredCodeOffset but code alignment "
455 return Operand
* CodeAlignmentFactor
;
458 llvm_unreachable("invalid operand type");
461 llvm::Expected
<int64_t>
462 CFIProgram::Instruction::getOperandAsSigned(const CFIProgram
&CFIP
,
463 uint32_t OperandIdx
) const {
464 if (OperandIdx
>= MaxOperands
)
465 return createStringError(errc::invalid_argument
,
466 "operand index %" PRIu32
" is not valid",
468 OperandType Type
= CFIP
.getOperandTypes()[Opcode
][OperandIdx
];
469 uint64_t Operand
= Ops
[OperandIdx
];
474 return createStringError(errc::invalid_argument
,
475 "op[%" PRIu32
"] has type %s which has no value",
476 OperandIdx
, CFIProgram::operandTypeString(Type
));
480 case OT_AddressSpace
:
481 return createStringError(
482 errc::invalid_argument
,
483 "op[%" PRIu32
"] has OperandType %s which produces an unsigned result, "
484 "call getOperandAsUnsigned instead",
485 OperandIdx
, CFIProgram::operandTypeString(Type
));
488 return (int64_t)Operand
;
490 case OT_FactoredCodeOffset
:
491 case OT_SignedFactDataOffset
: {
492 const int64_t DataAlignmentFactor
= CFIP
.dataAlign();
493 if (DataAlignmentFactor
== 0)
494 return createStringError(errc::invalid_argument
,
495 "op[%" PRIu32
"] has type %s but data "
497 OperandIdx
, CFIProgram::operandTypeString(Type
));
498 return int64_t(Operand
) * DataAlignmentFactor
;
501 case OT_UnsignedFactDataOffset
: {
502 const int64_t DataAlignmentFactor
= CFIP
.dataAlign();
503 if (DataAlignmentFactor
== 0)
504 return createStringError(errc::invalid_argument
,
506 "] has type OT_UnsignedFactDataOffset but data "
509 return Operand
* DataAlignmentFactor
;
512 llvm_unreachable("invalid operand type");
515 Error
UnwindTable::parseRows(const CFIProgram
&CFIP
, UnwindRow
&Row
,
516 const RegisterLocations
*InitialLocs
) {
517 // State consists of CFA value and register locations.
518 std::vector
<std::pair
<UnwindLocation
, RegisterLocations
>> States
;
519 for (const CFIProgram::Instruction
&Inst
: CFIP
) {
520 switch (Inst
.Opcode
) {
521 case dwarf::DW_CFA_set_loc
: {
522 // The DW_CFA_set_loc instruction takes a single operand that
523 // represents a target address. The required action is to create a new
524 // table row using the specified address as the location. All other
525 // values in the new row are initially identical to the current row.
526 // The new location value is always greater than the current one. If
527 // the segment_size field of this FDE's CIE is non- zero, the initial
528 // location is preceded by a segment selector of the given length
529 llvm::Expected
<uint64_t> NewAddress
= Inst
.getOperandAsUnsigned(CFIP
, 0);
531 return NewAddress
.takeError();
532 if (*NewAddress
<= Row
.getAddress())
533 return createStringError(
534 errc::invalid_argument
,
535 "%s with adrress 0x%" PRIx64
" which must be greater than the "
536 "current row address 0x%" PRIx64
,
537 CFIP
.callFrameString(Inst
.Opcode
).str().c_str(), *NewAddress
,
540 Row
.setAddress(*NewAddress
);
544 case dwarf::DW_CFA_advance_loc
:
545 case dwarf::DW_CFA_advance_loc1
:
546 case dwarf::DW_CFA_advance_loc2
:
547 case dwarf::DW_CFA_advance_loc4
: {
548 // The DW_CFA_advance instruction takes a single operand that
549 // represents a constant delta. The required action is to create a new
550 // table row with a location value that is computed by taking the
551 // current entry’s location value and adding the value of delta *
552 // code_alignment_factor. All other values in the new row are initially
553 // identical to the current row.
555 llvm::Expected
<uint64_t> Offset
= Inst
.getOperandAsUnsigned(CFIP
, 0);
557 return Offset
.takeError();
558 Row
.slideAddress(*Offset
);
562 case dwarf::DW_CFA_restore
:
563 case dwarf::DW_CFA_restore_extended
: {
564 // The DW_CFA_restore instruction takes a single operand (encoded with
565 // the opcode) that represents a register number. The required action
566 // is to change the rule for the indicated register to the rule
567 // assigned it by the initial_instructions in the CIE.
568 if (InitialLocs
== nullptr)
569 return createStringError(
570 errc::invalid_argument
, "%s encountered while parsing a CIE",
571 CFIP
.callFrameString(Inst
.Opcode
).str().c_str());
572 llvm::Expected
<uint64_t> RegNum
= Inst
.getOperandAsUnsigned(CFIP
, 0);
574 return RegNum
.takeError();
575 if (std::optional
<UnwindLocation
> O
=
576 InitialLocs
->getRegisterLocation(*RegNum
))
577 Row
.getRegisterLocations().setRegisterLocation(*RegNum
, *O
);
579 Row
.getRegisterLocations().removeRegisterLocation(*RegNum
);
583 case dwarf::DW_CFA_offset
:
584 case dwarf::DW_CFA_offset_extended
:
585 case dwarf::DW_CFA_offset_extended_sf
: {
586 llvm::Expected
<uint64_t> RegNum
= Inst
.getOperandAsUnsigned(CFIP
, 0);
588 return RegNum
.takeError();
589 llvm::Expected
<int64_t> Offset
= Inst
.getOperandAsSigned(CFIP
, 1);
591 return Offset
.takeError();
592 Row
.getRegisterLocations().setRegisterLocation(
593 *RegNum
, UnwindLocation::createAtCFAPlusOffset(*Offset
));
597 case dwarf::DW_CFA_nop
:
600 case dwarf::DW_CFA_remember_state
:
602 std::make_pair(Row
.getCFAValue(), Row
.getRegisterLocations()));
605 case dwarf::DW_CFA_restore_state
:
607 return createStringError(errc::invalid_argument
,
608 "DW_CFA_restore_state without a matching "
609 "previous DW_CFA_remember_state");
610 Row
.getCFAValue() = States
.back().first
;
611 Row
.getRegisterLocations() = States
.back().second
;
615 case dwarf::DW_CFA_GNU_window_save
:
616 switch (CFIP
.triple()) {
617 case Triple::aarch64
:
618 case Triple::aarch64_be
:
619 case Triple::aarch64_32
: {
620 // DW_CFA_GNU_window_save is used for different things on different
621 // architectures. For aarch64 it is known as
622 // DW_CFA_AARCH64_negate_ra_state. The action is to toggle the
623 // value of the return address state between 1 and 0. If there is
624 // no rule for the AARCH64_DWARF_PAUTH_RA_STATE register, then it
625 // should be initially set to 1.
626 constexpr uint32_t AArch64DWARFPAuthRaState
= 34;
627 auto LRLoc
= Row
.getRegisterLocations().getRegisterLocation(
628 AArch64DWARFPAuthRaState
);
630 if (LRLoc
->getLocation() == UnwindLocation::Constant
) {
631 // Toggle the constant value from 0 to 1 or 1 to 0.
632 LRLoc
->setConstant(LRLoc
->getConstant() ^ 1);
633 Row
.getRegisterLocations().setRegisterLocation(
634 AArch64DWARFPAuthRaState
, *LRLoc
);
636 return createStringError(
637 errc::invalid_argument
,
638 "%s encountered when existing rule for this register is not "
640 CFIP
.callFrameString(Inst
.Opcode
).str().c_str());
643 Row
.getRegisterLocations().setRegisterLocation(
644 AArch64DWARFPAuthRaState
, UnwindLocation::createIsConstant(1));
650 case Triple::sparcv9
:
651 case Triple::sparcel
:
652 for (uint32_t RegNum
= 16; RegNum
< 32; ++RegNum
) {
653 Row
.getRegisterLocations().setRegisterLocation(
654 RegNum
, UnwindLocation::createAtCFAPlusOffset((RegNum
- 16) * 8));
659 return createStringError(
661 "DW_CFA opcode %#x is not supported for architecture %s",
662 Inst
.Opcode
, Triple::getArchTypeName(CFIP
.triple()).str().c_str());
669 case dwarf::DW_CFA_AARCH64_negate_ra_state_with_pc
: {
670 constexpr uint32_t AArch64DWARFPAuthRaState
= 34;
671 auto LRLoc
= Row
.getRegisterLocations().getRegisterLocation(
672 AArch64DWARFPAuthRaState
);
674 if (LRLoc
->getLocation() == UnwindLocation::Constant
) {
675 // Toggle the constant value of bits[1:0] from 0 to 1 or 1 to 0.
676 LRLoc
->setConstant(LRLoc
->getConstant() ^ 0x3);
678 return createStringError(
679 errc::invalid_argument
,
680 "%s encountered when existing rule for this register is not "
682 CFIP
.callFrameString(Inst
.Opcode
).str().c_str());
685 Row
.getRegisterLocations().setRegisterLocation(
686 AArch64DWARFPAuthRaState
, UnwindLocation::createIsConstant(0x3));
691 case dwarf::DW_CFA_undefined
: {
692 llvm::Expected
<uint64_t> RegNum
= Inst
.getOperandAsUnsigned(CFIP
, 0);
694 return RegNum
.takeError();
695 Row
.getRegisterLocations().setRegisterLocation(
696 *RegNum
, UnwindLocation::createUndefined());
700 case dwarf::DW_CFA_same_value
: {
701 llvm::Expected
<uint64_t> RegNum
= Inst
.getOperandAsUnsigned(CFIP
, 0);
703 return RegNum
.takeError();
704 Row
.getRegisterLocations().setRegisterLocation(
705 *RegNum
, UnwindLocation::createSame());
709 case dwarf::DW_CFA_GNU_args_size
:
712 case dwarf::DW_CFA_register
: {
713 llvm::Expected
<uint64_t> RegNum
= Inst
.getOperandAsUnsigned(CFIP
, 0);
715 return RegNum
.takeError();
716 llvm::Expected
<uint64_t> NewRegNum
= Inst
.getOperandAsUnsigned(CFIP
, 1);
718 return NewRegNum
.takeError();
719 Row
.getRegisterLocations().setRegisterLocation(
720 *RegNum
, UnwindLocation::createIsRegisterPlusOffset(*NewRegNum
, 0));
724 case dwarf::DW_CFA_val_offset
:
725 case dwarf::DW_CFA_val_offset_sf
: {
726 llvm::Expected
<uint64_t> RegNum
= Inst
.getOperandAsUnsigned(CFIP
, 0);
728 return RegNum
.takeError();
729 llvm::Expected
<int64_t> Offset
= Inst
.getOperandAsSigned(CFIP
, 1);
731 return Offset
.takeError();
732 Row
.getRegisterLocations().setRegisterLocation(
733 *RegNum
, UnwindLocation::createIsCFAPlusOffset(*Offset
));
737 case dwarf::DW_CFA_expression
: {
738 llvm::Expected
<uint64_t> RegNum
= Inst
.getOperandAsUnsigned(CFIP
, 0);
740 return RegNum
.takeError();
741 Row
.getRegisterLocations().setRegisterLocation(
742 *RegNum
, UnwindLocation::createAtDWARFExpression(*Inst
.Expression
));
746 case dwarf::DW_CFA_val_expression
: {
747 llvm::Expected
<uint64_t> RegNum
= Inst
.getOperandAsUnsigned(CFIP
, 0);
749 return RegNum
.takeError();
750 Row
.getRegisterLocations().setRegisterLocation(
751 *RegNum
, UnwindLocation::createIsDWARFExpression(*Inst
.Expression
));
755 case dwarf::DW_CFA_def_cfa_register
: {
756 llvm::Expected
<uint64_t> RegNum
= Inst
.getOperandAsUnsigned(CFIP
, 0);
758 return RegNum
.takeError();
759 if (Row
.getCFAValue().getLocation() != UnwindLocation::RegPlusOffset
)
761 UnwindLocation::createIsRegisterPlusOffset(*RegNum
, 0);
763 Row
.getCFAValue().setRegister(*RegNum
);
767 case dwarf::DW_CFA_def_cfa_offset
:
768 case dwarf::DW_CFA_def_cfa_offset_sf
: {
769 llvm::Expected
<int64_t> Offset
= Inst
.getOperandAsSigned(CFIP
, 0);
771 return Offset
.takeError();
772 if (Row
.getCFAValue().getLocation() != UnwindLocation::RegPlusOffset
) {
773 return createStringError(
774 errc::invalid_argument
,
775 "%s found when CFA rule was not RegPlusOffset",
776 CFIP
.callFrameString(Inst
.Opcode
).str().c_str());
778 Row
.getCFAValue().setOffset(*Offset
);
782 case dwarf::DW_CFA_def_cfa
:
783 case dwarf::DW_CFA_def_cfa_sf
: {
784 llvm::Expected
<uint64_t> RegNum
= Inst
.getOperandAsUnsigned(CFIP
, 0);
786 return RegNum
.takeError();
787 llvm::Expected
<int64_t> Offset
= Inst
.getOperandAsSigned(CFIP
, 1);
789 return Offset
.takeError();
791 UnwindLocation::createIsRegisterPlusOffset(*RegNum
, *Offset
);
795 case dwarf::DW_CFA_LLVM_def_aspace_cfa
:
796 case dwarf::DW_CFA_LLVM_def_aspace_cfa_sf
: {
797 llvm::Expected
<uint64_t> RegNum
= Inst
.getOperandAsUnsigned(CFIP
, 0);
799 return RegNum
.takeError();
800 llvm::Expected
<int64_t> Offset
= Inst
.getOperandAsSigned(CFIP
, 1);
802 return Offset
.takeError();
803 llvm::Expected
<uint32_t> CFAAddrSpace
=
804 Inst
.getOperandAsUnsigned(CFIP
, 2);
806 return CFAAddrSpace
.takeError();
807 Row
.getCFAValue() = UnwindLocation::createIsRegisterPlusOffset(
808 *RegNum
, *Offset
, *CFAAddrSpace
);
812 case dwarf::DW_CFA_def_cfa_expression
:
814 UnwindLocation::createIsDWARFExpression(*Inst
.Expression
);
818 return Error::success();
821 ArrayRef
<CFIProgram::OperandType
[CFIProgram::MaxOperands
]>
822 CFIProgram::getOperandTypes() {
823 static OperandType OpTypes
[DW_CFA_restore
+ 1][MaxOperands
];
824 static bool Initialized
= false;
826 return ArrayRef
<OperandType
[MaxOperands
]>(&OpTypes
[0], DW_CFA_restore
+ 1);
830 #define DECLARE_OP3(OP, OPTYPE0, OPTYPE1, OPTYPE2) \
832 OpTypes[OP][0] = OPTYPE0; \
833 OpTypes[OP][1] = OPTYPE1; \
834 OpTypes[OP][2] = OPTYPE2; \
836 #define DECLARE_OP2(OP, OPTYPE0, OPTYPE1) \
837 DECLARE_OP3(OP, OPTYPE0, OPTYPE1, OT_None)
838 #define DECLARE_OP1(OP, OPTYPE0) DECLARE_OP2(OP, OPTYPE0, OT_None)
839 #define DECLARE_OP0(OP) DECLARE_OP1(OP, OT_None)
841 DECLARE_OP1(DW_CFA_set_loc
, OT_Address
);
842 DECLARE_OP1(DW_CFA_advance_loc
, OT_FactoredCodeOffset
);
843 DECLARE_OP1(DW_CFA_advance_loc1
, OT_FactoredCodeOffset
);
844 DECLARE_OP1(DW_CFA_advance_loc2
, OT_FactoredCodeOffset
);
845 DECLARE_OP1(DW_CFA_advance_loc4
, OT_FactoredCodeOffset
);
846 DECLARE_OP1(DW_CFA_MIPS_advance_loc8
, OT_FactoredCodeOffset
);
847 DECLARE_OP2(DW_CFA_def_cfa
, OT_Register
, OT_Offset
);
848 DECLARE_OP2(DW_CFA_def_cfa_sf
, OT_Register
, OT_SignedFactDataOffset
);
849 DECLARE_OP1(DW_CFA_def_cfa_register
, OT_Register
);
850 DECLARE_OP3(DW_CFA_LLVM_def_aspace_cfa
, OT_Register
, OT_Offset
,
852 DECLARE_OP3(DW_CFA_LLVM_def_aspace_cfa_sf
, OT_Register
,
853 OT_SignedFactDataOffset
, OT_AddressSpace
);
854 DECLARE_OP1(DW_CFA_def_cfa_offset
, OT_Offset
);
855 DECLARE_OP1(DW_CFA_def_cfa_offset_sf
, OT_SignedFactDataOffset
);
856 DECLARE_OP1(DW_CFA_def_cfa_expression
, OT_Expression
);
857 DECLARE_OP1(DW_CFA_undefined
, OT_Register
);
858 DECLARE_OP1(DW_CFA_same_value
, OT_Register
);
859 DECLARE_OP2(DW_CFA_offset
, OT_Register
, OT_UnsignedFactDataOffset
);
860 DECLARE_OP2(DW_CFA_offset_extended
, OT_Register
, OT_UnsignedFactDataOffset
);
861 DECLARE_OP2(DW_CFA_offset_extended_sf
, OT_Register
, OT_SignedFactDataOffset
);
862 DECLARE_OP2(DW_CFA_val_offset
, OT_Register
, OT_UnsignedFactDataOffset
);
863 DECLARE_OP2(DW_CFA_val_offset_sf
, OT_Register
, OT_SignedFactDataOffset
);
864 DECLARE_OP2(DW_CFA_register
, OT_Register
, OT_Register
);
865 DECLARE_OP2(DW_CFA_expression
, OT_Register
, OT_Expression
);
866 DECLARE_OP2(DW_CFA_val_expression
, OT_Register
, OT_Expression
);
867 DECLARE_OP1(DW_CFA_restore
, OT_Register
);
868 DECLARE_OP1(DW_CFA_restore_extended
, OT_Register
);
869 DECLARE_OP0(DW_CFA_remember_state
);
870 DECLARE_OP0(DW_CFA_restore_state
);
871 DECLARE_OP0(DW_CFA_GNU_window_save
);
872 DECLARE_OP0(DW_CFA_AARCH64_negate_ra_state_with_pc
);
873 DECLARE_OP1(DW_CFA_GNU_args_size
, OT_Offset
);
874 DECLARE_OP0(DW_CFA_nop
);
880 return ArrayRef
<OperandType
[MaxOperands
]>(&OpTypes
[0], DW_CFA_restore
+ 1);
883 /// Print \p Opcode's operand number \p OperandIdx which has value \p Operand.
884 void CFIProgram::printOperand(raw_ostream
&OS
, DIDumpOptions DumpOpts
,
885 const Instruction
&Instr
, unsigned OperandIdx
,
887 std::optional
<uint64_t> &Address
) const {
888 assert(OperandIdx
< MaxOperands
);
889 uint8_t Opcode
= Instr
.Opcode
;
890 OperandType Type
= getOperandTypes()[Opcode
][OperandIdx
];
894 OS
<< " Unsupported " << (OperandIdx
? "second" : "first") << " operand to";
895 auto OpcodeName
= callFrameString(Opcode
);
896 if (!OpcodeName
.empty())
897 OS
<< " " << OpcodeName
;
899 OS
<< format(" Opcode %x", Opcode
);
905 OS
<< format(" %" PRIx64
, Operand
);
909 // The offsets are all encoded in a unsigned form, but in practice
910 // consumers use them signed. It's most certainly legacy due to
911 // the lack of signed variants in the first Dwarf standards.
912 OS
<< format(" %+" PRId64
, int64_t(Operand
));
914 case OT_FactoredCodeOffset
: // Always Unsigned
915 if (CodeAlignmentFactor
)
916 OS
<< format(" %" PRId64
, Operand
* CodeAlignmentFactor
);
918 OS
<< format(" %" PRId64
"*code_alignment_factor", Operand
);
919 if (Address
&& CodeAlignmentFactor
) {
920 *Address
+= Operand
* CodeAlignmentFactor
;
921 OS
<< format(" to 0x%" PRIx64
, *Address
);
924 case OT_SignedFactDataOffset
:
925 if (DataAlignmentFactor
)
926 OS
<< format(" %" PRId64
, int64_t(Operand
) * DataAlignmentFactor
);
928 OS
<< format(" %" PRId64
"*data_alignment_factor" , int64_t(Operand
));
930 case OT_UnsignedFactDataOffset
:
931 if (DataAlignmentFactor
)
932 OS
<< format(" %" PRId64
, Operand
* DataAlignmentFactor
);
934 OS
<< format(" %" PRId64
"*data_alignment_factor" , Operand
);
938 printRegister(OS
, DumpOpts
, Operand
);
940 case OT_AddressSpace
:
941 OS
<< format(" in addrspace%" PRId64
, Operand
);
944 assert(Instr
.Expression
&& "missing DWARFExpression object");
946 Instr
.Expression
->print(OS
, DumpOpts
, nullptr);
951 void CFIProgram::dump(raw_ostream
&OS
, DIDumpOptions DumpOpts
,
952 unsigned IndentLevel
,
953 std::optional
<uint64_t> Address
) const {
954 for (const auto &Instr
: Instructions
) {
955 uint8_t Opcode
= Instr
.Opcode
;
956 OS
.indent(2 * IndentLevel
);
957 OS
<< callFrameString(Opcode
) << ":";
958 for (unsigned i
= 0; i
< Instr
.Ops
.size(); ++i
)
959 printOperand(OS
, DumpOpts
, Instr
, i
, Instr
.Ops
[i
], Address
);
964 // Returns the CIE identifier to be used by the requested format.
965 // CIE ids for .debug_frame sections are defined in Section 7.24 of DWARFv5.
966 // For CIE ID in .eh_frame sections see
967 // https://refspecs.linuxfoundation.org/LSB_5.0.0/LSB-Core-generic/LSB-Core-generic/ehframechpt.html
968 constexpr uint64_t getCIEId(bool IsDWARF64
, bool IsEH
) {
976 void CIE::dump(raw_ostream
&OS
, DIDumpOptions DumpOpts
) const {
977 // A CIE with a zero length is a terminator entry in the .eh_frame section.
978 if (DumpOpts
.IsEH
&& Length
== 0) {
979 OS
<< format("%08" PRIx64
, Offset
) << " ZERO terminator\n";
983 OS
<< format("%08" PRIx64
, Offset
)
984 << format(" %0*" PRIx64
, IsDWARF64
? 16 : 8, Length
)
985 << format(" %0*" PRIx64
, IsDWARF64
&& !DumpOpts
.IsEH
? 16 : 8,
986 getCIEId(IsDWARF64
, DumpOpts
.IsEH
))
988 << " Format: " << FormatString(IsDWARF64
) << "\n";
989 if (DumpOpts
.IsEH
&& Version
!= 1)
990 OS
<< "WARNING: unsupported CIE version\n";
991 OS
<< format(" Version: %d\n", Version
)
992 << " Augmentation: \"" << Augmentation
<< "\"\n";
994 OS
<< format(" Address size: %u\n", (uint32_t)AddressSize
);
995 OS
<< format(" Segment desc size: %u\n",
996 (uint32_t)SegmentDescriptorSize
);
998 OS
<< format(" Code alignment factor: %u\n", (uint32_t)CodeAlignmentFactor
);
999 OS
<< format(" Data alignment factor: %d\n", (int32_t)DataAlignmentFactor
);
1000 OS
<< format(" Return address column: %d\n", (int32_t)ReturnAddressRegister
);
1002 OS
<< format(" Personality Address: %016" PRIx64
"\n", *Personality
);
1003 if (!AugmentationData
.empty()) {
1004 OS
<< " Augmentation data: ";
1005 for (uint8_t Byte
: AugmentationData
)
1006 OS
<< ' ' << hexdigit(Byte
>> 4) << hexdigit(Byte
& 0xf);
1010 CFIs
.dump(OS
, DumpOpts
, /*IndentLevel=*/1, /*InitialLocation=*/{});
1013 if (Expected
<UnwindTable
> RowsOrErr
= UnwindTable::create(this))
1014 RowsOrErr
->dump(OS
, DumpOpts
, 1);
1016 DumpOpts
.RecoverableErrorHandler(joinErrors(
1017 createStringError(errc::invalid_argument
,
1018 "decoding the CIE opcodes into rows failed"),
1019 RowsOrErr
.takeError()));
1024 void FDE::dump(raw_ostream
&OS
, DIDumpOptions DumpOpts
) const {
1025 OS
<< format("%08" PRIx64
, Offset
)
1026 << format(" %0*" PRIx64
, IsDWARF64
? 16 : 8, Length
)
1027 << format(" %0*" PRIx64
, IsDWARF64
&& !DumpOpts
.IsEH
? 16 : 8, CIEPointer
)
1030 OS
<< format("%08" PRIx64
, LinkedCIE
->getOffset());
1032 OS
<< "<invalid offset>";
1033 OS
<< format(" pc=%08" PRIx64
"...%08" PRIx64
"\n", InitialLocation
,
1034 InitialLocation
+ AddressRange
);
1035 OS
<< " Format: " << FormatString(IsDWARF64
) << "\n";
1037 OS
<< format(" LSDA Address: %016" PRIx64
"\n", *LSDAAddress
);
1038 CFIs
.dump(OS
, DumpOpts
, /*IndentLevel=*/1, InitialLocation
);
1041 if (Expected
<UnwindTable
> RowsOrErr
= UnwindTable::create(this))
1042 RowsOrErr
->dump(OS
, DumpOpts
, 1);
1044 DumpOpts
.RecoverableErrorHandler(joinErrors(
1045 createStringError(errc::invalid_argument
,
1046 "decoding the FDE opcodes into rows failed"),
1047 RowsOrErr
.takeError()));
1052 DWARFDebugFrame::DWARFDebugFrame(Triple::ArchType Arch
,
1053 bool IsEH
, uint64_t EHFrameAddress
)
1054 : Arch(Arch
), IsEH(IsEH
), EHFrameAddress(EHFrameAddress
) {}
1056 DWARFDebugFrame::~DWARFDebugFrame() = default;
1058 static void LLVM_ATTRIBUTE_UNUSED
dumpDataAux(DataExtractor Data
,
1059 uint64_t Offset
, int Length
) {
1061 for (int i
= 0; i
< Length
; ++i
) {
1062 uint8_t c
= Data
.getU8(&Offset
);
1063 errs().write_hex(c
); errs() << " ";
1068 Error
DWARFDebugFrame::parse(DWARFDataExtractor Data
) {
1069 uint64_t Offset
= 0;
1070 DenseMap
<uint64_t, CIE
*> CIEs
;
1072 while (Data
.isValidOffset(Offset
)) {
1073 uint64_t StartOffset
= Offset
;
1077 std::tie(Length
, Format
) = Data
.getInitialLength(&Offset
);
1078 bool IsDWARF64
= Format
== DWARF64
;
1080 // If the Length is 0, then this CIE is a terminator. We add it because some
1081 // dumper tools might need it to print something special for such entries
1082 // (e.g. llvm-objdump --dwarf=frames prints "ZERO terminator").
1084 auto Cie
= std::make_unique
<CIE
>(
1085 IsDWARF64
, StartOffset
, 0, 0, SmallString
<8>(), 0, 0, 0, 0, 0,
1086 SmallString
<8>(), 0, 0, std::nullopt
, std::nullopt
, Arch
);
1087 CIEs
[StartOffset
] = Cie
.get();
1088 Entries
.push_back(std::move(Cie
));
1092 // At this point, Offset points to the next field after Length.
1093 // Length is the structure size excluding itself. Compute an offset one
1094 // past the end of the structure (needed to know how many instructions to
1096 uint64_t StartStructureOffset
= Offset
;
1097 uint64_t EndStructureOffset
= Offset
+ Length
;
1099 // The Id field's size depends on the DWARF format
1100 Error Err
= Error::success();
1101 uint64_t Id
= Data
.getRelocatedValue((IsDWARF64
&& !IsEH
) ? 8 : 4, &Offset
,
1102 /*SectionIndex=*/nullptr, &Err
);
1106 if (Id
== getCIEId(IsDWARF64
, IsEH
)) {
1107 uint8_t Version
= Data
.getU8(&Offset
);
1108 const char *Augmentation
= Data
.getCStr(&Offset
);
1109 StringRef
AugmentationString(Augmentation
? Augmentation
: "");
1110 uint8_t AddressSize
= Version
< 4 ? Data
.getAddressSize() :
1111 Data
.getU8(&Offset
);
1112 Data
.setAddressSize(AddressSize
);
1113 uint8_t SegmentDescriptorSize
= Version
< 4 ? 0 : Data
.getU8(&Offset
);
1114 uint64_t CodeAlignmentFactor
= Data
.getULEB128(&Offset
);
1115 int64_t DataAlignmentFactor
= Data
.getSLEB128(&Offset
);
1116 uint64_t ReturnAddressRegister
=
1117 Version
== 1 ? Data
.getU8(&Offset
) : Data
.getULEB128(&Offset
);
1119 // Parse the augmentation data for EH CIEs
1120 StringRef
AugmentationData("");
1121 uint32_t FDEPointerEncoding
= DW_EH_PE_absptr
;
1122 uint32_t LSDAPointerEncoding
= DW_EH_PE_omit
;
1123 std::optional
<uint64_t> Personality
;
1124 std::optional
<uint32_t> PersonalityEncoding
;
1126 std::optional
<uint64_t> AugmentationLength
;
1127 uint64_t StartAugmentationOffset
;
1128 uint64_t EndAugmentationOffset
;
1130 // Walk the augmentation string to get all the augmentation data.
1131 for (unsigned i
= 0, e
= AugmentationString
.size(); i
!= e
; ++i
) {
1132 switch (AugmentationString
[i
]) {
1134 return createStringError(
1135 errc::invalid_argument
,
1136 "unknown augmentation character %c in entry at 0x%" PRIx64
,
1137 AugmentationString
[i
], StartOffset
);
1139 LSDAPointerEncoding
= Data
.getU8(&Offset
);
1143 return createStringError(
1144 errc::invalid_argument
,
1145 "duplicate personality in entry at 0x%" PRIx64
, StartOffset
);
1146 PersonalityEncoding
= Data
.getU8(&Offset
);
1147 Personality
= Data
.getEncodedPointer(
1148 &Offset
, *PersonalityEncoding
,
1149 EHFrameAddress
? EHFrameAddress
+ Offset
: 0);
1153 FDEPointerEncoding
= Data
.getU8(&Offset
);
1156 // Current frame is a signal trampoline.
1160 return createStringError(
1161 errc::invalid_argument
,
1162 "'z' must be the first character at 0x%" PRIx64
, StartOffset
);
1163 // Parse the augmentation length first. We only parse it if
1164 // the string contains a 'z'.
1165 AugmentationLength
= Data
.getULEB128(&Offset
);
1166 StartAugmentationOffset
= Offset
;
1167 EndAugmentationOffset
= Offset
+ *AugmentationLength
;
1170 // B-Key is used for signing functions associated with this
1171 // augmentation string
1173 // This stack frame contains MTE tagged data, so needs to be
1174 // untagged on unwind.
1180 if (AugmentationLength
) {
1181 if (Offset
!= EndAugmentationOffset
)
1182 return createStringError(errc::invalid_argument
,
1183 "parsing augmentation data at 0x%" PRIx64
1186 AugmentationData
= Data
.getData().slice(StartAugmentationOffset
,
1187 EndAugmentationOffset
);
1191 auto Cie
= std::make_unique
<CIE
>(
1192 IsDWARF64
, StartOffset
, Length
, Version
, AugmentationString
,
1193 AddressSize
, SegmentDescriptorSize
, CodeAlignmentFactor
,
1194 DataAlignmentFactor
, ReturnAddressRegister
, AugmentationData
,
1195 FDEPointerEncoding
, LSDAPointerEncoding
, Personality
,
1196 PersonalityEncoding
, Arch
);
1197 CIEs
[StartOffset
] = Cie
.get();
1198 Entries
.emplace_back(std::move(Cie
));
1201 uint64_t CIEPointer
= Id
;
1202 uint64_t InitialLocation
= 0;
1203 uint64_t AddressRange
= 0;
1204 std::optional
<uint64_t> LSDAAddress
;
1205 CIE
*Cie
= CIEs
[IsEH
? (StartStructureOffset
- CIEPointer
) : CIEPointer
];
1208 // The address size is encoded in the CIE we reference.
1210 return createStringError(errc::invalid_argument
,
1211 "parsing FDE data at 0x%" PRIx64
1212 " failed due to missing CIE",
1215 Data
.getEncodedPointer(&Offset
, Cie
->getFDEPointerEncoding(),
1216 EHFrameAddress
+ Offset
)) {
1217 InitialLocation
= *Val
;
1219 if (auto Val
= Data
.getEncodedPointer(
1220 &Offset
, Cie
->getFDEPointerEncoding(), 0)) {
1221 AddressRange
= *Val
;
1224 StringRef AugmentationString
= Cie
->getAugmentationString();
1225 if (!AugmentationString
.empty()) {
1226 // Parse the augmentation length and data for this FDE.
1227 uint64_t AugmentationLength
= Data
.getULEB128(&Offset
);
1229 uint64_t EndAugmentationOffset
= Offset
+ AugmentationLength
;
1231 // Decode the LSDA if the CIE augmentation string said we should.
1232 if (Cie
->getLSDAPointerEncoding() != DW_EH_PE_omit
) {
1233 LSDAAddress
= Data
.getEncodedPointer(
1234 &Offset
, Cie
->getLSDAPointerEncoding(),
1235 EHFrameAddress
? Offset
+ EHFrameAddress
: 0);
1238 if (Offset
!= EndAugmentationOffset
)
1239 return createStringError(errc::invalid_argument
,
1240 "parsing augmentation data at 0x%" PRIx64
1245 InitialLocation
= Data
.getRelocatedAddress(&Offset
);
1246 AddressRange
= Data
.getRelocatedAddress(&Offset
);
1249 Entries
.emplace_back(new FDE(IsDWARF64
, StartOffset
, Length
, CIEPointer
,
1250 InitialLocation
, AddressRange
, Cie
,
1251 LSDAAddress
, Arch
));
1255 Entries
.back()->cfis().parse(Data
, &Offset
, EndStructureOffset
))
1258 if (Offset
!= EndStructureOffset
)
1259 return createStringError(
1260 errc::invalid_argument
,
1261 "parsing entry instructions at 0x%" PRIx64
" failed", StartOffset
);
1264 return Error::success();
1267 FrameEntry
*DWARFDebugFrame::getEntryAtOffset(uint64_t Offset
) const {
1268 auto It
= partition_point(Entries
, [=](const std::unique_ptr
<FrameEntry
> &E
) {
1269 return E
->getOffset() < Offset
;
1271 if (It
!= Entries
.end() && (*It
)->getOffset() == Offset
)
1276 void DWARFDebugFrame::dump(raw_ostream
&OS
, DIDumpOptions DumpOpts
,
1277 std::optional
<uint64_t> Offset
) const {
1278 DumpOpts
.IsEH
= IsEH
;
1280 if (auto *Entry
= getEntryAtOffset(*Offset
))
1281 Entry
->dump(OS
, DumpOpts
);
1286 for (const auto &Entry
: Entries
)
1287 Entry
->dump(OS
, DumpOpts
);