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

711 lines
19 KiB

  1. /*++
  2. Copyright (c) 1990 Microsoft Corporation
  3. Module Name:
  4. sym.c
  5. Abstract:
  6. This function contains the 16-bit symbol support for VDMDBG
  7. Author:
  8. Bob Day (bobday) 29-Feb-1992 Grabbed standard header
  9. Revision History:
  10. Neil Sandlin (NeilSa) 15-Jan-1996 Merged with vdmexts
  11. Neil Sandlin (NeilSa) 01-Mar-1997 Moved it to VDMDBG,
  12. Rewrote it
  13. --*/
  14. #include <precomp.h>
  15. #pragma hdrstop
  16. #define PRINTF(x) TRUE
  17. #define MYOF_FLAGS (OF_READ | OF_SHARE_DENY_NONE)
  18. #define MAX_MODULE_LIST 200
  19. char ModuleList[MAX_MODULE_LIST][9];
  20. int ModuleListCount = 0;
  21. typedef struct _SYM_MAP {
  22. WORD map_ptr;
  23. WORD map_lsa;
  24. WORD pgm_ent;
  25. WORD abs_cnt;
  26. WORD abs_ptr;
  27. WORD seg_cnt;
  28. WORD seg_ptr;
  29. BYTE sym_nam_max;
  30. BYTE map_nam_len;
  31. char map_name[20];
  32. } SYM_MAP;
  33. typedef struct _SYM_SEG {
  34. WORD nxt_seg;
  35. WORD sym_cnt;
  36. WORD sym_ptr;
  37. WORD seg_lsa;
  38. WORD seg_in[4];
  39. WORD seg_lin;
  40. BYTE seg_ldd;
  41. char seg_cin;
  42. BYTE seg_nam_len;
  43. char seg_name[20];
  44. } SYM_SEG;
  45. typedef struct _SYM_ITEM {
  46. WORD sym_val;
  47. BYTE sym_nam_len;
  48. char sym_name[256];
  49. } SYM_ITEM;
  50. BOOL
  51. FindExport(
  52. LPSTR filename,
  53. WORD segment,
  54. WORD offset,
  55. LPSTR sym_text,
  56. BOOL next,
  57. LONG *dist
  58. )
  59. {
  60. int iFile;
  61. OFSTRUCT ofs;
  62. int rc;
  63. IMAGE_DOS_HEADER doshdr;
  64. IMAGE_OS2_HEADER winhdr;
  65. BYTE Table[65536];
  66. BYTE bBundles;
  67. BYTE bFlags;
  68. BYTE *ptr;
  69. WORD wIndex = 1;
  70. int i;
  71. int this_dist;
  72. int wIndexBest = -1;
  73. char myfilename[256];
  74. #pragma pack(1)
  75. typedef struct
  76. {
  77. BYTE bFlags;
  78. UNALIGNED WORD wSegOffset;
  79. } FENTRY, *PFENTRY;
  80. typedef struct
  81. {
  82. BYTE bFlags;
  83. UNALIGNED WORD wINT3F;
  84. BYTE bSegNumber;
  85. UNALIGNED WORD wSegOffset;
  86. } MENTRY, *PMENTRY;
  87. #pragma pack()
  88. strncpy(myfilename, filename, sizeof(myfilename));
  89. myfilename[sizeof(myfilename)-1] = '\0';
  90. if (-1 == (iFile=OpenFile(myfilename, &ofs, MYOF_FLAGS))) {
  91. //PRINTF("VDMDBG: Error reading file %s\n", filename);
  92. strncpy(myfilename, filename, sizeof(myfilename)-sizeof(".exe"));
  93. myfilename[sizeof(myfilename)-sizeof(".exe")-1] = '\0';
  94. strcat(myfilename, ".exe");
  95. if (-1 == (iFile=OpenFile(myfilename, &ofs, MYOF_FLAGS))) {
  96. //PRINTF("VDMDBG: Error reading file %s\n", myfilename);
  97. strncpy(myfilename, filename, sizeof(myfilename)-sizeof(".dll"));
  98. myfilename[sizeof(myfilename)-sizeof(".dll")-1] = '\0';
  99. strcat(myfilename, ".dll");
  100. if (-1 == (iFile=OpenFile(myfilename, &ofs, MYOF_FLAGS))) {
  101. //PRINTF("VDMDBG: Error reading file %s\n", myfilename);
  102. PRINTF("VDMDBG: Error reading file\n");
  103. return FALSE;
  104. }
  105. }
  106. }
  107. rc = _lread(iFile, &doshdr, sizeof(doshdr));
  108. if (rc != sizeof(doshdr)) {
  109. PRINTF("VDMDBG: Error reading DOS header\n");
  110. goto Error;
  111. }
  112. if (doshdr.e_magic != IMAGE_DOS_SIGNATURE) {
  113. PRINTF("VDMDBG: Error - no DOS EXE signature");
  114. goto Error;
  115. }
  116. rc = _llseek(iFile, doshdr.e_lfanew, FILE_BEGIN);
  117. if (rc == -1) {
  118. PRINTF("VDMDBG: Error - could not seek - probably not Win3.1 exe\n");
  119. goto Error;
  120. }
  121. rc = _lread(iFile, &winhdr, sizeof(winhdr));
  122. if (rc != sizeof(winhdr)) {
  123. PRINTF("VDMDBG: Error - could not read WIN header - probably not Win3.1 exe\n");
  124. goto Error;
  125. }
  126. if (winhdr.ne_magic != IMAGE_OS2_SIGNATURE) {
  127. PRINTF("VDMDBG: Error - not WIN EXE signature\n");
  128. goto Error;
  129. }
  130. rc = _llseek(iFile, doshdr.e_lfanew+winhdr.ne_enttab, FILE_BEGIN);
  131. if (rc == -1) {
  132. PRINTF("VDMDBG: Error - could not seek to entry table\n");
  133. goto Error;
  134. }
  135. rc = _lread(iFile, Table, winhdr.ne_cbenttab);
  136. if (rc != winhdr.ne_cbenttab) {
  137. PRINTF("VDMDBG: Error - could not read entry table\n");
  138. goto Error;
  139. }
  140. ptr = Table;
  141. while (TRUE) {
  142. bBundles = *ptr++;
  143. if (bBundles == 0)
  144. break;
  145. bFlags = *ptr++;
  146. switch (bFlags) {
  147. case 0: // Placeholders
  148. wIndex += bBundles;
  149. break;
  150. case 0xff: // movable segments
  151. for (i=0; i<(int)bBundles; ++i) {
  152. PMENTRY pe = (PMENTRY )ptr;
  153. if (pe->bSegNumber == segment) {
  154. this_dist = (!next) ? offset - pe->wSegOffset
  155. : pe->wSegOffset - offset;
  156. if ( this_dist >= 0 && (this_dist < *dist || *dist == -1) ) {
  157. // mark this as the best match so far
  158. *dist = this_dist;
  159. wIndexBest = wIndex;
  160. }
  161. }
  162. ptr += sizeof(MENTRY);
  163. wIndex++;
  164. }
  165. break;
  166. default: // fixed segments
  167. if ((int)bFlags != segment) {
  168. ptr += (int)bBundles * sizeof(FENTRY);
  169. wIndex += (int)bBundles;
  170. } else {
  171. for (i=0; i<(int)bBundles; ++i) {
  172. PFENTRY pe = (PFENTRY)ptr;
  173. this_dist = (!next) ? offset - pe->wSegOffset
  174. : pe->wSegOffset - offset;
  175. if ( this_dist >= 0 && (this_dist < *dist || *dist == -1) ) {
  176. // mark this as the best match so far
  177. *dist = this_dist;
  178. wIndexBest = wIndex;
  179. }
  180. ptr += sizeof(FENTRY);
  181. wIndex++;
  182. }
  183. }
  184. break;
  185. }
  186. }
  187. if (wIndexBest == -1) {
  188. // no match found - error out
  189. Error:
  190. _lclose(iFile);
  191. return FALSE;
  192. }
  193. // Success: match found
  194. // wIndexBest = ordinal of the function
  195. // segment:offset = address to look up
  196. // *dist = distance from segment:offset to the symbol
  197. // filename = name of .exe/.dll
  198. // Look for the ordinal in the resident name table
  199. rc = _llseek(iFile, doshdr.e_lfanew+winhdr.ne_restab, FILE_BEGIN);
  200. if (rc == -1) {
  201. PRINTF("VDMDBG: Error - unable to seek to residentname table\n");
  202. goto Error;
  203. }
  204. rc = _lread(iFile, Table, winhdr.ne_modtab-winhdr.ne_restab);
  205. if (rc != winhdr.ne_modtab-winhdr.ne_restab) {
  206. PRINTF("VDMDBG: Error - unable to read entire resident name table\n");
  207. goto Error;
  208. }
  209. ptr = Table;
  210. while (*ptr) {
  211. if ( *(UNALIGNED USHORT *)(ptr+1+*ptr) == (USHORT)wIndexBest) {
  212. // found the matching name
  213. *(ptr+1+*ptr) = '\0'; // null-terminate the function name
  214. strcpy(sym_text, ptr+1);
  215. goto Finished;
  216. }
  217. ptr += *ptr + 3;
  218. }
  219. // Look for the ordinal in the non-resident name table
  220. rc = _llseek(iFile, doshdr.e_lfanew+winhdr.ne_nrestab, FILE_BEGIN);
  221. if (rc == -1) {
  222. PRINTF("VDMDBG: Error - unable to seek to non-residentname table\n");
  223. goto Error;
  224. }
  225. rc = _lread(iFile, Table, winhdr.ne_cbnrestab);
  226. if (rc != winhdr.ne_cbnrestab) {
  227. PRINTF("VDMDBG: Error - unable to read entire non-resident name table\n");
  228. goto Error;
  229. }
  230. ptr = Table;
  231. while (*ptr) {
  232. if ( *(UNALIGNED USHORT *)(ptr+1+*ptr) == (USHORT)wIndexBest) {
  233. // found the matching name
  234. *(ptr+1+*ptr) = '\0'; // null-terminate the function name
  235. strcpy(sym_text, ptr+1);
  236. goto Finished;
  237. }
  238. ptr += *ptr + 3;
  239. }
  240. // fall into error path - no match found
  241. goto Error;
  242. Finished:
  243. _lclose(iFile);
  244. return TRUE;
  245. }
  246. BOOL
  247. ExtractSymbol(
  248. int iFile,
  249. DWORD ulSegPos,
  250. DWORD ulSymPos,
  251. WORD csym,
  252. WORD seglsa,
  253. WORD segment,
  254. DWORD offset,
  255. BOOL next,
  256. LPSTR sym_text,
  257. PLONG pdist
  258. )
  259. {
  260. WORD uLastSymdefPos=0;
  261. /* ulWrap allows for wrapping around with more than 64K of symbols */
  262. DWORD ulWrap=0;
  263. LONG SymOffset;
  264. LONG this_dist;
  265. BOOL fResult = FALSE;
  266. char name_text[256];
  267. for (; csym--; ulSymPos+=sizeof(WORD))
  268. {
  269. WORD uSymdefPos;
  270. SYM_ITEM sym;
  271. if (_llseek(iFile, ulSymPos, FILE_BEGIN) == -1)
  272. return FALSE;
  273. if (_lread(iFile, (LPSTR)&uSymdefPos, sizeof(uSymdefPos)) != sizeof(uSymdefPos))
  274. return FALSE;
  275. if (uSymdefPos < uLastSymdefPos)
  276. ulWrap += 0x10000L;
  277. _llseek(iFile, ulSegPos + uSymdefPos + ulWrap, FILE_BEGIN);
  278. _lread(iFile, (LPSTR)&sym, sizeof(sym));
  279. if (segment == 0) {
  280. SymOffset = (LONG)seglsa*16 + sym.sym_val;
  281. } else {
  282. SymOffset = (LONG)sym.sym_val;
  283. }
  284. // Depending on whether the caller wants the closest symbol
  285. // from below or above, compute the distance from the current
  286. // symbol to the target offset.
  287. switch( next ) {
  288. case FALSE:
  289. this_dist = offset - SymOffset;
  290. break;
  291. case TRUE:
  292. this_dist = SymOffset - offset;
  293. break;
  294. }
  295. //
  296. // Since we don't really know if the current symbol is actually
  297. // the nearest symbol, just remember it if it qualifies. Keep
  298. // the best distance so far in 'dist'.
  299. //
  300. if ((this_dist >= 0) && ((this_dist < *pdist) || (*pdist == -1))) {
  301. *pdist = this_dist;
  302. strncpy(name_text, sym.sym_name, sym.sym_nam_len);
  303. name_text[sym.sym_nam_len] = 0;
  304. fResult = TRUE;
  305. }
  306. uLastSymdefPos = uSymdefPos;
  307. }
  308. if (fResult) {
  309. //
  310. // The scan of the symbols in this segment produced a winner.
  311. // Copy the name and displacement back up to the caller.
  312. //
  313. strcpy(sym_text, name_text);
  314. }
  315. return fResult;
  316. }
  317. BOOL
  318. WalkSegmentsForSymbol(
  319. int iFile,
  320. SYM_MAP *pMap,
  321. ULONG ulMapPos,
  322. WORD segment,
  323. DWORD offset,
  324. BOOL next,
  325. LPSTR sym_text,
  326. PDWORD pDisplacement
  327. )
  328. {
  329. DWORD ulSegPos;
  330. LONG dist = -1;
  331. BOOL fResult = FALSE;
  332. WORD this_seg;
  333. #if 0
  334. /* first, walk absolute segment */
  335. if (fAbsolute && map.abs_cnt != 0) {
  336. /* the thing with seg_ptr below is to allow for an absolute
  337. * segment with more than 64K of symbols: if the segment
  338. * pointer of the next symbol is more than 64K away, then
  339. * add 64K to the beginning of the table of symbol pointers.
  340. */
  341. if (ExtractSymbol(iFile,
  342. ulMapPos,
  343. ulMapPos + pMap->abs_ptr + (pMap->seg_ptr&0xF000)*0x10L,
  344. pMap->abs_cnt,
  345. 0,
  346. segment,
  347. offset,
  348. next,
  349. sym_text,
  350. pDisplacement)) {
  351. return TRUE;
  352. }
  353. }
  354. #endif
  355. /* now walk other segments */
  356. ulSegPos = (DWORD)pMap->seg_ptr * 16;
  357. for (this_seg = 0; this_seg < pMap->seg_cnt; this_seg++) {
  358. SYM_SEG seg;
  359. if (_llseek(iFile, ulSegPos, FILE_BEGIN) == -1)
  360. return FALSE;
  361. if (_lread(iFile, (LPSTR)&seg, sizeof(seg)) != sizeof(seg))
  362. return FALSE;
  363. if ((segment == 0) || (segment == this_seg+1)) {
  364. if (ExtractSymbol(iFile,
  365. ulSegPos,
  366. ulSegPos + seg.sym_ptr,
  367. seg.sym_cnt,
  368. seg.seg_lsa,
  369. segment,
  370. offset,
  371. next,
  372. sym_text,
  373. &dist)) {
  374. fResult = TRUE;
  375. if (segment != 0) {
  376. // only looking in one segment
  377. break;
  378. }
  379. }
  380. }
  381. ulSegPos = (DWORD)seg.nxt_seg * 16;
  382. }
  383. if (fResult) {
  384. *pDisplacement = dist;
  385. }
  386. return fResult;
  387. }
  388. BOOL
  389. WINAPI
  390. VDMGetSymbol(
  391. LPSTR fn,
  392. WORD segment,
  393. DWORD offset,
  394. BOOL bProtectMode,
  395. BOOL next,
  396. LPSTR sym_text,
  397. PDWORD pDisplacement
  398. )
  399. {
  400. int iFile;
  401. char filename[256];
  402. OFSTRUCT ofs;
  403. SYM_MAP map;
  404. SYM_SEG seg;
  405. SYM_ITEM item;
  406. ULONG ulMapPos = 0;
  407. strncpy(filename, fn,sizeof(filename)-sizeof(".sym"));
  408. filename[sizeof(filename)-sizeof(".sym")-1] = '\0';
  409. strcat(filename,".sym");
  410. iFile = OpenFile( filename, &ofs, MYOF_FLAGS );
  411. if ( iFile == -1 ) {
  412. // Open the .EXE/.DLL file and see if the address corresponds
  413. // to an exported function.
  414. return(FindExport(fn,segment,(WORD)offset,sym_text,next,pDisplacement));
  415. }
  416. do {
  417. if (_llseek( iFile, ulMapPos, FILE_BEGIN) == -1) {
  418. PRINTF("VDMDBG: GetSymbol failed to seek to map\n");
  419. break;
  420. }
  421. if (_lread( iFile, (LPSTR)&map, sizeof(map)) != sizeof(map)) {
  422. PRINTF("VDMDBG: GetSymbol failed to read map\n");
  423. break;
  424. }
  425. if (WalkSegmentsForSymbol(iFile, &map, ulMapPos,
  426. segment, offset, next,
  427. sym_text, pDisplacement)) {
  428. _lclose( iFile );
  429. return TRUE;
  430. }
  431. } while(ulMapPos);
  432. _lclose( iFile );
  433. return FALSE;
  434. }
  435. BOOL
  436. ExtractValue(
  437. int iFile,
  438. DWORD ulSegPos,
  439. DWORD ulSymPos,
  440. WORD csym,
  441. LPSTR szSymbol,
  442. PWORD pValue
  443. )
  444. {
  445. WORD uLastSymdefPos=0;
  446. /* ulWrap allows for wrapping around with more than 64K of symbols */
  447. DWORD ulWrap=0;
  448. LONG SymOffset;
  449. char name_text[256];
  450. for (; csym--; ulSymPos+=sizeof(WORD))
  451. {
  452. WORD uSymdefPos;
  453. SYM_ITEM sym;
  454. if (_llseek(iFile, ulSymPos, FILE_BEGIN) == -1)
  455. return FALSE;
  456. if (_lread(iFile, (LPSTR)&uSymdefPos, sizeof(uSymdefPos)) != sizeof(uSymdefPos))
  457. return FALSE;
  458. if (uSymdefPos < uLastSymdefPos)
  459. ulWrap += 0x10000L;
  460. _llseek(iFile, ulSegPos + uSymdefPos + ulWrap, FILE_BEGIN);
  461. _lread(iFile, (LPSTR)&sym, sizeof(sym));
  462. strncpy(name_text, sym.sym_name, sym.sym_nam_len);
  463. name_text[sym.sym_nam_len] = 0;
  464. if (_stricmp(szSymbol, name_text) == 0) {
  465. *pValue = sym.sym_val;
  466. return TRUE;
  467. }
  468. uLastSymdefPos = uSymdefPos;
  469. }
  470. return FALSE;
  471. }
  472. BOOL
  473. WalkSegmentsForValue(
  474. int iFile,
  475. SYM_MAP *pMap,
  476. ULONG ulMapPos,
  477. LPSTR szSymbol,
  478. PWORD pSegmentBase,
  479. PWORD pSegmentNumber,
  480. PWORD pValue
  481. )
  482. {
  483. DWORD ulSegPos;
  484. WORD this_seg;
  485. #if 0
  486. /* first, walk absolute segment */
  487. if (fAbsolute && pMap->abs_cnt != 0) {
  488. /* the thing with seg_ptr below is to allow for an absolute
  489. * segment with more than 64K of symbols: if the segment
  490. * pointer of the next symbol is more than 64K away, then
  491. * add 64K to the beginning of the table of symbol pointers.
  492. */
  493. if (ExtractValue(iFile,
  494. ulMapPos,
  495. ulMapPos + pMap->abs_ptr + (pMap->seg_ptr&0xF000)*0x10L,
  496. pMap->abs_cnt,
  497. szSymbol,
  498. pValue)) {
  499. return TRUE;
  500. }
  501. }
  502. #endif
  503. /* now walk other segments */
  504. ulSegPos = (DWORD)pMap->seg_ptr * 16;
  505. for (this_seg = 0; this_seg < pMap->seg_cnt; this_seg++) {
  506. SYM_SEG seg;
  507. if (_llseek(iFile, ulSegPos, FILE_BEGIN) == -1)
  508. return FALSE;
  509. if (_lread(iFile, (LPSTR)&seg, sizeof(seg)) != sizeof(seg))
  510. return FALSE;
  511. if (ExtractValue(iFile,
  512. ulSegPos,
  513. ulSegPos + seg.sym_ptr,
  514. seg.sym_cnt,
  515. szSymbol,
  516. pValue)) {
  517. *pSegmentBase = seg.seg_lsa;
  518. *pSegmentNumber = this_seg+1;
  519. return TRUE;
  520. }
  521. ulSegPos = (DWORD)seg.nxt_seg * 16;
  522. }
  523. return FALSE;
  524. }
  525. BOOL
  526. WalkMapForValue(
  527. LPSTR fn,
  528. LPSTR szSymbol,
  529. PWORD pSelector,
  530. PDWORD pOffset,
  531. PWORD pType
  532. )
  533. {
  534. int iFile;
  535. char filename[256];
  536. OFSTRUCT ofs;
  537. SYM_MAP map;
  538. SYM_SEG seg;
  539. SYM_ITEM item;
  540. ULONG ulMapPos = 0;
  541. WORD SegmentNumber;
  542. WORD SegmentBase;
  543. WORD Value;
  544. strncpy(filename, fn, sizeof(filename)-sizeof(".sym"));
  545. filename[sizeof(filename)-sizeof(".sym")-1] = '\0';
  546. strcat(filename,".sym");
  547. iFile = OpenFile( filename, &ofs, MYOF_FLAGS );
  548. if ( iFile == -1 ) {
  549. return FALSE;
  550. }
  551. do {
  552. if (_llseek( iFile, ulMapPos, FILE_BEGIN) == -1) {
  553. PRINTF("VDMDBG: failed to seek to map\n");
  554. break;
  555. }
  556. if (_lread( iFile, (LPSTR)&map, sizeof(map)) != sizeof(map)) {
  557. PRINTF("VDMDBG: failed to read map\n");
  558. break;
  559. }
  560. if (WalkSegmentsForValue(iFile, &map, ulMapPos,
  561. szSymbol, &SegmentBase, &SegmentNumber, &Value)) {
  562. VDM_SEGINFO si;
  563. if (GetInfoBySegmentNumber(fn, SegmentNumber, &si)) {
  564. *pSelector = si.Selector;
  565. if (!si.Type) {
  566. *pType = VDMADDR_V86;
  567. if (!si.SegNumber) {
  568. // This is a "combined" map of all the segments,
  569. // so we need to calculate the offset
  570. *pOffset = (DWORD)SegmentBase*16 + Value;
  571. } else {
  572. // This is a "split" v86 map
  573. *pOffset = (DWORD) Value;
  574. }
  575. } else {
  576. *pType = VDMADDR_PM16;
  577. *pOffset = (DWORD)Value;
  578. }
  579. _lclose( iFile );
  580. return TRUE;
  581. }
  582. }
  583. } while(ulMapPos);
  584. _lclose( iFile );
  585. return FALSE;
  586. }
  587. BOOL
  588. WINAPI
  589. VDMGetAddrExpression(
  590. LPSTR szModule,
  591. LPSTR szSymbol,
  592. PWORD pSelector,
  593. PDWORD pOffset,
  594. PWORD pType
  595. )
  596. {
  597. int iFile;
  598. char filename[256];
  599. OFSTRUCT ofs;
  600. SYM_MAP map;
  601. SYM_SEG seg;
  602. SYM_ITEM item;
  603. ULONG ulMapPos = 0;
  604. if (szModule) {
  605. return(WalkMapForValue(szModule, szSymbol, pSelector, pOffset, pType));
  606. }
  607. return (EnumerateModulesForValue(VDMGetAddrExpression,
  608. szSymbol,
  609. pSelector,
  610. pOffset,
  611. pType));
  612. }