This is an automated email from Gerrit.

"Tomas Vanek <van...@fbl.cz>" just uploaded a new patch set to Gerrit, which 
you can find at https://review.openocd.org/c/openocd/+/6774

-- gerrit

commit ebcafdeddd636da03c1ea67fcca95ef1c088620b
Author: Tomas Vanek <van...@fbl.cz>
Date:   Mon Dec 6 18:56:44 2021 +0100

    target/cortex_m: workaround setting invalid bp due to gdb bug
    
    Cortex-M uses "magic" addresses for exception return and lockup.
    The magic addresses are in execute never range.
    
    GDB bug in 'advance' and 'until' commands causes the magic
    in LR register is not properly handled and GDB tries to set a breakpoint
    at magic address. All tested versions of GDB up to current git master
    suffer from this bug.
    
    If gdb_server propagates the error from breakpoint setting to GDB, commands
    'advance' and 'until' fail without running the target.
    
    How to replicate the problem with gdb (versions 8.3, 9.2, 10.2, 12.0.50)
    and a Cortex-M0/3/4 device with normal app loaded to the flash:
     (gdb) mon reset halt
     (gdb) step
     - synchronize GDB register cache after reset halt
     (gdb) info registers
     - check LR, CPU should set it to 0xffffffff
     (gdb) advance main
     Warning:
     Cannot insert breakpoint 0.
     Cannot access memory at address 0xfffffffe
    
     Command aborted.
    
    ----Part of openocd -d3 log:----
    Debug: gdb_log_incoming_packet(): received packet: Z0,fffffffe,2
    Debug: gdb_breakpoint_watchpoint_packet(): [stm32g4x.cpu]
    Debug: cmsis_dap_swd_read_process(): SWD ack not OK @ 4 FAULT
     ...
    Error: mem_ap_read(): Failed to read memory at 0xfffff000
    Error: breakpoint_add_internal(): can't add breakpoint: unknown reason
    --------------------------------
    
    Refuse setting a breakpoint at magic address.
    Do not propagate this error to GDB.
    
    Change-Id: I18aeab9e8a71c3eadbd5cf8782f570ce05eb0118
    Signed-off-by: Tomas Vanek <van...@fbl.cz>

diff --git a/src/server/gdb_server.c b/src/server/gdb_server.c
index 0d2d1ae2c..6cb2d7ca5 100644
--- a/src/server/gdb_server.c
+++ b/src/server/gdb_server.c
@@ -1750,6 +1750,17 @@ static int gdb_breakpoint_watchpoint_packet(struct 
connection *connection,
                case 1:
                        if (packet[0] == 'Z') {
                                retval = breakpoint_add(target, address, size, 
bp_type);
+                               /*
+                                * GDB bug workaround:
+                                * 'advance' and 'until' commands do not handle 
EXC_RETURN magic
+                                * in LR register and try to set breakpoint at 
magic address.
+                                * Propagation of the error to GDB would 
prevent target
+                                * from run. Just ignore the error.
+                                */
+                               if (retval == ERROR_TARGET_MAGIC_ADDRESS) {
+                                       LOG_DEBUG("GDB bug workaround: 
Breakpoint requested at magic address. Ignore to allow the target run.");
+                                       retval = ERROR_OK;
+                               }
                                if (retval != ERROR_OK) {
                                        retval = gdb_error(connection, retval);
                                        if (retval != ERROR_OK)
diff --git a/src/target/cortex_m.c b/src/target/cortex_m.c
index 649ee32f2..3b92c0db2 100644
--- a/src/target/cortex_m.c
+++ b/src/target/cortex_m.c
@@ -1586,6 +1586,18 @@ int cortex_m_set_breakpoint(struct target *target, 
struct breakpoint *breakpoint
                return ERROR_OK;
        }
 
+       /*
+        * GDB bug workaround:
+        * 'advance' and 'until' commands do not handle EXC_RETURN magic
+        * in LR register and try to set breakpoint at magic address.
+        * gdb_server will not propagate this error to GDB.
+        */
+       if (cortex_m_is_magic(breakpoint->address)) {
+               LOG_ERROR("Refusing to set breakpoint at magic address "
+                       TARGET_ADDR_FMT, breakpoint->address);
+               return ERROR_TARGET_MAGIC_ADDRESS;
+       }
+
        if (breakpoint->type == BKPT_HARD) {
                uint32_t fpcr_value;
                while (comparator_list[fp_num].used && (fp_num < 
cortex_m->fp_num_code))

-- 

Reply via email to