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.

3715 lines
128 KiB

  1. /*
  2. * TITLE
  3. * newfix.c
  4. * Pete Stewart
  5. * (C) Copyright Microsoft Corp 1984-89
  6. * 12 October 1984
  7. *
  8. * DESCRIPTION
  9. * This file contains routines for the linker that
  10. * read and interpret fixup records during the second
  11. * pass of the linking process.
  12. *
  13. */
  14. #include <minlit.h> /* Types and constants */
  15. #include <bndtrn.h> /* Basic types and constants */
  16. #include <bndrel.h> /* Relocation definitions */
  17. #include <lnkio.h> /* Linker I/O definitions */
  18. #include <newexe.h> /* DOS & 286 .EXE format structure def.s */
  19. #if EXE386
  20. #include <exe386.h> /* 386 .EXE format structure def.s */
  21. #include <fixup386.h> /* Linker internal fixup representation */
  22. #endif
  23. #include <lnkmsg.h> /* Error messages */
  24. #include <extern.h> /* External declarations */
  25. #include <nmsg.h> /* Near message strings */
  26. #define RelocWarn(a,b,c,d,e) FixErrSub(a,b,c,d,e,(FTYPE)FALSE)
  27. #define RelocErr(a,b,c,d,e) FixErrSub(a,b,c,d,e,(FTYPE)TRUE)
  28. #define FixupOverflow(a,b,c,d) RelocErr(ER_fixovf,a,b,c,d)
  29. #define IsSELECTED(x) ((x)&SELECTED_BIT)
  30. __inline void addword(BYTE *pdata, WORD w)
  31. // add a word to the word at location pdata... enforce little endian add
  32. // even if linker hosted on a big endian machine
  33. {
  34. w += pdata[0] + (pdata[1]<<BYTELN);
  35. pdata[0] = (BYTE)w;
  36. pdata[1] = (BYTE)(w>>BYTELN);
  37. }
  38. #if defined( _WIN32 )
  39. #define fixword(x,y) ((*(WORD UNALIGNED *)(x)) = (WORD)(y))
  40. #define fixdword(x,y) ((*(DWORD UNALIGNED *)(x)) = (DWORD)(y))
  41. #else
  42. #if M_I386
  43. #define fixword(x,y) ((*(WORD *)(x)) = (WORD)(y))
  44. #define fixdword(x,y) ((*(DWORD *)(x)) = (DWORD)(y))
  45. #else
  46. #define fixword(x,y) ((x)[0]) = (BYTE)(y); \
  47. ((x)[1]) = (BYTE)((y) >> BYTELN);
  48. #define fixdword(x,y) ((x)[0]) = (BYTE)(y); \
  49. ((x)[1]) = (BYTE)((y) >> BYTELN); \
  50. ((x)[2]) = (BYTE)((y) >> (BYTELN*2)); \
  51. ((x)[3]) = (BYTE)((y) >> (BYTELN*3));
  52. #endif // NOT M_I386
  53. #endif // NOT _WIN32
  54. #if OSEGEXE
  55. extern RLCPTR rlcLidata; /* Pointer to LIDATA fixup array */
  56. extern RLCPTR rlcCurLidata; /* Pointer to current LIDATA fixup */
  57. # if ODOS3EXE OR defined(LEGO)
  58. #define DoFixup (*pfProcFixup)
  59. # else
  60. #if EXE386
  61. #define DoFixup Fix386
  62. #else
  63. #define DoFixup FixNew
  64. #endif
  65. # endif
  66. #else
  67. #define DoFixup FixOld
  68. #endif
  69. #if NOT ODOS3EXE
  70. #define fNoGrpAssoc FALSE
  71. #endif
  72. WORD mpthdidx[RLCMAX]; /* f(thread) = tgt index */
  73. KINDTYPE mpthdmtd[RLCMAX]; /* f(thread) = tgt method */
  74. LOCAL WORD mpthdfidx[RLCMAX]; /* f(thread) = frm index */
  75. LOCAL KINDTYPE mpthdfmtd[RLCMAX]; /* f(thread) = frm method */
  76. FIXINFO fi; /* Fixup information record */
  77. #if EXE386
  78. LOCAL RATYPE objraCur; /* Current offset in object */
  79. #endif
  80. #if POOL_BAKPAT
  81. LOCAL void * poolBakpat;
  82. #endif
  83. /*
  84. * FUNCTION PROTOTYPES
  85. */
  86. LOCAL void NEAR GetFixdat(void);
  87. LOCAL unsigned char NEAR GetFixup(void);
  88. #if OSEGEXE
  89. LOCAL void NEAR SaveLiRel(RLCPTR pr);
  90. LOCAL RATYPE NEAR FinishRlc(RLCPTR r,
  91. unsigned short sa,
  92. RATYPE ra);
  93. #if NOT EXE386
  94. #if O68K
  95. LOCAL WORD NEAR GetFixupWord(BYTE *);
  96. LOCAL DWORD NEAR GetFixupDword(BYTE *);
  97. #else /* NOT O68K */
  98. #define GetFixupWord getword
  99. #define GetFixupDword getdword
  100. #endif /* NOT O68K */
  101. #endif /* NOT EXE386 */
  102. #endif /* OSEGEXE */
  103. LOCAL unsigned char NEAR lastbyte(unsigned char *pdata,
  104. RATYPE ra,
  105. unsigned char optest,
  106. unsigned char opnew);
  107. LOCAL void NEAR Getgsn(unsigned char kind,
  108. unsigned short idx,
  109. unsigned short *pgsn,
  110. RATYPE *pra);
  111. LOCAL unsigned char NEAR TransFAR(unsigned char *pdata,
  112. RATYPE ra,
  113. RATYPE raTarget);
  114. LOCAL void NEAR StartAddrOld(void);
  115. LOCAL unsigned short NEAR Mpgsnosn(unsigned short gsn);
  116. LOCAL void NEAR GetFrameTarget(unsigned short *pgsnFrame,
  117. unsigned short *pgsnTarget,
  118. RATYPE *praTarget);
  119. #if EXE386
  120. LOCAL void NEAR Fix386();
  121. #endif
  122. #if ODOS3EXE
  123. LOCAL WORD NEAR InOneGroup(WORD gsnTarget, WORD gsnFrame);
  124. #endif
  125. LOCAL WORD NEAR CallGateRequired(SATYPE saTarget);
  126. extern void AddTceEntryPoint( APROPCOMDAT *pC );
  127. /*
  128. * GetFixdat:
  129. *
  130. * Process the FIXDAT byte of a FIXUPP record.
  131. */
  132. LOCAL void NEAR GetFixdat()
  133. {
  134. REGISTER WORD fixdat; /* The FIXDAT byte */
  135. WORD i; /* Temporary index */
  136. fixdat = Gets(); /* Get FIXDAT byte */
  137. i = (WORD) ((fixdat >> 4) & 7); /* Get frame info */
  138. if (fixdat & F_BIT) /* If frame thread-specified */
  139. {
  140. i &= 3; /* Threads numbered from 0 to 3 */
  141. fi.f_fmtd = mpthdfmtd[i]; /* Get method */
  142. fi.f_fidx = mpthdfidx[i]; /* Get index */
  143. }
  144. else /* Else if frame explicit */
  145. {
  146. fi.f_fmtd = (KINDTYPE) i; /* Save frame method */
  147. switch(i) /* Switch on frame method */
  148. {
  149. case F0: /* Index to get */
  150. fi.f_fidx = GetIndex(1, (WORD) (snMac - 1));
  151. break;
  152. case F1:
  153. fi.f_fidx = GetIndex(1, (WORD) (grMac - 1));
  154. break;
  155. case F2:
  156. fi.f_fidx = (WORD) (GetIndex(1, EXTMAX) + QCExtDefDelta);
  157. if (fi.f_fidx >= extMac)
  158. InvalidObject();
  159. break;
  160. case F3: /* Frame number to punt */
  161. WGets();
  162. break;
  163. case F4: /* Nothing to get */
  164. case F5:
  165. break;
  166. default: /* Invalid object */
  167. InvalidObject();
  168. }
  169. }
  170. i = (WORD) (fixdat & 3); /* Get target info */
  171. if (fixdat & T_BIT) /* If target given by thread */
  172. {
  173. fi.f_mtd = mpthdmtd[i]; /* Get method */
  174. fi.f_idx = mpthdidx[i]; /* Get index */
  175. }
  176. else /* Else if target explicit */
  177. {
  178. fi.f_mtd = (KINDTYPE ) i; /* Save the method */
  179. ASSERT(fi.f_mtd != 3); /* Unimplemented method */
  180. fi.f_idx = GetIndex(1, EXTMAX); /* Get the index */
  181. if (fi.f_mtd == 2)
  182. {
  183. fi.f_idx += (WORD) QCExtDefDelta;
  184. if (fi.f_idx >= extMac)
  185. InvalidObject();
  186. }
  187. }
  188. #if OMF386
  189. if(rect&1)
  190. fi.f_disp = (fixdat & P_BIT) ? 0L : LGets();
  191. else
  192. #endif
  193. fi.f_disp = (DWORD) ((fixdat & P_BIT) ? 0 : WGets());
  194. /* Get displacement, if any */
  195. }
  196. /*
  197. * GetFixup:
  198. *
  199. * Read and interpret a fixup record, storing the information in
  200. * a buffer.
  201. * Returns TRUE if fixup, FALSE if thread definition.
  202. */
  203. LOCAL FTYPE NEAR GetFixup()
  204. {
  205. REGISTER WORD key; /* Key byte */
  206. WORD cbData; /* End point */
  207. key = Gets(); /* Get key byte */
  208. if(!(key & THREAD_BIT)) /* If thread definition */
  209. {
  210. fi.f_mtd = (KINDTYPE ) ((key >> 2) & 7);
  211. /* Get the thread method */
  212. ASSERT(fi.f_mtd != 3); /* Unimplemented */
  213. /*
  214. * If target thread, take modulo 4 of method. Primary/secondary
  215. * not specified by thread.
  216. */
  217. if(!(key & D_BIT))
  218. fi.f_mtd &= 3;
  219. switch(fi.f_mtd) /* Switch on the thread method */
  220. {
  221. case 0: /* Thread specifies an index */
  222. fi.f_idx = GetIndex(1, (WORD) (snMac - 1));
  223. break;
  224. case 1:
  225. fi.f_idx = GetIndex(1, (WORD) (grMac - 1));
  226. break;
  227. case 2:
  228. fi.f_idx = (WORD) (GetIndex(1, EXTMAX) + QCExtDefDelta);
  229. /* Get index */
  230. if (fi.f_idx >= extMac)
  231. InvalidObject();
  232. break;
  233. case 3: /* Frame number (unimplemented) */
  234. WGets(); /* Skip the frame number */
  235. break;
  236. case 4: /* No thread datum */
  237. case 5:
  238. break;
  239. default: /* Error */
  240. InvalidObject(); /* Die gracefully */
  241. }
  242. if(!(key & D_BIT)) /* If we have a target thread */
  243. {
  244. key &= 3; /* Get thread number */
  245. mpthdmtd[key] = fi.f_mtd; /* Get method */
  246. mpthdidx[key] = fi.f_idx; /* Get index */
  247. }
  248. else /* If we have a frame thread */
  249. {
  250. key &= 3; /* Get thread number */
  251. mpthdfmtd[key] = fi.f_mtd;/* Get method */
  252. mpthdfidx[key] = fi.f_idx;/* Get index */
  253. }
  254. return((FTYPE) FALSE); /* Not a fixup */
  255. }
  256. /*
  257. * At this point, we know we have a fixup to perform.
  258. */
  259. /* Get fixup location type */
  260. #if EXE386
  261. fi.f_loc = (WORD) ((key >> 2) & NRSTYP);
  262. #else
  263. #if OMF386
  264. if(rect & 1)
  265. fi.f_loc = (key >> 2) & NRSTYP;
  266. else
  267. #endif
  268. fi.f_loc = (key >> 2) & 7;
  269. #endif
  270. fi.f_self = (FTYPE) ((key & M_BIT)? FALSE: TRUE);
  271. /* Get fixup mode */
  272. fi.f_dri = (WORD) (((key & 3) << 8) + Gets());
  273. /* Get data record index */
  274. cbData = vcbData;
  275. /* Check if location goes beyond end of data record. */
  276. switch(fi.f_loc)
  277. {
  278. case LOCOFFSET:
  279. case LOCLOADOFFSET:
  280. case LOCSEGMENT:
  281. --cbData;
  282. break;
  283. case LOCPTR:
  284. #if OMF386
  285. case LOCOFFSET32:
  286. case LOCLOADOFFSET32:
  287. #endif
  288. cbData -= 3;
  289. break;
  290. #if OMF386
  291. case LOCPTR48:
  292. cbData -= 5;
  293. break;
  294. #endif
  295. }
  296. if(fi.f_dri >= cbData)
  297. Fatal(ER_badobj);
  298. GetFixdat(); /* Process FIXDAT byte */
  299. #if TCE
  300. if(!vfPass1)
  301. #endif
  302. fi.f_add = !!*(WORD UNALIGNED *)(rgmi + fi.f_dri);
  303. /* Check if fixup is additive */
  304. return((FTYPE ) TRUE); /* This is a fixup */
  305. }
  306. /****************************************************************
  307. * *
  308. * FixErrSub: *
  309. * *
  310. * Report a fixup error. *
  311. * *
  312. ****************************************************************/
  313. void NEAR FixErrSub(msg,ra,gsnFrame,gsnTarget,raTarget,fErr)
  314. MSGTYPE msg; /* Error message */
  315. RATYPE ra; /* Relative addr of error */
  316. SNTYPE gsnFrame;
  317. SNTYPE gsnTarget;
  318. RATYPE raTarget;
  319. FTYPE fErr; /* True if increment err cnt */
  320. {
  321. BYTE *sb; /* Pointer to name */
  322. #if EXE386
  323. char *kind;
  324. #endif
  325. if (fDebSeg)
  326. return; // Ignore warnings/errors for CV info
  327. for(;;) /* Loop to give message */
  328. {
  329. sb = 1 + GetFarSb(GetHte(mpgsnrprop[vgsnCur])->cch);
  330. #if EXE386
  331. if(fErr)
  332. OutError(msg,ra - mpsegraFirst[mpgsnseg[vgsnCur]],sb);
  333. else
  334. OutWarn(msg,ra - mpsegraFirst[mpgsnseg[vgsnCur]],sb);
  335. switch(fi.f_loc)
  336. {
  337. case LOCSEGMENT:
  338. kind = "Selector";
  339. break;
  340. case LOCPTR:
  341. kind = "16:16 pointer";
  342. break;
  343. case LOCPTR48:
  344. kind = "16:32 pointer";
  345. break;
  346. default:
  347. kind = "";
  348. break;
  349. }
  350. if(fi.f_mtd == KINDEXT && mpextprop && mpextprop[fi.f_idx])
  351. FmtPrint(" %s '%s'\r\n",__NMSG_TEXT(N_tgtexternal),
  352. 1 + GetPropName(FetchSym(mpextprop[fi.f_idx],FALSE)));
  353. else if (gsnTarget)
  354. { /* Output frame, target info */
  355. FmtPrint(" %s: %s %s, %s %lx\r\n", kind,
  356. __NMSG_TEXT(N_tgtseg),
  357. 1 + GetPropName(FetchSym(mpgsnrprop[gsnTarget],FALSE)),
  358. __NMSG_TEXT(N_tgtoff), (RATYPE) raTarget);
  359. }
  360. #else
  361. if(fErr)
  362. OutError(msg,ra - mpgsndra[vgsnCur],sb);
  363. else
  364. OutWarn(msg,ra - mpgsndra[vgsnCur],sb);
  365. if(fi.f_mtd == KINDEXT && mpextprop && mpextprop[fi.f_idx])
  366. FmtPrint(" %s '%s'\r\n",__NMSG_TEXT(N_tgtexternal),
  367. 1 + GetPropName(FetchSym(mpextprop[fi.f_idx],FALSE)));
  368. else if(gsnFrame && gsnTarget)
  369. { /* Output frame, target info */
  370. FmtPrint(" %s %s", __NMSG_TEXT(N_frmseg),
  371. 1 + GetPropName(FetchSym(mpgsnrprop[gsnFrame], FALSE)));
  372. FmtPrint(", %s %s", __NMSG_TEXT(N_tgtseg),
  373. 1 + GetPropName(FetchSym(mpgsnrprop[gsnTarget], FALSE)));
  374. FmtPrint(", %s %lX\r\n",
  375. __NMSG_TEXT(N_tgtoff), (RATYPE) raTarget);
  376. }
  377. #endif
  378. if(!fLstFileOpen || bsErr == bsLst) break;
  379. /* Exit loop */
  380. bsErr = bsLst; /* Insure loop exit */
  381. }
  382. if (fLstFileOpen && fErr)
  383. cErrors--; // We called OutError twice for one error
  384. bsErr = stderr;
  385. }
  386. #if OSEGEXE
  387. /*
  388. * SaveLiRel : Save an LIDATA relocation record
  389. */
  390. LOCAL void NEAR SaveLiRel (pr)
  391. RLCPTR pr; /* Generic relocation record */
  392. {
  393. #if EXE386
  394. LE_SOFF(*pr) = (WORD) (objraCur - vraCur);
  395. #else
  396. NR_SOFF(*pr) -= (WORD) vraCur; /* Save offset within LIDATA record */
  397. #endif
  398. if((char *) rlcCurLidata > (char *) &rgmi[DATAMAX - sizeof(RELOCATION)])
  399. { /* If too many fixups */
  400. OutError(ER_fixmax);
  401. /* Output error message */
  402. return; /* Try next fixup */
  403. }
  404. FMEMCPY(rlcCurLidata++, pr, sizeof(RELOCATION));
  405. /* Copy relocation into buffer */
  406. }
  407. /* HERE ARE THE RULES USED BY LINKER TO GENERATE ENTRY POINTS:
  408. *
  409. * +----+-------------+-------------+-------------+-------------+-------------+
  410. * | \ | | | | |
  411. * | \ referenced | data | code | code ring 2 | code ring 2 |
  412. * |entry \ from | any ring | ring 3 |nonconforming| conforming |
  413. * |point \ | | | | |
  414. * |target \---------+-------------+-------------+-------------+-------------+
  415. * | | | | | |
  416. * |data | no entry | no entry | no entry | no entry |
  417. * |nonexported | | | | |
  418. * |------------------+-------------+-------------+-------------+-------------+
  419. * | | | | | |
  420. * |data | fixed entry | fixed entry | fixed entry | fixed entry |
  421. * |exported | | | | |
  422. * |------------------+-------------+-------------+-------------+-------------+
  423. * | | | | | |
  424. * |code ring 3 | no entry(1)| no entry(1)| invalid | invalid |
  425. * |nonexported | | | | |
  426. * |------------------+-------------+-------------+-------------+-------------+
  427. * | | | | | |
  428. * |code ring 3 | fixed entry | fixed entry | invalid | invalid |
  429. * |exported | | | | |
  430. * |------------------+-------------+-------------+-------------+-------------+
  431. * |code ring 2 | | | | |
  432. * |nonconforming |movable entry|movable entry| no entry(1)|movable entry|
  433. * |nonexported | | | | |
  434. * |------------------+-------------+-------------+-------------+-------------+
  435. * |code ring 2 | | | | |
  436. * |nonconforming |movable entry|movable entry| fixed entry |movable entry|
  437. * |exported | | | | |
  438. * |------------------+-------------+-------------+-------------+-------------+
  439. * |code ring 2 | | | | |
  440. * |conforming | no entry(1)| no entry(1)| no entry(1)| no entry(1)|
  441. * |nonexported | | | | |
  442. * |------------------+-------------+-------------+-------------+-------------+
  443. * |code ring 2 | | | | |
  444. * |conforming | fixed entry | fixed entry | fixed entry | fixed entry |
  445. * |exported | | | | |
  446. * |------------------+-------------+-------------+-------------+-------------+
  447. *
  448. * (1) If the entry point requires windows compatable prolog editing then
  449. * this entry point must be defined as a "fixed entry".
  450. *
  451. *
  452. * Forget about the note, (1), for now. I don't think it applies with
  453. * PROTMODE.
  454. * Ring 2 means IOPL, ring 3 means NOIOPL.
  455. * To simplify the code we are taking advantage of segment attributes.
  456. * I.e. force all the following segments to FIXED:
  457. * data
  458. * code ring 3
  459. * code ring 2, conforming
  460. * force to MOVABLE:
  461. * code ring 2, nonconforming
  462. * Then just use the segment attribute to determine what type of entry
  463. * to generate. There are clearly two exceptions that you must check
  464. * for:
  465. * - code ring 2 nonconforming nonexported, referenced by code ring 2 nonconforming
  466. * - code ring 2 nonconforming exported, referenced by code ring 2 nonconforming
  467. *
  468. */
  469. #if NOT QCLINK
  470. /*** CallGateRequired - check if call gate required
  471. *
  472. * Purpose:
  473. * Check if call gate is required for given target segment.
  474. *
  475. * Input:
  476. * saTarget - fixup target segment (memory object)
  477. *
  478. * Output:
  479. * Returns TRUE if call gate required, othrewise FALSE.
  480. *
  481. * Exceptions:
  482. * None.
  483. *
  484. * Notes:
  485. * None.
  486. *
  487. *************************************************************************/
  488. LOCAL WORD NEAR CallGateRequired(SATYPE saTarget)
  489. {
  490. #if EXE386
  491. return(FALSE);
  492. #else
  493. register WORD flags;
  494. flags = mpsaflags[saTarget];
  495. if ((vFlags & NEPROT) || TargetOs == NE_OS2)
  496. {
  497. // If the target entry point segment is NONCONFORMING IOPL CODE 16-bit
  498. // and current segment is a different type, generate a callgate
  499. return(IsCodeFlg(flags) &&
  500. NonConfIOPL(flags) &&
  501. mpsaflags[mpsegsa[vsegCur]] != flags);
  502. }
  503. else
  504. {
  505. // If target segment is non-absolute and movable, generate
  506. // a movable-type fixup and a corresponding entry table entry:
  507. return(flags & NSMOVE);
  508. }
  509. #endif
  510. }
  511. #endif
  512. /*
  513. * FinishRlc:
  514. *
  515. * Finish processing a relocation for a segmented-exe.
  516. */
  517. LOCAL RATYPE NEAR FinishRlc(r,sa,ra)
  518. RLCPTR r; /* Relocation record to finish */
  519. SATYPE sa; /* Target file segment number */
  520. RATYPE ra; /* Target offset */
  521. {
  522. if (!sa || sa >= saMac)
  523. return(ra); /* Something is wrong */
  524. #if NOT EXE386
  525. #if NOT QCLINK
  526. if (CallGateRequired(sa))
  527. {
  528. NR_SEGNO(*r) = BNDMOV; /* Reference is to movable segment */
  529. NR_ENTRY(*r) = MpSaRaEto(sa,ra);/* Save Entry Table ordinal */
  530. }
  531. else
  532. {
  533. NR_SEGNO(*r) = (BYTE) sa; /* Reference is to fixed segment */
  534. if (
  535. #ifdef LEGO
  536. #if OSEGEXE
  537. !fKeepFixups &&
  538. #endif
  539. #endif /* LEGO */
  540. ((NR_STYPE(*r) & NRSTYP) == NRSSEG))
  541. NR_ENTRY(*r) = (WORD) 0; /* For non call-gate base fixups force offset to zero */
  542. else
  543. {
  544. #if O68K
  545. if (iMacType != MAC_NONE && IsDataFlg(mpsaflags[sa]))
  546. NR_ENTRY(*r) = (WORD) (ra - mpsadraDP[sa]);
  547. /* Save offset into fixed segment */
  548. else
  549. #endif /* O68K */
  550. NR_ENTRY(*r) = (WORD) ra;
  551. /* Save offset into fixed segment */
  552. }
  553. }
  554. #else
  555. NR_SEGNO(*r) = (BYTE) sa; /* Reference is to fixed segment */
  556. NR_ENTRY(*r) = (WORD) ra; /* Save offset into fixed segment */
  557. #endif
  558. #else
  559. if (sa == SANIL)
  560. {
  561. RelocWarn(ER_badfixflat,objraCur,SNNIL,0,ra);
  562. /* Oops ! - Flat relative refernce */
  563. return((RATYPE)0); /* OS doesn't know object number zero */
  564. }
  565. LE_OBJNO(*r) = sa; /* Target object number */
  566. if (CallGateRequired(sa))
  567. {
  568. NR_FLAGS(*r) |= NRRENT;
  569. LE_IATORD(*r) = MpSaRaEto(sa,ra);
  570. /* Save Entry Table ordinal */
  571. }
  572. else
  573. {
  574. /* Target is internal reference */
  575. if ((NR_STYPE(*r) & NRSTYP) == NRSSEG)
  576. ra = 0L; /* For non call-gate base fixups force offset to zero */
  577. }
  578. LE_TOFF(*r) = ra; /* Target offset */
  579. #endif
  580. if(TYPEOF(vrectData) == LIDATA) /* If we have an LIDATA record */
  581. {
  582. SaveLiRel(r); /* Save LIDATA relocation record */
  583. return(0); /* Nothing to add */
  584. }
  585. #if EXE386
  586. return(SaveFixup(mpsegsa[vsegCur],vpageCur,r));
  587. #else
  588. return(SaveFixup(mpsegsa[vsegCur],r));
  589. /* Save fixup, return chain */
  590. #endif
  591. }
  592. #endif /* OSEGEXE */
  593. /*
  594. * lastbyte:
  595. *
  596. * If the last byte before the current byte matches
  597. * optest, then replace it with opnew and return TRUE;
  598. * otherwise, return FALSE.
  599. */
  600. LOCAL FTYPE NEAR lastbyte(pdata,ra,optest,opnew)
  601. BYTE *pdata; /* Pointer into data record */
  602. RATYPE ra; /* Offset in current segment */
  603. BYTE optest; /* Op code to test against */
  604. BYTE opnew; /* New op code */
  605. {
  606. BYTE FAR *pb; /* Byte pointer */
  607. if(pdata > rgmi) /* If needed byte in buffer */
  608. {
  609. if(pdata[-1] != optest) return(FALSE);
  610. /* Test fails if bytes differ */
  611. pdata[-1] = opnew; /* Replace the op code */
  612. return((FTYPE) TRUE); /* Test succeeds */
  613. }
  614. if(ra == 0) return(FALSE); /* Test fails if no byte to test */
  615. if(fNewExe)
  616. pb = mpsaMem[mpsegsa[vsegCur]] + ra - 1; /* Map in the desired byte */
  617. else
  618. pb = mpsegMem[vsegCur] + ra - 1; /* Map in the desired byte */
  619. if(*pb != optest) return(FALSE); /* Test fails if bytes differ */
  620. *pb = opnew; /* Replace the op code */
  621. markvp(); /* Page has changed */
  622. return((FTYPE) TRUE); /* Test succeeds */
  623. }
  624. #if OSEGEXE
  625. /*
  626. * DoIteratedFixups:
  627. *
  628. * Process fixups on an LIDATA record for a segmented-exe.
  629. */
  630. void NEAR DoIteratedFixups(cb,pb)
  631. WORD cb; /* Byte count */
  632. BYTE *pb; /* Byte pointer */
  633. {
  634. RATYPE raChain; /* Fixup chain */
  635. RATYPE raMin; /* Starting record offset */
  636. RATYPE raMax; /* Ending record offset */
  637. RLCPTR r; /* Relocation record */
  638. WORD j; /* Index */
  639. DWORD SrcOff;
  640. if(rlcCurLidata == rlcLidata) return;
  641. /* Nothing to do if no fixups */
  642. raMin = (RATYPE)(pb - rgmi); /* Offset of start of data in record */
  643. raMax = raMin + cb - 1; /* Offset of end of data in record */
  644. r = rlcLidata;
  645. while (r < rlcCurLidata)
  646. { /* Do for all fixups in array */
  647. #if EXE386
  648. SrcOff = LE_SOFF(*r);
  649. #else
  650. SrcOff = (DWORD) NR_SOFF(*r);
  651. #endif
  652. if(SrcOff >= (DWORD) raMin && SrcOff <= (DWORD) raMax)
  653. { /* If fixup lies in range of data */
  654. j = (WORD) (SrcOff - (DWORD) raMin);
  655. /* Get index off pb */
  656. /* Calculate offset in segment */
  657. #if EXE386
  658. LE_SOFF(*r)= (WORD) ((vraCur + j) % (1 << pageAlign));
  659. vpageCur = ((vraCur + j) >> pageAlign) + 1;
  660. raChain = SaveFixup(mpsegsa[vsegCur], vpageCur, r);
  661. /* Save the fixup reference */
  662. #else
  663. NR_SOFF(*r) = (WORD) (vraCur + j);
  664. raChain = SaveFixup(mpsegsa[vsegCur],r);
  665. /* Save the fixup reference */
  666. if(!(NR_FLAGS(*r) & NRADD))
  667. { /* If not additive */
  668. pb[j] = (BYTE) raChain;
  669. /* Set low byte of chain */
  670. pb[j + 1] = (BYTE)(raChain >> BYTELN);
  671. /* Set high byte of chain */
  672. }
  673. #endif
  674. /* Restore offset in record */
  675. #if EXE386
  676. LE_SOFF(*r)= (WORD) ((raMin + j) % (1 << pageAlign));
  677. #else
  678. NR_SOFF(*r) = (WORD) (raMin + j);
  679. #endif
  680. }
  681. ((RLCPTR ) r)++;
  682. }
  683. }
  684. #endif /* OSEGEXE */
  685. /*
  686. * Getgsn:
  687. *
  688. * Obtain segment number and offset for the given fixup method and index.
  689. * Return values are stored in pointers.
  690. */
  691. LOCAL void NEAR Getgsn(kind,idx,pgsn,pra)
  692. KINDTYPE kind; /* Kind of index */
  693. WORD idx; /* The index */
  694. SEGTYPE *pgsn; /* gsn (ref) */
  695. RATYPE *pra; /* ra (ref) */
  696. {
  697. #if O68K
  698. SATYPE sa;
  699. #endif /* O68K */
  700. switch(kind) /* Decide what to do */
  701. {
  702. case KINDSEG: /* Segment index */
  703. #if FALSE
  704. if(idx >= snMac) InvalidObject();
  705. /* Make sure index not too big */
  706. #endif
  707. *pgsn = mpsngsn[idx]; /* Get gsn */
  708. *pra = mpgsndra[*pgsn]; /* Get ra */
  709. #if O68K
  710. if (iMacType != MAC_NONE && IsDataFlg(mpsaflags[sa =
  711. mpsegsa[mpgsnseg[*pgsn]]]))
  712. *pra += mpsadraDP[sa]; /* Get data ra */
  713. #endif /* O68K */
  714. break;
  715. case KINDGROUP: /* Group index */
  716. #if FALSE
  717. if(idx >= grMac) InvalidObject();
  718. /* Make sure index not too big */
  719. #endif
  720. *pgsn = mpggrgsn[mpgrggr[idx]];
  721. /* Get gsn */
  722. *pra = mpgsndra[*pgsn]; /* Get ra */
  723. #if O68K
  724. if (iMacType != MAC_NONE && IsDataFlg(mpsaflags[sa =
  725. mpsegsa[mpgsnseg[*pgsn]]]))
  726. *pra += mpsadraDP[sa]; /* Get data ra */
  727. #endif /* O68K */
  728. break;
  729. case KINDEXT: /* External index */
  730. #if FALSE
  731. if(idx >= extMac) InvalidObject();
  732. /* Make sure index not too big */
  733. #endif
  734. *pgsn = mpextgsn[idx]; /* Get gsn */
  735. *pra = mpextra[idx]; /* Get ra */
  736. break;
  737. default: /* All other kinds */
  738. *pgsn = SEGNIL; /* No gsn */
  739. *pra = 0; /* No ra */
  740. break;
  741. }
  742. // If this is $$SYMBOLS segment then return logical offset
  743. // NOT physical offset
  744. if (fDebSeg) {
  745. #if O68K
  746. if (iMacType == MAC_NONE)
  747. #endif
  748. *pra -= mpsegraFirst[mpgsnseg[*pgsn]];
  749. }
  750. }
  751. /*
  752. * TransFAR : Possibly translate an intra-segment FAR call or jump
  753. *
  754. * If the given location looks like a FAR call or jump,
  755. * translate it and return TRUE. Otherwise, do nothing and
  756. * return FALSE.
  757. */
  758. LOCAL FTYPE NEAR TransFAR (pdata, ra, raTarget)
  759. BYTE *pdata; /* Pointer to fixup location */
  760. RATYPE ra; /* Offset in current segment */
  761. RATYPE raTarget; /* Target offset */
  762. {
  763. #if O68K
  764. if (f68k)
  765. return FALSE;
  766. #else
  767. static RATYPE raPrev;
  768. static SATYPE saPrev; /* Location of the previous fixup */
  769. if(raPrev + 4 == ra && saPrev == mpsegsa[vsegCur])
  770. {
  771. if(!fOverlays)
  772. Fatal(ER_badfarcall); /* A far jump and/or ptr table present */
  773. else
  774. return(FALSE); /* The user can't turn off /FARC in an overlaid .exe */
  775. }
  776. else
  777. {
  778. raPrev = ra;
  779. saPrev = mpsegsa[vsegCur];
  780. }
  781. if(lastbyte(pdata,ra,CALLFARDIRECT,NOP))
  782. { /* If fixing up long call direct */
  783. *pdata++ = PUSHCS; /* Push CS */
  784. *pdata++ = CALLNEARDIRECT;
  785. /* Short call */
  786. raTarget -= ra + 4; /* Make offset self-relative */
  787. fixword(pdata, raTarget); /* store fixed up value */
  788. return((FTYPE) TRUE); /* All done */
  789. }
  790. else if(lastbyte(pdata,ra,JUMPFAR,JUMPNEAR))
  791. { /* If long jump direct */
  792. raTarget -= ra + 2; /* Make offset self-relative */
  793. fixword(pdata, raTarget); /* store fixed up value */
  794. pdata += 2;
  795. *pdata++ = NOP; /* Change base to NOPs */
  796. *pdata = NOP;
  797. return((FTYPE) TRUE); /* All done */
  798. }
  799. return(FALSE);
  800. #endif /* !O68K */
  801. }
  802. #if EXE386
  803. /*
  804. * Fix386:
  805. *
  806. * Procss a fixup for a linear-format exe.
  807. */
  808. LOCAL void NEAR Fix386()
  809. {
  810. REGISTER BYTE *pdata; /* Pointer into data record */
  811. RATYPE ra; /* Offset of location being fixed up */
  812. SNTYPE gsnTarget; /* Target segment definition number */
  813. SNTYPE gsnFrame; /* Frame segment definition number */
  814. SEGTYPE segTarget; /* Target segment order number */
  815. SATYPE saTarget; /* Target file segment number */
  816. SATYPE saFrame; /* Frame file segment number */
  817. RATYPE raTarget; /* Target offset */
  818. RATYPE vBase; /* Target virtual base address - FLAT relative */
  819. long vDist; /* Virtual distance between objects */
  820. RATYPE raTmp; /* Temporary */
  821. WORD dsa; /* Difference in sa's */
  822. DWORD dummy;
  823. RELOCATION r; /* Relocation item */
  824. WORD locType; /* Type of location to be fixed up */
  825. WORD fFlatRelative; /* TRUE if frame of pseudo group FLAT */
  826. APROPSNPTR apropSnSrc; /* Ptr to a segment record */
  827. DWORD srcFlags; /* Source segment flags */
  828. APROPNAMEPTR apropName; /* Ptr to import */
  829. DWORD align;
  830. if (vgsnCur < gsnMac)
  831. {
  832. // Get source flags - only non-debug segments
  833. apropSnSrc = (APROPSNPTR ) FetchSym(mpgsnrprop[vgsnCur], FALSE);
  834. srcFlags = apropSnSrc->as_flags;
  835. }
  836. // Check for floating-point fixups here
  837. if(fi.f_mtd == T2 &&
  838. ((mpextflags[fi.f_idx] & FFPMASK) || (mpextflags[fi.f_idx] & FFP2ND)))
  839. return; /* Ignore f.p. fixups */
  840. align = (1L << pageAlign) - 1;
  841. memset(&r, 0, sizeof(struct le_rlc));
  842. ra = vraCur + fi.f_dri; /* Get offset of fixup */
  843. objraCur = ra;
  844. vpageCur = (ra >> pageAlign) + 1; /* Set object page number */
  845. LE_SOFF(r) = (WORD) (ra & align);
  846. NR_STYPE(r) = (BYTE) fi.f_loc; /* Save fixup type */
  847. #if FALSE
  848. if (vpageCur == 1 && mpsegsa[vsegCur] == 1)
  849. fprintf(stdout, "Processing fixup: type %02x; source offset %lx (page %x offset %x)\r\n",
  850. fi.f_loc, ra, vpageCur, LE_SOFF(r));
  851. #endif
  852. pdata = &rgmi[fi.f_dri]; /* Set pointer to fixup location */
  853. locType = (WORD) (fi.f_loc & NRSRCMASK);
  854. /* Get location type */
  855. Getgsn(fi.f_mtd, fi.f_idx, &gsnTarget, &raTarget);
  856. // Check if frame of pseudo group FLAT
  857. if (ggrFlat)
  858. {
  859. // FLAT pseudo group defined
  860. if (fi.f_fmtd == KINDGROUP)
  861. fFlatRelative = (WORD) (mpgrggr[fi.f_fidx] == ggrFlat);
  862. else if (fi.f_fmtd == KINDTARGET && fi.f_mtd == KINDGROUP)
  863. fFlatRelative = (WORD) (mpgrggr[fi.f_idx] == ggrFlat);
  864. else
  865. fFlatRelative = FALSE;
  866. }
  867. else
  868. fFlatRelative = FALSE;
  869. if (fFlatRelative &&
  870. fi.f_mtd == KINDGROUP &&
  871. mpgrggr[fi.f_idx] == ggrFlat)
  872. RelocWarn(ER_badfixflat,objraCur,SNNIL, gsnTarget, raTarget);
  873. // Pseudo group FLAT is an illegal fixup target
  874. segTarget = mpgsnseg[gsnTarget]; // Get target object
  875. saTarget = mpsegsa[segTarget]; // Get target object number
  876. // Check for imports here. Depending on reference kind or place
  877. // of the reference generate the run-time relocation or treat
  878. // it as internal reference via thunk. The following cases
  879. // generate run-time relocation:
  880. //
  881. // - 16:16 pointer
  882. // - 16:16 gate pointer
  883. //
  884. // The 0:32 FLAT offset references are threated as internal references
  885. // and the thunk address for given import is used as target address
  886. // of fixup. Thunk does indirect jump via entry in Import Address
  887. // Table which is processed by the loader.
  888. if (fi.f_mtd == T2 && (mpextflags[fi.f_idx] & FIMPORT))
  889. {
  890. // If target is dynamic link
  891. if (fDebSeg)
  892. {
  893. /* Import in $$SYMBOLS */
  894. if (fi.f_loc == LOCSEGMENT)
  895. {
  896. fixword(pdata, 0); /* Install fake segment selector */
  897. }
  898. return;
  899. }
  900. else
  901. {
  902. // Emit run-time relocation if reference to imported symbol is:
  903. //
  904. // - it is NOT self-relative 32-bit FLAT offset
  905. // - it is NOT 32-bit FLAT offset
  906. // - there is no thunk allocated for this import (importing DATA)
  907. //
  908. // The self-relative 32-bit FLAT offset and 32-bit FLAT offset
  909. // fixups have their target address redirected to the Thunk Table
  910. // entry for a given imported symbol and treated as internal fixup.
  911. apropName = (APROPNAMEPTR) FetchSym(mpextprop[fi.f_idx], TRUE);
  912. if ((apropName->an_flags & IMPDATA) || (locType != LOCOFFSET32))
  913. {
  914. switch (locType)
  915. {
  916. case LOCLOBYTE: // Lo-byte (8-bit) fixup
  917. case LOCSEGMENT: // Segment (16-bit) fixup
  918. case LOCPTR: // "Pointer" (32-bit) fixup
  919. case LOCLOADOFFSET: // Loader-resolved offset fixup
  920. case LOCPTR48: // 48-bit pointer
  921. case LOCOFFSET: // Offset (16-bit) fixup
  922. OutError(ER_badfixpure32, 1 + GetPropName(mpextprop[fi.f_idx]));
  923. break;
  924. case LOCOFFSET32: // Offset (32-bit) fixup
  925. break;
  926. }
  927. // Get index to the Import Address Table
  928. LE_OBJNO(r) = (WORD) (mpsegsa[mpgsnseg[gsnImport]]);
  929. LE_IDTIDX(r) = (WORD) (apropName->an_module - 1);
  930. // Get Import Module Directory index
  931. LE_IATORD(r) = (WORD) apropName->an_entry;
  932. // Use FLAT entry
  933. /* If we have an LIDATA record */
  934. if (TYPEOF(vrectData) == LIDATA)
  935. SaveLiRel(&r); /* Copy relocation into buffer */
  936. else
  937. raTarget = SaveFixup(mpsegsa[vsegCur],vpageCur, &r);
  938. /* Record reference */
  939. return; /* Next fixup item */
  940. }
  941. }
  942. }
  943. // Internal reference (non-import) or reference to import thunk
  944. // It is assumed that we're always fixing up relative to the
  945. // physical segment or group, not the logical segment. So the
  946. // offset of the frame segment is not taken into account.
  947. if (fi.f_fmtd == KINDLOCAT)
  948. {
  949. gsnFrame = vgsnCur;
  950. }
  951. else if (fi.f_fmtd == KINDTARGET)
  952. {
  953. gsnFrame = gsnTarget;
  954. }
  955. else
  956. {
  957. Getgsn((KINDTYPE) fi.f_fmtd, fi.f_fidx, &gsnFrame, &dummy);
  958. }
  959. // The original LINK4 behavior was to fix up relative
  960. // to the physical segment. At one point it was changed
  961. // to subtract the displacement of the target segment (from
  962. // its physical segment) from the target value, if loc. type =
  963. // offset and frame and tgt. method = T0. This was no good
  964. // and the change was repealed. The /WARNFIXUP switch warns
  965. // about fixups which may be affected.
  966. if (fWarnFixup && fi.f_fmtd == KINDSEG && locType == LOCOFFSET
  967. && mpsegraFirst[mpgsnseg[gsnFrame]])
  968. RelocWarn(ER_fixsegd,ra,gsnFrame,gsnTarget,raTarget);
  969. if (fFlatRelative)
  970. {
  971. saFrame = 1; // Pseudo-group FLAT has frame of first object
  972. gsnFrame = 0;
  973. }
  974. else
  975. saFrame = mpsegsa[mpgsnseg[gsnFrame]];
  976. // Get frame's object number
  977. vBase = virtBase + mpsaBase[saTarget];
  978. // Get TARGET object virtual base address
  979. if (gsnTarget == SNNIL) // If no target info
  980. {
  981. if (locType == LOCPTR) // If "pointer" (4 byte) fixup
  982. {
  983. lastbyte(pdata,ra,CALLFARDIRECT,BREAKPOINT);
  984. // Replace long call w/ breakpoint
  985. return;
  986. }
  987. if (locType == LOCSEGMENT) return;
  988. // Next fixup if "base" fixup
  989. if (locType == LOCLOADOFFSET)
  990. locType = LOCOFFSET; // Treat as regular offset
  991. }
  992. else
  993. {
  994. if (fi.f_self) // If self-relative fixup
  995. {
  996. if (saTarget != mpsegsa[vsegCur])
  997. {
  998. if (locType == LOCOFFSET)
  999. RelocErr(ER_fixinter,ra,gsnFrame,gsnTarget,raTarget);
  1000. // 16-bit must be in same segment
  1001. if (fFlatRelative)
  1002. {
  1003. // If crossing object boundry include in raTarget
  1004. // virtual distance between objects.
  1005. //
  1006. // mpsaBase[mpsegsa[vsegCur]] --> ---+------------------+
  1007. // ^ | |
  1008. // | | |
  1009. // ra | mpsegsa[vsegCur] |
  1010. // | | |
  1011. // V | |
  1012. // ---+------------------+---
  1013. // | | ^
  1014. // . . |
  1015. // . . |
  1016. // . . |
  1017. // | | vDist
  1018. // +------------------+ |
  1019. // |
  1020. // V
  1021. // masaBase[saTarget] --> ---+------------------+---
  1022. // ^ | |
  1023. // | | |
  1024. // raTarget | saTarget |
  1025. // | | |
  1026. // V | |
  1027. // ---+------------------+
  1028. // | |
  1029. // . .
  1030. // . .
  1031. // . .
  1032. // | |
  1033. // +------------------+
  1034. //
  1035. vDist = (long) (mpsaBase[saTarget] - (mpsaBase[mpsegsa[vsegCur]] + ra));
  1036. raTarget += vDist;
  1037. }
  1038. }
  1039. else
  1040. raTarget -= ra;
  1041. if (locType == LOCOFFSET)
  1042. raTarget -= sizeof(WORD);
  1043. else if (locType == LOCOFFSET32 || locType == LOCLOADOFFSET32)
  1044. raTarget -= sizeof(DWORD);
  1045. else
  1046. raTarget -= sizeof(BYTE);
  1047. }
  1048. else if (saFrame != saTarget && !fFlatRelative)
  1049. { /* If frame, target segs differ */
  1050. /* and not FLAT frame */
  1051. if (mpgsnseg[gsnFrame] <= segLast || segTarget <= segLast)
  1052. { /* If either is non-absolute */
  1053. RelocWarn(ER_fixfrm,ra,gsnFrame,gsnTarget,raTarget);
  1054. saFrame = saTarget; /* assume target seg */
  1055. }
  1056. else
  1057. {
  1058. RelocWarn(ER_fixfrmab,ra,gsnFrame,gsnTarget,raTarget);
  1059. dsa = (WORD) (saTarget - saFrame);
  1060. raTmp = raTarget + ((dsa & 0xfff) << 4);
  1061. if(dsa >= 0x1000 || raTmp < raTarget)
  1062. {
  1063. raTarget += fi.f_disp;
  1064. #if OMF386
  1065. if ((rect & 1) && (fi.f_loc >= LOCOFFSET32))
  1066. raTarget += getdword(pdata);
  1067. else
  1068. #endif
  1069. raTarget += getword(pdata);
  1070. FixupOverflow(ra,gsnFrame,gsnTarget,raTarget);
  1071. }
  1072. raTarget = raTmp;
  1073. segTarget = mpgsnseg[gsnFrame];
  1074. /* Make target seg that of frame */
  1075. saTarget = mpsegsa[segTarget];
  1076. } /* Reset saTarget */
  1077. }
  1078. }
  1079. raTmp = raTarget;
  1080. raTarget += fi.f_disp;
  1081. if (locType >= LOCOFFSET32)
  1082. if (rect & 1)
  1083. raTarget += getdword(pdata);
  1084. else
  1085. {
  1086. RelocWarn(ER_fixtyp,ra,gsnFrame,gsnTarget,raTarget);
  1087. return;
  1088. }
  1089. else
  1090. raTarget += getword(pdata);
  1091. if (saTarget && fFlatRelative && !fi.f_self)
  1092. raTarget += vBase;
  1093. LE_FIXDAT(r) = raTarget;
  1094. if (saTarget && fFlatRelative && !fDebSeg)
  1095. {
  1096. // The FLAT-relative offset fixups need to be propagated into
  1097. // the .EXE file in the following cases:
  1098. //
  1099. // - for .EXE's - by user request
  1100. // - for .DLL's - only FLAT-relative offset fixups
  1101. if ((fKeepFixups || !IsAPLIPROG(vFlags)) &&
  1102. (locType == LOCOFFSET32 || locType == LOCLOADOFFSET32))
  1103. {
  1104. if (!fi.f_self)
  1105. {
  1106. FinishRlc(&r, saTarget, raTarget - vBase);
  1107. /* Don't pass virtual offsets */
  1108. }
  1109. #if FALSE
  1110. // Self-relative offset fixups crossing memory object
  1111. // boudry are not longer propagated to the exe for PE images
  1112. else if ((mpsegsa[vsegCur] != saTarget) && fKeepFixups)
  1113. {
  1114. FinishRlc(&r, saTarget, raTarget - vDist + sizeof(DWORD));
  1115. /* Don't pass virtual offsets */
  1116. }
  1117. #endif
  1118. }
  1119. else if (locType == LOCOFFSET)
  1120. {
  1121. if (!fi.f_self)
  1122. RelocWarn(ER_badfix16off,ra,gsnFrame,gsnTarget,raTarget);
  1123. else if (raTarget > LXIVK)
  1124. FixupOverflow(ra,gsnFrame,gsnTarget,raTarget);
  1125. /* For 16:16 alias raTarget must be <= 64k */
  1126. }
  1127. }
  1128. switch(locType) /* Switch on fixup type */
  1129. {
  1130. case LOCLOBYTE: /* 8-bit "lobyte" fixup */
  1131. raTarget = raTmp + B2W(pdata[0]) + fi.f_disp;
  1132. pdata[0] = (BYTE) raTarget;
  1133. if (raTarget >= 0x100 && fi.f_self)
  1134. FixupOverflow(ra,gsnFrame,gsnTarget,raTarget);
  1135. break;
  1136. case LOCHIBYTE: /* 8-bit "hibyte" fixup */
  1137. raTarget = raTmp + fi.f_disp;
  1138. pdata[0] = (BYTE) (B2W(pdata[0]) + (raTarget >> 8));
  1139. break;
  1140. case LOCLOADOFFSET: /* Loader-resolved offset fixup */
  1141. case LOCOFFSET: /* 16-bit "offset" fixup */
  1142. fixword(pdata, raTarget);
  1143. break;
  1144. case LOCLOADOFFSET32: /* 32-bit "offset" fixup */
  1145. case LOCOFFSET32: /* 32-bit "offset" fixup */
  1146. fixword(pdata, raTarget); /* Perform low word fixup */
  1147. pdata += 2;
  1148. raTarget >>= 16; /* Get high word */
  1149. fixword(pdata, raTarget); /* Perform fixup */
  1150. break;
  1151. case LOCSEGMENT: /* 16-bit "base" fixup */
  1152. #if SYMDEB
  1153. if(segTarget > segLast || fDebSeg)
  1154. #else
  1155. if(segTarget > segLast) /* If target segment absolute */
  1156. #endif
  1157. {
  1158. if (fDebSeg)
  1159. {
  1160. // For debug segments use logical segment number (seg)
  1161. // instead of physical segment number (sa)
  1162. saTarget = segTarget;
  1163. }
  1164. else
  1165. saTarget += getword(pdata);
  1166. /* Calculate base address */
  1167. fixword(pdata, saTarget); /* Store base address */
  1168. break; /* Done */
  1169. }
  1170. RelocErr(ER_fixbad,ra,gsnFrame,gsnTarget,raTarget);
  1171. break;
  1172. case LOCPTR48: /* 48-bit "pointer" fixup */
  1173. #if SYMDEB
  1174. if(segTarget > segLast || fDebSeg)
  1175. #else
  1176. if(segTarget > segLast) /* If target segment absolute */
  1177. #endif
  1178. {
  1179. fixword(pdata, raTarget); /* Store offset portion */
  1180. pdata += 2;
  1181. raTarget >>= WORDLN; /* Get high word */
  1182. fixword(pdata, raTarget); /* Store offset portion */
  1183. pdata += 2;
  1184. if (fDebSeg)
  1185. {
  1186. // For debug segments use logical segment number (seg)
  1187. // instead of physical segment number (sa)
  1188. saTarget = segTarget;
  1189. }
  1190. else
  1191. saTarget += getword(pdata); /* Calculate base address */
  1192. fixword(pdata, saTarget); /* Store base address */
  1193. break; /* Done */
  1194. }
  1195. RelocErr(ER_fixbad,ra,gsnFrame,gsnTarget,raTarget);
  1196. break;
  1197. case LOCPTR: /* 32-bit "pointer" fixup */
  1198. #if SYMDEB
  1199. if(segTarget > segLast || fDebSeg)
  1200. #else
  1201. if(segTarget > segLast) /* If target segment absolute */
  1202. #endif
  1203. {
  1204. fixword(pdata, raTarget); /* Store offset portion */
  1205. pdata += 2;
  1206. saTarget += getword(pdata);
  1207. /* Calculate base address */
  1208. fixword(pdata, saTarget); /* Store base address */
  1209. break; /* Done */
  1210. }
  1211. if (fFlatRelative)
  1212. RelocWarn(ER_badfix16ptr, ra, gsnFrame, gsnTarget, raTarget);
  1213. else
  1214. RelocErr(ER_fixbad,ra,gsnFrame,gsnTarget,raTarget);
  1215. break;
  1216. default: /* Unsupported fixup type */
  1217. RelocErr(ER_fixbad,ra,gsnFrame,gsnTarget,raTarget);
  1218. break;
  1219. }
  1220. }
  1221. #endif /* EXE386 */
  1222. #if OSEGEXE AND NOT EXE386
  1223. /*
  1224. * FixNew:
  1225. *
  1226. * Procss a fixup for a new-format exe.
  1227. */
  1228. void NEAR FixNew ()
  1229. {
  1230. REGISTER BYTE *pdata; /* Pointer into data record */
  1231. RATYPE ra; /* Offset of location being fixed up */
  1232. SNTYPE gsnTarget; /* Target segment definition number */
  1233. SNTYPE gsnFrame; /* Frame segment definition number */
  1234. SEGTYPE segTarget; /* Target segment order number */
  1235. SATYPE saTarget; /* Target file segment number */
  1236. SEGTYPE segFrame; /* Frame segment order number */
  1237. SATYPE saFrame; /* Frame file segment number */
  1238. RATYPE raTarget; /* Target offset */
  1239. RATYPE raTmp; /* Temporary */
  1240. WORD dsa; /* Difference in sa's */
  1241. RATYPE dummy;
  1242. RELOCATION r; /* Relocation item */
  1243. memset(&r, 0, sizeof(RELOCATION));
  1244. ra = vraCur + (RATYPE) fi.f_dri; /* Get offset of fixup */
  1245. /* Save location in record */
  1246. NR_SOFF(r) = (WORD) ra;
  1247. NR_STYPE(r) = (BYTE) fi.f_loc; /* Save fixup type */
  1248. NR_FLAGS(r) = (BYTE) (fi.f_add? NRADD: 0);
  1249. if(fi.f_mtd == T2 && (mpextflags[fi.f_idx] & FFPMASK)
  1250. #if ILINK
  1251. && !fQCIncremental // For real-mode incremental
  1252. // floating-point fixups are
  1253. // treated as normal symbol fixups
  1254. #endif
  1255. )
  1256. { /* If floating-point fixup */
  1257. if (vFlags & NEPROT && TargetOs == NE_OS2)
  1258. return; /* If protected mode only, ignore */
  1259. NR_FLAGS(r) = NRROSF | NRADD;
  1260. NR_STYPE(r) = LOCLOADOFFSET;/* No 3-byte type, so we lie */
  1261. NR_OSTYPE(r) = (mpextflags[fi.f_idx] >> FFPSHIFT) & 7;
  1262. /* Type # = ordinal in table */
  1263. NR_OSRES(r) = 0; /* Clear reserved word */
  1264. SaveFixup(mpsegsa[vsegCur],&r);
  1265. return;
  1266. }
  1267. if(fi.f_mtd == T2 && (mpextflags[fi.f_idx] & FFP2ND))
  1268. return; /* Ignore secondary f.p. fixups */
  1269. pdata = &rgmi[fi.f_dri]; /* Set pointer to fixup location */
  1270. /*
  1271. * Check for imports here.
  1272. */
  1273. if(fi.f_mtd == T2 && (mpextflags[fi.f_idx] & FIMPORT))
  1274. { /* If target is dynamic link */
  1275. if (fDebSeg)
  1276. {
  1277. /* Import in $$SYMBOLS */
  1278. if (fi.f_loc == LOCSEGMENT)
  1279. {
  1280. fixword(pdata, 0); /* Install fake segment selector */
  1281. }
  1282. return;
  1283. }
  1284. /*
  1285. * Check for invalid import fixup types: self-rel, HIBYTE.
  1286. */
  1287. if(fi.f_self)
  1288. {
  1289. RelocErr(ER_fixinter,ra,SNNIL,SNNIL,0L);
  1290. return;
  1291. }
  1292. else if(fi.f_loc == LOCHIBYTE)
  1293. {
  1294. RelocErr(ER_fixbad,ra,SNNIL,SNNIL,0L);
  1295. return;
  1296. }
  1297. else if(fi.f_loc == LOCOFFSET)/* Convert offset to runtime offset */
  1298. NR_STYPE(r) = LOCLOADOFFSET;
  1299. NR_FLAGS(r) |= (mpextflags[fi.f_idx] & FIMPORD)? NRRORD: NRRNAM;
  1300. /* Set flag */
  1301. if(fi.f_disp || fi.f_loc == LOCLOBYTE) NR_FLAGS(r) |= NRADD;
  1302. /* Additive if non-zero displacement
  1303. or lobyte */
  1304. #if M_BYTESWAP
  1305. NR_SEGNO(r) = (BYTE) mpextgsn[fi.f_idx];
  1306. NR_RES(r) = (BYTE)(mpextgsn[fi.f_idx] >> BYTELN);
  1307. #else
  1308. NR_MOD(r) = mpextgsn[fi.f_idx];
  1309. #endif
  1310. /* Get module specification */
  1311. NR_PROC(r) = (WORD) mpextra[fi.f_idx];
  1312. /* Get entry specification */
  1313. if(TYPEOF(vrectData) == LIDATA) /* If we have an LIDATA record */
  1314. {
  1315. SaveLiRel(&r); /* Copy relocation into buffer */
  1316. raTarget = 0; /* Not chained yet */
  1317. }
  1318. else raTarget = SaveFixup(mpsegsa[vsegCur],&r);
  1319. /* Record reference */
  1320. if(NR_FLAGS(r) & NRADD) raTarget = fi.f_disp;
  1321. /* If additive, install displacement */
  1322. if(fi.f_loc == LOCLOBYTE)
  1323. {
  1324. *pdata++ += (BYTE)(raTarget & 0xFF);
  1325. }
  1326. #if O68K
  1327. else if (fTBigEndian)
  1328. {
  1329. *pdata++ += (BYTE)((raTarget >> BYTELN) & 0xFF);
  1330. *pdata += (BYTE)(raTarget & 0xFF);
  1331. }
  1332. #endif /* O68K */
  1333. else
  1334. {
  1335. addword((BYTE *)pdata, (WORD)raTarget);
  1336. }
  1337. return; /* Next fixup item */
  1338. }
  1339. NR_FLAGS(r) |= NRRINT; /* Internal reference (non-import) */
  1340. Getgsn(fi.f_mtd, fi.f_idx, &gsnTarget, &raTarget);
  1341. /*
  1342. * It is assumed that we're always fixing up relative to the
  1343. * physical segment or group, not the logical segment. So the
  1344. * offset of the frame segment is not taken into account.
  1345. */
  1346. if (fi.f_fmtd == KINDLOCAT)
  1347. {
  1348. gsnFrame = vgsnCur;
  1349. }
  1350. else if (fi.f_fmtd == KINDTARGET)
  1351. {
  1352. gsnFrame = gsnTarget;
  1353. }
  1354. else
  1355. {
  1356. Getgsn(fi.f_fmtd, fi.f_fidx, &gsnFrame, &dummy);
  1357. }
  1358. segTarget = mpgsnseg[gsnTarget]; /* Get target segment */
  1359. saTarget = mpsegsa[segTarget]; /* Get target file segment number */
  1360. segFrame = mpgsnseg[gsnFrame]; /* Get frame segment */
  1361. saFrame = mpsegsa[segFrame]; /* Get frame's file segment number */
  1362. /*
  1363. * The original LINK4 behavior was to fix up relative
  1364. * to the physical segment. At one point it was changed
  1365. * to subtract the displacement of the target segment (from
  1366. * its physical segment) from the target value, if loc. type =
  1367. * offset and frame and tgt. method = T0. This was no good
  1368. * and the change was repealed. The /WARNFIXUP switch warns
  1369. * about fixups which may be affected.
  1370. */
  1371. if(fWarnFixup && fi.f_fmtd == KINDSEG && fi.f_loc == LOCOFFSET
  1372. && mpsegraFirst[segFrame])
  1373. RelocWarn(ER_fixsegd,ra,gsnFrame,gsnTarget,raTarget);
  1374. #if O68K
  1375. /* 68k code does not permit segment fixups of any kind. */
  1376. if (f68k && !fDebSeg && ((1 << fi.f_loc) & ((1 << LOCSEGMENT) |
  1377. (1 << LOCPTR) | (1 << LOCPTR48))) != 0)
  1378. {
  1379. RelocErr(ER_fixbad, ra, gsnFrame, gsnTarget, raTarget + fi.f_disp);
  1380. return;
  1381. }
  1382. #endif /* O68K */
  1383. if(gsnTarget == SNNIL) /* If no target info */
  1384. {
  1385. if(fi.f_loc == LOCPTR) /* If "pointer" (4 byte) fixup */
  1386. {
  1387. lastbyte(pdata,ra,CALLFARDIRECT,BREAKPOINT);
  1388. /* Replace long call w/ breakpoint */
  1389. return;
  1390. }
  1391. if(fi.f_loc == LOCSEGMENT) return;
  1392. /* Next fixup if "base" fixup */
  1393. if(fi.f_loc == LOCLOADOFFSET)
  1394. fi.f_loc = LOCOFFSET; /* Treat as regular offset */
  1395. }
  1396. else
  1397. {
  1398. if(fi.f_self) /* If self-relative fixup */
  1399. {
  1400. #if O68K
  1401. if (iMacType != MAC_NONE)
  1402. {
  1403. switch (fi.f_loc)
  1404. {
  1405. case LOCOFFSET:
  1406. if (saTarget != mpsegsa[vsegCur])
  1407. {
  1408. NR_STYPE(r) = (BYTE)((NR_STYPE(r) & ~NRSTYP) | NRSOFF);
  1409. fi.f_loc = LOCLOADOFFSET;
  1410. }
  1411. else raTarget -= ra;
  1412. break;
  1413. case LOCOFFSET32:
  1414. if (saTarget != mpsegsa[vsegCur])
  1415. fi.f_loc = LOCLOADOFFSET32;
  1416. else raTarget -= ra - 2;
  1417. break;
  1418. }
  1419. }
  1420. else
  1421. #endif /* O68K */
  1422. {
  1423. if (saTarget != mpsegsa[vsegCur])
  1424. RelocErr(ER_fixinter,ra,gsnFrame,gsnTarget,raTarget);
  1425. /* Must be in same segment */
  1426. if(fi.f_loc == LOCOFFSET)
  1427. raTarget = raTarget - ra - 2;
  1428. #if OMF386
  1429. else if(fi.f_loc == LOCOFFSET32)
  1430. raTarget = raTarget - ra - 4;
  1431. #endif
  1432. else raTarget = raTarget - ra - 1;
  1433. }
  1434. }
  1435. else if (saFrame != saTarget)
  1436. { /* If frame, target segs differ */
  1437. if (segFrame <= segLast || segTarget <= segLast)
  1438. { /* If either is non-absolute */
  1439. RelocWarn(ER_fixfrm, ra, gsnFrame, gsnTarget, raTarget);
  1440. }
  1441. else
  1442. {
  1443. RelocWarn(ER_fixfrmab,ra,gsnFrame,gsnTarget,raTarget);
  1444. dsa = saTarget - saFrame;
  1445. raTmp = raTarget + ((dsa & 0xfff) << 4);
  1446. if(dsa >= 0x1000 || raTmp < raTarget)
  1447. {
  1448. raTarget += fi.f_disp;
  1449. #if OMF386
  1450. if ((rect & 1) && (fi.f_loc >= LOCOFFSET32))
  1451. raTarget += GetFixupDword(pdata);
  1452. else
  1453. #endif
  1454. raTarget += GetFixupWord(pdata);
  1455. FixupOverflow(ra,gsnFrame,gsnTarget,raTarget);
  1456. }
  1457. raTarget = raTmp;
  1458. }
  1459. segTarget = segFrame; /* Make target seg that of frame */
  1460. saTarget = saFrame; /* Reset saTarget */
  1461. }
  1462. }
  1463. raTmp = raTarget;
  1464. raTarget += fi.f_disp;
  1465. #if OMF386
  1466. if ((rect & 1) && (fi.f_loc >= LOCOFFSET32))
  1467. raTarget += GetFixupDword(pdata);
  1468. else
  1469. #endif
  1470. raTarget += GetFixupWord(pdata);
  1471. switch(fi.f_loc) /* Switch on fixup type */
  1472. {
  1473. case LOCLOBYTE: /* 8-bit "lobyte" fixup */
  1474. raTarget = raTmp + B2W(pdata[0]) + fi.f_disp;
  1475. pdata[0] = (BYTE) raTarget;
  1476. if(raTarget >= 0x100 && fi.f_self)
  1477. FixupOverflow(ra,gsnFrame,gsnTarget,raTarget);
  1478. break;
  1479. case LOCHIBYTE: /* 8-bit "hibyte" fixup */
  1480. raTarget = raTmp + fi.f_disp;
  1481. pdata[0] = (BYTE) (B2W(pdata[0]) + (raTarget >> 8));
  1482. break;
  1483. case LOCLOADOFFSET: /* Loader-resolved offset fixup */
  1484. NR_FLAGS(r) &= ~NRADD; /* Not additive */
  1485. if ((TargetOs == NE_WINDOWS && !(vFlags & NEPROT))
  1486. #if O68K
  1487. || iMacType != MAC_NONE
  1488. #endif /* O68K */
  1489. )
  1490. raTarget = FinishRlc(&r, saTarget, raTarget);
  1491. /* Finish relocation record */
  1492. #if O68K
  1493. if (fTBigEndian)
  1494. {
  1495. *pdata++ = (BYTE)((raTarget >> BYTELN) & 0xFF);
  1496. *pdata = (BYTE)(raTarget & 0xFF);
  1497. }
  1498. else
  1499. #endif /* O68K */
  1500. {
  1501. fixword(pdata, raTarget);
  1502. }
  1503. /* Install old head of chain */
  1504. break;
  1505. case LOCOFFSET: /* 16-bit "offset" fixup */
  1506. #if O68K
  1507. /* For 68K, LOCOFFSET is a signed 16-bit offset fixup. */
  1508. if (f68k &&
  1509. (raTarget & ~0x7FFF) != 0 && (raTarget & ~0x7FFF) != ~0x7FFF)
  1510. FixupOverflow(ra,gsnFrame,gsnTarget,raTarget);
  1511. #endif /* O68K */
  1512. #if O68K
  1513. if (fTBigEndian)
  1514. {
  1515. *pdata++ = (BYTE)((raTarget >> BYTELN) & 0xFF);
  1516. *pdata = (BYTE)(raTarget & 0xFF);
  1517. }
  1518. else
  1519. #endif /* O68K */
  1520. {
  1521. fixword(pdata, raTarget);
  1522. }
  1523. /* Install old head of chain */
  1524. break;
  1525. #if OMF386
  1526. case LOCLOADOFFSET32: /* 32-bit "offset" fixup */
  1527. if(!(rect & 1)) break; /* Not 386 extension */
  1528. NR_FLAGS(r) &= ~NRADD; /* Not additive */
  1529. NR_STYPE(r) = (BYTE) ((NR_STYPE(r) & ~NRSTYP) | NROFF32);
  1530. raTarget = FinishRlc(&r,saTarget,raTarget);
  1531. /* Finish relocation record */
  1532. case LOCOFFSET32: /* 32-bit "offset" fixup */
  1533. #if O68K
  1534. if (fTBigEndian)
  1535. {
  1536. *pdata++ = (BYTE)((raTarget >> (BYTELN + WORDLN)) & 0xFF);
  1537. *pdata++ = (BYTE)((raTarget >> WORDLN) & 0xFF);
  1538. *pdata++ = (BYTE)((raTarget >> BYTELN) & 0xFF);
  1539. *pdata = (BYTE)(raTarget & 0xFF);
  1540. }
  1541. else
  1542. #endif /* O68K */
  1543. {
  1544. fixdword(pdata, raTarget);
  1545. }
  1546. /* Perform fixup */
  1547. break;
  1548. #endif /* OMF386 */
  1549. case LOCSEGMENT: /* 16-bit "base" fixup */
  1550. #if SYMDEB
  1551. if(segTarget > segLast || fDebSeg)
  1552. #else
  1553. if(segTarget > segLast) /* If target segment absolute */
  1554. #endif
  1555. {
  1556. if (fDebSeg)
  1557. {
  1558. // For debug segments use logical segment number (seg)
  1559. // instead of physical segment number (sa)
  1560. saTarget = segTarget;
  1561. }
  1562. else
  1563. saTarget += getword(pdata);
  1564. /* Calculate base address */
  1565. fixword(pdata, saTarget); /* Store base address */
  1566. break; /* Done */
  1567. }
  1568. /*
  1569. * Treat the displacment as an ordinal increment to saTarget,
  1570. * for huge model. It would seem logical to include the primary
  1571. * displacment, f_disp, but MASM has a quirk: an instruction of
  1572. * the form "mov ax,ASEGMENT" generates a fixup with f_disp equal
  1573. * to the length of the segment even though "mov ax,seg
  1574. * ASEGMENT" causes f_disp to be 0! So for compatibility we
  1575. * ignore f_disp.
  1576. * Then force the fixup to non-additive since the secondary
  1577. * displacement has been added to saTarget.
  1578. */
  1579. if((saTarget += getword(pdata)) >= saMac)
  1580. FixupOverflow(ra,gsnFrame,gsnTarget,0L);
  1581. NR_FLAGS(r) &= ~NRADD;
  1582. #if FALSE
  1583. /*
  1584. * Too early to decide here. We don't know if a
  1585. * base fixup will require call-gate and if it
  1586. * does then we need the actual offset in call-gate.
  1587. *
  1588. * Forcing the offset to zero for base fixups:
  1589. * PRO's
  1590. * 1. Fewer fixup records in the .EXE.
  1591. * 2. No more than n dummy entries in the
  1592. * Entry Table for a program of n segments
  1593. * in the WORST case.
  1594. * CON's
  1595. * 1. Approximately n dummy entries in the
  1596. * Entry Table for a program of n segments
  1597. * in the AVERAGE case.
  1598. */
  1599. raTarget = FinishRlc(&r,saTarget,0L);
  1600. /* Finish relocation record */
  1601. #else
  1602. /*
  1603. * Leaving the offset alone for base fixups:
  1604. * PRO's
  1605. * 1. No more than 1 or 2 dummy entries in the
  1606. * Entry Table for a program of n segments
  1607. * in the AVERAGE case.
  1608. * CON's
  1609. * 1. More fixup records in the .EXE.
  1610. * 2. Number of dummy entries in the Entry Table
  1611. * only bounded by the maximum allowable size
  1612. * of the Entry Table in the WORST CASE.
  1613. */
  1614. raTarget = FinishRlc(&r,saTarget,raTarget);
  1615. /* Finish relocation record */
  1616. #endif
  1617. fixword(pdata, raTarget);
  1618. /* Install old head of chain */
  1619. break;
  1620. #if OMF386
  1621. case LOCPTR48: /* 48-bit "pointer" fixup */
  1622. if(!(rect & 1)) break; /* Not 386 extension */
  1623. NR_STYPE(r) = (BYTE) ((NR_STYPE(r) & ~NRSTYP) | NRPTR48);
  1624. fixword(pdata, raTarget);
  1625. pdata += 2;
  1626. raTarget >>= 16; /* Get high word, fall through ... */
  1627. #endif
  1628. case LOCPTR: /* 32-bit "pointer" fixup */
  1629. #if SYMDEB
  1630. if(segTarget > segLast || fDebSeg)
  1631. #else
  1632. if(segTarget > segLast) /* If target segment absolute */
  1633. #endif
  1634. {
  1635. fixword(pdata, raTarget);
  1636. pdata += 2;
  1637. /* Store offset portion */
  1638. if (fDebSeg)
  1639. {
  1640. // For debug segments use logical segment number (seg)
  1641. // instead of physical segment number (sa)
  1642. saTarget = segTarget;
  1643. }
  1644. else
  1645. saTarget += getword(pdata);
  1646. /* Calculate base address */
  1647. fixword(pdata, saTarget); /* Store base address */
  1648. break; /* Done */
  1649. }
  1650. if(fFarCallTrans && saTarget == mpsegsa[vsegCur]
  1651. && (mpsaflags[saTarget] & NSTYPE) == NSCODE)
  1652. { /* If intrasegment fixup */
  1653. if(TransFAR(pdata,ra,raTarget))
  1654. break;
  1655. }
  1656. /*
  1657. * Treat the high word at the location as an increment to the
  1658. * target segment index. Check for overflow and clear the high
  1659. * word at the location. Force fixup to be non-additive because
  1660. * the secondary displacement has already been added to raTarget.
  1661. */
  1662. if((saTarget += getword(pdata + 2)) >= saMac)
  1663. FixupOverflow(ra,gsnFrame,gsnTarget,raTarget);
  1664. pdata[2] = pdata[3] = 0;
  1665. NR_FLAGS(r) &= ~NRADD;
  1666. #if NOT QCLINK
  1667. if (fOptimizeFixups)
  1668. {
  1669. // Check if pointer fixup (16:16 or 16:32) can be split into
  1670. // linker resolved offset fixup (16 or 32 bit) and loader
  1671. // resolved base (selector) fixup.
  1672. if (!CallGateRequired(saTarget))
  1673. {
  1674. fixword(pdata, raTarget); /* Store offset portion */
  1675. pdata += 2;
  1676. NR_STYPE(r) = (BYTE) LOCSEGMENT;
  1677. if (fi.f_loc == LOCPTR48)
  1678. NR_SOFF(r) += 4;
  1679. else
  1680. NR_SOFF(r) += 2;
  1681. raTarget = 0L;
  1682. }
  1683. }
  1684. #endif
  1685. raTarget = FinishRlc(&r,saTarget,raTarget);
  1686. /* Finish relocation record */
  1687. fixword(pdata, raTarget);
  1688. /* Install old head of chain */
  1689. break;
  1690. default: /* Unsupported fixup type */
  1691. RelocErr(ER_fixbad,ra,gsnFrame,gsnTarget,raTarget);
  1692. break;
  1693. }
  1694. }
  1695. #ifdef LEGO
  1696. /*
  1697. * FixNewKeep:
  1698. *
  1699. * Process a fixup for a new-format exe.
  1700. */
  1701. void NEAR FixNewKeep()
  1702. {
  1703. BYTE *pdata; /* Pointer into data record */
  1704. RATYPE ra; /* Offset of location being fixed up */
  1705. SNTYPE gsnTarget; /* Target segment definition number */
  1706. SNTYPE gsnFrame; /* Frame segment definition number */
  1707. SEGTYPE segTarget; /* Target segment order number */
  1708. SATYPE saTarget; /* Target file segment number */
  1709. SEGTYPE segFrame; /* Frame segment order number */
  1710. SATYPE saFrame; /* Frame file segment number */
  1711. RATYPE raTarget; /* Target offset */
  1712. RATYPE raTmp; /* Temporary */
  1713. WORD dsa; /* Difference in sa's */
  1714. RATYPE dummy;
  1715. RELOCATION r; /* Relocation item */
  1716. memset(&r, 0, sizeof(RELOCATION));
  1717. ra = vraCur + (RATYPE) fi.f_dri; /* Get offset of fixup */
  1718. /* Save location in record */
  1719. NR_SOFF(r) = (WORD) ra;
  1720. NR_STYPE(r) = (BYTE) fi.f_loc; /* Save fixup type */
  1721. NR_FLAGS(r) = (BYTE) (fi.f_add ? NRADD : 0);
  1722. pdata = &rgmi[fi.f_dri]; /* Set pointer to fixup location */
  1723. if (fi.f_mtd == T2)
  1724. {
  1725. /* The target is an external symbol */
  1726. if (mpextflags[fi.f_idx] & FFPMASK)
  1727. {
  1728. /* This is a floating point fixup */
  1729. if (TargetOs == NE_OS2)
  1730. {
  1731. /* Floating point fixups are ignored in prot mode OS/2 */
  1732. return;
  1733. }
  1734. /* Emit an OS fixup. The loader will deal with these. */
  1735. NR_STYPE(r) = LOCLOADOFFSET;
  1736. NR_FLAGS(r) = NRROSF | NRADD;
  1737. NR_OSTYPE(r) = (mpextflags[fi.f_idx] >> FFPSHIFT) & 7;
  1738. NR_OSRES(r) = 0;
  1739. SaveFixup(mpsegsa[vsegCur], &r);
  1740. return;
  1741. }
  1742. if (mpextflags[fi.f_idx] & FFP2ND)
  1743. {
  1744. /* This is a secondary floating point fixup. */
  1745. /* These are always ignored. */
  1746. return;
  1747. }
  1748. /*
  1749. * Check for imports here.
  1750. */
  1751. if (mpextflags[fi.f_idx] & FIMPORT)
  1752. { /* If target is dynamic link */
  1753. if (fDebSeg)
  1754. {
  1755. /* Import in $$SYMBOLS */
  1756. if (fi.f_loc == LOCSEGMENT)
  1757. {
  1758. *pdata++ = 0; /* Install fake segment selector */
  1759. *pdata++ = 0;
  1760. }
  1761. return;
  1762. }
  1763. /*
  1764. * Check for invalid import fixup types: self-rel, HIBYTE.
  1765. */
  1766. if (fi.f_self)
  1767. {
  1768. RelocErr(ER_fixinter, ra, SNNIL, SNNIL, 0L);
  1769. return;
  1770. }
  1771. if (fi.f_loc == LOCHIBYTE)
  1772. {
  1773. RelocErr(ER_fixbad, ra, SNNIL, SNNIL, 0L);
  1774. return;
  1775. }
  1776. /* Convert offset to runtime offset */
  1777. if (fi.f_loc == LOCOFFSET)
  1778. NR_STYPE(r) = LOCLOADOFFSET;
  1779. NR_FLAGS(r) |= (mpextflags[fi.f_idx] & FIMPORD) ? NRRORD : NRRNAM;
  1780. if (fi.f_disp || fi.f_loc == LOCLOBYTE)
  1781. NR_FLAGS(r) |= NRADD; /* Additive if non-zero displacement
  1782. or lobyte */
  1783. #if M_BYTESWAP
  1784. NR_SEGNO(r) = (BYTE) mpextgsn[fi.f_idx];
  1785. NR_RES(r) = (BYTE)(mpextgsn[fi.f_idx] >> BYTELN);
  1786. #else
  1787. NR_MOD(r) = mpextgsn[fi.f_idx];
  1788. #endif
  1789. /* Get module specification */
  1790. NR_PROC(r) = (WORD) mpextra[fi.f_idx];
  1791. /* Get entry specification */
  1792. if (TYPEOF(vrectData) == LIDATA)/* If we have an LIDATA record */
  1793. {
  1794. SaveLiRel(&r); /* Copy relocation into buffer */
  1795. raTarget = 0; /* Not chained yet */
  1796. }
  1797. else
  1798. {
  1799. raTarget = SaveFixup(mpsegsa[vsegCur], &r);
  1800. }
  1801. /* Record reference */
  1802. if (NR_FLAGS(r) & NRADD) /* If additive, install displacement */
  1803. raTarget = fi.f_disp;
  1804. if (fi.f_loc == LOCLOBYTE)
  1805. {
  1806. *pdata++ += (BYTE)(raTarget & 0xFF);
  1807. }
  1808. else
  1809. {
  1810. addword((BYTE *)pdata, (WORD)raTarget);
  1811. }
  1812. return; /* Next fixup item */
  1813. }
  1814. }
  1815. NR_FLAGS(r) |= NRRINT; /* Internal reference (non-import) */
  1816. Getgsn(fi.f_mtd, fi.f_idx, &gsnTarget, &raTarget);
  1817. /*
  1818. * It is assumed that we're always fixing up relative to the
  1819. * physical segment or group, not the logical segment. So the
  1820. * offset of the frame segment is not taken into account.
  1821. */
  1822. if (fi.f_fmtd == KINDLOCAT)
  1823. {
  1824. gsnFrame = vgsnCur;
  1825. }
  1826. else if (fi.f_fmtd == KINDTARGET)
  1827. {
  1828. gsnFrame = gsnTarget;
  1829. }
  1830. else
  1831. {
  1832. Getgsn(fi.f_fmtd, fi.f_fidx, &gsnFrame, &dummy);
  1833. }
  1834. segTarget = mpgsnseg[gsnTarget]; /* Get target segment */
  1835. saTarget = mpsegsa[segTarget]; /* Get target file segment number */
  1836. segFrame = mpgsnseg[gsnFrame]; /* Get frame segment */
  1837. saFrame = mpsegsa[segFrame]; /* Get frame's file segment number */
  1838. /*
  1839. * The original LINK4 behavior was to fix up relative
  1840. * to the physical segment. At one point it was changed
  1841. * to subtract the displacement of the target segment (from
  1842. * its physical segment) from the target value, if loc. type =
  1843. * offset and frame and tgt. method = T0. This was no good
  1844. * and the change was repealed. The /WARNFIXUP switch warns
  1845. * about fixups which may be affected.
  1846. */
  1847. if (fWarnFixup &&
  1848. (fi.f_fmtd == KINDSEG) &&
  1849. (fi.f_loc == LOCOFFSET) &&
  1850. mpsegraFirst[segFrame])
  1851. RelocWarn(ER_fixsegd, ra, gsnFrame, gsnTarget, raTarget);
  1852. if (gsnTarget == SNNIL) /* If no target info */
  1853. {
  1854. if (fi.f_loc == LOCPTR) /* If "pointer" (4 byte) fixup */
  1855. {
  1856. lastbyte(pdata, ra, CALLFARDIRECT, BREAKPOINT);
  1857. /* Replace long call w/ breakpoint */
  1858. return;
  1859. }
  1860. if (fi.f_loc == LOCSEGMENT) /* Next fixup if "base" fixup */
  1861. return;
  1862. if (fi.f_loc == LOCLOADOFFSET)
  1863. fi.f_loc = LOCOFFSET; /* Treat as regular offset */
  1864. }
  1865. else
  1866. {
  1867. if (fi.f_self) /* If self-relative fixup */
  1868. {
  1869. if (saTarget != mpsegsa[vsegCur])
  1870. {
  1871. RelocErr(ER_fixinter, ra, gsnFrame, gsnTarget, raTarget);
  1872. return;
  1873. }
  1874. /* Must be in same segment */
  1875. if (fi.f_loc == LOCOFFSET)
  1876. raTarget -= ra + sizeof(WORD);
  1877. #if OMF386
  1878. else if (fi.f_loc == LOCOFFSET32)
  1879. raTarget -= ra + sizeof(DWORD);
  1880. #endif /* OMF386 */
  1881. else
  1882. raTarget -= ra + sizeof(BYTE);
  1883. }
  1884. else if (saFrame != saTarget)
  1885. {
  1886. /* If frame, target segs differ */
  1887. if (segFrame <= segLast || segTarget <= segLast)
  1888. {
  1889. /* If either is non-absolute */
  1890. RelocWarn(ER_fixfrm, ra, gsnFrame, gsnTarget, raTarget);
  1891. }
  1892. else
  1893. {
  1894. RelocWarn(ER_fixfrmab, ra, gsnFrame, gsnTarget, raTarget);
  1895. dsa = saTarget - saFrame;
  1896. raTmp = raTarget + ((dsa & 0xfff) << 4);
  1897. if (dsa >= 0x1000 || raTmp < raTarget)
  1898. {
  1899. raTarget += fi.f_disp;
  1900. #if OMF386
  1901. if ((rect & 1) && (fi.f_loc >= LOCOFFSET32))
  1902. raTarget += GetFixupDword(pdata);
  1903. else
  1904. #endif /* OMF386 */
  1905. raTarget += GetFixupWord(pdata);
  1906. FixupOverflow(ra, gsnFrame, gsnTarget, raTarget);
  1907. }
  1908. raTarget = raTmp;
  1909. }
  1910. segTarget = segFrame; /* Make target seg that of frame */
  1911. saTarget = saFrame; /* Reset saTarget */
  1912. }
  1913. }
  1914. raTmp = raTarget;
  1915. raTarget += fi.f_disp;
  1916. if (fDebSeg || fi.f_self)
  1917. {
  1918. /* If fKeepFixups is TRUE, the value stored at the fixed up */
  1919. /* location is not added to the target address. The fixup will */
  1920. /* be emitted as an additive fixup and the loader will add in */
  1921. /* the bias.
  1922. /* If the fixup is being applied to a debug segment, the offset is */
  1923. /* added because these fixups aren't handled by the loader. In */
  1924. /* other words, they can not be kept. */
  1925. /* If the fixup is being applied is self-relative, the offset is */
  1926. /* added because the loaded doesn't handle self-relative fixups. */
  1927. /* While the fixed up word would have the correct value, the target */
  1928. /* of the fixup would be artifical. */
  1929. #if OMF386
  1930. if ((rect & 1) && (fi.f_loc >= LOCOFFSET32))
  1931. raTarget += GetFixupDword(pdata);
  1932. else
  1933. #endif /* OMF386 */
  1934. raTarget += GetFixupWord(pdata);
  1935. }
  1936. switch (fi.f_loc) /* Switch on fixup type */
  1937. {
  1938. case LOCLOBYTE: /* 8-bit "lobyte" fixup */
  1939. raTarget = raTmp + B2W(pdata[0]) + fi.f_disp;
  1940. pdata[0] = (BYTE) raTarget;
  1941. if (raTarget >= 0x100 && fi.f_self)
  1942. FixupOverflow(ra, gsnFrame, gsnTarget, raTarget);
  1943. break;
  1944. case LOCHIBYTE: /* 8-bit "hibyte" fixup */
  1945. raTarget = raTmp + fi.f_disp;
  1946. pdata[0] = (BYTE) (B2W(pdata[0]) + (raTarget >> 8));
  1947. break;
  1948. case LOCLOADOFFSET: /* Loader-resolved offset fixup */
  1949. /* There are no LOCLOADOFFSET fixups that are */
  1950. /* self-relative or applied to debug segments. */
  1951. /* Force non-external fixups to be additive. The C */
  1952. /* compiler may emit a BAKPAT to a fixed up word. If the */
  1953. /* fixup is chained the BAKPAT will corrupt the chain. */
  1954. /* This does not occur when the target is external. We */
  1955. /* special case this so that the number of fixups is */
  1956. /* reduced. */
  1957. if (fi.f_mtd != T2)
  1958. NR_FLAGS(r) |= NRADD;
  1959. raTarget = FinishRlc(&r, saTarget, raTarget);
  1960. if (NR_FLAGS(r) & NRADD)
  1961. break;
  1962. fixword(pdata, raTarget);
  1963. break;
  1964. case LOCOFFSET: /* 16-bit "offset" fixup */
  1965. if (!fDebSeg && !fi.f_self)
  1966. {
  1967. /* Force non-external fixups to be additive. The C */
  1968. /* compiler may emit a BAKPAT to a fixed up word. If the */
  1969. /* fixup is chained the BAKPAT will corrupt the chain. */
  1970. /* This does not occur when the target is external. We */
  1971. /* special case this so that the number of fixups is */
  1972. /* reduced. */
  1973. if (fi.f_mtd != T2)
  1974. NR_FLAGS(r) |= NRADD;
  1975. NR_STYPE(r) = LOCLOADOFFSET;
  1976. raTarget = FinishRlc(&r, saTarget, raTarget);
  1977. if (NR_FLAGS(r) & NRADD)
  1978. break;
  1979. }
  1980. fixword(pdata, raTarget);
  1981. break;
  1982. case LOCSEGMENT: /* 16-bit "base" fixup */
  1983. #if SYMDEB
  1984. if (segTarget > segLast || fDebSeg)
  1985. #else
  1986. if (segTarget > segLast) /* If target segment absolute */
  1987. #endif
  1988. {
  1989. if (fDebSeg)
  1990. {
  1991. // For debug segments use logical segment number (seg)
  1992. // instead of physical segment number (sa)
  1993. saTarget = segTarget;
  1994. }
  1995. else
  1996. {
  1997. saTarget += getword(pdata);
  1998. }
  1999. /* Store base address */
  2000. fixword(pdata, saTarget);
  2001. break;
  2002. }
  2003. raTarget = FinishRlc(&r, saTarget, raTarget);
  2004. if (NR_FLAGS(r) & NRADD)
  2005. break;
  2006. fixword(pdata, raTarget);
  2007. break;
  2008. case LOCPTR: /* 32-bit "pointer" fixup */
  2009. #if SYMDEB
  2010. if (segTarget > segLast || fDebSeg)
  2011. #else
  2012. if (segTarget > segLast) /* If target segment absolute */
  2013. #endif
  2014. {
  2015. /* Store offset portion */
  2016. fixword(pdata, raTarget);
  2017. pdata += 2;
  2018. if (fDebSeg)
  2019. {
  2020. // For debug segments use logical segment number (seg)
  2021. // instead of physical segment number (sa)
  2022. saTarget = segTarget;
  2023. }
  2024. else
  2025. {
  2026. saTarget += getword(pdata);
  2027. }
  2028. /* Store base address */
  2029. fixword(pdata, saTarget);
  2030. break;
  2031. }
  2032. /* Force non-external fixups to be additive. The C */
  2033. /* compiler may emit a BAKPAT to a fixed up word. If the */
  2034. /* fixup is chained the BAKPAT will corrupt the chain. */
  2035. /* This does not occur when the target is external. We */
  2036. /* special case this so that the number of fixups is */
  2037. /* reduced. */
  2038. if (fi.f_mtd != T2)
  2039. NR_FLAGS(r) |= NRADD;
  2040. /* Check segment to see if fixup must be additive */
  2041. else if (getword(pdata + 2) != 0)
  2042. NR_FLAGS(r) |= NRADD;
  2043. raTarget = FinishRlc(&r, saTarget, raTarget);
  2044. if (NR_FLAGS(r) & NRADD)
  2045. break;
  2046. fixword(pdata, raTarget);
  2047. break;
  2048. #if OMF386
  2049. /* NOTE: Support for 32 bit fixups in 16 bit images is a joke. */
  2050. /* NOTE: The Windows loader doesn't understand these. We fake */
  2051. /* NOTE: out Windows by converting these fixups to NRSOFF type. */
  2052. /* NOTE: The Chicago loader now understands NROFF32 fixups so */
  2053. /* NOTE: we now use this type. This will generate an executable */
  2054. /* NOTE: that doesn't work under Windows 3.x. Oh Well! */
  2055. case LOCLOADOFFSET32: /* 32-bit Loader-resolved offset fixup */
  2056. /* There are no LOCLOADOFFSET32 fixups that are */
  2057. /* self-relative or applied to debug segments. */
  2058. /* Force non-external fixups to be additive. The C */
  2059. /* compiler may emit a BAKPAT to a fixed up word. If the */
  2060. /* fixup is chained the BAKPAT will corrupt the chain. */
  2061. /* This does not occur when the target is external. We */
  2062. /* special case this so that the number of fixups is */
  2063. /* reduced. */
  2064. if (fi.f_mtd != T2)
  2065. NR_FLAGS(r) |= NRADD;
  2066. if (raTarget > 0xffff)
  2067. RelocErr(ER_fixbad, ra, gsnFrame, gsnTarget, raTarget);
  2068. NR_STYPE(r) = NROFF32;
  2069. raTarget = FinishRlc(&r, saTarget, raTarget);
  2070. if (NR_FLAGS(r) & NRADD)
  2071. break;
  2072. fixdword(pdata, raTarget);
  2073. break;
  2074. case LOCOFFSET32: /* 32-bit "offset" fixup */
  2075. if (!fDebSeg && !fi.f_self)
  2076. {
  2077. /* Force non-external fixups to be additive. The C */
  2078. /* compiler may emit a BAKPAT to a fixed up word. If the */
  2079. /* fixup is chained the BAKPAT will corrupt the chain. */
  2080. /* This does not occur when the target is external. We */
  2081. /* special case this so that the number of fixups is */
  2082. /* reduced. */
  2083. if (fi.f_mtd != T2)
  2084. NR_FLAGS(r) |= NRADD;
  2085. if (raTarget > 0xffff)
  2086. RelocErr(ER_fixbad, ra, gsnFrame, gsnTarget, raTarget);
  2087. NR_STYPE(r) = NROFF32;
  2088. raTarget = FinishRlc(&r, saTarget, raTarget);
  2089. if (NR_FLAGS(r) & NRADD)
  2090. break;
  2091. }
  2092. fixdword(pdata, raTarget);
  2093. break;
  2094. case LOCPTR48: /* 48-bit "pointer" fixup */
  2095. #if SYMDEB
  2096. if (segTarget > segLast || fDebSeg)
  2097. #else
  2098. if (segTarget > segLast) /* If target segment absolute */
  2099. #endif
  2100. {
  2101. /* Store offset portion */
  2102. fixdword(pdata, raTarget);
  2103. pdata += 4;
  2104. if (fDebSeg)
  2105. {
  2106. // For debug segments use logical segment number (seg)
  2107. // instead of physical segment number (sa)
  2108. saTarget = segTarget;
  2109. }
  2110. else
  2111. {
  2112. saTarget += getword(pdata);
  2113. }
  2114. /* Store base address */
  2115. fixword(pdata, saTarget);
  2116. break;
  2117. }
  2118. /* Force non-external fixups to be additive. The C */
  2119. /* compiler may emit a BAKPAT to a fixed up word. If the */
  2120. /* fixup is chained the BAKPAT will corrupt the chain. */
  2121. /* This does not occur when the target is external. We */
  2122. /* special case this so that the number of fixups is */
  2123. /* reduced. */
  2124. if (fi.f_mtd != T2)
  2125. NR_FLAGS(r) |= NRADD;
  2126. /* Check segment to see if fixup must be additive */
  2127. else if (getword(pdata + 4) != 0)
  2128. NR_FLAGS(r) |= NRADD;
  2129. NR_STYPE(r) = NRPTR48;
  2130. raTarget = FinishRlc(&r, saTarget, raTarget);
  2131. if (NR_FLAGS(r) & NRADD)
  2132. break;
  2133. fixdword(pdata, raTarget);
  2134. break;
  2135. #endif /* OMF386 */
  2136. default: /* Unsupported fixup type */
  2137. RelocErr(ER_fixbad, ra, gsnFrame, gsnTarget, raTarget);
  2138. break;
  2139. }
  2140. }
  2141. #endif /* LEGO */
  2142. #if O68K
  2143. /*
  2144. * GetFixupWord:
  2145. *
  2146. * Gets a word depending of the value of fTBigEndian and fDebSeg
  2147. */
  2148. LOCAL WORD NEAR GetFixupWord (pdata)
  2149. BYTE *pdata;
  2150. {
  2151. if (fTBigEndian && !fDebSeg)
  2152. {
  2153. return (WORD)((B2W(pdata[0]) << BYTELN) + B2W(pdata[1]));
  2154. }
  2155. else
  2156. {
  2157. return getword(pdata);
  2158. }
  2159. }
  2160. /*
  2161. * GetFixupDword:
  2162. *
  2163. * Gets a dword depending of the value of fTBigEndian and fDebSeg
  2164. */
  2165. LOCAL DWORD NEAR GetFixupDword (pdata)
  2166. BYTE *pdata;
  2167. {
  2168. if (fTBigEndian && !fDebSeg)
  2169. {
  2170. return (DWORD)((((((B2L(pdata[0]) << BYTELN) + B2L(pdata[1])) << BYTELN)
  2171. + B2L(pdata[2])) << BYTELN) + B2L(pdata[3]));
  2172. }
  2173. else
  2174. {
  2175. return getdword(pdata);
  2176. }
  2177. }
  2178. #endif /* O68K */
  2179. #endif /* OSEGEXE AND NOT EXE386 */
  2180. #if ODOS3EXE OR OIAPX286
  2181. /*
  2182. * StartAddrOld:
  2183. *
  2184. * Process a MODEND record with a start address for an old-format exe.
  2185. */
  2186. LOCAL void NEAR StartAddrOld ()
  2187. {
  2188. SEGTYPE gsnTarget;
  2189. SEGTYPE gsnFrame;
  2190. RATYPE raTarget; /* Fixup target offset */
  2191. RATYPE ra;
  2192. SATYPE dsa;
  2193. SEGTYPE segTarget; /* Target segment */
  2194. SEGTYPE segFrame;
  2195. GetFrameTarget(&gsnFrame,&gsnTarget,&raTarget);
  2196. /* Get fixup information */
  2197. if(gsnFrame == SEGNIL) gsnFrame = gsnTarget;
  2198. /* Use target val. if none given */
  2199. segFrame = mpgsnseg[gsnFrame]; /* Get frame segment */
  2200. segTarget = mpgsnseg[gsnTarget];/* Get target segment */
  2201. dsa = mpsegsa[segTarget] - mpsegsa[segFrame];
  2202. /* Calculate base delta */
  2203. #if NOT OIAPX286
  2204. if(dsa > 0x1000)
  2205. FixupOverflow(raTarget + fi.f_disp,gsnFrame,gsnTarget,raTarget);
  2206. /* Delta > 64Kbytes */
  2207. ra = dsa << 4;
  2208. if(0xFFFF - ra < raTarget) /* If addition would overflow */
  2209. {
  2210. ra = ra - 0xFFFF + raTarget;
  2211. /* Fix up addition */
  2212. --ra;
  2213. FixupOverflow(raTarget + fi.f_disp,gsnFrame,gsnTarget,raTarget);
  2214. }
  2215. else ra = ra + raTarget;
  2216. /* Else perform addition */
  2217. #endif
  2218. #if OIAPX286
  2219. if(dsa) FixupOverflow(raTarget + fi.f_disp,gsnFrame,gsnTarget,raTarget);
  2220. /* No intersegment fixups */
  2221. ra = raTarget; /* Use target offset */
  2222. #endif
  2223. #if EXE386
  2224. if((rect & 1) && ra + fi.f_disp < ra)
  2225. {
  2226. ra = ra - 0xFFFFFFFF + fi.f_disp;
  2227. --ra;
  2228. FixupOverflow(raTarget + fi.f_disp,gsnFrame,gsnTarget,raTarget);
  2229. }
  2230. else if (!(rect & 1) && 0xFFFF - ra < fi.f_disp)
  2231. #else
  2232. if(0xFFFF - ra < fi.f_disp) /* If addition would overflow */
  2233. #endif
  2234. {
  2235. ra = ra - 0xFFFF + fi.f_disp;
  2236. /* Fix up addition */
  2237. --ra;
  2238. FixupOverflow(raTarget + fi.f_disp,gsnFrame,gsnTarget,raTarget);
  2239. }
  2240. else ra = ra + fi.f_disp; /* Else perform addition */
  2241. if(segStart == SEGNIL)
  2242. {
  2243. segStart = segFrame;
  2244. raStart = ra;
  2245. if(fLstFileOpen) /* If there is a listing file */
  2246. {
  2247. if(vcln) /* If writing line numbers */
  2248. {
  2249. NEWLINE(bsLst); /* End of line */
  2250. vcln = 0; /* Start on new line */
  2251. }
  2252. fprintf(bsLst,GetMsg(MAP_entry),
  2253. mpsegsa[segStart],raStart);/* Print entry point */
  2254. }
  2255. }
  2256. }
  2257. #endif /* ODOS3EXE OR OIAPX286 */
  2258. /****************************************************************
  2259. * *
  2260. * EndRec: *
  2261. * *
  2262. * This function is called to process the information *
  2263. * contained in a MODEND (type 8AH) record concerning the *
  2264. * program starting address. The function does not return a *
  2265. * meaningful value. *
  2266. * See pp. 80-81 in "8086 Object Module Formats EPS." *
  2267. * *
  2268. ****************************************************************/
  2269. void NEAR EndRec(void)
  2270. {
  2271. WORD modtyp; /* MODEND record modtyp byte */
  2272. SEGTYPE gsnTarget;
  2273. RATYPE ra;
  2274. modtyp = Gets(); /* Read modtyp byte */
  2275. if(modtyp & FSTARTADDRESS) /* If execution start address given */
  2276. {
  2277. ASSERT(modtyp & 1); /* Must have logical start address */
  2278. GetFixdat(); /* Get target information */
  2279. #if ODOS3EXE OR OIAPX286
  2280. /* Start address processed differently for DOS 3.x exes */
  2281. if(!fNewExe)
  2282. {
  2283. StartAddrOld();
  2284. return;
  2285. }
  2286. #endif
  2287. #if OSEGEXE
  2288. switch(fi.f_mtd) /* Switch on target method */
  2289. {
  2290. case T0: /* Segment index */
  2291. gsnTarget = mpsngsn[fi.f_idx];
  2292. ra = mpgsndra[gsnTarget];
  2293. break;
  2294. case T1: /* Group index */
  2295. gsnTarget = mpggrgsn[mpgrggr[fi.f_idx]];
  2296. ra = mpgsndra[gsnTarget];
  2297. break;
  2298. case T2: /* External index */
  2299. if(mpextflags[fi.f_idx] & FIMPORT)
  2300. {
  2301. OutError(ER_impent);
  2302. return;
  2303. }
  2304. gsnTarget = mpextgsn[fi.f_idx];
  2305. ra = mpextra[fi.f_idx];
  2306. break;
  2307. }
  2308. if(segStart == SEGNIL) /* If no entry point specified */
  2309. {
  2310. segStart = mpgsnseg[gsnTarget];
  2311. /* Get starting file segment number */
  2312. raStart = ra + fi.f_disp;
  2313. /* Get starting offset */
  2314. if(fLstFileOpen) /* If there is a listing file */
  2315. {
  2316. if(vcln) /* If writing line numbers */
  2317. {
  2318. NEWLINE(bsLst); /* End of line */
  2319. vcln = 0; /* Start on new line */
  2320. }
  2321. #if NOT QCLINK
  2322. /* Check if segStart is code */
  2323. #if EXE386
  2324. if (!IsEXECUTABLE(mpsaflags[mpsegsa[segStart]]))
  2325. #else
  2326. if((mpsaflags[mpsegsa[segStart]] & NSTYPE) != NSCODE
  2327. && !fRealMode && (TargetOs == NE_OS2 || TargetOs == NE_WINDOWS))
  2328. #endif
  2329. OutError(ER_startaddr);
  2330. #endif
  2331. fprintf(bsLst,"\r\nProgram entry point at %04x:%04x\r\n",
  2332. mpsegsa[segStart],raStart); /* Print entry point */
  2333. }
  2334. }
  2335. #endif /* OSEGEXE */
  2336. }
  2337. }
  2338. #if ODOS3EXE OR OXOUT
  2339. /****************************************************************
  2340. * *
  2341. * RecordSegmentReference: *
  2342. * *
  2343. * Generate a loadtime relocation for a DOS3 exe. *
  2344. * *
  2345. ****************************************************************/
  2346. void NEAR RecordSegmentReference(seg,ra,segDst)
  2347. SEGTYPE seg;
  2348. RATYPE ra;
  2349. SEGTYPE segDst;
  2350. {
  2351. SEGTYPE segAbsLast; /* Last absolute segemnt */
  2352. DOSRLC rlc; // Relocation address
  2353. long xxaddr; /* Twenty bit address */
  2354. void FAR *pTmp;
  2355. RUNRLC FAR *pRunRlc;
  2356. #if OVERLAYS
  2357. WORD iov; /* Overlay number */
  2358. #endif
  2359. #if FEXEPACK
  2360. WORD frame; /* Frame part of 20-bit address */
  2361. FRAMERLC FAR *pFrameRlc;
  2362. #endif
  2363. #if SYMDEB
  2364. if(fSymdeb && seg >= segDebFirst) /* Skip if debug segment */
  2365. return;
  2366. #endif
  2367. #if ODOS3EXE
  2368. segAbsLast = segLast + csegsAbs; /* Calc. last absolute seg no. */
  2369. if(vfDSAlloc) --segAbsLast;
  2370. if(segDst > segLast && segDst <= segAbsLast) return;
  2371. /* Don't bother if absolute segment */
  2372. #endif
  2373. if (TYPEOF(vrectData) == LIDATA)
  2374. ompimisegDstIdata[ra - vraCur] = (char) segDst;
  2375. else /* Else if not iterated data */
  2376. {
  2377. #if OVERLAYS
  2378. iov = mpsegiov[seg]; /* Get overlay number */
  2379. ASSERT(fOverlays || iov == IOVROOT);
  2380. /* If no overlays then iov = IOVROOT */
  2381. #endif
  2382. #if FEXEPACK
  2383. #if OVERLAYS
  2384. if (iov == 0) /* If root */
  2385. #endif
  2386. if (fExePack)
  2387. {
  2388. /*
  2389. * Optimize this reloc: form the 20-bit address, the
  2390. * frame is the high-order 4 bits, forming an index
  2391. * into mpframcRle (count of relocs by frame), which
  2392. * then forms an index into the packed relocation area,
  2393. * where the low-order 16 bits are stored. Finally,
  2394. * increment the frame's reloc count and return.
  2395. */
  2396. xxaddr = ((RATYPE) mpsegsa[seg] << 4) + (RATYPE) ra;
  2397. frame = (WORD) ((xxaddr >> 16) & 0xf);
  2398. pFrameRlc = &mpframeRlc[frame];
  2399. if (pFrameRlc->count > 0x7fff)
  2400. Fatal(ER_relovf);
  2401. ra = (RATYPE) (xxaddr & 0xffffL);
  2402. if (pFrameRlc->count >= pFrameRlc->count)
  2403. {
  2404. // We need more memory to store this relocation
  2405. if (pFrameRlc->rgRlc == NULL)
  2406. {
  2407. pFrameRlc->rgRlc = (WORD FAR *) GetMem(DEF_FRAMERLC*sizeof(WORD));
  2408. pFrameRlc->size = DEF_FRAMERLC;
  2409. }
  2410. else if (pFrameRlc->count >= pFrameRlc->size)
  2411. {
  2412. // Reallocate array of packed relocation offsets
  2413. pTmp = GetMem((pFrameRlc->size << 1)*sizeof(WORD));
  2414. FMEMCPY(pTmp, pFrameRlc->rgRlc, pFrameRlc->count*sizeof(WORD));
  2415. FFREE(pFrameRlc->rgRlc);
  2416. pFrameRlc->rgRlc = pTmp;
  2417. pFrameRlc->size <<= 1;
  2418. }
  2419. }
  2420. pFrameRlc->rgRlc[pFrameRlc->count] = (WORD) ra;
  2421. pFrameRlc->count++;
  2422. return;
  2423. }
  2424. #endif /* FEXEPACK */
  2425. rlc.sa = (WORD) mpsegsa[seg]; /* Get segment address */
  2426. rlc.ra = (WORD) ra; /* Save relative address */
  2427. #if OVERLAYS
  2428. pRunRlc = &mpiovRlc[iov];
  2429. if (pRunRlc->count >= pRunRlc->count)
  2430. {
  2431. // We need more memory to store this relocation
  2432. if (pRunRlc->rgRlc == NULL)
  2433. {
  2434. pRunRlc->rgRlc = (DOSRLC FAR *) GetMem(DEF_RUNRLC * CBRLC);
  2435. pRunRlc->size = DEF_RUNRLC;
  2436. }
  2437. else if (pRunRlc->count >= pRunRlc->size)
  2438. {
  2439. // Reallocate array of packed relocation offsets
  2440. pTmp = GetMem((pRunRlc->size << 1) * CBRLC);
  2441. FMEMCPY(pTmp, pRunRlc->rgRlc, pRunRlc->count * CBRLC);
  2442. FFREE(pRunRlc->rgRlc);
  2443. pRunRlc->rgRlc = pTmp;
  2444. pRunRlc->size <<= 1;
  2445. }
  2446. }
  2447. pRunRlc->rgRlc[pRunRlc->count] = rlc;
  2448. pRunRlc->count++;
  2449. #endif
  2450. }
  2451. }
  2452. #endif /* ODOS3EXE OR OXOUT */
  2453. #if OVERLAYS
  2454. /****************************************************************
  2455. * *
  2456. * Mpgsnosn: *
  2457. * *
  2458. * Map global segment number to overlay segment number. *
  2459. * *
  2460. ****************************************************************/
  2461. LOCAL SNTYPE NEAR Mpgsnosn(gsn)
  2462. SNTYPE gsn; /* Global SEGDEF number */
  2463. {
  2464. SNTYPE hgsn; /* Gsn hash value */
  2465. hgsn = (SNTYPE)(gsn & ((1 << LG2OSN) - 1)); /* Take the low-order bits */
  2466. while(mposngsn[htgsnosn[hgsn]] != gsn)
  2467. { /* While match not found */
  2468. if((hgsn += HTDELTA) >= OSNMAX) hgsn -= OSNMAX;
  2469. /* Calculate next hash value */
  2470. }
  2471. return(htgsnosn[hgsn]); /* Return overlay segment number */
  2472. }
  2473. #endif
  2474. #if ODOS3EXE OR OIAPX286
  2475. LOCAL void NEAR GetFrameTarget(pgsnFrame,pgsnTarget,praTarget)
  2476. SEGTYPE *pgsnFrame; /* Frame index */
  2477. SEGTYPE *pgsnTarget; /* Target index */
  2478. RATYPE *praTarget; /* Target offset */
  2479. {
  2480. RATYPE dummy;
  2481. WORD i;
  2482. /* Method no: Frame specification:
  2483. * 0 segment index
  2484. * 1 group index
  2485. * 2 external index
  2486. * 3 frame number
  2487. * 4 implicit (location)
  2488. * 5 implicit (target)
  2489. * 6 none
  2490. * 7 invalid
  2491. */
  2492. if(fi.f_fmtd == KINDTARGET) /* If frame is target's frame */
  2493. {
  2494. fi.f_fmtd = fi.f_mtd; /* Use target frame kind */
  2495. fi.f_fidx = fi.f_idx; /* Use target index */
  2496. }
  2497. if (fi.f_fmtd == KINDEXT && !fNoGrpAssoc)
  2498. { /* If frame given by pub sym */
  2499. if(fi.f_fidx >= extMac) InvalidObject();
  2500. /* Make sure index not too big */
  2501. if((i = mpextggr[fi.f_fidx]) != GRNIL)
  2502. /* If symbol has group association */
  2503. *pgsnFrame = mpggrgsn[i]; /* Get gsn for group */
  2504. else *pgsnFrame = mpextgsn[fi.f_fidx];
  2505. /* Else return target gsn */
  2506. }
  2507. else if (fi.f_fmtd == KINDLOCAT && !fNoGrpAssoc)
  2508. { /* If frame current segment */
  2509. *pgsnFrame = vgsnCur; /* Frame is location's segment */
  2510. }
  2511. else
  2512. {
  2513. Getgsn(fi.f_fmtd, fi.f_fidx, pgsnFrame, &dummy);
  2514. }
  2515. Getgsn(fi.f_mtd, fi.f_idx, pgsnTarget, praTarget);
  2516. /* Get gsn and ra, if any */
  2517. }
  2518. LOCAL WORD NEAR InOneGroup(WORD gsnTarget, WORD gsnFrame)
  2519. {
  2520. WORD ggrFrame; /* Fixup frame group */
  2521. WORD ggrTarget; /* Fixup frame group */
  2522. APROPSNPTR apropSn; /* Ptr to a segment record */
  2523. if (gsnFrame != SNNIL)
  2524. {
  2525. apropSn = (APROPSNPTR ) FetchSym(mpgsnrprop[gsnFrame], FALSE);
  2526. ggrFrame = apropSn->as_ggr;
  2527. }
  2528. else
  2529. ggrFrame = GRNIL;
  2530. if (gsnTarget != SNNIL)
  2531. {
  2532. apropSn = (APROPSNPTR ) FetchSym(mpgsnrprop[gsnTarget], FALSE);
  2533. ggrTarget = apropSn->as_ggr;
  2534. }
  2535. else
  2536. ggrFrame = GRNIL;
  2537. return(ggrFrame != GRNIL && ggrTarget != GRNIL && ggrFrame == ggrTarget);
  2538. }
  2539. LOCAL void NEAR AddThunk(SEGTYPE gsnTarget, SEGTYPE *psegTarget, RATYPE *praTarget)
  2540. {
  2541. #pragma pack(1) /* This data must be packed */
  2542. struct _thunk
  2543. {
  2544. BYTE thunkInt;
  2545. BYTE ovlInt;
  2546. WORD osnTgt;
  2547. WORD osnOff;
  2548. }
  2549. thunk;
  2550. #pragma pack() /* Stop packing */
  2551. // We need a new thunk
  2552. if (ovlThunkMac < (WORD) (ovlThunkMax - 1))
  2553. {
  2554. thunk.thunkInt = INTERRUPT;
  2555. thunk.ovlInt = (BYTE) vintno;
  2556. thunk.osnTgt = Mpgsnosn(gsnTarget);
  2557. thunk.osnOff = (WORD) *praTarget;
  2558. *praTarget = ovlThunkMac * OVLTHUNKSIZE;
  2559. *psegTarget = mpgsnseg[gsnOverlay];
  2560. MoveToVm(sizeof(struct _thunk), (BYTE *) &thunk, mpgsnseg[gsnOverlay], *praTarget);
  2561. /* Store thunk */
  2562. #if FALSE
  2563. fprintf(stdout, "%d. Thunk at %x:%04lx; Target osn = %x:%x\r\n",
  2564. ovlThunkMac , mpgsnseg[gsnOverlay], *praTarget, thunk.osnTgt, thunk.osnOff);
  2565. #endif
  2566. ovlThunkMac++;
  2567. }
  2568. else
  2569. {
  2570. Fatal(ER_ovlthunk, ovlThunkMax);
  2571. }
  2572. }
  2573. /*** DoThunking - generate thunk for inter-overlay calls
  2574. *
  2575. * Purpose:
  2576. * When the dynamic overlays are requested redirect all FAR calls or
  2577. * references to aproppriate thunks. If this is first call/reference
  2578. * to given symbol then add its thunk to the OVERLAY_THUNKS segment.
  2579. *
  2580. * Input:
  2581. * gsnTarget - global segment number of the fixup target
  2582. * psegTarget - poiter to logical segment number of the fixup target
  2583. * praTarget - pointer offset of the fixup target inside gsnTarget
  2584. *
  2585. * Output:
  2586. * The gsn and offset of the target are replaced by the gsn and offset
  2587. * of the thunk for target. For first references to a given symbol
  2588. * the thunk is created in OVERLAY_THUNKS segment (referenced via
  2589. * gsnOverlay global) and the current position in thunk segment is
  2590. * updated (ovlThunkMac).
  2591. *
  2592. * Exceptions:
  2593. * No space in OVERLAY_THUNKS for new thunk - fatal error - display message
  2594. * suggesting use of /DYNAMIC:<nnn> with <nnn> greater then current value.
  2595. *
  2596. * Notes:
  2597. * None.
  2598. *
  2599. *************************************************************************/
  2600. LOCAL void NEAR DoThunking(SEGTYPE gsnTarget, SEGTYPE *psegTarget, RATYPE *praTarget)
  2601. {
  2602. APROPNAMEPTR apropName; /* Public symbol property */
  2603. switch(fi.f_mtd)
  2604. {
  2605. case KINDEXT:
  2606. // Target is external
  2607. apropName = (APROPNAMEPTR) FetchSym(mpextprop[fi.f_idx], FALSE);
  2608. if (apropName->an_thunk != THUNKNIL)
  2609. {
  2610. // We already allocated thunk for this target
  2611. *praTarget = apropName->an_thunk;
  2612. *psegTarget = mpgsnseg[gsnOverlay];
  2613. #if FALSE
  2614. fprintf(stdout, "Using thunk for '%s' at %x:%04lx\r\n",
  2615. 1 + GetPropName(apropName), mpgsnseg[gsnOverlay], *praTarget);
  2616. #endif
  2617. }
  2618. else
  2619. {
  2620. // We need new thunk for new target
  2621. AddThunk(gsnTarget, psegTarget, praTarget);
  2622. apropName = (APROPNAMEPTR) FetchSym(mpextprop[fi.f_idx], TRUE);
  2623. apropName->an_thunk = *praTarget;
  2624. #if FALSE
  2625. fprintf(stdout, "%d. Thunk for '%s' at %x:%04lx; Target osn = %x:%x\r\n",
  2626. ovlThunkMac, 1 + GetPropName(apropName), mpgsnseg[gsnOverlay], *praTarget, thunk.osnTgt, thunk.osnOff);
  2627. #endif
  2628. }
  2629. break;
  2630. case KINDSEG:
  2631. AddThunk(gsnTarget, psegTarget, praTarget);
  2632. break;
  2633. default:
  2634. InvalidObject();
  2635. }
  2636. }
  2637. /*
  2638. * FixOld:
  2639. *
  2640. * Process a fixup for an old-format exe.
  2641. */
  2642. void NEAR FixOld ()
  2643. {
  2644. REGISTER BYTE *pdata; /* Pointer into data record */
  2645. SEGTYPE segTarget; /* Fixup target segment */
  2646. SEGTYPE segFrame; /* Fixup frame segment */
  2647. SEGTYPE gsnTarget;
  2648. SEGTYPE gsnFrame;
  2649. RATYPE raTarget; /* Fixup target rel. addr. */
  2650. RATYPE raTmp;
  2651. RATYPE ra; /* Current location offset */
  2652. long dra;
  2653. WORD dsa;
  2654. WORD saTmp; /* Temporary base variable */
  2655. #if OVERLAYS
  2656. WORD fFallThrough;
  2657. WORD fThunk;
  2658. fFallThrough = FALSE;
  2659. fThunk = FALSE;
  2660. #endif
  2661. ra = vraCur + fi.f_dri; /* Get rel. addr. of fixup */
  2662. pdata = &rgmi[fi.f_dri]; /* Set pointer to fixup location */
  2663. GetFrameTarget(&gsnFrame,&gsnTarget,&raTarget);
  2664. /* Process the FIXDAT byte */
  2665. segTarget = mpgsnseg[gsnTarget]; /* Get target segment */
  2666. if(gsnFrame != SNNIL) segFrame = mpgsnseg[gsnFrame];
  2667. else segFrame = SEGNIL;
  2668. if(vsegCur == SEGNIL) return;
  2669. if(gsnTarget == SNNIL)
  2670. {
  2671. if(fi.f_loc == LOCPTR) /* If "pointer" (4 byte) fixup */
  2672. {
  2673. if(mpsegFlags[vsegCur] & FCODE)
  2674. lastbyte(pdata,ra,CALLFARDIRECT,BREAKPOINT);
  2675. /* Replace long call w/ breakpoint */
  2676. return;
  2677. }
  2678. /* Return if "base" (2 byte) fixup */
  2679. if(fi.f_loc == LOCSEGMENT) return;
  2680. }
  2681. else
  2682. {
  2683. if (!fDebSeg && segFrame != SEGNIL)
  2684. {
  2685. dsa = mpsegsa[segTarget] - mpsegsa[segFrame];
  2686. #if NOT OIAPX286
  2687. dra = dsa << 4;
  2688. raTmp = raTarget + dra;
  2689. if(dsa >= 0x1000 || raTmp < raTarget)
  2690. FixupOverflow(ra,gsnFrame,gsnTarget,raTarget);
  2691. raTarget = raTmp;
  2692. segTarget = segFrame;
  2693. #else
  2694. if(dsa) /* No intersegment fixups */
  2695. FixupOverflow(ra,gsnFrame,gsnTarget,raTarget);
  2696. #endif
  2697. }
  2698. else segFrame = segTarget; /* Else use target's seg as frame */
  2699. if(fi.f_self) /* If self-relative fixup */
  2700. {
  2701. /* Here we process intersegment self-relative fixups.
  2702. * We assume that the only way this can work is if the
  2703. * both the target segment and the current segment assume
  2704. * the same CS, and that CS is the frame segment of the
  2705. * fixup. A common example is if vsegCur and segTarget
  2706. * are in the same group represented by segFrame.
  2707. * If this is true, vsegCur must be >= segFrame, so we
  2708. * use this assumption in checking for fixup overflow and
  2709. * adjusting the target offset.
  2710. */
  2711. if (vsegCur != segTarget && !InOneGroup(gsnTarget, gsnFrame))
  2712. RelocWarn(ER_fixovfw,ra,gsnFrame,vgsnCur,raTarget);
  2713. /*
  2714. * First, determine the distance from segFrame to vsegCur in
  2715. * paragraphs and bytes.
  2716. */
  2717. dsa = mpsegsa[vsegCur] - mpsegsa[segFrame];
  2718. /* dra is the adjustment to make ra relative to segFrame */
  2719. dra = (dsa & 0xFFF) << 4;
  2720. #if NOT OIAPX286
  2721. /* If the distance is >= 64K, or if the current offset ra plus
  2722. * plus the adjustment dra is >= 64K, or if vsegCur is above
  2723. * segFrame (see above), then we have fixup overflow.
  2724. */
  2725. if (dsa >= 0x1000 || (WORD) (0xFFFF - ra) < (WORD) dra)
  2726. FixupOverflow(ra,gsnFrame,vgsnCur,raTarget);
  2727. #else
  2728. /* In protected mode, intersegment self-relative fixups won't
  2729. * work.
  2730. */
  2731. if(dsa)
  2732. FixupOverflow(ra,gsnFrame,vgsnCur,raTarget);
  2733. #endif
  2734. /* Determine the fixup value which is raTarget minus the current
  2735. * location, ra. Adjust ra upward by dra to make it relative
  2736. * to segFrame, then adjust by the length of the location type
  2737. * (assume LOCOFFSET as the most common). This reduces to the
  2738. * expression below.
  2739. */
  2740. raTarget = raTarget - dra - ra - 2;
  2741. /* Adjust for less likely LOCtypes */
  2742. if(fi.f_loc == LOCLOBYTE)
  2743. raTarget += 1;
  2744. #if OMF386
  2745. else if(fi.f_loc >= LOCOFFSET32)
  2746. raTarget -= 2;
  2747. #endif
  2748. }
  2749. }
  2750. raTmp = raTarget;
  2751. raTarget += fi.f_disp;
  2752. #if OMF386
  2753. if ((rect & 1) && (fi.f_loc >= LOCOFFSET32))
  2754. raTarget += getdword(pdata);
  2755. else
  2756. #endif
  2757. raTarget += getword(pdata);
  2758. switch(fi.f_loc) /* Switch on fixup type */
  2759. {
  2760. case LOCLOBYTE: /* 8-bit "lobyte" fixup */
  2761. raTarget = raTmp + B2W(pdata[0]) + fi.f_disp;
  2762. pdata[0] = (BYTE) raTarget;
  2763. if(raTarget >= 0x100 && fi.f_self)
  2764. FixupOverflow(ra,gsnFrame,gsnTarget,raTarget);
  2765. break;
  2766. case LOCHIBYTE: /* 8-bit "hibyte" fixup */
  2767. raTarget = raTmp + fi.f_disp;
  2768. pdata[0] = (BYTE) (B2W(pdata[0]) + (raTarget >> 8));
  2769. break;
  2770. #if OMF386
  2771. case LOCOFFSET32: /* 32-bit "offset" fixup */
  2772. case LOCLOADOFFSET32:
  2773. if(!(rect & 1)) break; /* Not 386 extension */
  2774. fixword(pdata, raTarget);
  2775. pdata += 2;
  2776. raTarget >>= 16; /* Get high word, fall through ... */
  2777. #if OVERLAYS
  2778. fFallThrough = TRUE;
  2779. #endif
  2780. #endif
  2781. case LOCOFFSET: /* 16-bit "offset" fixup */
  2782. case LOCLOADOFFSET:
  2783. #if OVERLAYS
  2784. if (fDynamic && !fFallThrough && !fDebSeg &&
  2785. (fi.f_loc == LOCLOADOFFSET) &&
  2786. (mpsegFlags[vsegCur] & FCODE) && mpsegiov[segTarget])
  2787. DoThunking(gsnTarget, &segTarget, &raTarget);
  2788. #endif
  2789. fixword(pdata, raTarget);
  2790. /* Perform fixup */
  2791. break;
  2792. #if OMF386
  2793. case LOCPTR48: /* 48-bit "pointer" fixup */
  2794. if(!(rect & 1)) break; /* Not 386 extension */
  2795. fixword(pdata, raTarget);
  2796. pdata += 2;
  2797. raTarget >>= 16; /* Get high word, fall through ... */
  2798. #endif
  2799. case LOCPTR: /* 32-bit "pointer" fixup */
  2800. #if OVERLAYS
  2801. if (!fDebSeg)
  2802. { /* If root-overlay or interoverlay */
  2803. if (fDynamic)
  2804. {
  2805. // Gererate thunk if:
  2806. //
  2807. // - target is in overlay and
  2808. // - current position is in different overlay or
  2809. // - current position is in the same overlay but
  2810. // in a different segment (assuming initialization
  2811. // of a far pointer to the function)
  2812. if (mpsegiov[segTarget] &&
  2813. ((mpsegiov[vsegCur] != mpsegiov[segTarget]) ||
  2814. (mpsegiov[vsegCur] != IOVROOT && vsegCur != segTarget)))
  2815. {
  2816. DoThunking(gsnTarget, &segTarget, &raTarget);
  2817. fThunk = (FTYPE) TRUE;
  2818. }
  2819. }
  2820. else if (mpsegiov[segTarget] &&
  2821. (mpsegiov[vsegCur] != mpsegiov[segTarget]))
  2822. {
  2823. if ((mpsegFlags[vsegCur] & FCODE) &&
  2824. lastbyte(pdata,ra,CALLFARDIRECT,INTERRUPT))
  2825. { /* If fixing up long call direct */
  2826. *pdata++ = vintno; /* Interrupt number */
  2827. *pdata++ = (BYTE) Mpgsnosn(gsnTarget);
  2828. /* Target overlay segment number */
  2829. *pdata++ = (BYTE) (raTarget & 0xFF);
  2830. /* Lo word of offset */
  2831. *pdata = (BYTE)((raTarget >> BYTELN) & 0xFF);
  2832. /* Hi word of target */
  2833. break; /* All done */
  2834. }
  2835. }
  2836. }
  2837. #endif
  2838. if (!fDebSeg && fFarCallTrans &&
  2839. mpsegsa[segTarget] == mpsegsa[vsegCur] &&
  2840. (mpsegFlags[segTarget] & FCODE)
  2841. #if OVERLAYS
  2842. && mpsegiov[vsegCur] == mpsegiov[segTarget] && !fThunk
  2843. #endif
  2844. )
  2845. { /* If intrasegment fixup in the same overlay */
  2846. if(TransFAR(pdata,ra,raTarget))
  2847. break;
  2848. }
  2849. /* Root-root, overlay-root, and intraoverlay are normal calls */
  2850. fixword(pdata, raTarget); /* Fix up offset */
  2851. pdata += 2;
  2852. /* Advance to segment part and fall through . . . */
  2853. ra += 2;
  2854. #if OVERLAYS
  2855. fFallThrough = TRUE;
  2856. #endif
  2857. case LOCSEGMENT: /* 16-bit "base" fixup */
  2858. #if OVERLAYS
  2859. if (fDynamic && !fDebSeg &&
  2860. (mpsegFlags[vsegCur] & FCODE) && mpsegiov[segTarget])
  2861. {
  2862. if(!fFallThrough)
  2863. {
  2864. OutWarn(ER_farovl, 1+GetPropName(FetchSym(mpgsnrprop[gsnTarget],FALSE)),
  2865. 1+GetPropName(FetchSym(mpgsnrprop[gsnOverlay],FALSE)));
  2866. segTarget = mpgsnseg[gsnOverlay];
  2867. }
  2868. else
  2869. {
  2870. /* intra-overlay pointer fixups not supported - caviar:6806 */
  2871. OutError(ER_farovldptr);
  2872. }
  2873. }
  2874. #endif
  2875. if (fDebSeg)
  2876. {
  2877. // For debug segments use logical segment number (seg)
  2878. // instead of physical segment number (sa)
  2879. saTmp = segTarget;
  2880. }
  2881. else
  2882. {
  2883. saTmp = mpsegsa[segTarget];
  2884. // If MS OMF, high word is a segment ordinal, for huge model
  2885. // Shift left by appropriate amount to get selector
  2886. #if OEXE
  2887. if (vfNewOMF && !fDynamic)
  2888. saTmp += (B2W(pdata[0]) + (B2W(pdata[1]) << BYTELN)) << 12;
  2889. else
  2890. saTmp += B2W(pdata[0]) + (B2W(pdata[1]) << BYTELN);
  2891. /* Note fixup is ADDITIVE */
  2892. #endif
  2893. #if OIAPX286 OR OXOUT
  2894. if(vfNewOMF)
  2895. saTmp += (B2W(pdata[0]) + (B2W(pdata[1]) << BYTELN)) << 3;
  2896. #endif
  2897. /* Note that base fixups are NOT ADDITIVE for Xenix. This is
  2898. * to get around a bug in "as" which generates meaningless
  2899. * nonzero values at base fixup locations.
  2900. */
  2901. #if OIAPX286
  2902. /* Hack for impure model: code and data are packed into
  2903. * one physical segment which at runtime is accessed via 2
  2904. * selectors. The code selector is 8 below the data selector.
  2905. */
  2906. if(!fIandD && (mpsegFlags[segTarget] & FCODE))
  2907. saTmp -= 8;
  2908. #endif
  2909. }
  2910. fixword(pdata, saTmp); /* Perform fixup */
  2911. #if NOT OIAPX286
  2912. if (!fDebSeg)
  2913. RecordSegmentReference(vsegCur,ra,segTarget);
  2914. /* Record reference */
  2915. #endif
  2916. break;
  2917. default: /* Unsupported fixup type */
  2918. RelocErr(ER_fixbad,ra,gsnFrame,gsnTarget,raTarget);
  2919. break;
  2920. }
  2921. }
  2922. #endif /* ODOS3EXE OR OIAPX286 */
  2923. /*
  2924. * FixRc2:
  2925. *
  2926. * Process a FIXUPP record. This is a top-level routine which passes
  2927. * work out to various subroutines.
  2928. */
  2929. void NEAR FixRc2(void) /* Process a fixup record */
  2930. {
  2931. #if 0
  2932. #if SYMDEB
  2933. // this code is dead -- fDebSeg && !fSymdeb is never true [rm]
  2934. if (fDebSeg && !fSymdeb)
  2935. {
  2936. // If no /CodeView - skip fixups for debug segments
  2937. SkipBytes((WORD) (cbRec - 1));
  2938. return;
  2939. }
  2940. #endif
  2941. #endif
  2942. if (fSkipFixups)
  2943. {
  2944. fSkipFixups = (FTYPE) FALSE; // Only one FIXUP record can be skipped
  2945. SkipBytes((WORD) (cbRec - 1));
  2946. return;
  2947. }
  2948. while (cbRec > 1)
  2949. {
  2950. // While fixups or threads remain
  2951. // Get information on fixup
  2952. if (!GetFixup())
  2953. continue; // Fixup thread - keep registering them
  2954. // If absolute segment skip fixup
  2955. if (vgsnCur == 0xffff)
  2956. {
  2957. SkipBytes((WORD) (cbRec - 1));
  2958. return;
  2959. }
  2960. #if SYMDEB
  2961. if (fDebSeg)
  2962. {
  2963. if (fi.f_loc == LOCLOADOFFSET)
  2964. fi.f_loc = LOCOFFSET; /* Save Cmerge's butts */
  2965. #if OMF386
  2966. if (fi.f_loc == LOCOFFSET32 || fi.f_loc == LOCPTR48)
  2967. fi.f_fmtd = F5; /* Temp fix until compiler is fixed */
  2968. #endif
  2969. }
  2970. #endif
  2971. DoFixup();
  2972. }
  2973. }
  2974. // BAKPAT record bookeeping
  2975. typedef struct bphdr // BAKPAT bucket
  2976. {
  2977. struct bphdr FAR *next; // Next bucket
  2978. SNTYPE gsn; // Segment index
  2979. WORD cnt; // # of BAKPAT entries
  2980. BYTE loctyp; // Location type
  2981. BYTE fComdat; // TRUE if NBAKPAT
  2982. struct bpentry FAR *patch; // Table of BAKPAT entries
  2983. }
  2984. BPHDR;
  2985. struct bpentry // BAKPAT entry
  2986. {
  2987. RATYPE ra; // Offset to location to patch
  2988. #if OMF386
  2989. long value; // Value to add to patch location
  2990. #else
  2991. int value; // Value to add to patch location
  2992. #endif
  2993. };
  2994. LOCAL BPHDR FAR *pbpFirst; // List of BAKPAT buckets
  2995. LOCAL BPHDR FAR *pbpLast; // Tail of BAKPAT list
  2996. /*
  2997. * BakPat : Process a BAKPAT record (0xb2)
  2998. *
  2999. * Just accumulate the record information in virtual memory;
  3000. * we will do the backpatching later.
  3001. */
  3002. void NEAR BakPat()
  3003. {
  3004. BPHDR FAR *pHdr; // BAKPAT bucket
  3005. WORD cEntry;
  3006. WORD comdatIdx; // COMDAT symbol index
  3007. DWORD comdatRa; // Starting COMDAT offset
  3008. APROPCOMDATPTR comdat; // Pointer to symbol table entry
  3009. #if POOL_BAKPAT
  3010. if (!poolBakpat)
  3011. poolBakpat = PInit();
  3012. #endif
  3013. /* Get the segment index and location type */
  3014. #if POOL_BAKPAT
  3015. pHdr = (BPHDR FAR *) PAlloc(poolBakpat, sizeof(BPHDR));
  3016. #else
  3017. pHdr = (BPHDR FAR *) GetMem(sizeof(BPHDR));
  3018. #endif
  3019. if (TYPEOF(rect) == BAKPAT)
  3020. {
  3021. pHdr->fComdat = (FTYPE) FALSE;
  3022. pHdr->gsn = mpsngsn[GetIndex(1, (WORD) (snMac - 1))];
  3023. pHdr->loctyp = (BYTE) Gets();
  3024. comdatRa = 0L;
  3025. }
  3026. else
  3027. {
  3028. pHdr->fComdat = (BYTE) TRUE;
  3029. pHdr->loctyp = (BYTE) Gets();
  3030. comdatIdx = GetIndex(1, (WORD) (lnameMac - 1));
  3031. comdat = (APROPCOMDATPTR ) PropRhteLookup(mplnamerhte[comdatIdx], ATTRCOMDAT, FALSE);
  3032. if ((comdat->ac_obj != vrpropFile) || !IsSELECTED (comdat->ac_flags))
  3033. {
  3034. // Skip the nbakpat if it concerns an unselected comdat
  3035. // or a comdat from other .obj
  3036. SkipBytes((WORD) (cbRec - 1));
  3037. return;
  3038. }
  3039. else
  3040. {
  3041. if (comdat != NULL)
  3042. {
  3043. pHdr->gsn = comdat->ac_gsn;
  3044. comdatRa = comdat->ac_ra;
  3045. }
  3046. else
  3047. InvalidObject(); // Invalid module
  3048. }
  3049. }
  3050. /* If BAKPAT record for CV info and /CO not used - skip record */
  3051. #if SYMDEB
  3052. if (pHdr->gsn == 0xffff)
  3053. {
  3054. SkipBytes((WORD) (cbRec - 1));
  3055. return; /* Good-bye! */
  3056. }
  3057. #endif
  3058. switch(pHdr->loctyp)
  3059. {
  3060. case LOCLOBYTE:
  3061. case LOCOFFSET:
  3062. #if OMF386
  3063. case LOCOFFSET32:
  3064. #endif
  3065. break;
  3066. default:
  3067. InvalidObject();
  3068. }
  3069. /* Determine # of entries */
  3070. #if OMF386
  3071. if (rect & 1)
  3072. pHdr->cnt = (WORD) ((cbRec - 1) >> 3);
  3073. else
  3074. #endif
  3075. pHdr->cnt = (WORD) ((cbRec - 1) >> 2);
  3076. if (pHdr->cnt == 0)
  3077. {
  3078. #if NOT POOL_BAKPAT
  3079. FFREE(pHdr);
  3080. #endif
  3081. return;
  3082. }
  3083. #if DEBUG
  3084. sbModule[sbModule[0]+1] = '\0';
  3085. fprintf(stdout, "\r\nBakPat in module %s, at %x, entries : %x", sbModule+1, lfaLast,pHdr->cnt);
  3086. fprintf(stdout, " pHdr %x, pbpLast %x ", pHdr, pbpLast);
  3087. fprintf(stdout, "\r\n gsn %d ", pHdr->gsn);
  3088. fflush(stdout);
  3089. #endif
  3090. // Store all the BAKPAT entries
  3091. #if POOL_BAKPAT
  3092. pHdr->patch = (struct bpentry FAR *) PAlloc(poolBakpat, pHdr->cnt * sizeof(struct bpentry));
  3093. #else
  3094. pHdr->patch = (struct bpentry FAR *) GetMem(pHdr->cnt * sizeof(struct bpentry));
  3095. #endif
  3096. cbBakpat = 1; // only need to show backpatches are present [rm]
  3097. cEntry = 0;
  3098. while (cbRec > 1)
  3099. {
  3100. #if OMF386
  3101. if (rect & 1)
  3102. {
  3103. pHdr->patch[cEntry].ra = LGets() + comdatRa;
  3104. pHdr->patch[cEntry].value = LGets();
  3105. }
  3106. else
  3107. #endif
  3108. {
  3109. pHdr->patch[cEntry].ra = (WORD) (WGets() + comdatRa);
  3110. pHdr->patch[cEntry].value = WGets();
  3111. }
  3112. cEntry++;
  3113. }
  3114. // Add bucket to the list
  3115. if (pbpFirst == NULL)
  3116. pbpFirst = pHdr;
  3117. else
  3118. pbpLast->next = pHdr;
  3119. pbpLast = pHdr;
  3120. }
  3121. /*
  3122. * FixBakpat : Fix up backpatches
  3123. * Called at the end of processing a module in Pass 2.
  3124. */
  3125. void NEAR FixBakpat(void)
  3126. {
  3127. BPHDR FAR *pHdr;
  3128. BPHDR FAR *pHdrNext=NULL;
  3129. WORD n;
  3130. BYTE FAR *pSegImage; /* Segment memory image */
  3131. SEGTYPE seg; /* Logical segment index */
  3132. #if DEBUG
  3133. int i,iTotal=0,j=1;
  3134. char *ibase;
  3135. fprintf(stdout, "\r\nFixBakpat, pbpFirst : %x ", pbpFirst);
  3136. #endif
  3137. // Go through the backpatch list and do the backpatches
  3138. for (pHdr = pbpFirst; pHdr != NULL; pHdr = pHdrNext)
  3139. {
  3140. // While there are backpatches remaining, do them
  3141. #if DEBUG
  3142. fprintf(stdout, "\r\nBAKPAT at %x, entries : %x ",pHdr,pHdr->cnt);
  3143. #endif
  3144. for (n = 0; n < pHdr->cnt; n++)
  3145. {
  3146. // Determine the address of the patch location
  3147. #if SYMDEB
  3148. if (pHdr->gsn & 0x8000)
  3149. pSegImage = ((APROPFILEPTR) vrpropFile)->af_cvInfo->cv_sym + pHdr->patch[n].ra;
  3150. /* In debug segment */
  3151. else
  3152. {
  3153. #endif
  3154. seg = mpgsnseg[pHdr->gsn];
  3155. if(fNewExe)
  3156. pSegImage = mpsaMem[mpsegsa[seg]];
  3157. else
  3158. pSegImage = mpsegMem[seg];
  3159. /* In other segment */
  3160. pSegImage += pHdr->patch[n].ra;
  3161. if (!pHdr->fComdat)
  3162. pSegImage += mpgsndra[pHdr->gsn];
  3163. else
  3164. pSegImage += mpsegraFirst[seg];
  3165. #if SYMDEB
  3166. }
  3167. #endif
  3168. #if DEBUG
  3169. fprintf(stdout, "\r\nseg %d, mpsegsa[seg] sa %d ", seg, mpsegsa[seg]);
  3170. fprintf(stdout, "mpsaMem[seg] %x, mpsegraFirst[seg] %x, pHdr->patch[n].ra %x\r\n",
  3171. mpsaMem[seg], (int)mpsegraFirst[seg], (int)pHdr->patch[n].ra);
  3172. fprintf(stdout, " gsn %x, mpgsndra[gsn] %x ",pHdr->gsn,mpgsndra[pHdr->gsn]);
  3173. ibase = pSegImage - pHdr->patch[n].ra;
  3174. iTotal = (int) ibase;
  3175. for(i=0; i<50; i++)
  3176. {
  3177. if(j==1)
  3178. {
  3179. fprintf( stdout,"\r\n\t%04X\t",iTotal);
  3180. }
  3181. fprintf( stdout,"%02X ",*((char*)ibase+i));
  3182. iTotal++;
  3183. if(++j > 16)
  3184. j=1;
  3185. }
  3186. fprintf(stdout, "\r\nseg:ra %x:%x, value : %x",seg,pHdr->patch[n].ra,pHdr->patch[n].value);
  3187. fflush(stdout);
  3188. #endif
  3189. /* Do the fixup according to the location type */
  3190. switch(pHdr->loctyp)
  3191. {
  3192. case LOCLOBYTE:
  3193. pSegImage[0] += (BYTE) pHdr->patch[n].value;
  3194. break;
  3195. case LOCOFFSET:
  3196. ((WORD FAR *) pSegImage)[0] += (WORD) pHdr->patch[n].value;
  3197. break;
  3198. #if OMF386
  3199. case LOCOFFSET32:
  3200. ((DWORD FAR *) pSegImage)[0]+= (DWORD) pHdr->patch[n].value;
  3201. break;
  3202. #endif
  3203. }
  3204. }
  3205. pHdrNext = pHdr->next;
  3206. #if NOT POOL_BAKPAT
  3207. FFREE(pHdr);
  3208. #endif
  3209. }
  3210. #if POOL_BAKPAT
  3211. PReinit(poolBakpat); // reuse same memory again...
  3212. #endif
  3213. pbpFirst = NULL;
  3214. cbBakpat = 0;
  3215. }
  3216. #if TCE
  3217. void NEAR FixRc1(void) /* Process a fixup record */
  3218. {
  3219. if (fSkipFixups)
  3220. {
  3221. fSkipFixups = (FTYPE) FALSE; // Only one FIXUP record can be skipped
  3222. SkipBytes((WORD) (cbRec - 1));
  3223. pActiveComdat = NULL;
  3224. return;
  3225. }
  3226. while (cbRec > 1)
  3227. {
  3228. // While fixups or threads remain
  3229. // Get information on fixup
  3230. if (!GetFixup())
  3231. continue; // Fixup thread - keep registering them
  3232. if(fi.f_mtd == KINDEXT)
  3233. {
  3234. RBTYPE rhte;
  3235. APROPCOMDAT *pUsedComdat;
  3236. if( mpextprop && mpextprop[fi.f_idx]) // Is there a COMDAT with this name?
  3237. {
  3238. rhte = RhteFromProp(mpextprop[fi.f_idx]);
  3239. ASSERT(rhte);
  3240. pUsedComdat = PropRhteLookup(rhte, ATTRCOMDAT, FALSE);
  3241. if(pActiveComdat)
  3242. {
  3243. if(pUsedComdat)
  3244. {
  3245. AddComdatUses(pActiveComdat, pUsedComdat);
  3246. #if TCE_DEBUG
  3247. fprintf(stdout, "\r\nCOMDAT %s uses COMDAT %s ", 1 + GetPropName(pActiveComdat) ,1+ GetPropName(mpextprop[fi.f_idx]));
  3248. #endif
  3249. }
  3250. else
  3251. {
  3252. AddComdatUses(pActiveComdat, mpextprop[fi.f_idx]);
  3253. #if TCE_DEBUG
  3254. fprintf(stdout, "\r\nCOMDAT %s uses EXTDEF %s ", 1 + GetPropName(pActiveComdat) ,1+ GetPropName(mpextprop[fi.f_idx]));
  3255. #endif
  3256. }
  3257. }
  3258. else // no COMDAT of this name
  3259. {
  3260. if(pUsedComdat)
  3261. {
  3262. pUsedComdat->ac_fAlive = TRUE;
  3263. if(!fDebSeg)
  3264. {
  3265. AddTceEntryPoint(pUsedComdat);
  3266. #if TCE_DEBUG
  3267. fprintf(stdout, "\r\nLEDATA uses COMDAT %s ", 1 + GetPropName(mpextprop[fi.f_idx]));
  3268. sbModule[sbModule[0]+1] = '\0';
  3269. fprintf(stdout, " module %s, offset %x ", sbModule+1, lfaLast);
  3270. #endif
  3271. }
  3272. }
  3273. else
  3274. {
  3275. if(((APROPUNDEFPTR)mpextprop[fi.f_idx])->au_attr == ATTRUND)
  3276. {
  3277. #if TCE_DEBUG
  3278. fprintf(stdout, "\r\nLEDATA uses EXTDEF %s ", 1 + GetPropName(mpextprop[fi.f_idx]));
  3279. #endif
  3280. ((APROPUNDEFPTR)mpextprop[fi.f_idx])->au_fAlive = TRUE;
  3281. }
  3282. }
  3283. }
  3284. }
  3285. }
  3286. }
  3287. pActiveComdat = NULL;
  3288. }
  3289. #endif