aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gdb/ChangeLog26
-rw-r--r--gdb/arm-linux-tdep.c37
-rw-r--r--gdb/arm-tdep.c22
-rw-r--r--gdb/arm-tdep.h14
-rw-r--r--gdb/armnbsd-nat.c6
-rw-r--r--gdb/armnbsd-tdep.c7
-rw-r--r--gdb/breakpoint.c20
-rw-r--r--gdb/config/arm/tm-linux.h8
-rw-r--r--gdb/config/arm/tm-nbsd.h13
-rw-r--r--gdb/gdbarch.c38
-rw-r--r--gdb/gdbarch.h39
-rwxr-xr-xgdb/gdbarch.sh2
-rw-r--r--gdb/infrun.c12
13 files changed, 159 insertions, 85 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index b0007fc..a415c6b 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,29 @@
+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.
+
2002-02-17 Kevin Buettner <kevinb@redhat.com>
From Peter Schauer <pes@regent.e-technik.tu-muenchen.de>:
diff --git a/gdb/arm-linux-tdep.c b/gdb/arm-linux-tdep.c
index 6049cf5..6faa4a2 100644
--- a/gdb/arm-linux-tdep.c
+++ b/gdb/arm-linux-tdep.c
@@ -58,40 +58,10 @@ LONGEST arm_linux_call_dummy_words[] =
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
+/* Description of the longjmp buffer. */
+#define JB_ELEMENT_SIZE INT_REGISTER_RAW_SIZE
#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. */
@@ -548,6 +518,9 @@ arm_linux_init_abi (struct gdbarch_info info,
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
diff --git a/gdb/arm-tdep.c b/gdb/arm-tdep.c
index a60f497..7f20267 100644
--- a/gdb/arm-tdep.c
+++ b/gdb/arm-tdep.c
@@ -2272,6 +2272,23 @@ arm_store_struct_return (CORE_ADDR addr, CORE_ADDR sp)
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
@@ -2775,7 +2792,9 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
"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);
@@ -2904,6 +2923,9 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
/* 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
building here. */
diff --git a/gdb/arm-tdep.h b/gdb/arm-tdep.h
index 85d9e4f..29c8bc9 100644
--- a/gdb/arm-tdep.h
+++ b/gdb/arm-tdep.h
@@ -123,10 +123,16 @@ struct gdbarch_tdep
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;
+
+ 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
diff --git a/gdb/armnbsd-nat.c b/gdb/armnbsd-nat.c
index a270772..2d09bd3 100644
--- a/gdb/armnbsd-nat.c
+++ b/gdb/armnbsd-nat.c
@@ -97,9 +97,3 @@ fetch_core_registers (core_reg_sect, core_reg_size, which, ignore)
#else
#error Not FETCH_INFERIOR_REGISTERS
#endif /* !FETCH_INFERIOR_REGISTERS */
-
-int
-get_longjmp_target (CORE_ADDR *addr)
-{
- return 0;
-}
diff --git a/gdb/armnbsd-tdep.c b/gdb/armnbsd-tdep.c
index 25c2f16..291273b 100644
--- a/gdb/armnbsd-tdep.c
+++ b/gdb/armnbsd-tdep.c
@@ -22,6 +22,10 @@
#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};
@@ -35,6 +39,9 @@ arm_netbsd_init_abi_common (struct gdbarch_info info,
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
diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c
index b22a206..640505e 100644
--- a/gdb/breakpoint.c
+++ b/gdb/breakpoint.c
@@ -143,9 +143,7 @@ static int cover_target_enable_exception_callback (PTR);
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 *);
@@ -3758,7 +3756,6 @@ create_internal_breakpoint (CORE_ADDR address, enum bptype type)
return b;
}
-#ifdef GET_LONGJMP_TARGET
static void
create_longjmp_breakpoint (char *func_name)
@@ -3782,8 +3779,6 @@ create_longjmp_breakpoint (char *func_name)
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. */
@@ -6967,13 +6962,14 @@ breakpoint_re_set (void)
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
+ 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");
}
diff --git a/gdb/config/arm/tm-linux.h b/gdb/config/arm/tm-linux.h
index aa3fa52..11de4fa 100644
--- a/gdb/config/arm/tm-linux.h
+++ b/gdb/config/arm/tm-linux.h
@@ -76,14 +76,6 @@ extern CORE_ADDR arm_linux_push_arguments (int, struct value **, CORE_ADDR,
/* 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
diff --git a/gdb/config/arm/tm-nbsd.h b/gdb/config/arm/tm-nbsd.h
index 4dfc329..5119879 100644
--- a/gdb/config/arm/tm-nbsd.h
+++ b/gdb/config/arm/tm-nbsd.h
@@ -24,24 +24,11 @@
#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
diff --git a/gdb/gdbarch.c b/gdb/gdbarch.c
index f4000b5..8467d41 100644
--- a/gdb/gdbarch.c
+++ b/gdb/gdbarch.c
@@ -182,6 +182,7 @@ struct gdbarch
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;
@@ -346,6 +347,7 @@ struct gdbarch startup_gdbarch =
0,
0,
0,
+ 0,
generic_get_saved_register,
0,
0,
@@ -638,6 +640,7 @@ verify_gdbarch (struct gdbarch *gdbarch)
/* 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");
@@ -1282,6 +1285,17 @@ gdbarch_dump (struct gdbarch *gdbarch, struct ui_file *file)
"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 */
@@ -3030,6 +3044,30 @@ set_gdbarch_cannot_store_register (struct gdbarch *gdbarch,
}
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
gdbarch_use_generic_dummy_frames (struct gdbarch *gdbarch)
{
if (gdbarch->use_generic_dummy_frames == -1)
diff --git a/gdb/gdbarch.h b/gdb/gdbarch.h
index da5156c..2dba00f 100644
--- a/gdb/gdbarch.h
+++ b/gdb/gdbarch.h
@@ -883,6 +883,45 @@ extern void set_gdbarch_cannot_store_register (struct gdbarch *gdbarch, gdbarch_
#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
diff --git a/gdb/gdbarch.sh b/gdb/gdbarch.sh
index 29aca34..996b876 100755
--- a/gdb/gdbarch.sh
+++ b/gdb/gdbarch.sh
@@ -466,6 +466,8 @@ f:2:REGISTER_SIM_REGNO:int:register_sim_regno:int reg_nr:reg_nr:::default_regist
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
diff --git a/gdb/infrun.c b/gdb/infrun.c
index c935db8..1efe87b 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -114,15 +114,6 @@ static ptid_t previous_inferior_ptid;
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
@@ -2306,7 +2297,8 @@ handle_inferior_event (struct execution_control_state *ecs)
disable_longjmp_breakpoint ();
remove_breakpoints ();
breakpoints_inserted = 0;
- if (!GET_LONGJMP_TARGET (&jmp_buf_pc))
+ if (!GET_LONGJMP_TARGET_P ()
+ || !GET_LONGJMP_TARGET (&jmp_buf_pc))
{
keep_going (ecs);
return;