1//===----------------------------------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//
8// Processor specific interpretation of DWARF unwind info.
9//
10//===----------------------------------------------------------------------===//
11
12#ifndef __DWARF_INSTRUCTIONS_HPP__
13#define __DWARF_INSTRUCTIONS_HPP__
14
15#include <stdint.h>
16#include <stdio.h>
17#include <stdlib.h>
18
19#include "DwarfParser.hpp"
20#include "Registers.hpp"
21#include "config.h"
22#include "dwarf2.h"
23#include "libunwind_ext.h"
24
25namespace libunwind {
26
27
28/// DwarfInstructions maps abstract DWARF unwind instructions to a particular
29/// architecture
30template <typename A, typename R>
31class DwarfInstructions {
32public:
33 typedef typename A::pint_t pint_t;
34 typedef typename A::sint_t sint_t;
35
36 static int stepWithDwarf(A &addressSpace,
37 typename R::link_hardened_reg_arg_t pc,
38 pint_t fdeStart, R &registers, bool &isSignalFrame,
39 bool stage2);
40
41private:
42
43 enum {
44 DW_X86_64_RET_ADDR = 16
45 };
46
47 enum {
48 DW_X86_RET_ADDR = 8
49 };
50
51 typedef typename CFI_Parser<A>::RegisterLocation RegisterLocation;
52 typedef typename CFI_Parser<A>::PrologInfo PrologInfo;
53 typedef typename CFI_Parser<A>::FDE_Info FDE_Info;
54 typedef typename CFI_Parser<A>::CIE_Info CIE_Info;
55
56 static pint_t evaluateExpression(pint_t expression, A &addressSpace,
57 const R &registers,
58 pint_t initialStackValue);
59 static pint_t getSavedRegister(A &addressSpace, const R &registers,
60 pint_t cfa, const RegisterLocation &savedReg);
61 static double getSavedFloatRegister(A &addressSpace, const R &registers,
62 pint_t cfa, const RegisterLocation &savedReg);
63 static v128 getSavedVectorRegister(A &addressSpace, const R &registers,
64 pint_t cfa, const RegisterLocation &savedReg);
65
66 static pint_t getCFA(A &addressSpace, const PrologInfo &prolog,
67 const R &registers) {
68 if (prolog.cfaRegister != 0) {
69 uintptr_t cfaRegister = registers.getRegister((int)prolog.cfaRegister);
70 return (pint_t)(cfaRegister + prolog.cfaRegisterOffset);
71 }
72 if (prolog.cfaExpression != 0)
73 return evaluateExpression(expression: (pint_t)prolog.cfaExpression, addressSpace,
74 registers, initialStackValue: 0);
75 assert(0 && "getCFA(): unknown location");
76 __builtin_unreachable();
77 }
78#if defined(_LIBUNWIND_TARGET_AARCH64)
79 static bool isReturnAddressSigned(A &addressSpace, R registers, pint_t cfa,
80 PrologInfo &prolog);
81 static bool isReturnAddressSignedWithPC(A &addressSpace, R registers,
82 pint_t cfa, PrologInfo &prolog);
83#endif
84};
85
86template <typename R>
87auto getSparcWCookie(const R &r, int) -> decltype(r.getWCookie()) {
88 return r.getWCookie();
89}
90template <typename R> uint64_t getSparcWCookie(const R &, long) {
91 return 0;
92}
93
94template <typename A, typename R>
95typename A::pint_t DwarfInstructions<A, R>::getSavedRegister(
96 A &addressSpace, const R &registers, pint_t cfa,
97 const RegisterLocation &savedReg) {
98 switch (savedReg.location) {
99 case CFI_Parser<A>::kRegisterInCFA:
100 return (pint_t)addressSpace.getRegister(cfa + (pint_t)savedReg.value);
101
102 case CFI_Parser<A>::kRegisterInCFADecrypt: // sparc64 specific
103 return (pint_t)(addressSpace.getP(cfa + (pint_t)savedReg.value) ^
104 getSparcWCookie(registers, 0));
105
106 case CFI_Parser<A>::kRegisterAtExpression:
107 return (pint_t)addressSpace.getRegister(evaluateExpression(
108 expression: (pint_t)savedReg.value, addressSpace, registers, initialStackValue: cfa));
109
110 case CFI_Parser<A>::kRegisterIsExpression:
111 return evaluateExpression(expression: (pint_t)savedReg.value, addressSpace,
112 registers, initialStackValue: cfa);
113
114 case CFI_Parser<A>::kRegisterInRegister:
115 return registers.getRegister((int)savedReg.value);
116 case CFI_Parser<A>::kRegisterUndefined:
117 return 0;
118 case CFI_Parser<A>::kRegisterUnused:
119 case CFI_Parser<A>::kRegisterOffsetFromCFA:
120 // FIX ME
121 break;
122 }
123 _LIBUNWIND_ABORT("unsupported restore location for register");
124}
125
126template <typename A, typename R>
127double DwarfInstructions<A, R>::getSavedFloatRegister(
128 A &addressSpace, const R &registers, pint_t cfa,
129 const RegisterLocation &savedReg) {
130 switch (savedReg.location) {
131 case CFI_Parser<A>::kRegisterInCFA:
132 return addressSpace.getDouble(cfa + (pint_t)savedReg.value);
133
134 case CFI_Parser<A>::kRegisterAtExpression:
135 return addressSpace.getDouble(
136 evaluateExpression(expression: (pint_t)savedReg.value, addressSpace,
137 registers, initialStackValue: cfa));
138 case CFI_Parser<A>::kRegisterUndefined:
139 return 0.0;
140 case CFI_Parser<A>::kRegisterInRegister:
141#ifndef _LIBUNWIND_TARGET_ARM
142 return registers.getFloatRegister((int)savedReg.value);
143#endif
144 case CFI_Parser<A>::kRegisterIsExpression:
145 case CFI_Parser<A>::kRegisterUnused:
146 case CFI_Parser<A>::kRegisterOffsetFromCFA:
147 case CFI_Parser<A>::kRegisterInCFADecrypt:
148 // FIX ME
149 break;
150 }
151 _LIBUNWIND_ABORT("unsupported restore location for float register");
152}
153
154template <typename A, typename R>
155v128 DwarfInstructions<A, R>::getSavedVectorRegister(
156 A &addressSpace, const R &registers, pint_t cfa,
157 const RegisterLocation &savedReg) {
158 switch (savedReg.location) {
159 case CFI_Parser<A>::kRegisterInCFA:
160 return addressSpace.getVector(cfa + (pint_t)savedReg.value);
161
162 case CFI_Parser<A>::kRegisterAtExpression:
163 return addressSpace.getVector(
164 evaluateExpression(expression: (pint_t)savedReg.value, addressSpace,
165 registers, initialStackValue: cfa));
166
167 case CFI_Parser<A>::kRegisterIsExpression:
168 case CFI_Parser<A>::kRegisterUnused:
169 case CFI_Parser<A>::kRegisterUndefined:
170 case CFI_Parser<A>::kRegisterOffsetFromCFA:
171 case CFI_Parser<A>::kRegisterInRegister:
172 case CFI_Parser<A>::kRegisterInCFADecrypt:
173 // FIX ME
174 break;
175 }
176 _LIBUNWIND_ABORT("unsupported restore location for vector register");
177}
178#if defined(_LIBUNWIND_TARGET_AARCH64)
179template <typename A, typename R>
180bool DwarfInstructions<A, R>::isReturnAddressSigned(A &addressSpace,
181 R registers, pint_t cfa,
182 PrologInfo &prolog) {
183 pint_t raSignState;
184 auto regloc = prolog.savedRegisters[UNW_AARCH64_RA_SIGN_STATE];
185 if (regloc.location == CFI_Parser<A>::kRegisterUnused)
186 raSignState = static_cast<pint_t>(regloc.value);
187 else
188 raSignState = getSavedRegister(addressSpace, registers, cfa, regloc);
189
190 // Only bit[0] is meaningful.
191 return raSignState & 0x01;
192}
193
194template <typename A, typename R>
195bool DwarfInstructions<A, R>::isReturnAddressSignedWithPC(A &addressSpace,
196 R registers,
197 pint_t cfa,
198 PrologInfo &prolog) {
199 pint_t raSignState;
200 auto regloc = prolog.savedRegisters[UNW_AARCH64_RA_SIGN_STATE];
201 if (regloc.location == CFI_Parser<A>::kRegisterUnused)
202 raSignState = static_cast<pint_t>(regloc.value);
203 else
204 raSignState = getSavedRegister(addressSpace, registers, cfa, regloc);
205
206 // Only bit[1] is meaningful.
207 return raSignState & 0x02;
208}
209#endif
210
211template <typename A, typename R>
212int DwarfInstructions<A, R>::stepWithDwarf(
213 A &addressSpace, typename R::link_hardened_reg_arg_t pc, pint_t fdeStart,
214 R &registers, bool &isSignalFrame, bool stage2) {
215 FDE_Info fdeInfo;
216 CIE_Info cieInfo;
217 if (CFI_Parser<A>::decodeFDE(addressSpace, fdeStart, &fdeInfo,
218 &cieInfo) == NULL) {
219 PrologInfo prolog;
220 if (CFI_Parser<A>::template parseFDEInstructions<R>(
221 addressSpace, fdeInfo, cieInfo, pc, R::getArch(), &prolog)) {
222 // get pointer to cfa (architecture specific)
223 pint_t cfa = getCFA(addressSpace, prolog, registers);
224
225 (void)stage2;
226 // __unw_step_stage2 is not used for cross unwinding, so we use
227 // __aarch64__ rather than LIBUNWIND_TARGET_AARCH64 to make sure we are
228 // building for AArch64 natively.
229#if defined(__aarch64__)
230 if (stage2 && cieInfo.mteTaggedFrame) {
231 pint_t sp = registers.getSP();
232 pint_t p = sp;
233 // AArch64 doesn't require the value of SP to be 16-byte aligned at
234 // all times, only at memory accesses and public interfaces [1]. Thus,
235 // a signal could arrive at a point where SP is not aligned properly.
236 // In that case, the kernel fixes up [2] the signal frame, but we
237 // still have a misaligned SP in the previous frame. If that signal
238 // handler caused stack unwinding, we would have an unaligned SP.
239 // We do not need to fix up the CFA, as that is the SP at a "public
240 // interface".
241 // [1]:
242 // https://github.com/ARM-software/abi-aa/blob/main/aapcs64/aapcs64.rst#622the-stack
243 // [2]:
244 // https://github.com/torvalds/linux/blob/1930a6e739c4b4a654a69164dbe39e554d228915/arch/arm64/kernel/signal.c#L718
245 p &= ~0xfULL;
246 // CFA is the bottom of the current stack frame.
247 for (; p < cfa; p += 16) {
248 __asm__ __volatile__(".arch armv8.5-a\n"
249 ".arch_extension memtag\n"
250 "stg %[Ptr], [%[Ptr]]\n"
251 :
252 : [Ptr] "r"(p)
253 : "memory");
254 }
255 }
256#endif
257 // restore registers that DWARF says were saved
258 R newRegisters = registers;
259
260 // Typically, the CFA is the stack pointer at the call site in
261 // the previous frame. However, there are scenarios in which this is not
262 // true. For example, if we switched to a new stack. In that case, the
263 // value of the previous SP might be indicated by a CFI directive.
264 //
265 // We set the SP here to the CFA, allowing for it to be overridden
266 // by a CFI directive later on.
267 newRegisters.setSP(cfa);
268
269 typename R::reg_t returnAddress = 0;
270 constexpr int lastReg = R::lastDwarfRegNum();
271 static_assert(static_cast<int>(CFI_Parser<A>::kMaxRegisterNumber) >=
272 lastReg,
273 "register range too large");
274 assert(lastReg >= (int)cieInfo.returnAddressRegister &&
275 "register range does not contain return address register");
276 for (int i = 0; i <= lastReg; ++i) {
277 if (prolog.savedRegisters[i].location !=
278 CFI_Parser<A>::kRegisterUnused) {
279 if (registers.validFloatRegister(i))
280 newRegisters.setFloatRegister(
281 i, getSavedFloatRegister(addressSpace, registers, cfa,
282 savedReg: prolog.savedRegisters[i]));
283 else if (registers.validVectorRegister(i))
284 newRegisters.setVectorRegister(
285 i, getSavedVectorRegister(addressSpace, registers, cfa,
286 savedReg: prolog.savedRegisters[i]));
287 else if (i == (int)cieInfo.returnAddressRegister)
288 returnAddress = getSavedRegister(addressSpace, registers, cfa,
289 savedReg: prolog.savedRegisters[i]);
290 else if (registers.validRegister(i))
291 newRegisters.setRegister(
292 i, getSavedRegister(addressSpace, registers, cfa,
293 savedReg: prolog.savedRegisters[i]));
294 else
295 return UNW_EBADREG;
296 } else if (i == (int)cieInfo.returnAddressRegister) {
297 // Leaf function keeps the return address in register and there is no
298 // explicit instructions how to restore it.
299 returnAddress = registers.getRegister(cieInfo.returnAddressRegister);
300 }
301 }
302
303 isSignalFrame = cieInfo.isSignalFrame;
304
305#if defined(_LIBUNWIND_TARGET_AARCH64) && \
306 !defined(_LIBUNWIND_TARGET_AARCH64_AUTHENTICATED_UNWINDING)
307 // There are two ways of return address signing: pac-ret (enabled via
308 // -mbranch-protection=pac-ret) and ptrauth-returns (enabled as part of
309 // Apple's arm64e or experimental pauthtest ABI on Linux). The code
310 // below handles signed RA for pac-ret, while ptrauth-returns uses
311 // different logic.
312 // TODO: unify logic for both cases, see
313 // https://github.com/llvm/llvm-project/issues/160110
314 //
315 // If the target is aarch64 then the return address may have been signed
316 // using the v8.3 pointer authentication extensions. The original
317 // return address needs to be authenticated before the return address is
318 // restored. autia1716 is used instead of autia as autia1716 assembles
319 // to a NOP on pre-v8.3a architectures.
320 if ((R::getArch() == REGISTERS_ARM64) &&
321 isReturnAddressSigned(addressSpace, registers, cfa, prolog) &&
322 returnAddress != 0) {
323#if !defined(_LIBUNWIND_IS_NATIVE_ONLY)
324 return UNW_ECROSSRASIGNING;
325#else
326 register unsigned long long x17 __asm("x17") = returnAddress;
327 register unsigned long long x16 __asm("x16") = cfa;
328
329 // We use the hint versions of the authentication instructions below to
330 // ensure they're assembled by the compiler even for targets with no
331 // FEAT_PAuth/FEAT_PAuth_LR support.
332 if (isReturnAddressSignedWithPC(addressSpace, registers, cfa, prolog)) {
333 register unsigned long long x15 __asm("x15") =
334 prolog.ptrAuthDiversifier;
335 if (cieInfo.addressesSignedWithBKey) {
336 asm("hint 0x27\n\t" // pacm
337 "hint 0xe"
338 : "+r"(x17)
339 : "r"(x16), "r"(x15)); // autib1716
340 } else {
341 asm("hint 0x27\n\t" // pacm
342 "hint 0xc"
343 : "+r"(x17)
344 : "r"(x16), "r"(x15)); // autia1716
345 }
346 } else {
347 if (cieInfo.addressesSignedWithBKey)
348 asm("hint 0xe" : "+r"(x17) : "r"(x16)); // autib1716
349 else
350 asm("hint 0xc" : "+r"(x17) : "r"(x16)); // autia1716
351 }
352 returnAddress = x17;
353#endif
354 }
355#endif
356
357#if defined(_LIBUNWIND_IS_NATIVE_ONLY) && defined(_LIBUNWIND_TARGET_ARM) && \
358 defined(__ARM_FEATURE_PAUTH)
359 if ((R::getArch() == REGISTERS_ARM) &&
360 prolog.savedRegisters[UNW_ARM_RA_AUTH_CODE].value) {
361 pint_t pac =
362 getSavedRegister(addressSpace, registers, cfa,
363 prolog.savedRegisters[UNW_ARM_RA_AUTH_CODE]);
364 __asm__ __volatile__("autg %0, %1, %2"
365 :
366 : "r"(pac), "r"(returnAddress), "r"(cfa)
367 :);
368 }
369#endif
370
371#if defined(_LIBUNWIND_TARGET_SPARC)
372 if (R::getArch() == REGISTERS_SPARC) {
373 // Skip call site instruction and delay slot
374 returnAddress += 8;
375 // Skip unimp instruction if function returns a struct
376 if ((addressSpace.get32(returnAddress) & 0xC1C00000) == 0)
377 returnAddress += 4;
378 }
379#endif
380
381#if defined(_LIBUNWIND_TARGET_SPARC64)
382 // Skip call site instruction and delay slot.
383 if (R::getArch() == REGISTERS_SPARC64)
384 returnAddress += 8;
385#endif
386
387#if defined(_LIBUNWIND_TARGET_PPC64)
388#define PPC64_ELFV1_R2_LOAD_INST_ENCODING 0xe8410028u // ld r2,40(r1)
389#define PPC64_ELFV1_R2_OFFSET 40
390#define PPC64_ELFV2_R2_LOAD_INST_ENCODING 0xe8410018u // ld r2,24(r1)
391#define PPC64_ELFV2_R2_OFFSET 24
392 // If the instruction at return address is a TOC (r2) restore,
393 // then r2 was saved and needs to be restored.
394 // ELFv2 ABI specifies that the TOC Pointer must be saved at SP + 24,
395 // while in ELFv1 ABI it is saved at SP + 40.
396 if (R::getArch() == REGISTERS_PPC64 && returnAddress != 0) {
397 pint_t sp = newRegisters.getRegister(UNW_REG_SP);
398 pint_t r2 = 0;
399 switch (addressSpace.get32(returnAddress)) {
400 case PPC64_ELFV1_R2_LOAD_INST_ENCODING:
401 r2 = addressSpace.get64(sp + PPC64_ELFV1_R2_OFFSET);
402 break;
403 case PPC64_ELFV2_R2_LOAD_INST_ENCODING:
404 r2 = addressSpace.get64(sp + PPC64_ELFV2_R2_OFFSET);
405 break;
406 }
407 if (r2)
408 newRegisters.setRegister(UNW_PPC64_R2, r2);
409 }
410#endif
411
412 // Return address is address after call site instruction, so setting IP to
413 // that does simulates a return.
414 newRegisters.setIP(returnAddress);
415
416 // Simulate the step by replacing the register set with the new ones.
417 registers = newRegisters;
418
419 return UNW_STEP_SUCCESS;
420 }
421 }
422 return UNW_EBADFRAME;
423}
424
425template <typename A, typename R>
426typename A::pint_t
427DwarfInstructions<A, R>::evaluateExpression(pint_t expression, A &addressSpace,
428 const R &registers,
429 pint_t initialStackValue) {
430 const bool log = false;
431 pint_t p = expression;
432 pint_t expressionEnd = expression + 20; // temp, until len read
433 pint_t length = (pint_t)addressSpace.getULEB128(p, expressionEnd);
434 expressionEnd = p + length;
435 if (log)
436 fprintf(stderr, format: "evaluateExpression(): length=%" PRIu64 "\n",
437 (uint64_t)length);
438 pint_t stack[100];
439 pint_t *sp = stack;
440 *(++sp) = initialStackValue;
441
442 while (p < expressionEnd) {
443 if (log) {
444 for (pint_t *t = sp; t > stack; --t) {
445 fprintf(stderr, format: "sp[] = 0x%" PRIx64 "\n", (uint64_t)(*t));
446 }
447 }
448 uint8_t opcode = addressSpace.get8(p++);
449 sint_t svalue, svalue2;
450 pint_t value;
451 uint32_t reg;
452 switch (opcode) {
453 case DW_OP_addr:
454 // push immediate address sized value
455 value = addressSpace.getP(p);
456 p += sizeof(pint_t);
457 *(++sp) = value;
458 if (log)
459 fprintf(stderr, format: "push 0x%" PRIx64 "\n", (uint64_t)value);
460 break;
461
462 case DW_OP_deref:
463 // pop stack, dereference, push result
464 value = *sp--;
465 *(++sp) = addressSpace.getP(value);
466 if (log)
467 fprintf(stderr, format: "dereference 0x%" PRIx64 "\n", (uint64_t)value);
468 break;
469
470 case DW_OP_const1u:
471 // push immediate 1 byte value
472 value = addressSpace.get8(p);
473 p += 1;
474 *(++sp) = value;
475 if (log)
476 fprintf(stderr, format: "push 0x%" PRIx64 "\n", (uint64_t)value);
477 break;
478
479 case DW_OP_const1s:
480 // push immediate 1 byte signed value
481 svalue = (int8_t) addressSpace.get8(p);
482 p += 1;
483 *(++sp) = (pint_t)svalue;
484 if (log)
485 fprintf(stderr, format: "push 0x%" PRIx64 "\n", (uint64_t)svalue);
486 break;
487
488 case DW_OP_const2u:
489 // push immediate 2 byte value
490 value = addressSpace.get16(p);
491 p += 2;
492 *(++sp) = value;
493 if (log)
494 fprintf(stderr, format: "push 0x%" PRIx64 "\n", (uint64_t)value);
495 break;
496
497 case DW_OP_const2s:
498 // push immediate 2 byte signed value
499 svalue = (int16_t) addressSpace.get16(p);
500 p += 2;
501 *(++sp) = (pint_t)svalue;
502 if (log)
503 fprintf(stderr, format: "push 0x%" PRIx64 "\n", (uint64_t)svalue);
504 break;
505
506 case DW_OP_const4u:
507 // push immediate 4 byte value
508 value = addressSpace.get32(p);
509 p += 4;
510 *(++sp) = value;
511 if (log)
512 fprintf(stderr, format: "push 0x%" PRIx64 "\n", (uint64_t)value);
513 break;
514
515 case DW_OP_const4s:
516 // push immediate 4 byte signed value
517 svalue = (int32_t)addressSpace.get32(p);
518 p += 4;
519 *(++sp) = (pint_t)svalue;
520 if (log)
521 fprintf(stderr, format: "push 0x%" PRIx64 "\n", (uint64_t)svalue);
522 break;
523
524 case DW_OP_const8u:
525 // push immediate 8 byte value
526 value = (pint_t)addressSpace.get64(p);
527 p += 8;
528 *(++sp) = value;
529 if (log)
530 fprintf(stderr, format: "push 0x%" PRIx64 "\n", (uint64_t)value);
531 break;
532
533 case DW_OP_const8s:
534 // push immediate 8 byte signed value
535 value = (pint_t)addressSpace.get64(p);
536 p += 8;
537 *(++sp) = value;
538 if (log)
539 fprintf(stderr, format: "push 0x%" PRIx64 "\n", (uint64_t)value);
540 break;
541
542 case DW_OP_constu:
543 // push immediate ULEB128 value
544 value = (pint_t)addressSpace.getULEB128(p, expressionEnd);
545 *(++sp) = value;
546 if (log)
547 fprintf(stderr, format: "push 0x%" PRIx64 "\n", (uint64_t)value);
548 break;
549
550 case DW_OP_consts:
551 // push immediate SLEB128 value
552 svalue = (sint_t)addressSpace.getSLEB128(p, expressionEnd);
553 *(++sp) = (pint_t)svalue;
554 if (log)
555 fprintf(stderr, format: "push 0x%" PRIx64 "\n", (uint64_t)svalue);
556 break;
557
558 case DW_OP_dup:
559 // push top of stack
560 value = *sp;
561 *(++sp) = value;
562 if (log)
563 fprintf(stderr, format: "duplicate top of stack\n");
564 break;
565
566 case DW_OP_drop:
567 // pop
568 --sp;
569 if (log)
570 fprintf(stderr, format: "pop top of stack\n");
571 break;
572
573 case DW_OP_over:
574 // dup second
575 value = sp[-1];
576 *(++sp) = value;
577 if (log)
578 fprintf(stderr, format: "duplicate second in stack\n");
579 break;
580
581 case DW_OP_pick:
582 // pick from
583 reg = addressSpace.get8(p);
584 p += 1;
585 value = sp[-(int)reg];
586 *(++sp) = value;
587 if (log)
588 fprintf(stderr, format: "duplicate %d in stack\n", reg);
589 break;
590
591 case DW_OP_swap:
592 // swap top two
593 value = sp[0];
594 sp[0] = sp[-1];
595 sp[-1] = value;
596 if (log)
597 fprintf(stderr, format: "swap top of stack\n");
598 break;
599
600 case DW_OP_rot:
601 // rotate top three
602 value = sp[0];
603 sp[0] = sp[-1];
604 sp[-1] = sp[-2];
605 sp[-2] = value;
606 if (log)
607 fprintf(stderr, format: "rotate top three of stack\n");
608 break;
609
610 case DW_OP_xderef:
611 // pop stack, dereference, push result
612 value = *sp--;
613 *sp = *((pint_t*)value);
614 if (log)
615 fprintf(stderr, format: "x-dereference 0x%" PRIx64 "\n", (uint64_t)value);
616 break;
617
618 case DW_OP_abs:
619 svalue = (sint_t)*sp;
620 if (svalue < 0)
621 *sp = (pint_t)(-svalue);
622 if (log)
623 fprintf(stderr, format: "abs\n");
624 break;
625
626 case DW_OP_and:
627 value = *sp--;
628 *sp &= value;
629 if (log)
630 fprintf(stderr, format: "and\n");
631 break;
632
633 case DW_OP_div:
634 svalue = (sint_t)(*sp--);
635 svalue2 = (sint_t)*sp;
636 *sp = (pint_t)(svalue2 / svalue);
637 if (log)
638 fprintf(stderr, format: "div\n");
639 break;
640
641 case DW_OP_minus:
642 value = *sp--;
643 *sp = *sp - value;
644 if (log)
645 fprintf(stderr, format: "minus\n");
646 break;
647
648 case DW_OP_mod:
649 svalue = (sint_t)(*sp--);
650 svalue2 = (sint_t)*sp;
651 *sp = (pint_t)(svalue2 % svalue);
652 if (log)
653 fprintf(stderr, format: "module\n");
654 break;
655
656 case DW_OP_mul:
657 svalue = (sint_t)(*sp--);
658 svalue2 = (sint_t)*sp;
659 *sp = (pint_t)(svalue2 * svalue);
660 if (log)
661 fprintf(stderr, format: "mul\n");
662 break;
663
664 case DW_OP_neg:
665 *sp = 0 - *sp;
666 if (log)
667 fprintf(stderr, format: "neg\n");
668 break;
669
670 case DW_OP_not:
671 svalue = (sint_t)(*sp);
672 *sp = (pint_t)(~svalue);
673 if (log)
674 fprintf(stderr, format: "not\n");
675 break;
676
677 case DW_OP_or:
678 value = *sp--;
679 *sp |= value;
680 if (log)
681 fprintf(stderr, format: "or\n");
682 break;
683
684 case DW_OP_plus:
685 value = *sp--;
686 *sp += value;
687 if (log)
688 fprintf(stderr, format: "plus\n");
689 break;
690
691 case DW_OP_plus_uconst:
692 // pop stack, add uelb128 constant, push result
693 *sp += static_cast<pint_t>(addressSpace.getULEB128(p, expressionEnd));
694 if (log)
695 fprintf(stderr, format: "add constant\n");
696 break;
697
698 case DW_OP_shl:
699 value = *sp--;
700 *sp = *sp << value;
701 if (log)
702 fprintf(stderr, format: "shift left\n");
703 break;
704
705 case DW_OP_shr:
706 value = *sp--;
707 *sp = *sp >> value;
708 if (log)
709 fprintf(stderr, format: "shift left\n");
710 break;
711
712 case DW_OP_shra:
713 value = *sp--;
714 svalue = (sint_t)*sp;
715 *sp = (pint_t)(svalue >> value);
716 if (log)
717 fprintf(stderr, format: "shift left arithmetic\n");
718 break;
719
720 case DW_OP_xor:
721 value = *sp--;
722 *sp ^= value;
723 if (log)
724 fprintf(stderr, format: "xor\n");
725 break;
726
727 case DW_OP_skip:
728 svalue = (int16_t) addressSpace.get16(p);
729 p += 2;
730 p = (pint_t)((sint_t)p + svalue);
731 if (log)
732 fprintf(stderr, format: "skip %" PRIu64 "\n", (uint64_t)svalue);
733 break;
734
735 case DW_OP_bra:
736 svalue = (int16_t) addressSpace.get16(p);
737 p += 2;
738 if (*sp--)
739 p = (pint_t)((sint_t)p + svalue);
740 if (log)
741 fprintf(stderr, format: "bra %" PRIu64 "\n", (uint64_t)svalue);
742 break;
743
744 case DW_OP_eq:
745 value = *sp--;
746 *sp = (*sp == value);
747 if (log)
748 fprintf(stderr, format: "eq\n");
749 break;
750
751 case DW_OP_ge:
752 value = *sp--;
753 *sp = (*sp >= value);
754 if (log)
755 fprintf(stderr, format: "ge\n");
756 break;
757
758 case DW_OP_gt:
759 value = *sp--;
760 *sp = (*sp > value);
761 if (log)
762 fprintf(stderr, format: "gt\n");
763 break;
764
765 case DW_OP_le:
766 value = *sp--;
767 *sp = (*sp <= value);
768 if (log)
769 fprintf(stderr, format: "le\n");
770 break;
771
772 case DW_OP_lt:
773 value = *sp--;
774 *sp = (*sp < value);
775 if (log)
776 fprintf(stderr, format: "lt\n");
777 break;
778
779 case DW_OP_ne:
780 value = *sp--;
781 *sp = (*sp != value);
782 if (log)
783 fprintf(stderr, format: "ne\n");
784 break;
785
786 case DW_OP_lit0:
787 case DW_OP_lit1:
788 case DW_OP_lit2:
789 case DW_OP_lit3:
790 case DW_OP_lit4:
791 case DW_OP_lit5:
792 case DW_OP_lit6:
793 case DW_OP_lit7:
794 case DW_OP_lit8:
795 case DW_OP_lit9:
796 case DW_OP_lit10:
797 case DW_OP_lit11:
798 case DW_OP_lit12:
799 case DW_OP_lit13:
800 case DW_OP_lit14:
801 case DW_OP_lit15:
802 case DW_OP_lit16:
803 case DW_OP_lit17:
804 case DW_OP_lit18:
805 case DW_OP_lit19:
806 case DW_OP_lit20:
807 case DW_OP_lit21:
808 case DW_OP_lit22:
809 case DW_OP_lit23:
810 case DW_OP_lit24:
811 case DW_OP_lit25:
812 case DW_OP_lit26:
813 case DW_OP_lit27:
814 case DW_OP_lit28:
815 case DW_OP_lit29:
816 case DW_OP_lit30:
817 case DW_OP_lit31:
818 value = static_cast<pint_t>(opcode - DW_OP_lit0);
819 *(++sp) = value;
820 if (log)
821 fprintf(stderr, format: "push literal 0x%" PRIx64 "\n", (uint64_t)value);
822 break;
823
824 case DW_OP_reg0:
825 case DW_OP_reg1:
826 case DW_OP_reg2:
827 case DW_OP_reg3:
828 case DW_OP_reg4:
829 case DW_OP_reg5:
830 case DW_OP_reg6:
831 case DW_OP_reg7:
832 case DW_OP_reg8:
833 case DW_OP_reg9:
834 case DW_OP_reg10:
835 case DW_OP_reg11:
836 case DW_OP_reg12:
837 case DW_OP_reg13:
838 case DW_OP_reg14:
839 case DW_OP_reg15:
840 case DW_OP_reg16:
841 case DW_OP_reg17:
842 case DW_OP_reg18:
843 case DW_OP_reg19:
844 case DW_OP_reg20:
845 case DW_OP_reg21:
846 case DW_OP_reg22:
847 case DW_OP_reg23:
848 case DW_OP_reg24:
849 case DW_OP_reg25:
850 case DW_OP_reg26:
851 case DW_OP_reg27:
852 case DW_OP_reg28:
853 case DW_OP_reg29:
854 case DW_OP_reg30:
855 case DW_OP_reg31:
856 reg = static_cast<uint32_t>(opcode - DW_OP_reg0);
857 *(++sp) = registers.getRegister((int)reg);
858 if (log)
859 fprintf(stderr, format: "push reg %d\n", reg);
860 break;
861
862 case DW_OP_regx:
863 reg = static_cast<uint32_t>(addressSpace.getULEB128(p, expressionEnd));
864 *(++sp) = registers.getRegister((int)reg);
865 if (log)
866 fprintf(stderr, format: "push reg %d + 0x%" PRIx64 "\n", reg, (uint64_t)svalue);
867 break;
868
869 case DW_OP_breg0:
870 case DW_OP_breg1:
871 case DW_OP_breg2:
872 case DW_OP_breg3:
873 case DW_OP_breg4:
874 case DW_OP_breg5:
875 case DW_OP_breg6:
876 case DW_OP_breg7:
877 case DW_OP_breg8:
878 case DW_OP_breg9:
879 case DW_OP_breg10:
880 case DW_OP_breg11:
881 case DW_OP_breg12:
882 case DW_OP_breg13:
883 case DW_OP_breg14:
884 case DW_OP_breg15:
885 case DW_OP_breg16:
886 case DW_OP_breg17:
887 case DW_OP_breg18:
888 case DW_OP_breg19:
889 case DW_OP_breg20:
890 case DW_OP_breg21:
891 case DW_OP_breg22:
892 case DW_OP_breg23:
893 case DW_OP_breg24:
894 case DW_OP_breg25:
895 case DW_OP_breg26:
896 case DW_OP_breg27:
897 case DW_OP_breg28:
898 case DW_OP_breg29:
899 case DW_OP_breg30:
900 case DW_OP_breg31:
901 reg = static_cast<uint32_t>(opcode - DW_OP_breg0);
902 svalue = (sint_t)addressSpace.getSLEB128(p, expressionEnd);
903 svalue += static_cast<sint_t>(registers.getRegister((int)reg));
904 *(++sp) = (pint_t)(svalue);
905 if (log)
906 fprintf(stderr, format: "push reg %d + 0x%" PRIx64 "\n", reg, (uint64_t)svalue);
907 break;
908
909 case DW_OP_bregx:
910 reg = static_cast<uint32_t>(addressSpace.getULEB128(p, expressionEnd));
911 svalue = (sint_t)addressSpace.getSLEB128(p, expressionEnd);
912 svalue += static_cast<sint_t>(registers.getRegister((int)reg));
913 *(++sp) = (pint_t)(svalue);
914 if (log)
915 fprintf(stderr, format: "push reg %d + 0x%" PRIx64 "\n", reg, (uint64_t)svalue);
916 break;
917
918 case DW_OP_fbreg:
919 _LIBUNWIND_ABORT("DW_OP_fbreg not implemented");
920 break;
921
922 case DW_OP_piece:
923 _LIBUNWIND_ABORT("DW_OP_piece not implemented");
924 break;
925
926 case DW_OP_deref_size:
927 // pop stack, dereference, push result
928 value = *sp--;
929 switch (addressSpace.get8(p++)) {
930 case 1:
931 value = addressSpace.get8(value);
932 break;
933 case 2:
934 value = addressSpace.get16(value);
935 break;
936 case 4:
937 value = addressSpace.get32(value);
938 break;
939 case 8:
940 value = (pint_t)addressSpace.get64(value);
941 break;
942 default:
943 _LIBUNWIND_ABORT("DW_OP_deref_size with bad size");
944 }
945 *(++sp) = value;
946 if (log)
947 fprintf(stderr, format: "sized dereference 0x%" PRIx64 "\n", (uint64_t)value);
948 break;
949
950 case DW_OP_xderef_size:
951 case DW_OP_nop:
952 case DW_OP_push_object_addres:
953 case DW_OP_call2:
954 case DW_OP_call4:
955 case DW_OP_call_ref:
956 default:
957 _LIBUNWIND_ABORT("DWARF opcode not implemented");
958 }
959
960 }
961 if (log)
962 fprintf(stderr, format: "expression evaluates to 0x%" PRIx64 "\n", (uint64_t)*sp);
963 return *sp;
964}
965
966
967
968} // namespace libunwind
969
970#endif // __DWARF_INSTRUCTIONS_HPP__
971