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.

461 lines
17 KiB

  1. /*
  2. * Copyright Microsoft Corporation, 1983-1989
  3. *
  4. * This Module contains Proprietary Information of Microsoft
  5. * Corporation and should be treated as Confidential.
  6. */
  7. /* Addressing frame for segmented executable */
  8. /*
  9. * NEWMAP5.C
  10. */
  11. #include <minlit.h> /* Types and constants */
  12. #include <bndtrn.h> /* Types and constants */
  13. #include <bndrel.h> /* Reloc. type definitions */
  14. #include <lnkio.h> /* Linker I/O definitions */
  15. #include <newexe.h> /* DOS & 286 .EXE data structures */
  16. #if EXE386
  17. #include <exe386.h> /* 386 .EXE data structures */
  18. #endif
  19. #include <lnkmsg.h> /* Error messages */
  20. #include <extern.h> /* External declarations */
  21. #if NOT EXE386
  22. #define SEGTOPADDR ((WORD)0xffff)
  23. #endif
  24. /*
  25. * AssignSegAddr:
  26. *
  27. * Assign addresses for a segmented-executable format program.
  28. * Called by AssignAddresses.
  29. */
  30. void NEAR AssignSegAddr()
  31. {
  32. REGISTER SNTYPE gsn;
  33. REGISTER SEGTYPE seg;
  34. APROPSNPTR papropSn;
  35. ALIGNTYPE align;
  36. GRTYPE ggr;
  37. SEGTYPE segTop;
  38. AHTEPTR pahte; /* Pointer to group name hte */
  39. DWORD sacb; /* Physical segment ("frame") size */
  40. SEGTYPE segi; /* Segment index */
  41. DWORD CurrentPackLim;
  42. WORD fMixed; // TRUE if mixing use16 with use32 allowed
  43. WORD fUse16; // TRUE if group is use16
  44. #if FALSE AND NOT EXE386
  45. WORD ShiftDelta;
  46. #endif
  47. segTop = 0;
  48. saMac = 1; /* Initialize counter */
  49. #if EXE386
  50. if (ggrFlat)
  51. mpggrgsn[ggrFlat] = gsnMac; /* Mark base of pseudo-group */
  52. #endif
  53. for(seg = 1; seg <= segLast; ++seg) /* Loop to combine segments */
  54. {
  55. if(saMac >= SAMAX) Fatal(ER_fsegmax);
  56. /* Check for table overflow */
  57. mpsegsa[seg] = saMac; /* Save phys. seg. in table */
  58. mpsegraFirst[seg] = 0; /* First byte at offset zero */
  59. mpgsndra[mpseggsn[seg]] = 0; /* First byte at offset zero */
  60. papropSn = (APROPSNPTR ) FetchSym(mpgsnrprop[mpseggsn[seg]],FALSE);
  61. /* Look up segment definition */
  62. sacb = papropSn->as_cbMx; /* Save initial phys. seg. size */
  63. mpsacb[saMac] = sacb; /* Save in table also */
  64. mpsaflags[saMac] = papropSn->as_flags;
  65. /* Save the flags */
  66. mpsacbinit[saMac] = 0L; /* Initialize */
  67. mpsaRlc[saMac] = NULL; /* Initialize */
  68. ggr = papropSn->as_ggr; /* Get global GRPDEF index */
  69. if (ggr != GRNIL) /* If we've found a group member */
  70. {
  71. fUse16 = !Is32BIT(papropSn->as_flags);
  72. fMixed = (papropSn->as_fExtra & MIXED1632);
  73. mpggrgsn[ggr] = mpseggsn[seg];
  74. /* Remember base of group */
  75. for (segTop = segLast; segTop > seg; --segTop)
  76. { /* Loop to find highest member */
  77. papropSn = (APROPSNPTR )
  78. FetchSym(mpgsnrprop[mpseggsn[segTop]],FALSE);
  79. /* Get segment definition */
  80. if (ggr == papropSn->as_ggr) break;
  81. /* Break loop when found */
  82. }
  83. }
  84. else if (gsnAppLoader && mpseggsn[seg] == gsnAppLoader)
  85. {
  86. // Don't pack aplication loader with other CODE segments
  87. segTop = seg;
  88. }
  89. #if EXE386
  90. else if (gsnImport && mpseggsn[seg] == gsnImport)
  91. {
  92. // Don't pack IAT segment with other DATA segments
  93. segTop = seg;
  94. }
  95. #endif
  96. else if (packLim != 0L && IsCodeFlg(papropSn->as_flags))
  97. { /* If packing code segments */
  98. segTop = segCodeLast; /* Pack as much code as possible */
  99. #if EXE386
  100. if (!Is32BIT(papropSn->as_flags))
  101. CurrentPackLim = LXIVK - 36;
  102. else
  103. #endif
  104. CurrentPackLim = packLim;
  105. }
  106. else if(DataPackLim != 0L && IsDataFlg(papropSn->as_flags))
  107. { /* If packing data segments */
  108. segTop = segDataLast; /* Pack as much data as possible */
  109. #if EXE386
  110. if (!Is32BIT(papropSn->as_flags))
  111. CurrentPackLim = LXIVK;
  112. else
  113. #endif
  114. CurrentPackLim = DataPackLim;
  115. }
  116. else segTop = seg; /* Else stop with current segment */
  117. for(segi = seg + 1; segi <= segTop; ++segi)
  118. { /* Loop to end of group */
  119. papropSn = (APROPSNPTR )
  120. FetchSym(mpgsnrprop[mpseggsn[segi]],FALSE);
  121. /* Get segment definition */
  122. if (!fMixed && papropSn->as_ggr != GRNIL)
  123. fMixed = (papropSn->as_fExtra & MIXED1632);
  124. // Check if mixing use16
  125. // and use32 for group allowed
  126. if(papropSn->as_ggr != ggr && papropSn->as_ggr != GRNIL)
  127. { /* If groups do not match */
  128. if(ggr == GRNIL) /* If not in a true group */
  129. {
  130. segTop = segi - 1; /* Stop after last segment */
  131. break; /* Exit loop */
  132. }
  133. /* Output warning message */
  134. OutWarn(ER_grpovl,
  135. 1 + GetPropName(FetchSym(mpggrrhte[ggr],FALSE)),
  136. 1 + GetPropName(FetchSym(mpggrrhte[papropSn->as_ggr],FALSE)));
  137. }
  138. if(IsIOPL(mpsaflags[saMac]) != IsIOPL(papropSn->as_flags))
  139. {
  140. /* Don't pack IOPL with NIOPL */
  141. if (ggr == GRNIL)
  142. {
  143. /* Not a members of any group - stop packing */
  144. segTop = segi - 1;
  145. break;
  146. }
  147. else
  148. {
  149. /* Issue error and continue */
  150. pahte = (AHTEPTR ) FetchSym(mpggrrhte[ggr],FALSE);
  151. /* Get hash table entry */
  152. OutError(ER_iopl, 1 + GetPropName(papropSn),
  153. 1 + GetFarSb(pahte->cch));
  154. }
  155. }
  156. #if EXE386
  157. if(Is32BIT(mpsaflags[saMac]) != Is32BIT(papropSn->as_flags))
  158. {
  159. /* Don't pack 32-bit segments with 16-bit segments */
  160. if (ggr == GRNIL)
  161. {
  162. /* Not a members of any group - stop packing */
  163. segTop = segi - 1;
  164. break;
  165. }
  166. else if (!fMixed)
  167. {
  168. /* Issue error and continue */
  169. pahte = (AHTEPTR ) FetchSym(mpggrrhte[ggr],FALSE);
  170. /* Get hash table entry */
  171. OutError(ER_32_16_bit, 1 + GetPropName(papropSn),
  172. 1 + GetFarSb(pahte->cch));
  173. }
  174. }
  175. #endif
  176. if (IsDataFlg(mpsaflags[saMac]) && IsDataFlg(papropSn->as_flags))
  177. {
  178. // If we are packing DATA segments, check NSSHARED bit
  179. #if EXE386
  180. if (IsSHARED(mpsaflags[saMac]) != IsSHARED(papropSn->as_flags))
  181. #else
  182. if ((mpsaflags[saMac] & NSSHARED) !=
  183. (papropSn->as_flags & NSSHARED))
  184. #endif
  185. {
  186. // Don't pack SHARED with NONSHARED data segments
  187. if (ggr == GRNIL)
  188. {
  189. // Not a members of any group - stop packing
  190. segTop = segi - 1;
  191. break;
  192. }
  193. else
  194. {
  195. // Issue error and continue
  196. pahte = (AHTEPTR ) FetchSym(mpggrrhte[ggr],FALSE);
  197. OutError(ER_shared, 1 + GetPropName(papropSn),
  198. 1 + GetFarSb(pahte->cch));
  199. }
  200. }
  201. }
  202. mpsegsa[segi] = saMac; /* Assign phys. seg. to segment */
  203. /* Fix the flags */
  204. #if EXE386
  205. if (IsCODEOBJ(mpsaflags[saMac]) && !IsCODEOBJ(papropSn->as_flags))
  206. #else
  207. if((mpsaflags[saMac] & NSTYPE) != (papropSn->as_flags & NSTYPE))
  208. #endif
  209. { /* If types do not agree */
  210. /* If packing code or data segs, stop current packing group.
  211. * But allow program to explicitly group code and data.
  212. */
  213. if(ggr == GRNIL)
  214. {
  215. segTop = segi - 1;
  216. break;
  217. }
  218. #if EXE386
  219. else
  220. {
  221. /* Issue warning and convert segment type */
  222. WORD warningKind;
  223. if (IsCODEOBJ(papropSn->as_flags))
  224. warningKind = ER_codeindata;
  225. else
  226. warningKind = ER_dataincode;
  227. pahte = (AHTEPTR ) FetchSym(mpggrrhte[ggr],FALSE);
  228. /* Get hash table entry */
  229. OutWarn(warningKind, 1 + GetPropName(papropSn),
  230. 1 + GetFarSb(pahte->cch));
  231. }
  232. #else
  233. mpsaflags[saMac] &= (~NSSHARED & ~NSTYPE);
  234. mpsaflags[saMac] |= NSCODE;
  235. /* Set type to impure code */
  236. #endif
  237. }
  238. #if EXE386
  239. else if (!IsSHARED(papropSn->as_flags))
  240. mpsaflags[saMac] &= ~OBJ_SHARED;
  241. #else
  242. else if(!(papropSn->as_flags & NSSHARED))
  243. mpsaflags[saMac] &= ~NSSHARED;
  244. #endif
  245. /* Turn off pure bit if impure */
  246. #if EXE386
  247. if (!IsREADABLE(papropSn->as_flags)) mpsaflags[saMac] &= ~OBJ_READ;
  248. #else
  249. #if O68K
  250. if((papropSn->as_flags & (NSMOVE | NSPRELOAD | NSEXRD)) !=
  251. (mpsaflags[saMac] & (NSMOVE | NSPRELOAD | NSEXRD)))
  252. {
  253. if(ggr == GRNIL)
  254. {
  255. segTop = segi - 1;
  256. break;
  257. }
  258. else
  259. #else
  260. {
  261. #endif
  262. {
  263. if(!(papropSn->as_flags & NSMOVE))
  264. mpsaflags[saMac] &= ~NSMOVE;
  265. /* Turn off movable bit if fixed */
  266. if(papropSn->as_flags & NSPRELOAD)
  267. mpsaflags[saMac] |= NSPRELOAD;
  268. /* Set preload bit if preloaded */
  269. if (!(papropSn->as_flags & NSEXRD))
  270. mpsaflags[saMac] &= ~NSEXRD;
  271. /* Turn off execute/read-only */
  272. }
  273. }
  274. #endif
  275. /* Adjust alignment */
  276. align = (ALIGNTYPE) ((papropSn->as_tysn >> 5) & 7);
  277. /* Get alignment type */
  278. switch(align) /* Switch on alignment type */
  279. {
  280. case ALGNWRD: /* Word-aligned */
  281. sacb = (sacb + 1) & ~1L;
  282. /* Round up size to word boundary */
  283. break;
  284. #if OMF386
  285. case ALGNDBL: /* Double word-aligned */
  286. sacb = (sacb + 3) & ~3L; /* Round up to dword offset */
  287. break;
  288. #endif
  289. case ALGNPAR: /* Paragraph-aligned */
  290. sacb = (sacb + 0xF) & ~0xFL;
  291. /* Round up size to para boundary */
  292. break;
  293. case ALGNPAG: /* Page-aligned */
  294. sacb = (sacb + 0xFF) & ~0xFFL;
  295. /* Round up size to page boundary */
  296. break;
  297. }
  298. mpsegraFirst[segi] = sacb;
  299. /* Save offset of first byte */
  300. mpgsndra[mpseggsn[segi]] = sacb;
  301. /* Save offset of first byte */
  302. sacb += papropSn->as_cbMx; /* Increment size of file segment */
  303. #if NOT EXE386
  304. if(ggr != GRNIL) /* If true group */
  305. {
  306. if (fMixed && !fUse16)
  307. {
  308. pahte = (AHTEPTR ) FetchSym(mpggrrhte[ggr],FALSE);
  309. /* Get hash table entry */
  310. OutWarn(ER_mixgrp32, 1 + GetFarSb(pahte->cch));
  311. }
  312. if(sacb > LXIVK ||
  313. (IsCodeFlg(mpsaflags[saMac]) && sacb > LXIVK - 36))
  314. { /* If group overflow or unreliable */
  315. pahte = (AHTEPTR ) FetchSym(mpggrrhte[ggr],FALSE);
  316. /* Get hash table entry */
  317. if(sacb > LXIVK)
  318. Fatal(ER_grpovf,1 + GetFarSb(pahte->cch));
  319. else
  320. OutWarn(ER_codunsf,1 + GetFarSb(pahte->cch));
  321. }
  322. }
  323. else
  324. #endif
  325. if(sacb > CurrentPackLim)/* Else if packing limit exceeded */
  326. {
  327. segTop = segi - 1; /* Set top to last segment that fit */
  328. break; /* Break inner loop */
  329. }
  330. mpsacb[saMac] = sacb; /* Update file segment size */
  331. }
  332. #if NOT EXE386
  333. /*
  334. * Make DGROUP segment flags conform to auto data. It is assumed
  335. * that all conflicts have been resolved earlier.
  336. */
  337. if(ggr == ggrDGroup)
  338. {
  339. if(vFlags & NESOLO) mpsaflags[saMac] |= NSSHARED;
  340. else if(vFlags & NEINST) mpsaflags[saMac] &= ~NSSHARED;
  341. }
  342. #if FALSE
  343. if (IsDataFlg(mpsaflags[saMac]) && (mpsaflags[saMac] & NSEXPDOWN))
  344. {
  345. /* If this is data segment and NSEXPDOWN big is set - shitf it up */
  346. ShiftDelta = SEGTOPADDR - mpsacb[saMac];
  347. for (segi = seg; segi <= segTop; segi++)
  348. {
  349. mpsegraFirst[segi] += ShiftDelta;
  350. mpgsndra[mpseggsn[segi]] += ShiftDelta;
  351. }
  352. }
  353. #endif
  354. #endif
  355. if(mpsacb[saMac] != 0L)
  356. ++saMac;
  357. seg = segTop; /* Set counter appropriately */
  358. }
  359. /* We haven't yet assigned absolute segments (it is assumed
  360. * they are empty and are used only for addressing purposes),
  361. * but now we must assign them somewhere.
  362. */
  363. segTop = segLast; /* Initialize */
  364. for(gsn = 1; gsn < gsnMac; ++gsn) /* Loop to complete initialization */
  365. {
  366. papropSn = (APROPSNPTR ) FetchSym(mpgsnrprop[gsn],TRUE);
  367. /* Get symbol table entry */
  368. seg = mpgsnseg[gsn]; /* Get segment number */
  369. if(seg == SEGNIL) /* If we have an absolute segment */
  370. {
  371. mpgsnseg[gsn] = ++segTop; /* Assign a segment order number */
  372. mpsegsa[segTop] = (SATYPE) papropSn->as_cbMx;
  373. /* Assign absolute segs their loc. */
  374. }
  375. /* Define special symbols "_edata" and "_end" */
  376. if (fSegOrder)
  377. Define_edata_end(papropSn);
  378. }
  379. if (fSegOrder)
  380. Check_edata_end(0, 0);
  381. #if O68K
  382. /* The Macintosh addresses data as a negative offset to the A5 register.
  383. This limits "near" data to within 32k of A5; "far" data is defined as
  384. anything beyond the 32k limit and requires special addressing to reach it.
  385. To fold this into the standard linker model, the Macintosh post-processor
  386. treats the first data segment as "near" data and all subsequent data
  387. segments as "far". Thus, N data segments are arranged as follows:
  388. A5 -> +----------+ High memory
  389. | DATA 0 |
  390. +----------+
  391. | DATA N |
  392. +----------+
  393. | DATA N-1 |
  394. +----------+
  395. | . |
  396. | . |
  397. | . |
  398. +----------+
  399. | DATA 2 |
  400. +----------+
  401. | DATA 1 |
  402. +----------+ Low memory
  403. Consequently, we must calculate the displacment from the start of each data
  404. segment to its ultimate place in memory relative to A5. */
  405. if (iMacType != MAC_NONE)
  406. {
  407. RATYPE draDP;
  408. SATYPE sa;
  409. SATYPE saDataFirst;
  410. draDP = -((mpsacb[saDataFirst = mpsegsa[mpgsnseg[mpggrgsn[ggrDGroup]]]]
  411. + 3L) & ~3L);
  412. mpsadraDP[saDataFirst] = draDP;
  413. for (sa = mpsegsa[segDataLast]; sa > saDataFirst; sa--)
  414. draDP = mpsadraDP[sa] = draDP - ((mpsacb[sa] + 3L) & ~3L);
  415. }
  416. #endif
  417. }