This is an automated email from Gerrit. "Antonio Borneo <borneo.anto...@gmail.com>" just uploaded a new patch set to Gerrit, which you can find at https://review.openocd.org/c/openocd/+/7434
-- gerrit commit e3c05d54d5f118f88f7ccbbc4f1a74cd8028a204 Author: Antonio Borneo <borneo.anto...@gmail.com> Date: Wed Jan 4 23:42:00 2023 +0100 server: gdb: ignore mem read during gdb_sync ARMv8-A provides the feature of Exclusive access instructions [1], that allows a memory address to be accessed exclusively within a block of instructions. The block starts with a 'Load Exclusive' instruction and ends with a 'Store Exclusive' instruction. While executing "stepi" command in GDB, GDB detects the Exclusive access block and executes it atomically by adding a breakpoint at the end of the block. GDB detects the Exclusive access blocks by reading from memory the next instruction, checking if it is a 'Load Exclusive' and then reading ahead to look for the end of the block [2]. Such GDB memory accesses can cause the target to crash when GDB uses invalid addresses, e.g. by executing this usual sequence of commands: monitor reset halt monitor gdb_sync stepi The command 'gdb_sync' is used to inform OpenOCD that GDB is not anymore in sync with the target and that a following 'stepi' will be used to re-sync GDB with target. But at the very beginning of 'stepi', GDB will issue memory reads at addresses that were valid 'before' the 'reset halt' but which are probably not valid anymore. If by chance the invalid address contains a value corresponding to a 'Load Exclusive' instruction, GDB will use breakpoints and will not send the 'stepi' command to OpenOCD, invalidating the sequence 'gdb_sync' + "stepi'. Preventing the memory access from GDB side, by temporarily setting some memory attribute, e.g. set mem inaccessible-by-default mem 0 4 ro 8 nocache doesn't work as it causes 'stepi' to return a read error Cannot access memory at address 0xffff800008e6ad7c that blocks the execution of 'stepi'. Make OpenOCD able to ignore the memory read from GDB after the command 'gdb_sync', as every address known by GDB has now to be considered as invalid. Log a debug message and gracefully return zeros to GDB. Apply this change for every target, not only for aarch64, as the GDB addresses are always suppose to be invalid after a 'gdb_sync'. So far, there is no reason to extend this to memory write too. Link: [1] https://developer.arm.com/documentation/100934/0100/Exclusive-access-instructions Link: [2] https://sourceware.org/git/?p=binutils-gdb.git;a=blob;f=gdb/aarch64-tdep.c;hb=refs/tags/gdb-12.1-release#l2876 Change-Id: I6e0554cfbf475ef34d483ee944e1df70ad417e92 Signed-off-by: Antonio Borneo <borneo.anto...@gmail.com> diff --git a/src/server/gdb_server.c b/src/server/gdb_server.c index d8dbc2c8b7..ed0f5853c1 100644 --- a/src/server/gdb_server.c +++ b/src/server/gdb_server.c @@ -1492,6 +1492,7 @@ static int gdb_read_memory_packet(struct connection *connection, char const *packet, int packet_size) { struct target *target = get_target_from_connection(connection); + struct gdb_connection *gdb_connection = connection->priv; char *separator; uint64_t addr = 0; uint32_t len = 0; @@ -1519,6 +1520,16 @@ static int gdb_read_memory_packet(struct connection *connection, return ERROR_OK; } + if (gdb_connection->sync) { + LOG_TARGET_DEBUG(target, "gdb_sync dummy read: addr: 0x%" PRIx64 ", len: 0x%8.8" PRIx32, addr, len); + hex_buffer = malloc(len * 2 + 1); + memset(hex_buffer, '0', len * 2); + hex_buffer[len * 2] = 0; + gdb_put_packet(connection, hex_buffer, len * 2); + free(hex_buffer); + return ERROR_OK; + } + buffer = malloc(len); LOG_DEBUG("addr: 0x%16.16" PRIx64 ", len: 0x%8.8" PRIx32 "", addr, len); --