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.

520 lines
11 KiB

  1. #include <windows.h>
  2. #include <stdio.h>
  3. #include "dump.h"
  4. #include "main.h"
  5. PBASEINFO g_BaseHead = 0;
  6. PTHREADINFO g_ThreadHead = 0;
  7. DWORD g_dwThreadCount = 0;
  8. HANDLE g_MapInformation = INVALID_HANDLE_VALUE;
  9. HANDLE g_ErrorInformation = INVALID_HANDLE_VALUE;
  10. int
  11. _cdecl
  12. main(int argc, char *argv[])
  13. {
  14. PCHAR pszFile;
  15. PCHAR pszBaseFileName;
  16. BOOL bResult;
  17. if (argc < 3) {
  18. return -1;
  19. }
  20. pszFile = argv[1]; //1st parameter
  21. pszBaseFileName = argv[2]; //2nd parameter
  22. bResult = ProcessRuntimeData(pszFile, pszBaseFileName);
  23. if (FALSE == bResult) {
  24. return -1;
  25. }
  26. //
  27. // Close any open file handles
  28. //
  29. if (INVALID_HANDLE_VALUE != g_MapInformation) {
  30. CloseHandle(g_MapInformation);
  31. }
  32. if (INVALID_HANDLE_VALUE != g_ErrorInformation) {
  33. CloseHandle(g_ErrorInformation);
  34. }
  35. CloseThreadHandles();
  36. return 0;
  37. }
  38. BOOL
  39. ProcessRuntimeData(PCHAR pszFile, PCHAR pszBaseFileName)
  40. {
  41. HANDLE hFile = INVALID_HANDLE_VALUE;
  42. HANDLE hMap = 0;
  43. BOOL bResult = FALSE;
  44. PVOID pFileBits = 0;
  45. PBYTE pMappedBits;
  46. LONG lFileSize;
  47. //
  48. // Get our file online and start the data processing
  49. //
  50. hFile = CreateFileA(pszFile,
  51. GENERIC_READ | GENERIC_WRITE,
  52. 0,
  53. 0,
  54. OPEN_EXISTING,
  55. FILE_ATTRIBUTE_NORMAL,
  56. 0);
  57. if (INVALID_HANDLE_VALUE == hFile) {
  58. bResult = FALSE;
  59. goto HandleError;
  60. }
  61. lFileSize = GetFileSize(hFile,
  62. 0);
  63. //
  64. // Process the data stream
  65. //
  66. hMap = CreateFileMapping(hFile,
  67. 0,
  68. PAGE_READWRITE,
  69. 0,
  70. 0,
  71. 0);
  72. if (0 == hMap) {
  73. bResult = FALSE;
  74. goto HandleError;
  75. }
  76. pFileBits = MapViewOfFile(hMap,
  77. FILE_MAP_READ,
  78. 0,
  79. 0,
  80. 0);
  81. if (0 == pFileBits) {
  82. bResult = FALSE;
  83. goto HandleError;
  84. }
  85. pMappedBits = (PBYTE)pFileBits;
  86. //
  87. // Process stream data
  88. //
  89. while (lFileSize > 0) {
  90. switch(*pMappedBits) {
  91. case ThreadStartId:
  92. bResult = AddThreadInformation(pszBaseFileName,
  93. (PTHREADSTART)pMappedBits);
  94. if (FALSE == bResult) {
  95. goto HandleError;
  96. }
  97. lFileSize -= sizeof(THREADSTART);
  98. pMappedBits += sizeof(THREADSTART);
  99. break;
  100. case ExeFlowId:
  101. bResult = AddExeFlowInformation((PEXEFLOW)pMappedBits);
  102. // if (FALSE == bResult) {
  103. // goto HandleError;
  104. // }
  105. lFileSize -= sizeof(EXEFLOW);
  106. pMappedBits += sizeof(EXEFLOW);
  107. break;
  108. case DllBaseInfoId:
  109. bResult = AddToBaseInformation((PDLLBASEINFO)pMappedBits);
  110. if (FALSE == bResult) {
  111. goto HandleError;
  112. }
  113. lFileSize -= sizeof(DLLBASEINFO);
  114. pMappedBits += sizeof(DLLBASEINFO);
  115. break;
  116. case MapInfoId:
  117. bResult = AddMappedInformation(pszBaseFileName,
  118. (PMAPINFO)pMappedBits);
  119. if (FALSE == bResult) {
  120. goto HandleError;
  121. }
  122. lFileSize -= sizeof(MAPINFO);
  123. pMappedBits += sizeof(MAPINFO);
  124. break;
  125. case ErrorInfoId:
  126. bResult = AddErrorInformation(pszBaseFileName,
  127. (PERRORINFO)pMappedBits);
  128. if (FALSE == bResult) {
  129. goto HandleError;
  130. }
  131. lFileSize -= sizeof(ERRORINFO);
  132. pMappedBits += sizeof(ERRORINFO);
  133. break;
  134. default:
  135. 0;
  136. }
  137. }
  138. //
  139. // No problems in processing log
  140. //
  141. bResult = TRUE;
  142. HandleError:
  143. if (pFileBits) {
  144. UnmapViewOfFile(pFileBits);
  145. }
  146. if (hMap) {
  147. CloseHandle(hMap);
  148. }
  149. if (INVALID_HANDLE_VALUE != hFile) {
  150. CloseHandle(hFile);
  151. }
  152. return bResult;
  153. }
  154. BOOL
  155. AddThreadInformation(PCHAR pszBaseFileName,
  156. PTHREADSTART pThreadStart)
  157. {
  158. PTHREADINFO ptTemp = 0;
  159. BOOL bResult;
  160. DWORD dwBytesWritten;
  161. CHAR szBuffer[MAX_PATH];
  162. CHAR szAddress[MAX_PATH];
  163. //
  164. // Allocate some memory for the new thread data
  165. //
  166. ptTemp = LocalAlloc(LPTR,
  167. sizeof(THREADINFO));
  168. if (0 == ptTemp) {
  169. return FALSE;
  170. }
  171. //
  172. // Initialize file data
  173. //
  174. ptTemp->dwThreadId = pThreadStart->dwThreadId;
  175. sprintf(szBuffer,"%s.thread%ld", pszBaseFileName, g_dwThreadCount);
  176. ptTemp->hFile = CreateFileA(szBuffer,
  177. GENERIC_READ | GENERIC_WRITE,
  178. 0,
  179. 0,
  180. CREATE_ALWAYS,
  181. FILE_ATTRIBUTE_NORMAL,
  182. 0);
  183. if (INVALID_HANDLE_VALUE == ptTemp->hFile) {
  184. return FALSE;
  185. }
  186. //
  187. // Add thread base information to new thread log
  188. //
  189. bResult = FillBufferWithRelocationInfo(szAddress,
  190. pThreadStart->dwStartAddress);
  191. if (FALSE == bResult) {
  192. return bResult;
  193. }
  194. sprintf(szBuffer,"Thread started at %s\r\n", szAddress);
  195. bResult = WriteFile(ptTemp->hFile,
  196. szBuffer,
  197. strlen(szBuffer),
  198. &dwBytesWritten,
  199. 0);
  200. if (FALSE == bResult) {
  201. return FALSE;
  202. }
  203. //
  204. // Chain up thread data
  205. //
  206. if (0 == g_ThreadHead) {
  207. ptTemp->pNext = 0;
  208. g_ThreadHead = ptTemp;
  209. }
  210. else {
  211. ptTemp->pNext = g_ThreadHead;
  212. g_ThreadHead = ptTemp;
  213. }
  214. return TRUE;
  215. }
  216. VOID
  217. CloseThreadHandles(VOID)
  218. {
  219. PTHREADINFO ptTemp = 0;
  220. ptTemp = g_ThreadHead;
  221. while(ptTemp) {
  222. if (ptTemp->hFile != INVALID_HANDLE_VALUE) {
  223. CloseHandle(ptTemp->hFile);
  224. }
  225. ptTemp = ptTemp->pNext;
  226. }
  227. }
  228. BOOL
  229. AddExeFlowInformation(PEXEFLOW pExeFlow)
  230. {
  231. PTHREADINFO ptTemp = 0;
  232. BOOL bResult;
  233. DWORD dwBytesWritten;
  234. CHAR szAddress[MAX_PATH];
  235. CHAR szBuffer[MAX_PATH];
  236. //
  237. // Locate thread for this point of execution
  238. //
  239. ptTemp = g_ThreadHead;
  240. while(ptTemp) {
  241. if (ptTemp->dwThreadId == pExeFlow->dwThreadId) {
  242. break;
  243. }
  244. ptTemp = ptTemp->pNext;
  245. }
  246. if (0 == ptTemp) {
  247. //
  248. // Couldn't locate thread info
  249. //
  250. return FALSE;
  251. }
  252. bResult = FillBufferWithRelocationInfo(szAddress,
  253. pExeFlow->dwAddress);
  254. if (FALSE == bResult) {
  255. return bResult;
  256. }
  257. sprintf(szBuffer, "%s : %ld\r\n", szAddress, pExeFlow->dwCallLevel);
  258. bResult = WriteFile(ptTemp->hFile,
  259. szBuffer,
  260. strlen(szBuffer),
  261. &dwBytesWritten,
  262. 0);
  263. if (FALSE == bResult) {
  264. return FALSE;
  265. }
  266. return TRUE;
  267. }
  268. BOOL
  269. AddErrorInformation(PCHAR pszBaseFileName,
  270. PERRORINFO pErrorInfo)
  271. {
  272. BOOL bResult;
  273. DWORD dwBytesWritten;
  274. CHAR szBuffer[MAX_PATH];
  275. if (INVALID_HANDLE_VALUE == g_ErrorInformation) {
  276. strcpy(szBuffer, pszBaseFileName);
  277. strcat(szBuffer, ".err");
  278. g_ErrorInformation = CreateFileA(szBuffer,
  279. GENERIC_READ | GENERIC_WRITE,
  280. 0,
  281. 0,
  282. CREATE_ALWAYS,
  283. FILE_ATTRIBUTE_NORMAL,
  284. 0);
  285. if (INVALID_HANDLE_VALUE == g_ErrorInformation) {
  286. return FALSE;
  287. }
  288. }
  289. //
  290. // Write out error message
  291. //
  292. bResult = WriteFile(g_ErrorInformation,
  293. pErrorInfo->szMessage,
  294. strlen(pErrorInfo->szMessage),
  295. &dwBytesWritten,
  296. 0);
  297. if (FALSE == bResult) {
  298. return FALSE;
  299. }
  300. return TRUE;
  301. }
  302. BOOL
  303. AddMappedInformation(PCHAR pszBaseFileName,
  304. PMAPINFO pMapInfo)
  305. {
  306. BOOL bResult;
  307. CHAR szBuffer[MAX_PATH];
  308. CHAR szAddress[MAX_PATH];
  309. CHAR szAddress2[MAX_PATH];
  310. DWORD dwBytesWritten;
  311. if (INVALID_HANDLE_VALUE == g_MapInformation) {
  312. strcpy(szBuffer, pszBaseFileName);
  313. strcat(szBuffer, ".map");
  314. g_MapInformation = CreateFileA(szBuffer,
  315. GENERIC_READ | GENERIC_WRITE,
  316. 0,
  317. 0,
  318. CREATE_ALWAYS,
  319. FILE_ATTRIBUTE_NORMAL,
  320. 0);
  321. if (INVALID_HANDLE_VALUE == g_MapInformation) {
  322. return FALSE;
  323. }
  324. }
  325. //
  326. // Write out the mapping information
  327. //
  328. bResult = FillBufferWithRelocationInfo(szAddress,
  329. pMapInfo->dwAddress);
  330. if (FALSE == bResult) {
  331. return bResult;
  332. }
  333. bResult = FillBufferWithRelocationInfo(szAddress2,
  334. pMapInfo->dwMaxMapLength);
  335. if (FALSE == bResult) {
  336. return bResult;
  337. }
  338. sprintf(szBuffer, "%s -> %s\r\n", szAddress, szAddress2);
  339. bResult = WriteFile(g_MapInformation,
  340. szBuffer,
  341. strlen(szBuffer),
  342. &dwBytesWritten,
  343. 0);
  344. if (FALSE == bResult) {
  345. return FALSE;
  346. }
  347. return TRUE;
  348. }
  349. BOOL
  350. FillBufferWithRelocationInfo(PCHAR pszDestination,
  351. DWORD dwAddress)
  352. {
  353. PBASEINFO pTemp;
  354. //
  355. // Find the address in the module info
  356. //
  357. pTemp = g_BaseHead;
  358. while (pTemp) {
  359. //
  360. // Did we find the address?
  361. //
  362. if ((dwAddress >= pTemp->dwStartAddress) &&
  363. (dwAddress <= pTemp->dwEndAddress)) {
  364. break;
  365. }
  366. pTemp = pTemp->pNext;
  367. }
  368. if (pTemp) {
  369. sprintf(pszDestination, "%s+%08X", pTemp->szModule, (dwAddress - pTemp->dwStartAddress));
  370. }
  371. else {
  372. sprintf(pszDestination, "%08X", dwAddress);
  373. }
  374. return TRUE;
  375. }
  376. BOOL
  377. AddToBaseInformation(PDLLBASEINFO pDLLBaseInfo)
  378. {
  379. PBASEINFO pTemp;
  380. if (0 == g_BaseHead) {
  381. //
  382. // Store off the base information
  383. //
  384. pTemp = LocalAlloc(LPTR,
  385. sizeof(BASEINFO));
  386. if (0 == pTemp) {
  387. return FALSE;
  388. }
  389. pTemp->dwStartAddress = pDLLBaseInfo->dwBase;
  390. pTemp->dwEndAddress = pTemp->dwStartAddress + pDLLBaseInfo->dwLength;
  391. strcpy(pTemp->szModule, pDLLBaseInfo->szDLLName);
  392. _strupr(pTemp->szModule);
  393. pTemp->pNext = 0;
  394. g_BaseHead = pTemp;
  395. }
  396. else {
  397. //
  398. // See if our module has already been mapped, and if so update module base info
  399. //
  400. pTemp = g_BaseHead;
  401. while(pTemp) {
  402. if (0 == _stricmp(pDLLBaseInfo->szDLLName, pTemp->szModule)) {
  403. break;
  404. }
  405. pTemp = pTemp->pNext;
  406. }
  407. if (pTemp) {
  408. //
  409. // Found the DLL already in the list, update
  410. //
  411. pTemp->dwStartAddress = pDLLBaseInfo->dwBase;
  412. pTemp->dwEndAddress = pTemp->dwStartAddress + pDLLBaseInfo->dwLength;
  413. }
  414. else {
  415. //
  416. // New DLL
  417. //
  418. pTemp = LocalAlloc(LPTR,
  419. sizeof(BASEINFO));
  420. if (0 == pTemp) {
  421. return FALSE;
  422. }
  423. pTemp->dwStartAddress = pDLLBaseInfo->dwBase;
  424. pTemp->dwEndAddress = pTemp->dwStartAddress + pDLLBaseInfo->dwLength;
  425. strcpy(pTemp->szModule, pDLLBaseInfo->szDLLName);
  426. _strupr(pTemp->szModule);
  427. //
  428. // Chain up the new DLL
  429. //
  430. pTemp->pNext = g_BaseHead;
  431. g_BaseHead = pTemp;
  432. }
  433. }
  434. return TRUE;
  435. }