Index: arm-linux-tdep.c =================================================================== RCS file: /cvs/src/src/gdb/arm-linux-tdep.c,v retrieving revision 1.16 diff -p -r1.16 arm-linux-tdep.c *** arm-linux-tdep.c 2002/02/15 16:12:22 1.16 --- arm-linux-tdep.c 2002/02/18 13:28:16 *************** LONGEST arm_linux_call_dummy_words[] = *** 58,97 **** 0xe1a0e00f, 0xe1a0f004, 0xef9f001 }; ! #ifdef GET_LONGJMP_TARGET ! ! /* Figure out where the longjmp will land. We expect that we have ! just entered longjmp and haven't yet altered r0, r1, so the ! arguments are still in the registers. (ARM_A1_REGNUM) points at ! the jmp_buf structure from which we extract the pc (JB_PC) that we ! will land at. The pc is copied into ADDR. This routine returns ! true on success. */ ! ! #define LONGJMP_TARGET_SIZE sizeof(int) ! #define JB_ELEMENT_SIZE sizeof(int) ! #define JB_SL 18 ! #define JB_FP 19 ! #define JB_SP 20 #define JB_PC 21 - int - arm_get_longjmp_target (CORE_ADDR * pc) - { - CORE_ADDR jb_addr; - char buf[LONGJMP_TARGET_SIZE]; - - jb_addr = read_register (ARM_A1_REGNUM); - - if (target_read_memory (jb_addr + JB_PC * JB_ELEMENT_SIZE, buf, - LONGJMP_TARGET_SIZE)) - return 0; - - *pc = extract_address (buf, LONGJMP_TARGET_SIZE); - return 1; - } - - #endif /* GET_LONGJMP_TARGET */ - /* Extract from an array REGBUF containing the (raw) register state a function return value of type TYPE, and copy that, in virtual format, into VALBUF. */ --- 58,67 ---- 0xe1a0e00f, 0xe1a0f004, 0xef9f001 }; ! /* Description of the longjmp buffer. */ ! #define JB_ELEMENT_SIZE INT_REGISTER_RAW_SIZE #define JB_PC 21 /* Extract from an array REGBUF containing the (raw) register state a function return value of type TYPE, and copy that, in virtual format, into VALBUF. */ *************** arm_linux_init_abi (struct gdbarch_info *** 548,553 **** --- 518,526 ---- tdep->lowest_pc = 0x8000; tdep->arm_breakpoint = arm_linux_arm_le_breakpoint; tdep->arm_breakpoint_size = sizeof (arm_linux_arm_le_breakpoint); + + tdep->jb_pc = JB_PC; + tdep->jb_elt_size = JB_ELEMENT_SIZE; } void Index: arm-tdep.c =================================================================== RCS file: /cvs/src/src/gdb/arm-tdep.c,v retrieving revision 1.43 diff -p -r1.43 arm-tdep.c *** arm-tdep.c 2002/02/15 16:12:22 1.43 --- arm-tdep.c 2002/02/18 13:28:16 *************** arm_store_struct_return (CORE_ADDR addr, *** 2272,2277 **** --- 2272,2294 ---- write_register (ARM_A1_REGNUM, addr); } + static int + arm_get_longjmp_target (CORE_ADDR *pc) + { + CORE_ADDR jb_addr; + char buf[INT_REGISTER_RAW_SIZE]; + struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch); + + jb_addr = read_register (ARM_A1_REGNUM); + + if (target_read_memory (jb_addr + tdep->jb_pc * tdep->jb_elt_size, buf, + INT_REGISTER_RAW_SIZE)) + return 0; + + *pc = extract_address (buf, INT_REGISTER_RAW_SIZE); + return 1; + } + /* Return non-zero if the PC is inside a thumb call thunk. */ int *************** arm_gdbarch_init (struct gdbarch_info in *** 2775,2781 **** --- 2792,2800 ---- "arm_gdbarch_init: bad byte order for float format"); } + /* This should be low enough for everything. */ tdep->lowest_pc = 0x20; + tdep->jb_pc = -1; /* Longjump support not enabled by default. */ set_gdbarch_use_generic_dummy_frames (gdbarch, 0); *************** arm_gdbarch_init (struct gdbarch_info in *** 2903,2908 **** --- 2922,2930 ---- /* Now we have tuned the configuration, set a few final things, based on what the OS ABI has told us. */ + + if (tdep->jb_pc >= 0) + set_gdbarch_get_longjmp_target (gdbarch, arm_get_longjmp_target); /* We can't use SIZEOF_FRAME_SAVED_REGS here, since that still references the old architecture vector, not the one we are Index: arm-tdep.h =================================================================== RCS file: /cvs/src/src/gdb/arm-tdep.h,v retrieving revision 1.4 diff -p -r1.4 arm-tdep.h *** arm-tdep.h 2002/02/15 16:12:22 1.4 --- arm-tdep.h 2002/02/18 13:28:16 *************** struct gdbarch_tdep *** 123,132 **** const char *abi_name; /* Name of the above. */ CORE_ADDR lowest_pc; /* Lowest address at which instructions will appear. */ ! const char *arm_breakpoint; ! int arm_breakpoint_size; ! const char *thumb_breakpoint; ! int thumb_breakpoint_size; }; #ifndef LOWEST_PC --- 123,138 ---- const char *abi_name; /* Name of the above. */ CORE_ADDR lowest_pc; /* Lowest address at which instructions will appear. */ ! ! const char *arm_breakpoint; /* Breakpoint pattern for an ARM insn. */ ! int arm_breakpoint_size; /* And its size. */ ! const char *thumb_breakpoint; /* Breakpoint pattern for an ARM insn. */ ! int thumb_breakpoint_size; /* And its size. */ ! ! int jb_pc; /* Offset to PC value in jump buffer. ! If this is negative, longjmp support ! will be disabled. */ ! size_t jb_elt_size; /* And the size of each entry in the buf. */ }; #ifndef LOWEST_PC Index: armnbsd-nat.c =================================================================== RCS file: /cvs/src/src/gdb/armnbsd-nat.c,v retrieving revision 1.4 diff -p -r1.4 armnbsd-nat.c *** armnbsd-nat.c 2002/02/15 13:35:26 1.4 --- armnbsd-nat.c 2002/02/18 13:28:16 *************** fetch_core_registers (core_reg_sect, cor *** 97,105 **** #else #error Not FETCH_INFERIOR_REGISTERS #endif /* !FETCH_INFERIOR_REGISTERS */ - - int - get_longjmp_target (CORE_ADDR *addr) - { - return 0; - } --- 97,99 ---- Index: armnbsd-tdep.c =================================================================== RCS file: /cvs/src/src/gdb/armnbsd-tdep.c,v retrieving revision 1.1 diff -p -r1.1 armnbsd-tdep.c *** armnbsd-tdep.c 2002/02/15 16:12:22 1.1 --- armnbsd-tdep.c 2002/02/18 13:28:16 *************** *** 22,27 **** --- 22,31 ---- #include "arm-tdep.h" + /* Description of the longjmp buffer. */ + #define JB_PC 24 + #define JB_ELEMENT_SIZE INT_REGISTER_RAW_SIZE + /* For compatibility with previous implemenations of GDB on arm/NetBSD, override the default little-endian breakpoint. */ static const char arm_nbsd_arm_le_breakpoint[] = {0x11, 0x00, 0x00, 0xe6}; *************** arm_netbsd_init_abi_common (struct gdbar *** 35,40 **** --- 39,47 ---- tdep->lowest_pc = 0x8000; tdep->arm_breakpoint = arm_nbsd_arm_le_breakpoint; tdep->arm_breakpoint_size = sizeof (arm_nbsd_arm_le_breakpoint); + + tdep->jb_pc = JB_PC; + tdep->jb_elt_size = JB_ELEMENT_SIZE; } static void Index: breakpoint.c =================================================================== RCS file: /cvs/src/src/gdb/breakpoint.c,v retrieving revision 1.65 diff -p -r1.65 breakpoint.c *** breakpoint.c 2002/02/06 18:31:06 1.65 --- breakpoint.c 2002/02/18 13:28:17 *************** static int cover_target_enable_exception *** 143,151 **** static void maintenance_info_breakpoints (char *, int); - #ifdef GET_LONGJMP_TARGET static void create_longjmp_breakpoint (char *); - #endif static void create_overlay_event_breakpoint (char *); --- 143,149 ---- *************** create_internal_breakpoint (CORE_ADDR ad *** 3758,3764 **** return b; } - #ifdef GET_LONGJMP_TARGET static void create_longjmp_breakpoint (char *func_name) --- 3756,3761 ---- *************** create_longjmp_breakpoint (char *func_na *** 3782,3789 **** b->addr_string = xstrdup (func_name); } - #endif /* #ifdef GET_LONGJMP_TARGET */ - /* Call this routine when stepping and nexting to enable a breakpoint if we do a longjmp(). When we hit that breakpoint, call set_longjmp_resume_breakpoint() to figure out where we are going. */ --- 3779,3784 ---- *************** breakpoint_re_set (void) *** 6967,6979 **** set_language (save_language); input_radix = save_input_radix; ! #ifdef GET_LONGJMP_TARGET ! create_longjmp_breakpoint ("longjmp"); ! create_longjmp_breakpoint ("_longjmp"); ! create_longjmp_breakpoint ("siglongjmp"); ! create_longjmp_breakpoint ("_siglongjmp"); ! create_longjmp_breakpoint (NULL); ! #endif create_overlay_event_breakpoint ("_ovly_debug_event"); } --- 6962,6975 ---- set_language (save_language); input_radix = save_input_radix; ! if (GET_LONGJMP_TARGET_P ()) ! { ! create_longjmp_breakpoint ("longjmp"); ! create_longjmp_breakpoint ("_longjmp"); ! create_longjmp_breakpoint ("siglongjmp"); ! create_longjmp_breakpoint ("_siglongjmp"); ! create_longjmp_breakpoint (NULL); ! } create_overlay_event_breakpoint ("_ovly_debug_event"); } Index: gdbarch.c =================================================================== RCS file: /cvs/src/src/gdb/gdbarch.c,v retrieving revision 1.108 diff -p -r1.108 gdbarch.c *** gdbarch.c 2002/02/16 23:09:16 1.108 --- gdbarch.c 2002/02/18 13:28:17 *************** struct gdbarch *** 182,187 **** --- 182,188 ---- gdbarch_register_bytes_ok_ftype *register_bytes_ok; gdbarch_cannot_fetch_register_ftype *cannot_fetch_register; gdbarch_cannot_store_register_ftype *cannot_store_register; + gdbarch_get_longjmp_target_ftype *get_longjmp_target; int use_generic_dummy_frames; int call_dummy_location; gdbarch_call_dummy_address_ftype *call_dummy_address; *************** struct gdbarch startup_gdbarch = *** 346,351 **** --- 347,353 ---- 0, 0, 0, + 0, generic_get_saved_register, 0, 0, *************** verify_gdbarch (struct gdbarch *gdbarch) *** 638,643 **** --- 640,646 ---- /* Skip verify of register_bytes_ok, has predicate */ /* Skip verify of cannot_fetch_register, invalid_p == 0 */ /* Skip verify of cannot_store_register, invalid_p == 0 */ + /* Skip verify of get_longjmp_target, has predicate */ if ((GDB_MULTI_ARCH >= GDB_MULTI_ARCH_PARTIAL) && (gdbarch->use_generic_dummy_frames == -1)) fprintf_unfiltered (log, "\n\tuse_generic_dummy_frames"); *************** gdbarch_dump (struct gdbarch *gdbarch, s *** 1282,1287 **** --- 1285,1301 ---- "gdbarch_dump: FUNCTION_START_OFFSET = %ld\n", (long) FUNCTION_START_OFFSET); #endif + #ifdef GET_LONGJMP_TARGET + fprintf_unfiltered (file, + "gdbarch_dump: %s # %s\n", + "GET_LONGJMP_TARGET(pc)", + XSTRING (GET_LONGJMP_TARGET (pc))); + if (GDB_MULTI_ARCH) + fprintf_unfiltered (file, + "gdbarch_dump: GET_LONGJMP_TARGET = 0x%08lx\n", + (long) current_gdbarch->get_longjmp_target + /*GET_LONGJMP_TARGET ()*/); + #endif #ifdef GET_SAVED_REGISTER #if GDB_MULTI_ARCH /* Macro might contain `[{}]' when not multi-arch */ *************** set_gdbarch_cannot_store_register (struc *** 3027,3032 **** --- 3041,3070 ---- gdbarch_cannot_store_register_ftype cannot_store_register) { gdbarch->cannot_store_register = cannot_store_register; + } + + int + gdbarch_get_longjmp_target_p (struct gdbarch *gdbarch) + { + return gdbarch->get_longjmp_target != 0; + } + + int + gdbarch_get_longjmp_target (struct gdbarch *gdbarch, CORE_ADDR *pc) + { + if (gdbarch->get_longjmp_target == 0) + internal_error (__FILE__, __LINE__, + "gdbarch: gdbarch_get_longjmp_target invalid"); + if (gdbarch_debug >= 2) + fprintf_unfiltered (gdb_stdlog, "gdbarch_get_longjmp_target called\n"); + return gdbarch->get_longjmp_target (pc); + } + + void + set_gdbarch_get_longjmp_target (struct gdbarch *gdbarch, + gdbarch_get_longjmp_target_ftype get_longjmp_target) + { + gdbarch->get_longjmp_target = get_longjmp_target; } int Index: gdbarch.h =================================================================== RCS file: /cvs/src/src/gdb/gdbarch.h,v retrieving revision 1.82 diff -p -r1.82 gdbarch.h *** gdbarch.h 2002/02/16 23:09:16 1.82 --- gdbarch.h 2002/02/18 13:28:18 *************** extern void set_gdbarch_cannot_store_reg *** 883,888 **** --- 883,927 ---- #endif #endif + /* setjmp/longjmp support. */ + + #if defined (GET_LONGJMP_TARGET) + /* Legacy for systems yet to multi-arch GET_LONGJMP_TARGET */ + #if !defined (GET_LONGJMP_TARGET_P) + #define GET_LONGJMP_TARGET_P() (1) + #endif + #endif + + /* Default predicate for non- multi-arch targets. */ + #if (!GDB_MULTI_ARCH) && !defined (GET_LONGJMP_TARGET_P) + #define GET_LONGJMP_TARGET_P() (0) + #endif + + extern int gdbarch_get_longjmp_target_p (struct gdbarch *gdbarch); + #if (GDB_MULTI_ARCH > GDB_MULTI_ARCH_PARTIAL) && defined (GET_LONGJMP_TARGET_P) + #error "Non multi-arch definition of GET_LONGJMP_TARGET" + #endif + #if (GDB_MULTI_ARCH > GDB_MULTI_ARCH_PARTIAL) || !defined (GET_LONGJMP_TARGET_P) + #define GET_LONGJMP_TARGET_P() (gdbarch_get_longjmp_target_p (current_gdbarch)) + #endif + + /* Default (function) for non- multi-arch platforms. */ + #if (!GDB_MULTI_ARCH) && !defined (GET_LONGJMP_TARGET) + #define GET_LONGJMP_TARGET(pc) (internal_error (__FILE__, __LINE__, "GET_LONGJMP_TARGET"), 0) + #endif + + typedef int (gdbarch_get_longjmp_target_ftype) (CORE_ADDR *pc); + extern int gdbarch_get_longjmp_target (struct gdbarch *gdbarch, CORE_ADDR *pc); + extern void set_gdbarch_get_longjmp_target (struct gdbarch *gdbarch, gdbarch_get_longjmp_target_ftype *get_longjmp_target); + #if (GDB_MULTI_ARCH > GDB_MULTI_ARCH_PARTIAL) && defined (GET_LONGJMP_TARGET) + #error "Non multi-arch definition of GET_LONGJMP_TARGET" + #endif + #if GDB_MULTI_ARCH + #if (GDB_MULTI_ARCH > GDB_MULTI_ARCH_PARTIAL) || !defined (GET_LONGJMP_TARGET) + #define GET_LONGJMP_TARGET(pc) (gdbarch_get_longjmp_target (current_gdbarch, pc)) + #endif + #endif + /* Non multi-arch DUMMY_FRAMES are a mess (multi-arch ones are not that much better but at least they are vaguely consistent). The headers and body contain convoluted #if/#else sequences for determine how Index: gdbarch.sh =================================================================== RCS file: /cvs/src/src/gdb/gdbarch.sh,v retrieving revision 1.116 diff -p -r1.116 gdbarch.sh *** gdbarch.sh 2002/02/16 23:09:16 1.116 --- gdbarch.sh 2002/02/18 13:28:18 *************** f:2:REGISTER_SIM_REGNO:int:register_sim_ *** 466,471 **** --- 466,473 ---- F:2:REGISTER_BYTES_OK:int:register_bytes_ok:long nr_bytes:nr_bytes::0:0 f:2:CANNOT_FETCH_REGISTER:int:cannot_fetch_register:int regnum:regnum:::cannot_register_not::0 f:2:CANNOT_STORE_REGISTER:int:cannot_store_register:int regnum:regnum:::cannot_register_not::0 + # setjmp/longjmp support. + F:2:GET_LONGJMP_TARGET:int:get_longjmp_target:CORE_ADDR *pc:pc::0:0 # # Non multi-arch DUMMY_FRAMES are a mess (multi-arch ones are not that # much better but at least they are vaguely consistent). The headers Index: infrun.c =================================================================== RCS file: /cvs/src/src/gdb/infrun.c,v retrieving revision 1.52 diff -p -r1.52 infrun.c *** infrun.c 2002/02/05 04:37:21 1.52 --- infrun.c 2002/02/18 13:28:20 *************** static ptid_t previous_inferior_ptid; *** 114,128 **** static int may_follow_exec = MAY_FOLLOW_EXEC; - /* GET_LONGJMP_TARGET returns the PC at which longjmp() will resume the - program. It needs to examine the jmp_buf argument and extract the PC - from it. The return value is non-zero on success, zero otherwise. */ - - #ifndef GET_LONGJMP_TARGET - #define GET_LONGJMP_TARGET(PC_ADDR) 0 - #endif - - /* Dynamic function trampolines are similar to solib trampolines in that they are between the caller and the callee. The difference is that when you enter a dynamic trampoline, you can't determine the callee's address. Some --- 114,119 ---- *************** handle_inferior_event (struct execution_ *** 2306,2312 **** disable_longjmp_breakpoint (); remove_breakpoints (); breakpoints_inserted = 0; ! if (!GET_LONGJMP_TARGET (&jmp_buf_pc)) { keep_going (ecs); return; --- 2297,2304 ---- disable_longjmp_breakpoint (); remove_breakpoints (); breakpoints_inserted = 0; ! if (!GET_LONGJMP_TARGET_P () ! || !GET_LONGJMP_TARGET (&jmp_buf_pc)) { keep_going (ecs); return; Index: config/arm/tm-linux.h =================================================================== RCS file: /cvs/src/src/gdb/config/arm/tm-linux.h,v retrieving revision 1.12 diff -p -r1.12 tm-linux.h *** tm-linux.h 2002/02/15 16:12:24 1.12 --- tm-linux.h 2002/02/18 13:28:21 *************** extern CORE_ADDR arm_linux_push_argument *** 76,89 **** /* Offset to saved PC in sigcontext structure, from */ #define SIGCONTEXT_PC_OFFSET (sizeof(unsigned long) * 18) - /* Figure out where the longjmp will land. The code expects that longjmp - has just been entered and the code had not altered the registers, so - the arguments are are still in r0-r1. r0 points at the jmp_buf structure - from which the target pc (JB_PC) is extracted. This pc value is copied - into ADDR. This routine returns true on success */ - extern int arm_get_longjmp_target (CORE_ADDR *); - #define GET_LONGJMP_TARGET(addr) arm_get_longjmp_target (addr) - /* On ARM Linux, each call to a library routine goes through a small piece of trampoline code in the ".plt" section. The wait_for_inferior() routine uses this macro to detect when we have stepped into one of --- 76,81 ---- Index: config/arm/tm-nbsd.h =================================================================== RCS file: /cvs/src/src/gdb/config/arm/tm-nbsd.h,v retrieving revision 1.5 diff -p -r1.5 tm-nbsd.h *** tm-nbsd.h 2002/02/15 16:12:24 1.5 --- tm-nbsd.h 2002/02/18 13:28:21 *************** *** 24,46 **** #include "arm/tm-arm.h" #include "tm-nbsd.h" - #define JB_ELEMENT_SIZE sizeof(long) /* jmp_buf[_JBLEN] is array of ints */ - #define JB_PC 24 /* Setjmp()'s return PC saved here */ - /* Return non-zero if inside a shared-library entry stub. */ #undef IN_SOLIB_CALL_TRAMPOLINE #define IN_SOLIB_CALL_TRAMPOLINE(pc, name) \ STREQ ((name), "_PROCEDURE_LINKAGE_TABLE_") - - /* Figure out where the longjmp will land. Slurp the args out of the stack. - We expect the first arg to be a pointer to the jmp_buf structure from which - we extract the pc (JB_PC) that we will land at. The pc is copied into ADDR. - This routine returns true on success */ - - extern int - get_longjmp_target (CORE_ADDR *); - - #define GET_LONGJMP_TARGET(ADDR) get_longjmp_target(ADDR) /* By convention, NetBSD uses the "other" register names. */ #define DEFAULT_REGISTER_NAMES additional_register_names --- 24,33 ----