Introduce pascal_value_print_inner
[deliverable/binutils-gdb.git] / gdb / aarch64-tdep.c
index 9b6324f0fcf05133f59b7bc4f38ccd383dfb1cf9..216e85d448edc2a2290792ad55ef88e26a1664a2 100644 (file)
@@ -1,6 +1,6 @@
 /* Common target dependent code for GDB on AArch64 systems.
 
-   Copyright (C) 2009-2019 Free Software Foundation, Inc.
+   Copyright (C) 2009-2020 Free Software Foundation, Inc.
    Contributed by ARM Ltd.
 
    This file is part of GDB.
@@ -21,7 +21,6 @@
 #include "defs.h"
 
 #include "frame.h"
-#include "inferior.h"
 #include "gdbcmd.h"
 #include "gdbcore.h"
 #include "dis-asm.h"
 #include "trad-frame.h"
 #include "objfiles.h"
 #include "dwarf2.h"
-#include "dwarf2-frame.h"
+#include "dwarf2/frame.h"
 #include "gdbtypes.h"
 #include "prologue-value.h"
 #include "target-descriptions.h"
 #include "user-regs.h"
-#include "language.h"
-#include "infcall.h"
-#include "ax.h"
 #include "ax-gdb.h"
 #include "gdbsupport/selftest.h"
 
 #include "aarch64-tdep.h"
 #include "aarch64-ravenscar-thread.h"
 
-#include "elf-bfd.h"
-#include "elf/aarch64.h"
-
-#include "gdbsupport/vec.h"
-
 #include "record.h"
 #include "record-full.h"
 #include "arch/aarch64-insn.h"
@@ -273,6 +264,17 @@ aarch64_frame_unmask_lr (struct gdbarch_tdep *tdep,
   return addr;
 }
 
+/* Implement the "get_pc_address_flags" gdbarch method.  */
+
+static std::string
+aarch64_get_pc_address_flags (frame_info *frame, CORE_ADDR pc)
+{
+  if (pc != 0 && get_frame_pc_masked (frame))
+    return "PAC";
+
+  return "";
+}
+
 /* Analyze a prologue, looking for a recognizable stack frame
    and frame pointer.  Scan until we encounter a store that could
    clobber the stack frame unexpectedly, or an unknown instruction.  */
@@ -387,17 +389,16 @@ aarch64_analyze_prologue (struct gdbarch *gdbarch,
        {
          unsigned rt = inst.operands[0].reg.regno;
          unsigned rn = inst.operands[1].addr.base_regno;
-         int is64
-           = (aarch64_get_qualifier_esize (inst.operands[0].qualifier) == 8);
+         int size = aarch64_get_qualifier_esize (inst.operands[0].qualifier);
 
          gdb_assert (aarch64_num_of_operands (inst.opcode) == 2);
          gdb_assert (inst.operands[0].type == AARCH64_OPND_Rt);
          gdb_assert (inst.operands[1].type == AARCH64_OPND_ADDR_SIMM9);
          gdb_assert (!inst.operands[1].addr.offset.is_reg);
 
-         stack.store (pv_add_constant (regs[rn],
-                                       inst.operands[1].addr.offset.imm),
-                      is64 ? 8 : 4, regs[rt]);
+         stack.store
+           (pv_add_constant (regs[rn], inst.operands[1].addr.offset.imm),
+            size, regs[rt]);
        }
       else if ((inst.opcode->iclass == ldstpair_off
                || (inst.opcode->iclass == ldstpair_indexed
@@ -409,6 +410,7 @@ aarch64_analyze_prologue (struct gdbarch *gdbarch,
          unsigned rt2;
          unsigned rn = inst.operands[2].addr.base_regno;
          int32_t imm = inst.operands[2].addr.offset.imm;
+         int size = aarch64_get_qualifier_esize (inst.operands[0].qualifier);
 
          gdb_assert (inst.operands[0].type == AARCH64_OPND_Rt
                      || inst.operands[0].type == AARCH64_OPND_Ft);
@@ -430,17 +432,12 @@ aarch64_analyze_prologue (struct gdbarch *gdbarch,
          rt2 = inst.operands[1].reg.regno;
          if (inst.operands[0].type == AARCH64_OPND_Ft)
            {
-             /* Only bottom 64-bit of each V register (D register) need
-                to be preserved.  */
-             gdb_assert (inst.operands[0].qualifier == AARCH64_OPND_QLF_S_D);
              rt1 += AARCH64_X_REGISTER_COUNT;
              rt2 += AARCH64_X_REGISTER_COUNT;
            }
 
-         stack.store (pv_add_constant (regs[rn], imm), 8,
-                      regs[rt1]);
-         stack.store (pv_add_constant (regs[rn], imm + 8), 8,
-                      regs[rt2]);
+         stack.store (pv_add_constant (regs[rn], imm), size, regs[rt1]);
+         stack.store (pv_add_constant (regs[rn], imm + size), size, regs[rt2]);
 
          if (inst.operands[2].addr.writeback)
            regs[rn] = pv_add_constant (regs[rn], imm);
@@ -457,21 +454,14 @@ aarch64_analyze_prologue (struct gdbarch *gdbarch,
          unsigned int rt = inst.operands[0].reg.regno;
          int32_t imm = inst.operands[1].addr.offset.imm;
          unsigned int rn = inst.operands[1].addr.base_regno;
-         bool is64
-           = (aarch64_get_qualifier_esize (inst.operands[0].qualifier) == 8);
+         int size = aarch64_get_qualifier_esize (inst.operands[0].qualifier);
          gdb_assert (inst.operands[0].type == AARCH64_OPND_Rt
                      || inst.operands[0].type == AARCH64_OPND_Ft);
 
          if (inst.operands[0].type == AARCH64_OPND_Ft)
-           {
-             /* Only bottom 64-bit of each V register (D register) need
-                to be preserved.  */
-             gdb_assert (inst.operands[0].qualifier == AARCH64_OPND_QLF_S_D);
-             rt += AARCH64_X_REGISTER_COUNT;
-           }
+           rt += AARCH64_X_REGISTER_COUNT;
 
-         stack.store (pv_add_constant (regs[rn], imm),
-                      is64 ? 8 : 4, regs[rt]);
+         stack.store (pv_add_constant (regs[rn], imm), size, regs[rt]);
          if (inst.operands[1].addr.writeback)
            regs[rn] = pv_add_constant (regs[rn], imm);
        }
@@ -1211,6 +1201,39 @@ aarch64_execute_dwarf_cfa_vendor_op (struct gdbarch *gdbarch, gdb_byte op,
   return false;
 }
 
+/* Used for matching BRK instructions for AArch64.  */
+static constexpr uint32_t BRK_INSN_MASK = 0xffe0001f;
+static constexpr uint32_t BRK_INSN_BASE = 0xd4200000;
+
+/* Implementation of gdbarch_program_breakpoint_here_p for aarch64.  */
+
+static bool
+aarch64_program_breakpoint_here_p (gdbarch *gdbarch, CORE_ADDR address)
+{
+  const uint32_t insn_len = 4;
+  gdb_byte target_mem[4];
+
+  /* Enable the automatic memory restoration from breakpoints while
+     we read the memory.  Otherwise we may find temporary breakpoints, ones
+     inserted by GDB, and flag them as permanent breakpoints.  */
+  scoped_restore restore_memory
+    = make_scoped_restore_show_memory_breakpoints (0);
+
+  if (target_read_memory (address, target_mem, insn_len) == 0)
+    {
+      uint32_t insn =
+       (uint32_t) extract_unsigned_integer (target_mem, insn_len,
+                                            gdbarch_byte_order_for_code (gdbarch));
+
+      /* Check if INSN is a BRK instruction pattern.  There are multiple choices
+        of such instructions with different immediate values.  Different OS'
+        may use a different variation, but they have the same outcome.  */
+       return ((insn & BRK_INSN_MASK) == BRK_INSN_BASE);
+    }
+
+  return false;
+}
+
 /* When arguments must be pushed onto the stack, they go on in reverse
    order.  The code below implements a FILO (stack) to do this.  */
 
@@ -1417,7 +1440,7 @@ struct aarch64_call_info
 };
 
 /* Pass a value in a sequence of consecutive X registers.  The caller
-   is responsbile for ensuring sufficient registers are available.  */
+   is responsible for ensuring sufficient registers are available.  */
 
 static void
 pass_in_x (struct gdbarch *gdbarch, struct regcache *regcache,
@@ -1944,7 +1967,7 @@ aarch64_vnv_type (struct gdbarch *gdbarch)
 
   if (tdep->vnv_type == NULL)
     {
-      /* The other AArch64 psuedo registers (Q,D,H,S,B) refer to a single value
+      /* The other AArch64 pseudo registers (Q,D,H,S,B) refer to a single value
         slice from the non-pseudo vector registers.  However NEON V registers
         are always vector registers, and need constructing as such.  */
       const struct builtin_type *bt = builtin_type (gdbarch);
@@ -2745,9 +2768,10 @@ struct aarch64_displaced_step_closure : public displaced_step_closure
 {
   /* It is true when condition instruction, such as B.CON, TBZ, etc,
      is being displaced stepping.  */
-  int cond = 0;
+  bool cond = false;
 
-  /* PC adjustment offset after displaced stepping.  */
+  /* PC adjustment offset after displaced stepping.  If 0, then we don't
+     write the PC back, assuming the PC is already the right address.  */
   int32_t pc_adjust = 0;
 };
 
@@ -2825,7 +2849,7 @@ aarch64_displaced_step_b_cond (const unsigned cond, const int32_t offset,
   */
 
   emit_bcond (dsd->insn_buf, cond, 8);
-  dsd->dsc->cond = 1;
+  dsd->dsc->cond = true;
   dsd->dsc->pc_adjust = offset;
   dsd->insn_count = 1;
 }
@@ -2860,7 +2884,7 @@ aarch64_displaced_step_cb (const int32_t offset, const int is_cbnz,
   */
   emit_cb (dsd->insn_buf, is_cbnz, aarch64_register (rn, is64), 8);
   dsd->insn_count = 1;
-  dsd->dsc->cond = 1;
+  dsd->dsc->cond = true;
   dsd->dsc->pc_adjust = offset;
 }
 
@@ -2885,7 +2909,7 @@ aarch64_displaced_step_tb (const int32_t offset, int is_tbnz,
   */
   emit_tb (dsd->insn_buf, is_tbnz, bit, aarch64_register (rt, 1), 8);
   dsd->insn_count = 1;
-  dsd->dsc->cond = 1;
+  dsd->dsc->cond = true;
   dsd->dsc->pc_adjust = offset;
 }
 
@@ -2975,7 +2999,7 @@ static const struct aarch64_insn_visitor visitor =
 
 /* Implement the "displaced_step_copy_insn" gdbarch method.  */
 
-struct displaced_step_closure *
+displaced_step_closure_up
 aarch64_displaced_step_copy_insn (struct gdbarch *gdbarch,
                                  CORE_ADDR from, CORE_ADDR to,
                                  struct regcache *regs)
@@ -3029,7 +3053,8 @@ aarch64_displaced_step_copy_insn (struct gdbarch *gdbarch,
       dsc = NULL;
     }
 
-  return dsc.release ();
+  /* This is a work around for a problem with g++ 4.8.  */
+  return displaced_step_closure_up (dsc.release ());
 }
 
 /* Implement the "displaced_step_fixup" gdbarch method.  */
@@ -3042,11 +3067,20 @@ aarch64_displaced_step_fixup (struct gdbarch *gdbarch,
 {
   aarch64_displaced_step_closure *dsc = (aarch64_displaced_step_closure *) dsc_;
 
+  ULONGEST pc;
+
+  regcache_cooked_read_unsigned (regs, AARCH64_PC_REGNUM, &pc);
+
+  if (debug_displaced)
+    debug_printf ("Displaced: PC after stepping: %s (was %s).\n",
+                 paddress (gdbarch, pc), paddress (gdbarch, to));
+
   if (dsc->cond)
     {
-      ULONGEST pc;
+      if (debug_displaced)
+       debug_printf ("Displaced: [Conditional] pc_adjust before: %d\n",
+                     dsc->pc_adjust);
 
-      regcache_cooked_read_unsigned (regs, AARCH64_PC_REGNUM, &pc);
       if (pc - to == 8)
        {
          /* Condition is true.  */
@@ -3058,13 +3092,35 @@ aarch64_displaced_step_fixup (struct gdbarch *gdbarch,
        }
       else
        gdb_assert_not_reached ("Unexpected PC value after displaced stepping");
+
+      if (debug_displaced)
+       debug_printf ("Displaced: [Conditional] pc_adjust after: %d\n",
+                     dsc->pc_adjust);
     }
 
+  if (debug_displaced)
+    debug_printf ("Displaced: %s PC by %d\n",
+                 dsc->pc_adjust? "adjusting" : "not adjusting",
+                 dsc->pc_adjust);
+
+
   if (dsc->pc_adjust != 0)
     {
+      /* Make sure the previous instruction was executed (that is, the PC
+        has changed).  If the PC didn't change, then discard the adjustment
+        offset.  Otherwise we may skip an instruction before its execution
+        took place.  */
+      if ((pc - to) == 0)
+       {
+         if (debug_displaced)
+           debug_printf ("Displaced: PC did not move. Discarding PC "
+                         "adjustment.\n");
+         dsc->pc_adjust = 0;
+       }
+
       if (debug_displaced)
        {
-         debug_printf ("displaced: fixup: set PC to %s:%d\n",
+         debug_printf ("Displaced: fixup: set PC to %s:%d\n",
                        paddress (gdbarch, from), dsc->pc_adjust);
        }
       regcache_cooked_write_unsigned (regs, AARCH64_PC_REGNUM,
@@ -3367,6 +3423,10 @@ aarch64_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   set_gdbarch_execute_dwarf_cfa_vendor_op (gdbarch,
                                           aarch64_execute_dwarf_cfa_vendor_op);
 
+  /* Permanent/Program breakpoint handling.  */
+  set_gdbarch_program_breakpoint_here_p (gdbarch,
+                                        aarch64_program_breakpoint_here_p);
+
   /* Add some default predicates.  */
   frame_unwind_append_unwinder (gdbarch, &aarch64_stub_unwind);
   dwarf2_append_unwinders (gdbarch);
@@ -3382,6 +3442,8 @@ aarch64_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
 
   set_gdbarch_gen_return_address (gdbarch, aarch64_gen_return_address);
 
+  set_gdbarch_get_pc_address_flags (gdbarch, aarch64_get_pc_address_flags);
+
   tdesc_use_registers (gdbarch, tdesc, tdesc_data);
 
   /* Add standard register aliases.  */
@@ -3414,8 +3476,9 @@ static void aarch64_process_record_test (void);
 }
 #endif
 
+void _initialize_aarch64_tdep ();
 void
-_initialize_aarch64_tdep (void)
+_initialize_aarch64_tdep ()
 {
   gdbarch_register (bfd_arch_aarch64, aarch64_gdbarch_init,
                    aarch64_dump_tdep);
@@ -3551,7 +3614,7 @@ aarch64_record_data_proc_reg (insn_decode_record *aarch64_insn_r)
            }
          else if (insn_bits21_23 == 0x04 || insn_bits21_23 == 0x06)
            {
-             /* CConditional select.  */
+             /* Conditional select.  */
              /* Data-processing (2 source).  */
              /* Data-processing (1 source).  */
              record_buf[0] = reg_rd;
This page took 0.033552 seconds and 4 git commands to generate.