* 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>
|
||||
|
||||
* xtensa-tdep.c (XTENSA_IS_ENTRY, extract_call_winsize)
|
||||
|
|
|
@ -40,33 +40,6 @@
|
|||
#include "frame-unwind.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 */
|
||||
#define PPC_LINUX_PT_R0 0
|
||||
#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_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
|
||||
ppc_linux_skip_trampoline_code (CORE_ADDR pc)
|
||||
|
|
Loading…
Reference in New Issue