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.

448 lines
9.4 KiB

  1. /*++
  2. Copyright (c) 1990 Microsoft Corporation
  3. Module Name:
  4. wdbgxlib.c
  5. Abstract:
  6. This module realizes most of the routines needed for the rdbss/smbmini debugger extension.
  7. Author:
  8. Balan Sethu Raman (SethuR) 11-May-1994
  9. Notes:
  10. Revision History:
  11. 11-Nov-1994 SethuR Created
  12. 11-Nov-1995 Changed to newer windbg apis
  13. --*/
  14. #include <ntos.h>
  15. #include <nturtl.h>
  16. #include "ntverp.h"
  17. #include <windows.h>
  18. #include <wdbgexts.h>
  19. #include <stdlib.h>
  20. #include <string.h>
  21. #include <stdio.h>
  22. #include <kdextlib.h>
  23. WINDBG_EXTENSION_APIS ExtensionApis;
  24. EXT_API_VERSION ApiVersion = { 3, 5, EXT_API_VERSION_NUMBER, 0 };
  25. #define ERRPRT dprintf
  26. #define NL 1
  27. #define NONL 0
  28. USHORT SavedMajorVersion;
  29. USHORT SavedMinorVersion;
  30. BOOL ChkTarget; // is debuggee a CHK build?
  31. /*
  32. * Print out an optional message, an ANSI_STRING, and maybe a new-line
  33. */
  34. BOOL
  35. wPrintStringA( IN LPSTR msg OPTIONAL, IN PANSI_STRING pStr, IN BOOL nl )
  36. {
  37. PCHAR StringData;
  38. ULONG BytesRead;
  39. if( msg )
  40. dprintf( msg );
  41. if( pStr->Length == 0 ) {
  42. if( nl )
  43. dprintf( "\n" );
  44. return TRUE;
  45. }
  46. StringData = (PCHAR)LocalAlloc( LPTR, pStr->Length + 1 );
  47. if( StringData == NULL ) {
  48. ERRPRT( "Out of memory!\n" );
  49. return FALSE;
  50. }
  51. ReadMemory( (ULONG_PTR)pStr->Buffer,
  52. StringData,
  53. pStr->Length,
  54. &BytesRead );
  55. if ( BytesRead ) {
  56. StringData[ pStr->Length ] = '\0';
  57. dprintf("%s%s", StringData, nl ? "\n" : "" );
  58. }
  59. LocalFree((HLOCAL)StringData);
  60. return BytesRead;
  61. }
  62. BOOL
  63. wPrintStringW( IN LPSTR msg OPTIONAL, IN PUNICODE_STRING pStr, IN BOOL nl )
  64. {
  65. UNICODE_STRING NewStr;
  66. ULONG BytesRead;
  67. if( msg )
  68. dprintf( msg );
  69. if( pStr->Length == 0 ) {
  70. if( nl )
  71. dprintf( "\n" );
  72. return TRUE;
  73. }
  74. NewStr.Buffer = (WCHAR *)LocalAlloc( LPTR, pStr->Length + 1 );
  75. NewStr.Length = pStr->Length;
  76. NewStr.MaximumLength = pStr->Length+1;
  77. if( NewStr.Buffer == NULL ) {
  78. ERRPRT( "Out of memory!\n" );
  79. return FALSE;
  80. }
  81. ReadMemory( (ULONG_PTR)pStr->Buffer,
  82. NewStr.Buffer,
  83. pStr->Length,
  84. &BytesRead );
  85. if ( BytesRead ) {
  86. dprintf("%wZ%s", &NewStr, nl ? "\n" : "" );
  87. }
  88. LocalFree((HLOCAL)NewStr.Buffer);
  89. return BytesRead;
  90. }
  91. /*
  92. * Fetches the data at the given address
  93. */
  94. BOOLEAN
  95. wGetData( ULONG_PTR dwAddress, PVOID ptr, ULONG size)
  96. {
  97. BOOL b;
  98. ULONG BytesRead;
  99. b = ReadMemory( dwAddress, ptr, size, &BytesRead );
  100. if (!b || BytesRead != size ) {
  101. dprintf( "Unable to read %u bytes at %X, for %s\n", size, dwAddress);
  102. return FALSE;
  103. }
  104. return TRUE;
  105. }
  106. /*
  107. * Fetch the null terminated ASCII string at dwAddress into buf
  108. */
  109. BOOL
  110. wGetString( ULONG_PTR dwAddress, PSZ buf )
  111. {
  112. for(;;) {
  113. if( !wGetData( dwAddress,buf, 1) ){
  114. //dprintf("readfailure at %08lx\n",dwAddress);
  115. return FALSE;
  116. }
  117. //dprintf ("stringing %08lx %08lx %c\n", dwAddress, buf,
  118. // ((*buf==0)?'.':*buf) );
  119. if ( *buf == '\0' ) { break; }
  120. dwAddress++;
  121. buf++;
  122. };
  123. return TRUE;
  124. }
  125. #if 0
  126. /*
  127. * Get 'size' bytes from the debuggee program at 'dwAddress' and place it
  128. * in our address space at 'ptr'. Use 'type' in an error printout if necessary
  129. */
  130. BOOL
  131. wGetData_srv( IN LPVOID ptr, IN ULONG_PTR dwAddress, IN ULONG size, IN PCSTR type )
  132. {
  133. BOOL b;
  134. ULONG BytesRead;
  135. ULONG count;
  136. while( size > 0 ) {
  137. count = min( size, 3000 );
  138. b = ReadMemory((ULONG) dwAddress, ptr, count, &BytesRead );
  139. if (!b || BytesRead != count ) {
  140. ERRPRT( "Unable to read %u bytes at %X, for %s\n", size, dwAddress, type );
  141. return FALSE;
  142. }
  143. dwAddress += count;
  144. size -= count;
  145. ptr = (LPVOID)((ULONG)ptr + count);
  146. }
  147. return TRUE;
  148. }
  149. /*
  150. * Follow a LIST_ENTRY list beginning with a head at dwListHeadAddr in the debugee's
  151. * address space. For each element in the list, print out the pointer value at 'offset'
  152. */
  153. BOOL
  154. PrintListEntryList( IN ULONG_PTR dwListHeadAddr, IN LONG offset )
  155. {
  156. LIST_ENTRY ListEntry;
  157. ULONG i=0;
  158. BOOL retval = TRUE;
  159. ULONG count = 20;
  160. if( !wGetData_srv( &ListEntry, dwListHeadAddr, sizeof( ListEntry ), "LIST_ENTRY" ) )
  161. return FALSE;
  162. while( count-- ) {
  163. if( (ULONG_PTR)ListEntry.Flink == dwListHeadAddr || (ULONG_PTR)ListEntry.Flink == 0 )
  164. break;
  165. if( !wGetData_srv( &ListEntry, (ULONG_PTR)ListEntry.Flink, sizeof( ListEntry ), "ListEntry" ) ) {
  166. retval = FALSE;
  167. break;
  168. }
  169. dprintf( "%16X%s", (LONG)ListEntry.Flink + offset, (i && !(i&3)) ? "\n" : "" );
  170. i++;
  171. }
  172. if( count == 0 && (ULONG_PTR)ListEntry.Flink != dwListHeadAddr && ListEntry.Flink ) {
  173. dprintf( "\nTruncated list dump\n" );
  174. } else if( ! ( i && !(i&3) ) ) {
  175. dprintf( "\n" );
  176. }
  177. return retval;
  178. }
  179. #endif
  180. /*
  181. * Print out a single HEX character
  182. */
  183. VOID
  184. wPrintHexChar( IN UCHAR c )
  185. {
  186. dprintf( "%c%c", "0123456789abcdef"[ (c>>4)&0xf ], "0123456789abcdef"[ c&0xf ] );
  187. }
  188. /*
  189. * Print out 'buf' of 'cbuf' bytes as HEX characters
  190. */
  191. VOID
  192. wPrintHexBuf( IN PUCHAR buf, IN ULONG cbuf )
  193. {
  194. while( cbuf-- ) {
  195. wPrintHexChar( *buf++ );
  196. dprintf( " " );
  197. }
  198. }
  199. #if 0
  200. /*
  201. * Fetch the null terminated UNICODE string at dwAddress into buf
  202. */
  203. BOOL
  204. GetString( IN ULONG_PTR dwAddress, IN LPWSTR buf, IN ULONG MaxChars )
  205. {
  206. do {
  207. if( !wGetData_srv( buf, dwAddress, sizeof( *buf ), "UNICODE Character" ) )
  208. return FALSE;
  209. dwAddress += sizeof( *buf );
  210. } while( --MaxChars && *buf++ != '\0' );
  211. return TRUE;
  212. }
  213. #endif
  214. VOID
  215. WinDbgExtensionDllInit(
  216. PWINDBG_EXTENSION_APIS lpExtensionApis,
  217. USHORT MajorVersion,
  218. USHORT MinorVersion
  219. )
  220. {
  221. ExtensionApis = *lpExtensionApis;
  222. SavedMajorVersion = MajorVersion;
  223. SavedMinorVersion = MinorVersion;
  224. ChkTarget = SavedMajorVersion == 0x0c ? TRUE : FALSE;
  225. }
  226. VOID
  227. CheckVersion(
  228. VOID
  229. )
  230. {
  231. #if DBG
  232. if ((SavedMajorVersion != 0x0c) || (SavedMinorVersion != VER_PRODUCTBUILD)) {
  233. dprintf("\r\n*** Extension DLL(%d Checked) does not match target system(%d %s)\r\n\r\n",
  234. VER_PRODUCTBUILD, SavedMinorVersion, (SavedMajorVersion==0x0f) ? "Free" : "Checked" );
  235. }
  236. #else
  237. if ((SavedMajorVersion != 0x0f) || (SavedMinorVersion != VER_PRODUCTBUILD)) {
  238. dprintf("\r\n*** Extension DLL(%d Free) does not match target system(%d %s)\r\n\r\n",
  239. VER_PRODUCTBUILD, SavedMinorVersion, (SavedMajorVersion==0x0f) ? "Free" : "Checked" );
  240. }
  241. #endif
  242. }
  243. LPEXT_API_VERSION
  244. ExtensionApiVersion(
  245. VOID
  246. )
  247. {
  248. return &ApiVersion;
  249. }
  250. ULONG FieldOffsetOfContextListEntryInRxC();
  251. VOID ReadRxContextFields(ULONG_PTR RxContext,PULONG_PTR pFcb,PULONG_PTR pThread, PULONG_PTR pMiniCtx2);
  252. DECLARE_API( dump );
  253. HANDLE DumpFile;
  254. CHAR wwDumpFormat[] = "-%06d: %s\n";
  255. VOID DumpRoutine(
  256. ULONG EntryNumber,
  257. PSZ OriginalStringToPrint
  258. )
  259. {
  260. UCHAR Buffer[200];
  261. UCHAR StringToPrint[160];
  262. PUCHAR p,q,r; LONG i;
  263. ULONG n,l3,l2,l1,l0; UCHAR Numbuf[32];
  264. ULONG ReturnedSize;
  265. //dprintf("before %d\n",EntryNumber);
  266. for (p=OriginalStringToPrint,q=StringToPrint,i=160;;) {
  267. PSZ format=NULL;
  268. if (*p==0) break;
  269. if (*p==0x4) {
  270. format = "%lx";
  271. } else if (*p==0x5) {
  272. format = "%ld";
  273. } else if (*p < ' ') {
  274. p++;i--;continue;
  275. }
  276. if (format!=NULL) {
  277. LONG Length;
  278. //translate the number
  279. p++;
  280. l0=*p++;
  281. l1=(*p++)<<8;
  282. l2=(*p++)<<16;
  283. l3=(*p++)<<24;
  284. n = l0 + l1 + l2 + l3;
  285. //dprintf("yaya %d %08lx %08lx %08lx %08lx %08lx\n",n,n,l0,l1,l2,l3);
  286. Length = sprintf(Numbuf,format,n);
  287. if (Length <= i) {
  288. for (r=Numbuf;*r;) { *q++ = *r++; }
  289. i -= Length;
  290. } else {
  291. i = 0;
  292. }
  293. if (i>0) continue;
  294. }
  295. if (i<=0) break;
  296. *q++ = *p++; i--;
  297. }
  298. *q = 0;
  299. //dprintf("after %d\n",EntryNumber);
  300. if (DumpFile == INVALID_HANDLE_VALUE) {
  301. dprintf(wwDumpFormat,EntryNumber,StringToPrint);
  302. return;
  303. }
  304. sprintf(Buffer,wwDumpFormat,EntryNumber,StringToPrint);
  305. WriteFile(DumpFile,Buffer,strlen(Buffer),&ReturnedSize,NULL);
  306. //should i check??
  307. return;
  308. }
  309. PCWSTR ExtensionLib = NULL;
  310. HANDLE hExtensionMod = NULL;
  311. ULONG DebugeeArchitecture = 0;
  312. PCWSTR GetExtensionLibPerDebugeeArchitecture(ULONG DebugeeArchitecture);
  313. DECLARE_API( dump );
  314. DECLARE_API( flags )
  315. {
  316. ULONG i,mask,newline,value;
  317. if( args && *args ) {
  318. sscanf(args,"%lx",&value);
  319. dprintf("Flags for %08lx\n",value);
  320. } else {
  321. dprintf("error in flags: no value presented\n");
  322. return;
  323. }
  324. for (i=newline=0,mask=1;i<32;i++,mask<<=1) {
  325. if (value&mask) {
  326. dprintf(" %02d 0x%08lx%c",i,mask,(newline==0)?' ':'\n');
  327. newline ^= 1;
  328. }
  329. }
  330. if (newline) {
  331. dprintf("\n");
  332. }
  333. }
  334. VOID dprintfsprintfbuffer(BYTE *Buffer)
  335. {
  336. dprintf("%s\n",Buffer);
  337. }
  338. BOOL
  339. wPrintLargeInt(
  340. LARGE_INTEGER *bigint)
  341. {
  342. dprintf( "%08x:%08x", bigint->HighPart, bigint->LowPart);
  343. return( TRUE );
  344. }