struct frame_state * __frame_state_for (void *pc_target, struct frame_state *state_in) { fde *f; void *insn, *end, *pc; struct cie_info info; struct frame_state_internal state; f = find_fde (pc_target); if (f == 0) return 0; insn = extract_cie_info (f, &info); if (insn == 0) return 0; memset (&state, 0, sizeof (state)); state.s.retaddr_column = info.ra_regno; state.s.eh_ptr = info.eh_ptr; /* First decode all the insns in the CIE. */ end = next_fde ((fde*) get_cie (f)); while (insn < end) insn = execute_cfa_insn (insn, &state, &info, 0); insn = ((fde *)f) + 1; if (info.augmentation[0] == 'z') { int i; insn = decode_uleb128 (insn, &i); insn += i; } /* Then the insns in the FDE up to our target PC. */ end = next_fde (f); pc = f->pc_begin; while (insn < end && pc <= pc_target) insn = execute_cfa_insn (insn, &state, &info, &pc); memcpy (state_in, &state.s, sizeof (state.s)); return state_in; }
static void * extract_cie_info (fde *f, struct cie_info *c) { void *p; int i; c->augmentation = get_cie (f)->augmentation; if (strcmp (c->augmentation, "") != 0 && strcmp (c->augmentation, "eh") != 0 && c->augmentation[0] != 'z') return 0; p = c->augmentation + strlen (c->augmentation) + 1; if (strcmp (c->augmentation, "eh") == 0) { c->eh_ptr = read_pointer (p); p += sizeof (void *); } else c->eh_ptr = 0; p = decode_uleb128 (p, &c->code_align); p = decode_sleb128 (p, &c->data_align); c->ra_regno = *(unsigned char *)p++; /* If the augmentation starts with 'z', we now see the length of the augmentation fields. */ if (c->augmentation[0] == 'z') { p = decode_uleb128 (p, &i); p += i; } return p; }
static inline int get_fde_encoding (struct dwarf_fde *f) { return get_cie_encoding (get_cie (f)); }