db_break.c 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260
  1. /* $OpenBSD: db_break.c,v 1.17 2015/03/14 03:38:46 jsg Exp $ */
  2. /* $NetBSD: db_break.c,v 1.7 1996/03/30 22:30:03 christos Exp $ */
  3. /*
  4. * Mach Operating System
  5. * Copyright (c) 1993,1992,1991,1990 Carnegie Mellon University
  6. * All Rights Reserved.
  7. *
  8. * Permission to use, copy, modify and distribute this software and its
  9. * documentation is hereby granted, provided that both the copyright
  10. * notice and this permission notice appear in all copies of the
  11. * software, derivative works or modified versions, and any portions
  12. * thereof, and that both notices appear in supporting documentation.
  13. *
  14. * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
  15. * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
  16. * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
  17. *
  18. * Carnegie Mellon requests users of this software to return to
  19. *
  20. * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
  21. * School of Computer Science
  22. * Carnegie Mellon University
  23. * Pittsburgh PA 15213-3890
  24. *
  25. * any improvements or extensions that they make and grant Carnegie Mellon
  26. * the rights to redistribute these changes.
  27. *
  28. * Author: David B. Golub, Carnegie Mellon University
  29. * Date: 7/90
  30. */
  31. /*
  32. * Breakpoints.
  33. */
  34. #include <sys/param.h>
  35. #include <sys/systm.h>
  36. #include <machine/db_machdep.h> /* type definitions */
  37. #include <ddb/db_access.h>
  38. #include <ddb/db_sym.h>
  39. #include <ddb/db_break.h>
  40. #include <ddb/db_output.h>
  41. #define NBREAKPOINTS 100
  42. struct db_breakpoint db_break_table[NBREAKPOINTS];
  43. db_breakpoint_t db_next_free_breakpoint = &db_break_table[0];
  44. db_breakpoint_t db_free_breakpoints = 0;
  45. db_breakpoint_t db_breakpoint_list = 0;
  46. db_breakpoint_t
  47. db_breakpoint_alloc(void)
  48. {
  49. db_breakpoint_t bkpt;
  50. if ((bkpt = db_free_breakpoints) != 0) {
  51. db_free_breakpoints = bkpt->link;
  52. return (bkpt);
  53. }
  54. if (db_next_free_breakpoint == &db_break_table[NBREAKPOINTS]) {
  55. db_printf("All breakpoints used.\n");
  56. return (0);
  57. }
  58. bkpt = db_next_free_breakpoint;
  59. db_next_free_breakpoint++;
  60. return (bkpt);
  61. }
  62. void
  63. db_breakpoint_free(db_breakpoint_t bkpt)
  64. {
  65. bkpt->link = db_free_breakpoints;
  66. db_free_breakpoints = bkpt;
  67. }
  68. void
  69. db_set_breakpoint(db_addr_t addr, int count)
  70. {
  71. db_breakpoint_t bkpt;
  72. if (db_find_breakpoint(addr)) {
  73. db_printf("Already set.\n");
  74. return;
  75. }
  76. #ifdef DB_VALID_BREAKPOINT
  77. if (!DB_VALID_BREAKPOINT(addr)) {
  78. db_printf("Not a valid address for a breakpoint.\n");
  79. return;
  80. }
  81. #endif
  82. bkpt = db_breakpoint_alloc();
  83. if (bkpt == 0) {
  84. db_printf("Too many breakpoints.\n");
  85. return;
  86. }
  87. bkpt->address = addr;
  88. bkpt->flags = 0;
  89. bkpt->init_count = count;
  90. bkpt->count = count;
  91. bkpt->link = db_breakpoint_list;
  92. db_breakpoint_list = bkpt;
  93. }
  94. void
  95. db_delete_breakpoint(db_addr_t addr)
  96. {
  97. db_breakpoint_t bkpt;
  98. db_breakpoint_t *prev;
  99. for (prev = &db_breakpoint_list; (bkpt = *prev) != 0;
  100. prev = &bkpt->link) {
  101. if (bkpt->address == addr) {
  102. *prev = bkpt->link;
  103. break;
  104. }
  105. }
  106. if (bkpt == 0) {
  107. db_printf("Not set.\n");
  108. return;
  109. }
  110. db_breakpoint_free(bkpt);
  111. }
  112. db_breakpoint_t
  113. db_find_breakpoint(db_addr_t addr)
  114. {
  115. db_breakpoint_t bkpt;
  116. for (bkpt = db_breakpoint_list; bkpt != 0; bkpt = bkpt->link)
  117. if (bkpt->address == addr)
  118. return (bkpt);
  119. return (0);
  120. }
  121. boolean_t db_breakpoints_inserted = TRUE;
  122. void
  123. db_set_breakpoints(void)
  124. {
  125. db_breakpoint_t bkpt;
  126. if (!db_breakpoints_inserted) {
  127. for (bkpt = db_breakpoint_list; bkpt != 0; bkpt = bkpt->link) {
  128. bkpt->bkpt_inst =
  129. db_get_value(bkpt->address, BKPT_SIZE, FALSE);
  130. db_put_value(bkpt->address, BKPT_SIZE,
  131. BKPT_SET(bkpt->bkpt_inst));
  132. }
  133. db_breakpoints_inserted = TRUE;
  134. }
  135. }
  136. void
  137. db_clear_breakpoints(void)
  138. {
  139. db_breakpoint_t bkpt;
  140. if (db_breakpoints_inserted) {
  141. for (bkpt = db_breakpoint_list; bkpt != 0; bkpt = bkpt->link)
  142. db_put_value(bkpt->address, BKPT_SIZE, bkpt->bkpt_inst);
  143. db_breakpoints_inserted = FALSE;
  144. }
  145. }
  146. /*
  147. * Set a temporary breakpoint.
  148. * The instruction is changed immediately,
  149. * so the breakpoint does not have to be on the breakpoint list.
  150. */
  151. db_breakpoint_t
  152. db_set_temp_breakpoint(db_addr_t addr)
  153. {
  154. db_breakpoint_t bkpt;
  155. #ifdef DB_VALID_BREAKPOINT
  156. if (!DB_VALID_BREAKPOINT(addr)) {
  157. db_printf("Not a valid address for a breakpoint.\n");
  158. return (0);
  159. }
  160. #endif
  161. bkpt = db_breakpoint_alloc();
  162. if (bkpt == 0) {
  163. db_printf("Too many breakpoints.\n");
  164. return (0);
  165. }
  166. bkpt->address = addr;
  167. bkpt->flags = BKPT_TEMP;
  168. bkpt->init_count = 1;
  169. bkpt->count = 1;
  170. bkpt->bkpt_inst = db_get_value(bkpt->address, BKPT_SIZE, FALSE);
  171. db_put_value(bkpt->address, BKPT_SIZE, BKPT_SET(bkpt->bkpt_inst));
  172. return bkpt;
  173. }
  174. void
  175. db_delete_temp_breakpoint(db_breakpoint_t bkpt)
  176. {
  177. db_put_value(bkpt->address, BKPT_SIZE, bkpt->bkpt_inst);
  178. db_breakpoint_free(bkpt);
  179. }
  180. /*
  181. * List breakpoints.
  182. */
  183. void
  184. db_list_breakpoints(void)
  185. {
  186. db_breakpoint_t bkpt;
  187. if (db_breakpoint_list == NULL) {
  188. db_printf("No breakpoints set\n");
  189. return;
  190. }
  191. db_printf(" Count Address\n");
  192. for (bkpt = db_breakpoint_list; bkpt != 0; bkpt = bkpt->link) {
  193. db_printf(" %5d ", bkpt->init_count);
  194. db_printsym(bkpt->address, DB_STGY_PROC, db_printf);
  195. db_printf("\n");
  196. }
  197. }
  198. /* Delete breakpoint */
  199. /*ARGSUSED*/
  200. void
  201. db_delete_cmd(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
  202. {
  203. db_delete_breakpoint((db_addr_t)addr);
  204. }
  205. /* Set breakpoint with skip count */
  206. /*ARGSUSED*/
  207. void
  208. db_breakpoint_cmd(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
  209. {
  210. if (count == -1)
  211. count = 1;
  212. db_set_breakpoint((db_addr_t)addr, count);
  213. }
  214. /* list breakpoints */
  215. /*ARGSUSED*/
  216. void
  217. db_listbreak_cmd(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
  218. {
  219. db_list_breakpoints();
  220. }