[PATCH v2] [gdb/tdep] Fix calc_ldst_datasize for strb
Tom de Vries
tdevries@suse.de
Tue Aug 19 10:13:04 GMT 2025
Consider aarch64 instruction strb w1, [x0].
It stores the least significant byte of 32-bit register w1 to memory, at an
address indicated by x0.
Currently, function calc_ldst_datasize returns 4 for this insn.
The way it calculates load/store data size, is to accumulate the size of the
operands before the address operand, and indeed that's 4 in this case.
But obviously, for strb the data size is 1.
The function seems to have been written specifically for FEAT_LRCPC3
(Load-Acquire RCpc instructions version 3) instructions [1].
Fix this by:
- getting the access size from the address operand, if possible, and
- otherwise falling back to the current implementation.
Add unit tests for calling calc_ldst_datasize with:
- strb,
- ldp/stp, for which the access size from the address operand needs to be
multiplied by two,
- ldap1, an insn from gas/testsuite/gas/aarch64/rcpc3-fp.s,
- stilp, an insn from gas/testsuite/gas/aarch64/rcpc3.s, and
- mov, for which 0 should be returned.
Tested gdb and gas testsuite on aarch64-linux.
Approved-By: Luis Machado <luis.machado.foss@gmail.com> (gdb)
PR tdep/33283
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=33283
[1] https://sourceware.org/pipermail/binutils/2024-January/131805.html
---
gdb/aarch64-tdep.c | 45 +++++++++++++++++++++++++++++++++++++++++++
opcodes/aarch64-opc.c | 32 ++++++++++++++++++++----------
2 files changed, 67 insertions(+), 10 deletions(-)
diff --git a/gdb/aarch64-tdep.c b/gdb/aarch64-tdep.c
index f2e3ce2a36c..4dd3e25955c 100644
--- a/gdb/aarch64-tdep.c
+++ b/gdb/aarch64-tdep.c
@@ -4914,6 +4914,49 @@ static void aarch64_process_record_test (void);
}
#endif
+#if GDB_SELF_TEST
+namespace selftests {
+
+static void
+aarch64_insn_analysis (void)
+{
+ uint32_t insn;
+ aarch64_inst inst;
+
+ /* 0x39000001 == strb w1, [x0]. */
+ insn = 0x39000001;
+ SELF_CHECK (aarch64_decode_insn (insn, &inst, true, NULL) == 0);
+ SELF_CHECK (calc_ldst_datasize (inst.operands) == 1);
+
+ /* 0xa8c17bfd == ldp x29, x30, [sp], #16. */
+ insn = 0xa8c17bfd;
+ SELF_CHECK (aarch64_decode_insn (insn, &inst, true, NULL) == 0);
+ SELF_CHECK (calc_ldst_datasize (inst.operands) == 16);
+
+ /* 0xa9bf7bf0 == stp x16, x30, [sp, #-16]!. */
+ insn = 0xa9bf7bf0;
+ SELF_CHECK (aarch64_decode_insn (insn, &inst, true, NULL) == 0);
+ SELF_CHECK (calc_ldst_datasize (inst.operands) == 16);
+
+ /* 0x0d4187e1 == ldap1 {v1.d}[0], [sp]. */
+ insn = 0x0d4187e1;
+ SELF_CHECK (aarch64_decode_insn (insn, &inst, true, NULL) == 0);
+ SELF_CHECK (calc_ldst_datasize (inst.operands) == 8);
+
+ /* 0xd9011860 == stilp x0, x1, [x3]. */
+ insn = 0xd9011860;
+ SELF_CHECK (aarch64_decode_insn (insn, &inst, true, NULL) == 0);
+ SELF_CHECK (calc_ldst_datasize (inst.operands) == 16);
+
+ /* 0x52800000 == mov w0, #0x0. */
+ insn = 0x52800000;
+ SELF_CHECK (aarch64_decode_insn (insn, &inst, true, NULL) == 0);
+ SELF_CHECK (calc_ldst_datasize (inst.operands) == 0);
+}
+
+}
+#endif
+
INIT_GDB_FILE (aarch64_tdep)
{
gdbarch_register (bfd_arch_aarch64, aarch64_gdbarch_init,
@@ -4933,6 +4976,8 @@ When on, AArch64 specific debugging is enabled."),
selftests::aarch64_analyze_prologue_test);
selftests::register_test ("aarch64-process-record",
selftests::aarch64_process_record_test);
+ selftests::register_test ("aarch64-insn-analysis",
+ selftests::aarch64_insn_analysis);
#endif
}
diff --git a/opcodes/aarch64-opc.c b/opcodes/aarch64-opc.c
index 5980841c394..8cdce6f82cc 100644
--- a/opcodes/aarch64-opc.c
+++ b/opcodes/aarch64-opc.c
@@ -1750,24 +1750,36 @@ check_za_access (const aarch64_opnd_info *opnd,
return true;
}
-/* Given a load/store operation, calculate the size of transferred data via a
- cumulative sum of qualifier sizes preceding the address operand in the
- OPNDS operand list argument. */
+/* Given a load/store operation, calculate the size of transferred data. */
+
int
calc_ldst_datasize (const aarch64_opnd_info *opnds)
{
- unsigned num_bytes = 0; /* total number of bytes transferred. */
- enum aarch64_operand_class opnd_class;
- enum aarch64_opnd type;
+ int addr_opnd = -1;
for (int i = 0; i < AARCH64_MAX_OPND_NUM; i++)
{
- type = opnds[i].type;
- opnd_class = aarch64_operands[type].op_class;
+ enum aarch64_opnd opnd_type = opnds[i].type;
+ enum aarch64_operand_class opnd_class
+ = aarch64_operands[opnd_type].op_class;
if (opnd_class == AARCH64_OPND_CLASS_ADDRESS)
- break;
- num_bytes += aarch64_get_qualifier_esize (opnds[i].qualifier);
+ {
+ addr_opnd = i;
+ break;
+ }
}
+
+ if (addr_opnd == -1)
+ return 0;
+
+ enum aarch64_opnd_qualifier addr_opnd_qualifier
+ = opnds[addr_opnd].qualifier;
+ if (operand_variant_qualifier_p (addr_opnd_qualifier))
+ return addr_opnd * aarch64_get_qualifier_esize (addr_opnd_qualifier);
+
+ unsigned num_bytes = 0; /* total number of bytes transferred. */
+ for (int i = 0; i < addr_opnd; i++)
+ num_bytes += aarch64_get_qualifier_esize (opnds[i].qualifier);
return num_bytes;
}
base-commit: 09292f4ae2ccb46130652f6b310ee7a5227326d3
--
2.43.0
More information about the Binutils
mailing list