Branch data Line data Source code
1 : : /* CFI program execution.
2 : : Copyright (C) 2009-2010, 2014, 2015 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 <dwarf.h>
34 : : #include "libebl.h"
35 : : #include "cfi.h"
36 : : #include "memory-access.h"
37 : : #include "encoded-value.h"
38 : : #include "system.h"
39 : : #include <assert.h>
40 : : #include <stdlib.h>
41 : : #include <string.h>
42 : :
43 : : #define CFI_PRIMARY_MAX 0x3f
44 : :
45 : : static Dwarf_Frame *
46 : 13890 : duplicate_frame_state (const Dwarf_Frame *original,
47 : : Dwarf_Frame *prev)
48 : : {
49 : 13890 : size_t size = offsetof (Dwarf_Frame, regs[original->nregs]);
50 : 13890 : Dwarf_Frame *copy = malloc (size);
51 [ + - ]: 13890 : if (likely (copy != NULL))
52 : : {
53 : 13890 : memcpy (copy, original, size);
54 : 13890 : copy->prev = prev;
55 : : }
56 : 13890 : return copy;
57 : : }
58 : :
59 : : static inline bool
60 : 3700 : enough_registers (Dwarf_Word reg, Dwarf_Frame **pfs, int *result)
61 : : {
62 : : /* Don't allow insanely large register numbers. 268435456 registers
63 : : should be enough for anybody. And very large values might overflow
64 : : the array size and offsetof calculations below. */
65 [ - + ]: 3700 : if (unlikely (reg >= INT32_MAX / sizeof ((*pfs)->regs[0])))
66 : : {
67 : 0 : *result = DWARF_E_INVALID_CFI;
68 : 0 : return false;
69 : : }
70 : :
71 [ + + ]: 3700 : if ((*pfs)->nregs <= reg)
72 : : {
73 : 1756 : size_t size = offsetof (Dwarf_Frame, regs[reg + 1]);
74 : 1756 : Dwarf_Frame *bigger = realloc (*pfs, size);
75 [ - + ]: 1756 : if (unlikely (bigger == NULL))
76 : : {
77 : 0 : *result = DWARF_E_NOMEM;
78 : 0 : return false;
79 : : }
80 : : else
81 : : {
82 : 1756 : eu_static_assert (reg_unspecified == 0);
83 : 1756 : memset (bigger->regs + bigger->nregs, 0,
84 : 1756 : (reg + 1 - bigger->nregs) * sizeof bigger->regs[0]);
85 : 1756 : bigger->nregs = reg + 1;
86 : 1756 : *pfs = bigger;
87 : : }
88 : : }
89 : : return true;
90 : : }
91 : :
92 : : static inline void
93 : 618 : require_cfa_offset (Dwarf_Frame *fs)
94 : : {
95 : 618 : if (unlikely (fs->cfa_rule != cfa_offset))
96 : 0 : fs->cfa_rule = cfa_invalid;
97 : : }
98 : :
99 : : /* Returns a DWARF_E_* error code, usually NOERROR or INVALID_CFI.
100 : : Frees *STATE on failure. */
101 : : static int
102 : 14236 : execute_cfi (Dwarf_CFI *cache,
103 : : const struct dwarf_cie *cie,
104 : : Dwarf_Frame **state,
105 : : const uint8_t *program, const uint8_t *const end, bool abi_cfi,
106 : : Dwarf_Addr loc, Dwarf_Addr find_pc)
107 : : {
108 : : /* The caller should not give us anything out of range. */
109 [ - + ]: 14236 : assert (loc <= find_pc);
110 : :
111 : 14236 : int result = DWARF_E_NOERROR;
112 : :
113 : : #define cfi_assert(ok) do { \
114 : : if (likely (ok)) break; \
115 : : result = DWARF_E_INVALID_CFI; \
116 : : goto out; \
117 : : } while (0)
118 : :
119 : 14236 : Dwarf_Frame *fs = *state;
120 : :
121 : : #define register_rule(regno, r_rule, r_value) do { \
122 : : if (unlikely (! enough_registers (regno, &fs, &result))) \
123 : : goto out; \
124 : : fs->regs[regno].rule = reg_##r_rule; \
125 : : fs->regs[regno].value = (r_value); \
126 : : } while (0)
127 : :
128 : : /* The AARCH64 DWARF ABI states that register 34 (ra_sign_state) must
129 : : be initialized to 0. So do it before executing the CFI. */
130 [ + + ]: 14236 : if (cache->e_machine == EM_AARCH64)
131 : : {
132 [ - + ]: 88 : if (unlikely (! enough_registers (DW_AARCH64_RA_SIGN_STATE, &fs, &result)))
133 : 0 : goto out;
134 : 88 : fs->regs[DW_AARCH64_RA_SIGN_STATE].value = 0;
135 : : }
136 : :
137 [ + + ]: 35298 : while (program < end)
138 : : {
139 : 29958 : uint8_t opcode = *program++;
140 : 29958 : Dwarf_Word regno;
141 : 29958 : Dwarf_Word offset;
142 : 29958 : Dwarf_Word sf_offset;
143 : 29958 : Dwarf_Word operand = opcode & CFI_PRIMARY_MAX;
144 [ + + + - : 29958 : switch (opcode)
- - + + -
+ - - + +
- + + - +
- + + - -
+ + + + +
- - ]
145 : : {
146 : : /* These cases move LOC, i.e. "create a new table row". */
147 : :
148 : 236 : case DW_CFA_advance_loc1:
149 : 236 : operand = *program++;
150 : 9682 : FALLTHROUGH;
151 : : case DW_CFA_advance_loc + 0 ... DW_CFA_advance_loc + CFI_PRIMARY_MAX:
152 : 9682 : advance_loc:
153 : 9682 : loc += operand * cie->code_alignment_factor;
154 : 9682 : break;
155 : :
156 : 26 : case DW_CFA_advance_loc2:
157 [ - + ]: 26 : cfi_assert (program + 2 <= end);
158 [ + + ]: 26 : operand = read_2ubyte_unaligned_inc (cache, program);
159 : 26 : goto advance_loc;
160 : 0 : case DW_CFA_advance_loc4:
161 [ # # ]: 0 : cfi_assert (program + 4 <= end);
162 [ # # ]: 0 : operand = read_4ubyte_unaligned_inc (cache, program);
163 : 0 : goto advance_loc;
164 : 0 : case DW_CFA_MIPS_advance_loc8:
165 [ # # ]: 0 : cfi_assert (program + 8 <= end);
166 [ # # ]: 0 : operand = read_8ubyte_unaligned_inc (cache, program);
167 : 0 : goto advance_loc;
168 : :
169 : 0 : case DW_CFA_set_loc:
170 [ # # ]: 0 : if (likely (!read_encoded_value (cache, cie->fde_encoding,
171 : : &program, &loc)))
172 : : break;
173 : 0 : result = INTUSE(dwarf_errno) ();
174 : 0 : goto out;
175 : :
176 : : /* Now all following cases affect this row, but do not touch LOC.
177 : : These cases end with 'continue'. We only get out of the
178 : : switch block for the row-copying (LOC-moving) cases above. */
179 : :
180 : 218 : case DW_CFA_def_cfa:
181 : 218 : get_uleb128 (operand, program, end);
182 [ - + ]: 218 : cfi_assert (program < end);
183 : 218 : get_uleb128 (offset, program, end);
184 : 218 : def_cfa:
185 : 218 : fs->cfa_rule = cfa_offset;
186 : 218 : fs->cfa_val_reg = operand;
187 : 218 : fs->cfa_val_offset = offset;
188 : : /* Prime the rest of the Dwarf_Op so dwarf_frame_cfa can use it. */
189 : 218 : fs->cfa_data.offset.atom = DW_OP_bregx;
190 : 218 : fs->cfa_data.offset.offset = 0;
191 : 218 : continue;
192 : :
193 : 114 : case DW_CFA_def_cfa_register:
194 : 114 : get_uleb128 (regno, program, end);
195 [ - + ]: 114 : require_cfa_offset (fs);
196 : 114 : fs->cfa_val_reg = regno;
197 : 114 : continue;
198 : :
199 : 0 : case DW_CFA_def_cfa_sf:
200 : 0 : get_uleb128 (operand, program, end);
201 [ # # ]: 0 : cfi_assert (program < end);
202 : 0 : get_sleb128 (sf_offset, program, end);
203 : 0 : offset = sf_offset * cie->data_alignment_factor;
204 : 0 : goto def_cfa;
205 : :
206 : 504 : case DW_CFA_def_cfa_offset:
207 : 504 : get_uleb128 (offset, program, end);
208 : 504 : def_cfa_offset:
209 [ - + ]: 504 : require_cfa_offset (fs);
210 : 504 : fs->cfa_val_offset = offset;
211 : 504 : continue;
212 : :
213 : 0 : case DW_CFA_def_cfa_offset_sf:
214 : 0 : get_sleb128 (sf_offset, program, end);
215 : 0 : offset = sf_offset * cie->data_alignment_factor;
216 : 0 : goto def_cfa_offset;
217 : :
218 : 0 : case DW_CFA_def_cfa_expression:
219 : : /* DW_FORM_block is a ULEB128 length followed by that many bytes. */
220 : 0 : get_uleb128 (operand, program, end);
221 [ # # ]: 0 : cfi_assert (operand <= (Dwarf_Word) (end - program));
222 : 0 : fs->cfa_rule = cfa_expr;
223 : 0 : fs->cfa_data.expr.data = (unsigned char *) program;
224 : 0 : fs->cfa_data.expr.length = operand;
225 : 0 : program += operand;
226 : 0 : continue;
227 : :
228 : 22 : case DW_CFA_undefined:
229 : 22 : get_uleb128 (regno, program, end);
230 [ - + ]: 22 : register_rule (regno, undefined, 0);
231 : 22 : continue;
232 : :
233 : 2382 : case DW_CFA_same_value:
234 : 2382 : get_uleb128 (regno, program, end);
235 [ - + ]: 2382 : register_rule (regno, same_value, 0);
236 : 2382 : continue;
237 : :
238 : 0 : case DW_CFA_offset_extended:
239 : 0 : get_uleb128 (operand, program, end);
240 [ # # ]: 0 : cfi_assert (program < end);
241 : 872 : FALLTHROUGH;
242 : : case DW_CFA_offset + 0 ... DW_CFA_offset + CFI_PRIMARY_MAX:
243 : 872 : get_uleb128 (offset, program, end);
244 : 872 : offset *= cie->data_alignment_factor;
245 : 894 : offset_extended:
246 [ - + ]: 894 : register_rule (operand, offset, offset);
247 : 894 : continue;
248 : :
249 : 22 : case DW_CFA_offset_extended_sf:
250 : 22 : get_uleb128 (operand, program, end);
251 [ - + ]: 22 : cfi_assert (program < end);
252 : 22 : get_sleb128 (sf_offset, program, end);
253 : 22 : offset_extended_sf:
254 : 22 : offset = sf_offset * cie->data_alignment_factor;
255 : 22 : goto offset_extended;
256 : :
257 : 0 : case DW_CFA_GNU_negative_offset_extended:
258 : : /* GNU extension obsoleted by DW_CFA_offset_extended_sf. */
259 : 0 : get_uleb128 (operand, program, end);
260 [ # # ]: 0 : cfi_assert (program < end);
261 : 0 : get_uleb128 (offset, program, end);
262 : 0 : sf_offset = -offset;
263 : 0 : goto offset_extended_sf;
264 : :
265 : 176 : case DW_CFA_val_offset:
266 : 176 : get_uleb128 (operand, program, end);
267 [ - + ]: 176 : cfi_assert (program < end);
268 : 176 : get_uleb128 (offset, program, end);
269 : 176 : offset *= cie->data_alignment_factor;
270 : 176 : val_offset:
271 [ - + ]: 176 : register_rule (operand, val_offset, offset);
272 : 176 : continue;
273 : :
274 : 0 : case DW_CFA_val_offset_sf:
275 : 0 : get_uleb128 (operand, program, end);
276 [ # # ]: 0 : cfi_assert (program < end);
277 : 0 : get_sleb128 (sf_offset, program, end);
278 : 0 : offset = sf_offset * cie->data_alignment_factor;
279 : 0 : goto val_offset;
280 : :
281 : 26 : case DW_CFA_register:
282 : 26 : get_uleb128 (regno, program, end);
283 [ - + ]: 26 : cfi_assert (program < end);
284 : 26 : get_uleb128 (operand, program, end);
285 [ - + ]: 26 : register_rule (regno, register, operand);
286 : 26 : continue;
287 : :
288 : 2 : case DW_CFA_expression:
289 : : /* Expression rule relies on section data, abi_cfi cannot use it. */
290 [ - + ]: 2 : assert (! abi_cfi);
291 : 2 : get_uleb128 (regno, program, end);
292 : 2 : offset = program - (const uint8_t *) cache->data->d.d_buf;
293 : : /* DW_FORM_block is a ULEB128 length followed by that many bytes. */
294 [ - + ]: 2 : cfi_assert (program < end);
295 : 2 : get_uleb128 (operand, program, end);
296 [ - + ]: 2 : cfi_assert (operand <= (Dwarf_Word) (end - program));
297 : 2 : program += operand;
298 [ - + ]: 2 : register_rule (regno, expression, offset);
299 : 2 : continue;
300 : :
301 : 0 : case DW_CFA_val_expression:
302 : : /* Expression rule relies on section data, abi_cfi cannot use it. */
303 [ # # ]: 0 : assert (! abi_cfi);
304 : 0 : get_uleb128 (regno, program, end);
305 : : /* DW_FORM_block is a ULEB128 length followed by that many bytes. */
306 : 0 : offset = program - (const uint8_t *) cache->data->d.d_buf;
307 [ # # ]: 0 : cfi_assert (program < end);
308 : 0 : get_uleb128 (operand, program, end);
309 [ # # ]: 0 : cfi_assert (operand <= (Dwarf_Word) (end - program));
310 : 0 : program += operand;
311 [ # # ]: 0 : register_rule (regno, val_expression, offset);
312 : 0 : continue;
313 : :
314 : 0 : case DW_CFA_restore_extended:
315 : 0 : get_uleb128 (operand, program, end);
316 : 74 : FALLTHROUGH;
317 : 74 : case DW_CFA_restore + 0 ... DW_CFA_restore + CFI_PRIMARY_MAX:
318 : :
319 [ - + - - ]: 74 : if (unlikely (abi_cfi) && likely (opcode == DW_CFA_restore))
320 : : {
321 : : /* Special case hack to give backend abi_cfi a shorthand. */
322 : 0 : cache->default_same_value = true;
323 : 0 : continue;
324 : : }
325 : :
326 : : /* This can't be used in the CIE's own initial instructions. */
327 [ - + ]: 74 : cfi_assert (cie->initial_state != NULL);
328 : :
329 : : /* Restore the CIE's initial rule for this register. */
330 [ - + ]: 74 : if (unlikely (! enough_registers (operand, &fs, &result)))
331 : 0 : goto out;
332 [ + - ]: 74 : if (cie->initial_state->nregs > operand)
333 : 74 : fs->regs[operand] = cie->initial_state->regs[operand];
334 : : else
335 : 0 : fs->regs[operand].rule = reg_unspecified;
336 : 74 : continue;
337 : :
338 : 30 : case DW_CFA_remember_state:
339 : 30 : {
340 : : /* Duplicate the state and chain the copy on. */
341 : 30 : Dwarf_Frame *copy = duplicate_frame_state (fs, fs);
342 [ - + ]: 30 : if (unlikely (copy == NULL))
343 : : {
344 : 0 : result = DWARF_E_NOMEM;
345 : 0 : goto out;
346 : : }
347 : 30 : fs = copy;
348 : 30 : continue;
349 : : }
350 : :
351 : 30 : case DW_CFA_restore_state:
352 : 30 : {
353 : : /* Pop the current state off and use the old one instead. */
354 : 30 : Dwarf_Frame *prev = fs->prev;
355 [ - + ]: 30 : cfi_assert (prev != NULL);
356 : 30 : free (fs);
357 : 30 : fs = prev;
358 : 30 : continue;
359 : : }
360 : :
361 : 15768 : case DW_CFA_nop:
362 : 15768 : continue;
363 : :
364 : 36 : case DW_CFA_GNU_window_save: /* DW_CFA_AARCH64_negate_ra_state */
365 [ + + ]: 36 : if (cache->e_machine == EM_AARCH64)
366 : : {
367 : : /* Toggles the return address state, indicating whether
368 : : the return address is encrypted or not on
369 : : aarch64. */
370 [ - + ]: 18 : if (unlikely (! enough_registers (DW_AARCH64_RA_SIGN_STATE, &fs, &result)))
371 : 0 : goto out;
372 : 18 : fs->regs[DW_AARCH64_RA_SIGN_STATE].value ^= 0x1;
373 : : }
374 : : else
375 : : {
376 : : /* This is magic shorthand used only by SPARC. It's
377 : : equivalent to a bunch of DW_CFA_register and
378 : : DW_CFA_offset operations. */
379 [ - + ]: 18 : if (unlikely (! enough_registers (31, &fs, &result)))
380 : 0 : goto out;
381 [ + + ]: 162 : for (regno = 8; regno < 16; ++regno)
382 : : {
383 : : /* Find each %oN in %iN. */
384 : 144 : fs->regs[regno].rule = reg_register;
385 : 144 : fs->regs[regno].value = regno + 16;
386 : : }
387 : 18 : unsigned int address_size;
388 : 36 : address_size = (cache->e_ident[EI_CLASS] == ELFCLASS32
389 [ + - ]: 18 : ? 4 : 8);
390 [ + + ]: 306 : for (; regno < 32; ++regno)
391 : : {
392 : : /* Find %l0..%l7 and %i0..%i7 in a block at the CFA. */
393 : 288 : fs->regs[regno].rule = reg_offset;
394 : 288 : fs->regs[regno].value = (regno - 16) * address_size;
395 : : }
396 : : }
397 : 36 : continue;
398 : :
399 : 0 : case DW_CFA_GNU_args_size:
400 : : /* XXX is this useful for anything? */
401 : 0 : get_uleb128 (operand, program, end);
402 : 0 : continue;
403 : :
404 : : default:
405 : 0 : cfi_assert (false);
406 : : continue;
407 : : }
408 : :
409 : : /* We get here only for the cases that have just moved LOC. */
410 [ - + ]: 9682 : cfi_assert (cie->initial_state != NULL);
411 [ + + ]: 9682 : if (find_pc >= loc)
412 : : /* This advance has not yet reached FIND_PC. */
413 : 786 : fs->start = loc;
414 : : else
415 : : {
416 : : /* We have just advanced past the address we're looking for.
417 : : The state currently described is what we want to see. */
418 : 8896 : fs->end = loc;
419 : 8896 : break;
420 : : }
421 : : }
422 : :
423 : : /* "The end of the instruction stream can be thought of as a
424 : : DW_CFA_set_loc (initial_location + address_range) instruction."
425 : : (DWARF 3.0 Section 6.4.3)
426 : :
427 : : When we fall off the end of the program without an advance_loc/set_loc
428 : : that put us past FIND_PC, the final state left by the FDE program
429 : : applies to this address (the caller ensured it was inside the FDE).
430 : : This address (FDE->end) is already in FS->end as set by the caller. */
431 : :
432 : : #undef register_rule
433 : : #undef cfi_assert
434 : :
435 : 5340 : out:
436 : :
437 : : /* Pop any remembered states left on the stack. */
438 [ - + ]: 14236 : while (fs->prev != NULL)
439 : : {
440 : 0 : Dwarf_Frame *prev = fs->prev;
441 : 0 : fs->prev = prev->prev;
442 : 0 : free (prev);
443 : : }
444 : :
445 [ + - ]: 14236 : if (likely (result == DWARF_E_NOERROR))
446 : 14236 : *state = fs;
447 : : else
448 : 0 : free (fs);
449 : :
450 : 14236 : return result;
451 : : }
452 : :
453 : : static int
454 : 13860 : cie_cache_initial_state (Dwarf_CFI *cache, struct dwarf_cie *cie)
455 : : {
456 : 13860 : int result = DWARF_E_NOERROR;
457 : :
458 [ + + ]: 13860 : if (likely (cie->initial_state != NULL))
459 : : return result;
460 : :
461 : : /* This CIE has not been used before. Play out its initial
462 : : instructions and cache the initial state that results.
463 : : First we'll let the backend fill in the default initial
464 : : state for this machine's ABI. */
465 : :
466 : 188 : Dwarf_CIE abi_info = { DW_CIE_ID_64, NULL, NULL, 1, 1, -1, "", NULL, 0, 0 };
467 : :
468 : : /* Make sure we have a backend handle cached. */
469 [ + + ]: 188 : if (unlikely (cache->ebl == NULL))
470 : : {
471 : 12 : cache->ebl = ebl_openbackend (cache->data->s->elf);
472 [ - + ]: 12 : if (unlikely (cache->ebl == NULL))
473 : 0 : cache->ebl = (void *) -1l;
474 : : }
475 : :
476 : : /* Fetch the ABI's default CFI program. */
477 [ + - ]: 188 : if (likely (cache->ebl != (void *) -1l)
478 [ + - ]: 188 : && unlikely (ebl_abi_cfi (cache->ebl, &abi_info) < 0))
479 : : return DWARF_E_UNKNOWN_ERROR;
480 : :
481 : 188 : Dwarf_Frame *cie_fs = calloc (1, sizeof (Dwarf_Frame));
482 [ + - ]: 188 : if (unlikely (cie_fs == NULL))
483 : : return DWARF_E_NOMEM;
484 : :
485 : : /* If the default state of any register is not "undefined"
486 : : (i.e. call-clobbered), then the backend supplies instructions
487 : : for the standard initial state. */
488 [ + - ]: 188 : if (abi_info.initial_instructions_end > abi_info.initial_instructions)
489 : : {
490 : : /* Dummy CIE for backend's instructions. */
491 : 188 : struct dwarf_cie abi_cie =
492 : : {
493 : 188 : .code_alignment_factor = abi_info.code_alignment_factor,
494 : 188 : .data_alignment_factor = abi_info.data_alignment_factor,
495 : : };
496 : 188 : result = execute_cfi (cache, &abi_cie, &cie_fs,
497 : : abi_info.initial_instructions,
498 : : abi_info.initial_instructions_end, true,
499 : : 0, (Dwarf_Addr) -1l);
500 : : }
501 : :
502 : : /* Now run the CIE's initial instructions. */
503 [ + - ]: 188 : if (cie->initial_instructions_end > cie->initial_instructions
504 [ + - ]: 188 : && likely (result == DWARF_E_NOERROR))
505 : 188 : result = execute_cfi (cache, cie, &cie_fs,
506 : : cie->initial_instructions,
507 : : cie->initial_instructions_end, false,
508 : : 0, (Dwarf_Addr) -1l);
509 : :
510 [ + - ]: 188 : if (likely (result == DWARF_E_NOERROR))
511 : : {
512 : : /* Now we have the initial state of things that all
513 : : FDEs using this CIE will start from. */
514 : 188 : cie_fs->cache = cache;
515 : 188 : cie->initial_state = cie_fs;
516 : : }
517 : :
518 : : return result;
519 : : }
520 : :
521 : : int
522 : : internal_function
523 : 13860 : __libdw_frame_at_address (Dwarf_CFI *cache, struct dwarf_fde *fde,
524 : : Dwarf_Addr address, Dwarf_Frame **frame)
525 : : {
526 : 13860 : int result = cie_cache_initial_state (cache, fde->cie);
527 [ + - ]: 13860 : if (likely (result == DWARF_E_NOERROR))
528 : : {
529 : 13860 : Dwarf_Frame *fs = duplicate_frame_state (fde->cie->initial_state, NULL);
530 [ - + ]: 13860 : if (unlikely (fs == NULL))
531 : 0 : return DWARF_E_NOMEM;
532 : :
533 : 13860 : fs->fde = fde;
534 : 13860 : fs->start = fde->start;
535 : 13860 : fs->end = fde->end;
536 : :
537 : 13860 : result = execute_cfi (cache, fde->cie, &fs,
538 : : fde->instructions, fde->instructions_end, false,
539 : : fde->start, address);
540 [ + - ]: 13860 : if (likely (result == DWARF_E_NOERROR))
541 : 13860 : *frame = fs;
542 : : }
543 : : return result;
544 : : }
|