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