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 enum class InitializeTime
{ kLazy
, kNormal
};
96 // When saving registers, this data structure is lazily initialized.
97 PrologInfo(InitializeTime IT
= InitializeTime::kNormal
) {
98 if (IT
== InitializeTime::kNormal
)
99 memset(this, 0, sizeof(*this));
101 void checkSaveRegister(uint64_t reg
, PrologInfo
&initialState
) {
102 if (!savedRegisters
[reg
].initialStateSaved
) {
103 initialState
.savedRegisters
[reg
] = savedRegisters
[reg
];
104 savedRegisters
[reg
].initialStateSaved
= true;
107 void setRegister(uint64_t reg
, RegisterSavedWhere newLocation
,
108 int64_t newValue
, PrologInfo
&initialState
) {
109 checkSaveRegister(reg
, initialState
);
110 savedRegisters
[reg
].location
= newLocation
;
111 savedRegisters
[reg
].value
= newValue
;
113 void setRegisterLocation(uint64_t reg
, RegisterSavedWhere newLocation
,
114 PrologInfo
&initialState
) {
115 checkSaveRegister(reg
, initialState
);
116 savedRegisters
[reg
].location
= newLocation
;
118 void setRegisterValue(uint64_t reg
, int64_t newValue
,
119 PrologInfo
&initialState
) {
120 checkSaveRegister(reg
, initialState
);
121 savedRegisters
[reg
].value
= newValue
;
123 void restoreRegisterToInitialState(uint64_t reg
, PrologInfo
&initialState
) {
124 if (savedRegisters
[reg
].initialStateSaved
)
125 savedRegisters
[reg
] = initialState
.savedRegisters
[reg
];
126 // else the register still holds its initial state
130 struct PrologInfoStackEntry
{
131 PrologInfoStackEntry(PrologInfoStackEntry
*n
, const PrologInfo
&i
)
132 : next(n
), info(i
) {}
133 PrologInfoStackEntry
*next
;
137 struct RememberStack
{
138 PrologInfoStackEntry
*entry
;
139 RememberStack() : entry(nullptr) {}
141 #if defined(_LIBUNWIND_REMEMBER_CLEANUP_NEEDED)
142 // Clean up rememberStack. Even in the case where every
143 // DW_CFA_remember_state is paired with a DW_CFA_restore_state,
144 // parseInstructions can skip restore opcodes if it reaches the target PC
145 // and stops interpreting, so we have to make sure we don't leak memory.
147 PrologInfoStackEntry
*next
= entry
->next
;
148 _LIBUNWIND_REMEMBER_FREE(entry
);
155 static bool findFDE(A
&addressSpace
, pint_t pc
, pint_t ehSectionStart
,
156 size_t sectionLength
, pint_t fdeHint
, FDE_Info
*fdeInfo
,
158 static const char *decodeFDE(A
&addressSpace
, pint_t fdeStart
,
159 FDE_Info
*fdeInfo
, CIE_Info
*cieInfo
,
160 bool useCIEInfo
= false);
161 static bool parseFDEInstructions(A
&addressSpace
, const FDE_Info
&fdeInfo
,
162 const CIE_Info
&cieInfo
, pint_t upToPC
,
163 int arch
, PrologInfo
*results
);
165 static const char *parseCIE(A
&addressSpace
, pint_t cie
, CIE_Info
*cieInfo
);
168 /// Parse a FDE into a CIE_Info and an FDE_Info. If useCIEInfo is
169 /// true, treat cieInfo as already-parsed CIE_Info (whose start offset
170 /// must match the one specified by the FDE) rather than parsing the
171 /// one indicated within the FDE.
172 template <typename A
>
173 const char *CFI_Parser
<A
>::decodeFDE(A
&addressSpace
, pint_t fdeStart
,
174 FDE_Info
*fdeInfo
, CIE_Info
*cieInfo
,
177 pint_t cfiLength
= (pint_t
)addressSpace
.get32(p
);
179 if (cfiLength
== 0xffffffff) {
180 // 0xffffffff means length is really next 8 bytes
181 cfiLength
= (pint_t
)addressSpace
.get64(p
);
185 return "FDE has zero length"; // zero terminator
186 uint32_t ciePointer
= addressSpace
.get32(p
);
188 return "FDE is really a CIE"; // this is a CIE not an FDE
189 pint_t nextCFI
= p
+ cfiLength
;
190 pint_t cieStart
= p
- ciePointer
;
192 if (cieInfo
->cieStart
!= cieStart
)
193 return "CIE start does not match";
195 const char *err
= parseCIE(addressSpace
, cieStart
, cieInfo
);
200 // Parse pc begin and range.
202 addressSpace
.getEncodedP(p
, nextCFI
, cieInfo
->pointerEncoding
);
204 addressSpace
.getEncodedP(p
, nextCFI
, cieInfo
->pointerEncoding
& 0x0F);
205 // Parse rest of info.
207 // Check for augmentation length.
208 if (cieInfo
->fdesHaveAugmentationData
) {
209 pint_t augLen
= (pint_t
)addressSpace
.getULEB128(p
, nextCFI
);
210 pint_t endOfAug
= p
+ augLen
;
211 if (cieInfo
->lsdaEncoding
!= DW_EH_PE_omit
) {
212 // Peek at value (without indirection). Zero means no LSDA.
213 pint_t lsdaStart
= p
;
214 if (addressSpace
.getEncodedP(p
, nextCFI
, cieInfo
->lsdaEncoding
& 0x0F) !=
216 // Reset pointer and re-parse LSDA address.
219 addressSpace
.getEncodedP(p
, nextCFI
, cieInfo
->lsdaEncoding
);
224 fdeInfo
->fdeStart
= fdeStart
;
225 fdeInfo
->fdeLength
= nextCFI
- fdeStart
;
226 fdeInfo
->fdeInstructions
= p
;
227 fdeInfo
->pcStart
= pcStart
;
228 fdeInfo
->pcEnd
= pcStart
+ pcRange
;
229 return NULL
; // success
232 /// Scan an eh_frame section to find an FDE for a pc
233 template <typename A
>
234 bool CFI_Parser
<A
>::findFDE(A
&addressSpace
, pint_t pc
, pint_t ehSectionStart
,
235 size_t sectionLength
, pint_t fdeHint
,
236 FDE_Info
*fdeInfo
, CIE_Info
*cieInfo
) {
237 //fprintf(stderr, "findFDE(0x%llX)\n", (long long)pc);
238 pint_t p
= (fdeHint
!= 0) ? fdeHint
: ehSectionStart
;
239 const pint_t ehSectionEnd
= (sectionLength
== SIZE_MAX
)
240 ? static_cast<pint_t
>(-1)
241 : (ehSectionStart
+ sectionLength
);
242 while (p
< ehSectionEnd
) {
243 pint_t currentCFI
= p
;
244 //fprintf(stderr, "findFDE() CFI at 0x%llX\n", (long long)p);
245 pint_t cfiLength
= addressSpace
.get32(p
);
247 if (cfiLength
== 0xffffffff) {
248 // 0xffffffff means length is really next 8 bytes
249 cfiLength
= (pint_t
)addressSpace
.get64(p
);
253 return false; // zero terminator
254 uint32_t id
= addressSpace
.get32(p
);
259 // Process FDE to see if it covers pc.
260 pint_t nextCFI
= p
+ cfiLength
;
261 uint32_t ciePointer
= addressSpace
.get32(p
);
262 pint_t cieStart
= p
- ciePointer
;
263 // Validate pointer to CIE is within section.
264 if ((ehSectionStart
<= cieStart
) && (cieStart
< ehSectionEnd
)) {
265 if (parseCIE(addressSpace
, cieStart
, cieInfo
) == NULL
) {
267 // Parse pc begin and range.
269 addressSpace
.getEncodedP(p
, nextCFI
, cieInfo
->pointerEncoding
);
270 pint_t pcRange
= addressSpace
.getEncodedP(
271 p
, nextCFI
, cieInfo
->pointerEncoding
& 0x0F);
272 // Test if pc is within the function this FDE covers.
273 if ((pcStart
< pc
) && (pc
<= pcStart
+ pcRange
)) {
274 // parse rest of info
276 // check for augmentation length
277 if (cieInfo
->fdesHaveAugmentationData
) {
278 pint_t augLen
= (pint_t
)addressSpace
.getULEB128(p
, nextCFI
);
279 pint_t endOfAug
= p
+ augLen
;
280 if (cieInfo
->lsdaEncoding
!= DW_EH_PE_omit
) {
281 // Peek at value (without indirection). Zero means no LSDA.
282 pint_t lsdaStart
= p
;
283 if (addressSpace
.getEncodedP(
284 p
, nextCFI
, cieInfo
->lsdaEncoding
& 0x0F) != 0) {
285 // Reset pointer and re-parse LSDA address.
287 fdeInfo
->lsda
= addressSpace
288 .getEncodedP(p
, nextCFI
, cieInfo
->lsdaEncoding
);
293 fdeInfo
->fdeStart
= currentCFI
;
294 fdeInfo
->fdeLength
= nextCFI
- currentCFI
;
295 fdeInfo
->fdeInstructions
= p
;
296 fdeInfo
->pcStart
= pcStart
;
297 fdeInfo
->pcEnd
= pcStart
+ pcRange
;
300 // pc is not in begin/range, skip this FDE
303 // Malformed CIE, now augmentation describing pc range encoding.
306 // malformed FDE. CIE is bad
314 /// Extract info from a CIE
315 template <typename A
>
316 const char *CFI_Parser
<A
>::parseCIE(A
&addressSpace
, pint_t cie
,
318 cieInfo
->pointerEncoding
= 0;
319 cieInfo
->lsdaEncoding
= DW_EH_PE_omit
;
320 cieInfo
->personalityEncoding
= 0;
321 cieInfo
->personalityOffsetInCIE
= 0;
322 cieInfo
->personality
= 0;
323 cieInfo
->codeAlignFactor
= 0;
324 cieInfo
->dataAlignFactor
= 0;
325 cieInfo
->isSignalFrame
= false;
326 cieInfo
->fdesHaveAugmentationData
= false;
327 #if defined(_LIBUNWIND_TARGET_AARCH64)
328 cieInfo
->addressesSignedWithBKey
= false;
329 cieInfo
->mteTaggedFrame
= false;
331 cieInfo
->cieStart
= cie
;
333 pint_t cieLength
= (pint_t
)addressSpace
.get32(p
);
335 pint_t cieContentEnd
= p
+ cieLength
;
336 if (cieLength
== 0xffffffff) {
337 // 0xffffffff means length is really next 8 bytes
338 cieLength
= (pint_t
)addressSpace
.get64(p
);
340 cieContentEnd
= p
+ cieLength
;
344 // CIE ID is always 0
345 if (addressSpace
.get32(p
) != 0)
346 return "CIE ID is not zero";
348 // Version is always 1 or 3
349 uint8_t version
= addressSpace
.get8(p
);
350 if ((version
!= 1) && (version
!= 3))
351 return "CIE version is not 1 or 3";
353 // save start of augmentation string and find end
355 while (addressSpace
.get8(p
) != 0)
358 // parse code alignment factor
359 cieInfo
->codeAlignFactor
= (uint32_t)addressSpace
.getULEB128(p
, cieContentEnd
);
360 // parse data alignment factor
361 cieInfo
->dataAlignFactor
= (int)addressSpace
.getSLEB128(p
, cieContentEnd
);
362 // parse return address register
363 uint64_t raReg
= (version
== 1) ? addressSpace
.get8(p
++)
364 : addressSpace
.getULEB128(p
, cieContentEnd
);
365 assert(raReg
< 255 && "return address register too large");
366 cieInfo
->returnAddressRegister
= (uint8_t)raReg
;
367 // parse augmentation data based on augmentation string
368 const char *result
= NULL
;
369 if (addressSpace
.get8(strStart
) == 'z') {
370 // parse augmentation data length
371 addressSpace
.getULEB128(p
, cieContentEnd
);
372 for (pint_t s
= strStart
; addressSpace
.get8(s
) != '\0'; ++s
) {
373 switch (addressSpace
.get8(s
)) {
375 cieInfo
->fdesHaveAugmentationData
= true;
378 cieInfo
->personalityEncoding
= addressSpace
.get8(p
);
380 cieInfo
->personalityOffsetInCIE
= (uint8_t)(p
- cie
);
381 cieInfo
->personality
= addressSpace
382 .getEncodedP(p
, cieContentEnd
, cieInfo
->personalityEncoding
);
385 cieInfo
->lsdaEncoding
= addressSpace
.get8(p
);
389 cieInfo
->pointerEncoding
= addressSpace
.get8(p
);
393 cieInfo
->isSignalFrame
= true;
395 #if defined(_LIBUNWIND_TARGET_AARCH64)
397 cieInfo
->addressesSignedWithBKey
= true;
400 cieInfo
->mteTaggedFrame
= true;
404 // ignore unknown letters
409 cieInfo
->cieLength
= cieContentEnd
- cieInfo
->cieStart
;
410 cieInfo
->cieInstructions
= p
;
415 /// "run" the DWARF instructions and create the abstract PrologInfo for an FDE
416 template <typename A
>
417 bool CFI_Parser
<A
>::parseFDEInstructions(A
&addressSpace
,
418 const FDE_Info
&fdeInfo
,
419 const CIE_Info
&cieInfo
, pint_t upToPC
,
420 int arch
, PrologInfo
*results
) {
421 // Alloca is used for the allocation of the rememberStack entries. It removes
422 // the dependency on new/malloc but the below for loop can not be refactored
423 // into functions. Entry could be saved during the processing of a CIE and
424 // restored by an FDE.
425 RememberStack rememberStack
;
429 pint_t instructionsEnd
;
433 ParseInfo parseInfoArray
[] = {
434 {cieInfo
.cieInstructions
, cieInfo
.cieStart
+ cieInfo
.cieLength
,
436 {fdeInfo
.fdeInstructions
, fdeInfo
.fdeStart
+ fdeInfo
.fdeLength
,
437 upToPC
- fdeInfo
.pcStart
}};
439 for (const auto &info
: parseInfoArray
) {
440 pint_t p
= info
.instructions
;
441 pint_t instructionsEnd
= info
.instructionsEnd
;
442 pint_t pcoffset
= info
.pcoffset
;
443 pint_t codeOffset
= 0;
445 // initialState initialized as registers in results are modified. Use
446 // PrologInfo accessor functions to avoid reading uninitialized data.
447 PrologInfo
initialState(PrologInfo::InitializeTime::kLazy
);
449 _LIBUNWIND_TRACE_DWARF("parseFDEInstructions(instructions=0x%0" PRIx64
451 static_cast<uint64_t>(instructionsEnd
));
453 // see DWARF Spec, section 6.4.2 for details on unwind opcodes
454 while ((p
< instructionsEnd
) && (codeOffset
< pcoffset
)) {
459 uint8_t opcode
= addressSpace
.get8(p
);
465 _LIBUNWIND_TRACE_DWARF("DW_CFA_nop\n");
468 codeOffset
= addressSpace
.getEncodedP(p
, instructionsEnd
,
469 cieInfo
.pointerEncoding
);
470 _LIBUNWIND_TRACE_DWARF("DW_CFA_set_loc\n");
472 case DW_CFA_advance_loc1
:
473 codeOffset
+= (addressSpace
.get8(p
) * cieInfo
.codeAlignFactor
);
475 _LIBUNWIND_TRACE_DWARF("DW_CFA_advance_loc1: new offset=%" PRIu64
"\n",
476 static_cast<uint64_t>(codeOffset
));
478 case DW_CFA_advance_loc2
:
479 codeOffset
+= (addressSpace
.get16(p
) * cieInfo
.codeAlignFactor
);
481 _LIBUNWIND_TRACE_DWARF("DW_CFA_advance_loc2: new offset=%" PRIu64
"\n",
482 static_cast<uint64_t>(codeOffset
));
484 case DW_CFA_advance_loc4
:
485 codeOffset
+= (addressSpace
.get32(p
) * cieInfo
.codeAlignFactor
);
487 _LIBUNWIND_TRACE_DWARF("DW_CFA_advance_loc4: new offset=%" PRIu64
"\n",
488 static_cast<uint64_t>(codeOffset
));
490 case DW_CFA_offset_extended
:
491 reg
= addressSpace
.getULEB128(p
, instructionsEnd
);
492 offset
= (int64_t)addressSpace
.getULEB128(p
, instructionsEnd
) *
493 cieInfo
.dataAlignFactor
;
494 if (reg
> kMaxRegisterNumber
) {
496 "malformed DW_CFA_offset_extended DWARF unwind, reg too big");
499 results
->setRegister(reg
, kRegisterInCFA
, offset
, initialState
);
500 _LIBUNWIND_TRACE_DWARF("DW_CFA_offset_extended(reg=%" PRIu64
", "
501 "offset=%" PRId64
")\n",
504 case DW_CFA_restore_extended
:
505 reg
= addressSpace
.getULEB128(p
, instructionsEnd
);
506 if (reg
> kMaxRegisterNumber
) {
508 "malformed DW_CFA_restore_extended DWARF unwind, reg too big");
511 results
->restoreRegisterToInitialState(reg
, initialState
);
512 _LIBUNWIND_TRACE_DWARF("DW_CFA_restore_extended(reg=%" PRIu64
")\n",
515 case DW_CFA_undefined
:
516 reg
= addressSpace
.getULEB128(p
, instructionsEnd
);
517 if (reg
> kMaxRegisterNumber
) {
519 "malformed DW_CFA_undefined DWARF unwind, reg too big");
522 results
->setRegisterLocation(reg
, kRegisterUndefined
, initialState
);
523 _LIBUNWIND_TRACE_DWARF("DW_CFA_undefined(reg=%" PRIu64
")\n", reg
);
525 case DW_CFA_same_value
:
526 reg
= addressSpace
.getULEB128(p
, instructionsEnd
);
527 if (reg
> kMaxRegisterNumber
) {
529 "malformed DW_CFA_same_value DWARF unwind, reg too big");
532 // <rdar://problem/8456377> DW_CFA_same_value unsupported
533 // "same value" means register was stored in frame, but its current
534 // value has not changed, so no need to restore from frame.
535 // We model this as if the register was never saved.
536 results
->setRegisterLocation(reg
, kRegisterUnused
, initialState
);
537 _LIBUNWIND_TRACE_DWARF("DW_CFA_same_value(reg=%" PRIu64
")\n", reg
);
539 case DW_CFA_register
:
540 reg
= addressSpace
.getULEB128(p
, instructionsEnd
);
541 reg2
= addressSpace
.getULEB128(p
, instructionsEnd
);
542 if (reg
> kMaxRegisterNumber
) {
544 "malformed DW_CFA_register DWARF unwind, reg too big");
547 if (reg2
> kMaxRegisterNumber
) {
549 "malformed DW_CFA_register DWARF unwind, reg2 too big");
552 results
->setRegister(reg
, kRegisterInRegister
, (int64_t)reg2
,
554 _LIBUNWIND_TRACE_DWARF(
555 "DW_CFA_register(reg=%" PRIu64
", reg2=%" PRIu64
")\n", reg
, reg2
);
557 case DW_CFA_remember_state
: {
558 // Avoid operator new because that would be an upward dependency.
559 // Avoid malloc because it needs heap allocation.
560 PrologInfoStackEntry
*entry
=
561 (PrologInfoStackEntry
*)_LIBUNWIND_REMEMBER_ALLOC(
562 sizeof(PrologInfoStackEntry
));
564 entry
->next
= rememberStack
.entry
;
565 entry
->info
= *results
;
566 rememberStack
.entry
= entry
;
570 _LIBUNWIND_TRACE_DWARF("DW_CFA_remember_state\n");
573 case DW_CFA_restore_state
:
574 if (rememberStack
.entry
!= NULL
) {
575 PrologInfoStackEntry
*top
= rememberStack
.entry
;
576 *results
= top
->info
;
577 rememberStack
.entry
= top
->next
;
578 _LIBUNWIND_REMEMBER_FREE(top
);
582 _LIBUNWIND_TRACE_DWARF("DW_CFA_restore_state\n");
585 reg
= addressSpace
.getULEB128(p
, instructionsEnd
);
586 offset
= (int64_t)addressSpace
.getULEB128(p
, instructionsEnd
);
587 if (reg
> kMaxRegisterNumber
) {
588 _LIBUNWIND_LOG0("malformed DW_CFA_def_cfa DWARF unwind, reg too big");
591 results
->cfaRegister
= (uint32_t)reg
;
592 results
->cfaRegisterOffset
= (int32_t)offset
;
593 _LIBUNWIND_TRACE_DWARF("DW_CFA_def_cfa(reg=%" PRIu64
", offset=%" PRIu64
597 case DW_CFA_def_cfa_register
:
598 reg
= addressSpace
.getULEB128(p
, instructionsEnd
);
599 if (reg
> kMaxRegisterNumber
) {
601 "malformed DW_CFA_def_cfa_register DWARF unwind, reg too big");
604 results
->cfaRegister
= (uint32_t)reg
;
605 _LIBUNWIND_TRACE_DWARF("DW_CFA_def_cfa_register(%" PRIu64
")\n", reg
);
607 case DW_CFA_def_cfa_offset
:
608 results
->cfaRegisterOffset
=
609 (int32_t)addressSpace
.getULEB128(p
, instructionsEnd
);
610 _LIBUNWIND_TRACE_DWARF("DW_CFA_def_cfa_offset(%d)\n",
611 results
->cfaRegisterOffset
);
613 case DW_CFA_def_cfa_expression
:
614 results
->cfaRegister
= 0;
615 results
->cfaExpression
= (int64_t)p
;
616 length
= addressSpace
.getULEB128(p
, instructionsEnd
);
617 assert(length
< static_cast<pint_t
>(~0) && "pointer overflow");
618 p
+= static_cast<pint_t
>(length
);
619 _LIBUNWIND_TRACE_DWARF("DW_CFA_def_cfa_expression(expression=0x%" PRIx64
620 ", length=%" PRIu64
")\n",
621 results
->cfaExpression
, length
);
623 case DW_CFA_expression
:
624 reg
= addressSpace
.getULEB128(p
, instructionsEnd
);
625 if (reg
> kMaxRegisterNumber
) {
627 "malformed DW_CFA_expression DWARF unwind, reg too big");
630 results
->setRegister(reg
, kRegisterAtExpression
, (int64_t)p
,
632 length
= addressSpace
.getULEB128(p
, instructionsEnd
);
633 assert(length
< static_cast<pint_t
>(~0) && "pointer overflow");
634 p
+= static_cast<pint_t
>(length
);
635 _LIBUNWIND_TRACE_DWARF("DW_CFA_expression(reg=%" PRIu64
", "
636 "expression=0x%" PRIx64
", "
637 "length=%" PRIu64
")\n",
638 reg
, results
->savedRegisters
[reg
].value
, length
);
640 case DW_CFA_offset_extended_sf
:
641 reg
= addressSpace
.getULEB128(p
, instructionsEnd
);
642 if (reg
> kMaxRegisterNumber
) {
644 "malformed DW_CFA_offset_extended_sf DWARF unwind, reg too big");
647 offset
= addressSpace
.getSLEB128(p
, instructionsEnd
) *
648 cieInfo
.dataAlignFactor
;
649 results
->setRegister(reg
, kRegisterInCFA
, offset
, initialState
);
650 _LIBUNWIND_TRACE_DWARF("DW_CFA_offset_extended_sf(reg=%" PRIu64
", "
651 "offset=%" PRId64
")\n",
654 case DW_CFA_def_cfa_sf
:
655 reg
= addressSpace
.getULEB128(p
, instructionsEnd
);
656 offset
= addressSpace
.getSLEB128(p
, instructionsEnd
) *
657 cieInfo
.dataAlignFactor
;
658 if (reg
> kMaxRegisterNumber
) {
660 "malformed DW_CFA_def_cfa_sf DWARF unwind, reg too big");
663 results
->cfaRegister
= (uint32_t)reg
;
664 results
->cfaRegisterOffset
= (int32_t)offset
;
665 _LIBUNWIND_TRACE_DWARF("DW_CFA_def_cfa_sf(reg=%" PRIu64
", "
666 "offset=%" PRId64
")\n",
669 case DW_CFA_def_cfa_offset_sf
:
670 results
->cfaRegisterOffset
=
671 (int32_t)(addressSpace
.getSLEB128(p
, instructionsEnd
) *
672 cieInfo
.dataAlignFactor
);
673 _LIBUNWIND_TRACE_DWARF("DW_CFA_def_cfa_offset_sf(%d)\n",
674 results
->cfaRegisterOffset
);
676 case DW_CFA_val_offset
:
677 reg
= addressSpace
.getULEB128(p
, instructionsEnd
);
678 if (reg
> kMaxRegisterNumber
) {
680 "malformed DW_CFA_val_offset DWARF unwind, reg (%" PRIu64
685 offset
= (int64_t)addressSpace
.getULEB128(p
, instructionsEnd
) *
686 cieInfo
.dataAlignFactor
;
687 results
->setRegister(reg
, kRegisterOffsetFromCFA
, offset
, initialState
);
688 _LIBUNWIND_TRACE_DWARF("DW_CFA_val_offset(reg=%" PRIu64
", "
689 "offset=%" PRId64
"\n",
692 case DW_CFA_val_offset_sf
:
693 reg
= addressSpace
.getULEB128(p
, instructionsEnd
);
694 if (reg
> kMaxRegisterNumber
) {
696 "malformed DW_CFA_val_offset_sf DWARF unwind, reg too big");
699 offset
= addressSpace
.getSLEB128(p
, instructionsEnd
) *
700 cieInfo
.dataAlignFactor
;
701 results
->setRegister(reg
, kRegisterOffsetFromCFA
, offset
, initialState
);
702 _LIBUNWIND_TRACE_DWARF("DW_CFA_val_offset_sf(reg=%" PRIu64
", "
703 "offset=%" PRId64
"\n",
706 case DW_CFA_val_expression
:
707 reg
= addressSpace
.getULEB128(p
, instructionsEnd
);
708 if (reg
> kMaxRegisterNumber
) {
710 "malformed DW_CFA_val_expression DWARF unwind, reg too big");
713 results
->setRegister(reg
, kRegisterIsExpression
, (int64_t)p
,
715 length
= addressSpace
.getULEB128(p
, instructionsEnd
);
716 assert(length
< static_cast<pint_t
>(~0) && "pointer overflow");
717 p
+= static_cast<pint_t
>(length
);
718 _LIBUNWIND_TRACE_DWARF("DW_CFA_val_expression(reg=%" PRIu64
", "
719 "expression=0x%" PRIx64
", length=%" PRIu64
721 reg
, results
->savedRegisters
[reg
].value
, length
);
723 case DW_CFA_GNU_args_size
:
724 length
= addressSpace
.getULEB128(p
, instructionsEnd
);
725 results
->spExtraArgSize
= (uint32_t)length
;
726 _LIBUNWIND_TRACE_DWARF("DW_CFA_GNU_args_size(%" PRIu64
")\n", length
);
728 case DW_CFA_GNU_negative_offset_extended
:
729 reg
= addressSpace
.getULEB128(p
, instructionsEnd
);
730 if (reg
> kMaxRegisterNumber
) {
731 _LIBUNWIND_LOG0("malformed DW_CFA_GNU_negative_offset_extended DWARF "
732 "unwind, reg too big");
735 offset
= (int64_t)addressSpace
.getULEB128(p
, instructionsEnd
) *
736 cieInfo
.dataAlignFactor
;
737 results
->setRegister(reg
, kRegisterInCFA
, -offset
, initialState
);
738 _LIBUNWIND_TRACE_DWARF(
739 "DW_CFA_GNU_negative_offset_extended(%" PRId64
")\n", offset
);
742 #if defined(_LIBUNWIND_TARGET_AARCH64) || defined(_LIBUNWIND_TARGET_SPARC) || \
743 defined(_LIBUNWIND_TARGET_SPARC64)
744 // The same constant is used to represent different instructions on
745 // AArch64 (negate_ra_state) and SPARC (window_save).
746 static_assert(DW_CFA_AARCH64_negate_ra_state
== DW_CFA_GNU_window_save
,
747 "uses the same constant");
748 case DW_CFA_AARCH64_negate_ra_state
:
750 #if defined(_LIBUNWIND_TARGET_AARCH64)
751 case REGISTERS_ARM64
: {
753 results
->savedRegisters
[UNW_AARCH64_RA_SIGN_STATE
].value
^ 0x1;
754 results
->setRegisterValue(UNW_AARCH64_RA_SIGN_STATE
, value
,
756 _LIBUNWIND_TRACE_DWARF("DW_CFA_AARCH64_negate_ra_state\n");
760 #if defined(_LIBUNWIND_TARGET_SPARC)
761 // case DW_CFA_GNU_window_save:
762 case REGISTERS_SPARC
:
763 _LIBUNWIND_TRACE_DWARF("DW_CFA_GNU_window_save()\n");
764 for (reg
= UNW_SPARC_O0
; reg
<= UNW_SPARC_O7
; reg
++) {
765 results
->setRegister(reg
, kRegisterInRegister
,
766 ((int64_t)reg
- UNW_SPARC_O0
) + UNW_SPARC_I0
,
770 for (reg
= UNW_SPARC_L0
; reg
<= UNW_SPARC_I7
; reg
++) {
771 results
->setRegister(reg
, kRegisterInCFA
,
772 ((int64_t)reg
- UNW_SPARC_L0
) * 4,
778 #if defined(_LIBUNWIND_TARGET_SPARC64)
779 // case DW_CFA_GNU_window_save:
780 case REGISTERS_SPARC64
:
781 // Don't save %o0-%o7 on sparc64.
782 // https://reviews.llvm.org/D32450#736405
784 for (reg
= UNW_SPARC_L0
; reg
<= UNW_SPARC_I7
; reg
++) {
785 if (reg
== UNW_SPARC_I7
)
786 results
->setRegister(
787 reg
, kRegisterInCFADecrypt
,
788 static_cast<int64_t>((reg
- UNW_SPARC_L0
) * sizeof(pint_t
)),
791 results
->setRegister(
793 static_cast<int64_t>((reg
- UNW_SPARC_L0
) * sizeof(pint_t
)),
796 _LIBUNWIND_TRACE_DWARF("DW_CFA_GNU_window_save\n");
807 operand
= opcode
& 0x3F;
808 switch (opcode
& 0xC0) {
811 if (reg
> kMaxRegisterNumber
) {
812 _LIBUNWIND_LOG("malformed DW_CFA_offset DWARF unwind, reg (%" PRIu64
817 offset
= (int64_t)addressSpace
.getULEB128(p
, instructionsEnd
) *
818 cieInfo
.dataAlignFactor
;
819 results
->setRegister(reg
, kRegisterInCFA
, offset
, initialState
);
820 _LIBUNWIND_TRACE_DWARF("DW_CFA_offset(reg=%d, offset=%" PRId64
")\n",
823 case DW_CFA_advance_loc
:
824 codeOffset
+= operand
* cieInfo
.codeAlignFactor
;
825 _LIBUNWIND_TRACE_DWARF("DW_CFA_advance_loc: new offset=%" PRIu64
"\n",
826 static_cast<uint64_t>(codeOffset
));
830 if (reg
> kMaxRegisterNumber
) {
832 "malformed DW_CFA_restore DWARF unwind, reg (%" PRIu64
837 results
->restoreRegisterToInitialState(reg
, initialState
);
838 _LIBUNWIND_TRACE_DWARF("DW_CFA_restore(reg=%" PRIu64
")\n",
839 static_cast<uint64_t>(operand
));
842 _LIBUNWIND_TRACE_DWARF("unknown CFA opcode 0x%02X\n", opcode
);
851 } // namespace libunwind
853 #endif // __DWARF_PARSER_HPP__