* lib/gdb.exp (standard_output_file): Use "file join".
[deliverable/binutils-gdb.git] / gdb / amd64-tdep.c
index 14be77686b6806607ab709b7f34ddba03a7d73f4..8ae1142c47e35bde014af73938adc83aa6c12595 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.
 
 
 #include "features/i386/amd64.c"
 #include "features/i386/amd64-avx.c"
+#include "features/i386/x32.c"
+#include "features/i386/x32-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
@@ -254,7 +258,8 @@ static const char *amd64_word_names[] =
 static const char *amd64_dword_names[] =
 {
   "eax", "ebx", "ecx", "edx", "esi", "edi", "ebp", "esp", 
-  "r8d", "r9d", "r10d", "r11d", "r12d", "r13d", "r14d", "r15d"
+  "r8d", "r9d", "r10d", "r11d", "r12d", "r13d", "r14d", "r15d",
+  "eip"
 };
 
 /* Return the name of register REGNUM.  */
@@ -590,7 +595,7 @@ amd64_classify (struct type *type, enum amd64_reg_class class[2])
 }
 
 static enum return_value_convention
-amd64_return_value (struct gdbarch *gdbarch, struct type *func_type,
+amd64_return_value (struct gdbarch *gdbarch, struct value *function,
                    struct type *type, struct regcache *regcache,
                    gdb_byte *readbuf, const gdb_byte *writebuf)
 {
@@ -875,7 +880,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 +1083,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
        {
@@ -1257,7 +1261,7 @@ amd64_displaced_step_copy_insn (struct gdbarch *gdbarch,
                                struct regcache *regs)
 {
   int len = gdbarch_max_insn_length (gdbarch);
-  /* Extra space for sentinels so fixup_{riprel,displaced_copy don't have to
+  /* Extra space for sentinels so fixup_{riprel,displaced_copy} don't have to
      continually watch for running off the end of the buffer.  */
   int fixup_sentinel_space = len;
   struct displaced_step_closure *dsc =
@@ -1548,7 +1552,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)
 {
@@ -1857,6 +1861,188 @@ amd64_analyze_stack_align (CORE_ADDR pc, CORE_ADDR current_pc,
   return min (pc + offset + 2, current_pc);
 }
 
+/* Similar to amd64_analyze_stack_align for x32.  */
+
+static CORE_ADDR
+amd64_x32_analyze_stack_align (CORE_ADDR pc, CORE_ADDR current_pc,
+                              struct amd64_frame_cache *cache) 
+{
+  /* There are 2 code sequences to re-align stack before the frame
+     gets set up:
+
+       1. Use a caller-saved saved register:
+
+               leaq  8(%rsp), %reg
+               andq  $-XXX, %rsp
+               pushq -8(%reg)
+
+          or
+
+               [addr32] leal  8(%rsp), %reg
+               andl  $-XXX, %esp
+               [addr32] pushq -8(%reg)
+
+       2. Use a callee-saved saved register:
+
+               pushq %reg
+               leaq  16(%rsp), %reg
+               andq  $-XXX, %rsp
+               pushq -8(%reg)
+
+          or
+
+               pushq %reg
+               [addr32] leal  16(%rsp), %reg
+               andl  $-XXX, %esp
+               [addr32] pushq -8(%reg)
+
+     "andq $-XXX, %rsp" can be either 4 bytes or 7 bytes:
+     
+       0x48 0x83 0xe4 0xf0                     andq $-16, %rsp
+       0x48 0x81 0xe4 0x00 0xff 0xff 0xff      andq $-256, %rsp
+
+     "andl $-XXX, %esp" can be either 3 bytes or 6 bytes:
+     
+       0x83 0xe4 0xf0                  andl $-16, %esp
+       0x81 0xe4 0x00 0xff 0xff 0xff   andl $-256, %esp
+   */
+
+  gdb_byte buf[19];
+  int reg, r;
+  int offset, offset_and;
+
+  if (target_read_memory (pc, buf, sizeof buf))
+    return pc;
+
+  /* Skip optional addr32 prefix.  */
+  offset = buf[0] == 0x67 ? 1 : 0;
+
+  /* Check caller-saved saved register.  The first instruction has
+     to be "leaq 8(%rsp), %reg" or "leal 8(%rsp), %reg".  */
+  if (((buf[offset] & 0xfb) == 0x48 || (buf[offset] & 0xfb) == 0x40)
+      && buf[offset + 1] == 0x8d
+      && buf[offset + 3] == 0x24
+      && buf[offset + 4] == 0x8)
+    {
+      /* MOD must be binary 10 and R/M must be binary 100.  */
+      if ((buf[offset + 2] & 0xc7) != 0x44)
+       return pc;
+
+      /* REG has register number.  */
+      reg = (buf[offset + 2] >> 3) & 7;
+
+      /* Check the REX.R bit.  */
+      if ((buf[offset] & 0x4) != 0)
+       reg += 8;
+
+      offset += 5;
+    }
+  else
+    {
+      /* Check callee-saved saved register.  The first instruction
+        has to be "pushq %reg".  */
+      reg = 0;
+      if ((buf[offset] & 0xf6) == 0x40
+         && (buf[offset + 1] & 0xf8) == 0x50)
+       {
+         /* Check the REX.B bit.  */
+         if ((buf[offset] & 1) != 0)
+           reg = 8;
+
+         offset += 1;
+       }
+      else if ((buf[offset] & 0xf8) != 0x50)
+       return pc;
+
+      /* Get register.  */
+      reg += buf[offset] & 0x7;
+
+      offset++;
+
+      /* Skip optional addr32 prefix.  */
+      if (buf[offset] == 0x67)
+       offset++;
+
+      /* The next instruction has to be "leaq 16(%rsp), %reg" or
+        "leal 16(%rsp), %reg".  */
+      if (((buf[offset] & 0xfb) != 0x48 && (buf[offset] & 0xfb) != 0x40)
+         || buf[offset + 1] != 0x8d
+         || buf[offset + 3] != 0x24
+         || buf[offset + 4] != 0x10)
+       return pc;
+
+      /* MOD must be binary 10 and R/M must be binary 100.  */
+      if ((buf[offset + 2] & 0xc7) != 0x44)
+       return pc;
+      
+      /* REG has register number.  */
+      r = (buf[offset + 2] >> 3) & 7;
+
+      /* Check the REX.R bit.  */
+      if ((buf[offset] & 0x4) != 0)
+       r += 8;
+
+      /* Registers in pushq and leaq have to be the same.  */
+      if (reg != r)
+       return pc;
+
+      offset += 5;
+    }
+
+  /* Rigister can't be %rsp nor %rbp.  */
+  if (reg == 4 || reg == 5)
+    return pc;
+
+  /* The next instruction may be "andq $-XXX, %rsp" or
+     "andl $-XXX, %esp".  */
+  if (buf[offset] != 0x48)
+    offset--;
+
+  if (buf[offset + 2] != 0xe4
+      || (buf[offset + 1] != 0x81 && buf[offset + 1] != 0x83))
+    return pc;
+
+  offset_and = offset;
+  offset += buf[offset + 1] == 0x81 ? 7 : 4;
+
+  /* Skip optional addr32 prefix.  */
+  if (buf[offset] == 0x67)
+    offset++;
+
+  /* The next instruction has to be "pushq -8(%reg)".  */
+  r = 0;
+  if (buf[offset] == 0xff)
+    offset++;
+  else if ((buf[offset] & 0xf6) == 0x40
+          && buf[offset + 1] == 0xff)
+    {
+      /* Check the REX.B bit.  */
+      if ((buf[offset] & 0x1) != 0)
+       r = 8;
+      offset += 2;
+    }
+  else
+    return pc;
+
+  /* 8bit -8 is 0xf8.  REG must be binary 110 and MOD must be binary
+     01.  */
+  if (buf[offset + 1] != 0xf8
+      || (buf[offset] & 0xf8) != 0x70)
+    return pc;
+
+  /* R/M has register.  */
+  r += buf[offset] & 7;
+
+  /* Registers in leaq and pushq have to be the same.  */
+  if (reg != r)
+    return pc;
+
+  if (current_pc > pc + offset_and)
+    cache->saved_sp_reg = amd64_arch_reg_to_regnum (reg);
+
+  return min (pc + offset + 2, current_pc);
+}
+
 /* Do a limited analysis of the prologue at PC and update CACHE
    accordingly.  Bail out early if CURRENT_PC is reached.  Return the
    address where the analysis stopped.
@@ -1864,10 +2050,16 @@ amd64_analyze_stack_align (CORE_ADDR pc, CORE_ADDR current_pc,
    We will handle only functions beginning with:
 
       pushq %rbp        0x55
-      movq %rsp, %rbp   0x48 0x89 0xe5
+      movq %rsp, %rbp   0x48 0x89 0xe5 (or 0x48 0x8b 0xec)
+
+   or (for the X32 ABI):
+
+      pushq %rbp        0x55
+      movl %esp, %ebp   0x89 0xe5 (or 0x8b 0xec)
 
-   Any function that doesn't start with this sequence will be assumed
-   to have no prologue and thus no valid frame pointer in %rbp.  */
+   Any function that doesn't start with one of these sequences will be
+   assumed to have no prologue and thus no valid frame pointer in
+   %rbp.  */
 
 static CORE_ADDR
 amd64_analyze_prologue (struct gdbarch *gdbarch,
@@ -1875,14 +2067,23 @@ amd64_analyze_prologue (struct gdbarch *gdbarch,
                        struct amd64_frame_cache *cache)
 {
   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
-  static gdb_byte proto[3] = { 0x48, 0x89, 0xe5 }; /* movq %rsp, %rbp */
+  /* There are two variations of movq %rsp, %rbp.  */
+  static const gdb_byte mov_rsp_rbp_1[3] = { 0x48, 0x89, 0xe5 };
+  static const gdb_byte mov_rsp_rbp_2[3] = { 0x48, 0x8b, 0xec };
+  /* Ditto for movl %esp, %ebp.  */
+  static const gdb_byte mov_esp_ebp_1[2] = { 0x89, 0xe5 };
+  static const gdb_byte mov_esp_ebp_2[2] = { 0x8b, 0xec };
+
   gdb_byte buf[3];
   gdb_byte op;
 
   if (current_pc <= pc)
     return current_pc;
 
-  pc = amd64_analyze_stack_align (pc, current_pc, cache);
+  if (gdbarch_ptr_bit (gdbarch) == 32)
+    pc = amd64_x32_analyze_stack_align (pc, current_pc, cache);
+  else
+    pc = amd64_analyze_stack_align (pc, current_pc, cache);
 
   op = read_memory_unsigned_integer (pc, 1, byte_order);
 
@@ -1897,56 +2098,66 @@ amd64_analyze_prologue (struct gdbarch *gdbarch,
       if (current_pc <= pc + 1)
         return current_pc;
 
-      /* Check for `movq %rsp, %rbp'.  */
       read_memory (pc + 1, buf, 3);
-      if (memcmp (buf, proto, 3) != 0)
-       return pc + 1;
 
-      /* OK, we actually have a frame.  */
-      cache->frameless_p = 0;
-      return pc + 4;
+      /* Check for `movq %rsp, %rbp'.  */
+      if (memcmp (buf, mov_rsp_rbp_1, 3) == 0
+         || memcmp (buf, mov_rsp_rbp_2, 3) == 0)
+       {
+         /* OK, we actually have a frame.  */
+         cache->frameless_p = 0;
+         return pc + 4;
+       }
+
+      /* For X32, also check for `movq %esp, %ebp'.  */
+      if (gdbarch_ptr_bit (gdbarch) == 32)
+       {
+         if (memcmp (buf, mov_esp_ebp_1, 2) == 0
+             || memcmp (buf, mov_esp_ebp_2, 2) == 0)
+           {
+             /* OK, we actually have a frame.  */
+             cache->frameless_p = 0;
+             return pc + 3;
+           }
+       }
+
+      return pc + 1;
     }
 
   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 +2179,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 +2206,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 +2382,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 +2902,55 @@ 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);
+
+  /* SystemTap variables and functions.  */
+  set_gdbarch_stap_integer_prefix (gdbarch, "$");
+  set_gdbarch_stap_register_prefix (gdbarch, "%");
+  set_gdbarch_stap_register_indirection_prefix (gdbarch, "(");
+  set_gdbarch_stap_register_indirection_suffix (gdbarch, ")");
+  set_gdbarch_stap_is_single_operand (gdbarch,
+                                     i386_stap_is_single_operand);
+  set_gdbarch_stap_parse_special_token (gdbarch,
+                                       i386_stap_parse_special_token);
+}
+\f
+
+static struct type *
+amd64_x32_pseudo_register_type (struct gdbarch *gdbarch, int regnum)
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
+  switch (regnum - tdep->eax_regnum)
+    {
+    case AMD64_RBP_REGNUM:     /* %ebp */
+    case AMD64_RSP_REGNUM:     /* %esp */
+      return builtin_type (gdbarch)->builtin_data_ptr;
+    case AMD64_RIP_REGNUM:     /* %eip */
+      return builtin_type (gdbarch)->builtin_func_ptr;
+    }
+
+  return i386_pseudo_register_type (gdbarch, regnum);
+}
+
+void
+amd64_x32_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  const struct target_desc *tdesc = info.target_desc;
+
+  amd64_init_abi (info, gdbarch);
+
+  if (! tdesc_has_registers (tdesc))
+    tdesc = tdesc_x32;
+  tdep->tdesc = tdesc;
+
+  tdep->num_dword_regs = 17;
+  set_tdesc_pseudo_register_type (gdbarch, amd64_x32_pseudo_register_type);
+
+  set_gdbarch_long_bit (gdbarch, 32);
+  set_gdbarch_ptr_bit (gdbarch, 32);
 }
 
 /* Provide a prototype to silence -Wmissing-prototypes.  */
@@ -2666,6 +2961,8 @@ _initialize_amd64_tdep (void)
 {
   initialize_tdesc_amd64 ();
   initialize_tdesc_amd64_avx ();
+  initialize_tdesc_x32 ();
+  initialize_tdesc_x32_avx ();
 }
 \f
 
@@ -2690,7 +2987,8 @@ amd64_supply_fxsave (struct regcache *regcache, int regnum,
 
   i387_supply_fxsave (regcache, regnum, fxsave);
 
-  if (fxsave && gdbarch_ptr_bit (gdbarch) == 64)
+  if (fxsave
+      && gdbarch_bfd_arch_info (gdbarch)->bits_per_word == 64)
     {
       const gdb_byte *regs = fxsave;
 
@@ -2712,7 +3010,8 @@ amd64_supply_xsave (struct regcache *regcache, int regnum,
 
   i387_supply_xsave (regcache, regnum, xsave);
 
-  if (xsave && gdbarch_ptr_bit (gdbarch) == 64)
+  if (xsave
+      && gdbarch_bfd_arch_info (gdbarch)->bits_per_word == 64)
     {
       const gdb_byte *regs = xsave;
 
@@ -2740,7 +3039,7 @@ amd64_collect_fxsave (const struct regcache *regcache, int regnum,
 
   i387_collect_fxsave (regcache, regnum, fxsave);
 
-  if (gdbarch_ptr_bit (gdbarch) == 64)
+  if (gdbarch_bfd_arch_info (gdbarch)->bits_per_word == 64)
     {
       if (regnum == -1 || regnum == I387_FISEG_REGNUM (tdep))
        regcache_raw_collect (regcache, I387_FISEG_REGNUM (tdep), regs + 12);
@@ -2761,7 +3060,7 @@ amd64_collect_xsave (const struct regcache *regcache, int regnum,
 
   i387_collect_xsave (regcache, regnum, xsave, gcore);
 
-  if (gdbarch_ptr_bit (gdbarch) == 64)
+  if (gdbarch_bfd_arch_info (gdbarch)->bits_per_word == 64)
     {
       if (regnum == -1 || regnum == I387_FISEG_REGNUM (tdep))
        regcache_raw_collect (regcache, I387_FISEG_REGNUM (tdep),
This page took 0.030462 seconds and 4 git commands to generate.