~ubuntu-branches/ubuntu/trusty/emscripten/trusty-proposed

« back to all changes in this revision

Viewing changes to system/lib/libcxxabi/src/Unwind/DwarfInstructions.hpp

  • Committer: Package Import Robot
  • Author(s): Sylvestre Ledru
  • Date: 2014-01-19 14:12:40 UTC
  • mfrom: (1.2.4)
  • Revision ID: package-import@ubuntu.com-20140119141240-jg1l42cc158j59tn
Tags: 1.9.0~20140119~7dc8c2f-1
* New snapshot release (Closes: #733714)
* Provide sources for javascript and flash. Done in orig-tar.sh
  Available in third_party/websockify/include/web-socket-js/src/
  (Closes: #735903)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
//===-------------------------- DwarfInstructions.hpp ---------------------===//
 
2
//
 
3
//                     The LLVM Compiler Infrastructure
 
4
//
 
5
// This file is dual licensed under the MIT and the University of Illinois Open
 
6
// Source Licenses. See LICENSE.TXT for details.
 
7
//
 
8
//
 
9
//  Processor specific interpretation of dwarf unwind info.
 
10
//
 
11
//===----------------------------------------------------------------------===//
 
12
 
 
13
#ifndef __DWARF_INSTRUCTIONS_HPP__
 
14
#define __DWARF_INSTRUCTIONS_HPP__
 
15
 
 
16
#include <stdint.h>
 
17
#include <stdio.h>
 
18
#include <stdlib.h>
 
19
 
 
20
#include "dwarf2.h"
 
21
#include "AddressSpace.hpp"
 
22
#include "Registers.hpp"
 
23
#include "DwarfParser.hpp"
 
24
#include "config.h"
 
25
 
 
26
 
 
27
namespace libunwind {
 
28
 
 
29
 
 
30
/// DwarfInstructions maps abtract dwarf unwind instructions to a particular
 
31
/// architecture
 
32
template <typename A, typename R>
 
33
class DwarfInstructions {
 
34
public:
 
35
  typedef typename A::pint_t pint_t;
 
36
  typedef typename A::sint_t sint_t;
 
37
 
 
38
  static int stepWithDwarf(A &addressSpace, pint_t pc, pint_t fdeStart,
 
39
                           R &registers);
 
40
 
 
41
private:
 
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
  // 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 &);
 
71
 
 
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 &);
 
78
 
 
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 &);
 
85
 
 
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 &);
 
92
 
 
93
};
 
94
 
 
95
 
 
96
template <typename A, typename R>
 
97
typename A::pint_t DwarfInstructions<A, R>::getSavedRegister(
 
98
    A &addressSpace, const R &registers, 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);
 
103
 
 
104
  case CFI_Parser<A>::kRegisterAtExpression:
 
105
    return addressSpace.getP(
 
106
        evaluateExpression((pint_t)savedReg.value, addressSpace,
 
107
                            registers, cfa));
 
108
 
 
109
  case CFI_Parser<A>::kRegisterIsExpression:
 
110
    return evaluateExpression((pint_t)savedReg.value, addressSpace,
 
111
                              registers, cfa);
 
112
 
 
113
  case CFI_Parser<A>::kRegisterInRegister:
 
114
    return registers.getRegister((int)savedReg.value);
 
115
 
 
116
  case CFI_Parser<A>::kRegisterUnused:
 
117
  case CFI_Parser<A>::kRegisterOffsetFromCFA:
 
118
    // FIX ME
 
119
    break;
 
120
  }
 
121
  _LIBUNWIND_ABORT("unsupported restore location for register");
 
122
}
 
123
 
 
124
template <typename A, typename R>
 
125
double DwarfInstructions<A, R>::getSavedFloatRegister(
 
126
    A &addressSpace, const R &registers, 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);
 
131
 
 
132
  case CFI_Parser<A>::kRegisterAtExpression:
 
133
    return addressSpace.getDouble(
 
134
        evaluateExpression((pint_t)savedReg.value, addressSpace,
 
135
                            registers, cfa));
 
136
 
 
137
  case CFI_Parser<A>::kRegisterIsExpression:
 
138
  case CFI_Parser<A>::kRegisterUnused:
 
139
  case CFI_Parser<A>::kRegisterOffsetFromCFA:
 
140
  case CFI_Parser<A>::kRegisterInRegister:
 
141
    // FIX ME
 
142
    break;
 
143
  }
 
144
  _LIBUNWIND_ABORT("unsupported restore location for float register");
 
145
}
 
146
 
 
147
template <typename A, typename R>
 
148
v128 DwarfInstructions<A, R>::getSavedVectorRegister(
 
149
    A &addressSpace, const R &registers, 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);
 
154
 
 
155
  case CFI_Parser<A>::kRegisterAtExpression:
 
156
    return addressSpace.getVector(
 
157
        evaluateExpression((pint_t)savedReg.value, addressSpace,
 
158
                            registers, cfa));
 
159
 
 
160
  case CFI_Parser<A>::kRegisterIsExpression:
 
161
  case CFI_Parser<A>::kRegisterUnused:
 
162
  case CFI_Parser<A>::kRegisterOffsetFromCFA:
 
163
  case CFI_Parser<A>::kRegisterInRegister:
 
164
    // FIX ME
 
165
    break;
 
166
  }
 
167
  _LIBUNWIND_ABORT("unsupported restore location for vector register");
 
168
}
 
169
 
 
170
template <typename A, typename R>
 
171
int DwarfInstructions<A, R>::stepWithDwarf(A &addressSpace, pint_t pc,
 
172
                                           pint_t fdeStart, R &registers) {
 
173
  FDE_Info fdeInfo;
 
174
  CIE_Info cieInfo;
 
175
  if (CFI_Parser<A>::decodeFDE(addressSpace, fdeStart,
 
176
                                                  &fdeInfo, &cieInfo) == NULL) {
 
177
    PrologInfo prolog;
 
178
    if (CFI_Parser<A>::parseFDEInstructions(addressSpace, fdeInfo, cieInfo, pc,
 
179
                                                                     &prolog)) {
 
180
      R newRegisters = registers;
 
181
 
 
182
      // get pointer to cfa (architecture specific)
 
183
      pint_t cfa = getCFA(addressSpace, prolog, registers);
 
184
 
 
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]));
 
205
          else
 
206
            return UNW_EBADREG;
 
207
        }
 
208
      }
 
209
 
 
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);
 
213
 
 
214
      // Return address is address after call site instruction, so setting IP to
 
215
      // that does simualates a return.
 
216
      newRegisters.setIP(returnAddress);
 
217
 
 
218
      // Simulate the step by replacing the register set with the new ones.
 
219
      registers = newRegisters;
 
220
 
 
221
      return UNW_STEP_SUCCESS;
 
222
    }
 
223
  }
 
224
  return UNW_EBADFRAME;
 
225
}
 
226
 
 
227
template <typename A, typename R>
 
228
typename A::pint_t
 
229
DwarfInstructions<A, R>::evaluateExpression(pint_t expression, A &addressSpace,
 
230
                                            const R &registers,
 
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;
 
237
  if (log)
 
238
    fprintf(stderr, "evaluateExpression(): length=%llu\n", (uint64_t)length);
 
239
  pint_t stack[100];
 
240
  pint_t *sp = stack;
 
241
  *(++sp) = initialStackValue;
 
242
 
 
243
  while (p < expressionEnd) {
 
244
    if (log) {
 
245
      for (pint_t *t = sp; t > stack; --t) {
 
246
        fprintf(stderr, "sp[] = 0x%llX\n", (uint64_t)(*t));
 
247
      }
 
248
    }
 
249
    uint8_t opcode = addressSpace.get8(p++);
 
250
    sint_t svalue, svalue2;
 
251
    pint_t value;
 
252
    uint32_t reg;
 
253
    switch (opcode) {
 
254
    case DW_OP_addr:
 
255
      // push immediate address sized value
 
256
      value = addressSpace.getP(p);
 
257
      p += sizeof(pint_t);
 
258
      *(++sp) = value;
 
259
      if (log)
 
260
        fprintf(stderr, "push 0x%llX\n", (uint64_t) value);
 
261
      break;
 
262
 
 
263
    case DW_OP_deref:
 
264
      // pop stack, dereference, push result
 
265
      value = *sp--;
 
266
      *(++sp) = addressSpace.getP(value);
 
267
      if (log)
 
268
        fprintf(stderr, "dereference 0x%llX\n", (uint64_t) value);
 
269
      break;
 
270
 
 
271
    case DW_OP_const1u:
 
272
      // push immediate 1 byte value
 
273
      value = addressSpace.get8(p);
 
274
      p += 1;
 
275
      *(++sp) = value;
 
276
      if (log)
 
277
        fprintf(stderr, "push 0x%llX\n", (uint64_t) value);
 
278
      break;
 
279
 
 
280
    case DW_OP_const1s:
 
281
      // push immediate 1 byte signed value
 
282
      svalue = (int8_t) addressSpace.get8(p);
 
283
      p += 1;
 
284
      *(++sp) = (pint_t)svalue;
 
285
      if (log)
 
286
        fprintf(stderr, "push 0x%llX\n", (uint64_t) svalue);
 
287
      break;
 
288
 
 
289
    case DW_OP_const2u:
 
290
      // push immediate 2 byte value
 
291
      value = addressSpace.get16(p);
 
292
      p += 2;
 
293
      *(++sp) = value;
 
294
      if (log)
 
295
        fprintf(stderr, "push 0x%llX\n", (uint64_t) value);
 
296
      break;
 
297
 
 
298
    case DW_OP_const2s:
 
299
      // push immediate 2 byte signed value
 
300
      svalue = (int16_t) addressSpace.get16(p);
 
301
      p += 2;
 
302
      *(++sp) = (pint_t)svalue;
 
303
      if (log)
 
304
        fprintf(stderr, "push 0x%llX\n", (uint64_t) svalue);
 
305
      break;
 
306
 
 
307
    case DW_OP_const4u:
 
308
      // push immediate 4 byte value
 
309
      value = addressSpace.get32(p);
 
310
      p += 4;
 
311
      *(++sp) = value;
 
312
      if (log)
 
313
        fprintf(stderr, "push 0x%llX\n", (uint64_t) value);
 
314
      break;
 
315
 
 
316
    case DW_OP_const4s:
 
317
      // push immediate 4 byte signed value
 
318
      svalue = (int32_t)addressSpace.get32(p);
 
319
      p += 4;
 
320
      *(++sp) = (pint_t)svalue;
 
321
      if (log)
 
322
        fprintf(stderr, "push 0x%llX\n", (uint64_t) svalue);
 
323
      break;
 
324
 
 
325
    case DW_OP_const8u:
 
326
      // push immediate 8 byte value
 
327
      value = (pint_t)addressSpace.get64(p);
 
328
      p += 8;
 
329
      *(++sp) = value;
 
330
      if (log)
 
331
        fprintf(stderr, "push 0x%llX\n", (uint64_t) value);
 
332
      break;
 
333
 
 
334
    case DW_OP_const8s:
 
335
      // push immediate 8 byte signed value
 
336
      value = (pint_t)addressSpace.get64(p);
 
337
      p += 8;
 
338
      *(++sp) = value;
 
339
      if (log)
 
340
        fprintf(stderr, "push 0x%llX\n", (uint64_t) value);
 
341
      break;
 
342
 
 
343
    case DW_OP_constu:
 
344
      // push immediate ULEB128 value
 
345
      value = (pint_t)addressSpace.getULEB128(p, expressionEnd);
 
346
      *(++sp) = value;
 
347
      if (log)
 
348
        fprintf(stderr, "push 0x%llX\n", (uint64_t) value);
 
349
      break;
 
350
 
 
351
    case DW_OP_consts:
 
352
      // push immediate SLEB128 value
 
353
      svalue = (sint_t)addressSpace.getSLEB128(p, expressionEnd);
 
354
      *(++sp) = (pint_t)svalue;
 
355
      if (log)
 
356
        fprintf(stderr, "push 0x%llX\n", (uint64_t) svalue);
 
357
      break;
 
358
 
 
359
    case DW_OP_dup:
 
360
      // push top of stack
 
361
      value = *sp;
 
362
      *(++sp) = value;
 
363
      if (log)
 
364
        fprintf(stderr, "duplicate top of stack\n");
 
365
      break;
 
366
 
 
367
    case DW_OP_drop:
 
368
      // pop
 
369
      --sp;
 
370
      if (log)
 
371
        fprintf(stderr, "pop top of stack\n");
 
372
      break;
 
373
 
 
374
    case DW_OP_over:
 
375
      // dup second
 
376
      value = sp[-1];
 
377
      *(++sp) = value;
 
378
      if (log)
 
379
        fprintf(stderr, "duplicate second in stack\n");
 
380
      break;
 
381
 
 
382
    case DW_OP_pick:
 
383
      // pick from
 
384
      reg = addressSpace.get8(p);
 
385
      p += 1;
 
386
      value = sp[-reg];
 
387
      *(++sp) = value;
 
388
      if (log)
 
389
        fprintf(stderr, "duplicate %d in stack\n", reg);
 
390
      break;
 
391
 
 
392
    case DW_OP_swap:
 
393
      // swap top two
 
394
      value = sp[0];
 
395
      sp[0] = sp[-1];
 
396
      sp[-1] = value;
 
397
      if (log)
 
398
        fprintf(stderr, "swap top of stack\n");
 
399
      break;
 
400
 
 
401
    case DW_OP_rot:
 
402
      // rotate top three
 
403
      value = sp[0];
 
404
      sp[0] = sp[-1];
 
405
      sp[-1] = sp[-2];
 
406
      sp[-2] = value;
 
407
      if (log)
 
408
        fprintf(stderr, "rotate top three of stack\n");
 
409
      break;
 
410
 
 
411
    case DW_OP_xderef:
 
412
      // pop stack, dereference, push result
 
413
      value = *sp--;
 
414
      *sp = *((pint_t*)value);
 
415
      if (log)
 
416
        fprintf(stderr, "x-dereference 0x%llX\n", (uint64_t) value);
 
417
      break;
 
418
 
 
419
    case DW_OP_abs:
 
420
      svalue = (sint_t)*sp;
 
421
      if (svalue < 0)
 
422
        *sp = (pint_t)(-svalue);
 
423
      if (log)
 
424
        fprintf(stderr, "abs\n");
 
425
      break;
 
426
 
 
427
    case DW_OP_and:
 
428
      value = *sp--;
 
429
      *sp &= value;
 
430
      if (log)
 
431
        fprintf(stderr, "and\n");
 
432
      break;
 
433
 
 
434
    case DW_OP_div:
 
435
      svalue = (sint_t)(*sp--);
 
436
      svalue2 = (sint_t)*sp;
 
437
      *sp = (pint_t)(svalue2 / svalue);
 
438
      if (log)
 
439
        fprintf(stderr, "div\n");
 
440
      break;
 
441
 
 
442
    case DW_OP_minus:
 
443
      value = *sp--;
 
444
      *sp = *sp - value;
 
445
      if (log)
 
446
        fprintf(stderr, "minus\n");
 
447
      break;
 
448
 
 
449
    case DW_OP_mod:
 
450
      svalue = (sint_t)(*sp--);
 
451
      svalue2 = (sint_t)*sp;
 
452
      *sp = (pint_t)(svalue2 % svalue);
 
453
      if (log)
 
454
        fprintf(stderr, "module\n");
 
455
      break;
 
456
 
 
457
    case DW_OP_mul:
 
458
      svalue = (sint_t)(*sp--);
 
459
      svalue2 = (sint_t)*sp;
 
460
      *sp = (pint_t)(svalue2 * svalue);
 
461
      if (log)
 
462
        fprintf(stderr, "mul\n");
 
463
      break;
 
464
 
 
465
    case DW_OP_neg:
 
466
      *sp = 0 - *sp;
 
467
      if (log)
 
468
        fprintf(stderr, "neg\n");
 
469
      break;
 
470
 
 
471
    case DW_OP_not:
 
472
      svalue = (sint_t)(*sp);
 
473
      *sp = (pint_t)(~svalue);
 
474
      if (log)
 
475
        fprintf(stderr, "not\n");
 
476
      break;
 
477
 
 
478
    case DW_OP_or:
 
479
      value = *sp--;
 
480
      *sp |= value;
 
481
      if (log)
 
482
        fprintf(stderr, "or\n");
 
483
      break;
 
484
 
 
485
    case DW_OP_plus:
 
486
      value = *sp--;
 
487
      *sp += value;
 
488
      if (log)
 
489
        fprintf(stderr, "plus\n");
 
490
      break;
 
491
 
 
492
    case DW_OP_plus_uconst:
 
493
      // pop stack, add uelb128 constant, push result
 
494
      *sp += addressSpace.getULEB128(p, expressionEnd);
 
495
      if (log)
 
496
        fprintf(stderr, "add constant\n");
 
497
      break;
 
498
 
 
499
    case DW_OP_shl:
 
500
      value = *sp--;
 
501
      *sp = *sp << value;
 
502
      if (log)
 
503
        fprintf(stderr, "shift left\n");
 
504
      break;
 
505
 
 
506
    case DW_OP_shr:
 
507
      value = *sp--;
 
508
      *sp = *sp >> value;
 
509
      if (log)
 
510
        fprintf(stderr, "shift left\n");
 
511
      break;
 
512
 
 
513
    case DW_OP_shra:
 
514
      value = *sp--;
 
515
      svalue = (sint_t)*sp;
 
516
      *sp = (pint_t)(svalue >> value);
 
517
      if (log)
 
518
        fprintf(stderr, "shift left arithmetric\n");
 
519
      break;
 
520
 
 
521
    case DW_OP_xor:
 
522
      value = *sp--;
 
523
      *sp ^= value;
 
524
      if (log)
 
525
        fprintf(stderr, "xor\n");
 
526
      break;
 
527
 
 
528
    case DW_OP_skip:
 
529
      svalue = (int16_t) addressSpace.get16(p);
 
530
      p += 2;
 
531
      p = (pint_t)((sint_t)p + svalue);
 
532
      if (log)
 
533
        fprintf(stderr, "skip %lld\n", (uint64_t) svalue);
 
534
      break;
 
535
 
 
536
    case DW_OP_bra:
 
537
      svalue = (int16_t) addressSpace.get16(p);
 
538
      p += 2;
 
539
      if (*sp--)
 
540
        p = (pint_t)((sint_t)p + svalue);
 
541
      if (log)
 
542
        fprintf(stderr, "bra %lld\n", (uint64_t) svalue);
 
543
      break;
 
544
 
 
545
    case DW_OP_eq:
 
546
      value = *sp--;
 
547
      *sp = (*sp == value);
 
548
      if (log)
 
549
        fprintf(stderr, "eq\n");
 
550
      break;
 
551
 
 
552
    case DW_OP_ge:
 
553
      value = *sp--;
 
554
      *sp = (*sp >= value);
 
555
      if (log)
 
556
        fprintf(stderr, "ge\n");
 
557
      break;
 
558
 
 
559
    case DW_OP_gt:
 
560
      value = *sp--;
 
561
      *sp = (*sp > value);
 
562
      if (log)
 
563
        fprintf(stderr, "gt\n");
 
564
      break;
 
565
 
 
566
    case DW_OP_le:
 
567
      value = *sp--;
 
568
      *sp = (*sp <= value);
 
569
      if (log)
 
570
        fprintf(stderr, "le\n");
 
571
      break;
 
572
 
 
573
    case DW_OP_lt:
 
574
      value = *sp--;
 
575
      *sp = (*sp < value);
 
576
      if (log)
 
577
        fprintf(stderr, "lt\n");
 
578
      break;
 
579
 
 
580
    case DW_OP_ne:
 
581
      value = *sp--;
 
582
      *sp = (*sp != value);
 
583
      if (log)
 
584
        fprintf(stderr, "ne\n");
 
585
      break;
 
586
 
 
587
    case DW_OP_lit0:
 
588
    case DW_OP_lit1:
 
589
    case DW_OP_lit2:
 
590
    case DW_OP_lit3:
 
591
    case DW_OP_lit4:
 
592
    case DW_OP_lit5:
 
593
    case DW_OP_lit6:
 
594
    case DW_OP_lit7:
 
595
    case DW_OP_lit8:
 
596
    case DW_OP_lit9:
 
597
    case DW_OP_lit10:
 
598
    case DW_OP_lit11:
 
599
    case DW_OP_lit12:
 
600
    case DW_OP_lit13:
 
601
    case DW_OP_lit14:
 
602
    case DW_OP_lit15:
 
603
    case DW_OP_lit16:
 
604
    case DW_OP_lit17:
 
605
    case DW_OP_lit18:
 
606
    case DW_OP_lit19:
 
607
    case DW_OP_lit20:
 
608
    case DW_OP_lit21:
 
609
    case DW_OP_lit22:
 
610
    case DW_OP_lit23:
 
611
    case DW_OP_lit24:
 
612
    case DW_OP_lit25:
 
613
    case DW_OP_lit26:
 
614
    case DW_OP_lit27:
 
615
    case DW_OP_lit28:
 
616
    case DW_OP_lit29:
 
617
    case DW_OP_lit30:
 
618
    case DW_OP_lit31:
 
619
      value = opcode - DW_OP_lit0;
 
620
      *(++sp) = value;
 
621
      if (log)
 
622
        fprintf(stderr, "push literal 0x%llX\n", (uint64_t) value);
 
623
      break;
 
624
 
 
625
    case DW_OP_reg0:
 
626
    case DW_OP_reg1:
 
627
    case DW_OP_reg2:
 
628
    case DW_OP_reg3:
 
629
    case DW_OP_reg4:
 
630
    case DW_OP_reg5:
 
631
    case DW_OP_reg6:
 
632
    case DW_OP_reg7:
 
633
    case DW_OP_reg8:
 
634
    case DW_OP_reg9:
 
635
    case DW_OP_reg10:
 
636
    case DW_OP_reg11:
 
637
    case DW_OP_reg12:
 
638
    case DW_OP_reg13:
 
639
    case DW_OP_reg14:
 
640
    case DW_OP_reg15:
 
641
    case DW_OP_reg16:
 
642
    case DW_OP_reg17:
 
643
    case DW_OP_reg18:
 
644
    case DW_OP_reg19:
 
645
    case DW_OP_reg20:
 
646
    case DW_OP_reg21:
 
647
    case DW_OP_reg22:
 
648
    case DW_OP_reg23:
 
649
    case DW_OP_reg24:
 
650
    case DW_OP_reg25:
 
651
    case DW_OP_reg26:
 
652
    case DW_OP_reg27:
 
653
    case DW_OP_reg28:
 
654
    case DW_OP_reg29:
 
655
    case DW_OP_reg30:
 
656
    case DW_OP_reg31:
 
657
      reg = opcode - DW_OP_reg0;
 
658
      *(++sp) = registers.getRegister((int)reg);
 
659
      if (log)
 
660
        fprintf(stderr, "push reg %d\n", reg);
 
661
      break;
 
662
 
 
663
    case DW_OP_regx:
 
664
      reg = (uint32_t)addressSpace.getULEB128(p, expressionEnd);
 
665
      *(++sp) = registers.getRegister((int)reg);
 
666
      if (log)
 
667
        fprintf(stderr, "push reg %d + 0x%llX\n", reg, (uint64_t) svalue);
 
668
      break;
 
669
 
 
670
    case DW_OP_breg0:
 
671
    case DW_OP_breg1:
 
672
    case DW_OP_breg2:
 
673
    case DW_OP_breg3:
 
674
    case DW_OP_breg4:
 
675
    case DW_OP_breg5:
 
676
    case DW_OP_breg6:
 
677
    case DW_OP_breg7:
 
678
    case DW_OP_breg8:
 
679
    case DW_OP_breg9:
 
680
    case DW_OP_breg10:
 
681
    case DW_OP_breg11:
 
682
    case DW_OP_breg12:
 
683
    case DW_OP_breg13:
 
684
    case DW_OP_breg14:
 
685
    case DW_OP_breg15:
 
686
    case DW_OP_breg16:
 
687
    case DW_OP_breg17:
 
688
    case DW_OP_breg18:
 
689
    case DW_OP_breg19:
 
690
    case DW_OP_breg20:
 
691
    case DW_OP_breg21:
 
692
    case DW_OP_breg22:
 
693
    case DW_OP_breg23:
 
694
    case DW_OP_breg24:
 
695
    case DW_OP_breg25:
 
696
    case DW_OP_breg26:
 
697
    case DW_OP_breg27:
 
698
    case DW_OP_breg28:
 
699
    case DW_OP_breg29:
 
700
    case DW_OP_breg30:
 
701
    case DW_OP_breg31:
 
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);
 
706
      if (log)
 
707
        fprintf(stderr, "push reg %d + 0x%llX\n", reg, (uint64_t) svalue);
 
708
      break;
 
709
 
 
710
    case DW_OP_bregx:
 
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);
 
715
      if (log)
 
716
        fprintf(stderr, "push reg %d + 0x%llX\n", reg, (uint64_t) svalue);
 
717
      break;
 
718
 
 
719
    case DW_OP_fbreg:
 
720
      _LIBUNWIND_ABORT("DW_OP_fbreg not implemented");
 
721
      break;
 
722
 
 
723
    case DW_OP_piece:
 
724
      _LIBUNWIND_ABORT("DW_OP_piece not implemented");
 
725
      break;
 
726
 
 
727
    case DW_OP_deref_size:
 
728
      // pop stack, dereference, push result
 
729
      value = *sp--;
 
730
      switch (addressSpace.get8(p++)) {
 
731
      case 1:
 
732
        value = addressSpace.get8(value);
 
733
        break;
 
734
      case 2:
 
735
        value = addressSpace.get16(value);
 
736
        break;
 
737
      case 4:
 
738
        value = addressSpace.get32(value);
 
739
        break;
 
740
      case 8:
 
741
        value = (pint_t)addressSpace.get64(value);
 
742
        break;
 
743
      default:
 
744
        _LIBUNWIND_ABORT("DW_OP_deref_size with bad size");
 
745
      }
 
746
      *(++sp) = value;
 
747
      if (log)
 
748
        fprintf(stderr, "sized dereference 0x%llX\n", (uint64_t) value);
 
749
      break;
 
750
 
 
751
    case DW_OP_xderef_size:
 
752
    case DW_OP_nop:
 
753
    case DW_OP_push_object_addres:
 
754
    case DW_OP_call2:
 
755
    case DW_OP_call4:
 
756
    case DW_OP_call_ref:
 
757
    default:
 
758
      _LIBUNWIND_ABORT("dwarf opcode not implemented");
 
759
    }
 
760
 
 
761
  }
 
762
  if (log)
 
763
    fprintf(stderr, "expression evaluates to 0x%llX\n", (uint64_t) * sp);
 
764
  return *sp;
 
765
}
 
766
 
 
767
//
 
768
//  x86_64 specific functions
 
769
//
 
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;
 
775
}
 
776
 
 
777
template <typename A, typename R>
 
778
bool
 
779
DwarfInstructions<A, R>::isReturnAddressRegister(int regNum,
 
780
                                                 const Registers_x86_64 &) {
 
781
  return (regNum == DW_X86_64_RET_ADDR);
 
782
}
 
783
 
 
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 &registers) {
 
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);
 
793
  else
 
794
    _LIBUNWIND_ABORT("getCFA(): unknown location for x86_64 cfa");
 
795
}
 
796
 
 
797
 
 
798
//
 
799
//  x86 specific functions
 
800
//
 
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;
 
806
}
 
807
 
 
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);
 
812
}
 
813
 
 
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 &registers) {
 
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,
 
823
                                                                  registers, 0);
 
824
  else
 
825
    _LIBUNWIND_ABORT("getCFA(): unknown location for x86 cfa");
 
826
}
 
827
 
 
828
 
 
829
//
 
830
//  ppc specific functions
 
831
//
 
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;
 
837
}
 
838
 
 
839
template <typename A, typename R>
 
840
bool DwarfInstructions<A, R>::isReturnAddressRegister(int regNum,
 
841
                                                      const Registers_ppc &) {
 
842
  return (regNum == UNW_PPC_LR);
 
843
}
 
844
 
 
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 &registers) {
 
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,
 
853
                                                                  registers, 0);
 
854
  else
 
855
    _LIBUNWIND_ABORT("getCFA(): unknown location for ppc cfa");
 
856
}
 
857
 
 
858
 
 
859
 
 
860
//
 
861
// arm64 specific functions
 
862
//
 
863
template <typename A, typename R>
 
864
bool DwarfInstructions<A, R>::isReturnAddressRegister(int regNum,
 
865
                                                      const Registers_arm64 &) {
 
866
  return (regNum == UNW_ARM64_LR);
 
867
}
 
868
 
 
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;
 
874
}
 
875
 
 
876
template <typename A, typename R>
 
877
typename A::pint_t DwarfInstructions<A, R>::getCFA(A&, const PrologInfo &prolog,
 
878
                                             const Registers_arm64 &registers) {
 
879
  if (prolog.cfaRegister != 0)
 
880
    return registers.getRegister(prolog.cfaRegister) + prolog.cfaRegisterOffset;
 
881
  else
 
882
    _LIBUNWIND_ABORT("getCFA(): unsupported location for arm64 cfa");
 
883
}
 
884
 
 
885
 
 
886
} // namespace libunwind
 
887
 
 
888
#endif // __DWARF_INSTRUCTIONS_HPP__