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.

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