Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
* [RFC/i386newframe] Restore all registers from sigframe
@ 2003-05-29 13:03 Michal Ludvig
  2003-05-31 16:01 ` Mark Kettenis
  0 siblings, 1 reply; 3+ messages in thread
From: Michal Ludvig @ 2003-05-29 13:03 UTC (permalink / raw)
  To: Mark Kettenis; +Cc: GDB Patches

[-- 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

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [RFC/i386newframe] Restore all registers from sigframe
  2003-05-29 13:03 [RFC/i386newframe] Restore all registers from sigframe Michal Ludvig
@ 2003-05-31 16:01 ` Mark Kettenis
  2003-05-31 16:55   ` Andrew Cagney
  0 siblings, 1 reply; 3+ messages in thread
From: Mark Kettenis @ 2003-05-31 16:01 UTC (permalink / raw)
  To: mludvig; +Cc: gdb-patches

   Date: Thu, 29 May 2003 15:03:11 +0200
   From: Michal Ludvig <mludvig@suse.cz>

   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.

Indeed.  We defenitely need %ebp too to reliably unwind on the i386.
Might just as well go all the way.  The other registers are usefull
for local variables stored in registers too.  Floating-point registers
are a bit tricky though.  It's fine to leave them out for now though.

   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.

That's fine.  I killed the fallback for amd64 though.  And I added the
appropriate offsets for *BSD.

   Do you like the idea? Or would you choose a different approach?

This was more or less what I had in mind.  I made some changes to the
code though (you changed the offset of %esp on Linux :-().

Will check it in shortly.

Thanks,

Mark


^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [RFC/i386newframe] Restore all registers from sigframe
  2003-05-31 16:01 ` Mark Kettenis
@ 2003-05-31 16:55   ` Andrew Cagney
  0 siblings, 0 replies; 3+ messages in thread
From: Andrew Cagney @ 2003-05-31 16:55 UTC (permalink / raw)
  To: Mark Kettenis; +Cc: mludvig, gdb-patches

>    Date: Thu, 29 May 2003 15:03:11 +0200
>    From: Michal Ludvig <mludvig@suse.cz>
> 
>    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.
> 
> Indeed.  We defenitely need %ebp too to reliably unwind on the i386.
> Might just as well go all the way.  The other registers are usefull
> for local variables stored in registers too.  Floating-point registers
> are a bit tricky though.  It's fine to leave them out for now though.

Ya!  At least two people now get it!  A frame should unwind anything.

Andrew



^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2003-05-31 16:55 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2003-05-29 13:03 [RFC/i386newframe] Restore all registers from sigframe Michal Ludvig
2003-05-31 16:01 ` Mark Kettenis
2003-05-31 16:55   ` Andrew Cagney

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox