Windows NT 4.0 source code leak
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.

499 lines
12 KiB

4 years ago
  1. #include "ntsdp.h"
  2. #if defined(TARGET_i386)
  3. #include "86reg.h"
  4. #endif
  5. #include <string.h>
  6. extern ULONG pageSize;
  7. #ifdef KERNEL
  8. extern PVOID NtsdCurrentEThread;
  9. extern DBGKD_GET_VERSION vs;
  10. #endif
  11. #define SAVE_EBP(f) f.Reserved[0]
  12. #define TRAP_TSS(f) f.Reserved[1]
  13. #define TRAP_EDITED(f) f.Reserved[1]
  14. #define SAVE_TRAP(f) f.Reserved[2]
  15. #if defined(TARGET_i386) || defined(CHICAGO)
  16. #define MachineType IMAGE_FILE_MACHINE_I386
  17. #elif defined(TARGET_MIPS)
  18. #define MachineType IMAGE_FILE_MACHINE_R4000
  19. #elif defined(TARGET_ALPHA)
  20. #define MachineType IMAGE_FILE_MACHINE_ALPHA
  21. #elif defined(TARGET_PPC)
  22. #define MachineType IMAGE_FILE_MACHINE_POWERPC
  23. #else
  24. #error( "unknown target machine" );
  25. #endif
  26. VOID
  27. bangReload(
  28. IN PUCHAR args
  29. );
  30. LPVOID
  31. SwFunctionTableAccess(
  32. HANDLE hProcess,
  33. DWORD AddrBase
  34. )
  35. {
  36. #if defined(TARGET_i386) || defined(CHICAGO)
  37. return (LPVOID)FindFpoDataForModule( AddrBase );
  38. #else
  39. static IMAGE_RUNTIME_FUNCTION_ENTRY irfe;
  40. PIMAGE_FUNCTION_ENTRY pife = SymFunctionTableAccess( hProcess, AddrBase );
  41. if (pife) {
  42. irfe.BeginAddress = pife->StartingAddress;
  43. irfe.EndAddress = pife->EndingAddress;
  44. irfe.ExceptionHandler = 0;
  45. irfe.HandlerData = 0;
  46. irfe.PrologEndAddress = pife->EndOfPrologue;
  47. return &irfe;
  48. } else {
  49. return NULL;
  50. }
  51. #endif
  52. }
  53. DWORD
  54. SwTranslateAddress(
  55. HANDLE hProcess,
  56. HANDLE hThread,
  57. LPADDRESS lpaddress
  58. )
  59. {
  60. //
  61. // don't support 16bit stacks
  62. //
  63. return 0;
  64. }
  65. BOOL
  66. SwReadMemory(
  67. HANDLE hProcess,
  68. LPCVOID lpBaseAddress,
  69. LPVOID lpBuffer,
  70. DWORD nSize,
  71. LPDWORD lpNumberOfBytesRead
  72. )
  73. {
  74. #ifdef KERNEL
  75. BOOLEAN fSuccess;
  76. DWORD BytesRead;
  77. NTSTATUS Status;
  78. if ((LONG)lpNumberOfBytesRead == -1) {
  79. Status = DbgKdReadControlSpace(
  80. NtsdCurrentProcessor,
  81. (PVOID)lpBaseAddress,
  82. lpBuffer,
  83. nSize,
  84. &BytesRead );
  85. fSuccess = Status == STATUS_SUCCESS;
  86. } else {
  87. fSuccess = (BOOLEAN)NT_SUCCESS(DbgKdReadVirtualMemory(
  88. (PVOID)lpBaseAddress,
  89. lpBuffer,
  90. nSize,
  91. lpNumberOfBytesRead) );
  92. }
  93. return fSuccess;
  94. #else
  95. ULONG cTotalBytesRead = 0;
  96. ULONG cBytesRead;
  97. ULONG readcount;
  98. PUCHAR pBufSource;
  99. BOOLEAN fSuccess;
  100. DWORD addr;
  101. DWORD bias;
  102. pBufSource = (PUCHAR)lpBaseAddress;
  103. do {
  104. //
  105. // do not perform reads across page boundaries.
  106. // calculate bytes to read in present page in readcount.
  107. //
  108. readcount = min(nSize - cTotalBytesRead,
  109. pageSize - ((ULONG)pBufSource & (pageSize - 1)));
  110. fSuccess = ReadProcessMemory(hProcess, pBufSource, lpBuffer, readcount, &cBytesRead);
  111. // update total bytes read and new address for next read
  112. if (fSuccess) {
  113. cTotalBytesRead += cBytesRead;
  114. pBufSource += cBytesRead;
  115. (PUCHAR)lpBuffer += cBytesRead;
  116. }
  117. } while (fSuccess && cTotalBytesRead < nSize);
  118. if (lpNumberOfBytesRead) {
  119. *lpNumberOfBytesRead = cTotalBytesRead;
  120. }
  121. return TRUE;
  122. #endif
  123. }
  124. DWORD
  125. SwGetModuleBase(
  126. HANDLE hProcess,
  127. DWORD Address
  128. )
  129. {
  130. PIMAGE_INFO pImage = pProcessCurrent->pImageHead;
  131. while (pImage) {
  132. if ((Address >= (DWORD)pImage->lpBaseOfImage) &&
  133. (Address < (DWORD)((DWORD)pImage->lpBaseOfImage+pImage->dwSizeOfImage))) {
  134. return (DWORD)pImage->lpBaseOfImage;
  135. }
  136. pImage = pImage->pImageNext;
  137. }
  138. return 0;
  139. }
  140. #ifdef KERNEL
  141. void
  142. EnsureModLoadedForAddress(
  143. DWORD Address
  144. )
  145. {
  146. CHAR Buffer[11];
  147. if (!SwGetModuleBase(0, Address)) {
  148. sprintf(Buffer, "0x%08x", Address);
  149. bangReload(Buffer);
  150. }
  151. }
  152. #endif
  153. DWORD
  154. StackTrace(
  155. ULONG FramePointer,
  156. ULONG StackPointer,
  157. ULONG InstructionPointer,
  158. LPSTACKFRAME StackFrames,
  159. ULONG NumFrames,
  160. ULONG ExtThread
  161. )
  162. {
  163. CONTEXT Context;
  164. PCONTEXT RegContext;
  165. STACKFRAME VirtualFrame;
  166. DWORD i;
  167. #ifdef KERNEL
  168. RegContext = GetRegContext();
  169. #else
  170. RegContext = &RegisterContext;
  171. #endif
  172. Context = *RegContext;
  173. //
  174. // lets start clean
  175. //
  176. ZeroMemory( StackFrames, sizeof(STACKFRAME)*NumFrames );
  177. ZeroMemory( &VirtualFrame, sizeof(STACKFRAME) );
  178. #ifdef KERNEL
  179. if (vs.KeUserCallbackDispatcher == 0) {
  180. //
  181. // if debugger was initialized at boot, usermode addresses
  182. // were not available. Try it now:
  183. //
  184. DbgKdGetVersion( &vs );
  185. }
  186. VirtualFrame.KdHelp.Thread = ExtThread ? ExtThread : (DWORD)NtsdCurrentEThread;
  187. VirtualFrame.KdHelp.KiCallUserMode = vs.KiCallUserMode;
  188. VirtualFrame.KdHelp.ThCallbackStack = vs.ThCallbackStack;
  189. VirtualFrame.KdHelp.NextCallback = vs.NextCallback;
  190. VirtualFrame.KdHelp.KeUserCallbackDispatcher = vs.KeUserCallbackDispatcher;
  191. VirtualFrame.KdHelp.FramePointer = vs.FramePointer;
  192. #endif
  193. //
  194. // setup the program counter
  195. //
  196. #if defined(TARGET_i386)
  197. VirtualFrame.AddrPC.Mode = AddrModeFlat;
  198. VirtualFrame.AddrPC.Segment = (WORD)X86GetRegValue(REGCS);
  199. if (!InstructionPointer) {
  200. VirtualFrame.AddrPC.Offset = (ULONG)X86GetRegValue(REGEIP);
  201. } else {
  202. VirtualFrame.AddrPC.Offset = InstructionPointer;
  203. }
  204. //
  205. // setup the frame pointer
  206. //
  207. VirtualFrame.AddrFrame.Mode = AddrModeFlat;
  208. VirtualFrame.AddrFrame.Segment = (WORD)X86GetRegValue(REGSS);
  209. if (!FramePointer) {
  210. VirtualFrame.AddrFrame.Offset = (ULONG)X86GetRegValue(REGEBP);
  211. } else {
  212. VirtualFrame.AddrFrame.Offset = FramePointer;
  213. }
  214. //
  215. // setup the stack pointer
  216. //
  217. VirtualFrame.AddrStack.Mode = AddrModeFlat;
  218. VirtualFrame.AddrStack.Segment = (WORD)X86GetRegValue(REGSS);
  219. if (!StackPointer) {
  220. VirtualFrame.AddrStack.Offset = (ULONG)X86GetRegValue(REGESP);
  221. } else {
  222. VirtualFrame.AddrStack.Offset = StackPointer;
  223. }
  224. #endif
  225. #if defined (TARGET_MIPS) || defined(TARGET_ALPHA) || defined(TARGET_PPC)
  226. if (InstructionPointer) {
  227. VirtualFrame.AddrPC.Offset = InstructionPointer;
  228. VirtualFrame.AddrPC.Mode = AddrModeFlat;
  229. }
  230. //
  231. // setup the stack pointer
  232. //
  233. if (StackPointer) {
  234. VirtualFrame.AddrStack.Offset = StackPointer;
  235. VirtualFrame.AddrStack.Mode = AddrModeFlat;
  236. }
  237. if (FramePointer) {
  238. VirtualFrame.AddrFrame.Offset = FramePointer;
  239. VirtualFrame.AddrFrame.Mode = AddrModeFlat;
  240. }
  241. #endif
  242. for (i=0; i<NumFrames; i++) {
  243. if (!StackWalk( MachineType,
  244. pProcessCurrent->hProcess,
  245. #ifdef KERNEL
  246. (HANDLE)DefaultProcessor,
  247. #else
  248. pProcessCurrent->pThreadCurrent->hThread,
  249. #endif
  250. &VirtualFrame,
  251. &Context,
  252. SwReadMemory,
  253. SwFunctionTableAccess,
  254. SwGetModuleBase,
  255. SwTranslateAddress
  256. )) {
  257. break;
  258. }
  259. StackFrames[i] = VirtualFrame;
  260. }
  261. return i;
  262. }
  263. VOID
  264. DoStackTrace(
  265. ULONG FramePointer,
  266. ULONG StackPointer,
  267. ULONG InstructionPointer,
  268. ULONG NumFrames,
  269. ULONG TraceType
  270. )
  271. {
  272. LPSTACKFRAME StackFrames;
  273. DWORD FrameCount;
  274. DWORD i;
  275. DWORD displacement;
  276. CHAR symbuf[512];
  277. USHORT StdCallArgs;
  278. if (NumFrames == 0) {
  279. NumFrames = 20;
  280. }
  281. StackFrames = malloc( sizeof(STACKFRAME) * NumFrames );
  282. if (!StackFrames) {
  283. dprintf( "could not allocate memory for stack trace\n" );
  284. return;
  285. }
  286. FrameCount = StackTrace( FramePointer,
  287. StackPointer,
  288. InstructionPointer,
  289. StackFrames,
  290. NumFrames,
  291. 0
  292. );
  293. if (FrameCount == 0) {
  294. dprintf( "could not fetch any stack frames\n" );
  295. return;
  296. }
  297. #if defined(TARGET_i386)
  298. dprintf( "ChildEBP RetAddr" );
  299. if (TraceType) {
  300. dprintf(" Args to Child");
  301. }
  302. dprintf("\n");
  303. #else
  304. if (TraceType==1) {
  305. dprintf("\nCallee-SP Arguments to Callee Call Site\n\n");
  306. } else {
  307. dprintf("\nCallee-SP Return-RA Call Site\n\n");
  308. }
  309. #endif
  310. for (i=0; i<FrameCount; i++) {
  311. GetSymbolStdCall( StackFrames[i].AddrPC.Offset,
  312. symbuf,
  313. &displacement,
  314. &StdCallArgs
  315. );
  316. #if defined(TARGET_i386)
  317. dprintf( "%08x %08x ",
  318. StackFrames[i].AddrFrame.Offset,
  319. StackFrames[i].AddrReturn.Offset
  320. );
  321. if (TraceType > 0) {
  322. dprintf( "%08x %08x %08x ",
  323. StackFrames[i].Params[0],
  324. StackFrames[i].Params[1],
  325. StackFrames[i].Params[2]
  326. );
  327. }
  328. if (*symbuf) {
  329. dprintf( "%s", symbuf );
  330. if (displacement) {
  331. dprintf("+");
  332. }
  333. }
  334. if (displacement) {
  335. dprintf("0x%x", displacement);
  336. }
  337. if (TraceType == 2 && !StackFrames[i].FuncTableEntry) {
  338. if (StdCallArgs != 0xffff) {
  339. dprintf(" [Stdcall: %d]", StdCallArgs);
  340. }
  341. } else
  342. if (TraceType == 2 && StackFrames[i].FuncTableEntry) {
  343. PFPO_DATA pFpoData = (PFPO_DATA)StackFrames[i].FuncTableEntry;
  344. switch (pFpoData->cbFrame) {
  345. case FRAME_FPO:
  346. if (pFpoData->fHasSEH) {
  347. dprintf("(FPO: [SEH])");
  348. } else {
  349. dprintf(" (FPO:");
  350. if (pFpoData->fUseBP) {
  351. dprintf(" [EBP 0x%08x]", SAVE_EBP(StackFrames[i]));
  352. }
  353. dprintf(" [%d,%d,%d])", pFpoData->cdwParams,
  354. pFpoData->cdwLocals,
  355. pFpoData->cbRegs);
  356. }
  357. break;
  358. case FRAME_NONFPO:
  359. dprintf("(FPO: [Non-Fpo]" );
  360. break;
  361. #ifdef KERNEL
  362. case FRAME_TRAP:
  363. dprintf(" (FPO: [%d,%d] TrapFrame%s @ %08lx)",
  364. pFpoData->cdwParams,
  365. pFpoData->cdwLocals,
  366. TRAP_EDITED(StackFrames[i]) ? "" : "-EDITED",
  367. SAVE_TRAP(StackFrames[i]) );
  368. break;
  369. case FRAME_TSS:
  370. dprintf(" (FPO: TaskGate %lx:0)", TRAP_TSS(StackFrames[i]));
  371. break;
  372. #endif
  373. default:
  374. dprintf("(UKNOWN FPO TYPE)");
  375. break;
  376. }
  377. }
  378. dprintf( "\n" );
  379. #else
  380. if (TraceType == 1) {
  381. dprintf( " %08lx : ",
  382. StackFrames[i].AddrFrame.Offset
  383. );
  384. } else {
  385. dprintf( " %08lx %08lx : ",
  386. StackFrames[i].AddrFrame.Offset,
  387. StackFrames[i].AddrReturn.Offset
  388. );
  389. }
  390. if (TraceType == 1) {
  391. dprintf( "%08lx %08lx %08lx %08lx ",
  392. StackFrames[i].Params[0],
  393. StackFrames[i].Params[1],
  394. StackFrames[i].Params[2],
  395. StackFrames[i].Params[3]
  396. );
  397. }
  398. dprintf( "%s", symbuf );
  399. if (displacement) {
  400. dprintf("+0x%lx ", displacement);
  401. }
  402. dprintf( "\n" );
  403. #endif
  404. }
  405. free( StackFrames );
  406. return;
  407. }
  408. #ifdef KERNEL
  409. PVOID
  410. GetCallbackStackHead(
  411. PVOID Thread
  412. )
  413. {
  414. KTHREAD Tcb;
  415. DWORD dwRead;
  416. NTSTATUS Status;
  417. Status = DbgKdReadVirtualMemory(
  418. Thread,
  419. &Tcb,
  420. sizeof(KTHREAD),
  421. &dwRead);
  422. if (NT_SUCCESS(Status)) {
  423. return Tcb.CallbackStack;
  424. } else {
  425. return 0;
  426. }
  427. }
  428. #endif