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.

4512 lines
115 KiB

  1. /*++
  2. Copyright (c) 1995 Microsoft Corporation
  3. Module Name:
  4. symbolsp.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. #include <nt.h>
  13. #include <ntrtl.h>
  14. #include <nturtl.h>
  15. #include <ntldr.h>
  16. #include "private.h"
  17. #include "symbols.h"
  18. #include "globals.h"
  19. #include "tlhelp32.h"
  20. #include "fecache.hpp"
  21. typedef BOOL (WINAPI *PMODULE32)(HANDLE, LPMODULEENTRY32);
  22. typedef HANDLE (WINAPI *PCREATE32SNAPSHOT)(DWORD, DWORD);
  23. typedef ULONG (NTAPI *PRTLQUERYPROCESSDEBUGINFORMATION)(HANDLE,ULONG,PRTL_DEBUG_INFORMATION);
  24. typedef PRTL_DEBUG_INFORMATION (NTAPI *PRTLCREATEQUERYDEBUGBUFFER)(ULONG,BOOLEAN);
  25. typedef NTSTATUS (NTAPI *PRTLDESTROYQUERYDEBUGBUFFER)(PRTL_DEBUG_INFORMATION);
  26. typedef NTSTATUS (NTAPI *PNTQUERYSYSTEMINFORMATION)(SYSTEM_INFORMATION_CLASS,PVOID,ULONG,PULONG);
  27. typedef ULONG (NTAPI *PRTLNTSTATUSTODOSERROR)(NTSTATUS);
  28. //typedef NTSTATUS (NTAPI *PNTQUERYINFORMATIONPROCESS)(UINT_PTR,PROCESSINFOCLASS,UINT_PTR,ULONG,UINT_PTR);
  29. typedef NTSTATUS (NTAPI *PNTQUERYINFORMATIONPROCESS)(HANDLE,PROCESSINFOCLASS,PVOID,ULONG,PULONG);
  30. DWORD_PTR Win95GetProcessModules(HANDLE, PINTERNAL_GET_MODULE ,PVOID);
  31. DWORD_PTR NTGetProcessModules(HANDLE, PINTERNAL_GET_MODULE ,PVOID);
  32. DWORD64 miGetModuleBase(HANDLE hProcess, DWORD64 Address);
  33. // private version of qsort used to avoid compat problems on NT4 and win2k.
  34. // code is published from base\crts
  35. extern
  36. void __cdecl dbg_qsort(void *, size_t, size_t,
  37. int (__cdecl *) (const void *, const void *));
  38. typedef struct _SYMBOL_INFO_LOOKUP {
  39. ULONG Segment;
  40. ULONG64 Offset;
  41. PCHAR NamePtr;
  42. SYMBOL_INFO SymInfo;
  43. } SYMBOL_INFO_LOOKUP;
  44. BOOL
  45. LoadSymbols(
  46. HANDLE hp,
  47. PMODULE_ENTRY mi,
  48. DWORD flags
  49. )
  50. {
  51. if (flags & LS_JUST_TEST) {
  52. if ((mi->Flags & MIF_DEFERRED_LOAD) && !(mi->Flags & MIF_NO_SYMBOLS))
  53. return FALSE;
  54. else
  55. return TRUE;
  56. }
  57. if (flags & LS_QUALIFIED) {
  58. if (g.SymOptions & SYMOPT_NO_UNQUALIFIED_LOADS) {
  59. if ((mi->Flags & MIF_DEFERRED_LOAD) && !(mi->Flags & MIF_NO_SYMBOLS))
  60. return FALSE;
  61. }
  62. }
  63. if ((mi->Flags & MIF_DEFERRED_LOAD) && !(mi->Flags & MIF_NO_SYMBOLS))
  64. return load(hp, mi);
  65. else if (flags & LS_FAIL_IF_LOADED)
  66. return FALSE;
  67. return TRUE;
  68. }
  69. //
  70. // Get the address form section no and offset in a PE file
  71. //
  72. ULONG
  73. GetAddressFromOffset(
  74. PMODULE_ENTRY mi,
  75. ULONG section,
  76. ULONG64 Offset,
  77. PULONG64 pAddress
  78. )
  79. {
  80. ULONG Bias;
  81. if (section > mi->NumSections
  82. || !pAddress
  83. || !section
  84. || !mi
  85. )
  86. {
  87. // Invalid !!
  88. return FALSE;
  89. }
  90. *pAddress = mi->BaseOfDll + mi->OriginalSectionHdrs[section-1].VirtualAddress + Offset;
  91. *pAddress = ConvertOmapFromSrc( mi, *pAddress, &Bias );
  92. if (*pAddress) {
  93. *pAddress += Bias;
  94. }
  95. return TRUE;
  96. }
  97. /*
  98. * GetSymbolInfo
  99. * This extracts useful information from a CV SYMBOl record into a generic
  100. * SYMBOL_ENTRY structure.
  101. *
  102. *
  103. */
  104. ULONG
  105. GetSymbolInfo(
  106. PMODULE_ENTRY me,
  107. PCHAR pRawSym,
  108. SYMBOL_INFO_LOOKUP *pSymEntry
  109. )
  110. {
  111. PCHAR SymbolInfo = pRawSym;
  112. ULONG symIndex, typeIndex=0, segmentNum=0;
  113. ULONG64 Offset=0, Address=0, Value=0;
  114. // ULONG Register=0, bpRel=0, BaseReg=0;
  115. BOOL HasAddr=FALSE, HasValue=FALSE;
  116. PSYMBOL_INFO pSymInfo = &pSymEntry->SymInfo;
  117. if ((pRawSym != NULL) && (pSymEntry != NULL)) {
  118. SymbolInfo = (PCHAR) pRawSym;
  119. typeIndex = 0;
  120. symIndex = ((SYMTYPE *) (pRawSym))->rectyp;
  121. ZeroMemory(pSymEntry, sizeof(SYMBOL_INFO));
  122. pSymInfo->ModBase = me->BaseOfDll;
  123. #define ExtractSymName(from) (pSymEntry->NamePtr = ((PCHAR) from) + 1); pSymInfo->NameLen = (UCHAR) *((PUCHAR) from);
  124. switch (symIndex) {
  125. case S_COMPILE : // 0x0001 Compile flags symbol
  126. case S_REGISTER_16t : { // 0x0002 Register variable
  127. break;
  128. }
  129. case S_CONSTANT_16t : { // 0x0003 constant symbol
  130. DWORD len=4;
  131. CONSTSYM_16t *constSym;
  132. constSym = (CONSTSYM_16t *) SymbolInfo;
  133. typeIndex = constSym->typind;
  134. // GetNumericValue((PCHAR)&constSym->value, &Value, &len);
  135. pSymInfo->Flags |= IMAGEHLP_SYMBOL_INFO_VALUEPRESENT;
  136. pSymInfo->Value = Value;
  137. ExtractSymName((constSym->name + len));
  138. break;
  139. }
  140. case S_UDT_16t : { // 0x0004 User defined type
  141. UDTSYM_16t *udtSym;
  142. udtSym = (UDTSYM_16t *) SymbolInfo;
  143. typeIndex = udtSym->typind;
  144. ExtractSymName(udtSym->name); // strncpy(name, (PCHAR)symReturned + 7, (UCHAR) symReturned[6]);
  145. break;
  146. }
  147. case S_SSEARCH : // 0x0005 Start Search
  148. case S_END : // 0x0006 Block, procedure, "with" or thunk end
  149. case S_SKIP : // 0x0007 Reserve symbol space in $$Symbols table
  150. case S_CVRESERVE : // 0x0008 Reserved symbol for CV internal use
  151. case S_OBJNAME : // 0x0009 path to object file name
  152. case S_ENDARG : // 0x000a end of argument/return list
  153. case S_COBOLUDT_16t : // 0x000b special UDT for cobol that does not symbol pack
  154. case S_MANYREG_16t : // 0x000c multiple register variable
  155. case S_RETURN : // 0x000d return description symbol
  156. case S_ENTRYTHIS : // 0x000e description of this pointer on entry
  157. break;
  158. case S_BPREL16 : // 0x0100 BP-relative
  159. case S_LDATA16 : // 0x0101 Module-local symbol
  160. case S_GDATA16 : // 0x0102 Global data symbol
  161. case S_PUB16 : // 0x0103 a public symbol
  162. case S_LPROC16 : // 0x0104 Local procedure start
  163. case S_GPROC16 : // 0x0105 Global procedure start
  164. case S_THUNK16 : // 0x0106 Thunk Start
  165. case S_BLOCK16 : // 0x0107 block start
  166. case S_WITH16 : // 0x0108 with start
  167. case S_LABEL16 : // 0x0109 code label
  168. case S_CEXMODEL16 : // 0x010a change execution model
  169. case S_VFTABLE16 : // 0x010b address of virtual function table
  170. case S_REGREL16 : // 0x010c register relative address
  171. case S_BPREL32_16t : { // 0x0200 BP-relative
  172. break;
  173. }
  174. case S_LDATA32_16t :// 0x0201 Module-local symbol
  175. case S_GDATA32_16t :// 0x0202 Global data symbol
  176. case S_PUB32_16t : { // 0x0203 a public symbol (CV internal reserved)
  177. DATASYM32_16t *pData;
  178. pData = (DATASYM32_16t *) SymbolInfo;
  179. typeIndex = pData->typind;
  180. Offset = pData->off; segmentNum = pData->seg;
  181. HasAddr = TRUE;
  182. ExtractSymName(pData->name);
  183. // strncpy(name, (PCHAR)&pData->name[1], (UCHAR) pData->name[0]);
  184. break;
  185. }
  186. case S_LPROC32_16t : // 0x0204 Local procedure start
  187. case S_GPROC32_16t : { // 0x0205 Global procedure start
  188. PROCSYM32_16t *procSym;
  189. procSym = (PROCSYM32_16t *)SymbolInfo;
  190. // CONTEXT-SENSITIVE
  191. // Offset = procSym->off; segmentNum = procSym->seg;
  192. typeIndex = procSym->typind;
  193. ExtractSymName(procSym->name);
  194. // strncpy(name, (PCHAR)symReturned + 36, (UCHAR) symReturned[35]);
  195. break;
  196. }
  197. case S_THUNK32 : // 0x0206 Thunk Start
  198. case S_BLOCK32 : // 0x0207 block start
  199. case S_WITH32 : // 0x0208 with start
  200. case S_LABEL32 : // 0x0209 code label
  201. case S_CEXMODEL32 : // 0x020a change execution model
  202. case S_VFTABLE32_16t : // 0x020b address of virtual function table
  203. case S_REGREL32_16t : // 0x020c register relative address
  204. case S_LTHREAD32_16t : // 0x020d local thread storage
  205. case S_GTHREAD32_16t : // 0x020e global thread storage
  206. case S_SLINK32 : // 0x020f static link for MIPS EH implementation
  207. case S_LPROCMIPS_16t : // 0x0300 Local procedure start
  208. case S_GPROCMIPS_16t : { // 0x0301 Global procedure start
  209. break;
  210. }
  211. case S_PROCREF : { // 0x0400 Reference to a procedure
  212. // typeIndex = ((PDWORD) symReturned) + 3;
  213. // strncpy(name, symReturned + 13, (char) *(symReturned+12));
  214. break;
  215. }
  216. case S_DATAREF : // 0x0401 Reference to data
  217. case S_ALIGN : // 0x0402 Used for page alignment of symbols
  218. case S_LPROCREF : // 0x0403 Local Reference to a procedure
  219. // sym records with 32-bit types embedded instead of 16-bit
  220. // all have 0x1000 bit set for easy identification
  221. // only do the 32-bit target versions since we don't really
  222. // care about 16-bit ones anymore.
  223. case S_TI16_MAX : // 0x1000,
  224. break;
  225. case S_REGISTER : { // 0x1001 Register variable
  226. REGSYM *regSym;
  227. regSym = (REGSYM *)SymbolInfo;
  228. typeIndex = regSym->typind;
  229. pSymInfo->Flags = IMAGEHLP_SYMBOL_INFO_REGISTER;
  230. LookupRegID((DWORD)regSym->reg, me->MachineType, &pSymInfo->Register);
  231. ExtractSymName(regSym->name);
  232. break;
  233. }
  234. case S_CONSTANT : { // 0x1002 constant symbol
  235. CONSTSYM *constSym;
  236. DWORD len=4, val;
  237. constSym = (CONSTSYM *) SymbolInfo;
  238. // GetNumericValue((PCHAR)&constSym->value, &Value, &len);
  239. pSymInfo->Flags |= IMAGEHLP_SYMBOL_INFO_VALUEPRESENT;
  240. pSymInfo->Value = Value;
  241. typeIndex = constSym->typind;
  242. ExtractSymName((constSym->name+len));
  243. break;
  244. }
  245. case S_UDT : { // 0x1003 User defined type
  246. UDTSYM *udtSym;
  247. udtSym = (UDTSYM *) SymbolInfo;
  248. typeIndex = udtSym->typind;
  249. ExtractSymName(udtSym->name);
  250. break;
  251. }
  252. case S_COBOLUDT : // 0x1004 special UDT for cobol that does not symbol pack
  253. break;
  254. case S_MANYREG : // 0x1005 multiple register variable
  255. #if 0
  256. typedef struct MANYREGSYM {
  257. unsigned short reclen; // Record length
  258. unsigned short rectyp; // S_MANYREG
  259. CV_typ_t typind; // Type index
  260. unsigned char count; // count of number of registers
  261. unsigned char reg[1]; // count register enumerates followed by
  262. // length-prefixed name. Registers are
  263. // most significant first.
  264. } MANYREGSYM;
  265. typedef struct MANYREGSYM2 {
  266. unsigned short reclen; // Record length
  267. unsigned short rectyp; // S_MANYREG2
  268. CV_typ_t typind; // Type index
  269. unsigned short count; // count of number of registers
  270. unsigned short reg[1]; // count register enumerates followed by
  271. // length-prefixed name. Registers are
  272. // most significant first.
  273. } MANYREGSYM2;
  274. #endif
  275. break;
  276. case S_BPREL32 : { // 0x1006 BP-relative
  277. BPRELSYM32 *bprelSym;
  278. bprelSym = (BPRELSYM32 *)SymbolInfo;
  279. typeIndex = bprelSym->typind;
  280. pSymInfo->Flags = IMAGEHLP_SYMBOL_INFO_FRAMERELATIVE;
  281. pSymInfo->Address = bprelSym->off;
  282. ExtractSymName(bprelSym->name);
  283. break;
  284. }
  285. case S_LDATA32 : // 0x1007 Module-local symbol
  286. case S_GDATA32 : // 0x1008 Global data symbol
  287. case S_PUB32 : { // 0x1009 a public symbol (CV internal reserved)
  288. DATASYM32 *dataSym;
  289. dataSym = (DATASYM32 *)SymbolInfo;
  290. HasAddr = TRUE;
  291. Offset = dataSym->off; segmentNum = dataSym->seg;
  292. typeIndex = dataSym->typind; //(PDWORD) symReturned;
  293. ExtractSymName(dataSym->name); // strncpy(name, (PCHAR)symReturned+11, (UCHAR) symReturned[10]);
  294. break;
  295. }
  296. case S_LPROC32 : // 0x100a Local procedure start
  297. case S_GPROC32 : { // 0x100b Global procedure start
  298. PROCSYM32 *procSym;
  299. procSym = (PROCSYM32 *) SymbolInfo;
  300. // CONTEXT-SENSITIVE
  301. HasAddr = TRUE;
  302. Offset = procSym->off; segmentNum = procSym->seg;
  303. typeIndex = procSym->typind;
  304. ExtractSymName(procSym->name);
  305. break;
  306. }
  307. case S_VFTABLE32 : // 0x100c address of virtual function table
  308. break;
  309. case S_REGREL32 : { // 0x100d register relative address
  310. REGREL32 *regrelSym;
  311. regrelSym = (REGREL32 *)SymbolInfo;
  312. typeIndex = regrelSym->typind;
  313. pSymInfo->Flags = IMAGEHLP_SYMBOL_INFO_REGRELATIVE;
  314. pSymInfo->Address = regrelSym->off;
  315. LookupRegID((DWORD)regrelSym->reg, me->MachineType, &pSymInfo->Register);
  316. ExtractSymName(regrelSym->name);
  317. break;
  318. }
  319. case S_LTHREAD32 : // 0x100e local thread storage
  320. case S_GTHREAD32 : // 0x100f global thread storage
  321. case S_LPROCMIPS : // 0x1010 Local procedure start
  322. case S_GPROCMIPS : // 0x1011 Global procedure start
  323. case S_FRAMEPROC : // 0x1012 extra frame and proc information
  324. case S_COMPILE2 : // 0x1013 extended compile flags and info
  325. case S_MANYREG2 : // 0x1014 multiple register variable
  326. case S_LPROCIA64 : // 0x1015 Local procedure start (IA64)
  327. case S_GPROCIA64 : // 0x1016 Global procedure start (IA64)
  328. case S_RECTYPE_MAX :
  329. default:
  330. return FALSE;
  331. } /* switch */
  332. if (HasAddr && GetAddressFromOffset(me, segmentNum, Offset, &Address)) {
  333. pSymInfo->Address = Address;
  334. }
  335. pSymInfo->TypeIndex = typeIndex;
  336. pSymEntry->Offset = Offset;
  337. pSymEntry->Segment = segmentNum;
  338. } else {
  339. return FALSE;
  340. }
  341. return TRUE;
  342. }
  343. /*
  344. * cvExtractSymbolInfo
  345. * This extracts useful information from a CV SYMBOl record into a generic
  346. * SYMBOL_ENTRY structure.
  347. *
  348. *
  349. */
  350. ULONG
  351. cvExtractSymbolInfo(
  352. PMODULE_ENTRY me,
  353. PCHAR pRawSym,
  354. PSYMBOL_ENTRY pSymEntry,
  355. BOOL fCopyName
  356. )
  357. {
  358. SYMBOL_INFO_LOOKUP SymInfoLookup={0};
  359. ULONG reg;
  360. pSymEntry->Size = 0;
  361. pSymEntry->Flags = 0;
  362. pSymEntry->Address = 0;
  363. if (fCopyName)
  364. *pSymEntry->Name = 0;
  365. else
  366. pSymEntry->Name = 0;
  367. pSymEntry->NameLength = 0;
  368. pSymEntry->Segment = 0;
  369. pSymEntry->Offset = 0;
  370. pSymEntry->TypeIndex = 0;
  371. pSymEntry->ModBase = 0;
  372. if (GetSymbolInfo(me, pRawSym, &SymInfoLookup)) {
  373. LARGE_INTEGER li;
  374. pSymEntry->NameLength = SymInfoLookup.SymInfo.NameLen;
  375. pSymEntry->TypeIndex = SymInfoLookup.SymInfo.TypeIndex;
  376. pSymEntry->Offset = SymInfoLookup.Offset;
  377. pSymEntry->Segment = SymInfoLookup.Segment;
  378. pSymEntry->ModBase = me->BaseOfDll;
  379. // NOTE: this was implented as a mask - but used differently
  380. switch (SymInfoLookup.SymInfo.Flags)
  381. {
  382. case IMAGEHLP_SYMBOL_INFO_REGISTER:
  383. pSymEntry->Flags = SYMF_REGISTER;
  384. pSymEntry->Address = SymInfoLookup.SymInfo.Register;
  385. break;
  386. case IMAGEHLP_SYMBOL_INFO_REGRELATIVE:
  387. // DBGHELP_HACK - HiPart of Addr = RegId , LowPart = Pffset
  388. pSymEntry->Flags = SYMF_REGREL;
  389. //LookupRegID((DWORD)SymInfoLookup.SymInfo.Register, me->MachineType, &pSymEntry->Segment);
  390. li.LowPart = (ULONG) SymInfoLookup.SymInfo.Address;
  391. li.HighPart = SymInfoLookup.SymInfo.Register;
  392. pSymEntry->Segment = SymInfoLookup.SymInfo.Register;
  393. pSymEntry->Address = li.QuadPart;
  394. break;
  395. case IMAGEHLP_SYMBOL_INFO_FRAMERELATIVE:
  396. pSymEntry->Flags = SYMF_FRAMEREL;
  397. pSymEntry->Address = SymInfoLookup.SymInfo.Address;
  398. break;
  399. case IMAGEHLP_SYMBOL_INFO_VALUEPRESENT:
  400. default:
  401. pSymEntry->Address = SymInfoLookup.SymInfo.Address;
  402. break;
  403. }
  404. if (fCopyName) {
  405. if (!pSymEntry->Name)
  406. return FALSE;
  407. *pSymEntry->Name = 0;
  408. strncpy(pSymEntry->Name, SymInfoLookup.NamePtr ? SymInfoLookup.NamePtr : "", SymInfoLookup.SymInfo.NameLen);
  409. } else {
  410. pSymEntry->Name = SymInfoLookup.NamePtr;
  411. }
  412. return TRUE;
  413. }
  414. return FALSE;
  415. }
  416. DWORD_PTR
  417. NTGetPID(
  418. HANDLE hProcess
  419. )
  420. {
  421. HMODULE hModule;
  422. PNTQUERYINFORMATIONPROCESS NtQueryInformationProcess;
  423. PROCESS_BASIC_INFORMATION pi;
  424. NTSTATUS status;
  425. hModule = GetModuleHandle( "ntdll.dll" );
  426. if (!hModule) {
  427. return ERROR_MOD_NOT_FOUND;
  428. }
  429. NtQueryInformationProcess = (PNTQUERYINFORMATIONPROCESS)GetProcAddress(
  430. hModule,
  431. "NtQueryInformationProcess"
  432. );
  433. if (!NtQueryInformationProcess) {
  434. return ERROR_INVALID_FUNCTION;
  435. }
  436. status = NtQueryInformationProcess(hProcess,
  437. ProcessBasicInformation,
  438. &pi,
  439. sizeof(pi),
  440. NULL);
  441. if (!NT_SUCCESS(status))
  442. return 0;
  443. return pi.UniqueProcessId;
  444. }
  445. //
  446. // the block bounded by the #ifdef _X86_ statement
  447. // contains the code for getting the PID from an
  448. // HPROCESS when running under Win9X
  449. //
  450. #ifdef _X86_
  451. #define HANDLE_INVALID ((HANDLE)0xFFFFFFFF)
  452. #define HANDLE_CURRENT_PROCESS ((HANDLE)0x7FFFFFFF)
  453. #define HANDLE_CURRENT_THREAD ((HANDLE)0xFFFFFFFE)
  454. #define MAX_HANDLE_VALUE ((HANDLE)0x00FFFFFF)
  455. // Thread Information Block.
  456. typedef struct _TIB {
  457. DWORD unknown[12];
  458. DWORD_PTR ppdb;
  459. } TIB, *PTIB;
  460. // Task Data Block
  461. typedef struct _TDB {
  462. DWORD unknown[2];
  463. TIB tib;
  464. } TDB, *PTDB;
  465. typedef struct _OBJ {
  466. BYTE typObj; // object type
  467. BYTE objFlags; // object flags
  468. WORD cntUses; // count of this objects usage
  469. } OBJ, *POBJ;
  470. typedef struct _HTE {
  471. DWORD flFlags;
  472. POBJ pobj;
  473. } HTE, *PHTE;
  474. typedef struct _HTB {
  475. DWORD chteMax;
  476. HTE rghte[1];
  477. } HTB, *PHTB;
  478. typedef struct _W9XPDB {
  479. DWORD unknown[17];
  480. PHTB phtbHandles;
  481. } W9XPDB, *PW9XPDB;
  482. #pragma warning(disable:4035)
  483. _inline struct _TIB * GetCurrentTib(void) { _asm mov eax, fs:[0x18] }
  484. // stuff needed to convert local handle
  485. #define IHTETOHANDLESHIFT 2
  486. #define GLOBALHANDLEMASK (0x453a4d3cLU)
  487. #define IHTEFROMHANDLE(hnd) ((hnd) == HANDLE_INVALID ? (DWORD)(hnd) : (((DWORD)(hnd)) >> IHTETOHANDLESHIFT))
  488. #define IHTEISGLOBAL(ihte) \
  489. (((ihte) >> (32 - 8 - IHTETOHANDLESHIFT)) == (((DWORD)GLOBALHANDLEMASK) >> 24))
  490. #define IS_WIN32_PREDEFINED_HANDLE(hnd) \
  491. ((hnd == HANDLE_CURRENT_PROCESS)||(hnd == HANDLE_CURRENT_THREAD)||(hnd == HANDLE_INVALID))
  492. DWORD
  493. GetWin9xObsfucator(
  494. VOID
  495. )
  496. /*++
  497. Routine Description:
  498. GetWin9xObsfucator()
  499. Arguments:
  500. none
  501. Return Value:
  502. Obsfucator key used by Windows9x to hide Process and Thread Id's
  503. Notes:
  504. The code has only been tested on Windows98SE and Millennium.
  505. --*/
  506. {
  507. DWORD ppdb = 0; // W9XPDB = Process Data Block
  508. DWORD processId = (DWORD) GetCurrentProcessId();
  509. // get PDB pointer
  510. ppdb = GetCurrentTib()->ppdb;
  511. return ppdb ^ processId;
  512. }
  513. DWORD_PTR
  514. GetPtrFromHandle(
  515. IN HANDLE Handle
  516. )
  517. /*++
  518. Routine Description:
  519. GetPtrFromHandle()
  520. Arguments:
  521. Handle - handle from Process handle table
  522. Return Value:
  523. Real Pointer to object
  524. Notes:
  525. The code has only been tested on Windows98SE and Millennium.
  526. --*/
  527. {
  528. DWORD_PTR ptr = 0;
  529. DWORD ihte = 0;
  530. PW9XPDB ppdb = 0;
  531. ppdb = (PW9XPDB) GetCurrentTib()->ppdb;
  532. // check for pre-defined handle values.
  533. if (Handle == HANDLE_CURRENT_PROCESS) {
  534. ptr = (DWORD_PTR) ppdb;
  535. } else if (Handle == HANDLE_CURRENT_THREAD) {
  536. ptr = (DWORD_PTR) CONTAINING_RECORD(GetCurrentTib(), TDB, tib);
  537. } else if (Handle == HANDLE_INVALID) {
  538. ptr = 0;
  539. } else {
  540. // not a special handle, we can perform our magic.
  541. ihte = IHTEFROMHANDLE(Handle);
  542. // if we have a global handle, it is only meaningful in the context
  543. // of the kernel process's handle table...we don't currently deal with
  544. // this type of handle
  545. if (!(IHTEISGLOBAL(ihte))) {
  546. ptr = (DWORD_PTR) ppdb->phtbHandles->rghte[ihte].pobj;
  547. }
  548. }
  549. return ptr;
  550. }
  551. DWORD_PTR
  552. Win9xGetPID(
  553. IN HANDLE hProcess
  554. )
  555. /*++
  556. Routine Description:
  557. Win9xGetPid()
  558. Arguments:
  559. hProcess - Process handle
  560. Return Value:
  561. Process Id
  562. Notes:
  563. The code has only been tested on Windows98SE and Millennium.
  564. --*/
  565. {
  566. static DWORD dwObsfucator = 0;
  567. // check to see that we have a predefined handle or an index into
  568. // our local handle table.
  569. if (IS_WIN32_PREDEFINED_HANDLE(hProcess) || (hProcess < MAX_HANDLE_VALUE)) {
  570. if (!dwObsfucator) {
  571. dwObsfucator = GetWin9xObsfucator();
  572. assert(dwObsfucator != 0);
  573. }
  574. return dwObsfucator ^ GetPtrFromHandle(hProcess);
  575. }
  576. // don't know what we have here
  577. return 0;
  578. }
  579. #endif // _X86_
  580. DWORD_PTR
  581. GetPID(
  582. HANDLE hProcess
  583. )
  584. {
  585. OSVERSIONINFO VerInfo;
  586. if (hProcess == GetCurrentProcess())
  587. return GetCurrentProcessId();
  588. VerInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
  589. GetVersionEx(&VerInfo);
  590. if (VerInfo.dwPlatformId == VER_PLATFORM_WIN32_NT) {
  591. return NTGetPID(hProcess);
  592. } else {
  593. #ifdef _X86_
  594. return Win9xGetPID(hProcess);
  595. #else
  596. return 0;
  597. #endif
  598. }
  599. }
  600. PMODULE_ENTRY
  601. GetModFromAddr(
  602. PPROCESS_ENTRY pe,
  603. IN DWORD64 addr
  604. )
  605. {
  606. PMODULE_ENTRY mi = NULL;
  607. __try {
  608. mi = GetModuleForPC(pe, addr, FALSE);
  609. if (!mi) {
  610. SetLastError(ERROR_MOD_NOT_FOUND);
  611. return NULL;
  612. }
  613. if (!LoadSymbols(pe->hProcess, mi, 0)) {
  614. SetLastError(ERROR_MOD_NOT_FOUND);
  615. return NULL;
  616. }
  617. } __except (EXCEPTION_EXECUTE_HANDLER) {
  618. ImagepSetLastErrorFromStatus(GetExceptionCode());
  619. return NULL;
  620. }
  621. return mi;
  622. }
  623. DWORD
  624. GetProcessModules(
  625. HANDLE hProcess,
  626. PINTERNAL_GET_MODULE InternalGetModule,
  627. PVOID Context
  628. )
  629. {
  630. #ifdef _X86_
  631. OSVERSIONINFO VerInfo;
  632. VerInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
  633. GetVersionEx(&VerInfo);
  634. if (VerInfo.dwPlatformId == VER_PLATFORM_WIN32_NT) {
  635. return NTGetProcessModules(hProcess, InternalGetModule, Context);
  636. } else {
  637. return Win95GetProcessModules(hProcess, InternalGetModule, Context);
  638. }
  639. }
  640. DWORD
  641. Win95GetProcessModules(
  642. HANDLE hProcess,
  643. PINTERNAL_GET_MODULE InternalGetModule,
  644. PVOID Context
  645. )
  646. {
  647. MODULEENTRY32 mi;
  648. PMODULE32 pModule32Next, pModule32First;
  649. PCREATE32SNAPSHOT pCreateToolhelp32Snapshot;
  650. HANDLE hSnapshot;
  651. HMODULE hToolHelp;
  652. DWORD pid;
  653. // get the PID:
  654. // this hack supports old bug workaround, in which callers were passing
  655. // a pid, because an hprocess didn't work on W9X.
  656. pid = GetPID(hProcess);
  657. if (!pid)
  658. pid = (DWORD)hProcess;
  659. // get the module list from toolhelp apis
  660. hToolHelp = GetModuleHandle("kernel32.dll");
  661. if (!hToolHelp)
  662. return ERROR_MOD_NOT_FOUND;
  663. pModule32Next = (PMODULE32)GetProcAddress(hToolHelp, "Module32Next");
  664. pModule32First = (PMODULE32)GetProcAddress(hToolHelp, "Module32First");
  665. pCreateToolhelp32Snapshot = (PCREATE32SNAPSHOT)GetProcAddress(hToolHelp, "CreateToolhelp32Snapshot");
  666. if (!pModule32Next || !pModule32First || !pCreateToolhelp32Snapshot)
  667. return ERROR_MOD_NOT_FOUND;
  668. hSnapshot = pCreateToolhelp32Snapshot(TH32CS_SNAPMODULE, pid);
  669. if (hSnapshot == (HANDLE)-1) {
  670. return ERROR_MOD_NOT_FOUND;
  671. }
  672. mi.dwSize = sizeof(MODULEENTRY32);
  673. if (pModule32First(hSnapshot, &mi)) {
  674. do
  675. {
  676. if (!InternalGetModule(
  677. hProcess,
  678. mi.szModule,
  679. (DWORD) mi.modBaseAddr,
  680. mi.modBaseSize,
  681. Context))
  682. {
  683. break;
  684. }
  685. } while ( pModule32Next(hSnapshot, &mi) );
  686. }
  687. CloseHandle(hSnapshot);
  688. return(ERROR_SUCCESS);
  689. }
  690. DWORD
  691. NTGetProcessModules(
  692. HANDLE hProcess,
  693. PINTERNAL_GET_MODULE InternalGetModule,
  694. PVOID Context
  695. )
  696. {
  697. #endif // _X86_
  698. PRTLQUERYPROCESSDEBUGINFORMATION RtlQueryProcessDebugInformation;
  699. PRTLCREATEQUERYDEBUGBUFFER RtlCreateQueryDebugBuffer;
  700. PRTLDESTROYQUERYDEBUGBUFFER RtlDestroyQueryDebugBuffer;
  701. HMODULE hModule;
  702. NTSTATUS Status;
  703. PRTL_DEBUG_INFORMATION Buffer;
  704. ULONG i;
  705. DWORD_PTR ProcessId;
  706. hModule = GetModuleHandle( "ntdll.dll" );
  707. if (!hModule) {
  708. return ERROR_MOD_NOT_FOUND;
  709. }
  710. RtlQueryProcessDebugInformation = (PRTLQUERYPROCESSDEBUGINFORMATION)GetProcAddress(
  711. hModule,
  712. "RtlQueryProcessDebugInformation"
  713. );
  714. if (!RtlQueryProcessDebugInformation) {
  715. return ERROR_INVALID_FUNCTION;
  716. }
  717. RtlCreateQueryDebugBuffer = (PRTLCREATEQUERYDEBUGBUFFER)GetProcAddress(
  718. hModule,
  719. "RtlCreateQueryDebugBuffer"
  720. );
  721. if (!RtlCreateQueryDebugBuffer) {
  722. return ERROR_INVALID_FUNCTION;
  723. }
  724. RtlDestroyQueryDebugBuffer = (PRTLDESTROYQUERYDEBUGBUFFER)GetProcAddress(
  725. hModule,
  726. "RtlDestroyQueryDebugBuffer"
  727. );
  728. if (!RtlDestroyQueryDebugBuffer) {
  729. return ERROR_INVALID_FUNCTION;
  730. }
  731. Buffer = RtlCreateQueryDebugBuffer( 0, FALSE );
  732. if (!Buffer) {
  733. return ERROR_NOT_ENOUGH_MEMORY;
  734. }
  735. ProcessId = GetPID(hProcess);
  736. // for backwards compatibility with an old bug
  737. if (!ProcessId)
  738. ProcessId = (DWORD_PTR)hProcess;
  739. ULONG QueryFlags = RTL_QUERY_PROCESS_MODULES |
  740. RTL_QUERY_PROCESS_NONINVASIVE;
  741. if (g.SymOptions & SYMOPT_INCLUDE_32BIT_MODULES) {
  742. QueryFlags |= RTL_QUERY_PROCESS_MODULES32;
  743. }
  744. Status = RtlQueryProcessDebugInformation(
  745. (HANDLE)ProcessId,
  746. QueryFlags,
  747. Buffer
  748. );
  749. if (Status != STATUS_SUCCESS) {
  750. RtlDestroyQueryDebugBuffer( Buffer );
  751. return(ImagepSetLastErrorFromStatus(Status));
  752. }
  753. for (i=0; i<Buffer->Modules->NumberOfModules; i++) {
  754. PRTL_PROCESS_MODULE_INFORMATION Module = &Buffer->Modules->Modules[i];
  755. if (!InternalGetModule(
  756. hProcess,
  757. (LPSTR) &Module->FullPathName[Module->OffsetToFileName],
  758. (DWORD64)Module->ImageBase,
  759. (DWORD)Module->ImageSize,
  760. Context
  761. ))
  762. {
  763. break;
  764. }
  765. }
  766. RtlDestroyQueryDebugBuffer( Buffer );
  767. return ERROR_SUCCESS;
  768. }
  769. VOID
  770. FreeModuleEntry(
  771. PPROCESS_ENTRY pe,
  772. PMODULE_ENTRY mi
  773. )
  774. {
  775. FunctionEntryCache* Cache;
  776. if (pe && (Cache = GetFeCache(mi->MachineType, FALSE))) {
  777. Cache->InvalidateProcessOrModule(pe->hProcess, mi->BaseOfDll);
  778. }
  779. if (pe && pe->ipmi == mi) {
  780. pe->ipmi = NULL;
  781. }
  782. if (mi->symbolTable) {
  783. MemFree( mi->symbolTable );
  784. }
  785. if (mi->SectionHdrs) {
  786. MemFree( mi->SectionHdrs );
  787. }
  788. if (mi->OriginalSectionHdrs) {
  789. MemFree( mi->OriginalSectionHdrs );
  790. }
  791. if (mi->pFpoData) {
  792. VirtualFree( mi->pFpoData, 0, MEM_RELEASE );
  793. }
  794. if (mi->pFpoDataOmap) {
  795. VirtualFree( mi->pFpoDataOmap, 0, MEM_RELEASE );
  796. }
  797. if (mi->pExceptionData) {
  798. VirtualFree( mi->pExceptionData, 0, MEM_RELEASE );
  799. }
  800. if (mi->pPData) {
  801. MemFree( mi->pPData );
  802. }
  803. if (mi->pXData) {
  804. MemFree( mi->pXData );
  805. }
  806. if (mi->TmpSym.Name) {
  807. MemFree( mi->TmpSym.Name );
  808. }
  809. if (mi->ImageName) {
  810. MemFree( mi->ImageName );
  811. }
  812. if (mi->LoadedImageName) {
  813. MemFree( mi->LoadedImageName );
  814. }
  815. if (mi->LoadedPdbName) {
  816. MemFree( mi->LoadedPdbName );
  817. }
  818. if (mi->pOmapTo) {
  819. MemFree( mi->pOmapTo );
  820. }
  821. if (mi->pOmapFrom) {
  822. MemFree( mi->pOmapFrom );
  823. }
  824. if (mi->CallerData) {
  825. MemFree( mi->CallerData );
  826. }
  827. if (mi->SourceFiles) {
  828. PSOURCE_ENTRY Src, SrcNext;
  829. for (Src = mi->SourceFiles; Src != NULL; Src = SrcNext) {
  830. SrcNext = Src->Next;
  831. MemFree(Src);
  832. }
  833. }
  834. if (mi->dia) {
  835. diaRelease(mi->dia);
  836. }
  837. MemFree( mi );
  838. }
  839. BOOL
  840. MatchSymbolName(
  841. PSYMBOL_ENTRY sym,
  842. LPSTR SymName
  843. )
  844. {
  845. if (g.SymOptions & SYMOPT_CASE_INSENSITIVE) {
  846. if (_stricmp( sym->Name, SymName ) == 0) {
  847. return TRUE;
  848. }
  849. } else {
  850. if (strcmp( sym->Name, SymName ) == 0) {
  851. return TRUE;
  852. }
  853. }
  854. return FALSE;
  855. }
  856. PSYMBOL_ENTRY
  857. HandleDuplicateSymbols(
  858. PPROCESS_ENTRY pe,
  859. PMODULE_ENTRY mi,
  860. PSYMBOL_ENTRY sym
  861. )
  862. {
  863. DWORD i;
  864. DWORD Dups;
  865. DWORD NameSize;
  866. PIMAGEHLP_SYMBOL64 Syms64 = NULL;
  867. PIMAGEHLP_SYMBOL Syms32 = NULL;
  868. PIMAGEHLP_DUPLICATE_SYMBOL64 DupSym64 = NULL;
  869. PIMAGEHLP_DUPLICATE_SYMBOL DupSym32 = NULL;
  870. PULONG SymSave;
  871. if (!pe->pCallbackFunction32 && !pe->pCallbackFunction64) {
  872. return sym;
  873. }
  874. if (!(sym->Flags & SYMF_DUPLICATE)) {
  875. return sym;
  876. }
  877. Dups = 0;
  878. NameSize = 0;
  879. for (i = 0; i < mi->numsyms; i++) {
  880. if ((mi->symbolTable[i].NameLength == sym->NameLength) &&
  881. (strcmp( mi->symbolTable[i].Name, sym->Name ) == 0)) {
  882. Dups += 1;
  883. NameSize += (mi->symbolTable[i].NameLength + 1);
  884. }
  885. }
  886. if (pe->pCallbackFunction32) {
  887. DupSym32 = (PIMAGEHLP_DUPLICATE_SYMBOL) MemAlloc( sizeof(IMAGEHLP_DUPLICATE_SYMBOL) );
  888. if (!DupSym32) {
  889. return sym;
  890. }
  891. Syms32 = (PIMAGEHLP_SYMBOL) MemAlloc( (sizeof(IMAGEHLP_SYMBOL) * Dups) + NameSize );
  892. if (!Syms32) {
  893. MemFree( DupSym32 );
  894. return sym;
  895. }
  896. SymSave = (PULONG) MemAlloc( sizeof(ULONG) * Dups );
  897. if (!SymSave) {
  898. MemFree( Syms32 );
  899. MemFree( DupSym32 );
  900. return sym;
  901. }
  902. DupSym32->SizeOfStruct = sizeof(IMAGEHLP_DUPLICATE_SYMBOL);
  903. DupSym32->NumberOfDups = Dups;
  904. DupSym32->Symbol = Syms32;
  905. DupSym32->SelectedSymbol = (ULONG) -1;
  906. Dups = 0;
  907. for (i = 0; i < mi->numsyms; i++) {
  908. if ((mi->symbolTable[i].NameLength == sym->NameLength) &&
  909. (strcmp( mi->symbolTable[i].Name, sym->Name ) == 0)) {
  910. symcpy32( Syms32, &mi->symbolTable[i] );
  911. Syms32 += (sizeof(IMAGEHLP_SYMBOL) + mi->symbolTable[i].NameLength + 1);
  912. SymSave[Dups] = i;
  913. Dups += 1;
  914. }
  915. }
  916. } else {
  917. DupSym64 = (PIMAGEHLP_DUPLICATE_SYMBOL64) MemAlloc( sizeof(IMAGEHLP_DUPLICATE_SYMBOL64) );
  918. if (!DupSym64) {
  919. return sym;
  920. }
  921. Syms64 = (PIMAGEHLP_SYMBOL64) MemAlloc( (sizeof(IMAGEHLP_SYMBOL64) * Dups) + NameSize );
  922. if (!Syms64) {
  923. MemFree( DupSym64 );
  924. return sym;
  925. }
  926. SymSave = (PULONG) MemAlloc( sizeof(ULONG) * Dups );
  927. if (!SymSave) {
  928. MemFree( Syms64 );
  929. MemFree( DupSym64 );
  930. return sym;
  931. }
  932. DupSym64->SizeOfStruct = sizeof(IMAGEHLP_DUPLICATE_SYMBOL64);
  933. DupSym64->NumberOfDups = Dups;
  934. DupSym64->Symbol = Syms64;
  935. DupSym64->SelectedSymbol = (ULONG) -1;
  936. Dups = 0;
  937. for (i = 0; i < mi->numsyms; i++) {
  938. if ((mi->symbolTable[i].NameLength == sym->NameLength) &&
  939. (strcmp( mi->symbolTable[i].Name, sym->Name ) == 0)) {
  940. symcpy64( Syms64, &mi->symbolTable[i] );
  941. Syms64 += (sizeof(IMAGEHLP_SYMBOL64) + mi->symbolTable[i].NameLength + 1);
  942. SymSave[Dups] = i;
  943. Dups += 1;
  944. }
  945. }
  946. }
  947. sym = NULL;
  948. __try {
  949. if (pe->pCallbackFunction32) {
  950. pe->pCallbackFunction32(
  951. pe->hProcess,
  952. CBA_DUPLICATE_SYMBOL,
  953. (PVOID) DupSym32,
  954. (PVOID) pe->CallbackUserContext
  955. );
  956. if (DupSym32->SelectedSymbol != (ULONG) -1) {
  957. if (DupSym32->SelectedSymbol < DupSym32->NumberOfDups) {
  958. sym = &mi->symbolTable[SymSave[DupSym32->SelectedSymbol]];
  959. }
  960. }
  961. } else {
  962. pe->pCallbackFunction64(
  963. pe->hProcess,
  964. CBA_DUPLICATE_SYMBOL,
  965. (ULONG64) &DupSym64,
  966. pe->CallbackUserContext
  967. );
  968. if (DupSym64->SelectedSymbol != (ULONG) -1) {
  969. if (DupSym64->SelectedSymbol < DupSym64->NumberOfDups) {
  970. sym = &mi->symbolTable[SymSave[DupSym64->SelectedSymbol]];
  971. }
  972. }
  973. }
  974. } __except (EXCEPTION_EXECUTE_HANDLER) {
  975. ;
  976. }
  977. if (DupSym32) {
  978. MemFree( DupSym32 );
  979. }
  980. if (DupSym64) {
  981. MemFree( DupSym64 );
  982. }
  983. if (Syms32) {
  984. MemFree( Syms32 );
  985. }
  986. if (Syms64) {
  987. MemFree( Syms64 );
  988. }
  989. MemFree( SymSave );
  990. return sym;
  991. }
  992. PSYMBOL_ENTRY
  993. FindSymbolByName(
  994. PPROCESS_ENTRY pe,
  995. PMODULE_ENTRY mi,
  996. LPSTR SymName
  997. )
  998. {
  999. DWORD hash;
  1000. PSYMBOL_ENTRY sym;
  1001. DWORD i;
  1002. if (!mi || mi->dia)
  1003. return diaFindSymbolByName(pe, mi, SymName);
  1004. hash = ComputeHash( SymName, strlen(SymName) );
  1005. sym = mi->NameHashTable[hash];
  1006. if (sym) {
  1007. //
  1008. // there are collision(s) so lets walk the
  1009. // collision list and match the names
  1010. //
  1011. while( sym ) {
  1012. if (MatchSymbolName( sym, SymName )) {
  1013. sym = HandleDuplicateSymbols( pe, mi, sym );
  1014. return sym;
  1015. }
  1016. sym = sym->Next;
  1017. }
  1018. }
  1019. //
  1020. // the symbol did not hash to anything valid
  1021. // this is possible if the caller passed an undecorated name
  1022. // now we must look linearly thru the list
  1023. //
  1024. for (i=0; i<mi->numsyms; i++) {
  1025. sym = &mi->symbolTable[i];
  1026. if (MatchSymbolName( sym, SymName )) {
  1027. sym = HandleDuplicateSymbols( pe, mi, sym );
  1028. return sym;
  1029. }
  1030. }
  1031. return NULL;
  1032. }
  1033. IMGHLP_RVA_FUNCTION_DATA *
  1034. SearchRvaFunctionTable(
  1035. IMGHLP_RVA_FUNCTION_DATA *FunctionTable,
  1036. LONG High,
  1037. LONG Low,
  1038. DWORD dwPC
  1039. )
  1040. {
  1041. LONG Middle;
  1042. IMGHLP_RVA_FUNCTION_DATA *FunctionEntry;
  1043. // Perform binary search on the function table for a function table
  1044. // entry that subsumes the specified PC.
  1045. while (High >= Low) {
  1046. // Compute next probe index and test entry. If the specified PC
  1047. // is greater than of equal to the beginning address and less
  1048. // than the ending address of the function table entry, then
  1049. // return the address of the function table entry. Otherwise,
  1050. // continue the search.
  1051. Middle = (Low + High) >> 1;
  1052. FunctionEntry = &FunctionTable[Middle];
  1053. if (dwPC < FunctionEntry->rvaBeginAddress) {
  1054. High = Middle - 1;
  1055. } else if (dwPC >= FunctionEntry->rvaEndAddress) {
  1056. Low = Middle + 1;
  1057. } else {
  1058. return FunctionEntry;
  1059. }
  1060. }
  1061. return NULL;
  1062. }
  1063. PIMGHLP_RVA_FUNCTION_DATA
  1064. GetFunctionEntryFromDebugInfo (
  1065. PPROCESS_ENTRY pe,
  1066. DWORD64 ControlPc
  1067. )
  1068. {
  1069. PMODULE_ENTRY mi;
  1070. IMGHLP_RVA_FUNCTION_DATA *FunctionTable;
  1071. mi = GetModuleForPC( pe, ControlPc, FALSE );
  1072. if (mi == NULL) {
  1073. return NULL;
  1074. }
  1075. if (!GetPData(pe->hProcess, mi)) {
  1076. return NULL;
  1077. }
  1078. FunctionTable = (IMGHLP_RVA_FUNCTION_DATA *)mi->pExceptionData;
  1079. return SearchRvaFunctionTable(FunctionTable, mi->dwEntries - 1, 0,
  1080. (ULONG)(ControlPc - mi->BaseOfDll));
  1081. }
  1082. PIMAGE_FUNCTION_ENTRY
  1083. LookupFunctionEntryAxp32 (
  1084. HANDLE hProcess,
  1085. DWORD ControlPc
  1086. )
  1087. {
  1088. FunctionEntryCache* Cache;
  1089. FeCacheEntry* FunctionEntry;
  1090. if ((Cache = GetFeCache(IMAGE_FILE_MACHINE_ALPHA, TRUE)) == NULL) {
  1091. return NULL;
  1092. }
  1093. // Don't specify the function table access callback or it will
  1094. // cause recursion.
  1095. FunctionEntry = Cache->
  1096. Find(hProcess, (ULONG64)(LONG)ControlPc, ReadInProcMemory,
  1097. miGetModuleBase, NULL);
  1098. if ( FunctionEntry == NULL ) {
  1099. return NULL;
  1100. }
  1101. // Alpha function entries are always stored as 64-bit
  1102. // so downconvert.
  1103. tlsvar(FunctionEntry32).StartingAddress =
  1104. (ULONG)FunctionEntry->Data.Axp64.BeginAddress;
  1105. tlsvar(FunctionEntry32).EndingAddress =
  1106. (ULONG)FunctionEntry->Data.Axp64.EndAddress;
  1107. tlsvar(FunctionEntry32).EndOfPrologue =
  1108. (ULONG)FunctionEntry->Data.Axp64.PrologEndAddress;
  1109. return &tlsvar(FunctionEntry32);
  1110. }
  1111. PIMAGE_FUNCTION_ENTRY64
  1112. LookupFunctionEntryAxp64 (
  1113. HANDLE hProcess,
  1114. DWORD64 ControlPc
  1115. )
  1116. {
  1117. FunctionEntryCache* Cache;
  1118. FeCacheEntry* FunctionEntry;
  1119. if ((Cache = GetFeCache(IMAGE_FILE_MACHINE_ALPHA64, TRUE)) == NULL) {
  1120. return NULL;
  1121. }
  1122. // Don't specify the function table access callback or it will
  1123. // cause recursion.
  1124. FunctionEntry = Cache->
  1125. Find(hProcess, ControlPc, ReadInProcMemory,
  1126. miGetModuleBase, NULL);
  1127. if ( FunctionEntry == NULL ) {
  1128. return NULL;
  1129. }
  1130. tlsvar(FunctionEntry64).StartingAddress =
  1131. FunctionEntry->Data.Axp64.BeginAddress;
  1132. tlsvar(FunctionEntry64).EndingAddress =
  1133. FunctionEntry->Data.Axp64.EndAddress;
  1134. tlsvar(FunctionEntry64).EndOfPrologue =
  1135. FunctionEntry->Data.Axp64.PrologEndAddress;
  1136. return &tlsvar(FunctionEntry64);
  1137. }
  1138. // NTRAID#96939-2000/03/27-patst
  1139. //
  1140. // All the platform dependent "LookupFunctionEntryXxx" should be retyped as returning
  1141. // a PIMAGE_FUNCTION_ENTRY64. This would require a modification of the callers, especially
  1142. // the IA64 specific locations that assume that the returned function entries contains RVAs
  1143. // and not absolute addresses. I implemented a platform-independant
  1144. // "per address space / per module" cache of function entries - capable of supporting the
  1145. // dynamic function entries scheme but I fell short of time in delivering it.
  1146. PIMAGE_IA64_RUNTIME_FUNCTION_ENTRY
  1147. LookupFunctionEntryIa64 (
  1148. HANDLE hProcess,
  1149. DWORD64 ControlPc
  1150. )
  1151. {
  1152. FunctionEntryCache* Cache;
  1153. FeCacheEntry* FunctionEntry;
  1154. if ((Cache = GetFeCache(IMAGE_FILE_MACHINE_IA64, TRUE)) == NULL) {
  1155. return NULL;
  1156. }
  1157. //
  1158. // IA64-NOTE 08/99: IA64 Function entries contain file offsets, not absolute relocated addresses.
  1159. // IA64 Callers assume this.
  1160. //
  1161. // Don't specify the function table access callback or it will
  1162. // cause recursion.
  1163. FunctionEntry = Cache->
  1164. Find(hProcess, ControlPc, ReadInProcMemory,
  1165. miGetModuleBase, NULL);
  1166. if ( FunctionEntry == NULL ) {
  1167. return NULL;
  1168. }
  1169. tlsvar(Ia64FunctionEntry) = FunctionEntry->Data.Ia64;
  1170. return &tlsvar(Ia64FunctionEntry);
  1171. }
  1172. _PIMAGE_RUNTIME_FUNCTION_ENTRY
  1173. LookupFunctionEntryAmd64 (
  1174. HANDLE hProcess,
  1175. DWORD64 ControlPc
  1176. )
  1177. {
  1178. FunctionEntryCache* Cache;
  1179. FeCacheEntry* FunctionEntry;
  1180. if ((Cache = GetFeCache(IMAGE_FILE_MACHINE_AMD64, TRUE)) == NULL) {
  1181. return NULL;
  1182. }
  1183. // Don't specify the function table access callback or it will
  1184. // cause recursion.
  1185. FunctionEntry = Cache->
  1186. Find(hProcess, ControlPc, ReadInProcMemory,
  1187. miGetModuleBase, NULL);
  1188. if ( FunctionEntry == NULL ) {
  1189. return NULL;
  1190. }
  1191. tlsvar(Amd64FunctionEntry) = FunctionEntry->Data.Amd64;
  1192. return &tlsvar(Amd64FunctionEntry);
  1193. }
  1194. PFPO_DATA
  1195. SwSearchFpoData(
  1196. DWORD key,
  1197. PFPO_DATA base,
  1198. DWORD num
  1199. )
  1200. {
  1201. PFPO_DATA lo = base;
  1202. PFPO_DATA hi = base + (num - 1);
  1203. PFPO_DATA mid;
  1204. DWORD half;
  1205. while (lo <= hi) {
  1206. if (half = num / 2) {
  1207. mid = lo + ((num & 1) ? half : (half - 1));
  1208. if ((key >= mid->ulOffStart)&&(key < (mid->ulOffStart+mid->cbProcSize))) {
  1209. return mid;
  1210. }
  1211. if (key < mid->ulOffStart) {
  1212. hi = mid - 1;
  1213. num = (num & 1) ? half : half-1;
  1214. } else {
  1215. lo = mid + 1;
  1216. num = half;
  1217. }
  1218. } else
  1219. if (num) {
  1220. if ((key >= lo->ulOffStart)&&(key < (lo->ulOffStart+lo->cbProcSize))) {
  1221. return lo;
  1222. } else {
  1223. break;
  1224. }
  1225. } else {
  1226. break;
  1227. }
  1228. }
  1229. return(NULL);
  1230. }
  1231. BOOL
  1232. DoSymbolCallback (
  1233. PPROCESS_ENTRY pe,
  1234. ULONG CallbackType,
  1235. IN PMODULE_ENTRY mi,
  1236. PIMAGEHLP_DEFERRED_SYMBOL_LOAD64 idsl64,
  1237. LPSTR FileName
  1238. )
  1239. {
  1240. BOOL Status;
  1241. IMAGEHLP_DEFERRED_SYMBOL_LOAD idsl32;
  1242. Status = FALSE;
  1243. if (pe->pCallbackFunction32) {
  1244. idsl32.SizeOfStruct = sizeof(IMAGEHLP_DEFERRED_SYMBOL_LOAD);
  1245. idsl32.BaseOfImage = (ULONG)mi->BaseOfDll;
  1246. idsl32.CheckSum = mi->CheckSum;
  1247. idsl32.TimeDateStamp = mi->TimeDateStamp;
  1248. idsl32.Reparse = FALSE;
  1249. idsl32.FileName[0] = 0;
  1250. if (FileName) {
  1251. strncat( idsl32.FileName, FileName, MAX_PATH - 1 );
  1252. }
  1253. __try {
  1254. Status = pe->pCallbackFunction32(
  1255. pe->hProcess,
  1256. CallbackType,
  1257. (PVOID)&idsl32,
  1258. (PVOID)pe->CallbackUserContext
  1259. );
  1260. idsl64->SizeOfStruct = sizeof(IMAGEHLP_DEFERRED_SYMBOL_LOAD64);
  1261. idsl64->BaseOfImage = idsl32.BaseOfImage;
  1262. idsl64->CheckSum = idsl32.CheckSum;
  1263. idsl64->TimeDateStamp = idsl32.TimeDateStamp;
  1264. idsl64->Reparse = idsl32.Reparse;
  1265. if (idsl32.FileName) {
  1266. strncpy( idsl64->FileName, idsl32.FileName, MAX_PATH );
  1267. }
  1268. } __except (EXCEPTION_EXECUTE_HANDLER) {
  1269. }
  1270. } else
  1271. if (pe->pCallbackFunction64) {
  1272. idsl64->SizeOfStruct = sizeof(IMAGEHLP_DEFERRED_SYMBOL_LOAD64);
  1273. idsl64->BaseOfImage = mi->BaseOfDll;
  1274. idsl64->CheckSum = mi->CheckSum;
  1275. idsl64->TimeDateStamp = mi->TimeDateStamp;
  1276. idsl64->Reparse = FALSE;
  1277. idsl64->FileName[0] = 0;
  1278. if (FileName) {
  1279. strncat( idsl64->FileName, FileName, MAX_PATH );
  1280. }
  1281. __try {
  1282. Status = pe->pCallbackFunction64(
  1283. pe->hProcess,
  1284. CallbackType,
  1285. (ULONG64)(ULONG_PTR)idsl64,
  1286. pe->CallbackUserContext
  1287. );
  1288. } __except (EXCEPTION_EXECUTE_HANDLER) {
  1289. }
  1290. }
  1291. return Status;
  1292. }
  1293. BOOL
  1294. DoCallback(
  1295. PPROCESS_ENTRY pe,
  1296. ULONG type,
  1297. PVOID data
  1298. )
  1299. {
  1300. BOOL rc = TRUE;
  1301. __try {
  1302. // if we weren't passed a process entry, then call all processes
  1303. if (!pe) {
  1304. BOOL ret;
  1305. PLIST_ENTRY next;
  1306. next = g.ProcessList.Flink;
  1307. if (!next)
  1308. return FALSE;
  1309. while ((PVOID)next != (PVOID)&g.ProcessList) {
  1310. pe = CONTAINING_RECORD( next, PROCESS_ENTRY, ListEntry );
  1311. next = pe->ListEntry.Flink;
  1312. if (!pe)
  1313. return rc;
  1314. ret = DoCallback(pe, type, data);
  1315. if (!ret)
  1316. rc = ret;
  1317. }
  1318. return rc;
  1319. }
  1320. // otherwise call this process
  1321. if (pe->pCallbackFunction32) {
  1322. rc = pe->pCallbackFunction32(pe->hProcess,
  1323. type,
  1324. data,
  1325. (PVOID)pe->CallbackUserContext);
  1326. } else if (pe->pCallbackFunction64) {
  1327. rc = pe->pCallbackFunction64(pe->hProcess,
  1328. type,
  1329. (ULONG64)data,
  1330. pe->CallbackUserContext);
  1331. }
  1332. } __except (EXCEPTION_EXECUTE_HANDLER) {
  1333. rc = FALSE;
  1334. }
  1335. return rc;
  1336. }
  1337. VOID
  1338. SympSendDebugString(
  1339. PPROCESS_ENTRY pe,
  1340. LPSTR String
  1341. )
  1342. {
  1343. __try {
  1344. if (!pe)
  1345. pe = FindFirstProcessEntry();
  1346. if (!pe) {
  1347. printf(String);
  1348. } else if (pe->pCallbackFunction32) {
  1349. pe->pCallbackFunction32(pe->hProcess,
  1350. CBA_DEBUG_INFO,
  1351. (PVOID)String,
  1352. (PVOID)pe->CallbackUserContext
  1353. );
  1354. } else if (pe->pCallbackFunction64) {
  1355. pe->pCallbackFunction64(pe->hProcess,
  1356. CBA_DEBUG_INFO,
  1357. (ULONG64)String,
  1358. pe->CallbackUserContext
  1359. );
  1360. }
  1361. } __except (EXCEPTION_EXECUTE_HANDLER) {
  1362. }
  1363. }
  1364. int
  1365. WINAPIV
  1366. _pprint(
  1367. PPROCESS_ENTRY pe,
  1368. LPSTR Format,
  1369. ...
  1370. )
  1371. {
  1372. static char buf[1000] = "DBGHELP: ";
  1373. va_list args;
  1374. va_start(args, Format);
  1375. _vsnprintf(buf+9, sizeof(buf)-9, Format, args);
  1376. va_end(args);
  1377. SympSendDebugString(pe, buf);
  1378. return 1;
  1379. }
  1380. int
  1381. WINAPIV
  1382. _peprint(
  1383. PPROCESS_ENTRY pe,
  1384. LPSTR Format,
  1385. ...
  1386. )
  1387. {
  1388. static char buf[1000] = "";
  1389. va_list args;
  1390. va_start(args, Format);
  1391. _vsnprintf(buf, sizeof(buf), Format, args);
  1392. va_end(args);
  1393. SympSendDebugString(pe, buf);
  1394. return 1;
  1395. }
  1396. int
  1397. WINAPIV
  1398. _dprint(
  1399. LPSTR format,
  1400. ...
  1401. )
  1402. {
  1403. static char buf[1000] = "DBGHELP: ";
  1404. va_list args;
  1405. va_start(args, format);
  1406. _vsnprintf(buf+9, sizeof(buf)-9, format, args);
  1407. va_end(args);
  1408. SympSendDebugString(NULL, buf);
  1409. return 1;
  1410. }
  1411. int
  1412. WINAPIV
  1413. _eprint(
  1414. LPSTR format,
  1415. ...
  1416. )
  1417. {
  1418. static char buf[1000] = "";
  1419. va_list args;
  1420. va_start(args, format);
  1421. _vsnprintf(buf, sizeof(buf), format, args);
  1422. va_end(args);
  1423. SympSendDebugString(NULL, buf);
  1424. return 1;
  1425. }
  1426. BOOL
  1427. WINAPIV
  1428. evtprint(
  1429. PPROCESS_ENTRY pe,
  1430. DWORD severity,
  1431. DWORD code,
  1432. PVOID object,
  1433. LPSTR format,
  1434. ...
  1435. )
  1436. {
  1437. static char buf[1000] = "";
  1438. IMAGEHLP_CBA_EVENT evt;
  1439. va_list args;
  1440. va_start(args, format);
  1441. _vsnprintf(buf, sizeof(buf), format, args);
  1442. va_end(args);
  1443. evt.severity = severity;
  1444. evt.code = code;
  1445. evt.desc = buf;
  1446. evt.object = object;
  1447. return DoCallback(pe, CBA_EVENT, &evt);
  1448. }
  1449. BOOL
  1450. traceAddr(
  1451. DWORD64 addr
  1452. )
  1453. {
  1454. DWORD64 taddr = 0;
  1455. if (!*g.DebugToken)
  1456. return FALSE;
  1457. sscanf(g.DebugToken, "0x%I64x", &taddr);
  1458. taddr = EXTEND64(taddr);
  1459. addr = EXTEND64(addr);
  1460. return (addr == taddr);
  1461. }
  1462. BOOL
  1463. traceName(
  1464. PCHAR name
  1465. )
  1466. {
  1467. if (!*g.DebugToken)
  1468. return FALSE;
  1469. return !_strnicmp(name, g.DebugToken, strlen(g.DebugToken));
  1470. }
  1471. BOOL
  1472. traceSubName(
  1473. PCHAR name
  1474. )
  1475. {
  1476. char *lname;
  1477. BOOL rc;
  1478. if (!*g.DebugToken)
  1479. return FALSE;
  1480. lname = (char *)MemAlloc(sizeof(char) * (strlen(name) + 1));
  1481. if (!lname) {
  1482. return FALSE;
  1483. }
  1484. strcpy(lname, name);
  1485. if (!lname)
  1486. return FALSE;
  1487. _strlwr(lname);
  1488. rc = strstr(lname, g.DebugToken) ? TRUE : FALSE;
  1489. MemFree(lname);
  1490. return rc;
  1491. }
  1492. BOOL
  1493. load(
  1494. IN HANDLE hProcess,
  1495. IN PMODULE_ENTRY mi
  1496. )
  1497. {
  1498. IMAGEHLP_DEFERRED_SYMBOL_LOAD64 idsl;
  1499. PPROCESS_ENTRY pe;
  1500. ULONG i;
  1501. PIMGHLP_DEBUG_DATA pIDD;
  1502. ULONG bias;
  1503. PIMAGE_SYMBOL lpSymbolEntry;
  1504. PUCHAR lpStringTable;
  1505. PUCHAR p;
  1506. BOOL SymbolsLoaded = FALSE;
  1507. PCHAR CallbackFileName, ImageName;
  1508. ULONG Size;
  1509. g.LastSymLoadError = SYMLOAD_DEFERRED;
  1510. pe = FindProcessEntry( hProcess );
  1511. if (!pe) {
  1512. SetLastError(ERROR_INVALID_HANDLE);
  1513. return FALSE;
  1514. }
  1515. // if (traceName(mi->ModuleName)) // for setting debug breakpoints from DBGHELP_TOKEN
  1516. // pprint(pe, "debug(%s)\n", mi->ModuleName);
  1517. CallbackFileName = mi->LoadedImageName ? mi->LoadedImageName :
  1518. mi->ImageName ? mi->ImageName : mi->ModuleName;
  1519. DoSymbolCallback(
  1520. pe,
  1521. CBA_DEFERRED_SYMBOL_LOAD_START,
  1522. mi,
  1523. &idsl,
  1524. CallbackFileName
  1525. );
  1526. ImageName = mi->ImageName;
  1527. for (; ;) {
  1528. pIDD = GetDebugData(
  1529. hProcess,
  1530. mi->hFile,
  1531. ImageName,
  1532. pe->SymbolSearchPath,
  1533. mi->BaseOfDll,
  1534. &mi->mld,
  1535. 0
  1536. );
  1537. mi->SymLoadError = g.LastSymLoadError;
  1538. if (pIDD) {
  1539. break;
  1540. }
  1541. pprint(pe, "GetDebugData(%p, %s, %s, %I64x, 0) failed\n",
  1542. mi->hFile,
  1543. ImageName,
  1544. pe->SymbolSearchPath,
  1545. mi->BaseOfDll
  1546. );
  1547. if (!DoSymbolCallback(
  1548. pe,
  1549. CBA_DEFERRED_SYMBOL_LOAD_FAILURE,
  1550. mi,
  1551. &idsl,
  1552. CallbackFileName
  1553. ) || !idsl.Reparse)
  1554. {
  1555. mi->SymType = SymNone;
  1556. mi->Flags |= MIF_NO_SYMBOLS;
  1557. return FALSE;
  1558. }
  1559. ImageName = idsl.FileName;
  1560. CallbackFileName = idsl.FileName;
  1561. }
  1562. pIDD->flags = mi->Flags;
  1563. // The following code ONLY works if the dll wasn't rebased
  1564. // during install. Is it really useful?
  1565. if (!mi->BaseOfDll) {
  1566. //
  1567. // This case occurs when modules are loaded multiple times by
  1568. // name with no explicit base address.
  1569. //
  1570. if (GetModuleForPC( pe, pIDD->ImageBaseFromImage, TRUE )) {
  1571. if (pIDD->ImageBaseFromImage) {
  1572. pprint(pe, "GetModuleForPC(%p, %I64x, TRUE) failed\n",
  1573. pe,
  1574. pIDD->ImageBaseFromImage,
  1575. TRUE
  1576. );
  1577. } else {
  1578. pprint(pe, "No base address for %s: Please specify\n", ImageName);
  1579. }
  1580. return FALSE;
  1581. }
  1582. mi->BaseOfDll = pIDD->ImageBaseFromImage;
  1583. }
  1584. if (!mi->DllSize) {
  1585. mi->DllSize = pIDD->SizeOfImage;
  1586. }
  1587. mi->hProcess = pIDD->hProcess;
  1588. mi->InProcImageBase = pIDD->InProcImageBase;
  1589. mi->CheckSum = pIDD->CheckSum;
  1590. mi->TimeDateStamp = pIDD->TimeDateStamp;
  1591. mi->MachineType = pIDD->Machine;
  1592. mi->ImageType = pIDD->ImageType;
  1593. mi->PdbSrc = pIDD->PdbSrc;
  1594. mi->ImageSrc = pIDD->ImageSrc;
  1595. if (!mi->MachineType && g.MachineType) {
  1596. mi->MachineType = (USHORT) g.MachineType;
  1597. }
  1598. if (pIDD->dia) {
  1599. mi->LoadedPdbName = StringDup(pIDD->PdbFileName);
  1600. }
  1601. if (pIDD->DbgFileMap) {
  1602. mi->LoadedImageName = StringDup(pIDD->DbgFilePath);
  1603. } else if (*pIDD->ImageFilePath) {
  1604. mi->LoadedImageName = StringDup(pIDD->ImageFilePath);
  1605. } else if (pIDD->dia) {
  1606. mi->LoadedImageName = StringDup(pIDD->PdbFileName);
  1607. } else {
  1608. mi->LoadedImageName = StringDup("");
  1609. }
  1610. if (pIDD->fROM) {
  1611. mi->Flags |= MIF_ROM_IMAGE;
  1612. }
  1613. if (!mi->ImageName) {
  1614. mi->ImageName = StringDup(pIDD->OriginalImageFileName);
  1615. _splitpath( mi->ImageName, NULL, NULL, mi->ModuleName, NULL );
  1616. mi->AliasName[0] = 0;
  1617. }
  1618. mi->dsExceptions = pIDD->dsExceptions;
  1619. if (pIDD->cFpo) {
  1620. //
  1621. // use virtualalloc() because the rtf search function
  1622. // return a pointer into this memory. we want to make
  1623. // all of this memory read only so that callers cannot
  1624. // stomp on imagehlp's data
  1625. //
  1626. mi->pFpoData = (PFPO_DATA)VirtualAlloc(
  1627. NULL,
  1628. sizeof(FPO_DATA) * pIDD->cFpo,
  1629. MEM_COMMIT,
  1630. PAGE_READWRITE
  1631. );
  1632. if (mi->pFpoData) {
  1633. mi->dwEntries = pIDD->cFpo;
  1634. CopyMemory(
  1635. mi->pFpoData,
  1636. pIDD->pFpo,
  1637. sizeof(FPO_DATA) * mi->dwEntries
  1638. );
  1639. VirtualProtect(
  1640. mi->pFpoData,
  1641. sizeof(FPO_DATA) * mi->dwEntries,
  1642. PAGE_READONLY,
  1643. &i
  1644. );
  1645. }
  1646. }
  1647. // copy the pdata block from the pdb
  1648. if (pIDD->pPData) {
  1649. mi->pPData = MemAlloc(pIDD->cbPData);
  1650. if (mi->pPData) {
  1651. mi->cPData = pIDD->cPData;
  1652. mi->cbPData = pIDD->cbPData;
  1653. CopyMemory(mi->pPData, pIDD->pPData, pIDD->cbPData);
  1654. }
  1655. }
  1656. if (pIDD->pXData) {
  1657. mi->pXData = MemAlloc(pIDD->cbXData);
  1658. if (mi->pXData) {
  1659. mi->cXData = pIDD->cXData;
  1660. mi->cbXData = pIDD->cbXData;
  1661. CopyMemory(mi->pXData, pIDD->pXData, pIDD->cbXData);
  1662. }
  1663. }
  1664. // now the sections
  1665. mi->NumSections = pIDD->cCurrentSections;
  1666. if (pIDD->fCurrentSectionsMapped) {
  1667. mi->SectionHdrs = (PIMAGE_SECTION_HEADER) MemAlloc(
  1668. sizeof(IMAGE_SECTION_HEADER) * mi->NumSections
  1669. );
  1670. if (mi->SectionHdrs) {
  1671. CopyMemory(
  1672. mi->SectionHdrs,
  1673. pIDD->pCurrentSections,
  1674. sizeof(IMAGE_SECTION_HEADER) * mi->NumSections
  1675. );
  1676. }
  1677. } else {
  1678. mi->SectionHdrs = pIDD->pCurrentSections;
  1679. }
  1680. if (pIDD->pOriginalSections) {
  1681. mi->OriginalNumSections = pIDD->cOriginalSections;
  1682. mi->OriginalSectionHdrs = pIDD->pOriginalSections;
  1683. } else {
  1684. mi->OriginalNumSections = mi->NumSections;
  1685. mi->OriginalSectionHdrs = (PIMAGE_SECTION_HEADER) MemAlloc(
  1686. sizeof(IMAGE_SECTION_HEADER) * mi->NumSections
  1687. );
  1688. if (mi->OriginalSectionHdrs) {
  1689. CopyMemory(
  1690. mi->OriginalSectionHdrs,
  1691. pIDD->pCurrentSections,
  1692. sizeof(IMAGE_SECTION_HEADER) * mi->NumSections
  1693. );
  1694. }
  1695. }
  1696. // symbols
  1697. mi->TmpSym.Name = (LPSTR) MemAlloc( TMP_SYM_LEN );
  1698. if (pIDD->dia) {
  1699. mi->SymType = SymDia;
  1700. SymbolsLoaded = TRUE;
  1701. } else {
  1702. if (pIDD->pMappedCv) {
  1703. SymbolsLoaded = LoadCodeViewSymbols(
  1704. hProcess,
  1705. mi,
  1706. pIDD
  1707. );
  1708. pprint(pe, "codeview symbols %sloaded\n", SymbolsLoaded?"":"not ");
  1709. }
  1710. if (!SymbolsLoaded && pIDD->pMappedCoff) {
  1711. SymbolsLoaded = LoadCoffSymbols(hProcess, mi, pIDD);
  1712. pprint(pe, "coff symbols %sloaded\n", SymbolsLoaded?"":"not ");
  1713. }
  1714. if (!SymbolsLoaded && pIDD->cExports) {
  1715. SymbolsLoaded = LoadExportSymbols( mi, pIDD );
  1716. if (SymbolsLoaded) {
  1717. mi->PdbSrc = srcNone;
  1718. }
  1719. pprint(pe, "export symbols %sloaded\n", SymbolsLoaded?"":"not ");
  1720. }
  1721. if (!SymbolsLoaded) {
  1722. mi->SymType = SymNone;
  1723. pprint(pe, "no symbols loaded\n");
  1724. }
  1725. }
  1726. mi->dia = pIDD->dia;
  1727. ProcessOmapForModule( mi, pIDD );
  1728. ReleaseDebugData(pIDD,
  1729. IMGHLP_FREE_FPO | IMGHLP_FREE_SYMPATH | IMGHLP_FREE_PDATA | IMGHLP_FREE_XDATA);
  1730. mi->Flags &= ~MIF_DEFERRED_LOAD;
  1731. DoSymbolCallback(pe,
  1732. CBA_DEFERRED_SYMBOL_LOAD_COMPLETE,
  1733. mi,
  1734. &idsl,
  1735. CallbackFileName);
  1736. return TRUE;
  1737. }
  1738. DWORD64
  1739. InternalLoadModule(
  1740. IN HANDLE hProcess,
  1741. IN PSTR ImageName,
  1742. IN PSTR ModuleName,
  1743. IN DWORD64 BaseOfDll,
  1744. IN DWORD DllSize,
  1745. IN HANDLE hFile,
  1746. IN PMODLOAD_DATA data,
  1747. IN DWORD flags
  1748. )
  1749. {
  1750. IMAGEHLP_DEFERRED_SYMBOL_LOAD64 idsl;
  1751. PPROCESS_ENTRY pe;
  1752. PMODULE_ENTRY mi;
  1753. LPSTR p;
  1754. DWORD64 ip;
  1755. // if (traceSubName(ImageName)) // for setting debug breakpoints from DBGHELP_TOKEN
  1756. // dprint("debug(%s)\n", ImageName);
  1757. if (BaseOfDll == (DWORD64)-1)
  1758. return 0;
  1759. __try {
  1760. CHAR c;
  1761. if (ImageName)
  1762. c = *ImageName;
  1763. if (ModuleName)
  1764. c = *ModuleName;
  1765. } __except(EXCEPTION_EXECUTE_HANDLER) {
  1766. SetLastError(ERROR_INVALID_PARAMETER);
  1767. return 0;
  1768. }
  1769. pe = FindProcessEntry( hProcess );
  1770. if (!pe) {
  1771. return 0;
  1772. }
  1773. if (BaseOfDll) {
  1774. mi = GetModuleForPC( pe, BaseOfDll, TRUE );
  1775. } else {
  1776. mi = NULL;
  1777. }
  1778. if (mi) {
  1779. //
  1780. // in this case the symbols are already loaded
  1781. // so the caller really wants the deferred
  1782. // symbols to be loaded
  1783. //
  1784. if ( (mi->Flags & MIF_DEFERRED_LOAD) &&
  1785. load( hProcess, mi )) {
  1786. return mi->BaseOfDll;
  1787. } else {
  1788. return 0;
  1789. }
  1790. }
  1791. //
  1792. // look to see if there is an overlapping module entry
  1793. //
  1794. if (BaseOfDll) {
  1795. do {
  1796. mi = GetModuleForPC( pe, BaseOfDll, FALSE );
  1797. if (mi) {
  1798. RemoveEntryList( &mi->ListEntry );
  1799. DoSymbolCallback(
  1800. pe,
  1801. CBA_SYMBOLS_UNLOADED,
  1802. mi,
  1803. &idsl,
  1804. mi->LoadedImageName ? mi->LoadedImageName : mi->ImageName ? mi->ImageName : mi->ModuleName
  1805. );
  1806. FreeModuleEntry(pe, mi);
  1807. }
  1808. } while(mi);
  1809. }
  1810. mi = (PMODULE_ENTRY) MemAlloc( sizeof(MODULE_ENTRY) );
  1811. if (!mi) {
  1812. return 0;
  1813. }
  1814. InitModuleEntry(mi);
  1815. mi->BaseOfDll = BaseOfDll;
  1816. mi->DllSize = DllSize;
  1817. mi->hFile = hFile;
  1818. if (ImageName) {
  1819. char SplitMod[_MAX_FNAME];
  1820. mi->ImageName = StringDup(ImageName);
  1821. _splitpath( ImageName, NULL, NULL, SplitMod, NULL );
  1822. mi->ModuleName[0] = 0;
  1823. strncat(mi->ModuleName, SplitMod, sizeof(mi->ModuleName) - 1);
  1824. if (ModuleName && _stricmp( ModuleName, mi->ModuleName ) != 0) {
  1825. mi->AliasName[0] = 0;
  1826. strncat( mi->AliasName, ModuleName, sizeof(mi->AliasName) - 1 );
  1827. } else {
  1828. mi->AliasName[0] = 0;
  1829. }
  1830. } else {
  1831. if (ModuleName) {
  1832. mi->AliasName[0] = 0;
  1833. strncat( mi->AliasName, ModuleName, sizeof(mi->AliasName) - 1 );
  1834. }
  1835. }
  1836. mi->mod = NULL;
  1837. mi->cbPdbSymbols = 0;
  1838. mi->pPdbSymbols = NULL;
  1839. if (data) {
  1840. if (data->ssize != sizeof(MODLOAD_DATA)) {
  1841. SetLastError(ERROR_INVALID_PARAMETER);
  1842. return 0;
  1843. }
  1844. memcpy(&mi->mld, data, data->ssize);
  1845. mi->CallerData = MemAlloc(mi->mld.size);
  1846. if (!mi->CallerData) {
  1847. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  1848. return 0;
  1849. }
  1850. mi->mld.data = mi->CallerData;
  1851. memcpy(mi->mld.data, data->data, mi->mld.size);
  1852. }
  1853. if ((g.SymOptions & SYMOPT_DEFERRED_LOADS) && BaseOfDll) {
  1854. mi->Flags |= MIF_DEFERRED_LOAD;
  1855. mi->SymType = SymDeferred;
  1856. } else if (!load( hProcess, mi )) {
  1857. FreeModuleEntry(pe, mi);
  1858. return 0;
  1859. }
  1860. pe->Count += 1;
  1861. InsertTailList( &pe->ModuleList, &mi->ListEntry);
  1862. ip = GetIP(pe);
  1863. if ((mi->BaseOfDll <= ip) && (mi->BaseOfDll + DllSize >= ip))
  1864. diaSetModFromIP(pe);
  1865. return mi->BaseOfDll;
  1866. }
  1867. PPROCESS_ENTRY
  1868. FindProcessEntry(
  1869. HANDLE hProcess
  1870. )
  1871. {
  1872. PLIST_ENTRY next;
  1873. PPROCESS_ENTRY pe;
  1874. DWORD count;
  1875. next = g.ProcessList.Flink;
  1876. if (!next) {
  1877. return NULL;
  1878. }
  1879. for (count = 0; (PVOID)next != (PVOID)&g.ProcessList; count++) {
  1880. assert(count < g.cProcessList);
  1881. if (count >= g.cProcessList)
  1882. return NULL;
  1883. pe = CONTAINING_RECORD( next, PROCESS_ENTRY, ListEntry );
  1884. next = pe->ListEntry.Flink;
  1885. if (pe->hProcess == hProcess) {
  1886. return pe;
  1887. }
  1888. }
  1889. return NULL;
  1890. }
  1891. PPROCESS_ENTRY
  1892. FindFirstProcessEntry(
  1893. )
  1894. {
  1895. return CONTAINING_RECORD(g.ProcessList.Flink, PROCESS_ENTRY, ListEntry);
  1896. }
  1897. PMODULE_ENTRY
  1898. FindModule(
  1899. HANDLE hProcess,
  1900. PPROCESS_ENTRY pe,
  1901. LPSTR ModuleName,
  1902. BOOL fLoad
  1903. )
  1904. {
  1905. PLIST_ENTRY next;
  1906. PMODULE_ENTRY mi;
  1907. if (!ModuleName || !*ModuleName)
  1908. return NULL;
  1909. next = pe->ModuleList.Flink;
  1910. if (next) {
  1911. while ((PVOID)next != (PVOID)&pe->ModuleList) {
  1912. mi = CONTAINING_RECORD( next, MODULE_ENTRY, ListEntry );
  1913. next = mi->ListEntry.Flink;
  1914. if ((_stricmp( mi->ModuleName, ModuleName ) == 0) ||
  1915. (mi->AliasName[0] &&
  1916. _stricmp( mi->AliasName, ModuleName ) == 0))
  1917. {
  1918. if (fLoad && !LoadSymbols(hProcess, mi, 0)) {
  1919. return NULL;
  1920. }
  1921. return mi;
  1922. }
  1923. }
  1924. }
  1925. return NULL;
  1926. }
  1927. #ifndef _DBGHELP_USER_GENERATED_SYMBOLS_NOTSUPPORTED
  1928. BOOL
  1929. SymCheckUserGenerated(
  1930. ULONG64 dwAddr,
  1931. PSYMBOL_ENTRY sym,
  1932. PMODULE_ENTRY mi
  1933. )
  1934. {
  1935. PSYMBOL_ENTRY nextSym;
  1936. /*
  1937. // We do not know the size of a user generated symbol...
  1938. // This work because of the execution of CompleteSymbolTable() after AllocSym().
  1939. // Particularly, the size has been adjusted.
  1940. */
  1941. if ( !(sym->Flags & SYMF_USER_GENERATED) ) {
  1942. dprint("SymCheckUserGenerated: We should not call this function. This is not a user generated symbol...\n" );
  1943. return FALSE;
  1944. }
  1945. if ( (dwAddr == sym->Address) || (sym == &mi->symbolTable[mi->numsyms - 1]) ) {
  1946. return TRUE;
  1947. }
  1948. nextSym = sym + 1;
  1949. if ( dwAddr < nextSym->Address ) {
  1950. return TRUE;
  1951. }
  1952. return FALSE;
  1953. }
  1954. #endif // !_DBGHELP_USER_GENERATED_SYMBOLS_NOTSUPPORTED
  1955. PSYMBOL_ENTRY
  1956. GetSymFromAddr(
  1957. DWORD64 dwAddr,
  1958. PDWORD64 pqwDisplacement,
  1959. PMODULE_ENTRY mi
  1960. )
  1961. {
  1962. PSYMBOL_ENTRY sym = NULL;
  1963. LONG High;
  1964. LONG Low;
  1965. LONG Middle;
  1966. if (mi == NULL) {
  1967. return NULL;
  1968. }
  1969. if (mi->dia)
  1970. return diaGetSymFromAddr(dwAddr, mi, pqwDisplacement);
  1971. //
  1972. // do a binary search to locate the symbol
  1973. //
  1974. Low = 0;
  1975. High = mi->numsyms - 1;
  1976. while (High >= Low) {
  1977. Middle = (Low + High) >> 1;
  1978. sym = &mi->symbolTable[Middle];
  1979. if (dwAddr < sym->Address) {
  1980. High = Middle - 1;
  1981. } else if (dwAddr >= sym->Address + sym->Size) {
  1982. #ifndef _DBGHELP_USER_GENERATED_SYMBOLS_NOTSUPPORTED
  1983. if ( (sym->Flags & SYMF_USER_GENERATED) && SymCheckUserGenerated( dwAddr, sym, mi ) ) {
  1984. if (pqwDisplacement) {
  1985. *pqwDisplacement = dwAddr - sym->Address;
  1986. }
  1987. return sym;
  1988. }
  1989. #endif // !_DBGHELP_USER_GENERATED_SYMBOLS_NOTSUPPORTED
  1990. Low = Middle + 1;
  1991. } else {
  1992. if (pqwDisplacement) {
  1993. *pqwDisplacement = dwAddr - sym->Address;
  1994. }
  1995. return sym;
  1996. }
  1997. }
  1998. return NULL;
  1999. }
  2000. PMODULE_ENTRY
  2001. GetModuleForPC(
  2002. PPROCESS_ENTRY pe,
  2003. DWORD64 dwPcAddr,
  2004. BOOL ExactMatch
  2005. )
  2006. {
  2007. static PLIST_ENTRY next = NULL;
  2008. PMODULE_ENTRY mi;
  2009. if (dwPcAddr == (DWORD64)-1) {
  2010. if (!next)
  2011. return NULL;
  2012. if ((PVOID)next == (PVOID)&pe->ModuleList) {
  2013. // Reset to NULL so the list can be re-walked
  2014. next = NULL;
  2015. return NULL;
  2016. }
  2017. mi = CONTAINING_RECORD( next, MODULE_ENTRY, ListEntry );
  2018. next = mi->ListEntry.Flink;
  2019. return mi;
  2020. }
  2021. next = pe->ModuleList.Flink;
  2022. if (!next) {
  2023. return NULL;
  2024. }
  2025. while ((PVOID)next != (PVOID)&pe->ModuleList) {
  2026. mi = CONTAINING_RECORD( next, MODULE_ENTRY, ListEntry );
  2027. next = mi->ListEntry.Flink;
  2028. if (dwPcAddr == 0) {
  2029. return mi;
  2030. }
  2031. if (ExactMatch) {
  2032. if (dwPcAddr == mi->BaseOfDll) {
  2033. return mi;
  2034. }
  2035. } else
  2036. if ((dwPcAddr == mi->BaseOfDll && mi->DllSize == 0) ||
  2037. ((dwPcAddr >= mi->BaseOfDll) &&
  2038. (dwPcAddr < mi->BaseOfDll + mi->DllSize))) {
  2039. return mi;
  2040. }
  2041. }
  2042. return NULL;
  2043. }
  2044. PSYMBOL_ENTRY
  2045. GetSymFromAddrAllContexts(
  2046. DWORD64 dwAddr,
  2047. PDWORD64 pqwDisplacement,
  2048. PPROCESS_ENTRY pe
  2049. )
  2050. {
  2051. PMODULE_ENTRY mi = GetModuleForPC( pe, dwAddr, FALSE );
  2052. if (mi == NULL) {
  2053. return NULL;
  2054. }
  2055. return GetSymFromAddr( dwAddr, pqwDisplacement, mi );
  2056. }
  2057. DWORD
  2058. ComputeHash(
  2059. LPSTR lpbName,
  2060. ULONG cb
  2061. )
  2062. {
  2063. ULONG UNALIGNED * lpulName;
  2064. ULONG ulEnd = 0;
  2065. int cul;
  2066. int iul;
  2067. ULONG ulSum = 0;
  2068. while (cb & 3) {
  2069. ulEnd |= (lpbName[cb - 1] & 0xdf);
  2070. ulEnd <<= 8;
  2071. cb -= 1;
  2072. }
  2073. cul = cb / 4;
  2074. lpulName = (ULONG UNALIGNED *) lpbName;
  2075. for (iul =0; iul < cul; iul++) {
  2076. ulSum ^= (lpulName[iul] & 0xdfdfdfdf);
  2077. ulSum = _lrotl( ulSum, 4);
  2078. }
  2079. ulSum ^= ulEnd;
  2080. return ulSum % HASH_MODULO;
  2081. }
  2082. PSYMBOL_ENTRY
  2083. AllocSym(
  2084. PMODULE_ENTRY mi,
  2085. DWORD64 addr,
  2086. LPSTR name
  2087. )
  2088. {
  2089. PSYMBOL_ENTRY sym;
  2090. ULONG Length;
  2091. if (mi->numsyms == mi->MaxSyms) {
  2092. // dprint("AllocSym: ERROR - symbols Table overflow!\n");
  2093. return NULL;
  2094. }
  2095. if (!mi->StringSize) {
  2096. // dprint("AllocSym: ERROR - symbols strings not allocated for module!\n");
  2097. return NULL;
  2098. }
  2099. Length = strlen(name);
  2100. if ((Length + 1) > mi->StringSize) {
  2101. // dprint("AllocSym: ERROR - symbols strings buffer overflow!\n");
  2102. return NULL;
  2103. }
  2104. sym = &mi->symbolTable[mi->numsyms];
  2105. mi->numsyms += 1;
  2106. sym->Name = mi->SymStrings;
  2107. mi->SymStrings += (Length + 2);
  2108. mi->StringSize -= (Length + 2);
  2109. strcpy( sym->Name, name );
  2110. sym->Address = addr;
  2111. sym->Size = 0;
  2112. sym->Flags = 0;
  2113. sym->Next = NULL;
  2114. sym->NameLength = Length;
  2115. return sym;
  2116. }
  2117. int __cdecl
  2118. SymbolTableAddressCompare(
  2119. const void *e1,
  2120. const void *e2
  2121. )
  2122. {
  2123. PSYMBOL_ENTRY sym1 = (PSYMBOL_ENTRY) e1;
  2124. PSYMBOL_ENTRY sym2 = (PSYMBOL_ENTRY) e2;
  2125. LONG64 diff;
  2126. if ( sym1 && sym2 ) {
  2127. diff = (sym1->Address - sym2->Address);
  2128. return (diff < 0) ? -1 : (diff == 0) ? 0 : 1;
  2129. } else {
  2130. return 1;
  2131. }
  2132. }
  2133. int __cdecl
  2134. SymbolTableNameCompare(
  2135. const void *e1,
  2136. const void *e2
  2137. )
  2138. {
  2139. PSYMBOL_ENTRY sym1 = (PSYMBOL_ENTRY) e1;
  2140. PSYMBOL_ENTRY sym2 = (PSYMBOL_ENTRY) e2;
  2141. return strcmp( sym1->Name, sym2->Name );
  2142. }
  2143. VOID
  2144. CompleteSymbolTable(
  2145. PMODULE_ENTRY mi
  2146. )
  2147. {
  2148. PSYMBOL_ENTRY sym;
  2149. PSYMBOL_ENTRY symH;
  2150. ULONG Hash;
  2151. ULONG i;
  2152. ULONG dups;
  2153. ULONG seq;
  2154. //
  2155. // sort the symbols by name
  2156. //
  2157. dbg_qsort(
  2158. mi->symbolTable,
  2159. mi->numsyms,
  2160. sizeof(SYMBOL_ENTRY),
  2161. SymbolTableNameCompare
  2162. );
  2163. //
  2164. // mark duplicate names
  2165. //
  2166. seq = 0;
  2167. for (i=0; i<mi->numsyms; i++) {
  2168. dups = 0;
  2169. while ((mi->symbolTable[i+dups].NameLength == mi->symbolTable[i+dups+1].NameLength) &&
  2170. (strcmp( mi->symbolTable[i+dups].Name, mi->symbolTable[i+dups+1].Name ) == 0)) {
  2171. mi->symbolTable[i+dups].Flags |= SYMF_DUPLICATE;
  2172. mi->symbolTable[i+dups+1].Flags |= SYMF_DUPLICATE;
  2173. dups += 1;
  2174. }
  2175. i += dups;
  2176. }
  2177. //
  2178. // sort the symbols by address
  2179. //
  2180. dbg_qsort(
  2181. mi->symbolTable,
  2182. mi->numsyms,
  2183. sizeof(SYMBOL_ENTRY),
  2184. SymbolTableAddressCompare
  2185. );
  2186. //
  2187. // calculate the size of each symbol
  2188. //
  2189. for (i=0; i<mi->numsyms; i++) {
  2190. mi->symbolTable[i].Next = NULL;
  2191. if (i+1 < mi->numsyms) {
  2192. mi->symbolTable[i].Size = (ULONG)(mi->symbolTable[i+1].Address - mi->symbolTable[i].Address);
  2193. }
  2194. }
  2195. //
  2196. // compute the hash for each symbol
  2197. //
  2198. ZeroMemory( mi->NameHashTable, sizeof(mi->NameHashTable) );
  2199. for (i=0; i<mi->numsyms; i++) {
  2200. sym = &mi->symbolTable[i];
  2201. Hash = ComputeHash( sym->Name, sym->NameLength );
  2202. if (mi->NameHashTable[Hash]) {
  2203. //
  2204. // we have a collision
  2205. //
  2206. symH = mi->NameHashTable[Hash];
  2207. while( symH->Next ) {
  2208. symH = symH->Next;
  2209. }
  2210. symH->Next = sym;
  2211. } else {
  2212. mi->NameHashTable[Hash] = sym;
  2213. }
  2214. }
  2215. }
  2216. BOOL
  2217. CreateSymbolTable(
  2218. PMODULE_ENTRY mi,
  2219. DWORD SymbolCount,
  2220. SYM_TYPE SymType,
  2221. DWORD NameSize
  2222. )
  2223. {
  2224. //
  2225. // allocate the symbol table
  2226. //
  2227. NameSize += OMAP_SYM_STRINGS;
  2228. mi->symbolTable = (PSYMBOL_ENTRY) MemAlloc(
  2229. (sizeof(SYMBOL_ENTRY) * (SymbolCount + OMAP_SYM_EXTRA)) + NameSize + (SymbolCount * CPP_EXTRA)
  2230. );
  2231. if (!mi->symbolTable) {
  2232. return FALSE;
  2233. }
  2234. //
  2235. // initialize the relevant fields
  2236. //
  2237. mi->numsyms = 0;
  2238. mi->MaxSyms = SymbolCount + OMAP_SYM_EXTRA;
  2239. mi->SymType = SymType;
  2240. mi->StringSize = NameSize + (SymbolCount * CPP_EXTRA);
  2241. mi->SymStrings = (LPSTR)(mi->symbolTable + SymbolCount + OMAP_SYM_EXTRA);
  2242. return TRUE;
  2243. }
  2244. PIMAGE_SECTION_HEADER
  2245. FindSection(
  2246. PIMAGE_SECTION_HEADER sh,
  2247. ULONG NumSections,
  2248. ULONG Address
  2249. )
  2250. {
  2251. ULONG i;
  2252. for (i=0; i<NumSections; i++) {
  2253. if (Address >= sh[i].VirtualAddress &&
  2254. Address < (sh[i].VirtualAddress + sh[i].Misc.VirtualSize)) {
  2255. return &sh[i];
  2256. }
  2257. }
  2258. return NULL;
  2259. }
  2260. PVOID
  2261. GetSectionPhysical(
  2262. HANDLE hp,
  2263. ULONG64 base,
  2264. PIMGHLP_DEBUG_DATA pIDD,
  2265. ULONG Address
  2266. )
  2267. {
  2268. PIMAGE_SECTION_HEADER sh;
  2269. sh = FindSection( pIDD->pCurrentSections, pIDD->cCurrentSections, Address );
  2270. if (!sh) {
  2271. return 0;
  2272. }
  2273. return (PCHAR)pIDD->ImageMap + sh->PointerToRawData + (Address - sh->VirtualAddress);
  2274. }
  2275. BOOL
  2276. ReadSectionInfo(
  2277. HANDLE hp,
  2278. ULONG64 base,
  2279. PIMGHLP_DEBUG_DATA pIDD,
  2280. ULONG address,
  2281. PVOID buf,
  2282. DWORD size
  2283. )
  2284. {
  2285. PIMAGE_SECTION_HEADER sh;
  2286. DWORD_PTR status = TRUE;
  2287. sh = FindSection( pIDD->pCurrentSections, pIDD->cCurrentSections, address );
  2288. if (!sh)
  2289. return FALSE;
  2290. if (!hp) {
  2291. status = (DWORD_PTR)memcpy((PCHAR)buf,
  2292. (PCHAR)base + sh->PointerToRawData + (address - sh->VirtualAddress),
  2293. size);
  2294. } else {
  2295. status = ReadImageData(hp, base, address, buf, size);
  2296. }
  2297. if (!status)
  2298. return FALSE;
  2299. return TRUE;
  2300. }
  2301. PCHAR
  2302. expptr(
  2303. HANDLE hp,
  2304. ULONG64 base,
  2305. PIMGHLP_DEBUG_DATA pIDD,
  2306. ULONG address
  2307. )
  2308. {
  2309. PIMAGE_SECTION_HEADER sh;
  2310. DWORD_PTR status = TRUE;
  2311. if (hp)
  2312. return (PCHAR)base + address;
  2313. sh = FindSection( pIDD->pCurrentSections, pIDD->cCurrentSections, address );
  2314. if (!sh)
  2315. return FALSE;
  2316. return (PCHAR)base + sh->PointerToRawData + (address - sh->VirtualAddress);
  2317. }
  2318. ULONG
  2319. LoadExportSymbols(
  2320. PMODULE_ENTRY mi,
  2321. PIMGHLP_DEBUG_DATA pIDD
  2322. )
  2323. {
  2324. PULONG names;
  2325. PULONG addrs;
  2326. PUSHORT ordinals;
  2327. PUSHORT ordidx = NULL;
  2328. ULONG cnt;
  2329. ULONG idx;
  2330. PIMAGE_EXPORT_DIRECTORY expdir;
  2331. PCHAR expbuf = NULL;
  2332. ULONG i;
  2333. PSYMBOL_ENTRY sym;
  2334. ULONG NameSize;
  2335. HANDLE hp;
  2336. ULONG64 base;
  2337. CHAR name[2048];
  2338. BOOL rc;
  2339. DWORD64 endExports;
  2340. PCHAR p;
  2341. if (g.SymOptions & SYMOPT_EXACT_SYMBOLS)
  2342. return 0;
  2343. // setup pointers for grabing data
  2344. switch (pIDD->dsExports) {
  2345. case dsInProc:
  2346. hp = pIDD->hProcess;
  2347. expbuf = (PCHAR)MemAlloc(pIDD->cExports);
  2348. if (!expbuf)
  2349. goto cleanup;
  2350. if (!ReadImageData(hp, pIDD->InProcImageBase, pIDD->oExports, expbuf, pIDD->cExports))
  2351. goto cleanup;
  2352. base = (ULONG64)expbuf - pIDD->oExports;
  2353. expdir = (PIMAGE_EXPORT_DIRECTORY)expbuf;
  2354. break;
  2355. case dsImage:
  2356. hp = NULL;
  2357. expbuf = NULL;
  2358. if (!pIDD->ImageMap)
  2359. pIDD->ImageMap = MapItRO(pIDD->ImageFileHandle);
  2360. base = (ULONG64)pIDD->ImageMap;
  2361. expdir = &pIDD->expdir;
  2362. break;
  2363. default:
  2364. return 0;
  2365. }
  2366. cnt = 0;
  2367. names = (PULONG)expptr(hp, base, pIDD, expdir->AddressOfNames);
  2368. if (!names)
  2369. goto cleanup;
  2370. addrs = (PULONG)expptr(hp, base, pIDD, expdir->AddressOfFunctions);
  2371. if (!addrs)
  2372. goto cleanup;
  2373. ordinals = (PUSHORT)expptr(hp, base, pIDD, expdir->AddressOfNameOrdinals);
  2374. if (!ordinals)
  2375. goto cleanup;
  2376. ordidx = (PUSHORT) MemAlloc( max(expdir->NumberOfFunctions, expdir->NumberOfNames) * sizeof(USHORT) );
  2377. if (!ordidx)
  2378. goto cleanup;
  2379. cnt = 0;
  2380. NameSize = 0;
  2381. // count the symbols
  2382. for (i=0; i<expdir->NumberOfNames; i++) {
  2383. *name = 0;
  2384. p = expptr(hp, base, pIDD, names[i]);
  2385. if (!p)
  2386. continue;
  2387. strcpy(name, p);
  2388. if (!*name)
  2389. continue;
  2390. if (g.SymOptions & SYMOPT_UNDNAME) {
  2391. SymUnDNameInternal( mi->TmpSym.Name, TMP_SYM_LEN, name, strlen(name), mi->MachineType, TRUE );
  2392. NameSize += strlen(mi->TmpSym.Name);
  2393. cnt += 1;
  2394. } else {
  2395. NameSize += (strlen(name) + 2);
  2396. cnt += 1;
  2397. }
  2398. }
  2399. for (i=0,idx=expdir->NumberOfNames; i<expdir->NumberOfFunctions; i++) {
  2400. if (!ordidx[i]) {
  2401. NameSize += 16;
  2402. cnt += 1;
  2403. }
  2404. }
  2405. // allocate the symbol table
  2406. if (!CreateSymbolTable( mi, cnt, SymExport, NameSize )) {
  2407. cnt = 0;
  2408. goto cleanup;
  2409. }
  2410. // allocate the symbols
  2411. cnt = 0;
  2412. endExports = pIDD->oExports + pIDD->cExports;
  2413. for (i=0; i<expdir->NumberOfNames; i++) {
  2414. idx = ordinals[i];
  2415. ordidx[idx] = TRUE;
  2416. *name = 0;
  2417. p = expptr(hp, base, pIDD, names[i]);
  2418. if (!p)
  2419. continue;
  2420. strcpy(name, p);
  2421. if (!*name)
  2422. continue;
  2423. if (g.SymOptions & SYMOPT_UNDNAME) {
  2424. SymUnDNameInternal( mi->TmpSym.Name, TMP_SYM_LEN, (LPSTR)name, strlen(name), mi->MachineType, TRUE );
  2425. sym = AllocSym( mi, addrs[idx] + mi->BaseOfDll, mi->TmpSym.Name);
  2426. } else {
  2427. sym = AllocSym( mi, addrs[idx] + mi->BaseOfDll, name);
  2428. }
  2429. if (sym) {
  2430. cnt += 1;
  2431. }
  2432. if (pIDD->oExports <= addrs[idx]
  2433. && addrs[idx] <= endExports)
  2434. {
  2435. sym->Flags |= SYMF_FORWARDER;
  2436. } else {
  2437. sym->Flags |= SYMF_EXPORT;
  2438. }
  2439. }
  2440. for (i=0,idx=expdir->NumberOfNames; i<expdir->NumberOfFunctions; i++) {
  2441. if (!ordidx[i]) {
  2442. CHAR NameBuf[sizeof("Ordinal99999") + 1]; // Ordinals are only 64k max.
  2443. strcpy( NameBuf, "Ordinal" );
  2444. _itoa( i+expdir->Base, &NameBuf[7], 10 );
  2445. sym = AllocSym( mi, addrs[i] + mi->BaseOfDll, NameBuf);
  2446. if (sym) {
  2447. cnt += 1;
  2448. }
  2449. idx += 1;
  2450. }
  2451. }
  2452. CompleteSymbolTable( mi );
  2453. cleanup:
  2454. if (expbuf) {
  2455. MemFree(expbuf);
  2456. }
  2457. if (ordidx) {
  2458. MemFree(ordidx);
  2459. }
  2460. return cnt;
  2461. }
  2462. BOOL
  2463. LoadCoffSymbols(
  2464. HANDLE hProcess,
  2465. PMODULE_ENTRY mi,
  2466. PIMGHLP_DEBUG_DATA pIDD
  2467. )
  2468. {
  2469. PIMAGE_COFF_SYMBOLS_HEADER pCoffHeader = (PIMAGE_COFF_SYMBOLS_HEADER)(pIDD->pMappedCoff);
  2470. PUCHAR stringTable;
  2471. PIMAGE_SYMBOL allSymbols;
  2472. DWORD numberOfSymbols;
  2473. PIMAGE_LINENUMBER LineNumbers;
  2474. PIMAGE_SYMBOL NextSymbol;
  2475. PIMAGE_SYMBOL Symbol;
  2476. PSYMBOL_ENTRY sym;
  2477. CHAR szSymName[256];
  2478. DWORD i;
  2479. DWORD64 addr;
  2480. DWORD CoffSymbols = 0;
  2481. DWORD NameSize = 0;
  2482. DWORD64 Bias;
  2483. allSymbols = (PIMAGE_SYMBOL)((PCHAR)pCoffHeader +
  2484. pCoffHeader->LvaToFirstSymbol);
  2485. stringTable = (PUCHAR)pCoffHeader +
  2486. pCoffHeader->LvaToFirstSymbol +
  2487. (pCoffHeader->NumberOfSymbols * IMAGE_SIZEOF_SYMBOL);
  2488. numberOfSymbols = pCoffHeader->NumberOfSymbols;
  2489. LineNumbers = (PIMAGE_LINENUMBER)(PCHAR)pCoffHeader +
  2490. pCoffHeader->LvaToFirstLinenumber;
  2491. //
  2492. // count the number of actual symbols
  2493. //
  2494. NextSymbol = allSymbols;
  2495. for (i= 0; i < numberOfSymbols; i++) {
  2496. Symbol = NextSymbol++;
  2497. if (Symbol->StorageClass == IMAGE_SYM_CLASS_EXTERNAL &&
  2498. Symbol->SectionNumber > 0) {
  2499. GetSymName( Symbol, stringTable, szSymName, sizeof(szSymName) );
  2500. if (szSymName[0] == '?' && szSymName[1] == '?' &&
  2501. szSymName[2] == '_' && szSymName[3] == 'C' ) {
  2502. //
  2503. // ignore strings
  2504. //
  2505. } else if (g.SymOptions & SYMOPT_UNDNAME) {
  2506. SymUnDNameInternal(mi->TmpSym.Name,
  2507. TMP_SYM_LEN,
  2508. szSymName,
  2509. strlen(szSymName),
  2510. mi->MachineType,
  2511. TRUE);
  2512. NameSize += strlen(mi->TmpSym.Name);
  2513. CoffSymbols += 1;
  2514. } else {
  2515. CoffSymbols += 1;
  2516. NameSize += (strlen(szSymName) + 1);
  2517. }
  2518. }
  2519. NextSymbol += Symbol->NumberOfAuxSymbols;
  2520. i += Symbol->NumberOfAuxSymbols;
  2521. }
  2522. //
  2523. // allocate the symbol table
  2524. //
  2525. if (!CreateSymbolTable( mi, CoffSymbols, SymCoff, NameSize )) {
  2526. return FALSE;
  2527. }
  2528. //
  2529. // populate the symbol table
  2530. //
  2531. if (mi->Flags & MIF_ROM_IMAGE) {
  2532. Bias = mi->BaseOfDll & 0xffffffff00000000;
  2533. } else {
  2534. Bias = mi->BaseOfDll;
  2535. }
  2536. NextSymbol = allSymbols;
  2537. for (i= 0; i < numberOfSymbols; i++) {
  2538. Symbol = NextSymbol++;
  2539. if (Symbol->StorageClass == IMAGE_SYM_CLASS_EXTERNAL &&
  2540. Symbol->SectionNumber > 0) {
  2541. GetSymName( Symbol, stringTable, szSymName, sizeof(szSymName) );
  2542. addr = Symbol->Value + Bias;
  2543. if (szSymName[0] == '?' && szSymName[1] == '?' &&
  2544. szSymName[2] == '_' && szSymName[3] == 'C' ) {
  2545. //
  2546. // ignore strings
  2547. //
  2548. } else if (g.SymOptions & SYMOPT_UNDNAME) {
  2549. SymUnDNameInternal(mi->TmpSym.Name,
  2550. TMP_SYM_LEN,
  2551. szSymName,
  2552. strlen(szSymName),
  2553. mi->MachineType,
  2554. TRUE);
  2555. AllocSym( mi, addr, mi->TmpSym.Name);
  2556. } else {
  2557. AllocSym( mi, addr, szSymName );
  2558. }
  2559. }
  2560. NextSymbol += Symbol->NumberOfAuxSymbols;
  2561. i += Symbol->NumberOfAuxSymbols;
  2562. }
  2563. CompleteSymbolTable( mi );
  2564. if (g.SymOptions & SYMOPT_LOAD_LINES) {
  2565. AddLinesForCoff(mi, allSymbols, numberOfSymbols, LineNumbers);
  2566. }
  2567. return TRUE;
  2568. }
  2569. BOOL
  2570. LoadCodeViewSymbols(
  2571. HANDLE hProcess,
  2572. PMODULE_ENTRY mi,
  2573. PIMGHLP_DEBUG_DATA pIDD
  2574. )
  2575. {
  2576. DWORD i, j;
  2577. PPROCESS_ENTRY pe;
  2578. OMFSignature *omfSig;
  2579. OMFDirHeader *omfDirHdr;
  2580. OMFDirEntry *omfDirEntry;
  2581. OMFSymHash *omfSymHash;
  2582. DATASYM32 *dataSym;
  2583. DWORD64 addr;
  2584. DWORD CvSymbols;
  2585. DWORD NameSize;
  2586. SYMBOL_ENTRY SymEntry;
  2587. pe = FindProcessEntry( hProcess );
  2588. if (!pe) {
  2589. return FALSE;
  2590. }
  2591. pprint(pe, "LoadCodeViewSymbols:\n"
  2592. " hProcess %p\n"
  2593. " mi %p\n"
  2594. " pCvData %p\n"
  2595. " dwSize %x\n",
  2596. hProcess,
  2597. mi,
  2598. pIDD->pMappedCv,
  2599. pIDD->cMappedCv
  2600. );
  2601. omfSig = (OMFSignature*) pIDD->pMappedCv;
  2602. if ((*(DWORD *)(omfSig->Signature) != '80BN') &&
  2603. (*(DWORD *)(omfSig->Signature) != '90BN') &&
  2604. (*(DWORD *)(omfSig->Signature) != '11BN'))
  2605. {
  2606. if ((*(DWORD *)(omfSig->Signature) != '01BN') &&
  2607. (*(DWORD *)(omfSig->Signature) != 'SDSR'))
  2608. {
  2609. pprint(pe, "unrecognized OMF sig: %x\n", *(DWORD *)(omfSig->Signature));
  2610. }
  2611. return FALSE;
  2612. }
  2613. //
  2614. // count the number of actual symbols
  2615. //
  2616. omfDirHdr = (OMFDirHeader*) ((ULONG_PTR)omfSig + (DWORD)omfSig->filepos);
  2617. omfDirEntry = (OMFDirEntry*) ((ULONG_PTR)omfDirHdr + sizeof(OMFDirHeader));
  2618. NameSize = 0;
  2619. CvSymbols = 0;
  2620. for (i=0; i<omfDirHdr->cDir; i++,omfDirEntry++) {
  2621. LPSTR SymbolName;
  2622. UCHAR SymbolLen;
  2623. SYMBOL_ENTRY SymEntry;
  2624. if (omfDirEntry->SubSection == sstGlobalPub) {
  2625. omfSymHash = (OMFSymHash*) ((ULONG_PTR)omfSig + omfDirEntry->lfo);
  2626. dataSym = (DATASYM32*) ((ULONG_PTR)omfSig + omfDirEntry->lfo + sizeof(OMFSymHash));
  2627. for (j=sizeof(OMFSymHash); j<=omfSymHash->cbSymbol; ) {
  2628. addr = 0;
  2629. cvExtractSymbolInfo(mi, (PCHAR) dataSym, &SymEntry, FALSE);
  2630. if (SymEntry.Segment && (SymEntry.Segment <= mi->OriginalNumSections))
  2631. {
  2632. addr = mi->OriginalSectionHdrs[SymEntry.Segment-1].VirtualAddress + SymEntry.Offset + mi->BaseOfDll;
  2633. SymbolName = SymEntry.Name;
  2634. SymbolLen = (UCHAR) SymEntry.NameLength;
  2635. if (SymbolName[0] == '?' &&
  2636. SymbolName[1] == '?' &&
  2637. SymbolName[2] == '_' &&
  2638. SymbolName[3] == 'C' )
  2639. {
  2640. //
  2641. // ignore strings
  2642. //
  2643. } else if (g.SymOptions & SYMOPT_UNDNAME) {
  2644. SymUnDNameInternal(mi->TmpSym.Name,
  2645. TMP_SYM_LEN,
  2646. SymbolName,
  2647. SymbolLen,
  2648. mi->MachineType,
  2649. TRUE);
  2650. NameSize += strlen(mi->TmpSym.Name);
  2651. CvSymbols += 1;
  2652. } else {
  2653. CvSymbols += 1;
  2654. NameSize += SymbolLen + 1;
  2655. }
  2656. }
  2657. j += dataSym->reclen + 2;
  2658. dataSym = (DATASYM32*) ((ULONG_PTR)dataSym + dataSym->reclen + 2);
  2659. }
  2660. break;
  2661. }
  2662. }
  2663. //
  2664. // allocate the symbol table
  2665. //
  2666. if (!CreateSymbolTable( mi, CvSymbols, SymCv, NameSize )) {
  2667. pprint(pe, "CreateSymbolTable failed\n");
  2668. return FALSE;
  2669. }
  2670. //
  2671. // populate the symbol table
  2672. //
  2673. omfDirHdr = (OMFDirHeader*) ((ULONG_PTR)omfSig + (DWORD)omfSig->filepos);
  2674. omfDirEntry = (OMFDirEntry*) ((ULONG_PTR)omfDirHdr + sizeof(OMFDirHeader));
  2675. for (i=0; i<omfDirHdr->cDir; i++,omfDirEntry++) {
  2676. LPSTR SymbolName;
  2677. if (omfDirEntry->SubSection == sstGlobalPub) {
  2678. omfSymHash = (OMFSymHash*) ((ULONG_PTR)omfSig + omfDirEntry->lfo);
  2679. dataSym = (DATASYM32*) ((ULONG_PTR)omfSig + omfDirEntry->lfo + sizeof(OMFSymHash));
  2680. for (j=sizeof(OMFSymHash); j<=omfSymHash->cbSymbol; ) {
  2681. addr = 0;
  2682. cvExtractSymbolInfo(mi, (PCHAR) dataSym, &SymEntry, FALSE);
  2683. if (SymEntry.Segment && (SymEntry.Segment <= mi->OriginalNumSections))
  2684. {
  2685. addr = mi->OriginalSectionHdrs[SymEntry.Segment-1].VirtualAddress + SymEntry.Offset + mi->BaseOfDll;
  2686. SymbolName = SymEntry.Name;
  2687. if (SymbolName[0] == '?' &&
  2688. SymbolName[1] == '?' &&
  2689. SymbolName[2] == '_' &&
  2690. SymbolName[3] == 'C' )
  2691. {
  2692. //
  2693. // ignore strings
  2694. //
  2695. } else if (g.SymOptions & SYMOPT_UNDNAME) {
  2696. SymUnDNameInternal(mi->TmpSym.Name,
  2697. TMP_SYM_LEN,
  2698. SymbolName,
  2699. SymEntry.NameLength,
  2700. mi->MachineType,
  2701. TRUE);
  2702. AllocSym( mi, addr, (LPSTR) mi->TmpSym.Name);
  2703. } else {
  2704. mi->TmpSym.NameLength = SymEntry.NameLength;
  2705. memcpy( mi->TmpSym.Name, SymbolName, mi->TmpSym.NameLength );
  2706. mi->TmpSym.Name[mi->TmpSym.NameLength] = 0;
  2707. AllocSym( mi, addr, mi->TmpSym.Name);
  2708. }
  2709. }
  2710. j += dataSym->reclen + 2;
  2711. dataSym = (DATASYM32*) ((ULONG_PTR)dataSym + dataSym->reclen + 2);
  2712. }
  2713. break;
  2714. }
  2715. else if (omfDirEntry->SubSection == sstSrcModule &&
  2716. (g.SymOptions & SYMOPT_LOAD_LINES)) {
  2717. AddLinesForOmfSourceModule(mi,
  2718. (PUCHAR)(pIDD->pMappedCv)+omfDirEntry->lfo,
  2719. (OMFSourceModule *)
  2720. ((PCHAR)(pIDD->pMappedCv)+omfDirEntry->lfo),
  2721. NULL);
  2722. }
  2723. }
  2724. CompleteSymbolTable( mi );
  2725. return TRUE;
  2726. }
  2727. VOID
  2728. GetSymName(
  2729. PIMAGE_SYMBOL Symbol,
  2730. PUCHAR StringTable,
  2731. LPSTR s,
  2732. DWORD size
  2733. )
  2734. {
  2735. DWORD i;
  2736. if (Symbol->n_zeroes) {
  2737. for (i=0; i<8; i++) {
  2738. if ((Symbol->n_name[i]>0x1f) && (Symbol->n_name[i]<0x7f)) {
  2739. *s++ = Symbol->n_name[i];
  2740. }
  2741. }
  2742. *s = 0;
  2743. }
  2744. else {
  2745. strncpy( s, (char *) &StringTable[Symbol->n_offset], size );
  2746. }
  2747. }
  2748. VOID
  2749. ProcessOmapForModule(
  2750. PMODULE_ENTRY mi,
  2751. PIMGHLP_DEBUG_DATA pIDD
  2752. )
  2753. {
  2754. PSYMBOL_ENTRY sym;
  2755. PSYMBOL_ENTRY symN;
  2756. DWORD i;
  2757. ULONG64 addr;
  2758. DWORD bias;
  2759. PFPO_DATA fpo;
  2760. if (pIDD->cOmapTo && pIDD->pOmapTo) {
  2761. if (pIDD->fOmapToMapped || pIDD->dia) {
  2762. mi->pOmapTo = (POMAP)MemAlloc(pIDD->cOmapTo * sizeof(OMAP));
  2763. if (mi->pOmapTo) {
  2764. CopyMemory(
  2765. mi->pOmapTo,
  2766. pIDD->pOmapTo,
  2767. pIDD->cOmapTo * sizeof(OMAP)
  2768. );
  2769. }
  2770. } else {
  2771. mi->pOmapTo = pIDD->pOmapTo;
  2772. }
  2773. mi->cOmapTo = pIDD->cOmapTo;
  2774. }
  2775. if (pIDD->cOmapFrom && pIDD->pOmapFrom) {
  2776. if (pIDD->fOmapFromMapped) {
  2777. mi->pOmapFrom = (POMAP)MemAlloc(pIDD->cOmapFrom * sizeof(OMAP));
  2778. if (mi->pOmapFrom) {
  2779. CopyMemory(
  2780. mi->pOmapFrom,
  2781. pIDD->pOmapFrom,
  2782. pIDD->cOmapFrom * sizeof(OMAP)
  2783. );
  2784. }
  2785. } else {
  2786. mi->pOmapFrom = pIDD->pOmapFrom;
  2787. }
  2788. mi->cOmapFrom = pIDD->cOmapFrom;
  2789. }
  2790. if (mi->pFpoData) {
  2791. //
  2792. // if this module is BBT-optimized, then build
  2793. // another fpo table with omap transalation
  2794. //
  2795. mi->pFpoDataOmap = (PFPO_DATA)VirtualAlloc(
  2796. NULL,
  2797. sizeof(FPO_DATA) * mi->dwEntries,
  2798. MEM_COMMIT,
  2799. PAGE_READWRITE
  2800. );
  2801. if (mi->pFpoDataOmap) {
  2802. CopyMemory(
  2803. mi->pFpoDataOmap,
  2804. pIDD->pFpo,
  2805. sizeof(FPO_DATA) * mi->dwEntries
  2806. );
  2807. for (i = 0, fpo = mi->pFpoDataOmap;
  2808. i < mi->dwEntries;
  2809. i++, fpo++) {
  2810. addr = ConvertOmapFromSrc(mi,
  2811. mi->BaseOfDll + fpo->ulOffStart,
  2812. &bias);
  2813. if (addr)
  2814. fpo->ulOffStart = (ULONG)(addr - mi->BaseOfDll) + bias;
  2815. }
  2816. VirtualProtect(
  2817. mi->pFpoData,
  2818. sizeof(FPO_DATA) * mi->dwEntries,
  2819. PAGE_READONLY,
  2820. &i
  2821. );
  2822. }
  2823. }
  2824. if (!mi->pOmapFrom ||
  2825. !mi->symbolTable ||
  2826. ((mi->SymType != SymCoff) && (mi->SymType != SymCv))
  2827. )
  2828. {
  2829. return;
  2830. }
  2831. for (i=0; i<mi->numsyms; i++) {
  2832. ProcessOmapSymbol( mi, &mi->symbolTable[i] );
  2833. }
  2834. CompleteSymbolTable( mi );
  2835. }
  2836. BOOL
  2837. ProcessOmapSymbol(
  2838. PMODULE_ENTRY mi,
  2839. PSYMBOL_ENTRY sym
  2840. )
  2841. {
  2842. DWORD bias;
  2843. DWORD64 OptimizedSymAddr;
  2844. DWORD rvaSym;
  2845. POMAPLIST pomaplistHead;
  2846. DWORD64 SymbolValue;
  2847. DWORD64 OrgSymAddr;
  2848. POMAPLIST pomaplistNew;
  2849. POMAPLIST pomaplistPrev;
  2850. POMAPLIST pomaplistCur;
  2851. POMAPLIST pomaplistNext;
  2852. DWORD rva;
  2853. DWORD rvaTo;
  2854. DWORD cb;
  2855. DWORD end;
  2856. DWORD rvaToNext;
  2857. LPSTR NewSymName;
  2858. CHAR Suffix[32];
  2859. DWORD64 addrNew;
  2860. POMAP pomap;
  2861. PSYMBOL_ENTRY symOmap;
  2862. if ((sym->Flags & SYMF_OMAP_GENERATED) || (sym->Flags & SYMF_OMAP_MODIFIED)) {
  2863. return FALSE;
  2864. }
  2865. OrgSymAddr = SymbolValue = sym->Address;
  2866. OptimizedSymAddr = ConvertOmapFromSrc( mi, SymbolValue, &bias );
  2867. if (OptimizedSymAddr == 0) {
  2868. //
  2869. // No equivalent address
  2870. //
  2871. sym->Address = 0;
  2872. return FALSE;
  2873. }
  2874. //
  2875. // We have successfully converted
  2876. //
  2877. sym->Address = OptimizedSymAddr + bias;
  2878. rvaSym = (ULONG)(SymbolValue - mi->BaseOfDll);
  2879. SymbolValue = sym->Address;
  2880. pomap = GetOmapFromSrcEntry( mi, OrgSymAddr );
  2881. if (!pomap) {
  2882. goto exit;
  2883. }
  2884. pomaplistHead = NULL;
  2885. //
  2886. // Look for all OMAP entries belonging to SymbolEntry
  2887. //
  2888. end = (ULONG)(OrgSymAddr - mi->BaseOfDll + sym->Size);
  2889. while (pomap && (pomap->rva < end)) {
  2890. if (pomap->rvaTo == 0) {
  2891. pomap++;
  2892. continue;
  2893. }
  2894. //
  2895. // Allocate and initialize a new entry
  2896. //
  2897. pomaplistNew = (POMAPLIST) MemAlloc( sizeof(OMAPLIST) );
  2898. if (!pomaplistNew) {
  2899. return FALSE;
  2900. }
  2901. pomaplistNew->omap = *pomap;
  2902. pomaplistNew->cb = pomap[1].rva - pomap->rva;
  2903. pomaplistPrev = NULL;
  2904. pomaplistCur = pomaplistHead;
  2905. while (pomaplistCur != NULL) {
  2906. if (pomap->rvaTo < pomaplistCur->omap.rvaTo) {
  2907. //
  2908. // Insert between Prev and Cur
  2909. //
  2910. break;
  2911. }
  2912. pomaplistPrev = pomaplistCur;
  2913. pomaplistCur = pomaplistCur->next;
  2914. }
  2915. if (pomaplistPrev == NULL) {
  2916. //
  2917. // Insert in head position
  2918. //
  2919. pomaplistHead = pomaplistNew;
  2920. } else {
  2921. pomaplistPrev->next = pomaplistNew;
  2922. }
  2923. pomaplistNew->next = pomaplistCur;
  2924. pomap++;
  2925. }
  2926. if (pomaplistHead == NULL) {
  2927. goto exit;
  2928. }
  2929. pomaplistCur = pomaplistHead;
  2930. pomaplistNext = pomaplistHead->next;
  2931. //
  2932. // we do have a list
  2933. //
  2934. while (pomaplistNext != NULL) {
  2935. rva = pomaplistCur->omap.rva;
  2936. rvaTo = pomaplistCur->omap.rvaTo;
  2937. cb = pomaplistCur->cb;
  2938. rvaToNext = pomaplistNext->omap.rvaTo;
  2939. if (rvaToNext == sym->Address - mi->BaseOfDll) {
  2940. //
  2941. // Already inserted above
  2942. //
  2943. } else if (rvaToNext < (rvaTo + cb + 8)) {
  2944. //
  2945. // Adjacent to previous range
  2946. //
  2947. } else {
  2948. addrNew = mi->BaseOfDll + rvaToNext;
  2949. Suffix[0] = '_';
  2950. _ltoa( pomaplistNext->omap.rva - rvaSym, &Suffix[1], 10 );
  2951. memcpy( mi->TmpSym.Name, sym->Name, sym->NameLength );
  2952. strncpy( &mi->TmpSym.Name[sym->NameLength], Suffix, strlen(Suffix) + 1 );
  2953. symOmap = AllocSym( mi, addrNew, mi->TmpSym.Name);
  2954. if (symOmap) {
  2955. symOmap->Flags |= SYMF_OMAP_GENERATED;
  2956. }
  2957. }
  2958. MemFree(pomaplistCur);
  2959. pomaplistCur = pomaplistNext;
  2960. pomaplistNext = pomaplistNext->next;
  2961. }
  2962. MemFree(pomaplistCur);
  2963. exit:
  2964. if (sym->Address != OrgSymAddr) {
  2965. sym->Flags |= SYMF_OMAP_MODIFIED;
  2966. }
  2967. return TRUE;
  2968. }
  2969. DWORD64
  2970. ConvertOmapFromSrc(
  2971. PMODULE_ENTRY mi,
  2972. DWORD64 addr,
  2973. LPDWORD bias
  2974. )
  2975. {
  2976. DWORD rva;
  2977. DWORD comap;
  2978. POMAP pomapLow;
  2979. POMAP pomapHigh;
  2980. DWORD comapHalf;
  2981. POMAP pomapMid;
  2982. *bias = 0;
  2983. if (!mi->pOmapFrom) {
  2984. return addr;
  2985. }
  2986. rva = (DWORD)(addr - mi->BaseOfDll);
  2987. comap = mi->cOmapFrom;
  2988. pomapLow = mi->pOmapFrom;
  2989. pomapHigh = pomapLow + comap;
  2990. while (pomapLow < pomapHigh) {
  2991. comapHalf = comap / 2;
  2992. pomapMid = pomapLow + ((comap & 1) ? comapHalf : (comapHalf - 1));
  2993. if (rva == pomapMid->rva) {
  2994. if (pomapMid->rvaTo) {
  2995. return mi->BaseOfDll + pomapMid->rvaTo;
  2996. } else {
  2997. return(0); // No need adding the base. This address was discarded...
  2998. }
  2999. }
  3000. if (rva < pomapMid->rva) {
  3001. pomapHigh = pomapMid;
  3002. comap = (comap & 1) ? comapHalf : (comapHalf - 1);
  3003. } else {
  3004. pomapLow = pomapMid + 1;
  3005. comap = comapHalf;
  3006. }
  3007. }
  3008. //
  3009. // If no exact match, pomapLow points to the next higher address
  3010. //
  3011. if (pomapLow == mi->pOmapFrom) {
  3012. //
  3013. // This address was not found
  3014. //
  3015. return 0;
  3016. }
  3017. if (pomapLow[-1].rvaTo == 0) {
  3018. //
  3019. // This address is in a discarded block
  3020. //
  3021. return 0;
  3022. }
  3023. //
  3024. // Return the closest address plus the bias
  3025. //
  3026. *bias = rva - pomapLow[-1].rva;
  3027. return mi->BaseOfDll + pomapLow[-1].rvaTo;
  3028. }
  3029. DWORD64
  3030. ConvertOmapToSrc(
  3031. PMODULE_ENTRY mi,
  3032. DWORD64 addr,
  3033. LPDWORD bias,
  3034. BOOL fBackup
  3035. )
  3036. {
  3037. DWORD rva;
  3038. DWORD comap;
  3039. POMAP pomapLow;
  3040. POMAP pomapHigh;
  3041. DWORD comapHalf;
  3042. POMAP pomapMid;
  3043. *bias = 0;
  3044. if (!mi->pOmapTo) {
  3045. return addr;
  3046. }
  3047. rva = (DWORD)(addr - mi->BaseOfDll);
  3048. comap = mi->cOmapTo;
  3049. pomapLow = mi->pOmapTo;
  3050. pomapHigh = pomapLow + comap;
  3051. while (pomapLow < pomapHigh) {
  3052. comapHalf = comap / 2;
  3053. pomapMid = pomapLow + ((comap & 1) ? comapHalf : (comapHalf - 1));
  3054. if (rva == pomapMid->rva) {
  3055. if (pomapMid->rvaTo == 0) {
  3056. //
  3057. // We may be at the start of an inserted branch instruction
  3058. //
  3059. if (fBackup) {
  3060. //
  3061. // Return information about the next lower address
  3062. //
  3063. rva--;
  3064. pomapLow = pomapMid;
  3065. break;
  3066. }
  3067. return 0;
  3068. }
  3069. return mi->BaseOfDll + pomapMid->rvaTo;
  3070. }
  3071. if (rva < pomapMid->rva) {
  3072. pomapHigh = pomapMid;
  3073. comap = (comap & 1) ? comapHalf : (comapHalf - 1);
  3074. } else {
  3075. pomapLow = pomapMid + 1;
  3076. comap = comapHalf;
  3077. }
  3078. }
  3079. //
  3080. // If no exact match, pomapLow points to the next higher address
  3081. //
  3082. if (pomapLow == mi->pOmapTo) {
  3083. //
  3084. // This address was not found
  3085. //
  3086. return 0;
  3087. }
  3088. // find the previous valid item in the omap
  3089. do {
  3090. pomapLow--;
  3091. if (pomapLow->rvaTo)
  3092. break;
  3093. } while (pomapLow > mi->pOmapTo);
  3094. // should never occur
  3095. // assert(pomapLow->rvaTo);
  3096. if (pomapLow->rvaTo == 0) {
  3097. return 0;
  3098. }
  3099. //
  3100. // Return the new address plus the bias
  3101. //
  3102. *bias = rva - pomapLow->rva;
  3103. return mi->BaseOfDll + pomapLow->rvaTo;
  3104. }
  3105. POMAP
  3106. GetOmapFromSrcEntry(
  3107. PMODULE_ENTRY mi,
  3108. DWORD64 addr
  3109. )
  3110. {
  3111. DWORD rva;
  3112. DWORD comap;
  3113. POMAP pomapLow;
  3114. POMAP pomapHigh;
  3115. DWORD comapHalf;
  3116. POMAP pomapMid;
  3117. if (mi->pOmapFrom == NULL) {
  3118. return NULL;
  3119. }
  3120. rva = (DWORD)(addr - mi->BaseOfDll);
  3121. comap = mi->cOmapFrom;
  3122. pomapLow = mi->pOmapFrom;
  3123. pomapHigh = pomapLow + comap;
  3124. while (pomapLow < pomapHigh) {
  3125. comapHalf = comap / 2;
  3126. pomapMid = pomapLow + ((comap & 1) ? comapHalf : (comapHalf - 1));
  3127. if (rva == pomapMid->rva) {
  3128. return pomapMid;
  3129. }
  3130. if (rva < pomapMid->rva) {
  3131. pomapHigh = pomapMid;
  3132. comap = (comap & 1) ? comapHalf : (comapHalf - 1);
  3133. } else {
  3134. pomapLow = pomapMid + 1;
  3135. comap = comapHalf;
  3136. }
  3137. }
  3138. return NULL;
  3139. }
  3140. VOID
  3141. DumpOmapForModule(
  3142. PMODULE_ENTRY mi
  3143. )
  3144. {
  3145. POMAP pomap;
  3146. DWORD i;
  3147. i = sizeof(ULONG_PTR);
  3148. i = sizeof(DWORD);
  3149. if (!mi->pOmapFrom)
  3150. return;
  3151. dprint("\nOMAP FROM:\n");
  3152. for(i = 0, pomap = mi->pOmapFrom;
  3153. i < 100; // mi->cOmapFrom;
  3154. i++, pomap++)
  3155. {
  3156. dprint("%8x %8x\n", pomap->rva, pomap->rvaTo);
  3157. }
  3158. if (!mi->pOmapTo)
  3159. return;
  3160. dprint("\nOMAP TO:\n");
  3161. for(i = 0, pomap = mi->pOmapTo;
  3162. i < 100; // mi->cOmapTo;
  3163. i++, pomap++)
  3164. {
  3165. dprint("%8x %8x\n", pomap->rva, pomap->rvaTo);
  3166. }
  3167. }
  3168. LPSTR
  3169. StringDup(
  3170. LPSTR str
  3171. )
  3172. {
  3173. LPSTR ds = (LPSTR) MemAlloc( strlen(str) + 1 );
  3174. if (ds) {
  3175. strcpy( ds, str );
  3176. }
  3177. return ds;
  3178. }
  3179. BOOL
  3180. InternalGetModule(
  3181. HANDLE hProcess,
  3182. LPSTR ModuleName,
  3183. DWORD64 ImageBase,
  3184. DWORD ImageSize,
  3185. PVOID Context
  3186. )
  3187. {
  3188. InternalLoadModule(
  3189. hProcess,
  3190. ModuleName,
  3191. NULL,
  3192. ImageBase,
  3193. ImageSize,
  3194. NULL,
  3195. 0,
  3196. NULL
  3197. );
  3198. return TRUE;
  3199. }
  3200. BOOL
  3201. LoadedModuleEnumerator(
  3202. HANDLE hProcess,
  3203. LPSTR ModuleName,
  3204. DWORD64 ImageBase,
  3205. DWORD ImageSize,
  3206. PLOADED_MODULE lm
  3207. )
  3208. {
  3209. if (lm->EnumLoadedModulesCallback64) {
  3210. return lm->EnumLoadedModulesCallback64( ModuleName, ImageBase, ImageSize, lm->Context );
  3211. } else {
  3212. return lm->EnumLoadedModulesCallback32( ModuleName, (DWORD)ImageBase, ImageSize, lm->Context );
  3213. }
  3214. }
  3215. BOOL
  3216. ToggleFailCriticalErrors(
  3217. BOOL reset
  3218. )
  3219. {
  3220. static UINT oldmode = 0;
  3221. if (!(g.SymOptions & SYMOPT_FAIL_CRITICAL_ERRORS))
  3222. return FALSE;
  3223. if (reset)
  3224. SetErrorMode(oldmode);
  3225. else
  3226. oldmode = SetErrorMode(SEM_FAILCRITICALERRORS);
  3227. return TRUE;
  3228. }
  3229. DWORD
  3230. fnGetFileAttributes(
  3231. LPCTSTR lpFileName
  3232. )
  3233. {
  3234. DWORD rc;
  3235. SetCriticalErrorMode();
  3236. rc = GetFileAttributes(lpFileName);
  3237. ResetCriticalErrorMode();
  3238. return rc;
  3239. }
  3240. LPSTR
  3241. SymUnDNameInternal(
  3242. LPSTR UnDecName,
  3243. DWORD UnDecNameLength,
  3244. LPSTR DecName,
  3245. DWORD DecNameLength,
  3246. DWORD MachineType,
  3247. BOOL IsPublic
  3248. )
  3249. {
  3250. LPSTR p;
  3251. ULONG Suffix;
  3252. ULONG i;
  3253. LPSTR TmpDecName;
  3254. UnDecName[0] = 0;
  3255. if (DecName[0] == '?' || !strncmp(DecName, ".?", 2) || !strncmp(DecName, "..?", 3)) {
  3256. __try {
  3257. if (DecName[0] == '.') {
  3258. if (DecName[1] == '.') {
  3259. Suffix = 2;
  3260. UnDecName[0] = '.';
  3261. UnDecName[1] = '.';
  3262. } else { // DecName[1] = '?'
  3263. Suffix = 1;
  3264. UnDecName[0] = '.';
  3265. }
  3266. } else { // DecName[0] = '?'
  3267. Suffix = 0;
  3268. }
  3269. TmpDecName = (LPSTR)MemAlloc( 4096 );
  3270. if (!TmpDecName) {
  3271. strncat( UnDecName, DecName, min(DecNameLength,UnDecNameLength) );
  3272. return UnDecName;
  3273. }
  3274. TmpDecName[0] = 0;
  3275. strncat( TmpDecName, DecName+Suffix, DecNameLength );
  3276. if (UnDecorateSymbolName( TmpDecName,
  3277. UnDecName+Suffix,
  3278. UnDecNameLength-Suffix,
  3279. UNDNAME_NAME_ONLY ) == 0 ) {
  3280. strncat( UnDecName, DecName, min(DecNameLength,UnDecNameLength) );
  3281. }
  3282. MemFree( TmpDecName );
  3283. } __except (EXCEPTION_EXECUTE_HANDLER) {
  3284. strncat( UnDecName, DecName, min(DecNameLength,UnDecNameLength) );
  3285. }
  3286. } else {
  3287. __try {
  3288. if ((IsPublic && (DecName[0] == '_' || DecName[0] == '.'))
  3289. || DecName[0] == '@') {
  3290. DecName += 1;
  3291. DecNameLength -= 1;
  3292. }
  3293. p = 0;
  3294. for (i = 0; i < DecNameLength; i++) {
  3295. if (DecName [i] == '@') {
  3296. p = &DecName [i];
  3297. break;
  3298. }
  3299. }
  3300. if (p) {
  3301. i = (int)(p - DecName);
  3302. } else {
  3303. i = min(DecNameLength,UnDecNameLength);
  3304. }
  3305. strncat( UnDecName, DecName, i );
  3306. } __except (EXCEPTION_EXECUTE_HANDLER) {
  3307. strncat( UnDecName, DecName, min(DecNameLength,UnDecNameLength) );
  3308. }
  3309. }
  3310. if (g.SymOptions & SYMOPT_NO_CPP) {
  3311. while (p = strstr( UnDecName, "::" )) {
  3312. p[0] = '_';
  3313. p[1] = '_';
  3314. }
  3315. }
  3316. return UnDecName;
  3317. }
  3318. BOOL
  3319. MatchSymName(
  3320. LPSTR matchName,
  3321. LPSTR symName
  3322. )
  3323. {
  3324. assert(matchName && symName);
  3325. if (!*matchName || !*symName)
  3326. return FALSE;
  3327. if (g.SymOptions & SYMOPT_CASE_INSENSITIVE) {
  3328. if (!_strnicmp(matchName, symName, MAX_SYM_NAME))
  3329. return TRUE;
  3330. } else {
  3331. if (!strncmp(matchName, symName, MAX_SYM_NAME))
  3332. return TRUE;
  3333. }
  3334. return FALSE;
  3335. }
  3336. PIMAGEHLP_SYMBOL
  3337. symcpy32(
  3338. PIMAGEHLP_SYMBOL External,
  3339. PSYMBOL_ENTRY Internal
  3340. )
  3341. {
  3342. External->Address = (ULONG)Internal->Address;
  3343. External->Size = Internal->Size;
  3344. External->Flags = Internal->Flags;
  3345. External->Name[0] = 0;
  3346. strncat( External->Name, Internal->Name, External->MaxNameLength );
  3347. return External;
  3348. }
  3349. PIMAGEHLP_SYMBOL64
  3350. symcpy64(
  3351. PIMAGEHLP_SYMBOL64 External,
  3352. PSYMBOL_ENTRY Internal
  3353. )
  3354. {
  3355. External->Address = Internal->Address;
  3356. External->Size = Internal->Size;
  3357. External->Flags = Internal->Flags;
  3358. External->Name[0] = 0;
  3359. strncat( External->Name, Internal->Name, External->MaxNameLength );
  3360. return External;
  3361. }
  3362. BOOL
  3363. SympConvertSymbol64To32(
  3364. PIMAGEHLP_SYMBOL64 Symbol64,
  3365. PIMAGEHLP_SYMBOL Symbol32
  3366. )
  3367. {
  3368. Symbol32->Address = (DWORD)Symbol64->Address;
  3369. Symbol32->Size = Symbol64->Size;
  3370. Symbol32->Flags = Symbol64->Flags;
  3371. Symbol32->MaxNameLength = Symbol64->MaxNameLength;
  3372. Symbol32->Name[0] = 0;
  3373. strncat( Symbol32->Name, Symbol64->Name, Symbol32->MaxNameLength );
  3374. return (Symbol64->Address >> 32) == 0;
  3375. }
  3376. BOOL
  3377. SympConvertSymbol32To64(
  3378. PIMAGEHLP_SYMBOL Symbol32,
  3379. PIMAGEHLP_SYMBOL64 Symbol64
  3380. )
  3381. {
  3382. Symbol64->Address = Symbol32->Address;
  3383. Symbol64->Size = Symbol32->Size;
  3384. Symbol64->Flags = Symbol32->Flags;
  3385. Symbol64->MaxNameLength = Symbol32->MaxNameLength;
  3386. Symbol64->Name[0] = 0;
  3387. strncat( Symbol64->Name, Symbol32->Name, Symbol64->MaxNameLength );
  3388. return TRUE;
  3389. }
  3390. BOOL
  3391. SympConvertLine64To32(
  3392. PIMAGEHLP_LINE64 Line64,
  3393. PIMAGEHLP_LINE Line32
  3394. )
  3395. {
  3396. Line32->Key = Line64->Key;
  3397. Line32->LineNumber = Line64->LineNumber;
  3398. Line32->FileName = Line64->FileName;
  3399. Line32->Address = (DWORD)Line64->Address;
  3400. return (Line64->Address >> 32) == 0;
  3401. }
  3402. BOOL
  3403. SympConvertLine32To64(
  3404. PIMAGEHLP_LINE Line32,
  3405. PIMAGEHLP_LINE64 Line64
  3406. )
  3407. {
  3408. Line64->Key = Line32->Key;
  3409. Line64->LineNumber = Line32->LineNumber;
  3410. Line64->FileName = Line32->FileName;
  3411. Line64->Address = Line32->Address;
  3412. return TRUE;
  3413. }
  3414. BOOL
  3415. __stdcall
  3416. ReadInProcMemory(
  3417. HANDLE hProcess,
  3418. DWORD64 addr,
  3419. PVOID buf,
  3420. DWORD bytes,
  3421. DWORD *bytesread
  3422. )
  3423. {
  3424. DWORD rc;
  3425. PPROCESS_ENTRY pe;
  3426. IMAGEHLP_CBA_READ_MEMORY rm;
  3427. rm.addr = addr;
  3428. rm.buf = buf;
  3429. rm.bytes = bytes;
  3430. rm.bytesread = bytesread;
  3431. rc = FALSE;
  3432. __try {
  3433. pe = FindProcessEntry(hProcess);
  3434. if (!pe) {
  3435. SetLastError( ERROR_INVALID_HANDLE );
  3436. return FALSE;
  3437. }
  3438. if (pe->pCallbackFunction32) {
  3439. rc = pe->pCallbackFunction32(pe->hProcess,
  3440. CBA_READ_MEMORY,
  3441. (PVOID)&rm,
  3442. (PVOID)pe->CallbackUserContext);
  3443. } else if (pe->pCallbackFunction64) {
  3444. rc = pe->pCallbackFunction64(pe->hProcess,
  3445. CBA_READ_MEMORY,
  3446. (ULONG64)&rm,
  3447. pe->CallbackUserContext);
  3448. } else {
  3449. SIZE_T RealBytesRead=0;
  3450. rc = ReadProcessMemory(hProcess,
  3451. (LPVOID)(ULONG_PTR)addr,
  3452. buf,
  3453. bytes,
  3454. &RealBytesRead);
  3455. *bytesread = (DWORD)RealBytesRead;
  3456. }
  3457. } __except (EXCEPTION_EXECUTE_HANDLER) {
  3458. rc = FALSE;
  3459. }
  3460. return (rc != FALSE);
  3461. }
  3462. DWORD64
  3463. miGetModuleBase(
  3464. HANDLE hProcess,
  3465. DWORD64 Address
  3466. )
  3467. {
  3468. IMAGEHLP_MODULE64 ModuleInfo = {0};
  3469. ModuleInfo.SizeOfStruct = sizeof(ModuleInfo);
  3470. if (SymGetModuleInfo64(hProcess, Address, &ModuleInfo)) {
  3471. return ModuleInfo.BaseOfImage;
  3472. } else {
  3473. return 0;
  3474. }
  3475. }
  3476. BOOL
  3477. GetPData(
  3478. HANDLE hp,
  3479. PMODULE_ENTRY mi
  3480. )
  3481. {
  3482. BOOL status;
  3483. ULONG cb;
  3484. PCHAR pc;
  3485. BOOL fROM = FALSE;
  3486. IMAGE_DOS_HEADER DosHeader;
  3487. IMAGE_NT_HEADERS ImageNtHeaders;
  3488. PIMAGE_FILE_HEADER ImageFileHdr;
  3489. PIMAGE_OPTIONAL_HEADER ImageOptionalHdr;
  3490. PIMAGE_OPTIONAL_HEADER32 OptionalHeader32 = NULL;
  3491. PIMAGE_OPTIONAL_HEADER64 OptionalHeader64 = NULL;
  3492. ULONG feCount = 0;
  3493. ULONG i;
  3494. HANDLE fh = 0;
  3495. PCHAR base = NULL;
  3496. USHORT filetype;
  3497. PIMAGE_SEPARATE_DEBUG_HEADER sdh;
  3498. PIMAGE_DOS_HEADER dh;
  3499. PIMAGE_NT_HEADERS inth;
  3500. PIMAGE_OPTIONAL_HEADER32 ioh32;
  3501. PIMAGE_OPTIONAL_HEADER64 ioh64;
  3502. ULONG cdd;
  3503. PCHAR p;
  3504. PIMAGE_DEBUG_DIRECTORY dd;
  3505. ULONG cexp = 0;
  3506. ULONG tsize;
  3507. ULONG csize = 0;
  3508. // if the pdata is already loaded, return
  3509. if (mi->pExceptionData)
  3510. return TRUE;
  3511. if (!LoadSymbols(hp, mi, 0))
  3512. return FALSE;
  3513. // try to get pdata from dia
  3514. if (mi->dia) {
  3515. if ((mi->pPData) && (mi->dsExceptions == dsDia))
  3516. goto dia;
  3517. if (diaGetPData(mi)) {
  3518. p = (PCHAR)mi->pPData;
  3519. csize = mi->cbPData;
  3520. goto dia;
  3521. }
  3522. }
  3523. if (!mi->dsExceptions)
  3524. return FALSE;
  3525. // open the file and get the file type
  3526. SetCriticalErrorMode();
  3527. fh = CreateFile(mi->LoadedImageName,
  3528. GENERIC_READ,
  3529. g.OSVerInfo.dwPlatformId == VER_PLATFORM_WIN32_NT ? (FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE) : (FILE_SHARE_READ | FILE_SHARE_WRITE),
  3530. NULL,
  3531. OPEN_EXISTING,
  3532. 0,
  3533. NULL
  3534. );
  3535. ResetCriticalErrorMode();
  3536. if (fh == INVALID_HANDLE_VALUE)
  3537. return FALSE;
  3538. base = (PCHAR)MapItRO(fh);
  3539. if (!base)
  3540. goto cleanup;
  3541. p = base;
  3542. filetype = *(USHORT *)p;
  3543. if (filetype == IMAGE_DOS_SIGNATURE)
  3544. goto image;
  3545. if (filetype == IMAGE_SEPARATE_DEBUG_SIGNATURE)
  3546. goto dbg;
  3547. goto cleanup;
  3548. image:
  3549. // process disk-based image
  3550. dh = (PIMAGE_DOS_HEADER)p;
  3551. p += dh->e_lfanew;
  3552. inth = (PIMAGE_NT_HEADERS)p;
  3553. if (inth->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
  3554. ioh32 = (PIMAGE_OPTIONAL_HEADER32)&inth->OptionalHeader;
  3555. p = base + ioh32->DataDirectory[IMAGE_DIRECTORY_ENTRY_EXCEPTION].VirtualAddress;
  3556. csize = ioh32->DataDirectory[IMAGE_DIRECTORY_ENTRY_EXCEPTION].Size;
  3557. }
  3558. else if (inth->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
  3559. ioh64 = (PIMAGE_OPTIONAL_HEADER64)&inth->OptionalHeader;
  3560. p = base + ioh64->DataDirectory[IMAGE_DIRECTORY_ENTRY_EXCEPTION].VirtualAddress;
  3561. csize = ioh64->DataDirectory[IMAGE_DIRECTORY_ENTRY_EXCEPTION].Size;
  3562. }
  3563. dia:
  3564. if (!csize)
  3565. goto cleanup;
  3566. switch (mi->MachineType)
  3567. {
  3568. case IMAGE_FILE_MACHINE_ALPHA:
  3569. cexp = csize / sizeof(IMAGE_ALPHA_RUNTIME_FUNCTION_ENTRY);
  3570. break;
  3571. case IMAGE_FILE_MACHINE_ALPHA64:
  3572. cexp = csize / sizeof(IMAGE_ALPHA64_RUNTIME_FUNCTION_ENTRY);
  3573. break;
  3574. case IMAGE_FILE_MACHINE_IA64:
  3575. cexp = csize / sizeof(IMAGE_IA64_RUNTIME_FUNCTION_ENTRY);
  3576. break;
  3577. case IMAGE_FILE_MACHINE_AMD64:
  3578. cexp = csize / sizeof(_IMAGE_RUNTIME_FUNCTION_ENTRY);
  3579. break;
  3580. default:
  3581. goto cleanup;
  3582. }
  3583. goto table;
  3584. dbg:
  3585. // process dbg file
  3586. sdh = (PIMAGE_SEPARATE_DEBUG_HEADER)p;
  3587. cdd = sdh->DebugDirectorySize / sizeof(IMAGE_DEBUG_DIRECTORY);
  3588. p += sizeof(IMAGE_SEPARATE_DEBUG_HEADER) +
  3589. (sdh->NumberOfSections * sizeof(IMAGE_SECTION_HEADER)) +
  3590. sdh->ExportedNamesSize;
  3591. dd = (PIMAGE_DEBUG_DIRECTORY)p;
  3592. for (i = 0; i < cdd; i++, dd++) {
  3593. if (dd->Type == IMAGE_DEBUG_TYPE_EXCEPTION) {
  3594. p = base + dd->PointerToRawData;
  3595. cexp = dd->SizeOfData / sizeof(IMAGE_FUNCTION_ENTRY);
  3596. break;
  3597. }
  3598. }
  3599. table:
  3600. // parse the pdata into a table
  3601. if (!cexp)
  3602. goto cleanup;
  3603. tsize = cexp * sizeof(IMGHLP_RVA_FUNCTION_DATA);
  3604. mi->pExceptionData = (PIMGHLP_RVA_FUNCTION_DATA)VirtualAlloc( NULL, tsize, MEM_COMMIT, PAGE_READWRITE );
  3605. if (mi->pExceptionData) {
  3606. PIMGHLP_RVA_FUNCTION_DATA pIRFD = mi->pExceptionData;
  3607. switch (mi->MachineType) {
  3608. case IMAGE_FILE_MACHINE_ALPHA:
  3609. if (filetype == IMAGE_SEPARATE_DEBUG_SIGNATURE) {
  3610. // easy case. The addresses are already in rva format.
  3611. PIMAGE_FUNCTION_ENTRY pFE = (PIMAGE_FUNCTION_ENTRY)p;
  3612. for (i = 0; i < cexp; i++) {
  3613. pIRFD[i].rvaBeginAddress = pFE[i].StartingAddress;
  3614. pIRFD[i].rvaEndAddress = pFE[i].EndingAddress;
  3615. pIRFD[i].rvaPrologEndAddress = pFE[i].EndOfPrologue;
  3616. pIRFD[i].rvaExceptionHandler = 0;
  3617. pIRFD[i].rvaHandlerData = 0;
  3618. }
  3619. } else {
  3620. PIMAGE_ALPHA_RUNTIME_FUNCTION_ENTRY pRFE = (PIMAGE_ALPHA_RUNTIME_FUNCTION_ENTRY)p;
  3621. for (i = 0; i < cexp; i++) {
  3622. pIRFD[i].rvaBeginAddress = pRFE[i].BeginAddress - (ULONG)mi->BaseOfDll;
  3623. pIRFD[i].rvaEndAddress = pRFE[i].EndAddress - (ULONG)mi->BaseOfDll;
  3624. pIRFD[i].rvaPrologEndAddress = pRFE[i].PrologEndAddress - (ULONG)mi->BaseOfDll;
  3625. pIRFD[i].rvaExceptionHandler = pRFE[i].ExceptionHandler - (ULONG)mi->BaseOfDll;
  3626. pIRFD[i].rvaHandlerData = pRFE[i].HandlerData - (ULONG)mi->BaseOfDll;
  3627. }
  3628. }
  3629. break;
  3630. case IMAGE_FILE_MACHINE_ALPHA64:
  3631. {
  3632. PIMAGE_ALPHA64_RUNTIME_FUNCTION_ENTRY pRFE = (PIMAGE_ALPHA64_RUNTIME_FUNCTION_ENTRY)p;
  3633. for (i = 0; i < cexp; i++) {
  3634. pIRFD[i].rvaBeginAddress = (DWORD)(pRFE[i].BeginAddress - mi->BaseOfDll);
  3635. pIRFD[i].rvaEndAddress = (DWORD)(pRFE[i].EndAddress - mi->BaseOfDll);
  3636. pIRFD[i].rvaPrologEndAddress = (DWORD)(pRFE[i].PrologEndAddress - mi->BaseOfDll);
  3637. pIRFD[i].rvaExceptionHandler = (DWORD)(pRFE[i].ExceptionHandler - mi->BaseOfDll);
  3638. pIRFD[i].rvaHandlerData = (DWORD)(pRFE[i].HandlerData - mi->BaseOfDll);
  3639. }
  3640. }
  3641. break;
  3642. case IMAGE_FILE_MACHINE_IA64:
  3643. {
  3644. PIMAGE_IA64_RUNTIME_FUNCTION_ENTRY pRFE = (PIMAGE_IA64_RUNTIME_FUNCTION_ENTRY)p;
  3645. for (i = 0; i < cexp; i++) {
  3646. pIRFD[i].rvaBeginAddress = pRFE[i].BeginAddress;
  3647. pIRFD[i].rvaEndAddress = pRFE[i].EndAddress;
  3648. pIRFD[i].rvaPrologEndAddress = pRFE[i].UnwindInfoAddress;
  3649. pIRFD[i].rvaExceptionHandler = 0;
  3650. pIRFD[i].rvaHandlerData = 0;
  3651. }
  3652. }
  3653. break;
  3654. case IMAGE_FILE_MACHINE_AMD64:
  3655. {
  3656. _PIMAGE_RUNTIME_FUNCTION_ENTRY pRFE = (_PIMAGE_RUNTIME_FUNCTION_ENTRY)p;
  3657. for (i = 0; i < cexp; i++) {
  3658. pIRFD[i].rvaBeginAddress = pRFE[i].BeginAddress;
  3659. pIRFD[i].rvaEndAddress = pRFE[i].EndAddress;
  3660. pIRFD[i].rvaPrologEndAddress = pRFE[i].UnwindInfoAddress;
  3661. pIRFD[i].rvaExceptionHandler = 0;
  3662. pIRFD[i].rvaHandlerData = 0;
  3663. }
  3664. }
  3665. break;
  3666. default:
  3667. break;
  3668. }
  3669. VirtualProtect( mi->pExceptionData, tsize, PAGE_READONLY, &i );
  3670. mi->dwEntries = cexp;
  3671. }
  3672. cleanup:
  3673. if (mi->pPData) {
  3674. MemFree(mi->pPData);
  3675. mi->pPData = NULL;
  3676. }
  3677. if (base)
  3678. UnmapViewOfFile(base);
  3679. if (fh)
  3680. CloseHandle(fh);
  3681. return (cexp) ? TRUE : FALSE;
  3682. }
  3683. BOOL
  3684. GetXData(
  3685. HANDLE hp,
  3686. PMODULE_ENTRY mi
  3687. )
  3688. {
  3689. if (mi->pXData)
  3690. return TRUE;
  3691. if (LoadSymbols(hp, mi, 0) && !mi->pXData && mi->dia && !diaGetXData(mi))
  3692. return FALSE;
  3693. return (mi->pXData != NULL);
  3694. }
  3695. PVOID
  3696. GetXDataFromBase(
  3697. HANDLE hp,
  3698. DWORD64 base,
  3699. ULONG_PTR* size
  3700. )
  3701. {
  3702. PPROCESS_ENTRY pe;
  3703. PMODULE_ENTRY mi;
  3704. pe = FindProcessEntry(hp);
  3705. if (!pe) {
  3706. SetLastError(ERROR_INVALID_HANDLE);
  3707. return NULL;
  3708. }
  3709. mi = GetModuleForPC(pe, base, FALSE);
  3710. if (!mi) {
  3711. SetLastError(ERROR_MOD_NOT_FOUND);
  3712. return NULL;
  3713. }
  3714. if (!GetXData(hp, mi))
  3715. return NULL;
  3716. if (size) *size = mi->cbXData;
  3717. return mi->pXData;
  3718. }
  3719. PVOID
  3720. GetUnwindInfoFromSymbols(
  3721. HANDLE hProcess,
  3722. DWORD64 ModuleBase,
  3723. ULONG UnwindInfoAddress,
  3724. ULONG_PTR* Size
  3725. )
  3726. {
  3727. ULONG_PTR XDataSize;
  3728. PBYTE pXData = (PBYTE)GetXDataFromBase(hProcess, ModuleBase, &XDataSize);
  3729. if (!pXData)
  3730. return NULL;
  3731. DWORD DataBase = *(DWORD*)pXData;
  3732. pXData += sizeof(DWORD);
  3733. if (DataBase > UnwindInfoAddress)
  3734. return NULL;
  3735. ULONG_PTR Offset = UnwindInfoAddress - DataBase;
  3736. if (Offset >= XDataSize)
  3737. return NULL;
  3738. if (Size) *Size = XDataSize - Offset;
  3739. return pXData + Offset;
  3740. }