btrace: split record_btrace_step_thread
[deliverable/binutils-gdb.git] / gdb / aarch64-tdep.c
index 85974972608176e942110ae0751c0febc9de160a..9a4eda2f45131d8a8077f8f3efdec277dc59c3bb 100644 (file)
@@ -42,6 +42,8 @@
 #include "user-regs.h"
 #include "language.h"
 #include "infcall.h"
+#include "ax.h"
+#include "ax-gdb.h"
 
 #include "aarch64-tdep.h"
 
@@ -148,11 +150,23 @@ static const char *const aarch64_v_register_names[] =
 /* AArch64 prologue cache structure.  */
 struct aarch64_prologue_cache
 {
+  /* The program counter at the start of the function.  It is used to
+     identify this frame as a prologue frame.  */
+  CORE_ADDR func;
+
+  /* The program counter at the time this frame was created; i.e. where
+     this function was called from.  It is used to identify this frame as a
+     stub frame.  */
+  CORE_ADDR prev_pc;
+
   /* The stack pointer at the time this frame was created; i.e. the
      caller's stack pointer when this function was called.  It is used
      to identify this frame.  */
   CORE_ADDR prev_sp;
 
+  /* Is the target available to read from?  */
+  int available_p;
+
   /* The frame base for this frame is just prev_sp - frame size.
      FRAMESIZE is the distance from the frame pointer to the
      initial stack pointer.  */
@@ -247,10 +261,11 @@ decode_add_sub_imm (CORE_ADDR addr, uint32_t insn, unsigned *rd, unsigned *rn,
        *imm = -*imm;
 
       if (aarch64_debug)
-       fprintf_unfiltered (gdb_stdlog,
-                           "decode: 0x%s 0x%x add x%u, x%u, #%d\n",
-                           core_addr_to_string_nz (addr), insn, *rd, *rn,
-                           *imm);
+       {
+         debug_printf ("decode: 0x%s 0x%x add x%u, x%u, #%d\n",
+                       core_addr_to_string_nz (addr), insn, *rd, *rn,
+                       *imm);
+       }
       return 1;
     }
   return 0;
@@ -272,9 +287,10 @@ decode_adrp (CORE_ADDR addr, uint32_t insn, unsigned *rd)
       *rd = (insn >> 0) & 0x1f;
 
       if (aarch64_debug)
-       fprintf_unfiltered (gdb_stdlog,
-                           "decode: 0x%s 0x%x adrp x%u, #?\n",
-                           core_addr_to_string_nz (addr), insn, *rd);
+       {
+         debug_printf ("decode: 0x%s 0x%x adrp x%u, #?\n",
+                       core_addr_to_string_nz (addr), insn, *rd);
+       }
       return 1;
     }
   return 0;
@@ -285,27 +301,28 @@ decode_adrp (CORE_ADDR addr, uint32_t insn, unsigned *rd)
 
    ADDR specifies the address of the opcode.
    INSN specifies the opcode to test.
-   LINK receives the 'link' bit from the decoded instruction.
+   IS_BL receives the 'op' bit from the decoded instruction.
    OFFSET receives the immediate offset from the decoded instruction.
 
    Return 1 if the opcodes matches and is decoded, otherwise 0.  */
 
 static int
-decode_b (CORE_ADDR addr, uint32_t insn, unsigned *link, int32_t *offset)
+decode_b (CORE_ADDR addr, uint32_t insn, int *is_bl, int32_t *offset)
 {
   /* b  0001 01ii iiii iiii iiii iiii iiii iiii */
   /* bl 1001 01ii iiii iiii iiii iiii iiii iiii */
   if (decode_masked_match (insn, 0x7c000000, 0x14000000))
     {
-      *link = insn >> 31;
+      *is_bl = (insn >> 31) & 0x1;
       *offset = extract_signed_bitfield (insn, 26, 0) << 2;
 
       if (aarch64_debug)
-       fprintf_unfiltered (gdb_stdlog,
-                           "decode: 0x%s 0x%x %s 0x%s\n",
-                           core_addr_to_string_nz (addr), insn,
-                           *link ? "bl" : "b",
-                           core_addr_to_string_nz (addr + *offset));
+       {
+         debug_printf ("decode: 0x%s 0x%x %s 0x%s\n",
+                       core_addr_to_string_nz (addr), insn,
+                       *is_bl ? "bl" : "b",
+                       core_addr_to_string_nz (addr + *offset));
+       }
 
       return 1;
     }
@@ -325,16 +342,18 @@ decode_b (CORE_ADDR addr, uint32_t insn, unsigned *link, int32_t *offset)
 static int
 decode_bcond (CORE_ADDR addr, uint32_t insn, unsigned *cond, int32_t *offset)
 {
-  if (decode_masked_match (insn, 0xfe000000, 0x54000000))
+  /* b.cond  0101 0100 iiii iiii iiii iiii iii0 cccc */
+  if (decode_masked_match (insn, 0xff000010, 0x54000000))
     {
       *cond = (insn >> 0) & 0xf;
       *offset = extract_signed_bitfield (insn, 19, 5) << 2;
 
       if (aarch64_debug)
-       fprintf_unfiltered (gdb_stdlog,
-                           "decode: 0x%s 0x%x b<%u> 0x%s\n",
-                           core_addr_to_string_nz (addr), insn, *cond,
-                           core_addr_to_string_nz (addr + *offset));
+       {
+         debug_printf ("decode: 0x%s 0x%x b<%u> 0x%s\n",
+                       core_addr_to_string_nz (addr), insn, *cond,
+                       core_addr_to_string_nz (addr + *offset));
+       }
       return 1;
     }
   return 0;
@@ -344,27 +363,28 @@ decode_bcond (CORE_ADDR addr, uint32_t insn, unsigned *cond, int32_t *offset)
 
    ADDR specifies the address of the opcode.
    INSN specifies the opcode to test.
-   LINK receives the 'link' bit from the decoded instruction.
+   IS_BLR receives the 'op' bit from the decoded instruction.
    RN receives the 'rn' field from the decoded instruction.
 
    Return 1 if the opcodes matches and is decoded, otherwise 0.  */
 
 static int
-decode_br (CORE_ADDR addr, uint32_t insn, unsigned *link, unsigned *rn)
+decode_br (CORE_ADDR addr, uint32_t insn, int *is_blr, unsigned *rn)
 {
   /*         8   4   0   6   2   8   4   0 */
   /* blr  110101100011111100000000000rrrrr */
   /* br   110101100001111100000000000rrrrr */
   if (decode_masked_match (insn, 0xffdffc1f, 0xd61f0000))
     {
-      *link = (insn >> 21) & 1;
+      *is_blr = (insn >> 21) & 1;
       *rn = (insn >> 5) & 0x1f;
 
       if (aarch64_debug)
-       fprintf_unfiltered (gdb_stdlog,
-                           "decode: 0x%s 0x%x %s 0x%x\n",
-                           core_addr_to_string_nz (addr), insn,
-                           *link ? "blr" : "br", *rn);
+       {
+         debug_printf ("decode: 0x%s 0x%x %s 0x%x\n",
+                       core_addr_to_string_nz (addr), insn,
+                       *is_blr ?  "blr" : "br", *rn);
+       }
 
       return 1;
     }
@@ -376,33 +396,32 @@ decode_br (CORE_ADDR addr, uint32_t insn, unsigned *link, unsigned *rn)
    ADDR specifies the address of the opcode.
    INSN specifies the opcode to test.
    IS64 receives the 'sf' field from the decoded instruction.
-   OP receives the 'op' field from the decoded instruction.
+   IS_CBNZ receives the 'op' field from the decoded instruction.
    RN receives the 'rn' field from the decoded instruction.
    OFFSET receives the 'imm19' field from the decoded instruction.
 
    Return 1 if the opcodes matches and is decoded, otherwise 0.  */
 
 static int
-decode_cb (CORE_ADDR addr,
-          uint32_t insn, int *is64, unsigned *op, unsigned *rn,
-          int32_t *offset)
+decode_cb (CORE_ADDR addr, uint32_t insn, int *is64, int *is_cbnz,
+          unsigned *rn, int32_t *offset)
 {
+  /* cbz  T011 010o iiii iiii iiii iiii iiir rrrr */
+  /* cbnz T011 010o iiii iiii iiii iiii iiir rrrr */
   if (decode_masked_match (insn, 0x7e000000, 0x34000000))
     {
-      /* cbz  T011 010o iiii iiii iiii iiii iiir rrrr */
-      /* cbnz T011 010o iiii iiii iiii iiii iiir rrrr */
-
       *rn = (insn >> 0) & 0x1f;
       *is64 = (insn >> 31) & 0x1;
-      *op = (insn >> 24) & 0x1;
+      *is_cbnz = (insn >> 24) & 0x1;
       *offset = extract_signed_bitfield (insn, 19, 5) << 2;
 
       if (aarch64_debug)
-       fprintf_unfiltered (gdb_stdlog,
-                           "decode: 0x%s 0x%x %s 0x%s\n",
-                           core_addr_to_string_nz (addr), insn,
-                           *op ? "cbnz" : "cbz",
-                           core_addr_to_string_nz (addr + *offset));
+       {
+         debug_printf ("decode: 0x%s 0x%x %s 0x%s\n",
+                       core_addr_to_string_nz (addr), insn,
+                       *is_cbnz ? "cbnz" : "cbz",
+                       core_addr_to_string_nz (addr + *offset));
+       }
       return 1;
     }
   return 0;
@@ -422,8 +441,10 @@ decode_eret (CORE_ADDR addr, uint32_t insn)
   if (insn == 0xd69f03e0)
     {
       if (aarch64_debug)
-       fprintf_unfiltered (gdb_stdlog, "decode: 0x%s 0x%x eret\n",
-                           core_addr_to_string_nz (addr), insn);
+       {
+         debug_printf ("decode: 0x%s 0x%x eret\n",
+                       core_addr_to_string_nz (addr), insn);
+       }
       return 1;
     }
   return 0;
@@ -445,9 +466,10 @@ decode_movz (CORE_ADDR addr, uint32_t insn, unsigned *rd)
       *rd = (insn >> 0) & 0x1f;
 
       if (aarch64_debug)
-       fprintf_unfiltered (gdb_stdlog,
-                           "decode: 0x%s 0x%x movz x%u, #?\n",
-                           core_addr_to_string_nz (addr), insn, *rd);
+       {
+         debug_printf ("decode: 0x%s 0x%x movz x%u, #?\n",
+                       core_addr_to_string_nz (addr), insn, *rd);
+       }
       return 1;
     }
   return 0;
@@ -478,10 +500,11 @@ decode_orr_shifted_register_x (CORE_ADDR addr,
       *imm = (insn >> 10) & 0x3f;
 
       if (aarch64_debug)
-       fprintf_unfiltered (gdb_stdlog,
-                           "decode: 0x%s 0x%x orr x%u, x%u, x%u, #%u\n",
-                           core_addr_to_string_nz (addr), insn, *rd,
-                           *rn, *rm, *imm);
+       {
+         debug_printf ("decode: 0x%s 0x%x orr x%u, x%u, x%u, #%u\n",
+                       core_addr_to_string_nz (addr), insn, *rd, *rn,
+                       *rm, *imm);
+       }
       return 1;
     }
   return 0;
@@ -502,9 +525,10 @@ decode_ret (CORE_ADDR addr, uint32_t insn, unsigned *rn)
     {
       *rn = (insn >> 5) & 0x1f;
       if (aarch64_debug)
-       fprintf_unfiltered (gdb_stdlog,
-                           "decode: 0x%s 0x%x ret x%u\n",
-                           core_addr_to_string_nz (addr), insn, *rn);
+       {
+         debug_printf ("decode: 0x%s 0x%x ret x%u\n",
+                       core_addr_to_string_nz (addr), insn, *rn);
+       }
       return 1;
     }
   return 0;
@@ -536,10 +560,11 @@ decode_stp_offset (CORE_ADDR addr,
       *imm <<= 3;
 
       if (aarch64_debug)
-       fprintf_unfiltered (gdb_stdlog,
-                           "decode: 0x%s 0x%x stp x%u, x%u, [x%u + #%d]\n",
-                           core_addr_to_string_nz (addr), insn,
-                           *rt1, *rt2, *rn, *imm);
+       {
+         debug_printf ("decode: 0x%s 0x%x stp x%u, x%u, [x%u + #%d]\n",
+                       core_addr_to_string_nz (addr), insn, *rt1, *rt2,
+                       *rn, *imm);
+       }
       return 1;
     }
   return 0;
@@ -572,10 +597,11 @@ decode_stp_offset_wb (CORE_ADDR addr,
       *imm <<= 3;
 
       if (aarch64_debug)
-       fprintf_unfiltered (gdb_stdlog,
-                           "decode: 0x%s 0x%x stp x%u, x%u, [x%u + #%d]!\n",
-                           core_addr_to_string_nz (addr), insn,
-                           *rt1, *rt2, *rn, *imm);
+       {
+         debug_printf ("decode: 0x%s 0x%x stp x%u, x%u, [x%u + #%d]!\n",
+                       core_addr_to_string_nz (addr), insn, *rt1, *rt2,
+                       *rn, *imm);
+       }
       return 1;
     }
   return 0;
@@ -605,20 +631,21 @@ decode_stur (CORE_ADDR addr, uint32_t insn, int *is64, unsigned *rt,
       *imm = extract_signed_bitfield (insn, 9, 12);
 
       if (aarch64_debug)
-       fprintf_unfiltered (gdb_stdlog,
-                           "decode: 0x%s 0x%x stur %c%u, [x%u + #%d]\n",
-                           core_addr_to_string_nz (addr), insn,
-                           *is64 ? 'x' : 'w', *rt, *rn, *imm);
+       {
+         debug_printf ("decode: 0x%s 0x%x stur %c%u, [x%u + #%d]\n",
+                       core_addr_to_string_nz (addr), insn,
+                       *is64 ? 'x' : 'w', *rt, *rn, *imm);
+       }
       return 1;
     }
   return 0;
 }
 
-/* Decode an opcode if it represents a TB or TBNZ instruction.
+/* Decode an opcode if it represents a TBZ or TBNZ instruction.
 
    ADDR specifies the address of the opcode.
    INSN specifies the opcode to test.
-   OP receives the 'op' field from the decoded instruction.
+   IS_TBNZ receives the 'op' field from the decoded instruction.
    BIT receives the bit position field from the decoded instruction.
    RT receives 'rt' field from the decoded instruction.
    IMM receives 'imm' field from the decoded instruction.
@@ -626,26 +653,25 @@ decode_stur (CORE_ADDR addr, uint32_t insn, int *is64, unsigned *rt,
    Return 1 if the opcodes matches and is decoded, otherwise 0.  */
 
 static int
-decode_tb (CORE_ADDR addr,
-          uint32_t insn, unsigned *op, unsigned *bit, unsigned *rt,
-          int32_t *imm)
+decode_tb (CORE_ADDR addr, uint32_t insn, int *is_tbnz, unsigned *bit,
+          unsigned *rt, int32_t *imm)
 {
+  /* tbz  b011 0110 bbbb biii iiii iiii iiir rrrr */
+  /* tbnz B011 0111 bbbb biii iiii iiii iiir rrrr */
   if (decode_masked_match (insn, 0x7e000000, 0x36000000))
     {
-      /* tbz  b011 0110 bbbb biii iiii iiii iiir rrrr */
-      /* tbnz B011 0111 bbbb biii iiii iiii iiir rrrr */
-
       *rt = (insn >> 0) & 0x1f;
-      *op = insn & (1 << 24);
+      *is_tbnz = (insn >> 24) & 0x1;
       *bit = ((insn >> (31 - 4)) & 0x20) | ((insn >> 19) & 0x1f);
       *imm = extract_signed_bitfield (insn, 14, 5) << 2;
 
       if (aarch64_debug)
-       fprintf_unfiltered (gdb_stdlog,
-                           "decode: 0x%s 0x%x %s x%u, #%u, 0x%s\n",
-                           core_addr_to_string_nz (addr), insn,
-                           *op ? "tbnz" : "tbz", *rt, *bit,
-                           core_addr_to_string_nz (addr + *imm));
+       {
+         debug_printf ("decode: 0x%s 0x%x %s x%u, #%u, 0x%s\n",
+                       core_addr_to_string_nz (addr), insn,
+                       *is_tbnz ? "tbnz" : "tbz", *rt, *bit,
+                       core_addr_to_string_nz (addr + *imm));
+       }
       return 1;
     }
   return 0;
@@ -684,8 +710,9 @@ aarch64_analyze_prologue (struct gdbarch *gdbarch,
       int32_t imm;
       unsigned cond;
       int is64;
-      unsigned is_link;
-      unsigned op;
+      int is_link;
+      int is_cbnz;
+      int is_tbnz;
       unsigned bit;
       int32_t offset;
 
@@ -710,7 +737,7 @@ aarch64_analyze_prologue (struct gdbarch *gdbarch,
          /* Stop analysis on branch.  */
          break;
        }
-      else if (decode_cb (start, insn, &is64, &op, &rn, &offset))
+      else if (decode_cb (start, insn, &is64, &is_cbnz, &rn, &offset))
        {
          /* Stop analysis on branch.  */
          break;
@@ -730,12 +757,11 @@ aarch64_analyze_prologue (struct gdbarch *gdbarch,
          else
            {
              if (aarch64_debug)
-               fprintf_unfiltered
-                 (gdb_stdlog,
-                  "aarch64: prologue analysis gave up addr=0x%s "
-                  "opcode=0x%x (orr x register)\n",
-                  core_addr_to_string_nz (start),
-                  insn);
+               {
+                 debug_printf ("aarch64: prologue analysis gave up "
+                               "addr=0x%s opcode=0x%x (orr x register)\n",
+                               core_addr_to_string_nz (start), insn);
+               }
              break;
            }
        }
@@ -786,7 +812,7 @@ aarch64_analyze_prologue (struct gdbarch *gdbarch,
                         regs[rt2]);
          regs[rn] = pv_add_constant (regs[rn], imm);
        }
-      else if (decode_tb (start, insn, &op, &bit, &rn, &offset))
+      else if (decode_tb (start, insn, &is_tbnz, &bit, &rn, &offset))
        {
          /* Stop analysis on branch.  */
          break;
@@ -794,10 +820,11 @@ aarch64_analyze_prologue (struct gdbarch *gdbarch,
       else
        {
          if (aarch64_debug)
-           fprintf_unfiltered (gdb_stdlog,
-                               "aarch64: prologue analysis gave up addr=0x%s"
-                               " opcode=0x%x\n",
-                               core_addr_to_string_nz (start), insn);
+           {
+             debug_printf ("aarch64: prologue analysis gave up addr=0x%s"
+                           " opcode=0x%x\n",
+                           core_addr_to_string_nz (start), insn);
+           }
          break;
        }
     }
@@ -889,6 +916,8 @@ aarch64_scan_prologue (struct frame_info *this_frame,
   CORE_ADDR prev_pc = get_frame_pc (this_frame);
   struct gdbarch *gdbarch = get_frame_arch (this_frame);
 
+  cache->prev_pc = prev_pc;
+
   /* Assume we do not find a frame.  */
   cache->framereg = -1;
   cache->framesize = 0;
@@ -930,27 +959,25 @@ aarch64_scan_prologue (struct frame_info *this_frame,
     }
 }
 
-/* Allocate an aarch64_prologue_cache and fill it with information
-   about the prologue of *THIS_FRAME.  */
+/* Fill in *CACHE with information about the prologue of *THIS_FRAME.  This
+   function may throw an exception if the inferior's registers or memory is
+   not available.  */
 
-static struct aarch64_prologue_cache *
-aarch64_make_prologue_cache (struct frame_info *this_frame)
+static void
+aarch64_make_prologue_cache_1 (struct frame_info *this_frame,
+                              struct aarch64_prologue_cache *cache)
 {
-  struct aarch64_prologue_cache *cache;
   CORE_ADDR unwound_fp;
   int reg;
 
-  cache = FRAME_OBSTACK_ZALLOC (struct aarch64_prologue_cache);
-  cache->saved_regs = trad_frame_alloc_saved_regs (this_frame);
-
   aarch64_scan_prologue (this_frame, cache);
 
   if (cache->framereg == -1)
-    return cache;
+    return;
 
   unwound_fp = get_frame_register_unsigned (this_frame, cache->framereg);
   if (unwound_fp == 0)
-    return cache;
+    return;
 
   cache->prev_sp = unwound_fp + cache->framesize;
 
@@ -960,9 +987,65 @@ aarch64_make_prologue_cache (struct frame_info *this_frame)
     if (trad_frame_addr_p (cache->saved_regs, reg))
       cache->saved_regs[reg].addr += cache->prev_sp;
 
+  cache->func = get_frame_func (this_frame);
+
+  cache->available_p = 1;
+}
+
+/* Allocate and fill in *THIS_CACHE with information about the prologue of
+   *THIS_FRAME.  Do not do this is if *THIS_CACHE was already allocated.
+   Return a pointer to the current aarch64_prologue_cache in
+   *THIS_CACHE.  */
+
+static struct aarch64_prologue_cache *
+aarch64_make_prologue_cache (struct frame_info *this_frame, void **this_cache)
+{
+  struct aarch64_prologue_cache *cache;
+
+  if (*this_cache != NULL)
+    return *this_cache;
+
+  cache = FRAME_OBSTACK_ZALLOC (struct aarch64_prologue_cache);
+  cache->saved_regs = trad_frame_alloc_saved_regs (this_frame);
+  *this_cache = cache;
+
+  TRY
+    {
+      aarch64_make_prologue_cache_1 (this_frame, cache);
+    }
+  CATCH (ex, RETURN_MASK_ERROR)
+    {
+      if (ex.error != NOT_AVAILABLE_ERROR)
+       throw_exception (ex);
+    }
+  END_CATCH
+
   return cache;
 }
 
+/* Implement the "stop_reason" frame_unwind method.  */
+
+static enum unwind_stop_reason
+aarch64_prologue_frame_unwind_stop_reason (struct frame_info *this_frame,
+                                          void **this_cache)
+{
+  struct aarch64_prologue_cache *cache
+    = aarch64_make_prologue_cache (this_frame, this_cache);
+
+  if (!cache->available_p)
+    return UNWIND_UNAVAILABLE;
+
+  /* Halt the backtrace at "_start".  */
+  if (cache->prev_pc <= gdbarch_tdep (get_frame_arch (this_frame))->lowest_pc)
+    return UNWIND_OUTERMOST;
+
+  /* We've hit a wall, stop.  */
+  if (cache->prev_sp == 0)
+    return UNWIND_OUTERMOST;
+
+  return UNWIND_NO_REASON;
+}
+
 /* Our frame ID for a normal frame is the current function's starting
    PC and the caller's SP when we were called.  */
 
@@ -970,26 +1053,13 @@ static void
 aarch64_prologue_this_id (struct frame_info *this_frame,
                          void **this_cache, struct frame_id *this_id)
 {
-  struct aarch64_prologue_cache *cache;
-  struct frame_id id;
-  CORE_ADDR pc, func;
-
-  if (*this_cache == NULL)
-    *this_cache = aarch64_make_prologue_cache (this_frame);
-  cache = *this_cache;
-
-  /* This is meant to halt the backtrace at "_start".  */
-  pc = get_frame_pc (this_frame);
-  if (pc <= gdbarch_tdep (get_frame_arch (this_frame))->lowest_pc)
-    return;
-
-  /* If we've hit a wall, stop.  */
-  if (cache->prev_sp == 0)
-    return;
+  struct aarch64_prologue_cache *cache
+    = aarch64_make_prologue_cache (this_frame, this_cache);
 
-  func = get_frame_func (this_frame);
-  id = frame_id_build (cache->prev_sp, func);
-  *this_id = id;
+  if (!cache->available_p)
+    *this_id = frame_id_build_unavailable_stack (cache->func);
+  else
+    *this_id = frame_id_build (cache->prev_sp, cache->func);
 }
 
 /* Implement the "prev_register" frame_unwind method.  */
@@ -999,11 +1069,8 @@ aarch64_prologue_prev_register (struct frame_info *this_frame,
                                void **this_cache, int prev_regnum)
 {
   struct gdbarch *gdbarch = get_frame_arch (this_frame);
-  struct aarch64_prologue_cache *cache;
-
-  if (*this_cache == NULL)
-    *this_cache = aarch64_make_prologue_cache (this_frame);
-  cache = *this_cache;
+  struct aarch64_prologue_cache *cache
+    = aarch64_make_prologue_cache (this_frame, this_cache);
 
   /* If we are asked to unwind the PC, then we need to return the LR
      instead.  The prologue may save PC, but it will point into this
@@ -1043,45 +1110,75 @@ aarch64_prologue_prev_register (struct frame_info *this_frame,
 struct frame_unwind aarch64_prologue_unwind =
 {
   NORMAL_FRAME,
-  default_frame_unwind_stop_reason,
+  aarch64_prologue_frame_unwind_stop_reason,
   aarch64_prologue_this_id,
   aarch64_prologue_prev_register,
   NULL,
   default_frame_sniffer
 };
 
-/* Allocate an aarch64_prologue_cache and fill it with information
-   about the prologue of *THIS_FRAME.  */
+/* Allocate and fill in *THIS_CACHE with information about the prologue of
+   *THIS_FRAME.  Do not do this is if *THIS_CACHE was already allocated.
+   Return a pointer to the current aarch64_prologue_cache in
+   *THIS_CACHE.  */
 
 static struct aarch64_prologue_cache *
-aarch64_make_stub_cache (struct frame_info *this_frame)
+aarch64_make_stub_cache (struct frame_info *this_frame, void **this_cache)
 {
-  int reg;
   struct aarch64_prologue_cache *cache;
-  CORE_ADDR unwound_fp;
+
+  if (*this_cache != NULL)
+    return *this_cache;
 
   cache = FRAME_OBSTACK_ZALLOC (struct aarch64_prologue_cache);
   cache->saved_regs = trad_frame_alloc_saved_regs (this_frame);
+  *this_cache = cache;
 
-  cache->prev_sp
-    = get_frame_register_unsigned (this_frame, AARCH64_SP_REGNUM);
+  TRY
+    {
+      cache->prev_sp = get_frame_register_unsigned (this_frame,
+                                                   AARCH64_SP_REGNUM);
+      cache->prev_pc = get_frame_pc (this_frame);
+      cache->available_p = 1;
+    }
+  CATCH (ex, RETURN_MASK_ERROR)
+    {
+      if (ex.error != NOT_AVAILABLE_ERROR)
+       throw_exception (ex);
+    }
+  END_CATCH
 
   return cache;
 }
 
+/* Implement the "stop_reason" frame_unwind method.  */
+
+static enum unwind_stop_reason
+aarch64_stub_frame_unwind_stop_reason (struct frame_info *this_frame,
+                                      void **this_cache)
+{
+  struct aarch64_prologue_cache *cache
+    = aarch64_make_stub_cache (this_frame, this_cache);
+
+  if (!cache->available_p)
+    return UNWIND_UNAVAILABLE;
+
+  return UNWIND_NO_REASON;
+}
+
 /* Our frame ID for a stub frame is the current SP and LR.  */
 
 static void
 aarch64_stub_this_id (struct frame_info *this_frame,
                      void **this_cache, struct frame_id *this_id)
 {
-  struct aarch64_prologue_cache *cache;
+  struct aarch64_prologue_cache *cache
+    = aarch64_make_stub_cache (this_frame, this_cache);
 
-  if (*this_cache == NULL)
-    *this_cache = aarch64_make_stub_cache (this_frame);
-  cache = *this_cache;
-
-  *this_id = frame_id_build (cache->prev_sp, get_frame_pc (this_frame));
+  if (cache->available_p)
+    *this_id = frame_id_build (cache->prev_sp, cache->prev_pc);
+  else
+    *this_id = frame_id_build_unavailable_stack (cache->prev_pc);
 }
 
 /* Implement the "sniffer" frame_unwind method.  */
@@ -1108,7 +1205,7 @@ aarch64_stub_unwind_sniffer (const struct frame_unwind *self,
 struct frame_unwind aarch64_stub_unwind =
 {
   NORMAL_FRAME,
-  default_frame_unwind_stop_reason,
+  aarch64_stub_frame_unwind_stop_reason,
   aarch64_stub_this_id,
   aarch64_prologue_prev_register,
   NULL,
@@ -1120,11 +1217,8 @@ struct frame_unwind aarch64_stub_unwind =
 static CORE_ADDR
 aarch64_normal_frame_base (struct frame_info *this_frame, void **this_cache)
 {
-  struct aarch64_prologue_cache *cache;
-
-  if (*this_cache == NULL)
-    *this_cache = aarch64_make_prologue_cache (this_frame);
-  cache = *this_cache;
+  struct aarch64_prologue_cache *cache
+    = aarch64_make_prologue_cache (this_frame, this_cache);
 
   return cache->prev_sp - cache->framesize;
 }
@@ -1374,10 +1468,11 @@ pass_in_x (struct gdbarch *gdbarch, struct regcache *regcache,
        regval <<= ((X_REGISTER_SIZE - partial_len) * TARGET_CHAR_BIT);
 
       if (aarch64_debug)
-       fprintf_unfiltered (gdb_stdlog, "arg %d in %s = 0x%s\n",
-                           info->argnum,
-                           gdbarch_register_name (gdbarch, regnum),
-                           phex (regval, X_REGISTER_SIZE));
+       {
+         debug_printf ("arg %d in %s = 0x%s\n", info->argnum,
+                       gdbarch_register_name (gdbarch, regnum),
+                       phex (regval, X_REGISTER_SIZE));
+       }
       regcache_cooked_write_unsigned (regcache, regnum, regval);
       len -= partial_len;
       buf += partial_len;
@@ -1406,9 +1501,10 @@ pass_in_v (struct gdbarch *gdbarch,
 
       regcache_cooked_write (regcache, regnum, buf);
       if (aarch64_debug)
-       fprintf_unfiltered (gdb_stdlog, "arg %d in %s\n",
-                           info->argnum,
-                           gdbarch_register_name (gdbarch, regnum));
+       {
+         debug_printf ("arg %d in %s\n", info->argnum,
+                       gdbarch_register_name (gdbarch, regnum));
+       }
       return 1;
     }
   info->nsrn = 8;
@@ -1438,8 +1534,10 @@ pass_on_stack (struct aarch64_call_info *info, struct type *type,
     align = 16;
 
   if (aarch64_debug)
-    fprintf_unfiltered (gdb_stdlog, "arg %d len=%d @ sp + %d\n",
-                       info->argnum, len, info->nsaa);
+    {
+      debug_printf ("arg %d len=%d @ sp + %d\n", info->argnum, len,
+                   info->nsaa);
+    }
 
   item.len = len;
   item.data = buf;
@@ -1574,11 +1672,12 @@ aarch64_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
   if (struct_return || lang_struct_return)
     {
       if (aarch64_debug)
-       fprintf_unfiltered (gdb_stdlog, "struct return in %s = 0x%s\n",
-                           gdbarch_register_name
-                           (gdbarch,
-                            AARCH64_STRUCT_RETURN_REGNUM),
-                           paddress (gdbarch, struct_addr));
+       {
+         debug_printf ("struct return in %s = 0x%s\n",
+                       gdbarch_register_name (gdbarch,
+                                              AARCH64_STRUCT_RETURN_REGNUM),
+                       paddress (gdbarch, struct_addr));
+       }
       regcache_cooked_write_unsigned (regcache, AARCH64_STRUCT_RETURN_REGNUM,
                                      struct_addr);
     }
@@ -1983,10 +2082,11 @@ aarch64_extract_return_value (struct type *type, struct regcache *regs,
          bfd_byte buf[X_REGISTER_SIZE];
 
          if (aarch64_debug)
-           fprintf_unfiltered (gdb_stdlog,
-                               "read HFA return value element %d from %s\n",
-                               i + 1,
-                               gdbarch_register_name (gdbarch, regno));
+           {
+             debug_printf ("read HFA return value element %d from %s\n",
+                           i + 1,
+                           gdbarch_register_name (gdbarch, regno));
+           }
          regcache_cooked_read (regs, regno, buf);
 
          memcpy (valbuf, buf, len);
@@ -2023,7 +2123,7 @@ aarch64_return_in_memory (struct gdbarch *gdbarch, struct type *type)
   int nRc;
   enum type_code code;
 
-  CHECK_TYPEDEF (type);
+  type = check_typedef (type);
 
   /* In the AArch64 ABI, "integer" like aggregate types are returned
      in registers.  For an aggregate type to be integer like, its size
@@ -2111,10 +2211,11 @@ aarch64_store_return_value (struct type *type, struct regcache *regs,
          bfd_byte tmpbuf[MAX_REGISTER_SIZE];
 
          if (aarch64_debug)
-           fprintf_unfiltered (gdb_stdlog,
-                               "write HFA return value element %d to %s\n",
-                               i + 1,
-                               gdbarch_register_name (gdbarch, regno));
+           {
+             debug_printf ("write HFA return value element %d to %s\n",
+                           i + 1,
+                           gdbarch_register_name (gdbarch, regno));
+           }
 
          memcpy (tmpbuf, valbuf, len);
          regcache_cooked_write (regs, regno, tmpbuf);
@@ -2157,7 +2258,7 @@ aarch64_return_value (struct gdbarch *gdbarch, struct value *func_value,
       if (aarch64_return_in_memory (gdbarch, valtype))
        {
          if (aarch64_debug)
-           fprintf_unfiltered (gdb_stdlog, "return value in memory\n");
+           debug_printf ("return value in memory\n");
          return RETURN_VALUE_STRUCT_CONVENTION;
        }
     }
@@ -2169,7 +2270,7 @@ aarch64_return_value (struct gdbarch *gdbarch, struct value *func_value,
     aarch64_extract_return_value (valtype, regcache, readbuf);
 
   if (aarch64_debug)
-    fprintf_unfiltered (gdb_stdlog, "return value in registers\n");
+    debug_printf ("return value in registers\n");
 
   return RETURN_VALUE_REGISTER_CONVENTION;
 }
@@ -2194,6 +2295,18 @@ aarch64_get_longjmp_target (struct frame_info *frame, CORE_ADDR *pc)
   *pc = extract_unsigned_integer (buf, X_REGISTER_SIZE, byte_order);
   return 1;
 }
+
+/* Implement the "gen_return_address" gdbarch method.  */
+
+static void
+aarch64_gen_return_address (struct gdbarch *gdbarch,
+                           struct agent_expr *ax, struct axs_value *value,
+                           CORE_ADDR scope)
+{
+  value->type = register_type (gdbarch, AARCH64_LR_REGNUM);
+  value->kind = axs_lvalue_register;
+  value->u.reg = AARCH64_LR_REGNUM;
+}
 \f
 
 /* Return the pseudo register name corresponding to register regnum.  */
@@ -2389,7 +2502,11 @@ aarch64_pseudo_read_value (struct gdbarch *gdbarch,
 
       v_regnum = AARCH64_V0_REGNUM + regnum - AARCH64_S0_REGNUM;
       status = regcache_raw_read (regcache, v_regnum, reg_buf);
-      memcpy (buf, reg_buf, S_REGISTER_SIZE);
+      if (status != REG_VALID)
+       mark_value_bytes_unavailable (result_value, 0,
+                                     TYPE_LENGTH (value_type (result_value)));
+      else
+       memcpy (buf, reg_buf, S_REGISTER_SIZE);
       return result_value;
     }
 
@@ -2677,7 +2794,7 @@ aarch64_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
       return best_arch->gdbarch;
     }
 
-  tdep = xcalloc (1, sizeof (struct gdbarch_tdep));
+  tdep = XCNEW (struct gdbarch_tdep);
   gdbarch = gdbarch_alloc (&info, tdep);
 
   /* This should be low enough for everything.  */
@@ -2763,6 +2880,8 @@ aarch64_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   if (tdep->jb_pc >= 0)
     set_gdbarch_get_longjmp_target (gdbarch, aarch64_get_longjmp_target);
 
+  set_gdbarch_gen_return_address (gdbarch, aarch64_gen_return_address);
+
   tdesc_use_registers (gdbarch, tdesc, tdesc_data);
 
   /* Add standard register aliases.  */
@@ -3006,9 +3125,9 @@ aarch64_record_branch_except_sys (insn_decode_record *aarch64_insn_r)
       /* Exception generation instructions. */
       if (insn_bits24_27 == 0x04)
        {
-         if (!bits (aarch64_insn_r->aarch64_insn, 2, 4) &&
-             !bits (aarch64_insn_r->aarch64_insn, 21, 23) &&
-             bits (aarch64_insn_r->aarch64_insn, 0, 1) == 0x01)
+         if (!bits (aarch64_insn_r->aarch64_insn, 2, 4)
+             && !bits (aarch64_insn_r->aarch64_insn, 21, 23)
+             && bits (aarch64_insn_r->aarch64_insn, 0, 1) == 0x01)
            {
              ULONGEST svc_number;
 
@@ -3088,10 +3207,7 @@ aarch64_record_asimd_load_store (insn_decode_record *aarch64_insn_r)
   regcache_raw_read_unsigned (aarch64_insn_r->regcache, reg_rn, &address);
 
   if (record_debug)
-    {
-      fprintf_unfiltered (gdb_stdlog,
-                         "Process record: Advanced SIMD load/store\n");
-    }
+    debug_printf ("Process record: Advanced SIMD load/store\n");
 
   /* Load/store single structure.  */
   if (bit (aarch64_insn_r->aarch64_insn, 24))
@@ -3265,10 +3381,7 @@ aarch64_record_load_store (insn_decode_record *aarch64_insn_r)
   if (insn_bits24_27 == 0x08 && insn_bits28_29 == 0x00)
     {
       if (record_debug)
-       {
-         fprintf_unfiltered (gdb_stdlog,
-                             "Process record: load/store exclusive\n");
-       }
+       debug_printf ("Process record: load/store exclusive\n");
 
       if (ld_flag)
        {
@@ -3303,10 +3416,7 @@ aarch64_record_load_store (insn_decode_record *aarch64_insn_r)
   else if ((insn_bits24_27 & 0x0b) == 0x08 && insn_bits28_29 == 0x01)
     {
       if (record_debug)
-       {
-         fprintf_unfiltered (gdb_stdlog,
-                             "Process record: load register (literal)\n");
-       }
+       debug_printf ("Process record: load register (literal)\n");
       if (vector_flag)
         record_buf[0] = reg_rt + AARCH64_V0_REGNUM;
       else
@@ -3317,10 +3427,7 @@ aarch64_record_load_store (insn_decode_record *aarch64_insn_r)
   else if ((insn_bits24_27 & 0x0a) == 0x08 && insn_bits28_29 == 0x02)
     {
       if (record_debug)
-       {
-         fprintf_unfiltered (gdb_stdlog,
-                             "Process record: load/store pair\n");
-       }
+       debug_printf ("Process record: load/store pair\n");
 
       if (ld_flag)
         {
@@ -3381,10 +3488,9 @@ aarch64_record_load_store (insn_decode_record *aarch64_insn_r)
 
       if (record_debug)
        {
-         fprintf_unfiltered (gdb_stdlog,
-                             "Process record: load/store (unsigned immediate):"
-                             " size %x V %d opc %x\n", size_bits, vector_flag,
-                             opc);
+         debug_printf ("Process record: load/store (unsigned immediate):"
+                       " size %x V %d opc %x\n", size_bits, vector_flag,
+                       opc);
        }
 
       if (!ld_flag)
@@ -3410,14 +3516,11 @@ aarch64_record_load_store (insn_decode_record *aarch64_insn_r)
         }
     }
   /* Load/store register (register offset) instructions.  */
-  else if ((insn_bits24_27 & 0x0b) == 0x08 && insn_bits28_29 == 0x03 &&
-          insn_bits10_11 == 0x02 && insn_bit21)
+  else if ((insn_bits24_27 & 0x0b) == 0x08 && insn_bits28_29 == 0x03
+          && insn_bits10_11 == 0x02 && insn_bit21)
     {
       if (record_debug)
-       {
-         fprintf_unfiltered (gdb_stdlog,
-                             "Process record: load/store (register offset)\n");
-       }
+       debug_printf ("Process record: load/store (register offset)\n");
       opc = bits (aarch64_insn_r->aarch64_insn, 22, 23);
       if (!(opc >> 1))
         if (opc & 0x01)
@@ -3457,13 +3560,13 @@ aarch64_record_load_store (insn_decode_record *aarch64_insn_r)
         }
     }
   /* Load/store register (immediate and unprivileged) instructions.  */
-  else if ((insn_bits24_27 & 0x0b) == 0x08 && insn_bits28_29 == 0x03 &&
-          !insn_bit21)
+  else if ((insn_bits24_27 & 0x0b) == 0x08 && insn_bits28_29 == 0x03
+          && !insn_bit21)
     {
       if (record_debug)
        {
-         fprintf_unfiltered (gdb_stdlog,
-                             "Process record: load/store (immediate and unprivileged)\n");
+         debug_printf ("Process record: load/store "
+                       "(immediate and unprivileged)\n");
        }
       opc = bits (aarch64_insn_r->aarch64_insn, 22, 23);
       if (!(opc >> 1))
@@ -3539,10 +3642,7 @@ aarch64_record_data_proc_simd_fp (insn_decode_record *aarch64_insn_r)
   insn_bit21 = bit (aarch64_insn_r->aarch64_insn, 21);
 
   if (record_debug)
-    {
-      fprintf_unfiltered (gdb_stdlog,
-                         "Process record: data processing SIMD/FP: ");
-    }
+    debug_printf ("Process record: data processing SIMD/FP: ");
 
   if ((insn_bits28_31 & 0x05) == 0x01 && insn_bits24_27 == 0x0e)
     {
@@ -3550,7 +3650,7 @@ aarch64_record_data_proc_simd_fp (insn_decode_record *aarch64_insn_r)
       if (!insn_bit21)
        {
          if (record_debug)
-           fprintf_unfiltered (gdb_stdlog, "FP - fixed point conversion");
+           debug_printf ("FP - fixed point conversion");
 
          if ((opcode >> 1) == 0x0 && rmode == 0x03)
            record_buf[0] = reg_rd;
@@ -3561,7 +3661,7 @@ aarch64_record_data_proc_simd_fp (insn_decode_record *aarch64_insn_r)
       else if (insn_bits10_11 == 0x01)
        {
          if (record_debug)
-           fprintf_unfiltered (gdb_stdlog, "FP - conditional compare");
+           debug_printf ("FP - conditional compare");
 
          record_buf[0] = AARCH64_CPSR_REGNUM;
        }
@@ -3570,7 +3670,7 @@ aarch64_record_data_proc_simd_fp (insn_decode_record *aarch64_insn_r)
       else if (insn_bits10_11 == 0x02 || insn_bits10_11 == 0x03)
        {
          if (record_debug)
-           fprintf_unfiltered (gdb_stdlog, "FP - DP (2-source)");
+           debug_printf ("FP - DP (2-source)");
 
          record_buf[0] = reg_rd + AARCH64_V0_REGNUM;
        }
@@ -3581,24 +3681,24 @@ aarch64_record_data_proc_simd_fp (insn_decode_record *aarch64_insn_r)
              || (insn_bits12_15 & 0x07) == 0x04)
            {
              if (record_debug)
-               fprintf_unfiltered (gdb_stdlog, "FP - immediate");
+               debug_printf ("FP - immediate");
              record_buf[0] = reg_rd + AARCH64_V0_REGNUM;
            }
          /* Floating point - compare instructions.  */
          else if ((insn_bits12_15 & 0x03) == 0x02)
            {
              if (record_debug)
-               fprintf_unfiltered (gdb_stdlog, "FP - immediate");
+               debug_printf ("FP - immediate");
              record_buf[0] = AARCH64_CPSR_REGNUM;
            }
          /* Floating point - integer conversions instructions.  */
-         if (insn_bits12_15 == 0x00)
+         else if (insn_bits12_15 == 0x00)
            {
              /* Convert float to integer instruction.  */
              if (!(opcode >> 1) || ((opcode >> 1) == 0x02 && !rmode))
                {
                  if (record_debug)
-                   fprintf_unfiltered (gdb_stdlog, "float to int conversion");
+                   debug_printf ("float to int conversion");
 
                  record_buf[0] = reg_rd + AARCH64_X0_REGNUM;
                }
@@ -3606,7 +3706,7 @@ aarch64_record_data_proc_simd_fp (insn_decode_record *aarch64_insn_r)
              else if ((opcode >> 1) == 0x01 && !rmode)
                {
                  if (record_debug)
-                   fprintf_unfiltered (gdb_stdlog, "int to float conversion");
+                   debug_printf ("int to float conversion");
 
                  record_buf[0] = reg_rd + AARCH64_V0_REGNUM;
                }
@@ -3614,20 +3714,26 @@ aarch64_record_data_proc_simd_fp (insn_decode_record *aarch64_insn_r)
              else if ((opcode >> 1) == 0x03)
                {
                  if (record_debug)
-                   fprintf_unfiltered (gdb_stdlog, "move float to int");
+                   debug_printf ("move float to int");
 
                  if (!(opcode & 0x01))
                    record_buf[0] = reg_rd + AARCH64_X0_REGNUM;
                  else
                    record_buf[0] = reg_rd + AARCH64_V0_REGNUM;
                }
+             else
+               return AARCH64_RECORD_UNKNOWN;
             }
+         else
+           return AARCH64_RECORD_UNKNOWN;
         }
+      else
+       return AARCH64_RECORD_UNKNOWN;
     }
   else if ((insn_bits28_31 & 0x09) == 0x00 && insn_bits24_27 == 0x0e)
     {
       if (record_debug)
-       fprintf_unfiltered (gdb_stdlog, "SIMD copy");
+       debug_printf ("SIMD copy");
 
       /* Advanced SIMD copy instructions.  */
       if (!bits (aarch64_insn_r->aarch64_insn, 21, 23)
@@ -3646,13 +3752,13 @@ aarch64_record_data_proc_simd_fp (insn_decode_record *aarch64_insn_r)
   else
     {
       if (record_debug)
-       fprintf_unfiltered (gdb_stdlog, "all remain");
+       debug_printf ("all remain");
 
       record_buf[0] = reg_rd + AARCH64_V0_REGNUM;
     }
 
   if (record_debug)
-    fprintf_unfiltered (gdb_stdlog, "\n");
+    debug_printf ("\n");
 
   aarch64_insn_r->reg_rec_count++;
   gdb_assert (aarch64_insn_r->reg_rec_count == 1);
This page took 0.037132 seconds and 4 git commands to generate.