aboutsummaryrefslogtreecommitdiff
path: root/gdb/i386-linux-tdep.c
diff options
context:
space:
mode:
Diffstat (limited to 'gdb/i386-linux-tdep.c')
-rw-r--r--gdb/i386-linux-tdep.c127
1 files changed, 72 insertions, 55 deletions
diff --git a/gdb/i386-linux-tdep.c b/gdb/i386-linux-tdep.c
index afff548..6d284f1 100644
--- a/gdb/i386-linux-tdep.c
+++ b/gdb/i386-linux-tdep.c
@@ -81,7 +81,7 @@ i386_linux_register_reggroup_p (struct gdbarch *gdbarch, int regnum,
The instruction sequence for normal signals is
pop %eax
- mov $0x77,%eax
+ mov $0x77, %eax
int $0x80
or 0x58 0xb8 0x77 0x00 0x00 0x00 0xcd 0x80.
@@ -103,17 +103,17 @@ i386_linux_register_reggroup_p (struct gdbarch *gdbarch, int regnum,
to the ones used by the kernel. Therefore, these trampolines are
supported too. */
-#define LINUX_SIGTRAMP_INSN0 (0x58) /* pop %eax */
-#define LINUX_SIGTRAMP_OFFSET0 (0)
-#define LINUX_SIGTRAMP_INSN1 (0xb8) /* mov $NNNN,%eax */
-#define LINUX_SIGTRAMP_OFFSET1 (1)
-#define LINUX_SIGTRAMP_INSN2 (0xcd) /* int */
-#define LINUX_SIGTRAMP_OFFSET2 (6)
+#define LINUX_SIGTRAMP_INSN0 0x58 /* pop %eax */
+#define LINUX_SIGTRAMP_OFFSET0 0
+#define LINUX_SIGTRAMP_INSN1 0xb8 /* mov $NNNN, %eax */
+#define LINUX_SIGTRAMP_OFFSET1 1
+#define LINUX_SIGTRAMP_INSN2 0xcd /* int */
+#define LINUX_SIGTRAMP_OFFSET2 6
static const unsigned char linux_sigtramp_code[] =
{
LINUX_SIGTRAMP_INSN0, /* pop %eax */
- LINUX_SIGTRAMP_INSN1, 0x77, 0x00, 0x00, 0x00, /* mov $0x77,%eax */
+ LINUX_SIGTRAMP_INSN1, 0x77, 0x00, 0x00, 0x00, /* mov $0x77, %eax */
LINUX_SIGTRAMP_INSN2, 0x80 /* int $0x80 */
};
@@ -167,20 +167,20 @@ i386_linux_sigtramp_start (CORE_ADDR pc)
/* This function does the same for RT signals. Here the instruction
sequence is
- mov $0xad,%eax
+ mov $0xad, %eax
int $0x80
or 0xb8 0xad 0x00 0x00 0x00 0xcd 0x80.
The effect is to call the system call rt_sigreturn. */
-#define LINUX_RT_SIGTRAMP_INSN0 (0xb8) /* mov $NNNN,%eax */
-#define LINUX_RT_SIGTRAMP_OFFSET0 (0)
-#define LINUX_RT_SIGTRAMP_INSN1 (0xcd) /* int */
-#define LINUX_RT_SIGTRAMP_OFFSET1 (5)
+#define LINUX_RT_SIGTRAMP_INSN0 0xb8 /* mov $NNNN, %eax */
+#define LINUX_RT_SIGTRAMP_OFFSET0 0
+#define LINUX_RT_SIGTRAMP_INSN1 0xcd /* int */
+#define LINUX_RT_SIGTRAMP_OFFSET1 5
static const unsigned char linux_rt_sigtramp_code[] =
{
- LINUX_RT_SIGTRAMP_INSN0, 0xad, 0x00, 0x00, 0x00, /* mov $0xad,%eax */
+ LINUX_RT_SIGTRAMP_INSN0, 0xad, 0x00, 0x00, 0x00, /* mov $0xad, %eax */
LINUX_RT_SIGTRAMP_INSN1, 0x80 /* int $0x80 */
};
@@ -239,50 +239,47 @@ i386_linux_pc_in_sigtramp (CORE_ADDR pc, char *name)
|| strcmp ("__restore_rt", name) == 0);
}
-/* Assuming FRAME is for a GNU/Linux sigtramp routine, return the
- address of the associated sigcontext structure. */
+/* Offset to struct sigcontext in ucontext, from <asm/ucontext.h>. */
+#define I386_LINUX_UCONTEXT_SIGCONTEXT_OFFSET 20
+
+/* Assuming NEXT_FRAME is a frame following a GNU/Linux sigtramp
+ routine, return the address of the associated sigcontext structure. */
static CORE_ADDR
-i386_linux_sigcontext_addr (struct frame_info *frame)
+i386_linux_sigcontext_addr (struct frame_info *next_frame)
{
CORE_ADDR pc;
+ CORE_ADDR sp;
+ char buf[4];
+
+ frame_unwind_register (next_frame, I386_ESP_REGNUM, buf);
+ sp = extract_unsigned_integer (buf, 4);
- pc = i386_linux_sigtramp_start (get_frame_pc (frame));
+ pc = i386_linux_sigtramp_start (frame_pc_unwind (next_frame));
if (pc)
{
- CORE_ADDR sp;
-
- if (get_next_frame (frame))
- /* If this isn't the top frame, the next frame must be for the
- signal handler itself. The sigcontext structure lives on
- the stack, right after the signum argument. */
- return get_frame_base (get_next_frame (frame)) + 12;
-
- /* This is the top frame. We'll have to find the address of the
- sigcontext structure by looking at the stack pointer. Keep
- in mind that the first instruction of the sigtramp code is
- "pop %eax". If the PC is at this instruction, adjust the
- returned value accordingly. */
- sp = read_register (SP_REGNUM);
- if (pc == get_frame_pc (frame))
+ /* The sigcontext structure lives on the stack, right after
+ the signum argument. We determine the address of the
+ sigcontext structure by looking at the frame's stack
+ pointer. Keep in mind that the first instruction of the
+ sigtramp code is "pop %eax". If the PC is after this
+ instruction, adjust the returned value accordingly. */
+ if (pc == frame_pc_unwind (next_frame))
return sp + 4;
return sp;
}
- pc = i386_linux_rt_sigtramp_start (get_frame_pc (frame));
+ pc = i386_linux_rt_sigtramp_start (frame_pc_unwind (next_frame));
if (pc)
{
- if (get_next_frame (frame))
- /* If this isn't the top frame, the next frame must be for the
- signal handler itself. The sigcontext structure is part of
- the user context. A pointer to the user context is passed
- as the third argument to the signal handler. */
- return read_memory_integer (get_frame_base (get_next_frame (frame))
- + 16, 4) + 20;
-
- /* This is the top frame. Again, use the stack pointer to find
- the address of the sigcontext structure. */
- return read_memory_integer (read_register (SP_REGNUM) + 8, 4) + 20;
+ CORE_ADDR ucontext_addr;
+
+ /* The sigcontext structure is part of the user context. A
+ pointer to the user context is passed as the third argument
+ to the signal handler. */
+ read_memory (sp + 8, buf, 4);
+ ucontext_addr = extract_unsigned_integer (buf, 4) + 20;
+ return ucontext_addr + I386_LINUX_UCONTEXT_SIGCONTEXT_OFFSET;
}
error ("Couldn't recognize signal trampoline.");
@@ -294,7 +291,7 @@ i386_linux_sigcontext_addr (struct frame_info *frame)
static void
i386_linux_write_pc (CORE_ADDR pc, ptid_t ptid)
{
- write_register_pid (PC_REGNUM, pc, ptid);
+ write_register_pid (I386_EIP_REGNUM, pc, ptid);
/* We must be careful with modifying the program counter. If we
just interrupted a system call, the kernel might try to restart
@@ -322,7 +319,7 @@ i386_linux_write_pc (CORE_ADDR pc, ptid_t ptid)
be considered too special-purpose for general consumption. */
static struct minimal_symbol *
-find_minsym_and_objfile (char *name, struct objfile **objfile_p)
+find_minsym_and_objfile (char *name, struct objfile **objfilep)
{
struct objfile *objfile;
@@ -335,7 +332,7 @@ find_minsym_and_objfile (char *name, struct objfile **objfile_p)
if (SYMBOL_LINKAGE_NAME (msym)
&& strcmp (SYMBOL_LINKAGE_NAME (msym), name) == 0)
{
- *objfile_p = objfile;
+ *objfilep = objfile;
return msym;
}
}
@@ -345,9 +342,9 @@ find_minsym_and_objfile (char *name, struct objfile **objfile_p)
}
static CORE_ADDR
-skip_hurd_resolver (CORE_ADDR pc)
+skip_gnu_resolver (CORE_ADDR pc)
{
- /* The HURD dynamic linker is part of the GNU C library, so many
+ /* The GNU dynamic linker is part of the GNU C library, so many
GNU/Linux distributions use it. (All ELF versions, as far as I
know.) An unresolved PLT entry points to "_dl_runtime_resolve",
which calls "fixup" to patch the PLT, and then passes control to
@@ -374,7 +371,7 @@ skip_hurd_resolver (CORE_ADDR pc)
= lookup_minimal_symbol ("fixup", NULL, objfile);
if (fixup && SYMBOL_VALUE_ADDRESS (fixup) == pc)
- return (DEPRECATED_SAVED_PC_AFTER_CALL (get_current_frame ()));
+ return frame_pc_unwind (get_current_frame ());
}
return 0;
@@ -393,7 +390,7 @@ i386_linux_skip_solib_resolver (CORE_ADDR pc)
CORE_ADDR result;
/* Plug in functions for other kinds of resolvers here. */
- result = skip_hurd_resolver (pc);
+ result = skip_gnu_resolver (pc);
if (result)
return result;
@@ -442,6 +439,27 @@ i386_linux_svr4_fetch_link_map_offsets (void)
}
+/* From <asm/sigcontext.h>. */
+static int i386_linux_sc_reg_offset[I386_NUM_GREGS] =
+{
+ 11 * 4, /* %eax */
+ 10 * 4, /* %ecx */
+ 9 * 4, /* %edx */
+ 8 * 4, /* %ebx */
+ 7 * 4, /* %esp */
+ 6 * 4, /* %ebp */
+ 5 * 4, /* %esi */
+ 4 * 4, /* %edi */
+ 14 * 4, /* %eip */
+ 16 * 4, /* %eflags */
+ 15 * 4, /* %cs */
+ 18 * 4, /* %ss */
+ 3 * 4, /* %ds */
+ 2 * 4, /* %es */
+ 1 * 4, /* %fs */
+ 0 * 4 /* %gs */
+};
+
static void
i386_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
{
@@ -461,13 +479,12 @@ i386_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
set_gdbarch_num_regs (gdbarch, I386_SSE_NUM_REGS + 1);
set_gdbarch_register_name (gdbarch, i386_linux_register_name);
set_gdbarch_register_reggroup_p (gdbarch, i386_linux_register_reggroup_p);
- set_gdbarch_deprecated_register_bytes (gdbarch, I386_SSE_SIZEOF_REGS + 4);
tdep->jb_pc_offset = 20; /* From <bits/setjmp.h>. */
tdep->sigcontext_addr = i386_linux_sigcontext_addr;
- tdep->sc_pc_offset = 14 * 4; /* From <asm/sigcontext.h>. */
- tdep->sc_sp_offset = 7 * 4;
+ tdep->sc_reg_offset = i386_linux_sc_reg_offset;
+ tdep->sc_num_regs = I386_NUM_GREGS;
/* When the i386 Linux kernel calls a signal handler, the return
address points to a bit of code on the stack. This function is