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.
 
 
 
 
 
 

268 lines
7.0 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. int breakpoint_add(target_t *target, uint32_t address, uint32_t length, enum breakpoint_type type)
  38. {
  39. breakpoint_t *breakpoint = target->breakpoints;
  40. breakpoint_t **breakpoint_p = &target->breakpoints;
  41. int retval;
  42. while (breakpoint)
  43. {
  44. if (breakpoint->address == address)
  45. return ERROR_OK;
  46. breakpoint_p = &breakpoint->next;
  47. breakpoint = breakpoint->next;
  48. }
  49. (*breakpoint_p) = malloc(sizeof(breakpoint_t));
  50. (*breakpoint_p)->address = address;
  51. (*breakpoint_p)->length = length;
  52. (*breakpoint_p)->type = type;
  53. (*breakpoint_p)->set = 0;
  54. (*breakpoint_p)->orig_instr = malloc(length);
  55. (*breakpoint_p)->next = NULL;
  56. if ((retval = target_add_breakpoint(target, *breakpoint_p)) != ERROR_OK)
  57. {
  58. switch (retval)
  59. {
  60. case ERROR_TARGET_RESOURCE_NOT_AVAILABLE:
  61. LOG_INFO("can't add %s breakpoint, resource not available", breakpoint_type_strings[(*breakpoint_p)->type]);
  62. free((*breakpoint_p)->orig_instr);
  63. free(*breakpoint_p);
  64. *breakpoint_p = NULL;
  65. return retval;
  66. break;
  67. case ERROR_TARGET_NOT_HALTED:
  68. LOG_INFO("can't add breakpoint while target is running");
  69. free((*breakpoint_p)->orig_instr);
  70. free(*breakpoint_p);
  71. *breakpoint_p = NULL;
  72. return retval;
  73. break;
  74. default:
  75. break;
  76. }
  77. }
  78. LOG_DEBUG("added %s breakpoint at 0x%8.8" PRIx32 " of length 0x%8.8x",
  79. breakpoint_type_strings[(*breakpoint_p)->type],
  80. (*breakpoint_p)->address, (*breakpoint_p)->length);
  81. return ERROR_OK;
  82. }
  83. /* free up a breakpoint */
  84. static void breakpoint_free(target_t *target, breakpoint_t *breakpoint_remove)
  85. {
  86. breakpoint_t *breakpoint = target->breakpoints;
  87. breakpoint_t **breakpoint_p = &target->breakpoints;
  88. while (breakpoint)
  89. {
  90. if (breakpoint == breakpoint_remove)
  91. break;
  92. breakpoint_p = &breakpoint->next;
  93. breakpoint = breakpoint->next;
  94. }
  95. if (breakpoint == NULL)
  96. return;
  97. target_remove_breakpoint(target, breakpoint);
  98. (*breakpoint_p) = breakpoint->next;
  99. free(breakpoint->orig_instr);
  100. free(breakpoint);
  101. }
  102. void breakpoint_remove(target_t *target, uint32_t address)
  103. {
  104. breakpoint_t *breakpoint = target->breakpoints;
  105. breakpoint_t **breakpoint_p = &target->breakpoints;
  106. while (breakpoint)
  107. {
  108. if (breakpoint->address == address)
  109. break;
  110. breakpoint_p = &breakpoint->next;
  111. breakpoint = breakpoint->next;
  112. }
  113. if (breakpoint)
  114. {
  115. breakpoint_free(target, breakpoint);
  116. }
  117. else
  118. {
  119. LOG_ERROR("no breakpoint at address 0x%8.8" PRIx32 " found", address);
  120. }
  121. }
  122. void breakpoint_clear_target(target_t *target)
  123. {
  124. breakpoint_t *breakpoint;
  125. while ((breakpoint = target->breakpoints) != NULL)
  126. {
  127. breakpoint_free(target, breakpoint);
  128. }
  129. }
  130. breakpoint_t* breakpoint_find(target_t *target, uint32_t address)
  131. {
  132. breakpoint_t *breakpoint = target->breakpoints;
  133. while (breakpoint)
  134. {
  135. if (breakpoint->address == address)
  136. return breakpoint;
  137. breakpoint = breakpoint->next;
  138. }
  139. return NULL;
  140. }
  141. int watchpoint_add(target_t *target, uint32_t address, uint32_t length, enum watchpoint_rw rw, uint32_t value, uint32_t mask)
  142. {
  143. watchpoint_t *watchpoint = target->watchpoints;
  144. watchpoint_t **watchpoint_p = &target->watchpoints;
  145. int retval;
  146. while (watchpoint)
  147. {
  148. if (watchpoint->address == address)
  149. return ERROR_OK;
  150. watchpoint_p = &watchpoint->next;
  151. watchpoint = watchpoint->next;
  152. }
  153. (*watchpoint_p) = malloc(sizeof(watchpoint_t));
  154. (*watchpoint_p)->address = address;
  155. (*watchpoint_p)->length = length;
  156. (*watchpoint_p)->value = value;
  157. (*watchpoint_p)->mask = mask;
  158. (*watchpoint_p)->rw = rw;
  159. (*watchpoint_p)->set = 0;
  160. (*watchpoint_p)->next = NULL;
  161. if ((retval = target_add_watchpoint(target, *watchpoint_p)) != ERROR_OK)
  162. {
  163. switch (retval)
  164. {
  165. case ERROR_TARGET_RESOURCE_NOT_AVAILABLE:
  166. LOG_INFO("can't add %s watchpoint, resource not available", watchpoint_rw_strings[(*watchpoint_p)->rw]);
  167. free (*watchpoint_p);
  168. *watchpoint_p = NULL;
  169. return retval;
  170. break;
  171. case ERROR_TARGET_NOT_HALTED:
  172. LOG_INFO("can't add watchpoint while target is running");
  173. free (*watchpoint_p);
  174. *watchpoint_p = NULL;
  175. return retval;
  176. break;
  177. default:
  178. LOG_ERROR("unknown error");
  179. exit(-1);
  180. break;
  181. }
  182. }
  183. LOG_DEBUG("added %s watchpoint at 0x%8.8" PRIx32 " of length 0x%8.8x",
  184. watchpoint_rw_strings[(*watchpoint_p)->rw],
  185. (*watchpoint_p)->address, (*watchpoint_p)->length);
  186. return ERROR_OK;
  187. }
  188. static void watchpoint_free(target_t *target, watchpoint_t *watchpoint_remove)
  189. {
  190. watchpoint_t *watchpoint = target->watchpoints;
  191. watchpoint_t **watchpoint_p = &target->watchpoints;
  192. while (watchpoint)
  193. {
  194. if (watchpoint == watchpoint_remove)
  195. break;
  196. watchpoint_p = &watchpoint->next;
  197. watchpoint = watchpoint->next;
  198. }
  199. if (watchpoint == NULL)
  200. return;
  201. target_remove_watchpoint(target, watchpoint);
  202. (*watchpoint_p) = watchpoint->next;
  203. free(watchpoint);
  204. }
  205. void watchpoint_remove(target_t *target, uint32_t address)
  206. {
  207. watchpoint_t *watchpoint = target->watchpoints;
  208. watchpoint_t **watchpoint_p = &target->watchpoints;
  209. while (watchpoint)
  210. {
  211. if (watchpoint->address == address)
  212. break;
  213. watchpoint_p = &watchpoint->next;
  214. watchpoint = watchpoint->next;
  215. }
  216. if (watchpoint)
  217. {
  218. watchpoint_free(target, watchpoint);
  219. }
  220. else
  221. {
  222. LOG_ERROR("no watchpoint at address 0x%8.8" PRIx32 " found", address);
  223. }
  224. }
  225. void watchpoint_clear_target(target_t *target)
  226. {
  227. watchpoint_t *watchpoint;
  228. while ((watchpoint = target->watchpoints) != NULL)
  229. {
  230. watchpoint_free(target, watchpoint);
  231. }
  232. }