* 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.
This commit is contained in:
Richard Earnshaw 2002-02-18 13:35:31 +00:00
parent 82bd7b59c9
commit 9df628e0aa
13 changed files with 159 additions and 85 deletions

View file

@ -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>:

View file

@ -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

View file

@ -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. */

View file

@ -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

View file

@ -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;
}

View file

@ -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

View file

@ -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");
}

View file

@ -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

View file

@ -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

View file

@ -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 */
@ -3029,6 +3043,30 @@ set_gdbarch_cannot_store_register (struct gdbarch *gdbarch,
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
gdbarch_use_generic_dummy_frames (struct gdbarch *gdbarch)
{

View file

@ -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

View file

@ -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

View file

@ -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;