You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

305 lines
8.1 KiB

  1. /***************************************************************************
  2. * Copyright (C) 2005 by Dominic Rath *
  3. * Dominic.Rath@gmx.de *
  4. * *
  5. * This program is free software; you can redistribute it and/or modify *
  6. * it under the terms of the GNU General Public License as published by *
  7. * the Free Software Foundation; either version 2 of the License, or *
  8. * (at your option) any later version. *
  9. * *
  10. * This program is distributed in the hope that it will be useful, *
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of *
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
  13. * GNU General Public License for more details. *
  14. * *
  15. * You should have received a copy of the GNU General Public License *
  16. * along with this program; if not, write to the *
  17. * Free Software Foundation, Inc., *
  18. * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
  19. ***************************************************************************/
  20. #ifdef HAVE_CONFIG_H
  21. #include "config.h"
  22. #endif
  23. #include "target.h"
  24. #include <helper/log.h>
  25. #include "breakpoints.h"
  26. static char *breakpoint_type_strings[] =
  27. {
  28. "hardware",
  29. "software"
  30. };
  31. static char *watchpoint_rw_strings[] =
  32. {
  33. "read",
  34. "write",
  35. "access"
  36. };
  37. // monotonic counter/id-number for breakpoints and watch points
  38. static int bpwp_unique_id;
  39. int breakpoint_add(struct target *target, uint32_t address, uint32_t length, enum breakpoint_type type)
  40. {
  41. struct breakpoint *breakpoint = target->breakpoints;
  42. struct breakpoint **breakpoint_p = &target->breakpoints;
  43. char *reason;
  44. int retval;
  45. int n;
  46. n = 0;
  47. while (breakpoint)
  48. {
  49. n++;
  50. if (breakpoint->address == address) {
  51. /* FIXME don't assume "same address" means "same
  52. * breakpoint" ... check all the parameters before
  53. * succeeding.
  54. */
  55. LOG_DEBUG("Duplicate Breakpoint address: 0x%08" PRIx32 " (BP %d)",
  56. address, breakpoint->unique_id );
  57. return ERROR_OK;
  58. }
  59. breakpoint_p = &breakpoint->next;
  60. breakpoint = breakpoint->next;
  61. }
  62. (*breakpoint_p) = malloc(sizeof(struct breakpoint));
  63. (*breakpoint_p)->address = address;
  64. (*breakpoint_p)->length = length;
  65. (*breakpoint_p)->type = type;
  66. (*breakpoint_p)->set = 0;
  67. (*breakpoint_p)->orig_instr = malloc(length);
  68. (*breakpoint_p)->next = NULL;
  69. (*breakpoint_p)->unique_id = bpwp_unique_id++;
  70. retval = target_add_breakpoint(target, *breakpoint_p);
  71. switch (retval) {
  72. case ERROR_OK:
  73. break;
  74. case ERROR_TARGET_RESOURCE_NOT_AVAILABLE:
  75. reason = "resource not available";
  76. goto fail;
  77. case ERROR_TARGET_NOT_HALTED:
  78. reason = "target running";
  79. goto fail;
  80. default:
  81. reason = "unknown reason";
  82. fail:
  83. LOG_ERROR("can't add breakpoint: %s", reason);
  84. free((*breakpoint_p)->orig_instr);
  85. free(*breakpoint_p);
  86. *breakpoint_p = NULL;
  87. return retval;
  88. }
  89. LOG_DEBUG("added %s breakpoint at 0x%8.8" PRIx32 " of length 0x%8.8x, (BPID: %d)",
  90. breakpoint_type_strings[(*breakpoint_p)->type],
  91. (*breakpoint_p)->address, (*breakpoint_p)->length,
  92. (*breakpoint_p)->unique_id );
  93. return ERROR_OK;
  94. }
  95. /* free up a breakpoint */
  96. static void breakpoint_free(struct target *target, struct breakpoint *breakpoint_remove)
  97. {
  98. struct breakpoint *breakpoint = target->breakpoints;
  99. struct breakpoint **breakpoint_p = &target->breakpoints;
  100. int retval;
  101. while (breakpoint)
  102. {
  103. if (breakpoint == breakpoint_remove)
  104. break;
  105. breakpoint_p = &breakpoint->next;
  106. breakpoint = breakpoint->next;
  107. }
  108. if (breakpoint == NULL)
  109. return;
  110. retval = target_remove_breakpoint(target, breakpoint);
  111. LOG_DEBUG("free BPID: %d --> %d", breakpoint->unique_id, retval);
  112. (*breakpoint_p) = breakpoint->next;
  113. free(breakpoint->orig_instr);
  114. free(breakpoint);
  115. }
  116. void breakpoint_remove(struct target *target, uint32_t address)
  117. {
  118. struct breakpoint *breakpoint = target->breakpoints;
  119. struct breakpoint **breakpoint_p = &target->breakpoints;
  120. while (breakpoint)
  121. {
  122. if (breakpoint->address == address)
  123. break;
  124. breakpoint_p = &breakpoint->next;
  125. breakpoint = breakpoint->next;
  126. }
  127. if (breakpoint)
  128. {
  129. breakpoint_free(target, breakpoint);
  130. }
  131. else
  132. {
  133. LOG_ERROR("no breakpoint at address 0x%8.8" PRIx32 " found", address);
  134. }
  135. }
  136. void breakpoint_clear_target(struct target *target)
  137. {
  138. struct breakpoint *breakpoint;
  139. LOG_DEBUG("Delete all breakpoints for target: %s",
  140. target_name(target));
  141. while ((breakpoint = target->breakpoints) != NULL)
  142. {
  143. breakpoint_free(target, breakpoint);
  144. }
  145. }
  146. struct breakpoint* breakpoint_find(struct target *target, uint32_t address)
  147. {
  148. struct breakpoint *breakpoint = target->breakpoints;
  149. while (breakpoint)
  150. {
  151. if (breakpoint->address == address)
  152. return breakpoint;
  153. breakpoint = breakpoint->next;
  154. }
  155. return NULL;
  156. }
  157. int watchpoint_add(struct target *target, uint32_t address, uint32_t length,
  158. enum watchpoint_rw rw, uint32_t value, uint32_t mask)
  159. {
  160. struct watchpoint *watchpoint = target->watchpoints;
  161. struct watchpoint **watchpoint_p = &target->watchpoints;
  162. int retval;
  163. char *reason;
  164. while (watchpoint)
  165. {
  166. if (watchpoint->address == address) {
  167. if (watchpoint->length != length
  168. || watchpoint->value != value
  169. || watchpoint->mask != mask
  170. || watchpoint->rw != rw) {
  171. LOG_ERROR("address 0x%8.8" PRIx32
  172. "already has watchpoint %d",
  173. address, watchpoint->unique_id);
  174. return ERROR_FAIL;
  175. }
  176. /* ignore duplicate watchpoint */
  177. return ERROR_OK;
  178. }
  179. watchpoint_p = &watchpoint->next;
  180. watchpoint = watchpoint->next;
  181. }
  182. (*watchpoint_p) = calloc(1, sizeof(struct watchpoint));
  183. (*watchpoint_p)->address = address;
  184. (*watchpoint_p)->length = length;
  185. (*watchpoint_p)->value = value;
  186. (*watchpoint_p)->mask = mask;
  187. (*watchpoint_p)->rw = rw;
  188. (*watchpoint_p)->unique_id = bpwp_unique_id++;
  189. retval = target_add_watchpoint(target, *watchpoint_p);
  190. switch (retval) {
  191. case ERROR_OK:
  192. break;
  193. case ERROR_TARGET_RESOURCE_NOT_AVAILABLE:
  194. reason = "resource not available";
  195. goto bye;
  196. case ERROR_TARGET_NOT_HALTED:
  197. reason = "target running";
  198. goto bye;
  199. default:
  200. reason = "unrecognized error";
  201. bye:
  202. LOG_ERROR("can't add %s watchpoint at 0x%8.8" PRIx32 ", %s",
  203. watchpoint_rw_strings[(*watchpoint_p)->rw],
  204. address, reason);
  205. free (*watchpoint_p);
  206. *watchpoint_p = NULL;
  207. return retval;
  208. }
  209. LOG_DEBUG("added %s watchpoint at 0x%8.8" PRIx32
  210. " of length 0x%8.8" PRIx32 " (WPID: %d)",
  211. watchpoint_rw_strings[(*watchpoint_p)->rw],
  212. (*watchpoint_p)->address,
  213. (*watchpoint_p)->length,
  214. (*watchpoint_p)->unique_id );
  215. return ERROR_OK;
  216. }
  217. static void watchpoint_free(struct target *target, struct watchpoint *watchpoint_remove)
  218. {
  219. struct watchpoint *watchpoint = target->watchpoints;
  220. struct watchpoint **watchpoint_p = &target->watchpoints;
  221. int retval;
  222. while (watchpoint)
  223. {
  224. if (watchpoint == watchpoint_remove)
  225. break;
  226. watchpoint_p = &watchpoint->next;
  227. watchpoint = watchpoint->next;
  228. }
  229. if (watchpoint == NULL)
  230. return;
  231. retval = target_remove_watchpoint(target, watchpoint);
  232. LOG_DEBUG("free WPID: %d --> %d", watchpoint->unique_id, retval);
  233. (*watchpoint_p) = watchpoint->next;
  234. free(watchpoint);
  235. }
  236. void watchpoint_remove(struct target *target, uint32_t address)
  237. {
  238. struct watchpoint *watchpoint = target->watchpoints;
  239. struct watchpoint **watchpoint_p = &target->watchpoints;
  240. while (watchpoint)
  241. {
  242. if (watchpoint->address == address)
  243. break;
  244. watchpoint_p = &watchpoint->next;
  245. watchpoint = watchpoint->next;
  246. }
  247. if (watchpoint)
  248. {
  249. watchpoint_free(target, watchpoint);
  250. }
  251. else
  252. {
  253. LOG_ERROR("no watchpoint at address 0x%8.8" PRIx32 " found", address);
  254. }
  255. }
  256. void watchpoint_clear_target(struct target *target)
  257. {
  258. struct watchpoint *watchpoint;
  259. LOG_DEBUG("Delete all watchpoints for target: %s",
  260. target_name(target));
  261. while ((watchpoint = target->watchpoints) != NULL)
  262. {
  263. watchpoint_free(target, watchpoint);
  264. }
  265. }