Update mn10300 dwarf register map
[deliverable/binutils-gdb.git] / gdb / i386-tdep.c
index 597d672d2ae6f640a266037f9e9bc2ede0043323..57f18cbab8d43505c8f3078ec5bbc1d284f55ed2 100644 (file)
@@ -1,6 +1,6 @@
 /* Intel 386 target-dependent stuff.
 
-   Copyright (C) 1988-2013 Free Software Foundation, Inc.
+   Copyright (C) 1988-2014 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
@@ -530,6 +530,22 @@ i386_absolute_jmp_p (const gdb_byte *insn)
   return 0;
 }
 
+/* Return non-zero if INSN is a jump, zero otherwise.  */
+
+static int
+i386_jmp_p (const gdb_byte *insn)
+{
+  /* jump short, relative.  */
+  if (insn[0] == 0xeb)
+    return 1;
+
+  /* jump near, relative.  */
+  if (insn[0] == 0xe9)
+    return 1;
+
+  return i386_absolute_jmp_p (insn);
+}
+
 static int
 i386_absolute_call_p (const gdb_byte *insn)
 {
@@ -601,6 +617,45 @@ i386_syscall_p (const gdb_byte *insn, int *lengthp)
   return 0;
 }
 
+/* The gdbarch insn_is_call method.  */
+
+static int
+i386_insn_is_call (struct gdbarch *gdbarch, CORE_ADDR addr)
+{
+  gdb_byte buf[I386_MAX_INSN_LEN], *insn;
+
+  read_code (addr, buf, I386_MAX_INSN_LEN);
+  insn = i386_skip_prefixes (buf, I386_MAX_INSN_LEN);
+
+  return i386_call_p (insn);
+}
+
+/* The gdbarch insn_is_ret method.  */
+
+static int
+i386_insn_is_ret (struct gdbarch *gdbarch, CORE_ADDR addr)
+{
+  gdb_byte buf[I386_MAX_INSN_LEN], *insn;
+
+  read_code (addr, buf, I386_MAX_INSN_LEN);
+  insn = i386_skip_prefixes (buf, I386_MAX_INSN_LEN);
+
+  return i386_ret_p (insn);
+}
+
+/* The gdbarch insn_is_jump method.  */
+
+static int
+i386_insn_is_jump (struct gdbarch *gdbarch, CORE_ADDR addr)
+{
+  gdb_byte buf[I386_MAX_INSN_LEN], *insn;
+
+  read_code (addr, buf, I386_MAX_INSN_LEN);
+  insn = i386_skip_prefixes (buf, I386_MAX_INSN_LEN);
+
+  return i386_jmp_p (insn);
+}
+
 /* Some kernels may run one past a syscall insn, so we have to cope.
    Otherwise this is just simple_displaced_step_copy_insn.  */
 
@@ -931,13 +986,14 @@ i386_follow_jump (struct gdbarch *gdbarch, CORE_ADDR pc)
   long delta = 0;
   int data16 = 0;
 
-  if (target_read_memory (pc, &op, 1))
+  if (target_read_code (pc, &op, 1))
     return pc;
 
   if (op == 0x66)
     {
       data16 = 1;
-      op = read_memory_unsigned_integer (pc + 1, 1, byte_order);
+
+      op = read_code_unsigned_integer (pc + 1, 1, byte_order);
     }
 
   switch (op)
@@ -999,13 +1055,13 @@ i386_analyze_struct_return (CORE_ADDR pc, CORE_ADDR current_pc,
   if (current_pc <= pc)
     return pc;
 
-  if (target_read_memory (pc, &op, 1))
+  if (target_read_code (pc, &op, 1))
     return pc;
 
   if (op != 0x58)              /* popl %eax */
     return pc;
 
-  if (target_read_memory (pc + 1, buf, 4))
+  if (target_read_code (pc + 1, buf, 4))
     return pc;
 
   if (memcmp (buf, proto1, 3) != 0 && memcmp (buf, proto2, 4) != 0)
@@ -1046,7 +1102,7 @@ i386_skip_probe (CORE_ADDR pc)
   gdb_byte buf[8];
   gdb_byte op;
 
-  if (target_read_memory (pc, &op, 1))
+  if (target_read_code (pc, &op, 1))
     return pc;
 
   if (op == 0x68 || op == 0x6a)
@@ -1116,7 +1172,7 @@ i386_analyze_stack_align (CORE_ADDR pc, CORE_ADDR current_pc,
     I386_EDI_REGNUM            /* %edi */
   };
 
-  if (target_read_memory (pc, buf, sizeof buf))
+  if (target_read_code (pc, buf, sizeof buf))
     return pc;
 
   /* Check caller-saved saved register.  The first instruction has
@@ -1205,7 +1261,7 @@ i386_match_pattern (CORE_ADDR pc, struct i386_insn pattern)
 {
   gdb_byte op;
 
-  if (target_read_memory (pc, &op, 1))
+  if (target_read_code (pc, &op, 1))
     return 0;
 
   if ((op & pattern.mask[0]) == pattern.insn[0])
@@ -1217,7 +1273,7 @@ i386_match_pattern (CORE_ADDR pc, struct i386_insn pattern)
       gdb_assert (pattern.len > 1);
       gdb_assert (pattern.len <= I386_MAX_MATCHED_INSN_LEN);
 
-      if (target_read_memory (pc + 1, buf, pattern.len - 1))
+      if (target_read_code (pc + 1, buf, pattern.len - 1))
        return 0;
 
       for (i = 1; i < pattern.len; i++)
@@ -1347,7 +1403,7 @@ i386_skip_noop (CORE_ADDR pc)
   gdb_byte op;
   int check = 1;
 
-  if (target_read_memory (pc, &op, 1))
+  if (target_read_code (pc, &op, 1))
     return pc;
 
   while (check) 
@@ -1357,7 +1413,7 @@ i386_skip_noop (CORE_ADDR pc)
       if (op == 0x90) 
        {
          pc += 1;
-         if (target_read_memory (pc, &op, 1))
+         if (target_read_code (pc, &op, 1))
            return pc;
          check = 1;
        }
@@ -1374,13 +1430,13 @@ i386_skip_noop (CORE_ADDR pc)
 
       else if (op == 0x8b)
        {
-         if (target_read_memory (pc + 1, &op, 1))
+         if (target_read_code (pc + 1, &op, 1))
            return pc;
 
          if (op == 0xff)
            {
              pc += 2;
-             if (target_read_memory (pc, &op, 1))
+             if (target_read_code (pc, &op, 1))
                return pc;
 
              check = 1;
@@ -1408,7 +1464,7 @@ i386_analyze_frame_setup (struct gdbarch *gdbarch,
   if (limit <= pc)
     return limit;
 
-  if (target_read_memory (pc, &op, 1))
+  if (target_read_code (pc, &op, 1))
     return pc;
 
   if (op == 0x55)              /* pushl %ebp */
@@ -1444,7 +1500,7 @@ i386_analyze_frame_setup (struct gdbarch *gdbarch,
       if (limit <= pc + skip)
        return limit;
 
-      if (target_read_memory (pc + skip, &op, 1))
+      if (target_read_code (pc + skip, &op, 1))
        return pc + skip;
 
       /* The i386 prologue looks like
@@ -1465,19 +1521,19 @@ i386_analyze_frame_setup (struct gdbarch *gdbarch,
        {
          /* Check for `movl %esp, %ebp' -- can be written in two ways.  */
        case 0x8b:
-         if (read_memory_unsigned_integer (pc + skip + 1, 1, byte_order)
+         if (read_code_unsigned_integer (pc + skip + 1, 1, byte_order)
              != 0xec)
            return pc;
          pc += (skip + 2);
          break;
        case 0x89:
-         if (read_memory_unsigned_integer (pc + skip + 1, 1, byte_order)
+         if (read_code_unsigned_integer (pc + skip + 1, 1, byte_order)
              != 0xe5)
            return pc;
          pc += (skip + 2);
          break;
        case 0x8d: /* Check for 'lea (%ebp), %ebp'.  */
-         if (read_memory_unsigned_integer (pc + skip + 1, 2, byte_order)
+         if (read_code_unsigned_integer (pc + skip + 1, 2, byte_order)
              != 0x242c)
            return pc;
          pc += (skip + 3);
@@ -1504,38 +1560,38 @@ i386_analyze_frame_setup (struct gdbarch *gdbarch,
 
         NOTE: You can't subtract a 16-bit immediate from a 32-bit
         reg, so we don't have to worry about a data16 prefix.  */
-      if (target_read_memory (pc, &op, 1))
+      if (target_read_code (pc, &op, 1))
        return pc;
       if (op == 0x83)
        {
          /* `subl' with 8-bit immediate.  */
-         if (read_memory_unsigned_integer (pc + 1, 1, byte_order) != 0xec)
+         if (read_code_unsigned_integer (pc + 1, 1, byte_order) != 0xec)
            /* Some instruction starting with 0x83 other than `subl'.  */
            return pc;
 
          /* `subl' with signed 8-bit immediate (though it wouldn't
             make sense to be negative).  */
-         cache->locals = read_memory_integer (pc + 2, 1, byte_order);
+         cache->locals = read_code_integer (pc + 2, 1, byte_order);
          return pc + 3;
        }
       else if (op == 0x81)
        {
          /* Maybe it is `subl' with a 32-bit immediate.  */
-         if (read_memory_unsigned_integer (pc + 1, 1, byte_order) != 0xec)
+         if (read_code_unsigned_integer (pc + 1, 1, byte_order) != 0xec)
            /* Some instruction starting with 0x81 other than `subl'.  */
            return pc;
 
          /* It is `subl' with a 32-bit immediate.  */
-         cache->locals = read_memory_integer (pc + 2, 4, byte_order);
+         cache->locals = read_code_integer (pc + 2, 4, byte_order);
          return pc + 6;
        }
       else if (op == 0x8d)
        {
          /* The ModR/M byte is 0x64.  */
-         if (read_memory_unsigned_integer (pc + 1, 1, byte_order) != 0x64)
+         if (read_code_unsigned_integer (pc + 1, 1, byte_order) != 0x64)
            return pc;
          /* 'lea' with 8-bit displacement.  */
-         cache->locals = -1 * read_memory_integer (pc + 3, 1, byte_order);
+         cache->locals = -1 * read_code_integer (pc + 3, 1, byte_order);
          return pc + 4;
        }
       else
@@ -1546,7 +1602,7 @@ i386_analyze_frame_setup (struct gdbarch *gdbarch,
     }
   else if (op == 0xc8)         /* enter */
     {
-      cache->locals = read_memory_unsigned_integer (pc + 1, 2, byte_order);
+      cache->locals = read_code_unsigned_integer (pc + 1, 2, byte_order);
       return pc + 4;
     }
 
@@ -1570,7 +1626,7 @@ i386_analyze_register_saves (CORE_ADDR pc, CORE_ADDR current_pc,
     offset -= cache->locals;
   for (i = 0; i < 8 && pc < current_pc; i++)
     {
-      if (target_read_memory (pc, &op, 1))
+      if (target_read_code (pc, &op, 1))
        return pc;
       if (op < 0x50 || op > 0x57)
        break;
@@ -1680,7 +1736,7 @@ i386_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR start_pc)
 
   for (i = 0; i < 6; i++)
     {
-      if (target_read_memory (pc + i, &op, 1))
+      if (target_read_code (pc + i, &op, 1))
        return pc;
 
       if (pic_pat[i] != op)
@@ -1690,12 +1746,12 @@ i386_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR start_pc)
     {
       int delta = 6;
 
-      if (target_read_memory (pc + delta, &op, 1))
+      if (target_read_code (pc + delta, &op, 1))
        return pc;
 
       if (op == 0x89)          /* movl %ebx, x(%ebp) */
        {
-         op = read_memory_unsigned_integer (pc + delta + 1, 1, byte_order);
+         op = read_code_unsigned_integer (pc + delta + 1, 1, byte_order);
 
          if (op == 0x5d)       /* One byte offset from %ebp.  */
            delta += 3;
@@ -1704,13 +1760,13 @@ i386_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR start_pc)
          else                  /* Unexpected instruction.  */
            delta = 0;
 
-          if (target_read_memory (pc + delta, &op, 1))
+          if (target_read_code (pc + delta, &op, 1))
            return pc;
        }
 
       /* addl y,%ebx */
       if (delta > 0 && op == 0x81
-         && read_memory_unsigned_integer (pc + delta + 1, 1, byte_order)
+         && read_code_unsigned_integer (pc + delta + 1, 1, byte_order)
             == 0xc3)
        {
          pc += delta + 6;
@@ -1735,13 +1791,13 @@ i386_skip_main_prologue (struct gdbarch *gdbarch, CORE_ADDR pc)
   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
   gdb_byte op;
 
-  if (target_read_memory (pc, &op, 1))
+  if (target_read_code (pc, &op, 1))
     return pc;
   if (op == 0xe8)
     {
       gdb_byte buf[4];
 
-      if (target_read_memory (pc + 1, buf, sizeof buf) == 0)
+      if (target_read_code (pc + 1, buf, sizeof buf) == 0)
        {
          /* Make sure address is computed correctly as a 32bit
             integer even if CORE_ADDR is 64 bit wide.  */
@@ -1834,7 +1890,7 @@ i386_frame_cache_1 (struct frame_info *this_frame,
          cache->saved_regs[I386_EIP_REGNUM] -= cache->base;
        }
       else if (cache->pc != 0
-              || target_read_memory (get_frame_pc (this_frame), buf, 1))
+              || target_read_code (get_frame_pc (this_frame), buf, 1))
        {
          /* We're in a known function, but did not find a frame
             setup.  Assume that the function does not use %ebp.
@@ -1904,12 +1960,17 @@ i386_frame_this_id (struct frame_info *this_frame, void **this_cache,
 {
   struct i386_frame_cache *cache = i386_frame_cache (this_frame, this_cache);
 
-  /* This marks the outermost frame.  */
-  if (cache->base == 0)
-    return;
-
-  /* See the end of i386_push_dummy_call.  */
-  (*this_id) = frame_id_build (cache->base + 8, cache->pc);
+  if (!cache->base_p)
+    (*this_id) = frame_id_build_unavailable_stack (cache->pc);
+  else if (cache->base == 0)
+    {
+      /* This marks the outermost frame.  */
+    }
+  else
+    {
+      /* See the end of i386_push_dummy_call.  */
+      (*this_id) = frame_id_build (cache->base + 8, cache->pc);
+    }
 }
 
 static enum unwind_stop_reason
@@ -2090,9 +2151,9 @@ i386_epilogue_frame_this_id (struct frame_info *this_frame,
     i386_epilogue_frame_cache (this_frame, this_cache);
 
   if (!cache->base_p)
-    return;
-
-  (*this_id) = frame_id_build (cache->base + 8, cache->pc);
+    (*this_id) = frame_id_build_unavailable_stack (cache->pc);
+  else
+    (*this_id) = frame_id_build (cache->base + 8, cache->pc);
 }
 
 static struct value *
@@ -2283,10 +2344,12 @@ i386_sigtramp_frame_this_id (struct frame_info *this_frame, void **this_cache,
     i386_sigtramp_frame_cache (this_frame, this_cache);
 
   if (!cache->base_p)
-    return;
-
-  /* See the end of i386_push_dummy_call.  */
-  (*this_id) = frame_id_build (cache->base + 8, get_frame_pc (this_frame));
+    (*this_id) = frame_id_build_unavailable_stack (get_frame_pc (this_frame));
+  else
+    {
+      /* See the end of i386_push_dummy_call.  */
+      (*this_id) = frame_id_build (cache->base + 8, get_frame_pc (this_frame));
+    }
 }
 
 static struct value *
@@ -3597,311 +3660,338 @@ i386_stap_is_single_operand (struct gdbarch *gdbarch, const char *s)
          || (*s == '%' && isalpha (s[1]))); /* Register access.  */
 }
 
-/* Implementation of `gdbarch_stap_parse_special_token', as defined in
-   gdbarch.h.  */
+/* Helper function for i386_stap_parse_special_token.
 
-int
-i386_stap_parse_special_token (struct gdbarch *gdbarch,
-                              struct stap_parse_info *p)
+   This function parses operands of the form `-8+3+1(%rbp)', which
+   must be interpreted as `*(-8 + 3 - 1 + (void *) $eax)'.
+
+   Return 1 if the operand was parsed successfully, zero
+   otherwise.  */
+
+static int
+i386_stap_parse_special_token_triplet (struct gdbarch *gdbarch,
+                                      struct stap_parse_info *p)
 {
-  /* In order to parse special tokens, we use a state-machine that go
-     through every known token and try to get a match.  */
-  enum
+  const char *s = p->arg;
+
+  if (isdigit (*s) || *s == '-' || *s == '+')
     {
-      TRIPLET,
-      THREE_ARG_DISPLACEMENT,
-      DONE
-    } current_state;
+      int got_minus[3];
+      int i;
+      long displacements[3];
+      const char *start;
+      char *regname;
+      int len;
+      struct stoken str;
+      char *endp;
+
+      got_minus[0] = 0;
+      if (*s == '+')
+       ++s;
+      else if (*s == '-')
+       {
+         ++s;
+         got_minus[0] = 1;
+       }
 
-  current_state = TRIPLET;
+      displacements[0] = strtol (s, &endp, 10);
+      s = endp;
 
-  /* The special tokens to be parsed here are:
+      if (*s != '+' && *s != '-')
+       {
+         /* We are not dealing with a triplet.  */
+         return 0;
+       }
 
-     - `register base + (register index * size) + offset', as represented
-     in `(%rcx,%rax,8)', or `[OFFSET](BASE_REG,INDEX_REG[,SIZE])'.
+      got_minus[1] = 0;
+      if (*s == '+')
+       ++s;
+      else
+       {
+         ++s;
+         got_minus[1] = 1;
+       }
 
-     - Operands of the form `-8+3+1(%rbp)', which must be interpreted as
-     `*(-8 + 3 - 1 + (void *) $eax)'.  */
+      displacements[1] = strtol (s, &endp, 10);
+      s = endp;
 
-  while (current_state != DONE)
-    {
-      const char *s = p->arg;
+      if (*s != '+' && *s != '-')
+       {
+         /* We are not dealing with a triplet.  */
+         return 0;
+       }
 
-      switch (current_state)
+      got_minus[2] = 0;
+      if (*s == '+')
+       ++s;
+      else
        {
-       case TRIPLET:
-           {
-             if (isdigit (*s) || *s == '-' || *s == '+')
-               {
-                 int got_minus[3];
-                 int i;
-                 long displacements[3];
-                 const char *start;
-                 char *regname;
-                 int len;
-                 struct stoken str;
-                 char *endp;
-
-                 got_minus[0] = 0;
-                 if (*s == '+')
-                   ++s;
-                 else if (*s == '-')
-                   {
-                     ++s;
-                     got_minus[0] = 1;
-                   }
+         ++s;
+         got_minus[2] = 1;
+       }
 
-                 displacements[0] = strtol (s, &endp, 10);
-                 s = endp;
+      displacements[2] = strtol (s, &endp, 10);
+      s = endp;
 
-                 if (*s != '+' && *s != '-')
-                   {
-                     /* We are not dealing with a triplet.  */
-                     break;
-                   }
+      if (*s != '(' || s[1] != '%')
+       return 0;
 
-                 got_minus[1] = 0;
-                 if (*s == '+')
-                   ++s;
-                 else
-                   {
-                     ++s;
-                     got_minus[1] = 1;
-                   }
+      s += 2;
+      start = s;
 
-                 displacements[1] = strtol (s, &endp, 10);
-                 s = endp;
+      while (isalnum (*s))
+       ++s;
 
-                 if (*s != '+' && *s != '-')
-                   {
-                     /* We are not dealing with a triplet.  */
-                     break;
-                   }
+      if (*s++ != ')')
+       return 0;
 
-                 got_minus[2] = 0;
-                 if (*s == '+')
-                   ++s;
-                 else
-                   {
-                     ++s;
-                     got_minus[2] = 1;
-                   }
+      len = s - start;
+      regname = alloca (len + 1);
 
-                 displacements[2] = strtol (s, &endp, 10);
-                 s = endp;
+      strncpy (regname, start, len);
+      regname[len] = '\0';
 
-                 if (*s != '(' || s[1] != '%')
-                   break;
+      if (user_reg_map_name_to_regnum (gdbarch, regname, len) == -1)
+       error (_("Invalid register name `%s' on expression `%s'."),
+              regname, p->saved_arg);
 
-                 s += 2;
-                 start = s;
+      for (i = 0; i < 3; i++)
+       {
+         write_exp_elt_opcode (OP_LONG);
+         write_exp_elt_type (builtin_type (gdbarch)->builtin_long);
+         write_exp_elt_longcst (displacements[i]);
+         write_exp_elt_opcode (OP_LONG);
+         if (got_minus[i])
+           write_exp_elt_opcode (UNOP_NEG);
+       }
 
-                 while (isalnum (*s))
-                   ++s;
+      write_exp_elt_opcode (OP_REGISTER);
+      str.ptr = regname;
+      str.length = len;
+      write_exp_string (str);
+      write_exp_elt_opcode (OP_REGISTER);
 
-                 if (*s++ != ')')
-                   break;
+      write_exp_elt_opcode (UNOP_CAST);
+      write_exp_elt_type (builtin_type (gdbarch)->builtin_data_ptr);
+      write_exp_elt_opcode (UNOP_CAST);
 
-                 len = s - start;
-                 regname = alloca (len + 1);
+      write_exp_elt_opcode (BINOP_ADD);
+      write_exp_elt_opcode (BINOP_ADD);
+      write_exp_elt_opcode (BINOP_ADD);
 
-                 strncpy (regname, start, len);
-                 regname[len] = '\0';
+      write_exp_elt_opcode (UNOP_CAST);
+      write_exp_elt_type (lookup_pointer_type (p->arg_type));
+      write_exp_elt_opcode (UNOP_CAST);
 
-                 if (user_reg_map_name_to_regnum (gdbarch,
-                                                  regname, len) == -1)
-                   error (_("Invalid register name `%s' "
-                            "on expression `%s'."),
-                          regname, p->saved_arg);
+      write_exp_elt_opcode (UNOP_IND);
 
-                 for (i = 0; i < 3; i++)
-                   {
-                     write_exp_elt_opcode (OP_LONG);
-                     write_exp_elt_type
-                       (builtin_type (gdbarch)->builtin_long);
-                     write_exp_elt_longcst (displacements[i]);
-                     write_exp_elt_opcode (OP_LONG);
-                     if (got_minus[i])
-                       write_exp_elt_opcode (UNOP_NEG);
-                   }
+      p->arg = s;
 
-                 write_exp_elt_opcode (OP_REGISTER);
-                 str.ptr = regname;
-                 str.length = len;
-                 write_exp_string (str);
-                 write_exp_elt_opcode (OP_REGISTER);
+      return 1;
+    }
 
-                 write_exp_elt_opcode (UNOP_CAST);
-                 write_exp_elt_type (builtin_type (gdbarch)->builtin_data_ptr);
-                 write_exp_elt_opcode (UNOP_CAST);
+  return 0;
+}
 
-                 write_exp_elt_opcode (BINOP_ADD);
-                 write_exp_elt_opcode (BINOP_ADD);
-                 write_exp_elt_opcode (BINOP_ADD);
+/* Helper function for i386_stap_parse_special_token.
 
-                 write_exp_elt_opcode (UNOP_CAST);
-                 write_exp_elt_type (lookup_pointer_type (p->arg_type));
-                 write_exp_elt_opcode (UNOP_CAST);
+   This function parses operands of the form `register base +
+   (register index * size) + offset', as represented in
+   `(%rcx,%rax,8)', or `[OFFSET](BASE_REG,INDEX_REG[,SIZE])'.
 
-                 write_exp_elt_opcode (UNOP_IND);
+   Return 1 if the operand was parsed successfully, zero
+   otherwise.  */
 
-                 p->arg = s;
+static int
+i386_stap_parse_special_token_three_arg_disp (struct gdbarch *gdbarch,
+                                             struct stap_parse_info *p)
+{
+  const char *s = p->arg;
 
-                 return 1;
-               }
-             break;
-           }
-       case THREE_ARG_DISPLACEMENT:
-           {
-             if (isdigit (*s) || *s == '(' || *s == '-' || *s == '+')
-               {
-                 int offset_minus = 0;
-                 long offset = 0;
-                 int size_minus = 0;
-                 long size = 0;
-                 const char *start;
-                 char *base;
-                 int len_base;
-                 char *index;
-                 int len_index;
-                 struct stoken base_token, index_token;
-
-                 if (*s == '+')
-                   ++s;
-                 else if (*s == '-')
-                   {
-                     ++s;
-                     offset_minus = 1;
-                   }
+  if (isdigit (*s) || *s == '(' || *s == '-' || *s == '+')
+    {
+      int offset_minus = 0;
+      long offset = 0;
+      int size_minus = 0;
+      long size = 0;
+      const char *start;
+      char *base;
+      int len_base;
+      char *index;
+      int len_index;
+      struct stoken base_token, index_token;
+
+      if (*s == '+')
+       ++s;
+      else if (*s == '-')
+       {
+         ++s;
+         offset_minus = 1;
+       }
 
-                 if (offset_minus && !isdigit (*s))
-                   break;
+      if (offset_minus && !isdigit (*s))
+       return 0;
 
-                 if (isdigit (*s))
-                   {
-                     char *endp;
+      if (isdigit (*s))
+       {
+         char *endp;
 
-                     offset = strtol (s, &endp, 10);
-                     s = endp;
-                   }
+         offset = strtol (s, &endp, 10);
+         s = endp;
+       }
 
-                 if (*s != '(' || s[1] != '%')
-                   break;
+      if (*s != '(' || s[1] != '%')
+       return 0;
 
-                 s += 2;
-                 start = s;
+      s += 2;
+      start = s;
 
-                 while (isalnum (*s))
-                   ++s;
+      while (isalnum (*s))
+       ++s;
 
-                 if (*s != ',' || s[1] != '%')
-                   break;
+      if (*s != ',' || s[1] != '%')
+       return 0;
 
-                 len_base = s - start;
-                 base = alloca (len_base + 1);
-                 strncpy (base, start, len_base);
-                 base[len_base] = '\0';
+      len_base = s - start;
+      base = alloca (len_base + 1);
+      strncpy (base, start, len_base);
+      base[len_base] = '\0';
 
-                 if (user_reg_map_name_to_regnum (gdbarch,
-                                                  base, len_base) == -1)
-                   error (_("Invalid register name `%s' "
-                            "on expression `%s'."),
-                          base, p->saved_arg);
+      if (user_reg_map_name_to_regnum (gdbarch, base, len_base) == -1)
+       error (_("Invalid register name `%s' on expression `%s'."),
+              base, p->saved_arg);
 
-                 s += 2;
-                 start = s;
+      s += 2;
+      start = s;
 
-                 while (isalnum (*s))
-                   ++s;
+      while (isalnum (*s))
+       ++s;
 
-                 len_index = s - start;
-                 index = alloca (len_index + 1);
-                 strncpy (index, start, len_index);
-                 index[len_index] = '\0';
+      len_index = s - start;
+      index = alloca (len_index + 1);
+      strncpy (index, start, len_index);
+      index[len_index] = '\0';
 
-                 if (user_reg_map_name_to_regnum (gdbarch,
-                                                  index, len_index) == -1)
-                   error (_("Invalid register name `%s' "
-                            "on expression `%s'."),
-                          index, p->saved_arg);
+      if (user_reg_map_name_to_regnum (gdbarch, index, len_index) == -1)
+       error (_("Invalid register name `%s' on expression `%s'."),
+              index, p->saved_arg);
 
-                 if (*s != ',' && *s != ')')
-                   break;
+      if (*s != ',' && *s != ')')
+       return 0;
 
-                 if (*s == ',')
-                   {
-                     char *endp;
+      if (*s == ',')
+       {
+         char *endp;
 
-                     ++s;
-                     if (*s == '+')
-                       ++s;
-                     else if (*s == '-')
-                       {
-                         ++s;
-                         size_minus = 1;
-                       }
+         ++s;
+         if (*s == '+')
+           ++s;
+         else if (*s == '-')
+           {
+             ++s;
+             size_minus = 1;
+           }
 
-                     size = strtol (s, &endp, 10);
-                     s = endp;
+         size = strtol (s, &endp, 10);
+         s = endp;
 
-                     if (*s != ')')
-                       break;
-                   }
+         if (*s != ')')
+           return 0;
+       }
 
-                 ++s;
+      ++s;
 
-                 if (offset)
-                   {
-                     write_exp_elt_opcode (OP_LONG);
-                     write_exp_elt_type
-                       (builtin_type (gdbarch)->builtin_long);
-                     write_exp_elt_longcst (offset);
-                     write_exp_elt_opcode (OP_LONG);
-                     if (offset_minus)
-                       write_exp_elt_opcode (UNOP_NEG);
-                   }
+      if (offset)
+       {
+         write_exp_elt_opcode (OP_LONG);
+         write_exp_elt_type (builtin_type (gdbarch)->builtin_long);
+         write_exp_elt_longcst (offset);
+         write_exp_elt_opcode (OP_LONG);
+         if (offset_minus)
+           write_exp_elt_opcode (UNOP_NEG);
+       }
 
-                 write_exp_elt_opcode (OP_REGISTER);
-                 base_token.ptr = base;
-                 base_token.length = len_base;
-                 write_exp_string (base_token);
-                 write_exp_elt_opcode (OP_REGISTER);
+      write_exp_elt_opcode (OP_REGISTER);
+      base_token.ptr = base;
+      base_token.length = len_base;
+      write_exp_string (base_token);
+      write_exp_elt_opcode (OP_REGISTER);
 
-                 if (offset)
-                   write_exp_elt_opcode (BINOP_ADD);
+      if (offset)
+       write_exp_elt_opcode (BINOP_ADD);
 
-                 write_exp_elt_opcode (OP_REGISTER);
-                 index_token.ptr = index;
-                 index_token.length = len_index;
-                 write_exp_string (index_token);
-                 write_exp_elt_opcode (OP_REGISTER);
+      write_exp_elt_opcode (OP_REGISTER);
+      index_token.ptr = index;
+      index_token.length = len_index;
+      write_exp_string (index_token);
+      write_exp_elt_opcode (OP_REGISTER);
 
-                 if (size)
-                   {
-                     write_exp_elt_opcode (OP_LONG);
-                     write_exp_elt_type
-                       (builtin_type (gdbarch)->builtin_long);
-                     write_exp_elt_longcst (size);
-                     write_exp_elt_opcode (OP_LONG);
-                     if (size_minus)
-                       write_exp_elt_opcode (UNOP_NEG);
-                     write_exp_elt_opcode (BINOP_MUL);
-                   }
+      if (size)
+       {
+         write_exp_elt_opcode (OP_LONG);
+         write_exp_elt_type (builtin_type (gdbarch)->builtin_long);
+         write_exp_elt_longcst (size);
+         write_exp_elt_opcode (OP_LONG);
+         if (size_minus)
+           write_exp_elt_opcode (UNOP_NEG);
+         write_exp_elt_opcode (BINOP_MUL);
+       }
 
-                 write_exp_elt_opcode (BINOP_ADD);
+      write_exp_elt_opcode (BINOP_ADD);
 
-                 write_exp_elt_opcode (UNOP_CAST);
-                 write_exp_elt_type (lookup_pointer_type (p->arg_type));
-                 write_exp_elt_opcode (UNOP_CAST);
+      write_exp_elt_opcode (UNOP_CAST);
+      write_exp_elt_type (lookup_pointer_type (p->arg_type));
+      write_exp_elt_opcode (UNOP_CAST);
 
-                 write_exp_elt_opcode (UNOP_IND);
+      write_exp_elt_opcode (UNOP_IND);
 
-                 p->arg = s;
+      p->arg = s;
 
-                 return 1;
-               }
-             break;
-           }
+      return 1;
+    }
+
+  return 0;
+}
+
+/* Implementation of `gdbarch_stap_parse_special_token', as defined in
+   gdbarch.h.  */
+
+int
+i386_stap_parse_special_token (struct gdbarch *gdbarch,
+                              struct stap_parse_info *p)
+{
+  /* In order to parse special tokens, we use a state-machine that go
+     through every known token and try to get a match.  */
+  enum
+    {
+      TRIPLET,
+      THREE_ARG_DISPLACEMENT,
+      DONE
+    } current_state;
+
+  current_state = TRIPLET;
+
+  /* The special tokens to be parsed here are:
+
+     - `register base + (register index * size) + offset', as represented
+     in `(%rcx,%rax,8)', or `[OFFSET](BASE_REG,INDEX_REG[,SIZE])'.
+
+     - Operands of the form `-8+3+1(%rbp)', which must be interpreted as
+     `*(-8 + 3 - 1 + (void *) $eax)'.  */
+
+  while (current_state != DONE)
+    {
+      switch (current_state)
+       {
+       case TRIPLET:
+         if (i386_stap_parse_special_token_triplet (gdbarch, p))
+           return 1;
+         break;
+
+       case THREE_ARG_DISPLACEMENT:
+         if (i386_stap_parse_special_token_three_arg_disp (gdbarch, p))
+           return 1;
+         break;
        }
 
       /* Advancing to the next state.  */
@@ -3918,14 +4008,23 @@ i386_stap_parse_special_token (struct gdbarch *gdbarch,
 void
 i386_elf_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
 {
+  static const char *const stap_integer_prefixes[] = { "$", NULL };
+  static const char *const stap_register_prefixes[] = { "%", NULL };
+  static const char *const stap_register_indirection_prefixes[] = { "(",
+                                                                   NULL };
+  static const char *const stap_register_indirection_suffixes[] = { ")",
+                                                                   NULL };
+
   /* We typically use stabs-in-ELF with the SVR4 register numbering.  */
   set_gdbarch_stab_reg_to_regnum (gdbarch, i386_svr4_reg_to_regnum);
 
   /* Registering SystemTap handlers.  */
-  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_integer_prefixes (gdbarch, stap_integer_prefixes);
+  set_gdbarch_stap_register_prefixes (gdbarch, stap_register_prefixes);
+  set_gdbarch_stap_register_indirection_prefixes (gdbarch,
+                                         stap_register_indirection_prefixes);
+  set_gdbarch_stap_register_indirection_suffixes (gdbarch,
+                                         stap_register_indirection_suffixes);
   set_gdbarch_stap_is_single_operand (gdbarch,
                                      i386_stap_is_single_operand);
   set_gdbarch_stap_parse_special_token (gdbarch,
@@ -4192,9 +4291,9 @@ i386_record_lea_modrm_addr (struct i386_record_s *irp, uint64_t *addr)
   ULONGEST offset64;
 
   *addr = 0;
-  if (irp->aflag)
+  if (irp->aflag || irp->regmap[X86_RECORD_R8_REGNUM])
     {
-      /* 32 bits */
+      /* 32/64 bits */
       int havesib = 0;
       uint8_t scale = 0;
       uint8_t byte;
@@ -4265,6 +4364,13 @@ i386_record_lea_modrm_addr (struct i386_record_s *irp, uint64_t *addr)
          else
            *addr = (uint32_t) (*addr + (offset64 << scale));
        }
+
+      if (!irp->aflag)
+       {
+         /* Since we are in 64-bit mode with ADDR32 prefix, zero-extend
+            address from 32-bit to 64-bit.  */
+           *addr = (uint32_t) *addr;
+       }
     }
   else
     {
@@ -7024,7 +7130,8 @@ no_support_3dnow_data:
     case 0x0ffc:
     case 0x0ffd:
     case 0x0ffe:
-      switch (prefixes)
+      /* Mask out PREFIX_ADDR.  */
+      switch ((prefixes & ~PREFIX_ADDR))
         {
         case PREFIX_REPNZ:
           opcode |= 0xf20000;
@@ -7767,7 +7874,7 @@ i386_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
     return arches->gdbarch;
 
   /* Allocate space for the new architecture.  */
-  tdep = XCALLOC (1, struct gdbarch_tdep);
+  tdep = XCNEW (struct gdbarch_tdep);
   gdbarch = gdbarch_alloc (&info, tdep);
 
   /* General-purpose registers.  */
@@ -7965,6 +8072,10 @@ i386_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
 
   set_gdbarch_gen_return_address (gdbarch, i386_gen_return_address);
 
+  set_gdbarch_insn_is_call (gdbarch, i386_insn_is_call);
+  set_gdbarch_insn_is_ret (gdbarch, i386_insn_is_ret);
+  set_gdbarch_insn_is_jump (gdbarch, i386_insn_is_jump);
+
   /* Hook in ABI-specific overrides, if they have been registered.  */
   info.tdep_info = (void *) tdesc_data;
   gdbarch_init_osabi (info, gdbarch);
This page took 0.040511 seconds and 4 git commands to generate.