From: Thiago Jung Bauermann <thiago.bauermann@linaro.org>
To: gdb-patches@sourceware.org
Subject: [PATCH 1/5] gdb/aarch64: Implement software single stepping for MOPS instructions
Date: Fri, 3 May 2024 21:05:17 -0300 [thread overview]
Message-ID: <20240504000521.314531-2-thiago.bauermann@linaro.org> (raw)
In-Reply-To: <20240504000521.314531-1-thiago.bauermann@linaro.org>
The AArch64 MOPS (Memory Operation) instructions provide a standardised
instruction sequence to perform a memset, memcpy or memmove. A sequence is
always composed of three instructions: a prologue instruction, a main
instruction and an epilogue instruction. As an illustration, here are the
implementations of these memory operations in glibc 2.39:
(gdb) disassemble/r
Dump of assembler code for function __memset_mops:
=> 0x0000fffff7e8d780 <+0>: d503201f nop
0x0000fffff7e8d784 <+4>: aa0003e3 mov x3, x0
0x0000fffff7e8d788 <+8>: 19c10443 setp [x3]!, x2!, x1
0x0000fffff7e8d78c <+12>: 19c14443 setm [x3]!, x2!, x1
0x0000fffff7e8d790 <+16>: 19c18443 sete [x3]!, x2!, x1
0x0000fffff7e8d794 <+20>: d65f03c0 ret
End of assembler dump.
(gdb) disassemble/r
Dump of assembler code for function __memcpy_mops:
=> 0x0000fffff7e8c580 <+0>: d503201f nop
0x0000fffff7e8c584 <+4>: aa0003e3 mov x3, x0
0x0000fffff7e8c588 <+8>: 19010443 cpyfp [x3]!, [x1]!, x2!
0x0000fffff7e8c58c <+12>: 19410443 cpyfm [x3]!, [x1]!, x2!
0x0000fffff7e8c590 <+16>: 19810443 cpyfe [x3]!, [x1]!, x2!
0x0000fffff7e8c594 <+20>: d65f03c0 ret
End of assembler dump.
(gdb) disassemble/r
Dump of assembler code for function __memmove_mops:
=> 0x0000fffff7e8d180 <+0>: d503201f nop
0x0000fffff7e8d184 <+4>: aa0003e3 mov x3, x0
0x0000fffff7e8d188 <+8>: 1d010443 cpyp [x3]!, [x1]!, x2!
0x0000fffff7e8d18c <+12>: 1d410443 cpym [x3]!, [x1]!, x2!
0x0000fffff7e8d190 <+16>: 1d810443 cpye [x3]!, [x1]!, x2!
0x0000fffff7e8d194 <+20>: d65f03c0 ret
End of assembler dump.
The Arm Architecture Reference Manual says that "the prologue, main, and
epilogue instructions are expected to be run in succession and to appear
consecutively in memory". Therefore GDB needs to treat them as an atomic
instruction sequence, and also can't do displaced stepping with them.
This patch implements support for executing the sequence atomically, and
also disables displaced step on them.
PR tdep/31666
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=31666
---
gdb/aarch64-tdep.c | 107 ++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 105 insertions(+), 2 deletions(-)
diff --git a/gdb/aarch64-tdep.c b/gdb/aarch64-tdep.c
index 8d0553f3d7cd..e920cea49066 100644
--- a/gdb/aarch64-tdep.c
+++ b/gdb/aarch64-tdep.c
@@ -3444,6 +3444,104 @@ value_of_aarch64_user_reg (const frame_info_ptr &frame, const void *baton)
return value_of_register (*reg_p, get_next_frame_sentinel_okay (frame));
}
+/* Single step through MOPS instruction sequences on AArch64. */
+
+static std::vector<CORE_ADDR>
+aarch64_software_single_step_mops (struct regcache *regcache, CORE_ADDR loc,
+ uint32_t insn)
+{
+ const int insn_size = 4;
+ struct gdbarch *gdbarch = regcache->arch ();
+ enum bfd_endian byte_order_for_code = gdbarch_byte_order_for_code (gdbarch);
+ uint8_t o0 = bit (insn, 21);
+ uint8_t op1 = bits (insn, 22, 23);
+ uint8_t op2 = bits (insn, 12, 15);
+
+ /* Look for the prologue instruction that begins the sequence. */
+
+ /* CPYFP* */
+ if (!((o0 == 0 && op1 == 0)
+ /* SETP* */
+ || (o0 == 0 && op1 == 3 && op2 < 4)
+ /* CPYP* */
+ || (o0 == 1 && op1 == 0)
+ /* SETGP* */
+ || (o0 == 1 && op1 == 3 && op2 < 4)))
+ /* Prologue instruction not found. */
+ return {};
+
+ /* Now look for the main instruction in the middle of the sequence. */
+
+ loc += insn_size;
+ ULONGEST insn_from_memory;
+ if (!safe_read_memory_unsigned_integer (loc, insn_size,
+ byte_order_for_code,
+ &insn_from_memory))
+ {
+ /* Assume we don't have a MOPS sequence, as we couldn't read the
+ instruction in this location. */
+ return {};
+ }
+
+ insn = insn_from_memory;
+ aarch64_inst inst;
+ if (aarch64_decode_insn (insn, &inst, 1, nullptr) != 0)
+ return {};
+ if (!AARCH64_CPU_HAS_FEATURE (*inst.opcode->avariant, MOPS))
+ return {};
+
+ o0 = bit (insn, 21);
+ op1 = bits (insn, 22, 23);
+ op2 = bits (insn, 12, 15);
+
+ /* CPYFM* */
+ if (!((o0 == 0 && op1 == 1)
+ /* SETM* */
+ || (o0 == 0 && op1 == 3 && op2 >= 4 && op2 < 8)
+ /* CPYM* */
+ || (o0 == 1 && op1 == 1)
+ /* SETGM* */
+ || (o0 == 1 && op1 == 3 && op2 >= 4 && op2 < 8)))
+ /* Main instruction not found. */
+ return {};
+
+ /* Now look for the epilogue instruction that ends the sequence. */
+
+ loc += insn_size;
+ if (!safe_read_memory_unsigned_integer (loc, insn_size,
+ byte_order_for_code,
+ &insn_from_memory))
+ {
+ /* Assume we don't have a MOPS sequence, as we couldn't read the
+ instruction in this location. */
+ return {};
+ }
+
+ insn = insn_from_memory;
+ if (aarch64_decode_insn (insn, &inst, 1, nullptr) != 0)
+ return {};
+ if (!AARCH64_CPU_HAS_FEATURE (*inst.opcode->avariant, MOPS))
+ return {};
+
+ o0 = bit (insn, 21);
+ op1 = bits (insn, 22, 23);
+ op2 = bits (insn, 12, 15);
+
+ /* CPYFE* */
+ if (!((o0 == 0 && op1 == 2)
+ /* SETE* (op2 >= 12 is unallocated space) */
+ || (o0 == 0 && op1 == 3 && op2 >= 8 && op2 < 12)
+ /* CPYE* */
+ || (o0 == 1 && op1 == 2)
+ /* SETGE* (op2 >= 12 is unallocated space) */
+ || (o0 == 1 && op1 == 3 && op2 >= 8 && op2 < 12)))
+ /* Epilogue instruction not found. */
+ return {};
+
+ /* Insert breakpoint after the end of the atomic sequence. */
+ return { loc + insn_size };
+}
+
/* Implement the "software_single_step" gdbarch method, needed to
single step through atomic sequences on AArch64. */
@@ -3479,6 +3577,9 @@ aarch64_software_single_step (struct regcache *regcache)
if (aarch64_decode_insn (insn, &inst, 1, NULL) != 0)
return {};
+ if (AARCH64_CPU_HAS_FEATURE (*inst.opcode->avariant, MOPS))
+ return aarch64_software_single_step_mops (regcache, loc, insn);
+
/* Look for a Load Exclusive instruction which begins the sequence. */
if (inst.opcode->iclass != ldstexcl || bit (insn, 22) == 0)
return {};
@@ -3808,8 +3909,10 @@ aarch64_displaced_step_copy_insn (struct gdbarch *gdbarch,
if (aarch64_decode_insn (insn, &inst, 1, NULL) != 0)
return NULL;
- /* Look for a Load Exclusive instruction which begins the sequence. */
- if (inst.opcode->iclass == ldstexcl && bit (insn, 22))
+ /* Look for a Load Exclusive instruction which begins the sequence,
+ or for a MOPS instruction. */
+ if ((inst.opcode->iclass == ldstexcl && bit (insn, 22))
+ || AARCH64_CPU_HAS_FEATURE (*inst.opcode->avariant, MOPS))
{
/* We can't displaced step atomic sequences. */
return NULL;
next prev parent reply other threads:[~2024-05-04 0:05 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-05-04 0:05 [PATCH 0/5] Add support for AArch64 " Thiago Jung Bauermann
2024-05-04 0:05 ` Thiago Jung Bauermann [this message]
2024-05-06 9:29 ` [PATCH 1/5] gdb/aarch64: Implement software single stepping for " Christophe Lyon
2024-05-07 0:56 ` Thiago Jung Bauermann
2024-05-04 0:05 ` [PATCH 2/5] gdb/aarch64: Add record support " Thiago Jung Bauermann
2024-05-04 0:05 ` [PATCH 3/5] gdb/testsuite: Add gdb.arch/aarch64-mops-watchpoint.exp Thiago Jung Bauermann
2024-05-04 0:05 ` [PATCH 4/5] gdb/testsuite: Add gdb.arch/aarch64-mops-atomic-inst.exp Thiago Jung Bauermann
2024-05-06 9:42 ` Christophe Lyon
2024-05-07 2:10 ` Thiago Jung Bauermann
2024-05-04 0:05 ` [PATCH 5/5] gdb/testsuite: Add gdb.reverse/aarch64-mops.exp Thiago Jung Bauermann
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20240504000521.314531-2-thiago.bauermann@linaro.org \
--to=thiago.bauermann@linaro.org \
--cc=gdb-patches@sourceware.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).