* 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>
* 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) \
$(gdbtypes_h) $(floatformat_h) $(gdbcore_h) $(frame_h) $(regcache_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) \
$(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) \

View File

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

View File

@ -51,36 +51,6 @@
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
it as Thumb function. The MSB of the minimal symbol's "info" field
is used for this purpose.
@ -1063,84 +1033,6 @@ struct frame_base arm_normal_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
dummy frame. The frame ID's base needs to match the TOS value
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. */
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, arm_prologue_unwind_sniffer);

View File

@ -1,5 +1,6 @@
/* 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.
@ -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 */
#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 */