Leaked source code of windows server 2003
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.5 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. if(sscanf(lpArgumentString, "%d", &BPNum) != 1 || BPNum >= MAX_VDM_BREAKPOINTS) {
  176. PRINTF("Invalid breakpoint - %d\n", BPNum);
  177. return;
  178. }
  179. DoBreakPoints[BPNum] = TRUE;
  180. count++;
  181. SkipToNextWhiteSpace();
  182. }
  183. if (!count) {
  184. PRINTF("Please specify a breakpoint #\n");
  185. return;
  186. }
  187. for (BPNum=0; BPNum<MAX_VDM_BREAKPOINTS; BPNum++) {
  188. if (!DoBreakPoints[BPNum] && !DoAll) {
  189. continue;
  190. }
  191. if (!(VdmBPCache[BPNum].Flags & VDMBP_SET)) {
  192. continue;
  193. }
  194. switch(Cmd) {
  195. case BREAKPOINT_CLEAR:
  196. if (VdmBPCache[BPNum].Flags & VDMBP_ENABLED) {
  197. DisableBreakPoint(&VdmBPCache[BPNum]);
  198. }
  199. VdmBPCache[BPNum].Flags &= ~VDMBP_SET;
  200. break;
  201. case BREAKPOINT_DISABLE:
  202. if (VdmBPCache[BPNum].Flags & VDMBP_ENABLED) {
  203. DisableBreakPoint(&VdmBPCache[BPNum]);
  204. }
  205. break;
  206. case BREAKPOINT_ENABLE:
  207. if (!(VdmBPCache[BPNum].Flags & VDMBP_ENABLED)) {
  208. EnableBreakPoint(&VdmBPCache[BPNum]);
  209. }
  210. break;
  211. }
  212. }
  213. FlushBreakPointCache();
  214. }
  215. VOID
  216. bc(
  217. CMD_ARGLIST
  218. )
  219. {
  220. CMD_INIT();
  221. UpdateBreakPoint(BREAKPOINT_CLEAR);
  222. }
  223. VOID
  224. bd(
  225. CMD_ARGLIST
  226. )
  227. {
  228. CMD_INIT();
  229. UpdateBreakPoint(BREAKPOINT_DISABLE);
  230. }
  231. VOID
  232. be(
  233. CMD_ARGLIST
  234. )
  235. {
  236. CMD_INIT();
  237. UpdateBreakPoint(BREAKPOINT_ENABLE);
  238. }
  239. VOID
  240. bl(
  241. CMD_ARGLIST
  242. )
  243. {
  244. int BPNum;
  245. int mode;
  246. DWORD dist;
  247. CHAR sym_text[255];
  248. CMD_INIT();
  249. if (!LoadBreakPointCache()) {
  250. return;
  251. }
  252. for (BPNum = 0; BPNum < MAX_VDM_BREAKPOINTS; BPNum++) {
  253. if (VdmBPCache[BPNum].Flags & VDMBP_SET) {
  254. PRINTF("%d %s%s%s ", BPNum,
  255. (VdmBPCache[BPNum].Flags & VDMBP_ENABLED) ? "e" : "d",
  256. (VdmBPCache[BPNum].Flags & VDMBP_FLUSH) ? "f" : " ",
  257. (VdmBPCache[BPNum].Flags & VDMBP_PENDING) ? "p" : " ");
  258. if (VdmBPCache[BPNum].Flags & VDMBP_V86) {
  259. mode = V86_MODE;
  260. PRINTF("&");
  261. } else {
  262. mode = PROT_MODE;
  263. PRINTF("#");
  264. }
  265. PRINTF("%04X:", VdmBPCache[BPNum].Seg);
  266. if (VdmBPCache[BPNum].Offset > 0xffff) {
  267. PRINTF("%08X", VdmBPCache[BPNum].Offset);
  268. } else {
  269. PRINTF("%04X", VdmBPCache[BPNum].Offset);
  270. }
  271. PRINTF(" %04X:***", VdmBPCache[BPNum].Count);
  272. if (FindSymbol(VdmBPCache[BPNum].Seg, VdmBPCache[BPNum].Offset,
  273. sym_text, &dist, BEFORE, mode )) {
  274. if ( dist == 0 ) {
  275. PRINTF(" %s", sym_text );
  276. } else {
  277. PRINTF(" %s+0x%lx", sym_text, dist );
  278. }
  279. }
  280. PRINTF("\n");
  281. }
  282. }
  283. }
  284. VOID
  285. bp(
  286. CMD_ARGLIST
  287. )
  288. {
  289. #ifdef _X86_
  290. CMD_INIT();
  291. PRINTF("Error- Use native BP command on x86 platforms\n");
  292. #else
  293. int BPNum;
  294. VDMCONTEXT ThreadContext;
  295. WORD selector;
  296. ULONG offset;
  297. USHORT count = 1;
  298. int mode;
  299. USHORT flags = 0;
  300. CMD_INIT();
  301. if (!LoadBreakPointCache()) {
  302. return;
  303. }
  304. mode = GetContext( &ThreadContext );
  305. if (!GetNextToken()) {
  306. PRINTF("Please enter an address\n");
  307. return;
  308. }
  309. if (!ParseIntelAddress(&mode, &selector, &offset)) {
  310. return;
  311. }
  312. if (mode == V86_MODE) {
  313. flags = VDMBP_V86;
  314. }
  315. //
  316. // first see if it's set already
  317. //
  318. for (BPNum = 0; BPNum < MAX_VDM_BREAKPOINTS; BPNum++) {
  319. if (VdmBPCache[BPNum].Flags & VDMBP_SET) {
  320. if ((VdmBPCache[BPNum].Seg == selector) &&
  321. (VdmBPCache[BPNum].Offset == offset) &&
  322. !(VdmBPCache[BPNum].Flags ^ flags))
  323. {
  324. VdmBPCache[BPNum].Count = count;
  325. if (!(VdmBPCache[BPNum].Flags & VDMBP_ENABLED)) {
  326. EnableBreakPoint(&VdmBPCache[BPNum]);
  327. }
  328. FlushBreakPointCache();
  329. PRINTF("breakpoint %d redefined\n", BPNum);
  330. return;
  331. }
  332. }
  333. }
  334. //
  335. // Not found, set a new one
  336. for (BPNum = 1; BPNum < MAX_VDM_BREAKPOINTS; BPNum++) {
  337. if (!(VdmBPCache[BPNum].Flags & (VDMBP_SET | VDMBP_FLUSH))) {
  338. VdmBPCache[BPNum].Seg = selector;
  339. VdmBPCache[BPNum].Offset = offset;
  340. VdmBPCache[BPNum].Count = count;
  341. VdmBPCache[BPNum].Flags = VDMBP_SET | flags;
  342. EnableBreakPoint(&VdmBPCache[BPNum]);
  343. FlushBreakPointCache();
  344. return;
  345. }
  346. }
  347. #endif
  348. }