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.

546 lines
11 KiB

  1. /*++
  2. Copyright (c) 1995 Microsoft Corporation
  3. Module Name:
  4. imagehlp.c
  5. Abstract:
  6. This function implements a generic simple symbol handler.
  7. Author:
  8. Wesley Witt (wesw) 1-Sep-1994
  9. Environment:
  10. User Mode
  11. --*/
  12. #ifdef __cplusplus
  13. extern "C" {
  14. #endif
  15. #include <nt.h>
  16. #include <ntrtl.h>
  17. #include <nturtl.h>
  18. #ifdef __cplusplus
  19. }
  20. #endif
  21. #include "private.h"
  22. #include <globals.h>
  23. #ifdef IMAGEHLP_BUILD
  24. #define HEAP_SIZE 0
  25. __inline BOOL tlsAlloc()
  26. {
  27. return TRUE;
  28. }
  29. __inline void tlsFree()
  30. {
  31. }
  32. __inline void tlsMemFree()
  33. {
  34. }
  35. #else
  36. #define HEAP_SIZE 0x100000
  37. __inline BOOL tlsAlloc()
  38. {
  39. g.tlsIndex = TlsAlloc();
  40. return (g.tlsIndex == (DWORD)-1) ? FALSE : TRUE;
  41. }
  42. __inline void tlsFree()
  43. {
  44. if (g.tlsIndex != (DWORD)-1)
  45. TlsFree(g.tlsIndex);
  46. }
  47. __inline void tlsMemFree()
  48. {
  49. PVOID ptls;
  50. ptls = TlsGetValue(g.tlsIndex);
  51. MemFree(ptls);
  52. }
  53. #endif
  54. DWORD
  55. DllMain(
  56. HINSTANCE hInstance,
  57. DWORD Reason,
  58. LPVOID Context
  59. )
  60. /*++
  61. Routine Description:
  62. DLL initialization function.
  63. Arguments:
  64. hInstance - Instance handle
  65. Reason - Reason for the entrypoint being called
  66. Context - Context record
  67. Return Value:
  68. TRUE - Initialization succeeded
  69. FALSE - Initialization failed
  70. --*/
  71. {
  72. switch (Reason)
  73. {
  74. case DLL_PROCESS_ATTACH:
  75. g.hinst = hInstance;
  76. g.OSVerInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
  77. GetVersionEx(&g.OSVerInfo);
  78. DisableThreadLibraryCalls( hInstance );
  79. HeapInitList(&g.HeapHeader);
  80. g.hHeap = HeapCreate(0, HEAP_SIZE, 0);
  81. if (!tlsAlloc())
  82. return FALSE;
  83. return (g.hHeap != NULL);
  84. case DLL_PROCESS_DETACH:
  85. tlsFree();
  86. HeapDump("DLL_PROCESS_DETACH\n");
  87. // If this is a process shutdown, don't bother to
  88. // kill the heap. The OS will do it for us. This
  89. // allows us to be called from other DLLs' DLLMain
  90. // DLL_PROCESS_DETACH handler.
  91. if ( !Context && g.hHeap )
  92. HeapDestroy( g.hHeap );
  93. break;
  94. case DLL_THREAD_DETACH:
  95. tlsMemFree();
  96. break;
  97. }
  98. return TRUE;
  99. }
  100. #ifdef IMAGEHLP_HEAP_DEBUG
  101. BOOL
  102. pCheckHeap(
  103. PVOID MemPtr,
  104. ULONG Line,
  105. LPSTR File
  106. )
  107. {
  108. CHAR buf[256];
  109. CHAR ext[4];
  110. if (!HeapValidate( g.hHeap, 0, MemPtr )) {
  111. sprintf( buf, "IMAGEHLP: heap corruption - " );
  112. _splitpath( File, NULL, NULL, &buf[strlen(buf)], ext );
  113. strcat( buf, ext );
  114. sprintf( &buf[strlen(buf)], " @ %d\n", Line );
  115. OutputDebugString( buf );
  116. PrintAllocations();
  117. DebugBreak();
  118. return FALSE;
  119. }
  120. return TRUE;
  121. }
  122. BOOL
  123. pHeapDump(
  124. LPSTR sz,
  125. ULONG line,
  126. LPSTR file
  127. )
  128. {
  129. BOOL rc;
  130. if (sz && *sz)
  131. OutputDebugString(sz);
  132. rc = CheckHeap(NULL);
  133. if (rc)
  134. PrintAllocations();
  135. return rc;
  136. }
  137. #endif
  138. PVOID
  139. pMemReAlloc(
  140. PVOID OldAlloc,
  141. ULONG_PTR AllocSize
  142. #ifdef IMAGEHLP_HEAP_DEBUG
  143. , ULONG Line,
  144. LPSTR File
  145. #endif
  146. )
  147. {
  148. #ifdef IMAGEHLP_HEAP_DEBUG
  149. PVOID NewAlloc;
  150. PHEAP_BLOCK hb;
  151. if (!OldAlloc) {
  152. return NULL;
  153. }
  154. hb = (PHEAP_BLOCK) ((PUCHAR)OldAlloc - sizeof(HEAP_BLOCK));
  155. if (hb->Signature != HEAP_SIG) {
  156. OutputDebugString( "IMAGEHLP: Corrupt heap block\n" );
  157. DebugBreak();
  158. }
  159. NewAlloc = pMemAlloc(AllocSize, Line, File);
  160. if (!NewAlloc)
  161. return NULL;
  162. memcpy(NewAlloc, OldAlloc, min(hb->Size, AllocSize));
  163. RemoveEntryList( &hb->ListEntry );
  164. g.TotalMemory -= hb->Size;
  165. g.TotalAllocs -= 1;
  166. HeapFree( g.hHeap, 0, (PVOID) hb );
  167. return NewAlloc;
  168. #else
  169. return(HeapReAlloc(g.hHeap, HEAP_ZERO_MEMORY, OldAlloc, AllocSize));
  170. #endif
  171. }
  172. PVOID
  173. pMemAlloc(
  174. ULONG_PTR AllocSize
  175. #ifdef IMAGEHLP_HEAP_DEBUG
  176. , ULONG Line,
  177. LPSTR File
  178. #endif
  179. )
  180. {
  181. #ifdef IMAGEHLP_HEAP_DEBUG
  182. PHEAP_BLOCK hb;
  183. CHAR ext[4];
  184. hb = (PHEAP_BLOCK) HeapAlloc( g.hHeap, HEAP_ZERO_MEMORY, AllocSize + sizeof(HEAP_BLOCK) );
  185. if (hb) {
  186. g.TotalMemory += AllocSize;
  187. g.TotalAllocs += 1;
  188. InsertTailList( &g.HeapHeader, &hb->ListEntry );
  189. hb->Signature = HEAP_SIG;
  190. hb->Size = AllocSize;
  191. hb->Line = Line;
  192. _splitpath( File, NULL, NULL, hb->File, ext );
  193. strcat( hb->File, ext );
  194. return (PVOID) ((PUCHAR)hb + sizeof(HEAP_BLOCK));
  195. }
  196. return NULL;
  197. #else
  198. return HeapAlloc( g.hHeap, HEAP_ZERO_MEMORY, AllocSize );
  199. #endif
  200. }
  201. VOID
  202. pMemFree(
  203. PVOID MemPtr
  204. #ifdef IMAGEHLP_HEAP_DEBUG
  205. , ULONG Line,
  206. LPSTR File
  207. #endif
  208. )
  209. {
  210. #ifdef IMAGEHLP_HEAP_DEBUG
  211. PHEAP_BLOCK hb;
  212. if (!MemPtr) {
  213. return;
  214. }
  215. pCheckHeap(NULL, Line, File);
  216. hb = (PHEAP_BLOCK) ((PUCHAR)MemPtr - sizeof(HEAP_BLOCK));
  217. if (hb->Signature != HEAP_SIG) {
  218. OutputDebugString( "IMAGEHLP: Corrupt heap block\n" );
  219. DebugBreak();
  220. }
  221. RemoveEntryList( &hb->ListEntry );
  222. g.TotalMemory -= hb->Size;
  223. g.TotalAllocs -= 1;
  224. HeapFree( g.hHeap, 0, (PVOID) hb );
  225. #else
  226. if (!MemPtr) {
  227. return;
  228. }
  229. HeapFree( g.hHeap, 0, MemPtr );
  230. #endif
  231. }
  232. ULONG_PTR
  233. pMemSize(
  234. PVOID MemPtr
  235. )
  236. {
  237. return HeapSize(g.hHeap, 0, MemPtr);
  238. }
  239. #ifdef IMAGEHLP_HEAP_DEBUG
  240. VOID
  241. PrintAllocations(
  242. VOID
  243. )
  244. {
  245. PLIST_ENTRY Next;
  246. PHEAP_BLOCK hb;
  247. CHAR buf[256];
  248. LARGE_INTEGER PerfFreq;
  249. Next = g.HeapHeader.Flink;
  250. if (!Next) {
  251. return;
  252. }
  253. OutputDebugString( "-----------------------------------------------------------------------------\n" );
  254. sprintf( buf, "Memory Allocations for Heap 0x%08x, Allocs=%d, TotalMem=%I64d\n", (ULONG_PTR)g.hHeap, g.TotalAllocs, g.TotalMemory );
  255. OutputDebugString( buf );
  256. OutputDebugString( "-----------------------------------------------------------------------------\n" );
  257. OutputDebugString( "*\n" );
  258. while ((ULONG_PTR)Next != (ULONG_PTR)&g.HeapHeader) {
  259. hb = CONTAINING_RECORD( Next, HEAP_BLOCK, ListEntry );
  260. Next = hb->ListEntry.Flink;
  261. sprintf( buf, "%8d %16s @ %5d\n", hb->Size, hb->File, hb->Line );
  262. OutputDebugString( buf );
  263. }
  264. OutputDebugString( "*\n" );
  265. return;
  266. }
  267. #endif
  268. DWORD
  269. ImagepSetLastErrorFromStatus(
  270. IN DWORD Status
  271. )
  272. {
  273. DWORD dwErrorCode;
  274. // dwErrorCode = RtlNtStatusToDosError( Status );
  275. dwErrorCode = Status;
  276. SetLastError( dwErrorCode );
  277. return( dwErrorCode );
  278. }
  279. /////////////////////////////////////////////////////////////////////////////
  280. /*
  281. ******************************************************************************
  282. On a Hydra System, we don't want imaghlp.dll to load user32.dll since it
  283. prevents CSRSS from exiting when running a under a debugger.
  284. The following two functions have been copied from user32.dll so that we don't
  285. link to user32.dll.
  286. ******************************************************************************
  287. */
  288. ////////////////////////////////////////////////////////////////////////////
  289. LPSTR CharNext(
  290. LPCSTR lpCurrentChar)
  291. {
  292. if (IsDBCSLeadByte(*lpCurrentChar)) {
  293. lpCurrentChar++;
  294. }
  295. /*
  296. * if we have only DBCS LeadingByte, we will point string-terminaler.
  297. */
  298. if (*lpCurrentChar) {
  299. lpCurrentChar++;
  300. }
  301. return (LPSTR)lpCurrentChar;
  302. }
  303. LPSTR CharPrev(
  304. LPCSTR lpStart,
  305. LPCSTR lpCurrentChar)
  306. {
  307. if (lpCurrentChar > lpStart) {
  308. LPCSTR lpChar;
  309. BOOL bDBC = FALSE;
  310. for (lpChar = --lpCurrentChar - 1 ; lpChar >= lpStart ; lpChar--) {
  311. if (!IsDBCSLeadByte(*lpChar))
  312. break;
  313. bDBC = !bDBC;
  314. }
  315. if (bDBC)
  316. lpCurrentChar--;
  317. }
  318. return (LPSTR)lpCurrentChar;
  319. }
  320. void * __cdecl AllocIt(unsigned int cb)
  321. {
  322. return (MemAlloc(cb));
  323. }
  324. void __cdecl FreeIt(void * p)
  325. {
  326. MemFree(p);
  327. }
  328. DWORD
  329. IMAGEAPI
  330. WINAPI
  331. UnDecorateSymbolName(
  332. LPCSTR name,
  333. LPSTR outputString,
  334. DWORD maxStringLength,
  335. DWORD flags
  336. )
  337. {
  338. static HMODULE hMsvcrt = 0;
  339. static BOOL fLoadMsvcrtDLL = FALSE;
  340. static PUNDNAME pfUnDname = NULL;
  341. DWORD rc;
  342. // this prevents an AV in __unDName
  343. if (!name) {
  344. SetLastError(ERROR_INVALID_PARAMETER);
  345. return 0;
  346. }
  347. //
  348. // can't undecorate into a zero length buffer
  349. //
  350. if (maxStringLength < 2) {
  351. SetLastError(ERROR_INVALID_PARAMETER);
  352. return 0;
  353. }
  354. if (!fLoadMsvcrtDLL) {
  355. // The first time we run, see if we can find the system undname. Use
  356. // GetModuleHandle to avoid any additionally overhead.
  357. hMsvcrt = GetModuleHandle("msvcrt.dll");
  358. if (hMsvcrt) {
  359. pfUnDname = (PUNDNAME) GetProcAddress(hMsvcrt, "__unDName");
  360. }
  361. fLoadMsvcrtDLL = TRUE;
  362. }
  363. rc = 0; // Assume failure
  364. __try {
  365. if (pfUnDname) {
  366. if (flags & UNDNAME_NO_ARGUMENTS) {
  367. flags |= UNDNAME_NAME_ONLY;
  368. flags &= ~UNDNAME_NO_ARGUMENTS;
  369. }
  370. if (flags & UNDNAME_NO_SPECIAL_SYMS) {
  371. flags &= ~UNDNAME_NO_SPECIAL_SYMS;
  372. }
  373. if (pfUnDname(outputString, name, maxStringLength-1, AllocIt, FreeIt, (USHORT)flags)) {
  374. rc = strlen(outputString);
  375. }
  376. } else {
  377. rc = strlen(strncpy(outputString, "Unable to load msvcrt!__unDName", maxStringLength));
  378. }
  379. } __except(EXCEPTION_EXECUTE_HANDLER) { }
  380. if (!rc) {
  381. SetLastError(ERROR_INVALID_PARAMETER);
  382. }
  383. return rc;
  384. }
  385. DWORD
  386. IMAGEAPI
  387. GetTimestampForLoadedLibrary(
  388. HMODULE Module
  389. )
  390. {
  391. PIMAGE_DOS_HEADER DosHdr;
  392. DWORD dwTimeStamp;
  393. __try {
  394. DosHdr = (PIMAGE_DOS_HEADER) Module;
  395. if (DosHdr->e_magic == IMAGE_DOS_SIGNATURE) {
  396. dwTimeStamp = ((PIMAGE_NT_HEADERS32) ((LPBYTE)Module + DosHdr->e_lfanew))->FileHeader.TimeDateStamp;
  397. } else if (DosHdr->e_magic == IMAGE_NT_SIGNATURE) {
  398. dwTimeStamp = ((PIMAGE_NT_HEADERS32) DosHdr)->FileHeader.TimeDateStamp;
  399. } else {
  400. dwTimeStamp = 0;
  401. }
  402. } __except (EXCEPTION_EXECUTE_HANDLER) {
  403. dwTimeStamp = 0;
  404. }
  405. return dwTimeStamp;
  406. }
  407. VOID
  408. EnsureTrailingBackslash(
  409. LPSTR sz
  410. )
  411. {
  412. int i;
  413. assert(sz);
  414. i = lstrlen(sz);
  415. if (!i)
  416. return;
  417. if (sz[i - 1] == '\\')
  418. return;
  419. sz[i] = '\\';
  420. sz[i + 1] = '\0';
  421. }
  422. #if DBG
  423. VOID
  424. __cdecl
  425. dbPrint(
  426. LPCSTR fmt,
  427. ...
  428. )
  429. /*++
  430. This function replaces ntdll!DbgPrint(). We need this to keep from linking to
  431. ntdll so that this library will run on Windows.
  432. --*/
  433. {
  434. CHAR text[_MAX_PATH];
  435. va_list vaList;
  436. assert(fmt);
  437. va_start(vaList, fmt);
  438. vsprintf(text, fmt, vaList);
  439. va_end(vaList);
  440. OutputDebugString(text);
  441. }
  442. #endif