Coverage Report

Created: 2026-10-28 07:09

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libunwind/src/dwarf/Gparser.c
Line
Count
Source
1
/* libunwind - a platform-independent unwind library
2
   Copyright (c) 2003, 2005 Hewlett-Packard Development Company, L.P.
3
        Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
4
5
This file is part of libunwind.
6
7
Permission is hereby granted, free of charge, to any person obtaining
8
a copy of this software and associated documentation files (the
9
"Software"), to deal in the Software without restriction, including
10
without limitation the rights to use, copy, modify, merge, publish,
11
distribute, sublicense, and/or sell copies of the Software, and to
12
permit persons to whom the Software is furnished to do so, subject to
13
the following conditions:
14
15
The above copyright notice and this permission notice shall be
16
included in all copies or substantial portions of the Software.
17
18
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
22
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
23
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
24
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
25
26
#include "dwarf_i.h"
27
#include "libunwind_i.h"
28
#include <stddef.h>
29
#include <limits.h>
30
31
0
#define alloc_reg_state()       (mempool_alloc (&dwarf_reg_state_pool))
32
0
#define free_reg_state(rs)      (mempool_free (&dwarf_reg_state_pool, rs))
33
34
6.87k
#define DWARF_UNW_CACHE_SIZE(log_size)   (1 << log_size)
35
257
#define DWARF_UNW_HASH_SIZE(log_size)    (1 << (log_size + 1))
36
37
/* Read a register number that names the base register of the CFA.  The
38
   unwind cannot continue without it, so an unrepresentable one is fatal.  */
39
static inline int
40
read_cfa_regnum (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr,
41
                 unw_word_t *valp, void *arg)
42
30
{
43
30
  int ret;
44
45
30
  if ((ret = dwarf_read_uleb128 (as, a, addr, valp, arg)) < 0)
46
0
    return ret;
47
48
30
  if (*valp >= DWARF_NUM_PRESERVED_REGS)
49
0
    {
50
0
      Debug (1, "Invalid CFA register number %u\n", (unsigned int) *valp);
51
0
      return -UNW_EBADREG;
52
0
    }
53
30
  return 0;
54
30
}
55
56
/* Read a register number that names a saved register.  A target need not
57
   have a slot for every register the producer describes, so the rule for
58
   one we cannot represent is dropped rather than failing the whole FDE.
59
   See set_savedreg().  */
60
static inline int
61
read_regnum (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr,
62
             unw_word_t *valp, void *arg)
63
1
{
64
1
  return dwarf_read_uleb128 (as, a, addr, valp, arg);
65
1
}
66
67
static inline void
68
set_reg (dwarf_state_record_t *sr, unw_word_t regnum, dwarf_where_t where,
69
         unw_word_t val)
70
442
{
71
442
  sr->rs_current.reg.where[regnum] = where;
72
442
  sr->rs_current.reg.val[regnum] = val;
73
442
}
74
75
/* Record the rule for a saved register, ignoring registers this target has
76
   no slot for.  */
77
static inline void
78
set_savedreg (dwarf_state_record_t *sr, unw_word_t regnum, dwarf_where_t where,
79
              unw_word_t val)
80
75
{
81
75
  if (regnum >= DWARF_NUM_PRESERVED_REGS)
82
0
    {
83
0
      Debug (15, "ignoring rule for unrepresentable register r%lu\n",
84
0
             (long) regnum);
85
0
      return;
86
0
    }
87
75
  set_reg (sr, regnum, where, val);
88
75
}
89
90
/* Restore the rule a saved register had at the start of the FDE, ignoring
91
   registers this target has no slot for.  */
92
static inline void
93
restore_savedreg (dwarf_state_record_t *sr, unw_word_t regnum)
94
0
{
95
0
  if (regnum >= DWARF_NUM_PRESERVED_REGS)
96
0
    {
97
0
      Debug (15, "ignoring restore of unrepresentable register r%lu\n",
98
0
             (long) regnum);
99
0
      return;
100
0
    }
101
0
  sr->rs_current.reg.where[regnum] = sr->rs_initial.reg.where[regnum];
102
0
  sr->rs_current.reg.val[regnum] = sr->rs_initial.reg.val[regnum];
103
0
}
104
105
static inline int
106
push_rstate_stack(dwarf_stackable_reg_state_t **rs_stack)
107
0
{
108
0
  dwarf_stackable_reg_state_t *old_rs = *rs_stack;
109
0
  if (NULL == (*rs_stack = alloc_reg_state ()))
110
0
    {
111
0
      *rs_stack = old_rs;
112
0
      return -1;
113
0
    }
114
0
  (*rs_stack)->next = old_rs;
115
0
  return 0;
116
0
}
117
118
static inline void
119
pop_rstate_stack(dwarf_stackable_reg_state_t **rs_stack)
120
0
{
121
0
  dwarf_stackable_reg_state_t *old_rs = *rs_stack;
122
0
  *rs_stack = old_rs->next;
123
0
  free_reg_state (old_rs);
124
0
}
125
126
static inline void
127
empty_rstate_stack(dwarf_stackable_reg_state_t **rs_stack)
128
30
{
129
30
  while (*rs_stack)
130
0
    pop_rstate_stack(rs_stack);
131
30
}
132
133
#ifdef UNW_TARGET_AARCH64
134
135
static void
136
aarch64_negate_ra_sign_state(dwarf_state_record_t *sr);
137
138
#endif
139
140
/* Run a CFI program to update the register state.  */
141
static int
142
run_cfi_program (struct dwarf_cursor *c, dwarf_state_record_t *sr,
143
                 unw_word_t *ip, unw_word_t end_ip,
144
     unw_word_t *addr, unw_word_t end_addr,
145
     dwarf_stackable_reg_state_t **rs_stack,
146
                 struct dwarf_cie_info *dci)
147
30
{
148
30
  unw_addr_space_t as;
149
30
  void *arg;
150
151
30
  if (c->pi.flags & UNW_PI_FLAG_DEBUG_FRAME)
152
0
    {
153
      /* .debug_frame CFI is stored in local address space.  */
154
0
      as = unw_local_addr_space;
155
0
      arg = NULL;
156
0
    }
157
30
  else
158
30
    {
159
30
      as = c->as;
160
30
      arg = c->as_arg;
161
30
    }
162
30
  unw_accessors_t *a = unw_get_accessors_int (as);
163
30
  int ret = 0;
164
165
252
  while (*ip <= end_ip && *addr < end_addr && ret >= 0)
166
222
    {
167
222
      unw_word_t operand = 0, regnum, val, len;
168
222
      uint8_t u8, op;
169
222
      uint16_t u16;
170
222
      uint32_t u32;
171
172
222
      if ((ret = dwarf_readu8 (as, a, addr, &op, arg)) < 0)
173
0
        break;
174
175
222
      if (op & DWARF_CFA_OPCODE_MASK)
176
122
        {
177
122
          operand = op & DWARF_CFA_OPERAND_MASK;
178
122
          op &= ~DWARF_CFA_OPERAND_MASK;
179
122
        }
180
222
      switch ((dwarf_cfa_t) op)
181
222
        {
182
48
        case DW_CFA_advance_loc:
183
48
          *ip += operand * dci->code_align;
184
48
          Debug (15, "CFA_advance_loc to 0x%lx\n", (long) *ip);
185
48
          break;
186
187
5
        case DW_CFA_advance_loc1:
188
5
          if ((ret = dwarf_readu8 (as, a, addr, &u8, arg)) < 0)
189
0
            break;
190
5
          *ip += u8 * dci->code_align;
191
5
          Debug (15, "CFA_advance_loc1 to 0x%lx\n", (long) *ip);
192
5
          break;
193
194
7
        case DW_CFA_advance_loc2:
195
7
          if ((ret = dwarf_readu16 (as, a, addr, &u16, arg)) < 0)
196
0
            break;
197
7
          *ip += u16 * dci->code_align;
198
7
          Debug (15, "CFA_advance_loc2 to 0x%lx\n", (long) *ip);
199
7
          break;
200
201
0
        case DW_CFA_advance_loc4:
202
0
          if ((ret = dwarf_readu32 (as, a, addr, &u32, arg)) < 0)
203
0
            break;
204
0
          *ip += u32 * dci->code_align;
205
0
          Debug (15, "CFA_advance_loc4 to 0x%lx\n", (long) *ip);
206
0
          break;
207
208
0
        case DW_CFA_MIPS_advance_loc8:
209
#ifdef UNW_TARGET_MIPS
210
          {
211
            uint64_t u64 = 0;
212
213
            if ((ret = dwarf_readu64 (as, a, addr, &u64, arg)) < 0)
214
              break;
215
            *ip += u64 * dci->code_align;
216
            Debug (15, "CFA_MIPS_advance_loc8\n");
217
            break;
218
          }
219
#else
220
0
          Debug (1, "DW_CFA_MIPS_advance_loc8 on non-MIPS target\n");
221
0
          ret = -UNW_EINVAL;
222
0
          break;
223
0
#endif
224
225
74
        case DW_CFA_offset:
226
74
          regnum = operand;
227
74
          if ((ret = dwarf_read_uleb128 (as, a, addr, &val, arg)) < 0)
228
0
            break;
229
74
          set_savedreg (sr, regnum, DWARF_WHERE_CFAREL, val * dci->data_align);
230
74
          Debug (15, "CFA_offset r%lu at cfa+0x%lx\n",
231
74
                 (long) regnum, (long) (val * dci->data_align));
232
74
          break;
233
234
0
        case DW_CFA_offset_extended:
235
0
          if (((ret = read_regnum (as, a, addr, &regnum, arg)) < 0)
236
0
              || ((ret = dwarf_read_uleb128 (as, a, addr, &val, arg)) < 0))
237
0
            break;
238
0
          set_savedreg (sr, regnum, DWARF_WHERE_CFAREL, val * dci->data_align);
239
0
          Debug (15, "CFA_offset_extended r%lu at cf+0x%lx\n",
240
0
                 (long) regnum, (long) (val * dci->data_align));
241
0
          break;
242
243
0
        case DW_CFA_offset_extended_sf:
244
0
          if (((ret = read_regnum (as, a, addr, &regnum, arg)) < 0)
245
0
              || ((ret = dwarf_read_sleb128 (as, a, addr, &val, arg)) < 0))
246
0
            break;
247
0
          set_savedreg (sr, regnum, DWARF_WHERE_CFAREL, val * dci->data_align);
248
0
          Debug (15, "CFA_offset_extended_sf r%lu at cf+0x%lx\n",
249
0
                 (long) regnum, (long) (val * dci->data_align));
250
0
          break;
251
252
0
        case DW_CFA_restore:
253
0
          regnum = operand;
254
0
          restore_savedreg (sr, regnum);
255
0
          Debug (15, "CFA_restore r%lu\n", (long) regnum);
256
0
          break;
257
258
0
        case DW_CFA_restore_extended:
259
0
          if ((ret = dwarf_read_uleb128 (as, a, addr, &regnum, arg)) < 0)
260
0
            break;
261
0
          restore_savedreg (sr, regnum);
262
0
          Debug (15, "CFA_restore_extended r%lu\n", (long) regnum);
263
0
          break;
264
265
37
        case DW_CFA_nop:
266
37
          break;
267
268
0
        case DW_CFA_set_loc:
269
0
          if ((ret = dwarf_read_encoded_pointer (as, a, addr, dci->fde_encoding,
270
0
                                                 &c->pi, ip,
271
0
                                                 arg)) < 0)
272
0
            break;
273
0
          Debug (15, "CFA_set_loc to 0x%lx\n", (long) *ip);
274
0
          break;
275
276
1
        case DW_CFA_undefined:
277
1
          if ((ret = read_regnum (as, a, addr, &regnum, arg)) < 0)
278
0
            break;
279
1
          set_savedreg (sr, regnum, DWARF_WHERE_UNDEF, 0);
280
1
          Debug (15, "CFA_undefined r%lu\n", (long) regnum);
281
1
          break;
282
283
0
        case DW_CFA_same_value:
284
0
          if ((ret = read_regnum (as, a, addr, &regnum, arg)) < 0)
285
0
            break;
286
0
          set_savedreg (sr, regnum, DWARF_WHERE_SAME, 0);
287
0
          Debug (15, "CFA_same_value r%lu\n", (long) regnum);
288
0
          break;
289
290
0
        case DW_CFA_register:
291
0
          if (((ret = read_regnum (as, a, addr, &regnum, arg)) < 0)
292
0
              || ((ret = dwarf_read_uleb128 (as, a, addr, &val, arg)) < 0))
293
0
            break;
294
0
          set_savedreg (sr, regnum, DWARF_WHERE_REG, val);
295
0
          Debug (15, "CFA_register r%lu to r%lu\n", (long) regnum, (long) val);
296
0
          break;
297
298
0
        case DW_CFA_remember_state:
299
0
    if (push_rstate_stack(rs_stack) < 0)
300
0
      {
301
0
              Debug (1, "Out of memory in DW_CFA_remember_state\n");
302
0
              ret = -UNW_ENOMEM;
303
0
              break;
304
0
      }
305
0
          (*rs_stack)->state = sr->rs_current;
306
0
          Debug (15, "CFA_remember_state\n");
307
0
          break;
308
309
0
        case DW_CFA_restore_state:
310
0
          if (!*rs_stack)
311
0
            {
312
0
              Debug (1, "register-state stack underflow\n");
313
0
              ret = -UNW_EINVAL;
314
0
              break;
315
0
            }
316
0
          sr->rs_current = (*rs_stack)->state;
317
0
          pop_rstate_stack(rs_stack);
318
0
          Debug (15, "CFA_restore_state\n");
319
0
          break;
320
321
17
        case DW_CFA_def_cfa:
322
17
          if (((ret = read_cfa_regnum (as, a, addr, &regnum, arg)) < 0)
323
17
              || ((ret = dwarf_read_uleb128 (as, a, addr, &val, arg)) < 0))
324
0
            break;
325
17
          set_reg (sr, DWARF_CFA_REG_COLUMN, DWARF_WHERE_REG, regnum);
326
17
          set_reg (sr, DWARF_CFA_OFF_COLUMN, 0, val);   /* NOT factored! */
327
17
          Debug (15, "CFA_def_cfa r%lu+0x%lx\n", (long) regnum, (long) val);
328
17
          break;
329
330
0
        case DW_CFA_def_cfa_sf:
331
0
          if (((ret = read_cfa_regnum (as, a, addr, &regnum, arg)) < 0)
332
0
              || ((ret = dwarf_read_sleb128 (as, a, addr, &val, arg)) < 0))
333
0
            break;
334
0
          set_reg (sr, DWARF_CFA_REG_COLUMN, DWARF_WHERE_REG, regnum);
335
0
          set_reg (sr, DWARF_CFA_OFF_COLUMN, 0,
336
0
                   val * dci->data_align);              /* factored! */
337
0
          Debug (15, "CFA_def_cfa_sf r%lu+0x%lx\n",
338
0
                 (long) regnum, (long) (val * dci->data_align));
339
0
          break;
340
341
13
        case DW_CFA_def_cfa_register:
342
13
          if ((ret = read_cfa_regnum (as, a, addr, &regnum, arg)) < 0)
343
0
            break;
344
13
          set_reg (sr, DWARF_CFA_REG_COLUMN, DWARF_WHERE_REG, regnum);
345
13
          Debug (15, "CFA_def_cfa_register r%lu\n", (long) regnum);
346
13
          break;
347
348
20
        case DW_CFA_def_cfa_offset:
349
20
          if ((ret = dwarf_read_uleb128 (as, a, addr, &val, arg)) < 0)
350
0
            break;
351
20
          set_reg (sr, DWARF_CFA_OFF_COLUMN, 0, val);   /* NOT factored! */
352
20
          Debug (15, "CFA_def_cfa_offset 0x%lx\n", (long) val);
353
20
          break;
354
355
0
        case DW_CFA_def_cfa_offset_sf:
356
0
          if ((ret = dwarf_read_sleb128 (as, a, addr, &val, arg)) < 0)
357
0
            break;
358
0
          set_reg (sr, DWARF_CFA_OFF_COLUMN, 0,
359
0
                   val * dci->data_align);      /* factored! */
360
0
          Debug (15, "CFA_def_cfa_offset_sf 0x%lx\n",
361
0
                 (long) (val * dci->data_align));
362
0
          break;
363
364
0
        case DW_CFA_def_cfa_expression:
365
          /* Save the address of the DW_FORM_block for later evaluation. */
366
0
          set_reg (sr, DWARF_CFA_REG_COLUMN, DWARF_WHERE_EXPR, *addr);
367
368
0
          if ((ret = dwarf_read_uleb128 (as, a, addr, &len, arg)) < 0)
369
0
            break;
370
371
0
          Debug (15, "CFA_def_cfa_expr @ 0x%lx [%lu bytes]\n",
372
0
                 (long) *addr, (long) len);
373
0
          *addr += len;
374
0
          break;
375
376
0
        case DW_CFA_expression:
377
0
          if ((ret = read_regnum (as, a, addr, &regnum, arg)) < 0)
378
0
            break;
379
380
          /* Save the address of the DW_FORM_block for later evaluation. */
381
0
          set_savedreg (sr, regnum, DWARF_WHERE_EXPR, *addr);
382
383
0
          if ((ret = dwarf_read_uleb128 (as, a, addr, &len, arg)) < 0)
384
0
            break;
385
386
0
          Debug (15, "CFA_expression r%lu @ 0x%lx [%lu bytes]\n",
387
0
                 (long) regnum, (long) addr, (long) len);
388
0
          *addr += len;
389
0
          break;
390
391
0
        case DW_CFA_val_expression:
392
0
          if ((ret = read_regnum (as, a, addr, &regnum, arg)) < 0)
393
0
            break;
394
395
          /* Save the address of the DW_FORM_block for later evaluation. */
396
0
          set_savedreg (sr, regnum, DWARF_WHERE_VAL_EXPR, *addr);
397
398
0
          if ((ret = dwarf_read_uleb128 (as, a, addr, &len, arg)) < 0)
399
0
            break;
400
401
0
          Debug (15, "CFA_val_expression r%lu @ 0x%lx [%lu bytes]\n",
402
0
                 (long) regnum, (long) addr, (long) len);
403
0
          *addr += len;
404
0
          break;
405
406
0
        case DW_CFA_GNU_args_size:
407
0
          if ((ret = dwarf_read_uleb128 (as, a, addr, &val, arg)) < 0)
408
0
            break;
409
0
          sr->args_size = val;
410
0
          Debug (15, "CFA_GNU_args_size %lu\n", (long) val);
411
0
          break;
412
413
0
        case DW_CFA_GNU_negative_offset_extended:
414
          /* A comment in GCC says that this is obsoleted by
415
             DW_CFA_offset_extended_sf, but that it's used by older
416
             PowerPC code.  */
417
0
          if (((ret = read_regnum (as, a, addr, &regnum, arg)) < 0)
418
0
              || ((ret = dwarf_read_uleb128 (as, a, addr, &val, arg)) < 0))
419
0
            break;
420
0
          set_savedreg (sr, regnum, DWARF_WHERE_CFAREL, ~(val * dci->data_align) + 1);
421
0
          Debug (15, "CFA_GNU_negative_offset_extended cfa+0x%lx\n",
422
0
                 (long) (~(val * dci->data_align) + 1));
423
0
          break;
424
425
0
        case DW_CFA_GNU_window_save:
426
#ifdef UNW_TARGET_SPARC
427
          /* This is a special CFA to handle all 16 windowed registers
428
             on SPARC.  */
429
          for (regnum = 16; regnum < 32; ++regnum)
430
            set_savedreg (sr, regnum, DWARF_WHERE_CFAREL,
431
                     (regnum - 16) * sizeof (unw_word_t));
432
          Debug (15, "CFA_GNU_window_save\n");
433
          break;
434
#elif UNW_TARGET_AARCH64
435
          /* This is a specific opcode on aarch64, DW_CFA_AARCH64_negate_ra_state */
436
          Debug (15, "DW_CFA_AARCH64_negate_ra_state\n");
437
          aarch64_negate_ra_sign_state(sr);
438
          break;
439
#else
440
          /* FALL THROUGH */
441
0
#endif
442
0
        case DW_CFA_lo_user:
443
0
        case DW_CFA_hi_user:
444
0
          Debug (1, "Unexpected CFA opcode 0x%x\n", op);
445
0
          ret = -UNW_EINVAL;
446
0
          break;
447
222
        }
448
222
    }
449
450
30
  if (ret > 0)
451
0
    ret = 0;
452
30
  return ret;
453
30
}
454
455
static int
456
fetch_proc_info (struct dwarf_cursor *c, unw_word_t ip)
457
15
{
458
15
  int ret, dynamic = 1;
459
460
  /* The 'ip' can point either to the previous or next instruction
461
     depending on what type of frame we have: normal call or a place
462
     to resume execution (e.g. after signal frame).
463
464
     For a normal call frame we need to back up so we point within the
465
     call itself; this is important because a) the call might be the
466
     very last instruction of the function and the edge of the FDE,
467
     and b) so that run_cfi_program() runs locations up to the call
468
     but not more.
469
470
     For signal frame, we need to do the exact opposite and look
471
     up using the current 'ip' value.  That is where execution will
472
     continue, and it's important we get this right, as 'ip' could be
473
     right at the function entry and hence FDE edge, or at instruction
474
     that manipulates CFA (push/pop). */
475
476
15
  if (c->use_prev_instr)
477
15
    {
478
#if defined(__arm__)
479
      /* On arm, the least bit denotes thumb/arm mode, clear it. */
480
      ip &= ~(unw_word_t)0x1;
481
#endif
482
15
      --ip;
483
15
    }
484
485
15
  memset (&c->pi, 0, sizeof (c->pi));
486
487
  /* check dynamic info first --- it overrides everything else */
488
15
  ret = unwi_find_dynamic_proc_info (c->as, ip, &c->pi, 1,
489
15
                                     c->as_arg);
490
15
  if (ret == -UNW_ENOINFO)
491
15
    {
492
15
      dynamic = 0;
493
15
      if ((ret = tdep_find_proc_info (c, ip, 1)) < 0)
494
0
        return ret;
495
15
    }
496
497
15
  if (c->pi.format != UNW_INFO_FORMAT_DYNAMIC
498
15
      && c->pi.format != UNW_INFO_FORMAT_TABLE
499
0
      && c->pi.format != UNW_INFO_FORMAT_REMOTE_TABLE
500
#ifdef UNW_TARGET_ARM
501
      && c->pi.format != UNW_INFO_FORMAT_ARM_EXIDX
502
#endif
503
15
      )
504
0
    return -UNW_ENOINFO;
505
506
15
  c->pi_valid = 1;
507
15
  c->pi_is_dynamic = dynamic;
508
509
  /* Let system/machine-dependent code determine frame-specific attributes. */
510
15
  if (ret >= 0)
511
15
    tdep_fetch_frame (c, ip, 1);
512
513
15
  return ret;
514
15
}
515
516
static int
517
parse_dynamic (struct dwarf_cursor  *c UNUSED,
518
         unw_word_t            ip UNUSED,
519
               dwarf_state_record_t *sr UNUSED)
520
0
{
521
0
  Debug (1, "Not yet implemented\n");
522
0
  return -UNW_ENOINFO;
523
0
}
524
525
static inline void
526
put_unwind_info (struct dwarf_cursor *c, unw_proc_info_t *pi)
527
15
{
528
15
  if (c->pi_is_dynamic)
529
0
    unwi_put_dynamic_unwind_info (c->as, pi, c->as_arg);
530
15
  else if (pi->unwind_info && pi->format == UNW_INFO_FORMAT_TABLE)
531
15
    {
532
15
      mempool_free (&dwarf_cie_info_pool, pi->unwind_info);
533
15
      pi->unwind_info = NULL;
534
15
    }
535
15
  c->pi_valid = 0;
536
15
}
537
538
static inline int
539
setup_fde (struct dwarf_cursor *c, dwarf_state_record_t *sr)
540
15
{
541
15
  int i, ret;
542
543
15
  assert (c->pi_valid);
544
545
15
  memset (sr, 0, sizeof (*sr));
546
300
  for (i = 0; i < DWARF_NUM_PRESERVED_REGS + 2; ++i)
547
285
    set_reg (sr, i, DWARF_WHERE_SAME, 0);
548
549
15
#if !(defined(UNW_TARGET_MIPS) && _MIPS_SIM == _ABI64) \
550
15
    && !defined(UNW_TARGET_S390X)
551
  /* SP defaults to CFA. s390x excluded: CFA = R15+160, so this default gives
552
     caller's R15 = CFA instead of R15, breaking frameless functions like kill
553
     that never emit DW_CFA_offset for R15. */
554
15
  set_reg (sr, TDEP_DWARF_SP, DWARF_WHERE_CFA, 0);
555
15
#endif
556
557
15
  struct dwarf_cie_info *dci = c->pi.unwind_info;
558
15
  sr->rs_current.ret_addr_column  = dci->ret_addr_column;
559
15
  unw_word_t addr = dci->cie_instr_start;
560
15
  unw_word_t curr_ip = 0;
561
15
  dwarf_stackable_reg_state_t *rs_stack = NULL;
562
15
  ret = run_cfi_program (c, sr, &curr_ip, ~(unw_word_t) 0, &addr,
563
15
       dci->cie_instr_end,
564
15
       &rs_stack, dci);
565
15
  empty_rstate_stack(&rs_stack);
566
15
  if (ret < 0)
567
0
    return ret;
568
569
15
  memcpy (&sr->rs_initial, &sr->rs_current, sizeof (sr->rs_initial));
570
15
  return 0;
571
15
}
572
573
static inline int
574
parse_fde (struct dwarf_cursor *c, unw_word_t ip, dwarf_state_record_t *sr)
575
15
{
576
15
  int ret;
577
15
  struct dwarf_cie_info *dci = c->pi.unwind_info;
578
15
  unw_word_t addr = dci->fde_instr_start;
579
15
  unw_word_t curr_ip = c->pi.start_ip;
580
15
  dwarf_stackable_reg_state_t *rs_stack = NULL;
581
  /* Process up to current `ip` for signal frame and `ip - 1` for normal call frame
582
     See `c->use_prev_instr` use in `fetch_proc_info` for details. */
583
15
  ret = run_cfi_program (c, sr, &curr_ip, ip - c->use_prev_instr, &addr, dci->fde_instr_end,
584
15
       &rs_stack, dci);
585
15
  empty_rstate_stack(&rs_stack);
586
15
  if (ret < 0)
587
0
    return ret;
588
589
15
  return 0;
590
15
}
591
592
HIDDEN int
593
dwarf_flush_rs_cache (struct dwarf_rs_cache *cache)
594
1
{
595
1
  int i;
596
597
1
  if (cache->log_size == DWARF_DEFAULT_LOG_UNW_CACHE_SIZE
598
1
      || !cache->hash) {
599
1
    cache->hash = cache->default_hash;
600
1
    cache->buckets = cache->default_buckets;
601
1
    cache->links = cache->default_links;
602
1
    cache->log_size = DWARF_DEFAULT_LOG_UNW_CACHE_SIZE;
603
1
  } else {
604
0
    if (cache->hash && cache->hash != cache->default_hash)
605
0
      mi_munmap(cache->hash, DWARF_UNW_HASH_SIZE(cache->prev_log_size)
606
0
                              * sizeof (cache->hash[0]));
607
0
    if (cache->buckets && cache->buckets != cache->default_buckets)
608
0
      mi_munmap(cache->buckets, DWARF_UNW_CACHE_SIZE(cache->prev_log_size)
609
0
                              * sizeof (cache->buckets[0]));
610
0
    if (cache->links && cache->links != cache->default_links)
611
0
      mi_munmap(cache->links, DWARF_UNW_CACHE_SIZE(cache->prev_log_size)
612
0
                              * sizeof (cache->links[0]));
613
0
    GET_MEMORY(cache->hash, DWARF_UNW_HASH_SIZE(cache->log_size)
614
0
                             * sizeof (cache->hash[0]));
615
0
    GET_MEMORY(cache->buckets, DWARF_UNW_CACHE_SIZE(cache->log_size)
616
0
                                * sizeof (cache->buckets[0]));
617
0
    GET_MEMORY(cache->links, DWARF_UNW_CACHE_SIZE(cache->log_size)
618
0
                                * sizeof (cache->links[0]));
619
0
    if (!cache->hash || !cache->buckets || !cache->links)
620
0
      {
621
0
        Debug (1, "Unable to allocate cache memory");
622
0
        return -UNW_ENOMEM;
623
0
      }
624
0
    cache->prev_log_size = cache->log_size;
625
0
  }
626
627
1
  cache->rr_head = 0;
628
629
129
  for (i = 0; i < DWARF_UNW_CACHE_SIZE(cache->log_size); ++i)
630
128
    {
631
128
      cache->links[i].coll_chain = -1;
632
128
      cache->links[i].ip = 0;
633
128
      cache->links[i].valid = 0;
634
128
    }
635
257
  for (i = 0; i< DWARF_UNW_HASH_SIZE(cache->log_size); ++i)
636
256
    cache->hash[i] = -1;
637
638
1
  return 0;
639
1
}
640
641
static inline struct dwarf_rs_cache *
642
get_rs_cache (unw_addr_space_t as, intrmask_t *saved_maskp)
643
59.1k
{
644
59.1k
  struct dwarf_rs_cache *cache = &as->global_cache;
645
59.1k
  unw_caching_policy_t caching = as->caching_policy;
646
647
59.1k
  if (caching == UNW_CACHE_NONE)
648
0
    return NULL;
649
650
#if defined(HAVE___CACHE_PER_THREAD) && HAVE___CACHE_PER_THREAD
651
  if (likely (caching == UNW_CACHE_PER_THREAD))
652
    {
653
      static thread_local struct dwarf_rs_cache tls_cache __attribute__((tls_model("initial-exec")));
654
      Debug (16, "using TLS cache\n");
655
      cache = &tls_cache;
656
    }
657
  else
658
#else
659
59.1k
  if (likely (caching == UNW_CACHE_GLOBAL))
660
59.1k
#endif
661
59.1k
    {
662
59.1k
      Debug (16, "acquiring lock\n");
663
59.1k
      lock_acquire (&cache->lock, *saved_maskp);
664
59.1k
    }
665
666
59.1k
  if ((atomic_load (&as->cache_generation) != atomic_load (&cache->generation))
667
59.1k
       || !cache->hash)
668
1
    {
669
      /* cache_size is only set in the global_cache, copy it over before flushing */
670
1
      cache->log_size = as->global_cache.log_size;
671
1
      if (dwarf_flush_rs_cache (cache) < 0)
672
0
        return NULL;
673
1
      atomic_store (&cache->generation, atomic_load (&as->cache_generation));
674
1
    }
675
676
59.1k
  return cache;
677
59.1k
}
678
679
static inline void
680
put_rs_cache (unw_addr_space_t as, struct dwarf_rs_cache *cache,
681
                  intrmask_t *saved_maskp)
682
59.1k
{
683
59.1k
  assert (as->caching_policy != UNW_CACHE_NONE);
684
685
59.1k
  Debug (16, "unmasking signals/interrupts and releasing lock\n");
686
59.1k
  if (likely (as->caching_policy == UNW_CACHE_GLOBAL))
687
59.1k
    lock_release (&cache->lock, *saved_maskp);
688
59.1k
}
689
690
static inline unw_hash_index_t CONST_ATTR
691
hash (unw_word_t ip, unsigned short log_size)
692
6.75k
{
693
  /* based on (sqrt(5)/2-1)*2^64 */
694
6.75k
# define magic  ((unw_word_t) 0x9e3779b97f4a7c16ULL)
695
696
6.75k
  return (unw_hash_index_t) (ip * magic >> ((sizeof(unw_word_t) * 8) - (log_size + 1)));
697
6.75k
}
698
699
static inline long
700
cache_match (struct dwarf_rs_cache *cache, unsigned short index, unw_word_t ip)
701
59.2k
{
702
59.2k
  return (cache->links[index].valid && (ip == cache->links[index].ip));
703
59.2k
}
704
705
static dwarf_reg_state_t *
706
rs_lookup (struct dwarf_rs_cache *cache, struct dwarf_cursor *c)
707
59.1k
{
708
59.1k
  unsigned short index;
709
59.1k
  unw_word_t ip = c->ip;
710
711
59.1k
  if (c->hint > 0)
712
52.5k
    {
713
52.5k
      index = c->hint - 1;
714
52.5k
      if (cache_match (cache, index, ip))
715
52.4k
  return &cache->buckets[index];
716
52.5k
    }
717
718
6.73k
  for (index = cache->hash[hash (ip, cache->log_size)];
719
6.73k
       index < DWARF_UNW_CACHE_SIZE(cache->log_size);
720
6.73k
       index = cache->links[index].coll_chain)
721
6.70k
    {
722
6.70k
      if (cache_match (cache, index, ip))
723
6.70k
  return &cache->buckets[index];
724
6.70k
    }
725
30
  return NULL;
726
6.73k
}
727
728
static inline dwarf_reg_state_t *
729
rs_new (struct dwarf_rs_cache *cache, struct dwarf_cursor * c)
730
15
{
731
15
  unw_hash_index_t index;
732
15
  unsigned short head;
733
734
15
  head = cache->rr_head;
735
15
  cache->rr_head = (head + 1) & (DWARF_UNW_CACHE_SIZE(cache->log_size) - 1);
736
737
  /* remove the old rs from the hash table (if it's there): */
738
15
  if (cache->links[head].ip)
739
0
    {
740
0
      unsigned short *pindex;
741
0
      for (pindex = &cache->hash[hash (cache->links[head].ip, cache->log_size)];
742
0
     *pindex < DWARF_UNW_CACHE_SIZE(cache->log_size);
743
0
     pindex = &cache->links[*pindex].coll_chain)
744
0
  {
745
0
    if (*pindex == head)
746
0
      {
747
0
        *pindex = cache->links[*pindex].coll_chain;
748
0
        break;
749
0
      }
750
0
  }
751
0
    }
752
753
  /* enter new rs in the hash table */
754
15
  index = hash (c->ip, cache->log_size);
755
15
  cache->links[head].coll_chain = cache->hash[index];
756
15
  cache->hash[index] = head;
757
758
15
  cache->links[head].ip = c->ip;
759
15
  cache->links[head].valid = 1;
760
15
  cache->links[head].signal_frame = tdep_cache_frame(c) ? 1 : 0;
761
15
  cache->links[head].use_prev_instr = c->use_prev_instr;
762
15
  return cache->buckets + head;
763
15
}
764
765
static int
766
create_state_record_for (struct dwarf_cursor *c, dwarf_state_record_t *sr,
767
                         unw_word_t ip)
768
15
{
769
15
  int ret;
770
15
  switch (c->pi.format)
771
15
    {
772
15
    case UNW_INFO_FORMAT_TABLE:
773
15
    case UNW_INFO_FORMAT_REMOTE_TABLE:
774
15
      if ((ret = setup_fde(c, sr)) < 0)
775
0
  return ret;
776
15
      ret = parse_fde (c, ip, sr);
777
15
      break;
778
779
0
    case UNW_INFO_FORMAT_DYNAMIC:
780
0
      ret = parse_dynamic (c, ip, sr);
781
0
      break;
782
783
#ifdef UNW_TARGET_ARM
784
    case UNW_INFO_FORMAT_ARM_EXIDX:
785
      /* ARM exidx proc info is stepped by arm_exidx_step(), not the DWARF
786
         path; signal dwarf_step() to skip so the cursor is not advanced
787
         with an uninitialized state record. */
788
      ret = -UNW_ENOINFO;
789
      break;
790
#endif
791
792
0
    default:
793
0
      Debug (1, "Unexpected unwind-info format %d\n", c->pi.format);
794
0
      ret = -UNW_EINVAL;
795
15
    }
796
15
  return ret;
797
15
}
798
799
static inline int
800
eval_location_expr (struct dwarf_cursor *c, unw_word_t stack_val, unw_addr_space_t as,
801
                    unw_accessors_t *a, unw_word_t addr,
802
                    dwarf_loc_t *locp, void *arg)
803
0
{
804
0
  int ret, is_register;
805
0
  unw_word_t len, val;
806
807
  /* read the length of the expression: */
808
0
  if ((ret = dwarf_read_uleb128 (as, a, &addr, &len, arg)) < 0)
809
0
    return ret;
810
811
  /* evaluate the expression: */
812
0
  if ((ret = dwarf_eval_expr (c, stack_val, &addr, len, &val, &is_register)) < 0)
813
0
    return ret;
814
815
0
  if (is_register)
816
0
    *locp = DWARF_REG_LOC (c, dwarf_to_unw_regnum (val));
817
0
  else
818
0
    *locp = DWARF_MEM_LOC (c, val);
819
820
0
  return 0;
821
0
}
822
823
824
#ifdef UNW_TARGET_AARCH64
825
#include "libunwind-aarch64.h"
826
827
static void
828
aarch64_negate_ra_sign_state(dwarf_state_record_t *sr)
829
{
830
  unw_word_t ra_sign_state = sr->rs_current.reg.val[UNW_AARCH64_RA_SIGN_STATE];
831
  ra_sign_state ^= 0x1;
832
  set_reg(sr, UNW_AARCH64_RA_SIGN_STATE, DWARF_WHERE_SAME, ra_sign_state);
833
}
834
835
static unw_word_t
836
aarch64_get_ra_sign_state(struct dwarf_reg_state *rs)
837
{
838
   return rs->reg.val[UNW_AARCH64_RA_SIGN_STATE];
839
}
840
841
#endif
842
843
static int
844
apply_reg_state (struct dwarf_cursor *c, struct dwarf_reg_state *rs)
845
59.1k
{
846
59.1k
  unw_regnum_t regnum;
847
59.1k
  unw_word_t addr, cfa, ip;
848
59.1k
  unw_word_t prev_ip, prev_cfa;
849
59.1k
  unw_addr_space_t as;
850
59.1k
  dwarf_loc_t cfa_loc;
851
59.1k
  unw_accessors_t *a;
852
59.1k
  int i, ret;
853
59.1k
  void *arg;
854
855
  /* In the case that we have incorrect CFI, the return address column may be
856
   * outside the valid range of data and will read invalid data.  Protect
857
   * against the errant read and indicate that we have a bad frame.  */
858
59.1k
  if (rs->ret_addr_column >= DWARF_NUM_PRESERVED_REGS) {
859
0
    Dprintf ("%s: return address entry %zu is outside of range of CIE",
860
0
             __FUNCTION__, rs->ret_addr_column);
861
0
    return -UNW_EBADFRAME;
862
0
  }
863
864
59.1k
  prev_ip = c->ip;
865
59.1k
  prev_cfa = c->cfa;
866
867
59.1k
  as = c->as;
868
59.1k
  arg = c->as_arg;
869
59.1k
  a = unw_get_accessors_int (as);
870
871
  /* Evaluate the CFA first, because it may be referred to by other
872
     expressions.  */
873
874
59.1k
  if (rs->reg.where[DWARF_CFA_REG_COLUMN] == DWARF_WHERE_REG)
875
59.1k
    {
876
      /* CFA is equal to [reg] + offset: */
877
878
      /* As a special-case, if the stack-pointer is the CFA and the
879
         stack-pointer wasn't saved, popping the CFA implicitly pops
880
         the stack-pointer as well.  */
881
59.1k
      if ((rs->reg.val[DWARF_CFA_REG_COLUMN] == TDEP_DWARF_SP)
882
13.1k
          && (TDEP_DWARF_SP < ARRAY_SIZE(rs->reg.val))
883
13.1k
          && (DWARF_IS_NULL_LOC(c->loc[TDEP_DWARF_SP])))
884
0
          cfa = c->cfa;
885
59.1k
      else
886
59.1k
        {
887
59.1k
          regnum = dwarf_to_unw_regnum ((unw_regnum_t) rs->reg.val[DWARF_CFA_REG_COLUMN]);
888
59.1k
          if ((ret = unw_get_reg (dwarf_to_cursor(c), regnum, &cfa)) < 0)
889
0
            return ret;
890
59.1k
        }
891
59.1k
      cfa += rs->reg.val[DWARF_CFA_OFF_COLUMN];
892
59.1k
    }
893
0
  else
894
0
    {
895
      /* CFA is equal to EXPR: */
896
897
0
      assert (rs->reg.where[DWARF_CFA_REG_COLUMN] == DWARF_WHERE_EXPR);
898
899
0
      addr = rs->reg.val[DWARF_CFA_REG_COLUMN];
900
      /* The dwarf standard doesn't specify an initial value to be pushed on */
901
      /* the stack before DW_CFA_def_cfa_expression evaluation. We push on a */
902
      /* dummy value (0) to keep the eval_location_expr function consistent. */
903
0
      if ((ret = eval_location_expr (c, 0, as, a, addr, &cfa_loc, arg)) < 0)
904
0
        return ret;
905
      /* the returned location better be a memory location... */
906
0
      if (DWARF_IS_REG_LOC (cfa_loc))
907
0
        return -UNW_EBADFRAME;
908
0
      cfa = DWARF_GET_LOC (cfa_loc);
909
0
    }
910
911
59.1k
  dwarf_loc_t new_loc[DWARF_NUM_PRESERVED_REGS];
912
59.1k
  memcpy(new_loc, c->loc, sizeof(new_loc));
913
914
1.06M
  for (i = 0; i < DWARF_NUM_PRESERVED_REGS; ++i)
915
1.00M
    {
916
1.00M
      switch ((dwarf_where_t) rs->reg.where[i])
917
1.00M
        {
918
6.57k
        case DWARF_WHERE_UNDEF:
919
6.57k
          new_loc[i] = DWARF_NULL_LOC;
920
6.57k
          break;
921
922
651k
        case DWARF_WHERE_SAME:
923
651k
          break;
924
925
59.1k
        case DWARF_WHERE_CFA:
926
59.1k
          new_loc[i] = DWARF_VAL_LOC (c, cfa);
927
59.1k
          break;
928
929
289k
        case DWARF_WHERE_CFAREL:
930
289k
          new_loc[i] = DWARF_MEM_LOC (c, cfa + rs->reg.val[i]);
931
289k
          break;
932
933
0
        case DWARF_WHERE_REG:
934
#ifdef __s390x__
935
          /* GPRs can be saved in FPRs on s390x */
936
          if (unw_is_fpreg (dwarf_to_unw_regnum (rs->reg.val[i])))
937
            {
938
              new_loc[i] = DWARF_FPREG_LOC (c, dwarf_to_unw_regnum (rs->reg.val[i]));
939
              break;
940
            }
941
#endif
942
0
          new_loc[i] = new_loc[rs->reg.val[i]];
943
0
          break;
944
945
0
        case DWARF_WHERE_EXPR:
946
0
          addr = rs->reg.val[i];
947
          /* The dwarf standard requires the current CFA to be pushed on the */
948
          /* stack before DW_CFA_expression evaluation. */
949
0
          if ((ret = eval_location_expr (c, cfa, as, a, addr, new_loc + i, arg)) < 0)
950
0
            return ret;
951
0
          break;
952
953
0
        case DWARF_WHERE_VAL_EXPR:
954
0
          addr = rs->reg.val[i];
955
          /* The dwarf standard requires the current CFA to be pushed on the */
956
          /* stack before DW_CFA_val_expression evaluation. */
957
0
          if ((ret = eval_location_expr (c, cfa, as, a, addr, new_loc + i, arg)) < 0)
958
0
            return ret;
959
0
          new_loc[i] = DWARF_VAL_LOC (c, DWARF_GET_LOC (new_loc[i]));
960
0
          break;
961
1.00M
        }
962
1.00M
    }
963
964
59.1k
  memcpy(c->loc, new_loc, sizeof(new_loc));
965
966
59.1k
  c->cfa = cfa;
967
  /* DWARF spec says undefined return address location means end of stack. */
968
59.1k
  if (DWARF_IS_NULL_LOC (c->loc[rs->ret_addr_column]))
969
6.57k
    {
970
6.57k
      c->ip = 0;
971
6.57k
    }
972
52.6k
  else
973
52.6k
  {
974
52.6k
    ret = dwarf_get (c, c->loc[rs->ret_addr_column], &ip);
975
52.6k
    if (ret < 0)
976
0
      return ret;
977
#ifdef UNW_TARGET_AARCH64
978
    if (aarch64_get_ra_sign_state(rs))
979
      {
980
        ip = tdep_strip_ptrauth_insn_mask ((unw_cursor_t*)c, ip);
981
      }
982
#endif
983
52.6k
    c->ip = ip;
984
52.6k
  }
985
59.1k
  ret = (c->ip != 0) ? 1 : 0;
986
987
  /* XXX: check for ip to be code_aligned */
988
59.1k
  if (c->ip == prev_ip && c->cfa == prev_cfa)
989
0
    {
990
0
      Dprintf ("%s: ip and cfa unchanged; stopping here (ip=0x%lx)\n",
991
0
               __FUNCTION__, (long) c->ip);
992
0
      return -UNW_EBADFRAME;
993
0
    }
994
995
59.1k
  if (c->stash_frames)
996
0
    tdep_stash_frame (c, rs);
997
998
59.1k
  return ret;
999
59.1k
}
1000
1001
/* Find the saved locations. */
1002
static int
1003
find_reg_state (struct dwarf_cursor *c, dwarf_state_record_t *sr)
1004
59.1k
{
1005
59.1k
  dwarf_reg_state_t *rs = NULL;
1006
59.1k
  struct dwarf_rs_cache *cache;
1007
59.1k
  int ret = 0;
1008
59.1k
  intrmask_t saved_mask;
1009
1010
59.1k
  if ((cache = get_rs_cache(c->as, &saved_mask)) &&
1011
59.1k
      (rs = rs_lookup(cache, c)))
1012
59.1k
    {
1013
      /* update hint; no locking needed: single-word writes are atomic */
1014
59.1k
      unsigned short index = (unsigned short) (rs - cache->buckets);
1015
59.1k
      c->use_prev_instr = cache->links[index].use_prev_instr;
1016
59.1k
      memcpy (&sr->rs_current, rs, sizeof (*rs));
1017
59.1k
    }
1018
15
  else
1019
15
    {
1020
      /* Release the cache lock before looking up the saved locations.
1021
       * If we do not release the lock we risk deadlock if the lookup
1022
       * causes libunwind to be reentered.  */
1023
15
      if (cache)
1024
15
  {
1025
15
    put_rs_cache (c->as, cache, &saved_mask);
1026
15
    cache = NULL;
1027
15
  }
1028
1029
15
      assert (!cache);
1030
1031
15
      ret = fetch_proc_info (c, c->ip);
1032
15
      int next_use_prev_instr = c->use_prev_instr;
1033
15
      if (ret >= 0)
1034
15
  {
1035
    /* Update use_prev_instr for the next frame. */
1036
15
    assert(c->pi.unwind_info);
1037
#ifdef UNW_TARGET_SPARC
1038
    /* On SPARC, O7 = address of CALL instruction itself (not call+N),
1039
       and DWARF CFI annotations start at the CALL instruction.
1040
       No backward adjustment of ip is ever needed.  */
1041
    next_use_prev_instr = 0;
1042
#else
1043
15
    struct dwarf_cie_info *dci = c->pi.unwind_info;
1044
15
    next_use_prev_instr = ! dci->signal_frame;
1045
15
#endif
1046
15
    ret = create_state_record_for (c, sr, c->ip);
1047
15
  }
1048
15
      put_unwind_info (c, &c->pi);
1049
15
      c->use_prev_instr = next_use_prev_instr;
1050
1051
      /* Reacquire the cache lock.  We repeat the lookup in case the
1052
       * cache was updated by another thread while we did not hold the
1053
       * lock.  */
1054
15
      if (ret >= 0)
1055
15
  cache = get_rs_cache (c->as, &saved_mask);
1056
1057
15
      if (cache)
1058
15
  {
1059
15
    rs = rs_lookup (cache, c);
1060
15
    if (rs)
1061
0
      {
1062
0
        memcpy (&sr->rs_current, rs, sizeof(*rs));
1063
0
      }
1064
15
    else
1065
15
      {
1066
15
        rs = rs_new (cache, c);
1067
15
        cache->links[rs - cache->buckets].hint = 0;
1068
15
        memcpy (rs, &sr->rs_current, sizeof(*rs));
1069
15
      }
1070
15
  }
1071
0
      else if (ret >= 0)
1072
  /* Without a cache there is no entry to reuse below, but the
1073
     architecture still needs to set up its signal frame state. */
1074
0
  tdep_reuse_frame (c, tdep_cache_frame (c) ? 1 : 0);
1075
15
    }
1076
1077
59.1k
  unsigned short index = -1;
1078
59.1k
  if (cache)
1079
59.1k
    {
1080
59.1k
      if (rs)
1081
59.1k
  {
1082
59.1k
    index = (unsigned short) (rs - cache->buckets);
1083
59.1k
    c->hint = cache->links[index].hint;
1084
59.1k
    cache->links[c->prev_rs].hint = index + 1;
1085
59.1k
    c->prev_rs = index;
1086
59.1k
  }
1087
59.1k
      if (ret >= 0)
1088
59.1k
  {
1089
59.1k
    assert (rs);
1090
59.1k
    tdep_reuse_frame (c, cache->links[index].signal_frame);
1091
59.1k
  }
1092
59.1k
      put_rs_cache (c->as, cache, &saved_mask);
1093
59.1k
    }
1094
59.1k
  return ret;
1095
59.1k
}
1096
1097
/* The function finds the saved locations and applies the register
1098
   state as well. */
1099
HIDDEN int
1100
dwarf_step (struct dwarf_cursor *c)
1101
59.1k
{
1102
59.1k
  int ret;
1103
59.1k
  dwarf_state_record_t sr;
1104
59.1k
  if ((ret = find_reg_state (c, &sr)) < 0)
1105
0
    return ret;
1106
59.1k
  return apply_reg_state (c, &sr.rs_current);
1107
59.1k
}
1108
1109
HIDDEN int
1110
dwarf_make_proc_info (struct dwarf_cursor *c)
1111
0
{
1112
#if 0
1113
  if (c->as->caching_policy == UNW_CACHE_NONE
1114
      || get_cached_proc_info (c) < 0)
1115
#endif
1116
  /* Need to check if current frame contains
1117
     args_size, and set cursor appropriately.  Only
1118
     needed for unw_resume */
1119
0
  dwarf_state_record_t sr;
1120
0
  sr.args_size = 0;
1121
0
  int ret;
1122
1123
  /* Lookup it up the slow way... */
1124
0
  ret = fetch_proc_info (c, c->ip);
1125
0
  if (ret >= 0)
1126
0
      ret = create_state_record_for (c, &sr, c->ip);
1127
0
  put_unwind_info (c, &c->pi);
1128
0
  if (ret < 0)
1129
0
    return ret;
1130
0
  c->args_size = sr.args_size;
1131
1132
0
  return 0;
1133
0
}
1134
1135
static int
1136
dwarf_reg_states_dynamic_iterate(struct dwarf_cursor     *c UNUSED,
1137
                                 unw_reg_states_callback  cb UNUSED,
1138
                                 void                    *token UNUSED)
1139
0
{
1140
0
  Debug (1, "Not yet implemented\n");
1141
0
  return -UNW_ENOINFO;
1142
0
}
1143
1144
static int
1145
dwarf_reg_states_table_iterate(struct dwarf_cursor *c,
1146
             unw_reg_states_callback cb,
1147
             void *token)
1148
0
{
1149
0
  dwarf_state_record_t sr;
1150
0
  int ret = setup_fde(c, &sr);
1151
0
  struct dwarf_cie_info *dci = c->pi.unwind_info;
1152
0
  unw_word_t addr = dci->fde_instr_start;
1153
0
  unw_word_t curr_ip = c->pi.start_ip;
1154
0
  dwarf_stackable_reg_state_t *rs_stack = NULL;
1155
0
  while (ret >= 0 && curr_ip < c->pi.end_ip && addr < dci->fde_instr_end)
1156
0
    {
1157
0
      unw_word_t prev_ip = curr_ip;
1158
0
      ret = run_cfi_program (c, &sr, &curr_ip, prev_ip, &addr, dci->fde_instr_end,
1159
0
           &rs_stack, dci);
1160
0
      if (ret >= 0 && prev_ip < curr_ip)
1161
0
  ret = cb(token, &sr.rs_current, sizeof(sr.rs_current), prev_ip, curr_ip);
1162
0
    }
1163
0
  empty_rstate_stack(&rs_stack);
1164
#if defined(NEED_LAST_IP)
1165
  if (ret >= 0 && curr_ip < c->pi.last_ip)
1166
    /* report the dead zone after the procedure ends */
1167
    ret = cb(token, &sr.rs_current, sizeof(sr.rs_current), curr_ip, c->pi.last_ip);
1168
#else
1169
0
  if (ret >= 0 && curr_ip < c->pi.end_ip)
1170
    /* report for whatever is left before procedure end */
1171
0
    ret = cb(token, &sr.rs_current, sizeof(sr.rs_current), curr_ip, c->pi.end_ip);
1172
0
#endif
1173
0
  return ret;
1174
0
}
1175
1176
HIDDEN int
1177
dwarf_reg_states_iterate(struct dwarf_cursor *c,
1178
       unw_reg_states_callback cb,
1179
       void *token)
1180
0
{
1181
0
  int ret = fetch_proc_info (c, c->ip);
1182
0
  int next_use_prev_instr = c->use_prev_instr;
1183
0
  if (ret >= 0)
1184
0
    {
1185
      /* Update use_prev_instr for the next frame. */
1186
0
      assert(c->pi.unwind_info);
1187
#ifdef UNW_TARGET_SPARC
1188
      next_use_prev_instr = 0;
1189
#else
1190
0
      struct dwarf_cie_info *dci = c->pi.unwind_info;
1191
0
      next_use_prev_instr = ! dci->signal_frame;
1192
0
#endif
1193
0
      switch (c->pi.format)
1194
0
  {
1195
0
  case UNW_INFO_FORMAT_TABLE:
1196
0
  case UNW_INFO_FORMAT_REMOTE_TABLE:
1197
0
    ret = dwarf_reg_states_table_iterate(c, cb, token);
1198
0
    break;
1199
1200
0
  case UNW_INFO_FORMAT_DYNAMIC:
1201
0
    ret = dwarf_reg_states_dynamic_iterate (c, cb, token);
1202
0
    break;
1203
1204
0
  default:
1205
0
    Debug (1, "Unexpected unwind-info format %d\n", c->pi.format);
1206
0
    ret = -UNW_EINVAL;
1207
0
  }
1208
0
    }
1209
0
  put_unwind_info (c, &c->pi);
1210
0
  c->use_prev_instr = next_use_prev_instr;
1211
0
  return ret;
1212
0
}
1213
1214
HIDDEN int
1215
dwarf_apply_reg_state (struct dwarf_cursor *c, struct dwarf_reg_state *rs)
1216
0
{
1217
0
  return apply_reg_state(c, rs);
1218
0
}