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.
 
 
 
 
 
 

300 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 "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(target_t *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. int retval;
  44. int n;
  45. n = 0;
  46. while (breakpoint)
  47. {
  48. n++;
  49. if (breakpoint->address == address){
  50. LOG_DEBUG("Duplicate Breakpoint address: 0x%08" PRIx32 " (BP %d)",
  51. address, breakpoint->unique_id );
  52. return ERROR_OK;
  53. }
  54. breakpoint_p = &breakpoint->next;
  55. breakpoint = breakpoint->next;
  56. }
  57. (*breakpoint_p) = malloc(sizeof(struct breakpoint));
  58. (*breakpoint_p)->address = address;
  59. (*breakpoint_p)->length = length;
  60. (*breakpoint_p)->type = type;
  61. (*breakpoint_p)->set = 0;
  62. (*breakpoint_p)->orig_instr = malloc(length);
  63. (*breakpoint_p)->next = NULL;
  64. (*breakpoint_p)->unique_id = bpwp_unique_id++;
  65. if ((retval = target_add_breakpoint(target, *breakpoint_p)) != ERROR_OK)
  66. {
  67. switch (retval)
  68. {
  69. case ERROR_TARGET_RESOURCE_NOT_AVAILABLE:
  70. LOG_INFO("can't add %s breakpoint, resource not available (BPID=%d)",
  71. breakpoint_type_strings[(*breakpoint_p)->type],
  72. (*breakpoint_p)->unique_id );
  73. free((*breakpoint_p)->orig_instr);
  74. free(*breakpoint_p);
  75. *breakpoint_p = NULL;
  76. return retval;
  77. break;
  78. case ERROR_TARGET_NOT_HALTED:
  79. LOG_INFO("can't add breakpoint while target is running (BPID: %d)",
  80. (*breakpoint_p)->unique_id );
  81. free((*breakpoint_p)->orig_instr);
  82. free(*breakpoint_p);
  83. *breakpoint_p = NULL;
  84. return retval;
  85. break;
  86. default:
  87. break;
  88. }
  89. }
  90. LOG_DEBUG("added %s breakpoint at 0x%8.8" PRIx32 " of length 0x%8.8x, (BPID: %d)",
  91. breakpoint_type_strings[(*breakpoint_p)->type],
  92. (*breakpoint_p)->address, (*breakpoint_p)->length,
  93. (*breakpoint_p)->unique_id );
  94. return ERROR_OK;
  95. }
  96. /* free up a breakpoint */
  97. static void breakpoint_free(target_t *target, struct breakpoint *breakpoint_remove)
  98. {
  99. struct breakpoint *breakpoint = target->breakpoints;
  100. struct breakpoint **breakpoint_p = &target->breakpoints;
  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. target_remove_breakpoint(target, breakpoint);
  111. LOG_DEBUG("BPID: %d", breakpoint->unique_id );
  112. (*breakpoint_p) = breakpoint->next;
  113. free(breakpoint->orig_instr);
  114. free(breakpoint);
  115. }
  116. void breakpoint_remove(target_t *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(target_t *target)
  137. {
  138. struct breakpoint *breakpoint;
  139. LOG_DEBUG("Delete all breakpoints for target: %s", target_get_name( target ));
  140. while ((breakpoint = target->breakpoints) != NULL)
  141. {
  142. breakpoint_free(target, breakpoint);
  143. }
  144. }
  145. struct breakpoint* breakpoint_find(target_t *target, uint32_t address)
  146. {
  147. struct breakpoint *breakpoint = target->breakpoints;
  148. while (breakpoint)
  149. {
  150. if (breakpoint->address == address)
  151. return breakpoint;
  152. breakpoint = breakpoint->next;
  153. }
  154. return NULL;
  155. }
  156. int watchpoint_add(target_t *target, uint32_t address, uint32_t length,
  157. enum watchpoint_rw rw, uint32_t value, uint32_t mask)
  158. {
  159. struct watchpoint *watchpoint = target->watchpoints;
  160. struct watchpoint **watchpoint_p = &target->watchpoints;
  161. int retval;
  162. char *reason;
  163. while (watchpoint)
  164. {
  165. if (watchpoint->address == address) {
  166. if (watchpoint->length != length
  167. || watchpoint->value != value
  168. || watchpoint->mask != mask
  169. || watchpoint->rw != rw) {
  170. LOG_ERROR("address 0x%8.8" PRIx32
  171. "already has watchpoint %d",
  172. address, watchpoint->unique_id);
  173. return ERROR_FAIL;
  174. }
  175. /* ignore duplicate watchpoint */
  176. return ERROR_OK;
  177. }
  178. watchpoint_p = &watchpoint->next;
  179. watchpoint = watchpoint->next;
  180. }
  181. (*watchpoint_p) = calloc(1, sizeof(struct watchpoint));
  182. (*watchpoint_p)->address = address;
  183. (*watchpoint_p)->length = length;
  184. (*watchpoint_p)->value = value;
  185. (*watchpoint_p)->mask = mask;
  186. (*watchpoint_p)->rw = rw;
  187. (*watchpoint_p)->unique_id = bpwp_unique_id++;
  188. retval = target_add_watchpoint(target, *watchpoint_p);
  189. switch (retval) {
  190. case ERROR_OK:
  191. break;
  192. case ERROR_TARGET_RESOURCE_NOT_AVAILABLE:
  193. reason = "resource not available";
  194. goto bye;
  195. case ERROR_TARGET_NOT_HALTED:
  196. reason = "target running";
  197. goto bye;
  198. default:
  199. reason = "unrecognized error";
  200. bye:
  201. LOG_ERROR("can't add %s watchpoint at 0x%8.8" PRIx32 ", %s",
  202. watchpoint_rw_strings[(*watchpoint_p)->rw],
  203. address, reason);
  204. free (*watchpoint_p);
  205. *watchpoint_p = NULL;
  206. return retval;
  207. }
  208. LOG_DEBUG("added %s watchpoint at 0x%8.8" PRIx32 " of length 0x%8.8x (WPID: %d)",
  209. watchpoint_rw_strings[(*watchpoint_p)->rw],
  210. (*watchpoint_p)->address,
  211. (*watchpoint_p)->length,
  212. (*watchpoint_p)->unique_id );
  213. return ERROR_OK;
  214. }
  215. static void watchpoint_free(target_t *target, struct watchpoint *watchpoint_remove)
  216. {
  217. struct watchpoint *watchpoint = target->watchpoints;
  218. struct watchpoint **watchpoint_p = &target->watchpoints;
  219. while (watchpoint)
  220. {
  221. if (watchpoint == watchpoint_remove)
  222. break;
  223. watchpoint_p = &watchpoint->next;
  224. watchpoint = watchpoint->next;
  225. }
  226. if (watchpoint == NULL)
  227. return;
  228. target_remove_watchpoint(target, watchpoint);
  229. LOG_DEBUG("WPID: %d", watchpoint->unique_id );
  230. (*watchpoint_p) = watchpoint->next;
  231. free(watchpoint);
  232. }
  233. void watchpoint_remove(target_t *target, uint32_t address)
  234. {
  235. struct watchpoint *watchpoint = target->watchpoints;
  236. struct watchpoint **watchpoint_p = &target->watchpoints;
  237. while (watchpoint)
  238. {
  239. if (watchpoint->address == address)
  240. break;
  241. watchpoint_p = &watchpoint->next;
  242. watchpoint = watchpoint->next;
  243. }
  244. if (watchpoint)
  245. {
  246. watchpoint_free(target, watchpoint);
  247. }
  248. else
  249. {
  250. LOG_ERROR("no watchpoint at address 0x%8.8" PRIx32 " found", address);
  251. }
  252. }
  253. void watchpoint_clear_target(target_t *target)
  254. {
  255. struct watchpoint *watchpoint;
  256. LOG_DEBUG("Delete all watchpoints for target: %s", target_get_name( target ));
  257. while ((watchpoint = target->watchpoints) != NULL)
  258. {
  259. watchpoint_free(target, watchpoint);
  260. }
  261. }