Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

4896 lines
160 KiB

4 years ago
  1. /** ntsym.c - NT debugger symbolic routines
  2. *
  3. * Copyright <C> 1990, Microsoft Corporation
  4. *
  5. * Purpose:
  6. * To load and access the program symbolic information.
  7. *
  8. * Revision History:
  9. *
  10. * [-] 19-Apr-1990 Richk Created.
  11. *
  12. *************************************************************************/
  13. #include <string.h>
  14. #include <io.h>
  15. #include <fcntl.h>
  16. #ifndef NT_HOST
  17. #include <signal.h>
  18. #endif
  19. #undef NULL
  20. #include "ntsdp.h"
  21. #ifdef NT_SAPI
  22. #include <limits.h>
  23. #include <stdlib.h>
  24. // Taken from NTSDK.C
  25. PIMAGE_INFO pImageFromIndex (UCHAR index)
  26. {
  27. PIMAGE_INFO pImage;
  28. pImage = pProcessHead->pImageHead;
  29. while (pImage && pImage->index != index)
  30. pImage = pImage->pImageNext;
  31. return pImage;
  32. }
  33. // End from NTSDK.C
  34. void * _cdecl halloc(long, size_t);
  35. void _cdecl hfree(void *);
  36. int CV_CLOSE( int handle);
  37. int CV_OPEN( char *name, int ignore1, int ignore2);
  38. int CV_READ( int handle, void * buffer, unsigned count);
  39. int CV_SEEK( int handle, long offset, int origin);
  40. long CV_TELL( int handle);
  41. void TH_SetupCVfield(PIMAGE_INFO,PFIELD, IMAGE_SYMBOL*,IMAGE_AUX_SYMBOL*);
  42. void TH_SetupCVfunction(PIMAGE_INFO,PSYMBOL,PSYMBOL);
  43. void TH_SetupCVlocal(PIMAGE_INFO,PLOCAL, IMAGE_SYMBOL*,IMAGE_AUX_SYMBOL*);
  44. void TH_SetupCVpublic(PIMAGE_INFO,PSYMBOL,IMAGE_SYMBOL*,IMAGE_AUX_SYMBOL*);
  45. void TH_SetupCVstruct(PIMAGE_INFO,PSTRUCT,IMAGE_SYMBOL*,IMAGE_AUX_SYMBOL*);
  46. typedef enum { //* Error returns from some SH functions
  47. sheNone,
  48. sheNoSymbols,
  49. sheFutureSymbols,
  50. sheMustRelink,
  51. sheNotPacked,
  52. sheOutOfMemory,
  53. sheCorruptOmf,
  54. sheFileOpen, //* Last CV compatable SHE error
  55. sheBadDirectory
  56. } SHE;
  57. extern SHE SHerror;
  58. ULONG ObjectTableOffset;
  59. UINT ObjectTableCount;
  60. #else
  61. #define CV_OPEN(nam,acc,pro) open(nam,acc,pro);
  62. #define CV_READ(hnd,buf,siz) read(hnd, buf, siz);
  63. #define CV_SEEK(hnd,off,org) _lseek(hnd,off,org);
  64. #define CV_CLOSE(hnd) close(hnd);
  65. #define CV_TELL(hnd); tell(hnd);
  66. #endif
  67. /**********************************************************************
  68. Symbol table organization
  69. Each symbol in the table corresponds to a SYMBOL structure.
  70. Each structure has the symbol name and offset as well as two
  71. sets of pointers. Each set of pointers, defined as a NODE,
  72. consists of parent, left child, and right child pointers to
  73. the corresponding NODEs of other symbols. The symbol name
  74. is encoded into a count of leading underscores and a pointer
  75. to the remaining part of the string. The NODEs of one set
  76. of all symbols comprise a binary tree. Each NODE set, or
  77. tree, has a SYMCONTEXT structure. This structure has a
  78. pointer to the root of the tree, the position of the NODE
  79. structure within the SYMBOL, and a pointer to a comparison
  80. routine used to determine the tree order. Two trees exist,
  81. both using multiple keys.
  82. The "offset" tree orders its nodes on:
  83. 1. increasing offsets;
  84. 2. increasing case-insensitive strings;
  85. 3. increasing number of underscores;
  86. 4. increasing case-sensitive strings.
  87. The multiple keys are needed since more than one string can
  88. be associated with an offset.
  89. The "string" tree orders its nodes on:
  90. 1. increasing case-insensitive strings;
  91. 2. increasing number of underscores;
  92. 3. increasing module address values;
  93. 4. increasing case-sensitive strings.
  94. The case-insensitive/-sensitive searches allow optimal
  95. matching for case-insensitive input.
  96. **********************************************************************/
  97. #ifdef KERNEL
  98. #include <conio.h>
  99. #undef CONTAINING_RECORD
  100. #define CONTAINING_RECORD(farptr, type, field) \
  101. ((type far *)((char far *)farptr - (char far *)&((type far *)0)->field))
  102. #endif
  103. void InitSymContext(PPROCESS_INFO);
  104. #ifdef NT_HOST
  105. extern BOOL cdecl cmdHandler(ULONG);
  106. extern BOOL cdecl waitHandler(ULONG);
  107. #else
  108. extern BOOLEAN fJmpBuf;
  109. void cdecl cmdHandler(void);
  110. #endif
  111. int CompareSymbolOffset(PNODE, PNODE, PBOOLEAN);
  112. int CompareSymbolString(PNODE, PNODE, PBOOLEAN);
  113. int CompareSymfileOffset(PNODE, PNODE, PBOOLEAN);
  114. int CompareSymfileString(PNODE, PNODE, PBOOLEAN);
  115. static PSYMFILE pTempSymfile;
  116. #ifdef NT_SAPI
  117. SYMBOL symbolMax = { 0,0, { NULL, NULL, NULL }, { NULL, NULL, NULL }, -1L,
  118. 0, 0, SYMBOL_TYPE_SYMBOL, NULL,
  119. { '\177', '\177', '\0' } };
  120. SYMBOL structMax = { 0,0, { NULL, NULL, NULL }, { NULL, NULL, NULL }, -1L,
  121. 0, 0, SYMBOL_TYPE_SYMBOL, NULL,
  122. { '\177', '\177', '\0' } };
  123. #else
  124. SYMBOL symbolMax = { { NULL, NULL, NULL }, { NULL, NULL, NULL }, -1L,
  125. 0, 0, SYMBOL_TYPE_SYMBOL, NULL,
  126. { '\177', '\177', '\0' } };
  127. SYMBOL structMax = { { NULL, NULL, NULL }, { NULL, NULL, NULL }, -1L,
  128. 0, 0, SYMBOL_TYPE_SYMBOL, NULL,
  129. { '\177', '\177', '\0' } };
  130. #endif /* NT_SAPI */
  131. UCHAR stringMax[3] = { '\177', '\177', '\0' };
  132. SYMFILE symfileMax = { { NULL, NULL, NULL }, { NULL, NULL, NULL },
  133. "", stringMax, "", 0, NULL, NULL,
  134. 0L, 0L, 0, 0L, 0, 0, NULL, NULL };
  135. BOOLEAN fSourceOnly = FALSE;
  136. BOOLEAN fSourceMixed = FALSE;
  137. PSYMFILE pSymfileLast;
  138. USHORT lineNumberLast;
  139. void parseExamine(void);
  140. void DeferSymbolLoad(PIMAGE_INFO);
  141. void LoadSymbols(PIMAGE_INFO);
  142. void PackAuxNameEntry(PUCHAR, ULONG); // TEMP TEMP TEMP
  143. void UnloadSymbols(PIMAGE_INFO);
  144. void EnsureModuleSymbolsLoaded(CHAR);
  145. int EnsureOffsetSymbolsLoaded(ULONG);
  146. #ifdef KERNEL
  147. PUCHAR GetModuleName(PUCHAR);
  148. extern BOOLEAN KdVerbose;
  149. #define fVerboseOutput KdVerbose
  150. #endif
  151. PIMAGE_INFO ParseModuleIndex(void);
  152. PIMAGE_INFO GetModuleIndex(PUCHAR);
  153. PIMAGE_INFO GetCurrentModuleIndex(void);
  154. void DumpModuleTable(BOOLEAN);
  155. int AccessNode(PSYMCONTEXT, PNODE);
  156. BOOLEAN InsertNode(PSYMCONTEXT, PNODE);
  157. void DeleteNode(PSYMCONTEXT, PNODE);
  158. PNODE NextNode(PSYMCONTEXT, PNODE);
  159. void JoinTree(PSYMCONTEXT, PNODE);
  160. int SplitTree(PSYMCONTEXT, PNODE *, PNODE);
  161. PNODE SplayTree(PNODE);
  162. void OutputTree(PSYMCONTEXT);
  163. void OutputSymAddr(ULONG, BOOLEAN, BOOLEAN);
  164. void GetSymbol(ULONG, PUCHAR, PULONG);
  165. void AddLocalToFunction(PSYMBOL, PUCHAR, ULONG, USHORT, ULONG);
  166. void AddFieldToStructure(PSTRUCT, PUCHAR, ULONG ,USHORT, ULONG);
  167. PSTRUCT InsertStructure(ULONG, PUCHAR, CHAR);
  168. PSYMBOL InsertFunction(PUCHAR, ULONG); //, PSYMBOL);
  169. PSYMBOL InsertSymbol(ULONG, PUCHAR, CHAR);
  170. PSYMBOL AllocSymbol(ULONG, PUCHAR, CHAR);
  171. PSTRUCT GetStructFromValue(ULONG, LONG);
  172. void GetBytesFromFrame(PUCHAR, LONG, USHORT);
  173. ULONG GetLocalValue(LONG, USHORT, BOOLEAN);
  174. BOOLEAN GetLocalFromString(PUCHAR, PULONG);
  175. BOOLEAN GetOffsetFromSym(PUCHAR, PULONG, CHAR);
  176. BOOLEAN GetOffsetFromString(PUCHAR, PULONG, CHAR);
  177. PLINENO GetLinenoFromFilename(PUCHAR, PPSYMFILE, USHORT, CHAR);
  178. PLINENO GetCurrentLineno(PPSYMFILE);
  179. PLINENO GetLastLineno(PPSYMFILE, PUSHORT);
  180. PLINENO GetLinenoFromOffset(PPSYMFILE, ULONG);
  181. void GetLinenoString(PUCHAR, ULONG);
  182. void GetCurrentMemoryOffsets(PULONG, PULONG);
  183. void DeleteSymbol(PSYMBOL);
  184. void DeallocSymbol(PSYMBOL);
  185. PSYMFILE InsertSymfile(PUCHAR, PUCHAR, PUCHAR, PIMAGE_LINENUMBER,
  186. USHORT, ULONG, ULONG, CHAR);
  187. PSYMFILE AllocSymfile(PUCHAR, PUCHAR, PUCHAR, PIMAGE_LINENUMBER,
  188. USHORT, ULONG, ULONG, CHAR);
  189. void DeleteSymfile(PSYMFILE);
  190. void DeallocSymfile(PSYMFILE);
  191. int ntsdstricmp(PUCHAR, PUCHAR);
  192. void fnListNear(ULONG);
  193. void SortSrcLinePointers(PSYMFILE);
  194. //void OutputAtLineno (PSYMFILE, PLINENO);
  195. void UpdateLineno(PSYMFILE, PLINENO);
  196. FILE * LocateTextInSource(PSYMFILE, PLINENO);
  197. void OutputSourceLines(PSYMFILE, USHORT, USHORT);
  198. BOOLEAN OutputSourceFromOffset(ULONG, BOOLEAN);
  199. BOOLEAN OutputLines(PSYMFILE, PLINENO, USHORT, USHORT);
  200. PVOID FetchImageDirectoryEntry(int, USHORT, PULONG, PULONG);
  201. //#ifndef KERNEL
  202. extern int fControlC;
  203. //#endif
  204. #ifndef MIPS
  205. #ifdef KERNEL
  206. extern BOOLEAN cdecl _loadds ControlCHandler(void);
  207. #endif
  208. #endif
  209. extern void RemoveDelChar(PUCHAR);
  210. extern PIMAGE_INFO pImageFromIndex(UCHAR);
  211. extern BOOLEAN fLazyLoad;
  212. extern BOOLEAN fPointerExpression;
  213. // State transition arrays for comment processing
  214. UCHAR WhiteSpace[] = {
  215. stStart, stLine, stSlStar, stSlStStar, stSlSlash,
  216. stLine, stLine, stLSlStar, stLSlStar, stLSlSlash
  217. };
  218. UCHAR Slash[] = {
  219. stSlash, stSlSlash, stSlStar, stStart, stSlSlash,
  220. stLSlash, stLSlSlash, stLSlStar, stLine, stLSlSlash
  221. };
  222. UCHAR Star[] = {
  223. stLine, stSlStar, stSlStStar, stSlStStar, stSlSlash,
  224. stLine, stLSlStar, stLSlStStar, stSlStStar, stLSlSlash
  225. };
  226. UCHAR Pound[] = {
  227. stSlSlash, stLine, stSlStar, stSlStar, stSlSlash,
  228. stLine, stLine, stLSlStar, stLSlStar, stLSlSlash
  229. };
  230. UCHAR OtherChar[] = {
  231. stLine, stLine, stSlStar, stSlStar, stSlSlash,
  232. stLine, stLine, stLSlStar, stLSlStar, stLSlSlash
  233. };
  234. UCHAR Return[] = {
  235. stStart, stStart, stSlStar, stSlStar, stStart,
  236. stStart, stStart, stSlStar, stSlStar, stStart
  237. };
  238. UCHAR fCommentType[] = {
  239. TRUE, FALSE, TRUE, TRUE, TRUE,
  240. FALSE, FALSE, FALSE, FALSE, FALSE
  241. };
  242. ////////////////////////////////////////////////////////////////
  243. void InitSymContext (PPROCESS_INFO pProcess)
  244. {
  245. pProcess->symcontextStructOffset.pNodeRoot = NULL;
  246. pProcess->symcontextStructOffset.pNodeMax =
  247. (PNODE)((LONG)&structMax + NODE_SYMBOL_DISPLACEMENT(nodeOffset));
  248. pProcess->symcontextStructOffset.pfnCompare = &CompareSymbolOffset;
  249. pProcess->symcontextStructOffset.nodeDisplacement =
  250. NODE_SYMBOL_DISPLACEMENT(nodeOffset);
  251. pProcess->symcontextStructString.pNodeRoot = NULL;
  252. pProcess->symcontextStructString.pNodeMax =
  253. (PNODE)((LONG)&structMax + NODE_SYMBOL_DISPLACEMENT(nodeString));
  254. pProcess->symcontextStructString.pfnCompare = &CompareSymbolString;
  255. pProcess->symcontextStructString.nodeDisplacement =
  256. NODE_SYMBOL_DISPLACEMENT(nodeString);
  257. pProcess->symcontextSymbolOffset.pNodeRoot = NULL;
  258. pProcess->symcontextSymbolOffset.pNodeMax =
  259. (PNODE)((LONG)&symbolMax + NODE_SYMBOL_DISPLACEMENT(nodeOffset));
  260. pProcess->symcontextSymbolOffset.pfnCompare = &CompareSymbolOffset;
  261. pProcess->symcontextSymbolOffset.nodeDisplacement =
  262. NODE_SYMBOL_DISPLACEMENT(nodeOffset);
  263. pProcess->symcontextSymbolString.pNodeRoot = NULL;
  264. pProcess->symcontextSymbolString.pNodeMax =
  265. (PNODE)((LONG)&symbolMax + NODE_SYMBOL_DISPLACEMENT(nodeString));
  266. pProcess->symcontextSymbolString.pfnCompare = &CompareSymbolString;
  267. pProcess->symcontextSymbolString.nodeDisplacement =
  268. NODE_SYMBOL_DISPLACEMENT(nodeString);
  269. pProcess->symcontextSymfileOffset.pNodeRoot = NULL;
  270. pProcess->symcontextSymfileOffset.pNodeMax =
  271. (PNODE)((LONG)&symfileMax + NODE_SYMFILE_DISPLACEMENT(nodeOffset));
  272. pProcess->symcontextSymfileOffset.pfnCompare = &CompareSymfileOffset;
  273. pProcess->symcontextSymfileOffset.nodeDisplacement =
  274. NODE_SYMFILE_DISPLACEMENT(nodeOffset);
  275. pProcess->symcontextSymfileString.pNodeRoot = NULL;
  276. pProcess->symcontextSymfileString.pNodeMax =
  277. (PNODE)((LONG)&symfileMax + NODE_SYMFILE_DISPLACEMENT(nodeString));
  278. pProcess->symcontextSymfileString.pfnCompare = &CompareSymfileString;
  279. pProcess->symcontextSymfileString.nodeDisplacement =
  280. NODE_SYMFILE_DISPLACEMENT(nodeString);
  281. pTempSymfile = AllocSymfile("", "", "", NULL, 0, 0, 0, 0);
  282. }
  283. void DeferSymbolLoad (PIMAGE_INFO pImage)
  284. {
  285. #ifndef KERNEL
  286. HANDLE hMapping;
  287. PVOID lpFileBase;
  288. PIMAGE_EXPORT_DIRECTORY lpExportDir;
  289. PIMAGE_DEBUG_DIRECTORY lpDebugDir;
  290. PIMAGE_DEBUG_INFO lpDebugInfo;
  291. PIMAGE_SYMBOL lpSymbolEntry;
  292. PUCHAR lpModName;
  293. PUCHAR pszName = NULL;
  294. ULONG exportSize;
  295. ULONG debugSize;
  296. ULONG symsize;
  297. ULONG auxcount;
  298. ULONG rva;
  299. PUCHAR pPathname;
  300. PUCHAR pchName;
  301. // open file and process enough to get the image name
  302. if (!(hMapping = CreateFileMapping(pImage->hFile, NULL, PAGE_READONLY,
  303. 0L, 0L, NULL)))
  304. return;
  305. if (!(lpFileBase = MapViewOfFile(hMapping, FILE_MAP_READ, 0L, 0L, 0L))) {
  306. CloseHandle(hMapping);
  307. return;
  308. }
  309. pszName = malloc(32);
  310. if (!pszName) {
  311. printf("memory allocation error\n");
  312. ExitProcess(STATUS_UNSUCCESSFUL);
  313. }
  314. if (pImage->index != 0) {
  315. rva = (ULONG)RtlImageDirectoryEntryToData(lpFileBase, TRUE,
  316. IMAGE_DIRECTORY_ENTRY_EXPORT, &exportSize);
  317. rva -= (ULONG)lpFileBase;
  318. lpExportDir = (PIMAGE_EXPORT_DIRECTORY)RtlImageDirectoryEntryToData(
  319. lpFileBase, FALSE, IMAGE_DIRECTORY_ENTRY_EXPORT, &exportSize);
  320. if (lpExportDir) {
  321. lpModName = (PUCHAR)((ULONG)lpExportDir + (ULONG)lpExportDir->Name - rva);
  322. strncpy(pszName, lpModName, 31);
  323. *(pszName + strcspn(pszName, ".")) = '\0';
  324. }
  325. else
  326. strcpy(pszName, "unknown");
  327. }
  328. else {
  329. strcpy(pszName, "app");
  330. // try to name the main image using the first symbol table
  331. // entry which contains the path of the first file in it.
  332. symsize = IMAGE_SIZEOF_SYMBOL;
  333. lpDebugDir = (PIMAGE_DEBUG_DIRECTORY)RtlImageDirectoryEntryToData(
  334. lpFileBase, FALSE, IMAGE_DIRECTORY_ENTRY_DEBUG, &debugSize);
  335. if (lpDebugDir) {
  336. lpDebugInfo = (PIMAGE_DEBUG_INFO)((ULONG)lpFileBase + lpDebugDir->PointerToRawData);
  337. lpSymbolEntry = (PIMAGE_SYMBOL)((ULONG)lpDebugInfo
  338. + lpDebugInfo->LvaToFirstSymbol);
  339. auxcount = lpSymbolEntry->NumberOfAuxSymbols;
  340. if (lpSymbolEntry->StorageClass == IMAGE_SYM_CLASS_FILE) {
  341. lpSymbolEntry = (PIMAGE_SYMBOL)
  342. ((PUCHAR)lpSymbolEntry + symsize);
  343. // allocate and copy the pathname from the following
  344. // auxiliary entries.
  345. pPathname = malloc((int)(auxcount * symsize + 1));
  346. if (!pPathname) {
  347. printf("memory allocation error\n");
  348. ExitProcess(STATUS_UNSUCCESSFUL);
  349. }
  350. memcpy(pPathname, lpSymbolEntry, (int)(auxcount * symsize));
  351. // TEMP TEMP TEMP - pack entries 14/18 chars into string
  352. // PackAuxNameEntry(pPathname, auxcount);
  353. *(pPathname + auxcount * symsize) = '\0'; // TEMP TEMP TEMP
  354. // extract the filename from the pathname as the string
  355. // following the last '\' or ':', but not including any
  356. // characters after '.'.
  357. pchName = strrchr(pPathname, '\\');
  358. if (!pchName)
  359. pchName = strrchr(pPathname, ':');
  360. if (!pchName)
  361. pchName = pPathname;
  362. else
  363. pchName++;
  364. *(pchName + strcspn(pchName, ".")) = '\0';
  365. strcpy(pszName, pchName);
  366. free(pPathname);
  367. }
  368. }
  369. }
  370. pImage->pszName = pszName;
  371. if (fVerboseOutput)
  372. dprintf("NTSD: deferring symbol load for \"%s\"\n", pImage->pszName);
  373. UnmapViewOfFile(lpFileBase);
  374. CloseHandle(hMapping);
  375. #else
  376. int ImageReadHandle;
  377. IMAGE_OPTIONAL_HEADER coffOptionalHeader;
  378. USHORT Signature;
  379. ULONG DosHeader[16], NtSignature;
  380. if (fVerboseOutput)
  381. dprintf("KD: deferring symbol load for \"%s\"\n", pImage->pszName);
  382. if (pImage->lpBaseOfImage == (PVOID)-1L){
  383. #ifdef NT_SAPI
  384. SHerror = sheNone;
  385. ImageReadHandle = (int)pImage->hQCFile;
  386. #else
  387. ImageReadHandle = CV_OPEN(pImage->pszName, O_RDONLY|O_BINARY, 0);
  388. if (ImageReadHandle < 0) return;
  389. #endif /* NT_SAPI */
  390. CV_READ(ImageReadHandle, &Signature, sizeof(USHORT));
  391. CV_SEEK(ImageReadHandle, 0, SEEK_SET);
  392. if (Signature == IMAGE_DOS_SIGNATURE) {
  393. CV_READ(ImageReadHandle, &DosHeader, 16*sizeof(ULONG));
  394. CV_SEEK(ImageReadHandle, DosHeader[15], SEEK_SET);
  395. CV_READ(ImageReadHandle, &NtSignature, sizeof(ULONG));
  396. if (NtSignature != IMAGE_NT_SIGNATURE) {
  397. #ifdef NT_SAPI
  398. SHerror = sheCorruptOmf;
  399. #else
  400. dprintf("\nPE signature not found\n");
  401. #endif
  402. }
  403. }
  404. CV_SEEK(ImageReadHandle, (ULONG)sizeof(IMAGE_FILE_HEADER), SEEK_CUR);
  405. CV_READ(ImageReadHandle, &coffOptionalHeader,
  406. sizeof(IMAGE_OPTIONAL_HEADER));
  407. #ifndef NT_SAPI
  408. CV_CLOSE(ImageReadHandle);
  409. #endif
  410. pImage->lpBaseOfImage = (LPVOID)coffOptionalHeader.ImageBase;
  411. if (fVerboseOutput)
  412. dprintf("KD: Kernel image at %08lx\n", pImage->lpBaseOfImage);
  413. }
  414. #endif
  415. }
  416. #ifndef KERNEL
  417. BOOLEAN CountLinenumbers(PIMAGE_INFO pImage)
  418. {
  419. HANDLE hMapping;
  420. PVOID lpFileBase;
  421. PIMAGE_EXPORT_DIRECTORY lpExportDir;
  422. PIMAGE_DEBUG_DIRECTORY lpDebugDir;
  423. PIMAGE_DEBUG_INFO lpDebugInfo;
  424. PIMAGE_SYMBOL lpSymbolEntry;
  425. IMAGE_SYMBOL SymbolEntry;
  426. IMAGE_AUX_SYMBOL AuxSymbolEntry;
  427. PIMAGE_LINENUMBER lpPointerToLinenumbers;
  428. PIMAGE_LINENUMBER lpEndPointerToLinenumbers;
  429. PUCHAR lpStringTable;
  430. UCHAR ShortString[10];
  431. ULONG exportSize;
  432. ULONG debugSize;
  433. ULONG symsize;
  434. ULONG index;
  435. ULONG auxcount;
  436. ULONG symbolcount = 0;
  437. ULONG entrycount;
  438. PSYMBOL pCurrentFunction = NULL;
  439. PSTRUCT pCurrentStructure = NULL;
  440. #ifdef MIPS
  441. PRUNTIME_FUNCTION lpRuntimeFunction;
  442. PFUNCTION_ENTRY lpFunctionTable;
  443. ULONG pdataSize = 0L;
  444. ULONG cFunctions = 0;
  445. #endif
  446. PUCHAR pszName = NULL;
  447. PUCHAR pPathname = NULL;
  448. PUCHAR pFilename = NULL;
  449. PUCHAR pExtension = NULL;
  450. PIMAGE_LINENUMBER pLinenumbers = NULL;
  451. BOOLEAN nameFound = FALSE;
  452. BOOLEAN invalidOMF = FALSE;
  453. ULONG NumberOfLinenumbers;
  454. ULONG cLines=0L;
  455. ShortString[8] = '\0';
  456. if (!(hMapping = CreateFileMapping(pImage->hFile, NULL, PAGE_READONLY,
  457. 0L, 0L, NULL)))
  458. return FALSE;
  459. if (!(lpFileBase = MapViewOfFile(hMapping, FILE_MAP_READ, 0L, 0L, 0L))) {
  460. CloseHandle(hMapping);
  461. return FALSE;
  462. }
  463. if (pImage->index != 0) {
  464. lpExportDir = (PIMAGE_EXPORT_DIRECTORY)RtlImageDirectoryEntryToData(
  465. lpFileBase, FALSE, IMAGE_DIRECTORY_ENTRY_EXPORT, &exportSize);
  466. } else
  467. lpExportDir = NULL;
  468. pImage->offsetLow = 0xffffffff;
  469. pImage->offsetHigh = 0x0;
  470. symsize = IMAGE_SIZEOF_SYMBOL;
  471. lpDebugDir = (PIMAGE_DEBUG_DIRECTORY)RtlImageDirectoryEntryToData(
  472. lpFileBase, FALSE, IMAGE_DIRECTORY_ENTRY_DEBUG, &debugSize);
  473. // if no debug information, just return TRUE
  474. if (!lpDebugDir) {
  475. UnmapViewOfFile(hMapping);
  476. CloseHandle(hMapping);
  477. return TRUE;
  478. }
  479. lpDebugInfo = (PIMAGE_DEBUG_INFO)((ULONG)lpFileBase + lpDebugDir->PointerToRawData);
  480. lpPointerToLinenumbers = (PIMAGE_LINENUMBER)((ULONG)lpDebugInfo +
  481. + lpDebugInfo->LvaToFirstLinenumber);
  482. // dprintf("Correct # of lines = %ld\n",
  483. // NumberOfLinenumbers = lpDebugInfo->NumberOfLinenumbers);
  484. NumberOfLinenumbers = lpDebugInfo->NumberOfLinenumbers;
  485. lpSymbolEntry = (PIMAGE_SYMBOL)((ULONG)lpDebugInfo
  486. + lpDebugInfo->LvaToFirstSymbol);
  487. // PDK KLUDGE :::
  488. lpEndPointerToLinenumbers = (PIMAGE_LINENUMBER)lpSymbolEntry;
  489. lpStringTable = (PUCHAR)((ULONG)lpDebugInfo +
  490. lpDebugInfo->LvaToFirstSymbol +
  491. lpDebugInfo->NumberOfSymbols * symsize);
  492. for (entrycount = 0; entrycount < lpDebugInfo->NumberOfSymbols;
  493. entrycount++) {
  494. memcpy((PUCHAR)&SymbolEntry, lpSymbolEntry, symsize);
  495. lpSymbolEntry = (PIMAGE_SYMBOL)((PUCHAR)lpSymbolEntry + symsize);
  496. auxcount = SymbolEntry.NumberOfAuxSymbols;
  497. switch (SymbolEntry.StorageClass) {
  498. case IMAGE_SYM_CLASS_STATIC:
  499. if (SymbolEntry.SectionNumber > 0 &&
  500. SymbolEntry.Type == IMAGE_SYM_TYPE_NULL &&
  501. auxcount == 1) {
  502. index = SymbolEntry.SectionNumber - 1;
  503. memcpy((PUCHAR)&AuxSymbolEntry, lpSymbolEntry, symsize);
  504. if (AuxSymbolEntry.Section.Length &&
  505. AuxSymbolEntry.Section.NumberOfLinenumbers) {
  506. cLines += (int)AuxSymbolEntry.Section.NumberOfLinenumbers;
  507. }
  508. }
  509. // else
  510. // dprintf("STATIC class entry\n");
  511. break;
  512. }
  513. // auxcount has the number of auxiliary entries
  514. // skip over them for the next table entry
  515. entrycount += auxcount;
  516. lpSymbolEntry = (PIMAGE_SYMBOL)
  517. ((PUCHAR)lpSymbolEntry + auxcount * symsize);
  518. }
  519. // dprintf("Actual # of lines = %ld\n", cLines);
  520. UnmapViewOfFile(hMapping);
  521. CloseHandle(hMapping);
  522. return ((BOOLEAN)(cLines == NumberOfLinenumbers));
  523. }
  524. void LoadSymbols (PIMAGE_INFO pImage)
  525. {
  526. HANDLE hMapping;
  527. PVOID lpFileBase;
  528. PIMAGE_EXPORT_DIRECTORY lpExportDir;
  529. PIMAGE_DEBUG_DIRECTORY lpDebugDir;
  530. PIMAGE_DEBUG_INFO lpDebugInfo;
  531. PIMAGE_SYMBOL lpSymbolEntry;
  532. IMAGE_SYMBOL SymbolEntry;
  533. IMAGE_AUX_SYMBOL AuxSymbolEntry;
  534. PIMAGE_LINENUMBER lpPointerToLinenumbers;
  535. PIMAGE_LINENUMBER lpEndPointerToLinenumbers;
  536. IMAGE_LINENUMBER LineNumber;
  537. PUCHAR lpStringTable;
  538. PUCHAR lpSymbolName;
  539. UCHAR ShortString[10];
  540. ULONG exportSize;
  541. ULONG debugSize;
  542. ULONG symsize;
  543. ULONG index;
  544. ULONG ind;
  545. ULONG auxcount;
  546. ULONG symbolcount = 0;
  547. ULONG entrycount;
  548. ULONG SymbolValue;
  549. ULONG rva;
  550. PSYMBOL pNewSymbol = NULL;
  551. PSYMBOL pCurrentFunction = NULL;
  552. PSTRUCT pCurrentStructure = NULL;
  553. PULONG pAddrName;
  554. #ifdef MIPS
  555. PRUNTIME_FUNCTION lpRuntimeFunction;
  556. PFUNCTION_ENTRY lpFunctionTable;
  557. ULONG pdataSize = 0L;
  558. ULONG cFunctions = 0;
  559. #endif
  560. PUCHAR pszName = NULL;
  561. PUCHAR pPathname = NULL;
  562. PUCHAR pFilename = NULL;
  563. PUCHAR pExtension = NULL;
  564. PIMAGE_LINENUMBER pLinenumbers = NULL;
  565. PIMAGE_LINENUMBER pLinenumberNext;
  566. PUCHAR pchName;
  567. int cName;
  568. BOOLEAN nameFound = FALSE;
  569. BOOLEAN invalidOMF = FALSE;
  570. BOOLEAN validLinenumbers;
  571. validLinenumbers = CountLinenumbers(pImage);
  572. if (!validLinenumbers) {
  573. dprintf("NTSD: Line count mismatch in %s. Disabling source debugging\n",pImage->pszName);
  574. // CloseHandle(pImage->hFile);
  575. // return;
  576. }
  577. ShortString[8] = '\0';
  578. if (!(hMapping = CreateFileMapping(pImage->hFile, NULL, PAGE_READONLY,
  579. 0L, 0L, NULL)))
  580. return;
  581. if (!(lpFileBase = MapViewOfFile(hMapping, FILE_MAP_READ, 0L, 0L, 0L))) {
  582. CloseHandle(hMapping);
  583. CloseHandle(pImage->hFile);
  584. return;
  585. }
  586. #ifdef MIPS
  587. lpRuntimeFunction = (PRUNTIME_FUNCTION)RtlImageDirectoryEntryToData(
  588. lpFileBase, FALSE, IMAGE_DIRECTORY_ENTRY_EXCEPTION, &pdataSize);
  589. if (lpRuntimeFunction) {
  590. cFunctions = pdataSize / sizeof(RUNTIME_FUNCTION);
  591. pImage->LowAddress = MAXULONG;
  592. pImage->HighAddress = 0;
  593. lpFunctionTable = (PFUNCTION_ENTRY)
  594. malloc((int)(cFunctions * sizeof(FUNCTION_ENTRY)));
  595. if (!lpFunctionTable) {
  596. dprintf("NTSD: alloc error for exception table\n");
  597. exit(1);
  598. }
  599. pImage->FunctionTable = lpFunctionTable;
  600. pImage->LowAddress = MAXULONG;
  601. pImage->HighAddress = 0;
  602. for (index = 0; index < cFunctions; index++) {
  603. if (lpRuntimeFunction->BeginAddress == 0)
  604. break;
  605. lpFunctionTable->StartingAddress = lpRuntimeFunction->BeginAddress;
  606. if (lpRuntimeFunction->BeginAddress < pImage->LowAddress)
  607. pImage->LowAddress = lpRuntimeFunction->BeginAddress;
  608. lpFunctionTable->EndingAddress = lpRuntimeFunction->EndAddress;
  609. if (lpRuntimeFunction->EndAddress > pImage->HighAddress)
  610. pImage->HighAddress = lpRuntimeFunction->EndAddress;
  611. lpFunctionTable->EndOfPrologue = lpRuntimeFunction->PrologEndAddress;
  612. lpRuntimeFunction++;
  613. lpFunctionTable++;
  614. }
  615. }
  616. pImage->NumberOfFunctions = cFunctions;
  617. #endif
  618. if (pImage->index != 0) {
  619. rva = (ULONG)RtlImageDirectoryEntryToData(lpFileBase, TRUE,
  620. IMAGE_DIRECTORY_ENTRY_EXPORT, &exportSize);
  621. rva -= (ULONG)lpFileBase;
  622. lpExportDir = (PIMAGE_EXPORT_DIRECTORY)RtlImageDirectoryEntryToData(
  623. lpFileBase, FALSE, IMAGE_DIRECTORY_ENTRY_EXPORT, &exportSize);
  624. } else
  625. lpExportDir = NULL;
  626. pImage->offsetLow = 0xffffffff;
  627. pImage->offsetHigh = 0x0;
  628. symsize = IMAGE_SIZEOF_SYMBOL;
  629. lpDebugDir = (PIMAGE_DEBUG_DIRECTORY)RtlImageDirectoryEntryToData(
  630. lpFileBase, FALSE, IMAGE_DIRECTORY_ENTRY_DEBUG, &debugSize);
  631. // if no debug information, just close and return
  632. if (!lpDebugDir) {
  633. CloseHandle(hMapping);
  634. CloseHandle(pImage->hFile);
  635. return;
  636. }
  637. lpDebugInfo = (PIMAGE_DEBUG_INFO)((ULONG)lpFileBase + lpDebugDir->PointerToRawData);
  638. lpPointerToLinenumbers = (PIMAGE_LINENUMBER)((ULONG)lpDebugInfo +
  639. lpDebugInfo->LvaToFirstLinenumber);
  640. lpSymbolEntry = (PIMAGE_SYMBOL)((ULONG)lpDebugInfo +
  641. lpDebugInfo->LvaToFirstSymbol);
  642. // PDK KLUDGE :::
  643. lpEndPointerToLinenumbers = (PIMAGE_LINENUMBER)lpSymbolEntry;
  644. lpStringTable = (PUCHAR)((ULONG)lpDebugInfo +
  645. lpDebugInfo->LvaToFirstSymbol +
  646. lpDebugInfo->NumberOfSymbols * symsize);
  647. // dprintf("# lines %lx, # sys %lx\n", lpDebugInfo->NumberOfLinenumbers, lpDebugInfo->NumberOfSymbols);
  648. for (entrycount = 0; entrycount < lpDebugInfo->NumberOfSymbols;
  649. entrycount++) {
  650. memcpy((PUCHAR)&SymbolEntry, lpSymbolEntry, symsize);
  651. lpSymbolEntry = (PIMAGE_SYMBOL)((PUCHAR)lpSymbolEntry + symsize);
  652. auxcount = SymbolEntry.NumberOfAuxSymbols;
  653. switch (SymbolEntry.StorageClass) {
  654. case IMAGE_SYM_CLASS_FILE:
  655. // allocate and copy the pathname from the following
  656. // auxiliary entries.
  657. pPathname = realloc(pPathname, (int)(auxcount * symsize + 1));
  658. memcpy(pPathname, lpSymbolEntry, (int)(auxcount * symsize));
  659. // TEMP TEMP TEMP - pack entries 14/18 chars into string
  660. // PackAuxNameEntry(pPathname, auxcount);
  661. *(pPathname + auxcount * symsize) = '\0'; // TEMP TEMP TEMP
  662. // extract the filename from the pathname as the string
  663. // following the last '\' or ':', but not including any
  664. // characters after '.'.
  665. pchName = strrchr(pPathname, '\\');
  666. if (!pchName)
  667. pchName = strrchr(pPathname, ':');
  668. if (!pchName)
  669. pchName = pPathname;
  670. else
  671. pchName++;
  672. cName = strcspn(pchName, ".");
  673. // allocate a string and copy the filename part of the
  674. // path and convert to lower case.
  675. pFilename = realloc(pFilename, cName + 1);
  676. strncpy(pFilename, pchName, cName);
  677. *(pFilename + cName) = '\0';
  678. _strlwr(pFilename);
  679. // allocate a string and copy the extension part of the
  680. // path, if any, and convert to lower case.
  681. pExtension = realloc(pExtension, strlen(pchName + cName) + 1);
  682. strcpy(pExtension, pchName + cName);
  683. _strlwr(pExtension);
  684. // remove filename and extension from pathname by
  685. // null-terminating at the start of the filename
  686. // BUT, if null pathname, put in ".\" since a null
  687. // is interpreted as NO PATH available.
  688. if (pchName == pPathname) {
  689. *pchName++ = '.';
  690. *pchName++ = '\\';
  691. }
  692. *pchName = '\0';
  693. break;
  694. case IMAGE_SYM_CLASS_STATIC:
  695. if (validLinenumbers && SymbolEntry.SectionNumber > 0 &&
  696. SymbolEntry.Type == IMAGE_SYM_TYPE_NULL &&
  697. auxcount == 1) {
  698. index = SymbolEntry.SectionNumber - 1;
  699. memcpy((PUCHAR)&AuxSymbolEntry, lpSymbolEntry, symsize);
  700. if (AuxSymbolEntry.Section.Length &&
  701. AuxSymbolEntry.Section.NumberOfLinenumbers) {
  702. // PDK KLUDGE :::
  703. if (((PIMAGE_LINENUMBER)
  704. ((PUCHAR)lpPointerToLinenumbers+
  705. IMAGE_SIZEOF_LINENUMBER *
  706. (int)AuxSymbolEntry.Section.NumberOfLinenumbers) >=
  707. lpEndPointerToLinenumbers)
  708. || invalidOMF)
  709. {
  710. invalidOMF = TRUE;
  711. if (fVerboseOutput)
  712. dprintf("Invalid OMF in %s (%s%s)"
  713. "-- invalidating rest of image\n",
  714. pImage->pszName,
  715. pFilename, pExtension);
  716. }
  717. if (!invalidOMF){
  718. pLinenumbers =
  719. (PIMAGE_LINENUMBER)realloc((PUCHAR)pLinenumbers,
  720. IMAGE_SIZEOF_LINENUMBER *
  721. (int)AuxSymbolEntry.Section.NumberOfLinenumbers);
  722. pLinenumberNext = pLinenumbers;
  723. for (ind = 0; ind < AuxSymbolEntry.Section.NumberOfLinenumbers;
  724. ind++) {
  725. memcpy((PUCHAR)&LineNumber,
  726. (PUCHAR)lpPointerToLinenumbers,
  727. IMAGE_SIZEOF_LINENUMBER);
  728. LineNumber.Type.VirtualAddress +=
  729. (ULONG)pImage->lpBaseOfImage;
  730. memcpy((PUCHAR)pLinenumberNext,
  731. (PUCHAR)&LineNumber,
  732. IMAGE_SIZEOF_LINENUMBER);
  733. lpPointerToLinenumbers = (PIMAGE_LINENUMBER)
  734. ((PUCHAR)lpPointerToLinenumbers +
  735. IMAGE_SIZEOF_LINENUMBER);
  736. pLinenumberNext = (PIMAGE_LINENUMBER)
  737. ((PUCHAR)pLinenumberNext +
  738. IMAGE_SIZEOF_LINENUMBER);
  739. }
  740. //////////
  741. // memcpy((PUCHAR)pLinenumbers,
  742. // (PUCHAR)(lpPointerToLinenumbers),
  743. // IMAGE_SIZEOF_LINENUMBER
  744. // * (int)AuxSymbolEntry.Section.NumberOfLinenumbers);
  745. //
  746. // for (ind = 0; ind < AuxSymbolEntry.Section.NumberOfLinenumbers;
  747. // ind++)
  748. // ((PIMAGE_LINENUMBER)((PUCHAR)pLinenumbers
  749. // + IMAGE_SIZEOF_LINENUMBER * ind))->
  750. // Type.VirtualAddress +=
  751. // (ULONG)pImage->lpBaseOfImage;
  752. //
  753. // lpPointerToLinenumbers = (PIMAGE_LINENUMBER)
  754. // ((PUCHAR)lpPointerToLinenumbers
  755. // + IMAGE_SIZEOF_LINENUMBER
  756. // * AuxSymbolEntry.Section.NumberOfLinenumbers);
  757. ///////////
  758. }
  759. InsertSymfile(pPathname, pFilename, pExtension,
  760. (PIMAGE_LINENUMBER)(invalidOMF ? NULL : pLinenumbers),
  761. (USHORT)(invalidOMF ? 0 : AuxSymbolEntry.Section.NumberOfLinenumbers),
  762. SymbolEntry.Value + (ULONG)pImage->lpBaseOfImage,
  763. SymbolEntry.Value + (ULONG)pImage->lpBaseOfImage
  764. + AuxSymbolEntry.Section.Length,
  765. pImage->index);
  766. #if 0
  767. dprintf("\npath: <%s> file: <%s> ext: <%s> "
  768. "start: %08lx end: %08lx\n",
  769. pPathname, pFilename, pExtension,
  770. SymbolEntry.Value + (ULONG)pImage->lpBaseOfImage,
  771. SymbolEntry.Value + (ULONG)pImage->lpBaseOfImage
  772. + AuxSymbolEntry.Section.Length);
  773. dprintf("section %ld - length: %lx "
  774. "line number cnt: %d\n", index,
  775. AuxSymbolEntry.Section.Length,
  776. AuxSymbolEntry.Section.NumberOfLinenumbers);
  777. for (index = 0; index < AuxSymbolEntry.Section.NumberOfLinenumbers;
  778. index++)
  779. dprintf("index %ld, address: %08lx, "
  780. "line number %d\n", index,
  781. ((PIMAGE_LINENUMBER)((PUCHAR)pLinenumbers
  782. + index * IMAGE_SIZEOF_LINENUMBER))->
  783. Type.VirtualAddress,
  784. ((PIMAGE_LINENUMBER)((PUCHAR)pLinenumbers
  785. + index * IMAGE_SIZEOF_LINENUMBER))->
  786. Linenumber);
  787. #endif
  788. }
  789. }
  790. // else
  791. // dprintf("STATIC class entry\n");
  792. break;
  793. case IMAGE_SYM_CLASS_FUNCTION:
  794. if (SymbolEntry.N.Name.Short) {
  795. strncpy(ShortString, SymbolEntry.N.ShortName, 8);
  796. ShortString[8] = '\0';
  797. lpSymbolName = ShortString;
  798. }
  799. else
  800. lpSymbolName = lpStringTable + SymbolEntry.N.Name.Long;
  801. if (SymbolEntry.Value && pNewSymbol) {
  802. SymbolValue = SymbolEntry.Value + (ULONG)pImage->lpBaseOfImage;
  803. // dprintf("[FUNCTION:%s, val=%08lx, ",pNewSymbol->string,
  804. // pNewSymbol->offset);
  805. pCurrentFunction =
  806. InsertFunction(pNewSymbol->string, pNewSymbol->offset);
  807. // dprintf(pCurrentFunction ? "Inserted]\n"
  808. // : "Insertion failed]\n");
  809. }
  810. break;
  811. case IMAGE_SYM_CLASS_AUTOMATIC:
  812. case IMAGE_SYM_CLASS_ARGUMENT:
  813. case IMAGE_SYM_CLASS_REGISTER:
  814. case IMAGE_SYM_CLASS_MEMBER_OF_STRUCT:{
  815. ULONG auxValue;
  816. if (SymbolEntry.N.Name.Short) {
  817. strncpy(ShortString, SymbolEntry.N.ShortName, 8);
  818. ShortString[8] = '\0';
  819. lpSymbolName = ShortString;
  820. }
  821. else{
  822. if (!SymbolEntry.N.Name.Long) break;
  823. lpSymbolName = lpStringTable + SymbolEntry.N.Name.Long;
  824. }
  825. SymbolValue = SymbolEntry.Value;
  826. if (SymbolEntry.Type==IMAGE_SYM_TYPE_STRUCT){
  827. if (!auxcount) break; // Error in COFF
  828. auxValue = *((PULONG)lpSymbolEntry);
  829. }
  830. if(SymbolEntry.StorageClass!=IMAGE_SYM_CLASS_MEMBER_OF_STRUCT){
  831. // dprintf("\t[LOCAL:%s, value=%ld, aux=%lx]\n",
  832. // lpSymbolName, SymbolValue, auxValue);
  833. AddLocalToFunction(pCurrentFunction, lpSymbolName,
  834. SymbolValue, SymbolEntry.Type, auxValue);
  835. }
  836. else{
  837. // dprintf("\t[FIELD:%s, type=%ld, value=%ld, aux=%lx]\n",
  838. // lpSymbolName, SymbolEntry.Type, SymbolValue,
  839. // auxValue);
  840. AddFieldToStructure(pCurrentStructure, lpSymbolName,
  841. SymbolValue,SymbolEntry.Type, auxValue);
  842. }
  843. }
  844. break;
  845. case IMAGE_SYM_CLASS_STRUCT_TAG:
  846. if (SymbolEntry.N.Name.Short) {
  847. strncpy(ShortString, SymbolEntry.N.ShortName, 8);
  848. ShortString[8] = '\0';
  849. lpSymbolName = ShortString;
  850. }
  851. else
  852. lpSymbolName = lpStringTable + SymbolEntry.N.Name.Long;
  853. //dprintf("[STRUCT#%ld:%s \n",entrycount, lpSymbolName);
  854. pCurrentStructure = InsertStructure(entrycount,
  855. lpSymbolName,
  856. pImage->index);
  857. //dprintf(pCurrentStructure?"Inserted]\n":"Insertion failed]\n");
  858. break;
  859. case IMAGE_SYM_CLASS_EXTERNAL:
  860. if (SymbolEntry.N.Name.Short) {
  861. strncpy(ShortString, SymbolEntry.N.ShortName, 8);
  862. ShortString[8] = '\0';
  863. lpSymbolName = ShortString;
  864. }
  865. else
  866. lpSymbolName = lpStringTable + SymbolEntry.N.Name.Long;
  867. if (SymbolEntry.Value) {
  868. SymbolValue = SymbolEntry.Value + (ULONG)pImage->lpBaseOfImage;
  869. // dprintf("sym %s value %lx entryc %lx\n", lpSymbolName, SymbolValue, entrycount);
  870. pNewSymbol = InsertSymbol(SymbolValue, lpSymbolName,
  871. pImage->index);
  872. if (pNewSymbol) {
  873. if (SymbolValue > pImage->offsetHigh)
  874. pImage->offsetHigh = SymbolValue;
  875. if (SymbolValue < pImage->offsetLow)
  876. pImage->offsetLow = SymbolValue;
  877. symbolcount++;
  878. if (fVerboseOutput && symbolcount % 100 == 0)
  879. dprintf("NTSD: module \"%s\" loaded "
  880. "%ld symbols\r",
  881. pszName, symbolcount);
  882. }
  883. }
  884. break;
  885. default:
  886. // dprintf("OTHER class entry - class: %d\n",
  887. // SymbolEntry.StorageClass);
  888. break;
  889. }
  890. // auxcount has the number of auxiliary entries
  891. // skip over them for the next table entry
  892. entrycount += auxcount;
  893. lpSymbolEntry = (PIMAGE_SYMBOL)
  894. ((PUCHAR)lpSymbolEntry + auxcount * symsize);
  895. }
  896. if (fVerboseOutput)
  897. #ifdef MIPS
  898. dprintf("NTSD: \"%s\" loaded %ld symbols, "
  899. "%ld functions (%08lx-%08lx)\n",
  900. pImage->pszName, symbolcount, pImage->NumberOfFunctions,
  901. pImage->offsetLow, pImage->offsetHigh);
  902. #else
  903. dprintf("NTSD: \"%s\" loaded %ld symbols (%08lx-%08lx)\n",
  904. pImage->pszName, symbolcount,
  905. pImage->offsetLow, pImage->offsetHigh);
  906. #endif
  907. if (fVerboseOutput || !fLazyLoad)
  908. dprintf("NTSD: loading symbols for \"%s\"\n", pImage->pszName);
  909. if (lpExportDir) {
  910. ULONG offset;
  911. PSYMBOL pSymbol;
  912. entrycount= lpExportDir->NumberOfNames;
  913. pAddrName = (PULONG)((ULONG)lpExportDir
  914. + (ULONG)lpExportDir->AddressOfNames - rva);
  915. for (index = 0; index < entrycount; index++) {
  916. pszName = (PUCHAR)((ULONG)lpExportDir + *pAddrName++ - rva);
  917. //dprintf("\t%ld:%s\n", index, pszName);
  918. if (GetOffsetFromString(pszName, &offset, pImage->index)) {
  919. pSymbol = PNODE_TO_PSYMBOL
  920. (pProcessCurrent->symcontextSymbolString.pNodeRoot,
  921. &(pProcessCurrent->symcontextSymbolString));
  922. pSymbol->type = SYMBOL_TYPE_EXPORT;
  923. }
  924. else
  925. dprintf("NTSD: error exporting non-existent symbol\n");
  926. }
  927. }
  928. // free pointers to reallocated strings
  929. free(pExtension);
  930. free(pFilename);
  931. free(pPathname);
  932. free(pLinenumbers);
  933. UnmapViewOfFile(hMapping);
  934. CloseHandle(hMapping);
  935. CloseHandle(pImage->hFile);
  936. }
  937. #endif
  938. #ifdef KERNEL
  939. void LoadSymbols (PIMAGE_INFO pImage)
  940. {
  941. PSZ SymbolName;
  942. ULONG entrycount;
  943. ULONG auxcount;
  944. ULONG SymbolValue;
  945. UCHAR ShortString[10];
  946. IMAGE_SYMBOL SymbolEntry;
  947. IMAGE_AUX_SYMBOL AuxSymbolEntry;
  948. #ifdef MIPS
  949. RUNTIME_FUNCTION RuntimeFunction;
  950. PFUNCTION_ENTRY lpFunctionEntry;
  951. ULONG pdataSize = 0L;
  952. ULONG pdataStart;
  953. ULONG cFunctions = 0;
  954. ULONG junk;
  955. #endif
  956. ULONG StringTableSize;
  957. char huge * StringTable = NULL;
  958. ULONG Base;
  959. ULONG HdrBase;
  960. ULONG BaseOffset = 0;
  961. int symsize;
  962. int ImageReadHandle;
  963. PUCHAR pszName;
  964. PSYMBOL pNewSymbol = NULL;
  965. PSYMBOL pCurrentFunction = NULL;
  966. PSTRUCT pCurrentStructure = NULL;
  967. ULONG symbolcount = 0;
  968. ULONG index;
  969. ULONG ind;
  970. PUCHAR pPathname = NULL;
  971. PUCHAR pFilename = NULL;
  972. PUCHAR pExtension = NULL;
  973. ULONG pNextLinenumber;
  974. ULONG debugSize;
  975. IMAGE_DEBUG_DIRECTORY DebugDir;
  976. IMAGE_DEBUG_INFO DebugInfo;
  977. ULONG StartDebugInfo;
  978. PIMAGE_LINENUMBER pLinenumbers = NULL;
  979. PUCHAR pchName;
  980. int cName;
  981. ULONG seekSave;
  982. unsigned int n;
  983. unsigned int maxr;
  984. unsigned long needr;
  985. char huge * p;
  986. char buff[128];
  987. #ifdef NT_SAPI
  988. SHerror = sheNone;
  989. ImageReadHandle = pImage->hQCFile;
  990. if ( pImage->IgnoreSymbols ) {
  991. SHerror = sheNoSymbols;
  992. return;
  993. }
  994. #else
  995. ImageReadHandle = CV_OPEN(pImage->pszName, O_RDONLY | O_BINARY, 0);
  996. if (ImageReadHandle < 0) return;
  997. #endif /* NT_SAPI */
  998. if (fLazyLoad && fVerboseOutput)
  999. dprintf("KD: Loading \"%s\" (previously deferred)\n", pImage->pszName);
  1000. seekSave = (ULONG)FetchImageDirectoryEntry(ImageReadHandle,
  1001. IMAGE_DIRECTORY_ENTRY_DEBUG, &debugSize, &HdrBase);
  1002. if (!seekSave) {
  1003. #ifdef NT_SAPI
  1004. SHerror = sheBadDirectory;
  1005. #endif
  1006. return;
  1007. }
  1008. CV_SEEK(ImageReadHandle, seekSave, SEEK_SET);
  1009. CV_READ(ImageReadHandle, &DebugDir, sizeof(IMAGE_DEBUG_DIRECTORY));
  1010. StartDebugInfo = DebugDir.PointerToRawData;
  1011. CV_SEEK(ImageReadHandle, StartDebugInfo, SEEK_SET);
  1012. CV_READ(ImageReadHandle, &DebugInfo, sizeof(IMAGE_DEBUG_INFO));
  1013. pNextLinenumber = (StartDebugInfo + DebugInfo.LvaToFirstLinenumber);
  1014. #ifdef MIPS
  1015. if (pdataSize == 0) {
  1016. pdataStart = (ULONG)FetchImageDirectoryEntry(ImageReadHandle,
  1017. IMAGE_DIRECTORY_ENTRY_EXCEPTION, &pdataSize, &junk);
  1018. }
  1019. #endif
  1020. if (HdrBase) {
  1021. if (pImage->lpBaseOfImage) {
  1022. Base = (ULONG)pImage->lpBaseOfImage;
  1023. } else {
  1024. Base = HdrBase;
  1025. }
  1026. }
  1027. BaseOffset = Base - HdrBase;
  1028. #ifdef MIPS
  1029. if (pdataSize) {
  1030. cFunctions = pdataSize / sizeof(RUNTIME_FUNCTION);
  1031. lpFunctionEntry = (PFUNCTION_ENTRY)
  1032. malloc((int)(cFunctions * sizeof(FUNCTION_ENTRY)));
  1033. if (!lpFunctionEntry) {
  1034. dprintf("KD: alloc error for exception table\n");
  1035. exit(1);
  1036. }
  1037. pImage->FunctionTable = lpFunctionEntry;
  1038. pImage->LowAddress = MAXULONG;
  1039. pImage->HighAddress = 0;
  1040. CV_SEEK(ImageReadHandle, pdataStart, SEEK_SET);
  1041. for (index = 0; index < cFunctions; index++) {
  1042. CV_READ(ImageReadHandle, (PUCHAR)&RuntimeFunction,
  1043. sizeof(RUNTIME_FUNCTION));
  1044. if (RuntimeFunction.BeginAddress == 0)
  1045. break;
  1046. //
  1047. // Update the addresses with the new base address for the image.
  1048. //
  1049. RuntimeFunction.BeginAddress += BaseOffset;
  1050. RuntimeFunction.PrologEndAddress += BaseOffset;
  1051. RuntimeFunction.EndAddress += BaseOffset;
  1052. lpFunctionEntry[index].StartingAddress =
  1053. RuntimeFunction.BeginAddress;
  1054. if (RuntimeFunction.BeginAddress < pImage->LowAddress)
  1055. pImage->LowAddress = RuntimeFunction.BeginAddress;
  1056. lpFunctionEntry[index].EndingAddress = RuntimeFunction.EndAddress;
  1057. if (RuntimeFunction.EndAddress > pImage->HighAddress)
  1058. pImage->HighAddress = RuntimeFunction.EndAddress;
  1059. lpFunctionEntry[index].EndOfPrologue =
  1060. RuntimeFunction.PrologEndAddress;
  1061. }
  1062. }
  1063. pImage->NumberOfFunctions = cFunctions;
  1064. #endif
  1065. symsize = IMAGE_SIZEOF_SYMBOL;
  1066. CV_SEEK(ImageReadHandle, StartDebugInfo + DebugInfo.LvaToFirstSymbol
  1067. + DebugInfo.NumberOfSymbols * symsize, SEEK_SET);
  1068. CV_READ(ImageReadHandle, (PUCHAR)&StringTableSize, sizeof(ULONG));
  1069. if (StringTableSize > sizeof(ULONG)) {
  1070. #ifdef NT_HOST
  1071. // BUGBUG - W-Barry - 30-Apr-91 - Replacing call to halloc with a call
  1072. // to calloc. Halloc seems to be no longer in the 32-bit libraries.
  1073. if (!(StringTable = (PUCHAR)calloc(StringTableSize, 1))) {
  1074. #else
  1075. if (!(StringTable = (PUCHAR)halloc(StringTableSize, 1))) {
  1076. #endif
  1077. #ifdef NT_SAPI
  1078. SHerror = sheOutOfMemory;
  1079. return;
  1080. #else
  1081. dprintf("KD: alloc error for string table\n");
  1082. exit(1);
  1083. #endif
  1084. }
  1085. needr = StringTableSize - sizeof(ULONG);
  1086. p = StringTable;
  1087. while (needr) {
  1088. maxr = (unsigned int)min(needr, 0x8000);
  1089. n = CV_READ(ImageReadHandle, (char far *)p, maxr);
  1090. p += n;
  1091. needr -= n;
  1092. }
  1093. StringTable -= sizeof(ULONG);
  1094. }
  1095. // convert the name from the full path to only the filename
  1096. pszName = GetModuleName(pImage->pszName);
  1097. free(pImage->pszName); // remove entry pathname
  1098. pImage->pszName = pszName;
  1099. pImage->offsetLow = 0xffffffff;
  1100. pImage->offsetHigh = 0x0;
  1101. // seek to start of symbol table and read each entry
  1102. CV_SEEK(ImageReadHandle, StartDebugInfo + DebugInfo.LvaToFirstSymbol, SEEK_SET);
  1103. for (entrycount = 0; entrycount < DebugInfo.NumberOfSymbols;
  1104. entrycount++) {
  1105. CV_READ(ImageReadHandle, (PUCHAR)&SymbolEntry, symsize);
  1106. auxcount = SymbolEntry.NumberOfAuxSymbols;
  1107. switch (SymbolEntry.StorageClass) {
  1108. case IMAGE_SYM_CLASS_FILE:
  1109. // allocate and read the pathname from the following
  1110. // auxiliary entries.
  1111. pPathname = realloc(pPathname, (int)(auxcount * symsize + 1));
  1112. CV_READ(ImageReadHandle, pPathname, (int)(auxcount * symsize));
  1113. // TEMP TEMP TEMP - pack entries 14/18 chars into string
  1114. // PackAuxNameEntry(pPathname, auxcount);
  1115. *(pPathname + auxcount * symsize) = '\0'; // TEMP TEMP TEMP
  1116. entrycount += auxcount;
  1117. auxcount = 0;
  1118. // extract the filename from the pathname as the string
  1119. // following the last '\' or ':', but not including any
  1120. // characters after '.'.
  1121. pchName = strrchr(pPathname, '\\');
  1122. if (!pchName)
  1123. pchName = strrchr(pPathname, ':');
  1124. if (!pchName)
  1125. pchName = pPathname;
  1126. else
  1127. pchName++;
  1128. cName = strcspn(pchName, ".");
  1129. // allocate a string and copy the filename part of the
  1130. // path and convert to lower case.
  1131. pFilename = realloc(pFilename, cName + 1);
  1132. strncpy(pFilename, pchName, cName);
  1133. *(pFilename + cName) = '\0';
  1134. _strlwr(pFilename);
  1135. // allocate a string and copy the extension part of the
  1136. // path, if any, and convert to lower case.
  1137. pExtension = realloc(pExtension, strlen(pchName + cName) + 1);
  1138. strcpy(pExtension, pchName + cName);
  1139. _strlwr(pExtension);
  1140. // remove filename and extension from pathname by
  1141. // null-terminating at the start of the filename
  1142. // BUT, if null pathname, put in ".\" since a null
  1143. // is interpreted as NO PATH available.
  1144. if (pchName == pPathname) {
  1145. *pchName++ = '.';
  1146. *pchName++ = '\\';
  1147. }
  1148. *pchName = '\0';
  1149. break;
  1150. case IMAGE_SYM_CLASS_STATIC:
  1151. if ( SymbolEntry.SectionNumber > 0 &&
  1152. SymbolEntry.Type == IMAGE_SYM_TYPE_NULL &&
  1153. auxcount == 1) {
  1154. index = SymbolEntry.SectionNumber - 1;
  1155. CV_READ(ImageReadHandle, (PUCHAR)&AuxSymbolEntry, symsize);
  1156. entrycount += auxcount;
  1157. auxcount = 0;
  1158. if (AuxSymbolEntry.Section.Length &&
  1159. AuxSymbolEntry.Section.NumberOfLinenumbers) {
  1160. seekSave = CV_TELL(ImageReadHandle);
  1161. CV_SEEK(ImageReadHandle, pNextLinenumber, SEEK_SET);
  1162. pLinenumbers = (PIMAGE_LINENUMBER)realloc(
  1163. (PUCHAR)pLinenumbers,
  1164. sizeof(IMAGE_LINENUMBER) *
  1165. (int)AuxSymbolEntry.Section.NumberOfLinenumbers);
  1166. CV_READ(ImageReadHandle, (PUCHAR)pLinenumbers,
  1167. sizeof(IMAGE_LINENUMBER)
  1168. * (int)AuxSymbolEntry.Section.NumberOfLinenumbers);
  1169. pNextLinenumber = CV_TELL(ImageReadHandle);
  1170. for (ind = 0; ind < AuxSymbolEntry.Section.NumberOfLinenumbers;
  1171. ind++)
  1172. pLinenumbers[ind].Type.VirtualAddress
  1173. += Base;
  1174. InsertSymfile(pPathname, pFilename, pExtension,
  1175. pLinenumbers,
  1176. AuxSymbolEntry.Section.NumberOfLinenumbers,
  1177. SymbolEntry.Value + Base,
  1178. SymbolEntry.Value + Base
  1179. + AuxSymbolEntry.Section.Length,
  1180. pImage->index);
  1181. ////////////////
  1182. #if 0
  1183. dprintf("\npath: <%s> file: <%s> ext: <%s> "
  1184. "start: %08lx end: %08lx\n",
  1185. pPathname, pFilename, pExtension,
  1186. SymbolEntry.Value,
  1187. SymbolEntry.Value
  1188. + AuxSymbolEntry.Section.Length);
  1189. dprintf("section %ld - length: %lx "
  1190. "line number cnt: %d\n",
  1191. index, AuxSymbolEntry.Section.Length,
  1192. AuxSymbolEntry.Section.NumberOfLinenumbers);
  1193. for (index = 0; index < AuxSymbolEntry.Section.NumberOfLinenumbers;
  1194. index++)
  1195. dprintf("index %ld, address: %08lx, "
  1196. "line number %d\n", index,
  1197. (pLinenumbers + index)->
  1198. Type.VirtualAddress,
  1199. (pLinenumbers + index)->Linenumber);
  1200. #endif
  1201. /////////////////
  1202. CV_SEEK(ImageReadHandle, seekSave, SEEK_SET);
  1203. }
  1204. }
  1205. // else
  1206. // dprintf("STATIC class entry\n");
  1207. break;
  1208. case IMAGE_SYM_CLASS_EXTERNAL:
  1209. if (SymbolEntry.N.Name.Short) {
  1210. strncpy(ShortString, SymbolEntry.N.ShortName, 8);
  1211. ShortString[8] = '\0';
  1212. SymbolName = ShortString;
  1213. }
  1214. else {
  1215. //
  1216. // if this is a huge string table and the symbol
  1217. // is near a 64k boundary, then copy it by hand;
  1218. //
  1219. if (StringTableSize & 0xffff0000) {
  1220. p = StringTable + SymbolEntry.N.Name.Long;
  1221. if ((ULONG)((ULONG)p & 0x0000ff00) == 0x0000ff00) {
  1222. SymbolName = buff;
  1223. while (*p)
  1224. *SymbolName++ = *p++;
  1225. *SymbolName = '\0';
  1226. SymbolName = buff;
  1227. }
  1228. else
  1229. SymbolName = p;
  1230. }
  1231. else
  1232. SymbolName = StringTable + SymbolEntry.N.Name.Long;
  1233. }
  1234. if (SymbolEntry.Value) {
  1235. SymbolValue = SymbolEntry.Value + Base;
  1236. pNewSymbol = InsertSymbol(SymbolValue, SymbolName,
  1237. pImage->index);
  1238. #ifdef NT_SAPI
  1239. if (pNewSymbol) {
  1240. if (auxcount) {
  1241. entrycount++;
  1242. auxcount--;
  1243. CV_READ(ImageReadHandle,&AuxSymbolEntry,symsize);
  1244. }
  1245. else
  1246. memset( &AuxSymbolEntry, 0, symsize);
  1247. TH_SetupCVpublic( pImage, pNewSymbol,
  1248. &SymbolEntry, &AuxSymbolEntry);
  1249. }
  1250. #endif /* NT_SAPI */
  1251. if (SymbolValue > pImage->offsetHigh)
  1252. pImage->offsetHigh = SymbolValue;
  1253. if (SymbolValue < pImage->offsetLow)
  1254. pImage->offsetLow = SymbolValue;
  1255. symbolcount++;
  1256. // dprintf("mod: %s value: %08lx symbol: %s\n",
  1257. // pszName, SymbolValue, SymbolName);
  1258. // if (symbolcount % 100 == 0)
  1259. // dprintf("KD: module \"%s\" loaded %ld "
  1260. // "symbols\r", pszName, symbolcount);
  1261. }
  1262. break;
  1263. case IMAGE_SYM_CLASS_STRUCT_TAG:
  1264. if (SymbolEntry.N.Name.Short) {
  1265. strncpy(ShortString, SymbolEntry.N.ShortName, 8);
  1266. ShortString[8] = '\0';
  1267. SymbolName = ShortString;
  1268. }
  1269. else {
  1270. if (StringTableSize & 0xffff0000) {
  1271. p = StringTable + SymbolEntry.N.Name.Long;
  1272. if ((ULONG)((ULONG)p & 0x0000ff00) == 0x0000ff00) {
  1273. SymbolName = buff;
  1274. while (*p)
  1275. *SymbolName++ = *p++;
  1276. *SymbolName = '\0';
  1277. SymbolName = buff;
  1278. }
  1279. else
  1280. SymbolName = p;
  1281. }
  1282. else
  1283. SymbolName = StringTable + SymbolEntry.N.Name.Long;
  1284. }
  1285. pCurrentStructure = InsertStructure(entrycount,SymbolName,
  1286. pImage->index);
  1287. break;
  1288. case IMAGE_SYM_CLASS_FUNCTION:
  1289. if (SymbolEntry.N.Name.Short) {
  1290. strncpy(ShortString, SymbolEntry.N.ShortName, 8);
  1291. ShortString[8] = '\0';
  1292. SymbolName = ShortString;
  1293. }
  1294. else {
  1295. if (StringTableSize & 0xffff0000) {
  1296. p = StringTable + SymbolEntry.N.Name.Long;
  1297. if ((ULONG)((ULONG)p & 0x0000ff00) == 0x0000ff00) {
  1298. SymbolName = buff;
  1299. while (*p)
  1300. *SymbolName++ = *p++;
  1301. *SymbolName = '\0';
  1302. SymbolName = buff;
  1303. }
  1304. else
  1305. SymbolName = p;
  1306. }
  1307. else
  1308. SymbolName = StringTable + SymbolEntry.N.Name.Long;
  1309. }
  1310. if (strcmp(SymbolName,".bf")) {
  1311. #ifdef NT_SAPI
  1312. // End of Function setup CV types!!
  1313. if ( pCurrentFunction && pNewSymbol)
  1314. TH_SetupCVfunction( pImage,
  1315. pCurrentFunction,
  1316. pNewSymbol);
  1317. #endif /* NT_SAPI */
  1318. break;
  1319. }
  1320. if (SymbolEntry.Value && pNewSymbol) {
  1321. SymbolValue = SymbolEntry.Value +
  1322. (ULONG)pImage->lpBaseOfImage;
  1323. pCurrentFunction =
  1324. InsertFunction(pNewSymbol->string, pNewSymbol->offset);
  1325. }
  1326. break;
  1327. case IMAGE_SYM_CLASS_AUTOMATIC:
  1328. case IMAGE_SYM_CLASS_ARGUMENT:
  1329. case IMAGE_SYM_CLASS_REGISTER:
  1330. case IMAGE_SYM_CLASS_MEMBER_OF_STRUCT:{
  1331. ULONG auxValue;
  1332. if (SymbolEntry.Value==-1L) break;
  1333. if (SymbolEntry.N.Name.Short) {
  1334. strncpy(ShortString, SymbolEntry.N.ShortName, 8);
  1335. ShortString[8] = '\0';
  1336. SymbolName = ShortString;
  1337. }
  1338. else {
  1339. if (!SymbolEntry.N.Name.Long) break;
  1340. if (StringTableSize & 0xffff0000) {
  1341. p = StringTable + SymbolEntry.N.Name.Long;
  1342. if ((ULONG)((ULONG)p & 0x0000ff00) == 0x0000ff00) {
  1343. SymbolName = buff;
  1344. while (*p)
  1345. *SymbolName++ = *p++;
  1346. *SymbolName = '\0';
  1347. SymbolName = buff;
  1348. }
  1349. else
  1350. SymbolName = p;
  1351. }
  1352. else
  1353. SymbolName = StringTable + SymbolEntry.N.Name.Long;
  1354. }
  1355. // If we have a aux entry read it in, otherwise zero it
  1356. if (auxcount) {
  1357. entrycount++;
  1358. auxcount--;
  1359. CV_READ(ImageReadHandle, &AuxSymbolEntry, symsize);
  1360. }
  1361. else
  1362. memset( &AuxSymbolEntry, 0, symsize);
  1363. // Structures need the tag index
  1364. if (SymbolEntry.Type == IMAGE_SYM_TYPE_STRUCT)
  1365. auxValue = AuxSymbolEntry.Sym.TagIndex;
  1366. SymbolValue = SymbolEntry.Value;
  1367. if(SymbolEntry.StorageClass!=IMAGE_SYM_CLASS_MEMBER_OF_STRUCT){
  1368. // dprintf("\t[LOCAL:%s, value=%ld, aux=%lx]\n",
  1369. // SymbolName, SymbolValue, auxValue);
  1370. AddLocalToFunction(pCurrentFunction,SymbolName,SymbolValue,
  1371. SymbolEntry.Type, auxValue);
  1372. #ifdef NT_SAPI
  1373. if ( pCurrentFunction && pCurrentFunction->pLocal )
  1374. TH_SetupCVlocal( pImage, pCurrentFunction->pLocal,
  1375. &SymbolEntry, &AuxSymbolEntry);
  1376. #endif /* NT_SAPI */
  1377. }
  1378. else{
  1379. // dprintf("\t[FIELD:%s, type=%ld, value=%ld]\n",
  1380. // SymbolName, SymbolEntry.Type, SymbolValue);
  1381. AddFieldToStructure(pCurrentStructure, SymbolName,
  1382. SymbolValue,SymbolEntry.Type, auxValue);
  1383. #ifdef NT_SAPI
  1384. if ( pCurrentStructure && pCurrentStructure->pField)
  1385. TH_SetupCVfield( pImage, pCurrentStructure->pField,
  1386. &SymbolEntry, &AuxSymbolEntry);
  1387. #endif /* NT_SAPI */
  1388. }
  1389. }
  1390. break;
  1391. #ifdef NT_SAPI
  1392. case IMAGE_SYM_CLASS_END_OF_STRUCT:
  1393. if ( pCurrentStructure ) {
  1394. if (auxcount) {
  1395. entrycount++;
  1396. auxcount--;
  1397. CV_READ(ImageReadHandle,&AuxSymbolEntry,symsize);
  1398. }
  1399. else
  1400. memset( &AuxSymbolEntry, 0, symsize);
  1401. TH_SetupCVstruct( pImage, pCurrentStructure,
  1402. &SymbolEntry, &AuxSymbolEntry);
  1403. }
  1404. break;
  1405. #endif /* NT_SAPI */
  1406. default:
  1407. // dprintf("OTHER class entry - class: %d\n",
  1408. // SymbolEntry.StorageClass);
  1409. break;
  1410. }
  1411. // auxcount has the number of unprocessed auxiliary entries
  1412. // skip over them for the next table entry
  1413. entrycount += auxcount;
  1414. CV_SEEK(ImageReadHandle, symsize * auxcount, SEEK_CUR);
  1415. }
  1416. if (StringTable) {
  1417. StringTable += sizeof(ULONG);
  1418. #ifdef NT_HOST
  1419. // BUGBUG W-Barry 30-Apr-91 Replaced hfree call with free - same as
  1420. // with calloc above...
  1421. free(StringTable);
  1422. #else
  1423. hfree(StringTable);
  1424. #endif
  1425. }
  1426. if (fVerboseOutput) {
  1427. #ifdef MIPS
  1428. dprintf("KD: \"%s\" loaded %ld symbols, %ld functions (%08lx-%08lx)\n",
  1429. pszName, symbolcount, pImage->NumberOfFunctions,
  1430. pImage->offsetLow, pImage->offsetHigh);
  1431. #else
  1432. dprintf("KD: \"%s\" loaded %ld symbols (%08lx-%08lx)\n",
  1433. pszName, symbolcount,
  1434. pImage->offsetLow, pImage->offsetHigh);
  1435. #endif
  1436. }
  1437. free(pExtension);
  1438. free(pFilename);
  1439. free(pPathname);
  1440. free(pLinenumbers);
  1441. #ifndef NT_SAPI
  1442. CV_CLOSE(ImageReadHandle);
  1443. #endif
  1444. }
  1445. #endif
  1446. // TEMP TEMP TEMP - pack string with 14 characters out of 18 into
  1447. // string in place.
  1448. void PackAuxNameEntry (PUCHAR pPathname, ULONG auxcount)
  1449. {
  1450. PUCHAR pchDst;
  1451. PUCHAR pchSrc;
  1452. pchDst = pPathname + 14;
  1453. pchSrc = pPathname + 18;
  1454. while (auxcount-- > 1) {
  1455. memcpy(pchDst, pchSrc, 14);
  1456. pchDst += 14;
  1457. pchSrc += 18;
  1458. }
  1459. *pchDst = '\0';
  1460. }
  1461. void UnloadSymbols (PIMAGE_INFO pImage)
  1462. {
  1463. PSYMBOL pSymbol;
  1464. PSYMFILE pSymfile;
  1465. PNODE pNode;
  1466. PNODE pNodeNext;
  1467. // if module was never loaded, nothing to unload,
  1468. // just close open file handle and return
  1469. if (fLazyLoad && !pImage->fSymbolsLoaded)
  1470. {
  1471. #ifdef KERNEL
  1472. if (fVerboseOutput)
  1473. dprintf("KD: unloading \"%s\" (deferred)\n", pImage->pszName);
  1474. #else
  1475. CloseHandle(pImage->hFile);
  1476. #endif
  1477. return;
  1478. }
  1479. if (fVerboseOutput)
  1480. #ifdef KERNEL
  1481. dprintf("KD: unloading symbols for \"%s\"\n", pImage->pszName);
  1482. #else
  1483. dprintf("NTSD: unloading symbols for \"%s\"\n", pImage->pszName);
  1484. #endif
  1485. free(pImage->pszName);
  1486. #if defined(MIPS)
  1487. // for MIPS debugger, free the function entry table
  1488. if (pImage->NumberOfFunctions)
  1489. free(pImage->FunctionTable);
  1490. #endif
  1491. ////////////////////////////////////////////////////////////////
  1492. // delete all symbol structures with the specified module index
  1493. ////////////////////////////////////////////////////////////////
  1494. // make a symbol structure with the low offset in the image
  1495. pSymbol = AllocSymbol(pImage->offsetLow, "", -1);
  1496. // try to access the node with the offset given.
  1497. // the node pointer returned will be the nearest offset less
  1498. // than the argument (unless it is less than the tree minimum)
  1499. AccessNode(&(pProcessCurrent->symcontextSymbolOffset),
  1500. &(pSymbol->nodeOffset));
  1501. pNode = pProcessCurrent->symcontextSymbolOffset.pNodeRoot;
  1502. // deallocate the temporary symbol structure
  1503. DeallocSymbol(pSymbol);
  1504. // traverse the tree and delete symbols with the specified index
  1505. // until the offset is higher than the maximum
  1506. while (pNode) {
  1507. pSymbol = PNODE_TO_PSYMBOL(pNode,
  1508. &(pProcessCurrent->symcontextSymbolOffset));
  1509. if (pSymbol->offset > pImage->offsetHigh)
  1510. break;
  1511. pNodeNext = NextNode(&(pProcessCurrent->symcontextSymbolOffset),
  1512. pNode);
  1513. if (pSymbol->modIndex == (CHAR)pImage->index) {
  1514. // dprintf("** offset: %08lx string: %s deleted\n",
  1515. // pSymbol->offset, pSymbol->string);
  1516. DeleteSymbol(pSymbol);
  1517. }
  1518. pNode = pNodeNext;
  1519. }
  1520. /////////////////////////////////////////////////////////////////////
  1521. // delete all file symbol structures with the specified module index
  1522. /////////////////////////////////////////////////////////////////////
  1523. // search all entries in the current image - get the first
  1524. pNode = NextNode(&(pProcessCurrent->symcontextSymfileOffset), NULL);
  1525. // traverse the tree and delete symbols with the specified index
  1526. // until the end of the tree.
  1527. while (pNode) {
  1528. pSymfile = PNODE_TO_PSYMFILE(pNode,
  1529. &(pProcessCurrent->symcontextSymfileOffset));
  1530. pNodeNext = NextNode(&(pProcessCurrent->symcontextSymfileOffset),
  1531. pNode);
  1532. if (pSymfile->modIndex == (CHAR)pImage->index) {
  1533. if (fVerboseOutput)
  1534. #ifdef KERNEL
  1535. dprintf("KD: symfile: \"%s\" deleted\n", pSymfile->pchName);
  1536. #else
  1537. dprintf("NTSD: symfile: \"%s\" deleted\n", pSymfile->pchName);
  1538. #endif
  1539. DeleteSymfile(pSymfile);
  1540. }
  1541. pNode = pNodeNext;
  1542. }
  1543. }
  1544. void EnsureModuleSymbolsLoaded (CHAR iModule)
  1545. {
  1546. PIMAGE_INFO pImage;
  1547. if (fLazyLoad) {
  1548. pImage = pProcessCurrent->pImageHead;
  1549. while (pImage && pImage->index != (UCHAR)iModule)
  1550. pImage = pImage->pImageNext;
  1551. if (pImage && !pImage->fSymbolsLoaded) {
  1552. // NOTE! The order of the next two statements
  1553. // are critical. Reversing them will cause
  1554. // infinite recursion to occur.
  1555. pImage->fSymbolsLoaded = TRUE;
  1556. LoadSymbols(pImage);
  1557. }
  1558. }
  1559. }
  1560. int EnsureOffsetSymbolsLoaded (ULONG offset)
  1561. {
  1562. PIMAGE_INFO pImage = pProcessCurrent->pImageHead;
  1563. PIMAGE_INFO pImageFound = NULL;
  1564. // first, scan all modules for the one which has the highest
  1565. // starting offset less than the input offset.
  1566. while (pImage) {
  1567. if (offset >= (ULONG)pImage->lpBaseOfImage &&
  1568. (!pImageFound ||
  1569. ((ULONG)pImage->lpBaseOfImage >
  1570. (ULONG)pImageFound->lpBaseOfImage)))
  1571. pImageFound = pImage;
  1572. pImage = pImage->pImageNext;
  1573. }
  1574. // continue only if a candidate was found
  1575. if (pImageFound) {
  1576. // load the candidate image if deferred
  1577. if (fLazyLoad && !pImageFound->fSymbolsLoaded) {
  1578. // NOTE! The order of the next two statements
  1579. // are critical. Reversing them will cause
  1580. // infinite recursion to occur.
  1581. pImageFound->fSymbolsLoaded = TRUE;
  1582. LoadSymbols(pImageFound);
  1583. }
  1584. // with the candidate loaded, test if offset is more
  1585. // than the highest symbol. If so, clear pImageFound
  1586. if (offset > pImageFound->offsetHigh)
  1587. pImageFound = FALSE;
  1588. }
  1589. // return flag TRUE if offset was NOT in image
  1590. return (pImageFound == NULL);
  1591. }
  1592. #ifdef KERNEL
  1593. PUCHAR GetModuleName (PUCHAR pszPath)
  1594. {
  1595. PUCHAR pszStart;
  1596. PUCHAR pszEnd;
  1597. PUCHAR pszReturn;
  1598. pszStart = pszEnd = pszPath + strlen(pszPath);
  1599. while (pszStart >= pszPath && *pszStart != ':' && *pszStart != '\\') {
  1600. if (*pszStart == '.')
  1601. pszEnd = pszStart;
  1602. pszStart--;
  1603. }
  1604. // special case for module "ntoskrnl", change to "nt"
  1605. if ((pszEnd - pszStart) == 9 && !_strnicmp(pszStart + 1, "ntoskrnl", 8))
  1606. pszEnd = pszStart + 3;
  1607. pszReturn = (PUCHAR)malloc(pszEnd - pszStart);
  1608. if (!pszReturn) {
  1609. printf("memory allocation error\n");
  1610. ExitProcess(STATUS_UNSUCCESSFUL);
  1611. }
  1612. pszStart++;
  1613. strncpy(pszReturn, pszStart, pszEnd - pszStart);
  1614. *(pszReturn + (pszEnd - pszStart)) = '\0';
  1615. return pszReturn;
  1616. }
  1617. #endif
  1618. #ifndef NT_SAPI
  1619. /*** parseExamine - parse and execute examine command
  1620. *
  1621. * Purpose:
  1622. * Parse the current command string and examine the symbol
  1623. * table to display the appropriate entries. The entries
  1624. * are displayed in increasing string order. This function
  1625. * accepts underscores, alphabetic, and numeric characters
  1626. * to match as well as the special characters '?' and '*'.
  1627. * The '?' character matches any other character while '*'
  1628. * matches any string of zero or more characters. If used,
  1629. * '*' must be the last character in the pattern.
  1630. *
  1631. * Input:
  1632. * pchCommand - pointer to current command string
  1633. *
  1634. * Output:
  1635. * offset and string name of symbols displayed
  1636. *
  1637. *************************************************************************/
  1638. void parseExamine (void)
  1639. {
  1640. UCHAR chString[60];
  1641. UCHAR ch;
  1642. PUCHAR pchString = chString;
  1643. PUCHAR pchStart;
  1644. BOOLEAN fClosure = FALSE;
  1645. BOOLEAN fOutput;
  1646. ULONG cntunderscores = 0;
  1647. ULONG count;
  1648. PSYMBOL pSymbol;
  1649. PNODE pNode;
  1650. PNODE pNodeLast;
  1651. PUCHAR pchSrc;
  1652. PUCHAR pchDst;
  1653. UCHAR chSrc;
  1654. UCHAR chDst;
  1655. int status = 0;
  1656. PIMAGE_INFO pImage;
  1657. #if defined(KERNEL)
  1658. #if defined(NT_HOST)
  1659. SetConsoleCtrlHandler( waitHandler, FALSE );
  1660. SetConsoleCtrlHandler( cmdHandler, TRUE );
  1661. #else
  1662. signal(SIGINT, ControlCHandler);
  1663. #endif
  1664. #endif
  1665. // get module pointer from name in command line (<string>!)
  1666. pImage = ParseModuleIndex();
  1667. if (!pImage)
  1668. error(VARDEF);
  1669. if (fLazyLoad && pImage != (PIMAGE_INFO)-1 && !pImage->fSymbolsLoaded) {
  1670. LoadSymbols(pImage);
  1671. pImage->fSymbolsLoaded = TRUE;
  1672. }
  1673. ch = PeekChar();
  1674. // special case the command "x*!" to dump out the module table
  1675. // and "x*!*" to dump out module table with line number information
  1676. if (pImage == (PIMAGE_INFO)-1) {
  1677. fOutput = FALSE;
  1678. if (ch == '*') {
  1679. pchCommand++;
  1680. ch = PeekChar();
  1681. fOutput = TRUE;
  1682. }
  1683. if (ch == ';' || ch == '\0') {
  1684. DumpModuleTable(fOutput);
  1685. return;
  1686. }
  1687. else
  1688. error(SYNTAX);
  1689. }
  1690. // copy invariant part of input pattern into chString
  1691. // map to upper case to find first possibility in tree
  1692. pchCommand++;
  1693. while (ch == '_') {
  1694. *pchString++ = ch;
  1695. ch = *pchCommand++;
  1696. }
  1697. pchStart = pchString;
  1698. ch = (UCHAR)toupper(ch);
  1699. while ((ch >= 'A' && ch <= 'Z') || (ch == '_')
  1700. || (ch >= '0' && ch <= '9')) {
  1701. *pchString++ = ch;
  1702. ch = (UCHAR)toupper(*pchCommand++);
  1703. }
  1704. *pchString = '\0';
  1705. if (count = pchString - pchStart) {
  1706. // if nonNULL invariant part, set search range:
  1707. // set starting node to root of invariant access
  1708. // set ending node to next after invariant incremented
  1709. // for all modules, increment last character in variable
  1710. // (because of mapping, increment 'Z' to 'z'+1 = '{')
  1711. pSymbol = AllocSymbol(0, chString, -1);
  1712. AccessNode(&(pProcessCurrent->symcontextSymbolString),
  1713. &(pSymbol->nodeString));
  1714. pNode = pProcessCurrent->symcontextSymbolString.pNodeRoot;
  1715. pchSrc = &pSymbol->string[count - 1];
  1716. if (*pchSrc == 'Z')
  1717. *pchSrc = 'z';
  1718. (*pchSrc)++;
  1719. status = AccessNode(&(pProcessCurrent->symcontextSymbolString),
  1720. &(pSymbol->nodeString));
  1721. pNodeLast = pProcessCurrent->symcontextSymbolString.pNodeRoot;
  1722. if (status == -1 && pNodeLast)
  1723. pNodeLast = NextNode(&(pProcessCurrent->symcontextSymbolString),
  1724. pNodeLast);
  1725. DeallocSymbol(pSymbol);
  1726. }
  1727. else {
  1728. // if NULL invariant part, search the whole tree:
  1729. // set starting node to first in tree;
  1730. // set ending node to last in tree
  1731. pNode = NextNode(&(pProcessCurrent->symcontextSymbolString), NULL);
  1732. pNodeLast = NULL;
  1733. }
  1734. // copy rest of pattern into chString
  1735. while ((ch >= 'A' && ch <= 'Z') || (ch == '_')
  1736. || (ch >= '0' && ch <= '9') || (ch == '?')) {
  1737. *pchString++ = ch;
  1738. ch = (UCHAR)toupper(*pchCommand++);
  1739. }
  1740. *pchString = '\0';
  1741. // set closure flag if '*' is found
  1742. if (ch == '*') {
  1743. fClosure = TRUE;
  1744. ch = *pchCommand++;
  1745. }
  1746. // error if more pattern is seen
  1747. if (ch)
  1748. error(SYNTAX);
  1749. pchCommand--;
  1750. // for each node in search range:
  1751. // match if NULL input was entered
  1752. // nonmatch if underscores differ by more than one
  1753. // match if case-insensitive match with:
  1754. // '?' matching all characters
  1755. // '*' closes match if extra input after source null
  1756. cntunderscores = pchStart - chString;
  1757. while (pNode != pNodeLast) {
  1758. pSymbol = PNODE_TO_PSYMBOL(pNode,
  1759. &(pProcessCurrent->symcontextSymbolString));
  1760. fOutput = FALSE;
  1761. if (!chString[0])
  1762. fOutput = TRUE;
  1763. else if ((cntunderscores != (ULONG)pSymbol->underscores)
  1764. && (cntunderscores + 1 != (ULONG)pSymbol->underscores))
  1765. fOutput = FALSE;
  1766. else {
  1767. pchSrc = pchStart;
  1768. pchDst = pSymbol->string;
  1769. do {
  1770. chSrc = *pchSrc++;
  1771. chDst = (UCHAR)toupper(*pchDst++);
  1772. }
  1773. while ((chSrc == chDst || chSrc == '?') && chSrc && chDst);
  1774. fOutput = (BOOLEAN)(!chSrc && (fClosure || !chDst));
  1775. }
  1776. // if flag set, output the offset and symbol string
  1777. if (fOutput && (pImage == (PIMAGE_INFO)-1
  1778. || pSymbol->modIndex == (CHAR)pImage->index)) {
  1779. dprintf("%8lx %s!", pSymbol->offset,
  1780. pImageFromIndex(pSymbol->modIndex)->pszName);
  1781. count = pSymbol->underscores;
  1782. while (count--)
  1783. dprintf("_");
  1784. dprintf("%s\t%s\n", pSymbol->string,
  1785. (pSymbol->type == SYMBOL_TYPE_EXPORT) ? "[Export]" : "");
  1786. }
  1787. pNode = NextNode(&(pProcessCurrent->symcontextSymbolString), pNode);
  1788. //#ifndef KERNEL
  1789. if (fControlC) {
  1790. fControlC = 0;
  1791. return;
  1792. }
  1793. //#endif
  1794. }
  1795. }
  1796. PIMAGE_INFO ParseModuleIndex (void)
  1797. {
  1798. PUCHAR pchCmdSaved = pchCommand;
  1799. UCHAR chName[60];
  1800. PUCHAR pchDst = chName;
  1801. UCHAR ch;
  1802. // first, parse out a possible module name, either a '*' or
  1803. // a string of 'A'-'Z', 'a'-'z', '0'-'9', '_' (or null)
  1804. ch = PeekChar();
  1805. pchCommand++;
  1806. if (ch == '*')
  1807. *pchDst = ch;
  1808. else {
  1809. while ((ch >= 'A' && ch <= 'Z')
  1810. || (ch >= 'a' && ch <= 'z')
  1811. || (ch >= '0' && ch <= '9')
  1812. || ch == '_') {
  1813. *pchDst++ = ch;
  1814. ch = *pchCommand++;
  1815. }
  1816. *pchDst = '\0';
  1817. pchCommand--;
  1818. }
  1819. // if no '!' after name and white space, then no module specified
  1820. // restore text pointer and treat as null module (PC current)
  1821. if (PeekChar() == '!')
  1822. pchCommand++;
  1823. else {
  1824. pchCommand = pchCmdSaved;
  1825. chName[0] = '\0';
  1826. }
  1827. // chName either has: '*' for all modules,
  1828. // '\0' for current module,
  1829. // nonnull string for module name.
  1830. if (chName[0] == '*')
  1831. return (PIMAGE_INFO)-1;
  1832. else if (chName[0])
  1833. return GetModuleIndex(chName);
  1834. else
  1835. return GetCurrentModuleIndex();
  1836. }
  1837. PIMAGE_INFO GetModuleIndex (PUCHAR pszName)
  1838. {
  1839. PIMAGE_INFO pImage;
  1840. pImage = pProcessCurrent->pImageHead;
  1841. while (pImage && ntsdstricmp(pszName, pImage->pszName))
  1842. pImage = pImage->pImageNext;
  1843. return pImage;
  1844. }
  1845. PIMAGE_INFO GetCurrentModuleIndex (void)
  1846. {
  1847. NT_PADDR pcvalue = GetRegPCValue();
  1848. PIMAGE_INFO pImage;
  1849. pImage = pProcessCurrent->pImageHead;
  1850. while (pImage && (Flat(pcvalue) < pImage->offsetLow
  1851. || Flat(pcvalue) > pImage->offsetHigh))
  1852. pImage = pImage->pImageNext;
  1853. return pImage;
  1854. }
  1855. static UCHAR strBlank[] = " ";
  1856. void DumpModuleTable (BOOLEAN fLineInfo)
  1857. {
  1858. PIMAGE_INFO pImage;
  1859. PNODE pNode;
  1860. PSYMFILE pSymfile;
  1861. int strBlankIndex = 7;
  1862. dprintf("start end module name\n");
  1863. pImage = pProcessCurrent->pImageHead;
  1864. while (pImage) {
  1865. if (pImage->fSymbolsLoaded && pImage->offsetLow != 0xffffffff)
  1866. dprintf("%08lx %08lx", pImage->offsetLow, pImage->offsetHigh);
  1867. else
  1868. dprintf("%08lx ", pImage->lpBaseOfImage);
  1869. dprintf(" %s", pImage->pszName);
  1870. if (strlen(pImage->pszName) < 8)
  1871. strBlankIndex = strlen(pImage->pszName);
  1872. if (!pImage->fSymbolsLoaded)
  1873. dprintf("%s(load deferred)", &strBlank[strBlankIndex]);
  1874. else if (pImage->offsetLow == 0xffffffff)
  1875. dprintf("%s(no symbolic information)", &strBlank[strBlankIndex]);
  1876. dprintf("\n");
  1877. if (pImage->fSymbolsLoaded && fLineInfo) {
  1878. pNode = NextNode(&(pProcessCurrent->symcontextSymfileString),
  1879. NULL);
  1880. if (pNode) {
  1881. printf(" lines filename start pathname\n");
  1882. do {
  1883. pSymfile = PNODE_TO_PSYMFILE(pNode,
  1884. &(pProcessCurrent->symcontextSymfileString));
  1885. if (pSymfile->modIndex == (CHAR)pImage->index) {
  1886. dprintf(" %6d %-8s %08lx ", pSymfile->cLineno,
  1887. pSymfile->pchName, pSymfile->startOffset);
  1888. if (pSymfile->pchPath)
  1889. dprintf("%s%s%s", pSymfile->pchPath,
  1890. pSymfile->pchName, pSymfile->pchExtension);
  1891. dprintf("\n");
  1892. }
  1893. pNode = NextNode(
  1894. &(pProcessCurrent->symcontextSymfileString), pNode);
  1895. }
  1896. while (pNode);
  1897. }
  1898. }
  1899. pImage = pImage->pImageNext;
  1900. }
  1901. }
  1902. #endif /* NT_SAPI */
  1903. /*** AccessNode - access and splay node
  1904. *
  1905. * Purpose:
  1906. * Search a tree for a node and splay it.
  1907. *
  1908. * Input:
  1909. * pSymContext - pointer to context of tree
  1910. * pNodeAccess - pointer to node with access value set
  1911. *
  1912. * Output:
  1913. * tree splayed with new node at its root
  1914. * Returns:
  1915. * value of success:
  1916. * 1 = root is smallest value larger than input value
  1917. * (not found, no lesser value)
  1918. * 0 = root is input value (value found in tree)
  1919. * -1 = root is largest value less than input value
  1920. * (not found in tree)
  1921. *
  1922. * Notes:
  1923. * splay is done with resulting root
  1924. * if root is less than input value, a secondary splay is done
  1925. * to make the next node the right child of the root
  1926. *
  1927. *************************************************************************/
  1928. int AccessNode (PSYMCONTEXT pSymContext, PNODE pNodeAccess)
  1929. {
  1930. PNODE *ppNodeRoot = &(pSymContext->pNodeRoot);
  1931. PNODE pNentry = *ppNodeRoot;
  1932. PNODE pNminimum = NULL;
  1933. PNODE pNmaximum = NULL;
  1934. PNODE pNweakcmp = NULL;
  1935. PNODE pRootTemp;
  1936. BOOLEAN fWeakCmp;
  1937. int cmp;
  1938. // return 1 if empty tree
  1939. if (!pNentry)
  1940. return 1;
  1941. // search until value is found or terminating node
  1942. do {
  1943. // context-specific comparison routine compares values
  1944. // pointed by pNodeAccess and pNentry
  1945. cmp = (*(pSymContext->pfnCompare))(pNodeAccess, pNentry, &fWeakCmp);
  1946. // fWeakcmp is set if weak comparison, used if no
  1947. // true comparison is found
  1948. if (fWeakCmp)
  1949. pNweakcmp = pNentry;
  1950. // for unequal results, set minimum and maximum entry
  1951. // searched as tree is search for node
  1952. if (cmp == -1) {
  1953. pNmaximum = pNentry;
  1954. pNentry = pNentry->pLchild;
  1955. }
  1956. else {
  1957. pNminimum = pNentry;
  1958. pNentry = pNentry->pRchild;
  1959. }
  1960. }
  1961. while (pNentry && cmp);
  1962. // if no stong match found, but weak one was, use it
  1963. if (cmp && pNweakcmp) {
  1964. cmp = 0;
  1965. pNminimum = pNweakcmp;
  1966. }
  1967. // splay tree so minimum node is at root, but use maximum
  1968. // if no minimum node
  1969. *ppNodeRoot = SplayTree(pNminimum ? pNminimum : pNmaximum);
  1970. // if node not found, set result for value used in splay
  1971. if (cmp != 0)
  1972. cmp = pNminimum ? -1 : 1;
  1973. // if node not found and both minimum and maximum nodes
  1974. // were found, splay the next node as the right child of
  1975. // the root. this new node will not have a left child,
  1976. // and assists future accesses in some cases
  1977. if (cmp == -1 && pNminimum && pNmaximum) {
  1978. pRootTemp = pNminimum->pRchild;
  1979. pRootTemp->pParent = NULL;
  1980. pNmaximum = SplayTree(pNmaximum);
  1981. pNminimum->pRchild = pNmaximum;
  1982. pNmaximum->pParent = pNminimum;
  1983. }
  1984. return cmp;
  1985. }
  1986. /*** CompareSymbolOffset - comparison routine for symbol offsets
  1987. *
  1988. * Purpose:
  1989. * Compare two nodes in the offset tree. The ordering
  1990. * comparisons used are offset and string. The string
  1991. * comparison is done since and offset can have more than
  1992. * one string associated with it.
  1993. *
  1994. * Input:
  1995. * pNode1 - pointer to first node - usually the new one
  1996. * pNode2 - pointer to second node - usually in the tree searched
  1997. *
  1998. * Output:
  1999. * pfWeakCmp - always FALSE - comparisons are exact or they fail
  2000. *
  2001. * Returns:
  2002. * value of comparison result:
  2003. * -1 = value(pNode1) < value(pNode2)
  2004. * 0 = value(pNode1) == value(pNode2)
  2005. * 1 = value(pNode1) > value(pNode2)
  2006. *
  2007. *************************************************************************/
  2008. int CompareSymbolOffset (PNODE pNode1, PNODE pNode2, PBOOLEAN pfWeakCmp)
  2009. {
  2010. int cmp;
  2011. PSYMBOL pSymbol1 = CONTAINING_RECORD(pNode1, SYMBOL, nodeOffset);
  2012. PSYMBOL pSymbol2 = CONTAINING_RECORD(pNode2, SYMBOL, nodeOffset);
  2013. *pfWeakCmp = FALSE;
  2014. // compare offsets of the nodes
  2015. if (pSymbol1->offset < pSymbol2->offset)
  2016. cmp = -1;
  2017. else if (pSymbol1->offset > pSymbol2->offset)
  2018. cmp = 1;
  2019. // if the first node string is null, assume node is being
  2020. // searched for in tree, so report equality
  2021. else if (pSymbol1->string[0] == '\0')
  2022. cmp = 0;
  2023. // else the first node string is nonnull, and node is being
  2024. // inserted, so further test the string equality: case-
  2025. // insensitive search, underscore count, case-sensitive search
  2026. else {
  2027. cmp = ntsdstricmp(pSymbol1->string, pSymbol2->string);
  2028. if (!cmp) {
  2029. if (pSymbol1->underscores < pSymbol2->underscores)
  2030. cmp = -1;
  2031. else if (pSymbol1->underscores > pSymbol2->underscores)
  2032. cmp = 1;
  2033. else {
  2034. cmp = strcmp(pSymbol1->string, pSymbol2->string);
  2035. if (!cmp) {
  2036. if (pSymbol1->modIndex < pSymbol2->modIndex)
  2037. cmp = -1;
  2038. else if (pSymbol1->modIndex > pSymbol2->modIndex)
  2039. cmp = 1;
  2040. }
  2041. }
  2042. }
  2043. }
  2044. return cmp;
  2045. }
  2046. /*** CompareSymfileOffset - comparison routine for symbol file offsets
  2047. *
  2048. * Purpose:
  2049. * Compare two nodes in the symbol file offset tree. The ordering
  2050. * comparisons used are offset and string. The string
  2051. * comparison is done since and offset can have more than
  2052. * one string associated with it.
  2053. *
  2054. * Input:
  2055. * pNode1 - pointer to first node - usually the new one
  2056. * pNode2 - pointer to second node - usually in the tree searched
  2057. *
  2058. * Output:
  2059. * pfWeakCmp - always FALSE - comparisons are exact or they fail
  2060. *
  2061. * Returns:
  2062. * value of comparison result:
  2063. * -1 = value(pNode1) < value(pNode2)
  2064. * 0 = value(pNode1) == value(pNode2)
  2065. * 1 = value(pNode1) > value(pNode2)
  2066. *
  2067. *************************************************************************/
  2068. int CompareSymfileOffset (PNODE pNode1, PNODE pNode2, PBOOLEAN pfWeakCmp)
  2069. {
  2070. int cmp = 0;
  2071. PSYMFILE pSymfile1 = CONTAINING_RECORD(pNode1, SYMFILE, nodeOffset);
  2072. PSYMFILE pSymfile2 = CONTAINING_RECORD(pNode2, SYMFILE, nodeOffset);
  2073. *pfWeakCmp = FALSE;
  2074. // test if performing an insertion (pSymfile1->pLineno == NULL)
  2075. // a search (search only has offset defined in cLineno)
  2076. if (pSymfile1->pLineno) {
  2077. // compare starting offsets of the nodes
  2078. if (pSymfile1->startOffset < pSymfile2->startOffset)
  2079. cmp = -1;
  2080. else if (pSymfile1->startOffset > pSymfile2->startOffset)
  2081. cmp = 1;
  2082. // if same offset, further test the file and module equality
  2083. else {
  2084. cmp = strcmp(pSymfile1->pchName, pSymfile2->pchName);
  2085. if (!cmp) {
  2086. if (pSymfile1->modIndex < pSymfile2->modIndex)
  2087. cmp = -1;
  2088. else if (pSymfile1->modIndex > pSymfile2->modIndex)
  2089. cmp = 1;
  2090. }
  2091. }
  2092. }
  2093. else {
  2094. // search - test search offset in node against range
  2095. if (pSymfile1->startOffset < pSymfile2->startOffset)
  2096. cmp = -1;
  2097. else if (pSymfile1->startOffset > pSymfile2->endOffset)
  2098. cmp = 1;
  2099. }
  2100. return cmp;
  2101. }
  2102. /*** CompareSymbolString - comparison routine for symbol strings
  2103. *
  2104. * Purpose:
  2105. * Compare two nodes in the string tree. The ordering
  2106. * comparisons used are case-insensitivity, underscore
  2107. * count, module ordering, and case-sensitivity.
  2108. *
  2109. * Input:
  2110. * pNode1 - pointer to first node - usually the new one
  2111. * pNode2 - pointer to second node - usually in the tree searched
  2112. *
  2113. * Output:
  2114. * pfWeakCmp - TRUE if case-insensitive and underscores match
  2115. * FALSE otherwise (defined only if cmp nonzero)
  2116. *
  2117. * Returns:
  2118. * value of comparison result:
  2119. * -1 = value(pNode1) < value(pNode2)
  2120. * 0 = value(pNode1) == value(pNode2)
  2121. * 1 = value(pNode1) > value(pNode2)
  2122. *
  2123. *************************************************************************/
  2124. int CompareSymbolString (PNODE pNode1, PNODE pNode2, PBOOLEAN pfWeakCmp)
  2125. {
  2126. int cmp;
  2127. PSYMBOL pSymbol1 = CONTAINING_RECORD(pNode1, SYMBOL, nodeString);
  2128. PSYMBOL pSymbol2 = CONTAINING_RECORD(pNode2, SYMBOL, nodeString);
  2129. *pfWeakCmp = FALSE;
  2130. // compare case-insensitive value of the nodes
  2131. cmp = ntsdstricmp(pSymbol1->string, pSymbol2->string);
  2132. if (!cmp) {
  2133. // compare underscore counts of the nodes
  2134. if (pSymbol1->underscores < pSymbol2->underscores)
  2135. cmp = -1;
  2136. else if (pSymbol1->underscores > pSymbol2->underscores)
  2137. cmp = 1;
  2138. else {
  2139. // if null string in first node, then searching, not inserting
  2140. if (pSymbol1->offset == 0)
  2141. // test module index for weak comparison indication
  2142. // index of -1 is for no module, weakly match any
  2143. if (pSymbol1->modIndex == (CHAR)-1 ||
  2144. pSymbol1->modIndex == pSymbol2->modIndex)
  2145. *pfWeakCmp = TRUE;
  2146. // test for ordering due to module index
  2147. if (pSymbol1->modIndex == (CHAR)-1 ||
  2148. pSymbol1->modIndex < pSymbol2->modIndex)
  2149. cmp = -1;
  2150. else if (pSymbol1->modIndex > pSymbol2->modIndex)
  2151. cmp = 1;
  2152. else
  2153. // final test for strong match is case-sensitive comparison
  2154. cmp = strcmp(pSymbol1->string, pSymbol2->string);
  2155. }
  2156. }
  2157. return cmp;
  2158. }
  2159. /*** CompareSymfileString - comparison routine for symbol file strings
  2160. *
  2161. * Purpose:
  2162. * Compare two nodes in the string tree. The ordering
  2163. * comparisons used are case-insensitivity, underscore
  2164. * count, module ordering, and case-sensitivity.
  2165. *
  2166. * Input:
  2167. * pNode1 - pointer to first node - usually the new one
  2168. * pNode2 - pointer to second node - usually in the tree searched
  2169. *
  2170. * Output:
  2171. * pfWeakCmp - TRUE if case-insensitive and underscores match
  2172. * FALSE otherwise (defined only if cmp nonzero)
  2173. *
  2174. * Returns:
  2175. * value of comparison result:
  2176. * -1 = value(pNode1) < value(pNode2)
  2177. * 0 = value(pNode1) == value(pNode2)
  2178. * 1 = value(pNode1) > value(pNode2)
  2179. *
  2180. *************************************************************************/
  2181. int CompareSymfileString (PNODE pNode1, PNODE pNode2, PBOOLEAN pfWeakCmp)
  2182. {
  2183. int cmp;
  2184. PSYMFILE pSymfile1 = CONTAINING_RECORD(pNode1, SYMFILE, nodeString);
  2185. PSYMFILE pSymfile2 = CONTAINING_RECORD(pNode2, SYMFILE, nodeString);
  2186. *pfWeakCmp = FALSE;
  2187. // compare case-sensitive value of the filenames
  2188. cmp = strcmp(pSymfile1->pchName, pSymfile2->pchName);
  2189. if (!cmp) {
  2190. // if filenames match, test for module index
  2191. if (pSymfile1->modIndex < pSymfile2->modIndex)
  2192. cmp = -1;
  2193. else if (pSymfile1->modIndex > pSymfile2->modIndex)
  2194. cmp = 1;
  2195. // test if searching rather than inserting, a
  2196. // search structure has pLineno NULL and
  2197. // cLineno has the line number to search
  2198. else if (pSymfile1->pLineno != NULL) {
  2199. // inserting, so order on starting line number
  2200. // (this is the second item of the list)
  2201. if ((pSymfile1->pLineno + 1)->breakLineNumber
  2202. < (pSymfile2->pLineno + 1)->breakLineNumber)
  2203. cmp = -1;
  2204. else if ((pSymfile1->pLineno + 1)->breakLineNumber
  2205. > (pSymfile2->pLineno + 1)->breakLineNumber)
  2206. cmp = 1;
  2207. }
  2208. else {
  2209. // for viewing lines, set a weak match to TRUE
  2210. *pfWeakCmp = TRUE;
  2211. // searching, test for line number within the range
  2212. // defined in the structure
  2213. if (pSymfile1->cLineno
  2214. < (pSymfile2->pLineno + 1)->breakLineNumber)
  2215. cmp = -1;
  2216. else if (pSymfile1->cLineno
  2217. > (pSymfile2->pLineno
  2218. + pSymfile2->cLineno)->breakLineNumber)
  2219. cmp = 1;
  2220. }
  2221. }
  2222. return cmp;
  2223. }
  2224. /*** InsertSymbol - insert offset and string into new symbol
  2225. *
  2226. * Purpose:
  2227. * external routine.
  2228. * Allocate and insert a new symbol into the offset and
  2229. * string trees.
  2230. *
  2231. * Input:
  2232. * insertvalue - offset value of new symbol
  2233. * pinsertstring - string value if new symbol
  2234. *
  2235. * Output:
  2236. * None.
  2237. *
  2238. * Notes:
  2239. * Uses the routine InsertNode for both offset and string
  2240. * through different contexts.
  2241. *
  2242. *************************************************************************/
  2243. PSYMBOL InsertSymbol (ULONG insertvalue, PUCHAR pinsertstring,
  2244. CHAR insertmod)
  2245. {
  2246. PSYMBOL pSymbol;
  2247. pSymbol = AllocSymbol(insertvalue, pinsertstring, insertmod);
  2248. if (!InsertNode(&(pProcessCurrent->symcontextSymbolOffset),
  2249. &(pSymbol->nodeOffset))) {
  2250. DeallocSymbol(pSymbol);
  2251. // dprintf("insert - value %d already in tree\n", insertvalue);
  2252. return NULL;
  2253. }
  2254. if (!InsertNode(&(pProcessCurrent->symcontextSymbolString),
  2255. &(pSymbol->nodeString))) {
  2256. DeleteNode(&(pProcessCurrent->symcontextSymbolOffset),
  2257. &(pSymbol->nodeOffset));
  2258. DeallocSymbol(pSymbol);
  2259. // dprintf("insert - string %s already in tree\n", pinsertstring);
  2260. return NULL;
  2261. }
  2262. return pSymbol;
  2263. }
  2264. PSTRUCT InsertStructure (ULONG insertvalue, PUCHAR pinsertstring,
  2265. CHAR insertmod)
  2266. {
  2267. PSTRUCT pStruct;
  2268. pStruct = (PSTRUCT) AllocSymbol(insertvalue, pinsertstring, insertmod);
  2269. if (!InsertNode(&(pProcessCurrent->symcontextStructOffset),
  2270. &(pStruct->nodeOffset))) {
  2271. DeallocSymbol((PSYMBOL)pStruct);
  2272. //dprintf("insert - value %d already in tree\n", insertvalue);
  2273. return NULL;
  2274. }
  2275. if (!InsertNode(&(pProcessCurrent->symcontextStructString),
  2276. &(pStruct->nodeString))) {
  2277. DeleteNode(&(pProcessCurrent->symcontextStructOffset),
  2278. &(pStruct->nodeOffset));
  2279. DeallocSymbol((PSYMBOL)pStruct);
  2280. //dprintf("insert - string %s already in tree\n", pinsertstring);
  2281. return NULL;
  2282. }
  2283. pStruct->pField = NULL;
  2284. return pStruct;
  2285. }
  2286. /*** InsertSymfile - insert new file line numbers into search tree
  2287. *
  2288. * Purpose:
  2289. * Allocate and insert a new files and its line numbers into the
  2290. * offset and filename string trees.
  2291. *
  2292. * Input:
  2293. * pPathname - pointer to pathname string
  2294. * pFilename - pointer to filename string
  2295. * pExtension - pointer to extension string
  2296. * pLineno - pointer to COFF line number entries
  2297. * cLineno - count of entries pointed by pLineno
  2298. * endingOffset - ending offset of file section
  2299. * index - module index for file section
  2300. *
  2301. * Output:
  2302. * None.
  2303. *
  2304. * Notes:
  2305. * Uses the routine InsertNode for both offset and filename
  2306. * string through different contexts.
  2307. *
  2308. *************************************************************************/
  2309. PSYMFILE InsertSymfile (PUCHAR pPathname, PUCHAR pFilename,
  2310. PUCHAR pExtension,
  2311. PIMAGE_LINENUMBER pLineno, USHORT cLineno,
  2312. ULONG startingOffset, ULONG endingOffset,
  2313. CHAR index)
  2314. {
  2315. PSYMFILE pSymfile;
  2316. pSymfile = AllocSymfile(pPathname, pFilename, pExtension,
  2317. pLineno, cLineno,
  2318. startingOffset, endingOffset, index);
  2319. if (!InsertNode(&(pProcessCurrent->symcontextSymfileOffset),
  2320. &(pSymfile->nodeOffset))) {
  2321. DeallocSymfile(pSymfile);
  2322. // dprintf("insert - value %d already in tree\n", insertvalue);
  2323. return NULL;
  2324. }
  2325. if (!InsertNode(&(pProcessCurrent->symcontextSymfileString),
  2326. &(pSymfile->nodeString))) {
  2327. DeleteNode(&(pProcessCurrent->symcontextSymfileOffset),
  2328. &(pSymfile->nodeOffset));
  2329. DeallocSymfile(pSymfile);
  2330. // dprintf("insert - string %s already in tree\n", pinsertstring);
  2331. return NULL;
  2332. }
  2333. return pSymfile;
  2334. }
  2335. /*** InsertNode - insert new node into tree
  2336. *
  2337. * Purpose:
  2338. * Insert node into the tree of the specified context.
  2339. *
  2340. * Input:
  2341. * pSymContext - pointer to context to insert node
  2342. * pNodeNew - pointer to node to insert
  2343. *
  2344. * Returns:
  2345. * TRUE - node was inserted successfully
  2346. * FALSE - node already exists
  2347. *
  2348. * Notes:
  2349. * Both offset and string values of the node may be used
  2350. * in the ordering or duplication criteria.
  2351. *
  2352. *************************************************************************/
  2353. BOOLEAN InsertNode (PSYMCONTEXT pSymContext, PNODE pNodeNew)
  2354. {
  2355. PNODE *ppNodeRoot = &(pSymContext->pNodeRoot);
  2356. PNODE pNodeRootTemp;
  2357. int splitstatus;
  2358. // split tree into two subtrees:
  2359. // *ppNodeRoot - root of all nodes < value(pNodeNew)
  2360. // pNodeRootTemp - root of all nodes >= value(pNodeNew)
  2361. splitstatus = SplitTree(pSymContext, &pNodeRootTemp, pNodeNew);
  2362. if (splitstatus != 0) {
  2363. // value(pNodeNew) was not in tree
  2364. // make pNodeNew the root having the two subtrees as children
  2365. pNodeNew->pLchild = *ppNodeRoot;
  2366. if (*ppNodeRoot)
  2367. (*ppNodeRoot)->pParent = pNodeNew;
  2368. pNodeNew->pRchild = pNodeRootTemp;
  2369. if (pNodeRootTemp)
  2370. pNodeRootTemp->pParent = pNodeNew;
  2371. pNodeNew->pParent = NULL;
  2372. *ppNodeRoot = pNodeNew;
  2373. return TRUE;
  2374. }
  2375. else {
  2376. // value(pNodeNew) was in tree
  2377. // just rejoin the two subtrees back and report error
  2378. JoinTree(pSymContext, pNodeRootTemp);
  2379. return FALSE;
  2380. }
  2381. }
  2382. /*** DeleteSymbol - delete specified symbol from splay tree
  2383. *
  2384. * Purpose:
  2385. * external routine.
  2386. * Delete the specified symbol object in both the
  2387. * offset and string trees and deallocate its space.
  2388. *
  2389. * Input:
  2390. * pSymbol - pointer to symbol object to delete
  2391. *
  2392. * Output:
  2393. * None.
  2394. *
  2395. *************************************************************************/
  2396. void DeleteSymbol (PSYMBOL pSymbol)
  2397. {
  2398. DeleteNode(&(pProcessCurrent->symcontextSymbolOffset),
  2399. &(pSymbol->nodeOffset));
  2400. DeleteNode(&(pProcessCurrent->symcontextSymbolString),
  2401. &(pSymbol->nodeString));
  2402. DeallocSymbol(pSymbol);
  2403. }
  2404. /*** DeleteNode - delete specified node from tree
  2405. *
  2406. * Purpose:
  2407. * Delete node from tree of the context specified.
  2408. *
  2409. * Input:
  2410. * pSymContext - pointer to context of deletion
  2411. * pNodeDelete - pointer to node to actually delete
  2412. *
  2413. * Output:
  2414. * None.
  2415. *
  2416. *************************************************************************/
  2417. void DeleteNode (PSYMCONTEXT pSymContext, PNODE pNodeDelete)
  2418. {
  2419. PNODE pNodeRootTemp;
  2420. // splay the node to be deleted to move it to the root
  2421. //dprintf("before splay\n");
  2422. SplayTree(pNodeDelete);
  2423. //dprintf("after splay\n");
  2424. // point to the splayed node children and join them
  2425. pSymContext->pNodeRoot = pNodeDelete->pLchild;
  2426. pNodeRootTemp = pNodeDelete->pRchild;
  2427. //dprintf("before join\n");
  2428. JoinTree(pSymContext, pNodeRootTemp);
  2429. //dprintf("after join\n");
  2430. }
  2431. /*** JoinTree - join two trees into one
  2432. *
  2433. * Purpose:
  2434. * Join two trees into one where all nodes of the first
  2435. * tree have a lesser value than any of the second.
  2436. *
  2437. * Input:
  2438. * pSymContext - pointer to context containing the first tree
  2439. * pNodeRoot2 - pointer to root of second tree
  2440. *
  2441. * Output:
  2442. * pSymContext - pointer to context containing the joined tree
  2443. *
  2444. *************************************************************************/
  2445. void JoinTree (PSYMCONTEXT pSymContext, PNODE pNodeRoot2)
  2446. {
  2447. PNODE *ppNodeRoot1 = &(pSymContext->pNodeRoot);
  2448. // access and splay the first tree to have its maximum value
  2449. // as its root (no right child)
  2450. // AccessNode(pSymContext, PSYMBOL_TO_PNODE(&symbolMax, pSymContext));
  2451. AccessNode(pSymContext, pSymContext->pNodeMax);
  2452. if (*ppNodeRoot1) {
  2453. // nonnull first tree, connect second tree as
  2454. // right child of the first
  2455. (*ppNodeRoot1)->pRchild = pNodeRoot2;
  2456. if (pNodeRoot2)
  2457. pNodeRoot2->pParent = *ppNodeRoot1;
  2458. }
  2459. else {
  2460. // null first tree, make the second tree the result
  2461. *ppNodeRoot1 = pNodeRoot2;
  2462. if (pNodeRoot2)
  2463. pNodeRoot2->pParent = NULL;
  2464. }
  2465. }
  2466. /*** SplitTree - split one tree into two
  2467. *
  2468. * Purpose:
  2469. * Split the given tree into two subtrees, the first
  2470. * having nodes less than specific value, and the
  2471. * second having nodes greater than or equal to that
  2472. * value.
  2473. *
  2474. * Input:
  2475. * pSymContext - pointer to context containing tree to split
  2476. * pNodeNew - node with value used to specify split
  2477. *
  2478. * Output:
  2479. * pSymContext - pointer to context containing first tree
  2480. * *ppNodeRoot2 - pointer to pointer to root of second tree
  2481. *
  2482. * Returns:
  2483. * result of access:
  2484. * 1 = root is smallest value larger than input value
  2485. * (not found, no lesser value)
  2486. * 0 = root is input value (value found in tree)
  2487. * -1 = root is largest value less than input value
  2488. * (not found in tree)
  2489. *
  2490. *************************************************************************/
  2491. int SplitTree (PSYMCONTEXT pSymContext, PNODE *ppNodeRoot2, PNODE pNodeNew)
  2492. {
  2493. PNODE *ppNodeRoot1 = &(pSymContext->pNodeRoot);
  2494. int access;
  2495. if (*ppNodeRoot1) {
  2496. // nonnull tree, access and splay to make node
  2497. // with input value root.
  2498. access = AccessNode(pSymContext, pNodeNew);
  2499. if (access != 1) {
  2500. // break left child link of root to form two subtrees
  2501. *ppNodeRoot2 = (*ppNodeRoot1)->pRchild;
  2502. if (*ppNodeRoot2)
  2503. (*ppNodeRoot2)->pParent = NULL;
  2504. (*ppNodeRoot1)->pRchild = NULL;
  2505. }
  2506. else {
  2507. // break right child link of root to form two subtrees
  2508. *ppNodeRoot2 = *ppNodeRoot1;
  2509. *ppNodeRoot1 = (*ppNodeRoot1)->pLchild;
  2510. if (*ppNodeRoot1)
  2511. (*ppNodeRoot1)->pParent = NULL;
  2512. (*ppNodeRoot2)->pLchild = NULL;
  2513. }
  2514. }
  2515. else {
  2516. // null tree
  2517. access = 1;
  2518. *ppNodeRoot2 = NULL;
  2519. }
  2520. return access;
  2521. }
  2522. /*** SplayTree - splay tree with node specified
  2523. *
  2524. * Purpose:
  2525. * Perform rotations (splayings) on the specified tree
  2526. * until the node given is at the root.
  2527. *
  2528. * Input:
  2529. * pointer to node to splay to root
  2530. *
  2531. * Returns:
  2532. * pointer to node splayed
  2533. *
  2534. * Notes:
  2535. *
  2536. *************************************************************************/
  2537. PNODE SplayTree (PNODE pNentry)
  2538. {
  2539. PNODE pNparent;
  2540. PNODE pNgrand;
  2541. PNODE pNgreat;
  2542. PNODE pNchild;
  2543. if (pNentry) {
  2544. // repeat single or double rotations until node is root
  2545. while (pNentry->pParent) {
  2546. pNparent = pNentry->pParent;
  2547. if (!pNparent->pParent) {
  2548. if (pNentry == pNparent->pLchild) {
  2549. // case 1: PARENT ENTRY
  2550. // / \ / \
  2551. // ENTRY T(B) T(A) PARENT
  2552. // / \ / \
  2553. // T(A) CHILD CHILD T(B)
  2554. if (pNchild = pNentry->pRchild)
  2555. pNchild->pParent = pNparent;
  2556. pNparent->pLchild = pNchild;
  2557. pNparent->pParent = pNentry;
  2558. pNentry->pRchild = pNparent;
  2559. }
  2560. else {
  2561. // case 2: PARENT ENTRY
  2562. // / \ / \
  2563. // T(A) ENTRY PARENT T(B)
  2564. // / \ / \
  2565. // CHILD T(B) T(A) CHILD
  2566. if (pNchild = pNentry->pLchild)
  2567. pNchild->pParent = pNparent;
  2568. pNparent->pRchild = pNchild;
  2569. pNparent->pParent = pNentry;
  2570. pNentry->pLchild = pNparent;
  2571. }
  2572. pNentry->pParent = NULL;
  2573. }
  2574. else {
  2575. pNgrand = pNparent->pParent;
  2576. pNgreat = pNgrand->pParent;
  2577. if (pNentry == pNparent->pLchild) {
  2578. if (pNparent == pNgrand->pLchild) {
  2579. // case 3: (GREAT) (GREAT)
  2580. // | |
  2581. // GRAND ENTRY
  2582. // / \ / \
  2583. // PARENT T(B) T(A) PARENT
  2584. // / \ / \
  2585. // ENTRY CHILD2 CHILD1 GRAND
  2586. // / \ / \
  2587. // T(A) CHILD1 CHILD2 T(B)
  2588. if (pNchild = pNentry->pRchild)
  2589. pNchild->pParent = pNparent;
  2590. pNparent->pLchild = pNchild;
  2591. if (pNchild = pNparent->pRchild)
  2592. pNchild->pParent = pNgrand;
  2593. pNgrand->pLchild = pNchild;
  2594. pNgrand->pParent = pNparent;
  2595. pNparent->pRchild = pNgrand;
  2596. pNparent->pParent = pNentry;
  2597. pNentry->pRchild = pNparent;
  2598. }
  2599. else {
  2600. // case 4: (GREAT) (GREAT)
  2601. // | |
  2602. // GRAND _____ENTRY____
  2603. // / \ / \
  2604. // T(A) PARENT GRAND PARENT
  2605. // / \ / \ / \
  2606. // ENTRY T(B) T(A) CHILD1 CHILD2 T(B)
  2607. // / \
  2608. // CHILD1 CHILD2
  2609. if (pNchild = pNentry->pLchild)
  2610. pNchild->pParent = pNgrand;
  2611. pNgrand->pRchild = pNchild;
  2612. if (pNchild = pNentry->pRchild)
  2613. pNchild->pParent = pNparent;
  2614. pNparent->pLchild = pNchild;
  2615. pNgrand->pParent = pNentry;
  2616. pNentry->pLchild = pNgrand;
  2617. pNparent->pParent = pNentry;
  2618. pNentry->pRchild = pNparent;
  2619. }
  2620. }
  2621. else {
  2622. if (pNparent == pNgrand->pLchild) {
  2623. // case 5: (GREAT) (GREAT)
  2624. // | |
  2625. // GRAND _____ENTRY____
  2626. // / \ / \
  2627. // PARENT T(B) PARENT GRAND
  2628. // / \ / \ / \
  2629. // T(A) ENTRY T(A) CHILD1 CHILD2 T(B)
  2630. // / \
  2631. // CHILD1 CHILD2
  2632. if (pNchild = pNentry->pLchild)
  2633. pNchild->pParent = pNparent;
  2634. pNparent->pRchild = pNchild;
  2635. if (pNchild = pNentry->pRchild)
  2636. pNchild->pParent = pNgrand;
  2637. pNgrand->pLchild = pNchild;
  2638. pNparent->pParent = pNentry;
  2639. pNentry->pLchild = pNparent;
  2640. pNgrand->pParent = pNentry;
  2641. pNentry->pRchild = pNgrand;
  2642. }
  2643. else {
  2644. // case 6: (GREAT) (GREAT)
  2645. // | |
  2646. // GRAND ENTRY
  2647. // / \ / \
  2648. // T(A) PARENT PARENT T(B)
  2649. // / \ / \
  2650. // CHILD1 ENTRY GRAND CHILD2
  2651. // / \ / \
  2652. // CHILD2 T(B) T(A) CHILD1
  2653. if (pNchild = pNentry->pLchild)
  2654. pNchild->pParent = pNparent;
  2655. pNparent->pRchild = pNchild;
  2656. if (pNchild = pNparent->pLchild)
  2657. pNchild->pParent = pNgrand;
  2658. pNgrand->pRchild = pNchild;
  2659. pNgrand->pParent = pNparent;
  2660. pNparent->pLchild = pNgrand;
  2661. pNparent->pParent = pNentry;
  2662. pNentry->pLchild = pNparent;
  2663. }
  2664. }
  2665. if (pNgreat) {
  2666. if (pNgreat->pLchild == pNgrand)
  2667. pNgreat->pLchild = pNentry;
  2668. else
  2669. pNgreat->pRchild = pNentry;
  2670. }
  2671. pNentry->pParent = pNgreat;
  2672. }
  2673. }
  2674. }
  2675. return pNentry;
  2676. }
  2677. /*** NextNode - return node with next key in tree
  2678. *
  2679. * Purpose:
  2680. * With the specified context and node, determine
  2681. * the node with the next larger value.
  2682. *
  2683. * Input:
  2684. * pSymContext - pointer to context to test
  2685. * pNode - pointer to node within context
  2686. * NULL to return the first node in the tree
  2687. *
  2688. * Returns:
  2689. * pointer to node of the next value
  2690. * NULL if largest node was input
  2691. *
  2692. *************************************************************************/
  2693. PNODE NextNode (PSYMCONTEXT pSymContext, PNODE pNode)
  2694. {
  2695. PNODE pLast;
  2696. if (pNode) {
  2697. // nonnull input, if node has a right child,
  2698. // return the leftmost child of the right child
  2699. // or right child itself if not left children
  2700. if (pNode->pRchild) {
  2701. pNode = pNode->pRchild;
  2702. while (pNode->pLchild)
  2703. pNode = pNode->pLchild;
  2704. }
  2705. else {
  2706. // if no right child, go up through the parent
  2707. // links until the node comes from a left child
  2708. // and return it
  2709. do {
  2710. pLast = pNode;
  2711. pNode = pNode->pParent;
  2712. }
  2713. while (pNode && pNode->pLchild != pLast);
  2714. }
  2715. }
  2716. else {
  2717. // NULL input return first node of tree.
  2718. // return leftmost child of root or root itself
  2719. // if no left children.
  2720. pNode = pSymContext->pNodeRoot;
  2721. if (pNode)
  2722. while (pNode->pLchild)
  2723. pNode = pNode->pLchild;
  2724. }
  2725. return pNode;
  2726. }
  2727. /*** OutputTree - output tree node in ascending order
  2728. *
  2729. * Purpose:
  2730. * Using the specified context, output the corresponding
  2731. * tree from lowest to highest values.
  2732. *
  2733. * Input:
  2734. * pSymContext - pointer to context whose tree to output
  2735. *
  2736. * Output:
  2737. * contents of tree nodes from low to high
  2738. *
  2739. *************************************************************************/
  2740. void OutputTree (PSYMCONTEXT pSymContext)
  2741. {
  2742. PNODE pNode = NULL;
  2743. PSYMBOL pSymbol;
  2744. CHAR count;
  2745. dprintf("****** output tree ******\n");
  2746. while (TRUE) {
  2747. pNode = NextNode(pSymContext, pNode);
  2748. if (pNode) {
  2749. pSymbol = PNODE_TO_PSYMBOL(pNode, pSymContext);
  2750. dprintf("node:%8lx par:%8lx lch:%8lx rch:%8lx " ,
  2751. pNode, pNode->pParent, pNode->pLchild, pNode->pRchild);
  2752. dprintf("value: %8lx <", pSymbol->offset);
  2753. count = pSymbol->underscores;
  2754. while (count--)
  2755. dprintf("_");
  2756. dprintf("%s>\n", pSymbol->string);
  2757. }
  2758. else
  2759. break;
  2760. }
  2761. }
  2762. /*** GetOffsetFromSym - return offset from symbol specified
  2763. *
  2764. * Purpose:
  2765. * external routine.
  2766. * With the specified symbol, set the pointer to
  2767. * its offset. The variable chSymbolSuffix may
  2768. * be used to append a character to repeat the search
  2769. * if it first fails.
  2770. *
  2771. * Input:
  2772. * pString - pointer to input symbol
  2773. *
  2774. * Output:
  2775. * pOffset - pointer to offset to be set
  2776. *
  2777. * Returns:
  2778. * BOOLEAN value of success
  2779. *
  2780. *************************************************************************/
  2781. BOOLEAN GetOffsetFromSym (PUCHAR pString, PULONG pOffset, CHAR iModule)
  2782. {
  2783. UCHAR SuffixedString[80];
  2784. UCHAR Suffix[4];
  2785. if (GetOffsetFromString(pString, pOffset, iModule))
  2786. return TRUE;
  2787. if (chSymbolSuffix != 'n') {
  2788. strcpy(SuffixedString, pString);
  2789. Suffix[0] = chSymbolSuffix;
  2790. Suffix[1] = '\0';
  2791. strcat(SuffixedString, Suffix);
  2792. if (GetOffsetFromString(SuffixedString, pOffset, iModule))
  2793. return TRUE;
  2794. }
  2795. return FALSE;
  2796. }
  2797. /*** GetOffsetFromString - return offset from string specified
  2798. *
  2799. * Purpose:
  2800. * With the specified string, set the pointer to
  2801. * its offset.
  2802. *
  2803. * Input:
  2804. * pString - pointer to input string
  2805. *
  2806. * Output:
  2807. * pOffset - pointer to offset to be set
  2808. *
  2809. * Returns:
  2810. * BOOLEAN value of success
  2811. *
  2812. *************************************************************************/
  2813. BOOLEAN GetOffsetFromString (PUCHAR pString, PULONG pOffset, CHAR iModule)
  2814. {
  2815. PSYMBOL pSymSearch = AllocSymbol(0L, pString, iModule);
  2816. PSYMBOL pSymbol;
  2817. int st;
  2818. EnsureModuleSymbolsLoaded(iModule);
  2819. // search for string in tree
  2820. st = AccessNode(&(pProcessCurrent->symcontextSymbolString),
  2821. &(pSymSearch->nodeString));
  2822. if (st) {
  2823. // if not found, try again with underscore prepended to name
  2824. pSymSearch->underscores++;
  2825. st = AccessNode(&(pProcessCurrent->symcontextSymbolString),
  2826. &(pSymSearch->nodeString));
  2827. }
  2828. if (!st) {
  2829. // if found, get the pointer to its symbol and set the offset
  2830. pSymbol = PNODE_TO_PSYMBOL
  2831. (pProcessCurrent->symcontextSymbolString.pNodeRoot,
  2832. &(pProcessCurrent->symcontextSymbolString));
  2833. *pOffset = pSymbol->offset;
  2834. }
  2835. // deallocate the temporary symbol structure and return success
  2836. DeallocSymbol(pSymSearch);
  2837. return (BOOLEAN)(st == 0);
  2838. }
  2839. /*** GetOffsetFromLineno - return offset from file:lineno specified
  2840. *
  2841. * Purpose:
  2842. * With the specified file and line number, return
  2843. * its offset.
  2844. *
  2845. * Input:
  2846. * pString - pointer to input string for filename
  2847. * lineno - line number of filename specified
  2848. *
  2849. * Output:
  2850. * pOffset - pointer to offset to be set
  2851. *
  2852. * Returns:
  2853. * BOOLEAN value of success
  2854. *
  2855. *************************************************************************/
  2856. PLINENO GetLinenoFromFilename (PUCHAR pString, PPSYMFILE ppSymfile,
  2857. USHORT lineNum, CHAR iModule)
  2858. {
  2859. PPLINENO ppLineno;
  2860. PLINENO pLineno = NULL;
  2861. PSYMFILE pSymfileSearch = AllocSymfile("", pString, "", NULL,
  2862. lineNum, 0, 0, iModule);
  2863. PSYMFILE pSymfile;
  2864. USHORT indexLow;
  2865. USHORT indexHigh;
  2866. USHORT indexTest;
  2867. int st;
  2868. EnsureModuleSymbolsLoaded(iModule);
  2869. // search for symbol file containing line number in tree
  2870. st = AccessNode(&(pProcessCurrent->symcontextSymfileString),
  2871. &(pSymfileSearch->nodeString));
  2872. if (!st) {
  2873. // if found, search line number list for offset
  2874. pSymfile = PNODE_TO_PSYMFILE
  2875. (pProcessCurrent->symcontextSymfileString.pNodeRoot,
  2876. &(pProcessCurrent->symcontextSymfileString));
  2877. *ppSymfile = pSymfile;
  2878. // search the PLINENO array for the pointer to the LINENO
  2879. // structure having the line number given.
  2880. ppLineno = pSymfile->ppLinenoSrcLine;
  2881. indexLow = 1;
  2882. // PDK KLUGDE:::
  2883. if (indexHigh = pSymfile->cLineno)
  2884. do {
  2885. indexTest = (USHORT)((indexLow + indexHigh) / 2);
  2886. if (lineNum > (*(ppLineno + indexTest))->breakLineNumber)
  2887. indexLow = (USHORT)(indexTest + 1);
  2888. else if (lineNum < (*(ppLineno + indexTest))->breakLineNumber)
  2889. indexHigh = (USHORT)(indexTest - 1);
  2890. else
  2891. indexLow = indexHigh = indexTest;
  2892. }
  2893. while (indexLow < indexHigh);
  2894. pLineno = *(ppLineno + indexHigh);
  2895. }
  2896. // deallocate the temporary symbol structure and return pointer
  2897. DeallocSymfile(pSymfileSearch);
  2898. return pLineno;
  2899. }
  2900. #ifndef NT_SAPI
  2901. void GetLinenoString (PUCHAR pchBuffer, ULONG offset)
  2902. {
  2903. PLINENO pLineno;
  2904. PSYMFILE pSymfile;
  2905. *pchBuffer = '\0';
  2906. pLineno = GetLinenoFromOffset(&pSymfile, offset);
  2907. if (pLineno && pLineno->memoryOffset == offset)
  2908. sprintf(pchBuffer, "%s:%d", pSymfile->pchName,
  2909. pLineno->breakLineNumber);
  2910. }
  2911. void GetCurrentMemoryOffsets (PULONG pMemoryLow, PULONG pMemoryHigh)
  2912. {
  2913. NT_PADDR pcValue = GetRegPCValue();
  2914. PSYMFILE pSymfile;
  2915. PLINENO pLineno;
  2916. *pMemoryLow = -1L; // default value for no source
  2917. if (fSourceOnly) {
  2918. pLineno = GetLinenoFromOffset(&pSymfile, Flat(pcValue));
  2919. if (pLineno) {
  2920. *pMemoryLow = pLineno->memoryOffset;
  2921. if (pLineno == (pSymfile->pLineno + pSymfile->cLineno))
  2922. *pMemoryHigh = pSymfile->endOffset;
  2923. else
  2924. *pMemoryHigh = (pLineno + 1)->memoryOffset;
  2925. }
  2926. }
  2927. }
  2928. PLINENO GetCurrentLineno (PPSYMFILE ppSymfile)
  2929. {
  2930. NT_PADDR pcValue = GetRegPCValue();
  2931. return GetLinenoFromOffset(ppSymfile, Flat(pcValue));
  2932. }
  2933. PLINENO GetLastLineno (PPSYMFILE ppSymfile, PUSHORT pLineNum)
  2934. {
  2935. PLINENO pLineno = NULL;
  2936. PSYMFILE pSymfile;
  2937. if (pSymfileLast) {
  2938. pLineno = GetLinenoFromFilename(pSymfileLast->pchName,
  2939. &pSymfile, lineNumberLast,
  2940. pSymfileLast->modIndex);
  2941. if (pLineno) {
  2942. *ppSymfile = pSymfile;
  2943. *pLineNum = lineNumberLast;
  2944. }
  2945. }
  2946. return pLineno;
  2947. }
  2948. static PUCHAR Type[] = {"null", "void", "char", "short", "int",
  2949. "long", "float", "double", ""/*struct*/, "union",
  2950. "enum", "moe", "uchar", "ushort", "uint",
  2951. "ulong"};
  2952. static PUCHAR Dtype[]= {"", "*", "()", "[]"};
  2953. BOOLEAN GetLocalFromString(PUCHAR pszLocal, PULONG pValue)
  2954. {
  2955. PSYMFILE pSymfileSearch = pTempSymfile;
  2956. PSYMFILE pSymfile;
  2957. SYMBOL Symbol;
  2958. static NT_ADDR addrPC;
  2959. static PLOCAL pLocal;
  2960. PLOCAL pL;
  2961. NT_PADDR newPC = GetRegPCValue();
  2962. if (!AddrEqu(newPC, &addrPC)){
  2963. // search for symbol file containing offset in tree
  2964. pSymfileSearch->startOffset = Flat(&addrPC) = Flat(newPC);
  2965. if (AccessNode(&(pProcessCurrent->symcontextSymfileOffset),
  2966. &(pSymfileSearch->nodeOffset))){
  2967. pLocal = NULL;
  2968. return FALSE;
  2969. }
  2970. // Get the symfile from the root
  2971. pSymfile = PNODE_TO_PSYMFILE
  2972. (pProcessCurrent->symcontextSymfileOffset.pNodeRoot,
  2973. &(pProcessCurrent->symcontextSymfileOffset));
  2974. // create temporary symbol with offset (module not needed)
  2975. Symbol.offset = Flat(&addrPC);
  2976. Symbol.string[0] = '\0';
  2977. // access the function in the tree with value closest
  2978. if (AccessNode(&(pSymfile->symcontextFunctionOffset),
  2979. &(Symbol.nodeOffset)) != 1) {
  2980. pLocal = (PNODE_TO_PSYMBOL
  2981. (pSymfile->symcontextFunctionOffset.pNodeRoot,
  2982. &(pSymfile->symcontextFunctionOffset)))->pLocal;
  2983. }
  2984. else {
  2985. pLocal = NULL;
  2986. return FALSE;
  2987. }
  2988. }
  2989. for(pL=pLocal;pL;pL=pL->next){
  2990. if (_stricmp(pszLocal, pL->pszLocalName)) continue;
  2991. *pValue = GetLocalValue(pL->value, pL->type, FALSE);
  2992. return TRUE;
  2993. }
  2994. return FALSE;
  2995. }
  2996. #endif /* NT_SAPI */
  2997. PSYMBOL GetFunctionFromOffset (PPSYMFILE ppSymfile, ULONG offset)
  2998. {
  2999. PSYMFILE pSymfileSearch = pTempSymfile;
  3000. PSYMFILE pSymfile;
  3001. PSYMBOL pSymbol = NULL;
  3002. SYMBOL Symbol;
  3003. int st;
  3004. // PUCHAR pszCtrl;
  3005. // ULONG value;
  3006. // load symbols for offset if needed (and if possible)
  3007. st = EnsureOffsetSymbolsLoaded(offset);
  3008. if (!st) {
  3009. // search for symbol file containing offset in tree
  3010. pSymfileSearch->startOffset = offset;
  3011. st = AccessNode(&(pProcessCurrent->symcontextSymfileOffset),
  3012. &(pSymfileSearch->nodeOffset));
  3013. }
  3014. // DeallocSymfile(pSymfileSearch);
  3015. // fails if non-code static
  3016. if (st) {
  3017. // dprintf("no symfile for function offset %08lx\n", offset);
  3018. return NULL;
  3019. }
  3020. // Get the symfile from the root
  3021. pSymfile = PNODE_TO_PSYMFILE
  3022. (pProcessCurrent->symcontextSymfileOffset.pNodeRoot,
  3023. &(pProcessCurrent->symcontextSymfileOffset));
  3024. // Make this symfile available to the caller
  3025. *ppSymfile = pSymfile;
  3026. // create temporary symbol with offset (module not needed)
  3027. Symbol.offset = offset;
  3028. Symbol.string[0] = '\0';
  3029. // access the function in the tree with value (or nearest lesser value)
  3030. if (AccessNode(&(pSymfile->symcontextFunctionOffset),
  3031. &(Symbol.nodeOffset)) != 1) {
  3032. pSymbol = PNODE_TO_PSYMBOL
  3033. (pSymfile->symcontextFunctionOffset.pNodeRoot,
  3034. &(pSymfile->symcontextFunctionOffset));
  3035. // dprintf("%s(){\n", pSymbol->string);
  3036. // if (pSymbol->pLocal){
  3037. // PLOCAL pLocal = pSymbol->pLocal;
  3038. //
  3039. // while(pLocal){
  3040. //
  3041. // // stop output on break
  3042. //
  3043. // if (fControlC) {
  3044. // fControlC = 0;
  3045. // break;
  3046. // }
  3047. //
  3048. // MUST ITERATE THROUGH ALL THE DERIVED TYPES!!!!
  3049. // DO THIS LATER
  3050. // value = labs(pLocal->value);
  3051. // if (pLocal->type==IMAGE_SYM_TYPE_STRUCT){
  3052. // if (baseDefault==10) pszCtrl=" [EBP%s%ld]\t";
  3053. // else pszCtrl=" [EBP%s0x%lx]\t";
  3054. //
  3055. // dprintf(pszCtrl,
  3056. // *((LONG*)&pLocal->value)<0?"-":"+", value);
  3057. // THIS -2 IS DUE TO A CONVERTER/LINKER BUG. THIS OFFSET MIGHT CHANGE
  3058. // if(!GetStructFromValue(pLocal->aux, pLocal->value))
  3059. // GetStructFromValue(pLocal->aux-2, pLocal->value);
  3060. // dprintf("%s%s\n", pLocal->pszLocalName,
  3061. // Dtype[(pLocal->type>>4)&0x3]);
  3062. // }
  3063. // else{
  3064. // if (baseDefault==10) pszCtrl=" [EBP%s%ld]\t(%s%s)\t%s = ";
  3065. // else pszCtrl=" [EBP%s0x%lx]\t(%s%s)\t%s = ";
  3066. //
  3067. // dprintf(pszCtrl,
  3068. // *((LONG*)&pLocal->value)<0?"-":"+",
  3069. // value,
  3070. // Type[pLocal->type&0xF],
  3071. // Dtype[(pLocal->type>>4)&0x3],
  3072. // pLocal->pszLocalName);
  3073. // GetLocalValue(pLocal->value, pLocal->type, TRUE);
  3074. // dprintf("\n");
  3075. // }
  3076. // pLocal = pLocal->next;
  3077. // }
  3078. // }
  3079. // else dprintf("NO LOCALS");
  3080. // dprintf("}\n");
  3081. }
  3082. return pSymbol;
  3083. }
  3084. #ifndef NT_SAPI
  3085. PSTRUCT GetStructFromValue(ULONG value, LONG base)
  3086. {
  3087. PSTRUCT pStruct = NULL;
  3088. STRUCT Struct;
  3089. PUCHAR pszCtrl;
  3090. ULONG val;
  3091. // create temporary structure with the specified value
  3092. Struct.offset = value;
  3093. Struct.string[0] = '\0';
  3094. // access the structure in the tree with the specified value
  3095. if (!AccessNode(&(pProcessCurrent->symcontextStructOffset),
  3096. &(Struct.nodeOffset))) {
  3097. pStruct = (PSTRUCT) PNODE_TO_PSYMBOL (
  3098. pProcessCurrent->symcontextStructOffset.pNodeRoot,
  3099. &(pProcessCurrent->symcontextStructOffset));
  3100. dprintf("struct %s {\n", pStruct->string);
  3101. if (pStruct->pField){
  3102. PFIELD pField = pStruct->pField;
  3103. while(pField){
  3104. val = labs(pField->value);
  3105. if (baseDefault==10) pszCtrl="\t\t [%s%ld]\t(%s%s)\t%s = ";
  3106. else pszCtrl="\t\t [%s0x%lx]\t(%s%s)\t%s = ";
  3107. dprintf(pszCtrl,
  3108. *((LONG*)&pField->value)<0?"-":"+",
  3109. val,
  3110. Type[pField->type&0xF],
  3111. Dtype[(pField->type>>4)&0x3],
  3112. pField->pszFieldName);
  3113. GetLocalValue(base+pField->value, pField->type, TRUE);
  3114. dprintf("\n");
  3115. pField = pField->next;
  3116. }
  3117. }
  3118. else dprintf("NO FIELDS");
  3119. dprintf("\t\t} ");
  3120. return pStruct;
  3121. }
  3122. else return (PSTRUCT)NULL;
  3123. }
  3124. ULONG GetLocalValue(LONG value, USHORT type, BOOLEAN fPrint)
  3125. {
  3126. UCHAR dtype = (UCHAR)(type >> 4);
  3127. ULONG data;
  3128. PCHAR pszCtrl=NULL;
  3129. ULONG retValue;
  3130. #ifndef MIPS
  3131. float f;
  3132. double df;
  3133. #endif
  3134. type &= 0xF;
  3135. if (fPointerExpression) {
  3136. NT_PADDR paddr = GetRegFPValue();
  3137. AddrAdd(paddr, value);
  3138. if (fPrint) dprintAddr(paddr);
  3139. return (ULONG)Flat(paddr);
  3140. }
  3141. GetBytesFromFrame((PUCHAR)&data, value, sizeof(data));
  3142. if (dtype) {
  3143. if (fPrint) dprintf("0x%08lx", data);
  3144. return data;
  3145. }
  3146. switch(type){
  3147. case IMAGE_SYM_TYPE_NULL:
  3148. pszCtrl = "%lx??";
  3149. retValue = data;
  3150. break;
  3151. case IMAGE_SYM_TYPE_VOID:
  3152. pszCtrl = "VOID";
  3153. retValue = data;
  3154. break;
  3155. case IMAGE_SYM_TYPE_CHAR:
  3156. case IMAGE_SYM_TYPE_UCHAR:
  3157. pszCtrl = " [%u]";
  3158. data = retValue = (UCHAR)data;
  3159. if (fPrint) dprintf("%c", data);
  3160. break;
  3161. case IMAGE_SYM_TYPE_SHORT:
  3162. pszCtrl = "%d";
  3163. data = retValue = (USHORT)data;
  3164. break;
  3165. case IMAGE_SYM_TYPE_USHORT:
  3166. pszCtrl = "%u";
  3167. data = retValue = (USHORT)data;
  3168. break;
  3169. case IMAGE_SYM_TYPE_INT:
  3170. case IMAGE_SYM_TYPE_LONG:
  3171. pszCtrl = "%ld";
  3172. retValue = data;
  3173. break;
  3174. case IMAGE_SYM_TYPE_UINT:
  3175. case IMAGE_SYM_TYPE_ULONG:
  3176. pszCtrl = "%lu";
  3177. retValue = data;
  3178. break;
  3179. #ifndef MIPS
  3180. case IMAGE_SYM_TYPE_FLOAT:
  3181. pszCtrl = "%f";
  3182. GetBytesFromFrame((PUCHAR)&f, value, sizeof(float));
  3183. if (fPrint) dprintf(pszCtrl, f);
  3184. return data;
  3185. break;
  3186. case IMAGE_SYM_TYPE_DOUBLE:
  3187. pszCtrl = "%lf";
  3188. GetBytesFromFrame((PUCHAR)&df, value, sizeof(double));
  3189. if (fPrint) dprintf(pszCtrl, df);
  3190. return data;
  3191. break;
  3192. #endif
  3193. default:{
  3194. NT_PADDR paddr = GetRegFPValue();
  3195. pszCtrl = "???";
  3196. AddrAdd(paddr, value);
  3197. retValue = Flat(paddr);
  3198. }
  3199. break;
  3200. }
  3201. if (fPrint) dprintf(pszCtrl, data);
  3202. return retValue;
  3203. }
  3204. void
  3205. GetBytesFromFrame(PUCHAR pcb, LONG offset, USHORT cb)
  3206. {
  3207. NT_PADDR paddr = GetRegFPValue();
  3208. AddrAdd(paddr, offset);
  3209. GetMemString(paddr, pcb, cb);
  3210. }
  3211. #endif /* NT_SAPI */
  3212. void
  3213. AddFieldToStructure(PSTRUCT pStruct, PUCHAR pszFieldName, ULONG value,
  3214. USHORT type, ULONG auxValue)
  3215. {
  3216. PFIELD pField;
  3217. if (!pStruct)
  3218. return;
  3219. if (!(pField=(PFIELD)malloc(sizeof(FIELD)+strlen(pszFieldName))))
  3220. return;
  3221. strcpy(pField->pszFieldName, pszFieldName);
  3222. pField->type = type;
  3223. pField->value = value;
  3224. pField->aux = auxValue;
  3225. pField->next = pStruct->pField;
  3226. pStruct->pField = pField;
  3227. }
  3228. void
  3229. AddLocalToFunction(PSYMBOL pFunction, PUCHAR pszLocalName, ULONG value,
  3230. USHORT type, ULONG auxValue)
  3231. {
  3232. PLOCAL pLocal;
  3233. if (!pFunction)
  3234. return;
  3235. if (!(pLocal=(PLOCAL)malloc(sizeof(LOCAL)+strlen(pszLocalName))))
  3236. return;
  3237. strcpy(pLocal->pszLocalName, pszLocalName);
  3238. pLocal->type = type;
  3239. pLocal->value = value;
  3240. pLocal->aux = auxValue;
  3241. pLocal->next = pFunction->pLocal;
  3242. pFunction->pLocal = pLocal;
  3243. }
  3244. PSYMBOL InsertFunction(PUCHAR lpFunctionName, ULONG offset) //, PSYMBOL pS)
  3245. {
  3246. PSYMFILE pSymfileSearch = pTempSymfile;
  3247. //AllocSymfile("", "", "", NULL, 0, offset, 0, 0);
  3248. PSYMFILE pSymfile;
  3249. PSYMBOL pSymbol;
  3250. int st;
  3251. // Find the symbol file containing this function
  3252. pTempSymfile->startOffset = offset;
  3253. st = AccessNode(&(pProcessCurrent->symcontextSymfileOffset),
  3254. &(pSymfileSearch->nodeOffset));
  3255. // DeallocSymfile(pSymfileSearch);
  3256. // fails if non-code static
  3257. if (st) {
  3258. // dprintf("no symfile for function offset %08lx\n", offset);
  3259. return NULL;
  3260. }
  3261. // A symfile was found, now get it from the root
  3262. pSymfile = PNODE_TO_PSYMFILE
  3263. (pProcessCurrent->symcontextSymfileOffset.pNodeRoot,
  3264. &(pProcessCurrent->symcontextSymfileOffset));
  3265. // Allocate a function node.
  3266. pSymbol = AllocSymbol(offset, lpFunctionName, pSymfile->modIndex);
  3267. // pSymbol->pSymbol = pS;
  3268. // Now insert this function into this symfile's function tree
  3269. if (!InsertNode(&(pSymfile->symcontextFunctionOffset),
  3270. &(pSymbol->nodeOffset))) {
  3271. DeallocSymbol(pSymbol);
  3272. // dprintf("insert - value %d already in tree\n", lpFunctionName);
  3273. return NULL;
  3274. }
  3275. if (!InsertNode(&(pSymfile->symcontextFunctionString),
  3276. &(pSymbol->nodeString))) {
  3277. DeleteNode(&(pSymfile->symcontextFunctionOffset),
  3278. &(pSymbol->nodeOffset));
  3279. DeallocSymbol(pSymbol);
  3280. dprintf("insert - string %s already in tree\n", lpFunctionName);
  3281. return NULL;
  3282. }
  3283. return pSymbol;
  3284. }
  3285. PLINENO GetLinenoFromOffset (PPSYMFILE ppSymfile, ULONG offset)
  3286. {
  3287. PLINENO pLineno = NULL;
  3288. PSYMFILE pSymfileSearch = AllocSymfile("", "", "",
  3289. NULL, 0, offset, 0, 0);
  3290. PSYMFILE pSymfile;
  3291. USHORT indexLow;
  3292. USHORT indexHigh;
  3293. USHORT indexTest;
  3294. int st;
  3295. // load symbols for offset if needed (and if possible)
  3296. st = EnsureOffsetSymbolsLoaded(offset);
  3297. if (!st) {
  3298. // search for symbol file containing offset in tree
  3299. st = AccessNode(&(pProcessCurrent->symcontextSymfileOffset),
  3300. &(pSymfileSearch->nodeOffset));
  3301. }
  3302. if (!st) {
  3303. // if found, search line number list for offset
  3304. pSymfile = PNODE_TO_PSYMFILE
  3305. (pProcessCurrent->symcontextSymfileOffset.pNodeRoot,
  3306. &(pProcessCurrent->symcontextSymfileOffset));
  3307. // search for index with equal or closest lessor value to
  3308. // the offset given
  3309. indexLow = 1;
  3310. // PDK KLUDGE:::
  3311. if (indexHigh = pSymfile->cLineno)
  3312. do {
  3313. indexTest = (USHORT)((indexLow + indexHigh) / 2);
  3314. if (offset > (pSymfile->pLineno + indexTest)->memoryOffset)
  3315. indexLow = (USHORT)(indexTest + 1);
  3316. else if (offset < (pSymfile->pLineno + indexTest)->memoryOffset)
  3317. indexHigh = (USHORT)(indexTest - 1);
  3318. else
  3319. indexLow = indexHigh = indexTest;
  3320. }
  3321. while (indexLow < indexHigh);
  3322. *ppSymfile = pSymfile;
  3323. pLineno = pSymfile->pLineno + indexHigh;
  3324. }
  3325. // deallocate the temporary symbol structure and return pointer
  3326. DeallocSymfile(pSymfileSearch);
  3327. return pLineno;
  3328. }
  3329. /*** GetSymbol - get symbol name from offset specified
  3330. *
  3331. * Purpose:
  3332. * external routine.
  3333. * With the specified offset, return the nearest symbol string
  3334. * previous or equal to the offset and its displacement
  3335. *
  3336. * Input:
  3337. * offset - input offset to search
  3338. * offsetSymMax - maximum offset of a symbol (global value)
  3339. *
  3340. * Output:
  3341. * pchBuffer - pointer to buffer to fill with string
  3342. * pDisplacement - pointer to offset displacement
  3343. *
  3344. * Notes:
  3345. * if offset if less than any defined symbol, the NULL value
  3346. * is returned and the displacement is set to the offset
  3347. *
  3348. *************************************************************************/
  3349. void GetSymbol (ULONG offset, PUCHAR pchBuffer, PULONG pDisplacement)
  3350. {
  3351. SYMBOL Symbol;
  3352. ULONG disp = offset;
  3353. PSYMBOL pSymbol;
  3354. ULONG underscorecnt;
  3355. UCHAR ch;
  3356. PUCHAR pszTemp;
  3357. // create temporary symbol with offset (module not needed)
  3358. Symbol.offset = offset;
  3359. Symbol.string[0] = '\0';
  3360. *pchBuffer = '\0';
  3361. // load symbols if needed and check range, and if in range,
  3362. // access symbol in tree with value (or nearest lesser value)
  3363. if (!EnsureOffsetSymbolsLoaded(offset) &&
  3364. AccessNode(&(pProcessCurrent->symcontextSymbolOffset),
  3365. &(Symbol.nodeOffset)) != 1) {
  3366. pSymbol = PNODE_TO_PSYMBOL
  3367. (pProcessCurrent->symcontextSymbolOffset.pNodeRoot,
  3368. &(pProcessCurrent->symcontextSymbolOffset));
  3369. // build string from module name, underscore count,
  3370. // and remaining string
  3371. pszTemp = pImageFromIndex(pSymbol->modIndex)->pszName;
  3372. while (ch = *pszTemp++)
  3373. *pchBuffer++ = ch;
  3374. *pchBuffer++ = '!';
  3375. underscorecnt = pSymbol->underscores;
  3376. while (underscorecnt--)
  3377. *pchBuffer++ = '_';
  3378. strcpy(pchBuffer, pSymbol->string);
  3379. // displacement is input offset less symbol value offset
  3380. disp -= pSymbol->offset;
  3381. }
  3382. *pDisplacement = disp;
  3383. }
  3384. /*** AllocSymbol - build and allocate symbol
  3385. *
  3386. * Purpose:
  3387. * Allocate space for symbol structure.
  3388. *
  3389. * Input:
  3390. * offset - offset of symbol to be allocated
  3391. * pString - pointer to string of symbol to be allocated
  3392. *
  3393. * Returns:
  3394. * pointer to filled symbol structure
  3395. *
  3396. * Exceptions:
  3397. *
  3398. * Notes:
  3399. * space allocated is: sizeof(SYMBOL) -- nonstring info and 3 UCHAR's
  3400. * + strlen(pString) -- size of string
  3401. * + 1 -- space for terminating NULL
  3402. * the sum is rounded up using the 3 UCHAR's and and'ing with ~3
  3403. *
  3404. *************************************************************************/
  3405. PSYMBOL AllocSymbol (ULONG offset, PUCHAR pString, CHAR iModule)
  3406. {
  3407. PSYMBOL pSymbol;
  3408. PUCHAR pStringTemp = pString;
  3409. // allocate the space needed
  3410. pSymbol = malloc((sizeof(SYMBOL) + strlen(pString) + 1) & ~3);
  3411. if (!pSymbol) {
  3412. dprintf("AllocSymbol - Out of memory\n");
  3413. ExitProcess(STATUS_UNSUCCESSFUL);
  3414. }
  3415. // set the offset and decode the string into its count of
  3416. // underscores and copy the remaining string
  3417. pSymbol->offset = offset;
  3418. while (*pStringTemp == '_')
  3419. pStringTemp++;
  3420. pSymbol->underscores = (CHAR)(pStringTemp - pString);
  3421. pSymbol->modIndex = iModule;
  3422. pSymbol->type = SYMBOL_TYPE_SYMBOL;
  3423. pSymbol->pLocal = NULL;
  3424. strcpy(pSymbol->string, pStringTemp);
  3425. return pSymbol;
  3426. }
  3427. #ifdef NT_SAPI
  3428. static
  3429. SYMBOL symbolTemplate = { 0,0, {NULL, NULL, NULL }, { NULL, NULL, NULL }, -1L,
  3430. 0, 0, SYMBOL_TYPE_SYMBOL, NULL,
  3431. { '\177', '\177', '\0' } };
  3432. static
  3433. #else
  3434. SYMBOL symbolTemplate = { { NULL, NULL, NULL }, { NULL, NULL, NULL }, -1L,
  3435. 0, 0, SYMBOL_TYPE_SYMBOL, NULL, 0,
  3436. { '\177', '\177', '\0' } };
  3437. #endif /* NT_SAPI */
  3438. /*** AllocSymfile - build and allocate symbol file structure
  3439. *
  3440. * Purpose:
  3441. * Allocate space for symbol file structure.
  3442. *
  3443. * Input:
  3444. * offset - offset of symbol to be allocated
  3445. * pString - pointer to string of symbol to be allocated
  3446. *
  3447. * Returns:
  3448. * pointer to filled symbol structure
  3449. *
  3450. *************************************************************************/
  3451. PSYMFILE AllocSymfile (PUCHAR pPathname, PUCHAR pFilename,
  3452. PUCHAR pExtension,
  3453. PIMAGE_LINENUMBER pCoffLineno, USHORT cLineno,
  3454. ULONG startingOffset, ULONG endingOffset,
  3455. CHAR modIndex)
  3456. {
  3457. PSYMFILE pSymfile;
  3458. PLINENO pLineno;
  3459. USHORT index;
  3460. PSYMBOL symbolMax;
  3461. IMAGE_LINENUMBER CoffLineno;
  3462. pSymfile = malloc(sizeof(SYMFILE));
  3463. if (!pSymfile) {
  3464. dprintf("AllocSymfile - Out of memory\n");
  3465. ExitProcess(STATUS_UNSUCCESSFUL);
  3466. }
  3467. symbolMax = &pSymfile->maxSymbol;
  3468. *symbolMax = symbolTemplate;
  3469. pSymfile->symcontextFunctionOffset.pNodeRoot = NULL;
  3470. pSymfile->symcontextFunctionOffset.pNodeMax =
  3471. (PNODE)((LONG)symbolMax + NODE_SYMBOL_DISPLACEMENT(nodeOffset));
  3472. pSymfile->symcontextFunctionOffset.pfnCompare = &CompareSymbolOffset;
  3473. pSymfile->symcontextFunctionOffset.nodeDisplacement =
  3474. NODE_SYMBOL_DISPLACEMENT(nodeOffset);
  3475. pSymfile->symcontextFunctionString.pNodeRoot = NULL;
  3476. pSymfile->symcontextFunctionString.pNodeMax =
  3477. (PNODE)((LONG)symbolMax + NODE_SYMBOL_DISPLACEMENT(nodeString));
  3478. pSymfile->symcontextFunctionString.pfnCompare = &CompareSymbolString;
  3479. pSymfile->symcontextFunctionString.nodeDisplacement =
  3480. NODE_SYMBOL_DISPLACEMENT(nodeString);
  3481. pSymfile->pchPath = malloc(strlen(pPathname) + 1);
  3482. if (!pSymfile->pchPath) {
  3483. dprintf("AllocSymfile - Out of memory\n");
  3484. ExitProcess(STATUS_UNSUCCESSFUL);
  3485. }
  3486. strcpy(pSymfile->pchPath, pPathname);
  3487. pSymfile->pchName = malloc(strlen(pFilename) + 1);
  3488. if (!pSymfile->pchName) {
  3489. dprintf("AllocSymfile - Out of memory\n");
  3490. ExitProcess(STATUS_UNSUCCESSFUL);
  3491. }
  3492. strcpy(pSymfile->pchName, pFilename);
  3493. pSymfile->pchExtension = malloc(strlen(pExtension) + 1);
  3494. if (!pSymfile->pchExtension) {
  3495. dprintf("AllocSymfile - Out of memory\n");
  3496. ExitProcess(STATUS_UNSUCCESSFUL);
  3497. }
  3498. strcpy(pSymfile->pchExtension, pExtension);
  3499. pSymfile->modIndex = modIndex;
  3500. pSymfile->cLineno = cLineno;
  3501. if (pCoffLineno) {
  3502. pSymfile->pLineno = malloc((cLineno + 1) * sizeof(LINENO));
  3503. if (!pSymfile->pLineno) {
  3504. dprintf("AllocSymfile - Out of memory\n");
  3505. ExitProcess(STATUS_UNSUCCESSFUL);
  3506. }
  3507. pLineno = pSymfile->pLineno;
  3508. // define pseudo-lineno structure for start of file
  3509. pLineno->memoryOffset = 0;
  3510. pLineno->breakLineNumber = 1;
  3511. pLineno->topLineNumber = 1;
  3512. pLineno->topFileOffset = 0;
  3513. pLineno++;
  3514. // first lineno to process is after the pseudo entry
  3515. pSymfile->pLinenoNext = pLineno;
  3516. // process list into remaining entries in array
  3517. for (index = 0; index < pSymfile->cLineno; index++) {
  3518. memcpy((PUCHAR)&CoffLineno, (PUCHAR)pCoffLineno,
  3519. IMAGE_SIZEOF_LINENUMBER);
  3520. pLineno->memoryOffset = CoffLineno.Type.VirtualAddress;
  3521. pLineno->breakLineNumber = CoffLineno.Linenumber;
  3522. pLineno->topLineNumber = 0xffff;
  3523. pLineno->topFileOffset = -1L;
  3524. pLineno++;
  3525. pCoffLineno = (PIMAGE_LINENUMBER)((PUCHAR)pCoffLineno
  3526. + IMAGE_SIZEOF_LINENUMBER);
  3527. }
  3528. // initialize further...
  3529. pSymfile->nextFileOffset = 0;
  3530. pSymfile->nextLineNumber = 1;
  3531. pSymfile->nextScanState = stStart;
  3532. // allocate and initialize list of PLINENO's for sorting
  3533. // of line number for the file.
  3534. pSymfile->ppLinenoSrcLine = malloc(
  3535. (pSymfile->cLineno + 1) * sizeof(PLINENO));
  3536. if (!pSymfile->ppLinenoSrcLine) {
  3537. dprintf("AllocSymfile - Out of memory\n");
  3538. ExitProcess(STATUS_UNSUCCESSFUL);
  3539. }
  3540. for (index = 0; index < (USHORT)(pSymfile->cLineno + 1); index++)
  3541. *(pSymfile->ppLinenoSrcLine + index) = pSymfile->pLineno + index;
  3542. // first LINENO to process on scan is after pseudo-entry
  3543. pSymfile->ppLinenoSrcNext = pSymfile->ppLinenoSrcLine + 1;
  3544. // sort the pointers for increasing source line numbers
  3545. SortSrcLinePointers(pSymfile);
  3546. }
  3547. else {
  3548. pSymfile->pLineno = NULL;
  3549. pSymfile->ppLinenoSrcLine = NULL;
  3550. }
  3551. pSymfile->startOffset = startingOffset;
  3552. pSymfile->endOffset = endingOffset;
  3553. pSymfile->modIndex = modIndex;
  3554. return pSymfile;
  3555. }
  3556. /*** DeallocSymbol - release symbol space
  3557. *
  3558. * Purpose:
  3559. * Deallocate the symbol space given by the pointer
  3560. *
  3561. * Input:
  3562. * pSymbolReturn - pointer to symbol to return
  3563. *
  3564. * Output:
  3565. * None.
  3566. *
  3567. *************************************************************************/
  3568. void DeallocSymbol (PSYMBOL pSymbolReturn)
  3569. {
  3570. free(pSymbolReturn);
  3571. }
  3572. /*** DeleteSymfile - delete specified symbol file from splay tree
  3573. *
  3574. * Purpose:
  3575. * external routine.
  3576. * Delete the specified symbol file object in both the
  3577. * offset and string trees and deallocate its space.
  3578. *
  3579. * Input:
  3580. * pSymfile - pointer to symfile object to delete
  3581. *
  3582. * Output:
  3583. * None.
  3584. *
  3585. *************************************************************************/
  3586. void DeleteSymfile (PSYMFILE pSymfile)
  3587. {
  3588. DeleteNode(&(pProcessCurrent->symcontextSymfileOffset),
  3589. &(pSymfile->nodeOffset));
  3590. DeleteNode(&(pProcessCurrent->symcontextSymfileString),
  3591. &(pSymfile->nodeString));
  3592. DeallocSymfile(pSymfile);
  3593. }
  3594. /*** DeallocSymfile - release symbol file space
  3595. *
  3596. * Purpose:
  3597. * Deallocate the symbol file space given by the pointer
  3598. *
  3599. * Input:
  3600. * pSymfileReturn - pointer to symbol file to return
  3601. *
  3602. * Output:
  3603. * None.
  3604. *
  3605. *************************************************************************/
  3606. void DeallocSymfile (PSYMFILE pSymfile)
  3607. {
  3608. free(pSymfile->pchPath);
  3609. free(pSymfile->pchName);
  3610. free(pSymfile->pchExtension);
  3611. free(pSymfile->pLineno);
  3612. free(pSymfile->ppLinenoSrcLine);
  3613. free(pSymfile);
  3614. }
  3615. /*** ntsdstricmp - case-insensitive string compare
  3616. *
  3617. * Purpose:
  3618. * Compare two strings, but map upper case to lower
  3619. *
  3620. * Input:
  3621. * pchDst - pointer to first string
  3622. * pchSrc - pointer to second string
  3623. *
  3624. * Output:
  3625. * -1 if value(pchDst) < value(pchSrc)
  3626. * 0 if value(pchDst) = value(pchSrc)
  3627. * 1 if value(pchDst) > value(pchSrc)
  3628. *
  3629. *************************************************************************/
  3630. int ntsdstricmp (PUCHAR pchDst, PUCHAR pchSrc)
  3631. {
  3632. UCHAR ch1;
  3633. UCHAR ch2;
  3634. do {
  3635. ch1 = (UCHAR)tolower(*pchDst++);
  3636. ch2 = (UCHAR)tolower(*pchSrc++);
  3637. }
  3638. while (ch1 && ch1 == ch2);
  3639. if (ch1 < ch2)
  3640. return -1;
  3641. else
  3642. return ch1 > ch2;
  3643. }
  3644. #ifndef NT_SAPI
  3645. /*** fnListNear - function to list symbols near an address
  3646. *
  3647. * Purpose:
  3648. * from the address specified, access the symbol table to
  3649. * find the closest symbolic addresses both before and after
  3650. * it. output these on one line (if spaces permits).
  3651. *
  3652. * Input:
  3653. * addrstart - address to base listing
  3654. *
  3655. * Output:
  3656. * symbolic and absolute addresses of variable on or before
  3657. * and after the specified address
  3658. *
  3659. *************************************************************************/
  3660. static char szBlanks[] = " ";
  3661. void fnListNear (ULONG addrStart)
  3662. {
  3663. PSYMBOL pSymbol;
  3664. PNODE pNode;
  3665. ULONG cbString[2];
  3666. UCHAR szEntry[80];
  3667. PUCHAR pszEntry;
  3668. ULONG count;
  3669. ULONG index;
  3670. // make a symbol structure with the supplied offset
  3671. pSymbol = AllocSymbol(addrStart, "", -1);
  3672. // try to access the node with the offset given.
  3673. // the node pointer returned will be the nearest offset less
  3674. // than the argument (unless it is less than the tree minimum)
  3675. AccessNode(&(pProcessCurrent->symcontextSymbolOffset),
  3676. &(pSymbol->nodeOffset));
  3677. // Don't need this anymore, free it.
  3678. DeallocSymbol(pSymbol);
  3679. pNode = pProcessCurrent->symcontextSymbolOffset.pNodeRoot;
  3680. // if empty tree, no symbols, just return
  3681. if (!pNode)
  3682. return;
  3683. // if offset of initial node is less than request address,
  3684. // set node pointer to NULL
  3685. if (PNODE_TO_PSYMBOL(pNode,
  3686. &(pProcessCurrent->symcontextSymbolOffset))->offset
  3687. > addrStart)
  3688. pNode = NULL;
  3689. // build the string for the symbol before and after (index = 0 and 1)
  3690. for (index = 0; index < 2; index++) {
  3691. pszEntry = szEntry;
  3692. if (pNode) {
  3693. pSymbol = PNODE_TO_PSYMBOL(pNode,
  3694. &(pProcessCurrent->symcontextSymbolOffset));
  3695. pszEntry += sprintf(pszEntry, "(%08lx) ", pSymbol->offset);
  3696. pszEntry += sprintf(pszEntry, "%s!",
  3697. pImageFromIndex(pSymbol->modIndex)->pszName);
  3698. count = pSymbol->underscores;
  3699. while (count--)
  3700. pszEntry += sprintf(pszEntry, "_");
  3701. pszEntry += sprintf(pszEntry, "%s", pSymbol->string);
  3702. }
  3703. else {
  3704. if (index == 0)
  3705. pszEntry += sprintf(pszEntry, "(%08lx) ", addrStart);
  3706. pszEntry += sprintf(pszEntry, "<no symbol>");
  3707. }
  3708. cbString[index] = pszEntry - szEntry;
  3709. if (index == 0) {
  3710. dprintf("%s", szEntry);
  3711. pNode = NextNode(&(pProcessCurrent->symcontextSymbolOffset),
  3712. pNode);
  3713. }
  3714. }
  3715. // the first string has been output, szEntry has the second string
  3716. // and cbString[0] and [1] have their respective sizes.
  3717. if (cbString[0] + cbString[1] < 75)
  3718. dprintf(" | ");
  3719. else {
  3720. dprintf("\n");
  3721. count = 78 - cbString[1];
  3722. dprintf(&szBlanks[sizeof(szBlanks) - count]);
  3723. }
  3724. dprintf("%s\n", szEntry);
  3725. }
  3726. #endif /* NT_SAPI */
  3727. void SortSrcLinePointers (PSYMFILE pSymfile)
  3728. {
  3729. PPLINENO ppLineno = pSymfile->ppLinenoSrcLine;
  3730. PLINENO pLinenoV;
  3731. USHORT N;
  3732. USHORT h;
  3733. USHORT i;
  3734. USHORT j;
  3735. // PDK KLUGDE:::
  3736. if (!ppLineno) return;
  3737. N = (USHORT)(pSymfile->cLineno - 1);
  3738. h = 1;
  3739. do
  3740. h = (USHORT)(3 * h + 1);
  3741. while (h <= N);
  3742. do {
  3743. h = (USHORT)(h / 3);
  3744. for (i = h; i < N; i++) {
  3745. pLinenoV = *(ppLineno + i);
  3746. j = i;
  3747. while ((*(ppLineno + j - h))->breakLineNumber
  3748. > pLinenoV->breakLineNumber) {
  3749. *(ppLineno + j) = *(ppLineno + j - h);
  3750. j = j - h;
  3751. if (j < h)
  3752. break;
  3753. }
  3754. *(ppLineno + j) = pLinenoV;
  3755. }
  3756. }
  3757. while (h > 1);
  3758. }
  3759. #ifndef NT_SAPI
  3760. #if 0
  3761. void OutputAtLineno (PSYMFILE pSymfile, PLINENO pLineno)
  3762. {
  3763. USHORT index;
  3764. UCHAR buffer[180];
  3765. FILE * fhandle;
  3766. UpdateLineno(pSymfile, pLineno);
  3767. fhandle = LocateTextInSource(pSymfile, pLineno);
  3768. if (fhandle)
  3769. for (index = pLineno->topLineNumber;
  3770. index <= pLineno->breakLineNumber; index++) {
  3771. if (!fgets(buffer, sizeof(buffer), fhandle))
  3772. error(FILEREAD);
  3773. dprintf("%4d: %s", index, buffer);
  3774. }
  3775. }
  3776. #endif
  3777. void UpdateLineno (PSYMFILE pSymfile, PLINENO pLineno)
  3778. {
  3779. PPLINENO ppLinenoNext;
  3780. UCHAR scanState;
  3781. USHORT nextLineNumber;
  3782. USHORT topLineNumber;
  3783. ULONG topFileOffset;
  3784. FILE * fhandle;
  3785. UCHAR ch;
  3786. // if line number structure is already processed,
  3787. // then just return.
  3788. if (pLineno->topLineNumber == 0xffff) {
  3789. // copy variables from the symbol file structure
  3790. ppLinenoNext = pSymfile->ppLinenoSrcNext;
  3791. scanState = pSymfile->nextScanState;
  3792. nextLineNumber = pSymfile->nextLineNumber;
  3793. // open and locate the file to the position specified in
  3794. // the symbol file structure. if no handle, return error.
  3795. fhandle = LocateTextInSource(pSymfile, NULL);
  3796. if (!fhandle)
  3797. return;
  3798. // for each LINENO structure pointed by ppLinenoNext
  3799. // until pLineno is processed, compute the
  3800. // topLineNumber and topFileOffset.
  3801. do {
  3802. topFileOffset = ftell(fhandle);
  3803. topLineNumber = nextLineNumber;
  3804. // test if the current LINENO structure has the same
  3805. // breakLineNumber as the previous LINENO in the
  3806. // ppLineno list.
  3807. if ((*ppLinenoNext)->breakLineNumber ==
  3808. (*(ppLinenoNext - 1))->breakLineNumber) {
  3809. // if this is a repeating line number, just copy
  3810. // the topFileOffset and topLineNumber entries
  3811. (*ppLinenoNext)->topFileOffset =
  3812. (*(ppLinenoNext - 1))->topFileOffset;
  3813. (*ppLinenoNext)->topLineNumber =
  3814. (*(ppLinenoNext - 1))->topLineNumber;
  3815. }
  3816. else {
  3817. // nonrepeating line number - determine new topFileOffset
  3818. // and topLineNumber entries
  3819. // scan each line in the source file, numbered by
  3820. // nextLineNumber until the line numbered by
  3821. // (*ppLinenoNext)->breakLineNumber is scanned.
  3822. do {
  3823. // to scan a source file line, read each character
  3824. // and change scanState appropriately and exit
  3825. // when a '\n' is read.
  3826. do {
  3827. ch = (UCHAR)getc(fhandle);
  3828. switch (ch) {
  3829. case '\t':
  3830. case ' ':
  3831. scanState = WhiteSpace[scanState];
  3832. break;
  3833. case '/':
  3834. scanState = Slash[scanState];
  3835. break;
  3836. case '*':
  3837. scanState = Star[scanState];
  3838. break;
  3839. case '#':
  3840. scanState = Pound[scanState];
  3841. break;
  3842. case '\n':
  3843. case '\r':
  3844. break;
  3845. case (UCHAR)EOF:
  3846. error(FILEREAD);
  3847. default:
  3848. scanState = OtherChar[scanState];
  3849. break;
  3850. }
  3851. }
  3852. while (ch != '\n');
  3853. // if the final scan state of the line is a comment
  3854. // and the line is not a breaking line number,
  3855. // set the topFileOffset and topLineNumber to
  3856. // the line after the one just scanned.
  3857. if (fCommentType[scanState]
  3858. && nextLineNumber != pLineno->breakLineNumber) {
  3859. topFileOffset = ftell(fhandle);
  3860. topLineNumber = (USHORT)(nextLineNumber + 1);
  3861. }
  3862. // set the state for the next line, either stStart
  3863. // or stSlStar for a continuing multiline comment
  3864. scanState = Return[scanState];
  3865. }
  3866. while (nextLineNumber++ != (*ppLinenoNext)->breakLineNumber);
  3867. // put topFileOffset and topLineNumber into the pLineno
  3868. // to finish its processing
  3869. (*ppLinenoNext)->topFileOffset = topFileOffset;
  3870. (*ppLinenoNext)->topLineNumber = topLineNumber;
  3871. }
  3872. }
  3873. while (*(ppLinenoNext++) != pLineno);
  3874. // set the variables back in the symbol file structure
  3875. // for the next call
  3876. pSymfile->ppLinenoSrcNext = ppLinenoNext;
  3877. pSymfile->nextScanState = scanState;
  3878. pSymfile->nextFileOffset = ftell(fhandle);
  3879. pSymfile->nextLineNumber = nextLineNumber;
  3880. }
  3881. }
  3882. FILE * LocateTextInSource (PSYMFILE pSymfile, PLINENO pLineno)
  3883. {
  3884. static FILE * fhandle = NULL;
  3885. static PSYMFILE pSymfileOpened = NULL;
  3886. UCHAR chFilename[512];
  3887. PUCHAR pchTemp;
  3888. if (pSymfile != pSymfileOpened) {
  3889. if (fhandle) {
  3890. fclose(fhandle);
  3891. fhandle = NULL;
  3892. pSymfileOpened = NULL;
  3893. }
  3894. if (pSymfile && pSymfile->pchPath)
  3895. do {
  3896. strcpy(chFilename, pSymfile->pchPath);
  3897. strcat(chFilename, pSymfile->pchName);
  3898. strcat(chFilename, pSymfile->pchExtension);
  3899. fhandle = fopen(chFilename, "r");
  3900. if (!fhandle) {
  3901. dprintf("enter path for '%s%s%s' (cr for none):",
  3902. pSymfile->pchPath, pSymfile->pchName,
  3903. pSymfile->pchExtension);
  3904. NtsdPrompt("", chFilename, 512);
  3905. RemoveDelChar(chFilename);
  3906. // gets(chFilename);
  3907. //#ifdef KERNEL
  3908. // if (*chFilename!=13&&*chFilename!=10) {
  3909. //#else
  3910. if (*chFilename) {
  3911. //#endif
  3912. pchTemp = chFilename + strlen(chFilename) - 1;
  3913. if (*pchTemp != ':' && *pchTemp != '\\')
  3914. strcat(pchTemp + 1, "\\");
  3915. pSymfile->pchPath =
  3916. realloc(pSymfile->pchPath,
  3917. strlen(chFilename) + 1);
  3918. strcpy(pSymfile->pchPath, chFilename);
  3919. }
  3920. else {
  3921. free(pSymfile->pchPath);
  3922. pSymfile->pchPath = NULL;
  3923. return NULL;
  3924. }
  3925. }
  3926. else
  3927. pSymfileOpened = pSymfile;
  3928. }
  3929. while (!fhandle && chFilename[0]);
  3930. }
  3931. if (fhandle)
  3932. fseek(fhandle, pLineno ? pLineno->topFileOffset
  3933. : pSymfile->nextFileOffset, SEEK_SET);
  3934. return fhandle;
  3935. }
  3936. void OutputSourceLines (PSYMFILE pSymfile, USHORT startLineNum, USHORT count)
  3937. {
  3938. PPLINENO ppLineno;
  3939. USHORT indexLow;
  3940. USHORT indexTest;
  3941. USHORT indexHigh;
  3942. // search the PLINENO array for the pointer to the LINENO
  3943. // structure having the line number given.
  3944. ppLineno = pSymfile->ppLinenoSrcLine;
  3945. indexLow = 1;
  3946. // PDK KLUDGE:::
  3947. if (!(indexHigh = pSymfile->cLineno)) return;
  3948. do {
  3949. indexTest = (USHORT)((indexLow + indexHigh) / 2);
  3950. if (startLineNum > (*(ppLineno + indexTest))->breakLineNumber)
  3951. indexLow = (USHORT)(indexTest + 1);
  3952. else if (startLineNum < (*(ppLineno + indexTest))->breakLineNumber)
  3953. indexHigh = (USHORT)(indexTest - 1);
  3954. else
  3955. indexLow = indexHigh = indexTest;
  3956. }
  3957. while (indexLow < indexHigh);
  3958. // if startLineNum is larger than the maximum line number in
  3959. // the list, indexLow is past the last entry.
  3960. // set indexLow to the last entry in this case.
  3961. if (indexLow > pSymfile->cLineno)
  3962. indexLow--;
  3963. // indexLow refers to the LINENO structure with a line
  3964. // number equal to or greater than startLineNum.
  3965. UpdateLineno(pSymfile, *(ppLineno + indexLow));
  3966. if (startLineNum < (*(ppLineno + indexLow))->topLineNumber)
  3967. indexLow--;
  3968. OutputLines(pSymfile, *(ppLineno + indexLow), startLineNum, count);
  3969. }
  3970. BOOLEAN OutputSourceFromOffset (ULONG offset, BOOLEAN fMatch)
  3971. {
  3972. PSYMFILE pSymfile;
  3973. PLINENO pLineno;
  3974. BOOLEAN fOutput = FALSE;
  3975. pLineno = GetLinenoFromOffset(&pSymfile, offset);
  3976. if (pLineno) {
  3977. UpdateLineno(pSymfile, pLineno);
  3978. if (!fMatch || pLineno->memoryOffset == offset)
  3979. fOutput = OutputLines(pSymfile, pLineno, pLineno->topLineNumber,
  3980. (SHORT)(pLineno->breakLineNumber
  3981. - pLineno->topLineNumber + 1));
  3982. }
  3983. return fOutput;
  3984. }
  3985. BOOLEAN OutputLines (PSYMFILE pSymfile, PLINENO pLineno, USHORT startLineNum,
  3986. USHORT count)
  3987. {
  3988. FILE * fhandle;
  3989. UCHAR buffer[180];
  3990. USHORT lineNumber;
  3991. PSYMFILE pSymfileNext;
  3992. PLINENO pLinenoNext;
  3993. UpdateLineno(pSymfile, pLineno);
  3994. fhandle = LocateTextInSource(pSymfile, pLineno);
  3995. if (!fhandle)
  3996. return FALSE;
  3997. lineNumber = pLineno->topLineNumber;
  3998. // output module and filename as label.
  3999. dprintf("%s!%s:\n", pImageFromIndex(pSymfile->modIndex)->pszName,
  4000. pSymfile->pchName);
  4001. while (count) {
  4002. // read the next line - report read error
  4003. fgets(buffer, sizeof(buffer), fhandle);
  4004. if (ferror(fhandle))
  4005. error(FILEREAD);
  4006. // if EOF and no lines printed, break last valid line
  4007. // if lines printed, just exit
  4008. if (feof(fhandle)) {
  4009. if (--lineNumber < startLineNum) {
  4010. startLineNum = lineNumber;
  4011. count = 1;
  4012. }
  4013. else
  4014. break;
  4015. }
  4016. if (lineNumber >= startLineNum) {
  4017. dprintf("%4d", lineNumber);
  4018. // if linenumber is on a breakpoint,
  4019. // output a '>', if not, ':'.
  4020. pLinenoNext = GetLinenoFromFilename(pSymfile->pchName,
  4021. &pSymfileNext, lineNumber, pSymfile->modIndex);
  4022. if (lineNumber == pLinenoNext->breakLineNumber)
  4023. dprintf(">");
  4024. else
  4025. dprintf(":");
  4026. dprintf(" %s", buffer);
  4027. count--;
  4028. }
  4029. lineNumber++;
  4030. }
  4031. pSymfileLast = pSymfile;
  4032. lineNumberLast = lineNumber;
  4033. return TRUE;
  4034. }
  4035. #endif /* NT_SAPI */
  4036. PVOID FetchImageDirectoryEntry(int Handle, USHORT DirectoryEntry, PULONG Size, PULONG Base)
  4037. {
  4038. PUCHAR SectionName;
  4039. USHORT Signature;
  4040. ULONG i, DirectoryAddress;
  4041. IMAGE_FILE_HEADER CoffFileHdr;
  4042. IMAGE_OPTIONAL_HEADER CoffOptionalHdr;
  4043. IMAGE_SECTION_HEADER CoffSectionHdr;
  4044. ULONG DosHeader[16], NtSignature;
  4045. if ( DirectoryEntry >= IMAGE_NUMBEROF_DIRECTORY_ENTRIES ) {
  4046. return NULL;
  4047. }
  4048. CV_SEEK(Handle, 0, SEEK_SET);
  4049. CV_READ(Handle, &Signature, sizeof(USHORT));
  4050. CV_SEEK(Handle, 0, SEEK_SET);
  4051. if (Signature == IMAGE_DOS_SIGNATURE) {
  4052. CV_READ(Handle, &DosHeader, 16*sizeof(ULONG));
  4053. CV_SEEK(Handle, DosHeader[15], SEEK_SET);
  4054. CV_READ(Handle, &NtSignature, sizeof(ULONG));
  4055. if (NtSignature != IMAGE_NT_SIGNATURE) {
  4056. printf("\nPE signature not found\n");
  4057. }
  4058. }
  4059. CV_READ(Handle, &CoffFileHdr, sizeof(IMAGE_FILE_HEADER));
  4060. CV_READ(Handle, &CoffOptionalHdr, CoffFileHdr.SizeOfOptionalHeader);
  4061. #ifdef NT_SAPI
  4062. ObjectTableCount = CoffFileHdr.NumberOfSections;
  4063. ObjectTableOffset = CV_TELL(Handle);
  4064. #endif
  4065. if (CoffFileHdr.SizeOfOptionalHeader < IMAGE_SIZEOF_NT_OPTIONAL_HEADER) {
  4066. //
  4067. // must be a rom image
  4068. //
  4069. *Base = 0;
  4070. switch (DirectoryEntry) {
  4071. case IMAGE_DIRECTORY_ENTRY_EXPORT : SectionName = ".edata"; break;
  4072. case IMAGE_DIRECTORY_ENTRY_IMPORT : SectionName = ".idata"; break;
  4073. case IMAGE_DIRECTORY_ENTRY_RESOURCE : SectionName = ".rsrc"; break;
  4074. case IMAGE_DIRECTORY_ENTRY_EXCEPTION : SectionName = ".pdata"; break;
  4075. case IMAGE_DIRECTORY_ENTRY_SECURITY : SectionName = ".mdc"; break;
  4076. case IMAGE_DIRECTORY_ENTRY_BASERELOC : SectionName = ".reloc"; break;
  4077. case IMAGE_DIRECTORY_ENTRY_DEBUG : SectionName = ".debug"; break;
  4078. default : SectionName = "";
  4079. }
  4080. for (i=0; i<CoffFileHdr.NumberOfSections; i++) {
  4081. CV_READ(Handle, &CoffSectionHdr, sizeof(IMAGE_SECTION_HEADER));
  4082. if (!strcmp(CoffSectionHdr.Name, SectionName)) {
  4083. *Size = CoffSectionHdr.SizeOfRawData;
  4084. return( (PVOID)CoffSectionHdr.PointerToRawData );
  4085. }
  4086. }
  4087. return NULL;
  4088. } else {
  4089. *Base = CoffOptionalHdr.ImageBase;
  4090. }
  4091. if (!(DirectoryAddress = CoffOptionalHdr.DataDirectory[ DirectoryEntry ].VirtualAddress)) {
  4092. return( NULL );
  4093. }
  4094. *Size = CoffOptionalHdr.DataDirectory[ DirectoryEntry ].Size;
  4095. for (i=0; i<CoffFileHdr.NumberOfSections; i++) {
  4096. CV_READ(Handle, &CoffSectionHdr, sizeof(IMAGE_SECTION_HEADER));
  4097. if (DirectoryAddress >= CoffSectionHdr.VirtualAddress &&
  4098. DirectoryAddress <= CoffSectionHdr.VirtualAddress + CoffSectionHdr.SizeOfRawData) {
  4099. return( (PVOID)((DirectoryAddress - CoffSectionHdr.VirtualAddress) + CoffSectionHdr.PointerToRawData) );
  4100. }
  4101. }
  4102. return( NULL );
  4103. }