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.

588 lines
12 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. exts.c
  5. Abstract:
  6. This file contains the generic routines and initialization code
  7. for the kernel debugger extensions dll.
  8. Environment:
  9. User Mode
  10. --*/
  11. #include "precomp.h"
  12. #pragma hdrstop
  13. #include <ntverp.h>
  14. //
  15. // Valid for the lifetime of the debug session.
  16. //
  17. WINDBG_EXTENSION_APIS ExtensionApis;
  18. ULONG TargetMachine;
  19. BOOL Connected;
  20. ULONG g_TargetClass, g_TargetQual;
  21. //
  22. // Valid only during an extension API call
  23. //
  24. PDEBUG_ADVANCED g_ExtAdvanced;
  25. PDEBUG_CLIENT g_ExtClient;
  26. PDEBUG_CONTROL g_ExtControl;
  27. PDEBUG_DATA_SPACES g_ExtData;
  28. PDEBUG_REGISTERS g_ExtRegisters;
  29. PDEBUG_SYMBOLS2 g_ExtSymbols;
  30. PDEBUG_SYSTEM_OBJECTS g_ExtSystem;
  31. // Queries for all debugger interfaces.
  32. extern "C" HRESULT
  33. ExtQuery(PDEBUG_CLIENT Client)
  34. {
  35. HRESULT Status;
  36. if ((Status = Client->QueryInterface(__uuidof(IDebugAdvanced),
  37. (void **)&g_ExtAdvanced)) != S_OK)
  38. {
  39. goto Fail;
  40. }
  41. if ((Status = Client->QueryInterface(__uuidof(IDebugControl),
  42. (void **)&g_ExtControl)) != S_OK)
  43. {
  44. goto Fail;
  45. }
  46. if ((Status = Client->QueryInterface(__uuidof(IDebugDataSpaces),
  47. (void **)&g_ExtData)) != S_OK)
  48. {
  49. goto Fail;
  50. }
  51. if ((Status = Client->QueryInterface(__uuidof(IDebugRegisters),
  52. (void **)&g_ExtRegisters)) != S_OK)
  53. {
  54. goto Fail;
  55. }
  56. if ((Status = Client->QueryInterface(__uuidof(IDebugSymbols),
  57. (void **)&g_ExtSymbols)) != S_OK)
  58. {
  59. goto Fail;
  60. }
  61. if ((Status = Client->QueryInterface(__uuidof(IDebugSystemObjects),
  62. (void **)&g_ExtSystem)) != S_OK)
  63. {
  64. goto Fail;
  65. }
  66. g_ExtClient = Client;
  67. return S_OK;
  68. Fail:
  69. ExtRelease();
  70. return Status;
  71. }
  72. // Cleans up all debugger interfaces.
  73. void
  74. ExtRelease(void)
  75. {
  76. g_ExtClient = NULL;
  77. EXT_RELEASE(g_ExtAdvanced);
  78. EXT_RELEASE(g_ExtControl);
  79. EXT_RELEASE(g_ExtData);
  80. EXT_RELEASE(g_ExtRegisters);
  81. EXT_RELEASE(g_ExtSymbols);
  82. EXT_RELEASE(g_ExtSystem);
  83. }
  84. // Normal output.
  85. void __cdecl
  86. ExtOut(PCSTR Format, ...)
  87. {
  88. va_list Args;
  89. va_start(Args, Format);
  90. g_ExtControl->OutputVaList(DEBUG_OUTPUT_NORMAL, Format, Args);
  91. va_end(Args);
  92. }
  93. // Error output.
  94. void __cdecl
  95. ExtErr(PCSTR Format, ...)
  96. {
  97. va_list Args;
  98. va_start(Args, Format);
  99. g_ExtControl->OutputVaList(DEBUG_OUTPUT_ERROR, Format, Args);
  100. va_end(Args);
  101. }
  102. // Warning output.
  103. void __cdecl
  104. ExtWarn(PCSTR Format, ...)
  105. {
  106. va_list Args;
  107. va_start(Args, Format);
  108. g_ExtControl->OutputVaList(DEBUG_OUTPUT_WARNING, Format, Args);
  109. va_end(Args);
  110. }
  111. // Verbose output.
  112. void __cdecl
  113. ExtVerb(PCSTR Format, ...)
  114. {
  115. va_list Args;
  116. va_start(Args, Format);
  117. g_ExtControl->OutputVaList(DEBUG_OUTPUT_VERBOSE, Format, Args);
  118. va_end(Args);
  119. }
  120. extern "C"
  121. HRESULT
  122. CALLBACK
  123. DebugExtensionInitialize(PULONG Version, PULONG Flags)
  124. {
  125. IDebugClient *DebugClient;
  126. PDEBUG_CONTROL DebugControl;
  127. HRESULT Hr;
  128. *Version = DEBUG_EXTENSION_VERSION(1, 0);
  129. *Flags = 0;
  130. if ((Hr = DebugCreate(__uuidof(IDebugClient),
  131. (void **)&DebugClient)) != S_OK)
  132. {
  133. return Hr;
  134. }
  135. if ((Hr = DebugClient->QueryInterface(__uuidof(IDebugControl),
  136. (void **)&DebugControl)) != S_OK)
  137. {
  138. return Hr;
  139. }
  140. ExtensionApis.nSize = sizeof (ExtensionApis);
  141. if ((Hr = DebugControl->GetWindbgExtensionApis64(&ExtensionApis)) != S_OK) {
  142. return Hr;
  143. }
  144. DebugControl->Release();
  145. DebugClient->Release();
  146. return S_OK;
  147. }
  148. extern "C"
  149. void
  150. CALLBACK
  151. DebugExtensionNotify(ULONG Notify, ULONG64 Argument)
  152. {
  153. //
  154. // The first time we actually connect to a target, get the page size
  155. //
  156. if ((Notify == DEBUG_NOTIFY_SESSION_ACCESSIBLE) && (!Connected))
  157. {
  158. IDebugClient *DebugClient;
  159. PDEBUG_DATA_SPACES DebugDataSpaces;
  160. PDEBUG_CONTROL DebugControl;
  161. HRESULT Hr;
  162. ULONG64 Page;
  163. if ((Hr = DebugCreate(__uuidof(IDebugClient),
  164. (void **)&DebugClient)) == S_OK)
  165. {
  166. //
  167. // Get the architecture type.
  168. //
  169. if ((Hr = DebugClient->QueryInterface(__uuidof(IDebugControl),
  170. (void **)&DebugControl)) == S_OK)
  171. {
  172. if ((Hr = DebugControl->GetActualProcessorType(
  173. &TargetMachine)) == S_OK)
  174. {
  175. Connected = TRUE;
  176. }
  177. ULONG Qualifier;
  178. if ((Hr = DebugControl->GetDebuggeeType(&g_TargetClass, &g_TargetQual)) == S_OK)
  179. {
  180. }
  181. DebugControl->Release();
  182. }
  183. DebugClient->Release();
  184. }
  185. }
  186. if (Notify == DEBUG_NOTIFY_SESSION_INACTIVE)
  187. {
  188. Connected = FALSE;
  189. TargetMachine = 0;
  190. }
  191. return;
  192. }
  193. extern "C"
  194. void
  195. CALLBACK
  196. DebugExtensionUninitialize(void)
  197. {
  198. return;
  199. }
  200. DllInit(
  201. HANDLE hModule,
  202. DWORD dwReason,
  203. DWORD dwReserved
  204. )
  205. {
  206. switch (dwReason) {
  207. case DLL_THREAD_ATTACH:
  208. break;
  209. case DLL_THREAD_DETACH:
  210. break;
  211. case DLL_PROCESS_DETACH:
  212. break;
  213. case DLL_PROCESS_ATTACH:
  214. break;
  215. }
  216. return TRUE;
  217. }
  218. DECLARE_API ( time )
  219. {
  220. dprintf("*** !time is obsolete: Use '.time'\n");
  221. return S_OK;
  222. }
  223. HRESULT
  224. PrintString(
  225. BOOL Unicode,
  226. PDEBUG_CLIENT Client,
  227. LPCSTR args
  228. )
  229. {
  230. ULONG64 AddrString;
  231. ULONG64 Displacement;
  232. STRING32 String;
  233. UNICODE_STRING UnicodeString;
  234. ULONG64 AddrBuffer;
  235. CHAR Symbol[1024];
  236. LPSTR StringData;
  237. HRESULT hResult;
  238. BOOL b;
  239. AddrString = GetExpression(args);
  240. if (!AddrString)
  241. {
  242. return E_FAIL;
  243. }
  244. //
  245. // Get the symbolic name of the string
  246. //
  247. GetSymbol(AddrString, Symbol, &Displacement);
  248. //
  249. // Read the string from the debuggees address space into our
  250. // own.
  251. b = ReadMemory(AddrString, &String, sizeof(String), NULL);
  252. if ( !b )
  253. {
  254. return E_FAIL;
  255. }
  256. INIT_API();
  257. if (IsPtr64())
  258. {
  259. hResult = g_ExtData->ReadPointersVirtual(1,
  260. AddrString + FIELD_OFFSET(STRING64, Buffer),
  261. &AddrBuffer);
  262. }
  263. else
  264. {
  265. hResult = g_ExtData->ReadPointersVirtual(1,
  266. AddrString + FIELD_OFFSET(STRING32, Buffer),
  267. &AddrBuffer);
  268. }
  269. EXIT_API();
  270. if (hResult != S_OK)
  271. {
  272. return E_FAIL;
  273. }
  274. StringData = (LPSTR) LocalAlloc(LMEM_ZEROINIT,
  275. String.Length + sizeof(UNICODE_NULL));
  276. if (!StringData)
  277. {
  278. return E_FAIL;
  279. }
  280. dprintf("String(%d,%d)", String.Length, String.MaximumLength);
  281. if (Symbol[0])
  282. {
  283. dprintf(" %s+%p", Symbol, Displacement);
  284. }
  285. b = ReadMemory(AddrBuffer, StringData, String.Length, NULL);
  286. if ( b )
  287. {
  288. if (Unicode)
  289. {
  290. ANSI_STRING AnsiString;
  291. UnicodeString.Buffer = (PWSTR)StringData;
  292. UnicodeString.Length = String.Length;
  293. UnicodeString.MaximumLength = String.Length+sizeof(UNICODE_NULL);
  294. RtlUnicodeStringToAnsiString(&AnsiString, &UnicodeString,TRUE);
  295. dprintf(" at %p: %s\n", AddrString, AnsiString.Buffer);
  296. RtlFreeAnsiString(&AnsiString);
  297. }
  298. else
  299. {
  300. dprintf(" at %p: %s\n", AddrString, StringData);
  301. }
  302. LocalFree(StringData);
  303. return S_OK;
  304. }
  305. else
  306. {
  307. LocalFree(StringData);
  308. return E_FAIL;
  309. }
  310. }
  311. DECLARE_API( str )
  312. /*++
  313. Routine Description:
  314. This function is called to format and dump counted (ansi) string.
  315. Arguments:
  316. args - Address
  317. Return Value:
  318. None.
  319. --*/
  320. {
  321. return PrintString(FALSE, Client, args);
  322. }
  323. DECLARE_API( ustr )
  324. /*++
  325. Routine Description:
  326. This function is called to format and dump counted (unicode) string.
  327. Arguments:
  328. args - Address
  329. Return Value:
  330. None.
  331. --*/
  332. {
  333. return PrintString(TRUE, Client, args);
  334. }
  335. DECLARE_API( obja )
  336. /*++
  337. Routine Description:
  338. This function is called to format and dump an object attributes structure.
  339. Arguments:
  340. args - Address
  341. Return Value:
  342. None.
  343. --*/
  344. {
  345. ULONG64 AddrObja;
  346. ULONG64 Displacement;
  347. ULONG64 AddrString;
  348. STRING32 String;
  349. ULONG64 StrAddr = NULL;
  350. CHAR Symbol[1024];
  351. LPSTR StringData;
  352. BOOL b;
  353. ULONG Attr;
  354. HRESULT hResult;
  355. ULONG ObjectNameOffset;
  356. ULONG AttrOffset;
  357. ULONG StringOffset;
  358. if (IsPtr64())
  359. {
  360. ObjectNameOffset = FIELD_OFFSET(OBJECT_ATTRIBUTES64, ObjectName);
  361. AttrOffset = FIELD_OFFSET(OBJECT_ATTRIBUTES64, Attributes);
  362. StringOffset = FIELD_OFFSET(STRING64, Buffer);
  363. }
  364. else
  365. {
  366. ObjectNameOffset = FIELD_OFFSET(OBJECT_ATTRIBUTES32, ObjectName);
  367. AttrOffset = FIELD_OFFSET(OBJECT_ATTRIBUTES32, Attributes);
  368. StringOffset = FIELD_OFFSET(STRING32, Buffer);
  369. }
  370. AddrObja = GetExpression(args);
  371. if (!AddrObja)
  372. {
  373. return E_FAIL;
  374. }
  375. //
  376. // Get the symbolic name of the Obja
  377. //
  378. GetSymbol(AddrObja, Symbol, &Displacement);
  379. dprintf("Obja %s+%p at %p:\n", Symbol, Displacement, AddrObja);
  380. INIT_API();
  381. hResult = g_ExtData->ReadPointersVirtual(1,
  382. AddrObja + ObjectNameOffset,
  383. &AddrString);
  384. if (hResult != S_OK)
  385. {
  386. return E_FAIL;
  387. }
  388. if (AddrString)
  389. {
  390. b = ReadMemory(AddrString, &String, sizeof(String), NULL);
  391. hResult = g_ExtData->ReadPointersVirtual(1,
  392. AddrString + StringOffset,
  393. &StrAddr);
  394. }
  395. EXIT_API();
  396. if (StrAddr)
  397. {
  398. StringData = (LPSTR)LocalAlloc(LMEM_ZEROINIT,
  399. String.Length+sizeof(UNICODE_NULL));
  400. if (StringData)
  401. {
  402. b = ReadMemory(StrAddr, StringData, String.Length, NULL);
  403. if (b)
  404. {
  405. dprintf("\tName is %ws\n", StringData);
  406. }
  407. LocalFree(StringData);
  408. }
  409. }
  410. b = ReadMemory(AddrObja + AttrOffset, &Attr, sizeof(Attr), NULL);
  411. if (!b)
  412. {
  413. return E_FAIL;
  414. }
  415. if (Attr & OBJ_INHERIT )
  416. {
  417. dprintf("\tOBJ_INHERIT\n");
  418. }
  419. if (Attr & OBJ_PERMANENT )
  420. {
  421. dprintf("\tOBJ_PERMANENT\n");
  422. }
  423. if (Attr & OBJ_EXCLUSIVE )
  424. {
  425. dprintf("\tOBJ_EXCLUSIVE\n");
  426. }
  427. if (Attr & OBJ_CASE_INSENSITIVE )
  428. {
  429. dprintf("\tOBJ_CASE_INSENSITIVE\n");
  430. }
  431. if (Attr & OBJ_OPENIF )
  432. {
  433. dprintf("\tOBJ_OPENIF\n");
  434. }
  435. return S_OK;
  436. }
  437. DECLARE_API( help )
  438. {
  439. dprintf("analyzebugcheck - Perform bugcheck analysis\n");
  440. dprintf("ecb - Edit PCI ConfigSpace byte\n");
  441. dprintf("ecd - Edit PCI ConfigSpace dword\n");
  442. dprintf("ecw - Edit PCI ConfigSpace word\n");
  443. dprintf("exca <BasePort>.<SktNum> - Dump ExCA registers\n");
  444. dprintf("help - Show this help\n");
  445. dprintf("pci [flag] [bus] [device] [function] [rawdump:minaddr] [maxaddr] - Dumps pci type1 config\n");
  446. dprintf(" flag: 0x01 - verbose\n");
  447. dprintf(" 0x02 - from bus 0 to 'bus'\n");
  448. dprintf(" 0x04 - dump raw bytes\n");
  449. dprintf(" 0x08 - dump raw dwords\n");
  450. dprintf(" 0x10 - do not skip invalid devices\n");
  451. dprintf(" 0x20 - do not skip invalid functions\n");
  452. dprintf(" 0x40 - dump Capabilities if found\n");
  453. dprintf(" 0x80 - dump device specific on VendorID:8086\n");
  454. dprintf(" 0x100 - dump config space\n");
  455. return S_OK;
  456. }