[PATCH] Make arm_record_test work on big-endian machines

Simon Marchi
2018-03-12T03:09:57Z

While running selftests on a big-endian PPC, I noticed arm_record_test
failed a test. The reason is that the gdbarch_find_by_info call is done
with BFD_ENDIAN_UNKNOWN byte order in the info structure. In that case,
it uses the byte order of the current default BFD, which happened to be
big-endian on that GDB build, and the gdbarch returned is a big-endian
one. The instruction used for the 32-bits part of the test is written
in little-endian form, so GDB fails to decode the instruction properly.

Since ARM supports both endiannesses, and it should be possible to debug
using an host of both endiannesses, I changed the test to check with
gdbarches of both endiannesses.

gdb/ChangeLog:

* arm-tdep.c (arm_record_test): Test with big and little endian
gdbarch.
---
gdb/arm-tdep.c | 106 ++++++++++++++++++++++++++++++---------------------------
1 file changed, 56 insertions(+), 50 deletions(-)

diff --git a/gdb/arm-tdep.c b/gdb/arm-tdep.c
index ef7e66b36a..840b82b57c 100644
--- a/gdb/arm-tdep.c
+++ b/gdb/arm-tdep.c
@@ -13247,70 +13247,76 @@ private:
static void
arm_record_test (void)
{
- struct gdbarch_info info;
- gdbarch_info_init (&info);
- info.bfd_arch_info = bfd_scan_arch ("arm");
+ std::array<bfd_endian, 2> endiannesses{{ BFD_ENDIAN_BIG, BFD_ENDIAN_LITTLE }};

- struct gdbarch *gdbarch = gdbarch_find_by_info (info);
+ for (bfd_endian endian : endiannesses)
+ {
+ struct gdbarch_info info;
+ gdbarch_info_init (&info);
+ info.bfd_arch_info = bfd_scan_arch ("arm");
+ info.byte_order = endian;
+ info.byte_order_for_code = endian;

- SELF_CHECK (gdbarch != NULL);
+ struct gdbarch *gdbarch = gdbarch_find_by_info (info);

- /* 16-bit Thumb instructions. */
- {
- insn_decode_record arm_record;
+ SELF_CHECK (gdbarch != NULL);

- memset (&arm_record, 0, sizeof (insn_decode_record));
- arm_record.gdbarch = gdbarch;
+ /* 16-bit Thumb instructions. */
+ {
+ insn_decode_record arm_record;

- static const uint16_t insns[] = {
- /* db b2 uxtb r3, r3 */
- 0xb2db,
- /* cd 58 ldr r5, [r1, r3] */
- 0x58cd,
- };
+ memset (&arm_record, 0, sizeof (insn_decode_record));
+ arm_record.gdbarch = gdbarch;

- enum bfd_endian endian = gdbarch_byte_order_for_code (arm_record.gdbarch);
- instruction_reader_thumb reader (endian, insns);
- int ret = decode_insn (reader, &arm_record, THUMB_RECORD,
- THUMB_INSN_SIZE_BYTES);
+ static const uint16_t insns[] = {
+ /* db b2 uxtb r3, r3 */
+ 0xb2db,
+ /* cd 58 ldr r5, [r1, r3] */
+ 0x58cd,
+ };

- SELF_CHECK (ret == 0);
- SELF_CHECK (arm_record.mem_rec_count == 0);
- SELF_CHECK (arm_record.reg_rec_count == 1);
- SELF_CHECK (arm_record.arm_regs[0] == 3);
+ instruction_reader_thumb reader (endian, insns);
+ int ret = decode_insn (reader, &arm_record, THUMB_RECORD,
+ THUMB_INSN_SIZE_BYTES);

- arm_record.this_addr += 2;
- ret = decode_insn (reader, &arm_record, THUMB_RECORD,
- THUMB_INSN_SIZE_BYTES);
+ SELF_CHECK (ret == 0);
+ SELF_CHECK (arm_record.mem_rec_count == 0);
+ SELF_CHECK (arm_record.reg_rec_count == 1);
+ SELF_CHECK (arm_record.arm_regs[0] == 3);

- SELF_CHECK (ret == 0);
- SELF_CHECK (arm_record.mem_rec_count == 0);
- SELF_CHECK (arm_record.reg_rec_count == 1);
- SELF_CHECK (arm_record.arm_regs[0] == 5);
- }
+ arm_record.this_addr += 2;
+ ret = decode_insn (reader, &arm_record, THUMB_RECORD,
+ THUMB_INSN_SIZE_BYTES);

- /* 32-bit Thumb-2 instructions. */
- {
- insn_decode_record arm_record;
+ SELF_CHECK (ret == 0);
+ SELF_CHECK (arm_record.mem_rec_count == 0);
+ SELF_CHECK (arm_record.reg_rec_count == 1);
+ SELF_CHECK (arm_record.arm_regs[0] == 5);
+ }
+
+ /* 32-bit Thumb-2 instructions. */
+ {
+ insn_decode_record arm_record;

- memset (&arm_record, 0, sizeof (insn_decode_record));
- arm_record.gdbarch = gdbarch;
+ memset (&arm_record, 0, sizeof (insn_decode_record));
+ arm_record.gdbarch = gdbarch;

- static const uint16_t insns[] = {
- /* 1d ee 70 7f mrc 15, 0, r7, cr13, cr0, {3} */
- 0xee1d, 0x7f70,
- };
+ /* 1d ee 70 7f mrc 15, 0, r7, cr13, cr0, {3} */
+ static const uint16_t insns[2][2] = {
+ { 0x7f70, 0xee1d }, /* big */
+ { 0xee1d, 0x7f70 }, /* little */
+ };

- enum bfd_endian endian = gdbarch_byte_order_for_code (arm_record.gdbarch);
- instruction_reader_thumb reader (endian, insns);
- int ret = decode_insn (reader, &arm_record, THUMB2_RECORD,
- THUMB2_INSN_SIZE_BYTES);
+ instruction_reader_thumb reader (endian, insns[endian]);
+ int ret = decode_insn (reader, &arm_record, THUMB2_RECORD,
+ THUMB2_INSN_SIZE_BYTES);

- SELF_CHECK (ret == 0);
- SELF_CHECK (arm_record.mem_rec_count == 0);
- SELF_CHECK (arm_record.reg_rec_count == 1);
- SELF_CHECK (arm_record.arm_regs[0] == 7);
- }
+ SELF_CHECK (ret == 0);
+ SELF_CHECK (arm_record.mem_rec_count == 0);
+ SELF_CHECK (arm_record.reg_rec_count == 1);
+ SELF_CHECK (arm_record.arm_regs[0] == 7);
+ }
+ }
}
} // namespace selftests
#endif /* GDB_SELF_TEST */
--
2.16.2