gdb/DWARF: Support for arrays whose bound is a discriminant.
[deliverable/binutils-gdb.git] / gdb / arm-tdep.c
index ef75fe2bc9dcecdfebedb93b056907e06e227b59..8e9552a1e19d06784e5d48e15df064d5e061e196 100644 (file)
@@ -1,6 +1,6 @@
 /* Common target dependent code for GDB on ARM systems.
 
-   Copyright (C) 1988-2014 Free Software Foundation, Inc.
+   Copyright (C) 1988-2015 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
@@ -1204,7 +1204,9 @@ arm_analyze_load_stack_chk_guard(CORE_ADDR pc, struct gdbarch *gdbarch,
        {
          *destreg = bits (insn1, 8, 10);
          *offset = 2;
-         address = bits (insn1, 0, 7);
+         address = (pc & 0xfffffffc) + 4 + (bits (insn1, 0, 7) << 2);
+         address = read_memory_unsigned_integer (address, 4,
+                                                 byte_order_for_code);
        }
       else if ((insn1 & 0xfbf0) == 0xf240) /* movw Rd, #const */
        {
@@ -1233,9 +1235,12 @@ arm_analyze_load_stack_chk_guard(CORE_ADDR pc, struct gdbarch *gdbarch,
       unsigned int insn
        = read_memory_unsigned_integer (pc, 4, byte_order_for_code);
 
-      if ((insn & 0x0e5f0000) == 0x041f0000) /* ldr Rd, #immed */
+      if ((insn & 0x0e5f0000) == 0x041f0000) /* ldr Rd, [PC, #immed] */
        {
-         address = bits (insn, 0, 11);
+         address = bits (insn, 0, 11) + pc + 8;
+         address = read_memory_unsigned_integer (address, 4,
+                                                 byte_order_for_code);
+
          *destreg = bits (insn, 12, 15);
          *offset = 4;
        }
@@ -1306,11 +1311,10 @@ arm_skip_stack_protector(CORE_ADDR pc, struct gdbarch *gdbarch)
     return pc;
 
   stack_chk_guard = lookup_minimal_symbol_by_pc (addr);
-  /* If name of symbol doesn't start with '__stack_chk_guard', this
-     instruction sequence is not for stack protector.  If symbol is
-     removed, we conservatively think this sequence is for stack protector.  */
-  if (stack_chk_guard.minsym
-      && strncmp (MSYMBOL_LINKAGE_NAME (stack_chk_guard.minsym),
+  /* ADDR must correspond to a symbol whose name is __stack_chk_guard.
+     Otherwise, this sequence cannot be for stack protector.  */
+  if (stack_chk_guard.minsym == NULL
+      || strncmp (MSYMBOL_LINKAGE_NAME (stack_chk_guard.minsym),
                  "__stack_chk_guard",
                  strlen ("__stack_chk_guard")) != 0)
    return pc;
@@ -1384,7 +1388,6 @@ arm_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc)
 {
   enum bfd_endian byte_order_for_code = gdbarch_byte_order_for_code (gdbarch);
   unsigned long inst;
-  CORE_ADDR skip_pc;
   CORE_ADDR func_addr, limit_pc;
 
   /* See if we can determine the end of the prologue via the symbol table.
@@ -1394,7 +1397,7 @@ arm_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc)
     {
       CORE_ADDR post_prologue_pc
        = skip_prologue_using_sal (gdbarch, func_addr);
-      struct symtab *s = find_pc_symtab (func_addr);
+      struct compunit_symtab *cust = find_pc_compunit_symtab (func_addr);
 
       if (post_prologue_pc)
        post_prologue_pc
@@ -1408,10 +1411,12 @@ arm_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc)
         will have producer information for most binaries; if it is
         missing (e.g. for -gstabs), assuming the GNU tools.  */
       if (post_prologue_pc
-         && (s == NULL
-             || s->producer == NULL
-             || strncmp (s->producer, "GNU ", sizeof ("GNU ") - 1) == 0 
-             || strncmp (s->producer, "clang ", sizeof ("clang ") - 1) == 0))
+         && (cust == NULL
+             || COMPUNIT_PRODUCER (cust) == NULL
+             || strncmp (COMPUNIT_PRODUCER (cust), "GNU ",
+                         sizeof ("GNU ") - 1) == 0
+             || strncmp (COMPUNIT_PRODUCER (cust), "clang ",
+                         sizeof ("clang ") - 1) == 0))
        return post_prologue_pc;
 
       if (post_prologue_pc != 0)
@@ -1456,65 +1461,8 @@ arm_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc)
   /* Check if this is Thumb code.  */
   if (arm_pc_is_thumb (gdbarch, pc))
     return thumb_analyze_prologue (gdbarch, pc, limit_pc, NULL);
-
-  for (skip_pc = pc; skip_pc < limit_pc; skip_pc += 4)
-    {
-      inst = read_memory_unsigned_integer (skip_pc, 4, byte_order_for_code);
-
-      /* "mov ip, sp" is no longer a required part of the prologue.  */
-      if (inst == 0xe1a0c00d)                  /* mov ip, sp */
-       continue;
-
-      if ((inst & 0xfffff000) == 0xe28dc000)    /* add ip, sp #n */
-       continue;
-
-      if ((inst & 0xfffff000) == 0xe24dc000)    /* sub ip, sp #n */
-       continue;
-
-      /* Some prologues begin with "str lr, [sp, #-4]!".  */
-      if (inst == 0xe52de004)                  /* str lr, [sp, #-4]! */
-       continue;
-
-      if ((inst & 0xfffffff0) == 0xe92d0000)   /* stmfd sp!,{a1,a2,a3,a4} */
-       continue;
-
-      if ((inst & 0xfffff800) == 0xe92dd800)   /* stmfd sp!,{fp,ip,lr,pc} */
-       continue;
-
-      /* Any insns after this point may float into the code, if it makes
-        for better instruction scheduling, so we skip them only if we
-        find them, but still consider the function to be frame-ful.  */
-
-      /* We may have either one sfmfd instruction here, or several stfe
-        insns, depending on the version of floating point code we
-        support.  */
-      if ((inst & 0xffbf0fff) == 0xec2d0200)   /* sfmfd fn, <cnt>, [sp]! */
-       continue;
-
-      if ((inst & 0xffff8fff) == 0xed6d0103)   /* stfe fn, [sp, #-12]! */
-       continue;
-
-      if ((inst & 0xfffff000) == 0xe24cb000)   /* sub fp, ip, #nn */
-       continue;
-
-      if ((inst & 0xfffff000) == 0xe24dd000)   /* sub sp, sp, #nn */
-       continue;
-
-      if ((inst & 0xffffc000) == 0xe54b0000    /* strb r(0123),[r11,#-nn] */
-         || (inst & 0xffffc0f0) == 0xe14b00b0  /* strh r(0123),[r11,#-nn] */
-         || (inst & 0xffffc000) == 0xe50b0000) /* str  r(0123),[r11,#-nn] */
-       continue;
-
-      if ((inst & 0xffffc000) == 0xe5cd0000    /* strb r(0123),[sp,#nn] */
-         || (inst & 0xffffc0f0) == 0xe1cd00b0  /* strh r(0123),[sp,#nn] */
-         || (inst & 0xffffc000) == 0xe58d0000) /* str  r(0123),[sp,#nn] */
-       continue;
-
-      /* Un-recognized instruction; stop scanning.  */
-      break;
-    }
-
-  return skip_pc;              /* End of prologue.  */
+  else
+    return arm_analyze_prologue (gdbarch, pc, limit_pc, NULL);
 }
 
 /* *INDENT-OFF* */
@@ -1658,6 +1606,30 @@ arm_instruction_changes_pc (uint32_t this_instr)
       }
 }
 
+/* Return 1 if the ARM instruction INSN restores SP in epilogue, 0
+   otherwise.  */
+
+static int
+arm_instruction_restores_sp (unsigned int insn)
+{
+  if (bits (insn, 28, 31) != INST_NV)
+    {
+      if ((insn & 0x0df0f000) == 0x0080d000
+         /* ADD SP (register or immediate).  */
+         || (insn & 0x0df0f000) == 0x0040d000
+         /* SUB SP (register or immediate).  */
+         || (insn & 0x0ffffff0) == 0x01a0d000
+         /* MOV SP.  */
+         || (insn & 0x0fff0000) == 0x08bd0000
+         /* POP (LDMIA).  */
+         || (insn & 0x0fff0000) == 0x049d0000)
+         /* POP of a single register.  */
+       return 1;
+    }
+
+  return 0;
+}
+
 /* Analyze an ARM mode prologue starting at PROLOGUE_START and
    continuing no further than PROLOGUE_END.  If CACHE is non-NULL,
    fill it in.  Return the first address not recognized as a prologue
@@ -1680,7 +1652,6 @@ arm_analyze_prologue (struct gdbarch *gdbarch,
   pv_t regs[ARM_FPS_REGNUM];
   struct pv_area *stack;
   struct cleanup *back_to;
-  int framereg, framesize;
   CORE_ADDR unrecognized_pc = 0;
 
   /* Search the prologue looking for instructions that set up the
@@ -1856,6 +1827,11 @@ arm_analyze_prologue (struct gdbarch *gdbarch,
       else if (arm_instruction_changes_pc (insn))
        /* Don't scan past anything that might change control flow.  */
        break;
+      else if (arm_instruction_restores_sp (insn))
+       {
+         /* Don't scan past the epilogue.  */
+         break;
+       }
       else if ((insn & 0xfe500000) == 0xe8100000       /* ldm */
               && pv_is_register (regs[bits (insn, 16, 19)], ARM_SP_REGNUM))
        /* Ignore block loads from the stack, potentially copying
@@ -1871,33 +1847,42 @@ arm_analyze_prologue (struct gdbarch *gdbarch,
        continue;
       else
        {
-         /* The optimizer might shove anything into the prologue,
-            so we just skip what we don't recognize.  */
+         /* The optimizer might shove anything into the prologue, if
+            we build up cache (cache != NULL) from scanning prologue,
+            we just skip what we don't recognize and scan further to
+            make cache as complete as possible.  However, if we skip
+            prologue, we'll stop immediately on unrecognized
+            instruction.  */
          unrecognized_pc = current_pc;
-         continue;
+         if (cache != NULL)
+           continue;
+         else
+           break;
        }
     }
 
   if (unrecognized_pc == 0)
     unrecognized_pc = current_pc;
 
-  /* The frame size is just the distance from the frame register
-     to the original stack pointer.  */
-  if (pv_is_register (regs[ARM_FP_REGNUM], ARM_SP_REGNUM))
-    {
-      /* Frame pointer is fp.  */
-      framereg = ARM_FP_REGNUM;
-      framesize = -regs[ARM_FP_REGNUM].k;
-    }
-  else
-    {
-      /* Try the stack pointer... this is a bit desperate.  */
-      framereg = ARM_SP_REGNUM;
-      framesize = -regs[ARM_SP_REGNUM].k;
-    }
-
   if (cache)
     {
+      int framereg, framesize;
+
+      /* The frame size is just the distance from the frame register
+        to the original stack pointer.  */
+      if (pv_is_register (regs[ARM_FP_REGNUM], ARM_SP_REGNUM))
+       {
+         /* Frame pointer is fp.  */
+         framereg = ARM_FP_REGNUM;
+         framesize = -regs[ARM_FP_REGNUM].k;
+       }
+      else
+       {
+         /* Try the stack pointer... this is a bit desperate.  */
+         framereg = ARM_SP_REGNUM;
+         framesize = -regs[ARM_SP_REGNUM].k;
+       }
+
       cache->framereg = framereg;
       cache->framesize = framesize;
 
@@ -3344,7 +3329,7 @@ arm_in_function_epilogue_p (struct gdbarch *gdbarch, CORE_ADDR pc)
 {
   enum bfd_endian byte_order_for_code = gdbarch_byte_order_for_code (gdbarch);
   unsigned int insn;
-  int found_return, found_stack_adjust;
+  int found_return;
   CORE_ADDR func_start, func_end;
 
   if (arm_pc_is_thumb (gdbarch, pc))
@@ -3384,28 +3369,8 @@ arm_in_function_epilogue_p (struct gdbarch *gdbarch, CORE_ADDR pc)
   if (pc < func_start + 4)
     return 0;
 
-  found_stack_adjust = 0;
   insn = read_memory_unsigned_integer (pc - 4, 4, byte_order_for_code);
-  if (bits (insn, 28, 31) != INST_NV)
-    {
-      if ((insn & 0x0df0f000) == 0x0080d000)
-       /* ADD SP (register or immediate).  */
-       found_stack_adjust = 1;
-      else if ((insn & 0x0df0f000) == 0x0040d000)
-       /* SUB SP (register or immediate).  */
-       found_stack_adjust = 1;
-      else if ((insn & 0x0ffffff0) == 0x01a0d000)
-       /* MOV SP.  */
-       found_stack_adjust = 1;
-      else if ((insn & 0x0fff0000) == 0x08bd0000)
-       /* POP (LDMIA).  */
-       found_stack_adjust = 1;
-      else if ((insn & 0x0fff0000) == 0x049d0000)
-       /* POP of a single register.  */
-       found_stack_adjust = 1;
-    }
-
-  if (found_stack_adjust)
+  if (arm_instruction_restores_sp (insn))
     return 1;
 
   return 0;
@@ -10003,27 +9968,34 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
                                                        OBJ_ATTR_PROC,
                                                        Tag_ABI_VFP_args))
                        {
-                       case 0:
+                       case AEABI_VFP_args_base:
                          /* "The user intended FP parameter/result
                             passing to conform to AAPCS, base
                             variant".  */
                          fp_model = ARM_FLOAT_SOFT_VFP;
                          break;
-                       case 1:
+                       case AEABI_VFP_args_vfp:
                          /* "The user intended FP parameter/result
                             passing to conform to AAPCS, VFP
                             variant".  */
                          fp_model = ARM_FLOAT_VFP;
                          break;
-                       case 2:
+                       case AEABI_VFP_args_toolchain:
                          /* "The user intended FP parameter/result
                             passing to conform to tool chain-specific
                             conventions" - we don't know any such
                             conventions, so leave it as "auto".  */
                          break;
+                       case AEABI_VFP_args_compatible:
+                         /* "Code is compatible with both the base
+                            and VFP variants; the user did not permit
+                            non-variadic functions to pass FP
+                            parameters/results" - leave it as
+                            "auto".  */
+                         break;
                        default:
                          /* Attribute value not mentioned in the
-                            October 2008 ABI, so leave it as
+                            November 2012 ABI, so leave it as
                             "auto".  */
                          break;
                        }
@@ -13807,7 +13779,7 @@ extract_arm_insn (insn_decode_record *insn_record, uint32_t insn_size)
     return 1;
   insn_record->arm_insn = (uint32_t) extract_unsigned_integer (&buf[0],
                            insn_size, 
-                           gdbarch_byte_order (insn_record->gdbarch));
+                          gdbarch_byte_order_for_code (insn_record->gdbarch));
   return 0;
 }
 
This page took 0.037084 seconds and 4 git commands to generate.