source: vendor/emx/current/src/emxbind/exec.c

Last change on this file was 18, checked in by bird, 23 years ago

Initial revision

  • Property cvs2svn:cvs-rev set to 1.1
  • Property svn:eol-style set to native
  • Property svn:executable set to *
File size: 28.2 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/* Magic number for a.out executable files as used by emx. */
32
33#define A_OUT_MAGIC 0x010b
34
35
36/* String for relaxed checking of emxl.exe or emx.exe. */
37
38static char *relaxed = "emx ";
39
40/* String for strict checking of emxl.exe or emx.exe, including the
41 version number. */
42
43static char *version = "emx " VERSION;
44
45/* The first DOS EXE header read from emxl.exe or emx.exe. */
46
47static struct exe1_header emx_h1;
48
49/* The a.out header to be written to the output executable. */
50
51static struct a_out_header a_out_h;
52
53/* The header of the core dump file. */
54
55static struct user core_h;
56
57/* The offsets of the text section, text relocation table, and data
58 relocation table, respectively, of the source a.out (sub)file. */
59
60static long a_in_text;
61static long a_in_tr;
62static long a_in_dr;
63
64/* The offset of the string table in the source a.out (sub)file. */
65
66static long a_in_str;
67
68/* The offset and size, respectively, of the string table in the
69 destination a.out (sub)file. */
70
71static long a_out_str;
72static long a_out_str_size;
73
74/* The size of the a.out file, including the symbol table and the
75 string table. */
76
77static long a_out_size;
78
79/* The location of the emxl.exe or emx.exe image in the source and
80 destination executable, respectively. */
81
82static long src_image;
83static long dst_image;
84
85/* The size of the emxl.exe or emx.exe image. */
86
87static long emx_size;
88
89/* The size of the LX EXE header of the output executable. */
90
91static long os2_hdr_size;
92
93/* The number of text, data, and heap pages, respectively, in the LX
94 executable being created. */
95
96static int text_pages;
97static int data_pages;
98static int heap_pages;
99
100/* The number of pages between the data pages and the heap pages.
101 These are required for moving the heap to the correct address of
102 the a.out subfile. The LX header, however, does not map these
103 pages. */
104
105static int gap_pages;
106
107/* The number of zero bytes to insert between the relocation table of
108 the DOS header and the emx.exe or emxl.exe image. */
109
110static long fill1;
111
112/* The number of zero bytes to insert between the LX header (or the
113 end of the resources, if there are resources) and the a.out
114 header. */
115
116static long fill3;
117
118/* header holds the LX header while it is being built. */
119
120static struct grow header = GROW_INIT;
121
122
123/* Return the minimum of A and B. */
124
125#define min(a,b) (((a) < (b)) ? (a) : (b))
126
127/* Compute the virtual end address of a memory object of an LX
128 file. X is a struct object. */
129
130#define OBJ_END(x) ((x).virt_base + (x).virt_size)
131
132/* Round up to the next multiple of the segment alignment (0x10000). */
133
134#define round_segment(X) ((((X)-1) & ~0xffff) + 0x10000)
135
136
137/* Derive the main module name from the output file name, if not
138 defined by a NAME or LIBRARY statement. Put the main module name
139 into the resident name table. If there is a description
140 (DESCRIPTION statement), put it into the resident name table. */
141
142static void get_module_name (void)
143{
144 char *p, *q;
145
146 if (module_name == NULL)
147 {
148 module_name = xmalloc (FNAME_SIZE);
149 q = out_fname;
150 for (p = out_fname; *p != 0; ++p)
151 if (*p == ':' || *p == '/' || *p == '\\')
152 q = p + 1;
153 p = module_name;
154 while (*q != 0 && *q != '.')
155 *p++ = *q++;
156 *p = 0;
157 }
158 entry_name (&resnames, module_name, 0);
159 if (description != NULL)
160 entry_name (&nonresnames, description, 0);
161}
162
163
164/* Check the OS/2 emxbind header (patch area). See also crt0.s. */
165
166static int check_os2_bind_header (void)
167{
168 if (os2_bind_h.text_base != TEXT_BASE
169 || os2_bind_h.text_end != TEXT_BASE + a_in_h.text_size
170 || os2_bind_h.data_base != data_base)
171 return FALSE;
172 if (memchr (os2_bind_h.options, 0, sizeof (os2_bind_h.options)) == NULL)
173 return FALSE;
174 return TRUE;
175}
176
177
178/* Read EXE header and emxbind DOS header of emx.exe */
179
180void read_emx (void)
181{
182 my_read (&emx_h1, sizeof (emx_h1), &emx_file);
183 if (emx_h1.magic != 0x5a4d)
184 error ("invalid <emx>.exe");
185 src_image = (long)emx_h1.hdr_size << 4;
186 emx_size = ((long)emx_h1.pages << 9) - src_image;
187 if (emx_h1.last_page != 0)
188 emx_size += emx_h1.last_page - 512;
189
190 my_seek (&emx_file, src_image);
191 my_read (&emx_bind_h, sizeof (emx_bind_h), &emx_file);
192
193 if (memcmp (emx_bind_h.hdr, relaxed, strlen (relaxed)) != 0
194 || emx_bind_h.bind_flag != 0)
195 error ("invalid <emx>.exe");
196 if (memcmp (emx_bind_h.hdr, version, strlen (version)) != 0)
197 fputs ("emxbind: emx version mismatch (warning)\n", stderr);
198 dos_bind_h = emx_bind_h;
199}
200
201
202/* Read the a.out header of the input executable. */
203
204void read_a_out_header (void)
205{
206 byte buf[16];
207 int syms;
208
209 a_in_pos = my_tell (&inp_file);
210 my_read (&a_in_h, sizeof (a_in_h), &inp_file);
211 a_out_h = a_in_h;
212 if (a_in_h.magic != A_OUT_MAGIC || a_in_h.entry != TEXT_BASE)
213 error ("invalid a.out file (header)");
214 a_out_h.drsize = 0;
215 a_out_h.trsize = 0;
216 my_seek (&inp_file, A_OUT_OFFSET);
217 my_read (buf, sizeof (buf), &inp_file);
218 /* PUSH CALL JMP CALL */
219 if (buf[0] != 0x68 || buf[5] != 0xe8 || buf[10] != 0xeb || buf[12] != 0xe8)
220 error ("invalid a.out file (startup code)");
221 a_in_text = A_OUT_OFFSET;
222 a_in_data = a_in_text + round_page (a_in_h.text_size);
223 a_in_tr = a_in_data + round_page (a_in_h.data_size);
224 a_in_dr = a_in_tr + a_in_h.trsize;
225 a_in_sym = a_in_dr + a_in_h.drsize;
226 data_base = round_segment (TEXT_BASE + a_in_h.text_size);
227 my_seek (&inp_file, a_in_data);
228 my_read (&os2_bind_h, sizeof (os2_bind_h), &inp_file);
229 if (!check_os2_bind_header ())
230 error ("invalid a.out file (startup data)");
231 text_off = a_in_pos + a_in_text - TEXT_BASE;
232 data_off = a_in_pos + a_in_data - data_base;
233 syms = (a_in_h.sym_size != 0 &&
234 a_in_sym + a_in_h.sym_size + sizeof (a_in_str_size) <=
235 my_size (&inp_file));
236 if (syms)
237 {
238 a_in_str = a_in_sym + a_in_h.sym_size;
239 my_seek (&inp_file, a_in_str);
240 my_read (&a_in_str_size, sizeof (a_in_str_size), &inp_file);
241 }
242 else
243 {
244 a_in_str = a_in_sym;
245 a_in_str_size = 4;
246 }
247 if (syms && !opt_s)
248 {
249 a_out_str = a_in_str;
250 a_out_str_size = a_in_str_size;
251 }
252 else
253 {
254 a_out_str = a_in_sym;
255 a_out_str_size = 4;
256 a_out_h.sym_size = 0;
257 }
258 a_out_str -= a_in_h.drsize + a_in_h.trsize;
259 a_out_size = a_out_str + a_out_str_size;
260}
261
262
263/* Read the header of the core dump file. */
264
265void read_core (void)
266{
267 my_read (&core_h, sizeof (core_h), &core_file);
268 if (core_h.u_magic != UMAGIC)
269 error ("invalid core file (header)");
270 if (core_h.u_data_base != data_base
271 || core_h.u_data_end != data_base + a_in_h.data_size + a_in_h.bss_size)
272 error ("core file doesn't match a.out file");
273 a_out_h.data_size = round_page (core_h.u_data_end - core_h.u_data_base);
274 a_out_h.bss_size = 0;
275 if (core_h.u_heap_brk > core_h.u_heap_base)
276 {
277 if (core_h.u_heap_brk - core_h.u_heap_base > heap_size)
278 error ("the heap size is too small for the core file's heap");
279 a_out_h.data_size = round_page (core_h.u_heap_brk - core_h.u_data_base);
280 }
281 if (core_h.u_heapobjs_off != 0)
282 error ("%s: multiple heap objects are not supported", opt_c);
283}
284
285
286/* Read the LX header. */
287
288void read_os2_header (void)
289{
290 my_seek (&inp_file, sizeof (inp_h1));
291 my_read (&inp_h2, sizeof (inp_h2), &inp_file);
292 inp_os2_pos = COMBINE (inp_h2.new_lo, inp_h2.new_hi);
293 my_seek (&inp_file, inp_os2_pos);
294 my_read (&os2_h, sizeof (os2_h), &inp_file);
295}
296
297
298/* Read the text and data relocation tables of the input a.out
299 executable. */
300
301void read_reloc (void)
302{
303 if (tr_image == NULL)
304 {
305 my_seek (&inp_file, a_in_tr);
306 tr_image = xmalloc (a_in_h.trsize);
307 my_read (tr_image, a_in_h.trsize, &inp_file);
308 }
309 if (dr_image == NULL)
310 {
311 my_seek (&inp_file, a_in_dr);
312 dr_image = xmalloc (a_in_h.drsize);
313 my_read (dr_image, a_in_h.drsize, &inp_file);
314 }
315}
316
317
318/* Read the text and data sections from the input a.out file. */
319
320void read_segs (void)
321{
322 int d_size, t_size;
323
324 if (text_image == NULL)
325 {
326 t_size = round_page (a_in_h.text_size);
327 text_image = xmalloc (t_size);
328 my_seek (&inp_file, a_in_text);
329 my_read (text_image, t_size, &inp_file);
330 }
331 if (data_image == NULL)
332 {
333 d_size = round_page (a_in_h.data_size);
334 data_image = xmalloc (d_size);
335 my_seek (&inp_file, a_in_data);
336 my_read (data_image, d_size, &inp_file);
337 }
338}
339
340
341/* Read the symbol and string tables from the input a.out file. */
342
343void read_sym (void)
344{
345 if (sym_image == NULL)
346 {
347 sym_image = xmalloc (a_in_h.sym_size);
348 str_image = xmalloc (a_in_str_size);
349 my_seek (&inp_file, a_in_sym);
350 my_read (sym_image, a_in_h.sym_size, &inp_file);
351 my_seek (&inp_file, a_in_str);
352 my_read (str_image, a_in_str_size, &inp_file);
353 sym_count = a_in_h.sym_size / sizeof (struct nlist);
354 build_sym_hash_table ();
355 }
356}
357
358
359/* Read the DOS EXE header of the input executable. Fail if isn't a
360 bound executable file (unless the -L command option is in effect). */
361
362void check_bound (void)
363{
364 my_read (&inp_h1, sizeof (inp_h1), &inp_file);
365 if (inp_h1.magic != 0x5a4d)
366 error ("not an .exe file");
367 patch_pos = (long)inp_h1.hdr_size << 4;
368 my_seek (&inp_file, patch_pos);
369 my_read (&dos_bind_h, sizeof (dos_bind_h), &inp_file);
370 if (memcmp (dos_bind_h.hdr, relaxed, strlen (relaxed)) != 0
371 || dos_bind_h.bind_flag == 0)
372 {
373 is_bound = FALSE;
374 if (mode != 'L')
375 error ("invalid .exe file");
376 }
377 else
378 {
379 is_bound = TRUE;
380 if (mode != 'u' && mode != 'L' &&
381 memcmp (dos_bind_h.hdr, version, strlen (version)) != 0)
382 fputs ("emxbind: emx version mismatch in .exe file (warning)\n",
383 stderr);
384 a_in_pos = COMBINE (dos_bind_h.hdr_loc_lo, dos_bind_h.hdr_loc_hi);
385 my_seek (&inp_file, a_in_pos);
386 my_read (&a_in_h, sizeof (a_in_h), &inp_file);
387 a_out_h = a_in_h;
388 if (a_in_h.magic != A_OUT_MAGIC || a_in_h.entry != TEXT_BASE)
389 error ("invalid .exe file (a.out header)");
390 a_out_h.drsize = 0;
391 a_out_h.trsize = 0;
392 a_in_text = A_OUT_OFFSET;
393 a_in_data = a_in_text + round_page (a_in_h.text_size);
394 a_in_tr = a_in_data + round_page (a_in_h.data_size);
395 a_in_dr = a_in_tr + a_in_h.trsize;
396 a_in_sym = a_in_dr + a_in_h.drsize;
397 data_base = round_segment (TEXT_BASE + a_in_h.text_size);
398 my_seek (&inp_file, a_in_pos + a_in_data);
399 my_read (&os2_bind_h, sizeof (os2_bind_h), &inp_file);
400 if (!check_os2_bind_header ())
401 error ("invalid .exe file (startup data)");
402 }
403}
404
405
406/* Setup the DOS emxbind header, including emx options. */
407
408void set_dos_bind_header (void)
409{
410 dos_bind_h.bind_flag = 0xff;
411 dos_bind_h.hdr_loc_lo = LOWORD (a_out_pos);
412 dos_bind_h.hdr_loc_hi = HIWORD (a_out_pos);
413 set_options ();
414}
415
416
417/* Copy the emx options from options_for_dos and options_for_os2 to
418 dos_bind_h and os2_bind_h, respectively. Fail if the strings are
419 too long. */
420
421void set_options (void)
422{
423 if (strlen (options_for_dos) > sizeof (dos_bind_h.options) - 1)
424 error ("too many emx options for MS-DOS");
425 memset (dos_bind_h.options, 0, sizeof (dos_bind_h.options));
426 strcpy ((char *)dos_bind_h.options, options_for_dos);
427 if (strlen (options_for_os2) > sizeof (os2_bind_h.options) - 1)
428 error ("too many emx options for OS/2");
429 memset (os2_bind_h.options, 0, sizeof (os2_bind_h.options));
430 strcpy ((char *)os2_bind_h.options, options_for_os2);
431}
432
433
434/* Setup the DOS EXE headers for the destination executable. Compute
435 the location of the LX header. */
436
437void set_exe_header (void)
438{
439 long i;
440
441 i = (emx_h1.reloc_size << 2) + sizeof (out_h1) + sizeof (out_h2);
442#if 1
443 dst_image = (i + 0x0f) & ~0x0f;
444#else
445 dst_image = (i + 0x1ff) & ~0x1ff;
446#endif
447 fill1 = dst_image - i;
448 out_h1 = emx_h1;
449 out_h1.reloc_ptr = sizeof (out_h1) + sizeof (out_h2);
450 out_h1.hdr_size = dst_image >> 4;
451 out_h1.chksum = 0;
452 memset (out_h2.res1, 0, sizeof (out_h2.res1));
453 out_h2.new_lo = out_h2.new_hi = 0;
454 i = os2_hdr_pos = dst_image + emx_size;
455 if (os2_hdr_pos & 0x1ff)
456 os2_hdr_pos = (os2_hdr_pos + 0x1ff) & ~0x1ff;
457 fill2 = os2_hdr_pos - i;
458}
459
460
461/* Add the byte X to the LX header. */
462
463void put_header_byte (byte x)
464{
465 put_grow (&header, &x, sizeof (x));
466}
467
468
469/* Add the 16-bit word X to the LX header. */
470
471void put_header_word (word x)
472{
473 put_grow (&header, &x, sizeof (x));
474}
475
476
477/* Add the 32-bit word X to the LX header. */
478
479void put_header_dword (dword x)
480{
481 put_grow (&header, &x, sizeof (x));
482}
483
484
485/* Add SIZE bytes at SRC to the LX header. */
486
487void put_header_bytes (const void *src, size_t size)
488{
489 put_grow (&header, src, size);
490}
491
492
493/* Setup the OS/2 LX header. */
494
495void set_os2_header (void)
496{
497 dword i, first_heap_page;
498 int j, last_page, cur_page, obj;
499 struct object obj_res;
500
501 exe_flags ();
502 out_h2.new_lo = LOWORD (os2_hdr_pos);
503 out_h2.new_hi = HIWORD (os2_hdr_pos);
504 obj_text.virt_size = a_in_h.text_size;
505 obj_data.virt_size = a_in_h.data_size + a_in_h.bss_size;
506 obj_stk0.virt_size = stack_size;
507 obj_data.virt_base = round_segment (obj_text.virt_base + a_in_h.text_size);
508 obj_heap.virt_base = round_segment (OBJ_END (obj_data));
509 obj_stk0.virt_base = round_segment (OBJ_END (obj_heap));
510 os2_h.stack_esp = obj_stk0.virt_size;
511 text_pages = npages (a_in_h.text_size);
512 heap_pages = 0; gap_pages = 0;
513 if (opt_c != NULL)
514 {
515 data_pages = npages (a_in_h.data_size + a_in_h.bss_size);
516 if (!old_heap)
517 {
518 heap_pages = npages (core_h.u_heap_brk - core_h.u_heap_base);
519
520 /* Compute the number of pages between the last data page
521 and the first heap page, for padding the a.out subfile.
522 These pages are not mapped to any object. Round down! */
523
524 gap_pages = (core_h.u_heap_base - core_h.u_data_end) / 0x1000;
525 }
526 }
527 else
528 data_pages = npages (a_in_h.data_size);
529
530 /* The object page table and the fixup page table don't include the
531 pages between the last data page and the first heap page
532 (gap_pages). */
533
534 os2_h.mod_pages = res_pages + text_pages + data_pages + heap_pages;
535 obj_text.map_first = 1;
536 obj_text.map_count = text_pages;
537 obj_data.map_first = obj_text.map_first + obj_text.map_count;
538 obj_data.map_count = data_pages;
539 obj_heap.map_first = obj_data.map_first + obj_data.map_count;
540 obj_heap.map_count = heap_pages;
541 obj_stk0.map_first = obj_heap.map_first + obj_heap.map_count;
542 obj_stk0.map_count = 0;
543
544 /* The object numbers for the text object (OBJ_TEXT+1) and for the
545 data object (OBJ_DATA+1) are fixed, the remaining object numbers
546 are computed here. */
547
548 os2_h.obj_count = 0;
549 os2_h.stack_obj = 0;
550 for (j = 0; j < OBJECTS; ++j)
551 if (obj_h[j].virt_size != 0)
552 {
553 os2_h.obj_count += 1;
554 if (j == OBJ_STK0 && obj_stk0.virt_size != 0)
555 os2_h.stack_obj = os2_h.obj_count;
556 }
557 os2_h.obj_count += res_obj_count;
558
559 get_module_name ();
560 exports ();
561
562 header.len = 0;
563 put_header_bytes (&os2_h, sizeof (os2_h));
564
565 os2_h.obj_offset = header.len;
566 for (j = 0; j < OBJECTS; ++j)
567 if (obj_h[j].virt_size != 0)
568 put_header_bytes (&obj_h[j], sizeof (obj_h[j]));
569 memset (&obj_res, 0, sizeof (obj_res));
570 for (j = 0; j < res_obj_count; ++j)
571 put_header_bytes (&obj_res, sizeof (obj_res));
572 os2_h.pagemap_offset = header.len;
573 for (j = 0; j < text_pages + data_pages; ++j)
574 {
575 put_header_dword (j + res_pages);
576 put_header_word (0x1000);
577 put_header_word (0);
578 }
579 first_heap_page = res_pages + text_pages + data_pages + gap_pages;
580 for (j = 0; j < heap_pages; ++j)
581 {
582 put_header_dword (j + first_heap_page);
583 put_header_word (0x1000);
584 put_header_word (0);
585 }
586 for (j = 0; j < res_pages; ++j)
587 {
588 put_header_dword (j);
589 put_header_word (0x1000);
590 put_header_word (0);
591 }
592
593 if (res_count > 0)
594 {
595 os2_h.rsctab_offset = header.len;
596 put_rsctab ();
597 }
598
599 os2_h.resname_offset = header.len;
600 put_header_bytes (resnames.data, resnames.len);
601 put_header_byte (0);
602
603 os2_h.entry_offset = header.len;
604 put_header_bytes (entry_tab.data, entry_tab.len);
605
606 /* Record the location of the fixup page table and write a dummy
607 fixup page table to be filled-in while creating the fixup record
608 table. Note that there's one additional fixup page table entry
609 to hold the end address of the fixup section for the last
610 page. */
611
612 os2_h.fixpage_offset = header.len;
613 for (j = 0; j <= os2_h.mod_pages; ++j)
614 put_header_dword (0); /* will be patched later */
615
616 /* Record the location of the fixup record table. */
617
618 os2_h.fixrecord_offset = header.len;
619
620 /* Write the fixup record table. Fill-in the fixup page table
621 whenever changing to a new page. Note that the header may move
622 while adding fixup records. */
623
624#define FIXPAGE(PAGE) (((dword *)(header.data + os2_h.fixpage_offset))[PAGE])
625
626 last_page = 0;
627 for (j = 0; j < fixup_len; ++j)
628 {
629 /* Get the object number of the fixup. Note that fixups are
630 sorted by object, then by address. */
631
632 obj = fixup_data[j].obj;
633
634 /* Compute the page number for the fixup. */
635
636 cur_page = div_page (fixup_data[j].addr) + obj_h[obj].map_first - 1;
637
638 /* Abort if the page number is out of range. */
639
640 if (cur_page >= os2_h.mod_pages)
641 error ("internal error 1");
642 if (cur_page < last_page - 1)
643 error ("internal error 4");
644
645 /* Fill-in the fixup page table if we're on a new page. */
646
647 while (last_page <= cur_page)
648 {
649 FIXPAGE (last_page) = header.len - os2_h.fixrecord_offset;
650 ++last_page;
651 }
652
653 /* Add the fixup record to the fixup record table. This may
654 move the header in memory. */
655
656 create_fixup (&fixup_data[j], FALSE);
657
658 /* Treat fixups which cross page bounaries specially. Two fixup
659 records are created for such a fixup, one in the first page,
660 one in the second page involved. The offset for the second
661 page is negative. The method used here doesn't work with
662 overlapping fixups as we move to the next page and can't go
663 back (see internal error 4 above). */
664
665 if ((fixup_data[j].addr & 0x0fff) > 0x0ffc)
666 {
667 FIXPAGE (last_page) = header.len - os2_h.fixrecord_offset;
668 ++last_page;
669 create_fixup (&fixup_data[j], TRUE);
670 }
671 }
672
673 /* Fill-in the remaining entries of the fixup page table. */
674
675 while (last_page <= os2_h.mod_pages)
676 {
677 FIXPAGE (last_page) = header.len - os2_h.fixrecord_offset;
678 ++last_page;
679 }
680
681#undef FIXPAGE
682
683 os2_h.impmod_offset = header.len;
684 put_impmod ();
685
686 os2_h.impprocname_offset = header.len;
687 put_header_bytes (procs.data, procs.len);
688 os2_h.fixup_size = header.len - os2_h.fixpage_offset;
689 put_header_byte (0);
690 os2_hdr_size = header.len;
691
692 i = os2_hdr_pos + os2_hdr_size;
693 if (res_count > 0)
694 {
695 a_out_pos = round_page (i);
696 fill3 = a_out_pos - i;
697 a_out_pos += res_pages * 0x1000 - A_OUT_OFFSET;
698 }
699 else
700 {
701 a_out_pos = round_page (i + A_OUT_OFFSET) - A_OUT_OFFSET;
702 fill3 = a_out_pos - i;
703 }
704 os2_h.loader_size = os2_h.fixpage_offset - os2_h.obj_offset;
705 os2_h.enum_offset = a_out_pos + A_OUT_OFFSET - res_pages * 0x1000;
706 os2_h.instance_demand = data_pages + heap_pages;
707 os2_h.preload_count = res_preload_pages;
708
709 if (nonresnames.len != 0)
710 {
711 os2_h.nonresname_offset = a_out_pos + a_out_size;
712 os2_h.nonresname_size = nonresnames.len;
713 }
714
715 header.len = 0;
716 put_header_bytes (&os2_h, sizeof (os2_h));
717 for (j = 0; j < OBJECTS; ++j)
718 if (obj_h[j].virt_size != 0)
719 put_header_bytes (&obj_h[j], sizeof (obj_h[j]));
720
721 put_res_obj (obj_stk0.map_first + obj_stk0.map_count);
722 header.len = os2_hdr_size;
723 if (opt_c != NULL)
724 {
725 os2_bind_h.data_end = os2_bind_h.data_base + a_in_h.data_size + a_in_h.bss_size;
726 os2_bind_h.bss_base = os2_bind_h.data_end;
727 os2_bind_h.bss_end = os2_bind_h.bss_base;
728 os2_bind_h.heap_base = core_h.u_heap_base;
729 os2_bind_h.heap_end = core_h.u_heap_end;
730 os2_bind_h.heap_brk = core_h.u_heap_brk;
731 os2_bind_h.heap_off = a_out_pos + A_OUT_OFFSET
732 + round_page (a_in_h.text_size)
733 + round_segment (a_in_h.data_size + a_in_h.bss_size);
734 }
735 else
736 {
737 os2_bind_h.heap_base = obj_heap.virt_base;
738 os2_bind_h.heap_end = OBJ_END (obj_heap);
739 os2_bind_h.heap_brk = 0;
740 os2_bind_h.heap_off = 0;
741 }
742}
743
744
745/* Initialize the fixed part of the OS/2 LX header. Fields which are
746 overwritten later are initialized to X. */
747
748void init_os2_header (void)
749{
750 byte b;
751
752 b = 0;
753 put_grow (&procs, &b, 1);
754#define X 0
755 memset (&os2_h, 0, sizeof (os2_h));
756 os2_h.magic = 0x584c; /* LX */
757 os2_h.byte_order = 0; /* Little Endian byte order */
758 os2_h.word_order = 0; /* Little Endian word order */
759 os2_h.level = 0; /* Format level */
760 os2_h.cpu = 2; /* 386 */
761 os2_h.os = 1; /* Operating system type: OS/2 */
762 os2_h.ver = 0; /* Module version */
763 os2_h.mod_flags = 0x200; /* WINDOWCOMPAT */
764 if (!relocatable)
765 os2_h.mod_flags |= 0x10; /* no internal fixups */
766 os2_h.mod_pages = X; /* Number of pages in .exe file*/
767 os2_h.entry_obj = OBJ_TEXT+1; /* Object number for EIP */
768 os2_h.entry_eip = 0; /* EIP */
769 os2_h.stack_obj = X; /* Stack object */
770 os2_h.stack_esp = X; /* ESP */
771 os2_h.pagesize = 0x1000; /* System page size */
772 os2_h.pageshift = 12; /* Page offset shift */
773 os2_h.fixup_size = X; /* Fixup section size */
774 os2_h.fixup_checksum = 0; /* Fixup section checksum */
775 os2_h.loader_size = X; /* Loader section size */
776 os2_h.loader_checksum = 0; /* Loader section checksum */
777 os2_h.obj_offset = X; /* Object table offset */
778 os2_h.obj_count = X; /* Number of objects */
779 os2_h.pagemap_offset = X;
780 os2_h.itermap_offset = 0;
781 os2_h.rsctab_offset = 0;
782 os2_h.rsctab_count = 0;
783 os2_h.resname_offset = X;
784 os2_h.entry_offset = X;
785 os2_h.moddir_offset = 0;
786 os2_h.moddir_count = 0;
787 os2_h.fixpage_offset = X;
788 os2_h.fixrecord_offset = X;
789 os2_h.impmod_offset = X;
790 os2_h.impmod_count = X;
791 os2_h.impprocname_offset = X;
792 os2_h.page_checksum_offset = 0;
793 os2_h.enum_offset = X;
794 os2_h.preload_count = X;
795 os2_h.nonresname_offset = 0;
796 os2_h.nonresname_size = 0;
797 os2_h.nonresname_checksum = 0;
798 os2_h.auto_obj = OBJ_DATA+1;
799 os2_h.debug_offset = 0;
800 os2_h.debug_size = 0;
801 os2_h.instance_preload = 0;
802 os2_h.instance_demand = X;
803 os2_h.heap_size = 0;
804 os2_h.stack_size = 0;
805 obj_text.virt_size = 0;
806 obj_text.virt_base = TEXT_BASE;
807 obj_text.attr_flags = 0x2005; /* readable, executable, big */
808 obj_text.map_first = X;
809 obj_text.map_count = X;
810 obj_text.reserved = 0;
811 obj_data.virt_size = 0;
812 obj_data.virt_base = 0;
813 obj_data.attr_flags = 0x2003; /* readable, writable, big */
814 obj_data.map_first = X;
815 obj_data.map_count = X;
816 obj_data.reserved = 0;
817 obj_heap.virt_size = heap_size;
818 obj_heap.virt_base = 0;
819 if (old_heap || opt_c == NULL)
820 obj_heap.attr_flags = 0x2083; /* readable, writable, big, invalid */
821 else
822 obj_heap.attr_flags = 0x2003; /* readable, writable, big */
823 obj_heap.map_first = X;
824 obj_heap.map_count = X;
825 obj_heap.reserved = 0;
826 obj_stk0.virt_size = 0;
827 obj_stk0.virt_base = 0;
828 obj_stk0.attr_flags = 0x2003; /* readable, writable, big */
829 obj_stk0.map_first = X;
830 obj_stk0.map_count = X;
831 obj_stk0.reserved = 0;
832#undef X
833}
834
835
836/* Set the application type in the OS/2 LX header. */
837
838void exe_flags (void)
839{
840 if (opt_f)
841 {
842 os2_h.mod_flags &= ~0x700;
843 os2_h.mod_flags |= 0x100;
844 }
845 else if (opt_p)
846 {
847 os2_h.mod_flags &= ~0x700;
848 os2_h.mod_flags |= 0x300;
849 }
850 else if (opt_w)
851 {
852 os2_h.mod_flags &= ~0x700;
853 os2_h.mod_flags |= 0x200;
854 }
855 else
856 switch (app_type)
857 {
858 case _MDT_NOTWINDOWCOMPAT:
859 os2_h.mod_flags &= ~0x700;
860 os2_h.mod_flags |= 0x100;
861 break;
862 case _MDT_WINDOWAPI:
863 os2_h.mod_flags &= ~0x700;
864 os2_h.mod_flags |= 0x300;
865 break;
866 case _MDT_WINDOWCOMPAT:
867 os2_h.mod_flags &= ~0x700;
868 os2_h.mod_flags |= 0x200;
869 break;
870 }
871 if (dll_flag)
872 {
873 os2_h.mod_flags |= 0x8000;
874 if (!init_global)
875 os2_h.mod_flags |= 0x0004;
876 if (!term_global)
877 os2_h.mod_flags |= 0x40000000;
878 }
879}
880
881
882/* Write the DOS EXE headers, the emxl.exe or emx.exe image, and the
883 OS/2 LX header. */
884
885void write_header (void)
886{
887 my_write (&out_h1, sizeof (out_h1), &out_file);
888 my_write (&out_h2, sizeof (out_h2), &out_file);
889 my_seek (&emx_file, emx_h1.reloc_ptr);
890 copy (&emx_file, emx_h1.reloc_size * 4);
891 fill (fill1);
892 my_seek (&emx_file, src_image);
893 copy (&emx_file, emx_size);
894 fill (fill2);
895 if (mode != 'u')
896 {
897 my_write (header.data, os2_hdr_size, &out_file);
898 fill (fill3);
899 }
900}
901
902
903/* Write the emxbind headers (patch areas). */
904
905void write_bind_header (void)
906{
907 my_seek (&out_file, dst_image);
908 my_write (&dos_bind_h, sizeof (dos_bind_h), &out_file);
909 my_seek (&out_file, a_out_pos + A_OUT_OFFSET
910 + round_page (a_out_h.text_size));
911 my_write (&os2_bind_h, sizeof (os2_bind_h), &out_file);
912}
913
914
915/* Write the non-resident name table. */
916
917void write_nonres (void)
918{
919 if (nonresnames.len != 0)
920 {
921 my_seek (&out_file, os2_h.nonresname_offset);
922 my_write (nonresnames.data, nonresnames.len, &out_file);
923 }
924}
925
926
927/* Copy the a.out subfile (a.out header, text and data sections,
928 symbol table, and string table) to the destination executable. */
929
930void copy_a_out (void)
931{
932 long n, str_len;
933
934 my_write (&a_out_h, sizeof (a_out_h), &out_file);
935 fill (A_OUT_OFFSET - sizeof (a_out_h));
936 my_seek (&inp_file, a_in_text);
937 if (text_image != NULL)
938 my_write (text_image, round_page (a_in_h.text_size), &out_file);
939 else
940 copy (&inp_file, round_page (a_in_h.text_size));
941 if (opt_c != NULL)
942 {
943 my_seek (&core_file, core_h.u_data_off);
944 n = core_h.u_data_end - core_h.u_data_base;
945 copy (&core_file, n);
946 fill (round_page (n) - n);
947 if (core_h.u_heap_brk > core_h.u_heap_base)
948 {
949 fill (core_h.u_heap_base - round_page (core_h.u_data_end));
950 my_seek (&core_file, core_h.u_heap_off);
951 n = core_h.u_heap_brk - core_h.u_heap_base;
952 copy (&core_file, n);
953 fill (round_page (n) - n);
954 }
955 }
956 else if (data_image != NULL)
957 my_write (data_image, round_page (a_in_h.data_size), &out_file);
958 else
959 {
960 my_seek (&inp_file, a_in_data);
961 copy (&inp_file, round_page (a_in_h.data_size));
962 }
963 if (a_out_h.sym_size == 0)
964 {
965 str_len = 4;
966 my_write (&str_len, sizeof (str_len), &out_file);
967 }
968 else
969 {
970 if (sym_image != NULL)
971 my_write (sym_image, a_out_h.sym_size, &out_file);
972 else
973 {
974 my_seek (&inp_file, a_in_sym);
975 copy (&inp_file, a_out_h.sym_size);
976 }
977 if (str_image != NULL)
978 my_write (str_image, a_out_str_size, &out_file);
979 else
980 {
981 my_seek (&inp_file, a_in_str);
982 copy (&inp_file, a_out_str_size);
983 }
984 }
985}
986
987
988/* Copy SIZE bytes from the file SRC to the destination executable
989 file (out_file). */
990
991void copy (struct file *src, long size)
992{
993 char buf[BUFSIZ];
994 size_t n;
995
996 while (size > 0)
997 {
998 n = min (size, BUFSIZ);
999 my_read (buf, n, src);
1000 my_write (buf, n, &out_file);
1001 size -= n;
1002 }
1003}
1004
1005
1006/* Write COUNT zero bytes to the destination executable file
1007 (out_file). */
1008
1009void fill (long count)
1010{
1011 char buf[BUFSIZ];
1012 size_t n;
1013
1014 memset (buf, 0, BUFSIZ);
1015 while (count > 0)
1016 {
1017 n = min (count, BUFSIZ);
1018 my_write (buf, n, &out_file);
1019 count -= n;
1020 }
1021}
Note: See TracBrowser for help on using the repository browser.