source: trunk/emx/src/emxbind/exec.c@ 2446

Last change on this file since 2446 was 494, checked in by zap, 22 years ago

See ChangeLog.

  • Property cvs2svn:cvs-rev set to 1.6
  • Property svn:eol-style set to native
  • Property svn:executable set to *
File size: 22.9 KB
Line 
1/* exec.c -- Manage executable files
2 Copyright (c) 1991-1996 Eberhard Mattes
3
4This file is part of emxbind.
5
6emxbind is free software; you can redistribute it and/or modify it
7under the terms of the GNU General Public License as published by
8the Free Software Foundation; either version 2, or (at your option)
9any later version.
10
11emxbind is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with emxbind; see the file COPYING. If not, write to
18the Free Software Foundation, 59 Temple Place - Suite 330,
19Boston, MA 02111-1307, USA. */
20
21
22#include <stdio.h>
23#include <stdlib.h>
24#include <string.h>
25#include <sys/moddef.h>
26#include <sys/user.h>
27#include "defs.h"
28#include "emxbind.h"
29
30
31/* The first DOS EXE header read from emxl.exe or emx.exe. */
32
33static struct exe1_header stub_h1;
34
35/* The a.out header to be written to the output executable. */
36
37static struct exec a_out_h;
38
39/* The header of the core dump file. */
40
41static struct user core_h;
42
43/* The offsets of the text section, text relocation table, and data
44 relocation table, respectively, of the source a.out (sub)file. */
45
46static long a_in_text;
47static long a_in_tr;
48static long a_in_dr;
49
50/* The offset of the string table in the source a.out (sub)file. */
51
52static long a_in_str;
53
54/* The offset and size, respectively, of the string table in the
55 destination a.out (sub)file. */
56
57static long a_out_str;
58static long a_out_str_size;
59
60/* The size of the a.out file, including the symbol table and the
61 string table. */
62
63static long a_out_size;
64
65/* The location of the emxl.exe or emx.exe image in the source and
66 destination executable, respectively. */
67
68static long src_image;
69static long dst_image;
70
71/* The size of the DOS stub image. */
72
73static long stub_size;
74
75/* The size of the LX EXE header of the output executable. */
76
77static long os2_hdr_size;
78
79/* The number of text, data, and heap pages, respectively, in the LX
80 executable being created. */
81
82static int text_pages;
83static int data_pages;
84static int heap_pages;
85
86/* The number of pages between the data pages and the heap pages.
87 These are required for moving the heap to the correct address of
88 the a.out subfile. The LX header, however, does not map these
89 pages. */
90
91static int gap_pages;
92
93/* The number of zero bytes to insert between the relocation table of
94 the DOS header and the emx.exe or emxl.exe image. */
95
96static long fill1;
97
98/* The number of zero bytes to insert between the LX header (or the
99 end of the resources, if there are resources) and the a.out
100 header. */
101
102static long fill3;
103
104/* header holds the LX header while it is being built. */
105
106static struct grow header = GROW_INIT;
107
108
109/* Compute the virtual end address of a memory object of an LX
110 file. X is a struct object. */
111
112#define OBJ_END(x) ((x).virt_base + (x).virt_size)
113
114/* Round up to the next multiple of the segment alignment (0x10000). */
115
116#define round_segment(X) ((((X)-1) & ~0xffff) + 0x10000)
117
118
119/* Derive the main module name from the output file name, if not
120 defined by a NAME or LIBRARY statement. Put the main module name
121 into the resident name table. If there is a description
122 (DESCRIPTION statement), put it into the resident name table. */
123
124static void get_module_name (void)
125{
126 char *p, *q;
127
128 if (module_name == NULL)
129 {
130 module_name = xmalloc (FNAME_SIZE);
131 q = out_fname;
132 for (p = out_fname; *p != 0; ++p)
133 if (*p == ':' || *p == '/' || *p == '\\')
134 q = p + 1;
135 p = module_name;
136 while (*q != 0 && *q != '.')
137 *p++ = *q++;
138 *p = 0;
139 }
140 entry_name (&resnames, module_name, 0);
141 if (description != NULL)
142 entry_name (&nonresnames, description, 0);
143}
144
145
146/* Read EXE header and emxbind DOS header of emx.exe */
147
148void read_stub (void)
149{
150 my_read (&stub_h1, sizeof (stub_h1), &stub_file);
151 if (stub_h1.magic != 0x5a4d)
152 error ("invalid stub file");
153 src_image = (long)stub_h1.hdr_size << 4;
154 stub_size = ((long)stub_h1.pages << 9) - src_image;
155 if (stub_h1.last_page != 0)
156 stub_size += stub_h1.last_page - 512;
157}
158
159
160/* Read the a.out header of the input executable. */
161
162void read_a_out_header (void)
163{
164 byte buf[16];
165 int syms;
166
167 a_in_pos = my_tell (&inp_file);
168 my_read (&a_in_h, sizeof (a_in_h), &inp_file);
169 a_out_h = a_in_h;
170 if (N_MAGIC (a_in_h) != ZMAGIC || a_in_h.a_entry != TEXT_BASE)
171 error ("invalid a.out file (header)");
172 a_out_h.a_drsize = 0;
173 a_out_h.a_trsize = 0;
174 my_seek (&inp_file, A_OUT_OFFSET);
175 my_read (buf, sizeof (buf), &inp_file);
176 a_in_text = A_OUT_OFFSET;
177 a_in_data = a_in_text + round_page (a_in_h.a_text);
178 a_in_tr = a_in_data + round_page (a_in_h.a_data);
179 a_in_dr = a_in_tr + a_in_h.a_trsize;
180 a_in_sym = a_in_dr + a_in_h.a_drsize;
181 data_base = round_segment (TEXT_BASE + a_in_h.a_text);
182 text_off = a_in_pos + a_in_text - TEXT_BASE;
183 data_off = a_in_pos + a_in_data - data_base;
184 syms = (a_in_h.a_syms != 0 &&
185 a_in_sym + a_in_h.a_syms + sizeof (a_in_str_size) <=
186 my_size (&inp_file));
187 if (syms)
188 {
189 a_in_str = a_in_sym + a_in_h.a_syms;
190 my_seek (&inp_file, a_in_str);
191 my_read (&a_in_str_size, sizeof (a_in_str_size), &inp_file);
192 }
193 else
194 {
195 a_in_str = a_in_sym;
196 a_in_str_size = 4;
197 }
198 if (syms && !opt_s)
199 {
200 a_out_str = a_in_str;
201 a_out_str_size = a_in_str_size;
202 }
203 else
204 {
205 a_out_str = a_in_sym;
206 a_out_str_size = 4;
207 a_out_h.a_syms = 0;
208 }
209 a_out_str -= a_in_h.a_drsize + a_in_h.a_trsize;
210 a_out_size = a_out_str + a_out_str_size;
211}
212
213
214/* Read the header of the core dump file. */
215
216void read_core (void)
217{
218 my_read (&core_h, sizeof (core_h), &core_file);
219 if (core_h.u_magic != UMAGIC)
220 error ("invalid core file (header)");
221 if (core_h.u_data_base != data_base
222 || core_h.u_data_end != data_base + a_in_h.a_data + a_in_h.a_bss)
223 error ("core file doesn't match a.out file");
224 a_out_h.a_data = round_page (core_h.u_data_end - core_h.u_data_base);
225 a_out_h.a_bss = 0;
226 if (core_h.u_heap_brk > core_h.u_heap_base)
227 {
228 if (core_h.u_heap_brk - core_h.u_heap_base > heap_size)
229 error ("the heap size is too small for the core file's heap");
230 a_out_h.a_data = round_page (core_h.u_heap_brk - core_h.u_data_base);
231 }
232 if (core_h.u_heapobjs_off != 0)
233 error ("%s: multiple heap objects are not supported", opt_c);
234}
235
236
237/* Read the LX header. */
238
239void read_os2_header (void)
240{
241 my_seek (&inp_file, sizeof (inp_h1));
242 my_read (&inp_h2, sizeof (inp_h2), &inp_file);
243 inp_os2_pos = COMBINE (inp_h2.new_lo, inp_h2.new_hi);
244 my_seek (&inp_file, inp_os2_pos);
245 my_read (&os2_h, sizeof (os2_h), &inp_file);
246}
247
248
249/* Read the text and data relocation tables of the input a.out
250 executable. */
251
252void read_reloc (void)
253{
254 if (tr_image == NULL)
255 {
256 my_seek (&inp_file, a_in_tr);
257 tr_image = xmalloc (a_in_h.a_trsize);
258 my_read (tr_image, a_in_h.a_trsize, &inp_file);
259 }
260 if (dr_image == NULL)
261 {
262 my_seek (&inp_file, a_in_dr);
263 dr_image = xmalloc (a_in_h.a_drsize);
264 my_read (dr_image, a_in_h.a_drsize, &inp_file);
265 }
266}
267
268
269/* Read the text and data sections from the input a.out file. */
270
271void read_segs (void)
272{
273 int d_size, t_size;
274
275 if (text_image == NULL)
276 {
277 t_size = round_page (a_in_h.a_text);
278 text_image = xmalloc (t_size);
279 my_seek (&inp_file, a_in_text);
280 my_read (text_image, t_size, &inp_file);
281 }
282 if (data_image == NULL)
283 {
284 d_size = round_page (a_in_h.a_data);
285 data_image = xmalloc (d_size);
286 my_seek (&inp_file, a_in_data);
287 my_read (data_image, d_size, &inp_file);
288 }
289}
290
291
292/* Read the symbol and string tables from the input a.out file. */
293
294void read_sym (void)
295{
296 if (sym_image == NULL)
297 {
298 sym_image = xmalloc (a_in_h.a_syms);
299 str_image = xmalloc (a_in_str_size);
300 my_seek (&inp_file, a_in_sym);
301 my_read (sym_image, a_in_h.a_syms, &inp_file);
302 my_seek (&inp_file, a_in_str);
303 my_read (str_image, a_in_str_size, &inp_file);
304 sym_count = a_in_h.a_syms / sizeof (struct nlist);
305 build_sym_hash_table ();
306 }
307}
308
309
310/* Setup the DOS EXE headers for the destination executable. Compute
311 the location of the LX header. */
312
313void set_exe_header (void)
314{
315 long i;
316
317 i = (stub_h1.reloc_size << 2) + sizeof (out_h1) + sizeof (out_h2);
318#if 1
319 dst_image = (i + 0x0f) & ~0x0f;
320#else
321 dst_image = (i + 0x1ff) & ~0x1ff;
322#endif
323 fill1 = dst_image - i;
324 out_h1 = stub_h1;
325 out_h1.reloc_ptr = sizeof (out_h1) + sizeof (out_h2);
326 out_h1.hdr_size = dst_image >> 4;
327 out_h1.chksum = 0;
328 memset (out_h2.res1, 0, sizeof (out_h2.res1));
329 out_h2.new_lo = out_h2.new_hi = 0;
330 i = os2_hdr_pos = dst_image + stub_size;
331 if (os2_hdr_pos & 0x1ff)
332 os2_hdr_pos = (os2_hdr_pos + 0x1ff) & ~0x1ff;
333 fill2 = os2_hdr_pos - i;
334}
335
336
337/* Add the byte X to the LX header. */
338
339void put_header_byte (byte x)
340{
341 put_grow (&header, &x, sizeof (x));
342}
343
344
345/* Add the 16-bit word X to the LX header. */
346
347void put_header_word (word x)
348{
349 put_grow (&header, &x, sizeof (x));
350}
351
352
353/* Add the 32-bit word X to the LX header. */
354
355void put_header_dword (dword x)
356{
357 put_grow (&header, &x, sizeof (x));
358}
359
360
361/* Add SIZE bytes at SRC to the LX header. */
362
363void put_header_bytes (const void *src, size_t size)
364{
365 put_grow (&header, src, size);
366}
367
368
369/* Setup the OS/2 LX header. */
370
371void set_os2_header (void)
372{
373 dword i, first_heap_page;
374 int j, last_page, cur_page, obj;
375 struct object obj_res;
376
377 exe_flags ();
378 out_h2.new_lo = LOWORD (os2_hdr_pos);
379 out_h2.new_hi = HIWORD (os2_hdr_pos);
380 obj_text.virt_size = a_in_h.a_text;
381 obj_data.virt_size = a_in_h.a_data + a_in_h.a_bss;
382 obj_stk0.virt_size = stack_size;
383 obj_data.virt_base = round_segment (obj_text.virt_base + a_in_h.a_text);
384 obj_heap.virt_base = round_segment (OBJ_END (obj_data));
385 obj_stk0.virt_base = round_segment (OBJ_END (obj_heap));
386 os2_h.stack_esp = obj_stk0.virt_size;
387 text_pages = npages (a_in_h.a_text);
388 heap_pages = 0; gap_pages = 0;
389 if (opt_c != NULL)
390 {
391 data_pages = npages (a_in_h.a_data + a_in_h.a_bss);
392 heap_pages = npages (core_h.u_heap_brk - core_h.u_heap_base);
393
394 /* Compute the number of pages between the last data page
395 and the first heap page, for padding the a.out subfile.
396 These pages are not mapped to any object. Round down! */
397
398 gap_pages = (core_h.u_heap_base - core_h.u_data_end) / 0x1000;
399 }
400 else
401 data_pages = npages (a_in_h.a_data);
402
403 /* The object page table and the fixup page table don't include the
404 pages between the last data page and the first heap page
405 (gap_pages). */
406
407 os2_h.mod_pages = res_pages + text_pages + data_pages + heap_pages;
408 obj_text.map_first = 1;
409 obj_text.map_count = text_pages;
410 obj_data.map_first = obj_text.map_first + obj_text.map_count;
411 obj_data.map_count = data_pages;
412 obj_heap.map_first = obj_data.map_first + obj_data.map_count;
413 obj_heap.map_count = heap_pages;
414 obj_stk0.map_first = obj_heap.map_first + obj_heap.map_count;
415 obj_stk0.map_count = 0;
416
417 /* The object numbers for the text object (OBJ_TEXT+1) and for the
418 data object (OBJ_DATA+1) are fixed, the remaining object numbers
419 are computed here. */
420
421 os2_h.obj_count = 0;
422 os2_h.stack_obj = 0;
423 for (j = 0; j < OBJECTS; ++j)
424 if (obj_h[j].virt_size != 0)
425 {
426 os2_h.obj_count += 1;
427 if (j == OBJ_STK0 && obj_stk0.virt_size != 0)
428 os2_h.stack_obj = os2_h.obj_count;
429 }
430 os2_h.obj_count += res_obj_count;
431
432 get_module_name ();
433 exports ();
434
435 header.len = 0;
436 put_header_bytes (&os2_h, sizeof (os2_h));
437
438 os2_h.obj_offset = header.len;
439 for (j = 0; j < OBJECTS; ++j)
440 if (obj_h[j].virt_size != 0)
441 put_header_bytes (&obj_h[j], sizeof (obj_h[j]));
442 memset (&obj_res, 0, sizeof (obj_res));
443 for (j = 0; j < res_obj_count; ++j)
444 put_header_bytes (&obj_res, sizeof (obj_res));
445 os2_h.pagemap_offset = header.len;
446 for (j = 0; j < text_pages + data_pages; ++j)
447 {
448 put_header_dword (j + res_pages);
449 put_header_word (0x1000);
450 put_header_word (0);
451 }
452 first_heap_page = res_pages + text_pages + data_pages + gap_pages;
453 for (j = 0; j < heap_pages; ++j)
454 {
455 put_header_dword (j + first_heap_page);
456 put_header_word (0x1000);
457 put_header_word (0);
458 }
459 for (j = 0; j < res_pages; ++j)
460 {
461 put_header_dword (j);
462 put_header_word (0x1000);
463 put_header_word (0);
464 }
465
466 if (res_count > 0)
467 {
468 os2_h.rsctab_offset = header.len;
469 put_rsctab ();
470 }
471
472 os2_h.resname_offset = header.len;
473 put_header_bytes (resnames.data, resnames.len);
474 put_header_byte (0);
475
476 os2_h.entry_offset = header.len;
477 put_header_bytes (entry_tab.data, entry_tab.len);
478
479 /* Record the location of the fixup page table and write a dummy
480 fixup page table to be filled-in while creating the fixup record
481 table. Note that there's one additional fixup page table entry
482 to hold the end address of the fixup section for the last
483 page. */
484
485 os2_h.fixpage_offset = header.len;
486 for (j = 0; j <= os2_h.mod_pages; ++j)
487 put_header_dword (0); /* will be patched later */
488
489 /* Record the location of the fixup record table. */
490
491 os2_h.fixrecord_offset = header.len;
492
493 /* Write the fixup record table. Fill-in the fixup page table
494 whenever changing to a new page. Note that the header may move
495 while adding fixup records. */
496
497#define FIXPAGE(PAGE) (((dword *)(header.data + os2_h.fixpage_offset))[PAGE])
498
499 last_page = 0;
500 for (j = 0; j < fixup_len; ++j)
501 {
502 /* Get the object number of the fixup. Note that fixups are
503 sorted by object, then by address. */
504
505 obj = fixup_data[j].obj;
506
507 /* Compute the page number for the fixup. */
508
509 cur_page = div_page (fixup_data[j].addr) + obj_h[obj].map_first - 1;
510
511 /* Abort if the page number is out of range. */
512
513 if (cur_page >= os2_h.mod_pages)
514 error ("internal error 1");
515 if (cur_page < last_page - 1)
516 error ("internal error 4");
517
518 /* Fill-in the fixup page table if we're on a new page. */
519
520 while (last_page <= cur_page)
521 {
522 FIXPAGE (last_page) = header.len - os2_h.fixrecord_offset;
523 ++last_page;
524 }
525
526 /* Add the fixup record to the fixup record table. This may
527 move the header in memory. */
528
529 create_fixup (&fixup_data[j], FALSE);
530
531 /* Treat fixups which cross page bounaries specially. Two fixup
532 records are created for such a fixup, one in the first page,
533 one in the second page involved. The offset for the second
534 page is negative. The method used here doesn't work with
535 overlapping fixups as we move to the next page and can't go
536 back (see internal error 4 above). */
537
538 if ((fixup_data[j].addr & 0x0fff) > 0x0ffc)
539 {
540 FIXPAGE (last_page) = header.len - os2_h.fixrecord_offset;
541 ++last_page;
542 create_fixup (&fixup_data[j], TRUE);
543 }
544 }
545
546 /* Fill-in the remaining entries of the fixup page table. */
547
548 while (last_page <= os2_h.mod_pages)
549 {
550 FIXPAGE (last_page) = header.len - os2_h.fixrecord_offset;
551 ++last_page;
552 }
553
554#undef FIXPAGE
555
556 os2_h.impmod_offset = header.len;
557 put_impmod ();
558
559 os2_h.impprocname_offset = header.len;
560 put_header_bytes (procs.data, procs.len);
561 os2_h.fixup_size = header.len - os2_h.fixpage_offset;
562 put_header_byte (0);
563 os2_hdr_size = header.len;
564
565 i = os2_hdr_pos + os2_hdr_size;
566 if (res_count > 0)
567 {
568 a_out_pos = round_page (i);
569 fill3 = a_out_pos - i;
570 a_out_pos += res_pages * 0x1000 - A_OUT_OFFSET;
571 }
572 else
573 {
574 a_out_pos = round_page (i + A_OUT_OFFSET) - A_OUT_OFFSET;
575 fill3 = a_out_pos - i;
576 }
577 os2_h.loader_size = os2_h.fixpage_offset - os2_h.obj_offset;
578 os2_h.enum_offset = a_out_pos + A_OUT_OFFSET - res_pages * 0x1000;
579 os2_h.instance_demand = data_pages + heap_pages;
580 os2_h.preload_count = res_preload_pages;
581
582 if (nonresnames.len != 0)
583 {
584 os2_h.nonresname_offset = a_out_pos + a_out_size;
585 os2_h.nonresname_size = nonresnames.len;
586 }
587
588 header.len = 0;
589 put_header_bytes (&os2_h, sizeof (os2_h));
590 for (j = 0; j < OBJECTS; ++j)
591 if (obj_h[j].virt_size != 0)
592 put_header_bytes (&obj_h[j], sizeof (obj_h[j]));
593
594 put_res_obj (obj_stk0.map_first + obj_stk0.map_count);
595 header.len = os2_hdr_size;
596}
597
598
599/* Initialize the fixed part of the OS/2 LX header. Fields which are
600 overwritten later are initialized to X. */
601
602void init_os2_header (void)
603{
604 byte b;
605
606 b = 0;
607 put_grow (&procs, &b, 1);
608#define X 0
609 memset (&os2_h, 0, sizeof (os2_h));
610 os2_h.magic = 0x584c; /* LX */
611 os2_h.byte_order = 0; /* Little Endian byte order */
612 os2_h.word_order = 0; /* Little Endian word order */
613 os2_h.level = 0; /* Format level */
614 os2_h.cpu = 2; /* 386 */
615 os2_h.os = 1; /* Operating system type: OS/2 */
616 os2_h.ver = 0; /* Module version */
617 os2_h.mod_flags = 0x200; /* WINDOWCOMPAT */
618 if (!relocatable)
619 os2_h.mod_flags |= 0x10; /* no internal fixups */
620 os2_h.mod_pages = X; /* Number of pages in .exe file*/
621 os2_h.entry_obj = OBJ_TEXT+1; /* Object number for EIP */
622 os2_h.entry_eip = 0; /* EIP */
623 os2_h.stack_obj = X; /* Stack object */
624 os2_h.stack_esp = X; /* ESP */
625 os2_h.pagesize = 0x1000; /* System page size */
626 os2_h.pageshift = 12; /* Page offset shift */
627 os2_h.fixup_size = X; /* Fixup section size */
628 os2_h.fixup_checksum = 0; /* Fixup section checksum */
629 os2_h.loader_size = X; /* Loader section size */
630 os2_h.loader_checksum = 0; /* Loader section checksum */
631 os2_h.obj_offset = X; /* Object table offset */
632 os2_h.obj_count = X; /* Number of objects */
633 os2_h.pagemap_offset = X;
634 os2_h.itermap_offset = 0;
635 os2_h.rsctab_offset = 0;
636 os2_h.rsctab_count = 0;
637 os2_h.resname_offset = X;
638 os2_h.entry_offset = X;
639 os2_h.moddir_offset = 0;
640 os2_h.moddir_count = 0;
641 os2_h.fixpage_offset = X;
642 os2_h.fixrecord_offset = X;
643 os2_h.impmod_offset = X;
644 os2_h.impmod_count = X;
645 os2_h.impprocname_offset = X;
646 os2_h.page_checksum_offset = 0;
647 os2_h.enum_offset = X;
648 os2_h.preload_count = X;
649 os2_h.nonresname_offset = 0;
650 os2_h.nonresname_size = 0;
651 os2_h.nonresname_checksum = 0;
652 os2_h.auto_obj = OBJ_DATA+1;
653 os2_h.debug_offset = 0;
654 os2_h.debug_size = 0;
655 os2_h.instance_preload = 0;
656 os2_h.instance_demand = X;
657 os2_h.heap_size = 0;
658 os2_h.stack_size = 0;
659 obj_text.virt_size = 0;
660 obj_text.virt_base = TEXT_BASE;
661 obj_text.attr_flags = 0x2005; /* readable, executable, big */
662 obj_text.map_first = X;
663 obj_text.map_count = X;
664 obj_text.reserved = 0;
665 obj_data.virt_size = 0;
666 obj_data.virt_base = 0;
667 obj_data.attr_flags = 0x2003; /* readable, writable, big */
668 obj_data.map_first = X;
669 obj_data.map_count = X;
670 obj_data.reserved = 0;
671 obj_heap.virt_size = heap_size;
672 obj_heap.virt_base = 0;
673 obj_heap.attr_flags = 0x2003; /* readable, writable, big */
674 obj_heap.map_first = X;
675 obj_heap.map_count = X;
676 obj_heap.reserved = 0;
677 obj_stk0.virt_size = 0;
678 obj_stk0.virt_base = 0;
679 obj_stk0.attr_flags = 0x2003; /* readable, writable, big */
680 obj_stk0.map_first = X;
681 obj_stk0.map_count = X;
682 obj_stk0.reserved = 0;
683#undef X
684}
685
686
687/* Set the application type in the OS/2 LX header. */
688
689void exe_flags (void)
690{
691 if (opt_f)
692 {
693 os2_h.mod_flags &= ~0x700;
694 os2_h.mod_flags |= 0x100;
695 }
696 else if (opt_p)
697 {
698 os2_h.mod_flags &= ~0x700;
699 os2_h.mod_flags |= 0x300;
700 }
701 else if (opt_w)
702 {
703 os2_h.mod_flags &= ~0x700;
704 os2_h.mod_flags |= 0x200;
705 }
706 else
707 switch (app_type)
708 {
709 case _MDT_NOTWINDOWCOMPAT:
710 os2_h.mod_flags &= ~0x700;
711 os2_h.mod_flags |= 0x100;
712 break;
713 case _MDT_WINDOWAPI:
714 os2_h.mod_flags &= ~0x700;
715 os2_h.mod_flags |= 0x300;
716 break;
717 case _MDT_WINDOWCOMPAT:
718 os2_h.mod_flags &= ~0x700;
719 os2_h.mod_flags |= 0x200;
720 break;
721 }
722 if (dll_flag)
723 {
724 os2_h.mod_flags |= 0x8000;
725 if (!init_global)
726 os2_h.mod_flags |= 0x0004;
727 if (!term_global)
728 os2_h.mod_flags |= 0x40000000;
729 }
730}
731
732
733/* Write the DOS EXE headers, the stub image, and the OS/2 LX header. */
734
735void write_header (void)
736{
737 my_write (&out_h1, sizeof (out_h1), &out_file);
738 my_write (&out_h2, sizeof (out_h2), &out_file);
739 my_seek (&stub_file, stub_h1.reloc_ptr);
740 copy (&stub_file, stub_h1.reloc_size * 4);
741 fill (fill1);
742 my_seek (&stub_file, src_image);
743 copy (&stub_file, stub_size);
744 fill (fill2);
745 if (mode != 'u')
746 {
747 my_write (header.data, os2_hdr_size, &out_file);
748 fill (fill3);
749 }
750}
751
752
753/* Write the non-resident name table. */
754
755void write_nonres (void)
756{
757 if (nonresnames.len != 0)
758 {
759 my_seek (&out_file, os2_h.nonresname_offset);
760 my_write (nonresnames.data, nonresnames.len, &out_file);
761 }
762}
763
764
765/* Copy the a.out subfile (a.out header, text and data sections,
766 symbol table, and string table) to the destination executable. */
767
768void copy_a_out (void)
769{
770 long n, str_len;
771
772 my_write (&a_out_h, sizeof (a_out_h), &out_file);
773 fill (A_OUT_OFFSET - sizeof (a_out_h));
774 my_seek (&inp_file, a_in_text);
775 if (text_image != NULL)
776 my_write (text_image, round_page (a_in_h.a_text), &out_file);
777 else
778 copy (&inp_file, round_page (a_in_h.a_text));
779 if (opt_c != NULL)
780 {
781 my_seek (&core_file, core_h.u_data_off);
782 n = core_h.u_data_end - core_h.u_data_base;
783 copy (&core_file, n);
784 fill (round_page (n) - n);
785 if (core_h.u_heap_brk > core_h.u_heap_base)
786 {
787 fill (core_h.u_heap_base - round_page (core_h.u_data_end));
788 my_seek (&core_file, core_h.u_heap_off);
789 n = core_h.u_heap_brk - core_h.u_heap_base;
790 copy (&core_file, n);
791 fill (round_page (n) - n);
792 }
793 }
794 else if (data_image != NULL)
795 my_write (data_image, round_page (a_in_h.a_data), &out_file);
796 else
797 {
798 my_seek (&inp_file, a_in_data);
799 copy (&inp_file, round_page (a_in_h.a_data));
800 }
801 if (a_out_h.a_syms == 0)
802 {
803 str_len = 4;
804 my_write (&str_len, sizeof (str_len), &out_file);
805 }
806 else
807 {
808 if (sym_image != NULL)
809 my_write (sym_image, a_out_h.a_syms, &out_file);
810 else
811 {
812 my_seek (&inp_file, a_in_sym);
813 copy (&inp_file, a_out_h.a_syms);
814 }
815 if (str_image != NULL)
816 my_write (str_image, a_out_str_size, &out_file);
817 else
818 {
819 my_seek (&inp_file, a_in_str);
820 copy (&inp_file, a_out_str_size);
821 }
822 }
823}
824
825
826/* Copy SIZE bytes from the file SRC to the destination executable
827 file (out_file). */
828
829void copy (struct file *src, long size)
830{
831 char buf[BUFSIZ];
832 size_t n;
833
834 while (size > 0)
835 {
836 n = MIN (size, BUFSIZ);
837 my_read (buf, n, src);
838 my_write (buf, n, &out_file);
839 size -= n;
840 }
841}
842
843
844/* Write COUNT zero bytes to the destination executable file
845 (out_file). */
846
847void fill (long count)
848{
849 char buf[BUFSIZ];
850 size_t n;
851
852 memset (buf, 0, BUFSIZ);
853 while (count > 0)
854 {
855 n = MIN (count, BUFSIZ);
856 my_write (buf, n, &out_file);
857 count -= n;
858 }
859}
Note: See TracBrowser for help on using the repository browser.