+2021-01-27 Matthew Malcomson <matthew.malcomson@arm.com>
+
+ * aarch64-tdep.c (aarch64_displaced_step_others): Account for
+ BLR and BR instructions.
+ * arch/aarch64-insn.h (enum aarch64_opcodes): Add BR opcode.
+ (enum aarch64_masks): New.
+
2021-01-26 Tom Tromey <tromey@adacore.com>
* windows-nat.c (DEBUG_EXEC, DEBUG_EVENTS, DEBUG_MEM)
struct aarch64_displaced_step_data *dsd
= (struct aarch64_displaced_step_data *) data;
- aarch64_emit_insn (dsd->insn_buf, insn);
- dsd->insn_count = 1;
-
- if ((insn & 0xfffffc1f) == 0xd65f0000)
+ uint32_t masked_insn = (insn & CLEAR_Rn_MASK);
+ if (masked_insn == BLR)
{
- /* RET */
- dsd->dsc->pc_adjust = 0;
+ /* Emit a BR to the same register and then update LR to the original
+ address (similar to aarch64_displaced_step_b). */
+ aarch64_emit_insn (dsd->insn_buf, insn & 0xffdfffff);
+ regcache_cooked_write_unsigned (dsd->regs, AARCH64_LR_REGNUM,
+ data->insn_addr + 4);
}
+ else
+ aarch64_emit_insn (dsd->insn_buf, insn);
+ dsd->insn_count = 1;
+
+ if (masked_insn == RET || masked_insn == BR || masked_insn == BLR)
+ dsd->dsc->pc_adjust = 0;
else
dsd->dsc->pc_adjust = 4;
}
CBNZ = 0x21000000 | B,
TBZ = 0x36000000 | B,
TBNZ = 0x37000000 | B,
+ /* BR 1101 0110 0001 1111 0000 00rr rrr0 0000 */
/* BLR 1101 0110 0011 1111 0000 00rr rrr0 0000 */
+ BR = 0xd61f0000,
BLR = 0xd63f0000,
/* RET 1101 0110 0101 1111 0000 00rr rrr0 0000 */
RET = 0xd65f0000,
NOP = (0 << 5) | HINT,
};
+/* List of useful masks. */
+enum aarch64_masks
+{
+ /* Used for masking out an Rn argument from an opcode. */
+ CLEAR_Rn_MASK = 0xfffffc1f,
+};
+
/* Representation of a general purpose register of the form xN or wN.
This type is used by emitting functions that take registers as operands. */
+2021-01-27 Matthew Malcomson <matthew.malcomson@arm.com>
+
+ * gdb.arch/insn-reloc.c: Add tests for BR and BLR.
+
2021-01-26 Tom de Vries <tdevries@suse.de>
* gdb.threads/killed-outside.exp: Allow regular output.
: : : "x30"); /* Test that LR is updated correctly. */
}
+/* Make sure we can relocate a BR instruction.
+
+ ... Set x0 to target
+ set_point12:
+ BR x0 ; jump to target (tracepoint here).
+ fail()
+ return
+ target:
+ pass()
+ end
+
+ */
+
+static void
+can_relocate_br (void)
+{
+ int ok = 0;
+
+ asm goto (" adr x0, %l0\n"
+ "set_point12:\n"
+ " br x0\n"
+ :
+ :
+ : "x0"
+ : madejump);
+
+ fail ();
+ return;
+madejump:
+ pass ();
+}
+
+/* Make sure we can relocate a BLR instruction.
+
+ We use two different functions since the test runner expects one breakpoint
+ per function and we want to test two different things.
+ For BLR we want to test that the BLR actually jumps to the relevant
+ function, *and* that it sets the LR register correctly.
+
+ Hence we create one testcase that jumps to `pass` using BLR, and one
+ testcase that jumps to `pass` if BLR has set the LR correctly.
+
+ -- can_relocate_blr_jumps
+ ... Set x0 to pass
+ set_point13:
+ BLR x0 ; jump to pass (tracepoint here).
+
+ -- can_relocate_blr_sets_lr
+ ... Set x0 to foo
+ set_point14:
+ BLR x0 ; jumps somewhere else (tracepoint here).
+ BL pass ; ensures the LR was set correctly by the BLR.
+
+ */
+
+static void
+can_relocate_blr_jumps (void)
+{
+ int ok = 0;
+
+ /* Test BLR indeed jumps to the target. */
+ asm ("set_point13:\n"
+ " blr %[address]\n"
+ : : [address] "r" (&pass) : "x30");
+}
+
+static void
+can_relocate_blr_sets_lr (void)
+{
+ int ok = 0;
+
+ /* Test BLR sets the LR correctly. */
+ asm ("set_point14:\n"
+ " blr %[address]\n"
+ " bl pass\n"
+ : : [address] "r" (&foo) : "x30");
+}
+
#endif
/* Functions testing relocations need to be placed here. GDB will read
can_relocate_ldr,
can_relocate_bcond_false,
can_relocate_bl,
+ can_relocate_br,
+ can_relocate_blr_jumps,
+ can_relocate_blr_sets_lr,
#endif
};