/src/elfutils/libdwfl/frame_unwind.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* Get previous frame state for an existing frame state. |
2 | | Copyright (C) 2013, 2014, 2016, 2024 Red Hat, Inc. |
3 | | This file is part of elfutils. |
4 | | |
5 | | This file is free software; you can redistribute it and/or modify |
6 | | it under the terms of either |
7 | | |
8 | | * the GNU Lesser General Public License as published by the Free |
9 | | Software Foundation; either version 3 of the License, or (at |
10 | | your option) any later version |
11 | | |
12 | | or |
13 | | |
14 | | * the GNU General Public License as published by the Free |
15 | | Software Foundation; either version 2 of the License, or (at |
16 | | your option) any later version |
17 | | |
18 | | or both in parallel, as here. |
19 | | |
20 | | elfutils is distributed in the hope that it will be useful, but |
21 | | WITHOUT ANY WARRANTY; without even the implied warranty of |
22 | | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
23 | | General Public License for more details. |
24 | | |
25 | | You should have received copies of the GNU General Public License and |
26 | | the GNU Lesser General Public License along with this program. If |
27 | | not, see <http://www.gnu.org/licenses/>. */ |
28 | | |
29 | | #ifdef HAVE_CONFIG_H |
30 | | # include <config.h> |
31 | | #endif |
32 | | |
33 | | #include "cfi.h" |
34 | | #include <stdlib.h> |
35 | | #include "libdwflP.h" |
36 | | #include "dwarf.h" |
37 | | #include <system.h> |
38 | | |
39 | | /* Maximum number of DWARF expression stack slots before returning an error. */ |
40 | 0 | #define DWARF_EXPR_STACK_MAX 0x100 |
41 | | |
42 | | /* Maximum number of DWARF expression executed operations before returning an |
43 | | error. */ |
44 | 0 | #define DWARF_EXPR_STEPS_MAX 0x1000 |
45 | | |
46 | | int |
47 | | internal_function |
48 | | __libdwfl_frame_reg_get (Dwfl_Frame *state, unsigned regno, Dwarf_Addr *val) |
49 | 0 | { |
50 | 0 | Ebl *ebl = state->thread->process->ebl; |
51 | 0 | if (! ebl_dwarf_to_regno (ebl, ®no)) |
52 | 0 | return -1; |
53 | 0 | if (regno >= ebl_frame_nregs (ebl)) |
54 | 0 | return -1; |
55 | 0 | if ((state->regs_set[regno / sizeof (*state->regs_set) / 8] |
56 | 0 | & ((uint64_t) 1U << (regno % (sizeof (*state->regs_set) * 8)))) == 0) |
57 | 0 | return 1; |
58 | 0 | if (val) |
59 | 0 | *val = state->regs[regno]; |
60 | 0 | return 0; |
61 | 0 | } |
62 | | |
63 | | bool |
64 | | internal_function |
65 | | __libdwfl_frame_reg_set (Dwfl_Frame *state, unsigned regno, Dwarf_Addr val) |
66 | 0 | { |
67 | 0 | Ebl *ebl = state->thread->process->ebl; |
68 | 0 | if (! ebl_dwarf_to_regno (ebl, ®no)) |
69 | 0 | return false; |
70 | 0 | if (regno >= ebl_frame_nregs (ebl)) |
71 | 0 | return false; |
72 | | /* For example i386 user_regs_struct has signed fields. */ |
73 | 0 | if (ebl_get_elfclass (ebl) == ELFCLASS32) |
74 | 0 | val &= 0xffffffff; |
75 | 0 | state->regs_set[regno / sizeof (*state->regs_set) / 8] |= |
76 | 0 | ((uint64_t) 1U << (regno % (sizeof (*state->regs_set) * 8))); |
77 | 0 | state->regs[regno] = val; |
78 | 0 | return true; |
79 | 0 | } |
80 | | |
81 | | static int |
82 | | bra_compar (const void *key_voidp, const void *elem_voidp) |
83 | 0 | { |
84 | 0 | Dwarf_Word offset = (uintptr_t) key_voidp; |
85 | 0 | const Dwarf_Op *op = elem_voidp; |
86 | 0 | return (offset > op->offset) - (offset < op->offset); |
87 | 0 | } |
88 | | |
89 | | struct eval_stack { |
90 | | Dwarf_Addr *addrs; |
91 | | size_t used; |
92 | | size_t allocated; |
93 | | }; |
94 | | |
95 | | static bool |
96 | | do_push (struct eval_stack *stack, Dwarf_Addr val) |
97 | 0 | { |
98 | 0 | if (stack->used >= DWARF_EXPR_STACK_MAX) |
99 | 0 | { |
100 | 0 | __libdwfl_seterrno (DWFL_E_INVALID_DWARF); |
101 | 0 | return false; |
102 | 0 | } |
103 | 0 | if (stack->used == stack->allocated) |
104 | 0 | { |
105 | 0 | stack->allocated = MAX (stack->allocated * 2, 32); |
106 | 0 | Dwarf_Addr *new_addrs; |
107 | 0 | new_addrs = realloc (stack->addrs, |
108 | 0 | stack->allocated * sizeof (*stack->addrs)); |
109 | 0 | if (new_addrs == NULL) |
110 | 0 | { |
111 | 0 | __libdwfl_seterrno (DWFL_E_NOMEM); |
112 | 0 | return false; |
113 | 0 | } |
114 | 0 | stack->addrs = new_addrs; |
115 | 0 | } |
116 | 0 | stack->addrs[stack->used++] = val; |
117 | 0 | return true; |
118 | 0 | } |
119 | | |
120 | | static bool |
121 | | do_pop (struct eval_stack *stack, Dwarf_Addr *val) |
122 | 0 | { |
123 | 0 | if (stack->used == 0) |
124 | 0 | { |
125 | 0 | __libdwfl_seterrno (DWFL_E_INVALID_DWARF); |
126 | 0 | return false; |
127 | 0 | } |
128 | 0 | *val = stack->addrs[--stack->used]; |
129 | 0 | return true; |
130 | 0 | } |
131 | | |
132 | | /* If FRAME is NULL is are computing CFI frame base. In such case another |
133 | | DW_OP_call_frame_cfa is no longer permitted. */ |
134 | | |
135 | | static bool |
136 | | expr_eval (Dwfl_Frame *state, Dwarf_Frame *frame, const Dwarf_Op *ops, |
137 | | size_t nops, Dwarf_Addr *result, Dwarf_Addr bias) |
138 | 0 | { |
139 | 0 | Dwfl_Process *process = state->thread->process; |
140 | 0 | if (nops == 0) |
141 | 0 | { |
142 | 0 | __libdwfl_seterrno (DWFL_E_INVALID_DWARF); |
143 | 0 | return false; |
144 | 0 | } |
145 | 0 | struct eval_stack stack = |
146 | 0 | { |
147 | 0 | .addrs = NULL, |
148 | 0 | .used = 0, |
149 | 0 | .allocated = 0 |
150 | 0 | }; |
151 | |
|
152 | 0 | #define pop(x) do_pop(&stack, x) |
153 | 0 | #define push(x) do_push(&stack, x) |
154 | |
|
155 | 0 | Dwarf_Addr val1, val2; |
156 | 0 | bool is_location = false; |
157 | 0 | size_t steps_count = 0; |
158 | 0 | for (const Dwarf_Op *op = ops; op < ops + nops; op++) |
159 | 0 | { |
160 | 0 | if (++steps_count > DWARF_EXPR_STEPS_MAX) |
161 | 0 | { |
162 | 0 | __libdwfl_seterrno (DWFL_E_INVALID_DWARF); |
163 | 0 | return false; |
164 | 0 | } |
165 | 0 | switch (op->atom) |
166 | 0 | { |
167 | | /* DW_OP_* order matches libgcc/unwind-dw2.c execute_stack_op: */ |
168 | 0 | case DW_OP_lit0 ... DW_OP_lit31: |
169 | 0 | if (! push (op->atom - DW_OP_lit0)) |
170 | 0 | { |
171 | 0 | free (stack.addrs); |
172 | 0 | return false; |
173 | 0 | } |
174 | 0 | break; |
175 | 0 | case DW_OP_addr: |
176 | 0 | if (! push (op->number + bias)) |
177 | 0 | { |
178 | 0 | free (stack.addrs); |
179 | 0 | return false; |
180 | 0 | } |
181 | 0 | break; |
182 | 0 | case DW_OP_GNU_encoded_addr: |
183 | | /* Missing support in the rest of elfutils. */ |
184 | 0 | __libdwfl_seterrno (DWFL_E_UNSUPPORTED_DWARF); |
185 | 0 | return false; |
186 | 0 | case DW_OP_const1u: |
187 | 0 | case DW_OP_const1s: |
188 | 0 | case DW_OP_const2u: |
189 | 0 | case DW_OP_const2s: |
190 | 0 | case DW_OP_const4u: |
191 | 0 | case DW_OP_const4s: |
192 | 0 | case DW_OP_const8u: |
193 | 0 | case DW_OP_const8s: |
194 | 0 | case DW_OP_constu: |
195 | 0 | case DW_OP_consts: |
196 | 0 | if (! push (op->number)) |
197 | 0 | { |
198 | 0 | free (stack.addrs); |
199 | 0 | return false; |
200 | 0 | } |
201 | 0 | break; |
202 | 0 | case DW_OP_reg0 ... DW_OP_reg31: |
203 | 0 | if (INTUSE (dwfl_frame_reg) (state, op->atom - DW_OP_reg0, &val1) != 0 |
204 | 0 | || ! push (val1)) |
205 | 0 | { |
206 | 0 | free (stack.addrs); |
207 | 0 | return false; |
208 | 0 | } |
209 | 0 | break; |
210 | 0 | case DW_OP_regx: |
211 | 0 | if (INTUSE (dwfl_frame_reg) (state, op->number, &val1) != 0 || ! push (val1)) |
212 | 0 | { |
213 | 0 | free (stack.addrs); |
214 | 0 | return false; |
215 | 0 | } |
216 | 0 | break; |
217 | 0 | case DW_OP_breg0 ... DW_OP_breg31: |
218 | 0 | if (INTUSE (dwfl_frame_reg) (state, op->atom - DW_OP_breg0, &val1) != 0) |
219 | 0 | { |
220 | 0 | free (stack.addrs); |
221 | 0 | return false; |
222 | 0 | } |
223 | 0 | val1 += op->number; |
224 | 0 | if (! push (val1)) |
225 | 0 | { |
226 | 0 | free (stack.addrs); |
227 | 0 | return false; |
228 | 0 | } |
229 | 0 | break; |
230 | 0 | case DW_OP_bregx: |
231 | 0 | if (INTUSE (dwfl_frame_reg) (state, op->number, &val1) != 0) |
232 | 0 | { |
233 | 0 | free (stack.addrs); |
234 | 0 | return false; |
235 | 0 | } |
236 | 0 | val1 += op->number2; |
237 | 0 | if (! push (val1)) |
238 | 0 | { |
239 | 0 | free (stack.addrs); |
240 | 0 | return false; |
241 | 0 | } |
242 | 0 | break; |
243 | 0 | case DW_OP_dup: |
244 | 0 | if (! pop (&val1) || ! push (val1) || ! push (val1)) |
245 | 0 | { |
246 | 0 | free (stack.addrs); |
247 | 0 | return false; |
248 | 0 | } |
249 | 0 | break; |
250 | 0 | case DW_OP_drop: |
251 | 0 | if (! pop (&val1)) |
252 | 0 | { |
253 | 0 | free (stack.addrs); |
254 | 0 | return false; |
255 | 0 | } |
256 | 0 | break; |
257 | 0 | case DW_OP_pick: |
258 | 0 | if (stack.used <= op->number) |
259 | 0 | { |
260 | 0 | free (stack.addrs); |
261 | 0 | __libdwfl_seterrno (DWFL_E_INVALID_DWARF); |
262 | 0 | return false; |
263 | 0 | } |
264 | 0 | if (! push (stack.addrs[stack.used - 1 - op->number])) |
265 | 0 | { |
266 | 0 | free (stack.addrs); |
267 | 0 | return false; |
268 | 0 | } |
269 | 0 | break; |
270 | 0 | case DW_OP_over: |
271 | 0 | if (! pop (&val1) || ! pop (&val2) |
272 | 0 | || ! push (val2) || ! push (val1) || ! push (val2)) |
273 | 0 | { |
274 | 0 | free (stack.addrs); |
275 | 0 | return false; |
276 | 0 | } |
277 | 0 | break; |
278 | 0 | case DW_OP_swap: |
279 | 0 | if (! pop (&val1) || ! pop (&val2) || ! push (val1) || ! push (val2)) |
280 | 0 | { |
281 | 0 | free (stack.addrs); |
282 | 0 | return false; |
283 | 0 | } |
284 | 0 | break; |
285 | 0 | case DW_OP_rot: |
286 | 0 | { |
287 | 0 | Dwarf_Addr val3; |
288 | 0 | if (! pop (&val1) || ! pop (&val2) || ! pop (&val3) |
289 | 0 | || ! push (val1) || ! push (val3) || ! push (val2)) |
290 | 0 | { |
291 | 0 | free (stack.addrs); |
292 | 0 | return false; |
293 | 0 | } |
294 | 0 | } |
295 | 0 | break; |
296 | 0 | case DW_OP_deref: |
297 | 0 | case DW_OP_deref_size: |
298 | 0 | if (process->callbacks->memory_read == NULL) |
299 | 0 | { |
300 | 0 | free (stack.addrs); |
301 | 0 | __libdwfl_seterrno (DWFL_E_INVALID_ARGUMENT); |
302 | 0 | return false; |
303 | 0 | } |
304 | 0 | if (! pop (&val1) |
305 | 0 | || ! process->callbacks->memory_read (process->dwfl, val1, &val1, |
306 | 0 | process->callbacks_arg)) |
307 | 0 | { |
308 | 0 | free (stack.addrs); |
309 | 0 | return false; |
310 | 0 | } |
311 | 0 | if (op->atom == DW_OP_deref_size) |
312 | 0 | { |
313 | 0 | const int elfclass = frame->cache->e_ident[EI_CLASS]; |
314 | 0 | const unsigned addr_bytes = elfclass == ELFCLASS32 ? 4 : 8; |
315 | 0 | if (op->number > addr_bytes) |
316 | 0 | { |
317 | 0 | free (stack.addrs); |
318 | 0 | __libdwfl_seterrno (DWFL_E_INVALID_DWARF); |
319 | 0 | return false; |
320 | 0 | } |
321 | | #if BYTE_ORDER == BIG_ENDIAN |
322 | | if (op->number == 0) |
323 | | val1 = 0; |
324 | | else |
325 | | val1 >>= (addr_bytes - op->number) * 8; |
326 | | #else |
327 | 0 | if (op->number < 8) |
328 | 0 | val1 &= (1ULL << (op->number * 8)) - 1; |
329 | 0 | #endif |
330 | 0 | } |
331 | 0 | if (! push (val1)) |
332 | 0 | { |
333 | 0 | free (stack.addrs); |
334 | 0 | return false; |
335 | 0 | } |
336 | 0 | break; |
337 | 0 | #define UNOP(atom, expr) \ |
338 | 0 | case atom: \ |
339 | 0 | if (! pop (&val1) || ! push (expr)) \ |
340 | 0 | { \ |
341 | 0 | free (stack.addrs); \ |
342 | 0 | return false; \ |
343 | 0 | } \ |
344 | 0 | break; |
345 | 0 | UNOP (DW_OP_abs, llabs ((int64_t) val1)) |
346 | 0 | UNOP (DW_OP_neg, -(int64_t) val1) |
347 | 0 | UNOP (DW_OP_not, ~val1) |
348 | 0 | #undef UNOP |
349 | 0 | case DW_OP_plus_uconst: |
350 | 0 | if (! pop (&val1) || ! push (val1 + op->number)) |
351 | 0 | { |
352 | 0 | free (stack.addrs); |
353 | 0 | return false; |
354 | 0 | } |
355 | 0 | break; |
356 | 0 | #define BINOP(atom, op) \ |
357 | 0 | case atom: \ |
358 | 0 | if (! pop (&val2) || ! pop (&val1) || ! push (val1 op val2)) \ |
359 | 0 | { \ |
360 | 0 | free (stack.addrs); \ |
361 | 0 | return false; \ |
362 | 0 | } \ |
363 | 0 | break; |
364 | 0 | #define BINOP_SIGNED(atom, op) \ |
365 | 0 | case atom: \ |
366 | 0 | if (! pop (&val2) || ! pop (&val1) \ |
367 | 0 | || ! push ((int64_t) val1 op (int64_t) val2)) \ |
368 | 0 | { \ |
369 | 0 | free (stack.addrs); \ |
370 | 0 | return false; \ |
371 | 0 | } \ |
372 | 0 | break; |
373 | 0 | BINOP (DW_OP_and, &) |
374 | 0 | case DW_OP_div: |
375 | 0 | if (! pop (&val2) || ! pop (&val1)) |
376 | 0 | { |
377 | 0 | free (stack.addrs); |
378 | 0 | return false; |
379 | 0 | } |
380 | 0 | if (val2 == 0) |
381 | 0 | { |
382 | 0 | free (stack.addrs); |
383 | 0 | __libdwfl_seterrno (DWFL_E_INVALID_DWARF); |
384 | 0 | return false; |
385 | 0 | } |
386 | 0 | if (! push ((int64_t) val1 / (int64_t) val2)) |
387 | 0 | { |
388 | 0 | free (stack.addrs); |
389 | 0 | return false; |
390 | 0 | } |
391 | 0 | break; |
392 | 0 | BINOP (DW_OP_minus, -) |
393 | 0 | case DW_OP_mod: |
394 | 0 | if (! pop (&val2) || ! pop (&val1)) |
395 | 0 | { |
396 | 0 | free (stack.addrs); |
397 | 0 | return false; |
398 | 0 | } |
399 | 0 | if (val2 == 0) |
400 | 0 | { |
401 | 0 | free (stack.addrs); |
402 | 0 | __libdwfl_seterrno (DWFL_E_INVALID_DWARF); |
403 | 0 | return false; |
404 | 0 | } |
405 | 0 | if (! push (val1 % val2)) |
406 | 0 | { |
407 | 0 | free (stack.addrs); |
408 | 0 | return false; |
409 | 0 | } |
410 | 0 | break; |
411 | 0 | BINOP (DW_OP_mul, *) |
412 | 0 | BINOP (DW_OP_or, |) |
413 | 0 | BINOP (DW_OP_plus, +) |
414 | 0 | BINOP (DW_OP_shl, <<) |
415 | 0 | BINOP (DW_OP_shr, >>) |
416 | 0 | BINOP_SIGNED (DW_OP_shra, >>) |
417 | 0 | BINOP (DW_OP_xor, ^) |
418 | 0 | BINOP_SIGNED (DW_OP_le, <=) |
419 | 0 | BINOP_SIGNED (DW_OP_ge, >=) |
420 | 0 | BINOP_SIGNED (DW_OP_eq, ==) |
421 | 0 | BINOP_SIGNED (DW_OP_lt, <) |
422 | 0 | BINOP_SIGNED (DW_OP_gt, >) |
423 | 0 | BINOP_SIGNED (DW_OP_ne, !=) |
424 | 0 | #undef BINOP |
425 | 0 | #undef BINOP_SIGNED |
426 | 0 | case DW_OP_bra: |
427 | 0 | if (! pop (&val1)) |
428 | 0 | { |
429 | 0 | free (stack.addrs); |
430 | 0 | return false; |
431 | 0 | } |
432 | 0 | if (val1 == 0) |
433 | 0 | break; |
434 | 0 | FALLTHROUGH; |
435 | 0 | case DW_OP_skip:; |
436 | 0 | Dwarf_Word offset = op->offset + 1 + 2 + (int16_t) op->number; |
437 | 0 | const Dwarf_Op *found = bsearch ((void *) (uintptr_t) offset, ops, nops, |
438 | 0 | sizeof (*ops), bra_compar); |
439 | 0 | if (found == NULL) |
440 | 0 | { |
441 | 0 | free (stack.addrs); |
442 | | /* PPC32 vDSO has such invalid operations. */ |
443 | 0 | __libdwfl_seterrno (DWFL_E_INVALID_DWARF); |
444 | 0 | return false; |
445 | 0 | } |
446 | | /* Undo the 'for' statement increment. */ |
447 | 0 | op = found - 1; |
448 | 0 | break; |
449 | 0 | case DW_OP_nop: |
450 | 0 | break; |
451 | | /* DW_OP_* not listed in libgcc/unwind-dw2.c execute_stack_op: */ |
452 | 0 | case DW_OP_call_frame_cfa:; |
453 | | // Not used by CFI itself but it is synthetized by elfutils internation. |
454 | 0 | Dwarf_Op *cfa_ops; |
455 | 0 | size_t cfa_nops; |
456 | 0 | Dwarf_Addr cfa; |
457 | 0 | if (frame == NULL |
458 | 0 | || dwarf_frame_cfa (frame, &cfa_ops, &cfa_nops) != 0 |
459 | 0 | || ! expr_eval (state, NULL, cfa_ops, cfa_nops, &cfa, bias) |
460 | 0 | || ! push (cfa)) |
461 | 0 | { |
462 | 0 | __libdwfl_seterrno (DWFL_E_LIBDW); |
463 | 0 | free (stack.addrs); |
464 | 0 | return false; |
465 | 0 | } |
466 | 0 | is_location = true; |
467 | 0 | break; |
468 | 0 | case DW_OP_stack_value: |
469 | | // Not used by CFI itself but it is synthetized by elfutils internation. |
470 | 0 | is_location = false; |
471 | 0 | break; |
472 | 0 | default: |
473 | 0 | __libdwfl_seterrno (DWFL_E_INVALID_DWARF); |
474 | 0 | return false; |
475 | 0 | } |
476 | 0 | } |
477 | 0 | if (! pop (result)) |
478 | 0 | { |
479 | 0 | free (stack.addrs); |
480 | 0 | return false; |
481 | 0 | } |
482 | 0 | free (stack.addrs); |
483 | 0 | if (is_location) |
484 | 0 | { |
485 | 0 | if (process->callbacks->memory_read == NULL) |
486 | 0 | { |
487 | 0 | __libdwfl_seterrno (DWFL_E_INVALID_ARGUMENT); |
488 | 0 | return false; |
489 | 0 | } |
490 | 0 | if (! process->callbacks->memory_read (process->dwfl, *result, result, |
491 | 0 | process->callbacks_arg)) |
492 | 0 | return false; |
493 | 0 | } |
494 | 0 | return true; |
495 | 0 | #undef push |
496 | 0 | #undef pop |
497 | 0 | } |
498 | | |
499 | | static Dwfl_Frame * |
500 | | new_unwound (Dwfl_Frame *state) |
501 | 0 | { |
502 | 0 | assert (state->unwound == NULL); |
503 | 0 | Dwfl_Thread *thread = state->thread; |
504 | 0 | Dwfl_Process *process = thread->process; |
505 | 0 | Ebl *ebl = process->ebl; |
506 | 0 | size_t nregs = ebl_frame_nregs (ebl); |
507 | 0 | assert (nregs > 0); |
508 | 0 | Dwfl_Frame *unwound; |
509 | 0 | unwound = malloc (sizeof (*unwound) + sizeof (*unwound->regs) * nregs); |
510 | 0 | if (unlikely (unwound == NULL)) |
511 | 0 | return NULL; |
512 | 0 | state->unwound = unwound; |
513 | 0 | unwound->thread = thread; |
514 | 0 | unwound->unwound = NULL; |
515 | 0 | unwound->signal_frame = false; |
516 | 0 | unwound->initial_frame = false; |
517 | 0 | unwound->pc_state = DWFL_FRAME_STATE_ERROR; |
518 | 0 | unwound->unwound_source = DWFL_UNWOUND_NONE; |
519 | 0 | memset (unwound->regs_set, 0, sizeof (unwound->regs_set)); |
520 | 0 | return unwound; |
521 | 0 | } |
522 | | |
523 | | /* The logic is to call __libdwfl_seterrno for any CFI bytecode interpretation |
524 | | error so one can easily catch the problem with a debugger. Still there are |
525 | | archs with invalid CFI for some registers where the registers are never used |
526 | | later. Therefore we continue unwinding leaving the registers undefined. */ |
527 | | |
528 | | static void |
529 | | handle_cfi (Dwfl_Frame *state, Dwarf_Addr pc, Dwarf_CFI *cfi, Dwarf_Addr bias) |
530 | 0 | { |
531 | 0 | Dwarf_Frame *frame; |
532 | 0 | if (INTUSE(dwarf_cfi_addrframe) (cfi, pc, &frame) != 0) |
533 | 0 | { |
534 | 0 | __libdwfl_seterrno (DWFL_E_LIBDW); |
535 | 0 | return; |
536 | 0 | } |
537 | | |
538 | 0 | Dwfl_Frame *unwound = new_unwound (state); |
539 | 0 | if (unwound == NULL) |
540 | 0 | { |
541 | 0 | __libdwfl_seterrno (DWFL_E_NOMEM); |
542 | 0 | return; |
543 | 0 | } |
544 | | |
545 | 0 | unwound->signal_frame = frame->fde->cie->signal_frame; |
546 | 0 | Dwfl_Thread *thread = state->thread; |
547 | 0 | Dwfl_Process *process = thread->process; |
548 | 0 | Ebl *ebl = process->ebl; |
549 | 0 | size_t nregs = ebl_frame_nregs (ebl); |
550 | 0 | assert (nregs > 0); |
551 | | |
552 | | /* The return register is special for setting the unwound->pc_state. */ |
553 | 0 | unsigned ra = frame->fde->cie->return_address_register; |
554 | 0 | bool ra_set = false; |
555 | 0 | if (! ebl_dwarf_to_regno (ebl, &ra)) |
556 | 0 | { |
557 | 0 | __libdwfl_seterrno (DWFL_E_INVALID_REGISTER); |
558 | 0 | return; |
559 | 0 | } |
560 | | |
561 | 0 | for (unsigned regno = 0; regno < nregs; regno++) |
562 | 0 | { |
563 | 0 | Dwarf_Op reg_ops_mem[3], *reg_ops; |
564 | 0 | size_t reg_nops; |
565 | 0 | if (dwarf_frame_register (frame, regno, reg_ops_mem, ®_ops, |
566 | 0 | ®_nops) != 0) |
567 | 0 | { |
568 | 0 | __libdwfl_seterrno (DWFL_E_LIBDW); |
569 | 0 | continue; |
570 | 0 | } |
571 | 0 | Dwarf_Addr regval; |
572 | 0 | if (reg_nops == 0) |
573 | 0 | { |
574 | 0 | if (reg_ops == reg_ops_mem) |
575 | 0 | { |
576 | | /* REGNO is undefined. */ |
577 | 0 | if (regno == ra) |
578 | 0 | unwound->pc_state = DWFL_FRAME_STATE_PC_UNDEFINED; |
579 | 0 | continue; |
580 | 0 | } |
581 | 0 | else if (reg_ops == NULL) |
582 | 0 | { |
583 | | /* REGNO is same-value. */ |
584 | 0 | if (INTUSE (dwfl_frame_reg) (state, regno, ®val) != 0) |
585 | 0 | continue; |
586 | 0 | } |
587 | 0 | else |
588 | 0 | { |
589 | 0 | __libdwfl_seterrno (DWFL_E_INVALID_DWARF); |
590 | 0 | continue; |
591 | 0 | } |
592 | 0 | } |
593 | 0 | else if (! expr_eval (state, frame, reg_ops, reg_nops, ®val, bias)) |
594 | 0 | { |
595 | | /* PPC32 vDSO has various invalid operations, ignore them. The |
596 | | register will look as unset causing an error later, if used. |
597 | | But PPC32 does not use such registers. */ |
598 | 0 | continue; |
599 | 0 | } |
600 | | |
601 | | /* Some architectures encode some extra info in the return address. */ |
602 | 0 | if (regno == frame->fde->cie->return_address_register) |
603 | 0 | { |
604 | 0 | regval &= ebl_func_addr_mask (ebl); |
605 | | |
606 | | /* In aarch64, pseudo-register RA_SIGN_STATE indicates whether the |
607 | | return address needs demangling using the PAC mask from the |
608 | | thread. */ |
609 | 0 | if (cfi->e_machine == EM_AARCH64 && |
610 | 0 | frame->nregs > DW_AARCH64_RA_SIGN_STATE && |
611 | 0 | frame->regs[DW_AARCH64_RA_SIGN_STATE].value & 0x1) |
612 | 0 | { |
613 | 0 | regval &= ~(state->thread->aarch64.pauth_insn_mask); |
614 | 0 | } |
615 | 0 | } |
616 | | |
617 | | /* This is another strange PPC[64] case. There are two |
618 | | registers numbers that can represent the same DWARF return |
619 | | register number. We only want one to actually set the return |
620 | | register value. But we always want to override the value if |
621 | | the register is the actual CIE return address register. */ |
622 | 0 | if (ra_set && regno != frame->fde->cie->return_address_register) |
623 | 0 | { |
624 | 0 | unsigned r = regno; |
625 | 0 | if (ebl_dwarf_to_regno (ebl, &r) && r == ra) |
626 | 0 | continue; |
627 | 0 | } |
628 | | |
629 | 0 | if (! __libdwfl_frame_reg_set (unwound, regno, regval)) |
630 | 0 | { |
631 | 0 | __libdwfl_seterrno (DWFL_E_INVALID_REGISTER); |
632 | 0 | continue; |
633 | 0 | } |
634 | 0 | else if (! ra_set) |
635 | 0 | { |
636 | 0 | unsigned r = regno; |
637 | 0 | if (ebl_dwarf_to_regno (ebl, &r) && r == ra) |
638 | 0 | ra_set = true; |
639 | 0 | } |
640 | 0 | } |
641 | 0 | if (unwound->pc_state == DWFL_FRAME_STATE_ERROR) |
642 | 0 | { |
643 | 0 | int res = INTUSE (dwfl_frame_reg) (unwound, |
644 | 0 | frame->fde->cie->return_address_register, |
645 | 0 | &unwound->pc); |
646 | 0 | if (res == 0) |
647 | 0 | { |
648 | | /* PPC32 __libc_start_main properly CFI-unwinds PC as zero. |
649 | | Currently none of the archs supported for unwinding have |
650 | | zero as a valid PC. */ |
651 | 0 | if (unwound->pc == 0) |
652 | 0 | unwound->pc_state = DWFL_FRAME_STATE_PC_UNDEFINED; |
653 | 0 | else |
654 | 0 | { |
655 | 0 | unwound->pc_state = DWFL_FRAME_STATE_PC_SET; |
656 | | /* In SPARC the return address register actually contains |
657 | | the address of the call instruction instead of the return |
658 | | address. Therefore we add here an offset defined by the |
659 | | backend. Most likely 0. */ |
660 | 0 | unwound->pc += ebl_ra_offset (ebl); |
661 | 0 | } |
662 | 0 | } |
663 | 0 | else |
664 | 0 | { |
665 | | /* We couldn't set the return register, either it was bogus, |
666 | | or the return pc is undefined, maybe end of call stack. */ |
667 | 0 | unsigned pcreg = frame->fde->cie->return_address_register; |
668 | 0 | if (! ebl_dwarf_to_regno (ebl, &pcreg) |
669 | 0 | || pcreg >= ebl_frame_nregs (ebl)) |
670 | 0 | __libdwfl_seterrno (DWFL_E_INVALID_REGISTER); |
671 | 0 | else |
672 | 0 | unwound->pc_state = DWFL_FRAME_STATE_PC_UNDEFINED; |
673 | 0 | } |
674 | 0 | } |
675 | 0 | free (frame); |
676 | 0 | } |
677 | | |
678 | | static bool |
679 | | setfunc (int firstreg, unsigned nregs, const Dwarf_Word *regs, void *arg) |
680 | 0 | { |
681 | 0 | Dwfl_Frame *state = arg; |
682 | 0 | Dwfl_Frame *unwound = state->unwound; |
683 | 0 | if (firstreg < 0) |
684 | 0 | { |
685 | 0 | assert (firstreg == -1); |
686 | 0 | assert (nregs == 1); |
687 | 0 | assert (unwound->pc_state == DWFL_FRAME_STATE_PC_UNDEFINED); |
688 | 0 | unwound->pc = *regs; |
689 | 0 | unwound->pc_state = DWFL_FRAME_STATE_PC_SET; |
690 | 0 | return true; |
691 | 0 | } |
692 | 0 | while (nregs--) |
693 | 0 | if (! __libdwfl_frame_reg_set (unwound, firstreg++, *regs++)) |
694 | 0 | return false; |
695 | 0 | return true; |
696 | 0 | } |
697 | | |
698 | | static bool |
699 | | getfunc (int firstreg, unsigned nregs, Dwarf_Word *regs, void *arg) |
700 | 0 | { |
701 | 0 | Dwfl_Frame *state = arg; |
702 | 0 | assert (firstreg >= 0); |
703 | 0 | while (nregs--) |
704 | 0 | if (INTUSE (dwfl_frame_reg) (state, firstreg++, regs++) != 0) |
705 | 0 | return false; |
706 | 0 | return true; |
707 | 0 | } |
708 | | |
709 | | static bool |
710 | | readfunc (Dwarf_Addr addr, Dwarf_Word *datap, void *arg) |
711 | 0 | { |
712 | 0 | Dwfl_Frame *state = arg; |
713 | 0 | Dwfl_Thread *thread = state->thread; |
714 | 0 | Dwfl_Process *process = thread->process; |
715 | 0 | return process->callbacks->memory_read (process->dwfl, addr, datap, |
716 | 0 | process->callbacks_arg); |
717 | 0 | } |
718 | | |
719 | | void |
720 | | internal_function |
721 | | __libdwfl_frame_unwind (Dwfl_Frame *state) |
722 | 0 | { |
723 | 0 | if (state->unwound) |
724 | 0 | return; |
725 | | /* Do not ask dwfl_frame_pc for ISACTIVATION, it would try to unwind STATE |
726 | | which would deadlock us. */ |
727 | 0 | Dwarf_Addr pc; |
728 | 0 | bool ok = INTUSE(dwfl_frame_pc) (state, &pc, NULL); |
729 | 0 | if (!ok) |
730 | 0 | return; |
731 | | /* Check whether this is the initial frame or a signal frame. |
732 | | Then we need to unwind from the original, unadjusted PC. */ |
733 | 0 | if (! state->initial_frame && ! state->signal_frame) |
734 | 0 | pc--; |
735 | 0 | Dwfl_Module *mod = INTUSE(dwfl_addrmodule) (state->thread->process->dwfl, pc); |
736 | 0 | if (mod == NULL) |
737 | 0 | __libdwfl_seterrno (DWFL_E_NO_DWARF); |
738 | 0 | else |
739 | 0 | { |
740 | 0 | Dwarf_Addr bias; |
741 | 0 | Dwarf_CFI *cfi_eh = INTUSE(dwfl_module_eh_cfi) (mod, &bias); |
742 | 0 | if (cfi_eh) |
743 | 0 | { |
744 | 0 | handle_cfi (state, pc - bias, cfi_eh, bias); |
745 | 0 | if (state->unwound) |
746 | 0 | { |
747 | 0 | state->unwound->unwound_source = DWFL_UNWOUND_EH_CFI; |
748 | 0 | return; |
749 | 0 | } |
750 | 0 | } |
751 | 0 | Dwarf_CFI *cfi_dwarf = INTUSE(dwfl_module_dwarf_cfi) (mod, &bias); |
752 | 0 | if (cfi_dwarf) |
753 | 0 | { |
754 | 0 | handle_cfi (state, pc - bias, cfi_dwarf, bias); |
755 | 0 | if (state->unwound) |
756 | 0 | { |
757 | 0 | state->unwound->unwound_source = DWFL_UNWOUND_DWARF_CFI; |
758 | 0 | return; |
759 | 0 | } |
760 | 0 | } |
761 | 0 | } |
762 | 0 | assert (state->unwound == NULL); |
763 | 0 | Dwfl_Thread *thread = state->thread; |
764 | 0 | Dwfl_Process *process = thread->process; |
765 | 0 | Ebl *ebl = process->ebl; |
766 | 0 | if (new_unwound (state) == NULL) |
767 | 0 | { |
768 | 0 | __libdwfl_seterrno (DWFL_E_NOMEM); |
769 | 0 | return; |
770 | 0 | } |
771 | 0 | state->unwound->pc_state = DWFL_FRAME_STATE_PC_UNDEFINED; |
772 | | // &Dwfl_Frame.signal_frame cannot be passed as it is a bitfield. |
773 | 0 | bool signal_frame = false; |
774 | 0 | if (! ebl_unwind (ebl, pc, setfunc, getfunc, readfunc, state, &signal_frame)) |
775 | 0 | { |
776 | | // Discard the unwind attempt. During next __libdwfl_frame_unwind call |
777 | | // we may have for example the appropriate Dwfl_Module already mapped. |
778 | 0 | assert (state->unwound->unwound == NULL); |
779 | 0 | free (state->unwound); |
780 | 0 | state->unwound = NULL; |
781 | | // __libdwfl_seterrno has been called above. |
782 | 0 | return; |
783 | 0 | } |
784 | 0 | state->unwound->unwound_source = DWFL_UNWOUND_EBL; |
785 | 0 | assert (state->unwound->pc_state == DWFL_FRAME_STATE_PC_SET); |
786 | 0 | state->unwound->signal_frame = signal_frame; |
787 | 0 | } |