2003-10-24 Andrew Cagney <cagney@redhat.com>
[deliverable/binutils-gdb.git] / gdb / i386-linux-tdep.c
index f92f1ea0c6e97abe40aaf9a64e1dd70e5cfeea8e..6d284f1ea98e4d827bb5910bf797428b3c8ee578 100644 (file)
@@ -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 (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)
 }
 \f
 
+/* 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_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
This page took 0.027505 seconds and 4 git commands to generate.