OSDN Git Service

* i386-tdep.c (LINUX_SIGTRAMP_INSN0, LINUX_SIGTRAMP_OFFSET0,
authorJim Blandy <jimb@codesourcery.com>
Thu, 16 Mar 2000 22:46:30 +0000 (22:46 +0000)
committerJim Blandy <jimb@codesourcery.com>
Thu, 16 Mar 2000 22:46:30 +0000 (22:46 +0000)
LINUX_SIGTRAMP_INSN1, LINUX_SIGTRAMP_OFFSET1,
LINUX_SIGTRAMP_INSN2, LINUX_SIGTRAMP_OFFSET2, linux_sigtramp_code,
LINUX_SIGTRAMP_LEN, i386_linux_sigtramp_start,
LINUX_RT_SIGTRAMP_INSN0, LINUX_RT_SIGTRAMP_OFFSET0,
LINUX_RT_SIGTRAMP_INSN1, LINUX_RT_SIGTRAMP_OFFSET1,
linux_rt_sigtramp_code, LINUX_RT_SIGTRAMP_LEN,
i386_linux_rt_sigtramp_start, i386_linux_in_sigtramp,
i386_linux_sigcontext_addr, LINUX_SIGCONTEXT_PC_OFFSET,
i386_linux_sigtramp_saved_pc, LINUX_SIGCONTEXT_SP_OFFSET,
i386_linux_sigtramp_saved_sp): Deleted.  These all implement
Linux-specific signal trampoline detection, and should be moved to...
* i386-linux-nat.c: ... here.
* config/i386/tm-linux.h (I386_LINUX_SIGTRAMP): No need to define
this any more, since we're not enabling OS-specific code in a
OS-independent file.

gdb/ChangeLog
gdb/config/i386/tm-linux.h
gdb/i386-linux-nat.c
gdb/i386-tdep.c

index 7703083..2be3fab 100644 (file)
@@ -1,3 +1,22 @@
+2000-03-16  Jim Blandy  <jimb@redhat.com>
+
+       * i386-tdep.c (LINUX_SIGTRAMP_INSN0, LINUX_SIGTRAMP_OFFSET0,
+       LINUX_SIGTRAMP_INSN1, LINUX_SIGTRAMP_OFFSET1,
+       LINUX_SIGTRAMP_INSN2, LINUX_SIGTRAMP_OFFSET2, linux_sigtramp_code,
+       LINUX_SIGTRAMP_LEN, i386_linux_sigtramp_start,
+       LINUX_RT_SIGTRAMP_INSN0, LINUX_RT_SIGTRAMP_OFFSET0,
+       LINUX_RT_SIGTRAMP_INSN1, LINUX_RT_SIGTRAMP_OFFSET1,
+       linux_rt_sigtramp_code, LINUX_RT_SIGTRAMP_LEN,
+       i386_linux_rt_sigtramp_start, i386_linux_in_sigtramp,
+       i386_linux_sigcontext_addr, LINUX_SIGCONTEXT_PC_OFFSET,
+       i386_linux_sigtramp_saved_pc, LINUX_SIGCONTEXT_SP_OFFSET,
+       i386_linux_sigtramp_saved_sp): Deleted.  These all implement
+       Linux-specific signal trampoline detection, and should be moved to...
+       * i386-linux-nat.c: ... here.
+       * config/i386/tm-linux.h (I386_LINUX_SIGTRAMP): No need to define
+       this any more, since we're not enabling OS-specific code in a
+       OS-independent file.
+       
 2000-03-16  Eli Zaretskii  <eliz@is.elta.co.il>
 
        * Makefile.in (go32-nat.o): Add prerequisites.
index 3c557f0..c6d8dde 100644 (file)
@@ -98,7 +98,6 @@ extern int i387_store_floating   (PTR addr, int len, long double val);
    are used to identify this bit of code as a signal trampoline in
    order to support backtracing through calls to signal handlers.  */
 
-#define I386_LINUX_SIGTRAMP
 #define IN_SIGTRAMP(pc, name) i386_linux_in_sigtramp (pc, name)
 extern int i386_linux_in_sigtramp (CORE_ADDR, char *);
 
index 3239801..ca87ffd 100644 (file)
@@ -1042,6 +1042,252 @@ i386_linux_skip_solib_resolver (CORE_ADDR pc)
 }
 
 \f
+/* Recognizing signal handler frames.  */
+
+/* Linux has two flavors of signals.  Normal signal handlers, and
+   "realtime" (RT) signals.  The RT signals can provide additional
+   information to the signal handler if the SA_SIGINFO flag is set
+   when establishing a signal handler using `sigaction'.  It is not
+   unlikely that future versions of Linux will support SA_SIGINFO for
+   normal signals too.  */
+
+/* When the i386 Linux kernel calls a signal handler and the
+   SA_RESTORER flag isn't set, the return address points to a bit of
+   code on the stack.  This function returns whether the PC appears to
+   be within this bit of code.
+
+   The instruction sequence for normal signals is
+       pop    %eax
+       mov    $0x77,%eax
+       int    $0x80
+   or 0x58 0xb8 0x77 0x00 0x00 0x00 0xcd 0x80.
+
+   Checking for the code sequence should be somewhat reliable, because
+   the effect is to call the system call sigreturn.  This is unlikely
+   to occur anywhere other than a signal trampoline.
+
+   It kind of sucks that we have to read memory from the process in
+   order to identify a signal trampoline, but there doesn't seem to be
+   any other way.  The IN_SIGTRAMP macro in tm-linux.h arranges to
+   only call us if no function name could be identified, which should
+   be the case since the code is on the stack.
+
+   Detection of signal trampolines for handlers that set the
+   SA_RESTORER flag is in general not possible.  Unfortunately this is
+   what the GNU C Library has been doing for quite some time now.
+   However, as of version 2.1.2, the GNU C Library uses signal
+   trampolines (named __restore and __restore_rt) that are identical
+   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)
+
+static const unsigned char linux_sigtramp_code[] =
+{
+  LINUX_SIGTRAMP_INSN0,                                        /* pop %eax */
+  LINUX_SIGTRAMP_INSN1, 0x77, 0x00, 0x00, 0x00,                /* mov $0x77,%eax */
+  LINUX_SIGTRAMP_INSN2, 0x80                           /* int $0x80 */
+};
+
+#define LINUX_SIGTRAMP_LEN (sizeof linux_sigtramp_code)
+
+/* If PC is in a sigtramp routine, return the address of the start of
+   the routine.  Otherwise, return 0.  */
+
+static CORE_ADDR
+i386_linux_sigtramp_start (CORE_ADDR pc)
+{
+  unsigned char buf[LINUX_SIGTRAMP_LEN];
+
+  /* We only recognize a signal trampoline if PC is at the start of
+     one of the three instructions.  We optimize for finding the PC at
+     the start, as will be the case when the trampoline is not the
+     first frame on the stack.  We assume that in the case where the
+     PC is not at the start of the instruction sequence, there will be
+     a few trailing readable bytes on the stack.  */
+
+  if (read_memory_nobpt (pc, (char *) buf, LINUX_SIGTRAMP_LEN) != 0)
+    return 0;
+
+  if (buf[0] != LINUX_SIGTRAMP_INSN0)
+    {
+      int adjust;
+
+      switch (buf[0])
+       {
+       case LINUX_SIGTRAMP_INSN1:
+         adjust = LINUX_SIGTRAMP_OFFSET1;
+         break;
+       case LINUX_SIGTRAMP_INSN2:
+         adjust = LINUX_SIGTRAMP_OFFSET2;
+         break;
+       default:
+         return 0;
+       }
+
+      pc -= adjust;
+
+      if (read_memory_nobpt (pc, (char *) buf, LINUX_SIGTRAMP_LEN) != 0)
+       return 0;
+    }
+
+  if (memcmp (buf, linux_sigtramp_code, LINUX_SIGTRAMP_LEN) != 0)
+    return 0;
+
+  return pc;
+}
+
+/* This function does the same for RT signals.  Here the instruction
+   sequence is
+       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)
+
+static const unsigned char linux_rt_sigtramp_code[] =
+{
+  LINUX_RT_SIGTRAMP_INSN0, 0xad, 0x00, 0x00, 0x00,     /* mov $0xad,%eax */
+  LINUX_RT_SIGTRAMP_INSN1, 0x80                                /* int $0x80 */
+};
+
+#define LINUX_RT_SIGTRAMP_LEN (sizeof linux_rt_sigtramp_code)
+
+/* If PC is in a RT sigtramp routine, return the address of the start
+   of the routine.  Otherwise, return 0.  */
+
+static CORE_ADDR
+i386_linux_rt_sigtramp_start (CORE_ADDR pc)
+{
+  unsigned char buf[LINUX_RT_SIGTRAMP_LEN];
+
+  /* We only recognize a signal trampoline if PC is at the start of
+     one of the two instructions.  We optimize for finding the PC at
+     the start, as will be the case when the trampoline is not the
+     first frame on the stack.  We assume that in the case where the
+     PC is not at the start of the instruction sequence, there will be
+     a few trailing readable bytes on the stack.  */
+
+  if (read_memory_nobpt (pc, (char *) buf, LINUX_RT_SIGTRAMP_LEN) != 0)
+    return 0;
+
+  if (buf[0] != LINUX_RT_SIGTRAMP_INSN0)
+    {
+      if (buf[0] != LINUX_RT_SIGTRAMP_INSN1)
+       return 0;
+
+      pc -= LINUX_RT_SIGTRAMP_OFFSET1;
+
+      if (read_memory_nobpt (pc, (char *) buf, LINUX_RT_SIGTRAMP_LEN) != 0)
+       return 0;
+    }
+
+  if (memcmp (buf, linux_rt_sigtramp_code, LINUX_RT_SIGTRAMP_LEN) != 0)
+    return 0;
+
+  return pc;
+}
+
+/* Return whether PC is in a Linux sigtramp routine.  */
+
+int
+i386_linux_in_sigtramp (CORE_ADDR pc, char *name)
+{
+  if (name)
+    return STREQ ("__restore", name) || STREQ ("__restore_rt", name);
+  
+  return (i386_linux_sigtramp_start (pc) != 0
+         || i386_linux_rt_sigtramp_start (pc) != 0);
+}
+
+/* Assuming FRAME is for a Linux sigtramp routine, return the address
+   of the associated sigcontext structure.  */
+
+CORE_ADDR
+i386_linux_sigcontext_addr (struct frame_info *frame)
+{
+  CORE_ADDR pc;
+
+  pc = i386_linux_sigtramp_start (frame->pc);
+  if (pc)
+    {
+      CORE_ADDR sp;
+
+      if (frame->next)
+       /* 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 frame->next->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 == frame->pc)
+       return sp + 4;
+      return sp;
+    }
+
+  pc = i386_linux_rt_sigtramp_start (frame->pc);
+  if (pc)
+    {
+      if (frame->next)
+       /* 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 (frame->next->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;
+    }
+
+  error ("Couldn't recognize signal trampoline.");
+  return 0;
+}
+
+/* Offset to saved PC in sigcontext, from <asm/sigcontext.h>.  */
+#define LINUX_SIGCONTEXT_PC_OFFSET (56)
+
+/* Assuming FRAME is for a Linux sigtramp routine, return the saved
+   program counter.  */
+
+CORE_ADDR
+i386_linux_sigtramp_saved_pc (struct frame_info *frame)
+{
+  CORE_ADDR addr;
+  addr = i386_linux_sigcontext_addr (frame);
+  return read_memory_integer (addr + LINUX_SIGCONTEXT_PC_OFFSET, 4);
+}
+
+/* Offset to saved SP in sigcontext, from <asm/sigcontext.h>.  */
+#define LINUX_SIGCONTEXT_SP_OFFSET (28)
+
+/* Assuming FRAME is for a Linux sigtramp routine, return the saved
+   stack pointer.  */
+
+CORE_ADDR
+i386_linux_sigtramp_saved_sp (struct frame_info *frame)
+{
+  CORE_ADDR addr;
+  addr = i386_linux_sigcontext_addr (frame);
+  return read_memory_integer (addr + LINUX_SIGCONTEXT_SP_OFFSET, 4);
+}
+
+\f
 /* Register that we are able to handle Linux ELF core file formats.  */
 
 static struct core_fns linux_elf_core_fns =
index e940e2f..2420ec1 100644 (file)
@@ -779,263 +779,6 @@ i386v4_sigtramp_saved_pc (frame)
 }
 #endif /* I386V4_SIGTRAMP_SAVED_PC */
 
-#ifdef I386_LINUX_SIGTRAMP
-
-/* Linux has two flavors of signals.  Normal signal handlers, and
-   "realtime" (RT) signals.  The RT signals can provide additional
-   information to the signal handler if the SA_SIGINFO flag is set
-   when establishing a signal handler using `sigaction'.  It is not
-   unlikely that future versions of Linux will support SA_SIGINFO for
-   normal signals too.  */
-
-/* When the i386 Linux kernel calls a signal handler and the
-   SA_RESTORER flag isn't set, the return address points to a bit of
-   code on the stack.  This function returns whether the PC appears to
-   be within this bit of code.
-
-   The instruction sequence for normal signals is
-       pop    %eax
-       mov    $0x77,%eax
-       int    $0x80
-   or 0x58 0xb8 0x77 0x00 0x00 0x00 0xcd 0x80.
-
-   Checking for the code sequence should be somewhat reliable, because
-   the effect is to call the system call sigreturn.  This is unlikely
-   to occur anywhere other than a signal trampoline.
-
-   It kind of sucks that we have to read memory from the process in
-   order to identify a signal trampoline, but there doesn't seem to be
-   any other way.  The IN_SIGTRAMP macro in tm-linux.h arranges to
-   only call us if no function name could be identified, which should
-   be the case since the code is on the stack.
-
-   Detection of signal trampolines for handlers that set the
-   SA_RESTORER flag is in general not possible.  Unfortunately this is
-   what the GNU C Library has been doing for quite some time now.
-   However, as of version 2.1.2, the GNU C Library uses signal
-   trampolines (named __restore and __restore_rt) that are identical
-   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)
-
-static const unsigned char linux_sigtramp_code[] =
-{
-  LINUX_SIGTRAMP_INSN0,                                        /* pop %eax */
-  LINUX_SIGTRAMP_INSN1, 0x77, 0x00, 0x00, 0x00,                /* mov $0x77,%eax */
-  LINUX_SIGTRAMP_INSN2, 0x80                           /* int $0x80 */
-};
-
-#define LINUX_SIGTRAMP_LEN (sizeof linux_sigtramp_code)
-
-/* If PC is in a sigtramp routine, return the address of the start of
-   the routine.  Otherwise, return 0.  */
-
-static CORE_ADDR
-i386_linux_sigtramp_start (CORE_ADDR pc)
-{
-  unsigned char buf[LINUX_SIGTRAMP_LEN];
-
-  /* We only recognize a signal trampoline if PC is at the start of
-     one of the three instructions.  We optimize for finding the PC at
-     the start, as will be the case when the trampoline is not the
-     first frame on the stack.  We assume that in the case where the
-     PC is not at the start of the instruction sequence, there will be
-     a few trailing readable bytes on the stack.  */
-
-  if (read_memory_nobpt (pc, (char *) buf, LINUX_SIGTRAMP_LEN) != 0)
-    return 0;
-
-  if (buf[0] != LINUX_SIGTRAMP_INSN0)
-    {
-      int adjust;
-
-      switch (buf[0])
-       {
-       case LINUX_SIGTRAMP_INSN1:
-         adjust = LINUX_SIGTRAMP_OFFSET1;
-         break;
-       case LINUX_SIGTRAMP_INSN2:
-         adjust = LINUX_SIGTRAMP_OFFSET2;
-         break;
-       default:
-         return 0;
-       }
-
-      pc -= adjust;
-
-      if (read_memory_nobpt (pc, (char *) buf, LINUX_SIGTRAMP_LEN) != 0)
-       return 0;
-    }
-
-  if (memcmp (buf, linux_sigtramp_code, LINUX_SIGTRAMP_LEN) != 0)
-    return 0;
-
-  return pc;
-}
-
-/* This function does the same for RT signals.  Here the instruction
-   sequence is
-       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)
-
-static const unsigned char linux_rt_sigtramp_code[] =
-{
-  LINUX_RT_SIGTRAMP_INSN0, 0xad, 0x00, 0x00, 0x00,     /* mov $0xad,%eax */
-  LINUX_RT_SIGTRAMP_INSN1, 0x80                                /* int $0x80 */
-};
-
-#define LINUX_RT_SIGTRAMP_LEN (sizeof linux_rt_sigtramp_code)
-
-/* If PC is in a RT sigtramp routine, return the address of the start
-   of the routine.  Otherwise, return 0.  */
-
-static CORE_ADDR
-i386_linux_rt_sigtramp_start (CORE_ADDR pc)
-{
-  unsigned char buf[LINUX_RT_SIGTRAMP_LEN];
-
-  /* We only recognize a signal trampoline if PC is at the start of
-     one of the two instructions.  We optimize for finding the PC at
-     the start, as will be the case when the trampoline is not the
-     first frame on the stack.  We assume that in the case where the
-     PC is not at the start of the instruction sequence, there will be
-     a few trailing readable bytes on the stack.  */
-
-  if (read_memory_nobpt (pc, (char *) buf, LINUX_RT_SIGTRAMP_LEN) != 0)
-    return 0;
-
-  if (buf[0] != LINUX_RT_SIGTRAMP_INSN0)
-    {
-      if (buf[0] != LINUX_RT_SIGTRAMP_INSN1)
-       return 0;
-
-      pc -= LINUX_RT_SIGTRAMP_OFFSET1;
-
-      if (read_memory_nobpt (pc, (char *) buf, LINUX_RT_SIGTRAMP_LEN) != 0)
-       return 0;
-    }
-
-  if (memcmp (buf, linux_rt_sigtramp_code, LINUX_RT_SIGTRAMP_LEN) != 0)
-    return 0;
-
-  return pc;
-}
-
-/* Return whether PC is in a Linux sigtramp routine.  */
-
-int
-i386_linux_in_sigtramp (CORE_ADDR pc, char *name)
-{
-  if (name)
-    return STREQ ("__restore", name) || STREQ ("__restore_rt", name);
-  
-  return (i386_linux_sigtramp_start (pc) != 0
-         || i386_linux_rt_sigtramp_start (pc) != 0);
-}
-
-/* Assuming FRAME is for a Linux sigtramp routine, return the address
-   of the associated sigcontext structure.  */
-
-CORE_ADDR
-i386_linux_sigcontext_addr (struct frame_info *frame)
-{
-  CORE_ADDR pc;
-
-  pc = i386_linux_sigtramp_start (frame->pc);
-  if (pc)
-    {
-      CORE_ADDR sp;
-
-      if (frame->next)
-       /* 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 frame->next->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 == frame->pc)
-       return sp + 4;
-      return sp;
-    }
-
-  pc = i386_linux_rt_sigtramp_start (frame->pc);
-  if (pc)
-    {
-      if (frame->next)
-       /* 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 (frame->next->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;
-    }
-
-  error ("Couldn't recognize signal trampoline.");
-  return 0;
-}
-
-/* Offset to saved PC in sigcontext, from <asm/sigcontext.h>.  */
-#define LINUX_SIGCONTEXT_PC_OFFSET (56)
-
-/* Assuming FRAME is for a Linux sigtramp routine, return the saved
-   program counter.  */
-
-CORE_ADDR
-i386_linux_sigtramp_saved_pc (struct frame_info *frame)
-{
-  CORE_ADDR addr;
-  addr = i386_linux_sigcontext_addr (frame);
-  return read_memory_integer (addr + LINUX_SIGCONTEXT_PC_OFFSET, 4);
-}
-
-/* Offset to saved SP in sigcontext, from <asm/sigcontext.h>.  */
-#define LINUX_SIGCONTEXT_SP_OFFSET (28)
-
-/* Assuming FRAME is for a Linux sigtramp routine, return the saved
-   stack pointer.  */
-
-CORE_ADDR
-i386_linux_sigtramp_saved_sp (struct frame_info *frame)
-{
-  CORE_ADDR addr;
-  addr = i386_linux_sigcontext_addr (frame);
-  return read_memory_integer (addr + LINUX_SIGCONTEXT_SP_OFFSET, 4);
-}
-
-/* Immediately after a function call, return the saved pc.  */
-
-CORE_ADDR
-i386_linux_saved_pc_after_call (struct frame_info *frame)
-{
-  if (frame->signal_handler_caller)
-    return i386_linux_sigtramp_saved_pc (frame);
-
-  return read_memory_integer (read_register (SP_REGNUM), 4);
-}
-
-#endif /* I386_LINUX_SIGTRAMP */
 
 #ifdef STATIC_TRANSFORM_NAME
 /* SunPRO encodes the static variables.  This is not related to C++ mangling,