From: Michal Ludvig <mludvig@suse.cz>
To: Mark Kettenis <kettenis@chello.nl>
Cc: GDB Patches <gdb-patches@sources.redhat.com>
Subject: [RFC/i386newframe] Restore all registers from sigframe
Date: Thu, 29 May 2003 13:03:00 -0000 [thread overview]
Message-ID: <3ED6050F.9010908@suse.cz> (raw)
[-- Attachment #1: Type: text/plain, Size: 634 bytes --]
Hi,
the attachd patch enables restoration of all registers when unwinding
from a signal handler. Currenty only PC and SP were restored and it's a
loss since all GPRs are there on the stack.
It's even more important for AMD64 because there parameters are usually
passed in regs and not on the stack.
I did it for amd64-linux and i386-linux as I don't know appropriate
offsets for other i386-targets. For this reason I kept a fallback to
sc_pc_offset/sc_sp_offset.
Do you like the idea? Or would you choose a different approach?
Michal Ludvig
--
* SuSE CR, s.r.o * mludvig@suse.cz
* (+420) 296.545.373 * http://www.suse.cz
[-- Attachment #2: sc-restore-all-regs-2.diff --]
[-- Type: text/plain, Size: 10342 bytes --]
2003-05-29 Michal Ludvig <mludvig@suse.cz>
* i386-tdep.h (struct gdbarch_tdep): num_saved_registers,
sc_reg_offset - new records.
(I386_*_REGNUM): Moved from i386-tdep.c.
* i386-linux-tdep.c (i386_linux_init_abi): Initialize
offsets in tdep->sc_reg_offset[].
* x86-64-linux-tdep.c (x86_64_linux_init_abi): Ditto.
* i386-tdep.c (I386_*_REGNUM): Moved to i386-tdep.h.
(i386_sigtramp_frame_cache): Use tdep->sc_reg_offset
if initialized.
(i386_gdbarch_init): Set tdep->num_saved_registers.
* x86-64-tdep.c: Ditto for AMD64.
* x86-64-tdep.h (X86_64_*_REGNUM): Moved from x86-64-tdep.c.
Index: i386-tdep.h
===================================================================
RCS file: /cvs/src/src/gdb/i386-tdep.h,v
retrieving revision 1.21.2.2
diff -u -p -r1.21.2.2 i386-tdep.h
--- i386-tdep.h 18 May 2003 09:44:12 -0000 1.21.2.2
+++ i386-tdep.h 29 May 2003 12:57:45 -0000
@@ -71,11 +71,30 @@ struct gdbarch_tdep
/* Get address of sigcontext for sigtramp. */
CORE_ADDR (*sigcontext_addr) (struct frame_info *);
+ /* Max number of registers saved for each frame. */
+ int num_saved_registers;
+
+ /* Offsets of all registers in `struct sigcontext'. */
+ int *sc_reg_offset;
+
/* Offset of saved PC and SP in `struct sigcontext'. */
int sc_pc_offset;
int sc_sp_offset;
};
+/* Register numbers of various important registers. */
+
+#define I386_EAX_REGNUM 0 /* %eax */
+#define I386_ECX_REGNUM 1 /* %ecx */
+#define I386_EDX_REGNUM 2 /* %edx */
+#define I386_EBX_REGNUM 3 /* %ebx */
+#define I386_ESP_REGNUM 4 /* %esp */
+#define I386_EBP_REGNUM 5 /* %ebp */
+#define I386_ESI_REGNUM 6 /* %esi */
+#define I386_EDI_REGNUM 7 /* %edi */
+#define I386_EIP_REGNUM 8 /* %eip */
+#define I386_EFLAGS_REGNUM 9 /* %eflags */
+#define I386_ST0_REGNUM 16 /* %st(0) */
/* Floating-point registers. */
#define FPU_REG_RAW_SIZE 10
Index: i386-linux-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/i386-linux-tdep.c,v
retrieving revision 1.26.2.5
diff -u -p -r1.26.2.5 i386-linux-tdep.c
--- i386-linux-tdep.c 18 May 2003 09:44:12 -0000 1.26.2.5
+++ i386-linux-tdep.c 29 May 2003 12:57:43 -0000
@@ -444,6 +444,12 @@ i386_linux_init_abi (struct gdbarch_info
{
struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ /* These offsets come from <asm/sigcontext.h>. */
+ static int reg_offset[] = {
+ 11 * 4, 10 * 4, 9 * 4, 8 * 4, /* %eax, %ecx, %edx, %ebx */
+ 17 * 4, 6 * 4, 5 * 4, 4 * 4, /* %esp, %ebp, %esi, %edi */
+ 14 * 4 }; /* %eip */
+
/* GNU/Linux uses ELF. */
i386_elf_init_abi (info, gdbarch);
@@ -462,9 +468,14 @@ i386_linux_init_abi (struct gdbarch_info
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;
+ /* Offsets of registers saved in a struct sigcontext. */
+ tdep->sc_reg_offset = reg_offset;
+ tdep->num_saved_registers = sizeof (reg_offset) / sizeof (reg_offset[0]);
+
+ tdep->sc_pc_offset = tdep->sc_reg_offset[I386_EIP_REGNUM];
+ tdep->sc_sp_offset = tdep->sc_reg_offset[I386_ESP_REGNUM];
+
/* When the i386 Linux kernel calls a signal handler, the return
address points to a bit of code on the stack. This function is
used to identify this bit of code as a signal trampoline in order
Index: x86-64-linux-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/x86-64-linux-tdep.c,v
retrieving revision 1.17.18.2
diff -u -p -r1.17.18.2 x86-64-linux-tdep.c
--- x86-64-linux-tdep.c 28 May 2003 20:52:03 -0000 1.17.18.2
+++ x86-64-linux-tdep.c 29 May 2003 12:57:45 -0000
@@ -127,13 +127,27 @@ static void
x86_64_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
{
struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
+ /* These offsets come from <asm/sigcontext.h>. */
+ static int reg_offset[] = {
+ 13 * 8, 11 * 8, 14 * 8, 12 * 8, /* %rax, %rbx, %rcx, %rdx */
+ 9 * 8, 8 * 8, 10 * 8, 15 * 8, /* %rsi, %rdi, %rbp, %rsp */
+ 0 * 8, 1 * 8, 2 * 8, 3 * 8, /* %r8 - %r11 */
+ 4 * 8, 5 * 8, 6 * 8, 7 * 8, /* %r12 - %r15 */
+ 16 * 8 }; /* %rip */
+
x86_64_init_abi (info, gdbarch);
set_gdbarch_pc_in_sigtramp (gdbarch, x86_64_linux_pc_in_sigtramp);
tdep->sigcontext_addr = x86_64_linux_sigcontext_addr;
- tdep->sc_pc_offset = 16 * 8; /* From <asm/sigcontext.h>. */
- tdep->sc_sp_offset = 15 * 8;
+
+ /* Offsets of registers saved in a struct sigcontext. */
+ tdep->sc_reg_offset = reg_offset;
+ tdep->num_saved_registers = sizeof (reg_offset) / sizeof (reg_offset[0]);
+
+ tdep->sc_pc_offset = tdep->sc_reg_offset[X86_64_RIP_REGNUM];
+ tdep->sc_sp_offset = tdep->sc_reg_offset[X86_64_RSP_REGNUM];
}
\f
Index: i386-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/i386-tdep.c,v
retrieving revision 1.138.2.15
diff -u -p -r1.138.2.15 i386-tdep.c
--- i386-tdep.c 23 May 2003 20:18:32 -0000 1.138.2.15
+++ i386-tdep.c 29 May 2003 12:57:45 -0000
@@ -48,16 +48,6 @@
#include "i386-tdep.h"
#include "i387-tdep.h"
-/* Register numbers of various important registers. */
-
-#define I386_EAX_REGNUM 0 /* %eax */
-#define I386_EDX_REGNUM 2 /* %edx */
-#define I386_ESP_REGNUM 4 /* %esp */
-#define I386_EBP_REGNUM 5 /* %ebp */
-#define I386_EIP_REGNUM 8 /* %eip */
-#define I386_EFLAGS_REGNUM 9 /* %eflags */
-#define I386_ST0_REGNUM 16 /* %st(0) */
-
/* Names of the registers. The first 10 registers match the register
numbering scheme used by GCC for stabs and DWARF. */
@@ -879,6 +869,7 @@ i386_sigtramp_frame_cache (struct frame_
struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
CORE_ADDR addr;
char buf[4];
+ int i;
if (*this_cache)
return *this_cache;
@@ -889,8 +880,16 @@ i386_sigtramp_frame_cache (struct frame_
cache->base = extract_unsigned_integer (buf, 4) - 4;
addr = tdep->sigcontext_addr (next_frame);
- cache->saved_regs[I386_EIP_REGNUM] = addr + tdep->sc_pc_offset;
- cache->saved_regs[I386_ESP_REGNUM] = addr + tdep->sc_sp_offset;
+ if (tdep->sc_reg_offset)
+ /* If we have offsets for all registers use them. */
+ for (i = 0; i < tdep->num_saved_registers; i++)
+ cache->saved_regs[i] = addr + tdep->sc_reg_offset[i];
+ else
+ {
+ /* If not, use only %eip and %esp offsets. */
+ cache->saved_regs[I386_EIP_REGNUM] = addr + tdep->sc_pc_offset;
+ cache->saved_regs[I386_ESP_REGNUM] = addr + tdep->sc_sp_offset;
+ }
*this_cache = cache;
return cache;
@@ -1627,6 +1626,8 @@ i386_gdbarch_init (struct gdbarch_info i
tdep->sigcontext_addr = NULL;
tdep->sc_pc_offset = -1;
tdep->sc_sp_offset = -1;
+ tdep->sc_reg_offset = NULL;
+ tdep->num_saved_registers = 0;
/* The format used for `long double' on almost all i386 targets is
the i387 extended floating-point format. In fact, of all targets
Index: x86-64-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/x86-64-tdep.c,v
retrieving revision 1.67.2.5
diff -u -p -r1.67.2.5 x86-64-tdep.c
--- x86-64-tdep.c 19 May 2003 16:58:19 -0000 1.67.2.5
+++ x86-64-tdep.c 29 May 2003 12:57:45 -0000
@@ -40,19 +40,6 @@
#include "x86-64-tdep.h"
#include "i387-tdep.h"
-/* Register numbers of various important registers. */
-
-#define X86_64_RAX_REGNUM 0 /* %rax */
-#define X86_64_RDX_REGNUM 3 /* %rdx */
-#define X86_64_RDI_REGNUM 5 /* %rdi */
-#define X86_64_RBP_REGNUM 6 /* %rbp */
-#define X86_64_RSP_REGNUM 7 /* %rsp */
-#define X86_64_RIP_REGNUM 16 /* %rip */
-#define X86_64_EFLAGS_REGNUM 17 /* %eflags */
-#define X86_64_ST0_REGNUM 22 /* %st0 */
-#define X86_64_XMM0_REGNUM 38 /* %xmm0 */
-#define X86_64_XMM1_REGNUM 39 /* %xmm1 */
-
struct x86_64_register_info
{
char *name;
@@ -1040,6 +1027,7 @@ x86_64_sigtramp_frame_cache (struct fram
struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
CORE_ADDR addr;
char buf[8];
+ int i;
if (*this_cache)
return *this_cache;
@@ -1050,8 +1038,16 @@ x86_64_sigtramp_frame_cache (struct fram
cache->base = extract_unsigned_integer (buf, 8) - 8;
addr = tdep->sigcontext_addr (next_frame);
- cache->saved_regs[X86_64_RIP_REGNUM] = addr + tdep->sc_pc_offset;
- cache->saved_regs[X86_64_RSP_REGNUM] = addr + tdep->sc_sp_offset;
+ if (tdep->sc_reg_offset)
+ /* If we have offsets for all registers use them. */
+ for (i = 0; i < tdep->num_saved_registers; i++)
+ cache->saved_regs[i] = addr + tdep->sc_reg_offset[i];
+ else
+ {
+ /* If not, use only %rip and %rsp offsets. */
+ cache->saved_regs[X86_64_RIP_REGNUM] = addr + tdep->sc_pc_offset;
+ cache->saved_regs[X86_64_RSP_REGNUM] = addr + tdep->sc_sp_offset;
+ }
*this_cache = cache;
return cache;
Index: x86-64-tdep.h
===================================================================
RCS file: /cvs/src/src/gdb/x86-64-tdep.h,v
retrieving revision 1.14.2.1
diff -u -p -r1.14.2.1 x86-64-tdep.h
--- x86-64-tdep.h 17 May 2003 15:09:15 -0000 1.14.2.1
+++ x86-64-tdep.h 29 May 2003 12:57:45 -0000
@@ -33,6 +33,23 @@ struct frame_info;
/* Number of general purpose registers. */
#define X86_64_NUM_GREGS 22
+/* Register numbers of various important registers. */
+
+#define X86_64_RAX_REGNUM 0 /* %rax */
+#define X86_64_RBX_REGNUM 1 /* %rbx */
+#define X86_64_RCX_REGNUM 2 /* %rcx */
+#define X86_64_RDX_REGNUM 3 /* %rdx */
+#define X86_64_RSI_REGNUM 4 /* %rsi */
+#define X86_64_RDI_REGNUM 5 /* %rdi */
+#define X86_64_RBP_REGNUM 6 /* %rbp */
+#define X86_64_RSP_REGNUM 7 /* %rsp */
+#define X86_64_R8_REGNUM 8 /* %rsp */
+#define X86_64_RIP_REGNUM 16 /* %rip */
+#define X86_64_EFLAGS_REGNUM 17 /* %eflags */
+#define X86_64_ST0_REGNUM 22 /* %st0 */
+#define X86_64_XMM0_REGNUM 38 /* %xmm0 */
+#define X86_64_XMM1_REGNUM 39 /* %xmm1 */
+
void x86_64_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch);
/* Fill GDB's register array with the floating-point and SSE register
next reply other threads:[~2003-05-29 13:03 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2003-05-29 13:03 Michal Ludvig [this message]
2003-05-31 16:01 ` Mark Kettenis
2003-05-31 16:55 ` Andrew Cagney
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=3ED6050F.9010908@suse.cz \
--to=mludvig@suse.cz \
--cc=gdb-patches@sources.redhat.com \
--cc=kettenis@chello.nl \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox