1
//===-------------------------- DwarfInstructions.hpp ---------------------===//
3
// The LLVM Compiler Infrastructure
5
// This file is dual licensed under the MIT and the University of Illinois Open
6
// Source Licenses. See LICENSE.TXT for details.
9
// Processor specific interpretation of dwarf unwind info.
11
//===----------------------------------------------------------------------===//
13
#ifndef __DWARF_INSTRUCTIONS_HPP__
14
#define __DWARF_INSTRUCTIONS_HPP__
21
#include "AddressSpace.hpp"
22
#include "Registers.hpp"
23
#include "DwarfParser.hpp"
30
/// DwarfInstructions maps abtract dwarf unwind instructions to a particular
32
template <typename A, typename R>
33
class DwarfInstructions {
35
typedef typename A::pint_t pint_t;
36
typedef typename A::sint_t sint_t;
38
static int stepWithDwarf(A &addressSpace, pint_t pc, pint_t fdeStart,
44
DW_X86_64_RET_ADDR = 16
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;
56
static pint_t evaluateExpression(pint_t expression, A &addressSpace,
58
pint_t initialStackValue);
59
static pint_t getSavedRegister(A &addressSpace, const R ®isters,
60
pint_t cfa, const RegisterLocation &savedReg);
61
static double getSavedFloatRegister(A &addressSpace, const R ®isters,
62
pint_t cfa, const RegisterLocation &savedReg);
63
static v128 getSavedVectorRegister(A &addressSpace, const R ®isters,
64
pint_t cfa, const RegisterLocation &savedReg);
66
// x86 specific variants
67
static int lastRestoreReg(const Registers_x86 &);
68
static bool isReturnAddressRegister(int regNum, const Registers_x86 &);
69
static pint_t getCFA(A &addressSpace, const PrologInfo &prolog,
70
const Registers_x86 &);
72
// x86_64 specific variants
73
static int lastRestoreReg(const Registers_x86_64 &);
74
static bool isReturnAddressRegister(int regNum, const Registers_x86_64 &);
75
static pint_t getCFA(A &addressSpace,
76
const PrologInfo &prolog,
77
const Registers_x86_64 &);
79
// ppc specific variants
80
static int lastRestoreReg(const Registers_ppc &);
81
static bool isReturnAddressRegister(int regNum, const Registers_ppc &);
82
static pint_t getCFA(A &addressSpace,
83
const PrologInfo &prolog,
84
const Registers_ppc &);
86
// arm64 specific variants
87
static bool isReturnAddressRegister(int regNum, const Registers_arm64 &);
88
static int lastRestoreReg(const Registers_arm64 &);
89
static pint_t getCFA(A &addressSpace,
90
const PrologInfo &prolog,
91
const Registers_arm64 &);
96
template <typename A, typename R>
97
typename A::pint_t DwarfInstructions<A, R>::getSavedRegister(
98
A &addressSpace, const R ®isters, pint_t cfa,
99
const RegisterLocation &savedReg) {
100
switch (savedReg.location) {
101
case CFI_Parser<A>::kRegisterInCFA:
102
return addressSpace.getP(cfa + (pint_t)savedReg.value);
104
case CFI_Parser<A>::kRegisterAtExpression:
105
return addressSpace.getP(
106
evaluateExpression((pint_t)savedReg.value, addressSpace,
109
case CFI_Parser<A>::kRegisterIsExpression:
110
return evaluateExpression((pint_t)savedReg.value, addressSpace,
113
case CFI_Parser<A>::kRegisterInRegister:
114
return registers.getRegister((int)savedReg.value);
116
case CFI_Parser<A>::kRegisterUnused:
117
case CFI_Parser<A>::kRegisterOffsetFromCFA:
121
_LIBUNWIND_ABORT("unsupported restore location for register");
124
template <typename A, typename R>
125
double DwarfInstructions<A, R>::getSavedFloatRegister(
126
A &addressSpace, const R ®isters, pint_t cfa,
127
const RegisterLocation &savedReg) {
128
switch (savedReg.location) {
129
case CFI_Parser<A>::kRegisterInCFA:
130
return addressSpace.getDouble(cfa + (pint_t)savedReg.value);
132
case CFI_Parser<A>::kRegisterAtExpression:
133
return addressSpace.getDouble(
134
evaluateExpression((pint_t)savedReg.value, addressSpace,
137
case CFI_Parser<A>::kRegisterIsExpression:
138
case CFI_Parser<A>::kRegisterUnused:
139
case CFI_Parser<A>::kRegisterOffsetFromCFA:
140
case CFI_Parser<A>::kRegisterInRegister:
144
_LIBUNWIND_ABORT("unsupported restore location for float register");
147
template <typename A, typename R>
148
v128 DwarfInstructions<A, R>::getSavedVectorRegister(
149
A &addressSpace, const R ®isters, pint_t cfa,
150
const RegisterLocation &savedReg) {
151
switch (savedReg.location) {
152
case CFI_Parser<A>::kRegisterInCFA:
153
return addressSpace.getVector(cfa + (pint_t)savedReg.value);
155
case CFI_Parser<A>::kRegisterAtExpression:
156
return addressSpace.getVector(
157
evaluateExpression((pint_t)savedReg.value, addressSpace,
160
case CFI_Parser<A>::kRegisterIsExpression:
161
case CFI_Parser<A>::kRegisterUnused:
162
case CFI_Parser<A>::kRegisterOffsetFromCFA:
163
case CFI_Parser<A>::kRegisterInRegister:
167
_LIBUNWIND_ABORT("unsupported restore location for vector register");
170
template <typename A, typename R>
171
int DwarfInstructions<A, R>::stepWithDwarf(A &addressSpace, pint_t pc,
172
pint_t fdeStart, R ®isters) {
175
if (CFI_Parser<A>::decodeFDE(addressSpace, fdeStart,
176
&fdeInfo, &cieInfo) == NULL) {
178
if (CFI_Parser<A>::parseFDEInstructions(addressSpace, fdeInfo, cieInfo, pc,
180
R newRegisters = registers;
182
// get pointer to cfa (architecture specific)
183
pint_t cfa = getCFA(addressSpace, prolog, registers);
185
// restore registers that dwarf says were saved
186
pint_t returnAddress = 0;
187
for (int i = 0; i <= lastRestoreReg(newRegisters); ++i) {
188
if (prolog.savedRegisters[i].location !=
189
CFI_Parser<A>::kRegisterUnused) {
190
if (registers.validFloatRegister(i))
191
newRegisters.setFloatRegister(
192
i, getSavedFloatRegister(addressSpace, registers, cfa,
193
prolog.savedRegisters[i]));
194
else if (registers.validVectorRegister(i))
195
newRegisters.setVectorRegister(
196
i, getSavedVectorRegister(addressSpace, registers, cfa,
197
prolog.savedRegisters[i]));
198
else if (isReturnAddressRegister(i, registers))
199
returnAddress = getSavedRegister(addressSpace, registers, cfa,
200
prolog.savedRegisters[i]);
201
else if (registers.validRegister(i))
202
newRegisters.setRegister(
203
i, getSavedRegister(addressSpace, registers, cfa,
204
prolog.savedRegisters[i]));
210
// By definition, the CFA is the stack pointer at the call site, so
211
// restoring SP means setting it to CFA.
212
newRegisters.setSP(cfa);
214
// Return address is address after call site instruction, so setting IP to
215
// that does simualates a return.
216
newRegisters.setIP(returnAddress);
218
// Simulate the step by replacing the register set with the new ones.
219
registers = newRegisters;
221
return UNW_STEP_SUCCESS;
224
return UNW_EBADFRAME;
227
template <typename A, typename R>
229
DwarfInstructions<A, R>::evaluateExpression(pint_t expression, A &addressSpace,
231
pint_t initialStackValue) {
232
const bool log = false;
233
pint_t p = expression;
234
pint_t expressionEnd = expression + 20; // temp, until len read
235
pint_t length = (pint_t)addressSpace.getULEB128(p, expressionEnd);
236
expressionEnd = p + length;
238
fprintf(stderr, "evaluateExpression(): length=%llu\n", (uint64_t)length);
241
*(++sp) = initialStackValue;
243
while (p < expressionEnd) {
245
for (pint_t *t = sp; t > stack; --t) {
246
fprintf(stderr, "sp[] = 0x%llX\n", (uint64_t)(*t));
249
uint8_t opcode = addressSpace.get8(p++);
250
sint_t svalue, svalue2;
255
// push immediate address sized value
256
value = addressSpace.getP(p);
260
fprintf(stderr, "push 0x%llX\n", (uint64_t) value);
264
// pop stack, dereference, push result
266
*(++sp) = addressSpace.getP(value);
268
fprintf(stderr, "dereference 0x%llX\n", (uint64_t) value);
272
// push immediate 1 byte value
273
value = addressSpace.get8(p);
277
fprintf(stderr, "push 0x%llX\n", (uint64_t) value);
281
// push immediate 1 byte signed value
282
svalue = (int8_t) addressSpace.get8(p);
284
*(++sp) = (pint_t)svalue;
286
fprintf(stderr, "push 0x%llX\n", (uint64_t) svalue);
290
// push immediate 2 byte value
291
value = addressSpace.get16(p);
295
fprintf(stderr, "push 0x%llX\n", (uint64_t) value);
299
// push immediate 2 byte signed value
300
svalue = (int16_t) addressSpace.get16(p);
302
*(++sp) = (pint_t)svalue;
304
fprintf(stderr, "push 0x%llX\n", (uint64_t) svalue);
308
// push immediate 4 byte value
309
value = addressSpace.get32(p);
313
fprintf(stderr, "push 0x%llX\n", (uint64_t) value);
317
// push immediate 4 byte signed value
318
svalue = (int32_t)addressSpace.get32(p);
320
*(++sp) = (pint_t)svalue;
322
fprintf(stderr, "push 0x%llX\n", (uint64_t) svalue);
326
// push immediate 8 byte value
327
value = (pint_t)addressSpace.get64(p);
331
fprintf(stderr, "push 0x%llX\n", (uint64_t) value);
335
// push immediate 8 byte signed value
336
value = (pint_t)addressSpace.get64(p);
340
fprintf(stderr, "push 0x%llX\n", (uint64_t) value);
344
// push immediate ULEB128 value
345
value = (pint_t)addressSpace.getULEB128(p, expressionEnd);
348
fprintf(stderr, "push 0x%llX\n", (uint64_t) value);
352
// push immediate SLEB128 value
353
svalue = (sint_t)addressSpace.getSLEB128(p, expressionEnd);
354
*(++sp) = (pint_t)svalue;
356
fprintf(stderr, "push 0x%llX\n", (uint64_t) svalue);
364
fprintf(stderr, "duplicate top of stack\n");
371
fprintf(stderr, "pop top of stack\n");
379
fprintf(stderr, "duplicate second in stack\n");
384
reg = addressSpace.get8(p);
389
fprintf(stderr, "duplicate %d in stack\n", reg);
398
fprintf(stderr, "swap top of stack\n");
408
fprintf(stderr, "rotate top three of stack\n");
412
// pop stack, dereference, push result
414
*sp = *((pint_t*)value);
416
fprintf(stderr, "x-dereference 0x%llX\n", (uint64_t) value);
420
svalue = (sint_t)*sp;
422
*sp = (pint_t)(-svalue);
424
fprintf(stderr, "abs\n");
431
fprintf(stderr, "and\n");
435
svalue = (sint_t)(*sp--);
436
svalue2 = (sint_t)*sp;
437
*sp = (pint_t)(svalue2 / svalue);
439
fprintf(stderr, "div\n");
446
fprintf(stderr, "minus\n");
450
svalue = (sint_t)(*sp--);
451
svalue2 = (sint_t)*sp;
452
*sp = (pint_t)(svalue2 % svalue);
454
fprintf(stderr, "module\n");
458
svalue = (sint_t)(*sp--);
459
svalue2 = (sint_t)*sp;
460
*sp = (pint_t)(svalue2 * svalue);
462
fprintf(stderr, "mul\n");
468
fprintf(stderr, "neg\n");
472
svalue = (sint_t)(*sp);
473
*sp = (pint_t)(~svalue);
475
fprintf(stderr, "not\n");
482
fprintf(stderr, "or\n");
489
fprintf(stderr, "plus\n");
492
case DW_OP_plus_uconst:
493
// pop stack, add uelb128 constant, push result
494
*sp += addressSpace.getULEB128(p, expressionEnd);
496
fprintf(stderr, "add constant\n");
503
fprintf(stderr, "shift left\n");
510
fprintf(stderr, "shift left\n");
515
svalue = (sint_t)*sp;
516
*sp = (pint_t)(svalue >> value);
518
fprintf(stderr, "shift left arithmetric\n");
525
fprintf(stderr, "xor\n");
529
svalue = (int16_t) addressSpace.get16(p);
531
p = (pint_t)((sint_t)p + svalue);
533
fprintf(stderr, "skip %lld\n", (uint64_t) svalue);
537
svalue = (int16_t) addressSpace.get16(p);
540
p = (pint_t)((sint_t)p + svalue);
542
fprintf(stderr, "bra %lld\n", (uint64_t) svalue);
547
*sp = (*sp == value);
549
fprintf(stderr, "eq\n");
554
*sp = (*sp >= value);
556
fprintf(stderr, "ge\n");
563
fprintf(stderr, "gt\n");
568
*sp = (*sp <= value);
570
fprintf(stderr, "le\n");
577
fprintf(stderr, "lt\n");
582
*sp = (*sp != value);
584
fprintf(stderr, "ne\n");
619
value = opcode - DW_OP_lit0;
622
fprintf(stderr, "push literal 0x%llX\n", (uint64_t) value);
657
reg = opcode - DW_OP_reg0;
658
*(++sp) = registers.getRegister((int)reg);
660
fprintf(stderr, "push reg %d\n", reg);
664
reg = (uint32_t)addressSpace.getULEB128(p, expressionEnd);
665
*(++sp) = registers.getRegister((int)reg);
667
fprintf(stderr, "push reg %d + 0x%llX\n", reg, (uint64_t) svalue);
702
reg = opcode - DW_OP_breg0;
703
svalue = (sint_t)addressSpace.getSLEB128(p, expressionEnd);
704
svalue += registers.getRegister((int)reg);
705
*(++sp) = (pint_t)(svalue);
707
fprintf(stderr, "push reg %d + 0x%llX\n", reg, (uint64_t) svalue);
711
reg = (uint32_t)addressSpace.getULEB128(p, expressionEnd);
712
svalue = (sint_t)addressSpace.getSLEB128(p, expressionEnd);
713
svalue += registers.getRegister((int)reg);
714
*(++sp) = (pint_t)(svalue);
716
fprintf(stderr, "push reg %d + 0x%llX\n", reg, (uint64_t) svalue);
720
_LIBUNWIND_ABORT("DW_OP_fbreg not implemented");
724
_LIBUNWIND_ABORT("DW_OP_piece not implemented");
727
case DW_OP_deref_size:
728
// pop stack, dereference, push result
730
switch (addressSpace.get8(p++)) {
732
value = addressSpace.get8(value);
735
value = addressSpace.get16(value);
738
value = addressSpace.get32(value);
741
value = (pint_t)addressSpace.get64(value);
744
_LIBUNWIND_ABORT("DW_OP_deref_size with bad size");
748
fprintf(stderr, "sized dereference 0x%llX\n", (uint64_t) value);
751
case DW_OP_xderef_size:
753
case DW_OP_push_object_addres:
758
_LIBUNWIND_ABORT("dwarf opcode not implemented");
763
fprintf(stderr, "expression evaluates to 0x%llX\n", (uint64_t) * sp);
768
// x86_64 specific functions
770
template <typename A, typename R>
771
int DwarfInstructions<A, R>::lastRestoreReg(const Registers_x86_64 &) {
772
static_assert((int)CFI_Parser<A>::kMaxRegisterNumber
773
> (int)DW_X86_64_RET_ADDR, "register number out of range");
774
return DW_X86_64_RET_ADDR;
777
template <typename A, typename R>
779
DwarfInstructions<A, R>::isReturnAddressRegister(int regNum,
780
const Registers_x86_64 &) {
781
return (regNum == DW_X86_64_RET_ADDR);
784
template <typename A, typename R>
785
typename A::pint_t DwarfInstructions<A, R>::getCFA(
786
A &addressSpace, const PrologInfo &prolog,
787
const Registers_x86_64 ®isters) {
788
if (prolog.cfaRegister != 0)
789
return (pint_t)((sint_t)registers.getRegister((int)prolog.cfaRegister)
790
+ prolog.cfaRegisterOffset);
791
else if (prolog.cfaExpression != 0)
792
return evaluateExpression((pint_t)prolog.cfaExpression, addressSpace, registers, 0);
794
_LIBUNWIND_ABORT("getCFA(): unknown location for x86_64 cfa");
799
// x86 specific functions
801
template <typename A, typename R>
802
int DwarfInstructions<A, R>::lastRestoreReg(const Registers_x86 &) {
803
static_assert((int)CFI_Parser<A>::kMaxRegisterNumber
804
> (int)DW_X86_RET_ADDR, "register number out of range");
805
return DW_X86_RET_ADDR;
808
template <typename A, typename R>
809
bool DwarfInstructions<A, R>::isReturnAddressRegister(int regNum,
810
const Registers_x86 &) {
811
return (regNum == DW_X86_RET_ADDR);
814
template <typename A, typename R>
815
typename A::pint_t DwarfInstructions<A, R>::getCFA(
816
A &addressSpace, const PrologInfo &prolog,
817
const Registers_x86 ®isters) {
818
if (prolog.cfaRegister != 0)
819
return (pint_t)((sint_t)registers.getRegister((int)prolog.cfaRegister)
820
+ prolog.cfaRegisterOffset);
821
else if (prolog.cfaExpression != 0)
822
return evaluateExpression((pint_t)prolog.cfaExpression, addressSpace,
825
_LIBUNWIND_ABORT("getCFA(): unknown location for x86 cfa");
830
// ppc specific functions
832
template <typename A, typename R>
833
int DwarfInstructions<A, R>::lastRestoreReg(const Registers_ppc &) {
834
static_assert((int)CFI_Parser<A>::kMaxRegisterNumber
835
> (int)UNW_PPC_SPEFSCR, "register number out of range");
836
return UNW_PPC_SPEFSCR;
839
template <typename A, typename R>
840
bool DwarfInstructions<A, R>::isReturnAddressRegister(int regNum,
841
const Registers_ppc &) {
842
return (regNum == UNW_PPC_LR);
845
template <typename A, typename R>
846
typename A::pint_t DwarfInstructions<A, R>::getCFA(
847
A &addressSpace, const PrologInfo &prolog,
848
const Registers_ppc ®isters) {
849
if (prolog.cfaRegister != 0)
850
return registers.getRegister(prolog.cfaRegister) + prolog.cfaRegisterOffset;
851
else if (prolog.cfaExpression != 0)
852
return evaluateExpression((pint_t)prolog.cfaExpression, addressSpace,
855
_LIBUNWIND_ABORT("getCFA(): unknown location for ppc cfa");
861
// arm64 specific functions
863
template <typename A, typename R>
864
bool DwarfInstructions<A, R>::isReturnAddressRegister(int regNum,
865
const Registers_arm64 &) {
866
return (regNum == UNW_ARM64_LR);
869
template <typename A, typename R>
870
int DwarfInstructions<A, R>::lastRestoreReg(const Registers_arm64 &) {
871
static_assert((int)CFI_Parser<A>::kMaxRegisterNumber
872
> (int)UNW_ARM64_D31, "register number out of range");
873
return UNW_ARM64_D31;
876
template <typename A, typename R>
877
typename A::pint_t DwarfInstructions<A, R>::getCFA(A&, const PrologInfo &prolog,
878
const Registers_arm64 ®isters) {
879
if (prolog.cfaRegister != 0)
880
return registers.getRegister(prolog.cfaRegister) + prolog.cfaRegisterOffset;
882
_LIBUNWIND_ABORT("getCFA(): unsupported location for arm64 cfa");
886
} // namespace libunwind
888
#endif // __DWARF_INSTRUCTIONS_HPP__