Blame SOURCES/gdb-rhbz1093259-aarch64-single-step-atomic-seq.patch

2c2fa1
All attempts:
2c2fa1
2c2fa1
 - <https://sourceware.org/ml/gdb-patches/2014-03/msg00576.html>
2c2fa1
   Message-ID: <20140324161056.GB23291@redacted.bos.redhat.com>
2c2fa1
2c2fa1
 - <https://sourceware.org/ml/gdb-patches/2014-03/msg00624.html>
2c2fa1
   Message-ID: <20140327015125.GE3075@redacted.bos.redhat.com>
2c2fa1
   (see below)
2c2fa1
2c2fa1
 - <https://sourceware.org/ml/gdb-patches/2014-04/msg00433.html>
2c2fa1
   Message-ID: <20140422165542.GA748@redacted.bos.redhat.com>
2c2fa1
2c2fa1
 - <https://sourceware.org/ml/gdb-patches/2014-04/msg00505.html>
2c2fa1
   Message-ID: <20140424183510.GI7588@redacted.bos.redhat.com>
2c2fa1
2c2fa1
 - <https://sourceware.org/ml/gdb-patches/2014-04/msg00642.html>
2c2fa1
   Message-ID: <20140430160450.GE2148@redacted.bos.redhat.com>
2c2fa1
   (last version, applied)
2c2fa1
2c2fa1
2c2fa1
Second message from Kyle, which seems complete enough.
2c2fa1
2c2fa1
  Date: Wed, 26 Mar 2014 21:51:26 -0400
2c2fa1
  From: Kyle McMartin <kmcmarti at redhat dot com>
2c2fa1
  To: gdb-patches at sourceware dot org
2c2fa1
  Subject: [PATCHv2] aarch64: detect atomic sequences like other ll/sc architectures
2c2fa1
  Message-ID: <20140327015125.GE3075@redacted.bos.redhat.com>
2c2fa1
2c2fa1
  Add similar single-stepping over atomic sequences support like other
2c2fa1
  load-locked/store-conditional architectures (alpha, powerpc, arm, etc.)
2c2fa1
  do. Verified the decode_masked_match, and decode_bcond works against the
2c2fa1
  atomic sequences used in the Linux kernel atomic.h, and also gcc
2c2fa1
  libatomic. Thanks to Richard Henderson for feedback on my initial
2c2fa1
  attempt at this patch, and for the feedback from gdb-patches, which I
2c2fa1
  hope I've addressed...
2c2fa1
2c2fa1
2c2fa1
2c2fa1
commit 9404b58f46328b3b171b0d5eeb0691bd685bc4f5
2c2fa1
Author: Kyle McMartin <kmcmarti@redhat.com>
2c2fa1
Date:   Wed Apr 30 12:04:50 2014 -0400
2c2fa1
2c2fa1
    aarch64: detect atomic sequences like other ll/sc architectures
2c2fa1
    
2c2fa1
    gdb/Changelog:
2c2fa1
    
2c2fa1
            * aarch64-tdep.c (aarch64_software_single_step): New function.
2c2fa1
            (aarch64_gdbarch_init): Handle single stepping of atomic sequences
2c2fa1
            with aarch64_software_single_step.
2c2fa1
    
2c2fa1
    gdb/testsuite/ChangeLog:
2c2fa1
    
2c2fa1
            * gdb.arch/aarch64-atomic-inst.c: New file.
2c2fa1
            * gdb.arch/aarch64-atomic-inst.exp: New file.
2c2fa1
2c2fa1
Index: gdb-7.6.1/gdb/aarch64-tdep.c
2c2fa1
===================================================================
2c2fa1
--- gdb-7.6.1.orig/gdb/aarch64-tdep.c
2c2fa1
+++ gdb-7.6.1/gdb/aarch64-tdep.c
2c2fa1
@@ -2518,6 +2518,84 @@ value_of_aarch64_user_reg (struct frame_
2c2fa1
 }
2c2fa1
 
2c2fa1
 
2c2fa1
+/* Implement the "software_single_step" gdbarch method, needed to
2c2fa1
+   single step through atomic sequences on AArch64.  */
2c2fa1
+
2c2fa1
+static int
2c2fa1
+aarch64_software_single_step (struct frame_info *frame)
2c2fa1
+{
2c2fa1
+  struct gdbarch *gdbarch = get_frame_arch (frame);
2c2fa1
+  struct address_space *aspace = get_frame_address_space (frame);
2c2fa1
+  enum bfd_endian byte_order_for_code = gdbarch_byte_order_for_code (gdbarch);
2c2fa1
+  const int insn_size = 4;
2c2fa1
+  const int atomic_sequence_length = 16; /* Instruction sequence length.  */
2c2fa1
+  CORE_ADDR pc = get_frame_pc (frame);
2c2fa1
+  CORE_ADDR breaks[2] = { -1, -1 };
2c2fa1
+  CORE_ADDR loc = pc;
2c2fa1
+  CORE_ADDR closing_insn = 0;
2c2fa1
+  uint32_t insn = read_memory_unsigned_integer (loc, insn_size,
2c2fa1
+						byte_order_for_code);
2c2fa1
+  int index;
2c2fa1
+  int insn_count;
2c2fa1
+  int bc_insn_count = 0; /* Conditional branch instruction count.  */
2c2fa1
+  int last_breakpoint = 0; /* Defaults to 0 (no breakpoints placed).  */
2c2fa1
+
2c2fa1
+  /* Look for a Load Exclusive instruction which begins the sequence.  */
2c2fa1
+  if (!decode_masked_match (insn, 0x3fc00000, 0x08400000))
2c2fa1
+    return 0;
2c2fa1
+
2c2fa1
+  for (insn_count = 0; insn_count < atomic_sequence_length; ++insn_count)
2c2fa1
+    {
2c2fa1
+      int32_t offset;
2c2fa1
+      unsigned cond;
2c2fa1
+
2c2fa1
+      loc += insn_size;
2c2fa1
+      insn = read_memory_unsigned_integer (loc, insn_size,
2c2fa1
+					   byte_order_for_code);
2c2fa1
+
2c2fa1
+      /* Check if the instruction is a conditional branch.  */
2c2fa1
+      if (decode_bcond (loc, insn, &cond, &offset))
2c2fa1
+	{
2c2fa1
+	  if (bc_insn_count >= 1)
2c2fa1
+	    return 0;
2c2fa1
+
2c2fa1
+	  /* It is, so we'll try to set a breakpoint at the destination.  */
2c2fa1
+	  breaks[1] = loc + offset;
2c2fa1
+
2c2fa1
+	  bc_insn_count++;
2c2fa1
+	  last_breakpoint++;
2c2fa1
+	}
2c2fa1
+
2c2fa1
+      /* Look for the Store Exclusive which closes the atomic sequence.  */
2c2fa1
+      if (decode_masked_match (insn, 0x3fc00000, 0x08000000))
2c2fa1
+	{
2c2fa1
+	  closing_insn = loc;
2c2fa1
+	  break;
2c2fa1
+	}
2c2fa1
+    }
2c2fa1
+
2c2fa1
+  /* We didn't find a closing Store Exclusive instruction, fall back.  */
2c2fa1
+  if (!closing_insn)
2c2fa1
+    return 0;
2c2fa1
+
2c2fa1
+  /* Insert breakpoint after the end of the atomic sequence.  */
2c2fa1
+  breaks[0] = loc + insn_size;
2c2fa1
+
2c2fa1
+  /* Check for duplicated breakpoints, and also check that the second
2c2fa1
+     breakpoint is not within the atomic sequence.  */
2c2fa1
+  if (last_breakpoint
2c2fa1
+      && (breaks[1] == breaks[0]
2c2fa1
+	  || (breaks[1] >= pc && breaks[1] <= closing_insn)))
2c2fa1
+    last_breakpoint = 0;
2c2fa1
+
2c2fa1
+  /* Insert the breakpoint at the end of the sequence, and one at the
2c2fa1
+     destination of the conditional branch, if it exists.  */
2c2fa1
+  for (index = 0; index <= last_breakpoint; index++)
2c2fa1
+    insert_single_step_breakpoint (gdbarch, aspace, breaks[index]);
2c2fa1
+
2c2fa1
+  return 1;
2c2fa1
+}
2c2fa1
+
2c2fa1
 /* Initialize the current architecture based on INFO.  If possible,
2c2fa1
    re-use an architecture from ARCHES, which is a list of
2c2fa1
    architectures already created during this debugging session.
2c2fa1
@@ -2635,6 +2713,7 @@ aarch64_gdbarch_init (struct gdbarch_inf
2c2fa1
   set_gdbarch_breakpoint_from_pc (gdbarch, aarch64_breakpoint_from_pc);
2c2fa1
   set_gdbarch_cannot_step_breakpoint (gdbarch, 1);
2c2fa1
   set_gdbarch_have_nonsteppable_watchpoint (gdbarch, 1);
2c2fa1
+  set_gdbarch_software_single_step (gdbarch, aarch64_software_single_step);
2c2fa1
 
2c2fa1
   /* Information about registers, etc.  */
2c2fa1
   set_gdbarch_sp_regnum (gdbarch, AARCH64_SP_REGNUM);
2c2fa1
Index: gdb-7.6.1/gdb/testsuite/gdb.arch/aarch64-atomic-inst.c
2c2fa1
===================================================================
2c2fa1
--- /dev/null
2c2fa1
+++ gdb-7.6.1/gdb/testsuite/gdb.arch/aarch64-atomic-inst.c
2c2fa1
@@ -0,0 +1,48 @@
2c2fa1
+/* This file is part of GDB, the GNU debugger.
2c2fa1
+
2c2fa1
+   Copyright 2008-2014 Free Software Foundation, Inc.
2c2fa1
+
2c2fa1
+   This program is free software; you can redistribute it and/or modify
2c2fa1
+   it under the terms of the GNU General Public License as published by
2c2fa1
+   the Free Software Foundation; either version 3 of the License, or
2c2fa1
+   (at your option) any later version.
2c2fa1
+
2c2fa1
+   This program is distributed in the hope that it will be useful,
2c2fa1
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
2c2fa1
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
2c2fa1
+   GNU General Public License for more details.
2c2fa1
+
2c2fa1
+   You should have received a copy of the GNU General Public License
2c2fa1
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
2c2fa1
+
2c2fa1
+int main(void)
2c2fa1
+{
2c2fa1
+  unsigned long tmp, cond;
2c2fa1
+  unsigned long dword = 0;
2c2fa1
+
2c2fa1
+  /* Test that we can step over ldxr/stxr. This sequence should step from
2c2fa1
+     ldxr to the following __asm __volatile.  */
2c2fa1
+  __asm __volatile ("1:     ldxr    %0,%2\n"                             \
2c2fa1
+                    "       cmp     %0,#1\n"                             \
2c2fa1
+                    "       b.eq    out\n"                               \
2c2fa1
+                    "       add     %0,%0,1\n"                           \
2c2fa1
+                    "       stxr    %w1,%0,%2\n"                         \
2c2fa1
+                    "       cbnz    %w1,1b"                              \
2c2fa1
+                    : "=&r" (tmp), "=&r" (cond), "+Q" (dword)            \
2c2fa1
+                    : : "memory");
2c2fa1
+
2c2fa1
+  /* This sequence should take the conditional branch and step from ldxr
2c2fa1
+     to the return dword line.  */
2c2fa1
+  __asm __volatile ("1:     ldxr    %0,%2\n"                             \
2c2fa1
+                    "       cmp     %0,#1\n"                             \
2c2fa1
+                    "       b.eq    out\n"                               \
2c2fa1
+                    "       add     %0,%0,1\n"                           \
2c2fa1
+                    "       stxr    %w1,%0,%2\n"                         \
2c2fa1
+                    "       cbnz    %w1,1b\n"                            \
2c2fa1
+                    : "=&r" (tmp), "=&r" (cond), "+Q" (dword)            \
2c2fa1
+                    : : "memory");
2c2fa1
+
2c2fa1
+  dword = -1;
2c2fa1
+__asm __volatile ("out:\n");
2c2fa1
+  return dword;
2c2fa1
+}
2c2fa1
Index: gdb-7.6.1/gdb/testsuite/gdb.arch/aarch64-atomic-inst.exp
2c2fa1
===================================================================
2c2fa1
--- /dev/null
2c2fa1
+++ gdb-7.6.1/gdb/testsuite/gdb.arch/aarch64-atomic-inst.exp
2c2fa1
@@ -0,0 +1,48 @@
2c2fa1
+# Copyright 2008-2014 Free Software Foundation, Inc.
2c2fa1
+#
2c2fa1
+# This program is free software; you can redistribute it and/or modify
2c2fa1
+# it under the terms of the GNU General Public License as published by
2c2fa1
+# the Free Software Foundation; either version 3 of the License, or
2c2fa1
+# (at your option) any later version.
2c2fa1
+#
2c2fa1
+# This program is distributed in the hope that it will be useful,
2c2fa1
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
2c2fa1
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
2c2fa1
+# GNU General Public License for more details.
2c2fa1
+#
2c2fa1
+# You should have received a copy of the GNU General Public License
2c2fa1
+# along with this program; if not, write to the Free Software
2c2fa1
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
2c2fa1
+#
2c2fa1
+# This file is part of the gdb testsuite.
2c2fa1
+
2c2fa1
+# Test single stepping through atomic sequences beginning with
2c2fa1
+# a ldxr instruction and ending with a stxr instruction.
2c2fa1
+
2c2fa1
+if {![istarget "aarch64*"]} {
2c2fa1
+    verbose "Skipping ${gdb_test_file_name}."
2c2fa1
+    return
2c2fa1
+}
2c2fa1
+
2c2fa1
+standard_testfile
2c2fa1
+if { [prepare_for_testing ${testfile}.exp ${testfile} ${srcfile}] } {
2c2fa1
+    return -1
2c2fa1
+}
2c2fa1
+
2c2fa1
+if ![runto_main] {
2c2fa1
+    untested "could not run to main"
2c2fa1
+    return -1
2c2fa1
+}
2c2fa1
+
2c2fa1
+gdb_breakpoint "[gdb_get_line_number "ldxr"]" \
2c2fa1
+  "Breakpoint $decimal at $hex" \
2c2fa1
+  "Set the breakpoint at the start of the sequence"
2c2fa1
+
2c2fa1
+gdb_test "continue" "Continuing.*Breakpoint $decimal.*" \
2c2fa1
+  "Continue until breakpoint"
2c2fa1
+
2c2fa1
+gdb_test "next" ".*__asm __volatile.*" \
2c2fa1
+  "Step through the ldxr/stxr sequence"
2c2fa1
+
2c2fa1
+gdb_test "next" ".*return dword.*" \
2c2fa1
+  "Stepped through sequence through conditional branch"