source: vendor/emx/current/src/emxomf/emxomf.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: 100.1 KB
Line 
1/* emxomf.c -- Convert GNU-style a.out object files (with emx extensions)
2 to OS/2-style OMF (Object Module Formats) object files
3 Copyright (c) 1992-1998 Eberhard Mattes
4
5This file is part of emxomf.
6
7emxomf is free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
9the Free Software Foundation; either version 2, or (at your option)
10any later version.
11
12emxomf is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with emxomf; see the file COPYING. If not, write to
19the Free Software Foundation, 59 Temple Place - Suite 330,
20Boston, MA 02111-1307, USA. */
21
22
23#include <stdio.h>
24#include <stdlib.h>
25#include <stdarg.h>
26#include <string.h>
27#include <getopt.h>
28#include <sys/param.h>
29#include <sys/emxload.h>
30#include <ar.h>
31
32/* The version number of this program. This is printed with the usage
33 message. */
34
35#define VERSION "0.9d"
36
37/* Insert private header files. */
38
39#include "defs.h" /* Common definitions */
40#include "emxomf.h" /* Global definitions for emxomf */
41#include "stabshll.h" /* Convert debug information */
42#include "grow.h" /* Growing objects */
43
44/* This header must come after defs.h */
45
46#include <sys/omflib.h> /* Handling OMF libraries */
47
48/* Flag bits for FLAGS field of the struct symbol structure. */
49
50#define SF_FAR16 0x01 /* 16:16 pointer */
51
52/* This structure holds additional data for symbols. */
53
54struct symbol
55{
56 int index; /* EXTDEF index */
57 int flags; /* SF_FAR16 */
58};
59
60/* This program keeps OMF symbols (names) in a list of lname
61 structures. */
62
63struct lname
64{
65 struct lname *next; /* Pointer to next element */
66 char *name; /* Name of the symbol */
67 int index; /* OMF index of the symbol */
68};
69
70/* Names of files to be deleted on program termination are stored in a
71 list of delete structures. */
72
73struct delete
74{
75 struct delete *next; /* Pointer to next element */
76 char *name; /* Name of the file to be deleted */
77};
78
79/* This structure holds the information about one class (set) of a.out
80 set elements. Set elements are used for constructors and
81 destructors. These structures are chained in a list. See
82 write_set_data() for details. */
83
84struct set
85{
86 struct set *next; /* Pointer to next class of set elements */
87 char *name; /* Name of the set (the a.out symbol) */
88 int seg_name[3]; /* Name indices of the three segments */
89 int seg_index[3]; /* Segment indices of the three segments */
90 int group_name; /* Name index of the group */
91 int group_index; /* Group index of the group */
92 int def; /* Non-zero if head element encountered */
93 int count; /* Number of non-head non-tail elements */
94 dword *data; /* Values of set elements (COUNT elements) */
95 byte *seg; /* Segments of set elements (COUNT elements) */
96};
97
98/* Default library requests (see -i option) are stored in a list of
99 libreq structures. */
100
101struct libreq
102{
103 char *name; /* Name of the default library */
104 struct libreq *next; /* Pointer to next element */
105};
106
107/* This structure describes an OMF-style line number. */
108
109struct line
110{
111 dword addr; /* Start address of the line */
112 int line; /* Line number */
113 int file_index; /* File index */
114};
115
116/* fetch_modstr() caches the string it has retrieved from other
117 modules of the same library. The cache consists of a a linked list
118 of `struct modstr' structures. */
119
120struct modstr
121{
122 struct modstr *next; /* Pointer to next node */
123 char *symbol; /* Symbol attached to the string */
124 char *str; /* The value of the string */
125};
126
127
128/* The number of symbols in the a.out file. */
129int sym_count = 0;
130
131/* The sym_ptr variable points to an array of a.out symbols. There
132 are sym_count table entries. Note that this table is complemented
133 by the sym_more table. */
134const struct nlist *sym_ptr = NULL;
135
136/* The str_ptr variable points to the a.out string table. The
137 elements of sym_ptr contain offsets into this table. The table
138 starts with a 32-bit number. The rest of the table consists of
139 null-terminated strings. */
140const byte *str_ptr = NULL;
141
142/* The text_ptr variable points to the first byte of the text
143 segment. text_size bytes are available at text_ptr. */
144byte *text_ptr = NULL;
145long text_size = 0;
146
147/* The data_ptr variable points to the first byte of the data
148 segment. data_size bytes are available at data_ptr. */
149
150static byte *data_ptr;
151static long data_size;
152
153/* These varibles point to the text and data relocation tables. */
154
155static const struct reloc *text_rel;
156static const struct reloc *data_rel;
157
158/* Public variables for communication with stabshll.c. */
159
160struct buffer tt = BUFFER_INIT;
161struct buffer sst = BUFFER_INIT;
162struct buffer sst_reloc = BUFFER_INIT;
163struct grow sst_boundary_grow = GROW_INIT;
164struct grow tt_boundary_grow = GROW_INIT;
165int *sst_boundary = NULL;
166int *tt_boundary = NULL;
167
168
169/* Private variables. */
170
171/* The name of the current input file. */
172static const char *inp_fname;
173
174/* The name of the current output file. */
175static const char *out_fname = NULL;
176
177/* Use this file name for reporting errors. This is either the name
178 of the input file or a library name plus module name:
179 library(module). */
180static const char *error_fname;
181
182/* The output directory. This is set by the -O option. */
183static const char *output_dir = "";
184
185/* The current input file. */
186static FILE *inp_file;
187
188/* The current output file. */
189static FILE *out_file = NULL;
190
191/* While writing a LIB response file, this variable contains the
192 stream pointer. Otherwise, this variable is NULL. */
193static FILE *response_file = NULL;
194
195/* When creating an OMF library (.lib file), this variable contains
196 the descriptor used by the omflib library. Otherwise, this
197 variable is NULL. */
198static struct omflib *out_lib = NULL;
199
200/* This buffer receives error messages from the omflib library. */
201static char lib_errmsg[512];
202
203/* emxomf reads a complete a.out module into memory. inp_buf points
204 to the buffer holding the current a.out module. This pointer is
205 aliased by sym_ptr etc. */
206static byte *inp_buf;
207
208/* OMF records are constructed in this buffer. The first three bytes
209 are used for the record type and record length. One byte at the
210 end is used for the checksum. */
211static byte out_buf[1+2+MAX_REC_SIZE+1];
212
213/* Index into out_buf (to be more precise: it's a pointer into
214 out_data, which is an alias to out_buf+3) for the next byte of the
215 OMF record. */
216static int out_idx;
217
218/* The list of OMF names. lnames is the head of the list, lname_add
219 is used to add another name to the end of the list. */
220static struct lname *lnames;
221static struct lname **lname_add;
222
223/* The list of sets. sets is the head of the list, set_add is used to
224 add another set to the end of the list. */
225static struct set *sets;
226static struct set **set_add;
227
228/* For compatibility with emxomf 0.8h and older, generation of GRPDEF
229 records for sets can be enabled by using the -g option. That
230 option sets this variable to TRUE. By default, GRPDEF records are
231 not generated. */
232static int do_set_groups = FALSE;
233
234/* If this variable is TRUE, an a.out archive is split into several
235 OMF .obj files (-x option). If this variable is FALSE, an a.out
236 archive is converted into an OMF library file. */
237static int opt_x = FALSE;
238
239/* This is the page size for OMF libraries. It is set by the -p
240 option. */
241static int page_size = 16;
242
243/* The index of the next OMF name, used by find_lname(). Name indices
244 are established by LNAMES records written by write_lnames(). */
245static int lname_index;
246
247/* The index of the next segment, used by seg_def() for creating
248 SEGDEF records. */
249static int segdef_index;
250
251/* The index of the next group, used for creating GRPDEF records. */
252static int group_index;
253
254/* The index of the next symbol, used for creating EXTDEF and COMDEF
255 records. */
256static int sym_index;
257
258/* The index of the "WEAK$ZERO" symbol or 0. */
259static int weak_zero_index;
260
261/* OMF name indices: segments, classes, groups, etc. */
262static int ovl_name; /* Overlay name, "" */
263static int text_seg_name; /* Text segment, "TEXT32" */
264static int data_seg_name; /* Data segment, "DATA32" */
265static int udat_seg_name; /* Explicit data segment, see -D */
266static int stack_seg_name; /* Stack segment, "STACK" */
267static int bss_seg_name; /* Uninitialized data segment, "BSS32" */
268static int symbols_seg_name; /* Symbols segment, "$$SYMBOLS" */
269static int types_seg_name; /* Types segment */
270static int code_class_name; /* Code class, "CODE" */
271static int data_class_name; /* Data class, "DATA" */
272static int stack_class_name; /* Stack class, "STACK" */
273static int bss_class_name; /* Uninitialized data class, "BSS" */
274static int debsym_class_name; /* Symbols class, "DEBSYM" */
275static int debtyp_class_name; /* Types class, "DEBTYP" */
276static int flat_group_name; /* FLAT group, "FLAT" */
277static int dgroup_group_name; /* DGROUP group, "DGROUP" or "DATAGROUP" */
278
279/* Segment indices for the TEXT32, DATA32, STACK, BSS32, $$SYMBOLS,
280 $$TYPES and explicit data segments. */
281static int text_index; /* Text segment, TEXT32 */
282static int data_index; /* Data segment, DATA32 */
283static int udat_index; /* Data segment set by -D or same as above */
284static int stack_index; /* Stack segment, STACK */
285static int bss_index; /* Uninitialized data segment, BSS32 */
286static int symbols_index; /* Symbols segment, $$SYMBOLS */
287static int types_index; /* Types segment, $$TYPES */
288
289/* Group indices for the FLAT and DGROUP groups. */
290static int flat_index; /* FLAT group */
291static int dgroup_index; /* DGROUP group */
292
293/* Next FIXUPP thread index to be used for the frame and target
294 thread, respectively. */
295static int frame_thread_index; /* Frame thread */
296static int target_thread_index; /* Target thread */
297
298/* We define target threads for referencing the TEXT32, DATA32 (or the
299 one set by -D) and BSS32 segments and the FLAT group in FIXUPP
300 records. A thread has not been defined if the variable is -1.
301 Otherwise, the value is the thread number. */
302static int text_thread; /* TEXT32 segment */
303static int data_thread; /* Data segment (DATA32 or -D) */
304static int bss_thread; /* BSS32 segment */
305static int flat_thread; /* FLAT group */
306
307/* This variable holds the module name. See get_mod_name(). */
308static char mod_name[256];
309
310/* This growing array holds the file name table for generating line
311 number information. */
312static char **file_list;
313static struct grow file_grow;
314
315/* This variable points to the a.out header of the input module. */
316static const struct a_out_header *a_out_h;
317
318/* This table contains additional information for the a.out symbols.
319 Each entry of the sym_ptr table is complemented by an entry of this
320 table. */
321static struct symbol *sym_more;
322
323/* The length of the a.out string table, in bytes. This value
324 includes the 32-bit number at the start of the string table. */
325static long str_size;
326
327/* omflib_write_module() stored the page number of the module to this
328 variable. */
329static word mod_page;
330
331/* This variable is TRUE until we have written the first line to the
332 LIB response file. It is used to suppress the line continuation
333 character `&'. */
334static int response_first = TRUE;
335
336/* This is the list of files to be deleted on program termination.
337 See delete_files(). */
338static struct delete *files_to_delete = NULL;
339
340/* The module type (-l and -m options). It is MT_MODULE unless the -l
341 or -m option is used. */
342static enum {MT_MODULE, MT_MAIN, MT_LIB} mod_type = MT_MODULE;
343
344/* The start (entry point) symbol (-m option). This is NULL unless
345 the -m option (or -l with argument) is used. */
346static char *entry_name = NULL;
347
348/* The name of the identifier manipulation DLL. If this variable is
349 NULL, no IDMDLL record is written. */
350static char *idmdll_name = "GPPDEMID";
351
352/* If this variable is TRUE (-b option), we always use the 32-bit
353 variant of the OMF records. If this variable is FALSE, we use the
354 16-bit variant whenever possible. This non-documented feature is
355 used for debugging. */
356static int force_big = FALSE;
357
358/* The name of the LIB response file (-r and -R options). This value
359 is NULL unless the -r or -R option is used. */
360static char *response_fname = NULL;
361
362/* When creating a LIB response file, emit commands for replacing
363 modules if this variable is TRUE (-R option). Otherwise, emit
364 commands for adding modules (-r option). */
365static int response_replace;
366
367/* Delete input files after successful conversion if this variable is
368 TRUE (-d option). */
369static int delete_input_files = FALSE;
370
371/* Strip debug information if this variable is TRUE (-s option).
372 Otherwise, convert DBX debugging information to HLL debugging
373 information. */
374static int strip_symbols = FALSE;
375
376/* Print unknown symbol table entries if this variable is TRUE (-u
377 option). */
378static int unknown_stabs = FALSE;
379
380/* Supress certain warnings if this variable is TRUE (-q option). */
381static int quiet = FALSE;
382
383/* The libreq_head variable contains a pointer to the head of the list
384 of default libraries. The -i option is used to add a default
385 library request. The libreq_add pointer is used for appending new
386 elements to the tail of the list. */
387static struct libreq *libreq_head = NULL;
388static struct libreq **libreq_add = &libreq_head;
389
390/* fetch_mod_str() caches the string it has retrieved from other
391 modules of the same library. modstr_cache points to the head of
392 the linked list of `struct modstr' structures. */
393
394static struct modstr *modstr_cache = NULL;
395
396/* Simulate the data array of an OMF record. The data is stored along
397 with the record type (1 byte) and record length (2 bytes) in a
398 single buffer. */
399#define out_data (out_buf+1+2)
400
401/* The data segment name, set by the -D option. If this value is
402 non-NULL, put variables into the named data segment, which isn't a
403 member of DGROUP. */
404
405static char *udat_seg_string = NULL;
406
407/* Prototypes for private functions. */
408
409static void doesn_fit (void) NORETURN2;
410static void usage (void) NORETURN2;
411static int ar_read_header (struct ar_hdr *dst, long pos);
412static long ar_member_size (const struct ar_hdr *p);
413
414
415/* Display an error message on stderr, delete the output file and
416 quit. This function is invoked like printf(): FMT is a
417 printf-style format string, all other arguments are formatted
418 according to FMT. The message should not end with a newline. The
419 exit code is 2. */
420
421void error (const char *fmt, ...)
422{
423 va_list arg_ptr;
424
425 va_start (arg_ptr, fmt);
426 fprintf (stderr, "emxomf: ");
427 vfprintf (stderr, fmt, arg_ptr);
428 va_end (arg_ptr);
429 fputc ('\n', stderr);
430
431 /* If there is an output file, close and delete it. */
432
433 if (out_file != NULL)
434 {
435 fclose (out_file);
436 remove (out_fname);
437 }
438 exit (2);
439}
440
441
442/* Display a warning message on stderr (and do not quit). This
443 function is invoked like printf(): FMT is a printf-style format
444 string, all other arguments are formatted according to FMT. */
445
446void warning (const char *fmt, ...)
447{
448 va_list arg_ptr;
449
450 va_start (arg_ptr, fmt);
451 fprintf (stderr, "emxomf warning: ");
452 vfprintf (stderr, fmt, arg_ptr);
453 va_end (arg_ptr);
454 fputc ('\n', stderr);
455}
456
457
458/* Allocate N bytes of memory. Quit on failure. This function is
459 used like malloc(), but we don't have to check the return value. */
460
461void *xmalloc (size_t n)
462{
463 void *p;
464
465 p = malloc (n);
466 if (p == NULL)
467 error ("Out of memory");
468 return p;
469}
470
471
472/* Change the allocation of PTR to N bytes. Quit on failure. This
473 function is used like realloc(), but we don't have to check the
474 return value. */
475
476void *xrealloc (void *ptr, size_t n)
477{
478 void *p;
479
480 p = realloc (ptr, n);
481 if (p == NULL)
482 error ("Out of memory");
483 return p;
484}
485
486
487/* Create a duplicate of the string S on the heap. Quit on failure.
488 This function is used like strdup(), but we don't have to check the
489 return value. */
490
491char *xstrdup (const char *s)
492{
493 char *p;
494
495 p = xmalloc (strlen (s) + 1);
496 strcpy (p, s);
497 return p;
498}
499
500
501/* Find an a.out symbol. The underscore character `_' is prepended to
502 NAME. On success, a pointer to the symbol table entry (in the
503 array pointed to by sym_ptr) is returned. If the symbol is not
504 found, NULL is returned. */
505
506const struct nlist *find_symbol (const char *name)
507{
508 int i, j, n, len, ok, t;
509 const byte *s;
510
511 i = 4; len = strlen (name);
512
513 /* Search the string table for a matching string. */
514
515 while (i < str_size)
516 {
517 ok = TRUE; s = name;
518 if (str_ptr[i] == '_')
519 ++i;
520 else
521 ok = FALSE;
522 if (ok && memcmp (name, str_ptr+i, len+1) == 0)
523 {
524
525 /* Search the symbol table for an appropriate entry
526 referencing the string. */
527
528 n = sym_count;
529 --i; /* Move back to the underscore */
530 for (j = 0; j < n; ++j)
531 if (sym_ptr[j].string == i)
532 {
533 t = sym_ptr[j].type & ~N_EXT;
534 if (t == N_TEXT || t == N_DATA || t == N_BSS
535 || (t == 0 && sym_ptr[j].value != 0))
536 return sym_ptr+j;
537 }
538 }
539 i += strlen (str_ptr+i) + 1;
540 }
541 return NULL; /* Symbol not found */
542}
543
544
545/* Initialize variables for starting a new OMF output file. */
546
547static void init_obj (void)
548{
549 /* Initialize the list of OMF-style names. */
550
551 lnames = NULL; lname_add = &lnames; lname_index = 1;
552
553 /* Initialize segments. */
554
555 segdef_index = 1; sym_index = 1; group_index = 1; weak_zero_index = 0;
556
557 /* Initialize FIXUPP threads. */
558
559 text_thread = -1; data_thread = -1; bss_thread = -1; flat_thread = -1;
560 frame_thread_index = 0; target_thread_index = 0;
561
562 /* Initialize set elements management. */
563
564 sets = NULL; set_add = &sets;
565
566 /* Initialize the buffers used for converting debugging
567 information. */
568
569 buffer_init (&tt);
570 buffer_init (&sst);
571 buffer_init (&sst_reloc);
572}
573
574
575/* Find an OMF-style name. If NAME is not yet a known OMF-style name,
576 it is added to the list of OMF-style names. The index of the name
577 is returned. All the OMF-style names will be defined in LNAMES
578 records. Note: INDEX must be assigned sequentially, append to end
579 of list! Otherwise, write_lnames() would have to sort the list */
580
581static int find_lname (const char *name)
582{
583 struct lname *p;
584
585 /* Walk through the list of known OMF-style names. If there is a
586 match, return the index of the name. */
587
588 for (p = lnames; p != NULL; p = p->next)
589 if (strcmp (name, p->name) == 0)
590 return p->index;
591
592 /* The name is not yet known. Create a new entry. */
593
594 p = xmalloc (sizeof (struct lname));
595 p->name = xstrdup (name);
596 p->index = lname_index++;
597
598 /* Add the new entry to the tail of the list of names. */
599
600 p->next = NULL;
601 *lname_add = p;
602 lname_add = &p->next;
603
604 /* Return the index of the new name. */
605
606 return p->index;
607}
608
609
610/* Deallocate the memory used by the list of OMF-style names. */
611
612static void free_lnames (void)
613{
614 struct lname *p, *q;
615
616 for (p = lnames; p != NULL; p = q)
617 {
618 q = p->next;
619 free (p->name);
620 free (p);
621 }
622}
623
624
625/* Start a new OMF record. TYPE is the record type. */
626
627static void init_rec (int type)
628{
629 out_buf[0] = (byte)type;
630 out_idx = 0;
631}
632
633
634/* Write an OMF record. The record type has been defined by
635 init_rec(), the data has been defined by put_8(), put_idx() etc.
636 The checksum is computed by this function. An OMF record has the
637 following format:
638
639 struct omf_record
640 {
641 byte type; The record type
642 word length; The record length, exclusive TYPE and LENGTH
643 byte data[LENGTH-1]; The record data
644 byte checksum; The check sum. The sum of all the bytes in
645 the record is 0 (module 256)
646 };
647
648 If we're writing a LIB file, we call omflib_write_record().
649 Otherwise, we build and write the record here. An OMF record
650 usually contains multiple definitions, see write_lnames() for a
651 simple instance of the loop we use for packing multiple definitions
652 into OMF records. */
653
654static void write_rec (void)
655{
656 byte chksum;
657 int i;
658
659 if (out_lib != NULL)
660 {
661
662 /* Write the record to the library file. */
663
664 if (omflib_write_record (out_lib, out_buf[0], out_idx, out_data,
665 TRUE, lib_errmsg) != 0)
666 error (lib_errmsg);
667 }
668 else
669 {
670
671 /* Store the record length, LSB first. */
672
673 out_buf[1] = (byte)(out_idx+1);
674 out_buf[2] = (byte)((out_idx+1) >> 8);
675
676 /* Compute the check sum. */
677
678 chksum = 0;
679 for (i = 0; i < 1+2+out_idx; ++i)
680 chksum += out_buf[i];
681 out_data[out_idx] = (byte)(256-chksum);
682
683 /* Write the record. */
684
685 if (fwrite (out_buf, 1+2+out_idx+1, 1, out_file) != 1)
686 error ("Write error on output file `%s'", out_fname);
687 }
688}
689
690
691/* This macro yields TRUE iff we can put another X bytes into the
692 current OMF record. */
693
694#define fits(X) (out_idx + (X) <= MAX_REC_SIZE-4)
695
696/* This function is called if we try to build too big an OMF record.
697 This cannot happen unless there is a bug in this program. Display
698 an error message and quit. */
699
700static void doesn_fit (void)
701{
702 error ("Record too long");
703}
704
705
706/* Put the null-terminated string SRC into the current OMF record. In
707 the OMF record, the string is preceded by a length byte. The
708 string length must not exceed 255; if it is too long, display a
709 warning and truncate the string. Moreover, there must be enough
710 space left in the OMF record; if there isn't, display an error
711 message and abort. */
712
713static void put_str (const char *src)
714{
715 int len;
716
717 len = strlen (src);
718 if (len > 255)
719 {
720 warning ("Symbol length truncated to 255 characters for `%s'", src);
721 len = 255;
722 }
723 if (!fits (1+len))
724 doesn_fit ();
725 out_data[out_idx++] = (byte)len;
726 memcpy (out_data+out_idx, src, len);
727 out_idx += len;
728}
729
730
731/* Put the symbol SRC, a null-terminated string, into the current OMF
732 record. If SRC starts with the underscore character `_', that
733 character is skipped. This is where the leading underscore
734 character of a.out symbols is removed. C modules for emx.dll are
735 treated specially here: The leading underscore is not removed
736 unless the name looks like the name of an OS/2 API function. The
737 symbol length (after removing the leading underscore) must not
738 exceed 255 characters. There must be enough space left in the OMF
739 record. If these conditions are not met, display an error message
740 and quit. */
741
742static void put_sym (const char *src)
743{
744 if (*src == '_')
745 ++src;
746 put_str (src);
747}
748
749/* Put an 8-bit byte into the current OMF record. This macro does not
750 test for buffer / record overflow. */
751
752#define put_8(x) out_data[out_idx++] = (byte)(x)
753
754/* Put a 16-bit word (least significant byte first) into the current
755 OMF record. If there is not enough space left in the OMF record,
756 display an error message and quit. */
757
758static void put_16 (int x)
759{
760 if (!fits (2))
761 doesn_fit ();
762 out_data[out_idx++] = (byte)x;
763 out_data[out_idx++] = (byte)(x >> 8);
764}
765
766
767/* Put a 24-bit word (least significant byte first) into the current
768 OMF record. If there is not enough space left in the OMF record,
769 display an error message and quit. */
770
771static void put_24 (long x)
772{
773 if (!fits (3))
774 doesn_fit ();
775 out_data[out_idx++] = (byte)x;
776 out_data[out_idx++] = (byte)(x >> 8);
777 out_data[out_idx++] = (byte)(x >> 16);
778}
779
780
781/* Put a 32-bit word (least significant byte first) into the current
782 OMF record. If there is not enough space left in the OMF record,
783 display an error message and quit. */
784
785static void put_32 (long x)
786{
787 if (!fits (4))
788 doesn_fit ();
789 out_data[out_idx++] = (byte)x;
790 out_data[out_idx++] = (byte)(x >> 8);
791 out_data[out_idx++] = (byte)(x >> 16);
792 out_data[out_idx++] = (byte)(x >> 24);
793}
794
795
796/* Put the index X into the current OMF record. Indices are used for
797 identifying names (LNAMES), segments (SEGDEF), groups (GRPDEF)
798 etc. Indices are stored in one or two bytes, depending on the
799 value. Small indices (0 through 127) are stored as single byte.
800 Large indices (128 through 32767) are stored as two bytes: the
801 high-order byte comes first, with bit 7 set; the low-order byte
802 comes next. If there is not enough space left in the OMF record or
803 if the value exceeds 32767, display an error message and quit. */
804
805static void put_idx (int x)
806{
807 if (x <= 0x7f)
808 {
809 if (!fits (1))
810 doesn_fit ();
811 out_data[out_idx++] = (byte)x;
812 }
813 else if (x <=0x7fff)
814 {
815 if (!fits (2))
816 doesn_fit ();
817 out_data[out_idx++] = (byte)((x >> 8) | 0x80);
818 out_data[out_idx++] = (byte)x;
819 }
820 else
821 error ("Index too large");
822}
823
824
825/* Put SIZE bytes from SRC into the current OMF record. If there is
826 not enough space left in the OMF record, display an error message
827 and quit. */
828
829static void put_mem (const char *src, int size)
830{
831 if (!fits (size))
832 doesn_fit ();
833 memcpy (out_data+out_idx, src, size);
834 out_idx += size;
835}
836
837
838/* Write LNAMES records into the output file for defining all the
839 names stored in the LNAMES list.
840
841 LNAMES record:
842 Ú
843 ³1 String length n
844 ³n Name
845 À
846
847 Name indices are assigned sequentially. */
848
849static void write_lnames (void)
850{
851 const struct lname *p;
852 int started;
853
854 started = FALSE;
855 for (p = lnames; p != NULL; p = p->next)
856 {
857 if (started && !fits (strlen (p->name)+1))
858 {
859 write_rec ();
860 started = FALSE;
861 }
862 if (!started)
863 {
864 init_rec (LNAMES);
865 started = TRUE;
866 }
867 put_str (p->name);
868 }
869 if (started)
870 write_rec ();
871}
872
873
874/* Add a string to the current EXTDEF record or start a new EXTDEF
875 record. PSTARTED points to an object keeping state. */
876
877static void add_extdef (int *pstarted, const char *name)
878{
879 if (*pstarted && !fits (strlen (name)+3))
880 {
881 write_rec ();
882 *pstarted = FALSE;
883 }
884 if (!*pstarted)
885 {
886 init_rec (EXTDEF);
887 *pstarted = TRUE;
888 }
889 put_sym (name);
890 put_idx (0); /* type index */
891}
892
893
894/* Write EXTDEF records into the output file for all the external
895 symbols stored in the sym_ptr array.
896
897 EXTDEF record:
898 Ú
899 ³1 String length n
900 ³n External name
901 ³1-2 Type index
902 À
903
904 Symbol indices are assigned sequentially. */
905
906static void write_extdef (void)
907{
908 const char *name;
909 int i, started;
910
911 started = FALSE;
912 for (i = 0; i < sym_count; ++i)
913 if (sym_ptr[i].type == (N_INDR|N_EXT))
914 ++i; /* Skip immediately following entry */
915 else if (sym_ptr[i].type == N_EXT && sym_ptr[i].value == 0)
916 {
917 name = str_ptr + sym_ptr[i].string;
918 sym_more[i].index = sym_index++;
919 if (memcmp (name, "__16_", 5) == 0)
920 sym_more[i].flags |= SF_FAR16;
921 add_extdef (&started, name);
922 }
923 else if (sym_ptr[i].type == N_WEAKU)
924 {
925 if (weak_zero_index == 0)
926 {
927 weak_zero_index = sym_index++;
928 add_extdef (&started, "WEAK$ZERO");
929 }
930 sym_more[i].index = sym_index++;
931 add_extdef (&started, str_ptr + sym_ptr[i].string);
932 }
933 if (started)
934 write_rec ();
935}
936
937/* Write WKEXT records into the output file for all undefined weak
938 symbols stored in the sym_ptr array.
939
940 WKEXT record:
941 Ú
942 ³1-2 weak EXTDEF index
943 ³1-2 default resolution EXTDEF index
944 À
945
946 */
947
948static void write_wkext (void)
949{
950 int i;
951
952 for (i = 0; i < sym_count; ++i)
953 if (sym_ptr[i].type == (N_INDR|N_EXT))
954 ++i; /* Skip immediately following entry */
955 else if (sym_ptr[i].type == N_WEAKU)
956 {
957 init_rec (COMENT);
958 put_8 (0x80);
959 put_8 (0xa8);
960 put_idx (sym_more[i].index);
961 put_idx (weak_zero_index);
962 write_rec ();
963 }
964}
965
966
967/* Write ALIAS records into the output file for all indirect
968 references. */
969
970static void write_alias (void)
971{
972 int i;
973 const char *pub_name;
974
975 for (i = 0; i < sym_count - 1; ++i)
976 if (sym_ptr[i].type == (N_INDR|N_EXT) && sym_ptr[i+1].type == N_EXT)
977 {
978 init_rec (ALIAS);
979 put_sym (str_ptr + sym_ptr[i].string);
980 put_sym (str_ptr + sym_ptr[i+1].string);
981 write_rec ();
982
983 if (out_lib != NULL)
984 {
985 pub_name = str_ptr + sym_ptr[i].string;
986 if (*pub_name == '_')
987 ++pub_name;
988 if (omflib_add_pub (out_lib, pub_name, mod_page, lib_errmsg) != 0)
989 error (lib_errmsg);
990 }
991 }
992}
993
994
995/* Write PUBDEF records into the output file for the public symbols of
996 the a.out-style symbol type TYPE. Symbols of that type are defined
997 in the segment having the OMF segment index INDEX. Ignore symbols
998 not fitting into a 16-bit PUBDEF record if BIG is FALSE. Ignore
999 symbols fitting into a 16-bit PUBDEF record if BIG is TRUE. START
1000 is the virtual start address of the segment in the a.out file.
1001
1002 PUBDEF record:
1003 1-2 Base group
1004 1-2 Base segment
1005 0/2 Base frame
1006 Ú
1007 ³1 String length n
1008 ³n Public name
1009 ³2/4 Public offset (4 bytes for 32-bit PUBDEF record)
1010 ³1-2 Type index
1011 À
1012
1013 The base frame field is present only if the base segment field is
1014 0. */
1015
1016static void write_pubdef1 (int type, int index, int big, dword start)
1017{
1018 int i, started;
1019 const char *name, *pub_name;
1020 dword address;
1021
1022 started = FALSE;
1023 for (i = 0; i < sym_count; ++i)
1024 if ((sym_ptr[i].type & ~N_EXT) == type)
1025 {
1026 address = sym_ptr[i].value - start;
1027 if ((address >= 0x10000 || force_big) == big)
1028 {
1029 name = str_ptr + sym_ptr[i].string;
1030 if ((sym_ptr[i].type & N_EXT)
1031 || (type == N_TEXT && strncmp (name, "___POST$", 8) == 0))
1032 {
1033 if ((sym_ptr[i].type & N_EXT) && out_lib != NULL)
1034 {
1035 pub_name = name;
1036 if (*pub_name == '_')
1037 ++pub_name;
1038 if (omflib_add_pub (out_lib, pub_name, mod_page,
1039 lib_errmsg) != 0)
1040 error (lib_errmsg);
1041 }
1042 if (started && !fits (strlen (name) + 6))
1043 {
1044 write_rec ();
1045 started = FALSE;
1046 }
1047 if (!started)
1048 {
1049 init_rec (big ? PUBDEF|REC32 : PUBDEF);
1050 put_idx (flat_index);
1051 put_idx (index);
1052 started = TRUE;
1053 }
1054 put_sym (name);
1055 if (big)
1056 put_32 (address);
1057 else
1058 put_16 (address);
1059 put_idx (0); /* type index */
1060 }
1061 }
1062 }
1063 if (started)
1064 write_rec ();
1065}
1066
1067
1068/* Write PUBDEF records into the output file for all the public N_TEXT
1069 and N_DATA symbols stored in the sym_ptr array. Common symbols are
1070 handled by write_comdef() below. */
1071
1072static void write_pubdef (void)
1073{
1074 write_pubdef1 (N_TEXT, text_index, FALSE, 0);
1075 write_pubdef1 (N_TEXT, text_index, TRUE, 0);
1076 write_pubdef1 (N_DATA, udat_index, FALSE, text_size);
1077 write_pubdef1 (N_DATA, udat_index, TRUE, text_size);
1078}
1079
1080
1081/* Write COMDEF records into the output file for all the common
1082 symbols stored in the sym_ptr array. Common symbols are used for
1083 uninitialized variables. The TYPE field of these symbols is 0
1084 (plus N_EXT) and the VALUE field is non-zero (it is the size of the
1085 variable).
1086
1087 COMDEF record:
1088 Ú
1089 ³1 String length n
1090 ³n Communal name
1091 ³1-2 Type index
1092 ³1 Data type (0x61: FAR data, 0x62: NEAR data)
1093 ³1-5 Communal length
1094 À
1095
1096 The length is encoded in 1 to 5 bytes, depending on the value:
1097
1098 0 through 0x7f 1 byte, containing the value
1099 0 through 0xffff 0x81, followed by 16-bit word
1100 0 through 0xffffff 0x84, followed by 24-bit word
1101 0 through 0xffffffff 0x88, followed by 32-bit word */
1102
1103static void write_comdef (void)
1104{
1105 int i, started;
1106 long size;
1107 const char *name;
1108
1109 started = FALSE;
1110 for (i = 0; i < sym_count; ++i)
1111 if (sym_ptr[i].type == (N_INDR|N_EXT))
1112 ++i; /* Skip immediately following entry */
1113 else if (sym_ptr[i].type == N_EXT && sym_ptr[i].value != 0)
1114 {
1115 name = str_ptr + sym_ptr[i].string;
1116 sym_more[i].index = sym_index++;
1117 if (memcmp (name, "__16_", 5) == 0)
1118 sym_more[i].flags |= SF_FAR16;
1119 size = sym_ptr[i].value;
1120 if (started && !fits (strlen (name) + 12))
1121 {
1122 write_rec ();
1123 started = FALSE;
1124 }
1125 if (!started)
1126 {
1127 init_rec (COMDEF);
1128 started = TRUE;
1129 }
1130 put_sym (name);
1131 put_idx (0); /* Type index */
1132 put_8 (0x62); /* Data type */
1133 if (size < 0x80)
1134 put_8 (size);
1135 else if (size < 0x10000)
1136 {
1137 put_8 (0x81);
1138 put_16 (size);
1139 }
1140 else if (size < 0x1000000)
1141 {
1142 put_8 (0x84);
1143 put_24 (size);
1144 }
1145 else
1146 {
1147 put_8 (0x88);
1148 put_32 (size);
1149 }
1150 }
1151 if (started)
1152 write_rec ();
1153}
1154
1155
1156/* Write a SEGDEF record to define a segment. NAME_INDEX is the name
1157 index of the segment name. CLASS_INDEX is the name index of the
1158 class name. SIZE is the size of the segment in bytes. STACK is
1159 TRUE iff the segment is the stack segment. seg_def() returns the
1160 segment index of the new segment.
1161
1162 SEGDEF record:
1163 1 Segment attributes
1164 0/2 Frame number (present only if A=000)
1165 0/1 Offset (present only if A=000)
1166 2/4 Segment length (4 bytes for 32-bit SEGDEF record)
1167 1/2 Segment name index
1168 1/2 Segment class index
1169 1/2 Overlay name index
1170
1171 The segment attributes byte contains the following fields:
1172
1173 A (bits 5-7) Alignment (101=relocatable, 32-bit alignment)
1174 C (bits 2-4) Combination (010=PUBLIC, 101=STACK)
1175 B (bit 1) Big (segment length is 64KB)
1176 P (bit 0) USE32 */
1177
1178static int seg_def (int name_index, int class_index, long size, int stack)
1179{
1180 byte seg_attr;
1181
1182 seg_attr = (stack ? 0xb5 : 0xa9);
1183 if (size > 0x10000 || force_big)
1184 {
1185 init_rec (SEGDEF|REC32);
1186 put_8 (seg_attr);
1187 put_32 (size);
1188 }
1189 else if (size == 0x10000)
1190 {
1191 init_rec (SEGDEF);
1192 put_8 (seg_attr|2);
1193 put_16 (0);
1194 }
1195 else
1196 {
1197 init_rec (SEGDEF);
1198 put_8 (seg_attr);
1199 put_16 (size);
1200 }
1201 put_idx (name_index);
1202 put_idx (class_index);
1203 put_idx (ovl_name);
1204 write_rec ();
1205 return segdef_index++;
1206}
1207
1208
1209/* This function is passed to qsort() for sorting a relocation table.
1210 X1 and X2 point to reloc structures. We compare the ADDRESS fields
1211 of the structures. */
1212
1213static int reloc_compare (const void *x1, const void *x2)
1214{
1215 dword a1, a2;
1216
1217 a1 = ((struct reloc *)x1)->address;
1218 a2 = ((struct reloc *)x2)->address;
1219 if (a1 < a2)
1220 return -1;
1221 else if (a1 > a2)
1222 return 1;
1223 else
1224 return 0;
1225}
1226
1227
1228/* Write the segment contents (data) of one OMF segment to the output
1229 file. Create LEDATA and FIXUPP records. INDEX is the segment
1230 index. SEG_NAME is the name index of the segment name (not used).
1231 SRC points to the data to be written (will be modified for
1232 fixups!), SEG_SIZE is the number of bytes to be written. REL
1233 points to the relocation table (an array of struct reloc), REL_SIZE
1234 is the size of the relocation table, in bytes(!). SST_FLAG is TRUE
1235 when writing the symbol segment $$SYMBOLS. BOUNDARY points to an
1236 array of indices into SRC where the data can be split between
1237 records. That array has BOUNDARY_COUNT entries. SEG_TYPE is the
1238 segment type (N_TEXT or N_DATA or -1) and is used for relocation.
1239
1240 We can split the data at arbitrary points after the last BOUNDARY
1241 entry. In consequence, write_seg() splits the data at arbitrary
1242 points if BOUNDARY_COUNT is zero.
1243
1244 LEDATA record:
1245 1-2 Segment index
1246 2/4 Enumerated data offset (4 bytes for 32-bit LEDATA record)
1247 n Data bytes (n is derived from record length)
1248
1249 FIXUPP record:
1250 Ú
1251 ³? THREAD subrecord or FIXUP subrecord
1252 À
1253
1254 THREAD subrecord:
1255 1 Flags
1256 0-2 Index (present only for FRAME methods F0, F1 and F2)
1257
1258 The flags byte contains the following fields:
1259
1260 0 (bit 7) always 0 to indicate THREAD subrecord
1261 D (bit 6) 0=target thread, 1=frame thread
1262 0 (bit 5) reserved
1263 Method (bits 2-4) method (T0 through T6 and F0 through F6)
1264 Thred (bits 0-1) thread number
1265
1266 FIXUP subrecord:
1267 2 Locat
1268 0-1 Fix data
1269 0-2 Frame datum
1270 0-2 Target datum
1271 2/4 target displacement (4 bytes for 32-bit FIXUPP record)
1272
1273 The first locat byte contains the following fields:
1274
1275 1 (bit 7) always 1 to indicate FIXUP subrecord
1276 M (bit 6) 1=segment-relative fixup, 0=self-relative fixup
1277 Location (bit 2-5) Type of location to fix up:
1278 0010=16-bit selector
1279 0011=32-bit long pointer (16:16)
1280 1001=32-bit offset
1281 Offset (bits 0-1) Most significant bits of offset into LEDATA record
1282
1283 The second locat byte contains the least significant bits of the
1284 offset into the LEDATA record.
1285
1286 The Fix data byte contains the following fields:
1287
1288 F (bit 7) 1=frame thread, 0=methods F0 through F5
1289 Frame (bits 4-6) frame thread number (F=1) or frame method (F=0)
1290 T (bit 3) 1=target thread, 1=methods
1291 P (bit 2) Bit 2 of target method
1292 Targt (bits 0-1) target thread number (T=1) or target method (T=0) */
1293
1294static void write_seg (int index, int seg_name, byte *src, long seg_size,
1295 const struct reloc *rel, long rel_size, int sst_flag,
1296 const int *boundary, int boundary_count, int seg_type)
1297{
1298 long n, off, tmp, end;
1299 int i, reloc_count, reloc_idx, target_index, ok, data_off, far16;
1300 int boundary_idx, started, *threadp;
1301 struct reloc *reloc_tab;
1302 const struct reloc *r;
1303 byte locat;
1304 dword start_data, start_bss;
1305
1306 target_index = 0; threadp = NULL; /* keep the compiler happy */
1307
1308 /* Copy and sort the relocation table. */
1309
1310 reloc_count = rel_size / sizeof (struct reloc);
1311 reloc_tab = xmalloc (reloc_count * sizeof (struct reloc));
1312 memcpy (reloc_tab, rel, reloc_count * sizeof (struct reloc));
1313 qsort (reloc_tab, reloc_count, sizeof (struct reloc), reloc_compare);
1314
1315 /* First pass: apply fixups to data. Adjust fixup frames for OMF
1316 fixups. In a.out files, frames are relative to address 0, in OMF
1317 files, frames are relative to the start of the segment. The
1318 following two variables are used for doing these adjustments. */
1319
1320 start_data = text_size;
1321 start_bss = start_data + data_size;
1322
1323 /* Scan the relocation table for entries applying to this segment. */
1324
1325 for (i = 0, r = reloc_tab; i < reloc_count; ++i, ++r)
1326 if (r->length == 2)
1327 {
1328
1329 /* Here we have a 32-bit relocation. */
1330
1331 if (r->ext)
1332 {
1333
1334 /* The relocation refers to a symbol. Look into the
1335 symbol table to find the fixup type and target
1336 address. */
1337
1338 switch (sym_ptr[r->symbolnum].type)
1339 {
1340 case N_EXT:
1341 case N_WEAKU:
1342 if (r->pcrel)
1343 *(dword *)(src + r->address) = 0;
1344 break;
1345 case N_TEXT:
1346 break;
1347 case N_TEXT|N_EXT:
1348 *(dword *)(src + r->address) = 0;
1349 break;
1350 case N_DATA:
1351 case N_DATA|N_EXT:
1352 *(dword *)(src + r->address) -= start_data;
1353 break;
1354 case N_BSS:
1355 case N_BSS|N_EXT:
1356 *(dword *)(src + r->address) -= start_bss;
1357 break;
1358 default:
1359 error ("write_seg: Invalid symbol type (0x%.2x)",
1360 sym_ptr[r->symbolnum].type);
1361 }
1362 }
1363 else if (!(r->pcrel && (r->symbolnum & ~N_EXT) == seg_type))
1364 {
1365
1366 /* The relocation does not refer to a symbol, it's an
1367 internal relocation. Get the fixup type from the
1368 relocation table. */
1369
1370 switch (r->symbolnum & ~N_EXT)
1371 {
1372 case N_TEXT:
1373 break;
1374 case N_DATA:
1375 *(dword *)(src + r->address) -= start_data;
1376 break;
1377 case N_BSS:
1378 *(dword *)(src + r->address) -= start_bss;
1379 break;
1380 default:
1381 error ("write_seg: Invalid relocation type");
1382 }
1383 }
1384 }
1385
1386 /* Second pass: write LEDATA and FIXUPP records. */
1387
1388 off = 0; reloc_idx = 0; boundary_idx = 0;
1389 while (seg_size > 0)
1390 {
1391
1392 /* Compute the maximum number of bytes in the next LEDATA
1393 record, depending on the maximum record size, the record type
1394 (16-bit or 32-bit) and the number of bytes remaining. The
1395 number of bytes will be adjusted later to avoid splitting
1396 entries of the $$SYMBOLS and $$TYPES segments. */
1397
1398 n = MAX_REC_SIZE - 5;
1399 n -= (off >= 0x10000 || force_big ? 4 : 2);
1400 if (seg_size < n)
1401 n = seg_size;
1402
1403 /* Adjust the number of bytes to avoid splitting a fixup. Find
1404 the last relocation table entry which applies to this chunk.
1405 Then, lower the chunk size to stop at the start of the
1406 frame. */
1407
1408 i = reloc_idx; end = off + n;
1409 while (i < reloc_count && reloc_tab[i].address < end)
1410 ++i;
1411 if (i > reloc_idx)
1412 {
1413 --i;
1414 tmp = reloc_tab[i].address + (1 << reloc_tab[i].length) - off;
1415 if (tmp > n)
1416 n = reloc_tab[i].address - off;
1417 }
1418
1419 /* Consult the BOUNDARY table to find the last point where we
1420 are allowed to split the data into multiple LEDATA records.
1421 This must be done after adjusting for relocation table
1422 entries. */
1423
1424 end = off + n;
1425 while (boundary_idx < boundary_count && boundary[boundary_idx] < end)
1426 ++boundary_idx;
1427 if (boundary_idx > 0)
1428 {
1429 tmp = boundary[boundary_idx-1] - off;
1430 if (tmp > 0)
1431 n = tmp;
1432 }
1433
1434 /* Write the LEDATA record. This is simple. */
1435
1436 if (off >= 0x10000 || force_big)
1437 {
1438 init_rec (LEDATA|REC32);
1439 put_idx (index);
1440 put_32 (off);
1441 }
1442 else
1443 {
1444 init_rec (LEDATA);
1445 put_idx (index);
1446 put_16 (off);
1447 }
1448 put_mem (src, n);
1449 write_rec ();
1450
1451 /* Write the FIXUPP records for this LEDATA record. Quite
1452 hairy. */
1453
1454 end = off + n;
1455 started = FALSE;
1456 r = &reloc_tab[reloc_idx];
1457
1458 /* Look at all relocation table entries which apply to the
1459 current LEDATA chunk. */
1460
1461 while (reloc_idx < reloc_count && r->address < end)
1462 {
1463
1464 /* Set ok to TRUE if we should create a fixup for this
1465 relocation table entry. First, ignore all but 32-bit
1466 relocations. In the $$SYMBOLS segment, we also have
1467 16-bit selector fixups. far16 is later set to TRUE for
1468 16:16 fixups. */
1469
1470 ok = (r->length == 2 || (sst_flag && r->length == 1));
1471 far16 = FALSE;
1472
1473 if (r->ext)
1474 {
1475
1476 /* The relocation refers to a symbol -- we won't use a
1477 target thread. If the symbol is a 16:16 symbol, we
1478 set far16 to true to generate a 16:16 fixup. */
1479
1480 threadp = NULL;
1481 if (sym_more[r->symbolnum].flags & SF_FAR16)
1482 far16 = TRUE;
1483 }
1484 else if (r->pcrel && (r->symbolnum & ~N_EXT) == seg_type)
1485 {
1486 ok = FALSE;
1487 if (!quiet)
1488 warning ("Internal PC-relative relocation ignored");
1489 }
1490 else
1491 {
1492
1493 /* The relocation does not refer to a symbol -- we use
1494 an appropriate target thread. The target thread
1495 number is taken from or stored to *threadp.
1496 target_index is the OMF segment index. */
1497
1498 switch (r->symbolnum & ~N_EXT)
1499 {
1500 case N_TEXT:
1501 threadp = &text_thread;
1502 target_index = text_index;
1503 break;
1504 case N_DATA:
1505 threadp = &data_thread;
1506 target_index = udat_index;
1507 break;
1508 case N_BSS:
1509 threadp = &bss_thread;
1510 target_index = bss_index;
1511 break;
1512 case N_ABS:
1513 default:
1514 ok = FALSE;
1515 break;
1516 }
1517 }
1518
1519 if (ok)
1520 {
1521
1522 /* Now we build the FIXUPP record. */
1523
1524 if (started && !fits (32))
1525 {
1526 write_rec ();
1527 started = FALSE;
1528 }
1529 if (!started)
1530 {
1531 init_rec (FIXUPP|REC32);
1532 started = TRUE;
1533 }
1534
1535 /* If no frame thread has been defined for the FLAT
1536 group, define it now. */
1537
1538 if (flat_thread < 0 && !far16)
1539 {
1540 if (frame_thread_index >= 4)
1541 error ("Too many frame threads");
1542 /* THREAD: D=1, METHOD=F1 */
1543 put_8 (0x44 | frame_thread_index);
1544 put_idx (flat_index);
1545 flat_thread = frame_thread_index++;
1546 }
1547
1548 /* If we want to use a target thread and the target
1549 thread is not yet defined, define it now. */
1550
1551 if (threadp != NULL && *threadp < 0)
1552 {
1553 if (target_thread_index >= 4)
1554 error ("Too many target threads");
1555 /* THREAD: D=0, METHOD=T4 */
1556 put_8 (0x10 | target_thread_index);
1557 put_idx (target_index);
1558 *threadp = target_thread_index++;
1559 }
1560
1561 /* Compute and write the locat word. */
1562
1563 data_off = r->address - off;
1564 if (far16)
1565 locat = 0x8c; /* Method 3: 16:16 far pointer */
1566 else if (sst_flag && r->length == 1)
1567 locat = 0x88; /* Method 2: selector */
1568 else
1569 locat = 0xa4; /* Method 9: 32-bit offset */
1570 locat |= ((data_off >> 8) & 0x03);
1571 if (!r->pcrel)
1572 locat |= 0x40;
1573 put_8 (locat);
1574 put_8 (data_off);
1575
1576 /* Write the rest of the FIXUP subrecord. */
1577
1578 if (far16)
1579 {
1580 /* F=0, FRAME=F2, T=0, P=1, TARGT=T2 */
1581 put_8 (0x26);
1582 put_idx (sym_more[r->symbolnum].index);
1583 put_idx (sym_more[r->symbolnum].index);
1584 }
1585 else if (r->ext)
1586 {
1587 /* F=1, FRAME=F1, T=0, P=1, TARGT=T2 */
1588 put_8 (0x86 | (flat_thread << 4));
1589 put_idx (sym_more[r->symbolnum].index);
1590 }
1591 else
1592 {
1593 /* F=1, FRAME=F1, T=1, P=1, TARGT=T4 */
1594 put_8 (0x8c | (flat_thread << 4) | *threadp);
1595 }
1596 }
1597 ++reloc_idx; ++r;
1598 }
1599 if (started)
1600 write_rec ();
1601
1602 /* Adjust pointers and counters for the next chunk. */
1603
1604 src += n; off += n; seg_size -= n;
1605 }
1606
1607 /* Deallocate the sorted relocation table. */
1608
1609 free (reloc_tab);
1610}
1611
1612
1613/* Write a default library request record to the output file. The
1614 linker will search the library NAME to resolve external
1615 references. Create a COMENT record of class 0x9f. The name is
1616 stored without leading byte count, the linker gets the length of
1617 the name from the record length. */
1618
1619static void request_lib (const char *name)
1620{
1621 init_rec (COMENT);
1622 put_8 (0x40);
1623 put_8 (0x9f);
1624 put_mem (name, strlen (name));
1625 write_rec ();
1626}
1627
1628
1629/* Write default library request records for all the -i options. The
1630 library names are stored in a list. libreq_head points to the head
1631 of the list. */
1632
1633static void write_libs (void)
1634{
1635 struct libreq *p;
1636
1637 for (p = libreq_head; p != NULL; p = p->next)
1638 request_lib (p->name);
1639}
1640
1641
1642/* Write a record identifying the debug information style to the
1643 output file. The style we use is called HLL version 3. Create a
1644 COMENT record of class 0xa1. */
1645
1646static void write_debug_style (void)
1647{
1648 init_rec (COMENT);
1649 put_8 (0x80);
1650 put_8 (0xa1); /* Debug info style */
1651 put_8 (3); /* Version 3 */
1652 put_mem ("HL", 2); /* HLL style debug tables */
1653 write_rec ();
1654}
1655
1656
1657/* Write a link pass separator to the output file. The linker makes
1658 two passes through the object modules. The first pass stops when
1659 encountering the link pass separator. This is used for improving
1660 linking speed. The second pass ignores the link pass separator.
1661 The following records must precede the link pass separator: ALIAS,
1662 CEXTDEF COMDEF, EXTDEF, GRPDEF, LCOMDEF, LEXTDEF, LNAMES, LPUBDEF,
1663 PUBDEF, SEGDEF, TYPDEF, and most of the COMENT classes. Create a
1664 COMENT record of class 0xa2. */
1665
1666static void write_pass2 (void)
1667{
1668 init_rec (COMENT);
1669 put_8 (0x40);
1670 put_8 (0xa2); /* Link pass separator */
1671 put_8 (0x01);
1672 write_rec ();
1673}
1674
1675
1676/* Create segment names for all the sets. It is here where sets are
1677 created. See write_set_data() for details. */
1678
1679static void define_set_names (void)
1680{
1681 int i, j;
1682 struct set *set_ptr;
1683 char tmp[512];
1684 const char *name;
1685 byte type;
1686
1687 /* Loop through the symbol table. */
1688
1689 for (i = 0; i < sym_count; ++i)
1690 {
1691 type = sym_ptr[i].type & ~N_EXT;
1692 if ((type == N_SETA && sym_ptr[i].value == 0xffffffff)
1693 || type == N_SETT || type == N_SETD)
1694 {
1695
1696 /* This is a set element. If type is N_SETA the symbol is
1697 the head of the set, otherwise it is an ordinary set
1698 element. Search the table of sets to find out whether
1699 this set is already known. */
1700
1701 name = str_ptr + sym_ptr[i].string;
1702 for (set_ptr = sets; set_ptr != NULL; set_ptr = set_ptr->next)
1703 if (strcmp (set_ptr->name, name) == 0)
1704 break;
1705 if (set_ptr == NULL)
1706 {
1707
1708 /* The set is not yet known. Create a new table
1709 entry. */
1710
1711 set_ptr = xmalloc (sizeof (struct set));
1712 set_ptr->name = xstrdup (name);
1713 for (j = 0; j < 3; ++j)
1714 {
1715 set_ptr->seg_name[j] = -1;
1716 set_ptr->seg_index[j] = -1;
1717 }
1718 set_ptr->group_name = -1;
1719 set_ptr->count = 0;
1720 set_ptr->data = NULL;
1721 set_ptr->seg = NULL;
1722 set_ptr->def = 0;
1723 set_ptr->next = NULL;
1724 *set_add = set_ptr;
1725 set_add = &set_ptr->next;
1726 }
1727 else if (type == N_SETA && set_ptr->def)
1728 error ("Set `%s' defined more than once", name);
1729
1730 if (type == N_SETA)
1731 set_ptr->def = 1; /* Write SET1 and SET3 segments */
1732 else
1733 {
1734
1735 /* Add the element to the set. */
1736
1737 ++set_ptr->count;
1738 set_ptr->data = xrealloc (set_ptr->data, set_ptr->count * 4);
1739 set_ptr->seg = xrealloc (set_ptr->seg, set_ptr->count);
1740 set_ptr->data[set_ptr->count-1] = sym_ptr[i].value;
1741 set_ptr->seg[set_ptr->count-1]
1742 = (type == N_SETT ? N_TEXT : N_DATA);
1743 }
1744
1745 /* Define the OMF segment names for this set, if not yet
1746 done. */
1747
1748 if (set_ptr->seg_name[0] < 0)
1749 {
1750 strcpy (tmp, "SET#");
1751 strcat (tmp, name);
1752 for (j = 0; j < 3; ++j)
1753 {
1754 tmp[3] = (char)('1' + j);
1755 set_ptr->seg_name[j] = find_lname (tmp);
1756 }
1757 }
1758 }
1759 }
1760}
1761
1762
1763/* Create the group name with group name index for each set. */
1764
1765static void define_set_groups (void)
1766{
1767 struct set *set_ptr;
1768 char tmp[512];
1769
1770 for (set_ptr = sets; set_ptr != NULL; set_ptr = set_ptr->next)
1771 {
1772 strcpy (tmp, "GROUP");
1773 strcat (tmp, set_ptr->name);
1774 set_ptr->group_name = find_lname (tmp);
1775 }
1776}
1777
1778
1779/* Define three segments for each set. The segment names have already
1780 been defined, now write the SEGDEF records. */
1781
1782static void write_set_segs (void)
1783{
1784 int j;
1785 struct set *set_ptr;
1786
1787 for (set_ptr = sets; set_ptr != NULL; set_ptr = set_ptr->next)
1788 for (j = 0; j < 3; ++j)
1789 set_ptr->seg_index[j] =
1790 seg_def (set_ptr->seg_name[j], code_class_name,
1791 4 * (j == 1 ? set_ptr->count : set_ptr->def), FALSE);
1792}
1793
1794
1795/* Write the GRPDEF records for all the sets. One group consisting of
1796 three segments is defined for each set.
1797
1798 GRPDEF record:
1799 1/2 Group name index
1800 Ú
1801 ³1 0xff (use segment index)
1802 ³1/2 Segment index
1803 À
1804
1805 Group indices are assigned sequentially. */
1806
1807static void write_set_groups (void)
1808{
1809 int j;
1810 struct set *set_ptr;
1811
1812 for (set_ptr = sets; set_ptr != NULL; set_ptr = set_ptr->next)
1813 {
1814 set_ptr->group_index = group_index++;
1815 init_rec (GRPDEF);
1816 put_idx (set_ptr->group_name);
1817 for (j = 0; j < 3; ++j)
1818 {
1819 put_8 (0xff); put_idx (set_ptr->seg_index[j]);
1820 }
1821 write_rec ();
1822 }
1823}
1824
1825
1826/* Write the PUBDEF records for all the sets. One PUBDEF record is
1827 generated for each set, it defines the set name. */
1828
1829static void write_set_pub (void)
1830{
1831 struct set *set_ptr;
1832
1833 for (set_ptr = sets; set_ptr != NULL; set_ptr = set_ptr->next)
1834 if (set_ptr->def)
1835 {
1836 init_rec (force_big ? PUBDEF|REC32 : PUBDEF);
1837 put_idx (flat_index);
1838 put_idx (set_ptr->seg_index[0]);
1839 put_sym (set_ptr->name);
1840 if (force_big)
1841 put_32 (0);
1842 else
1843 put_16 (0);
1844 put_idx (0); /* Type index */
1845 write_rec ();
1846 }
1847}
1848
1849
1850/* Write the segment contents for all the sets. One or three segments
1851 are written for each set XXX:
1852
1853 SET1XXX long start = -2
1854 SET2XXX long table[]
1855 SET3XXX long end = 0
1856
1857 SET1XXX and SET3XXX are written only if there is a N_SETA symbol
1858 for the set. The N_SETA symbol defines the start of the set and
1859 must have a value of -1 (see crt0.s). SET2XXX is written for all
1860 modules which contain N_SETT or N_SETD symbols. All three segments
1861 belong to the group GROUPXXX. The linker combines all the segments
1862 of GROUPXXX into a single object. SET1XXX comes first, followed by
1863 the SET2XXX segments of all modules of the program, followed by
1864 SET3XXX. That way, we obtain a table of all set elements of a
1865 given set, preceded by -2 and terminated by 0. A symbol XXX is
1866 defined which points to the start of SET1XXX. See
1867 /emx/lib/gcc/main.c for code which uses sets. */
1868
1869static void write_set_data (void)
1870{
1871 struct set *set_ptr;
1872 dword x;
1873 int i, max_count;
1874 dword *buf;
1875 struct reloc *reloc_tab;
1876
1877 max_count = 0; buf = NULL; reloc_tab = NULL;
1878 for (set_ptr = sets; set_ptr != NULL; set_ptr = set_ptr->next)
1879 {
1880
1881 /* Write the first segment. It consists of a 32-bit word
1882 containing the number -2. This is used by the startup code
1883 to detect a delimited set. */
1884
1885 if (set_ptr->def)
1886 {
1887 x = 0xfffffffe;
1888 write_seg (set_ptr->seg_index[0], set_ptr->seg_name[0],
1889 (byte *)&x, sizeof (x), NULL, 0, FALSE, NULL, 0, -1);
1890 }
1891
1892 /* Write the second segment. It consists of the set elements as
1893 taken from the a.out module. The elements are assumed to be
1894 pointers into the text segment. */
1895
1896 if (set_ptr->count >= 1)
1897 {
1898
1899 /* Enlarge the relocation table, if required. */
1900
1901 if (set_ptr->count > max_count)
1902 {
1903 max_count = set_ptr->count;
1904 buf = xrealloc (buf, 4 * max_count);
1905 memset (buf, 0, 4 * max_count);
1906 reloc_tab = xrealloc (reloc_tab,
1907 max_count * sizeof (struct reloc));
1908 }
1909
1910 /* Create one relocation table entry for each set
1911 element. */
1912
1913 for (i = 0; i < set_ptr->count; ++i)
1914 {
1915 buf[i] = set_ptr->data[i];
1916 reloc_tab[i].address = i * 4;
1917 reloc_tab[i].symbolnum = set_ptr->seg[i];
1918 reloc_tab[i].pcrel = 0;
1919 reloc_tab[i].length = 2;
1920 reloc_tab[i].ext = 0;
1921 reloc_tab[i].unused = 0;
1922 }
1923
1924 /* Write the segment data and fixups. */
1925
1926 write_seg (set_ptr->seg_index[1], set_ptr->seg_name[1],
1927 (byte *)buf, set_ptr->count * 4, reloc_tab,
1928 set_ptr->count * sizeof (struct reloc), FALSE, NULL, 0,
1929 -1);
1930 }
1931
1932 /* Write the third segment. It consists of a 32-bit word
1933 containing the value 0, marking the end of the table. */
1934
1935 if (set_ptr->def)
1936 {
1937 x = 0;
1938 write_seg (set_ptr->seg_index[2], set_ptr->seg_name[2],
1939 (byte *)&x, sizeof (x), NULL, 0, FALSE, NULL, 0, -1);
1940 }
1941 }
1942 if (buf != NULL)
1943 free (buf);
1944}
1945
1946
1947/* Find a relocation table entry by fixup address. */
1948
1949static const struct reloc *find_reloc_fixup (const struct reloc *rel,
1950 long rel_size, dword addr)
1951{
1952 int i, count;
1953
1954 count = rel_size / sizeof (struct reloc);
1955 for (i = 0; i < count; ++i)
1956 if (rel[i].address == addr)
1957 return &rel[i];
1958 return NULL;
1959}
1960
1961
1962static void free_modstr_cache (void)
1963{
1964 struct modstr *p1, *p2;
1965
1966 for (p1 = modstr_cache; p1 != NULL; p1 = p2)
1967 {
1968 p2 = p1->next;
1969 free (p1->symbol);
1970 free (p1->str);
1971 free (p1);
1972 }
1973 modstr_cache = NULL;
1974}
1975
1976
1977/* Fetch a null-terminated string from a module. REL points to the
1978 relocation table entry of the pointer, ADDR is the pointer. Copy
1979 the string to DST, a buffer of DST_SIZE bytes. Return TRUE if
1980 successful, FALSE on failure. */
1981
1982static int fetch_modstr (const struct reloc *rel, dword addr,
1983 char *dst, size_t dst_size)
1984{
1985 const byte *seg_ptr;
1986 dword seg_size;
1987
1988 if (rel == NULL) return FALSE;
1989 if (rel->ext)
1990 {
1991 struct modstr *p;
1992 byte *buf;
1993 const char *sym_name;
1994 const struct nlist *m_sym = NULL;
1995 const struct a_out_header *m_ao = NULL;
1996
1997 /* We have to take the string from another module. First try to
1998 get the string from the cache. */
1999
2000 sym_name = str_ptr + sym_ptr[rel->symbolnum].string;
2001 for (p = modstr_cache; p != NULL; p = p->next)
2002 if (strcmp (p->symbol, sym_name) == 0)
2003 break;
2004 if (p == NULL)
2005 {
2006 long pos, size, m_str_size;
2007 struct ar_hdr ar;
2008 byte *t;
2009 size_t buf_size, len;
2010 const byte *m_str;
2011 int i, m_sym_count, found;
2012
2013 /* Search all modules until finding the symbol. */
2014
2015 buf = NULL; buf_size = 0; found = FALSE;
2016 pos = SARMAG;
2017 while (ar_read_header (&ar, pos))
2018 {
2019 size = ar_member_size (&ar);
2020 pos += (sizeof (ar) + size + 1) & -2;
2021 if (strcmp (ar.ar_name, "__.SYMDEF") == 0
2022 || strcmp (ar.ar_name, "__.IMPORT") == 0
2023 || memcmp (ar.ar_name, "IMPORT#", 7) == 0)
2024 continue;
2025 if (size > buf_size)
2026 {
2027 if (buf != NULL) free (buf);
2028 buf_size = size;
2029 buf = xmalloc (buf_size);
2030 }
2031 size = fread (buf, 1, size, inp_file);
2032 if (ferror (inp_file))
2033 error ("Cannot read `%s'", inp_fname);
2034 m_ao = (const struct a_out_header *)buf;
2035 if (size < sizeof (struct a_out_header) || m_ao->magic != 0407)
2036 break;
2037 t = buf + sizeof (struct a_out_header);
2038 t += m_ao->text_size; t += m_ao->data_size;
2039 t += m_ao->trsize; t += m_ao->drsize;
2040 m_sym = (const struct nlist *)t; t += m_ao->sym_size;
2041 m_str = t;
2042 if (m_str + 4 - buf > size)
2043 break;
2044 m_str_size = *(long *)m_str;
2045 m_sym_count = m_ao->sym_size / sizeof (struct nlist);
2046 if (m_str + m_str_size - buf > size)
2047 break;
2048 for (i = 0; i < m_sym_count; ++i)
2049 switch (m_sym[i].type)
2050 {
2051 case N_TEXT|N_EXT:
2052 case N_DATA|N_EXT:
2053 if (strcmp (m_str + m_sym[i].string, sym_name) == 0)
2054 {
2055 m_sym += i; found = TRUE; break;
2056 }
2057 }
2058 if (found)
2059 break;
2060 }
2061 if (!found)
2062 error ("Symbol `%s' not found", sym_name);
2063
2064 addr = m_sym->value;
2065 switch (m_sym->type)
2066 {
2067 case N_TEXT|N_EXT:
2068 seg_ptr = buf + sizeof (struct a_out_header);
2069 seg_size = m_ao->text_size;
2070 break;
2071 case N_DATA|N_EXT:
2072 seg_ptr = buf + sizeof (struct a_out_header) + m_ao->text_size;
2073 seg_size = m_ao->data_size;
2074 break;
2075 default:
2076 abort ();
2077 }
2078
2079 len = 0;
2080 for (;;)
2081 {
2082 if (addr + len >= seg_size)
2083 error ("String extends beyond end of segment");
2084 if (seg_ptr[addr + len] == 0)
2085 break;
2086 ++len;
2087 }
2088
2089 p = xmalloc (sizeof (struct modstr));
2090 p->symbol = xstrdup (sym_name);
2091 p->str = xmalloc (len + 1);
2092 memcpy (p->str, seg_ptr + addr, len + 1);
2093 p->next = modstr_cache;
2094 modstr_cache = p;
2095 if (buf != NULL) free (buf);
2096 }
2097 if (strlen (p->str) >= dst_size)
2098 return FALSE;
2099 strcpy (dst, p->str);
2100 return TRUE;
2101 }
2102 else
2103 {
2104 dword si;
2105
2106 switch (rel->symbolnum)
2107 {
2108 case N_TEXT:
2109 seg_ptr = text_ptr;
2110 seg_size = text_size;
2111 break;
2112 case N_DATA:
2113 seg_ptr = data_ptr;
2114 seg_size = data_size;
2115 break;
2116 default:
2117 return FALSE;
2118 }
2119 for (si = 0; addr + si < seg_size && si < dst_size; ++si)
2120 {
2121 dst[si] = seg_ptr[addr + si];
2122 if (seg_ptr[addr + si] == 0)
2123 return TRUE;
2124 }
2125 return FALSE;
2126 }
2127}
2128
2129
2130/* Create an import record and a PUBDEF record. */
2131
2132static void make_import (const char *pub_name, const char *proc_name,
2133 long ord, const char *mod)
2134{
2135 /* Skip a leading underscore character if present. */
2136
2137 if (*pub_name == '_')
2138 ++pub_name;
2139
2140 /* Make the symbol public in the output library. */
2141
2142 if (omflib_add_pub (out_lib, pub_name, mod_page, lib_errmsg) != 0)
2143 error (lib_errmsg);
2144
2145 /* Write the import definition record. */
2146
2147 init_rec (COMENT);
2148 put_8 (0x00);
2149 put_8 (IMPDEF_CLASS);
2150 put_8 (IMPDEF_SUBTYPE);
2151 put_8 (proc_name == NULL ? 0x01 : 0x00); /* Import by ordinal or by name */
2152 put_str (pub_name); /* Underscore already removed above */
2153 put_str (mod);
2154 if (proc_name == NULL)
2155 put_16 (ord);
2156 else if (strcmp (proc_name, pub_name) == 0)
2157 put_8 (0);
2158 else
2159 put_str (proc_name);
2160 write_rec ();
2161 init_rec (MODEND|REC32);
2162 put_8 (0x00); /* Non-main module without start address */
2163 write_rec ();
2164}
2165
2166
2167/* If the input file is an import module (method (I2) as created by
2168 emximp), create an OMF-style import module and return TRUE.
2169 Otherwise, return FALSE. */
2170
2171static int handle_import_i2 (void)
2172{
2173 int i, len1, mod_len;
2174 long ord;
2175 const char *name1, *name2, *proc_name, *p;
2176 char mod[256], *q;
2177
2178 /* Search the symbol table for N_IMP1 and N_IMP2 symbols. These are
2179 unique to import modules. */
2180
2181 name1 = NULL; name2 = NULL;
2182 for (i = 0; i < sym_count; ++i)
2183 switch (sym_ptr[i].type)
2184 {
2185 case N_IMP1|N_EXT:
2186 name1 = str_ptr + sym_ptr[i].string;
2187 break;
2188 case N_IMP2|N_EXT:
2189 name2 = str_ptr + sym_ptr[i].string;
2190 break;
2191 default:
2192 return FALSE;
2193 }
2194
2195 /* If no N_IMP1 and N_IMP2 symbols have been found, the module is
2196 not an import module. */
2197
2198 if (name1 == NULL || name2 == NULL)
2199 return FALSE;
2200
2201 /* Parse the special symbols into module name and ordinal number.
2202 name2 should look like
2203
2204 SYMBOL=MODULE.ORDINAL
2205
2206 where SYMBOL is name1, MODULE is the module name and ORDINAL is
2207 the ordinal number. */
2208
2209 len1 = strlen (name1);
2210 if (memcmp (name1, name2, len1) != 0)
2211 error ("Invalid import record: names don't match");
2212 name2 += len1;
2213 if (*name2 != '=')
2214 error ("Invalid import record: missing `='");
2215 ++name2;
2216 p = strchr (name2, '.');
2217 if (p == NULL)
2218 error ("Invalid import record: missing `.'");
2219 mod_len = p - name2;
2220 memcpy (mod, name2, mod_len);
2221 mod[mod_len] = 0;
2222 proc_name = NULL;
2223 errno = 0;
2224 ord = strtol (p + 1, &q, 10);
2225 if (q != p + 1 && *q == 0 && errno == 0)
2226 {
2227 if (ord < 1 || ord > 65535)
2228 error ("Invalid import record: invalid ordinal");
2229 }
2230 else
2231 {
2232 ord = -1;
2233 proc_name = p + 1;
2234 if (*proc_name == 0)
2235 error ("Invalid import record: invalid name");
2236 }
2237
2238 make_import (name1, proc_name, ord, mod);
2239 return TRUE;
2240}
2241
2242
2243/* If the input file is an import module (method (I1) as created by
2244 emximp), create an OMF-style import module and return TRUE.
2245 Otherwise, return FALSE. */
2246
2247static int handle_import_i1 (void)
2248{
2249 int i;
2250 const char *pub_name;
2251 char proc_name[257], dll_name[257];
2252 long table_off, ord, off;
2253 long *table;
2254 const struct reloc *rel;
2255
2256 /* There must be exactly one public symbol (which must defined for
2257 N_TEXT), otherwise we cannot safely eliminate all the code.
2258 Moreover, there must be an N_SETT|N_EXT entry for `__os2dll'. */
2259
2260 pub_name = NULL; table_off = -1;
2261 for (i = 0; i < sym_count; ++i)
2262 switch (sym_ptr[i].type)
2263 {
2264 case N_TEXT|N_EXT:
2265 if (pub_name != NULL) return FALSE;
2266 pub_name = str_ptr + sym_ptr[i].string;
2267 break;
2268
2269 case N_DATA|N_EXT:
2270 case N_BSS|N_EXT:
2271 return FALSE;
2272
2273 case N_SETT|N_EXT:
2274 if (strcmp (str_ptr + sym_ptr[i].string, "__os2dll") != 0)
2275 return FALSE;
2276 table_off = sym_ptr[i].value;
2277 break;
2278 }
2279
2280 if (pub_name == NULL || table_off == -1)
2281 return FALSE;
2282
2283 /* The table must be completely present. */
2284
2285 if (table_off < 0 || table_off + 4 * 4 > text_size)
2286 error ("Invalid import table: beyond end of segment");
2287
2288 /* Fetch the procedure name or the ordinal. */
2289
2290 table = (long *)(text_ptr + table_off);
2291 if (table[0] == 0)
2292 {
2293 ord = 0;
2294
2295 /* Check and fetch the procedure name. */
2296
2297 rel = find_reloc_fixup (text_rel, a_out_h->trsize, table_off + 3 * 4);
2298 if (!fetch_modstr (rel, table[3], proc_name, sizeof (proc_name)))
2299 error ("Invalid import table: invalid pointer to procedure name");
2300 }
2301 else if (table[0] == 1)
2302 {
2303 ord = table[3];
2304 if (ord < 1 || ord > 65535)
2305 error ("Invalid import table: invalid ordinal number");
2306 }
2307 else
2308 error ("Invalid import table: invalid flag");
2309
2310 /* Check the fixup address -- there must be a JMP instruction. */
2311
2312 off = table[1];
2313 if (off < 1 || off + 4 > text_size)
2314 error ("Invalid import table: invalid fixup address");
2315 if (text_ptr[off-1] != 0xe9)
2316 error ("Invalid import table: fixup does not belong to a JMP instruction");
2317
2318 /* Check and fetch the module name. */
2319
2320 rel = find_reloc_fixup (text_rel, a_out_h->trsize, table_off + 2 * 4);
2321 if (!fetch_modstr (rel, table[2], dll_name, sizeof (dll_name)))
2322 error ("Invalid import table: invalid pointer to module name");
2323
2324 make_import (pub_name, ord != 0 ? NULL : proc_name, ord, dll_name);
2325 return TRUE;
2326}
2327
2328
2329/* Convert a filename from Unix format to OS/2 format. All that has
2330 to be done is replacing slashes with backslashes as IPMD doesn't
2331 like slashes in file names. The conversion is done in place. */
2332
2333static void convert_filename (char *name)
2334{
2335 while (*name != 0)
2336 {
2337 if (*name == '/')
2338 *name = '\\';
2339 ++name;
2340 }
2341}
2342
2343
2344/* Derive the module name and store it to the mod_name variable.
2345 Search the symbol table for an N_SO symbol. If there is no such
2346 symbol, use the output file name. */
2347
2348static void get_mod_name (void)
2349{
2350 int i, len, ok;
2351 const char *p1, *p2;
2352
2353 ok = FALSE;
2354 for (i = 0; i < sym_count; ++i)
2355 if (sym_ptr[i].type == N_SO)
2356 {
2357 p1 = str_ptr + sym_ptr[i].string;
2358 len = strlen (p1);
2359 if (len > 0 && p1[len-1] != '/')
2360 {
2361 ok = TRUE;
2362 _strncpy (mod_name, p1, sizeof (mod_name));
2363 convert_filename (mod_name);
2364 break;
2365 }
2366 }
2367 if (!ok && out_lib == NULL)
2368 {
2369 p1 = out_fname;
2370 for (p2 = p1; *p2 != 0; ++p2)
2371 if (*p2 == '/' || *p2 == '\\' || *p2 == ':')
2372 p1 = p2 + 1;
2373 _strncpy (mod_name, p1, sizeof (mod_name));
2374 }
2375}
2376
2377
2378/* Write the translator module header record. When creating a .LIB
2379 file, this function does nothing. Otherwise, the module name is
2380 expected in the mod_name variable. */
2381
2382static void write_theadr (void)
2383{
2384 if (out_lib == NULL)
2385 {
2386 init_rec (THEADR);
2387 put_str (mod_name);
2388 write_rec ();
2389 }
2390}
2391
2392/* Tell LINK386 what identifier manipulator DLL to call. The name of
2393 the DLL is given by `idmdll_name', the default value of which is
2394 GPPDEMID. The name can be changed with the -I option. If -I- is
2395 given, no IDMDLL record will be written. The IDMDLL record will
2396 also be suppressed if the program hasn't been compiled by the GNU
2397 C++ compiler. */
2398
2399static void write_idmdll ()
2400{
2401 if (idmdll_name != NULL && find_symbol ("__gnu_compiled_cplusplus") != NULL)
2402 {
2403 init_rec (COMENT);
2404 put_8 (0x00);
2405 put_8 (0xaf);
2406 put_str (idmdll_name);
2407 put_str (""); /* Initialization parameter */
2408 write_rec ();
2409 }
2410}
2411
2412
2413/* Find a file name for creating line number information. */
2414
2415static int file_find (const char *name)
2416{
2417 int i;
2418
2419 for (i = 0; i < file_grow.count; ++i)
2420 if (strcmp (file_list[i], name) == 0)
2421 return i;
2422 if (file_grow.count >= 255)
2423 {
2424 warning ("Too many source files, cannot convert line number info");
2425 return file_grow.count;
2426 }
2427 grow_by (&file_grow, 1);
2428 i = file_grow.count++;
2429 file_list[i] = xstrdup (name);
2430 return i;
2431}
2432
2433
2434/* This function is passed to qsort() for sorting line numbers. X1
2435 and X2 point to struct line structures. Line number entries are
2436 sorted by address, file and line number. */
2437
2438static int line_compare (const void *x1, const void *x2)
2439{
2440 dword a1, a2;
2441 int i1, i2;
2442
2443 a1 = ((const struct line *)x1)->addr;
2444 a2 = ((const struct line *)x2)->addr;
2445 if (a1 < a2)
2446 return -1;
2447 else if (a1 > a2)
2448 return 1;
2449 i1 = ((const struct line *)x1)->file_index;
2450 i2 = ((const struct line *)x2)->file_index;
2451 if (i1 < i2)
2452 return -1;
2453 else if (i1 > i2)
2454 return 1;
2455 i1 = ((const struct line *)x1)->line;
2456 i2 = ((const struct line *)x2)->line;
2457 if (i1 < i2)
2458 return -1;
2459 else if (i1 > i2)
2460 return 1;
2461 return 0;
2462}
2463
2464
2465/* Write line number information to the output file. Unfortunately,
2466 the line number information format currently used by IPMD is not
2467 documented. This code is based on experimentation. */
2468
2469static void write_linnum (void)
2470{
2471 int i, started, len, file_index;
2472 int valid_lines;
2473 struct line *line_list;
2474 struct grow line_grow;
2475 char buf[256];
2476
2477 /* Initialize growing arrays for file names and line numbers. */
2478
2479 grow_init (&file_grow, &file_list, sizeof (*file_list), 8);
2480 grow_init (&line_grow, &line_list, sizeof (*line_list), 64);
2481
2482 /* Define file index for main source file. */
2483
2484 file_index = file_find (mod_name);
2485 started = FALSE;
2486
2487 /* Go through the symbol table, defining line numbers and additional
2488 source files. */
2489
2490 for (i = 0; i < sym_count; ++i)
2491 switch (sym_ptr[i].type)
2492 {
2493 case N_SOL:
2494 file_index = file_find (str_ptr + sym_ptr[i].string);
2495 break;
2496 case N_SLINE:
2497 grow_by (&line_grow, 1);
2498 line_list[line_grow.count].file_index = file_index;
2499 line_list[line_grow.count].line = sym_ptr[i].desc;
2500 line_list[line_grow.count].addr = sym_ptr[i].value;
2501 ++line_grow.count;
2502 }
2503
2504 /* Sort the line numbers by address, file and line number. */
2505
2506 qsort (line_list, line_grow.count, sizeof (*line_list), line_compare);
2507
2508 /* If there are multiple line numbers assigned to the same address,
2509 keep but the last line number. Delete line numbers by setting
2510 the line number to -1. */
2511
2512 for (i = 0; i < line_grow.count - 1; ++i)
2513 if (line_list[i].line >= 0 && line_list[i+1].line >= 0
2514 && line_list[i].addr == line_list[i+1].addr)
2515 line_list[i].line = -1;
2516
2517 /* Count the number of valid line numbers, that is, non-negative
2518 line numbers. */
2519
2520 valid_lines = 0;
2521 for (i = 0; i < line_grow.count; ++i)
2522 if (line_list[i].line >= 0)
2523 ++valid_lines;
2524
2525 /* Compute the size of the file names table. */
2526
2527 len = 3 * 4;
2528 for (i = 0; i < file_grow.count; ++i)
2529 len += 1 + strlen (file_list[i]);
2530
2531 /* Write the line number table. */
2532
2533 init_rec (LINNUM|REC32);
2534 started = TRUE;
2535 put_idx (0); /* Base Group */
2536 put_idx (text_index); /* Base Segment */
2537
2538 put_16 (0); /* Line number = 0 (special entry) */
2539 put_8 (0); /* Entry type: source and offset */
2540 put_8 (0); /* Reserved */
2541 put_16 (valid_lines); /* Count of line number entries */
2542 put_16 (0); /* Segment number */
2543 put_32 (len); /* Size of file names table */
2544
2545 for (i = 0; i < line_grow.count; ++i)
2546 if (line_list[i].line >= 0)
2547 {
2548 if (started && !fits (8))
2549 {
2550 write_rec ();
2551 started = FALSE;
2552 }
2553 if (!started)
2554 {
2555 init_rec (LINNUM|REC32);
2556 put_idx (0); /* Base Group */
2557 put_idx (text_index); /* Base Segment */
2558 started = TRUE;
2559 }
2560 put_16 (line_list[i].line);
2561 put_16(line_list[i].file_index + 1);
2562 put_32 (line_list[i].addr);
2563 }
2564
2565 /* Now write the file names table. */
2566
2567 if (started && !fits (12))
2568 {
2569 write_rec ();
2570 started = FALSE;
2571 }
2572 if (!started)
2573 {
2574 init_rec (LINNUM|REC32);
2575 put_idx (0); /* Base Group */
2576 put_idx (text_index); /* Base Segment */
2577 started = TRUE;
2578 }
2579 put_32 (0); /* First column */
2580 put_32 (0); /* Number of columns */
2581 put_32 (file_grow.count); /* Number of source and listing files */
2582
2583 for (i = 0; i < file_grow.count; ++i)
2584 {
2585 len = strlen (file_list[i]);
2586 if (len > sizeof (buf) - 1)
2587 len = sizeof (buf) - 1;
2588 memcpy (buf, file_list[i], len);
2589 buf[len] = 0;
2590 convert_filename (buf);
2591 if (started && !fits (1 + len))
2592 {
2593 write_rec ();
2594 started = FALSE;
2595 }
2596 if (!started)
2597 {
2598 init_rec (LINNUM|REC32);
2599 put_idx (0); /* Base Group */
2600 put_idx (text_index); /* Base Segment */
2601 started = TRUE;
2602 }
2603 put_8 (len);
2604 put_mem (buf, len);
2605 }
2606
2607 if (started)
2608 write_rec ();
2609
2610 grow_free (&line_grow);
2611 grow_free (&file_grow);
2612}
2613
2614
2615/* Print unknown symbol table entries (-u option). */
2616
2617static void list_unknown_stabs (void)
2618{
2619 int i;
2620
2621 for (i = 0; i < sym_count; ++i)
2622 switch (sym_ptr[i].type)
2623 {
2624 case 0: case 0 |N_EXT:
2625 case N_ABS: case N_ABS |N_EXT:
2626 case N_TEXT: case N_TEXT|N_EXT:
2627 case N_DATA: case N_DATA|N_EXT:
2628 case N_BSS: case N_BSS |N_EXT:
2629 case N_INDR|N_EXT:
2630 case N_WEAKU:
2631 case N_SETA: case N_SETA|N_EXT:
2632 case N_SETT: case N_SETT|N_EXT:
2633 case N_SETD: case N_SETD|N_EXT:
2634 case N_GSYM:
2635 case N_FUN:
2636 case N_STSYM:
2637 case N_LCSYM:
2638 case N_RSYM:
2639 case N_SLINE:
2640 case N_SO:
2641 case N_IMP1|N_EXT:
2642 case N_IMP2|N_EXT:
2643 case N_LSYM:
2644 case N_SOL:
2645 case N_PSYM:
2646 case N_LBRAC:
2647 case N_RBRAC:
2648 break;
2649 default:
2650 fprintf (stderr, "Unknown symbol table entry: 0x%.2x \"%s\"\n",
2651 sym_ptr[i].type, str_ptr + sym_ptr[i].string);
2652 break;
2653 }
2654}
2655
2656/* Convert an a.out module to an OMF module. SIZE is the number of
2657 bytes in the input file inp_file. */
2658
2659static void o_to_omf (long size)
2660{
2661 byte *t;
2662 const struct nlist *entry_symbol;
2663 int i;
2664
2665 /* Simplify things by reading the complete a.out module into
2666 memory. */
2667
2668 inp_buf = xmalloc (size);
2669 size = fread (inp_buf, 1, size, inp_file);
2670 if (ferror (inp_file))
2671 goto read_error;
2672
2673 /* Set up pointers to various sections of the module read into
2674 memory. */
2675
2676 a_out_h = (struct a_out_header *)inp_buf;
2677 if (size < sizeof (struct a_out_header) || a_out_h->magic != 0407)
2678 error ("Input file `%s' is not an a.out file", error_fname);
2679 text_size = a_out_h->text_size;
2680 data_size = a_out_h->data_size;
2681 t = inp_buf + sizeof (struct a_out_header);
2682 text_ptr = t; t += text_size;
2683 data_ptr = t; t += data_size;
2684 text_rel = (const struct reloc *)t; t += a_out_h->trsize;
2685 data_rel = (const struct reloc *)t; t += a_out_h->drsize;
2686 sym_ptr = (const struct nlist *)t; t += a_out_h->sym_size;
2687 str_ptr = t;
2688 if (a_out_h->sym_size == 0)
2689 str_size = 0;
2690 else
2691 {
2692 if (str_ptr + 4 - inp_buf > size)
2693 goto invalid;
2694 str_size = *(long *)str_ptr;
2695 }
2696 sym_count = a_out_h->sym_size / sizeof (struct nlist);
2697 if (str_ptr + str_size - inp_buf > size)
2698 goto invalid;
2699
2700 /* Build the complementary array of symbol data. */
2701
2702 sym_more = xmalloc (sym_count * sizeof (struct symbol));
2703 for (i = 0; i < sym_count; ++i)
2704 {
2705 sym_more[i].index = 0;
2706 sym_more[i].flags = 0;
2707 }
2708
2709 /* Print unknown symbol table entries if the -u option is given. */
2710
2711 if (unknown_stabs)
2712 list_unknown_stabs ();
2713
2714 /* Find the start symbol if converting a main module. */
2715
2716 if (entry_name != NULL)
2717 {
2718 entry_symbol = find_symbol (entry_name);
2719 if (entry_symbol == NULL)
2720 error ("Entry symbol not found");
2721 if ((entry_symbol->type & ~N_EXT) != N_TEXT)
2722 error ("Entry symbol not in text segment");
2723 }
2724 else
2725 entry_symbol = NULL; /* keep the compiler happy */
2726
2727 /* Initialize variables for a new OMF module. */
2728
2729 init_obj ();
2730
2731 /* If the a.out module is an import module as created by emximp,
2732 create an OMF import module. Everything is done by
2733 handle_import_i2() or handle_import_i1() in that case, therefore
2734 we can simply return. */
2735
2736 if (out_lib != NULL && (handle_import_i2 () || handle_import_i1 ()))
2737 return;
2738
2739 /* Initialize growing arrays for debug information conversion.
2740 These two arrays contain indices at which the $$SYMBOLS and
2741 $$TYPES segments, respectively, can be split into LEDATA records
2742 by write_seg(). */
2743
2744 grow_init (&sst_boundary_grow, &sst_boundary, sizeof (*sst_boundary), 32);
2745 grow_init (&tt_boundary_grow, &tt_boundary, sizeof (*tt_boundary), 32);
2746
2747 /* Create some OMF names. */
2748
2749 ovl_name = find_lname ("");
2750 text_seg_name = find_lname ("TEXT32");
2751 data_seg_name = find_lname ("DATA32");
2752 bss_seg_name = find_lname ("BSS32");
2753 if (udat_seg_string != NULL)
2754 udat_seg_name = find_lname (udat_seg_string);
2755 else
2756 udat_seg_name = data_seg_name;
2757 if (!strip_symbols)
2758 {
2759 symbols_seg_name = find_lname ("$$SYMBOLS");
2760 types_seg_name = find_lname ("$$TYPES");
2761 }
2762 code_class_name = find_lname ("CODE");
2763 data_class_name = find_lname ("DATA");
2764 bss_class_name = find_lname ("BSS");
2765 if (!strip_symbols)
2766 {
2767 debsym_class_name = find_lname ("DEBSYM");
2768 debtyp_class_name = find_lname ("DEBTYP");
2769 }
2770 define_set_names ();
2771 if (mod_type == MT_MAIN)
2772 {
2773 stack_seg_name = find_lname ("STACK");
2774 stack_class_name = find_lname ("STACK");
2775 }
2776 flat_group_name = find_lname ("FLAT");
2777 dgroup_group_name = find_lname ("DGROUP");
2778 if (do_set_groups)
2779 define_set_groups ();
2780
2781 /* Write the THREADR record. */
2782
2783 get_mod_name ();
2784 write_theadr ();
2785
2786 /* Tell LINK386 what identifier manipulator DLL to use. */
2787
2788 write_idmdll ();
2789
2790 /* Write default library requests and the debug information style
2791 record (COMENT records). */
2792
2793 write_libs ();
2794 write_debug_style ();
2795
2796 /* Define all the OMF names (LNAMES record). Of course, we must not
2797 define new OMF names after this point. */
2798
2799 write_lnames ();
2800
2801 /* Define segments (SEGDEF records). This must be done after
2802 defining the names and before defining the groups. */
2803
2804 text_index = seg_def (text_seg_name, code_class_name, text_size,
2805 FALSE);
2806 write_set_segs ();
2807
2808 if (udat_seg_string != NULL)
2809 udat_index = seg_def (udat_seg_name, data_class_name, data_size,
2810 FALSE);
2811 data_index = seg_def (data_seg_name, data_class_name,
2812 (udat_seg_string == NULL ? data_size : 0),
2813 FALSE);
2814 if (udat_seg_string == NULL)
2815 udat_index = data_index;
2816
2817 bss_index = seg_def (bss_seg_name, bss_class_name, a_out_h->bss_size,
2818 FALSE);
2819
2820 if (mod_type == MT_MAIN)
2821 stack_index = seg_def (stack_seg_name, stack_class_name, 0x8000, TRUE);
2822
2823 if (!strip_symbols)
2824 {
2825 convert_debug (); /* After seg_def of text, data & bss */
2826 symbols_index = seg_def (symbols_seg_name, debsym_class_name,
2827 sst.size, FALSE);
2828 types_index = seg_def (types_seg_name, debtyp_class_name,
2829 tt.size, FALSE);
2830 }
2831
2832 /* Define groups (GRPDEF records). This must be done after defining
2833 segments. */
2834
2835 flat_index = group_index++;
2836 init_rec (GRPDEF);
2837 put_idx (flat_group_name);
2838 write_rec ();
2839
2840 dgroup_index = group_index++;
2841 init_rec (GRPDEF);
2842 put_idx (dgroup_group_name);
2843 put_8 (0xff); put_idx (bss_index);
2844 put_8 (0xff); put_idx (data_index);
2845 write_rec ();
2846
2847 if (do_set_groups)
2848 write_set_groups ();
2849
2850 /* Define external, communal and public symbols (EXTDEF, WKEXT,
2851 COMDEF, PUBDEF, and ALIAS records). This must be done after
2852 defining the groups. */
2853
2854 write_extdef ();
2855 write_wkext ();
2856 write_comdef ();
2857 write_pubdef ();
2858 write_set_pub ();
2859 write_alias ();
2860
2861 /* Write link pass separator. */
2862
2863 write_pass2 ();
2864
2865 /* Write segment contents (LEDATA and FIXUPP records) and line
2866 number information (LINNUM record). */
2867
2868 write_seg (text_index, text_seg_name, text_ptr, text_size,
2869 text_rel, a_out_h->trsize, FALSE, NULL, 0, N_TEXT);
2870 write_seg (udat_index, udat_seg_name, data_ptr, data_size,
2871 data_rel, a_out_h->drsize, FALSE, NULL, 0, N_DATA);
2872
2873 write_set_data ();
2874
2875 if (!strip_symbols)
2876 {
2877 write_seg (types_index, types_seg_name, tt.buf, tt.size, NULL, 0, FALSE,
2878 tt_boundary, tt_boundary_grow.count, -1);
2879 write_seg (symbols_index, symbols_seg_name, sst.buf, sst.size,
2880 (const struct reloc *)sst_reloc.buf, sst_reloc.size, TRUE,
2881 sst_boundary, sst_boundary_grow.count, -1);
2882 write_linnum ();
2883 }
2884
2885 /* End of module. */
2886
2887 init_rec (MODEND|REC32);
2888 if (entry_name != NULL)
2889 {
2890 put_8 (0xc1); /* Main module with start address */
2891 put_8 (0x50); /* ENDDAT: F5, T0 */
2892 put_idx (text_index);
2893 put_32 (entry_symbol->value);
2894 }
2895 else
2896 put_8 (0x00); /* Non-main module without start address */
2897 write_rec ();
2898
2899 /* Clean up memory. */
2900
2901 free_lnames ();
2902 free (inp_buf);
2903 free (sym_more);
2904 buffer_free (&tt);
2905 buffer_free (&sst);
2906 buffer_free (&sst_reloc);
2907 grow_free (&sst_boundary_grow);
2908 grow_free (&tt_boundary_grow);
2909 return;
2910
2911read_error:
2912 error ("Cannot read `%s'", error_fname);
2913
2914invalid:
2915 error ("Malformed a.out file `%s'", error_fname);
2916}
2917
2918
2919/* Display some hints on using this program, then quit. */
2920
2921static void usage (void)
2922{
2923 puts ("emxomf " VERSION " -- Copyright (c) 1992-1995 by Eberhard Mattes\n");
2924 puts ("Usage:");
2925 puts (" emxomf [-dgqs] [-l[<symbol>]] [-m <symbol>] [-p <page_size>]");
2926 puts (" [-i <default_lib>] [-I <idmdll>] [-D <dataseg>]");
2927 puts (" -o <output_file> <input_file>");
2928 puts (" emxomf [-dgqsx] [-l[<symbol>]] [-m <symbol>] [-p <page_size>]");
2929 puts (" [-O <directory>] [-r|R <response_file>] [-i <default_lib>]");
2930 puts (" [-I <idmdll>] [-D <dataseg>] <input_file>...");
2931 puts ("\nOptions:");
2932 puts (" -d Delete input files except for archives");
2933 puts (" -g Create groups for sets");
2934 puts (" -i <default_lib> Add default library request");
2935 puts (" -l[<symbol>] Convert library modules, with optional entrypoint");
2936 puts (" -m <symbol> Convert main module with entrypoint <symbol>");
2937 puts (" -o <output_file> Write output to <output_file>");
2938 puts (" -p <page_size> Set page size for LIB files");
2939 puts (" -q Suppress certain warnings");
2940 puts (" -r <response_file> Write response file for adding modules");
2941 puts (" -R <response_file> Write response file for replacing modules");
2942 puts (" -s Strip debugging information");
2943 puts (" -u List symbol table entries unknown to emxomf");
2944 puts (" -x Extract archive members");
2945 puts (" -D <dataseg> Change the name of the data segment");
2946 puts (" -I <idmdll> Name the identifier manipulation DLL");
2947 puts (" -O <directory> Extract files to <directory>");
2948 exit (1);
2949}
2950
2951
2952/* Create the output file. If the -r or -R option is used, create the
2953 LIB resonse file. */
2954
2955static void open_output (void)
2956{
2957 char *tmp, *p;
2958
2959 out_file = fopen (out_fname, "wb");
2960 if (out_file == NULL)
2961 error ("Cannot create output file `%s'", out_fname);
2962 if (response_file != NULL)
2963 {
2964 if (response_first)
2965 response_first = FALSE;
2966 else
2967 fprintf (response_file, " &\n");
2968 tmp = alloca (strlen (out_fname) + 1);
2969 strcpy (tmp, out_fname);
2970 for (p = tmp; *p != 0; ++p)
2971 if (*p == '/')
2972 *p = '\\';
2973 fprintf (response_file, "%s %s", (response_replace ? "-+" : "+"), tmp);
2974 }
2975}
2976
2977
2978/* Close the output file. Display an error message and quit on
2979 failure. */
2980
2981static void close_output (void)
2982{
2983 if (fflush (out_file) != 0 || fclose (out_file) != 0)
2984 {
2985 out_file = NULL;
2986 error ("Write error on output file `%s'", out_fname);
2987 }
2988 out_file = NULL;
2989}
2990
2991
2992/* Define or build the name of the output file. If DST_FNAME is not
2993 NULL, use it as name of the output file. Otherwise, build the name
2994 from INP_FNAME (the input file name) and EXT (the extension). If
2995 an output directory has been specified with the -O option, remove
2996 the directory part of INP_FNAME and use output_dir instead. */
2997
2998static void make_out_fname (const char *dst_fname, const char *inp_fname,
2999 const char *ext)
3000{
3001 static char tmp1[MAXPATHLEN+3];
3002 char tmp2[MAXPATHLEN+3];
3003
3004 if (dst_fname == NULL)
3005 {
3006 if (*output_dir != 0)
3007 _splitpath (inp_fname, NULL, NULL, tmp2, NULL);
3008 else
3009 _strncpy (tmp2, inp_fname, MAXPATHLEN);
3010 if (strlen (output_dir) + strlen (tmp2) + 5 > MAXPATHLEN)
3011 error ("File name `%s' too long", inp_fname);
3012 strcpy (tmp1, output_dir);
3013 strcat (tmp1, tmp2);
3014 _remext (tmp1);
3015 strcat (tmp1, ext);
3016 out_fname = tmp1;
3017 }
3018 else
3019 out_fname = dst_fname;
3020}
3021
3022
3023/* Read the header of an archive member at file position POS. Return
3024 FALSE when reaching the end of the file. */
3025
3026static int ar_read_header (struct ar_hdr *dst, long pos)
3027{
3028 int size, i;
3029
3030 fseek (inp_file, pos, SEEK_SET);
3031 size = fread (dst, 1, sizeof (struct ar_hdr), inp_file);
3032 if (size == 0)
3033 return FALSE;
3034 else if (size != sizeof (struct ar_hdr))
3035 error ("Malformed archive `%s'", inp_fname);
3036
3037 /* Remove trailing blanks from the member name. */
3038
3039 i = sizeof (dst->ar_name) - 1;
3040 while (i > 0 && dst->ar_name[i-1] == ' ')
3041 --i;
3042 dst->ar_name[i] = 0;
3043 return TRUE;
3044}
3045
3046
3047/* Retrieve the size from the header of an archive member. */
3048
3049static long ar_member_size (const struct ar_hdr *p)
3050{
3051 long size;
3052 char *e;
3053
3054 errno = 0;
3055 size = strtol (p->ar_size, &e, 10);
3056 if (e == p->ar_size || errno != 0 || size <= 0 || *e != ' ')
3057 error ("Malformed archive header in `%s'", inp_fname);
3058 return size;
3059}
3060
3061
3062/* Convert the a.out file SRC_FNAME to an OMF file named DST_FNAME.
3063 If DST_FNAME is NULL, the output file name is derived from
3064 SRC_FNAME. */
3065
3066static void convert (const char *src_fname, const char *dst_fname)
3067{
3068 char tmp1[MAXPATHLEN+3], tmp2[MAXPATHLEN+3];
3069 char *p = NULL, *name, *end;
3070 long size, index;
3071 static char ar_magic[SARMAG+1] = ARMAG;
3072 char ar_test[SARMAG];
3073 struct ar_hdr ar;
3074 long ar_pos;
3075 struct delete *del;
3076 char *long_names = NULL;
3077 size_t long_names_size = 0;
3078
3079 inp_fname = src_fname;
3080 error_fname = inp_fname;
3081 mod_name[0] = 0;
3082 inp_file = fopen (inp_fname, "rb");
3083 if (inp_file == NULL)
3084 error ("Cannot open input file `%s'", inp_fname);
3085
3086 /* Read some bytes from the start of the file to find out whether
3087 this is an archive (.a) file or not. */
3088
3089 if (fread (ar_test, sizeof (ar_test), 1, inp_file) != 1)
3090 error ("Cannot read input file `%s'", inp_fname);
3091
3092 /* Create a LIB response file if requested and not yet done. */
3093
3094 if (response_fname != NULL && response_file == NULL)
3095 {
3096 response_file = fopen (response_fname, "wt");
3097 if (response_file == NULL)
3098 error ("Cannot create response file `%s'", response_fname);
3099 }
3100
3101 /* The rest of this function (save closing the input file) depends
3102 on whether the input file is an archive or not. */
3103
3104 if (memcmp (ar_test, ar_magic, SARMAG) == 0)
3105 {
3106
3107 /* The input file is an archive. We cannot procede if the user
3108 has specified an output file name and wants one OMF file to
3109 be written for each module in the archive (well, we could do
3110 it if there's exactly one module in the archive, but we
3111 don't). */
3112
3113 if (dst_fname != NULL && opt_x)
3114 error ("Cannot process archive if -o and -x are used");
3115 ar_pos = SARMAG;
3116
3117 /* Create an OMF library file (.LIB file) if the -x option is
3118 not given. */
3119
3120 if (!opt_x)
3121 {
3122 make_out_fname (dst_fname, inp_fname, ".lib");
3123 out_lib = omflib_create (out_fname, page_size, lib_errmsg);
3124 if (out_lib == NULL)
3125 error (lib_errmsg);
3126 if (omflib_header (out_lib, lib_errmsg) != 0)
3127 error (lib_errmsg);
3128 }
3129
3130 /* Loop over all the members of the archive. */
3131
3132 while (ar_read_header (&ar, ar_pos))
3133 {
3134 /* Decode the header. */
3135
3136 size = ar_member_size (&ar);
3137 ar_pos += (sizeof (ar) + size + 1) & -2;
3138
3139 if (strcmp (ar.ar_name, "ARFILENAMES/") == 0)
3140 {
3141 size_t i;
3142
3143 /* The "ARFILENAMES/" member contains the long file
3144 names, each one is terminated with a newline
3145 character. Member names starting with a space are
3146 also considered long file names because a leading
3147 space is used for names pointing into the
3148 "ARFILENAMES/" table. Read the "ARFILENAMES/" member
3149 to LONG_NAMES. */
3150
3151 if (size != 0)
3152 {
3153 long_names_size = (size_t)size;
3154 long_names = xmalloc (long_names_size);
3155 size = fread (long_names, 1, long_names_size, inp_file);
3156 if (ferror (inp_file))
3157 error ("Cannot read `%s'", inp_fname);
3158 if (size != long_names_size)
3159 error ("%s: ARFILENAMES/ member is truncated", inp_fname);
3160
3161 /* Replace the newlines with nulls to make
3162 processing a bit more convenient. */
3163
3164 for (i = 0; i < long_names_size; ++i)
3165 if (long_names[i] == '\n')
3166 long_names[i] = 0;
3167 if (long_names[long_names_size-1] != 0)
3168 error ("%s: ARFILENAMES/ member corrupt", inp_fname);
3169 }
3170 }
3171
3172 /* Ignore the __.SYMDEF and __.IMPORT members. Ignore
3173 import modules unless creating a library file. */
3174
3175 else if (strcmp (ar.ar_name, "__.SYMDEF") != 0
3176 && strcmp (ar.ar_name, "__.IMPORT") != 0
3177 && (memcmp (ar.ar_name, "IMPORT#", 7) != 0 || !opt_x))
3178 {
3179
3180 /* Convert the current member to OMF. First, fetch the
3181 name of the member. If the ar_name starts with a
3182 space, the decimal number following that space is an
3183 offset into the "ARFILENAMES/" member. The number
3184 may be followed by a space and a substring of the
3185 long file name. */
3186
3187 name = ar.ar_name;
3188 if (name[0] == ' ' && long_names != NULL
3189 && (index = strtol (name + 1, &end, 10)) >= 0
3190 && index < long_names_size - 1
3191 && (*end == 0 || *end == ' ')
3192 && (index == 0 || long_names[index-1] == 0))
3193 name = long_names + index;
3194
3195 /* Extract the base name of the member. */
3196
3197 _splitpath (name, NULL, NULL, tmp2, NULL);
3198 if (strlen (output_dir) + strlen (tmp2) + 5 > MAXPATHLEN)
3199 error ("File name `%s' too long", tmp2);
3200
3201 /* Provide for informative error message. Memory leak. */
3202
3203 p = xmalloc (strlen (inp_fname) + 3 + strlen (name));
3204 sprintf (p, "%s(%s)", inp_fname, name);
3205 error_fname = p;
3206
3207 /* Construct the module name for the THREADR record
3208 etc. */
3209
3210 _strncpy (mod_name, tmp2, sizeof (mod_name));
3211 strcat (tmp2, ".obj");
3212
3213 /* Create the output file (-x option) or add a new
3214 module to the output library (no -x option). */
3215
3216 if (opt_x)
3217 {
3218 strcpy (tmp1, output_dir);
3219 strcat (tmp1, tmp2);
3220 out_fname = tmp1;
3221 open_output ();
3222 }
3223 else
3224 {
3225 if (omflib_write_module (out_lib, tmp2, &mod_page,
3226 lib_errmsg) != 0)
3227 error (lib_errmsg);
3228 }
3229
3230 /* Convert the member and close the output file. */
3231
3232 o_to_omf (size);
3233 if (opt_x)
3234 close_output ();
3235 }
3236 if (p != NULL) free (p);
3237 }
3238
3239 /* Finish and close the library library if creating a library
3240 file. */
3241
3242 if (!opt_x)
3243 {
3244 if (omflib_finish (out_lib, lib_errmsg) != 0
3245 || omflib_close (out_lib, lib_errmsg) != 0)
3246 error (lib_errmsg);
3247 out_lib = NULL;
3248 }
3249 }
3250 else
3251 {
3252
3253 /* The input file is not an archive. We assume it being an
3254 a.out object file. Get the size of the file for
3255 o_to_omf(). */
3256
3257 if (fseek (inp_file, 0L, SEEK_END) != 0)
3258 error ("Input file `%s' is not seekable", inp_fname);
3259 size = ftell (inp_file);
3260 fseek (inp_file, 0L, SEEK_SET);
3261
3262 /* Convert the file. */
3263
3264 make_out_fname (dst_fname, inp_fname, ".obj");
3265 open_output ();
3266 o_to_omf (size);
3267 close_output ();
3268
3269 /* If input files are to be deleted (-d option), add the current
3270 input file to the list of files to be deleted. */
3271
3272 if (delete_input_files)
3273 {
3274 del = xmalloc (sizeof (struct delete));
3275 del->name = xstrdup (inp_fname);
3276 del->next = files_to_delete;
3277 files_to_delete = del;
3278 }
3279 }
3280 fclose (inp_file);
3281 free_modstr_cache ();
3282 if (long_names != NULL)
3283 free (long_names);
3284}
3285
3286
3287/* Delete all the files stored in the FILES_TO_DELETE list. While
3288 deleting the files, the list elements are deallocated. */
3289
3290static void delete_files (void)
3291{
3292 struct delete *p, *q;
3293
3294 for (p = files_to_delete; p != NULL; p = q)
3295 {
3296 q = p->next;
3297 remove (p->name);
3298 free (p->name);
3299 free (p);
3300 }
3301}
3302
3303
3304/* Main function of emxomf. Parse the command line and perform the
3305 requested actions. */
3306
3307int main (int argc, char *argv[])
3308{
3309 int c, i;
3310 char *opt_o, *opt_O, *tmp;
3311 struct libreq *lrp;
3312
3313 /* Keep emxomf in memory for the number of minutes indicated by the
3314 GCCLOAD environment variable. */
3315
3316 _emxload_env ("GCCLOAD");
3317
3318 /* Get options from the EMXOMFOPT environment variable, expand
3319 response files (@filename) and wildcard (*.o) on the command
3320 line. */
3321
3322 _envargs (&argc, &argv, "EMXOMFOPT");
3323 _response (&argc, &argv);
3324 _wildcard (&argc, &argv);
3325
3326 /* Set default values of some options. */
3327
3328 opt_o = NULL; opt_O = NULL;
3329 opterr = FALSE;
3330
3331 /* Parse the command line options. */
3332
3333 while ((c = getopt (argc, argv, "bdD:gi:I:m:l::o:p:qO:r:R:sux")) != EOF)
3334 switch (c)
3335 {
3336 case 'b':
3337 force_big = TRUE;
3338 break;
3339 case 'd':
3340 delete_input_files = TRUE;
3341 break;
3342 case 'D':
3343 udat_seg_string = optarg;
3344 break;
3345 case 'g':
3346 do_set_groups = TRUE;
3347 break;
3348 case 'i':
3349 lrp = xmalloc (sizeof (*lrp));
3350 lrp->next = NULL;
3351 lrp->name = xstrdup (optarg);
3352 *libreq_add = lrp;
3353 libreq_add = &lrp->next;
3354 break;
3355 case 'I':
3356 if (strcmp (optarg, "-") == 0)
3357 idmdll_name = NULL;
3358 else
3359 idmdll_name = optarg;
3360 break;
3361 case 'l':
3362 if (mod_type != MT_MODULE)
3363 usage ();
3364 mod_type = MT_LIB;
3365 entry_name = optarg;
3366 break;
3367 case 'm':
3368 if (mod_type != MT_MODULE)
3369 usage ();
3370 mod_type = MT_MAIN;
3371 entry_name = optarg;
3372 break;
3373 case 'o':
3374 if (opt_o != NULL || opt_O != NULL)
3375 usage ();
3376 opt_o = optarg;
3377 break;
3378 case 'p':
3379 errno = 0;
3380 page_size = (int)strtol (optarg, &tmp, 0);
3381 if (tmp == optarg || errno != 0 || *tmp != 0
3382 || page_size < 16 || page_size > 32768
3383 || (page_size & (page_size - 1)) != 0)
3384 usage ();
3385 break;
3386 case 'q':
3387 quiet = TRUE;
3388 break;
3389 case 'O':
3390 if (opt_o != NULL || opt_O != NULL)
3391 usage ();
3392 opt_O = optarg;
3393 break;
3394 case 'r':
3395 case 'R':
3396 if (response_fname != NULL)
3397 usage ();
3398 response_fname = optarg;
3399 response_replace = (c == 'R');
3400 break;
3401 case 's':
3402 strip_symbols = TRUE;
3403 break;
3404 case 'u':
3405 unknown_stabs = TRUE;
3406 break;
3407 case 'x':
3408 opt_x = TRUE;
3409 break;
3410 default:
3411 usage ();
3412 }
3413
3414 /* Check for non-option arguments. */
3415
3416 if (argc - optind == 0)
3417 usage ();
3418
3419 if (opt_o != NULL)
3420 {
3421
3422 /* If the -o option is used, there must be exactly one input
3423 file name. */
3424
3425 if (argc - optind != 1)
3426 usage ();
3427 convert (argv[optind], opt_o);
3428 }
3429 else
3430 {
3431
3432 /* The -o option is not used. If the -O option is used, set up
3433 output_dir. */
3434
3435 if (opt_O != NULL)
3436 {
3437 i = strlen (opt_O);
3438 tmp = xmalloc (i + 2);
3439 strcpy (tmp, opt_O);
3440 if (i > 0 && strchr (":\\/", tmp[i-1]) == NULL)
3441 strcat (tmp, "/");
3442 output_dir = tmp;
3443 }
3444
3445 /* Convert all the files named on the command line. */
3446
3447 for (i = optind; i < argc; ++i)
3448 convert (argv[i], NULL);
3449 }
3450
3451 /* If a LIB response file has been created, finish and close it. */
3452
3453 if (response_file != NULL)
3454 {
3455 if (!response_first)
3456 fprintf (response_file, "\n");
3457 if (fflush (response_file) != 0 || fclose (response_file) != 0)
3458 error ("Write error on response file `%s'", response_fname);
3459 }
3460
3461 /* If the user wants input files to be deleted, delete them now. */
3462
3463 if (delete_input_files)
3464 delete_files ();
3465 return 0;
3466}
Note: See TracBrowser for help on using the repository browser.