This is the mail archive of the
gdb-patches@sources.redhat.com
mailing list for the GDB project.
PATCH multi-arch GET_LONGJMP_TARGET
- From: Richard Earnshaw <rearnsha at arm dot com>
- To: gdb-patches at sources dot redhat dot com
- Cc: Richard dot Earnshaw at arm dot com
- Date: Mon, 18 Feb 2002 13:37:39 +0000
- Subject: PATCH multi-arch GET_LONGJMP_TARGET
- Organization: ARM Ltd.
- Reply-to: Richard dot Earnshaw at arm dot com
This patch multi-arches GET_LONGJMP_TARGET, using the predicate variant
with
GET_LONGJMP_TARGET_P() telling us whether the architecture supports this
or not.
Committed as obvious for multi-arch.
R.
2002-02-18 Richard Earnshaw <rearnsha@arm.com>
* gdbarch.sh (GET_LONGJMP_TARGET): Add rule.
* gdbarch.c gdbarch.h: Regenerate.
* breakpoint.c (create_longjmp_breakpoint): Always compile this
function.
(breakpoint_reset): Test GET_LONGJMP_TARGET_P().
* infrun.c (GET_LONGJMP_TARGET): Delete default definition.
(handle_inferior_event): Test GET_LONGJMP_TARGET_P().
* arm-tdep.h (struct gdbarch_tdep): Add jb_pc and jb_elt_size fields.
* arm-tdep.c (arm_get_longjmp_target): New function.
(arm_gdbarch_init): Initialize jb_pc to -1. If ABI handler changes
this to a positive value register arm_get_longjmp_target as the
longjmp handler.
* arm-linux-tdep.c (arm_get_longjmp_target): Delete.
(arm_linux_init_abi): Set up longjmp description in tdep.
* armnbsd-nat.c (get_longjmp_target): Delete.
* armnbsd-tdep.c (arm_netbsd_init_abi_common): Set up longjmp
description in tdep.
* config/arm/tm-nbsd.h (JB_ELEMENT_SIZE, JB_PC): Delete.
(get_longjmp_target): Delete declaration.
(GET_LONGJMP_TARGET): Delete.
* config/arm/tm-linux.h (arm_get_longjmp_target): Delete declaration.
(GET_LONGJMP_TARGET): Delete.
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 <asm/sigcontext.h> */
#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 ----