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"
29 using namespace dwarf
;
31 static void printRegister(raw_ostream
&OS
, DIDumpOptions DumpOpts
,
33 if (DumpOpts
.GetNameForDWARFReg
) {
34 auto RegName
= DumpOpts
.GetNameForDWARFReg(RegNum
, DumpOpts
.IsEH
);
35 if (!RegName
.empty()) {
40 OS
<< "reg" << RegNum
;
43 UnwindLocation
UnwindLocation::createUnspecified() { return {Unspecified
}; }
45 UnwindLocation
UnwindLocation::createUndefined() { return {Undefined
}; }
47 UnwindLocation
UnwindLocation::createSame() { return {Same
}; }
49 UnwindLocation
UnwindLocation::createIsConstant(int32_t Value
) {
50 return {Constant
, InvalidRegisterNumber
, Value
, std::nullopt
, false};
53 UnwindLocation
UnwindLocation::createIsCFAPlusOffset(int32_t Offset
) {
54 return {CFAPlusOffset
, InvalidRegisterNumber
, Offset
, std::nullopt
, false};
57 UnwindLocation
UnwindLocation::createAtCFAPlusOffset(int32_t Offset
) {
58 return {CFAPlusOffset
, InvalidRegisterNumber
, Offset
, std::nullopt
, true};
62 UnwindLocation::createIsRegisterPlusOffset(uint32_t RegNum
, int32_t Offset
,
63 std::optional
<uint32_t> AddrSpace
) {
64 return {RegPlusOffset
, RegNum
, Offset
, AddrSpace
, false};
68 UnwindLocation::createAtRegisterPlusOffset(uint32_t RegNum
, int32_t Offset
,
69 std::optional
<uint32_t> AddrSpace
) {
70 return {RegPlusOffset
, RegNum
, Offset
, AddrSpace
, true};
73 UnwindLocation
UnwindLocation::createIsDWARFExpression(DWARFExpression Expr
) {
77 UnwindLocation
UnwindLocation::createAtDWARFExpression(DWARFExpression Expr
) {
81 void UnwindLocation::dump(raw_ostream
&OS
, DIDumpOptions DumpOpts
) const {
103 printRegister(OS
, DumpOpts
, RegNum
);
104 if (Offset
== 0 && !AddrSpace
)
110 OS
<< " in addrspace" << *AddrSpace
;
113 Expr
->print(OS
, DumpOpts
, nullptr);
124 raw_ostream
&llvm::dwarf::operator<<(raw_ostream
&OS
,
125 const UnwindLocation
&UL
) {
126 auto DumpOpts
= DIDumpOptions();
127 UL
.dump(OS
, DumpOpts
);
131 bool UnwindLocation::operator==(const UnwindLocation
&RHS
) const {
132 if (Kind
!= RHS
.Kind
)
140 return Offset
== RHS
.Offset
&& Dereference
== RHS
.Dereference
;
142 return RegNum
== RHS
.RegNum
&& Offset
== RHS
.Offset
&&
143 Dereference
== RHS
.Dereference
;
145 return *Expr
== *RHS
.Expr
&& Dereference
== RHS
.Dereference
;
147 return Offset
== RHS
.Offset
;
152 void RegisterLocations::dump(raw_ostream
&OS
, DIDumpOptions DumpOpts
) const {
154 for (const auto &RegLocPair
: Locations
) {
159 printRegister(OS
, DumpOpts
, RegLocPair
.first
);
161 RegLocPair
.second
.dump(OS
, DumpOpts
);
165 raw_ostream
&llvm::dwarf::operator<<(raw_ostream
&OS
,
166 const RegisterLocations
&RL
) {
167 auto DumpOpts
= DIDumpOptions();
168 RL
.dump(OS
, DumpOpts
);
172 void UnwindRow::dump(raw_ostream
&OS
, DIDumpOptions DumpOpts
,
173 unsigned IndentLevel
) const {
174 OS
.indent(2 * IndentLevel
);
176 OS
<< format("0x%" PRIx64
": ", *Address
);
178 CFAValue
.dump(OS
, DumpOpts
);
179 if (RegLocs
.hasLocations()) {
181 RegLocs
.dump(OS
, DumpOpts
);
186 raw_ostream
&llvm::dwarf::operator<<(raw_ostream
&OS
, const UnwindRow
&Row
) {
187 auto DumpOpts
= DIDumpOptions();
188 Row
.dump(OS
, DumpOpts
, 0);
192 void UnwindTable::dump(raw_ostream
&OS
, DIDumpOptions DumpOpts
,
193 unsigned IndentLevel
) const {
194 for (const UnwindRow
&Row
: Rows
)
195 Row
.dump(OS
, DumpOpts
, IndentLevel
);
198 raw_ostream
&llvm::dwarf::operator<<(raw_ostream
&OS
, const UnwindTable
&Rows
) {
199 auto DumpOpts
= DIDumpOptions();
200 Rows
.dump(OS
, DumpOpts
, 0);
204 Expected
<UnwindTable
> UnwindTable::create(const FDE
*Fde
) {
205 const CIE
*Cie
= Fde
->getLinkedCIE();
207 return createStringError(errc::invalid_argument
,
208 "unable to get CIE for FDE at offset 0x%" PRIx64
,
211 // Rows will be empty if there are no CFI instructions.
212 if (Cie
->cfis().empty() && Fde
->cfis().empty())
213 return UnwindTable();
217 Row
.setAddress(Fde
->getInitialLocation());
218 UT
.EndAddress
= Fde
->getInitialLocation() + Fde
->getAddressRange();
219 if (Error CieError
= UT
.parseRows(Cie
->cfis(), Row
, nullptr))
220 return std::move(CieError
);
221 // We need to save the initial locations of registers from the CIE parsing
222 // in case we run into DW_CFA_restore or DW_CFA_restore_extended opcodes.
223 const RegisterLocations InitialLocs
= Row
.getRegisterLocations();
224 if (Error FdeError
= UT
.parseRows(Fde
->cfis(), Row
, &InitialLocs
))
225 return std::move(FdeError
);
226 // May be all the CFI instructions were DW_CFA_nop amd Row becomes empty.
227 // Do not add that to the unwind table.
228 if (Row
.getRegisterLocations().hasLocations() ||
229 Row
.getCFAValue().getLocation() != UnwindLocation::Unspecified
)
230 UT
.Rows
.push_back(Row
);
234 Expected
<UnwindTable
> UnwindTable::create(const CIE
*Cie
) {
235 // Rows will be empty if there are no CFI instructions.
236 if (Cie
->cfis().empty())
237 return UnwindTable();
241 if (Error CieError
= UT
.parseRows(Cie
->cfis(), Row
, nullptr))
242 return std::move(CieError
);
243 // May be all the CFI instructions were DW_CFA_nop amd Row becomes empty.
244 // Do not add that to the unwind table.
245 if (Row
.getRegisterLocations().hasLocations() ||
246 Row
.getCFAValue().getLocation() != UnwindLocation::Unspecified
)
247 UT
.Rows
.push_back(Row
);
251 // See DWARF standard v3, section 7.23
252 const uint8_t DWARF_CFI_PRIMARY_OPCODE_MASK
= 0xc0;
253 const uint8_t DWARF_CFI_PRIMARY_OPERAND_MASK
= 0x3f;
255 Error
CFIProgram::parse(DWARFDataExtractor Data
, uint64_t *Offset
,
256 uint64_t EndOffset
) {
257 DataExtractor::Cursor
C(*Offset
);
258 while (C
&& C
.tell() < EndOffset
) {
259 uint8_t Opcode
= Data
.getRelocatedValue(C
, 1);
263 // Some instructions have a primary opcode encoded in the top bits.
264 if (uint8_t Primary
= Opcode
& DWARF_CFI_PRIMARY_OPCODE_MASK
) {
265 // If it's a primary opcode, the first operand is encoded in the bottom
266 // bits of the opcode itself.
267 uint64_t Op1
= Opcode
& DWARF_CFI_PRIMARY_OPERAND_MASK
;
269 case DW_CFA_advance_loc
:
271 addInstruction(Primary
, Op1
);
274 addInstruction(Primary
, Op1
, Data
.getULEB128(C
));
277 llvm_unreachable("invalid primary CFI opcode");
282 // Extended opcode - its value is Opcode itself.
285 return createStringError(errc::illegal_byte_sequence
,
286 "invalid extended CFI opcode 0x%" PRIx8
, Opcode
);
288 case DW_CFA_remember_state
:
289 case DW_CFA_restore_state
:
290 case DW_CFA_GNU_window_save
:
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);
634 return createStringError(
635 errc::invalid_argument
,
636 "%s encountered when existing rule for this register is not "
638 CFIP
.callFrameString(Inst
.Opcode
).str().c_str());
641 Row
.getRegisterLocations().setRegisterLocation(
642 AArch64DWARFPAuthRaState
, UnwindLocation::createIsConstant(1));
648 case Triple::sparcv9
:
649 case Triple::sparcel
:
650 for (uint32_t RegNum
= 16; RegNum
< 32; ++RegNum
) {
651 Row
.getRegisterLocations().setRegisterLocation(
652 RegNum
, UnwindLocation::createAtCFAPlusOffset((RegNum
- 16) * 8));
657 return createStringError(
659 "DW_CFA opcode %#x is not supported for architecture %s",
660 Inst
.Opcode
, Triple::getArchTypeName(CFIP
.triple()).str().c_str());
667 case dwarf::DW_CFA_undefined
: {
668 llvm::Expected
<uint64_t> RegNum
= Inst
.getOperandAsUnsigned(CFIP
, 0);
670 return RegNum
.takeError();
671 Row
.getRegisterLocations().setRegisterLocation(
672 *RegNum
, UnwindLocation::createUndefined());
676 case dwarf::DW_CFA_same_value
: {
677 llvm::Expected
<uint64_t> RegNum
= Inst
.getOperandAsUnsigned(CFIP
, 0);
679 return RegNum
.takeError();
680 Row
.getRegisterLocations().setRegisterLocation(
681 *RegNum
, UnwindLocation::createSame());
685 case dwarf::DW_CFA_GNU_args_size
:
688 case dwarf::DW_CFA_register
: {
689 llvm::Expected
<uint64_t> RegNum
= Inst
.getOperandAsUnsigned(CFIP
, 0);
691 return RegNum
.takeError();
692 llvm::Expected
<uint64_t> NewRegNum
= Inst
.getOperandAsUnsigned(CFIP
, 1);
694 return NewRegNum
.takeError();
695 Row
.getRegisterLocations().setRegisterLocation(
696 *RegNum
, UnwindLocation::createIsRegisterPlusOffset(*NewRegNum
, 0));
700 case dwarf::DW_CFA_val_offset
:
701 case dwarf::DW_CFA_val_offset_sf
: {
702 llvm::Expected
<uint64_t> RegNum
= Inst
.getOperandAsUnsigned(CFIP
, 0);
704 return RegNum
.takeError();
705 llvm::Expected
<int64_t> Offset
= Inst
.getOperandAsSigned(CFIP
, 1);
707 return Offset
.takeError();
708 Row
.getRegisterLocations().setRegisterLocation(
709 *RegNum
, UnwindLocation::createIsCFAPlusOffset(*Offset
));
713 case dwarf::DW_CFA_expression
: {
714 llvm::Expected
<uint64_t> RegNum
= Inst
.getOperandAsUnsigned(CFIP
, 0);
716 return RegNum
.takeError();
717 Row
.getRegisterLocations().setRegisterLocation(
718 *RegNum
, UnwindLocation::createAtDWARFExpression(*Inst
.Expression
));
722 case dwarf::DW_CFA_val_expression
: {
723 llvm::Expected
<uint64_t> RegNum
= Inst
.getOperandAsUnsigned(CFIP
, 0);
725 return RegNum
.takeError();
726 Row
.getRegisterLocations().setRegisterLocation(
727 *RegNum
, UnwindLocation::createIsDWARFExpression(*Inst
.Expression
));
731 case dwarf::DW_CFA_def_cfa_register
: {
732 llvm::Expected
<uint64_t> RegNum
= Inst
.getOperandAsUnsigned(CFIP
, 0);
734 return RegNum
.takeError();
735 if (Row
.getCFAValue().getLocation() != UnwindLocation::RegPlusOffset
)
737 UnwindLocation::createIsRegisterPlusOffset(*RegNum
, 0);
739 Row
.getCFAValue().setRegister(*RegNum
);
743 case dwarf::DW_CFA_def_cfa_offset
:
744 case dwarf::DW_CFA_def_cfa_offset_sf
: {
745 llvm::Expected
<int64_t> Offset
= Inst
.getOperandAsSigned(CFIP
, 0);
747 return Offset
.takeError();
748 if (Row
.getCFAValue().getLocation() != UnwindLocation::RegPlusOffset
) {
749 return createStringError(
750 errc::invalid_argument
,
751 "%s found when CFA rule was not RegPlusOffset",
752 CFIP
.callFrameString(Inst
.Opcode
).str().c_str());
754 Row
.getCFAValue().setOffset(*Offset
);
758 case dwarf::DW_CFA_def_cfa
:
759 case dwarf::DW_CFA_def_cfa_sf
: {
760 llvm::Expected
<uint64_t> RegNum
= Inst
.getOperandAsUnsigned(CFIP
, 0);
762 return RegNum
.takeError();
763 llvm::Expected
<int64_t> Offset
= Inst
.getOperandAsSigned(CFIP
, 1);
765 return Offset
.takeError();
767 UnwindLocation::createIsRegisterPlusOffset(*RegNum
, *Offset
);
771 case dwarf::DW_CFA_LLVM_def_aspace_cfa
:
772 case dwarf::DW_CFA_LLVM_def_aspace_cfa_sf
: {
773 llvm::Expected
<uint64_t> RegNum
= Inst
.getOperandAsUnsigned(CFIP
, 0);
775 return RegNum
.takeError();
776 llvm::Expected
<int64_t> Offset
= Inst
.getOperandAsSigned(CFIP
, 1);
778 return Offset
.takeError();
779 llvm::Expected
<uint32_t> CFAAddrSpace
=
780 Inst
.getOperandAsUnsigned(CFIP
, 2);
782 return CFAAddrSpace
.takeError();
783 Row
.getCFAValue() = UnwindLocation::createIsRegisterPlusOffset(
784 *RegNum
, *Offset
, *CFAAddrSpace
);
788 case dwarf::DW_CFA_def_cfa_expression
:
790 UnwindLocation::createIsDWARFExpression(*Inst
.Expression
);
794 return Error::success();
797 ArrayRef
<CFIProgram::OperandType
[CFIProgram::MaxOperands
]>
798 CFIProgram::getOperandTypes() {
799 static OperandType OpTypes
[DW_CFA_restore
+ 1][MaxOperands
];
800 static bool Initialized
= false;
802 return ArrayRef
<OperandType
[MaxOperands
]>(&OpTypes
[0], DW_CFA_restore
+ 1);
806 #define DECLARE_OP3(OP, OPTYPE0, OPTYPE1, OPTYPE2) \
808 OpTypes[OP][0] = OPTYPE0; \
809 OpTypes[OP][1] = OPTYPE1; \
810 OpTypes[OP][2] = OPTYPE2; \
812 #define DECLARE_OP2(OP, OPTYPE0, OPTYPE1) \
813 DECLARE_OP3(OP, OPTYPE0, OPTYPE1, OT_None)
814 #define DECLARE_OP1(OP, OPTYPE0) DECLARE_OP2(OP, OPTYPE0, OT_None)
815 #define DECLARE_OP0(OP) DECLARE_OP1(OP, OT_None)
817 DECLARE_OP1(DW_CFA_set_loc
, OT_Address
);
818 DECLARE_OP1(DW_CFA_advance_loc
, OT_FactoredCodeOffset
);
819 DECLARE_OP1(DW_CFA_advance_loc1
, OT_FactoredCodeOffset
);
820 DECLARE_OP1(DW_CFA_advance_loc2
, OT_FactoredCodeOffset
);
821 DECLARE_OP1(DW_CFA_advance_loc4
, OT_FactoredCodeOffset
);
822 DECLARE_OP1(DW_CFA_MIPS_advance_loc8
, OT_FactoredCodeOffset
);
823 DECLARE_OP2(DW_CFA_def_cfa
, OT_Register
, OT_Offset
);
824 DECLARE_OP2(DW_CFA_def_cfa_sf
, OT_Register
, OT_SignedFactDataOffset
);
825 DECLARE_OP1(DW_CFA_def_cfa_register
, OT_Register
);
826 DECLARE_OP3(DW_CFA_LLVM_def_aspace_cfa
, OT_Register
, OT_Offset
,
828 DECLARE_OP3(DW_CFA_LLVM_def_aspace_cfa_sf
, OT_Register
,
829 OT_SignedFactDataOffset
, OT_AddressSpace
);
830 DECLARE_OP1(DW_CFA_def_cfa_offset
, OT_Offset
);
831 DECLARE_OP1(DW_CFA_def_cfa_offset_sf
, OT_SignedFactDataOffset
);
832 DECLARE_OP1(DW_CFA_def_cfa_expression
, OT_Expression
);
833 DECLARE_OP1(DW_CFA_undefined
, OT_Register
);
834 DECLARE_OP1(DW_CFA_same_value
, OT_Register
);
835 DECLARE_OP2(DW_CFA_offset
, OT_Register
, OT_UnsignedFactDataOffset
);
836 DECLARE_OP2(DW_CFA_offset_extended
, OT_Register
, OT_UnsignedFactDataOffset
);
837 DECLARE_OP2(DW_CFA_offset_extended_sf
, OT_Register
, OT_SignedFactDataOffset
);
838 DECLARE_OP2(DW_CFA_val_offset
, OT_Register
, OT_UnsignedFactDataOffset
);
839 DECLARE_OP2(DW_CFA_val_offset_sf
, OT_Register
, OT_SignedFactDataOffset
);
840 DECLARE_OP2(DW_CFA_register
, OT_Register
, OT_Register
);
841 DECLARE_OP2(DW_CFA_expression
, OT_Register
, OT_Expression
);
842 DECLARE_OP2(DW_CFA_val_expression
, OT_Register
, OT_Expression
);
843 DECLARE_OP1(DW_CFA_restore
, OT_Register
);
844 DECLARE_OP1(DW_CFA_restore_extended
, OT_Register
);
845 DECLARE_OP0(DW_CFA_remember_state
);
846 DECLARE_OP0(DW_CFA_restore_state
);
847 DECLARE_OP0(DW_CFA_GNU_window_save
);
848 DECLARE_OP1(DW_CFA_GNU_args_size
, OT_Offset
);
849 DECLARE_OP0(DW_CFA_nop
);
855 return ArrayRef
<OperandType
[MaxOperands
]>(&OpTypes
[0], DW_CFA_restore
+ 1);
858 /// Print \p Opcode's operand number \p OperandIdx which has value \p Operand.
859 void CFIProgram::printOperand(raw_ostream
&OS
, DIDumpOptions DumpOpts
,
860 const Instruction
&Instr
, unsigned OperandIdx
,
861 uint64_t Operand
) const {
862 assert(OperandIdx
< MaxOperands
);
863 uint8_t Opcode
= Instr
.Opcode
;
864 OperandType Type
= getOperandTypes()[Opcode
][OperandIdx
];
868 OS
<< " Unsupported " << (OperandIdx
? "second" : "first") << " operand to";
869 auto OpcodeName
= callFrameString(Opcode
);
870 if (!OpcodeName
.empty())
871 OS
<< " " << OpcodeName
;
873 OS
<< format(" Opcode %x", Opcode
);
879 OS
<< format(" %" PRIx64
, Operand
);
882 // The offsets are all encoded in a unsigned form, but in practice
883 // consumers use them signed. It's most certainly legacy due to
884 // the lack of signed variants in the first Dwarf standards.
885 OS
<< format(" %+" PRId64
, int64_t(Operand
));
887 case OT_FactoredCodeOffset
: // Always Unsigned
888 if (CodeAlignmentFactor
)
889 OS
<< format(" %" PRId64
, Operand
* CodeAlignmentFactor
);
891 OS
<< format(" %" PRId64
"*code_alignment_factor" , Operand
);
893 case OT_SignedFactDataOffset
:
894 if (DataAlignmentFactor
)
895 OS
<< format(" %" PRId64
, int64_t(Operand
) * DataAlignmentFactor
);
897 OS
<< format(" %" PRId64
"*data_alignment_factor" , int64_t(Operand
));
899 case OT_UnsignedFactDataOffset
:
900 if (DataAlignmentFactor
)
901 OS
<< format(" %" PRId64
, Operand
* DataAlignmentFactor
);
903 OS
<< format(" %" PRId64
"*data_alignment_factor" , Operand
);
907 printRegister(OS
, DumpOpts
, Operand
);
909 case OT_AddressSpace
:
910 OS
<< format(" in addrspace%" PRId64
, Operand
);
913 assert(Instr
.Expression
&& "missing DWARFExpression object");
915 Instr
.Expression
->print(OS
, DumpOpts
, nullptr);
920 void CFIProgram::dump(raw_ostream
&OS
, DIDumpOptions DumpOpts
,
921 unsigned IndentLevel
) const {
922 for (const auto &Instr
: Instructions
) {
923 uint8_t Opcode
= Instr
.Opcode
;
924 OS
.indent(2 * IndentLevel
);
925 OS
<< callFrameString(Opcode
) << ":";
926 for (unsigned i
= 0; i
< Instr
.Ops
.size(); ++i
)
927 printOperand(OS
, DumpOpts
, Instr
, i
, Instr
.Ops
[i
]);
932 // Returns the CIE identifier to be used by the requested format.
933 // CIE ids for .debug_frame sections are defined in Section 7.24 of DWARFv5.
934 // For CIE ID in .eh_frame sections see
935 // https://refspecs.linuxfoundation.org/LSB_5.0.0/LSB-Core-generic/LSB-Core-generic/ehframechpt.html
936 constexpr uint64_t getCIEId(bool IsDWARF64
, bool IsEH
) {
944 void CIE::dump(raw_ostream
&OS
, DIDumpOptions DumpOpts
) const {
945 // A CIE with a zero length is a terminator entry in the .eh_frame section.
946 if (DumpOpts
.IsEH
&& Length
== 0) {
947 OS
<< format("%08" PRIx64
, Offset
) << " ZERO terminator\n";
951 OS
<< format("%08" PRIx64
, Offset
)
952 << format(" %0*" PRIx64
, IsDWARF64
? 16 : 8, Length
)
953 << format(" %0*" PRIx64
, IsDWARF64
&& !DumpOpts
.IsEH
? 16 : 8,
954 getCIEId(IsDWARF64
, DumpOpts
.IsEH
))
956 << " Format: " << FormatString(IsDWARF64
) << "\n";
957 if (DumpOpts
.IsEH
&& Version
!= 1)
958 OS
<< "WARNING: unsupported CIE version\n";
959 OS
<< format(" Version: %d\n", Version
)
960 << " Augmentation: \"" << Augmentation
<< "\"\n";
962 OS
<< format(" Address size: %u\n", (uint32_t)AddressSize
);
963 OS
<< format(" Segment desc size: %u\n",
964 (uint32_t)SegmentDescriptorSize
);
966 OS
<< format(" Code alignment factor: %u\n", (uint32_t)CodeAlignmentFactor
);
967 OS
<< format(" Data alignment factor: %d\n", (int32_t)DataAlignmentFactor
);
968 OS
<< format(" Return address column: %d\n", (int32_t)ReturnAddressRegister
);
970 OS
<< format(" Personality Address: %016" PRIx64
"\n", *Personality
);
971 if (!AugmentationData
.empty()) {
972 OS
<< " Augmentation data: ";
973 for (uint8_t Byte
: AugmentationData
)
974 OS
<< ' ' << hexdigit(Byte
>> 4) << hexdigit(Byte
& 0xf);
978 CFIs
.dump(OS
, DumpOpts
);
981 if (Expected
<UnwindTable
> RowsOrErr
= UnwindTable::create(this))
982 RowsOrErr
->dump(OS
, DumpOpts
, 1);
984 DumpOpts
.RecoverableErrorHandler(joinErrors(
985 createStringError(errc::invalid_argument
,
986 "decoding the CIE opcodes into rows failed"),
987 RowsOrErr
.takeError()));
992 void FDE::dump(raw_ostream
&OS
, DIDumpOptions DumpOpts
) const {
993 OS
<< format("%08" PRIx64
, Offset
)
994 << format(" %0*" PRIx64
, IsDWARF64
? 16 : 8, Length
)
995 << format(" %0*" PRIx64
, IsDWARF64
&& !DumpOpts
.IsEH
? 16 : 8, CIEPointer
)
998 OS
<< format("%08" PRIx64
, LinkedCIE
->getOffset());
1000 OS
<< "<invalid offset>";
1001 OS
<< format(" pc=%08" PRIx64
"...%08" PRIx64
"\n", InitialLocation
,
1002 InitialLocation
+ AddressRange
);
1003 OS
<< " Format: " << FormatString(IsDWARF64
) << "\n";
1005 OS
<< format(" LSDA Address: %016" PRIx64
"\n", *LSDAAddress
);
1006 CFIs
.dump(OS
, DumpOpts
);
1009 if (Expected
<UnwindTable
> RowsOrErr
= UnwindTable::create(this))
1010 RowsOrErr
->dump(OS
, DumpOpts
, 1);
1012 DumpOpts
.RecoverableErrorHandler(joinErrors(
1013 createStringError(errc::invalid_argument
,
1014 "decoding the FDE opcodes into rows failed"),
1015 RowsOrErr
.takeError()));
1020 DWARFDebugFrame::DWARFDebugFrame(Triple::ArchType Arch
,
1021 bool IsEH
, uint64_t EHFrameAddress
)
1022 : Arch(Arch
), IsEH(IsEH
), EHFrameAddress(EHFrameAddress
) {}
1024 DWARFDebugFrame::~DWARFDebugFrame() = default;
1026 static void LLVM_ATTRIBUTE_UNUSED
dumpDataAux(DataExtractor Data
,
1027 uint64_t Offset
, int Length
) {
1029 for (int i
= 0; i
< Length
; ++i
) {
1030 uint8_t c
= Data
.getU8(&Offset
);
1031 errs().write_hex(c
); errs() << " ";
1036 Error
DWARFDebugFrame::parse(DWARFDataExtractor Data
) {
1037 uint64_t Offset
= 0;
1038 DenseMap
<uint64_t, CIE
*> CIEs
;
1040 while (Data
.isValidOffset(Offset
)) {
1041 uint64_t StartOffset
= Offset
;
1045 std::tie(Length
, Format
) = Data
.getInitialLength(&Offset
);
1046 bool IsDWARF64
= Format
== DWARF64
;
1048 // If the Length is 0, then this CIE is a terminator. We add it because some
1049 // dumper tools might need it to print something special for such entries
1050 // (e.g. llvm-objdump --dwarf=frames prints "ZERO terminator").
1052 auto Cie
= std::make_unique
<CIE
>(
1053 IsDWARF64
, StartOffset
, 0, 0, SmallString
<8>(), 0, 0, 0, 0, 0,
1054 SmallString
<8>(), 0, 0, std::nullopt
, std::nullopt
, Arch
);
1055 CIEs
[StartOffset
] = Cie
.get();
1056 Entries
.push_back(std::move(Cie
));
1060 // At this point, Offset points to the next field after Length.
1061 // Length is the structure size excluding itself. Compute an offset one
1062 // past the end of the structure (needed to know how many instructions to
1064 uint64_t StartStructureOffset
= Offset
;
1065 uint64_t EndStructureOffset
= Offset
+ Length
;
1067 // The Id field's size depends on the DWARF format
1068 Error Err
= Error::success();
1069 uint64_t Id
= Data
.getRelocatedValue((IsDWARF64
&& !IsEH
) ? 8 : 4, &Offset
,
1070 /*SectionIndex=*/nullptr, &Err
);
1074 if (Id
== getCIEId(IsDWARF64
, IsEH
)) {
1075 uint8_t Version
= Data
.getU8(&Offset
);
1076 const char *Augmentation
= Data
.getCStr(&Offset
);
1077 StringRef
AugmentationString(Augmentation
? Augmentation
: "");
1078 uint8_t AddressSize
= Version
< 4 ? Data
.getAddressSize() :
1079 Data
.getU8(&Offset
);
1080 Data
.setAddressSize(AddressSize
);
1081 uint8_t SegmentDescriptorSize
= Version
< 4 ? 0 : Data
.getU8(&Offset
);
1082 uint64_t CodeAlignmentFactor
= Data
.getULEB128(&Offset
);
1083 int64_t DataAlignmentFactor
= Data
.getSLEB128(&Offset
);
1084 uint64_t ReturnAddressRegister
=
1085 Version
== 1 ? Data
.getU8(&Offset
) : Data
.getULEB128(&Offset
);
1087 // Parse the augmentation data for EH CIEs
1088 StringRef
AugmentationData("");
1089 uint32_t FDEPointerEncoding
= DW_EH_PE_absptr
;
1090 uint32_t LSDAPointerEncoding
= DW_EH_PE_omit
;
1091 std::optional
<uint64_t> Personality
;
1092 std::optional
<uint32_t> PersonalityEncoding
;
1094 std::optional
<uint64_t> AugmentationLength
;
1095 uint64_t StartAugmentationOffset
;
1096 uint64_t EndAugmentationOffset
;
1098 // Walk the augmentation string to get all the augmentation data.
1099 for (unsigned i
= 0, e
= AugmentationString
.size(); i
!= e
; ++i
) {
1100 switch (AugmentationString
[i
]) {
1102 return createStringError(
1103 errc::invalid_argument
,
1104 "unknown augmentation character %c in entry at 0x%" PRIx64
,
1105 AugmentationString
[i
], StartOffset
);
1107 LSDAPointerEncoding
= Data
.getU8(&Offset
);
1111 return createStringError(
1112 errc::invalid_argument
,
1113 "duplicate personality in entry at 0x%" PRIx64
, StartOffset
);
1114 PersonalityEncoding
= Data
.getU8(&Offset
);
1115 Personality
= Data
.getEncodedPointer(
1116 &Offset
, *PersonalityEncoding
,
1117 EHFrameAddress
? EHFrameAddress
+ Offset
: 0);
1121 FDEPointerEncoding
= Data
.getU8(&Offset
);
1124 // Current frame is a signal trampoline.
1128 return createStringError(
1129 errc::invalid_argument
,
1130 "'z' must be the first character at 0x%" PRIx64
, StartOffset
);
1131 // Parse the augmentation length first. We only parse it if
1132 // the string contains a 'z'.
1133 AugmentationLength
= Data
.getULEB128(&Offset
);
1134 StartAugmentationOffset
= Offset
;
1135 EndAugmentationOffset
= Offset
+ *AugmentationLength
;
1138 // B-Key is used for signing functions associated with this
1139 // augmentation string
1141 // This stack frame contains MTE tagged data, so needs to be
1142 // untagged on unwind.
1148 if (AugmentationLength
) {
1149 if (Offset
!= EndAugmentationOffset
)
1150 return createStringError(errc::invalid_argument
,
1151 "parsing augmentation data at 0x%" PRIx64
1154 AugmentationData
= Data
.getData().slice(StartAugmentationOffset
,
1155 EndAugmentationOffset
);
1159 auto Cie
= std::make_unique
<CIE
>(
1160 IsDWARF64
, StartOffset
, Length
, Version
, AugmentationString
,
1161 AddressSize
, SegmentDescriptorSize
, CodeAlignmentFactor
,
1162 DataAlignmentFactor
, ReturnAddressRegister
, AugmentationData
,
1163 FDEPointerEncoding
, LSDAPointerEncoding
, Personality
,
1164 PersonalityEncoding
, Arch
);
1165 CIEs
[StartOffset
] = Cie
.get();
1166 Entries
.emplace_back(std::move(Cie
));
1169 uint64_t CIEPointer
= Id
;
1170 uint64_t InitialLocation
= 0;
1171 uint64_t AddressRange
= 0;
1172 std::optional
<uint64_t> LSDAAddress
;
1173 CIE
*Cie
= CIEs
[IsEH
? (StartStructureOffset
- CIEPointer
) : CIEPointer
];
1176 // The address size is encoded in the CIE we reference.
1178 return createStringError(errc::invalid_argument
,
1179 "parsing FDE data at 0x%" PRIx64
1180 " failed due to missing CIE",
1183 Data
.getEncodedPointer(&Offset
, Cie
->getFDEPointerEncoding(),
1184 EHFrameAddress
+ Offset
)) {
1185 InitialLocation
= *Val
;
1187 if (auto Val
= Data
.getEncodedPointer(
1188 &Offset
, Cie
->getFDEPointerEncoding(), 0)) {
1189 AddressRange
= *Val
;
1192 StringRef AugmentationString
= Cie
->getAugmentationString();
1193 if (!AugmentationString
.empty()) {
1194 // Parse the augmentation length and data for this FDE.
1195 uint64_t AugmentationLength
= Data
.getULEB128(&Offset
);
1197 uint64_t EndAugmentationOffset
= Offset
+ AugmentationLength
;
1199 // Decode the LSDA if the CIE augmentation string said we should.
1200 if (Cie
->getLSDAPointerEncoding() != DW_EH_PE_omit
) {
1201 LSDAAddress
= Data
.getEncodedPointer(
1202 &Offset
, Cie
->getLSDAPointerEncoding(),
1203 EHFrameAddress
? Offset
+ EHFrameAddress
: 0);
1206 if (Offset
!= EndAugmentationOffset
)
1207 return createStringError(errc::invalid_argument
,
1208 "parsing augmentation data at 0x%" PRIx64
1213 InitialLocation
= Data
.getRelocatedAddress(&Offset
);
1214 AddressRange
= Data
.getRelocatedAddress(&Offset
);
1217 Entries
.emplace_back(new FDE(IsDWARF64
, StartOffset
, Length
, CIEPointer
,
1218 InitialLocation
, AddressRange
, Cie
,
1219 LSDAAddress
, Arch
));
1223 Entries
.back()->cfis().parse(Data
, &Offset
, EndStructureOffset
))
1226 if (Offset
!= EndStructureOffset
)
1227 return createStringError(
1228 errc::invalid_argument
,
1229 "parsing entry instructions at 0x%" PRIx64
" failed", StartOffset
);
1232 return Error::success();
1235 FrameEntry
*DWARFDebugFrame::getEntryAtOffset(uint64_t Offset
) const {
1236 auto It
= partition_point(Entries
, [=](const std::unique_ptr
<FrameEntry
> &E
) {
1237 return E
->getOffset() < Offset
;
1239 if (It
!= Entries
.end() && (*It
)->getOffset() == Offset
)
1244 void DWARFDebugFrame::dump(raw_ostream
&OS
, DIDumpOptions DumpOpts
,
1245 std::optional
<uint64_t> Offset
) const {
1246 DumpOpts
.IsEH
= IsEH
;
1248 if (auto *Entry
= getEntryAtOffset(*Offset
))
1249 Entry
->dump(OS
, DumpOpts
);
1254 for (const auto &Entry
: Entries
)
1255 Entry
->dump(OS
, DumpOpts
);