cortex_a: fix handling of Thumb-2 32bit breakpoints

When debugging Thumb-2 code, Gdb will at times send a
breakpoint packet 'Z0,<addr>,3', the number 3 denoting that
the instruction to break on is 32 bits long. Handle this by
replacing it with two consecutive 16bit Thumb BKPTs and make
sure to save and restore the full, original 32bit
instruction.

Note that this fix is only applicable if you debug a bare-metal program
(like the linux kernel) with the 'wrong' gdb, e.g. use an 
"arm-linux" gdb instead of an "arm-eabi" gdb. But since most people
may not know about the subtle differences between gdb configurations
regarding thumb2 breakpoints it's still valid.

Change-Id: Ib93025faf35b11f0dba747a8c1fc36fd09a4c0f8
Signed-off-by: Matthias Welwarsky <matthias.welwarsky@sysgo.com>
Reviewed-on: http://openocd.zylin.com/4241
Reviewed-by: Matthias Welwarsky <matthias@welwarsky.de>
Tested-by: jenkins
This commit is contained in:
Matthias Welwarsky 2017-10-05 14:50:16 +02:00 committed by Matthias Welwarsky
parent dd60dd84f2
commit b551c62a7f
1 changed files with 12 additions and 0 deletions

View File

@ -1500,10 +1500,22 @@ static int cortex_a_set_breakpoint(struct target *target,
brp_list[brp_i].value); brp_list[brp_i].value);
} else if (breakpoint->type == BKPT_SOFT) { } else if (breakpoint->type == BKPT_SOFT) {
uint8_t code[4]; uint8_t code[4];
/* length == 2: Thumb breakpoint */
if (breakpoint->length == 2) if (breakpoint->length == 2)
buf_set_u32(code, 0, 32, ARMV5_T_BKPT(0x11)); buf_set_u32(code, 0, 32, ARMV5_T_BKPT(0x11));
else else
/* length == 3: Thumb-2 breakpoint, actual encoding is
* a regular Thumb BKPT instruction but we replace a
* 32bit Thumb-2 instruction, so fix-up the breakpoint
* length
*/
if (breakpoint->length == 3) {
buf_set_u32(code, 0, 32, ARMV5_T_BKPT(0x11));
breakpoint->length = 4;
} else
/* length == 4, normal ARM breakpoint */
buf_set_u32(code, 0, 32, ARMV5_BKPT(0x11)); buf_set_u32(code, 0, 32, ARMV5_BKPT(0x11));
retval = target_read_memory(target, retval = target_read_memory(target,
breakpoint->address & 0xFFFFFFFE, breakpoint->address & 0xFFFFFFFE,
breakpoint->length, 1, breakpoint->length, 1,