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