* ppc-linux-tdep.c (INSTR_SC, INSTR_LI_R0_0x6666, INSTR_LI_R0_0x7777,
INSTR_LI_R0_NR_sigreturn, INSTR_LI_R0_NR_rt_sigreturn): Remove. (PPC_LINUX_SIGNAL_FRAMESIZE, PPC_LINUX_REGS_PTR_OFFSET, PPC_LINUX_HANDLER_PTR_OFFSET): Remove. (ppc_linux_in_sigtramp, insn_is_sigreturn, ppc_linux_at_sigtramp_return_path): Remove.
This commit is contained in:
parent
f7c5c4b53e
commit
c3fc7e628a
|
@ -1,3 +1,12 @@
|
||||||
|
2007-06-01 Ulrich Weigand <uweigand@de.ibm.com>
|
||||||
|
|
||||||
|
* ppc-linux-tdep.c (INSTR_SC, INSTR_LI_R0_0x6666, INSTR_LI_R0_0x7777,
|
||||||
|
INSTR_LI_R0_NR_sigreturn, INSTR_LI_R0_NR_rt_sigreturn): Remove.
|
||||||
|
(PPC_LINUX_SIGNAL_FRAMESIZE, PPC_LINUX_REGS_PTR_OFFSET,
|
||||||
|
PPC_LINUX_HANDLER_PTR_OFFSET): Remove.
|
||||||
|
(ppc_linux_in_sigtramp, insn_is_sigreturn,
|
||||||
|
ppc_linux_at_sigtramp_return_path): Remove.
|
||||||
|
|
||||||
2007-05-31 Markus Deuling <deuling@de.ibm.com>
|
2007-05-31 Markus Deuling <deuling@de.ibm.com>
|
||||||
|
|
||||||
* xtensa-tdep.c (XTENSA_IS_ENTRY, extract_call_winsize)
|
* xtensa-tdep.c (XTENSA_IS_ENTRY, extract_call_winsize)
|
||||||
|
|
|
@ -40,33 +40,6 @@
|
||||||
#include "frame-unwind.h"
|
#include "frame-unwind.h"
|
||||||
#include "tramp-frame.h"
|
#include "tramp-frame.h"
|
||||||
|
|
||||||
/* The following instructions are used in the signal trampoline code
|
|
||||||
on GNU/Linux PPC. The kernel used to use magic syscalls 0x6666 and
|
|
||||||
0x7777 but now uses the sigreturn syscalls. We check for both. */
|
|
||||||
#define INSTR_LI_R0_0x6666 0x38006666
|
|
||||||
#define INSTR_LI_R0_0x7777 0x38007777
|
|
||||||
#define INSTR_LI_R0_NR_sigreturn 0x38000077
|
|
||||||
#define INSTR_LI_R0_NR_rt_sigreturn 0x380000AC
|
|
||||||
|
|
||||||
#define INSTR_SC 0x44000002
|
|
||||||
|
|
||||||
/* Since the *-tdep.c files are platform independent (i.e, they may be
|
|
||||||
used to build cross platform debuggers), we can't include system
|
|
||||||
headers. Therefore, details concerning the sigcontext structure
|
|
||||||
must be painstakingly rerecorded. What's worse, if these details
|
|
||||||
ever change in the header files, they'll have to be changed here
|
|
||||||
as well. */
|
|
||||||
|
|
||||||
/* __SIGNAL_FRAMESIZE from <asm/ptrace.h> */
|
|
||||||
#define PPC_LINUX_SIGNAL_FRAMESIZE 64
|
|
||||||
|
|
||||||
/* From <asm/sigcontext.h>, offsetof(struct sigcontext_struct, regs) == 0x1c */
|
|
||||||
#define PPC_LINUX_REGS_PTR_OFFSET (PPC_LINUX_SIGNAL_FRAMESIZE + 0x1c)
|
|
||||||
|
|
||||||
/* From <asm/sigcontext.h>,
|
|
||||||
offsetof(struct sigcontext_struct, handler) == 0x14 */
|
|
||||||
#define PPC_LINUX_HANDLER_PTR_OFFSET (PPC_LINUX_SIGNAL_FRAMESIZE + 0x14)
|
|
||||||
|
|
||||||
/* From <asm/ptrace.h>, values for PT_NIP, PT_R1, and PT_LNK */
|
/* From <asm/ptrace.h>, values for PT_NIP, PT_R1, and PT_LNK */
|
||||||
#define PPC_LINUX_PT_R0 0
|
#define PPC_LINUX_PT_R0 0
|
||||||
#define PPC_LINUX_PT_R1 1
|
#define PPC_LINUX_PT_R1 1
|
||||||
|
@ -111,116 +84,6 @@
|
||||||
#define PPC_LINUX_PT_FPR31 (PPC_LINUX_PT_FPR0 + 2*31)
|
#define PPC_LINUX_PT_FPR31 (PPC_LINUX_PT_FPR0 + 2*31)
|
||||||
#define PPC_LINUX_PT_FPSCR (PPC_LINUX_PT_FPR0 + 2*32 + 1)
|
#define PPC_LINUX_PT_FPSCR (PPC_LINUX_PT_FPR0 + 2*32 + 1)
|
||||||
|
|
||||||
static int ppc_linux_at_sigtramp_return_path (CORE_ADDR pc);
|
|
||||||
|
|
||||||
/* Determine if pc is in a signal trampoline...
|
|
||||||
|
|
||||||
Ha! That's not what this does at all. wait_for_inferior in
|
|
||||||
infrun.c calls get_frame_type() in order to detect entry into a
|
|
||||||
signal trampoline just after delivery of a signal. But on
|
|
||||||
GNU/Linux, signal trampolines are used for the return path only.
|
|
||||||
The kernel sets things up so that the signal handler is called
|
|
||||||
directly.
|
|
||||||
|
|
||||||
If we use in_sigtramp2() in place of in_sigtramp() (see below)
|
|
||||||
we'll (often) end up with stop_pc in the trampoline and prev_pc in
|
|
||||||
the (now exited) handler. The code there will cause a temporary
|
|
||||||
breakpoint to be set on prev_pc which is not very likely to get hit
|
|
||||||
again.
|
|
||||||
|
|
||||||
If this is confusing, think of it this way... the code in
|
|
||||||
wait_for_inferior() needs to be able to detect entry into a signal
|
|
||||||
trampoline just after a signal is delivered, not after the handler
|
|
||||||
has been run.
|
|
||||||
|
|
||||||
So, we define in_sigtramp() below to return 1 if the following is
|
|
||||||
true:
|
|
||||||
|
|
||||||
1) The previous frame is a real signal trampoline.
|
|
||||||
|
|
||||||
- and -
|
|
||||||
|
|
||||||
2) pc is at the first or second instruction of the corresponding
|
|
||||||
handler.
|
|
||||||
|
|
||||||
Why the second instruction? It seems that wait_for_inferior()
|
|
||||||
never sees the first instruction when single stepping. When a
|
|
||||||
signal is delivered while stepping, the next instruction that
|
|
||||||
would've been stepped over isn't, instead a signal is delivered and
|
|
||||||
the first instruction of the handler is stepped over instead. That
|
|
||||||
puts us on the second instruction. (I added the test for the first
|
|
||||||
instruction long after the fact, just in case the observed behavior
|
|
||||||
is ever fixed.) */
|
|
||||||
|
|
||||||
int
|
|
||||||
ppc_linux_in_sigtramp (CORE_ADDR pc, char *func_name)
|
|
||||||
{
|
|
||||||
CORE_ADDR lr;
|
|
||||||
CORE_ADDR sp;
|
|
||||||
CORE_ADDR tramp_sp;
|
|
||||||
gdb_byte buf[4];
|
|
||||||
CORE_ADDR handler;
|
|
||||||
|
|
||||||
lr = read_register (gdbarch_tdep (current_gdbarch)->ppc_lr_regnum);
|
|
||||||
if (!ppc_linux_at_sigtramp_return_path (lr))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
sp = read_register (SP_REGNUM);
|
|
||||||
|
|
||||||
if (target_read_memory (sp, buf, sizeof (buf)) != 0)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
tramp_sp = extract_unsigned_integer (buf, 4);
|
|
||||||
|
|
||||||
if (target_read_memory (tramp_sp + PPC_LINUX_HANDLER_PTR_OFFSET, buf,
|
|
||||||
sizeof (buf)) != 0)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
handler = extract_unsigned_integer (buf, 4);
|
|
||||||
|
|
||||||
return (pc == handler || pc == handler + 4);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
insn_is_sigreturn (unsigned long pcinsn)
|
|
||||||
{
|
|
||||||
switch(pcinsn)
|
|
||||||
{
|
|
||||||
case INSTR_LI_R0_0x6666:
|
|
||||||
case INSTR_LI_R0_0x7777:
|
|
||||||
case INSTR_LI_R0_NR_sigreturn:
|
|
||||||
case INSTR_LI_R0_NR_rt_sigreturn:
|
|
||||||
return 1;
|
|
||||||
default:
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The signal handler trampoline is on the stack and consists of exactly
|
|
||||||
* two instructions. The easiest and most accurate way of determining
|
|
||||||
* whether the pc is in one of these trampolines is by inspecting the
|
|
||||||
* instructions. It'd be faster though if we could find a way to do this
|
|
||||||
* via some simple address comparisons.
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
ppc_linux_at_sigtramp_return_path (CORE_ADDR pc)
|
|
||||||
{
|
|
||||||
gdb_byte buf[12];
|
|
||||||
unsigned long pcinsn;
|
|
||||||
if (target_read_memory (pc - 4, buf, sizeof (buf)) != 0)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
/* extract the instruction at the pc */
|
|
||||||
pcinsn = extract_unsigned_integer (buf + 4, 4);
|
|
||||||
|
|
||||||
return (
|
|
||||||
(insn_is_sigreturn (pcinsn)
|
|
||||||
&& extract_unsigned_integer (buf + 8, 4) == INSTR_SC)
|
|
||||||
||
|
|
||||||
(pcinsn == INSTR_SC
|
|
||||||
&& insn_is_sigreturn (extract_unsigned_integer (buf, 4))));
|
|
||||||
}
|
|
||||||
|
|
||||||
static CORE_ADDR
|
static CORE_ADDR
|
||||||
ppc_linux_skip_trampoline_code (CORE_ADDR pc)
|
ppc_linux_skip_trampoline_code (CORE_ADDR pc)
|
||||||
|
|
Loading…
Reference in New Issue