1 //===----------------------------------------------------------------------===//
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
8 // Parses DWARF CFIs (FDEs and CIEs).
10 //===----------------------------------------------------------------------===//
12 #ifndef __DWARF_PARSER_HPP__
13 #define __DWARF_PARSER_HPP__
20 #include "libunwind.h"
22 #include "Registers.hpp"
28 /// CFI_Parser does basic parsing of a CFI (Call Frame Information) records.
29 /// See DWARF Spec for details:
30 /// http://refspecs.linuxbase.org/LSB_3.1.0/LSB-Core-generic/LSB-Core-generic/ehframechpt.html
35 typedef typename
A::pint_t pint_t
;
37 /// Information encoded in a CIE (Common Information Entry)
41 pint_t cieInstructions
;
42 uint8_t pointerEncoding
;
44 uint8_t personalityEncoding
;
45 uint8_t personalityOffsetInCIE
;
47 uint32_t codeAlignFactor
;
50 bool fdesHaveAugmentationData
;
51 uint8_t returnAddressRegister
;
52 #if defined(_LIBUNWIND_TARGET_AARCH64)
53 bool addressesSignedWithBKey
;
58 /// Information about an FDE (Frame Description Entry)
62 pint_t fdeInstructions
;
69 kMaxRegisterNumber
= _LIBUNWIND_HIGHEST_DWARF_REGISTER
71 enum RegisterSavedWhere
{
75 kRegisterInCFADecrypt
, // sparc64 specific
76 kRegisterOffsetFromCFA
,
78 kRegisterAtExpression
,
81 struct RegisterLocation
{
82 RegisterSavedWhere location
;
83 bool initialStateSaved
;
86 /// Information about a frame layout and registers saved determined
87 /// by "running" the DWARF FDE "instructions"
90 int32_t cfaRegisterOffset
; // CFA = (cfaRegister)+cfaRegisterOffset
91 int64_t cfaExpression
; // CFA = expression
92 uint32_t spExtraArgSize
;
93 RegisterLocation savedRegisters
[kMaxRegisterNumber
+ 1];
94 #if defined(_LIBUNWIND_TARGET_AARCH64)
95 pint_t ptrAuthDiversifier
;
97 enum class InitializeTime
{ kLazy
, kNormal
};
99 // When saving registers, this data structure is lazily initialized.
100 PrologInfo(InitializeTime IT
= InitializeTime::kNormal
) {
101 if (IT
== InitializeTime::kNormal
)
102 memset(this, 0, sizeof(*this));
104 void checkSaveRegister(uint64_t reg
, PrologInfo
&initialState
) {
105 if (!savedRegisters
[reg
].initialStateSaved
) {
106 initialState
.savedRegisters
[reg
] = savedRegisters
[reg
];
107 savedRegisters
[reg
].initialStateSaved
= true;
110 void setRegister(uint64_t reg
, RegisterSavedWhere newLocation
,
111 int64_t newValue
, PrologInfo
&initialState
) {
112 checkSaveRegister(reg
, initialState
);
113 savedRegisters
[reg
].location
= newLocation
;
114 savedRegisters
[reg
].value
= newValue
;
116 void setRegisterLocation(uint64_t reg
, RegisterSavedWhere newLocation
,
117 PrologInfo
&initialState
) {
118 checkSaveRegister(reg
, initialState
);
119 savedRegisters
[reg
].location
= newLocation
;
121 void setRegisterValue(uint64_t reg
, int64_t newValue
,
122 PrologInfo
&initialState
) {
123 checkSaveRegister(reg
, initialState
);
124 savedRegisters
[reg
].value
= newValue
;
126 void restoreRegisterToInitialState(uint64_t reg
, PrologInfo
&initialState
) {
127 if (savedRegisters
[reg
].initialStateSaved
)
128 savedRegisters
[reg
] = initialState
.savedRegisters
[reg
];
129 // else the register still holds its initial state
133 struct PrologInfoStackEntry
{
134 PrologInfoStackEntry(PrologInfoStackEntry
*n
, const PrologInfo
&i
)
135 : next(n
), info(i
) {}
136 PrologInfoStackEntry
*next
;
140 struct RememberStack
{
141 PrologInfoStackEntry
*entry
;
142 RememberStack() : entry(nullptr) {}
144 #if defined(_LIBUNWIND_REMEMBER_CLEANUP_NEEDED)
145 // Clean up rememberStack. Even in the case where every
146 // DW_CFA_remember_state is paired with a DW_CFA_restore_state,
147 // parseInstructions can skip restore opcodes if it reaches the target PC
148 // and stops interpreting, so we have to make sure we don't leak memory.
150 PrologInfoStackEntry
*next
= entry
->next
;
151 _LIBUNWIND_REMEMBER_FREE(entry
);
158 static bool findFDE(A
&addressSpace
, pint_t pc
, pint_t ehSectionStart
,
159 size_t sectionLength
, pint_t fdeHint
, FDE_Info
*fdeInfo
,
161 static const char *decodeFDE(A
&addressSpace
, pint_t fdeStart
,
162 FDE_Info
*fdeInfo
, CIE_Info
*cieInfo
,
163 bool useCIEInfo
= false);
164 static bool parseFDEInstructions(A
&addressSpace
, const FDE_Info
&fdeInfo
,
165 const CIE_Info
&cieInfo
, pint_t upToPC
,
166 int arch
, PrologInfo
*results
);
168 static const char *parseCIE(A
&addressSpace
, pint_t cie
, CIE_Info
*cieInfo
);
171 /// Parse a FDE into a CIE_Info and an FDE_Info. If useCIEInfo is
172 /// true, treat cieInfo as already-parsed CIE_Info (whose start offset
173 /// must match the one specified by the FDE) rather than parsing the
174 /// one indicated within the FDE.
175 template <typename A
>
176 const char *CFI_Parser
<A
>::decodeFDE(A
&addressSpace
, pint_t fdeStart
,
177 FDE_Info
*fdeInfo
, CIE_Info
*cieInfo
,
180 pint_t cfiLength
= (pint_t
)addressSpace
.get32(p
);
182 if (cfiLength
== 0xffffffff) {
183 // 0xffffffff means length is really next 8 bytes
184 cfiLength
= (pint_t
)addressSpace
.get64(p
);
188 return "FDE has zero length"; // zero terminator
189 uint32_t ciePointer
= addressSpace
.get32(p
);
191 return "FDE is really a CIE"; // this is a CIE not an FDE
192 pint_t nextCFI
= p
+ cfiLength
;
193 pint_t cieStart
= p
- ciePointer
;
195 if (cieInfo
->cieStart
!= cieStart
)
196 return "CIE start does not match";
198 const char *err
= parseCIE(addressSpace
, cieStart
, cieInfo
);
203 // Parse pc begin and range.
205 addressSpace
.getEncodedP(p
, nextCFI
, cieInfo
->pointerEncoding
);
207 addressSpace
.getEncodedP(p
, nextCFI
, cieInfo
->pointerEncoding
& 0x0F);
208 // Parse rest of info.
210 // Check for augmentation length.
211 if (cieInfo
->fdesHaveAugmentationData
) {
212 pint_t augLen
= (pint_t
)addressSpace
.getULEB128(p
, nextCFI
);
213 pint_t endOfAug
= p
+ augLen
;
214 if (cieInfo
->lsdaEncoding
!= DW_EH_PE_omit
) {
215 // Peek at value (without indirection). Zero means no LSDA.
216 pint_t lsdaStart
= p
;
217 if (addressSpace
.getEncodedP(p
, nextCFI
, cieInfo
->lsdaEncoding
& 0x0F) !=
219 // Reset pointer and re-parse LSDA address.
222 addressSpace
.getEncodedP(p
, nextCFI
, cieInfo
->lsdaEncoding
);
227 fdeInfo
->fdeStart
= fdeStart
;
228 fdeInfo
->fdeLength
= nextCFI
- fdeStart
;
229 fdeInfo
->fdeInstructions
= p
;
230 fdeInfo
->pcStart
= pcStart
;
231 fdeInfo
->pcEnd
= pcStart
+ pcRange
;
232 return NULL
; // success
235 /// Scan an eh_frame section to find an FDE for a pc
236 template <typename A
>
237 bool CFI_Parser
<A
>::findFDE(A
&addressSpace
, pint_t pc
, pint_t ehSectionStart
,
238 size_t sectionLength
, pint_t fdeHint
,
239 FDE_Info
*fdeInfo
, CIE_Info
*cieInfo
) {
240 //fprintf(stderr, "findFDE(0x%llX)\n", (long long)pc);
241 pint_t p
= (fdeHint
!= 0) ? fdeHint
: ehSectionStart
;
242 const pint_t ehSectionEnd
= (sectionLength
== SIZE_MAX
)
243 ? static_cast<pint_t
>(-1)
244 : (ehSectionStart
+ sectionLength
);
245 while (p
< ehSectionEnd
) {
246 pint_t currentCFI
= p
;
247 //fprintf(stderr, "findFDE() CFI at 0x%llX\n", (long long)p);
248 pint_t cfiLength
= addressSpace
.get32(p
);
250 if (cfiLength
== 0xffffffff) {
251 // 0xffffffff means length is really next 8 bytes
252 cfiLength
= (pint_t
)addressSpace
.get64(p
);
256 return false; // zero terminator
257 uint32_t id
= addressSpace
.get32(p
);
262 // Process FDE to see if it covers pc.
263 pint_t nextCFI
= p
+ cfiLength
;
264 uint32_t ciePointer
= addressSpace
.get32(p
);
265 pint_t cieStart
= p
- ciePointer
;
266 // Validate pointer to CIE is within section.
267 if ((ehSectionStart
<= cieStart
) && (cieStart
< ehSectionEnd
)) {
268 if (parseCIE(addressSpace
, cieStart
, cieInfo
) == NULL
) {
270 // Parse pc begin and range.
272 addressSpace
.getEncodedP(p
, nextCFI
, cieInfo
->pointerEncoding
);
273 pint_t pcRange
= addressSpace
.getEncodedP(
274 p
, nextCFI
, cieInfo
->pointerEncoding
& 0x0F);
275 // Test if pc is within the function this FDE covers.
276 if ((pcStart
< pc
) && (pc
<= pcStart
+ pcRange
)) {
277 // parse rest of info
279 // check for augmentation length
280 if (cieInfo
->fdesHaveAugmentationData
) {
281 pint_t augLen
= (pint_t
)addressSpace
.getULEB128(p
, nextCFI
);
282 pint_t endOfAug
= p
+ augLen
;
283 if (cieInfo
->lsdaEncoding
!= DW_EH_PE_omit
) {
284 // Peek at value (without indirection). Zero means no LSDA.
285 pint_t lsdaStart
= p
;
286 if (addressSpace
.getEncodedP(
287 p
, nextCFI
, cieInfo
->lsdaEncoding
& 0x0F) != 0) {
288 // Reset pointer and re-parse LSDA address.
290 fdeInfo
->lsda
= addressSpace
291 .getEncodedP(p
, nextCFI
, cieInfo
->lsdaEncoding
);
296 fdeInfo
->fdeStart
= currentCFI
;
297 fdeInfo
->fdeLength
= nextCFI
- currentCFI
;
298 fdeInfo
->fdeInstructions
= p
;
299 fdeInfo
->pcStart
= pcStart
;
300 fdeInfo
->pcEnd
= pcStart
+ pcRange
;
303 // pc is not in begin/range, skip this FDE
306 // Malformed CIE, now augmentation describing pc range encoding.
309 // malformed FDE. CIE is bad
317 /// Extract info from a CIE
318 template <typename A
>
319 const char *CFI_Parser
<A
>::parseCIE(A
&addressSpace
, pint_t cie
,
321 cieInfo
->pointerEncoding
= 0;
322 cieInfo
->lsdaEncoding
= DW_EH_PE_omit
;
323 cieInfo
->personalityEncoding
= 0;
324 cieInfo
->personalityOffsetInCIE
= 0;
325 cieInfo
->personality
= 0;
326 cieInfo
->codeAlignFactor
= 0;
327 cieInfo
->dataAlignFactor
= 0;
328 cieInfo
->isSignalFrame
= false;
329 cieInfo
->fdesHaveAugmentationData
= false;
330 #if defined(_LIBUNWIND_TARGET_AARCH64)
331 cieInfo
->addressesSignedWithBKey
= false;
332 cieInfo
->mteTaggedFrame
= false;
334 cieInfo
->cieStart
= cie
;
336 pint_t cieLength
= (pint_t
)addressSpace
.get32(p
);
338 pint_t cieContentEnd
= p
+ cieLength
;
339 if (cieLength
== 0xffffffff) {
340 // 0xffffffff means length is really next 8 bytes
341 cieLength
= (pint_t
)addressSpace
.get64(p
);
343 cieContentEnd
= p
+ cieLength
;
347 // CIE ID is always 0
348 if (addressSpace
.get32(p
) != 0)
349 return "CIE ID is not zero";
351 // Version is always 1 or 3
352 uint8_t version
= addressSpace
.get8(p
);
353 if ((version
!= 1) && (version
!= 3))
354 return "CIE version is not 1 or 3";
356 // save start of augmentation string and find end
358 while (addressSpace
.get8(p
) != 0)
361 // parse code alignment factor
362 cieInfo
->codeAlignFactor
= (uint32_t)addressSpace
.getULEB128(p
, cieContentEnd
);
363 // parse data alignment factor
364 cieInfo
->dataAlignFactor
= (int)addressSpace
.getSLEB128(p
, cieContentEnd
);
365 // parse return address register
366 uint64_t raReg
= (version
== 1) ? addressSpace
.get8(p
++)
367 : addressSpace
.getULEB128(p
, cieContentEnd
);
368 assert(raReg
< 255 && "return address register too large");
369 cieInfo
->returnAddressRegister
= (uint8_t)raReg
;
370 // parse augmentation data based on augmentation string
371 const char *result
= NULL
;
372 if (addressSpace
.get8(strStart
) == 'z') {
373 // parse augmentation data length
374 addressSpace
.getULEB128(p
, cieContentEnd
);
375 for (pint_t s
= strStart
; addressSpace
.get8(s
) != '\0'; ++s
) {
376 switch (addressSpace
.get8(s
)) {
378 cieInfo
->fdesHaveAugmentationData
= true;
381 cieInfo
->personalityEncoding
= addressSpace
.get8(p
);
383 cieInfo
->personalityOffsetInCIE
= (uint8_t)(p
- cie
);
384 cieInfo
->personality
= addressSpace
385 .getEncodedP(p
, cieContentEnd
, cieInfo
->personalityEncoding
);
388 cieInfo
->lsdaEncoding
= addressSpace
.get8(p
);
392 cieInfo
->pointerEncoding
= addressSpace
.get8(p
);
396 cieInfo
->isSignalFrame
= true;
398 #if defined(_LIBUNWIND_TARGET_AARCH64)
400 cieInfo
->addressesSignedWithBKey
= true;
403 cieInfo
->mteTaggedFrame
= true;
407 // ignore unknown letters
412 cieInfo
->cieLength
= cieContentEnd
- cieInfo
->cieStart
;
413 cieInfo
->cieInstructions
= p
;
418 /// "run" the DWARF instructions and create the abstract PrologInfo for an FDE
419 template <typename A
>
420 bool CFI_Parser
<A
>::parseFDEInstructions(A
&addressSpace
,
421 const FDE_Info
&fdeInfo
,
422 const CIE_Info
&cieInfo
, pint_t upToPC
,
423 int arch
, PrologInfo
*results
) {
424 // Alloca is used for the allocation of the rememberStack entries. It removes
425 // the dependency on new/malloc but the below for loop can not be refactored
426 // into functions. Entry could be saved during the processing of a CIE and
427 // restored by an FDE.
428 RememberStack rememberStack
;
432 pint_t instructionsEnd
;
436 ParseInfo parseInfoArray
[] = {
437 {cieInfo
.cieInstructions
, cieInfo
.cieStart
+ cieInfo
.cieLength
,
439 {fdeInfo
.fdeInstructions
, fdeInfo
.fdeStart
+ fdeInfo
.fdeLength
,
440 upToPC
- fdeInfo
.pcStart
}};
442 for (const auto &info
: parseInfoArray
) {
443 pint_t p
= info
.instructions
;
444 pint_t instructionsEnd
= info
.instructionsEnd
;
445 pint_t pcoffset
= info
.pcoffset
;
446 pint_t codeOffset
= 0;
448 // initialState initialized as registers in results are modified. Use
449 // PrologInfo accessor functions to avoid reading uninitialized data.
450 PrologInfo
initialState(PrologInfo::InitializeTime::kLazy
);
452 _LIBUNWIND_TRACE_DWARF("parseFDEInstructions(instructions=0x%0" PRIx64
454 static_cast<uint64_t>(instructionsEnd
));
456 // see DWARF Spec, section 6.4.2 for details on unwind opcodes
457 while ((p
< instructionsEnd
) && (codeOffset
< pcoffset
)) {
462 uint8_t opcode
= addressSpace
.get8(p
);
468 _LIBUNWIND_TRACE_DWARF("DW_CFA_nop\n");
471 codeOffset
= addressSpace
.getEncodedP(p
, instructionsEnd
,
472 cieInfo
.pointerEncoding
);
473 _LIBUNWIND_TRACE_DWARF("DW_CFA_set_loc\n");
475 case DW_CFA_advance_loc1
:
476 codeOffset
+= (addressSpace
.get8(p
) * cieInfo
.codeAlignFactor
);
478 _LIBUNWIND_TRACE_DWARF("DW_CFA_advance_loc1: new offset=%" PRIu64
"\n",
479 static_cast<uint64_t>(codeOffset
));
481 case DW_CFA_advance_loc2
:
482 codeOffset
+= (addressSpace
.get16(p
) * cieInfo
.codeAlignFactor
);
484 _LIBUNWIND_TRACE_DWARF("DW_CFA_advance_loc2: new offset=%" PRIu64
"\n",
485 static_cast<uint64_t>(codeOffset
));
487 case DW_CFA_advance_loc4
:
488 codeOffset
+= (addressSpace
.get32(p
) * cieInfo
.codeAlignFactor
);
490 _LIBUNWIND_TRACE_DWARF("DW_CFA_advance_loc4: new offset=%" PRIu64
"\n",
491 static_cast<uint64_t>(codeOffset
));
493 case DW_CFA_offset_extended
:
494 reg
= addressSpace
.getULEB128(p
, instructionsEnd
);
495 offset
= (int64_t)addressSpace
.getULEB128(p
, instructionsEnd
) *
496 cieInfo
.dataAlignFactor
;
497 if (reg
> kMaxRegisterNumber
) {
499 "malformed DW_CFA_offset_extended DWARF unwind, reg too big");
502 results
->setRegister(reg
, kRegisterInCFA
, offset
, initialState
);
503 _LIBUNWIND_TRACE_DWARF("DW_CFA_offset_extended(reg=%" PRIu64
", "
504 "offset=%" PRId64
")\n",
507 case DW_CFA_restore_extended
:
508 reg
= addressSpace
.getULEB128(p
, instructionsEnd
);
509 if (reg
> kMaxRegisterNumber
) {
511 "malformed DW_CFA_restore_extended DWARF unwind, reg too big");
514 results
->restoreRegisterToInitialState(reg
, initialState
);
515 _LIBUNWIND_TRACE_DWARF("DW_CFA_restore_extended(reg=%" PRIu64
")\n",
518 case DW_CFA_undefined
:
519 reg
= addressSpace
.getULEB128(p
, instructionsEnd
);
520 if (reg
> kMaxRegisterNumber
) {
522 "malformed DW_CFA_undefined DWARF unwind, reg too big");
525 results
->setRegisterLocation(reg
, kRegisterUndefined
, initialState
);
526 _LIBUNWIND_TRACE_DWARF("DW_CFA_undefined(reg=%" PRIu64
")\n", reg
);
528 case DW_CFA_same_value
:
529 reg
= addressSpace
.getULEB128(p
, instructionsEnd
);
530 if (reg
> kMaxRegisterNumber
) {
532 "malformed DW_CFA_same_value DWARF unwind, reg too big");
535 // <rdar://problem/8456377> DW_CFA_same_value unsupported
536 // "same value" means register was stored in frame, but its current
537 // value has not changed, so no need to restore from frame.
538 // We model this as if the register was never saved.
539 results
->setRegisterLocation(reg
, kRegisterUnused
, initialState
);
540 _LIBUNWIND_TRACE_DWARF("DW_CFA_same_value(reg=%" PRIu64
")\n", reg
);
542 case DW_CFA_register
:
543 reg
= addressSpace
.getULEB128(p
, instructionsEnd
);
544 reg2
= addressSpace
.getULEB128(p
, instructionsEnd
);
545 if (reg
> kMaxRegisterNumber
) {
547 "malformed DW_CFA_register DWARF unwind, reg too big");
550 if (reg2
> kMaxRegisterNumber
) {
552 "malformed DW_CFA_register DWARF unwind, reg2 too big");
555 results
->setRegister(reg
, kRegisterInRegister
, (int64_t)reg2
,
557 _LIBUNWIND_TRACE_DWARF(
558 "DW_CFA_register(reg=%" PRIu64
", reg2=%" PRIu64
")\n", reg
, reg2
);
560 case DW_CFA_remember_state
: {
561 // Avoid operator new because that would be an upward dependency.
562 // Avoid malloc because it needs heap allocation.
563 PrologInfoStackEntry
*entry
=
564 (PrologInfoStackEntry
*)_LIBUNWIND_REMEMBER_ALLOC(
565 sizeof(PrologInfoStackEntry
));
567 entry
->next
= rememberStack
.entry
;
568 entry
->info
= *results
;
569 rememberStack
.entry
= entry
;
573 _LIBUNWIND_TRACE_DWARF("DW_CFA_remember_state\n");
576 case DW_CFA_restore_state
:
577 if (rememberStack
.entry
!= NULL
) {
578 PrologInfoStackEntry
*top
= rememberStack
.entry
;
579 *results
= top
->info
;
580 rememberStack
.entry
= top
->next
;
581 _LIBUNWIND_REMEMBER_FREE(top
);
585 _LIBUNWIND_TRACE_DWARF("DW_CFA_restore_state\n");
588 reg
= addressSpace
.getULEB128(p
, instructionsEnd
);
589 offset
= (int64_t)addressSpace
.getULEB128(p
, instructionsEnd
);
590 if (reg
> kMaxRegisterNumber
) {
591 _LIBUNWIND_LOG0("malformed DW_CFA_def_cfa DWARF unwind, reg too big");
594 results
->cfaRegister
= (uint32_t)reg
;
595 results
->cfaRegisterOffset
= (int32_t)offset
;
596 _LIBUNWIND_TRACE_DWARF("DW_CFA_def_cfa(reg=%" PRIu64
", offset=%" PRIu64
600 case DW_CFA_def_cfa_register
:
601 reg
= addressSpace
.getULEB128(p
, instructionsEnd
);
602 if (reg
> kMaxRegisterNumber
) {
604 "malformed DW_CFA_def_cfa_register DWARF unwind, reg too big");
607 results
->cfaRegister
= (uint32_t)reg
;
608 _LIBUNWIND_TRACE_DWARF("DW_CFA_def_cfa_register(%" PRIu64
")\n", reg
);
610 case DW_CFA_def_cfa_offset
:
611 results
->cfaRegisterOffset
=
612 (int32_t)addressSpace
.getULEB128(p
, instructionsEnd
);
613 _LIBUNWIND_TRACE_DWARF("DW_CFA_def_cfa_offset(%d)\n",
614 results
->cfaRegisterOffset
);
616 case DW_CFA_def_cfa_expression
:
617 results
->cfaRegister
= 0;
618 results
->cfaExpression
= (int64_t)p
;
619 length
= addressSpace
.getULEB128(p
, instructionsEnd
);
620 assert(length
< static_cast<pint_t
>(~0) && "pointer overflow");
621 p
+= static_cast<pint_t
>(length
);
622 _LIBUNWIND_TRACE_DWARF("DW_CFA_def_cfa_expression(expression=0x%" PRIx64
623 ", length=%" PRIu64
")\n",
624 results
->cfaExpression
, length
);
626 case DW_CFA_expression
:
627 reg
= addressSpace
.getULEB128(p
, instructionsEnd
);
628 if (reg
> kMaxRegisterNumber
) {
630 "malformed DW_CFA_expression DWARF unwind, reg too big");
633 results
->setRegister(reg
, kRegisterAtExpression
, (int64_t)p
,
635 length
= addressSpace
.getULEB128(p
, instructionsEnd
);
636 assert(length
< static_cast<pint_t
>(~0) && "pointer overflow");
637 p
+= static_cast<pint_t
>(length
);
638 _LIBUNWIND_TRACE_DWARF("DW_CFA_expression(reg=%" PRIu64
", "
639 "expression=0x%" PRIx64
", "
640 "length=%" PRIu64
")\n",
641 reg
, results
->savedRegisters
[reg
].value
, length
);
643 case DW_CFA_offset_extended_sf
:
644 reg
= addressSpace
.getULEB128(p
, instructionsEnd
);
645 if (reg
> kMaxRegisterNumber
) {
647 "malformed DW_CFA_offset_extended_sf DWARF unwind, reg too big");
650 offset
= addressSpace
.getSLEB128(p
, instructionsEnd
) *
651 cieInfo
.dataAlignFactor
;
652 results
->setRegister(reg
, kRegisterInCFA
, offset
, initialState
);
653 _LIBUNWIND_TRACE_DWARF("DW_CFA_offset_extended_sf(reg=%" PRIu64
", "
654 "offset=%" PRId64
")\n",
657 case DW_CFA_def_cfa_sf
:
658 reg
= addressSpace
.getULEB128(p
, instructionsEnd
);
659 offset
= addressSpace
.getSLEB128(p
, instructionsEnd
) *
660 cieInfo
.dataAlignFactor
;
661 if (reg
> kMaxRegisterNumber
) {
663 "malformed DW_CFA_def_cfa_sf DWARF unwind, reg too big");
666 results
->cfaRegister
= (uint32_t)reg
;
667 results
->cfaRegisterOffset
= (int32_t)offset
;
668 _LIBUNWIND_TRACE_DWARF("DW_CFA_def_cfa_sf(reg=%" PRIu64
", "
669 "offset=%" PRId64
")\n",
672 case DW_CFA_def_cfa_offset_sf
:
673 results
->cfaRegisterOffset
=
674 (int32_t)(addressSpace
.getSLEB128(p
, instructionsEnd
) *
675 cieInfo
.dataAlignFactor
);
676 _LIBUNWIND_TRACE_DWARF("DW_CFA_def_cfa_offset_sf(%d)\n",
677 results
->cfaRegisterOffset
);
679 case DW_CFA_val_offset
:
680 reg
= addressSpace
.getULEB128(p
, instructionsEnd
);
681 if (reg
> kMaxRegisterNumber
) {
683 "malformed DW_CFA_val_offset DWARF unwind, reg (%" PRIu64
688 offset
= (int64_t)addressSpace
.getULEB128(p
, instructionsEnd
) *
689 cieInfo
.dataAlignFactor
;
690 results
->setRegister(reg
, kRegisterOffsetFromCFA
, offset
, initialState
);
691 _LIBUNWIND_TRACE_DWARF("DW_CFA_val_offset(reg=%" PRIu64
", "
692 "offset=%" PRId64
"\n",
695 case DW_CFA_val_offset_sf
:
696 reg
= addressSpace
.getULEB128(p
, instructionsEnd
);
697 if (reg
> kMaxRegisterNumber
) {
699 "malformed DW_CFA_val_offset_sf DWARF unwind, reg too big");
702 offset
= addressSpace
.getSLEB128(p
, instructionsEnd
) *
703 cieInfo
.dataAlignFactor
;
704 results
->setRegister(reg
, kRegisterOffsetFromCFA
, offset
, initialState
);
705 _LIBUNWIND_TRACE_DWARF("DW_CFA_val_offset_sf(reg=%" PRIu64
", "
706 "offset=%" PRId64
"\n",
709 case DW_CFA_val_expression
:
710 reg
= addressSpace
.getULEB128(p
, instructionsEnd
);
711 if (reg
> kMaxRegisterNumber
) {
713 "malformed DW_CFA_val_expression DWARF unwind, reg too big");
716 results
->setRegister(reg
, kRegisterIsExpression
, (int64_t)p
,
718 length
= addressSpace
.getULEB128(p
, instructionsEnd
);
719 assert(length
< static_cast<pint_t
>(~0) && "pointer overflow");
720 p
+= static_cast<pint_t
>(length
);
721 _LIBUNWIND_TRACE_DWARF("DW_CFA_val_expression(reg=%" PRIu64
", "
722 "expression=0x%" PRIx64
", length=%" PRIu64
724 reg
, results
->savedRegisters
[reg
].value
, length
);
726 case DW_CFA_GNU_args_size
:
727 length
= addressSpace
.getULEB128(p
, instructionsEnd
);
728 results
->spExtraArgSize
= (uint32_t)length
;
729 _LIBUNWIND_TRACE_DWARF("DW_CFA_GNU_args_size(%" PRIu64
")\n", length
);
731 case DW_CFA_GNU_negative_offset_extended
:
732 reg
= addressSpace
.getULEB128(p
, instructionsEnd
);
733 if (reg
> kMaxRegisterNumber
) {
734 _LIBUNWIND_LOG0("malformed DW_CFA_GNU_negative_offset_extended DWARF "
735 "unwind, reg too big");
738 offset
= (int64_t)addressSpace
.getULEB128(p
, instructionsEnd
) *
739 cieInfo
.dataAlignFactor
;
740 results
->setRegister(reg
, kRegisterInCFA
, -offset
, initialState
);
741 _LIBUNWIND_TRACE_DWARF(
742 "DW_CFA_GNU_negative_offset_extended(%" PRId64
")\n", offset
);
745 #if defined(_LIBUNWIND_TARGET_AARCH64) || defined(_LIBUNWIND_TARGET_SPARC) || \
746 defined(_LIBUNWIND_TARGET_SPARC64)
747 // The same constant is used to represent different instructions on
748 // AArch64 (negate_ra_state) and SPARC (window_save).
749 static_assert(DW_CFA_AARCH64_negate_ra_state
== DW_CFA_GNU_window_save
,
750 "uses the same constant");
751 case DW_CFA_AARCH64_negate_ra_state
:
753 #if defined(_LIBUNWIND_TARGET_AARCH64)
754 case REGISTERS_ARM64
: {
756 results
->savedRegisters
[UNW_AARCH64_RA_SIGN_STATE
].value
^ 0x1;
757 results
->setRegisterValue(UNW_AARCH64_RA_SIGN_STATE
, value
,
759 _LIBUNWIND_TRACE_DWARF("DW_CFA_AARCH64_negate_ra_state\n");
763 #if defined(_LIBUNWIND_TARGET_SPARC)
764 // case DW_CFA_GNU_window_save:
765 case REGISTERS_SPARC
:
766 _LIBUNWIND_TRACE_DWARF("DW_CFA_GNU_window_save()\n");
767 for (reg
= UNW_SPARC_O0
; reg
<= UNW_SPARC_O7
; reg
++) {
768 results
->setRegister(reg
, kRegisterInRegister
,
769 ((int64_t)reg
- UNW_SPARC_O0
) + UNW_SPARC_I0
,
773 for (reg
= UNW_SPARC_L0
; reg
<= UNW_SPARC_I7
; reg
++) {
774 results
->setRegister(reg
, kRegisterInCFA
,
775 ((int64_t)reg
- UNW_SPARC_L0
) * 4,
781 #if defined(_LIBUNWIND_TARGET_SPARC64)
782 // case DW_CFA_GNU_window_save:
783 case REGISTERS_SPARC64
:
784 // Don't save %o0-%o7 on sparc64.
785 // https://reviews.llvm.org/D32450#736405
787 for (reg
= UNW_SPARC_L0
; reg
<= UNW_SPARC_I7
; reg
++) {
788 if (reg
== UNW_SPARC_I7
)
789 results
->setRegister(
790 reg
, kRegisterInCFADecrypt
,
791 static_cast<int64_t>((reg
- UNW_SPARC_L0
) * sizeof(pint_t
)),
794 results
->setRegister(
796 static_cast<int64_t>((reg
- UNW_SPARC_L0
) * sizeof(pint_t
)),
799 _LIBUNWIND_TRACE_DWARF("DW_CFA_GNU_window_save\n");
805 #if defined(_LIBUNWIND_TARGET_AARCH64)
806 case DW_CFA_AARCH64_negate_ra_state_with_pc
: {
808 results
->savedRegisters
[UNW_AARCH64_RA_SIGN_STATE
].value
^ 0x3;
809 results
->setRegisterValue(UNW_AARCH64_RA_SIGN_STATE
, value
,
811 // When calculating the value of the PC, it is assumed that the CFI
812 // instruction is placed before the signing instruction, however it is
813 // placed after. Because of this, we need to take into account the CFI
814 // instruction is one instruction call later than expected, and reduce
815 // the PC value by 4 bytes to compensate.
816 results
->ptrAuthDiversifier
= fdeInfo
.pcStart
+ codeOffset
- 0x4;
817 _LIBUNWIND_TRACE_DWARF(
818 "DW_CFA_AARCH64_negate_ra_state_with_pc(pc=0x%" PRIx64
")\n",
819 static_cast<uint64_t>(results
->ptrAuthDiversifier
));
828 operand
= opcode
& 0x3F;
829 switch (opcode
& 0xC0) {
832 if (reg
> kMaxRegisterNumber
) {
833 _LIBUNWIND_LOG("malformed DW_CFA_offset DWARF unwind, reg (%" PRIu64
838 offset
= (int64_t)addressSpace
.getULEB128(p
, instructionsEnd
) *
839 cieInfo
.dataAlignFactor
;
840 results
->setRegister(reg
, kRegisterInCFA
, offset
, initialState
);
841 _LIBUNWIND_TRACE_DWARF("DW_CFA_offset(reg=%d, offset=%" PRId64
")\n",
844 case DW_CFA_advance_loc
:
845 codeOffset
+= operand
* cieInfo
.codeAlignFactor
;
846 _LIBUNWIND_TRACE_DWARF("DW_CFA_advance_loc: new offset=%" PRIu64
"\n",
847 static_cast<uint64_t>(codeOffset
));
851 if (reg
> kMaxRegisterNumber
) {
853 "malformed DW_CFA_restore DWARF unwind, reg (%" PRIu64
858 results
->restoreRegisterToInitialState(reg
, initialState
);
859 _LIBUNWIND_TRACE_DWARF("DW_CFA_restore(reg=%" PRIu64
")\n",
860 static_cast<uint64_t>(operand
));
863 _LIBUNWIND_TRACE_DWARF("unknown CFA opcode 0x%02X\n", opcode
);
872 } // namespace libunwind
874 #endif // __DWARF_PARSER_HPP__