void libunwind_frame_prev_register (struct frame_info *next_frame, void **this_cache, int regnum, int *optimizedp, enum lval_type *lvalp, CORE_ADDR *addrp, int *realnump, void *valuep) { struct libunwind_frame_cache *cache = libunwind_frame_cache (next_frame, this_cache); void *ptr; unw_cursor_t *c; unw_save_loc_t sl; int i, ret; unw_word_t intval; unw_fpreg_t fpval; unw_regnum_t uw_regnum; struct libunwind_descr *descr; /* Convert from gdb register number to libunwind register number. */ descr = libunwind_descr (get_frame_arch (next_frame)); uw_regnum = descr->gdb2uw (regnum); gdb_assert (regnum >= 0); if (!target_has_registers) error ("No registers."); *optimizedp = 0; *addrp = 0; *lvalp = not_lval; *realnump = -1; if (valuep) memset (valuep, 0, register_size (current_gdbarch, regnum)); if (uw_regnum < 0) return; /* To get the previous register, we use the libunwind register APIs with the cursor we have already pushed back to the previous frame. */ if (descr->is_fpreg (uw_regnum)) { ret = unw_get_fpreg_p (&cache->cursor, uw_regnum, &fpval); ptr = &fpval; } else { ret = unw_get_reg_p (&cache->cursor, uw_regnum, &intval); ptr = &intval; } if (ret < 0) return; if (valuep) memcpy (valuep, ptr, register_size (current_gdbarch, regnum)); if (unw_get_saveloc_p (&cache->cursor, uw_regnum, &sl) < 0) return; switch (sl.type) { case UNW_SLT_NONE: *optimizedp = 1; break; case UNW_SLT_MEMORY: *lvalp = lval_memory; *addrp = sl.u.addr; break; case UNW_SLT_REG: *lvalp = lval_register; *realnump = regnum; break; } }
struct value * libunwind_frame_prev_register (struct frame_info *this_frame, void **this_cache, int regnum) { struct libunwind_frame_cache *cache = libunwind_frame_cache (this_frame, this_cache); struct gdbarch *gdbarch = get_frame_arch (this_frame); void *ptr; unw_cursor_t *c; unw_save_loc_t sl; int i, ret; unw_word_t intval; unw_fpreg_t fpval; unw_regnum_t uw_regnum; struct libunwind_descr *descr; struct value *val = NULL; if (cache == NULL) return frame_unwind_got_constant (this_frame, regnum, 0); /* Convert from gdb register number to libunwind register number. */ descr = libunwind_descr (get_frame_arch (this_frame)); uw_regnum = descr->gdb2uw (regnum); gdb_assert (regnum >= 0); if (!target_has_registers) error (_("No registers.")); if (uw_regnum < 0) return frame_unwind_got_constant (this_frame, regnum, 0); if (unw_get_saveloc_p (&cache->cursor, uw_regnum, &sl) < 0) return frame_unwind_got_constant (this_frame, regnum, 0); switch (sl.type) { case UNW_SLT_MEMORY: val = frame_unwind_got_memory (this_frame, regnum, sl.u.addr); break; case UNW_SLT_REG: val = frame_unwind_got_register (this_frame, regnum, descr->uw2gdb (sl.u.regnum)); break; case UNW_SLT_NONE: { /* The register is not stored at a specific memory address nor inside another register. So use libunwind to fetch the register value for us, and create a constant value with the result. */ if (descr->is_fpreg (uw_regnum)) { ret = unw_get_fpreg_p (&cache->cursor, uw_regnum, &fpval); if (ret < 0) return frame_unwind_got_constant (this_frame, regnum, 0); val = frame_unwind_got_bytes (this_frame, regnum, (gdb_byte *) &fpval); } else { ret = unw_get_reg_p (&cache->cursor, uw_regnum, &intval); if (ret < 0) return frame_unwind_got_constant (this_frame, regnum, 0); val = frame_unwind_got_constant (this_frame, regnum, intval); } break; } } return val; }