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; }
/* search this fde table for the one containing the pc */ static fde * search_fdes (fde *this_fde, void *pc) { for (; this_fde->length != 0; this_fde = next_fde (this_fde)) { /* Skip CIEs and linked once FDE entries. */ if (this_fde->CIE_delta == 0 || this_fde->pc_begin == 0) continue; if ((uaddr)((char *)pc - (char *)this_fde->pc_begin) < this_fde->pc_range) return this_fde; } return NULL; }
static size_t count_fdes (fde *this_fde) { size_t count; for (count = 0; this_fde->length != 0; this_fde = next_fde (this_fde)) { /* Skip CIEs and linked once FDE entries. */ if (this_fde->CIE_delta == 0 || this_fde->pc_begin == 0) continue; ++count; } return count; }
static void add_fdes (fde *this_fde, fde_accumulator *accu, void **beg_ptr, void **end_ptr) { void *pc_begin = *beg_ptr; void *pc_end = *end_ptr; for (; this_fde->length != 0; this_fde = next_fde (this_fde)) { /* Skip CIEs and linked once FDE entries. */ if (this_fde->CIE_delta == 0 || this_fde->pc_begin == 0) continue; fde_insert (accu, this_fde); if (this_fde->pc_begin < pc_begin) pc_begin = this_fde->pc_begin; if (this_fde->pc_begin + this_fde->pc_range > pc_end) pc_end = this_fde->pc_begin + this_fde->pc_range; } *beg_ptr = pc_begin; *end_ptr = pc_end; }