From patchwork Tue Apr 7 12:49:48 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pedro Alves X-Patchwork-Id: 6055 Received: (qmail 1419 invoked by alias); 7 Apr 2015 12:50:19 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Delivered-To: mailing list gdb-patches@sourceware.org Received: (qmail 1309 invoked by uid 89); 7 Apr 2015 12:50:19 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-1.9 required=5.0 tests=AWL, BAYES_00, SPF_HELO_PASS, SPF_PASS, T_RP_MATCHES_RCVD autolearn=ham version=3.3.2 X-HELO: mx1.redhat.com Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES256-GCM-SHA384 encrypted) ESMTPS; Tue, 07 Apr 2015 12:50:17 +0000 Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id t37CoEA8003409 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=FAIL) for ; Tue, 7 Apr 2015 08:50:15 -0400 Received: from brno.lan (ovpn01.gateway.prod.ext.ams2.redhat.com [10.39.146.11]) by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id t37Cnox7022139 for ; Tue, 7 Apr 2015 08:50:13 -0400 From: Pedro Alves To: gdb-patches@sourceware.org Subject: [PATCH v2 21/23] PPC64: Fix gdb.arch/ppc64-atomic-inst.exp with displaced stepping Date: Tue, 7 Apr 2015 13:49:48 +0100 Message-Id: <1428410990-28560-22-git-send-email-palves@redhat.com> In-Reply-To: <1428410990-28560-1-git-send-email-palves@redhat.com> References: <1428410990-28560-1-git-send-email-palves@redhat.com> The ppc64 displaced step code can't handle atomic sequences. Fallback to stepping over the breakpoint in-line if we detect one. gdb/ChangeLog: 2015-04-07 Pedro Alves * infrun.c (displaced_step_prepare): Return -1 if gdbarch_displaced_step_copy_insn returns NULL. (resume): When displaced stepping doesn't work, try software single-stepping. * rs6000-tdep.c (LWARX_MASK, LWARX_INSTRUCTION, LDARX_INSTRUCTION) (STWCX_MASK, STWCX_INSTRUCTION, STDCX_INSTRUCTION): Move higher up in file. (ppc_displaced_step_copy_insn): New function. (ppc_displaced_step_fixup): Update comment. (rs6000_gdbarch_init): Install ppc_displaced_step_copy_insn as gdbarch_displaced_step_copy_insn hook. gdb/testsuite/ChangeLog: 2015-04-07 Pedro Alves * gdb.arch/ppc64-atomic-inst.exp (do_test): New procedure, move tests here. (top level): Run do_test with and without displaced stepping. --- gdb/infrun.c | 11 +++-- gdb/rs6000-tdep.c | 68 +++++++++++++++++++++++----- gdb/testsuite/gdb.arch/ppc64-atomic-inst.exp | 50 ++++++++++++-------- 3 files changed, 97 insertions(+), 32 deletions(-) diff --git a/gdb/infrun.c b/gdb/infrun.c index 2f288a0..8ba81ec 100644 --- a/gdb/infrun.c +++ b/gdb/infrun.c @@ -1765,9 +1765,14 @@ displaced_step_prepare (ptid_t ptid) closure = gdbarch_displaced_step_copy_insn (gdbarch, original, copy, regcache); - - /* We don't support the fully-simulated case at present. */ - gdb_assert (closure); + if (closure == NULL) + { + /* The architecture doesn't know how or want to displaced step + this instruction or instruction sequence. Fallback to + stepping over the breakpoint in-line. */ + do_cleanups (old_cleanups); + return -1; + } /* Save the information we need to fix things up if the step succeeds. */ diff --git a/gdb/rs6000-tdep.c b/gdb/rs6000-tdep.c index a125000..6106029 100644 --- a/gdb/rs6000-tdep.c +++ b/gdb/rs6000-tdep.c @@ -974,6 +974,61 @@ rs6000_breakpoint_from_pc (struct gdbarch *gdbarch, CORE_ADDR *bp_addr, #define BXL_INSN 0x4c000000 #define BP_INSN 0x7C000008 +/* Instruction masks used during single-stepping of atomic + sequences. */ +#define LWARX_MASK 0xfc0007fe +#define LWARX_INSTRUCTION 0x7c000028 +#define LDARX_INSTRUCTION 0x7c0000A8 +#define STWCX_MASK 0xfc0007ff +#define STWCX_INSTRUCTION 0x7c00012d +#define STDCX_INSTRUCTION 0x7c0001ad + +/* We can't displaces step atomic sequenes. Otherwise this is just + simple_displaced_step_copy_insn. */ + +static struct displaced_step_closure * +ppc_displaced_step_copy_insn (struct gdbarch *gdbarch, + CORE_ADDR from, CORE_ADDR to, + struct regcache *regs) +{ + size_t len = gdbarch_max_insn_length (gdbarch); + gdb_byte *buf = xmalloc (len); + struct cleanup *old_chain = make_cleanup (xfree, buf); + enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); + int insn; + + read_memory (from, buf, len); + + insn = extract_signed_integer (buf, PPC_INSN_SIZE, byte_order); + + /* Assume all atomic sequences start with a lwarx/ldarx instruction. */ + if ((insn & LWARX_MASK) == LWARX_INSTRUCTION + || (insn & LWARX_MASK) == LDARX_INSTRUCTION) + { + if (debug_displaced) + { + fprintf_unfiltered (gdb_stdlog, + "displaced: can't displaced step " + "atomic sequence at %s\n", + paddress (gdbarch, from)); + } + do_cleanups (old_chain); + return NULL; + } + + write_memory (to, buf, len); + + if (debug_displaced) + { + fprintf_unfiltered (gdb_stdlog, "displaced: copy %s->%s: ", + paddress (gdbarch, from), paddress (gdbarch, to)); + displaced_step_dump_bytes (gdb_stdlog, buf, len); + } + + discard_cleanups (old_chain); + return (struct displaced_step_closure *) buf; +} + /* Fix up the state of registers and memory after having single-stepped a displaced instruction. */ static void @@ -983,8 +1038,7 @@ ppc_displaced_step_fixup (struct gdbarch *gdbarch, struct regcache *regs) { enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); - /* Since we use simple_displaced_step_copy_insn, our closure is a - copy of the instruction. */ + /* Our closure is a copy of the instruction. */ ULONGEST insn = extract_unsigned_integer ((gdb_byte *) closure, PPC_INSN_SIZE, byte_order); ULONGEST opcode = 0; @@ -1077,14 +1131,6 @@ ppc_displaced_step_hw_singlestep (struct gdbarch *gdbarch, return 1; } -/* Instruction masks used during single-stepping of atomic sequences. */ -#define LWARX_MASK 0xfc0007fe -#define LWARX_INSTRUCTION 0x7c000028 -#define LDARX_INSTRUCTION 0x7c0000A8 -#define STWCX_MASK 0xfc0007ff -#define STWCX_INSTRUCTION 0x7c00012d -#define STDCX_INSTRUCTION 0x7c0001ad - /* Checks for an atomic sequence of instructions beginning with a LWARX/LDARX instruction and ending with a STWCX/STDCX instruction. If such a sequence is found, attempt to step through it. A breakpoint is placed at the end of @@ -5923,7 +5969,7 @@ rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) /* Setup displaced stepping. */ set_gdbarch_displaced_step_copy_insn (gdbarch, - simple_displaced_step_copy_insn); + ppc_displaced_step_copy_insn); set_gdbarch_displaced_step_hw_singlestep (gdbarch, ppc_displaced_step_hw_singlestep); set_gdbarch_displaced_step_fixup (gdbarch, ppc_displaced_step_fixup); diff --git a/gdb/testsuite/gdb.arch/ppc64-atomic-inst.exp b/gdb/testsuite/gdb.arch/ppc64-atomic-inst.exp index d251425..08518fb 100644 --- a/gdb/testsuite/gdb.arch/ppc64-atomic-inst.exp +++ b/gdb/testsuite/gdb.arch/ppc64-atomic-inst.exp @@ -32,27 +32,41 @@ if { [prepare_for_testing ${testfile}.exp ${testfile} ${srcfile} {debug quiet}] return -1 } -if ![runto_main] then { - untested "could not run to main" - return -1 -} +# The test proper. DISPLACED is true if we should try with displaced +# stepping. +proc do_test { displaced } { + global decimal hex + + if ![runto_main] then { + untested "could not run to main" + return -1 + } + + gdb_test_no_output "set displaced-stepping $displaced" -set bp1 [gdb_get_line_number "lwarx"] -gdb_breakpoint "$bp1" "Breakpoint $decimal at $hex" \ - "Set the breakpoint at the start of the lwarx/stwcx sequence" + set bp1 [gdb_get_line_number "lwarx"] + gdb_breakpoint "$bp1" "Breakpoint $decimal at $hex" \ + "Set the breakpoint at the start of the lwarx/stwcx sequence" -set bp2 [gdb_get_line_number "ldarx"] -gdb_breakpoint "$bp2" "Breakpoint $decimal at $hex" \ - "Set the breakpoint at the start of the ldarx/stdcx sequence" + set bp2 [gdb_get_line_number "ldarx"] + gdb_breakpoint "$bp2" "Breakpoint $decimal at $hex" \ + "Set the breakpoint at the start of the ldarx/stdcx sequence" -gdb_test continue "Continuing.*Breakpoint $decimal.*" \ - "Continue until lwarx/stwcx start breakpoint" + gdb_test continue "Continuing.*Breakpoint $decimal.*" \ + "Continue until lwarx/stwcx start breakpoint" -gdb_test nexti "bne.*1b" \ - "Step through the lwarx/stwcx sequence" + gdb_test nexti "bne.*1b" \ + "Step through the lwarx/stwcx sequence" -gdb_test continue "Continuing.*Breakpoint $decimal.*" \ - "Continue until ldarx/stdcx start breakpoint" + gdb_test continue "Continuing.*Breakpoint $decimal.*" \ + "Continue until ldarx/stdcx start breakpoint" -gdb_test nexti "bne.*1b" \ - "Step through the ldarx/stdcx sequence" + gdb_test nexti "bne.*1b" \ + "Step through the ldarx/stdcx sequence" +} + +foreach displaced { "off" "on" } { + with_test_prefix "displaced=$displaced" { + do_test $displaced + } +}