* arm-linux-tdep.c (ARM_SET_R7_SIGRETURN, ARM_SET_R7_RT_SIGRETURN)

(ARM_EABI_SYSCALL, arm_linux_sigtramp_cache, arm_linux_sigreturn_init)
	(arm_linux_rt_sigreturn_init, arm_linux_sigreturn_tramp_frame)
	(arm_linux_rt_sigreturn_tramp_frame)
	(arm_eabi_linux_sigreturn_tramp_frame)
	(arm_eabi_linux_rt_sigreturn_tramp_frame): New.
	(arm_linux_init_abi): Register the new signal unwinders.
	(arm_linux_in_sigtramp, arm_linux_sigcontext_register_address):
	Delete.
	* arm-tdep.c (SIGCONTEXT_REGISTER_ADDRESS_P)
	(SIGCONTEXT_REGISTER_ADDRESS, arm_make_sigtramp_cache)
	(arm_sigtramp_this_id, arm_sigtramp_prev_register)
	(arm_sigtramp_unwind, arm_sigtramp_unwind_sniffer): Delete.
	(arm_gdbarch_init): Don't register a signal unwinder.
	* config/arm/tm-linux.h (arm_linux_in_sigtramp)
	(arm_linux_sigcontext_register_address): Delete prototypes.
	(DEPRECATED_IN_SIGTRAMP, SIGCONTEXT_REGISTER_ADDRESS): Delete.
	* Makefile.in (arm-linux-tdep.o): Update.
This commit is contained in:
Daniel Jacobowitz 2005-12-22 17:06:25 +00:00
parent 2e1e12b1f4
commit 8e9d1a243c
5 changed files with 121 additions and 196 deletions

View file

@ -1,3 +1,24 @@
2005-12-22 Daniel Jacobowitz <dan@codesourcery.com>
* arm-linux-tdep.c (ARM_SET_R7_SIGRETURN, ARM_SET_R7_RT_SIGRETURN)
(ARM_EABI_SYSCALL, arm_linux_sigtramp_cache, arm_linux_sigreturn_init)
(arm_linux_rt_sigreturn_init, arm_linux_sigreturn_tramp_frame)
(arm_linux_rt_sigreturn_tramp_frame)
(arm_eabi_linux_sigreturn_tramp_frame)
(arm_eabi_linux_rt_sigreturn_tramp_frame): New.
(arm_linux_init_abi): Register the new signal unwinders.
(arm_linux_in_sigtramp, arm_linux_sigcontext_register_address):
Delete.
* arm-tdep.c (SIGCONTEXT_REGISTER_ADDRESS_P)
(SIGCONTEXT_REGISTER_ADDRESS, arm_make_sigtramp_cache)
(arm_sigtramp_this_id, arm_sigtramp_prev_register)
(arm_sigtramp_unwind, arm_sigtramp_unwind_sniffer): Delete.
(arm_gdbarch_init): Don't register a signal unwinder.
* config/arm/tm-linux.h (arm_linux_in_sigtramp)
(arm_linux_sigcontext_register_address): Delete prototypes.
(DEPRECATED_IN_SIGTRAMP, SIGCONTEXT_REGISTER_ADDRESS): Delete.
* Makefile.in (arm-linux-tdep.o): Update.
2005-12-22 Daniel Jacobowitz <dan@codesourcery.com> 2005-12-22 Daniel Jacobowitz <dan@codesourcery.com>
* amd64obsd-tdep.c (amd64obsd_trapframe_sniffer): Spelling fix. * amd64obsd-tdep.c (amd64obsd_trapframe_sniffer): Spelling fix.

View file

@ -1741,7 +1741,7 @@ arm-linux-nat.o: arm-linux-nat.c $(defs_h) $(inferior_h) $(gdbcore_h) \
arm-linux-tdep.o: arm-linux-tdep.c $(defs_h) $(target_h) $(value_h) \ arm-linux-tdep.o: arm-linux-tdep.c $(defs_h) $(target_h) $(value_h) \
$(gdbtypes_h) $(floatformat_h) $(gdbcore_h) $(frame_h) $(regcache_h) \ $(gdbtypes_h) $(floatformat_h) $(gdbcore_h) $(frame_h) $(regcache_h) \
$(doublest_h) $(solib_svr4_h) $(osabi_h) $(arm_tdep_h) \ $(doublest_h) $(solib_svr4_h) $(osabi_h) $(arm_tdep_h) \
$(glibc_tdep_h) $(glibc_tdep_h) $(trad_frame_h) $(tramp_frame_h) $(gdb_string_h)
armnbsd-nat.o: armnbsd-nat.c $(defs_h) $(gdbcore_h) $(inferior_h) \ armnbsd-nat.o: armnbsd-nat.c $(defs_h) $(gdbcore_h) $(inferior_h) \
$(regcache_h) $(target_h) $(gdb_string_h) $(arm_tdep_h) $(inf_ptrace_h) $(regcache_h) $(target_h) $(gdb_string_h) $(arm_tdep_h) $(inf_ptrace_h)
armnbsd-tdep.o: armnbsd-tdep.c $(defs_h) $(osabi_h) $(gdb_string_h) \ armnbsd-tdep.o: armnbsd-tdep.c $(defs_h) $(osabi_h) $(gdb_string_h) \

View file

@ -1,7 +1,7 @@
/* GNU/Linux on ARM target support. /* GNU/Linux on ARM target support.
Copyright (C) 1999, 2000, 2001, 2002, 2003, 2005 Free Software Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005
Foundation, Inc. Free Software Foundation, Inc.
This file is part of GDB. This file is part of GDB.
@ -31,10 +31,14 @@
#include "doublest.h" #include "doublest.h"
#include "solib-svr4.h" #include "solib-svr4.h"
#include "osabi.h" #include "osabi.h"
#include "trad-frame.h"
#include "tramp-frame.h"
#include "arm-tdep.h" #include "arm-tdep.h"
#include "glibc-tdep.h" #include "glibc-tdep.h"
#include "gdb_string.h"
/* Under ARM GNU/Linux the traditional way of performing a breakpoint /* Under ARM GNU/Linux the traditional way of performing a breakpoint
is to execute a particular software interrupt, rather than use a is to execute a particular software interrupt, rather than use a
particular undefined instruction to provoke a trap. Upon exection particular undefined instruction to provoke a trap. Upon exection
@ -262,76 +266,97 @@ arm_linux_svr4_fetch_link_map_offsets (void)
#define ARM_LINUX_SIGRETURN_INSTR 0xef900077 #define ARM_LINUX_SIGRETURN_INSTR 0xef900077
#define ARM_LINUX_RT_SIGRETURN_INSTR 0xef9000ad #define ARM_LINUX_RT_SIGRETURN_INSTR 0xef9000ad
/* arm_linux_in_sigtramp determines if PC points at one of the /* For ARM EABI, recognize the pattern that glibc uses... alternatively,
instructions which cause control to return to the Linux kernel upon we could arrange to do this by function name, but they are not always
return from a signal handler. FUNC_NAME is unused. */ exported. */
#define ARM_SET_R7_SIGRETURN 0xe3a07077
#define ARM_SET_R7_RT_SIGRETURN 0xe3a070ad
#define ARM_EABI_SYSCALL 0xef000000
int static void
arm_linux_in_sigtramp (CORE_ADDR pc, char *func_name) arm_linux_sigtramp_cache (struct frame_info *next_frame,
struct trad_frame_cache *this_cache,
CORE_ADDR func, int regs_offset)
{ {
unsigned long inst; CORE_ADDR sp = frame_unwind_register_unsigned (next_frame, ARM_SP_REGNUM);
CORE_ADDR base = sp + regs_offset;
int i;
inst = read_memory_integer (pc, 4); for (i = 0; i < 16; i++)
trad_frame_set_reg_addr (this_cache, i, base + i * 4);
return (inst == ARM_LINUX_SIGRETURN_INSTR trad_frame_set_reg_addr (this_cache, ARM_PS_REGNUM, base + 16 * 4);
|| inst == ARM_LINUX_RT_SIGRETURN_INSTR);
/* The VFP or iWMMXt registers may be saved on the stack, but there's
no reliable way to restore them (yet). */
/* Save a frame ID. */
trad_frame_set_id (this_cache, frame_id_build (sp, func));
} }
/* arm_linux_sigcontext_register_address returns the address in the static void
sigcontext of register REGNO given a stack pointer value SP and arm_linux_sigreturn_init (const struct tramp_frame *self,
program counter value PC. The value 0 is returned if PC is not struct frame_info *next_frame,
pointing at one of the signal return instructions or if REGNO is struct trad_frame_cache *this_cache,
not saved in the sigcontext struct. */ CORE_ADDR func)
CORE_ADDR
arm_linux_sigcontext_register_address (CORE_ADDR sp, CORE_ADDR pc, int regno)
{ {
unsigned long inst; arm_linux_sigtramp_cache (next_frame, this_cache, func,
CORE_ADDR reg_addr = 0; 0x0c /* Offset to registers. */);
}
inst = read_memory_integer (pc, 4); static void
arm_linux_rt_sigreturn_init (const struct tramp_frame *self,
struct frame_info *next_frame,
struct trad_frame_cache *this_cache,
CORE_ADDR func)
{
arm_linux_sigtramp_cache (next_frame, this_cache, func,
0x88 /* Offset to ucontext_t. */
+ 0x14 /* Offset to sigcontext. */
+ 0x0c /* Offset to registers. */);
}
if (inst == ARM_LINUX_SIGRETURN_INSTR static struct tramp_frame arm_linux_sigreturn_tramp_frame = {
|| inst == ARM_LINUX_RT_SIGRETURN_INSTR) SIGTRAMP_FRAME,
4,
{ {
CORE_ADDR sigcontext_addr; { ARM_LINUX_SIGRETURN_INSTR, -1 },
{ TRAMP_SENTINEL_INSN }
},
arm_linux_sigreturn_init
};
/* The sigcontext structure is at different places for the two static struct tramp_frame arm_linux_rt_sigreturn_tramp_frame = {
signal return instructions. For ARM_LINUX_SIGRETURN_INSTR, SIGTRAMP_FRAME,
it starts at the SP value. For ARM_LINUX_RT_SIGRETURN_INSTR, 4,
it is at SP+8. For the latter instruction, it may also be {
the case that the address of this structure may be determined { ARM_LINUX_RT_SIGRETURN_INSTR, -1 },
by reading the 4 bytes at SP, but I'm not convinced this is { TRAMP_SENTINEL_INSN }
reliable. },
arm_linux_rt_sigreturn_init
};
In any event, these magic constants (0 and 8) may be static struct tramp_frame arm_eabi_linux_sigreturn_tramp_frame = {
determined by examining struct sigframe and struct SIGTRAMP_FRAME,
rt_sigframe in arch/arm/kernel/signal.c in the Linux kernel 4,
sources. */ {
{ ARM_SET_R7_SIGRETURN, -1 },
{ ARM_EABI_SYSCALL, -1 },
{ TRAMP_SENTINEL_INSN }
},
arm_linux_sigreturn_init
};
if (inst == ARM_LINUX_RT_SIGRETURN_INSTR) static struct tramp_frame arm_eabi_linux_rt_sigreturn_tramp_frame = {
sigcontext_addr = sp + 8; SIGTRAMP_FRAME,
else /* inst == ARM_LINUX_SIGRETURN_INSTR */ 4,
sigcontext_addr = sp + 0; {
{ ARM_SET_R7_RT_SIGRETURN, -1 },
/* The layout of the sigcontext structure for ARM GNU/Linux is { ARM_EABI_SYSCALL, -1 },
in include/asm-arm/sigcontext.h in the Linux kernel sources. { TRAMP_SENTINEL_INSN }
},
There are three 4-byte fields which precede the saved r0 arm_linux_rt_sigreturn_init
field. (This accounts for the 12 in the code below.) The };
sixteen registers (4 bytes per field) follow in order. The
PSR value follows the sixteen registers which accounts for
the constant 19 below. */
if (0 <= regno && regno <= ARM_PC_REGNUM)
reg_addr = sigcontext_addr + 12 + (4 * regno);
else if (regno == ARM_PS_REGNUM)
reg_addr = sigcontext_addr + 19 * 4;
}
return reg_addr;
}
static void static void
arm_linux_init_abi (struct gdbarch_info info, arm_linux_init_abi (struct gdbarch_info info,
@ -378,6 +403,15 @@ arm_linux_init_abi (struct gdbarch_info info,
/* Enable TLS support. */ /* Enable TLS support. */
set_gdbarch_fetch_tls_load_module_address (gdbarch, set_gdbarch_fetch_tls_load_module_address (gdbarch,
svr4_fetch_objfile_link_map); svr4_fetch_objfile_link_map);
tramp_frame_prepend_unwinder (gdbarch,
&arm_linux_sigreturn_tramp_frame);
tramp_frame_prepend_unwinder (gdbarch,
&arm_linux_rt_sigreturn_tramp_frame);
tramp_frame_prepend_unwinder (gdbarch,
&arm_eabi_linux_sigreturn_tramp_frame);
tramp_frame_prepend_unwinder (gdbarch,
&arm_eabi_linux_rt_sigreturn_tramp_frame);
} }
void void

View file

@ -51,36 +51,6 @@
static int arm_debug; static int arm_debug;
/* Each OS has a different mechanism for accessing the various
registers stored in the sigcontext structure.
SIGCONTEXT_REGISTER_ADDRESS should be defined to the name (or
function pointer) which may be used to determine the addresses
of the various saved registers in the sigcontext structure.
For the ARM target, there are three parameters to this function.
The first is the pc value of the frame under consideration, the
second the stack pointer of this frame, and the last is the
register number to fetch.
If the tm.h file does not define this macro, then it's assumed that
no mechanism is needed and we define SIGCONTEXT_REGISTER_ADDRESS to
be 0.
When it comes time to multi-arching this code, see the identically
named machinery in ia64-tdep.c for an example of how it could be
done. It should not be necessary to modify the code below where
this macro is used. */
#ifdef SIGCONTEXT_REGISTER_ADDRESS
#ifndef SIGCONTEXT_REGISTER_ADDRESS_P
#define SIGCONTEXT_REGISTER_ADDRESS_P() 1
#endif
#else
#define SIGCONTEXT_REGISTER_ADDRESS(SP,PC,REG) 0
#define SIGCONTEXT_REGISTER_ADDRESS_P() 0
#endif
/* Macros for setting and testing a bit in a minimal symbol that marks /* Macros for setting and testing a bit in a minimal symbol that marks
it as Thumb function. The MSB of the minimal symbol's "info" field it as Thumb function. The MSB of the minimal symbol's "info" field
is used for this purpose. is used for this purpose.
@ -1063,84 +1033,6 @@ struct frame_base arm_normal_base = {
arm_normal_frame_base arm_normal_frame_base
}; };
static struct arm_prologue_cache *
arm_make_sigtramp_cache (struct frame_info *next_frame)
{
struct arm_prologue_cache *cache;
int reg;
cache = frame_obstack_zalloc (sizeof (struct arm_prologue_cache));
cache->prev_sp = frame_unwind_register_unsigned (next_frame, ARM_SP_REGNUM);
cache->saved_regs = trad_frame_alloc_saved_regs (next_frame);
for (reg = 0; reg < NUM_REGS; reg++)
cache->saved_regs[reg].addr
= SIGCONTEXT_REGISTER_ADDRESS (cache->prev_sp,
frame_pc_unwind (next_frame), reg);
/* FIXME: What about thumb mode? */
cache->framereg = ARM_SP_REGNUM;
cache->prev_sp
= read_memory_integer (cache->saved_regs[cache->framereg].addr,
register_size (current_gdbarch, cache->framereg));
return cache;
}
static void
arm_sigtramp_this_id (struct frame_info *next_frame,
void **this_cache,
struct frame_id *this_id)
{
struct arm_prologue_cache *cache;
if (*this_cache == NULL)
*this_cache = arm_make_sigtramp_cache (next_frame);
cache = *this_cache;
/* FIXME drow/2003-07-07: This isn't right if we single-step within
the sigtramp frame; the PC should be the beginning of the trampoline. */
*this_id = frame_id_build (cache->prev_sp, frame_pc_unwind (next_frame));
}
static void
arm_sigtramp_prev_register (struct frame_info *next_frame,
void **this_cache,
int prev_regnum,
int *optimized,
enum lval_type *lvalp,
CORE_ADDR *addrp,
int *realnump,
gdb_byte *valuep)
{
struct arm_prologue_cache *cache;
if (*this_cache == NULL)
*this_cache = arm_make_sigtramp_cache (next_frame);
cache = *this_cache;
trad_frame_get_prev_register (next_frame, cache->saved_regs, prev_regnum,
optimized, lvalp, addrp, realnump, valuep);
}
struct frame_unwind arm_sigtramp_unwind = {
SIGTRAMP_FRAME,
arm_sigtramp_this_id,
arm_sigtramp_prev_register
};
static const struct frame_unwind *
arm_sigtramp_unwind_sniffer (struct frame_info *next_frame)
{
if (SIGCONTEXT_REGISTER_ADDRESS_P ()
&& legacy_pc_in_sigtramp (frame_pc_unwind (next_frame), (char *) 0))
return &arm_sigtramp_unwind;
return NULL;
}
/* Assuming NEXT_FRAME->prev is a dummy, return the frame ID of that /* Assuming NEXT_FRAME->prev is a dummy, return the frame ID of that
dummy frame. The frame ID's base needs to match the TOS value dummy frame. The frame ID's base needs to match the TOS value
saved by save_dummy_frame_tos() and returned from saved by save_dummy_frame_tos() and returned from
@ -2907,7 +2799,6 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
/* Add some default predicates. */ /* Add some default predicates. */
frame_unwind_append_sniffer (gdbarch, arm_stub_unwind_sniffer); frame_unwind_append_sniffer (gdbarch, arm_stub_unwind_sniffer);
frame_unwind_append_sniffer (gdbarch, arm_sigtramp_unwind_sniffer);
frame_unwind_append_sniffer (gdbarch, dwarf2_frame_sniffer); frame_unwind_append_sniffer (gdbarch, dwarf2_frame_sniffer);
frame_unwind_append_sniffer (gdbarch, arm_prologue_unwind_sniffer); frame_unwind_append_sniffer (gdbarch, arm_prologue_unwind_sniffer);

View file

@ -1,5 +1,6 @@
/* Target definitions for GNU/Linux on ARM, for GDB. /* Target definitions for GNU/Linux on ARM, for GDB.
Copyright 1999, 2000 Free Software Foundation, Inc. Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2005
Free Software Foundation, Inc.
This file is part of GDB. This file is part of GDB.
@ -43,26 +44,4 @@ extern CORE_ADDR in_svr4_dynsym_resolve_code (CORE_ADDR pc, char *name);
#define IN_SOLIB_DYNSYM_RESOLVE_CODE in_svr4_dynsym_resolve_code */ #define IN_SOLIB_DYNSYM_RESOLVE_CODE in_svr4_dynsym_resolve_code */
#endif #endif
/* When the ARM Linux kernel invokes a signal handler, the return
address points at a special instruction which'll trap back into
the kernel. These definitions are used to identify this bit of
code as a signal trampoline in order to support backtracing
through calls to signal handlers. */
int arm_linux_in_sigtramp (CORE_ADDR pc, char *name);
#define DEPRECATED_IN_SIGTRAMP(pc, name) arm_linux_in_sigtramp (pc, name)
/* Each OS has different mechanisms for accessing the various
registers stored in the sigcontext structure. These definitions
provide a mechanism by which the generic code in arm-tdep.c can
find the addresses at which various registers are saved at in the
sigcontext structure. If SIGCONTEXT_REGISTER_ADDRESS is not
defined, arm-tdep.c will define it to be 0. (See ia64-tdep.c and
ia64-linux-tdep.c to see what a similar mechanism looks like when
multi-arched.) */
extern CORE_ADDR arm_linux_sigcontext_register_address (CORE_ADDR, CORE_ADDR,
int);
#define SIGCONTEXT_REGISTER_ADDRESS arm_linux_sigcontext_register_address
#endif /* TM_ARMLINUX_H */ #endif /* TM_ARMLINUX_H */