* config/i386/tm-i386sol2.h (STAB_REG_TO_REGNUM): Redefine to call
[deliverable/binutils-gdb.git] / gdb / i386-linux-tdep.c
index ee6ad8f7cf5c8d104ea417ae0347762ad9dd887c..1949b0e203c0ab597126e7dda1f888a7384fda4c 100644 (file)
@@ -28,7 +28,8 @@
 #include "symtab.h"
 #include "symfile.h"
 #include "objfiles.h"
-#include "solib-svr4.h"        /* for struct link_map_offsets */
+
+#include "solib-svr4.h"                /* For struct link_map_offsets.  */
 
 \f
 /* Recognizing signal handler frames.  */
@@ -254,7 +255,7 @@ i386_linux_sigcontext_addr (struct frame_info *frame)
 /* Assuming FRAME is for a Linux sigtramp routine, return the saved
    program counter.  */
 
-CORE_ADDR
+static CORE_ADDR
 i386_linux_sigtramp_saved_pc (struct frame_info *frame)
 {
   CORE_ADDR addr;
@@ -268,7 +269,7 @@ i386_linux_sigtramp_saved_pc (struct frame_info *frame)
 /* Assuming FRAME is for a Linux sigtramp routine, return the saved
    stack pointer.  */
 
-CORE_ADDR
+static CORE_ADDR
 i386_linux_sigtramp_saved_sp (struct frame_info *frame)
 {
   CORE_ADDR addr;
@@ -276,6 +277,61 @@ i386_linux_sigtramp_saved_sp (struct frame_info *frame)
   return read_memory_integer (addr + LINUX_SIGCONTEXT_SP_OFFSET, 4);
 }
 
+/* Signal trampolines don't have a meaningful frame.  As in
+   "i386/tm-i386.h", the frame pointer value we use is actually the
+   frame pointer of the calling frame -- that is, the frame which was
+   in progress when the signal trampoline was entered.  GDB mostly
+   treats this frame pointer value as a magic cookie.  We detect the
+   case of a signal trampoline by looking at the SIGNAL_HANDLER_CALLER
+   field, which is set based on IN_SIGTRAMP.
+
+   When a signal trampoline is invoked from a frameless function, we
+   essentially have two frameless functions in a row.  In this case,
+   we use the same magic cookie for three frames in a row.  We detect
+   this case by seeing whether the next frame has
+   SIGNAL_HANDLER_CALLER set, and, if it does, checking whether the
+   current frame is actually frameless.  In this case, we need to get
+   the PC by looking at the SP register value stored in the signal
+   context.
+
+   This should work in most cases except in horrible situations where
+   a signal occurs just as we enter a function but before the frame
+   has been set up.  */
+
+#define FRAMELESS_SIGNAL(frame)                                        \
+  ((frame)->next != NULL                                       \
+   && (frame)->next->signal_handler_caller                     \
+   && frameless_look_for_prologue (frame))
+
+CORE_ADDR
+i386_linux_frame_chain (struct frame_info *frame)
+{
+  if (frame->signal_handler_caller || FRAMELESS_SIGNAL (frame))
+    return frame->frame;
+
+  if (! inside_entry_file (frame->pc))
+    return read_memory_unsigned_integer (frame->frame, 4);
+
+  return 0;
+}
+
+/* Return the saved program counter for FRAME.  */
+
+CORE_ADDR
+i386_linux_frame_saved_pc (struct frame_info *frame)
+{
+  if (frame->signal_handler_caller)
+    return i386_linux_sigtramp_saved_pc (frame);
+
+  if (FRAMELESS_SIGNAL (frame))
+    {
+      CORE_ADDR sp = i386_linux_sigtramp_saved_sp (frame->next);
+      return read_memory_unsigned_integer (sp, 4);
+    }
+
+  return read_memory_unsigned_integer (frame->frame + 4, 4);
+}
+
 /* Immediately after a function call, return the saved pc.  */
 
 CORE_ADDR
@@ -284,9 +340,8 @@ 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);
+  return read_memory_unsigned_integer (read_register (SP_REGNUM), 4);
 }
-
 \f
 
 /* Calling functions in shared libraries.  */
@@ -375,31 +430,30 @@ i386_linux_skip_solib_resolver (CORE_ADDR pc)
   return 0;
 }
 
-/* Fetch (and possibly build) an appropriate link_map_offsets structure
-   for native i386 linux targets using the struct offsets defined in
-   link.h (but without actual reference to that file).
+/* Fetch (and possibly build) an appropriate link_map_offsets
+   structure for native Linux/x86 targets using the struct offsets
+   defined in link.h (but without actual reference to that file).
 
-   This makes it possible to access i386-linux shared libraries from
-   a gdb that was not built on an i386-linux host (for cross debugging).
-   */
+   This makes it possible to access Linux/x86 shared libraries from a
+   GDB that was not built on an Linux/x86 host (for cross debugging).  */
 
 struct link_map_offsets *
 i386_linux_svr4_fetch_link_map_offsets (void)
 {
   static struct link_map_offsets lmo;
-  static struct link_map_offsets *lmp = 0;
+  static struct link_map_offsets *lmp = NULL;
 
-  if (lmp == 0)
+  if (lmp == NULL)
     {
       lmp = &lmo;
 
-      lmo.r_debug_size = 8;    /* 20 not actual size but all we need */
-
+      lmo.r_debug_size = 8;    /* The actual size is 20 bytes, but
+                                  this is all we need.  */
       lmo.r_map_offset = 4;
       lmo.r_map_size   = 4;
 
-      lmo.link_map_size = 20;  /* 552 not actual size but all we need */
-
+      lmo.link_map_size = 20;  /* The actual size is 552 bytes, but
+                                  this is all we need.  */
       lmo.l_addr_offset = 0;
       lmo.l_addr_size   = 4;
 
@@ -413,6 +467,5 @@ i386_linux_svr4_fetch_link_map_offsets (void)
       lmo.l_prev_size   = 4;
     }
 
-    return lmp;
+  return lmp;
 }
-
This page took 0.025097 seconds and 4 git commands to generate.