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

1110 lines
37 KiB

  1. /* SCCSID = @(#)newpri.c 4.7 86/09/23 */
  2. /*
  3. * Copyright Microsoft Corporation, 1983-1987
  4. *
  5. * This Module contains Proprietary Information of Microsoft
  6. * Corporation and should be treated as Confidential.
  7. */
  8. /* MAP file printer */
  9. /****************************************************************
  10. * *
  11. * NEWPRI.C *
  12. * *
  13. ****************************************************************/
  14. #include <minlit.h> /* Types and constants */
  15. #include <bndtrn.h> /* Basic type & const declarations */
  16. #include <bndrel.h> /* Types and constants */
  17. #include <lnkio.h> /* Linker I/O definitions */
  18. #include <lnkmsg.h> /* Error messages */
  19. #include <newexe.h>
  20. #include <extern.h> /* External declarations */
  21. #include <impexp.h>
  22. #if EXE386
  23. #include <exe386.h>
  24. #endif
  25. #include <undname.h>
  26. #define parent(i) (((i) - 1) >> 1)/* Parent of i */
  27. #define lchild(i) (((i) << 1) + 1)/* Left child of i */
  28. #define rchild(i) (((i) << 1) + 2)/* Right child of i */
  29. #define isleft(i) ((i) & 1) /* True if i is a left child */
  30. RBTYPE *mpsymrbExtra; /* Sort table for extra symbols */
  31. RBTYPE *ompsymrb; /* Stack-allocated sort table */
  32. WORD stkMax; /* Max # of symbols on stack */
  33. LOCAL FTYPE fGrps; /* True if there are groups */
  34. /*
  35. * LOCAL FUNCTION PROTOTYPES
  36. */
  37. LOCAL void NEAR ChkMapErr(void);
  38. LOCAL void NEAR PrintOne(BYTE *sbName,
  39. APROPNAMEPTR apropName);
  40. LOCAL void NEAR PrintProp(RBTYPE rb,
  41. FTYPE attr);
  42. LOCAL void NEAR PrintSyms(WORD irbMac,
  43. FTYPE attr);
  44. LOCAL void SaveHteSym(APROPNAMEPTR prop,
  45. RBTYPE rhte,
  46. RBTYPE rprop,
  47. WORD fNewHte);
  48. LOCAL void NEAR PutSpaces(int HowMany);
  49. LOCAL void NEAR HdrExport(FTYPE attr);
  50. LOCAL void NEAR ShowExp(AHTEPTR ahte,
  51. RBTYPE rprop);
  52. LOCAL void NEAR PrintExps(WORD irbMac,
  53. FTYPE attr);
  54. LOCAL void NEAR HdrName(FTYPE attr);
  55. LOCAL void NEAR HdrValue(FTYPE attr);
  56. LOCAL void NEAR PrintContributors(SNTYPE gsn);
  57. #if AUTOVM
  58. extern BYTE FAR * NEAR FetchSym1(RBTYPE rb, WORD Dirty);
  59. #define FETCHSYM FetchSym1
  60. #else
  61. #define FETCHSYM FetchSym
  62. #endif
  63. LOCAL void NEAR ChkMapErr(void)
  64. {
  65. if (ferror(bsLst))
  66. {
  67. ExitCode = 4;
  68. Fatal(ER_spclst); /* Fatal error */
  69. }
  70. }
  71. LOCAL void NEAR PrintOne(sbName,apropName)
  72. BYTE *sbName; /* Symbol name */
  73. REGISTER APROPNAMEPTR apropName; /* Symbol definition record pointer */
  74. {
  75. SBTYPE sbImp; /* Import name */
  76. SATYPE sa; /* Symbol base */
  77. RATYPE ra; /* Symbol offset */
  78. SEGTYPE seg; /* Segment number */
  79. BYTE FAR *pb;
  80. #if EXE386
  81. typedef struct impMod
  82. {
  83. DWORD am_Name; // Imported module name
  84. RBTYPE am_1stImp; // Head of imported names list
  85. RBTYPE am_lastImp; // Tail of imported names list
  86. DWORD am_count; // Module number/count of imports
  87. }
  88. IMPMOD;
  89. DWORD entry;
  90. IMPMOD *curMod; // Imported module
  91. #else
  92. WORD entry;
  93. #endif
  94. WORD module;
  95. WORD flags;
  96. SNTYPE gsn;
  97. #if NOT OIAPX286
  98. APROPSNPTR papropSn;
  99. SATYPE saGroup;
  100. #endif
  101. SBTYPE sbUndecor;
  102. /*
  103. * Store all needed fields in local variables, because
  104. * page containing symbol definition record can be
  105. * swapped out.
  106. */
  107. ra = apropName->an_ra;
  108. gsn = apropName->an_gsn;
  109. flags = apropName->an_flags;
  110. #if OSEGEXE
  111. #if EXE386
  112. entry = apropName->an_name;
  113. #else
  114. entry = apropName->an_entry;
  115. #endif
  116. module = apropName->an_module;
  117. #endif
  118. if(gsn) /* If not absolute symbol */
  119. {
  120. seg = mpgsnseg[gsn]; /* Get segment number */
  121. sa = mpsegsa[seg]; /* Get base value */
  122. #if NOT OIAPX286
  123. if(!fNewExe && seg <= segLast)
  124. {
  125. papropSn = (APROPSNPTR ) FETCHSYM(mpgsnrprop[gsn],
  126. FALSE);
  127. if(papropSn->as_ggr != GRNIL)
  128. {
  129. saGroup = mpsegsa[mpgsnseg[mpggrgsn[papropSn->as_ggr]]];
  130. ra += (sa - saGroup) << 4;
  131. sa = saGroup;
  132. }
  133. }
  134. #endif
  135. }
  136. else sa = 0; /* Else no base */
  137. if (flags & FUNREF)
  138. {
  139. sa = 0;
  140. ra = 0L;
  141. }
  142. #if EXE386
  143. fprintf(bsLst," %04X:%08lX",sa,ra);
  144. #else
  145. #if O68K
  146. if (f386 || f68k)
  147. #else
  148. if (f386)
  149. #endif
  150. fprintf(bsLst," %04X:%08lX",sa,ra);
  151. else
  152. fprintf(bsLst," %04X:%04X",sa, (WORD) ra);
  153. #endif
  154. /* Write address */
  155. #if OSEGEXE
  156. if (fNewExe && (flags & FIMPORT))
  157. fputs(" Imp ",bsLst); /* If public is an import */
  158. else
  159. #endif
  160. if (flags & FUNREF)
  161. fputs(" Unr ", bsLst);
  162. else if ((!gsn || seg > segLast))
  163. fputs(" Abs ",bsLst); /* Segment type */
  164. #if OVERLAYS
  165. else if (fOverlays)
  166. {
  167. if(mpsegiov[seg] != IOVROOT)
  168. fputs(" Ovl ",bsLst);
  169. else
  170. fputs(" Res ",bsLst);
  171. }
  172. #endif
  173. else
  174. PutSpaces(7);
  175. OutSb(bsLst,sbName); /* Output the symbol */
  176. #if NOT WIN_NT
  177. if (fFullMap && sbName[1] == '?')
  178. {
  179. fputs("\n", bsLst);
  180. UndecorateSb(sbName, sbUndecor, sizeof(sbUndecor));
  181. #if EXE386
  182. PutSpaces(24);
  183. #else
  184. #if O68K
  185. if (f386 || f68k)
  186. #else
  187. if (f386)
  188. #endif
  189. PutSpaces(24);
  190. else
  191. PutSpaces(20);
  192. #endif
  193. OutSb(bsLst, sbUndecor);
  194. fputs("\n", bsLst);
  195. #if OSEGEXE
  196. if (fNewExe && flags & FIMPORT)
  197. PutSpaces(24);
  198. #endif
  199. }
  200. #endif
  201. #if OSEGEXE
  202. if (fNewExe && flags & FIMPORT)
  203. { /* If public is an import */
  204. PutSpaces(20 - B2W(sbName[0])); /* Space fill */
  205. /* Print the module name */
  206. #if EXE386
  207. // Get known import module descriptor
  208. curMod = (IMPMOD *) mapva(AREAMOD + module * sizeof(IMPMOD), FALSE);
  209. strcpy(&sbImp[1], mapva(AREAIMPMOD + curMod->am_Name, FALSE));
  210. /* Get module name */
  211. sbImp[0] = (BYTE) strlen((char *) &sbImp[1]);
  212. #else
  213. pb = &(ImportedName.rgByte[ModuleRefTable.rgWord[module-1]]);
  214. FMEMCPY(sbImp, pb, pb[0] + 1);
  215. #endif
  216. fputs(" (",bsLst); /* Print module name */
  217. OutSb(bsLst,sbImp);
  218. if(!(flags & FIMPORD))
  219. { /* If not imported by ordinal */
  220. /* Print the entry name */
  221. #if EXE386
  222. strnset((char *) sbImp, '\0', sizeof(sbImp));
  223. vmmove(sizeof(sbImp) - 1, &sbImp[1], AREAIMPS + entry + sizeof(WORD), FALSE);
  224. sbImp[0] = (BYTE) strlen((char *) &sbImp[1]);
  225. fputc('!',bsLst);
  226. #else
  227. pb = &(ImportedName.rgByte[entry]);
  228. FMEMCPY(sbImp, pb, pb[0]+1);
  229. fputc('.',bsLst);
  230. #endif
  231. OutSb(bsLst,sbImp);
  232. fputc(')',bsLst);
  233. }
  234. else
  235. fprintf(bsLst,".%u)",entry);
  236. /* Else print entry number */
  237. NEWLINE(bsLst);
  238. return;
  239. }
  240. #endif /* OSEGEXE */
  241. #if OVERLAYS
  242. if (fOverlays && gsn && seg <= segLast && mpsegiov[seg] != IOVROOT)
  243. fprintf(bsLst," (%XH)",mpsegiov[seg]);
  244. #endif
  245. NEWLINE(bsLst);
  246. ChkMapErr();
  247. }
  248. /*
  249. * PrintProp:
  250. *
  251. * Print a symbol, given a virtual property address or hash table
  252. * entry. Called by PrintSyms.
  253. */
  254. LOCAL void NEAR PrintProp (rb, attr)
  255. RBTYPE rb;
  256. ATTRTYPE attr; /* Symbol attribute */
  257. {
  258. #if NOT NEWSYM
  259. APROPNAMETYPE apropName; /* Buffer for symbol def */
  260. #endif
  261. AHTEPTR pahte; /* Pointer to hash table entry */
  262. APROPPTR paprop; /* Pointer to property cell */
  263. SBTYPE sbName; /* Public symbol text */
  264. RBTYPE rprop; /* Property cell virtual address */
  265. paprop = (APROPPTR ) FETCHSYM(rb,FALSE);
  266. /* Fetch property cell from VM */
  267. if(paprop->a_attr == ATTRNIL) /* If we have a hash table entry */
  268. {
  269. pahte = (AHTEPTR ) paprop; /* Recast pointer */
  270. memcpy(sbName,GetFarSb(pahte->cch),B2W(pahte->cch[0]) + 1);
  271. /* Copy the symbol */
  272. paprop = (APROPPTR ) FETCHSYM(pahte->rprop,FALSE);
  273. /* Get pointer to property list */
  274. while(paprop->a_attr != ATTRNIL)
  275. { /* Look through properties */
  276. rprop = paprop->a_next; /* Save link to next cell */
  277. if(paprop->a_attr == attr)
  278. { /* If match found */
  279. #if NEWSYM
  280. PrintOne(sbName,(APROPNAMEPTR)paprop);
  281. #else
  282. memcpy(&apropName,paprop,CBPROPNAME);
  283. /* Copy record from virtual memory */
  284. PrintOne(sbName,&apropName);
  285. /* Print the symbol entry */
  286. #endif
  287. }
  288. paprop = (APROPPTR ) FETCHSYM(rprop,FALSE);
  289. /* Try next in list */
  290. }
  291. return; /* Done */
  292. }
  293. #if NOT NEWSYM
  294. memcpy(&apropName,paprop,CBPROPNAME);
  295. /* Save record in buffer */
  296. #endif
  297. while(paprop->a_attr != ATTRNIL) /* Find symbol */
  298. paprop = (APROPPTR ) FETCHSYM(paprop->a_next,FALSE);
  299. pahte = (AHTEPTR ) paprop; /* Recast pointer */
  300. memcpy(sbName,GetFarSb(pahte->cch),B2W(pahte->cch[0]) + 1);
  301. /* Copy the symbol */
  302. /* Print the symbol entry */
  303. #if NEWSYM
  304. PrintOne(sbName,(APROPNAMEPTR)FETCHSYM(rb,FALSE));
  305. #else
  306. PrintOne(sbName,&apropName);
  307. #endif
  308. }
  309. /****************************************************************
  310. * *
  311. * PrintSyms: *
  312. * *
  313. ****************************************************************/
  314. LOCAL void NEAR PrintSyms(irbMac,attr)
  315. WORD irbMac; /* Table size */
  316. ATTRTYPE attr; /* Symbol attribute */
  317. {
  318. WORD x; /* Sort table index */
  319. for (x = irbMac; x > 0; x--)
  320. PrintProp(ExtractMin(x), attr);
  321. }
  322. /***************************************************************
  323. * *
  324. * SavePropSym: *
  325. * *
  326. ****************************************************************/
  327. void SavePropSym(APROPNAMEPTR prop,
  328. RBTYPE rhte,
  329. RBTYPE rprop,
  330. WORD fNewHte)
  331. {
  332. if(prop->an_attr != ATTRPNM || (prop->an_flags & FPRINT))
  333. { /* If printable, save ptr to info */
  334. Store(rprop);
  335. }
  336. return;
  337. }
  338. /****************************************************************
  339. * *
  340. * SaveHteSym: *
  341. * *
  342. ****************************************************************/
  343. LOCAL void SaveHteSym(APROPNAMEPTR prop,
  344. RBTYPE rhte,
  345. RBTYPE rprop,
  346. WORD fNewHte)
  347. {
  348. if(fNewHte && (prop->an_attr != ATTRPNM || (prop->an_flags & FPRINT)))
  349. { /* If first time and printable */
  350. Store(rhte);
  351. }
  352. return;
  353. }
  354. /*
  355. * FGtAddr:
  356. *
  357. * Compare addresses of symbols pointed to by rb1 and rb2. Return
  358. * -1, 0, or 1 as the address of rb1 is less than, equal to, or greater
  359. * than the address of rb2.
  360. */
  361. int cdecl FGtAddr(const RBTYPE *rb1, const RBTYPE *rb2)
  362. {
  363. APROPNAMEPTR paprop; /* Property cell pointer */
  364. REGISTER SEGTYPE seg1; /* Segment number */
  365. REGISTER SEGTYPE seg2;
  366. WORD sa1; /* Segment base */
  367. WORD sa2;
  368. RATYPE ra1;
  369. RATYPE ra2;
  370. DWORD ibMem1; /* Memory address */
  371. DWORD ibMem2;
  372. paprop = (APROPNAMEPTR ) FETCHSYM(*rb1,FALSE);
  373. /* Fetch from VM */
  374. seg1 = paprop->an_gsn? mpgsnseg[paprop->an_gsn]: SEGNIL;
  375. /* Get segment number */
  376. sa1 = seg1 != SEGNIL? mpsegsa[seg1]: 0;
  377. /* Get frame number */
  378. ra1 = paprop->an_ra;
  379. paprop = (APROPNAMEPTR ) FETCHSYM(*rb2,FALSE);
  380. /* Fetch from VM */
  381. seg2 = paprop->an_gsn? mpgsnseg[paprop->an_gsn]: SEGNIL;
  382. /* Get segment number */
  383. sa2 = seg2 != SEGNIL? mpsegsa[seg2]: 0;
  384. /* Get frame number */
  385. ra2 = paprop->an_ra;
  386. #if OXOUT OR OIAPX286
  387. if(seg1 != SEGNIL && seg2 != SEGNIL)
  388. {
  389. if((mpsegFlags[seg1] & FCODE) &&
  390. !(mpsegFlags[seg2] & FCODE)) return(-1);
  391. /* Code before data */
  392. if((mpsegFlags[seg2] & FCODE) &&
  393. !(mpsegFlags[seg1] & FCODE)) return(1);
  394. /* Data after code */
  395. }
  396. #endif
  397. #if OVERLAYS
  398. if(fOverlays && seg1 != SEGNIL && seg2 != SEGNIL)
  399. {
  400. if(mpsegiov[seg1] > mpsegiov[seg2]) return(1);
  401. if(mpsegiov[seg2] > mpsegiov[seg1]) return(-1);
  402. }
  403. #endif
  404. #if OSEGEXE
  405. if (fNewExe)
  406. {
  407. #if EXE386
  408. if (sa1 == sa2)
  409. {
  410. ibMem1 = ra1;
  411. ibMem2 = ra2;
  412. }
  413. else
  414. ibMem1 = ibMem2 = 0L;
  415. #else
  416. ibMem1 = ((long) sa1 << 16) + ra1;
  417. ibMem2 = ((long) sa2 << 16) + ra2;
  418. #endif
  419. }
  420. else
  421. {
  422. #endif
  423. ibMem1 = ((long) sa1 << 4) + ra1;
  424. ibMem2 = ((long) sa2 << 4) + ra2;
  425. #if OSEGEXE
  426. }
  427. #endif
  428. #ifdef LATER
  429. if ((sa1 != 0 || sa2 != 0) && (sa1 != 0xa9 || sa2 != 0xa9))
  430. fprintf(stderr, "%x:%x %x:%x (%d)\r\n", sa1, paprop1->an_ra,
  431. sa2, paprop2->an_ra, (ibMem1 > ibMem2) ? 1 :
  432. ((ibMem1 < ibMem2) ? -1 : 0));
  433. #endif /*!LATER*/
  434. if (ibMem1 < ibMem2) return(-1);
  435. if (ibMem1 > ibMem2) return(1);
  436. #if EXE386
  437. if (sa1 < sa2) return(-1);
  438. if (sa1 > sa2) return(1);
  439. #endif
  440. return(0);
  441. }
  442. /*
  443. * FGtName:
  444. *
  445. * Compare names of two symbols pointed to by rb1 and rb2. Return
  446. * -1, 0, 1 as the name of rb1 is alphabetically less than, equal to,
  447. * or greater than the name of rb2.
  448. * Ignore case.
  449. */
  450. int cdecl FGtName(const RBTYPE *rb1, const RBTYPE *rb2)
  451. {
  452. AHTEPTR pahte1; /* Hash table pointer */
  453. AHTEPTR pahte2;
  454. REGISTER BYTE *ps1; /* Pointer to first symbol */
  455. REGISTER BYTE FAR *ps2; /* Pointer to second symbol */
  456. WORD len1; /* Symbol length */
  457. WORD len2; /* Symbol length */
  458. WORD length; /* No. of char.s to compare */
  459. int value; /* Comparison value */
  460. pahte1 = (AHTEPTR ) FETCHSYM(*rb1,FALSE);
  461. /* Fetch from VM */
  462. ps1 = GetFarSb((BYTE FAR *) pahte1->cch);
  463. /* Get pointer to first */
  464. pahte2 = (AHTEPTR ) FETCHSYM(*rb2,FALSE);
  465. /* Fetch from VM */
  466. ps2 = (BYTE FAR *) pahte2->cch; /* Get pointer to second */
  467. if((len1 = B2W(*ps1)) < (len2 = B2W(*ps2))) length = len1;
  468. else length = len2; /* Get smallest length */
  469. while(length--) /* While not at end of symbol */
  470. if(value = (*++ps1 & 0137) - (*++ps2 & 0137))
  471. return(value < 0 ? -1 : 1);
  472. if(len1 < len2)
  473. return(-1);
  474. if(len1 > len2)
  475. return(1);
  476. return(0);
  477. }
  478. #if OWNSORT
  479. /*
  480. * An implementation of heapsort follows. It is only used if
  481. * quicksort() from the runtime library is not used.
  482. */
  483. LOCAL reheap(a,n,i) /* Reheapify */
  484. RBTYPE *a; /* Array to reheapify */
  485. WORD n; /* Size of array */
  486. REGISTER WORD i; /* Subtree to start with */
  487. {
  488. REGISTER WORD j; /* Index */
  489. RBTYPE t; /* Temporary */
  490. for(; (j = rchild(i)) < n; i = j) /* Loop through array */
  491. {
  492. if((*cmpf)(&a[i],&a[j]) > 0 && (*cmpf)(&a[i],&a[j - 1]) > 0) return;
  493. /* Done if subtree is heap */
  494. if((*cmpf)(&a[j - 1],&a[j]) > 0) --j; /* Pick "greater" child */
  495. t = a[i]; /* Swap parent and child */
  496. a[i] = a[j];
  497. a[j] = t;
  498. }
  499. if(--j < n && (*cmpf)(&a[j],&a[i]) > 0) /* If swap needed */
  500. {
  501. t = a[i]; /* Swap parent and child */
  502. a[i] = a[j];
  503. a[j] = t;
  504. }
  505. }
  506. LOCAL heap(a,n) /* Heapify */
  507. RBTYPE *a; /* Array to heapify */
  508. WORD n; /* Size of array */
  509. {
  510. REGISTER WORD k; /* Index to "kid" */
  511. REGISTER WORD p; /* Index to "parent" */
  512. RBTYPE t; /* Temporary */
  513. if(n && (k = n - 1)) /* If there are kids */
  514. {
  515. if(isleft(k)) /* If youngest kid an only child */
  516. {
  517. p = parent(k); /* Find the parent */
  518. if((*cmpf)(&a[k],&a[p]) > 0) /* If swap necessary */
  519. {
  520. t = a[k]; /* Swap parent and kid */
  521. a[k] = a[p];
  522. a[p] = t;
  523. }
  524. --k; /* Index a righty */
  525. }
  526. while(k) /* While there are parents */
  527. {
  528. p = parent(k); /* Find the parent */
  529. if((*cmpf)(&a[k],&a[p]) > 0 || (*cmpf)(&a[k - 1],&a[p]) > 0)
  530. { /* If a kid is "greater" */
  531. t = a[p]; /* Swap parent... */
  532. if((*cmpf)(&a[k],&a[k - 1]) > 0)
  533. { /* ...with "greater" kid */
  534. a[p] = a[k];
  535. a[k] = t;
  536. reheap(a,n,k--); /* And reheapify */
  537. }
  538. else
  539. {
  540. a[p] = a[--k];
  541. a[k] = t;
  542. reheap(a,n,k); /* And reheapify */
  543. }
  544. }
  545. else --k; /* Point at left kid */
  546. --k; /* Point at right kid */
  547. }
  548. }
  549. }
  550. #endif /* OWNSORT */
  551. /****************************************************************
  552. * *
  553. * PrintGroupOrigins: *
  554. * *
  555. ****************************************************************/
  556. void PrintGroupOrigins(APROPNAMEPTR papropGroup,
  557. RBTYPE rhte,
  558. RBTYPE rprop,
  559. WORD fNewHte)
  560. {
  561. AHTEPTR hte;
  562. APROPGROUPPTR pGroup;
  563. pGroup = (APROPGROUPPTR) papropGroup;
  564. if (mpggrgsn[pGroup->ag_ggr] != SNNIL)
  565. { /* If group has members */
  566. if (!fGrps) /* If no groups yet */
  567. {
  568. fputs(GetMsg(MAP_group), bsLst);
  569. /* Header */
  570. fGrps = (FTYPE) TRUE; /* Yes, there are groups */
  571. }
  572. fprintf(bsLst," %04X:0 ", mpsegsa[mpgsnseg[mpggrgsn[pGroup->ag_ggr]]]);
  573. /* Write the group base */
  574. hte = (AHTEPTR ) FETCHSYM(rhte,FALSE);
  575. /* Fetch group name */
  576. OutSb(bsLst,GetFarSb(hte->cch));/* Output name */
  577. NEWLINE(bsLst);
  578. ChkMapErr();
  579. }
  580. }
  581. #if OSEGEXE
  582. LOCAL void NEAR HdrExport(ATTRTYPE attr)
  583. {
  584. ASSERT(attr == ATTREXP); /* Must be an export */
  585. fputs(GetMsg(MAP_expaddr), bsLst);
  586. #if EXE386
  587. PutSpaces(7);
  588. #else
  589. if (f386)
  590. PutSpaces(7);
  591. else
  592. PutSpaces(3);
  593. #endif
  594. fputs(GetMsg(MAP_expexp), bsLst);
  595. PutSpaces(18);
  596. fputs(GetMsg(MAP_expalias), bsLst);
  597. /* Header */
  598. ChkMapErr();
  599. }
  600. LOCAL void NEAR ShowExp(ahte,rprop)
  601. AHTEPTR ahte; /* Pointer to hash table entry */
  602. RBTYPE rprop; /* Property cell address */
  603. {
  604. SBTYPE sbExport; /* Export name */
  605. APROPNAMEPTR apropnam; /* Public definition record */
  606. short i; /* Index */
  607. memcpy(sbExport,GetFarSb(ahte->cch),B2W(ahte->cch[0]) + 1);
  608. /* Save the name */
  609. apropnam = (APROPNAMEPTR ) FETCHSYM(rprop,FALSE);
  610. /* Fetch alias record */
  611. #if EXE386
  612. fprintf(bsLst," %04X:%08lX ",
  613. #else
  614. fprintf(bsLst," %04X:%04X ",
  615. #endif
  616. mpsegsa[mpgsnseg[apropnam->an_gsn]],apropnam->an_ra);
  617. /* Print the address */
  618. OutSb(bsLst,sbExport); /* Print the exported name */
  619. for(i = 22 - B2W(sbExport[0]); i > 0; --i) fputc(' ',bsLst);
  620. /* Fill with spaces */
  621. fputs(" ",bsLst); /* Skip two spaces */
  622. ahte = GetHte(apropnam->an_next); /* Get the alias name */
  623. OutSb(bsLst,GetFarSb(ahte->cch)); /* Output export name */
  624. NEWLINE(bsLst);
  625. ChkMapErr();
  626. }
  627. LOCAL void NEAR PrintExps(WORD irbMac, ATTRTYPE attr)
  628. {
  629. AHTEPTR ahte; /* Pointer to hash table entry */
  630. APROPEXPPTR apropexp; /* Pointer to property cell */
  631. RBTYPE rprop; /* Alias record address */
  632. WORD i; /* Index */
  633. RBTYPE CurrSym;
  634. for(i = irbMac; i > 0; i--) /* Loop through sorted symbols */
  635. {
  636. CurrSym = ExtractMin(i);
  637. ahte = (AHTEPTR ) FETCHSYM(CurrSym,FALSE);
  638. /* Fetch hash table entry */
  639. apropexp = (APROPEXPPTR ) FETCHSYM(ahte->rprop,FALSE);
  640. /* Fetch property cell */
  641. while(apropexp->ax_attr != attr)
  642. { /* Loop to find property cell */
  643. apropexp = (APROPEXPPTR ) FETCHSYM(apropexp->ax_next,FALSE);
  644. /* Fetch the next cell in the chain */
  645. }
  646. if((rprop = apropexp->ax_symdef) == RHTENIL) continue;
  647. ShowExp((AHTEPTR) FETCHSYM(CurrSym,FALSE),rprop);
  648. /* Print the export */
  649. /* Save address of alias */
  650. }
  651. }
  652. #endif /* OSEGEXE */
  653. LOCAL void NEAR PutSpaces(int HowMany)
  654. {
  655. for (; HowMany > 0; HowMany--)
  656. putc(' ', bsLst);
  657. ChkMapErr();
  658. }
  659. LOCAL void NEAR HdrName(attr)
  660. ATTRTYPE attr; /* Symbol attribute type */
  661. {
  662. fputs(GetMsg(MAP_hdraddr), bsLst);
  663. PutSpaces(9);
  664. fputs(GetMsg((MSGTYPE)((attr == ATTRPNM) ? MAP_hdrpubnam : MAP_hdrlocnam)), bsLst);
  665. /* Header (MAPSYM keys on "Value") */
  666. ChkMapErr();
  667. }
  668. LOCAL void NEAR HdrValue(attr)
  669. ATTRTYPE attr; /* Symbol attribute type */
  670. {
  671. fputs(GetMsg(MAP_hdraddr), bsLst);
  672. PutSpaces(9);
  673. fputs(GetMsg((MSGTYPE)((attr == ATTRPNM) ? MAP_hdrpubval : MAP_hdrlocval)), bsLst);
  674. /* Header (MAPSYM keys on "Value") */
  675. ChkMapErr();
  676. }
  677. /****************************************************************
  678. * *
  679. * SortSyms: *
  680. * *
  681. * List symbols, sorted. *
  682. * *
  683. ****************************************************************/
  684. void NEAR SortSyms(ATTRTYPE attr,
  685. /* Symbol attribute type */
  686. void (*savf)(APROPNAMEPTR prop,
  687. RBTYPE rhte,
  688. RBTYPE rprop,
  689. WORD fNewHte),
  690. /* Function to save symbols */
  691. int (cdecl *scmpf)(const RBTYPE *sb1,
  692. const RBTYPE *sb2),
  693. /* Function to compare symbols */
  694. void (NEAR *hdrf)(ATTRTYPE attr),
  695. /* Function to print header */
  696. void (NEAR *lstf)(WORD irbMac,
  697. ATTRTYPE attr))
  698. /* Function to list symbols */
  699. {
  700. symMac = 0; /* Initialize counter to zero */
  701. cmpf = scmpf; /* Set comparison function */
  702. EnSyms(savf,attr); /* Apply function to symbols */
  703. (*hdrf)(attr); /* Print a header */
  704. (*lstf)(symMac,attr); /* Print them */
  705. }
  706. /*** AddContributor - add current file to list
  707. *
  708. * Purpose:
  709. * Add current .OBJ file that contribiute to definition of given
  710. * segment. The list of .OBJ files is kept in virtual memory.
  711. * Each segment description record has Head and Tail pointers to
  712. * its contributor list.
  713. *
  714. * Input:
  715. * gsn - global segment number - linker internal way of
  716. * recognizing segments
  717. * raComdat - if contribution is comming from a COMDAT symbol
  718. * this is its initial offset in the segment
  719. * size - contribution size
  720. * vrpropFile - pointer to current .OBJ file description - global variable
  721. *
  722. * Output:
  723. * No explicit return value. Updated list of contributors for segment.
  724. *
  725. * Exceptions:
  726. * None.
  727. *
  728. *************************************************************************/
  729. void AddContributor(SNTYPE gsn, DWORD raComdat, DWORD size)
  730. {
  731. APROPSNPTR apropSn; /* Pointer to seg. record */
  732. CONTRIBUTOR FAR *NewObj; /* New .OBJ file that contrbiuts to seg */
  733. apropSn = (APROPSNPTR ) FETCHSYM(mpgsnrprop[gsn],FALSE);
  734. NewObj = (CONTRIBUTOR FAR *) GetMem(sizeof(CONTRIBUTOR));
  735. /* Build new list element */
  736. NewObj->next = 0L; /* End of list */
  737. NewObj->file = vrpropFile; /* Save global file description pointer */
  738. NewObj->len = size; /* Size of contribution */
  739. if (raComdat != -1L)
  740. NewObj->offset = raComdat;
  741. else
  742. NewObj->offset = mpgsndra[gsn];
  743. /* Attach new record at the list end */
  744. if (apropSn->as_CHead)
  745. apropSn->as_CTail->next = NewObj;
  746. else
  747. apropSn->as_CHead = NewObj;
  748. apropSn->as_CTail = NewObj;
  749. }
  750. /*** PrintContributors - print out list of files
  751. *
  752. * Purpose:
  753. * Print list of .OBJ files that contribute to form given segment.
  754. * For each file print number of bytes that it contribute.
  755. *
  756. * Input:
  757. * gsn - global segment number - linker internal way of
  758. * recognizing segments
  759. *
  760. * Output:
  761. * No explicit return value.
  762. *
  763. * Exceptions:
  764. * None.
  765. *
  766. *************************************************************************/
  767. LOCAL void NEAR PrintContributors(SNTYPE gsn)
  768. {
  769. APROPFILEPTR apropFile; /* Pointer to file property cell */
  770. APROPSNPTR apropSn; /* Pointer to seg. record */
  771. CONTRIBUTOR FAR *pElem; /* Real pointer to list element */
  772. AHTEPTR ahte; /* Pointer symbol name */
  773. SBTYPE sb, sb1; /* String buffers */
  774. int n; /* String length counter */
  775. apropSn = (APROPSNPTR ) FETCHSYM(mpgsnrprop[gsn],FALSE);
  776. if (apropSn->as_CHead == NULL)
  777. return;
  778. /* Print list */
  779. fprintf(bsLst,"\r\n");
  780. pElem = apropSn->as_CHead;
  781. do
  782. {
  783. if(fNewExe || OIAPX286)
  784. {
  785. #if EXE386
  786. if (f386)
  787. fprintf(bsLst," at offset %08lXH %05lXH bytes from", pElem->offset, pElem->len);
  788. else
  789. #endif
  790. fprintf(bsLst," at offset %05lXH %05lXH bytes from", pElem->offset, pElem->len);
  791. }
  792. else
  793. fprintf(bsLst," at offset %05lXH %05lXH bytes from", pElem->offset, pElem->len);
  794. apropFile = (APROPFILEPTR ) FETCHSYM(pElem->file,FALSE);
  795. ahte = GetHte(pElem->file);
  796. for(n = B2W(ahte->cch[0]), sb[n+1] = 0; n >= 0; sb[n] = ahte->cch[n], --n);
  797. if (apropFile->af_rMod)
  798. {
  799. ahte = (AHTEPTR ) FETCHSYM(apropFile->af_rMod,FALSE);
  800. while(ahte->attr != ATTRNIL)
  801. ahte = (AHTEPTR ) FETCHSYM(ahte->rhteNext,FALSE);
  802. for (n = B2W(ahte->cch[0]); n >= 0; --n)
  803. sb1[n] = ahte->cch[n];
  804. sb1[1 + B2W(sb1[0])] = '\0'; /* Null-terminate */
  805. fprintf(bsLst, " %s (%s)\r\n", 1 + sb, 1 + sb1);
  806. }
  807. else
  808. fprintf(bsLst," %s\r\n", 1 + sb);
  809. ChkMapErr();
  810. pElem = pElem->next;
  811. } while (pElem != NULL);
  812. }
  813. /****************************************************************
  814. * *
  815. * PrintMap: *
  816. * *
  817. ****************************************************************/
  818. void PrintMap(void)
  819. {
  820. SEGTYPE seg;
  821. WORD cch;
  822. APROPSNPTR papropSn;
  823. AHTEPTR pahte;
  824. SNTYPE gsn;
  825. RBTYPE rhteClass; /* Virt. addr. of class name */
  826. long addrStart;
  827. long addr;
  828. #if OVERLAYS
  829. IOVTYPE iov;
  830. #endif
  831. #if OSMSDOS
  832. int oldbsize; /* Old file buffer size */
  833. char *oldbase; /* Old file buffer */
  834. #endif
  835. WORD flags;
  836. #if OSMSDOS
  837. #if OWNSTDIO
  838. oldbsize = bsLst->_bsize;
  839. #else
  840. oldbsize = 512;
  841. #endif
  842. oldbase = bsLst->_base;
  843. setvbuf(bsLst,bigbuf,_IOFBF,sizeof(bigbuf));
  844. #endif
  845. #if OSEGEXE
  846. if(fNewExe && rhteModule != RHTENIL)/* If there is a module name */
  847. {
  848. pahte = (AHTEPTR ) FETCHSYM(rhteModule,FALSE);
  849. /* Fetch the hash table entry */
  850. fputs("\r\n ",bsLst); /* Indent one space */
  851. OutSb(bsLst,GetFarSb(pahte->cch));/* Print the module name */
  852. NEWLINE(bsLst);
  853. ChkMapErr();
  854. }
  855. #endif
  856. if(fNewExe || OIAPX286)
  857. {
  858. fputs(GetMsg(MAP_hdrstart), bsLst);
  859. #if EXE386
  860. PutSpaces(9);
  861. #else
  862. if (f386)
  863. PutSpaces(9);
  864. else
  865. PutSpaces(5);
  866. #endif
  867. fputs(GetMsg(MAP_hdrlen), bsLst);
  868. PutSpaces(5);
  869. fputs(GetMsg(MAP_hdrname), bsLst);
  870. PutSpaces(19);
  871. fputs(GetMsg(MAP_hdrclass), bsLst);
  872. }
  873. else
  874. {
  875. fputs(GetMsg(MAP_hdrseg86), bsLst);
  876. PutSpaces(19);
  877. fputs(GetMsg(MAP_hdrclass), bsLst);
  878. }
  879. ChkMapErr();
  880. #if OVERLAYS
  881. for(iov = 0; iov < (IOVTYPE) iovMac; ++iov)
  882. {
  883. if(fOverlays)
  884. {
  885. if (iov == IOVROOT)
  886. fputs(GetMsg(MAP_resident), bsLst);
  887. else
  888. fprintf(bsLst, GetMsg(MAP_overlay), iov);
  889. ChkMapErr();
  890. }
  891. #endif
  892. for(seg = 1; seg <= segLast; ++seg) /* Look at all segments */
  893. {
  894. #if OVERLAYS
  895. if(!fOverlays || mpsegiov[seg] == iov)
  896. {
  897. #endif
  898. if(fNewExe || OIAPX286)
  899. {
  900. #if EXE386
  901. fprintf(bsLst," %04X:%08lX", mpsegsa[seg],mpsegraFirst[seg]);
  902. #else
  903. if (f386)
  904. fprintf(bsLst," %04X:%08lX", mpsegsa[seg],mpsegraFirst[seg]);
  905. else
  906. fprintf(bsLst," %04X:%04X",mpsegsa[seg],(int)mpsegraFirst[seg]);
  907. #endif
  908. ChkMapErr();
  909. }
  910. else
  911. addrStart = (long) mpsegsa[seg] << 4;
  912. for(gsn = 1; gsn < gsnMac; ++gsn)
  913. {
  914. if(mpgsnseg[gsn] == seg)
  915. {
  916. papropSn = (APROPSNPTR ) FETCHSYM(mpgsnrprop[gsn],FALSE);
  917. rhteClass = papropSn->as_rCla;
  918. /* Save key to class name */
  919. #if NOT EXE386
  920. flags = papropSn->as_flags;
  921. #endif
  922. if(fNewExe || OIAPX286)
  923. #if EXE386
  924. fprintf(bsLst," %09lXH ",papropSn->as_cbMx);
  925. #else
  926. fprintf(bsLst," %05lXH ",papropSn->as_cbMx);
  927. #endif
  928. else
  929. {
  930. addr = addrStart + (long) mpsegraFirst[seg];
  931. fprintf(bsLst," %05lXH",addr);
  932. if(papropSn->as_cbMx) addr += papropSn->as_cbMx - 1;
  933. fprintf(bsLst," %05lXH",addr);
  934. fprintf(bsLst," %05lXH ",papropSn->as_cbMx);
  935. }
  936. pahte = GetHte(papropSn->as_next);
  937. /* Get the segment name */
  938. OutSb(bsLst,GetFarSb(pahte->cch));
  939. /* Write segment name */
  940. if(B2W(pahte->cch[0]) > 22) cch = 1;
  941. else cch = 23 - B2W(pahte->cch[0]);
  942. /* Get number of spaces to emit */
  943. while(cch--) OutByte(bsLst,' ');
  944. /* Emit spaces */
  945. pahte = (AHTEPTR ) FETCHSYM(rhteClass,FALSE);
  946. /* Fetch class names from VM */
  947. OutSb(bsLst,GetFarSb(pahte->cch));
  948. /* Output class name */
  949. if (fFullMap)
  950. {
  951. #if EXE386
  952. fprintf(bsLst, " 32-bit");
  953. #else
  954. if (Is32BIT(flags))
  955. fprintf(bsLst, " 32-bit");
  956. else
  957. fprintf(bsLst, " 16-bit");
  958. #endif
  959. PrintContributors(gsn);
  960. }
  961. NEWLINE(bsLst);
  962. ChkMapErr();
  963. break; /* Exit loop */
  964. }
  965. }
  966. #if OVERLAYS
  967. }
  968. #endif
  969. }
  970. #if OVERLAYS
  971. }
  972. #endif
  973. fGrps = FALSE; /* Assume no groups */
  974. EnSyms(PrintGroupOrigins,ATTRGRP); /* Apply function to symbols */
  975. #if OSEGEXE
  976. if(vfMap || expMac)
  977. #else
  978. if(vfMap)
  979. #endif
  980. {
  981. AllocSortBuffer(pubMac > expMac ? pubMac : expMac, TRUE);
  982. }
  983. #if OSEGEXE
  984. if(expMac)
  985. {
  986. /* Sort or list exported names */
  987. SortSyms(ATTREXP,SaveHteSym,FGtName,HdrExport, PrintExps);
  988. }
  989. #endif
  990. if(vfMap) /* If publics requested */
  991. {
  992. if(!fListAddrOnly)
  993. SortSyms(ATTRPNM,SaveHteSym,FGtName,HdrName, PrintSyms);
  994. /* Sort public symbols by name */
  995. SortSyms(ATTRPNM,SavePropSym,FGtAddr,HdrValue, PrintSyms);
  996. /* Sort public symbols by value */
  997. }
  998. #if LOCALSYMS
  999. if(fLocals) /* If locals requested */
  1000. {
  1001. SortSyms(ATTRLNM,SaveHteSym,FGtName,HdrName, PrintSyms);
  1002. /* Sort local symbols by name */
  1003. SortSyms(ATTRLNM,SavePropSym,FGtAddr,HdrValue, PrintSyms);
  1004. /* Sort local symbols by value */
  1005. }
  1006. #endif
  1007. ChkMapErr();
  1008. FreeSortBuffer();
  1009. #if OSMSDOS
  1010. setvbuf(bsLst,oldbase,_IOFBF,oldbsize);
  1011. #endif
  1012. }