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.

483 lines
10 KiB

  1. /*++
  2. Copyright (c) 1999-2000 Microsoft Corporation
  3. Module Name:
  4. w64cpuex.cpp
  5. Abstract:
  6. Debugger extension DLL for debugging the CPU
  7. Author:
  8. 27-Sept-1999 BarryBo
  9. Revision History:
  10. --*/
  11. #define _WOW64CPUDBGAPI_
  12. #define DECLARE_CPU_DEBUGGER_INTERFACE
  13. #include <nt.h>
  14. #include <ntrtl.h>
  15. #include <nturtl.h>
  16. #include <windows.h>
  17. #include <imagehlp.h>
  18. #include <dbgeng.h>
  19. #include <ntosp.h>
  20. #if defined _X86_
  21. #define WOW64EXTS_386
  22. #endif
  23. #include "wow64.h"
  24. #include "wow64cpu.h"
  25. #include "ia64cpu.h"
  26. // Safe release and NULL.
  27. #define EXT_RELEASE(Unk) \
  28. ((Unk) != NULL ? ((Unk)->Release(), (Unk) = NULL) : NULL)
  29. #define CONTEXT_OFFSET FIELD_OFFSET(TEB64, TlsSlots[WOW64_TLS_CPURESERVED])
  30. CPUCONTEXT LocalCpuContext;
  31. PWOW64GETCPUDATA CpuGetData;
  32. PDEBUG_ADVANCED g_ExtAdvanced;
  33. PDEBUG_CLIENT g_ExtClient;
  34. PDEBUG_CONTROL g_ExtControl;
  35. PDEBUG_DATA_SPACES g_ExtData;
  36. PDEBUG_REGISTERS g_ExtRegisters;
  37. PDEBUG_SYMBOLS g_ExtSymbols;
  38. PDEBUG_SYSTEM_OBJECTS g_ExtSystem;
  39. void
  40. ExtRelease(void)
  41. {
  42. g_ExtClient = NULL;
  43. EXT_RELEASE(g_ExtAdvanced);
  44. EXT_RELEASE(g_ExtControl);
  45. EXT_RELEASE(g_ExtData);
  46. EXT_RELEASE(g_ExtRegisters);
  47. EXT_RELEASE(g_ExtSymbols);
  48. EXT_RELEASE(g_ExtSystem);
  49. }
  50. // Queries for all debugger interfaces.
  51. HRESULT
  52. ExtQuery(PDEBUG_CLIENT Client)
  53. {
  54. HRESULT Status;
  55. if ((Status = Client->QueryInterface(__uuidof(IDebugAdvanced),
  56. (void **)&g_ExtAdvanced)) != S_OK)
  57. {
  58. goto Fail;
  59. }
  60. if ((Status = Client->QueryInterface(__uuidof(IDebugControl),
  61. (void **)&g_ExtControl)) != S_OK)
  62. {
  63. goto Fail;
  64. }
  65. if ((Status = Client->QueryInterface(__uuidof(IDebugDataSpaces),
  66. (void **)&g_ExtData)) != S_OK)
  67. {
  68. goto Fail;
  69. }
  70. if ((Status = Client->QueryInterface(__uuidof(IDebugRegisters),
  71. (void **)&g_ExtRegisters)) != S_OK)
  72. {
  73. goto Fail;
  74. }
  75. if ((Status = Client->QueryInterface(__uuidof(IDebugSymbols),
  76. (void **)&g_ExtSymbols)) != S_OK)
  77. {
  78. goto Fail;
  79. }
  80. if ((Status = Client->QueryInterface(__uuidof(IDebugSystemObjects),
  81. (void **)&g_ExtSystem)) != S_OK)
  82. {
  83. goto Fail;
  84. }
  85. g_ExtClient = Client;
  86. return S_OK;
  87. Fail:
  88. ExtRelease();
  89. return Status;
  90. }
  91. // Normal output.
  92. void __cdecl
  93. ExtOut(PCSTR Format, ...)
  94. {
  95. va_list Args;
  96. va_start(Args, Format);
  97. g_ExtControl->OutputVaList(DEBUG_OUTPUT_NORMAL, Format, Args);
  98. va_end(Args);
  99. }
  100. // Error output.
  101. void __cdecl
  102. ExtErr(PCSTR Format, ...)
  103. {
  104. va_list Args;
  105. va_start(Args, Format);
  106. g_ExtControl->OutputVaList(DEBUG_OUTPUT_ERROR, Format, Args);
  107. va_end(Args);
  108. }
  109. // Warning output.
  110. void __cdecl
  111. ExtWarn(PCSTR Format, ...)
  112. {
  113. va_list Args;
  114. va_start(Args, Format);
  115. g_ExtControl->OutputVaList(DEBUG_OUTPUT_WARNING, Format, Args);
  116. va_end(Args);
  117. }
  118. // Verbose output.
  119. void __cdecl
  120. ExtVerb(PCSTR Format, ...)
  121. {
  122. va_list Args;
  123. va_start(Args, Format);
  124. g_ExtControl->OutputVaList(DEBUG_OUTPUT_VERBOSE, Format, Args);
  125. va_end(Args);
  126. }
  127. WOW64CPUDBGAPI VOID
  128. CpuDbgInitEngapi(
  129. PWOW64GETCPUDATA lpGetData
  130. )
  131. {
  132. CpuGetData = lpGetData;
  133. }
  134. HRESULT
  135. EngGetContextThread(
  136. IN OUT PCONTEXT32 Context)
  137. /*++
  138. Routine Description:
  139. This routine extract the context record of any thread. This is a generic routine.
  140. When entered, if the target thread isn't the current thread, then it should be
  141. guaranteed that the target thread is suspended at a proper CPU state.
  142. Arguments:
  143. Context - Context record to fill
  144. Return Value:
  145. HRESULT.
  146. --*/
  147. {
  148. HRESULT hr;
  149. NTSTATUS NtStatus;
  150. CONTEXT ContextEM;
  151. ULONG64 CpuRemoteContext;
  152. ULONG64 Teb;
  153. CPUCONTEXT CpuContext;
  154. ContextEM.ContextFlags = CONTEXT_FULL;
  155. hr = g_ExtSystem->GetCurrentThreadTeb(&Teb);
  156. if (FAILED(hr)) {
  157. return hr;
  158. }
  159. hr = g_ExtData->ReadVirtual(Teb + CONTEXT_OFFSET,
  160. &CpuRemoteContext,
  161. sizeof(CpuRemoteContext),
  162. NULL);
  163. if (FAILED(hr)) {
  164. return hr;
  165. }
  166. hr = g_ExtData->ReadVirtual(CpuRemoteContext,
  167. &CpuContext,
  168. sizeof(CpuContext),
  169. NULL);
  170. if (FAILED(hr)) {
  171. return hr;
  172. }
  173. NtStatus = GetContextRecord(&CpuContext, Context);
  174. if (!NT_SUCCESS(NtStatus)) {
  175. return E_FAIL;
  176. }
  177. return hr;
  178. }
  179. WOW64CPUDBGAPI BOOL
  180. CpuDbgGetRemoteContext(
  181. PDEBUG_CLIENT Client,
  182. PVOID CpuData
  183. )
  184. {
  185. BOOL bRet = FALSE;
  186. HRESULT hr;
  187. CONTEXT Context;
  188. hr = ExtQuery(Client);
  189. if (FAILED(hr)) {
  190. return FALSE;
  191. }
  192. LocalCpuContext.Context.ContextFlags = CONTEXT32_FULLFLOAT;
  193. hr = EngGetContextThread(&LocalCpuContext.Context);
  194. if (FAILED(hr)) {
  195. goto Done;
  196. }
  197. bRet = TRUE;
  198. Done:
  199. ExtRelease();
  200. return bRet;
  201. }
  202. HRESULT
  203. EngSetContextThread(
  204. IN OUT PCONTEXT32 Context)
  205. /*++
  206. Routine Description:
  207. This routine sets the context record of any thread. This is a generic routine.
  208. When entered, if the target thread isn't the currently executing thread, then it should be
  209. guaranteed that the target thread is suspended at a proper CPU state.
  210. Arguments:
  211. Context - Context record to set
  212. Return Value:
  213. HRESULT.
  214. --*/
  215. {
  216. HRESULT hr;
  217. NTSTATUS NtStatus;
  218. CONTEXT ContextEM;
  219. ULONG64 CpuRemoteContext;
  220. ULONG64 Teb;
  221. CPUCONTEXT CpuContext;
  222. ContextEM.ContextFlags = CONTEXT_FULL;
  223. hr = g_ExtAdvanced->SetThreadContext(&ContextEM, sizeof(ContextEM));
  224. hr = g_ExtSystem->GetCurrentThreadTeb(&Teb);
  225. if (FAILED(hr)) {
  226. return hr;
  227. }
  228. hr = g_ExtData->ReadVirtual(Teb + CONTEXT_OFFSET,
  229. &CpuRemoteContext,
  230. sizeof(CpuRemoteContext),
  231. NULL);
  232. if (FAILED(hr)) {
  233. return hr;
  234. }
  235. hr = g_ExtData->ReadVirtual(CpuRemoteContext,
  236. &CpuContext,
  237. sizeof(CpuContext),
  238. NULL);
  239. if (FAILED(hr)) {
  240. return hr;
  241. }
  242. NtStatus = SetContextRecord(&CpuContext, Context);
  243. if (!NT_SUCCESS(NtStatus)) {
  244. return E_FAIL;
  245. }
  246. hr = g_ExtData->WriteVirtual(CpuRemoteContext,
  247. &CpuContext,
  248. sizeof(CpuContext),
  249. NULL);
  250. return hr;
  251. }
  252. WOW64CPUDBGAPI BOOL
  253. CpuDbgSetRemoteContext(
  254. PDEBUG_CLIENT Client
  255. )
  256. {
  257. BOOL bRet = FALSE;
  258. HRESULT hr;
  259. NTSTATUS Status;
  260. CONTEXT Context;
  261. hr = ExtQuery(Client);
  262. if (FAILED(hr)) {
  263. return FALSE;
  264. }
  265. LocalCpuContext.Context.ContextFlags = CONTEXT32_FULLFLOAT;
  266. hr = EngSetContextThread(&LocalCpuContext.Context);
  267. if (FAILED(hr)) {
  268. ExtOut("CpuDbgSetRemoteContext: Error %x writing CPU context\n", hr);
  269. goto Done;
  270. }
  271. bRet = TRUE;
  272. Done:
  273. ExtRelease();
  274. return bRet;
  275. }
  276. WOW64CPUDBGAPI BOOL
  277. CpuDbgGetLocalContext(
  278. PDEBUG_CLIENT Client,
  279. PCONTEXT32 Context
  280. )
  281. {
  282. return NT_SUCCESS(GetContextRecord(&LocalCpuContext,
  283. Context));
  284. }
  285. WOW64CPUDBGAPI BOOL
  286. CpuDbgSetLocalContext(
  287. PDEBUG_CLIENT Client,
  288. PCONTEXT32 Context
  289. )
  290. {
  291. return NT_SUCCESS(SetContextRecord(&LocalCpuContext,
  292. Context));
  293. }
  294. WOW64CPUDBGAPI VOID
  295. CpuDbgFlushInstructionCacheWithHandle(
  296. HANDLE Process,
  297. PVOID Addr,
  298. DWORD Length
  299. )
  300. {
  301. NtFlushInstructionCache((HANDLE)Process, Addr, Length);
  302. }
  303. WOW64CPUDBGAPI VOID
  304. CpuDbgFlushInstructionCache(
  305. PDEBUG_CLIENT Client,
  306. PVOID Addr,
  307. DWORD Length
  308. )
  309. {
  310. HRESULT hr;
  311. ULONG64 Process;
  312. hr = ExtQuery(Client);
  313. if (FAILED(hr)) {
  314. return;
  315. }
  316. hr = g_ExtSystem->GetCurrentProcessHandle(&Process);
  317. if (FAILED(hr)) {
  318. ExtOut("CpuDbgFlushInstructionCache: failed to get Process Handle!\n");
  319. return;
  320. }
  321. CpuDbgFlushInstructionCacheWithHandle((HANDLE)Process, Addr, Length);
  322. ExtRelease();
  323. }
  324. VOID SetEax(ULONG ul) {
  325. LocalCpuContext.Context.Eax = ul;
  326. }
  327. VOID SetEbx(ULONG ul) {
  328. LocalCpuContext.Context.Ebx = ul;
  329. }
  330. VOID SetEcx(ULONG ul) {
  331. LocalCpuContext.Context.Ecx = ul;
  332. }
  333. VOID SetEdx(ULONG ul) {
  334. LocalCpuContext.Context.Edx = ul;
  335. }
  336. VOID SetEsi(ULONG ul) {
  337. LocalCpuContext.Context.Esi = ul;
  338. }
  339. VOID SetEdi(ULONG ul) {
  340. LocalCpuContext.Context.Edi = ul;
  341. }
  342. VOID SetEbp(ULONG ul) {
  343. LocalCpuContext.Context.Ebp = ul;
  344. }
  345. VOID SetEsp(ULONG ul) {
  346. LocalCpuContext.Context.Esp = ul;
  347. }
  348. VOID SetEip(ULONG ul) {
  349. LocalCpuContext.Context.Eip = ul;
  350. }
  351. VOID SetEfl(ULONG ul) {
  352. LocalCpuContext.Context.EFlags = ul;
  353. }
  354. ULONG GetEax(VOID) {
  355. return LocalCpuContext.Context.Eax;
  356. }
  357. ULONG GetEbx(VOID) {
  358. return LocalCpuContext.Context.Ebx;
  359. }
  360. ULONG GetEcx(VOID) {
  361. return LocalCpuContext.Context.Ecx;
  362. }
  363. ULONG GetEdx(VOID) {
  364. return LocalCpuContext.Context.Edx;
  365. }
  366. ULONG GetEsi(VOID) {
  367. return LocalCpuContext.Context.Esi;
  368. }
  369. ULONG GetEdi(VOID) {
  370. return LocalCpuContext.Context.Edi;
  371. }
  372. ULONG GetEbp(VOID) {
  373. return LocalCpuContext.Context.Ebp;
  374. }
  375. ULONG GetEsp(VOID) {
  376. return LocalCpuContext.Context.Esp;
  377. }
  378. ULONG GetEip(VOID) {
  379. return LocalCpuContext.Context.Eip;
  380. }
  381. ULONG GetEfl(VOID) {
  382. return LocalCpuContext.Context.EFlags;
  383. }
  384. CPUREGFUNCS CpuRegFuncs[] = {
  385. { "Eax", SetEax, GetEax },
  386. { "Ebx", SetEbx, GetEbx },
  387. { "Ecx", SetEcx, GetEcx },
  388. { "Edx", SetEdx, GetEdx },
  389. { "Esi", SetEsi, GetEsi },
  390. { "Edi", SetEdi, GetEdi },
  391. { "Ebp", SetEbp, GetEbp },
  392. { "Esp", SetEsp, GetEsp },
  393. { "Eip", SetEip, GetEip },
  394. { "Efl", SetEfl, GetEfl },
  395. { NULL, NULL, NULL}
  396. };
  397. WOW64CPUDBGAPI PCPUREGFUNCS
  398. CpuDbgGetRegisterFuncs(
  399. void
  400. )
  401. {
  402. return CpuRegFuncs;
  403. }