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.
 
 
 
 
 
 

293 lines
7.8 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. breakpoint_t *breakpoint = target->breakpoints;
  42. breakpoint_t **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(breakpoint_t));
  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, breakpoint_t *breakpoint_remove)
  98. {
  99. breakpoint_t *breakpoint = target->breakpoints;
  100. breakpoint_t **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. breakpoint_t *breakpoint = target->breakpoints;
  119. breakpoint_t **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. breakpoint_t *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. breakpoint_t* breakpoint_find(target_t *target, uint32_t address)
  146. {
  147. breakpoint_t *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, enum watchpoint_rw rw, uint32_t value, uint32_t mask)
  157. {
  158. watchpoint_t *watchpoint = target->watchpoints;
  159. watchpoint_t **watchpoint_p = &target->watchpoints;
  160. int retval;
  161. while (watchpoint)
  162. {
  163. if (watchpoint->address == address)
  164. return ERROR_OK;
  165. watchpoint_p = &watchpoint->next;
  166. watchpoint = watchpoint->next;
  167. }
  168. (*watchpoint_p) = malloc(sizeof(watchpoint_t));
  169. (*watchpoint_p)->address = address;
  170. (*watchpoint_p)->length = length;
  171. (*watchpoint_p)->value = value;
  172. (*watchpoint_p)->mask = mask;
  173. (*watchpoint_p)->rw = rw;
  174. (*watchpoint_p)->set = 0;
  175. (*watchpoint_p)->next = NULL;
  176. (*watchpoint_p)->unique_id = bpwp_unique_id++;
  177. if ((retval = target_add_watchpoint(target, *watchpoint_p)) != ERROR_OK)
  178. {
  179. switch (retval)
  180. {
  181. case ERROR_TARGET_RESOURCE_NOT_AVAILABLE:
  182. LOG_INFO("can't add %s watchpoint, resource not available (WPID: %d)",
  183. watchpoint_rw_strings[(*watchpoint_p)->rw],
  184. (*watchpoint_p)->unique_id );
  185. free (*watchpoint_p);
  186. *watchpoint_p = NULL;
  187. return retval;
  188. break;
  189. case ERROR_TARGET_NOT_HALTED:
  190. LOG_INFO("can't add watchpoint while target is running (WPID: %d)",
  191. (*watchpoint_p)->unique_id );
  192. free (*watchpoint_p);
  193. *watchpoint_p = NULL;
  194. return retval;
  195. break;
  196. default:
  197. LOG_ERROR("unknown error");
  198. exit(-1);
  199. break;
  200. }
  201. }
  202. LOG_DEBUG("added %s watchpoint at 0x%8.8" PRIx32 " of length 0x%8.8x (WPID: %d)",
  203. watchpoint_rw_strings[(*watchpoint_p)->rw],
  204. (*watchpoint_p)->address,
  205. (*watchpoint_p)->length,
  206. (*watchpoint_p)->unique_id );
  207. return ERROR_OK;
  208. }
  209. static void watchpoint_free(target_t *target, watchpoint_t *watchpoint_remove)
  210. {
  211. watchpoint_t *watchpoint = target->watchpoints;
  212. watchpoint_t **watchpoint_p = &target->watchpoints;
  213. while (watchpoint)
  214. {
  215. if (watchpoint == watchpoint_remove)
  216. break;
  217. watchpoint_p = &watchpoint->next;
  218. watchpoint = watchpoint->next;
  219. }
  220. if (watchpoint == NULL)
  221. return;
  222. target_remove_watchpoint(target, watchpoint);
  223. LOG_DEBUG("WPID: %d", watchpoint->unique_id );
  224. (*watchpoint_p) = watchpoint->next;
  225. free(watchpoint);
  226. }
  227. void watchpoint_remove(target_t *target, uint32_t address)
  228. {
  229. watchpoint_t *watchpoint = target->watchpoints;
  230. watchpoint_t **watchpoint_p = &target->watchpoints;
  231. while (watchpoint)
  232. {
  233. if (watchpoint->address == address)
  234. break;
  235. watchpoint_p = &watchpoint->next;
  236. watchpoint = watchpoint->next;
  237. }
  238. if (watchpoint)
  239. {
  240. watchpoint_free(target, watchpoint);
  241. }
  242. else
  243. {
  244. LOG_ERROR("no watchpoint at address 0x%8.8" PRIx32 " found", address);
  245. }
  246. }
  247. void watchpoint_clear_target(target_t *target)
  248. {
  249. watchpoint_t *watchpoint;
  250. LOG_DEBUG("Delete all watchpoints for target: %s", target_get_name( target ));
  251. while ((watchpoint = target->watchpoints) != NULL)
  252. {
  253. watchpoint_free(target, watchpoint);
  254. }
  255. }