Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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