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.

1175 lines
42 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. * NEWADR.C *
  11. * *
  12. * Common address-assignment routines. *
  13. * *
  14. ****************************************************************/
  15. #include <minlit.h> /* Types and constants */
  16. #include <bndtrn.h> /* Types and constants */
  17. #include <bndrel.h> /* Reloc. type definitions */
  18. #include <lnkio.h> /* Linker I/O definitions */
  19. #include <newexe.h> /* DOS & 286 .EXE data structures */
  20. #if EXE386
  21. #include <exe386.h> /* 386 .EXE data structures */
  22. #endif
  23. #include <lnkmsg.h> /* Error messages */
  24. #include <extern.h> /* External function declarations */
  25. /*
  26. * FUNCTION PROTOTYPES
  27. */
  28. LOCAL void FixSymRa(APROPNAMEPTR papropName,
  29. RBTYPE rhte,
  30. RBTYPE rprop,
  31. WORD fNewHte);
  32. LOCAL void AllocateCommon(APROPNAMEPTR papropName,
  33. RBTYPE rhte,
  34. RBTYPE rprop,
  35. WORD fNewHte);
  36. #if OSEGEXE AND SYMDEB AND NOT EXE386
  37. LOCAL void GenImports(APROPNAMEPTR papropName,
  38. RBTYPE rhte,
  39. RBTYPE rprop,
  40. FTYPE fNewHte);
  41. #endif
  42. LOCAL void NEAR AssignClasses(unsigned short (NEAR *ffun)(APROPSNPTR prop));
  43. LOCAL WORD NEAR IsNotAbs(APROPSNPTR apropSn);
  44. LOCAL WORD NEAR IsCode(APROPSNPTR prop);
  45. LOCAL WORD NEAR IsNotDGroup(APROPSNPTR prop);
  46. LOCAL WORD NEAR IsBegdata(APROPSNPTR prop);
  47. LOCAL WORD NEAR IsNotBssStack(APROPSNPTR prop);
  48. LOCAL WORD NEAR IsNotStack(APROPSNPTR prop);
  49. #if QBLIB
  50. extern RBTYPE rhteFarData; /* "FARDATA" class name */
  51. extern RBTYPE rhteFarBss; /* "FARBSS" class name */
  52. extern SEGTYPE segFD1st, segFDLast;
  53. extern SEGTYPE segFB1st, segFBLast;
  54. #endif
  55. #define IsAbsTysn(tysn) ((tysn & ~(BIGBIT | CODE386BIT)) == TYSNABS)
  56. SNTYPE gsnText; /* Global SEGDEF for _TEXT */
  57. /* Local variables */
  58. LOCAL long cbCommon; /* Count of bytes in COMMON */
  59. LOCAL long cbFar; /* Count of bytes in far common */
  60. LOCAL GRTYPE ggrCommon; /* Global group no. for common */
  61. LOCAL SNTYPE gsnCommon; /* Global SEGDEF for common */
  62. LOCAL SNTYPE gsnFar; /* Far common SEGDEF number */
  63. LOCAL FTYPE fNoEdata = (FTYPE) TRUE;
  64. LOCAL FTYPE fNoEnd = (FTYPE) TRUE;
  65. #if SYMDEB
  66. LOCAL int NEAR IsDebug(APROPSNPTR propSn);
  67. /************************************************************
  68. * *
  69. * Returns true if segment definition record is a debug *
  70. * segment: private and a recognized class. *
  71. * *
  72. ************************************************************/
  73. LOCAL int NEAR IsDebug(APROPSNPTR propSn)
  74. {
  75. return (fSymdeb && propSn->as_attr == ATTRLSN &&
  76. (propSn->as_rCla == rhteDebTyp ||
  77. propSn->as_rCla == rhteDebSym || propSn->as_rCla == rhteDebSrc));
  78. }
  79. #else
  80. #define IsDebug(a) FALSE
  81. #endif
  82. AHTEPTR GetHte(rprop) /* Get hash table entry */
  83. RBTYPE rprop; /* Property cell address */
  84. {
  85. REGISTER AHTEPTR ahte; /* Hash table entry pointer */
  86. ahte = (AHTEPTR ) FetchSym(rprop,FALSE);
  87. /* Fetch property cell */
  88. /* While not at hash table entry, get next cell in chain */
  89. while(ahte->attr != ATTRNIL)
  90. ahte = (AHTEPTR ) FetchSym(ahte->rhteNext,FALSE);
  91. return(ahte); /* Return ptr to hash table entry */
  92. }
  93. /****************************************************************
  94. * *
  95. * FixSymRa: *
  96. * *
  97. * Fix symbol offset. Called by EnSyms. *
  98. * *
  99. ****************************************************************/
  100. LOCAL void FixSymRa (papropName,rhte,rprop,fNewHte)
  101. APROPNAMEPTR papropName; /* Symbol property cell */
  102. RBTYPE rhte; /* Hash table virt address */
  103. RBTYPE rprop; /* Symbol virt address */
  104. WORD fNewHte;
  105. {
  106. SNTYPE gsn;
  107. #if O68K
  108. SATYPE sa;
  109. #endif /* O68K */
  110. if(!(gsn = papropName->an_gsn)) return;
  111. papropName->an_ra += mpgsndra[gsn];
  112. #if O68K
  113. if (iMacType != MAC_NONE && IsDataFlg(mpsaflags[sa =
  114. mpsegsa[mpgsnseg[gsn]]]))
  115. papropName->an_ra += mpsadraDP[sa];
  116. #endif /* O68K */
  117. MARKVP();
  118. }
  119. /****************************************************************
  120. * *
  121. * GenSeg: *
  122. * *
  123. * Generate a segment definition. *
  124. * *
  125. ****************************************************************/
  126. #if EXE386
  127. APROPSNPTR GenSeg(sbName,sbClass,ggr,fPublic)
  128. #else
  129. APROPSNPTR NEAR GenSeg(sbName,sbClass,ggr,fPublic)
  130. #endif
  131. BYTE *sbName; /* Segment name */
  132. BYTE *sbClass; /* Class name */
  133. GRTYPE ggr; /* Global GRPDEF number */
  134. WORD fPublic; /* True if public segment */
  135. {
  136. APROPSNPTR apropSn; /* Pointer to SEGDEF */
  137. RBTYPE rhteClass; /* Class name virt addr */
  138. PropSymLookup(sbClass, ATTRNIL, TRUE);/* Insert class name in hash table */
  139. rhteClass = vrhte; /* Save class name virt addr */
  140. if(fPublic) /* If public segment */
  141. {
  142. apropSn = (APROPSNPTR ) PropSymLookup(sbName, ATTRPSN, TRUE);
  143. /* Create segment */
  144. if(!vfCreated) return(apropSn); /* If it existed, return pointer */
  145. #if EXE386
  146. apropSn->as_tysn = DWORDPUBSEG; /* Segment is public */
  147. #else
  148. apropSn->as_tysn = PARAPUBSEG; /* Segment is public */
  149. #endif
  150. }
  151. else /* Else if private segment */
  152. {
  153. PropSymLookup(sbName, ATTRNIL, TRUE);
  154. /* Look up name */
  155. apropSn = (APROPSNPTR ) PropAdd(vrhte,ATTRLSN);
  156. /* Segment is local */
  157. #if EXE386
  158. apropSn->as_tysn = DWORDPRVSEG; /* Segment is private */
  159. #else
  160. apropSn->as_tysn = PARAPRVSEG; /* Segment is private */
  161. #endif
  162. }
  163. if(gsnMac >= gsnMax) Fatal(ER_segmax);
  164. /* Check for table overflow */
  165. apropSn->as_rCla = rhteClass; /* Save segment's class */
  166. mpgsnrprop[gsnMac] = vrprop; /* Save property cell address */
  167. apropSn->as_gsn = gsnMac++; /* Give it a global SEGDEF number */
  168. apropSn->as_ggr = ggr; /* Give specified group association */
  169. return(apropSn); /* Return global SEGDEF */
  170. }
  171. #if FALSE AND OSEGEXE AND SYMDEB AND NOT EXE386
  172. /* Postponed CV not ready yet */
  173. /*** GenImports - fill in $$IMPORTS segment for CV
  174. *
  175. * Purpose:
  176. * Build $$IMPORTS segment for CV. This segment enables symbolic information
  177. * in CV for dyncalls. The $$IMPORTS segment contains sequence of entries
  178. * in the following format:
  179. *
  180. * 16-bit 16-bit 32-bit
  181. * +--------+--------+-----------------+
  182. * | iMod | iName | far address |
  183. * +--------+--------+-----------------+
  184. *
  185. * Where:
  186. * - iMod - index to Module Reference Table in .EXE
  187. * - iName - index to Imported Names Table in .EXE (32-bit for 386)
  188. * - address - import's address fixed up by loader
  189. *
  190. * Input:
  191. * This function is called by EnSyms, so it takes standard set of arguments.
  192. * papropName - pointer to import property cell
  193. * rprop - virtual address of property cell
  194. * rhte - virt address of hash table entry
  195. * fNewHte - TRUE if name has been written
  196. *
  197. * Output:
  198. * No explicit value is returned. Segment data is created and run-time
  199. * fiuxps.
  200. *
  201. * Exceptions:
  202. * None.
  203. *
  204. * Notes:
  205. * None.
  206. *
  207. *************************************************************************/
  208. LOCAL void GenImports(papropName,rhte,rprop,fNewHte)
  209. APROPNAMEPTR papropName;
  210. RBTYPE rhte;
  211. RBTYPE rprop;
  212. FTYPE fNewHte;
  213. {
  214. static WORD raImpSeg = 0;
  215. APROPIMPPTR lpImport;
  216. APROPNAMEPTR lpPublic;
  217. CVIMP cvImp;
  218. RELOCATION r; /* Relocation item */
  219. lpImport = (APROPIMPPTR) papropName;
  220. if (lpImport->am_mod)
  221. return; /* Skip module name */
  222. /* Build CV import descriptor and save it in $$IMPORTS segment */
  223. cvImp.iName = lpImport->am_offset; /* Save index to Imported Name Table */
  224. cvImp.address = (char far *) 0L;
  225. lpPublic = (APROPNAMEPTR) FetchSym((RBTYPE)lpImport->am_public, FALSE);
  226. cvImp.iMod = lpPublic->an_module; /* Save index to Module Reference Table */
  227. vgsnCur = gsnImports;
  228. MoveToVm(sizeof(CVIMP), (BYTE *) &cvImp, mpgsnseg[gsnImports], raImpSeg);
  229. /* Emit run-time fixup for import, so loader will fill in addrss field */
  230. #if EXE386
  231. R32_SOFF(r) = (WORD) ((raImpSeg + 6) % OBJPAGELEN);
  232. #else
  233. NR_SOFF(r) = (WORD) raImpSeg + 4;
  234. #endif
  235. NR_STYPE(r) = (BYTE) NRSPTR; /* Save fixup type - 16:16 pointer */
  236. NR_FLAGS(r) = (lpPublic->an_flags & FIMPORD) ? NRRORD : NRRNAM;
  237. #if EXE386
  238. R32_MODORD(r) = lpPublic->an_module;/* Get module specification */
  239. if (NR_FLAGS(r) & NRRNAM) /* Get entry specification */
  240. {
  241. if (cbImports < LXIVK)
  242. R32_PROCOFF16(r) = (WORD) lpPublic->an_entry;
  243. /* 16-bit offset */
  244. else
  245. { /* 32-bit offset */
  246. R32_PROCOFF32(r) = lpPublic->an_entry;
  247. NR_FLAGS(r) |= NR32BITOFF;
  248. }
  249. }
  250. else
  251. R32_PROCORD(r) = (WORD) lpPublic->an_entry;
  252. SaveFixup(mpsegsa[mpgsnseg[gsnImports]], ((raImpSeg + 6) >> pageAlign) + 1, &r);
  253. #else
  254. NR_MOD(r) = lpPublic->an_module; /* Get module specification */
  255. NR_PROC(r) = lpPublic->an_entry; /* Get entry specification */
  256. SaveFixup(mpsegsa[mpgsnseg[gsnImports]],&r);
  257. #endif
  258. raImpSeg += sizeof(CVIMP);
  259. }
  260. #endif
  261. /****************************************************************
  262. * *
  263. * AllocateCommon: *
  264. * *
  265. * Allocate space for C common variables. Called by EnSyms. *
  266. * *
  267. ****************************************************************/
  268. LOCAL void AllocateCommon(papropName,rhte,rprop,fNewHte)
  269. APROPNAMEPTR papropName;
  270. RBTYPE rhte;
  271. RBTYPE rprop;
  272. WORD fNewHte;
  273. {
  274. APROPUNDEFPTR papropUndef; /* Pointer to undefined symbol */
  275. APROPSNPTR apropSn; /* SEGDEF pointer */
  276. long len; /* Length of common variable */
  277. WORD cbElem; /* Bytes per element */
  278. long cbSeg; /* Number of bytes per segment */
  279. papropUndef = (APROPUNDEFPTR ) papropName;
  280. /* Recast pointer */
  281. if (papropUndef->au_flags & COMMUNAL)/* If symbol is defined common */
  282. {
  283. len = papropUndef->au_len; /* Get object's length */
  284. cbElem = papropUndef->au_cbEl; /* Get number of bytes per element */
  285. papropName->an_attr = ATTRPNM; /* Give it the public attribute */
  286. papropName->an_flags = FPRINT; /* Symbol is printable */
  287. #if ILINK
  288. papropName->an_module = 0; /* Special "module" for communals */
  289. #endif
  290. MARKVP(); /* Mark virtual page as dirty */
  291. ++pubMac; /* Increment count of public symbols */
  292. if(!cbElem) /* If near variable */
  293. {
  294. #if OMF386
  295. if (f386) /* DWORD-align objects >= len 4 */
  296. {
  297. if(len >= 4 && cbCommon + 3 > cbCommon)
  298. cbCommon = (cbCommon + 3) & ~3L;
  299. }
  300. else
  301. #endif
  302. if(!(len & 1)) cbCommon = (cbCommon + 1) & ~1L;
  303. /* Word-align even-lengthed objects */
  304. papropName->an_ra = (RATYPE) cbCommon;
  305. /* Assign an offset */
  306. papropName->an_gsn = gsnCommon;
  307. /* Assign to c_common segment */
  308. papropName->an_ggr = ggrCommon;
  309. /* Set up group association */
  310. #if OMF386
  311. if(f386)
  312. {
  313. if(cbCommon + len < cbCommon) Fatal(ER_32comarea);
  314. else cbCommon += len;
  315. } else
  316. #endif
  317. if((cbCommon += len) > LXIVK) Fatal(ER_comarea);
  318. /* Fatal if too much common */
  319. }
  320. else if ((len *= cbElem) < LXIVK)
  321. { /* Else if object not "huge" */
  322. if (cbFar + len > LXIVK) /* If new segment needed */
  323. {
  324. if (gsnFar != SNNIL) /* If there is an "old" segment */
  325. {
  326. apropSn = (APROPSNPTR ) FetchSym(mpgsnrprop[gsnFar],TRUE);
  327. /* Get old SEGDEF */
  328. apropSn->as_cbMx = cbFar;
  329. /* Save old length */
  330. }
  331. apropSn = GenSeg((BYTE *) "\007FAR_BSS",
  332. (BYTE *) "\007FAR_BSS", GRNIL, FALSE);
  333. /* Generate one */
  334. apropSn->as_flags = dfData;
  335. /* Use default data flags */
  336. #if EXE386
  337. apropSn->as_flags &= ~OBJ_INITDATA;
  338. // Clear initialized data bit
  339. apropSn->as_flags |= OBJ_UNINITDATA;
  340. // Set uninitialized data bit
  341. #endif
  342. #if O68K
  343. if(f68k)
  344. apropSn->as_flags |= NS32BIT;
  345. // 32-bit data
  346. #endif
  347. gsnFar = apropSn->as_gsn;
  348. /* Get global SEGDEF number */
  349. cbFar = 0L; /* Initialize size */
  350. papropName = (APROPNAMEPTR ) FetchSym(rprop,TRUE);
  351. /* Refetch */
  352. }
  353. if (!(len & 1))
  354. cbFar = (cbFar + 1) & ~1L;
  355. /* Word-align even-lengthed objects */
  356. papropName->an_ra = (RATYPE) cbFar;
  357. /* Assign an offset */
  358. papropName->an_gsn = gsnFar;/* Assign to far segment */
  359. papropName->an_ggr = GRNIL; /* No group association */
  360. cbFar += len; /* Update length */
  361. }
  362. else /* Else if "huge" object */
  363. {
  364. cbSeg = (LXIVK / cbElem)*cbElem;
  365. /* Calculate bytes per seg */
  366. papropName->an_ra = LXIVK - cbSeg;
  367. /* Assign offset so last element in
  368. first seg. not split */
  369. papropName->an_gsn = gsnMac;/* Assign to segment */
  370. papropName->an_ggr = GRNIL; /* No group association */
  371. while(len) /* While bytes remain */
  372. {
  373. if(cbSeg > len) cbSeg = len;
  374. /* Clamp segment length to len */
  375. apropSn = GenSeg((BYTE *) "\010HUGE_BSS",
  376. (BYTE *) "\010HUGE_BSS",GRNIL,FALSE);
  377. /* Create segment */
  378. apropSn->as_cbMx = len > LXIVK ? LXIVK : len;
  379. /* Set segment size */
  380. apropSn->as_flags = dfData;
  381. /* Use default data flags */
  382. #if EXE386
  383. apropSn->as_flags &= ~OBJ_INITDATA;
  384. // Clear initialized data bit
  385. apropSn->as_flags |= OBJ_UNINITDATA;
  386. // Set uninitialized data bit
  387. #endif
  388. #if O68K
  389. if(f68k)
  390. apropSn->as_flags |= NS32BIT;
  391. // 32-bit data
  392. #endif
  393. len -= cbSeg; /* Decrement length */
  394. }
  395. }
  396. }
  397. }
  398. /****************************************************************
  399. * *
  400. * AssignClasses: *
  401. * *
  402. * Assign the ordering of all segments in all classes that *
  403. * pass the given test function. *
  404. * *
  405. ****************************************************************/
  406. LOCAL void NEAR AssignClasses(WORD (NEAR *ffun)(APROPSNPTR prop))
  407. {
  408. REGISTER SNTYPE gsn; /* Index */
  409. REGISTER APROPSNPTR apropSn; /* Segment definition pointer */
  410. SNTYPE gsnFirst; /* Index of first segment in class */
  411. RBTYPE rhteClass; /* Class name */
  412. for(gsnFirst = 1; gsnFirst < gsnMac; ++gsnFirst)
  413. { /* Loop through the segments */
  414. rhteClass = RHTENIL; /* Initialize */
  415. for(gsn = gsnFirst; gsn < gsnMac; ++gsn)
  416. { /* Loop to examine segment records */
  417. if(mpgsnseg[gsn] != SEGNIL) continue;
  418. /* Skip assigned segments */
  419. apropSn = (APROPSNPTR ) FetchSym(mpgsnrprop[gsn],FALSE);
  420. /* Fetch SEGDEF from virt. mem. */
  421. if(rhteClass == RHTENIL) rhteClass = apropSn->as_rCla;
  422. /* Get class if we don't have one */
  423. if(apropSn->as_rCla == rhteClass &&
  424. (ffun == ((WORD (NEAR *)(APROPSNPTR)) 0) || (*ffun)(apropSn)))
  425. { /* If class member found */
  426. mpgsnseg[gsn] = ++segLast;
  427. /* Save ordering number */
  428. #if QBLIB
  429. if(fQlib)
  430. {
  431. if(rhteClass == rhteFarData && segFD1st == SEGNIL)
  432. segFD1st = segLast;
  433. else if(rhteClass == rhteFarBss && segFB1st == SEGNIL)
  434. segFB1st = segLast;
  435. }
  436. #endif
  437. mpseggsn[segLast] = gsn;// Map the other way
  438. if(IsCodeFlg(apropSn->as_flags))
  439. {
  440. #if OSEGEXE AND ODOS3EXE
  441. /* Set FCODE here for 3.x segments. FNOTEMPTY later */
  442. if(!fNewExe)
  443. mpsegFlags[segLast] = FCODE;
  444. #endif
  445. segCodeLast = segLast;
  446. /* Remember last code segment */
  447. }
  448. else if(IsDataFlg(apropSn->as_flags))
  449. segDataLast = segLast;
  450. /* Remember last data segment */
  451. #if NOT OSEGEXE
  452. mpsegFlags[segLast] = apropSn->as_flags;
  453. #endif
  454. }
  455. }
  456. #if QBLIB
  457. if(fQlib)
  458. {
  459. if(rhteClass == rhteFarData && segFD1st != SEGNIL)
  460. segFDLast = segLast;
  461. else if(rhteClass == rhteFarBss && segFB1st != SEGNIL)
  462. segFBLast = segLast;
  463. }
  464. #endif
  465. }
  466. }
  467. #if OEXE
  468. /****************************************************************
  469. * *
  470. * MkPubSym: *
  471. * *
  472. * Adds a public symbol record with the given parameters *
  473. * to the symbol table. Used for things like "$$MAIN". *
  474. * *
  475. ****************************************************************/
  476. void MkPubSym(sb,ggr,gsn,ra)
  477. BYTE *sb; /* Length-prefixed symbol name */
  478. GRTYPE ggr; /* Global GRPDEF number */
  479. SNTYPE gsn; /* Global SEGDEF number */
  480. RATYPE ra; /* Segment offset */
  481. {
  482. APROPNAMEPTR apropName; /* Public name pointer */
  483. if(PropSymLookup(sb,ATTRPNM,FALSE) != PROPNIL)
  484. { /* If symbol already defined */
  485. OutError(ER_pubdup,sb + 1);
  486. return; /* And return */
  487. }
  488. /* If not undefined, create as public */
  489. if((apropName = (APROPNAMEPTR )
  490. PropSymLookup(sb,ATTRUND,FALSE)) == PROPNIL)
  491. apropName = (APROPNAMEPTR ) PropSymLookup(sb,ATTRPNM,TRUE);
  492. apropName->an_attr = ATTRPNM; /* Public symbol */
  493. apropName->an_gsn = gsn; /* Save segment definition number */
  494. apropName->an_ra = ra; /* Starts at 4th byte of segment */
  495. apropName->an_ggr = ggr; /* Save group definition number */
  496. ++pubMac; /* Increment public count */
  497. apropName->an_flags = FPRINT; /* Public is printable */
  498. MARKVP(); /* Page has changed */
  499. #if SYMDEB
  500. if (fSymdeb) /* If ISLAND support on */
  501. DebPublic(vrprop, PUBDEF);
  502. /* Make a PUBLICS entry */
  503. #endif
  504. #if ILINK
  505. if (fIncremental)
  506. apropName->an_module = imodFile;
  507. #endif
  508. }
  509. #endif /* OEXE */
  510. LOCAL WORD NEAR IsNotAbs(apropSn)
  511. APROPSNPTR apropSn; /* Pointer to segment record */
  512. {
  513. return(!IsDebug(apropSn) && !IsAbsTysn(apropSn->as_tysn));
  514. /* Return true if not absolute segment */
  515. }
  516. #if EXE386
  517. LOCAL WORD NEAR IsImportData(prop)
  518. APROPSNPTR prop; /* Pointer to segment record */
  519. {
  520. return(prop->as_gsn == gsnImport); /* Return true if import data segment */
  521. }
  522. #endif
  523. LOCAL WORD NEAR IsCode(prop)
  524. APROPSNPTR prop; /* Pointer to segment record */
  525. {
  526. return(IsCodeFlg(prop->as_flags) && !IsAbsTysn(prop->as_tysn));
  527. /* Return true if code segment */
  528. }
  529. #if OEXE
  530. LOCAL WORD NEAR IsNotDGroup(prop)
  531. APROPSNPTR prop; /* Pointer to segment record */
  532. {
  533. return(prop->as_ggr != ggrDGroup && !IsDebug(prop) &&
  534. !IsAbsTysn(prop->as_tysn));
  535. /* True if segment not in DGROUP */
  536. }
  537. LOCAL WORD NEAR IsBegdata(prop)
  538. APROPSNPTR prop; /* Pointer to segment record */
  539. {
  540. return(prop->as_rCla == rhteBegdata && !IsAbsTysn(prop->as_tysn));
  541. /* True if segment class BEGDATA */
  542. }
  543. LOCAL WORD NEAR IsNotBssStack(prop)
  544. APROPSNPTR prop; /* Pointer to segment record */
  545. {
  546. return(prop->as_rCla != rhteBss && prop->as_rCla != rhteStack &&
  547. !IsDebug(prop) && !IsAbsTysn(prop->as_tysn));
  548. /* True if neither BSS nor STACK */
  549. }
  550. LOCAL WORD NEAR IsNotStack(prop)
  551. APROPSNPTR prop; /* Pointer to segment record */
  552. {
  553. return(prop->as_rCla != rhteStack && !IsDebug(prop) &&
  554. !IsAbsTysn(prop->as_tysn)); /* True if not class STACK */
  555. }
  556. #endif /* OEXE */
  557. #if INMEM
  558. WORD saExe = FALSE;
  559. void SetInMem ()
  560. {
  561. WORD cparExe;
  562. WORD cparSave;
  563. if(fOverlays || fSymdeb)
  564. return;
  565. cparExe = mpsegsa[segLast] +
  566. ((mpsegraFirst[segLast] + mpsegcb[segLast] + 0xf) >> 4);
  567. cparSave = cparExe;
  568. if(!(saExe = Dos3AllocMem(&cparExe)))
  569. return;
  570. if(cparExe != cparSave)
  571. {
  572. Dos3FreeMem(saExe);
  573. saExe = 0;
  574. return;
  575. }
  576. Dos3ClrMem(saExe,cparExe);
  577. }
  578. #endif /* INMEM */
  579. /****************************************************************
  580. * *
  581. * AssignAddresses: *
  582. * *
  583. * This function scans the set of segments, given their *
  584. * ordering, and assigns segment registers and addresses. *
  585. * *
  586. ****************************************************************/
  587. void NEAR AssignAddresses()
  588. {
  589. APROPSNPTR apropSn; /* Ptr to a segment record */
  590. #if FDEBUG
  591. SNTYPE gsn; /* Current global segment number */
  592. long dbsize; /* Length of segment */
  593. RBTYPE rbClass; /* Pointer to segment class */
  594. #endif
  595. BSTYPE bsTmp;
  596. #if QBLIB
  597. SNTYPE gsnQbSym; /* gsn of SYMBOL segment for .QLB */
  598. #endif
  599. #if OSEGEXE
  600. extern FTYPE fNoNulls; /* True if not inserting 16 nulls */
  601. #else
  602. #define fNoNulls FALSE
  603. #endif
  604. // Set up stack allocation
  605. if (gsnStack != SNNIL) /* If stack segment exists */
  606. {
  607. apropSn = (APROPSNPTR ) FetchSym(mpgsnrprop[gsnStack],TRUE);
  608. /* Fetch segment definition */
  609. #if OEXE
  610. apropSn->as_tysn = (BYTE) ((apropSn->as_tysn & 0x1F) | (ALGNPAR << 5));
  611. /* Force paragraph alignment */
  612. #if EXE386
  613. if (!cbStack)
  614. cbStack = apropSn->as_cbMx;
  615. cbStack = (cbStack + 3) & ~3; /* Must be even number of bytes */
  616. apropSn->as_cbMx = cbStack;
  617. #else
  618. if (!cbStack)
  619. cbStack = (WORD) apropSn->as_cbMx;
  620. cbStack = (cbStack + 1) & ~1; /* Must be even number of bytes */
  621. apropSn->as_cbMx = (DWORD) cbStack;
  622. #endif /* Save size of stack segment */
  623. #else
  624. /* Force size to 0 for Xenix executables */
  625. apropSn->as_cbMx = 0L;
  626. #endif
  627. }
  628. #if OEXE
  629. #if OSEGEXE
  630. else if(cbStack == 0 &&
  631. #if O68K
  632. iMacType == MAC_NONE &&
  633. #endif
  634. #if EXE386
  635. IsAPLIPROG(vFlags))
  636. #else
  637. !(vFlags & NENOTP) && !fBinary)
  638. #endif
  639. #else
  640. else if(cbStack == 0 && !fBinary)
  641. #endif
  642. { /* Else if no stack and not library */
  643. #if 0
  644. /* Issue warning message */
  645. if(fLstFileOpen && bsLst != stderr)
  646. {
  647. bsTmp = bsErr;
  648. bsErr = bsLst;
  649. OutWarn(ER_nostack);
  650. bsErr = bsTmp;
  651. }
  652. OutWarn(ER_nostack);
  653. #endif
  654. }
  655. #endif
  656. if(fCommon) /* If there are communal variables */
  657. {
  658. apropSn = GenSeg((BYTE *) "\010c_common",
  659. (BYTE *) "\003BSS",ggrDGroup,TRUE);
  660. /* Generate communal variable seg */
  661. if(vfCreated) apropSn->as_flags = dfData;
  662. /* Use default data flags */
  663. gsnCommon = apropSn->as_gsn; /* Save common segment number */
  664. ggrCommon = apropSn->as_ggr; /* Save common group number */
  665. cbCommon = apropSn->as_cbMx; /* Initialize size of common */
  666. gsnFar = SNNIL; /* No far BSS yet */
  667. #if NOT EXE386
  668. #if OMF386
  669. if(f386)
  670. {
  671. cbFar = ~0L;
  672. apropSn->as_flags |= FCODE386;
  673. }
  674. else
  675. #endif
  676. #if O68K
  677. if(f68k)
  678. {
  679. cbFar = LXIVK + 1; /* Force creation of far BSS segment */
  680. apropSn->as_flags |= NS32BIT;
  681. }
  682. else
  683. #endif
  684. #endif
  685. cbFar = LXIVK + 1; /* Force creation of far BSS segment */
  686. DEBUGVALUE(cbCommon); /* Debug info */
  687. EnSyms(AllocateCommon,ATTRUND);
  688. /* Assign common variables */
  689. /* Don't use SmallEnEnsyms - symbol */
  690. /* table may grow while in EnSyms */
  691. apropSn = (APROPSNPTR ) FetchSym(mpgsnrprop[gsnCommon],TRUE);
  692. apropSn->as_cbMx = cbCommon; /* Save segment size */
  693. if(gsnFar != SNNIL) /* If far BSS created */
  694. {
  695. apropSn = (APROPSNPTR ) FetchSym(mpgsnrprop[gsnFar],TRUE);
  696. apropSn->as_cbMx = cbFar; /* Save segment size */
  697. }
  698. }
  699. #if FALSE AND OSEGEXE AND SYMDEB AND NOT EXE386
  700. if (fSymdeb && fNewExe && cImpMods)
  701. {
  702. apropSn = GenSeg("\011$$IMPORTS", "\010FAR_DATA", GRNIL, FALSE);
  703. /* Support for dyncalls for CV */
  704. gsnImports = apropSn->as_gsn;
  705. apropSn->as_flags = dfData; /* Use default data flags */
  706. apropSn->as_cbMx = cbImpSeg; /* Save segment size */
  707. }
  708. #endif
  709. #if EXE386
  710. GenImportTable();
  711. #endif
  712. /* Initialize segment-based tables for pass 2 */
  713. InitP2Tabs();
  714. #if OVERLAYS
  715. if(fOverlays) SetupOverlays();
  716. #endif
  717. #if OEXE
  718. /*
  719. * If /DOSSEG is enabled and /NONULLSDOSSEG is not enabled, look for
  720. * segment _TEXT. If found, increase size by 16 in preparation for
  721. * reserving first 16 addresses for the sake of signal().
  722. */
  723. if(fSegOrder && !fNoNulls)
  724. {
  725. apropSn = (APROPSNPTR ) PropSymLookup((BYTE *) "\005_TEXT",ATTRPSN,FALSE);
  726. /* Look for public segment _TEXT */
  727. if(apropSn != PROPNIL) /* If it exists */
  728. {
  729. gsnText = apropSn->as_gsn; /* Save the segment index */
  730. if ((apropSn->as_tysn)>>5 == ALGNPAG)
  731. NullDelta = 256;
  732. #if EXE386
  733. if (apropSn->as_cbMx > CBMAXSEG32 - NullDelta)
  734. Fatal(ER_txtmax);
  735. else
  736. apropSn->as_cbMx += NullDelta;
  737. #else
  738. if((apropSn->as_cbMx += NullDelta) > LXIVK)
  739. Fatal(ER_txtmax);
  740. #endif
  741. fTextMoved = TRUE;
  742. /* Bump the size up */
  743. MARKVP(); /* Page has changed */
  744. }
  745. }
  746. #endif
  747. #if FDEBUG
  748. if(fDebug && fLstFileOpen) /* If debugging on */
  749. {
  750. /* Dump segments and lengths */
  751. for(gsn = 1; gsn < gsnMac; ++gsn)
  752. {
  753. apropSn = (APROPSNPTR ) FetchSym(mpgsnrprop[gsn],FALSE);
  754. dbsize = apropSn->as_cbMx;
  755. rbClass = apropSn->as_rCla;
  756. FmtPrint("%3d segment \"%s\"",gsn,1 + GetPropName(apropSn));
  757. FmtPrint(" class \"%s\" length %lxH bytes\r\n",
  758. 1 + GetPropName(FetchSym(rbClass,FALSE)),dbsize);
  759. }
  760. }
  761. #endif
  762. #if OSEGEXE
  763. if (gsnAppLoader)
  764. {
  765. // Make sure that aplication loder gets its own segment
  766. mpgsnseg[gsnAppLoader] = ++segLast;
  767. mpseggsn[segLast] = gsnAppLoader;
  768. }
  769. #endif
  770. #if OEXE
  771. if (fSegOrder) /* If forcing segment ordering */
  772. {
  773. AssignClasses(IsCode); /* Code first,... */
  774. #if EXE386
  775. AssignClasses(IsImportData); /* ...then import data */
  776. #endif
  777. AssignClasses(IsNotDGroup); /* ...then non-DGROUP,... */
  778. AssignClasses(IsBegdata); /* ...then class BEGDATA,... */
  779. AssignClasses(IsNotBssStack); /* ...then all but BSS and STACK,... */
  780. AssignClasses(IsNotStack); /* ...then all but class STACK */
  781. }
  782. #endif
  783. #if OXOUT OR OIAPX286
  784. if(fIandD) /* If separate code and data */
  785. AssignClasses(IsCode); /* Assign ordering to code */
  786. #endif
  787. AssignClasses(IsNotAbs); /* Assign order to segments */
  788. #if QBLIB
  789. /* If building QB userlib, generate the symbol segment last */
  790. if(fQlib)
  791. {
  792. gsnQbSym = GenSeg("\006SYMBOL", "", GRNIL, FALSE)->as_gsn;
  793. mpgsnseg[gsnQbSym] = ++segLast;
  794. }
  795. #endif
  796. #if NOT EXE386
  797. if (fBinary && cbStack && mpgsnseg[gsnStack] == 1)
  798. {
  799. /*
  800. * In .COM file first segment is a stack and it has non zero
  801. * size. We warn user about making his stack segment size
  802. * equal zero.
  803. */
  804. apropSn = (APROPSNPTR ) FetchSym(mpgsnrprop[gsnStack],TRUE);
  805. apropSn->as_cbMx = 0L;
  806. OutWarn(ER_stksize);
  807. }
  808. #endif
  809. /* Assign addresses according to which format exe is being produced */
  810. #if OIAPX286
  811. AssignXenAddr();
  812. #endif
  813. #if OSEGEXE AND ODOS3EXE
  814. if (fNewExe)
  815. AssignSegAddr();
  816. else
  817. AssignDos3Addr();
  818. #else
  819. #if OSEGEXE
  820. AssignSegAddr();
  821. #endif
  822. #if ODOS3EXE
  823. AssignDos3Addr();
  824. #endif
  825. #endif
  826. // Remember index for first debug segment
  827. segDebFirst = segLast +
  828. #if ODOS3EXE
  829. csegsAbs +
  830. #endif
  831. (SEGTYPE) 1;
  832. #if OEXE
  833. // If /DOSSEG enabled and segment _TEXT found, initialize offset
  834. // of _TEXT to 16 to reserve addresses 0-15. WARNING: gsnText must
  835. // be initialized to SNNIL.
  836. if (gsnText != SNNIL)
  837. {
  838. mpgsndra[gsnText] += NullDelta;
  839. // If no program starting address, initialize it to 0:NullDelta
  840. if (segStart == SEGNIL && !raStart && !mpsegsa[mpgsnseg[gsnText]])
  841. raStart = NullDelta;
  842. // If /DOSSEG enabled and segment _TEXT found, initialize offset
  843. // of _TEXT to NulDelta to reserve addresses 0-NullDelta-1.
  844. // This was done after the COMDAT's were allocated so the offsets
  845. // of COMDAT's allocated in _TEXT segment are off by NullDelta bytes.
  846. // Here we adjust them, so the data block associated with COMDAT
  847. // is placed in the right spot in the memory image. The matching
  848. // public symbol will be shifted by the call to EnSyms(FixSymRa, ATTRPNM).
  849. FixComdatRa();
  850. }
  851. #endif
  852. EnSyms(FixSymRa, ATTRPNM);
  853. #if LOCALSYMS
  854. if (fLocals)
  855. EnSyms(FixSymRa, ATTRLNM);
  856. #endif
  857. #if INMEM
  858. SetInMem();
  859. #endif
  860. // Allocate memory blocks for the final program's memory image
  861. if (fNewExe)
  862. {
  863. // Segmented-executable
  864. mpsaMem = (BYTE FAR * FAR *) GetMem(saMac * sizeof(BYTE FAR *));
  865. }
  866. else
  867. {
  868. // DOS executable
  869. mpsegMem = (BYTE FAR * FAR *) GetMem((segLast + 1) * sizeof(BYTE FAR *));
  870. }
  871. #if OVERLAYS
  872. if (fOverlays && gsnOvlData != SNNIL)
  873. FixOvlData(); // Initialize overlay data tables
  874. #endif
  875. #if QBLIB
  876. if(fQlib) BldQbSymbols(gsnQbSym); /* Build QB SYMBOL segment */
  877. #endif
  878. }
  879. /*** Define_edata_end - define special C run-time symbols
  880. *
  881. * Purpose:
  882. * Define special symbols _edata and _end used by the C run-time.
  883. * These symbols are defined as follows:
  884. *
  885. * The DGROUP layout
  886. *
  887. * +------------+
  888. * | |
  889. * | |
  890. * | |
  891. * | Near Heap |
  892. * | |
  893. * | |
  894. * +------------+
  895. * | |
  896. * | |
  897. * | STACK |
  898. * | |
  899. * | |
  900. * +------------+ <-- _end
  901. * | |
  902. * | _BSS |
  903. * | |
  904. * +------------+ <-- _edata
  905. * | |
  906. * | _CONST |
  907. * | |
  908. * +------------+
  909. * | |
  910. * | _DATA |
  911. * | |
  912. * +------------+
  913. *
  914. * Input:
  915. * papropSn - pointer to segment descriptor
  916. *
  917. * Output:
  918. * None.
  919. *
  920. * Exceptions:
  921. * None.
  922. *
  923. * Notes:
  924. * None.
  925. *
  926. *************************************************************************/
  927. void NEAR Define_edata_end(APROPSNPTR papropSn)
  928. {
  929. APROPNAMEPTR apropName; // Public name pointer
  930. SNTYPE gsn; // Global segment number
  931. // Symbols were defined by SwDosseg(), now adjust addresses.
  932. if (papropSn->as_tysn != TYSNABS && papropSn->as_ggr == ggrDGroup)
  933. {
  934. // This is not absolute segment and it belong to DGROUP
  935. gsn = papropSn->as_gsn;
  936. if (fNoEdata && papropSn->as_rCla == rhteBss)
  937. {
  938. fNoEdata = FALSE;
  939. apropName = (APROPNAMEPTR )
  940. PropSymLookup((BYTE *) "\006_edata",ATTRPNM,FALSE);
  941. // Fetch symbol
  942. apropName->an_gsn = gsn; // Save segment definition number
  943. apropName->an_ggr = ggrDGroup;
  944. // Save group definition number
  945. MARKVP(); // Page has changed
  946. }
  947. else if (fNoEnd && papropSn->as_rCla == rhteStack)
  948. {
  949. fNoEnd = FALSE;
  950. apropName = (APROPNAMEPTR )
  951. PropSymLookup((BYTE *) "\004_end",ATTRPNM,FALSE);
  952. // Fetch symbol
  953. apropName->an_gsn = gsn; // Save segment definition number
  954. apropName->an_ggr = ggrDGroup;
  955. // Save group definition number
  956. MARKVP(); // Page has changed
  957. }
  958. }
  959. }
  960. /*** Check_edata_end - check the definiton of special C run-time symbols
  961. *
  962. * Purpose:
  963. * Check the definition of special symbols _edata and _end used
  964. * by the C run-time.
  965. *
  966. * Input:
  967. * None.
  968. *
  969. * Output:
  970. * None.
  971. *
  972. * Exceptions:
  973. * None.
  974. *
  975. * Notes:
  976. * None.
  977. *
  978. *************************************************************************/
  979. void NEAR Check_edata_end(SNTYPE gsnTop, SEGTYPE segTop)
  980. {
  981. APROPNAMEPTR apropName; // Public name pointer
  982. APROPNAMEPTR apropName1; // Public name pointer
  983. // Check if both symbols are defined properly
  984. if (fNoEdata)
  985. {
  986. // No class 'BSS' segment defined;
  987. // make _edata point to end of 'DATA' segments
  988. apropName = (APROPNAMEPTR )
  989. PropSymLookup((BYTE *) "\006_edata",ATTRPNM,FALSE);
  990. // Fetch symbol
  991. if (fNoEnd)
  992. {
  993. // No class 'STACK' segment defined;
  994. // set _edata to end of DGROUP
  995. if (fNewExe)
  996. {
  997. apropName->an_gsn = mpggrgsn[ggrDGroup];
  998. // Save segment definition number
  999. apropName->an_ggr = ggrDGroup;
  1000. // Save group definition number
  1001. apropName->an_ra = mpsacb[mpsegsa[mpgsnseg[apropName->an_gsn]]];
  1002. // Save 'DATA' segments size
  1003. }
  1004. #if NOT EXE386
  1005. else
  1006. {
  1007. apropName->an_gsn = gsnTop;
  1008. apropName->an_ggr = ggrDGroup;
  1009. apropName->an_ra = mpsegcb[segTop];
  1010. }
  1011. #endif
  1012. }
  1013. else
  1014. {
  1015. // set _edata to _end
  1016. apropName1 = (APROPNAMEPTR )
  1017. PropSymLookup((BYTE *) "\004_end",ATTRPNM,FALSE);
  1018. // Fetch symbol
  1019. apropName->an_gsn = apropName1->an_gsn;
  1020. // Save segment definition number
  1021. apropName->an_ggr = apropName1->an_ggr;
  1022. // Save group definition number
  1023. apropName->an_ra = apropName1->an_ra;
  1024. // Save 'DATA' segments size
  1025. }
  1026. MARKVP(); // Page has changed
  1027. }
  1028. if (fNoEnd)
  1029. {
  1030. // No class 'STACK' segment defined;
  1031. // make _end point to end of 'BSS' or 'DATA' segments
  1032. apropName = (APROPNAMEPTR )
  1033. PropSymLookup((BYTE *) "\004_end",ATTRPNM,FALSE);
  1034. // Fetch symbol
  1035. if (fNewExe)
  1036. {
  1037. apropName->an_gsn = mpggrgsn[ggrDGroup];
  1038. // Save segment definition number
  1039. apropName->an_ggr = ggrDGroup;
  1040. // Save group definition number
  1041. apropName->an_ra = mpsacb[mpsegsa[mpgsnseg[apropName->an_gsn]]];
  1042. // Save 'BSS' segments size
  1043. }
  1044. #if NOT EXE386
  1045. else
  1046. {
  1047. apropName->an_gsn = gsnTop;
  1048. apropName->an_ggr = ggrDGroup;
  1049. apropName->an_ra = mpsegcb[segTop];
  1050. }
  1051. #endif
  1052. MARKVP(); // Page has changed
  1053. }
  1054. // Make __end and __edata the same as _end and _edata
  1055. apropName = (APROPNAMEPTR ) PropSymLookup((BYTE *) "\006_edata",ATTRPNM,FALSE);
  1056. apropName1 = (APROPNAMEPTR ) PropSymLookup((BYTE *) "\007__edata",ATTRPNM,TRUE);
  1057. apropName1->an_gsn = apropName->an_gsn;
  1058. apropName1->an_ggr = apropName->an_ggr;
  1059. apropName1->an_ra = apropName->an_ra;
  1060. apropName = (APROPNAMEPTR ) PropSymLookup((BYTE *) "\004_end",ATTRPNM,FALSE);
  1061. apropName1 = (APROPNAMEPTR ) PropSymLookup((BYTE *) "\005__end",ATTRPNM,TRUE);
  1062. apropName1->an_gsn = apropName->an_gsn;
  1063. apropName1->an_ggr = apropName->an_ggr;
  1064. apropName1->an_ra = apropName->an_ra;
  1065. }