Source code of Windows XP (NT5)
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.

451 lines
9.0 KiB

  1. /*++
  2. Copyright (c) 1991 Microsoft Corporation
  3. Module Name:
  4. debug.c
  5. Abstract:
  6. This file contains code to manage software breakpoints
  7. Author:
  8. Neil Sandlin (neilsa) 1-Nov-1995
  9. Revision History:
  10. --*/
  11. #include <precomp.h>
  12. #pragma hdrstop
  13. #include <dpmi.h>
  14. #include <dbgsvc.h>
  15. #include <dbginfo.h>
  16. #include <stdio.h>
  17. #define BREAKPOINT_CLEAR 1
  18. #define BREAKPOINT_DISABLE 2
  19. #define BREAKPOINT_ENABLE 3
  20. #define VDMBP_ARRAY "ntvdmd!VdmBreakPoints"
  21. VDM_BREAKPOINT VdmBPCache[MAX_VDM_BREAKPOINTS] = {0};
  22. // BP zero is reserved for internal use
  23. #define TEMP_BP 0
  24. BOOL
  25. LoadBreakPointCache(
  26. VOID
  27. )
  28. {
  29. ULONG lpAddress;
  30. lpAddress = (*GetExpression)(VDMBP_ARRAY);
  31. if (!lpAddress) {
  32. PRINTF("Could not find symbol %s\n",VDMBP_ARRAY);
  33. return FALSE;
  34. }
  35. if (!READMEM((PVOID)lpAddress, &VdmBPCache, sizeof(VdmBPCache))) {
  36. PRINTF("Error reading BP memory\n");
  37. return FALSE;
  38. }
  39. return TRUE;
  40. }
  41. BOOL
  42. FlushBreakPointCache(
  43. VOID
  44. )
  45. {
  46. ULONG lpAddress;
  47. lpAddress = (*GetExpression)(VDMBP_ARRAY);
  48. if (!lpAddress) {
  49. PRINTF("Could not find symbol %s\n",VDMBP_ARRAY);
  50. return FALSE;
  51. }
  52. if (!WRITEMEM((PVOID)lpAddress, &VdmBPCache, sizeof(VdmBPCache))) {
  53. PRINTF("Error writing BP memory\n");
  54. return FALSE;
  55. }
  56. return TRUE;
  57. }
  58. BOOL
  59. IsVdmBreakPoint(
  60. USHORT selector,
  61. ULONG offset,
  62. BOOL bProt,
  63. PULONG pBpNum,
  64. PUCHAR pBpData
  65. )
  66. //
  67. // Callers of this function must first call LoadBreakPointCache()
  68. //
  69. {
  70. ULONG BPNum;
  71. for (BPNum = 0; BPNum < MAX_VDM_BREAKPOINTS; BPNum++) {
  72. if ((VdmBPCache[BPNum].Flags & VDMBP_SET) &&
  73. (VdmBPCache[BPNum].Seg == selector) &&
  74. (VdmBPCache[BPNum].Offset == offset)) {
  75. if ((bProt && ~(VdmBPCache[BPNum].Flags & VDMBP_V86)) ||
  76. (~bProt && (VdmBPCache[BPNum].Flags & VDMBP_V86))) {
  77. *pBpNum = BPNum;
  78. *pBpData = VdmBPCache[BPNum].Opcode;
  79. return TRUE;
  80. }
  81. }
  82. }
  83. return FALSE;
  84. }
  85. VOID
  86. DisableBreakPoint(
  87. VDM_BREAKPOINT *pBP
  88. )
  89. {
  90. int mode;
  91. ULONG lpAddress;
  92. BYTE byte;
  93. if (!(pBP->Flags & VDMBP_ENABLED)) {
  94. // already not enabled
  95. return;
  96. }
  97. pBP->Flags &= ~VDMBP_ENABLED;
  98. if (pBP->Flags & VDMBP_PENDING) {
  99. pBP->Flags &= ~VDMBP_PENDING;
  100. return;
  101. }
  102. if (pBP->Flags & VDMBP_V86) {
  103. mode = V86_MODE;
  104. } else {
  105. mode = PROT_MODE;
  106. }
  107. lpAddress = GetInfoFromSelector(pBP->Seg, mode, NULL) + GetIntelBase() + pBP->Offset;
  108. if (READMEM((PVOID)lpAddress, &byte, 1)) {
  109. if (byte == 0xcc) {
  110. WRITEMEM((PVOID)lpAddress, &pBP->Opcode, 1);
  111. }
  112. }
  113. pBP->Flags |= VDMBP_FLUSH;
  114. pBP->Flags &= ~VDMBP_PENDING;
  115. #ifndef i386
  116. if (!InVdmPrompt()) {
  117. PRINTF("\n***Warning: command not issued from VDM> prompt.\nOpcode has not been flushed!\n\n");
  118. }
  119. #endif
  120. }
  121. VOID
  122. EnableBreakPoint(
  123. VDM_BREAKPOINT *pBP
  124. )
  125. {
  126. int mode;
  127. ULONG lpAddress;
  128. BYTE byte;
  129. if (pBP->Flags & VDMBP_ENABLED) {
  130. return;
  131. }
  132. EnableDebuggerBreakpoints();
  133. if (pBP->Flags & VDMBP_V86) {
  134. mode = V86_MODE;
  135. } else {
  136. mode = PROT_MODE;
  137. }
  138. lpAddress = GetInfoFromSelector(pBP->Seg, mode, NULL) + GetIntelBase() + pBP->Offset;
  139. if (READMEM((PVOID)lpAddress, &byte, 1)) {
  140. if (byte != 0xcc) {
  141. static BYTE bpOp = 0xcc;
  142. WRITEMEM((PVOID)lpAddress, &bpOp, 1);
  143. pBP->Opcode = byte;
  144. }
  145. } else {
  146. PRINTF("Error enabling breakpoint at %04X:%08X\n", pBP->Seg, pBP->Offset);
  147. return;
  148. }
  149. pBP->Flags |= (VDMBP_ENABLED | VDMBP_FLUSH);
  150. pBP->Flags &= ~VDMBP_PENDING;
  151. #ifndef i386
  152. if (!InVdmPrompt()) {
  153. PRINTF("\n***Warning: command not issued from VDM> prompt.\nBP has not been flushed!\n\n");
  154. }
  155. #endif
  156. }
  157. VOID
  158. UpdateBreakPoint(
  159. int Cmd
  160. )
  161. {
  162. int BPNum;
  163. int count = 0;
  164. BOOL DoBreakPoints[MAX_VDM_BREAKPOINTS] = {FALSE};
  165. BOOL DoAll = FALSE;
  166. if (!LoadBreakPointCache()) {
  167. return;
  168. }
  169. while (GetNextToken()) {
  170. if (*lpArgumentString == '*') {
  171. DoAll = TRUE;
  172. count++;
  173. break;
  174. }
  175. sscanf(lpArgumentString, "%d", &BPNum);
  176. if (BPNum >= MAX_VDM_BREAKPOINTS) {
  177. PRINTF("Invalid breakpoint - %d\n", BPNum);
  178. return;
  179. }
  180. DoBreakPoints[BPNum] = TRUE;
  181. count++;
  182. SkipToNextWhiteSpace();
  183. }
  184. if (!count) {
  185. PRINTF("Please specify a breakpoint #\n");
  186. return;
  187. }
  188. for (BPNum=0; BPNum<MAX_VDM_BREAKPOINTS; BPNum++) {
  189. if (!DoBreakPoints[BPNum] && !DoAll) {
  190. continue;
  191. }
  192. if (!(VdmBPCache[BPNum].Flags & VDMBP_SET)) {
  193. continue;
  194. }
  195. switch(Cmd) {
  196. case BREAKPOINT_CLEAR:
  197. if (VdmBPCache[BPNum].Flags & VDMBP_ENABLED) {
  198. DisableBreakPoint(&VdmBPCache[BPNum]);
  199. }
  200. VdmBPCache[BPNum].Flags &= ~VDMBP_SET;
  201. break;
  202. case BREAKPOINT_DISABLE:
  203. if (VdmBPCache[BPNum].Flags & VDMBP_ENABLED) {
  204. DisableBreakPoint(&VdmBPCache[BPNum]);
  205. }
  206. break;
  207. case BREAKPOINT_ENABLE:
  208. if (!(VdmBPCache[BPNum].Flags & VDMBP_ENABLED)) {
  209. EnableBreakPoint(&VdmBPCache[BPNum]);
  210. }
  211. break;
  212. }
  213. }
  214. FlushBreakPointCache();
  215. }
  216. VOID
  217. bc(
  218. CMD_ARGLIST
  219. )
  220. {
  221. CMD_INIT();
  222. UpdateBreakPoint(BREAKPOINT_CLEAR);
  223. }
  224. VOID
  225. bd(
  226. CMD_ARGLIST
  227. )
  228. {
  229. CMD_INIT();
  230. UpdateBreakPoint(BREAKPOINT_DISABLE);
  231. }
  232. VOID
  233. be(
  234. CMD_ARGLIST
  235. )
  236. {
  237. CMD_INIT();
  238. UpdateBreakPoint(BREAKPOINT_ENABLE);
  239. }
  240. VOID
  241. bl(
  242. CMD_ARGLIST
  243. )
  244. {
  245. int BPNum;
  246. int mode;
  247. DWORD dist;
  248. CHAR sym_text[255];
  249. CMD_INIT();
  250. if (!LoadBreakPointCache()) {
  251. return;
  252. }
  253. for (BPNum = 0; BPNum < MAX_VDM_BREAKPOINTS; BPNum++) {
  254. if (VdmBPCache[BPNum].Flags & VDMBP_SET) {
  255. PRINTF("%d %s%s%s ", BPNum,
  256. (VdmBPCache[BPNum].Flags & VDMBP_ENABLED) ? "e" : "d",
  257. (VdmBPCache[BPNum].Flags & VDMBP_FLUSH) ? "f" : " ",
  258. (VdmBPCache[BPNum].Flags & VDMBP_PENDING) ? "p" : " ");
  259. if (VdmBPCache[BPNum].Flags & VDMBP_V86) {
  260. mode = V86_MODE;
  261. PRINTF("&");
  262. } else {
  263. mode = PROT_MODE;
  264. PRINTF("#");
  265. }
  266. PRINTF("%04X:", VdmBPCache[BPNum].Seg);
  267. if (VdmBPCache[BPNum].Offset > 0xffff) {
  268. PRINTF("%08X", VdmBPCache[BPNum].Offset);
  269. } else {
  270. PRINTF("%04X", VdmBPCache[BPNum].Offset);
  271. }
  272. PRINTF(" %04X:***", VdmBPCache[BPNum].Count);
  273. if (FindSymbol(VdmBPCache[BPNum].Seg, VdmBPCache[BPNum].Offset,
  274. sym_text, &dist, BEFORE, mode )) {
  275. if ( dist == 0 ) {
  276. PRINTF(" %s", sym_text );
  277. } else {
  278. PRINTF(" %s+0x%lx", sym_text, dist );
  279. }
  280. }
  281. PRINTF("\n");
  282. }
  283. }
  284. }
  285. VOID
  286. bp(
  287. CMD_ARGLIST
  288. )
  289. {
  290. #ifdef _X86_
  291. CMD_INIT();
  292. PRINTF("Error- Use native BP command on x86 platforms\n");
  293. #else
  294. int BPNum;
  295. VDMCONTEXT ThreadContext;
  296. WORD selector;
  297. ULONG offset;
  298. USHORT count = 1;
  299. int mode;
  300. USHORT flags = 0;
  301. CMD_INIT();
  302. if (!LoadBreakPointCache()) {
  303. return;
  304. }
  305. mode = GetContext( &ThreadContext );
  306. if (!GetNextToken()) {
  307. PRINTF("Please enter an address\n");
  308. return;
  309. }
  310. if (!ParseIntelAddress(&mode, &selector, &offset)) {
  311. return;
  312. }
  313. if (mode == V86_MODE) {
  314. flags = VDMBP_V86;
  315. }
  316. //
  317. // first see if it's set already
  318. //
  319. for (BPNum = 0; BPNum < MAX_VDM_BREAKPOINTS; BPNum++) {
  320. if (VdmBPCache[BPNum].Flags & VDMBP_SET) {
  321. if ((VdmBPCache[BPNum].Seg == selector) &&
  322. (VdmBPCache[BPNum].Offset == offset) &&
  323. !(VdmBPCache[BPNum].Flags ^ flags))
  324. {
  325. VdmBPCache[BPNum].Count = count;
  326. if (!(VdmBPCache[BPNum].Flags & VDMBP_ENABLED)) {
  327. EnableBreakPoint(&VdmBPCache[BPNum]);
  328. }
  329. FlushBreakPointCache();
  330. PRINTF("breakpoint %d redefined\n", BPNum);
  331. return;
  332. }
  333. }
  334. }
  335. //
  336. // Not found, set a new one
  337. for (BPNum = 1; BPNum < MAX_VDM_BREAKPOINTS; BPNum++) {
  338. if (!(VdmBPCache[BPNum].Flags & (VDMBP_SET | VDMBP_FLUSH))) {
  339. VdmBPCache[BPNum].Seg = selector;
  340. VdmBPCache[BPNum].Offset = offset;
  341. VdmBPCache[BPNum].Count = count;
  342. VdmBPCache[BPNum].Flags = VDMBP_SET | flags;
  343. EnableBreakPoint(&VdmBPCache[BPNum]);
  344. FlushBreakPointCache();
  345. return;
  346. }
  347. }
  348. #endif
  349. }