*** empty log message ***
[deliverable/binutils-gdb.git] / gdb / i386-linux-tdep.c
index 97dda8248d887f49e49dc597f5429017425720f0..5284f4a6ead34134c7e822565f56cb5682eefd01 100644 (file)
@@ -1,13 +1,13 @@
 /* Target-dependent code for GNU/Linux i386.
 
-   Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005
+   Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008
    Free Software Foundation, Inc.
 
    This file is part of GDB.
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
+   the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
 
    This program is distributed in the hope that it will be useful,
@@ -16,9 +16,7 @@
    GNU General Public License for more details.
 
    You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 51 Franklin Street, Fifth Floor,
-   Boston, MA 02110-1301, USA.  */
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #include "defs.h"
 #include "gdbcore.h"
 #include "i386-linux-tdep.h"
 #include "glibc-tdep.h"
 #include "solib-svr4.h"
+#include "symtab.h"
+#include "arch-utils.h"
+#include "regset.h"
+
+/* Supported register note sections.  */
+static struct core_regset_section i386_linux_regset_sections[] =
+{
+  { ".reg", 144 },
+  { ".reg2", 108 },
+  { ".reg-xfp", 512 },
+  { NULL, 0 }
+};
 
 /* Return the name of register REG.  */
 
 static const char *
-i386_linux_register_name (int reg)
+i386_linux_register_name (struct gdbarch *gdbarch, int reg)
 {
   /* Deal with the extra "orig_eax" pseudo register.  */
   if (reg == I386_LINUX_ORIG_EAX_REGNUM)
     return "orig_eax";
 
-  return i386_register_name (reg);
+  return i386_register_name (gdbarch, reg);
 }
 
 /* Return non-zero, when the register is in the corresponding register
@@ -116,13 +126,13 @@ static const gdb_byte linux_sigtramp_code[] =
 
 #define LINUX_SIGTRAMP_LEN (sizeof linux_sigtramp_code)
 
-/* If NEXT_FRAME unwinds into a sigtramp routine, return the address
-   of the start of the routine.  Otherwise, return 0.  */
+/* If THIS_FRAME is a sigtramp routine, return the address of the
+   start of the routine.  Otherwise, return 0.  */
 
 static CORE_ADDR
-i386_linux_sigtramp_start (struct frame_info *next_frame)
+i386_linux_sigtramp_start (struct frame_info *this_frame)
 {
-  CORE_ADDR pc = frame_pc_unwind (next_frame);
+  CORE_ADDR pc = get_frame_pc (this_frame);
   gdb_byte buf[LINUX_SIGTRAMP_LEN];
 
   /* We only recognize a signal trampoline if PC is at the start of
@@ -132,7 +142,7 @@ i386_linux_sigtramp_start (struct frame_info *next_frame)
      PC is not at the start of the instruction sequence, there will be
      a few trailing readable bytes on the stack.  */
 
-  if (!safe_frame_unwind_memory (next_frame, pc, buf, LINUX_SIGTRAMP_LEN))
+  if (!safe_frame_unwind_memory (this_frame, pc, buf, LINUX_SIGTRAMP_LEN))
     return 0;
 
   if (buf[0] != LINUX_SIGTRAMP_INSN0)
@@ -153,7 +163,7 @@ i386_linux_sigtramp_start (struct frame_info *next_frame)
 
       pc -= adjust;
 
-      if (!safe_frame_unwind_memory (next_frame, pc, buf, LINUX_SIGTRAMP_LEN))
+      if (!safe_frame_unwind_memory (this_frame, pc, buf, LINUX_SIGTRAMP_LEN))
        return 0;
     }
 
@@ -184,13 +194,13 @@ static const gdb_byte linux_rt_sigtramp_code[] =
 
 #define LINUX_RT_SIGTRAMP_LEN (sizeof linux_rt_sigtramp_code)
 
-/* If NEXT_FRAME unwinds into an RT sigtramp routine, return the
-   address of the start of the routine.  Otherwise, return 0.  */
+/* If THIS_FRAME is an RT sigtramp routine, return the address of the
+   start of the routine.  Otherwise, return 0.  */
 
 static CORE_ADDR
-i386_linux_rt_sigtramp_start (struct frame_info *next_frame)
+i386_linux_rt_sigtramp_start (struct frame_info *this_frame)
 {
-  CORE_ADDR pc = frame_pc_unwind (next_frame);
+  CORE_ADDR pc = get_frame_pc (this_frame);
   gdb_byte buf[LINUX_RT_SIGTRAMP_LEN];
 
   /* We only recognize a signal trampoline if PC is at the start of
@@ -200,7 +210,7 @@ i386_linux_rt_sigtramp_start (struct frame_info *next_frame)
      PC is not at the start of the instruction sequence, there will be
      a few trailing readable bytes on the stack.  */
 
-  if (!safe_frame_unwind_memory (next_frame, pc, buf, LINUX_RT_SIGTRAMP_LEN))
+  if (!safe_frame_unwind_memory (this_frame, pc, buf, LINUX_RT_SIGTRAMP_LEN))
     return 0;
 
   if (buf[0] != LINUX_RT_SIGTRAMP_INSN0)
@@ -210,7 +220,7 @@ i386_linux_rt_sigtramp_start (struct frame_info *next_frame)
 
       pc -= LINUX_RT_SIGTRAMP_OFFSET1;
 
-      if (!safe_frame_unwind_memory (next_frame, pc, buf,
+      if (!safe_frame_unwind_memory (this_frame, pc, buf,
                                     LINUX_RT_SIGTRAMP_LEN))
        return 0;
     }
@@ -221,13 +231,13 @@ i386_linux_rt_sigtramp_start (struct frame_info *next_frame)
   return pc;
 }
 
-/* Return whether the frame preceding NEXT_FRAME corresponds to a
-   GNU/Linux sigtramp routine.  */
+/* Return whether THIS_FRAME corresponds to a GNU/Linux sigtramp
+   routine.  */
 
 static int
-i386_linux_sigtramp_p (struct frame_info *next_frame)
+i386_linux_sigtramp_p (struct frame_info *this_frame)
 {
-  CORE_ADDR pc = frame_pc_unwind (next_frame);
+  CORE_ADDR pc = get_frame_pc (this_frame);
   char *name;
 
   find_pc_partial_function (pc, &name, NULL, NULL);
@@ -238,21 +248,21 @@ i386_linux_sigtramp_p (struct frame_info *next_frame)
      be part of the preceding function.  This should always be sigaction,
      __sigaction, or __libc_sigaction (all aliases to the same function).  */
   if (name == NULL || strstr (name, "sigaction") != NULL)
-    return (i386_linux_sigtramp_start (next_frame) != 0
-           || i386_linux_rt_sigtramp_start (next_frame) != 0);
+    return (i386_linux_sigtramp_start (this_frame) != 0
+           || i386_linux_rt_sigtramp_start (this_frame) != 0);
 
   return (strcmp ("__restore", name) == 0
          || strcmp ("__restore_rt", name) == 0);
 }
 
-/* Return one if the unwound PC from NEXT_FRAME is in a signal trampoline
-   which may have DWARF-2 CFI.  */
+/* Return one if the PC of THIS_FRAME is in a signal trampoline which
+   may have DWARF-2 CFI.  */
 
 static int
 i386_linux_dwarf_signal_frame_p (struct gdbarch *gdbarch,
-                                struct frame_info *next_frame)
+                                struct frame_info *this_frame)
 {
-  CORE_ADDR pc = frame_pc_unwind (next_frame);
+  CORE_ADDR pc = get_frame_pc (this_frame);
   char *name;
 
   find_pc_partial_function (pc, &name, NULL, NULL);
@@ -269,20 +279,20 @@ i386_linux_dwarf_signal_frame_p (struct gdbarch *gdbarch,
 /* 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.  */
+/* Assuming THIS_FRAME is a GNU/Linux sigtramp routine, return the
+   address of the associated sigcontext structure.  */
 
 static CORE_ADDR
-i386_linux_sigcontext_addr (struct frame_info *next_frame)
+i386_linux_sigcontext_addr (struct frame_info *this_frame)
 {
   CORE_ADDR pc;
   CORE_ADDR sp;
   gdb_byte buf[4];
 
-  frame_unwind_register (next_frame, I386_ESP_REGNUM, buf);
+  get_frame_register (this_frame, I386_ESP_REGNUM, buf);
   sp = extract_unsigned_integer (buf, 4);
 
-  pc = i386_linux_sigtramp_start (next_frame);
+  pc = i386_linux_sigtramp_start (this_frame);
   if (pc)
     {
       /* The sigcontext structure lives on the stack, right after
@@ -291,12 +301,12 @@ i386_linux_sigcontext_addr (struct frame_info *next_frame)
         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))
+      if (pc == get_frame_pc (this_frame))
        return sp + 4;
       return sp;
     }
 
-  pc = i386_linux_rt_sigtramp_start (next_frame);
+  pc = i386_linux_rt_sigtramp_start (this_frame);
   if (pc)
     {
       CORE_ADDR ucontext_addr;
@@ -316,9 +326,9 @@ i386_linux_sigcontext_addr (struct frame_info *next_frame)
 /* Set the program counter for process PTID to PC.  */
 
 static void
-i386_linux_write_pc (CORE_ADDR pc, ptid_t ptid)
+i386_linux_write_pc (struct regcache *regcache, CORE_ADDR pc)
 {
-  write_register_pid (I386_EIP_REGNUM, pc, ptid);
+  regcache_cooked_write_unsigned (regcache, I386_EIP_REGNUM, pc);
 
   /* We must be careful with modifying the program counter.  If we
      just interrupted a system call, the kernel might try to restart
@@ -334,7 +344,7 @@ i386_linux_write_pc (CORE_ADDR pc, ptid_t ptid)
      when we resume the inferior on return from a function call from
      within GDB.  In all other cases the system call will not be
      restarted.  */
-  write_register_pid (I386_LINUX_ORIG_EAX_REGNUM, -1, ptid);
+  regcache_cooked_write_unsigned (regcache, I386_LINUX_ORIG_EAX_REGNUM, -1);
 }
 \f
 
@@ -430,7 +440,12 @@ i386_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
   tdep->sc_reg_offset = i386_linux_sc_reg_offset;
   tdep->sc_num_regs = ARRAY_SIZE (i386_linux_sc_reg_offset);
 
+  /* N_FUN symbols in shared libaries have 0 for their values and need
+     to be relocated. */
+  set_gdbarch_sofun_address_maybe_missing (gdbarch, 1);
+
   /* GNU/Linux uses SVR4-style shared libraries.  */
+  set_gdbarch_skip_trampoline_code (gdbarch, find_solib_trampoline_target);
   set_solib_svr4_fetch_link_map_offsets
     (gdbarch, svr4_ilp32_fetch_link_map_offsets);
 
@@ -442,6 +457,18 @@ i386_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
   /* Enable TLS support.  */
   set_gdbarch_fetch_tls_load_module_address (gdbarch,
                                              svr4_fetch_objfile_link_map);
+
+  /* Install supported register note sections.  */
+  set_gdbarch_core_regset_sections (gdbarch, i386_linux_regset_sections);
+
+  /* Displaced stepping.  */
+  set_gdbarch_displaced_step_copy_insn (gdbarch,
+                                        simple_displaced_step_copy_insn);
+  set_gdbarch_displaced_step_fixup (gdbarch, i386_displaced_step_fixup);
+  set_gdbarch_displaced_step_free_closure (gdbarch,
+                                           simple_displaced_step_free_closure);
+  set_gdbarch_displaced_step_location (gdbarch,
+                                       displaced_step_at_entry_point);
 }
 
 /* Provide a prototype to silence -Wmissing-prototypes.  */
This page took 0.028163 seconds and 4 git commands to generate.