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.

1193 lines
46 KiB

  1. /* SCCSID = %W% %E% */
  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. /****************************************************************
  9. * *
  10. * NEWTP2.C *
  11. * *
  12. * This module contains functions to process object modules on *
  13. * pass 2. *
  14. * *
  15. ****************************************************************/
  16. #include <minlit.h> /* Types, constants, macros */
  17. #include <bndtrn.h> /* Types and constants */
  18. #include <bndrel.h> /* More types and constants */
  19. #include <lnkio.h> /* Linker I/O definitions */
  20. #include <newexe.h> /* DOS & 286 .EXE structure definitions */
  21. #if EXE386
  22. #include <exe386.h> /* 386 .EXE structure definitions */
  23. #endif
  24. #include <lnkmsg.h> /* Error messages */
  25. #if OXOUT OR OIAPX286
  26. #include <xenfmt.h> /* Xenix format definitions */
  27. #endif
  28. #include <extern.h> /* External declarations */
  29. #if OSEGEXE
  30. extern RLCPTR rlcLidata; /* Pointer to LIDATA fixup array */
  31. extern RLCPTR rlcCurLidata; /* Pointer to current LIDATA fixup */
  32. #endif
  33. /*
  34. * LOCAL FUNCTION PROTOTYPES
  35. */
  36. LOCAL void NEAR DataRec(void);
  37. BYTE * ObExpandIteratedData(unsigned char *pb,
  38. unsigned short cBlocks, WORD *pSize);
  39. LOCAL void NEAR DataBlockToVM(void);
  40. LOCAL void NEAR SegRec2(void);
  41. LOCAL void NEAR GrpRec2(void);
  42. LOCAL void NEAR ExtRec2(void);
  43. LOCAL void NEAR ComDef2(void);
  44. #if ALIGN_REC
  45. #else
  46. /*
  47. * GetBytesNoLim : just like GetBytes but no fixed limit
  48. */
  49. void NEAR GetBytesNoLim(pb,n)
  50. BYTE *pb; /* Pointer to buffer */
  51. WORD n; /* Number of bytes to read in */
  52. {
  53. FILE *f = bsInput;
  54. if (n <= f->_cnt)
  55. {
  56. memcpy(pb,f->_ptr, n);
  57. f->_cnt -= n;
  58. f->_ptr += n;
  59. }
  60. else
  61. fread(pb,1,n,bsInput); /* Ask for n bytes */
  62. // ChkInput();
  63. cbRec -= n; /* Update byte count */
  64. }
  65. #endif
  66. /****************************************************************
  67. * *
  68. * DataRec: *
  69. * *
  70. * This function takes no arguments. It processes a LEDATA *
  71. * record or an LIDATA record. It does not return a *
  72. * meaningful value. See "8086 Object Formats EPS." *
  73. * *
  74. ****************************************************************/
  75. LOCAL void NEAR DataRec(void) /* Process a data record */
  76. {
  77. SNTYPE sn; /* SEGDEF number */
  78. RATYPE ra; /* Segment offset */
  79. SNTYPE gsn; /* Global SEGDEF number */
  80. fSkipFixups = FALSE; // Make sure that we don't skip fixups
  81. sn = GetIndex((WORD)1,(WORD)(snMac - 1)); /* Get segment number */
  82. #if OMF386
  83. if(rect & 1) ra = LGets();
  84. else
  85. #endif
  86. ra = WGets(); /* Get relative address */
  87. vcbData = cbRec - 1; /* Get no. of data bytes in rec */
  88. if(vcbData > DATAMAX) Fatal(ER_datarec);
  89. /* Check if record too large */
  90. #if NOT RGMI_IN_PLACE
  91. GetBytesNoLim(rgmi,vcbData); /* Fill the buffer */
  92. #endif
  93. gsn = mpsngsn[sn]; /* Map SEGDEF no. to global SEGDEF */
  94. vgsnCur = gsn; /* Set global */
  95. fDebSeg = (fSymdeb) ? (FTYPE) ((0x8000 & gsn) != 0) : fSymdeb;
  96. /* If debug option on check for debug segs*/
  97. if (fDebSeg)
  98. { /* If debug segment */
  99. vraCur = ra; /* Set current relative address */
  100. vsegCur = vgsnCur = 0x7fff & gsn; /* Set current segment */
  101. }
  102. else
  103. {
  104. /* If not a valid segment, don't process datarec */
  105. #if SYMDEB
  106. if(gsn == 0xffff || !gsn || mpgsnseg[gsn] > segLast)
  107. #else
  108. if(!gsn || mpgsnseg[gsn] > segLast)
  109. #endif
  110. {
  111. vsegCur = SEGNIL;
  112. vrectData = RECTNIL;
  113. #if RGMI_IN_PLACE
  114. SkipBytes(vcbData); /* must skip bytes for this record...*/
  115. #endif
  116. fSkipFixups = TRUE; /* plus skip any associated fixups */
  117. return; /* Good-bye! */
  118. }
  119. vraCur = ra + mpgsndra[gsn]; /* Set current relative address */
  120. vsegCur = mpgsnseg[gsn]; /* Set current segment */
  121. }
  122. vrectData = rect; /* Set the record type */
  123. #if RGMI_IN_PLACE
  124. if(TYPEOF(rect) == LIDATA) /* If LIDATA record */
  125. {
  126. rgmi = bufg; /* use general purpose buffer for read*/
  127. }
  128. else
  129. {
  130. rgmi = PchSegAddress(vcbData,vsegCur,vraCur);
  131. /* read data in place... */
  132. }
  133. GetBytesNoLim(rgmi,vcbData); /* Fill the buffer */
  134. #endif
  135. if(TYPEOF(vrectData) == LIDATA) /* If LIDATA record */
  136. {
  137. #if OSEGEXE
  138. if(fNewExe)
  139. {
  140. if (vcbData >= DATAMAX)
  141. Fatal(ER_lidata);
  142. rlcLidata = (RLCPTR ) &rgmi[(vcbData + 1) & ~1];
  143. /* Set base of fixup array */
  144. rlcCurLidata = rlcLidata; /* Initialize pointer */
  145. return;
  146. }
  147. #endif
  148. #if ODOS3EXE OR OIAPX286
  149. if(vcbData > (DATAMAX / 2))
  150. {
  151. OutError(ER_lidata);
  152. memset(&rgmi[vcbData],0,DATAMAX - vcbData);
  153. }
  154. else
  155. memset(&rgmi[vcbData],0,vcbData);
  156. ompimisegDstIdata = (char *) rgmi + vcbData;
  157. #endif
  158. }
  159. }
  160. /****************************************************************
  161. * *
  162. * SegRec2: *
  163. * *
  164. * This function processes SEGDEF records on pass 2. *
  165. * See pp. 32-35 in "8086 Object Module Formats EPS." *
  166. * *
  167. ****************************************************************/
  168. LOCAL void NEAR SegRec2(void)
  169. {
  170. WORD tysn; /* ACBP field */
  171. WORD align; /* Alignment subfield of ACBP */
  172. SATYPE saAbs; /* Frame number of absolute LSEG */
  173. LNAMETYPE lname; /* Segment name index */
  174. WORD comb; /* Segment combining information */
  175. APROPSNPTR apropSn; /* Pointer to segment hash tab entry */
  176. SNTYPE gsn; /* Global SEGDEF no. */
  177. RATYPE dra;
  178. RBTYPE rhteClass; /* Segment class name rhte */
  179. WORD DebKind; /* Debug seg kind; 1-$$TYPES; 2-$$SYMBOLS */
  180. DWORD gsnLen; /* Segment length */
  181. #if ILINK
  182. WORD cbPad; /* size of padding used */
  183. #endif
  184. ASSERT(snMac < SNMAX); /* No overflow on Pass 2 */
  185. tysn = Gets(); /* Read in ACBP byte */
  186. align = (tysn >> 5) & 7; /* Get alignment subfield */
  187. ASSERT(align != 5); /* Unnamed absolute not supported */
  188. ASSERT(align != 6); /* LTL LSEG not supported */
  189. if(align == ALGNABS) /* If absolute LSEG */
  190. {
  191. saAbs = WGets(); /* Read in frame number */
  192. Gets(); /* Skip frame offset */
  193. }
  194. #if OMF386
  195. if(rect & 1)
  196. gsnLen = LGets();
  197. else
  198. #endif
  199. gsnLen = (long) WGets(); /* Read in segment length */
  200. /* Don't need to check for 386 record, done in pass 1: */
  201. if(tysn & BIGBIT) gsnLen = LXIVK; /* Length 64K if big bit set */
  202. lname = GetIndex((WORD)1,(WORD)(lnameMac - 1)); /* Get segment name index */
  203. rhteClass = mplnamerhte[GetIndex((WORD)1,(WORD)(lnameMac - 1))];
  204. /* Get segment class name rhte */
  205. #if SYMDEB
  206. if (DebKind = IsDebSeg(rhteClass, mplnamerhte[lname]))
  207. { /* If MS debug segment then mark it */
  208. if (!fSymdeb)
  209. mpsngsn[snMac++] = 0xffff;
  210. else
  211. mpsngsn[snMac++] = ((DebKind == 1) ?
  212. segDebFirst + segDebLast :
  213. segDebFirst + segDebLast + ObjDebTotal
  214. ) | 0x8000; /* Set debug global number */
  215. SkipBytes((WORD)(cbRec - 1));
  216. return;
  217. }
  218. #endif
  219. GetIndex((WORD)0,(WORD)(lnameMac - 1)); /* Skip overlay name index */
  220. switch(align) /* Switch on alignment type */
  221. {
  222. case ALGNABS: /* Absolute LSEG */
  223. case ALGNWRD: /* Word-aligned LSEG */
  224. case ALGNBYT: /* Byte-aligned LSEG */
  225. case ALGNPAR: /* Paragraph-aligned LSEG */
  226. case ALGNPAG: /* Page-aligned LSEG */
  227. #if OMF386
  228. case ALGNDBL: /* Double-aligned LSEG */
  229. #endif
  230. break;
  231. default: /* Unsupported or illegal types */
  232. mpsngsn[snMac++] = 0; /* Map to nothing */
  233. return; /* And return */
  234. }
  235. ++snkey; /* Increment segment i.d. key */
  236. if(comb = (tysn >> 2) & 7) /* If not a private segment */
  237. {
  238. apropSn = (APROPSNPTR )
  239. PropRhteLookup(mplnamerhte[lname],ATTRPSN,FALSE);
  240. /* Look up property cell */
  241. ASSERT(apropSn != PROPNIL); /* Should always be true */
  242. while(apropSn->as_attr != ATTRNIL)
  243. { /* Look for matching class */
  244. if(apropSn->as_attr == ATTRPSN &&
  245. apropSn->as_rCla == rhteClass) break;
  246. /* Break if a match is found */
  247. apropSn = (APROPSNPTR ) FetchSym(apropSn->as_next,FALSE);
  248. /* Try next link in list */
  249. }
  250. ASSERT(apropSn->as_attr == ATTRPSN);
  251. }
  252. else /* Else if private segment */
  253. {
  254. apropSn = (APROPSNPTR )
  255. PropRhteLookup(mplnamerhte[lname],ATTRLSN,FALSE);
  256. /* Look up property cell */
  257. ASSERT(apropSn != PROPNIL); /* Should always be true */
  258. while(apropSn->as_attr != ATTRNIL)
  259. { /* Search for match */
  260. if(apropSn->as_attr == ATTRLSN && apropSn->as_key == snkey) break;
  261. /* Break when match found */
  262. apropSn = (APROPSNPTR ) FetchSym(apropSn->as_next,FALSE);
  263. /* Try next link in list */
  264. }
  265. ASSERT(apropSn->as_attr == ATTRLSN);
  266. }
  267. gsn = apropSn->as_gsn; /* Get global SEGDEF no. */
  268. #if ILINK
  269. if (fIncremental && !fLibraryFile && !(apropSn->as_fExtra & NOPAD) &&
  270. gsnLen && gsnLen != LXIVK)
  271. /* Add code/data padding to non-library segments if it doesn't
  272. * overflow.
  273. */
  274. gsnLen += (cbPad = ((apropSn->as_flags & NSTYPE) == NSCODE) ?
  275. cbPadCode : cbPadData);
  276. else
  277. cbPad = 0; /* no padding please */
  278. #endif
  279. if(comb == COMBSTK) mpgsndra[gsn] =
  280. mpsegraFirst[mpgsnseg[gsn]] + apropSn->as_cbMx - gsnLen;
  281. else
  282. {
  283. /* If combine-type public, start at end of combined segment. */
  284. if(comb != COMBCOM)
  285. dra = mpgsndra[gsn] + apropSn->as_cbPv;
  286. /*
  287. * Else if common, start at beginning of segment. Save current
  288. * combined size, except this portion, in as_cbPv. If this
  289. * portion is bigger as_cbPv is reset below.
  290. */
  291. else
  292. {
  293. dra = mpsegraFirst[mpgsnseg[gsn]];
  294. apropSn->as_cbPv += mpgsndra[gsn] - dra;
  295. }
  296. switch(align) /* Switch on alignment type */
  297. {
  298. case ALGNWRD: /* Word-aligned LSEG */
  299. mpgsndra[gsn] = (~0L<<1) & (dra + (1<<1) - 1);
  300. /* Round to next word offset */
  301. break;
  302. #if OMF386
  303. case ALGNDBL: /* Double-aligned LSEG */
  304. mpgsndra[gsn] = (~0L<<2) & (dra + (1<<2) - 1);
  305. /* Round to next double offset */
  306. break;
  307. #endif
  308. case ALGNPAR: /* Paragraph-aligned LSEG */
  309. mpgsndra[gsn] = (~0L<<4) & (dra + (1<<4) - 1);
  310. /* Round to next paragraph offset */
  311. break;
  312. case ALGNPAG: /* Page-aligned LSEG */
  313. mpgsndra[gsn] = (~0L<<8) & (dra + (1<<8) - 1);
  314. /* Round to next page offset */
  315. break;
  316. default: /* All others */
  317. mpgsndra[gsn] = dra; /* Use byte offset */
  318. break;
  319. }
  320. }
  321. /*
  322. * If public, as_cbPv is size of this public portion; if common,
  323. * as_cbPv is the larger of total combined publics and this
  324. * common portion. Skip empty SEGDEFs.
  325. */
  326. if (/*gsnLen != 0L && */(comb != COMBCOM || gsnLen > apropSn->as_cbPv))
  327. apropSn->as_cbPv = gsnLen;
  328. mpsngsn[snMac++] = gsn; /* Map SEGDEF no. to gsn */
  329. if(align == ALGNABS) mpsegsa[mpgsnseg[gsn]] = saAbs;
  330. /* Map seg base to frame number */
  331. MARKVP(); /* Mark page as changed */
  332. #if ILINK
  333. if (fIncremental)
  334. {
  335. AddContribution(gsn,
  336. (WORD) (mpgsndra[gsn] - mpsegraFirst[mpgsnseg[gsn]]),
  337. (WORD) (mpgsndra[gsn] - mpsegraFirst[mpgsnseg[gsn]] + gsnLen),
  338. cbPad);
  339. gsnLen -= cbPad; /* Don't include padding for CV */
  340. }
  341. #endif
  342. #if SYMDEB
  343. if(fSymdeb && gsnLen && IsCodeFlg(apropSn->as_flags))
  344. SaveCode(gsn, gsnLen, (DWORD) -1L);
  345. #endif
  346. }
  347. /****************************************************************
  348. * *
  349. * GrpRec2: *
  350. * *
  351. * This function processes GRPDEF records on pass 2. *
  352. * See pp. 36-39 in "8086 Object Module Formats EPS." *
  353. * *
  354. ****************************************************************/
  355. LOCAL void NEAR GrpRec2(void)
  356. {
  357. LNAMETYPE lnameGroup; /* Group name index */
  358. APROPGROUPPTR apropGroup; /* Pointer to property cell */
  359. lnameGroup = GetIndex((WORD)1,(WORD)(lnameMac - 1));
  360. /* Read in group name index */
  361. apropGroup = (APROPGROUPPTR )
  362. PropRhteLookup(mplnamerhte[lnameGroup],ATTRGRP,FALSE);
  363. /* Look up entry in hash table */
  364. ASSERT(grMac < GRMAX); /* Should have been caught on pass 1 */
  365. mpgrggr[grMac++] = apropGroup->ag_ggr;
  366. /* Map GRPDEF to global GRPDEF */
  367. SkipBytes((WORD)(cbRec - 1)); /* Skip to checksum byte */
  368. }
  369. /*
  370. * AddVmProp : Add a symbol-table property address to a list
  371. *
  372. * Returns: pointer to the new list element; the pointer is
  373. * a word offset from the start of the list area in VM
  374. */
  375. PLTYPE FAR * NEAR AddVmProp (PLTYPE FAR *list, RBTYPE rprop)
  376. {
  377. PLTYPE FAR *new;
  378. new = (PLTYPE FAR *) GetMem(sizeof(PLTYPE));
  379. // Add unresolved external at the list head
  380. new->pl_next = list;
  381. new->pl_rprop = rprop;
  382. return(new);
  383. }
  384. /****************************************************************
  385. * *
  386. * ExtRec2: *
  387. * *
  388. * This function processes EXTDEF records on pass 2. Note *
  389. * that in pass 2, any undefined externals are errors. *
  390. * See pp. 47-48 in "8086 Object Module Formats EPS." *
  391. * *
  392. ****************************************************************/
  393. LOCAL void NEAR ExtRec2(void)
  394. {
  395. SBTYPE sb; /* External symbol name */
  396. APROPNAMEPTR apropName; /* Property cell pointer */
  397. APROPUNDEFPTR apropUndef; /* Property cell pointer */
  398. APROPALIASPTR apropAlias; /* Property cell pointer */
  399. RBTYPE rhte; /* Virt. addr. of hash table entry */
  400. #if OSEGEXE
  401. APROPEXPPTR apropExp; /* Export cell pointer */
  402. #endif
  403. while (cbRec > 1) /* While not at end of record */
  404. {
  405. ASSERT(extMac < EXTMAX); /* Should be checked on Pass 1 */
  406. if (TYPEOF(rect) == CEXTDEF)
  407. {
  408. /* Look for symbol among PUBDEFs */
  409. rhte = mplnamerhte[GetIndex(1, (WORD)(lnameMac - 1))];
  410. apropName = (APROPNAMEPTR) PropRhteLookup(rhte, ATTRPNM, FALSE);
  411. }
  412. else
  413. {
  414. sb[0] = (BYTE) Gets(); /* Read in symbol length */
  415. if(TYPEOF(rect) == EXTDEF)
  416. GetBytes(&sb[1], B2W(sb[0]));
  417. /* Read in the text of the symbol */
  418. else
  419. GetLocName(sb); /* Transform local name */
  420. #if CMDXENIX
  421. if (symlen && B2W(sb[0]) > symlen)
  422. sb[0] = symlen; /* Truncate if necessary */
  423. #endif
  424. /* Look for symbol among PUBDEFs */
  425. apropName = (APROPNAMEPTR) PropSymLookup(sb, ATTRPNM, FALSE);
  426. rhte = vrhte;
  427. }
  428. GetIndex(0, 0x7FFF); /* Skip the type index */
  429. apropUndef = PROPNIL;
  430. if (apropName == PROPNIL)
  431. {
  432. /* Look for symbol among ALIASES */
  433. apropAlias = (APROPALIASPTR) PropRhteLookup(rhte, ATTRALIAS, FALSE);
  434. if (apropAlias != PROPNIL)
  435. {
  436. // Every call to PropRhteLookup as a side effect sets
  437. // the global variable 'vrprop' pointing to the
  438. // just retrieved proprety cell from symbol table.
  439. // Because for substitute symbols we don't call
  440. // PropRhteLookup instead we use direct pointer from
  441. // alias property cell, then we have to reset the
  442. // 'vrprop' here.
  443. vrprop = apropAlias->al_sym;
  444. apropName = (APROPNAMEPTR) FetchSym(apropAlias->al_sym, FALSE);
  445. if (apropName->an_attr == ATTRUND)
  446. {
  447. apropUndef = (APROPUNDEFPTR) apropName;
  448. apropName = PROPNIL;
  449. }
  450. }
  451. #if OSEGEXE
  452. /* If public definition not found and this is segmented DLL,
  453. * handle the possibility that this is a self-imported alias.
  454. */
  455. if (apropName == PROPNIL && fNewExe && (vFlags & NENOTP))
  456. {
  457. /* Look up exported name. */
  458. apropExp = (APROPEXPPTR) PropRhteLookup(rhte, ATTREXP, FALSE);
  459. /* If found, get the symbol definition which might be different
  460. * from the export name (i.e. an alias). If not marked public,
  461. * assume not found.
  462. */
  463. if (apropExp != PROPNIL && apropExp->ax_symdef != RHTENIL)
  464. apropName = (APROPNAMEPTR) FetchSym(apropExp->ax_symdef, FALSE);
  465. }
  466. #endif
  467. if (apropName == PROPNIL)
  468. {
  469. /* If not among PUBDEFs, ALIASes, or EXPORTs */
  470. /* Look among undefs */
  471. if (apropUndef == PROPNIL)
  472. apropUndef = (APROPUNDEFPTR) PropRhteLookup(rhte, ATTRUND, FALSE);
  473. if (apropUndef != PROPNIL) /* Should always exist */
  474. {
  475. if ((apropUndef->au_flags & STRONGEXT) ||
  476. (apropUndef->au_flags & UNDECIDED) )
  477. {
  478. /* "Strong" extern */
  479. apropUndef->au_flags &= ~(WEAKEXT | UNDECIDED);
  480. apropUndef->au_flags |= STRONGEXT;
  481. fUndefinedExterns = (FTYPE) TRUE;
  482. /* There are undefined externals */
  483. apropUndef->u.au_rFil =
  484. AddVmProp(apropUndef->u.au_rFil,vrpropFile);
  485. }
  486. else
  487. {
  488. /* "Weak" extern - find default resolution */
  489. apropName = (APROPNAMEPTR) FetchSym(apropUndef->au_Default, FALSE);
  490. }
  491. }
  492. }
  493. }
  494. if (apropName != PROPNIL) /* If among PUBDEFs or EXPDEF's or "weak" extern or ALIASes */
  495. {
  496. mpextprop[extMac] = vrprop; /* Save the property addr */
  497. #if OSEGEXE
  498. if(fNewExe)
  499. mpextflags[extMac] = apropName->an_flags;
  500. /* Save the flags */
  501. #if ODOS3EXE
  502. else
  503. #endif
  504. #endif
  505. #if ODOS3EXE OR OIAPX286
  506. mpextggr[extMac] = apropName->an_ggr;
  507. /* Save the global GRPDEF number */
  508. #endif
  509. #if OSEGEXE
  510. if(apropName->an_flags & FIMPORT)
  511. { /* If we have a dynamic link */
  512. #if EXE386
  513. mpextgsn[extMac] = gsnImport;
  514. /* Save the thunk segment no. */
  515. mpextra[extMac] = apropName->an_thunk;
  516. /* Save the offset in thunk segment */
  517. #else
  518. mpextgsn[extMac] = apropName->an_module;
  519. /* Save the module specification */
  520. mpextra[extMac] = apropName->an_entry;
  521. /* Save the entry specification */
  522. #endif
  523. }
  524. else /* Else if internal reference */
  525. #endif
  526. {
  527. mpextra[extMac] = apropName->an_ra;
  528. /* Save the offset */
  529. mpextgsn[extMac] = apropName->an_gsn;
  530. /* Save the global SEGDEF number */
  531. }
  532. }
  533. else
  534. {
  535. /* External is undefined */
  536. mpextra[extMac] = 0;
  537. mpextgsn[extMac] = SNNIL;
  538. mpextprop[extMac] = PROPNIL;
  539. #if OSEGEXE
  540. if (fNewExe)
  541. mpextflags[extMac] = 0;
  542. #if ODOS3EXE
  543. else
  544. #endif
  545. #endif
  546. #if ODOS3EXE OR OIAPX286
  547. mpextggr[extMac] = GRNIL;
  548. #endif
  549. }
  550. ++extMac; /* Increment public symbol counter */
  551. }
  552. }
  553. LOCAL void NEAR ComDef2(void)
  554. {
  555. int tmp; /* workaround a cl bug */
  556. SBTYPE sb; /* External symbol name */
  557. APROPNAMEPTR apropName; /* Property cell pointer */
  558. while(cbRec > 1) /* While not at end of record */
  559. {
  560. sb[0] = (BYTE) Gets(); /* Read in symbol length */
  561. if(rect == COMDEF)
  562. GetBytes(&sb[1],B2W(sb[0]));/* Read in the text of the symbol */
  563. else
  564. GetLocName(sb); /* Transform local name */
  565. #if CMDXENIX
  566. if(symlen && B2W(sb[0]) > symlen) sb[0] = symlen;
  567. /* Truncate if necessary */
  568. #endif
  569. GetIndex(0,0x7FFF); /* Skip the type index */
  570. tmp = Gets();
  571. switch(tmp)
  572. {
  573. case TYPEFAR:
  574. TypLen(); /* Skip num. elems. field */
  575. /* Fall through ... */
  576. case TYPENEAR:
  577. TypLen(); /* Skip length field */
  578. }
  579. apropName = (APROPNAMEPTR ) PropSymLookup(sb,ATTRPNM,FALSE);
  580. /* Look for symbol among PUBDEFs */
  581. if (apropName == PROPNIL)
  582. {
  583. ExitCode = 4;
  584. Fatal(ER_unrcom); /* Internal error */
  585. }
  586. #if OSEGEXE
  587. if(fNewExe)
  588. mpextflags[extMac] = apropName->an_flags;
  589. /* Save the flags */
  590. #if ODOS3EXE
  591. else
  592. #endif
  593. #endif
  594. #if ODOS3EXE OR OIAPX286
  595. mpextggr[extMac] = apropName->an_ggr;
  596. /* Save the global GRPDEF number */
  597. #endif
  598. #if OSEGEXE
  599. if(fNewExe && (apropName->an_flags & FIMPORT))
  600. DupErr(sb); /* Communal vars can't resolve to dynamic links */
  601. #endif
  602. mpextra[extMac] = apropName->an_ra;
  603. /* Save the offset */
  604. mpextgsn[extMac] = apropName->an_gsn;
  605. /* Save the global SEGDEF number */
  606. mpextprop[extMac] = vrprop; /* Save the property address */
  607. ++extMac; /* Increment public symbol counter */
  608. }
  609. }
  610. /****************************************************************
  611. * *
  612. * ObExpandIteratedData: *
  613. * *
  614. * This function expands a LIDATA record and moves it to *
  615. * virtual memory. The function returns a pointer to the *
  616. * start of the next iterated data block (if any). This is a *
  617. * recursive function. *
  618. * See pp. 68-69,63 in "8086 Object Module Formats EPS." *
  619. * *
  620. ****************************************************************/
  621. BYTE * ObExpandIteratedData(pb,cBlocks, pSize)
  622. BYTE *pb; /* Pointer into LIDATA buffer */
  623. WORD cBlocks; /* Current block count subfield */
  624. WORD *pSize; /* != NULL if all the caller wants
  625. is the size of expanded block */
  626. {
  627. WORD cNextLevelBlocks;
  628. /* Block count for next level */
  629. RATYPE cRepeat; /* Repeat count */
  630. WORD cbContent; /* Size of content subfield in bytes */
  631. BYTE *pbRet; /* Recursion return value */
  632. DEBUGVALUE(pb); /* Debug info */
  633. DEBUGVALUE(cBlocks); /* Debug info */
  634. DEBUGVALUE(vraCur); /* Debug info */
  635. if(!cBlocks) /* If block count subfield is zero */
  636. {
  637. cbContent = B2W(*pb++); /* Get size of content subfield */
  638. if (pSize!=NULL)
  639. *pSize += cbContent;
  640. #if OIAPX286
  641. if(pSize==NULL)
  642. MoveToVm(cbContent,pb,vsegCur,vraCur - mpsegraFirst[vsegCur]);
  643. /* Move data to virtual memory */
  644. #endif
  645. #if NOT OIAPX286
  646. #if OSEGEXE
  647. if (fNewExe && (pSize==NULL))
  648. DoIteratedFixups(cbContent,pb);/* Do any iterated fixups */
  649. #endif
  650. if(pSize==NULL)
  651. MoveToVm(cbContent,pb,vsegCur,vraCur);
  652. /* Move data to virtual memory */
  653. #if ODOS3EXE
  654. if(!fNewExe)
  655. {
  656. while(cbContent--)
  657. {
  658. if(pb[vcbData] && (pSize==NULL))
  659. RecordSegmentReference(vsegCur,(long)vraCur,B2W(pb[vcbData]));
  660. ++vraCur; /* Increment current offset */
  661. ++pb; /* Increment buffer pointer */
  662. }
  663. cbContent++;
  664. }
  665. #endif
  666. #endif /* NOT OIAPX286 */
  667. vraCur += cbContent; /* Adjust current offset */
  668. pb += cbContent; /* Move ahead in buffer */
  669. }
  670. else /* Else if non-zero block count */
  671. {
  672. while(cBlocks--) /* While there are blocks to do */
  673. {
  674. #if OMF386
  675. if(vrectData & 1)
  676. {
  677. cRepeat = getword(pb) + ((long)(getword(&pb[2])) << 16);
  678. cNextLevelBlocks = getword(&pb[4]);
  679. pb += 6;
  680. }
  681. else
  682. #endif
  683. {
  684. cRepeat = getword(pb); /* Get repeat count */
  685. cNextLevelBlocks = getword(&pb[2]);
  686. /* Get block count */
  687. pb += 4; /* Skip over fields */
  688. }
  689. ASSERT(cRepeat != 0); /* One hopes it won't happen */
  690. if(!cRepeat) InvalidObject();
  691. /* Must have non-zero repeat count */
  692. while(cRepeat--) pbRet = ObExpandIteratedData(pb,cNextLevelBlocks, pSize);
  693. /* Recurse to expand record */
  694. pb = pbRet; /* Skip over expanded block */
  695. }
  696. }
  697. DEBUGVALUE(pb); /* Debug info */
  698. DEBUGVALUE(rgmi + vcbData + 1); /* Debug info */
  699. ASSERT(pb <= rgmi + vcbData + 1); /* Should be true always */
  700. if(pb > rgmi + vcbData + 1) InvalidObject();
  701. /* Length must agree with format */
  702. return(pb); /* Ret ptr to next iterated data blk */
  703. }
  704. /****************************************************************
  705. * *
  706. * DataBlockToVm: *
  707. * *
  708. * This function moves data from a LEDATA record or a LIDATA *
  709. * record into virtual memory. *
  710. * See pp. 66-69 in "8086 Object Module Formats EPS." *
  711. * *
  712. ****************************************************************/
  713. LOCAL void NEAR DataBlockToVM(void)
  714. {
  715. REGISTER BYTE *pb; /* Pointer to data buffer */
  716. REGISTER RECTTYPE rect; /* Record type */
  717. DEBUGVALUE(vcbData); /* Debug info */
  718. /*
  719. * In new-format exes, disallow initialization of the stack segment
  720. * if it is in DGROUP.
  721. */
  722. if(fNewExe && vgsnCur == gsnStack && ggrDGroup != GRNIL &&
  723. mpsegsa[mpgsnseg[mpggrgsn[ggrDGroup]]] == mpsegsa[mpgsnseg[gsnStack]])
  724. return;
  725. rect = vrectData; /* Get record type */
  726. /*
  727. * Mask off all but the low bit of vrectData here, since ObExp.
  728. * will call RecordSegmentReference for runtime relocations which
  729. * were postponed until the LIDATA record was expanded.
  730. * RecordSegmentReference will think it's at the earlier phase if
  731. * vrectData is LIDATA, and the reloc won't get generated.
  732. * Leave low bit of vrectData so ObExp. can tell if OMF 386.
  733. */
  734. #if OMF386
  735. vrectData &= 1;
  736. #else
  737. vrectData = RECTNIL;
  738. #endif
  739. if(TYPEOF(rect) == LEDATA) /* If enumerated data record */
  740. {
  741. DEBUGVALUE(vraCur); /* Debug info */
  742. #if RGMI_IN_PLACE
  743. if (!fDebSeg && fNewExe)
  744. {
  745. // If data is going up to or past current end of initialized data,
  746. // omit any trailing null bytes and reset mpsacbinit. Mpsacbinit
  747. // will usually go up but may go down if a common segment over-
  748. // writes previous end data with nulls.
  749. SATYPE sa = mpsegsa[vsegCur];
  750. WORD cb = vcbData;
  751. long cbtot = (long)cb + vraCur;
  752. if ((DWORD) cbtot >= mpsacbinit[sa])
  753. {
  754. if ((DWORD) vraCur < mpsacbinit[sa] ||
  755. (cb = zcheck(rgmi, cb)) != 0)
  756. mpsacbinit[sa] = (long)vraCur + cb;
  757. }
  758. }
  759. #else
  760. #if OIAPX286
  761. if (fDebSeg)
  762. MoveToVm(vcbData,rgmi,vsegCur,vraCur);
  763. else
  764. MoveToVm(vcbData,rgmi,vsegCur,vraCur - mpsegraFirst[vsegCur]);
  765. #else
  766. MoveToVm(vcbData,rgmi,vsegCur,vraCur);
  767. #endif
  768. #endif
  769. /* Move data to virtual memory */
  770. vraCur += vcbData; /* Update current offset */
  771. }
  772. else /* Else if iterated data record */
  773. {
  774. pb = rgmi; /* Get address of buffer */
  775. while((pb = ObExpandIteratedData(pb,1, NULL)) < rgmi + vcbData);
  776. /* Expand and move to VM */
  777. }
  778. DEBUGVALUE(vsegCur); /* Debug info */
  779. #if ODOS3EXE OR OIAPX286
  780. if (!fNewExe && !fDebSeg) mpsegFlags[vsegCur] |= FNOTEMPTY;
  781. #endif
  782. #if OMF386
  783. vrectData = RECTNIL;
  784. #endif
  785. }
  786. /****************************************************************
  787. * *
  788. * LinRec2: *
  789. * *
  790. * This function processes LINNUM records on pass 2. *
  791. * See pp. 51-52 in "8086 Object Module Formats EPS." *
  792. * *
  793. ****************************************************************/
  794. void NEAR LinRec2(void)
  795. {
  796. SNTYPE sn; /* SEGDEF index value */
  797. SNTYPE gsn; /* Global SEGDEF no. */
  798. SEGTYPE seg;
  799. WORD ln; /* Line number */
  800. RATYPE ra; /* Offset */
  801. APROPPTR aprop;
  802. AHTEPTR ahte; // Pointer to hash table entry
  803. WORD attr; // COMDAT flags
  804. WORD comdatIdx; // COMDAT index
  805. APROPCOMDATPTR comdat; // Pointer to symbol table entry
  806. DWORD comdatRa; // Offset of the COMDAT symbol
  807. /*
  808. * Get the group index and ignore it, so the linker can work with
  809. * other compilers.
  810. */
  811. if ((rect & ~1) == LINNUM)
  812. {
  813. // Read regular LINNUM record
  814. GetIndex((WORD)0,(WORD)(grMac - 1));
  815. sn = GetIndex(1, (WORD)(snMac - 1));
  816. gsn = mpsngsn[sn]; /* Get global SEGDEF number */
  817. comdatRa = 0L;
  818. }
  819. else
  820. {
  821. // Read LINSYM record - line numbers for COMDAT
  822. attr = (WORD) Gets();
  823. comdatIdx = GetIndex(1, (WORD)(lnameMac - 1));
  824. comdat = (APROPCOMDATPTR ) PropRhteLookup(mplnamerhte[comdatIdx], ATTRCOMDAT, FALSE);
  825. if (comdat != NULL)
  826. {
  827. gsn = comdat->ac_gsn;
  828. comdatRa = comdat->ac_ra;
  829. }
  830. else
  831. InvalidObject(); /* Invalid module */
  832. }
  833. /* If LINNUM record is empty, don't do anything. */
  834. if(cbRec == 1)
  835. return;
  836. seg = mpgsnseg[gsn];
  837. if(gsn != vgsnLineNosPrev) /* If we weren't doing line numbers */
  838. { /* for this segment last time */
  839. if(vcln) NEWLINE(bsLst); /* Newline */
  840. fputs("\r\nLine numbers for ",bsLst);
  841. /* Message */
  842. OutFileCur(bsLst); /* File name */
  843. fputs(" segment ",bsLst); /* Message */
  844. aprop = (APROPPTR ) FetchSym(mpgsnrprop[gsn],FALSE);
  845. /* Fetch from virtual memory */
  846. ASSERT(aprop != PROPNIL); /* Should never happen! */
  847. ahte = GetHte(aprop->a_next); /* Get hash table entry */
  848. OutSb(bsLst,GetFarSb(ahte->cch)); /* Segment name */
  849. fputs("\r\n\r\n",bsLst); /* End line, skip a line */
  850. vgsnLineNosPrev = gsn; /* Save global SEGDEF number */
  851. vcln = 0; /* No entries on line yet */
  852. }
  853. while(cbRec > 1) /* While not at checksum */
  854. {
  855. if(vcln >= 4) /* If four entries on this line */
  856. {
  857. vcln = 0; /* Reset counter */
  858. NEWLINE(bsLst); /* Newline */
  859. }
  860. ln = WGets() + QCLinNumDelta; /* Read in line number */
  861. #if OMF386
  862. if (rect & 1)
  863. ra = LGets();
  864. else
  865. #endif
  866. ra = (RATYPE) WGets();
  867. ra += mpgsndra[gsn] + comdatRa; /* Get fixed segment offset */
  868. if(gsn == gsnText && comdatRa && fTextMoved)
  869. ra -= NullDelta;
  870. fprintf(bsLst," %4d %04x:",ln,mpsegsa[seg]);
  871. #if EXE386
  872. if (f386)
  873. fprintf(bsLst,"%08lx",(long) ra);
  874. else
  875. #endif
  876. fprintf(bsLst,"%04x",(WORD) ra);
  877. ++vcln; /* Increment counter */
  878. }
  879. }
  880. /****************************************************************
  881. * *
  882. * ProcP2: *
  883. * *
  884. * This function controls the processing of object modules *
  885. * during pass 2. *
  886. * *
  887. ****************************************************************/
  888. #pragma check_stack(on)
  889. void NEAR ProcP2(void)
  890. {
  891. #if EXE386
  892. WORD extflags[EXTMAX];
  893. #else
  894. BYTE extflags[EXTMAX];
  895. #endif
  896. SNTYPE extgsn[EXTMAX];
  897. RATYPE extra[EXTMAX];
  898. FTYPE fFirstMod;
  899. FTYPE fModEnd;
  900. #if SYMDEB
  901. WORD bTmp=TRUE;
  902. #endif
  903. #if OXOUT OR OIAPX286
  904. LFATYPE lfa; /* Seek value */
  905. #endif
  906. /* Group associations for EXTDEFs are only used for old exes and
  907. * EXTDEF flags are only used for new exes, so they can share the
  908. * same space. */
  909. #if OSEGEXE
  910. if(fNewExe)
  911. mpextflags = extflags; /* Initialize pointer */
  912. #if ODOS3EXE
  913. else
  914. #endif
  915. #endif
  916. #if ODOS3EXE OR OIAPX286
  917. mpextggr = extflags;
  918. #endif
  919. mpextgsn = extgsn; /* Initialize pointer */
  920. mpextra = extra; /* Initialize pointer */
  921. vgsnLineNosPrev = SNNIL; /* No line numbers from this module */
  922. fFirstMod = (FTYPE) TRUE; /* First module */
  923. for(;;) /* Loop to process modules */
  924. {
  925. snMac = 1; /* Initialize counter */
  926. grMac = 1; /* Initialize counter */
  927. extMac = 1; /* Initialize counter */
  928. lnameMac = 1; /* Initialize counter */
  929. QCExtDefDelta = 0; /* Initialize QC deltas */
  930. QCLinNumDelta = 0;
  931. vrectData = RECTNIL; /* Initialize record type variable */
  932. cbBakpat = 0; /* Initialize */
  933. #if OXOUT OR OIAPX286
  934. lfa = ftell(bsInput); /* Save initial file position */
  935. cbRec = WSGets(); /* Read record length */
  936. if(cbRec == X_MAGIC) fseek(bsInput,(long) CBRUN - sizeof(WORD),1);
  937. /* Skip x.out header if any */
  938. else fseek(bsInput,lfa,0); /* Else return to start */
  939. #endif
  940. #if RGMI_IN_PLACE
  941. rgmi = NULL; /* There is no data available */
  942. vcbData = 0; /* There is really no data, honest */
  943. #endif
  944. fModEnd = FALSE; /* Not end of module */
  945. while(!fModEnd) /* Loop to process object module */
  946. {
  947. rect = getc(bsInput); /* Read record type */
  948. if (IsBadRec(rect))
  949. {
  950. if(fFirstMod) break; /* Break if 1st module invalid */
  951. return; /* Else return */
  952. }
  953. cbRec = getc(bsInput) | (getc(bsInput) << 8);
  954. /* Read record length */
  955. #if ALIGN_REC
  956. if (bsInput->_cnt >= cbRec)
  957. {
  958. pbRec = bsInput->_ptr;
  959. bsInput->_ptr += cbRec;
  960. bsInput->_cnt -= cbRec;
  961. }
  962. else
  963. {
  964. if (cbRec >= sizeof(recbuf))
  965. {
  966. // error -- record too large [rm]
  967. InvalidObject();
  968. }
  969. // read record into contiguous buffer
  970. fread(recbuf,1,cbRec,bsInput);
  971. pbRec = recbuf;
  972. }
  973. #endif
  974. lfaLast += cbRec + 3; /* Update current file position */
  975. DEBUGVALUE(rect); /* Debug info */
  976. DEBUGVALUE(cbRec); /* Debug info */
  977. /* If FIXUPP, perform relocation */
  978. if (TYPEOF(rect) == FIXUPP) FixRc2();
  979. else /* Else if not fixup record */
  980. {
  981. if (vrectData != RECTNIL)
  982. {
  983. DataBlockToVM(); /* Move data to virtual memory */
  984. fFarCallTrans = fFarCallTransSave;
  985. /* Restore the /FARCALL state */
  986. }
  987. fDebSeg = FALSE;
  988. switch(TYPEOF(rect)) /* Switch on record type */
  989. {
  990. case SEGDEF:
  991. SegRec2();
  992. break;
  993. case THEADR:
  994. case LHEADR:
  995. fSkipFixups = FALSE;
  996. ModRc1();
  997. break;
  998. case GRPDEF:
  999. GrpRec2();
  1000. break;
  1001. case EXTDEF:
  1002. case LEXTDEF:
  1003. case CEXTDEF:
  1004. ExtRec2();
  1005. break;
  1006. case COMDEF:
  1007. case LCOMDEF:
  1008. ComDef2();
  1009. break;
  1010. case LNAMES:
  1011. case LLNAMES:
  1012. LNmRc1((WORD)(TYPEOF(rect) == LLNAMES));
  1013. break;
  1014. case LINNUM:
  1015. case LINSYM:
  1016. #if SYMDEB
  1017. if (fSymdeb)
  1018. bTmp=DoDebSrc();
  1019. #endif
  1020. if (fLstFileOpen && vfLineNos
  1021. #if SYMDEB
  1022. && bTmp
  1023. #endif
  1024. )
  1025. LinRec2();
  1026. else
  1027. SkipBytes((WORD)(cbRec - 1));
  1028. break;
  1029. case LEDATA:
  1030. case LIDATA:
  1031. DataRec();
  1032. break;
  1033. case MODEND:
  1034. #if OVERLAYS
  1035. if (!fOverlays) EndRec();
  1036. else SkipBytes((WORD)(cbRec - 1));
  1037. #else
  1038. EndRec();
  1039. #endif
  1040. fModEnd = (FTYPE) TRUE;
  1041. break;
  1042. case BAKPAT:
  1043. case NBAKPAT:
  1044. BakPat();
  1045. break;
  1046. case COMENT: /* COMENT records are processed in */
  1047. /* pass 2 for support of INCDEF for QC */
  1048. Gets(); /* Skip byte 1 of comment type field */
  1049. if (Gets() == 0xA0)
  1050. { /* if Microsoft OMF extension */
  1051. if (Gets() == 0x03)
  1052. { /* QC 2.0 - INCremental DEFinition */
  1053. QCExtDefDelta += WGets();
  1054. QCLinNumDelta += WGets();
  1055. }
  1056. }
  1057. SkipBytes((WORD)(cbRec - 1));
  1058. break;
  1059. case COMDAT:
  1060. ComDatRc2();
  1061. break;
  1062. default:
  1063. if (rect == EOF)
  1064. InvalidObject();
  1065. SkipBytes((WORD)(cbRec - 1));
  1066. /* Skip to checksum byte */
  1067. break;
  1068. }
  1069. }
  1070. DEBUGVALUE(cbRec); /* Debug info */
  1071. if(cbRec != 1) break; /* If record length bad */
  1072. Gets(); /* Eat the checksum byte */
  1073. }
  1074. if(!fModEnd)
  1075. {
  1076. ChkInput(); /* First check for I/O problems */
  1077. InvalidObject(); /* Invalid module */
  1078. }
  1079. ++modkey; /* For local symbols */
  1080. #if SYMDEB
  1081. if (fSymdeb) DebMd2(); /* Module post-processing for ISLAND */
  1082. #endif
  1083. if(cbBakpat) /* Fix up backpatches if any */
  1084. FixBakpat();
  1085. if(fLibraryFile) return; /* One at a time from libraries */
  1086. fFirstMod = FALSE; /* No longer first module */
  1087. }
  1088. }
  1089. #pragma check_stack(off)