static const struct frame_unwind * frv_linux_sigtramp_frame_sniffer (struct frame_info *next_frame) { CORE_ADDR pc = frame_pc_unwind (next_frame); char *name; find_pc_partial_function (pc, &name, NULL, NULL); if (frv_linux_pc_in_sigtramp (pc, name)) return &frv_linux_sigtramp_frame_unwind; return NULL; }
static int frv_linux_sigtramp_frame_sniffer (const struct frame_unwind *self, struct frame_info *this_frame, void **this_cache) { CORE_ADDR pc = get_frame_pc (this_frame); char *name; find_pc_partial_function (pc, &name, NULL, NULL); if (frv_linux_pc_in_sigtramp (pc, name)) return 1; return 0; }
static LONGEST frv_linux_sigcontext_reg_addr (struct frame_info *this_frame, int regno, CORE_ADDR *sc_addr_cache_ptr) { struct gdbarch *gdbarch = get_frame_arch (this_frame); enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); CORE_ADDR sc_addr; if (sc_addr_cache_ptr && *sc_addr_cache_ptr) { sc_addr = *sc_addr_cache_ptr; } else { CORE_ADDR pc, sp; gdb_byte buf[4]; int tramp_type; pc = get_frame_pc (this_frame); tramp_type = frv_linux_pc_in_sigtramp (gdbarch, pc, 0); get_frame_register (this_frame, sp_regnum, buf); sp = extract_unsigned_integer (buf, sizeof buf, byte_order); if (tramp_type == NORMAL_SIGTRAMP) { /* For a normal sigtramp frame, the sigcontext struct starts at SP + 8. */ sc_addr = sp + 8; } else if (tramp_type == RT_SIGTRAMP) { /* For a realtime sigtramp frame, SP + 12 contains a pointer to a ucontext struct. The ucontext struct contains a sigcontext struct starting 24 bytes in. (The offset of uc_mcontext within struct ucontext is derived as follows: stack_t is a 12-byte struct and struct sigcontext is 8-byte aligned. This gives an offset of 8 + 12 + 4 (for padding) = 24.) */ if (target_read_memory (sp + 12, buf, sizeof buf) != 0) { warning (_("Can't read realtime sigtramp frame.")); return 0; } sc_addr = extract_unsigned_integer (buf, sizeof buf, byte_order); sc_addr += 24; } else internal_error (__FILE__, __LINE__, _("not a signal trampoline")); if (sc_addr_cache_ptr) *sc_addr_cache_ptr = sc_addr; } switch (regno) { case psr_regnum : return sc_addr + 0; /* sc_addr + 4 has "isr", the Integer Status Register. */ case ccr_regnum : return sc_addr + 8; case cccr_regnum : return sc_addr + 12; case lr_regnum : return sc_addr + 16; case lcr_regnum : return sc_addr + 20; case pc_regnum : return sc_addr + 24; /* sc_addr + 28 is __status, the exception status. sc_addr + 32 is syscallno, the syscall number or -1. sc_addr + 36 is orig_gr8, the original syscall arg #1. sc_addr + 40 is gner[0]. sc_addr + 44 is gner[1]. */ case iacc0h_regnum : return sc_addr + 48; case iacc0l_regnum : return sc_addr + 52; default : if (first_gpr_regnum <= regno && regno <= last_gpr_regnum) return sc_addr + 56 + 4 * (regno - first_gpr_regnum); else if (first_fpr_regnum <= regno && regno <= last_fpr_regnum) return sc_addr + 312 + 4 * (regno - first_fpr_regnum); else return -1; /* not saved. */ } }