|
|
1.1 root 1: /******************************Module*Header*******************************\
2: * Module Name: debug.c
3: *
4: * debug helper routines
5: *
6: * Copyright (c) 1992-1993 Microsoft Corporation
7: *
8: \**************************************************************************/
9:
10: #include <stdio.h>
11: #include <stdarg.h>
12: #include <stdlib.h>
13:
14: #include "driver.h"
15:
16: #include <ntsdexts.h>
17:
18: #include "lines.h"
19:
20:
21: #if DBG
22:
23: #define LOG_SIZE_IN_BYTES 4000
24:
25: typedef struct _LOGGER {
26: ULONG ulEnd;
27: ULONG ulCurrent;
28: CHAR achBuf[LOG_SIZE_IN_BYTES];
29: } DBGLOG;
30:
31: #define GetAddress(dst, src)\
32: try {\
33: dst = (VOID*) lpGetExpressionRoutine(src);\
34: } except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?\
35: EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {\
36: lpOutputRoutine("NTSD: Access violation on \"%s\", switch to server context\n", src);\
37: return;\
38: }
39:
40: DBGLOG glog = {0, 0}; // If you muck with this, fix 'dumplog' too
41: ULONG DebugLevel = 0;
42: ULONG LogLevel = 1;
43:
44: #endif // DBG
45:
46: /*****************************************************************************
47: *
48: * Routine Description:
49: *
50: * This function is variable-argument, level-sensitive debug print
51: * routine.
52: * If the specified debug level for the print statement is lower or equal
53: * to the current debug level, the message will be printed.
54: *
55: * Arguments:
56: *
57: * DebugPrintLevel - Specifies at which debugging level the string should
58: * be printed
59: *
60: * DebugMessage - Variable argument ascii c string
61: *
62: * Return Value:
63: *
64: * None.
65: *
66: ***************************************************************************/
67:
68: VOID
69: DebugPrint(
70: ULONG DebugPrintLevel,
71: PCHAR DebugMessage,
72: ...
73: )
74:
75:
76: {
77:
78: #if DBG
79:
80: va_list ap;
81:
82: va_start(ap, DebugMessage);
83:
84: if (DebugPrintLevel <= DebugLevel) {
85:
86: char buffer[128];
87:
88: vsprintf(buffer, DebugMessage, ap);
89:
90: OutputDebugStringA(buffer);
91: }
92:
93: va_end(ap);
94:
95: #endif // DBG
96:
97: } // DebugPrint()
98:
99:
100: /*****************************************************************************
101: *
102: * Routine Description:
103: *
104: * This function is variable-argument, level-sensitive debug log
105: * routine.
106: * If the specified debug level for the log statement is lower or equal
107: * to the current debug level, the message will be logged.
108: *
109: * Arguments:
110: *
111: * DebugLogLevel - Specifies at which debugging level the string should
112: * be logged
113: *
114: * DebugMessage - Variable argument ascii c string
115: *
116: * Return Value:
117: *
118: * None.
119: *
120: ***************************************************************************/
121:
122: VOID
123: DebugLog(
124: ULONG DebugLogLevel,
125: PCHAR DebugMessage,
126: ...
127: )
128:
129:
130: {
131:
132: #if DBG
133:
134: va_list ap;
135:
136: va_start(ap, DebugMessage);
137:
138: if (DebugLogLevel <= LogLevel) {
139:
140: char buffer[128];
141: int length;
142:
143: length = vsprintf(buffer, DebugMessage, ap);
144:
145: length++; // Don't forget '\0' terminator!
146:
147: // Wrap around to the beginning of the log if not enough room for
148: // string:
149:
150: if (glog.ulCurrent + length >= LOG_SIZE_IN_BYTES) {
151: glog.ulEnd = glog.ulCurrent;
152: glog.ulCurrent = 0;
153: }
154:
155: memcpy(&glog.achBuf[glog.ulCurrent], buffer, length);
156: glog.ulCurrent += length;
157: }
158:
159: va_end(ap);
160:
161: #endif // DBG
162:
163: } // DebugLog()
164:
165:
166: /*****************************************************************************
167: *
168: * Routine Description:
169: *
170: * This function is called as an NTSD extension to dump a LineState
171: *
172: * Arguments:
173: *
174: * hCurrentProcess - Supplies a handle to the current process (at the
175: * time the extension was called).
176: *
177: * hCurrentThread - Supplies a handle to the current thread (at the
178: * time the extension was called).
179: *
180: * CurrentPc - Supplies the current pc at the time the extension is
181: * called.
182: *
183: * lpExtensionApis - Supplies the address of the functions callable
184: * by this extension.
185: *
186: * lpArgumentString - the float to display
187: *
188: * Return Value:
189: *
190: * None.
191: *
192: ***************************************************************************/
193: VOID dumplog(
194: HANDLE hCurrentProcess,
195: HANDLE hCurrentThread,
196: DWORD dwCurrentPc,
197: PNTSD_EXTENSION_APIS lpExtensionApis,
198: LPSTR lpArgumentString)
199: {
200:
201: #if DBG
202:
203: PNTSD_OUTPUT_ROUTINE lpOutputRoutine;
204: PNTSD_GET_EXPRESSION lpGetExpressionRoutine;
205: PNTSD_GET_SYMBOL lpGetSymbolRoutine;
206:
207: ULONG cFrom;
208: ULONG cTo;
209: ULONG cCurrent;
210: DBGLOG* plogOriginal;
211: DBGLOG* plog;
212: ULONG ulCurrent;
213: ULONG ulEnd;
214: CHAR* pchEnd;
215: CHAR* pch;
216:
217: UNREFERENCED_PARAMETER(hCurrentThread);
218: UNREFERENCED_PARAMETER(dwCurrentPc);
219:
220: lpOutputRoutine = lpExtensionApis->lpOutputRoutine;
221: lpGetExpressionRoutine = lpExtensionApis->lpGetExpressionRoutine;
222: lpGetSymbolRoutine = lpExtensionApis->lpGetSymbolRoutine;
223:
224: lpOutputRoutine("!s3.dumplog [<from#> [<to#>]]\n\n");
225:
226: // Evaluate the argument string to get the address of
227: // the Line Structure
228:
229: cTo = 1; // Defaults
230: cFrom = 20;
231:
232: pch = strpbrk(lpArgumentString, "0123456789");
233: if (pch != NULL) // Use defaults if no args given
234: {
235: cFrom = atoi(pch);
236: pch = strchr(pch, ' ');
237: if (pch != NULL)
238: {
239: pch = strpbrk(pch, "0123456789");
240: if (pch != NULL)
241: cTo = atoi(pch);
242: }
243: }
244:
245: // Do some parameter validation, then read the log into the
246: // debugger process's address space:
247:
248: if (cTo >= cFrom)
249: cTo = cFrom;
250:
251: if (cTo < 1)
252: {
253: cTo = 1;
254: cFrom = 1;
255: }
256:
257: GetAddress(plogOriginal, "glog");
258:
259: if (!ReadProcessMemory(hCurrentProcess,
260: (LPVOID) &(plogOriginal->ulCurrent),
261: &ulCurrent,
262: sizeof(ulCurrent),
263: NULL))
264: return;
265:
266: if (!ReadProcessMemory(hCurrentProcess,
267: (LPVOID) &(plogOriginal->ulEnd),
268: &ulEnd,
269: sizeof(ulEnd),
270: NULL))
271: return;
272:
273: if (ulCurrent == 0 && ulEnd == 0)
274: {
275: lpOutputRoutine("Log empty\n\n");
276: return;
277: }
278:
279: plog = (DBGLOG*) LocalAlloc(0, sizeof(DBGLOG) + 1);
280:
281: if (plog == NULL) {
282: lpOutputRoutine("Couldn't allocate temporary buffer!\n");
283: return;
284: }
285:
286: if (!ReadProcessMemory(hCurrentProcess,
287: (LPVOID) &(plogOriginal->achBuf[0]),
288: &plog->achBuf[1],
289: LOG_SIZE_IN_BYTES,
290: NULL))
291: return;
292:
293: // Mark the first byte in the buffer as being a zero, because
294: // we're going to search backwards through the buffer for zeroes,
295: // and we'll want to stop when we get to the beginning:
296:
297: plog->achBuf[0] = 0;
298: ulCurrent++;
299: ulEnd++;
300:
301: // Find the start string by going backwards through the buffer
302: // and counting strings until the count becomes equal to 'cFrom':
303:
304: cCurrent = 0;
305: pch = &plog->achBuf[ulCurrent - 1];
306: pchEnd = &plog->achBuf[0];
307:
308: while (TRUE)
309: {
310: if (*(--pch) == 0)
311: {
312: cCurrent++;
313: if (--cFrom == 0)
314: break;
315:
316: if (pch == &plog->achBuf[ulCurrent - 1])
317: break; // We're back to where we started!
318: }
319:
320: // Make sure we wrap the end of the buffer:
321:
322: if (pch <= pchEnd)
323: {
324: if (ulCurrent >= ulEnd)
325: break;
326:
327: pch = &plog->achBuf[ulEnd - 1];
328: }
329: }
330:
331: // pch is pointing to zero byte before our start string:
332:
333: pch++;
334:
335: // Output the strings:
336:
337: pchEnd = &plog->achBuf[max(ulEnd, ulCurrent)];
338:
339: while (cCurrent >= cTo)
340: {
341: lpOutputRoutine("-%li: %s", cCurrent, pch);
342: pch += strlen(pch) + 1;
343: cCurrent--;
344:
345: // Make sure we wrap when we get to the end of the buffer:
346:
347: if (pch >= pchEnd)
348: pch = &plog->achBuf[1]; // First char in buffer is a NULL
349: }
350:
351: lpOutputRoutine("\n");
352: LocalFree(plog);
353:
354: #endif // DBG
355:
356: return;
357: }
358:
359: /*****************************************************************************
360: *
361: * Routine Description:
362: *
363: * This function is called as an NTSD extension to dump
364: * the CRTC registers of an S3 chip
365: *
366: * Arguments:
367: *
368: * hCurrentProcess - Supplies a handle to the current process (at the
369: * time the extension was called).
370: *
371: * hCurrentThread - Supplies a handle to the current thread (at the
372: * time the extension was called).
373: *
374: * CurrentPc - Supplies the current pc at the time the extension is
375: * called.
376: *
377: * lpExtensionApis - Supplies the address of the functions callable
378: * by this extension.
379: *
380: * lpArgumentString - the float to display
381: *
382: * Return Value:
383: *
384: * None.
385: *
386: ***************************************************************************/
387: VOID dcrtc(
388: HANDLE hCurrentProcess,
389: HANDLE hCurrentThread,
390: DWORD dwCurrentPc,
391: PNTSD_EXTENSION_APIS lpExtensionApis,
392: LPSTR lpArgumentString)
393: {
394:
395: #if DBG
396:
397: PNTSD_OUTPUT_ROUTINE lpOutputRoutine;
398: PNTSD_GET_EXPRESSION lpGetExpressionRoutine;
399: PNTSD_GET_SYMBOL lpGetSymbolRoutine;
400: CHAR Symbol[64];
401: DWORD Displacement;
402: BOOL b;
403:
404: BYTE szBuff[256];
405: INT i;
406: BYTE ajCrtc[0x65];
407: DWORD dwAddr;
408:
409: UNREFERENCED_PARAMETER(hCurrentThread);
410: UNREFERENCED_PARAMETER(dwCurrentPc);
411:
412: lpOutputRoutine = lpExtensionApis->lpOutputRoutine;
413: lpGetExpressionRoutine = lpExtensionApis->lpGetExpressionRoutine;
414: lpGetSymbolRoutine = lpExtensionApis->lpGetSymbolRoutine;
415:
416: //
417: // Evaluate the argument string to get the address of
418: // the Line Structure
419: //
420:
421: dwAddr = (lpGetExpressionRoutine)(lpArgumentString);
422: if (!dwAddr) {
423: return;
424: }
425:
426: //
427: // Get the symbolic name
428: //
429:
430: (lpGetSymbolRoutine)((LPVOID)dwAddr, Symbol, &Displacement);
431:
432: //
433: // Read from the debuggees address space into our own.
434: //
435:
436: b = ReadProcessMemory(hCurrentProcess,
437: (LPVOID)dwAddr,
438: ajCrtc,
439: sizeof(ajCrtc),
440: NULL);
441:
442: if (!b) {
443: return;
444: }
445:
446: for (i = 0; i < 0x65; i++)
447: {
448: sprintf(szBuff, "%4.4x: %2.2x\n", i, ajCrtc[i]);
449: (lpOutputRoutine)(szBuff);
450: }
451:
452:
453: #endif // DBG
454:
455: return;
456: }
457:
458:
459:
460:
461:
462: /*****************************************************************************
463: *
464: * Routine Description:
465: *
466: * This function is called as an NTSD extension to dump a LineState
467: *
468: * Arguments:
469: *
470: * hCurrentProcess - Supplies a handle to the current process (at the
471: * time the extension was called).
472: *
473: * hCurrentThread - Supplies a handle to the current thread (at the
474: * time the extension was called).
475: *
476: * CurrentPc - Supplies the current pc at the time the extension is
477: * called.
478: *
479: * lpExtensionApis - Supplies the address of the functions callable
480: * by this extension.
481: *
482: * lpArgumentString - the float to display
483: *
484: * Return Value:
485: *
486: * None.
487: *
488: ***************************************************************************/
489: VOID dls(
490: HANDLE hCurrentProcess,
491: HANDLE hCurrentThread,
492: DWORD dwCurrentPc,
493: PNTSD_EXTENSION_APIS lpExtensionApis,
494: LPSTR lpArgumentString)
495: {
496:
497: #if DBG
498:
499: PNTSD_OUTPUT_ROUTINE lpOutputRoutine;
500: PNTSD_GET_EXPRESSION lpGetExpressionRoutine;
501: PNTSD_GET_SYMBOL lpGetSymbolRoutine;
502: CHAR Symbol[64];
503: DWORD Displacement;
504: BOOL b;
505:
506: DWORD dwAddr;
507: LINESTATE ls;
508: BYTE szBuff[256];
509:
510: UNREFERENCED_PARAMETER(hCurrentThread);
511: UNREFERENCED_PARAMETER(dwCurrentPc);
512:
513: lpOutputRoutine = lpExtensionApis->lpOutputRoutine;
514: lpGetExpressionRoutine = lpExtensionApis->lpGetExpressionRoutine;
515: lpGetSymbolRoutine = lpExtensionApis->lpGetSymbolRoutine;
516:
517: //
518: // Evaluate the argument string to get the address of
519: // the Line Structure
520: //
521:
522: dwAddr = (lpGetExpressionRoutine)(lpArgumentString);
523: if (!dwAddr) {
524: return;
525: }
526:
527: //
528: // Get the symbolic name
529: //
530:
531: (lpGetSymbolRoutine)((LPVOID)dwAddr, Symbol, &Displacement);
532:
533: //
534: // Read from the debuggees address space into our own.
535: //
536:
537: b = ReadProcessMemory(hCurrentProcess,
538: (LPVOID)dwAddr,
539: &ls,
540: sizeof(ls),
541: NULL);
542:
543: if (!b) {
544: return;
545: }
546:
547:
548: sprintf(szBuff, "LineState: %8.8x\n", dwAddr);
549: (lpOutputRoutine)(szBuff);
550:
551: sprintf(szBuff, "\tjAnd : %2.2x\n", ls.jAnd);
552: (lpOutputRoutine)(szBuff);
553:
554: sprintf(szBuff, "\tjXor : %2.2x\n", ls.jXor);
555: (lpOutputRoutine)(szBuff);
556:
557: sprintf(szBuff, "\tpspStart : %4.4x\n", ls.pspStart);
558: (lpOutputRoutine)(szBuff);
559:
560: sprintf(szBuff, "\tpspEnd : %4.4x\n", ls.pspEnd);
561: (lpOutputRoutine)(szBuff);
562:
563: sprintf(szBuff, "\tpsp : %4.4x\n", ls.psp);
564: (lpOutputRoutine)(szBuff);
565:
566: sprintf(szBuff, "\tspRemaining : %4.4x\n", ls.spRemaining);
567: (lpOutputRoutine)(szBuff);
568:
569: sprintf(szBuff, "\tspTotal : %4.4x\n", ls.spTotal);
570: (lpOutputRoutine)(szBuff);
571:
572: sprintf(szBuff, "\tspTotal2 : %4.4x\n", ls.spTotal2);
573: (lpOutputRoutine)(szBuff);
574:
575: sprintf(szBuff, "\tspNext : %4.4x\n", ls.spNext);
576: (lpOutputRoutine)(szBuff);
577:
578: sprintf(szBuff, "\tspComplex : %4.4x\n", ls.spComplex);
579: (lpOutputRoutine)(szBuff);
580:
581: sprintf(szBuff, "\taspRtoL : %4.4x\n", ls.aspRtoL);
582: (lpOutputRoutine)(szBuff);
583:
584: sprintf(szBuff, "\taspLtoR : %4.4x\n", ls.aspLtoR);
585: (lpOutputRoutine)(szBuff);
586:
587: sprintf(szBuff, "\tulStyleMask : %4.4x\n", ls.ulStyleMask);
588: (lpOutputRoutine)(szBuff);
589:
590: sprintf(szBuff, "\txyDensity : %4.4x\n", ls.xyDensity);
591: (lpOutputRoutine)(szBuff);
592:
593: sprintf(szBuff, "\tcStyle : %4.4x\n", ls.cStyle);
594: (lpOutputRoutine)(szBuff);
595:
596: sprintf(szBuff, "\tulStyleMaskLtoR : %4.4x\n", ls.ulStyleMaskLtoR);
597: (lpOutputRoutine)(szBuff);
598:
599: sprintf(szBuff, "\tulStyleMaskRtoL : %4.4x\n", ls.ulStyleMaskRtoL);
600: (lpOutputRoutine)(szBuff);
601:
602: sprintf(szBuff, "\tulStartMask : %4.4x\n", ls.ulStartMask);
603: (lpOutputRoutine)(szBuff);
604:
605: #endif // DBG
606:
607: return;
608: }
609:
610: /*****************************************************************************
611: *
612: * Routine Description:
613: *
614: * This function is called as an NTSD extension to dump a dword
615: * (It's real function is as a prototype for other NT extensions.)
616: *
617: * Arguments:
618: *
619: * hCurrentProcess - Supplies a handle to the current process (at the
620: * time the extension was called).
621: *
622: * hCurrentThread - Supplies a handle to the current thread (at the
623: * time the extension was called).
624: *
625: * CurrentPc - Supplies the current pc at the time the extension is
626: * called.
627: *
628: * lpExtensionApis - Supplies the address of the functions callable
629: * by this extension.
630: *
631: * lpArgumentString - the float to display
632: *
633: * Return Value:
634: *
635: * None.
636: *
637: ***************************************************************************/
638: VOID dd(
639: HANDLE hCurrentProcess,
640: HANDLE hCurrentThread,
641: DWORD dwCurrentPc,
642: PNTSD_EXTENSION_APIS lpExtensionApis,
643: LPSTR lpArgumentString)
644: {
645:
646: #if DBG
647:
648: PNTSD_OUTPUT_ROUTINE lpOutputRoutine;
649: PNTSD_GET_EXPRESSION lpGetExpressionRoutine;
650: PNTSD_GET_SYMBOL lpGetSymbolRoutine;
651: CHAR Symbol[64];
652: DWORD Displacement;
653: BOOL b;
654:
655: DWORD dwAddr;
656: DWORD val;
657: BYTE szBuff[256];
658:
659: UNREFERENCED_PARAMETER(hCurrentThread);
660: UNREFERENCED_PARAMETER(dwCurrentPc);
661:
662: lpOutputRoutine = lpExtensionApis->lpOutputRoutine;
663: lpGetExpressionRoutine = lpExtensionApis->lpGetExpressionRoutine;
664: lpGetSymbolRoutine = lpExtensionApis->lpGetSymbolRoutine;
665:
666: //
667: // Evaluate the argument string to get the address of
668: // the Line Structure
669: //
670:
671: dwAddr = (lpGetExpressionRoutine)(lpArgumentString);
672: if (!dwAddr) {
673: return;
674: }
675:
676: //
677: // Get the symbolic name
678: //
679:
680: (lpGetSymbolRoutine)((LPVOID)dwAddr, Symbol, &Displacement);
681:
682: //
683: // Read from the debuggees address space into our own.
684: //
685:
686: b = ReadProcessMemory(hCurrentProcess,
687: (LPVOID)dwAddr,
688: &val,
689: sizeof(val),
690: NULL);
691:
692: if (!b) {
693: return;
694: }
695:
696: sprintf(szBuff, "%8.8x: %8.8x\n", dwAddr, val);
697: (lpOutputRoutine)(szBuff);
698: #endif // DBG
699:
700: return;
701: }
702:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.