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.

475 lines
9.8 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 "amd64cpu.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. ULONG64 CpuRemoteContext;
  151. ULONG64 Teb;
  152. CPUCONTEXT CpuContext;
  153. hr = g_ExtSystem->GetCurrentThreadTeb(&Teb);
  154. if (FAILED(hr)) {
  155. return hr;
  156. }
  157. hr = g_ExtData->ReadVirtual(Teb + CONTEXT_OFFSET,
  158. &CpuRemoteContext,
  159. sizeof(CpuRemoteContext),
  160. NULL);
  161. if (FAILED(hr)) {
  162. return hr;
  163. }
  164. hr = g_ExtData->ReadVirtual(CpuRemoteContext,
  165. &CpuContext,
  166. sizeof(CpuContext),
  167. NULL);
  168. if (FAILED(hr)) {
  169. return hr;
  170. }
  171. NtStatus = GetContextRecord(&CpuContext, Context);
  172. if (!NT_SUCCESS(NtStatus)) {
  173. return E_FAIL;
  174. }
  175. return hr;
  176. }
  177. WOW64CPUDBGAPI BOOL
  178. CpuDbgGetRemoteContext(
  179. PDEBUG_CLIENT Client,
  180. PVOID CpuData
  181. )
  182. {
  183. BOOL bRet = FALSE;
  184. HRESULT hr;
  185. CONTEXT Context;
  186. hr = ExtQuery(Client);
  187. if (FAILED(hr)) {
  188. return FALSE;
  189. }
  190. LocalCpuContext.Context.ContextFlags = CONTEXT32_FULL;
  191. hr = EngGetContextThread(&LocalCpuContext.Context);
  192. if (FAILED(hr)) {
  193. goto Done;
  194. }
  195. bRet = TRUE;
  196. Done:
  197. ExtRelease();
  198. return bRet;
  199. }
  200. HRESULT
  201. EngSetContextThread(
  202. IN OUT PCONTEXT32 Context)
  203. /*++
  204. Routine Description:
  205. This routine sets the context record of any thread. This is a generic routine.
  206. When entered, if the target thread isn't the currently executing thread, then it should be
  207. guaranteed that the target thread is suspended at a proper CPU state.
  208. Arguments:
  209. Context - Context record to set
  210. Return Value:
  211. HRESULT.
  212. --*/
  213. {
  214. HRESULT hr;
  215. NTSTATUS NtStatus;
  216. ULONG64 CpuRemoteContext;
  217. ULONG64 Teb;
  218. CPUCONTEXT CpuContext;
  219. hr = g_ExtSystem->GetCurrentThreadTeb(&Teb);
  220. if (FAILED(hr)) {
  221. return hr;
  222. }
  223. hr = g_ExtData->ReadVirtual(Teb + CONTEXT_OFFSET,
  224. &CpuRemoteContext,
  225. sizeof(CpuRemoteContext),
  226. NULL);
  227. if (FAILED(hr)) {
  228. return hr;
  229. }
  230. hr = g_ExtData->ReadVirtual(CpuRemoteContext,
  231. &CpuContext,
  232. sizeof(CpuContext),
  233. NULL);
  234. if (FAILED(hr)) {
  235. return hr;
  236. }
  237. NtStatus = SetContextRecord(&CpuContext, Context);
  238. if (!NT_SUCCESS(NtStatus)) {
  239. return E_FAIL;
  240. }
  241. hr = g_ExtData->WriteVirtual(CpuRemoteContext,
  242. &CpuContext,
  243. sizeof(CpuContext),
  244. NULL);
  245. return hr;
  246. }
  247. WOW64CPUDBGAPI BOOL
  248. CpuDbgSetRemoteContext(
  249. PDEBUG_CLIENT Client
  250. )
  251. {
  252. BOOL bRet = FALSE;
  253. HRESULT hr;
  254. NTSTATUS Status;
  255. CONTEXT Context;
  256. hr = ExtQuery(Client);
  257. if (FAILED(hr)) {
  258. return FALSE;
  259. }
  260. LocalCpuContext.Context.ContextFlags = CONTEXT32_FULL;
  261. hr = EngSetContextThread(&LocalCpuContext.Context);
  262. if (FAILED(hr)) {
  263. ExtOut("CpuDbgSetRemoteContext: Error %x writing CPU context\n", hr);
  264. goto Done;
  265. }
  266. bRet = TRUE;
  267. Done:
  268. ExtRelease();
  269. return bRet;
  270. }
  271. WOW64CPUDBGAPI BOOL
  272. CpuDbgGetLocalContext(
  273. PDEBUG_CLIENT Client,
  274. PCONTEXT32 Context
  275. )
  276. {
  277. return NT_SUCCESS(GetContextRecord(&LocalCpuContext,
  278. Context));
  279. }
  280. WOW64CPUDBGAPI BOOL
  281. CpuDbgSetLocalContext(
  282. PDEBUG_CLIENT Client,
  283. PCONTEXT32 Context
  284. )
  285. {
  286. return NT_SUCCESS(SetContextRecord(&LocalCpuContext,
  287. Context));
  288. }
  289. WOW64CPUDBGAPI VOID
  290. CpuDbgFlushInstructionCacheWithHandle(
  291. HANDLE Process,
  292. PVOID Addr,
  293. DWORD Length
  294. )
  295. {
  296. NtFlushInstructionCache((HANDLE)Process, Addr, Length);
  297. }
  298. WOW64CPUDBGAPI VOID
  299. CpuDbgFlushInstructionCache(
  300. PDEBUG_CLIENT Client,
  301. PVOID Addr,
  302. DWORD Length
  303. )
  304. {
  305. HRESULT hr;
  306. ULONG64 Process;
  307. hr = ExtQuery(Client);
  308. if (FAILED(hr)) {
  309. return;
  310. }
  311. hr = g_ExtSystem->GetCurrentProcessHandle(&Process);
  312. if (FAILED(hr)) {
  313. ExtOut("CpuDbgFlushInstructionCache: failed to get Process Handle!\n");
  314. return;
  315. }
  316. CpuDbgFlushInstructionCacheWithHandle((HANDLE)Process, Addr, Length);
  317. ExtRelease();
  318. }
  319. VOID SetEax(ULONG ul) {
  320. LocalCpuContext.Context.Eax = ul;
  321. }
  322. VOID SetEbx(ULONG ul) {
  323. LocalCpuContext.Context.Ebx = ul;
  324. }
  325. VOID SetEcx(ULONG ul) {
  326. LocalCpuContext.Context.Ecx = ul;
  327. }
  328. VOID SetEdx(ULONG ul) {
  329. LocalCpuContext.Context.Edx = ul;
  330. }
  331. VOID SetEsi(ULONG ul) {
  332. LocalCpuContext.Context.Esi = ul;
  333. }
  334. VOID SetEdi(ULONG ul) {
  335. LocalCpuContext.Context.Edi = ul;
  336. }
  337. VOID SetEbp(ULONG ul) {
  338. LocalCpuContext.Context.Ebp = ul;
  339. }
  340. VOID SetEsp(ULONG ul) {
  341. LocalCpuContext.Context.Esp = ul;
  342. }
  343. VOID SetEip(ULONG ul) {
  344. LocalCpuContext.Context.Eip = ul;
  345. }
  346. VOID SetEfl(ULONG ul) {
  347. LocalCpuContext.Context.EFlags = ul;
  348. }
  349. ULONG GetEax(VOID) {
  350. return LocalCpuContext.Context.Eax;
  351. }
  352. ULONG GetEbx(VOID) {
  353. return LocalCpuContext.Context.Ebx;
  354. }
  355. ULONG GetEcx(VOID) {
  356. return LocalCpuContext.Context.Ecx;
  357. }
  358. ULONG GetEdx(VOID) {
  359. return LocalCpuContext.Context.Edx;
  360. }
  361. ULONG GetEsi(VOID) {
  362. return LocalCpuContext.Context.Esi;
  363. }
  364. ULONG GetEdi(VOID) {
  365. return LocalCpuContext.Context.Edi;
  366. }
  367. ULONG GetEbp(VOID) {
  368. return LocalCpuContext.Context.Ebp;
  369. }
  370. ULONG GetEsp(VOID) {
  371. return LocalCpuContext.Context.Esp;
  372. }
  373. ULONG GetEip(VOID) {
  374. return LocalCpuContext.Context.Eip;
  375. }
  376. ULONG GetEfl(VOID) {
  377. return LocalCpuContext.Context.EFlags;
  378. }
  379. CPUREGFUNCS CpuRegFuncs[] = {
  380. { "Eax", SetEax, GetEax },
  381. { "Ebx", SetEbx, GetEbx },
  382. { "Ecx", SetEcx, GetEcx },
  383. { "Edx", SetEdx, GetEdx },
  384. { "Esi", SetEsi, GetEsi },
  385. { "Edi", SetEdi, GetEdi },
  386. { "Ebp", SetEbp, GetEbp },
  387. { "Esp", SetEsp, GetEsp },
  388. { "Eip", SetEip, GetEip },
  389. { "Efl", SetEfl, GetEfl },
  390. { NULL, NULL, NULL}
  391. };
  392. WOW64CPUDBGAPI PCPUREGFUNCS
  393. CpuDbgGetRegisterFuncs(
  394. void
  395. )
  396. {
  397. return CpuRegFuncs;
  398. }