This is an automated email from Gerrit.

"Jan Matyas <mat...@codasip.com>" just uploaded a new patch set to Gerrit, 
which you can find at https://review.openocd.org/c/openocd/+/6880

-- gerrit

commit ada5cf8665153c313f83f6894e9dd6b7bc76be44
Author: Jan Matyas <mat...@codasip.com>
Date:   Fri Mar 18 16:19:08 2022 +0100

    target: Add option to disable SW breakpoints
    
    Added "my_target configure -allow-sw-breaks on|off".
    Default: on.
    
    This option is important when debugging multiple CPUs
    /cores with shared memory as separate targets (using
    separate GDB instances).
    
    In such cases, SW breakpoints cannot be reliably used:
    each debugger only keeps track of SW breaks inserted
    by itself but is still affected by breaks from other
    debuggers - due to the shared memory.
    
    If where was no option to disable the SW breaks, the
    following issues would occur during the debugging:
    
    - 1) Debugger may get unexpectedly stopped by SW BPs
      that they do not know about as they were placed by
      other debuggers.
    
    - 2) If multiple breakpoints are placed onto the same
      address, the breakpoint instruction may get stuck
      in the memory even when all debuggers removed those
      SW BPs (if the removal took place in a not favourable
      order).
    
    The option added in this commit allows the user to
    disable the SW breaks in such scenarios and still be
    able to run reliable debug sessions.
    
    Change-Id: I6857868347260eced8e96429b43209dea25d220e
    Signed-off-by: Jan Matyas <mat...@codasip.com>

diff --git a/doc/openocd.texi b/doc/openocd.texi
index 0cd9621ff4..98a7f76a23 100644
--- a/doc/openocd.texi
+++ b/doc/openocd.texi
@@ -4923,6 +4923,12 @@ where it is a mandatory configuration for the target run 
control.
 @xref{armcrosstrigger,,ARM Cross-Trigger Interface},
 for instruction on how to declare and control a CTI instance.
 
+@item @code{-allow-sw-breaks} @var{on|off} -- allow to disable SW breakpoints 
+on a per-target basis. By default, SW breakpoints are enabled (@var{on}) for
+all targets.  Disabling SW breakpoints may be useful when debugging multiple 
+targets with shared program memory, in which case the use of SW breakpoints by
+multiple debuggers would lead to clashes and unexpected debug behavior.
+
 @anchor{gdbportoverride}
 @item @code{-gdb-port} @var{number} -- see command @command{gdb_port} for the
 possible values of the parameter @var{number}, which are not only numeric 
values.
diff --git a/src/target/breakpoints.c b/src/target/breakpoints.c
index 8439ff395e..4270502e61 100644
--- a/src/target/breakpoints.c
+++ b/src/target/breakpoints.c
@@ -217,6 +217,11 @@ int breakpoint_add(struct target *target,
        uint32_t length,
        enum breakpoint_type type)
 {
+       if (type == BKPT_SOFT && !target->allow_sw_breaks) {
+               LOG_TARGET_WARNING(target, "can't add breakpoint: SW BPs are 
disabled");
+               return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
+       }
+
        if (target->smp) {
                struct target_list *head;
 
diff --git a/src/target/target.c b/src/target/target.c
index 7b8271339c..b7ec3a58cb 100644
--- a/src/target/target.c
+++ b/src/target/target.c
@@ -5293,6 +5293,7 @@ enum target_cfg_param {
        TCFG_DEFER_EXAMINE,
        TCFG_GDB_PORT,
        TCFG_GDB_MAX_CONNECTIONS,
+       TCFG_ALLOW_SW_BREAKS,
 };
 
 static struct jim_nvp nvp_config_opts[] = {
@@ -5310,6 +5311,7 @@ static struct jim_nvp nvp_config_opts[] = {
        { .name = "-defer-examine",    .value = TCFG_DEFER_EXAMINE },
        { .name = "-gdb-port",         .value = TCFG_GDB_PORT },
        { .name = "-gdb-max-connections",   .value = TCFG_GDB_MAX_CONNECTIONS },
+       { .name = "-allow-sw-breaks",  .value = TCFG_ALLOW_SW_BREAKS },
        { .name = NULL, .value = -1 }
 };
 
@@ -5572,6 +5574,7 @@ no_params:
                        Jim_SetResultString(goi->interp, 
target->tap->dotted_name, -1);
                        /* loop for more e*/
                        break;
+
                case TCFG_DBGBASE:
                        if (goi->isconfigure) {
                                e = jim_getopt_wide(goi, &w);
@@ -5586,6 +5589,7 @@ no_params:
                        Jim_SetResult(goi->interp, Jim_NewIntObj(goi->interp, 
target->dbgbase));
                        /* loop for more */
                        break;
+
                case TCFG_RTOS:
                        /* RTOS */
                        {
@@ -5641,12 +5645,41 @@ no_params:
                                        goto no_params;
                        }
                        Jim_SetResult(goi->interp, Jim_NewIntObj(goi->interp, 
target->gdb_max_connections));
+                       /* loop for more */
                        break;
-               }
+
+               case TCFG_ALLOW_SW_BREAKS:
+                               if (goi->isconfigure) {
+                                               const char *s;
+                                               e = jim_getopt_string(goi, &s, 
NULL);
+                                               if (e != JIM_OK)
+                                                       return e;
+                                               if (strcmp(s, "on") == 0) {
+                                                       LOG_TARGET_INFO(target, 
"SW breakpoints enabled by user");
+                                                       target->allow_sw_breaks 
= true;
+                                               }
+                                               else if (strcmp(s, "off") == 0) 
{
+                                                       LOG_TARGET_INFO(target, 
"SW breakpoints disabled by user");
+                                                       target->allow_sw_breaks 
= false;
+                                               }
+                                               else {
+                                                       
Jim_SetResultString(goi->interp,
+                                                               
"-allow-sw-breaks expects \"on\" or \"off\" argument", -1);
+                                                       return JIM_ERR;
+                                               }
+                               } else {
+                                       if (goi->argc != 0)
+                                               goto no_params;
+                               }
+                               Jim_SetResultString(goi->interp, 
target->allow_sw_breaks ? "on" : "off", -1);
+                               /* loop for more */
+                               break;
+
+               } /* switch (n->value) */
        } /* while (goi->argc) */
 
 
-               /* done - we return */
+       /* done - we return */
        return JIM_OK;
 }
 
@@ -6275,6 +6308,8 @@ static int target_create(struct jim_getopt_info *goi)
        target->gdb_port_override = NULL;
        target->gdb_max_connections = 1;
 
+       target->allow_sw_breaks = true;
+
        /* Do the rest as "configure" options */
        goi->isconfigure = 1;
        e = target_configure(goi, target);
diff --git a/src/target/target.h b/src/target/target.h
index 1f1a354207..f386790e88 100644
--- a/src/target/target.h
+++ b/src/target/target.h
@@ -219,6 +219,17 @@ struct target {
 
        /* The semihosting information, extracted from the target. */
        struct semihosting *semihosting;
+
+       bool allow_sw_breaks;                           /* Option to manually 
disable SW breakpoints on per-target basis.
+                                                                               
 * When SW breaks are disabled, debuggers will typically
+                                                                               
 * fall back to HW breakpoints.
+                                                                               
 *
+                                                                               
 * Disabling SW breaks is useful when debugging multiple
+                                                                               
 * cores with symmetric memory view as independent targets.
+                                                                               
 * SW breakpoints are problematic in this case as they are
+                                                                               
 * inherently shared via the main memory but no debugger
+                                                                               
 * is aware of SW breaks placed by other debuggers. */
+
 };
 
 struct target_list {

-- 

Reply via email to