2012-02-21 Pedro Alves <palves@redhat.com>
[deliverable/binutils-gdb.git] / gdb / amd64-tdep.c
index 14be77686b6806607ab709b7f34ddba03a7d73f4..ea65d0d55bc8ba795f514d802b89e1eaf212cabe 100644 (file)
@@ -1,7 +1,6 @@
 /* Target-dependent code for AMD64.
 
-   Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
-   2011 Free Software Foundation, Inc.
+   Copyright (C) 2001-2012 Free Software Foundation, Inc.
 
    Contributed by Jiri Smid, SuSE Labs.
 
@@ -45,6 +44,9 @@
 #include "features/i386/amd64.c"
 #include "features/i386/amd64-avx.c"
 
+#include "ax.h"
+#include "ax-gdb.h"
+
 /* Note that the AMD64 architecture was previously known as x86-64.
    The latter is (forever) engraved into the canonical system name as
    returned by config.guess, and used as the name for the AMD64 port
@@ -875,7 +877,6 @@ amd64_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
   /* Pass "hidden" argument".  */
   if (struct_return)
     {
-      struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
       /* The "hidden" argument is passed throught the first argument
          register.  */
       const int arg_regnum = tdep->call_dummy_integer_regs[0];
@@ -1079,9 +1080,9 @@ amd64_get_unused_input_int_reg (const struct amd64_insn *details)
       if (have_sib)
        {
          int base = SIB_BASE_FIELD (details->raw_insn[details->modrm_offset + 1]);
-         int index = SIB_INDEX_FIELD (details->raw_insn[details->modrm_offset + 1]);
+         int idx = SIB_INDEX_FIELD (details->raw_insn[details->modrm_offset + 1]);
          used_regs_mask |= 1 << base;
-         used_regs_mask |= 1 << index;
+         used_regs_mask |= 1 << idx;
        }
       else
        {
@@ -1548,7 +1549,7 @@ append_insns (CORE_ADDR *to, ULONGEST len, const gdb_byte *buf)
   *to += len;
 }
 
-void
+static void
 amd64_relocate_instruction (struct gdbarch *gdbarch,
                            CORE_ADDR *to, CORE_ADDR oldloc)
 {
@@ -1910,43 +1911,37 @@ amd64_analyze_prologue (struct gdbarch *gdbarch,
   return pc;
 }
 
-/* Return PC of first real instruction.  */
+/* Work around false termination of prologue - GCC PR debug/48827.
+
+   START_PC is the first instruction of a function, PC is its minimal already
+   determined advanced address.  Function returns PC if it has nothing to do.
+
+   84 c0                test   %al,%al
+   74 23                je     after
+   <-- here is 0 lines advance - the false prologue end marker.
+   0f 29 85 70 ff ff ff movaps %xmm0,-0x90(%rbp)
+   0f 29 4d 80          movaps %xmm1,-0x80(%rbp)
+   0f 29 55 90          movaps %xmm2,-0x70(%rbp)
+   0f 29 5d a0          movaps %xmm3,-0x60(%rbp)
+   0f 29 65 b0          movaps %xmm4,-0x50(%rbp)
+   0f 29 6d c0          movaps %xmm5,-0x40(%rbp)
+   0f 29 75 d0          movaps %xmm6,-0x30(%rbp)
+   0f 29 7d e0          movaps %xmm7,-0x20(%rbp)
+   after:  */
 
 static CORE_ADDR
-amd64_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR start_pc)
+amd64_skip_xmm_prologue (CORE_ADDR pc, CORE_ADDR start_pc)
 {
-  struct amd64_frame_cache cache;
-  CORE_ADDR pc;
   struct symtab_and_line start_pc_sal, next_sal;
   gdb_byte buf[4 + 8 * 7];
   int offset, xmmreg;
 
-  amd64_init_frame_cache (&cache);
-  pc = amd64_analyze_prologue (gdbarch, start_pc, 0xffffffffffffffffLL,
-                              &cache);
-  if (cache.frameless_p)
-    return start_pc;
-
-  /* GCC PR debug/48827 produced false prologue end:
-     84 c0                test   %al,%al
-     74 23                je     after
-     <-- here is 0 lines advance - the false prologue end marker.
-     0f 29 85 70 ff ff ff movaps %xmm0,-0x90(%rbp)
-     0f 29 4d 80          movaps %xmm1,-0x80(%rbp)
-     0f 29 55 90          movaps %xmm2,-0x70(%rbp)
-     0f 29 5d a0          movaps %xmm3,-0x60(%rbp)
-     0f 29 65 b0          movaps %xmm4,-0x50(%rbp)
-     0f 29 6d c0          movaps %xmm5,-0x40(%rbp)
-     0f 29 75 d0          movaps %xmm6,-0x30(%rbp)
-     0f 29 7d e0          movaps %xmm7,-0x20(%rbp)
-     after:  */
-
   if (pc == start_pc)
     return pc;
 
   start_pc_sal = find_pc_sect_line (start_pc, NULL, 0);
   if (start_pc_sal.symtab == NULL
-      || !start_pc_sal.symtab->amd64_prologue_line_bug
+      || producer_is_gcc_ge_4 (start_pc_sal.symtab->producer) < 6
       || start_pc_sal.pc != start_pc || pc >= start_pc_sal.end)
     return pc;
 
@@ -1968,17 +1963,19 @@ amd64_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR start_pc)
   offset = 4;
   for (xmmreg = 0; xmmreg < 8; xmmreg++)
     {
-      /* movaps %xmmreg?,-0x??(%rbp) */
+      /* 0x0f 0x29 0b??000101 movaps %xmmreg?,-0x??(%rbp) */
       if (buf[offset] != 0x0f || buf[offset + 1] != 0x29
-          || (buf[offset + 2] & 0b00111111) != (xmmreg << 3 | 0b101))
+          || (buf[offset + 2] & 0x3f) != (xmmreg << 3 | 0x5))
        return pc;
 
-      if ((buf[offset + 2] & 0b11000000) == 0b01000000)
+      /* 0b01?????? */
+      if ((buf[offset + 2] & 0xc0) == 0x40)
        {
          /* 8-bit displacement.  */
          offset += 4;
        }
-      else if ((buf[offset + 2] & 0b11000000) == 0b10000000)
+      /* 0b10?????? */
+      else if ((buf[offset + 2] & 0xc0) == 0x80)
        {
          /* 32-bit displacement.  */
          offset += 7;
@@ -1993,6 +1990,23 @@ amd64_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR start_pc)
 
   return next_sal.end;
 }
+
+/* Return PC of first real instruction.  */
+
+static CORE_ADDR
+amd64_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR start_pc)
+{
+  struct amd64_frame_cache cache;
+  CORE_ADDR pc;
+
+  amd64_init_frame_cache (&cache);
+  pc = amd64_analyze_prologue (gdbarch, start_pc, 0xffffffffffffffffLL,
+                              &cache);
+  if (cache.frameless_p)
+    return start_pc;
+
+  return amd64_skip_xmm_prologue (pc, start_pc);
+}
 \f
 
 /* Normal frames.  */
@@ -2152,6 +2166,22 @@ static const struct frame_unwind amd64_frame_unwind =
   default_frame_sniffer
 };
 \f
+/* Generate a bytecode expression to get the value of the saved PC.  */
+
+static void
+amd64_gen_return_address (struct gdbarch *gdbarch,
+                         struct agent_expr *ax, struct axs_value *value,
+                         CORE_ADDR scope)
+{
+  /* The following sequence assumes the traditional use of the base
+     register.  */
+  ax_reg (ax, AMD64_RBP_REGNUM);
+  ax_const_l (ax, 8);
+  ax_simple (ax, aop_add);
+  value->type = register_type (gdbarch, AMD64_RIP_REGNUM);
+  value->kind = axs_lvalue_memory;
+}
+\f
 
 /* Signal trampolines.  */
 
@@ -2656,6 +2686,8 @@ amd64_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
   set_gdbarch_get_longjmp_target (gdbarch, amd64_get_longjmp_target);
 
   set_gdbarch_relocate_instruction (gdbarch, amd64_relocate_instruction);
+
+  set_gdbarch_gen_return_address (gdbarch, amd64_gen_return_address);
 }
 
 /* Provide a prototype to silence -Wmissing-prototypes.  */
This page took 0.026927 seconds and 4 git commands to generate.