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);

-- 

Reply via email to