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.

794 lines
24 KiB

  1. /*
  2. * Copyright Microsoft Corporation 1986,1987
  3. *
  4. * This Module contains Proprietary Information of Microsoft
  5. * Corporation and should be treated as Confidential.
  6. */
  7. /*
  8. * NEWOUT3.C
  9. *
  10. * Functions to output DOS3 exe.
  11. */
  12. #include <minlit.h> /* Types and constants */
  13. #include <bndtrn.h> /* Types and constants */
  14. #include <bndrel.h> /* Types and constants */
  15. #include <lnkio.h> /* Linker I/O definitions */
  16. #include <lnkmsg.h> /* Error messages */
  17. #include <extern.h> /* External declarations */
  18. #include <sys\types.h>
  19. #include <sys\stat.h>
  20. #include <newexe.h>
  21. #define E_VERNO(x) (x).e_sym_tab
  22. #define IBWCHKSUM 18L
  23. #define IBWCSIP 20L
  24. #define CBRUN sizeof(struct exe_hdr)
  25. #define CBRUN_OLD 0x1e /* Size of header for DOS 1, 2 & 3 */
  26. #define EMAGIC 0x5A4D /* Old magic number */
  27. FTYPE parity; /* For DOS3 checksum */
  28. SEGTYPE segAdjCom = SEGNIL; /* Segment moved by 0x100 in .com programs */
  29. /*
  30. * LOCAL FUNCTION PROTOTYPES
  31. */
  32. #if OVERLAYS
  33. LOCAL void NEAR OutRlc(IOVTYPE iov);
  34. #endif
  35. #if QBLIB
  36. LOCAL unsigned short NEAR SkipLead0(unsigned short seg);
  37. LOCAL void NEAR FixQStart(long cbFix,struct exe_hdr *prun);
  38. #endif
  39. /****************************************************************
  40. * *
  41. * OutRlc: *
  42. * *
  43. * This function writes the reloc table to the run file. *
  44. * NOTE: relocation table entries must be a factor of the *
  45. * virtual memory page length. *
  46. * *
  47. ****************************************************************/
  48. #if OVERLAYS
  49. LOCAL void NEAR OutRlc(IOVTYPE iov)
  50. {
  51. RUNRLC FAR *pRlc;
  52. pRlc = &mpiovRlc[iov];
  53. WriteExe(pRlc->rgRlc, CBRLC*pRlc->count);
  54. }
  55. #endif
  56. void OutHeader (prun)
  57. struct exe_hdr *prun;
  58. {
  59. WriteExe(prun, E_LFARLC(*prun));
  60. }
  61. #if INMEM
  62. #if CPU8086 OR CPU286
  63. #include <dos.h>
  64. /*
  65. * WriteExe : write() with a far buffer
  66. *
  67. * Emulate write() except use a far buffer. Call the system
  68. * directly.
  69. *
  70. * Returns:
  71. * 0 if error, else number of bytes written.
  72. */
  73. LOCAL int WriteExe (fh, buf, n)
  74. int fh; /* File handle */
  75. char FAR *buf; /* Buffer to store bytes in */
  76. int n; /* # bytes to write */
  77. {
  78. #if OSMSDOS
  79. #if CPU8086
  80. union REGS regs; /* Non-segment registers */
  81. struct SREGS sregs; /* Segment registers */
  82. regs.x.ax = 0x4000;
  83. regs.x.bx = fh;
  84. regs.x.cx = n;
  85. sregs.ds = FP_SEG(buf);
  86. sregs.es = sregs.ds;
  87. regs.x.dx = FP_OFF(buf);
  88. intdosx(&regs,&regs,&sregs);
  89. if(regs.x.cflag)
  90. return(0);
  91. return(regs.x.ax);
  92. #else
  93. ERROR
  94. #endif
  95. #endif /* OSMSDOS */
  96. #if OSXENIX
  97. char mybuf[PAGLEN];
  98. int cppage;
  99. char *p;
  100. while(n > 0)
  101. {
  102. cppage = n > PAGLEN ? PAGLEN : n;
  103. for(p = mybuf; p < mybuf[cppage]; *p++ = *buf++);
  104. if(write(fh,mybuf,cppage) != cppage)
  105. return(0);
  106. n -= cppage;
  107. }
  108. #endif
  109. }
  110. #else
  111. #define readfar read
  112. #endif
  113. extern WORD saExe;
  114. LOCAL void OutExeBlock (seg1, segEnd)
  115. {
  116. long cb;
  117. unsigned cbWrite;
  118. WORD sa;
  119. FTYPE parity; /* 1 odd, 0 even */
  120. fflush(bsRunfile);
  121. parity = 0;
  122. cb = ((long)(mpsegsa[segEnd] - mpsegsa[seg1]) << 4) + mpsegcb[segEnd] +
  123. mpsegraFirst[segEnd];
  124. sa = saExe;
  125. while(cb)
  126. {
  127. if(cb > 0xfff0)
  128. cbWrite = 0xfff0;
  129. else
  130. cbWrite = cb;
  131. ChkSum(cbWrite,(BYTE FAR *)((long) sa << 16),parity);
  132. parity = parity ^ (cbWrite & 1);
  133. if(WriteExe(fileno(bsRunfile),(long)sa << 16,cbWrite) != cbWrite)
  134. {
  135. ExitCode = 4;
  136. Fatal(ER_spcrun); /* Fatal error */
  137. }
  138. cb -= cbWrite;
  139. sa += 0xfff;
  140. }
  141. }
  142. #endif /* INMEM */
  143. #if QBLIB
  144. /*
  145. * SkipLead0 : Output a segment, skipping leading zeroes
  146. *
  147. * Count the number of leading 0s in the segment and write
  148. * a word holding the count. Then write the segment starting
  149. * with the first nonzero byte. Return number of leading 0s.
  150. *
  151. * Parameters:
  152. * seg Segment number
  153. * Returns:
  154. * Number of leading 0s
  155. */
  156. WORD NEAR SkipLead0 (SEGTYPE seg)
  157. {
  158. BYTE FAR *pSegImage; // Segment memory image
  159. long cZero; // Number of zero bytes at the begin of the segment
  160. WORD cbSkip; /* # bytes of leading 0s */
  161. DWORD cbRemain; // no-zero bytes
  162. // Initialize starting address
  163. pSegImage = mpsegMem[seg] + mpsegraFirst[seg];
  164. // Count zero bytes at segment start
  165. for (cZero = 0; cZero < mpsegcb[seg] && *pSegImage == 0; cZero++, pSegImage++)
  166. ;
  167. // If segment is 64K and entirely 0s, write 0 and 64k of zeros.
  168. if (cZero == mpsegcb[seg] && cZero == LXIVK)
  169. {
  170. cbSkip = 0;
  171. pSegImage = mpsegMem[seg] + mpsegraFirst[seg];
  172. cbRemain = LXIVK;
  173. }
  174. else
  175. {
  176. cbSkip = (WORD) cZero;
  177. cbRemain = mpsegcb[seg] - cZero;
  178. }
  179. WriteExe((char FAR *)&cbSkip, CBWORD);
  180. WriteExe(pSegImage, cbRemain);
  181. return(cbSkip);
  182. }
  183. /*
  184. * FixQStart : Fix up (patch) .QLB starting address
  185. *
  186. * Parameters:
  187. * cbFix Number of bytes skipped (may be negative)
  188. * prun Pointer to DOS3 exe header
  189. * ASSUMES:
  190. * File pointer is at CS:IP.
  191. */
  192. void NEAR FixQStart (cbFix,prun)
  193. long cbFix;
  194. struct exe_hdr *prun;
  195. {
  196. /*
  197. * WARNNG: dra must be long since it holds numbers in the range
  198. * -4 to 0x10000, inclusive.
  199. */
  200. long dra; /* Delta for raStart adjustment */
  201. SATYPE saStart; /* Initial CS */
  202. saStart = prun->e_cs; /* Initialize */
  203. /*
  204. * Adjust initial CS:IP for .QLB's since it is used by loader
  205. * to point to symbol table, and all addresses are off by the
  206. * amount of leading 0s skipped. Luckily CS:IP comes right after
  207. * checksum so we don't have to seek.
  208. * First, normalize CS:IP downward if underflow will occur.
  209. */
  210. if((dra = cbFix - raStart) > 0)
  211. {
  212. raStart += (dra + 0xf) & ~0xf;
  213. saStart -= (SATYPE) ((dra + 0xf) >> 4);
  214. }
  215. /* Patch the header */
  216. OutWord((WORD) (raStart -= cbFix));
  217. OutWord(saStart);
  218. }
  219. #endif /*QBLIB*/
  220. /*
  221. * OutDos3Exe:
  222. *
  223. * Output DOS3-format executable file.
  224. * Called by OutRunfile.
  225. */
  226. void NEAR OutDos3Exe()
  227. {
  228. SEGTYPE seg; /* Current segment */
  229. struct exe_hdr run; /* Executable header */
  230. WORD cbPadding; /* # bytes of padding */
  231. WORD cb; /* # bytes on last page */
  232. WORD pn; /* # pages */
  233. long lfaPrev; /* Previous file offset */
  234. RATYPE ra; /* Current address offset */
  235. SATYPE sa; /* Current address base */
  236. SEGTYPE segIovFirst; /* First segment in overlay */
  237. SEGTYPE segFinaliov; /* Last seg in overlay to output */
  238. SEGTYPE segIovLast; /* Last segment in overlay */
  239. long cbDirectory; /* # bytes in entire header */
  240. WORD cparDirectory; /* # para. in entire header */
  241. SEGTYPE segStack; /* Segment index of stack segment */
  242. #if OVERLAYS
  243. IOVTYPE iov; /* Current overlay number */
  244. #endif
  245. #if FEXEPACK
  246. FTYPE fSave; /* Scratch var. */
  247. #endif
  248. SATYPE saStart; /* Start of current segment */
  249. WORD segcbDelta = 0; /* For /TINY segment size adjustment */
  250. WORD fOrgStriped = FALSE;
  251. /* TRUE when 0x100 bytes striped */
  252. WORD tmp;
  253. #if OVERLAYS
  254. DWORD ovlLfa; /* Seek offset for overlay */
  255. DWORD imageSize; /* Overlay memory image size */
  256. DWORD ovlRootBeg; /* Seek offset to the begin of root memory image */
  257. WORD ovlDataOffset;
  258. #endif
  259. #if QBLIB
  260. /* Count of bytes skipped in the load image must be a long since
  261. * it can be negative (if there were less than 4 leading 0s)
  262. * or greater than 0x8000.
  263. */
  264. long cbSkip = 0; /* # bytes skipped */
  265. extern SEGTYPE segQCode; /* .QLB code segment */
  266. #endif
  267. if (fBinary)
  268. {
  269. #if OVERLAYS
  270. if (fOverlays)
  271. Fatal(ER_swbadovl, "/TINY");
  272. /* Overlays not allowed in .COM */
  273. #endif
  274. if (mpiovRlc[0].count)
  275. Fatal(ER_binary); /* Run time relocations not allowed in .COM */
  276. }
  277. memset(&run,0,sizeof(run)); /* Clear everything in fixed header */
  278. E_MAGIC(run) = EMAGIC; /* Magic number */
  279. if (vFlagsOthers & NENEWFILES || fDOSExtended)
  280. {
  281. /* DOS header is 0x40 bytes long */
  282. E_LFARLC(run) = CBRUN; /* Offset of loadtime relocations */
  283. if (vFlagsOthers & NENEWFILES)
  284. E_FLAGS(run) |= EKNOWEAS;
  285. if (fDOSExtended)
  286. E_FLAGS(run) |= EDOSEXTENDED;
  287. }
  288. else
  289. {
  290. /* DOS header is 0x1e bytes long */
  291. E_LFARLC(run) = CBRUN_OLD; /* Offset of loadtime relocations */
  292. }
  293. E_VERNO(run) = 1; /* DOS ver. for compatibility only */
  294. lfaPrev = 0L;
  295. #if OVERLAYS
  296. for(iov = 0; iov < (IOVTYPE) iovMac; ++iov) /* Loop thru overlays */
  297. {
  298. #endif
  299. /* Get size of overlay */
  300. cb = 0;
  301. pn = 0;
  302. #if OVERLAYS
  303. /* Find lowest seg in overlay */
  304. for(seg = 1; seg <= segLast && mpsegiov[seg] != iov; ++seg)
  305. #else
  306. seg = 1;
  307. #endif
  308. /* If no overlay to output, we're done with this one. */
  309. if(seg > segLast)
  310. #if OVERLAYS
  311. continue;
  312. #else
  313. return;
  314. #endif
  315. /* Get starting address of lowest segment */
  316. segIovFirst = seg;
  317. ra = mpsegraFirst[seg];
  318. sa = mpsegsa[seg];
  319. /* Find the last segment in the overlay */
  320. segIovLast = SEGNIL;
  321. for(seg = segLast; seg; --seg)
  322. {
  323. #if OVERLAYS
  324. if(mpsegiov[seg] == iov)
  325. {
  326. #endif
  327. if(segIovLast == SEGNIL) segIovLast = seg;
  328. if(!cparMaxAlloc) break;
  329. if((mpsegFlags[seg] & FNOTEMPTY) == FNOTEMPTY) break;
  330. #if OVERLAYS
  331. }
  332. #endif
  333. }
  334. /* If no data in overlay, we're done with it. */
  335. if(!seg)
  336. #if OVERLAYS
  337. continue;
  338. #else
  339. return;
  340. #endif
  341. /* Get size in between 1st, last segs in this overlay */
  342. segFinaliov = seg;
  343. sa = mpsegsa[seg] - sa - 1;
  344. ra = mpsegraFirst[seg] - ra + 16;
  345. /* Normalize */
  346. sa += (SATYPE) (ra >> 4);
  347. ra &= 0xF;
  348. /* Take into account size of last segment */
  349. if(mpsegcb[seg] + ra < LXIVK)
  350. ra += (WORD) mpsegcb[seg];
  351. else
  352. {
  353. ra -= LXIVK - mpsegcb[seg];
  354. sa += 0x1000;
  355. }
  356. /* Normalize again */
  357. sa += (SATYPE) (ra >> 4);
  358. ra &= 0xF;
  359. /* Determine # pages, bytes on last page */
  360. pn = sa >> 5;
  361. cb = (WORD) (((sa << 4) + ra) & MASKRB);
  362. E_CBLP(run) = cb;
  363. if(cb)
  364. {
  365. cb = 0x200 - cb;
  366. ++pn;
  367. }
  368. /* If empty overlay, skip it */
  369. #if OVERLAYS
  370. if(iov && !pn)
  371. continue;
  372. #else
  373. if(!pn) return;
  374. #endif
  375. vchksum = parity = 0; /* Initialize check sum */
  376. if (segStart == SEGNIL)
  377. {
  378. if (fBinary)
  379. OutWarn(ER_comstart);
  380. #if 0
  381. else
  382. OutWarn(ER_nostartaddr);
  383. #endif
  384. }
  385. else if (mpsegiov[segStart] != IOVROOT)
  386. Fatal(ER_ovlstart); /* Starting address can't be in overlay */
  387. E_CS(run) = mpsegsa[segStart]; /* Base of starting segment */
  388. E_IP(run) = (WORD) raStart; /* Offset of starting procedure */
  389. #if QBLIB
  390. /*
  391. * For .QLB, set minalloc field to an impossible amount to force
  392. * DOS3 loader to abort.
  393. */
  394. if(fQlib)
  395. E_MINALLOC(run) = 0xffff;
  396. else
  397. #endif
  398. /* If no uninitialized segments, minalloc = 0 */
  399. if (segFinaliov == segIovLast)
  400. E_MINALLOC(run) = 0;
  401. else
  402. {
  403. /* Otherwise determine the minalloc value: */
  404. /* sa:ra is end of overlay being output. Find empty area size */
  405. sa = mpsegsa[segIovLast] - sa - 1;
  406. ra = mpsegraFirst[segIovLast] - ra + 0x10;
  407. /* Add in last segment size */
  408. if(mpsegcb[segIovLast] + ra < LXIVK) ra += mpsegcb[segIovLast];
  409. else
  410. {
  411. ra -= LXIVK - mpsegcb[segIovLast];
  412. sa += 0x1000;
  413. }
  414. /* Normalize */
  415. sa += (SATYPE) (ra >> 4);
  416. ra &= 0xF;
  417. /* Set field with min. no of para.s above image */
  418. E_MINALLOC(run) = (WORD) (sa + ((ra + 0xF) >> 4));
  419. /* If /HIGH not given, then cparmaxAlloc = max(maxalloc,minalloc) */
  420. if(cparMaxAlloc && E_MINALLOC(run) > cparMaxAlloc)
  421. cparMaxAlloc = E_MINALLOC(run);
  422. }
  423. E_MAXALLOC(run) = cparMaxAlloc;
  424. #if OVERLAYS
  425. E_CRLC(run) = mpiovRlc[iov].count;
  426. #else
  427. E_CRLC(run) = mpiovRlc[0].count;
  428. #endif
  429. segStack = mpgsnseg[gsnStack];
  430. E_SS(run) = mpsegsa[segStack];
  431. E_SP(run) = (WORD) (cbStack + mpsegraFirst[segStack]);
  432. E_CSUM(run) = 0;
  433. E_CP(run) = pn;
  434. /* Get true size of header */
  435. #if OVERLAYS
  436. cbDirectory = (long) E_LFARLC(run) + ((long) mpiovRlc[iov].count << 2);
  437. #else
  438. cbDirectory = (long) E_LFARLC(run) + ((long) mpiovRlc[0].count << 2);
  439. #endif
  440. /* Get padding needed for header */
  441. if (fBinary)
  442. cbPadding = 0;
  443. else
  444. cbPadding = (0x200 - ((WORD) cbDirectory & 0x1FF)) & 0x1FF;
  445. /* Pages in header */
  446. pn = (WORD)((cbDirectory + 0x1FF) >> 9);
  447. cparDirectory = pn << SHPNTOPAR; /* Paragraphs in header */
  448. E_CPARHDR(run) = cparDirectory; /* Store in header */
  449. E_CP(run) += pn; /* Add header pages to file size */
  450. #if OVERLAYS
  451. E_OVNO(run) = iov;
  452. #else
  453. E_OVNO(run) = 0;
  454. #endif
  455. ovlLfa = ftell(bsRunfile);
  456. if (fBinary)
  457. {
  458. if (E_IP(run) != 0 && E_IP(run) != 0x100)
  459. OutWarn(ER_comstart);
  460. }
  461. else
  462. OutHeader(&run);
  463. /* Output relocation table. Turn exepack off first. */
  464. #if FEXEPACK
  465. fSave = fExePack;
  466. fExePack = FALSE;
  467. #endif
  468. #if OVERLAYS
  469. if (!fBinary)
  470. OutRlc(iov);
  471. #else
  472. if (!fBinary)
  473. OutRlc();
  474. #endif
  475. /* Restore exepack */
  476. #if FEXEPACK
  477. fExePack = fSave;
  478. #endif
  479. /* Output padding */
  480. WriteZeros(cbPadding);
  481. ra = mpsegraFirst[segIovFirst]; /* Offset of first segment */
  482. sa = mpsegsa[segIovFirst]; /* Base of first segment */
  483. #if INMEM
  484. if(saExe)
  485. OutExeBlock(segIovFirst,segFinaliov);
  486. else
  487. #endif
  488. /* Loop through segs in overlay */
  489. if (!iov)
  490. ovlRootBeg = ftell(bsRunfile);
  491. for(seg = segIovFirst; seg <= segFinaliov; ++seg)
  492. {
  493. #if OVERLAYS
  494. if(mpsegiov[seg] == iov)
  495. {
  496. #endif
  497. /*
  498. * Pad up to start of segment. First determine destination
  499. * segment address. We could just use mpsegsa[seg] were it
  500. * not for packcode.
  501. */
  502. saStart = (SATYPE) (mpsegsa[seg] + (mpsegraFirst[seg] >> 4));
  503. tmp = 0;
  504. while(ra != (mpsegraFirst[seg] & 0xf) || sa < saStart)
  505. {
  506. #if FEXEPACK
  507. if (fExePack)
  508. OutPack("\0", 1);
  509. else
  510. #endif
  511. tmp++;
  512. if(++ra > 0xF)
  513. {
  514. ra &= 0xF;
  515. ++sa;
  516. }
  517. parity ^= 1;
  518. }
  519. if (!fExePack && tmp)
  520. WriteZeros(tmp);
  521. /* Output the segment and update the address */
  522. #if QBLIB
  523. /*
  524. * If /QUICKLIB and segment is 1st in DGROUP or 1st code,
  525. * skip leading 0s and adjust the count, less 2 for the
  526. * count word.
  527. */
  528. if(fQlib && (seg == mpgsnseg[mpggrgsn[ggrDGroup]] ||
  529. seg == segQCode))
  530. cbSkip += (long) SkipLead0(seg) - 2;
  531. else
  532. #endif
  533. {
  534. if (fBinary && !fOrgStriped && mpsegcb[seg] > 0x100)
  535. {
  536. /*
  537. * For .Com files strip first 0x100 bytes
  538. * from the first non-empyt segment
  539. */
  540. mpsegraFirst[seg] += E_IP(run);
  541. mpsegcb[seg] -= E_IP(run);
  542. segcbDelta = E_IP(run);
  543. fOrgStriped = TRUE;
  544. segAdjCom = seg;
  545. }
  546. if (mpsegMem[seg])
  547. {
  548. #if FEXEPACK
  549. if (fExePack)
  550. OutPack(mpsegMem[seg] + mpsegraFirst[seg], mpsegcb[seg]);
  551. else
  552. #endif
  553. WriteExe(mpsegMem[seg] + mpsegraFirst[seg], mpsegcb[seg]);
  554. if (seg != mpgsnseg[gsnOvlData])
  555. FFREE(mpsegMem[seg]);
  556. }
  557. }
  558. mpsegcb[seg] += segcbDelta;
  559. segcbDelta = 0;
  560. sa += (WORD)(mpsegcb[seg] >> 4);
  561. ra += (WORD)(mpsegcb[seg] & 0xF);
  562. if(ra > 0xF)
  563. {
  564. ra &= 0xF;
  565. ++sa;
  566. }
  567. #if OVERLAYS
  568. }
  569. #endif
  570. }
  571. #if FALSE
  572. if (!fBinary)
  573. {
  574. /* Complement checksum, go to checksum field and output it. */
  575. vchksum = (~vchksum) & ~(~0 << WORDLN);
  576. fseek(bsRunfile,lfaPrev + IBWCHKSUM,0);
  577. OutWord(vchksum);
  578. }
  579. #endif
  580. #if QBLIB
  581. /*
  582. * If /QUICKLIB, patch the starting address which has been
  583. * invalidated by processing leading 0s.
  584. */
  585. if(fQlib)
  586. {
  587. // Seek to the CS:IP field
  588. fseek(bsRunfile,lfaPrev + IBWCSIP,0);
  589. FixQStart(cbSkip,&run);
  590. }
  591. #endif
  592. #if FEXEPACK
  593. /* Finish up with exepack stuff if necessary */
  594. if (fExePack)
  595. {
  596. EndPack(&run);
  597. cb = 0x1ff & (0x200 - E_CBLP(run)); /* Correct cb */
  598. fExePack = FALSE; /* In case of overlays */
  599. }
  600. #endif
  601. #if OVERLAYS
  602. /*
  603. * If not last overlay: return to end of file, pad to page boundary,
  604. * and get length of file.
  605. */
  606. fseek(bsRunfile,0L,2);
  607. if (iov != (IOVTYPE) (iovMac - 1))
  608. {
  609. while(cb--) OutByte(bsRunfile,'\0');
  610. }
  611. lfaPrev = ftell(bsRunfile);
  612. if (fDynamic)
  613. {
  614. // Update $$MPOVLLFA and $$MPOVLSIZE tables
  615. //
  616. // OVERLAY_DATA --> +-------------+
  617. // | DW $$CGSN |
  618. // +-------------+
  619. // | DW $$COVL |
  620. // +-------------+
  621. // | $$MPGSNBASE |
  622. // | osnMac * DW |
  623. // +-------------+
  624. // | $$MPGSNOVL |
  625. // | osnMac * DW |
  626. // +-------------+
  627. // | $$MPOVLLFA |
  628. // | iovMac * DD |
  629. // +-------------+
  630. // | $$MPOVLSIZE |
  631. // | iovMac * DD |
  632. // +-------------+
  633. vgsnCur = gsnOvlData;
  634. ovlDataOffset = 4 + (osnMac << 2) + iov * sizeof(DWORD);
  635. MoveToVm(sizeof(DWORD), (BYTE *) &ovlLfa, mpgsnseg[gsnOvlData], ovlDataOffset);
  636. ovlDataOffset += iovMac << 2;
  637. // Exclude the header size
  638. imageSize = ((DWORD) (E_CP(run) - (E_CPARHDR(run) >> SHPNTOPAR) - 1) << 9) + (E_CBLP(run) ? E_CBLP(run) : 512);
  639. imageSize = ((imageSize + 0xf) & ~0xf) >> 4;
  640. imageSize += E_MINALLOC(run);
  641. if ((imageSize<<4) > LXIVK && iov)
  642. Fatal(ER_ovl64k, iov);
  643. MoveToVm(sizeof(DWORD), (BYTE *) &imageSize, mpgsnseg[gsnOvlData], ovlDataOffset);
  644. }
  645. }
  646. #endif
  647. if (E_MINALLOC(run) == 0 && E_MAXALLOC(run) == 0)
  648. OutError(ER_nosegdef); /* No code or initialized data in .EXE */
  649. if (fDynamic)
  650. {
  651. // Patch $$MPOVLLFA and $$MPOVLSIZE table in the .EXE file
  652. seg = mpgsnseg[gsnOvlData];
  653. fseek(bsRunfile, ovlRootBeg + ((long) mpsegsa[seg] << 4), 0);
  654. WriteExe(mpsegMem[seg] + mpsegraFirst[seg], mpsegcb[seg]);
  655. FFREE(mpsegMem[seg]);
  656. }
  657. if (fExeStrSeen)
  658. {
  659. fseek(bsRunfile,0L,2);
  660. WriteExe(ExeStrBuf, ExeStrLen);
  661. }
  662. #if SYMDEB
  663. if (fSymdeb)
  664. {
  665. if (fBinary)
  666. {
  667. /*
  668. * For .COM files CV info goes into separate file.
  669. */
  670. SBTYPE sbDbg; /* .DBG file name */
  671. AHTEPTR hte; /* Hash table entry address */
  672. struct _stat fileInfo;
  673. _fstat(fileno(bsRunfile), &fileInfo);
  674. CloseFile(bsRunfile);
  675. hte = (AHTEPTR ) FetchSym(rhteRunfile,FALSE);
  676. /* Get run file name */
  677. #if OSMSDOS
  678. if(hte->cch[2] != ':')
  679. { /* If no drive spec */
  680. sbDbg[1] = chRunFile;
  681. /* Use saved drive letter */
  682. sbDbg[2] = ':'; /* Put in colon */
  683. sbDbg[0] = '\002'; /* Set length */
  684. }
  685. else
  686. sbDbg[0] = '\0'; /* Length is zero */
  687. memcpy(&sbDbg[B2W(sbDbg[0]) + 1],&GetFarSb(hte->cch)[1],B2W(hte->cch[0]));
  688. /* Get name from hash table */
  689. sbDbg[0] += (BYTE)hte->cch[0];
  690. /* Fix length */
  691. #else
  692. memcpy(sbDbg,GetFarSb(hte->cch),B2W(hte->cch[0]) + 1);
  693. /* Get name from hash table */
  694. #endif
  695. UpdateFileParts(sbDbg, sbDotDbg);
  696. /* Force extension to .DBG */
  697. sbDbg[B2W(sbDbg[0]) + 1] = '\0';
  698. /* Null-terminate name */
  699. if((bsRunfile = fopen(&sbDbg[1], WRBIN)) == NULL)
  700. Fatal(ER_openw, &sbDbg[1]);
  701. #if OSMSDOS
  702. setvbuf(bsRunfile,bigbuf,_IOFBF,sizeof(bigbuf));
  703. #endif
  704. /* Write time stamp into .DBG file */
  705. WriteExe(&fileInfo.st_atime, sizeof(time_t));
  706. }
  707. OutDebSections(); /* Generate ISLAND sections */
  708. }
  709. #endif
  710. }