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