target: make local symbols static
[fw/openocd] / src / target / breakpoints.c
index 959171460ea771d3de7b1d24c7be48d3d7f82a8e..2653cbd7b8b7c4f9715b1c52e7b2043932100b98 100644 (file)
@@ -1,22 +1,11 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
 /***************************************************************************
  *   Copyright (C) 2005 by Dominic Rath                                    *
  *   Dominic.Rath@gmx.de                                                   *
  *                                                                         *
  *   Copyright (C) ST-Ericsson SA 2011                                     *
  *   michel.jaouen@stericsson.com : smp minimum support                    *
- *                                                                         *
- *   This program is free software; you can redistribute it and/or modify  *
- *   it under the terms of the GNU General Public License as published by  *
- *   the Free Software Foundation; either version 2 of the License, or     *
- *   (at your option) any later version.                                   *
- *                                                                         *
- *   This program is distributed in the hope that it will be useful,       *
- *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
- *   GNU General Public License for more details.                          *
- *                                                                         *
- *   You should have received a copy of the GNU General Public License     *
- *   along with this program.  If not, see <http://www.gnu.org/licenses/>. *
  ***************************************************************************/
 
 #ifdef HAVE_CONFIG_H
@@ -26,6 +15,7 @@
 #include "target.h"
 #include <helper/log.h>
 #include "breakpoints.h"
+#include "smp.h"
 
 static const char * const breakpoint_type_strings[] = {
        "hardware",
@@ -41,8 +31,8 @@ static const char * const watchpoint_rw_strings[] = {
 /* monotonic counter/id-number for breakpoints and watch points */
 static int bpwp_unique_id;
 
-int breakpoint_add_internal(struct target *target,
-       uint32_t address,
+static int breakpoint_add_internal(struct target *target,
+       target_addr_t address,
        uint32_t length,
        enum breakpoint_type type)
 {
@@ -50,19 +40,16 @@ int breakpoint_add_internal(struct target *target,
        struct breakpoint **breakpoint_p = &target->breakpoints;
        const char *reason;
        int retval;
-       int n;
 
-       n = 0;
        while (breakpoint) {
-               n++;
                if (breakpoint->address == address) {
                        /* FIXME don't assume "same address" means "same
                         * breakpoint" ... check all the parameters before
                         * succeeding.
                         */
-                       LOG_DEBUG("Duplicate Breakpoint address: 0x%08" PRIx32 " (BP %" PRIu32 ")",
+                       LOG_ERROR("Duplicate Breakpoint address: " TARGET_ADDR_FMT " (BP %" PRIu32 ")",
                                address, breakpoint->unique_id);
-                       return ERROR_OK;
+                       return ERROR_TARGET_DUPLICATE_BREAKPOINT;
                }
                breakpoint_p = &breakpoint->next;
                breakpoint = breakpoint->next;
@@ -73,7 +60,7 @@ int breakpoint_add_internal(struct target *target,
        (*breakpoint_p)->asid = 0;
        (*breakpoint_p)->length = length;
        (*breakpoint_p)->type = type;
-       (*breakpoint_p)->set = 0;
+       (*breakpoint_p)->is_set = false;
        (*breakpoint_p)->orig_instr = malloc(length);
        (*breakpoint_p)->next = NULL;
        (*breakpoint_p)->unique_id = bpwp_unique_id++;
@@ -98,7 +85,9 @@ fail:
                        return retval;
        }
 
-       LOG_DEBUG("added %s breakpoint at 0x%8.8" PRIx32 " of length 0x%8.8x, (BPID: %" PRIu32 ")",
+       LOG_DEBUG("[%d] added %s breakpoint at " TARGET_ADDR_FMT
+                       " of length 0x%8.8x, (BPID: %" PRIu32 ")",
+               target->coreid,
                breakpoint_type_strings[(*breakpoint_p)->type],
                (*breakpoint_p)->address, (*breakpoint_p)->length,
                (*breakpoint_p)->unique_id);
@@ -106,7 +95,7 @@ fail:
        return ERROR_OK;
 }
 
-int context_breakpoint_add_internal(struct target *target,
+static int context_breakpoint_add_internal(struct target *target,
        uint32_t asid,
        uint32_t length,
        enum breakpoint_type type)
@@ -114,19 +103,16 @@ int context_breakpoint_add_internal(struct target *target,
        struct breakpoint *breakpoint = target->breakpoints;
        struct breakpoint **breakpoint_p = &target->breakpoints;
        int retval;
-       int n;
 
-       n = 0;
        while (breakpoint) {
-               n++;
                if (breakpoint->asid == asid) {
                        /* FIXME don't assume "same address" means "same
                         * breakpoint" ... check all the parameters before
                         * succeeding.
                         */
-                       LOG_DEBUG("Duplicate Breakpoint asid: 0x%08" PRIx32 " (BP %" PRIu32 ")",
+                       LOG_ERROR("Duplicate Breakpoint asid: 0x%08" PRIx32 " (BP %" PRIu32 ")",
                                asid, breakpoint->unique_id);
-                       return -1;
+                       return ERROR_TARGET_DUPLICATE_BREAKPOINT;
                }
                breakpoint_p = &breakpoint->next;
                breakpoint = breakpoint->next;
@@ -137,7 +123,7 @@ int context_breakpoint_add_internal(struct target *target,
        (*breakpoint_p)->asid = asid;
        (*breakpoint_p)->length = length;
        (*breakpoint_p)->type = type;
-       (*breakpoint_p)->set = 0;
+       (*breakpoint_p)->is_set = false;
        (*breakpoint_p)->orig_instr = malloc(length);
        (*breakpoint_p)->next = NULL;
        (*breakpoint_p)->unique_id = bpwp_unique_id++;
@@ -158,8 +144,8 @@ int context_breakpoint_add_internal(struct target *target,
        return ERROR_OK;
 }
 
-int hybrid_breakpoint_add_internal(struct target *target,
-       uint32_t address,
+static int hybrid_breakpoint_add_internal(struct target *target,
+       target_addr_t address,
        uint32_t asid,
        uint32_t length,
        enum breakpoint_type type)
@@ -167,22 +153,20 @@ int hybrid_breakpoint_add_internal(struct target *target,
        struct breakpoint *breakpoint = target->breakpoints;
        struct breakpoint **breakpoint_p = &target->breakpoints;
        int retval;
-       int n;
-       n = 0;
+
        while (breakpoint) {
-               n++;
                if ((breakpoint->asid == asid) && (breakpoint->address == address)) {
                        /* FIXME don't assume "same address" means "same
                         * breakpoint" ... check all the parameters before
                         * succeeding.
                         */
-                       LOG_DEBUG("Duplicate Hybrid Breakpoint asid: 0x%08" PRIx32 " (BP %" PRIu32 ")",
+                       LOG_ERROR("Duplicate Hybrid Breakpoint asid: 0x%08" PRIx32 " (BP %" PRIu32 ")",
                                asid, breakpoint->unique_id);
-                       return -1;
+                       return ERROR_TARGET_DUPLICATE_BREAKPOINT;
                } else if ((breakpoint->address == address) && (breakpoint->asid == 0)) {
-                       LOG_DEBUG("Duplicate Breakpoint IVA: 0x%08" PRIx32 " (BP %" PRIu32 ")",
+                       LOG_ERROR("Duplicate Breakpoint IVA: " TARGET_ADDR_FMT " (BP %" PRIu32 ")",
                                address, breakpoint->unique_id);
-                       return -1;
+                       return ERROR_TARGET_DUPLICATE_BREAKPOINT;
 
                }
                breakpoint_p = &breakpoint->next;
@@ -193,7 +177,7 @@ int hybrid_breakpoint_add_internal(struct target *target,
        (*breakpoint_p)->asid = asid;
        (*breakpoint_p)->length = length;
        (*breakpoint_p)->type = type;
-       (*breakpoint_p)->set = 0;
+       (*breakpoint_p)->is_set = false;
        (*breakpoint_p)->orig_instr = malloc(length);
        (*breakpoint_p)->next = NULL;
        (*breakpoint_p)->unique_id = bpwp_unique_id++;
@@ -208,7 +192,7 @@ int hybrid_breakpoint_add_internal(struct target *target,
                return retval;
        }
        LOG_DEBUG(
-               "added %s Hybrid breakpoint at address 0x%8.8" PRIx32 " of length 0x%8.8x, (BPID: %" PRIu32 ")",
+               "added %s Hybrid breakpoint at address " TARGET_ADDR_FMT " of length 0x%8.8x, (BPID: %" PRIu32 ")",
                breakpoint_type_strings[(*breakpoint_p)->type],
                (*breakpoint_p)->address,
                (*breakpoint_p)->length,
@@ -218,69 +202,69 @@ int hybrid_breakpoint_add_internal(struct target *target,
 }
 
 int breakpoint_add(struct target *target,
-       uint32_t address,
+       target_addr_t address,
        uint32_t length,
        enum breakpoint_type type)
 {
-       int retval = ERROR_OK;
        if (target->smp) {
                struct target_list *head;
-               struct target *curr;
-               head = target->head;
-               if (type == BKPT_SOFT)
+
+               if (type == BKPT_SOFT) {
+                       head = list_first_entry(target->smp_targets, struct target_list, lh);
                        return breakpoint_add_internal(head->target, address, length, type);
+               }
 
-               while (head != (struct target_list *)NULL) {
-                       curr = head->target;
-                       retval = breakpoint_add_internal(curr, address, length, type);
+               foreach_smp_target(head, target->smp_targets) {
+                       struct target *curr = head->target;
+                       int retval = breakpoint_add_internal(curr, address, length, type);
                        if (retval != ERROR_OK)
                                return retval;
-                       head = head->next;
                }
-               return retval;
-       } else
+
+               return ERROR_OK;
+       } else {
                return breakpoint_add_internal(target, address, length, type);
+       }
 }
+
 int context_breakpoint_add(struct target *target,
        uint32_t asid,
        uint32_t length,
        enum breakpoint_type type)
 {
-       int retval = ERROR_OK;
        if (target->smp) {
                struct target_list *head;
-               struct target *curr;
-               head = target->head;
-               while (head != (struct target_list *)NULL) {
-                       curr = head->target;
-                       retval = context_breakpoint_add_internal(curr, asid, length, type);
+
+               foreach_smp_target(head, target->smp_targets) {
+                       struct target *curr = head->target;
+                       int retval = context_breakpoint_add_internal(curr, asid, length, type);
                        if (retval != ERROR_OK)
                                return retval;
-                       head = head->next;
                }
-               return retval;
-       } else
+
+               return ERROR_OK;
+       } else {
                return context_breakpoint_add_internal(target, asid, length, type);
+       }
 }
+
 int hybrid_breakpoint_add(struct target *target,
-       uint32_t address,
+       target_addr_t address,
        uint32_t asid,
        uint32_t length,
        enum breakpoint_type type)
 {
-       int retval = ERROR_OK;
        if (target->smp) {
                struct target_list *head;
-               struct target *curr;
-               head = target->head;
-               while (head != (struct target_list *)NULL) {
-                       curr = head->target;
-                       retval = hybrid_breakpoint_add_internal(curr, address, asid, length, type);
+
+               foreach_smp_target(head, target->smp_targets) {
+                       struct target *curr = head->target;
+                       int retval = hybrid_breakpoint_add_internal(curr, address, asid, length, type);
                        if (retval != ERROR_OK)
                                return retval;
-                       head = head->next;
                }
-               return retval;
+
+               return ERROR_OK;
        } else
                return hybrid_breakpoint_add_internal(target, address, asid, length, type);
 }
@@ -299,7 +283,7 @@ static void breakpoint_free(struct target *target, struct breakpoint *breakpoint
                breakpoint = breakpoint->next;
        }
 
-       if (breakpoint == NULL)
+       if (!breakpoint)
                return;
 
        retval = target_remove_breakpoint(target, breakpoint);
@@ -310,16 +294,13 @@ static void breakpoint_free(struct target *target, struct breakpoint *breakpoint
        free(breakpoint);
 }
 
-int breakpoint_remove_internal(struct target *target, uint32_t address)
+static int breakpoint_remove_internal(struct target *target, target_addr_t address)
 {
        struct breakpoint *breakpoint = target->breakpoints;
 
        while (breakpoint) {
-               if ((breakpoint->address == address) && (breakpoint->asid == 0))
-                       break;
-               else if ((breakpoint->address == 0) && (breakpoint->asid == address))
-                       break;
-               else if ((breakpoint->address == address) && (breakpoint->asid != 0))
+               if ((breakpoint->address == address) ||
+                   (breakpoint->address == 0 && breakpoint->asid == address))
                        break;
                breakpoint = breakpoint->next;
        }
@@ -329,33 +310,58 @@ int breakpoint_remove_internal(struct target *target, uint32_t address)
                return 1;
        } else {
                if (!target->smp)
-                       LOG_ERROR("no breakpoint at address 0x%8.8" PRIx32 " found", address);
+                       LOG_ERROR("no breakpoint at address " TARGET_ADDR_FMT " found", address);
                return 0;
        }
 }
-void breakpoint_remove(struct target *target, uint32_t address)
+
+static void breakpoint_remove_all_internal(struct target *target)
+{
+       struct breakpoint *breakpoint = target->breakpoints;
+
+       while (breakpoint) {
+               struct breakpoint *tmp = breakpoint;
+               breakpoint = breakpoint->next;
+               breakpoint_free(target, tmp);
+       }
+}
+
+void breakpoint_remove(struct target *target, target_addr_t address)
 {
-       int found = 0;
        if (target->smp) {
+               unsigned int num_breakpoints = 0;
                struct target_list *head;
-               struct target *curr;
-               head = target->head;
-               while (head != (struct target_list *)NULL) {
-                       curr = head->target;
-                       found += breakpoint_remove_internal(curr, address);
-                       head = head->next;
+
+               foreach_smp_target(head, target->smp_targets) {
+                       struct target *curr = head->target;
+                       num_breakpoints += breakpoint_remove_internal(curr, address);
                }
-               if (found == 0)
-                       LOG_ERROR("no breakpoint at address 0x%8.8" PRIx32 " found", address);
-       } else
+               if (!num_breakpoints)
+                       LOG_ERROR("no breakpoint at address " TARGET_ADDR_FMT " found", address);
+       } else {
                breakpoint_remove_internal(target, address);
+       }
 }
 
-void breakpoint_clear_target_internal(struct target *target)
+void breakpoint_remove_all(struct target *target)
+{
+       if (target->smp) {
+               struct target_list *head;
+
+               foreach_smp_target(head, target->smp_targets) {
+                       struct target *curr = head->target;
+                       breakpoint_remove_all_internal(curr);
+               }
+       } else {
+               breakpoint_remove_all_internal(target);
+       }
+}
+
+static void breakpoint_clear_target_internal(struct target *target)
 {
        LOG_DEBUG("Delete all breakpoints for target: %s",
                target_name(target));
-       while (target->breakpoints != NULL)
+       while (target->breakpoints)
                breakpoint_free(target, target->breakpoints);
 }
 
@@ -363,19 +369,17 @@ void breakpoint_clear_target(struct target *target)
 {
        if (target->smp) {
                struct target_list *head;
-               struct target *curr;
-               head = target->head;
-               while (head != (struct target_list *)NULL) {
-                       curr = head->target;
+
+               foreach_smp_target(head, target->smp_targets) {
+                       struct target *curr = head->target;
                        breakpoint_clear_target_internal(curr);
-                       head = head->next;
                }
-       } else
+       } else {
                breakpoint_clear_target_internal(target);
-
+       }
 }
 
-struct breakpoint *breakpoint_find(struct target *target, uint32_t address)
+struct breakpoint *breakpoint_find(struct target *target, target_addr_t address)
 {
        struct breakpoint *breakpoint = target->breakpoints;
 
@@ -388,8 +392,8 @@ struct breakpoint *breakpoint_find(struct target *target, uint32_t address)
        return NULL;
 }
 
-int watchpoint_add(struct target *target, uint32_t address, uint32_t length,
-       enum watchpoint_rw rw, uint32_t value, uint32_t mask)
+static int watchpoint_add_internal(struct target *target, target_addr_t address,
+               uint32_t length, enum watchpoint_rw rw, uint32_t value, uint32_t mask)
 {
        struct watchpoint *watchpoint = target->watchpoints;
        struct watchpoint **watchpoint_p = &target->watchpoints;
@@ -402,8 +406,8 @@ int watchpoint_add(struct target *target, uint32_t address, uint32_t length,
                                || watchpoint->value != value
                                || watchpoint->mask != mask
                                || watchpoint->rw != rw) {
-                               LOG_ERROR("address 0x%8.8" PRIx32
-                                       "already has watchpoint %d",
+                               LOG_ERROR("address " TARGET_ADDR_FMT
+                                       " already has watchpoint %d",
                                        address, watchpoint->unique_id);
                                return ERROR_FAIL;
                        }
@@ -436,7 +440,7 @@ int watchpoint_add(struct target *target, uint32_t address, uint32_t length,
                default:
                        reason = "unrecognized error";
 bye:
-                       LOG_ERROR("can't add %s watchpoint at 0x%8.8" PRIx32 ", %s",
+                       LOG_ERROR("can't add %s watchpoint at " TARGET_ADDR_FMT ", %s",
                                watchpoint_rw_strings[(*watchpoint_p)->rw],
                                address, reason);
                        free(*watchpoint_p);
@@ -444,8 +448,9 @@ bye:
                        return retval;
        }
 
-       LOG_DEBUG("added %s watchpoint at 0x%8.8" PRIx32
-               " of length 0x%8.8" PRIx32 " (WPID: %d)",
+       LOG_DEBUG("[%d] added %s watchpoint at " TARGET_ADDR_FMT
+                       " of length 0x%8.8" PRIx32 " (WPID: %d)",
+               target->coreid,
                watchpoint_rw_strings[(*watchpoint_p)->rw],
                (*watchpoint_p)->address,
                (*watchpoint_p)->length,
@@ -454,6 +459,26 @@ bye:
        return ERROR_OK;
 }
 
+int watchpoint_add(struct target *target, target_addr_t address,
+               uint32_t length, enum watchpoint_rw rw, uint32_t value, uint32_t mask)
+{
+       if (target->smp) {
+               struct target_list *head;
+
+               foreach_smp_target(head, target->smp_targets) {
+                       struct target *curr = head->target;
+                       int retval = watchpoint_add_internal(curr, address, length, rw, value, mask);
+                       if (retval != ERROR_OK)
+                               return retval;
+               }
+
+               return ERROR_OK;
+       } else {
+               return watchpoint_add_internal(target, address, length, rw, value,
+                               mask);
+       }
+}
+
 static void watchpoint_free(struct target *target, struct watchpoint *watchpoint_to_remove)
 {
        struct watchpoint *watchpoint = target->watchpoints;
@@ -467,7 +492,7 @@ static void watchpoint_free(struct target *target, struct watchpoint *watchpoint
                watchpoint = watchpoint->next;
        }
 
-       if (watchpoint == NULL)
+       if (!watchpoint)
                return;
        retval = target_remove_watchpoint(target, watchpoint);
        LOG_DEBUG("free WPID: %d --> %d", watchpoint->unique_id, retval);
@@ -475,7 +500,7 @@ static void watchpoint_free(struct target *target, struct watchpoint *watchpoint
        free(watchpoint);
 }
 
-void watchpoint_remove(struct target *target, uint32_t address)
+static int watchpoint_remove_internal(struct target *target, target_addr_t address)
 {
        struct watchpoint *watchpoint = target->watchpoints;
 
@@ -485,21 +510,43 @@ void watchpoint_remove(struct target *target, uint32_t address)
                watchpoint = watchpoint->next;
        }
 
-       if (watchpoint)
+       if (watchpoint) {
                watchpoint_free(target, watchpoint);
-       else
-               LOG_ERROR("no watchpoint at address 0x%8.8" PRIx32 " found", address);
+               return 1;
+       } else {
+               if (!target->smp)
+                       LOG_ERROR("no watchpoint at address " TARGET_ADDR_FMT " found", address);
+               return 0;
+       }
+}
+
+void watchpoint_remove(struct target *target, target_addr_t address)
+{
+       if (target->smp) {
+               unsigned int num_watchpoints = 0;
+               struct target_list *head;
+
+               foreach_smp_target(head, target->smp_targets) {
+                       struct target *curr = head->target;
+                       num_watchpoints += watchpoint_remove_internal(curr, address);
+               }
+               if (num_watchpoints == 0)
+                       LOG_ERROR("no watchpoint at address " TARGET_ADDR_FMT " num_watchpoints", address);
+       } else {
+               watchpoint_remove_internal(target, address);
+       }
 }
 
 void watchpoint_clear_target(struct target *target)
 {
        LOG_DEBUG("Delete all watchpoints for target: %s",
                target_name(target));
-       while (target->watchpoints != NULL)
+       while (target->watchpoints)
                watchpoint_free(target, target->watchpoints);
 }
 
-int watchpoint_hit(struct target *target, enum watchpoint_rw *rw, uint32_t *address)
+int watchpoint_hit(struct target *target, enum watchpoint_rw *rw,
+                  target_addr_t *address)
 {
        int retval;
        struct watchpoint *hit_watchpoint;
@@ -511,7 +558,7 @@ int watchpoint_hit(struct target *target, enum watchpoint_rw *rw, uint32_t *addr
        *rw = hit_watchpoint->rw;
        *address = hit_watchpoint->address;
 
-       LOG_DEBUG("Found hit watchpoint at 0x%8.8" PRIx32 " (WPID: %d)",
+       LOG_DEBUG("Found hit watchpoint at " TARGET_ADDR_FMT " (WPID: %d)",
                hit_watchpoint->address,
                hit_watchpoint->unique_id);