source: trunk/emx/src/emxomf/emxomf.c@ 3920

Last change on this file since 3920 was 3920, checked in by bird, 11 years ago

trunk,0.6: Reduce stabs -> hll conversion warnings to a single warning per file by default, use new '-v' option to get all warnings and '-q' to shut them up completely.

  • Property cvs2svn:cvs-rev set to 1.43
  • Property svn:eol-style set to native
  • Property svn:executable set to *
File size: 130.8 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 <alloca.h>
28#include <ctype.h>
29#include <getopt.h>
30#include <alloca.h>
31#include <sys/param.h>
32#include <sys/emxload.h>
33#include <sys/types.h>
34#include <sys/stat.h>
35#include <sys/time.h>
36#include <ar.h>
37#include <assert.h>
38
39/* Insert private header files. */
40
41#include "defs.h" /* Common definitions */
42#include "emxomf.h" /* Global definitions for emxomf */
43#include "stabshll.h" /* Convert debug information */
44#include "grow.h" /* Growing objects */
45
46/* This header must come after defs.h */
47
48#include <sys/omflib.h> /* Handling OMF libraries */
49
50/* Flag bits for FLAGS field of the struct symbol structure. */
51
52#define SF_FAR16 0x01 /* 16:16 pointer */
53
54/* Length of the weak marker. */
55
56#define SYMBOL_WEAK_LENGTH (3 + 11 + 6)
57
58/* Length of the OMF symbol hash */
59
60#define SYMBOL_HASH_LENGTH (2 + 6)
61
62/* Max OMF symbol length */
63
64#define SYMBOL_MAX_LENGTH (255 - SYMBOL_HASH_LENGTH - SYMBOL_WEAK_LENGTH)
65/* This structure holds additional data for symbols. */
66
67struct symbol
68{
69 int index; /* EXTDEF index */
70 int flags; /* SF_FAR16 */
71 int hll_type; /* HLL type index. */
72};
73
74/* This program keeps OMF symbols (names) in a list of lname
75 structures. */
76
77struct lname
78{
79 struct lname *next; /* Pointer to next element */
80 char *name; /* Name of the symbol */
81 int index; /* OMF index of the symbol */
82};
83
84/* Names of files to be deleted on program termination are stored in a
85 list of delete structures. */
86
87struct delete
88{
89 struct delete *next; /* Pointer to next element */
90 char *name; /* Name of the file to be deleted */
91};
92
93/* This structure holds the information about one class (set) of a.out
94 set elements. Set elements are used for constructors and
95 destructors. These structures are chained in a list. See
96 write_set_data() for details. */
97
98struct set
99{
100 struct set *next; /* Pointer to next class of set elements */
101 char *name; /* Name of the set (the a.out symbol) */
102 int seg_name[3]; /* Name indices of the three segments */
103 int seg_index[3]; /* Segment indices of the three segments */
104 int def; /* Non-zero if head element encountered */
105 int count; /* Number of non-head non-tail elements */
106 dword *data; /* Values of set elements (COUNT elements) */
107 byte *seg; /* Segments of set elements (COUNT elements) */
108};
109
110/* Default library requests (see -i option) are stored in a list of
111 libreq structures. */
112
113struct libreq
114{
115 char *name; /* Name of the default library */
116 struct libreq *next; /* Pointer to next element */
117};
118
119/* This structure describes an OMF-style line number. */
120
121struct line
122{
123 dword addr; /* Start address of the line */
124 int line; /* Line number */
125 int file_index; /* File index */
126};
127
128/* fetch_modstr() caches the string it has retrieved from other
129 modules of the same library. The cache consists of a a linked list
130 of `struct modstr' structures. */
131
132struct modstr
133{
134 struct modstr *next; /* Pointer to next node */
135 char *symbol; /* Symbol attached to the string */
136 char *str; /* The value of the string */
137};
138
139
140/* The number of symbols in the a.out file. */
141int sym_count = 0;
142
143/* The sym_ptr variable points to an array of a.out symbols. There
144 are sym_count table entries. Note that this table is complemented
145 by the sym_more table. */
146const struct nlist *sym_ptr = NULL;
147
148/* The str_ptr variable points to the a.out string table. The
149 elements of sym_ptr contain offsets into this table. The table
150 starts with a 32-bit number. The rest of the table consists of
151 null-terminated strings. */
152const byte *str_ptr = NULL;
153
154/* The text_ptr variable points to the first byte of the text
155 segment. text_size bytes are available at text_ptr. */
156byte *text_ptr = NULL;
157long text_size = 0;
158
159/* The data_ptr variable points to the first byte of the data
160 segment. data_size bytes are available at data_ptr. */
161
162static byte *data_ptr;
163static long data_size;
164
165/* These varibles point to the text and data relocation tables. */
166
167static const struct relocation_info *text_rel;
168static const struct relocation_info *data_rel;
169
170/* Public variables for communication with stabshll.c. */
171
172struct buffer tt = BUFFER_INIT;
173struct buffer sst = BUFFER_INIT;
174struct buffer sst_reloc = BUFFER_INIT;
175struct grow sst_boundary_grow = GROW_INIT;
176struct grow tt_boundary_grow = GROW_INIT;
177int *sst_boundary = NULL;
178int *tt_boundary = NULL;
179/** The HLL version of the HLL debuginfo we're generating.
180 * Default level is 4.
181 *
182 * VisualAge 3.65 iLink support HLL v6
183 * VisualAge 3.08 iLink support HLL v4
184 * Link386 support HLL v3 (?)
185 */
186int hll_version = 4;
187
188/* Private variables. */
189
190/* The name of the current input file. */
191static const char *inp_fname;
192
193/* The name of the current output file. */
194static const char *out_fname = NULL;
195
196/* Use this file name for reporting errors. This is either the name
197 of the input file or a library name plus module name:
198 library(module). */
199const char *error_fname;
200
201/* The output directory. This is set by the -O option. */
202static const char *output_dir = "";
203
204/* The current input file. */
205static FILE *inp_file;
206
207/* The current output file. */
208static FILE *out_file = NULL;
209
210/* While writing a LIB response file, this variable contains the
211 stream pointer. Otherwise, this variable is NULL. */
212static FILE *response_file = NULL;
213
214/* When creating an OMF library (.lib file), this variable contains
215 the descriptor used by the omflib library. Otherwise, this
216 variable is NULL. */
217static struct omflib *out_lib = NULL;
218
219/* This buffer receives error messages from the omflib library. */
220static char lib_errmsg[512];
221
222/* emxomf reads a complete a.out module into memory. inp_buf points
223 to the buffer holding the current a.out module. This pointer is
224 aliased by sym_ptr etc. */
225static byte *inp_buf;
226
227/* OMF records are constructed in this buffer. The first three bytes
228 are used for the record type and record length. One byte at the
229 end is used for the checksum. */
230static byte out_buf[1+2+MAX_REC_SIZE+1];
231
232/* Index into out_buf (to be more precise: it's a pointer into
233 out_data, which is an alias to out_buf+3) for the next byte of the
234 OMF record. */
235static int out_idx;
236
237/* The list of OMF names. lnames is the head of the list, lname_add
238 is used to add another name to the end of the list. */
239static struct lname *lnames;
240static struct lname **lname_add;
241
242/* The list of sets. sets is the head of the list, set_add is used to
243 add another set to the end of the list. */
244static struct set *sets;
245static struct set **set_add;
246
247/* If this variable is TRUE, an a.out archive is split into several
248 OMF .obj files (-x option). If this variable is FALSE, an a.out
249 archive is converted into an OMF library file. */
250static int opt_x = FALSE;
251
252/* Remove underscores from all symbol names */
253static int opt_rmunder = FALSE;
254
255/* This is the page size for OMF libraries. It is set by the -p
256 option. */
257static int page_size = 0;
258
259/* The index of the next OMF name, used by find_lname(). Name indices
260 are established by LNAMES records written by write_lnames(). */
261static int lname_index;
262
263/* The index of the next segment, used by seg_def() for creating
264 SEGDEF records. */
265static int segdef_index;
266
267/* The index of the next group, used for creating GRPDEF records. */
268static int group_index;
269
270/* The index of the next symbol, used for creating EXTDEF and COMDEF
271 records. */
272static int sym_index;
273
274/* The index of the "WEAK$ZERO" symbol or 0. */
275static int weak_zero_index;
276
277/* OMF name indices: segments, classes, groups, etc. */
278static int ovl_name; /* Overlay name, "" */
279static int text_seg_name; /* Text segment, "TEXT32" */
280static int data_seg_name; /* Data segment, "DATA32" */
281static int udat_seg_name; /* Explicit data segment, see -D */
282static int stack_seg_name; /* Stack segment, "STACK" */
283static int bss_seg_name; /* Uninitialized data segment, "BSS32" */
284static int symbols_seg_name; /* Symbols segment, "$$SYMBOLS" */
285static int types_seg_name; /* Types segment */
286static int code_class_name; /* Code class, "CODE" */
287static int data_class_name; /* Data class, "DATA" */
288static int stack_class_name; /* Stack class, "STACK" */
289static int bss_class_name; /* Uninitialized data class, "BSS" */
290static int debsym_class_name; /* Symbols class, "DEBSYM" */
291static int debtyp_class_name; /* Types class, "DEBTYP" */
292static int flat_group_name; /* FLAT group, "FLAT" */
293static int dgroup_group_name; /* DGROUP group, "DGROUP" or "DATAGROUP" */
294
295/* Segment indices for the TEXT32, DATA32, STACK, BSS32, $$SYMBOLS,
296 $$TYPES and explicit data segments. */
297static int text_index; /* Text segment, TEXT32 */
298static int data_index; /* Data segment, DATA32 */
299static int udat_index; /* Data segment set by -D or same as above */
300static int stack_index; /* Stack segment, STACK */
301static int bss_index; /* Uninitialized data segment, BSS32 */
302static int symbols_index; /* Symbols segment, $$SYMBOLS */
303static int types_index; /* Types segment, $$TYPES */
304
305/* Group indices for the FLAT and DGROUP groups. */
306static int flat_index; /* FLAT group */
307static int dgroup_index; /* DGROUP group */
308
309/* Next FIXUPP thread index to be used for the frame and target
310 thread, respectively. */
311static int frame_thread_index; /* Frame thread */
312static int target_thread_index; /* Target thread */
313
314/* We define target threads for referencing the TEXT32, DATA32 (or the
315 one set by -D) and BSS32 segments and the FLAT group in FIXUPP
316 records. A thread has not been defined if the variable is -1.
317 Otherwise, the value is the thread number. */
318static int text_thread; /* TEXT32 segment */
319static int data_thread; /* Data segment (DATA32 or -D) */
320static int bss_thread; /* BSS32 segment */
321static int flat_thread; /* FLAT group */
322
323/* This variable holds the module name. See get_mod_name(). */
324static char mod_name[256];
325
326/* This variable holds the base(=current) directory. See get_mod_name(). */
327static char base_dir[256];
328
329/* This variable holds the timestamped weak marker for the current module. */
330static char weak_marker[SYMBOL_WEAK_LENGTH + 1];
331
332/* This growing array holds the file name table for generating line
333 number information. */
334static char **file_list;
335static struct grow file_grow;
336
337/* This variable points to the a.out header of the input module. */
338static const struct exec *a_out_h;
339
340/* This table contains additional information for the a.out symbols.
341 Each entry of the sym_ptr table is complemented by an entry of this
342 table. */
343static struct symbol *sym_more;
344
345/* The length of the a.out string table, in bytes. This value
346 includes the 32-bit number at the start of the string table. */
347static long str_size;
348
349/* omflib_write_module() stored the page number of the module to this
350 variable. */
351static word mod_page;
352
353/* This variable is TRUE until we have written the first line to the
354 LIB response file. It is used to suppress the line continuation
355 character `&'. */
356static int response_first = TRUE;
357
358/* This is the list of files to be deleted on program termination.
359 See delete_files(). */
360static struct delete *files_to_delete = NULL;
361
362/* The module type (-l and -m options). It is MT_MODULE unless the -l
363 or -m option is used. */
364static enum {MT_MODULE, MT_MAIN, MT_LIB} mod_type = MT_MODULE;
365
366/* The start (entry point) symbol (-m option). This is NULL unless
367 the -m option (or -l with argument) is used. */
368static char *entry_name = NULL;
369
370/* The name of the identifier manipulation DLL. If this variable is
371 NULL, no IDMDLL record is written. */
372static char *idmdll_name = "INNIDM";
373
374/* the name of the debug packing DLL. This variable is not used when
375 debug info is stripped. If NULL we'll select the default for the
376 linker type (EMXOMFLD_TYPE). */
377static char *dbgpack_name = NULL;
378
379/* If this variable is TRUE (-b option), we always use the 32-bit
380 variant of the OMF records. If this variable is FALSE, we use the
381 16-bit variant whenever possible. This non-documented feature is
382 used for debugging. */
383static int force_big = FALSE;
384
385/* The name of the LIB response file (-r and -R options). This value
386 is NULL unless the -r or -R option is used. */
387static char *response_fname = NULL;
388
389/* When creating a LIB response file, emit commands for replacing
390 modules if this variable is TRUE (-R option). Otherwise, emit
391 commands for adding modules (-r option). */
392static int response_replace;
393
394/* Delete input files after successful conversion if this variable is
395 TRUE (-d option). */
396static int delete_input_files = FALSE;
397
398/* Strip debug information if this variable is TRUE (-s option).
399 Otherwise, convert DBX debugging information to HLL debugging
400 information. */
401static int strip_symbols = FALSE;
402
403/* Print unknown symbol table entries if this variable is TRUE (-u
404 option). */
405static int unknown_stabs = FALSE;
406
407/* Warning level (-q & -v options). */
408int warning_level = 1;
409
410/* The libreq_head variable contains a pointer to the head of the list
411 of default libraries. The -i option is used to add a default
412 library request. The libreq_add pointer is used for appending new
413 elements to the tail of the list. */
414static struct libreq *libreq_head = NULL;
415static struct libreq **libreq_add = &libreq_head;
416
417/* fetch_mod_str() caches the string it has retrieved from other
418 modules of the same library. modstr_cache points to the head of
419 the linked list of `struct modstr' structures. */
420
421static struct modstr *modstr_cache = NULL;
422
423/* Simulate the data array of an OMF record. The data is stored along
424 with the record type (1 byte) and record length (2 bytes) in a
425 single buffer. */
426#define out_data (out_buf+1+2)
427
428/* The data segment name, set by the -D option. If this value is
429 non-NULL, put variables into the named data segment, which isn't a
430 member of DGROUP. */
431
432static char *udat_seg_string = NULL;
433
434/* Prototypes for private functions. */
435
436static void doesn_fit (void) NORETURN2;
437static void usage (void) NORETURN2;
438static int ar_read_header (struct ar_hdr *dst, long pos);
439static long ar_member_size (const struct ar_hdr *p);
440
441
442/* Display an error message on stderr, delete the output file and
443 quit. This function is invoked like printf(): FMT is a
444 printf-style format string, all other arguments are formatted
445 according to FMT. The message should not end with a newline. The
446 exit code is 2. */
447
448void error (const char *fmt, ...)
449{
450 va_list arg_ptr;
451
452 va_start (arg_ptr, fmt);
453 fprintf (stderr, "emxomf: ");
454 vfprintf (stderr, fmt, arg_ptr);
455 va_end (arg_ptr);
456 fputc ('\n', stderr);
457
458 /* If there is an output file, close and delete it. */
459
460 if (out_file != NULL)
461 {
462 fclose (out_file);
463 remove (out_fname);
464 }
465 exit (2);
466}
467
468
469/* Display a warning message on stderr (and do not quit). This
470 function is invoked like printf(): FMT is a printf-style format
471 string, all other arguments are formatted according to FMT. */
472
473void warning (const char *fmt, ...)
474{
475 va_list arg_ptr;
476
477 va_start (arg_ptr, fmt);
478 fprintf (stderr, "emxomf warning: ");
479 vfprintf (stderr, fmt, arg_ptr);
480 va_end (arg_ptr);
481 fputc ('\n', stderr);
482}
483
484
485/* Allocate N bytes of memory. Quit on failure. This function is
486 used like malloc(), but we don't have to check the return value. */
487
488void *xmalloc (size_t n)
489{
490 void *p;
491
492 p = malloc (n);
493 if (p == NULL && n)
494 error ("Out of memory");
495 return p;
496}
497
498
499/* Change the allocation of PTR to N bytes. Quit on failure. This
500 function is used like realloc(), but we don't have to check the
501 return value. */
502
503void *xrealloc (void *ptr, size_t n)
504{
505 void *p;
506
507 p = realloc (ptr, n);
508 if (p == NULL && n)
509 error ("Out of memory");
510 return p;
511}
512
513
514/* Create a duplicate of the string S on the heap. Quit on failure.
515 This function is used like strdup(), but we don't have to check the
516 return value. */
517
518char *xstrdup (const char *s)
519{
520 char *p;
521
522 p = xmalloc (strlen (s) + 1);
523 strcpy (p, s);
524 return p;
525}
526
527
528/* Check if we should remove the leading underscore from a symbol name */
529static inline int strip_underscore (const char *name)
530{
531 if (!opt_rmunder)
532 return 0;
533
534 return (*name == '_');
535}
536
537
538/* Find an a.out symbol. The underscore character `_' is prepended to
539 NAME. On success, a pointer to the symbol table entry (in the
540 array pointed to by sym_ptr) is returned. If the symbol is not
541 found, NULL is returned.
542 NOT_ENTRY is an entry index which is not to be found.
543 FEXT is an indicator on whether or not we can find external symbols or
544 not. */
545const struct nlist *find_symbol_ex (const char *name, int not_entry, int fext)
546{
547 int i, j, n, len, t;
548 const byte *s;
549
550 i = 4; len = strlen (name);
551
552 /* Search the string table for a matching string. */
553 while (i < str_size)
554 {
555 int sym_ofs = i;
556 s = (const byte *)name;
557 if (strip_underscore ((const char *)(str_ptr + i)))
558 ++i;
559 if (memcmp (name, str_ptr+i, len+1) == 0)
560 {
561 /* Search the symbol table for an appropriate entry
562 referencing the string. */
563 n = sym_count;
564 for (j = 0; j < n; ++j)
565 if (sym_ptr[j].n_un.n_strx == sym_ofs && j != not_entry)
566 {
567 t = sym_ptr[j].n_type & ~N_EXT;
568 if ( t == N_TEXT || t == N_DATA || t == N_BSS
569 || (fext && sym_ptr[j].n_type == N_EXT)
570 || (sym_ptr[j].n_type >= N_WEAKA && sym_ptr[j].n_type <= N_WEAKB)
571 || (t == 0 && sym_ptr[j].n_value != 0))
572 return sym_ptr+j;
573 }
574 }
575 i += strlen ((const char *)(str_ptr + i)) + 1;
576 }
577 return NULL; /* Symbol not found */
578}
579
580/* Find an a.out symbol. The underscore character `_' is prepended to
581 NAME. On success, a pointer to the symbol table entry (in the
582 array pointed to by sym_ptr) is returned. If the symbol is not
583 found, NULL is returned. */
584const struct nlist *find_symbol (const char *name)
585{
586 return find_symbol_ex (name, -1, 0);
587}
588
589
590/* Set the hll_type of a symbols. */
591void set_hll_type (int index, int hll_type)
592{
593 if (index > sym_count || index < 0)
594 error ("Internal error! Invalid index (%d) passed to set_hll_type().", index);
595
596 /* Ignore type indexes we cannot encode (see put_idx), though, issue a
597 warning the first time we see this in a file (our repeat detection
598 isn't prefect as heap can be reused, but it'll have to do). */
599 if (hll_type < 0 || hll_type > 0x7fff)
600 {
601 static const char *s_pszComplainedFor = NULL;
602 if (s_pszComplainedFor != error_fname)
603 {
604 s_pszComplainedFor = error_fname;
605 if (warning_level >= 1)
606 warning("Input file '%s' has more HLL debug types than we can index in PUBDEF and EXTDEF records.",
607 error_fname);
608 }
609 hll_type = 0;
610 }
611
612 sym_more[index].hll_type = hll_type;
613}
614
615
616/* Initialize variables for starting a new OMF output file. */
617
618static void init_obj (void)
619{
620 /* Initialize the list of OMF-style names. */
621
622 lnames = NULL; lname_add = &lnames; lname_index = 1;
623
624 /* Initialize segments. */
625
626 segdef_index = 1; sym_index = 1; group_index = 1; weak_zero_index = 0;
627
628 /* Initialize FIXUPP threads. */
629
630 text_thread = -1; data_thread = -1; bss_thread = -1; flat_thread = -1;
631 frame_thread_index = 0; target_thread_index = 0;
632
633 /* Initialize set elements management. */
634
635 sets = NULL; set_add = &sets;
636
637 /* Initialize the buffers used for converting debugging
638 information. */
639
640 buffer_init (&tt);
641 buffer_init (&sst);
642 buffer_init (&sst_reloc);
643
644 /* Init weak markers */
645
646 weak_marker[0] = '\0';
647}
648
649
650/* Find an OMF-style name. If NAME is not yet a known OMF-style name,
651 it is added to the list of OMF-style names. The index of the name
652 is returned. All the OMF-style names will be defined in LNAMES
653 records. Note: INDEX must be assigned sequentially, append to end
654 of list! Otherwise, write_lnames() would have to sort the list */
655
656static int find_lname (const char *name)
657{
658 struct lname *p;
659
660/** @todo: change this to use a stringpool for speed reasons! */
661
662 /* Walk through the list of known OMF-style names. If there is a
663 match, return the index of the name. */
664
665 for (p = lnames; p != NULL; p = p->next)
666 if (strcmp (name, p->name) == 0)
667 return p->index;
668
669 /* The name is not yet known. Create a new entry. */
670
671 p = xmalloc (sizeof (struct lname));
672 p->name = xstrdup (name);
673 p->index = lname_index++;
674
675 /* Add the new entry to the tail of the list of names. */
676
677 p->next = NULL;
678 *lname_add = p;
679 lname_add = &p->next;
680
681 /* Return the index of the new name. */
682
683 return p->index;
684}
685
686
687/* Deallocate the memory used by the list of OMF-style names. */
688
689static void free_lnames (void)
690{
691 struct lname *p, *q;
692
693 for (p = lnames; p != NULL; p = q)
694 {
695 q = p->next;
696 free (p->name);
697 free (p);
698 }
699}
700
701
702/* Start a new OMF record. TYPE is the record type. */
703
704static void init_rec (int type)
705{
706 out_buf[0] = (byte)type;
707 out_idx = 0;
708}
709
710
711/* Write an OMF record. The record type has been defined by
712 init_rec(), the data has been defined by put_8(), put_idx() etc.
713 The checksum is computed by this function. An OMF record has the
714 following format:
715
716 struct omf_record
717 {
718 byte type; The record type
719 word length; The record length, exclusive TYPE and LENGTH
720 byte data[LENGTH-1]; The record data
721 byte checksum; The check sum. The sum of all the bytes in
722 the record is 0 (module 256)
723 };
724
725 If we're writing a LIB file, we call omflib_write_record().
726 Otherwise, we build and write the record here. An OMF record
727 usually contains multiple definitions, see write_lnames() for a
728 simple instance of the loop we use for packing multiple definitions
729 into OMF records. */
730
731static void write_rec (void)
732{
733 byte chksum;
734 int i;
735
736 if (out_lib != NULL)
737 {
738
739 /* Write the record to the library file. */
740
741 if (omflib_write_record (out_lib, out_buf[0], out_idx, out_data,
742 TRUE, lib_errmsg) != 0)
743 error (lib_errmsg);
744 }
745 else
746 {
747
748 /* Store the record length, LSB first. */
749
750 out_buf[1] = (byte)(out_idx+1);
751 out_buf[2] = (byte)((out_idx+1) >> 8);
752
753 /* Compute the check sum. */
754
755 chksum = 0;
756 for (i = 0; i < 1+2+out_idx; ++i)
757 chksum += out_buf[i];
758 out_data[out_idx] = (byte)(256-chksum);
759
760 /* Write the record. */
761
762 if (fwrite (out_buf, 1+2+out_idx+1, 1, out_file) != 1)
763 error ("Write error on output file `%s'", out_fname);
764 }
765}
766
767
768/* This macro yields TRUE iff we can put another X bytes into the
769 current OMF record. */
770
771#define fits(X) (out_idx + (X) <= MAX_REC_SIZE-4)
772
773/* This function is called if we try to build too big an OMF record.
774 This cannot happen unless there is a bug in this program. Display
775 an error message and quit. */
776
777static void doesn_fit (void)
778{
779 error ("Record too long");
780}
781
782
783/* Calculates the hash for a string using the original djb2 aglorithm. */
784
785static unsigned hash_string(const char *pch, size_t cch)
786{
787 unsigned uHash;
788 for (uHash = 5381; cch > 0; pch++, cch--)
789 uHash += (uHash << 5) + *pch;
790 return uHash;
791}
792
793/* Formats a 64-bit number with a fixed with. The purpose is to encode
794 a unique number as tiny as possible while keeping within what any
795 linker should accept. The width is fixed, and the string is clipped
796 or padded with zeros to satisfy that. The return value is psz + cchWidth. */
797
798static char *format_u64(uint64_t u64, char *psz, unsigned uRadix, int cchWidth)
799{
800 static const char s_achDigits[] = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
801 static const unsigned s_cchDigits = sizeof(s_achDigits) / sizeof(s_achDigits[0]) - 1;
802 assert(uRadix <= s_cchDigits);
803 while (cchWidth-- > 0)
804 {
805 unsigned i = u64 % uRadix;
806 *psz++ = s_achDigits[i];
807 u64 /= uRadix;
808 }
809 assert(!u64);
810 *psz = '\0';
811 return psz;
812}
813
814/* Put the string pszName into the given buffer pOutBuf (which must be at least
815 256 bytes long). The string length must not exceed 255 bytes (OMF format
816 requirement); if it is too long, display a warning and truncate the string.
817 The string returned in pOutBuf is zero-terminated. The function returns the
818 length of the resulting string. */
819
820static int make_nstr (const char *pszName, size_t cch, char *pszOutBuf)
821{
822 if ( cch > SYMBOL_MAX_LENGTH
823 && !strstr(pszName + SYMBOL_MAX_LENGTH - SYMBOL_WEAK_LENGTH, "!_")
824 && !strstr(pszName + SYMBOL_MAX_LENGTH - SYMBOL_WEAK_LENGTH, "$w$"))
825 {
826 /* Hash the symbol to help making it unique.
827 * NOTE that the hash algorithm is not fixed, so is the !_%X marker too.
828 * the weakld is parsing it!
829 */
830 unsigned uHash = hash_string(pszName, cch);
831 char szHash[SYMBOL_HASH_LENGTH + 1];
832 char *psz;
833 szHash[0] = '!';
834 szHash[1] = '_';
835 psz = format_u64((uint32_t)uHash, &szHash[2], 62, 6);
836 assert(psz - &szHash[0] == SYMBOL_HASH_LENGTH);
837
838 memcpy(pszOutBuf, pszName, SYMBOL_MAX_LENGTH);
839 memcpy(pszOutBuf + SYMBOL_MAX_LENGTH, szHash, SYMBOL_HASH_LENGTH);
840 pszOutBuf[SYMBOL_MAX_LENGTH + SYMBOL_HASH_LENGTH] = '\0';
841
842 warning ("Truncated symbol '%.*s' to '%.*s%s'", cch, pszName, SYMBOL_MAX_LENGTH, pszName, szHash);
843
844 cch = SYMBOL_MAX_LENGTH + SYMBOL_HASH_LENGTH;
845 }
846 else
847 {
848 assert(cch <= 0xff);
849 cch &= 0xff;
850 memcpy(pszOutBuf, pszName, cch);
851 pszOutBuf[cch] = '\0';
852 }
853 return cch;
854}
855
856/* Put the string pszName into the current OMF record.
857 In the OMF record, the string is preceded by a length byte. The
858 string length must not exceed 255; if it is too long, display a
859 warning and truncate the string. Moreover, there must be enough
860 space left in the OMF record; if there isn't, display an error
861 message and abort. */
862
863static void put_nstr(const char *pszName, size_t cch)
864{
865 char szName[256];
866
867 cch = make_nstr(pszName, cch, szName);
868
869 if (!fits(1 + cch))
870 doesn_fit();
871 out_data[out_idx++] = (byte)cch;
872 memcpy(out_data+out_idx, szName, cch);
873 out_idx += cch;
874}
875
876/* Put the null-terminated string pszName into the current OMF record.
877 See put_nstr() for full details on string handling. */
878
879static inline void put_str(const char *pszName)
880{
881 put_nstr(pszName, strlen(pszName));
882}
883
884
885/* Put the symbol SRC, a null-terminated string, into the current OMF
886 record. If SRC starts with the underscore character `_', that
887 character is skipped. This is where the leading underscore
888 character of a.out symbols is removed. C modules for emx.dll are
889 treated specially here: The leading underscore is not removed
890 unless the name looks like the name of an OS/2 API function. The
891 symbol length (after removing the leading underscore) must not
892 exceed 255 characters. There must be enough space left in the OMF
893 record. If these conditions are not met, display an error message
894 and quit. */
895
896static void put_sym (const char *src)
897{
898 if (strip_underscore (src))
899 ++src;
900 put_str (src);
901}
902
903/* Put an 8-bit byte into the current OMF record. This macro does not
904 test for buffer / record overflow. */
905
906#define put_8(x) out_data[out_idx++] = (byte)(x)
907
908/* Put a 16-bit word (least significant byte first) into the current
909 OMF record. If there is not enough space left in the OMF record,
910 display an error message and quit. */
911
912static void put_16 (int x)
913{
914 if (!fits (2))
915 doesn_fit ();
916 out_data[out_idx++] = (byte)x;
917 out_data[out_idx++] = (byte)(x >> 8);
918}
919
920
921/* Put a 24-bit word (least significant byte first) into the current
922 OMF record. If there is not enough space left in the OMF record,
923 display an error message and quit. */
924
925static void put_24 (long x)
926{
927 if (!fits (3))
928 doesn_fit ();
929 out_data[out_idx++] = (byte)x;
930 out_data[out_idx++] = (byte)(x >> 8);
931 out_data[out_idx++] = (byte)(x >> 16);
932}
933
934
935/* Put a 32-bit word (least significant byte first) into the current
936 OMF record. If there is not enough space left in the OMF record,
937 display an error message and quit. */
938
939static void put_32 (long x)
940{
941 if (!fits (4))
942 doesn_fit ();
943 out_data[out_idx++] = (byte)x;
944 out_data[out_idx++] = (byte)(x >> 8);
945 out_data[out_idx++] = (byte)(x >> 16);
946 out_data[out_idx++] = (byte)(x >> 24);
947}
948
949
950/* Put the index X into the current OMF record. Indices are used for
951 identifying names (LNAMES), segments (SEGDEF), groups (GRPDEF)
952 etc. Indices are stored in one or two bytes, depending on the
953 value. Small indices (0 through 127) are stored as single byte.
954 Large indices (128 through 32767) are stored as two bytes: the
955 high-order byte comes first, with bit 7 set; the low-order byte
956 comes next. If there is not enough space left in the OMF record or
957 if the value exceeds 32767, display an error message and quit. */
958
959static void put_idx (int x)
960{
961 if (x <= 0x7f)
962 {
963 if (!fits (1))
964 doesn_fit ();
965 out_data[out_idx++] = (byte)x;
966 }
967 else if (x <=0x7fff)
968 {
969 if (!fits (2))
970 doesn_fit ();
971 out_data[out_idx++] = (byte)((x >> 8) | 0x80);
972 out_data[out_idx++] = (byte)x;
973 }
974 else
975 error ("Index too large");
976}
977
978
979/* Put SIZE bytes from SRC into the current OMF record. If there is
980 not enough space left in the OMF record, display an error message
981 and quit. */
982
983static void put_mem (const void *src, int size)
984{
985 if (!fits (size))
986 doesn_fit ();
987 memcpy (out_data+out_idx, src, size);
988 out_idx += size;
989}
990
991
992/* Write LNAMES records into the output file for defining all the
993 names stored in the LNAMES list.
994
995 LNAMES record:
996 Ú
997 ³1 String length n
998 ³n Name
999 À
1000
1001 Name indices are assigned sequentially. */
1002
1003static void write_lnames (void)
1004{
1005 const struct lname *p;
1006 int started;
1007
1008 started = FALSE;
1009 for (p = lnames; p != NULL; p = p->next)
1010 {
1011 if (started && !fits (strlen (p->name)+1))
1012 {
1013 write_rec ();
1014 started = FALSE;
1015 }
1016 if (!started)
1017 {
1018 init_rec (LNAMES);
1019 started = TRUE;
1020 }
1021 put_str (p->name);
1022 }
1023 if (started)
1024 write_rec ();
1025}
1026
1027
1028/* Add a string to the current EXTDEF record or start a new EXTDEF
1029 record. PSTARTED points to an object keeping state. */
1030
1031static void add_extdef (int *pstarted, const char *name, int type)
1032{
1033 if (*pstarted)
1034 {
1035 size_t cchEncodedName = strlen(name);
1036 if ( cchEncodedName > SYMBOL_MAX_LENGTH
1037 && !strstr(name + SYMBOL_MAX_LENGTH - SYMBOL_WEAK_LENGTH, "$w$"))
1038 cchEncodedName = SYMBOL_MAX_LENGTH + SYMBOL_HASH_LENGTH;
1039 if (!fits(cchEncodedName + 3 + (type > 127)))
1040 {
1041 write_rec();
1042 *pstarted = FALSE;
1043 }
1044 }
1045 if (!*pstarted)
1046 {
1047 init_rec(EXTDEF);
1048 *pstarted = TRUE;
1049 }
1050 put_sym(name);
1051 put_idx(type); /* type index */
1052}
1053
1054
1055/* Write EXTDEF records into the output file for all the external
1056 symbols stored in the sym_ptr array.
1057
1058 EXTDEF record:
1059 Ú
1060 ³1 String length n
1061 ³n External name
1062 ³1-2 Type index
1063 À
1064
1065 Symbol indices are assigned sequentially. */
1066
1067static void write_extdef (void)
1068{
1069 const char *name;
1070 int i, started;
1071
1072 started = FALSE;
1073 for (i = 0; i < sym_count; ++i)
1074 if (sym_ptr[i].n_type == (N_INDR|N_EXT))
1075 ++i; /* Skip immediately following entry */
1076 else if (sym_ptr[i].n_type == N_EXT && sym_ptr[i].n_value == 0)
1077 {
1078 name = (const char *)(str_ptr + sym_ptr[i].n_un.n_strx);
1079 sym_more[i].index = sym_index++;
1080 if (memcmp (name, "_16_", 4) == 0)
1081 sym_more[i].flags |= SF_FAR16;
1082 add_extdef (&started, name, sym_more[i].hll_type);
1083 }
1084 else if (sym_ptr[i].n_type == N_WEAKU)
1085 {
1086 if (weak_zero_index == 0)
1087 {
1088 weak_zero_index = sym_index++;
1089 add_extdef (&started, "WEAK$ZERO", 0);
1090 }
1091 sym_more[i].index = sym_index++;
1092 add_extdef (&started, (const char *)(str_ptr + sym_ptr[i].n_un.n_strx), sym_more[i].hll_type);
1093 }
1094#if 1 /* this isn't actually required if only the assembler could do what it's supposed to... */
1095 else if (sym_ptr[i].n_type >= N_WEAKA && sym_ptr[i].n_type <= N_WEAKB)
1096 { /* Not convinced about this yet, I mean there should really be
1097 external records for this, perhaps...
1098 At least I can't see why this will be wrong. */
1099 name = (const char *)(str_ptr + sym_ptr[i].n_un.n_strx);
1100 sym_more[i].index = sym_index++;
1101 add_extdef (&started, name, sym_more[i].hll_type);
1102 }
1103#endif
1104 if (started)
1105 write_rec ();
1106}
1107
1108/* Write WKEXT records into the output file for all undefined weak
1109 symbols stored in the sym_ptr array.
1110
1111 WKEXT record:
1112 Ú
1113 ³1-2 weak EXTDEF index
1114 ³1-2 default resolution EXTDEF index
1115 À
1116
1117 */
1118
1119static void write_wkext (void)
1120{
1121 int i;
1122
1123 for (i = 0; i < sym_count; ++i)
1124 if (sym_ptr[i].n_type == (N_INDR|N_EXT))
1125 ++i; /* Skip immediately following entry */
1126 else if (sym_ptr[i].n_type == N_WEAKU)
1127 {
1128 init_rec (COMENT);
1129 put_8 (0x80);
1130 put_8 (CLASS_WKEXT);
1131 put_idx (sym_more[i].index);
1132 put_idx (weak_zero_index);
1133 write_rec ();
1134 }
1135}
1136
1137
1138/**
1139 * Generates new names for weak symbols.
1140 *
1141 * These names will be catch bye emxomfld and an alias from the generated to
1142 * the real name will be generated and put in a library before linking.
1143 *
1144 * @returns Pointer to pszOrgName or pszName.
1145 * @param pSym Pointer to the symbol in question.
1146 * @param pszOrgName Pointer to the symbols actual name.
1147 * @param pachName Pointer to a character buffer of size cchName where the
1148 * new name will be written.
1149 * @param cchName Size of the buffer pointed to by pachName.
1150 * This must be at least 256, the code make this assumption!
1151 * @remark I'm sorry this function is written in my coding style - not!
1152 */
1153static const char *weak_process_name(const struct nlist *pSym, const char *pszOrgName, char *pachName, int cchName)
1154{
1155 switch (pSym->n_type)
1156 {
1157 /*
1158 * Weak external.
1159 */
1160 case N_WEAKU: /* 0x0d Weak undefined symbol. */
1161 default:
1162 break;
1163
1164 /*
1165 * These symbols are defined in this module, so we need to
1166 * make a unique and recognizable name for them.
1167 */
1168 case N_WEAKA: /* 0x0e Weak absolute symbol. */
1169 case N_WEAKT: /* 0x0f Weak text symbol. */
1170 case N_WEAKD: /* 0x10 Weak data symbol. */
1171 case N_WEAKB: /* 0x11 Weak bss symbol. */
1172 {
1173 int cch;
1174
1175 /* Init the weak marker if it hasn't already been done for this module. */
1176 if (!weak_marker[0])
1177 {
1178 struct timeval tv = {0, 0};
1179 uint64_t u64;
1180 char *psz;
1181
1182 /* prefix */
1183 psz = (char *)memcpy(&weak_marker[0], "$w$", sizeof("$w$")) + sizeof("$w$") - 1;
1184
1185 /* use time-of-day + 4 random bits for the 11 char value */
1186 gettimeofday(&tv, NULL);
1187 u64 = (uint64_t)tv.tv_sec * 1000000 + tv.tv_usec;
1188 u64 <<= 12;
1189 u64 |= rand() & 0xfff;
1190 psz = format_u64(u64, psz, 62, 11);
1191
1192 /* simply hash the current filename for the next 6 chars value. */
1193 u64 = hash_string(mod_name, strlen(mod_name));
1194 psz = format_u64((uint32_t)u64, psz, 62, 6);
1195 assert((psz - &weak_marker[0]) == SYMBOL_WEAK_LENGTH);
1196 }
1197
1198
1199 /* generate the weak symbol name. */
1200 cch = strlen(pszOrgName);
1201 if (cch <= SYMBOL_MAX_LENGTH) /* Must cut exactly where add_nstr cuts. */
1202 snprintf(pachName, cchName, "%s%s", pszOrgName, weak_marker);
1203 else
1204 { /* too long. truncate to: name+!_[hash]$w$[weakmarker] */
1205 uint32_t u32Hash = hash_string(pszOrgName, cch);
1206 memcpy(pachName, pszOrgName, SYMBOL_MAX_LENGTH);
1207 pachName[SYMBOL_MAX_LENGTH + 0] = '!';
1208 pachName[SYMBOL_MAX_LENGTH + 1] = '_';
1209 format_u64(u32Hash, &pachName[SYMBOL_MAX_LENGTH + 2], 62, 6);
1210 memcpy(&pachName[SYMBOL_MAX_LENGTH + SYMBOL_HASH_LENGTH], weak_marker, SYMBOL_WEAK_LENGTH + 1);
1211 warning("Truncated symbol '%s' to '%s' (weak)", pszOrgName, pachName);
1212 }
1213
1214 return pachName;
1215 }
1216
1217 }
1218 /* default is to keep the original name */
1219 return pszOrgName;
1220}
1221
1222
1223
1224/* Write ALIAS records into the output file for all indirect references. */
1225
1226static void write_alias (void)
1227{
1228 int i;
1229 const char *pub_name;
1230 char szPubName[256];
1231 int cchPubName;
1232
1233 for (i = 0; i < sym_count - 1; ++i)
1234 if (sym_ptr[i].n_type == (N_INDR|N_EXT) && sym_ptr[i+1].n_type == N_EXT)
1235 {
1236 pub_name = (const char *)(str_ptr + sym_ptr[i].n_un.n_strx);
1237 if (strip_underscore (pub_name))
1238 ++pub_name;
1239 cchPubName = make_nstr (pub_name, strlen(pub_name), szPubName);
1240
1241 init_rec (ALIAS);
1242 put_8 (cchPubName);
1243 put_mem (szPubName, cchPubName);
1244 put_sym ((const char *)(str_ptr + sym_ptr[i+1].n_un.n_strx));
1245 write_rec ();
1246
1247 if (out_lib != NULL)
1248 {
1249 if (omflib_add_pub (out_lib, szPubName, mod_page, lib_errmsg) != 0)
1250 error (lib_errmsg);
1251 }
1252 }
1253}
1254
1255
1256/* Write PUBDEF records into the output file for the public symbols of
1257 the a.out-style symbol type TYPE. Symbols of that type are defined
1258 in the segment having the OMF segment index INDEX. Ignore symbols
1259 not fitting into a 16-bit PUBDEF record if BIG is FALSE. Ignore
1260 symbols fitting into a 16-bit PUBDEF record if BIG is TRUE. START
1261 is the virtual start address of the segment in the a.out file.
1262
1263 PUBDEF record:
1264 1-2 Base group
1265 1-2 Base segment
1266 0/2 Base frame
1267 Ú
1268 ³1 String length n
1269 ³n Public name
1270 ³2/4 Public offset (4 bytes for 32-bit PUBDEF record)
1271 ³1-2 Type index
1272 À
1273
1274 The base frame field is present only if the base segment field is
1275 0. */
1276
1277static void write_pubdef1 (int type, int index, int big, dword start)
1278{
1279 int i, started;
1280 const char *name, *pub_name;
1281 dword address;
1282 char szName[256];
1283 char szPubName[256];
1284 int cchPubName;
1285
1286 started = FALSE;
1287 for (i = 0; i < sym_count; ++i)
1288 if ( sym_ptr[i].n_type == type
1289 || ((type < N_WEAKU || type > N_WEAKB) && (sym_ptr[i].n_type & ~N_EXT) == type)
1290 )
1291 {
1292 address = sym_ptr[i].n_value - start;
1293 if ((address >= 0x10000 || force_big) == big)
1294 {
1295 name = (const char *)(str_ptr + sym_ptr[i].n_un.n_strx);
1296 if ( (sym_ptr[i].n_type & N_EXT)
1297 || (type == N_TEXT && strncmp (name, "___POST$", 8) == 0)
1298 || (sym_ptr[i].n_type >= N_WEAKU && sym_ptr[i].n_type <= N_WEAKB) )
1299 {
1300 /* for weaksymbols we may have to decorate the name */
1301 if ( sym_ptr[i].n_type >= N_WEAKU && sym_ptr[i].n_type <= N_WEAKB )
1302 name = weak_process_name(&sym_ptr[i], name, szName, sizeof(szName));
1303 pub_name = name;
1304 if (strip_underscore (pub_name))
1305 ++pub_name;
1306 cchPubName = make_nstr (pub_name, strlen (pub_name), szPubName);
1307
1308 if ( out_lib != NULL
1309 && ( ( (sym_ptr[i].n_type & N_EXT)
1310 && sym_ptr[i].n_type != N_WEAKB
1311 && sym_ptr[i].n_type != N_WEAKU)
1312 || sym_ptr[i].n_type == N_WEAKT
1313 || sym_ptr[i].n_type == N_WEAKD ) )
1314 {
1315 if (omflib_add_pub (out_lib, szPubName, mod_page,
1316 lib_errmsg) != 0)
1317 error (lib_errmsg);
1318 }
1319
1320 if (started && !fits (strlen (name) + 6 + (sym_more[i].hll_type > 127)))
1321 {
1322 write_rec ();
1323 started = FALSE;
1324 }
1325 if (!started)
1326 {
1327 init_rec (big ? PUBDEF|REC32 : PUBDEF);
1328 put_idx (flat_index);
1329 put_idx (index);
1330 if (!index)
1331 put_16 (0);
1332 started = TRUE;
1333 }
1334 put_8 (cchPubName);
1335 put_mem (szPubName, cchPubName);
1336 if (big)
1337 put_32 (address);
1338 else
1339 put_16 (address);
1340 put_idx (sym_more[i].hll_type); /* type index */
1341 }
1342 }
1343 }
1344 if (started)
1345 write_rec ();
1346}
1347
1348/* Write main alias if _main is a pubdef.
1349 The debugger looks for 'main' not '_main' in the symbol table. */
1350static void write_pubdef_main ()
1351{
1352 int i;
1353
1354 if (opt_rmunder || strip_symbols || !a_out_h->a_syms)
1355 return;
1356
1357 for (i = 0; i < sym_count; ++i)
1358 if ((sym_ptr[i].n_type & ~N_EXT) == N_TEXT)
1359 {
1360 const char * name = (const char *)(str_ptr + sym_ptr[i].n_un.n_strx);
1361 dword address = sym_ptr[i].n_value;
1362 if ( (sym_ptr[i].n_type & N_EXT)
1363 && !strcmp(name, "_main"))
1364 {
1365 int big = ((address >= 0x10000 || force_big) == big);
1366
1367 name++; /* skip the underscore */
1368 if (out_lib != NULL)
1369 {
1370 /* Note! make_nstr is not needed here, main is too short. */
1371 if (omflib_add_pub (out_lib, name, mod_page, lib_errmsg) != 0)
1372 error (lib_errmsg);
1373 }
1374 init_rec (big ? PUBDEF|REC32 : PUBDEF);
1375 put_idx (flat_index);
1376 put_idx (text_index);
1377 put_sym (name);
1378 if (big)
1379 put_32 (address);
1380 else
1381 put_16 (address);
1382 put_idx (sym_more[i].hll_type); /* type index */
1383 write_rec ();
1384 break;
1385 }
1386 }
1387}
1388
1389/* Write PUBDEF records into the output file for all the public N_TEXT
1390 and N_DATA symbols stored in the sym_ptr array. Common symbols are
1391 handled by write_comdef() below. */
1392
1393static void write_pubdef (void)
1394{
1395 write_pubdef1 (N_ABS, 0, FALSE, 0);
1396 write_pubdef1 (N_ABS, 0, TRUE, 0);
1397 write_pubdef1 (N_TEXT, text_index, FALSE, 0);
1398 write_pubdef1 (N_TEXT, text_index, TRUE, 0);
1399 write_pubdef1 (N_DATA, udat_index, FALSE, text_size);
1400 write_pubdef1 (N_DATA, udat_index, TRUE, text_size);
1401 write_pubdef1 (N_BSS, bss_index, FALSE, text_size + data_size);
1402 write_pubdef1 (N_BSS, bss_index, TRUE, text_size + data_size);
1403 write_pubdef1 (N_WEAKA, 0, FALSE, 0);
1404 write_pubdef1 (N_WEAKA, 0, TRUE, 0);
1405 write_pubdef1 (N_WEAKT, text_index, FALSE, 0);
1406 write_pubdef1 (N_WEAKT, text_index, TRUE, 0);
1407 write_pubdef1 (N_WEAKD, udat_index, FALSE, text_size);
1408 write_pubdef1 (N_WEAKD, udat_index, TRUE, text_size);
1409 write_pubdef1 (N_WEAKB, bss_index, FALSE, text_size + data_size);
1410 write_pubdef1 (N_WEAKB, bss_index, TRUE, text_size + data_size);
1411 /* kso #456 2003-06-10: The debugger looks for 'main' not '_main'. */
1412 write_pubdef_main ();
1413}
1414
1415
1416/* Write COMDEF records into the output file for all the common
1417 symbols stored in the sym_ptr array. Common symbols are used for
1418 uninitialized variables. The TYPE field of these symbols is 0
1419 (plus N_EXT) and the VALUE field is non-zero (it is the size of the
1420 variable).
1421
1422 COMDEF record:
1423 Ú
1424 ³1 String length n
1425 ³n Communal name
1426 ³1-2 Type index
1427 ³1 Data type (0x61: FAR data, 0x62: NEAR data)
1428 ³1-5 Communal length
1429 À
1430
1431 The length is encoded in 1 to 5 bytes, depending on the value:
1432
1433 0 through 0x7f 1 byte, containing the value
1434 0 through 0xffff 0x81, followed by 16-bit word
1435 0 through 0xffffff 0x84, followed by 24-bit word
1436 0 through 0xffffffff 0x88, followed by 32-bit word */
1437
1438static void write_comdef (void)
1439{
1440 int i, started;
1441 long size;
1442 const char *name;
1443
1444 started = FALSE;
1445 for (i = 0; i < sym_count; ++i)
1446 if (sym_ptr[i].n_type == (N_INDR|N_EXT))
1447 ++i; /* Skip immediately following entry */
1448 else if (sym_ptr[i].n_type == N_EXT && sym_ptr[i].n_value != 0)
1449 {
1450 name = (const char *)(str_ptr + sym_ptr[i].n_un.n_strx);
1451 sym_more[i].index = sym_index++;
1452 if (memcmp (name, "_16_", 4) == 0)
1453 sym_more[i].flags |= SF_FAR16;
1454 size = sym_ptr[i].n_value;
1455 if (started && !fits (strlen (name) + 12))
1456 {
1457 write_rec ();
1458 started = FALSE;
1459 }
1460 if (!started)
1461 {
1462 init_rec (COMDEF);
1463 started = TRUE;
1464 }
1465 put_sym (name);
1466 put_idx (0); /* Type index */
1467 put_8 (0x62); /* Data type */
1468 if (size < 4)
1469 size = 4; /* VAC308 ilink freaks out if size = 1 or something */
1470 if (size < 0x80)
1471 put_8 (size);
1472 else if (size < 0x10000)
1473 {
1474 put_8 (0x81);
1475 put_16 (size);
1476 }
1477 else if (size < 0x1000000)
1478 {
1479 put_8 (0x84);
1480 put_24 (size);
1481 }
1482 else
1483 {
1484 put_8 (0x88);
1485 put_32 (size);
1486 }
1487 }
1488 if (started)
1489 write_rec ();
1490}
1491
1492
1493/* Write a SEGDEF record to define a segment. NAME_INDEX is the name
1494 index of the segment name. CLASS_INDEX is the name index of the
1495 class name. SIZE is the size of the segment in bytes. STACK is
1496 TRUE iff the segment is the stack segment. seg_def() returns the
1497 segment index of the new segment.
1498
1499 SEGDEF record:
1500 1 Segment attributes
1501 0/2 Frame number (present only if A=000)
1502 0/1 Offset (present only if A=000)
1503 2/4 Segment length (4 bytes for 32-bit SEGDEF record)
1504 1/2 Segment name index
1505 1/2 Segment class index
1506 1/2 Overlay name index
1507
1508 The segment attributes byte contains the following fields:
1509
1510 A (bits 5-7) Alignment (011=relocatable, paragraph (16b) alignment)
1511 (before gcc 3.2.2: 101=relocatable, 32-bit alignment)
1512 C (bits 2-4) Combination (010=PUBLIC, 101=STACK)
1513 B (bit 1) Big (segment length is 64KB)
1514 P (bit 0) USE32 */
1515
1516static int seg_def (int name_index, int class_index, long size, int stack, int is_set)
1517{
1518 byte seg_attr;
1519
1520 seg_attr = (is_set ? (stack ? 0xb5 : 0xa9) : (stack ? 0x75 : 0x69) );
1521 if (size > 0x10000 || force_big)
1522 {
1523 init_rec (SEGDEF|REC32);
1524 put_8 (seg_attr);
1525 put_32 (size);
1526 }
1527 else if (size == 0x10000)
1528 {
1529 init_rec (SEGDEF);
1530 put_8 (seg_attr|2);
1531 put_16 (0);
1532 }
1533 else
1534 {
1535 init_rec (SEGDEF);
1536 put_8 (seg_attr);
1537 put_16 (size);
1538 }
1539 put_idx (name_index);
1540 put_idx (class_index);
1541 put_idx (ovl_name);
1542 write_rec ();
1543 return segdef_index++;
1544}
1545
1546
1547/* This function is passed to qsort() for sorting a relocation table.
1548 X1 and X2 point to reloc structures. We compare the ADDRESS fields
1549 of the structures. */
1550
1551static int reloc_compare (const void *x1, const void *x2)
1552{
1553 dword a1, a2;
1554
1555 a1 = ((struct relocation_info *)x1)->r_address;
1556 a2 = ((struct relocation_info *)x2)->r_address;
1557 if (a1 < a2)
1558 return -1;
1559 else if (a1 > a2)
1560 return 1;
1561 else
1562 return 0;
1563}
1564
1565
1566/* Write the segment contents (data) of one OMF segment to the output
1567 file. Create LEDATA and FIXUPP records. INDEX is the segment
1568 index. SEG_NAME is the name index of the segment name (not used).
1569 SRC points to the data to be written (will be modified for
1570 fixups!), SEG_SIZE is the number of bytes to be written. REL
1571 points to the relocation table (an array of struct relocation_info), REL_SIZE
1572 is the size of the relocation table, in bytes(!). SST_FLAG is TRUE
1573 when writing the symbol segment $$SYMBOLS. BOUNDARY points to an
1574 array of indices into SRC where the data can be split between
1575 records. That array has BOUNDARY_COUNT entries. SEG_TYPE is the
1576 segment type (N_TEXT or N_DATA or -1) and is used for relocation.
1577
1578 We can split the data at arbitrary points after the last BOUNDARY
1579 entry. In consequence, write_seg() splits the data at arbitrary
1580 points if BOUNDARY_COUNT is zero.
1581
1582 LEDATA record:
1583 1-2 Segment index
1584 2/4 Enumerated data offset (4 bytes for 32-bit LEDATA record)
1585 n Data bytes (n is derived from record length)
1586
1587 FIXUPP record:
1588 Ú
1589 ³? THREAD subrecord or FIXUP subrecord
1590 À
1591
1592 THREAD subrecord:
1593 1 Flags
1594 0-2 Index (present only for FRAME methods F0, F1 and F2)
1595
1596 The flags byte contains the following fields:
1597
1598 0 (bit 7) always 0 to indicate THREAD subrecord
1599 D (bit 6) 0=target thread, 1=frame thread
1600 0 (bit 5) reserved
1601 Method (bits 2-4) method (T0 through T6 and F0 through F6)
1602 Thred (bits 0-1) thread number
1603
1604 FIXUP subrecord:
1605 2 Locat
1606 0-1 Fix data
1607 0-2 Frame datum
1608 0-2 Target datum
1609 2/4 target displacement (4 bytes for 32-bit FIXUPP record)
1610
1611 The first locat byte contains the following fields:
1612
1613 1 (bit 7) always 1 to indicate FIXUP subrecord
1614 M (bit 6) 1=segment-relative fixup, 0=self-relative fixup
1615 Location (bit 2-5) Type of location to fix up:
1616 0010=16-bit selector
1617 0011=32-bit long pointer (16:16)
1618 1001=32-bit offset
1619 Offset (bits 0-1) Most significant bits of offset into LEDATA record
1620
1621 The second locat byte contains the least significant bits of the
1622 offset into the LEDATA record.
1623
1624 The Fix data byte contains the following fields:
1625
1626 F (bit 7) 1=frame thread, 0=methods F0 through F5
1627 Frame (bits 4-6) frame thread number (F=1) or frame method (F=0)
1628 T (bit 3) 1=target thread, 1=methods
1629 P (bit 2) Bit 2 of target method
1630 Targt (bits 0-1) target thread number (T=1) or target method (T=0) */
1631
1632static void write_seg (int index, int seg_name, byte *src, long seg_size,
1633 const struct relocation_info *rel, long rel_size, int sst_flag,
1634 const int *boundary, int boundary_count, int seg_type)
1635{
1636 long n, off, tmp, end;
1637 int i, reloc_count, reloc_idx, target_index, ok, data_off, far16;
1638 int boundary_idx, started, *threadp;
1639 struct relocation_info *reloc_tab;
1640 const struct relocation_info *r;
1641 byte locat;
1642 dword start_data, start_bss;
1643
1644 target_index = 0; threadp = NULL; /* keep the compiler happy */
1645
1646 /* Copy and sort the relocation table. */
1647
1648 reloc_count = rel_size / sizeof (struct relocation_info);
1649 reloc_tab = xmalloc (reloc_count * sizeof (struct relocation_info));
1650 memcpy (reloc_tab, rel, reloc_count * sizeof (struct relocation_info));
1651 qsort (reloc_tab, reloc_count, sizeof (struct relocation_info), reloc_compare);
1652
1653 /* First pass: apply fixups to data. Adjust fixup frames for OMF
1654 fixups. In a.out files, frames are relative to address 0, in OMF
1655 files, frames are relative to the start of the segment. The
1656 following two variables are used for doing these adjustments. */
1657
1658 start_data = text_size;
1659 start_bss = start_data + data_size;
1660
1661 /* Scan the relocation table for entries applying to this segment. */
1662
1663 for (i = 0, r = reloc_tab; i < reloc_count; ++i, ++r)
1664 if (r->r_length == 2)
1665 {
1666
1667 /* Here we have a 32-bit relocation. */
1668
1669 if (r->r_extern)
1670 {
1671
1672 /* The relocation refers to a symbol. Look into the
1673 symbol table to find the fixup type and target
1674 address. */
1675 const struct nlist *sym = &sym_ptr[r->r_symbolnum];
1676/*#ifdef DEBUG
1677 const char *psz = sym->n_un.n_strx + str_ptr;
1678#endif*/
1679 switch (sym->n_type)
1680 {
1681 case N_TEXT:
1682 case N_WEAKD:
1683 case N_WEAKB:
1684 case N_WEAKA:
1685 break;
1686
1687 case N_EXT:
1688 case N_WEAKU:
1689 case N_TEXT|N_EXT:
1690 case N_WEAKT:
1691 if (r->r_pcrel)
1692 { /* example: r_address = 0xc, dw=0xfffffff6. disp=6 */
1693 dword dw = *(dword *)(src + r->r_address);
1694 dw += r->r_address + 4;
1695 *(dword *)(src + r->r_address) = dw;
1696 }
1697 break;
1698 case N_DATA:
1699 case N_DATA|N_EXT:
1700 *(dword *)(src + r->r_address) -= start_data;
1701 break;
1702 case N_BSS:
1703 case N_BSS|N_EXT:
1704 *(dword *)(src + r->r_address) -= start_bss;
1705 break;
1706
1707 default:
1708 error ("write_seg: Invalid symbol type (0x%.2x)",
1709 sym_ptr[r->r_symbolnum].n_type);
1710 }
1711 }
1712 else if (!(r->r_pcrel && (r->r_symbolnum & ~N_EXT) == seg_type))
1713 {
1714
1715 /* The relocation does not refer to a symbol, it's an
1716 internal relocation. Get the fixup type from the
1717 relocation table. */
1718
1719 switch (r->r_symbolnum & ~N_EXT)
1720 {
1721 /* kso #465 2003-06-04: WEAK hack - bogus */
1722 case N_WEAKT:
1723 case N_TEXT:
1724 break;
1725 /* kso #465 2003-06-04: WEAK hack - bogus */
1726 case N_WEAKD:
1727 case N_DATA:
1728 *(dword *)(src + r->r_address) -= start_data;
1729 break;
1730 /* kso #465 2003-06-04: WEAK hack - bogus */
1731 case N_WEAKB:
1732 case N_BSS:
1733 *(dword *)(src + r->r_address) -= start_bss;
1734 break;
1735 /* kso #465 2003-06-04: WEAK hack - bogus */
1736 case N_WEAKA:
1737 break;
1738 default:
1739 error ("write_seg: Invalid relocation type (0x%.2x)", r->r_symbolnum);
1740 }
1741 }
1742 }
1743
1744 /* Second pass: write LEDATA and FIXUPP records. */
1745
1746 off = 0; reloc_idx = 0; boundary_idx = 0;
1747 while (seg_size > 0)
1748 {
1749
1750 /* Compute the maximum number of bytes in the next LEDATA
1751 record, depending on the maximum record size, the record type
1752 (16-bit or 32-bit) and the number of bytes remaining. The
1753 number of bytes will be adjusted later to avoid splitting
1754 entries of the $$SYMBOLS and $$TYPES segments. */
1755
1756 n = MAX_REC_SIZE - 5;
1757 n -= (off >= 0x10000 || force_big ? 4 : 2);
1758 if (seg_size < n)
1759 n = seg_size;
1760
1761 /* Adjust the number of bytes to avoid splitting a fixup. Find
1762 the last relocation table entry which applies to this chunk.
1763 Then, lower the chunk size to stop at the start of the
1764 frame. */
1765
1766 i = reloc_idx; end = off + n;
1767 while (i < reloc_count && reloc_tab[i].r_address < end)
1768 ++i;
1769 if (i > reloc_idx)
1770 {
1771 --i;
1772 tmp = reloc_tab[i].r_address + (1 << reloc_tab[i].r_length) - off;
1773 if (tmp > n)
1774 n = reloc_tab[i].r_address - off;
1775 }
1776
1777 /* Consult the BOUNDARY table to find the last point where we
1778 are allowed to split the data into multiple LEDATA records.
1779 This must be done after adjusting for relocation table
1780 entries. */
1781
1782 end = off + n;
1783 while (boundary_idx < boundary_count && boundary[boundary_idx] < end)
1784 ++boundary_idx;
1785 #if 1/* kso #456 2003-06-05: This must be wrong cause we're splitting unneedingly.
1786 * Check if we acutally hit the '< end' check. */
1787 if (boundary_idx > 0 && boundary_idx < boundary_count)
1788 #else
1789 if (boundary_idx > 0)
1790 #endif
1791 {
1792 tmp = boundary[boundary_idx-1] - off;
1793 if (tmp > 0)
1794 n = tmp;
1795 }
1796
1797 /* Write the LEDATA record. This is simple. */
1798
1799 if (off >= 0x10000 || force_big)
1800 {
1801 init_rec (LEDATA|REC32);
1802 put_idx (index);
1803 put_32 (off);
1804 }
1805 else
1806 {
1807 init_rec (LEDATA);
1808 put_idx (index);
1809 put_16 (off);
1810 }
1811 put_mem (src, n);
1812 write_rec ();
1813
1814 /* Write the FIXUPP records for this LEDATA record. Quite
1815 hairy. */
1816
1817 end = off + n;
1818 started = FALSE;
1819 r = &reloc_tab[reloc_idx];
1820
1821 /* Look at all relocation table entries which apply to the
1822 current LEDATA chunk. */
1823
1824 while (reloc_idx < reloc_count && r->r_address < end)
1825 {
1826
1827 /* Set ok to TRUE if we should create a fixup for this
1828 relocation table entry. First, ignore all but 32-bit
1829 relocations. In the $$SYMBOLS segment, we also have
1830 16-bit selector fixups. far16 is later set to TRUE for
1831 16:16 fixups. */
1832
1833 ok = (r->r_length == 2 || (sst_flag && r->r_length == 1));
1834 far16 = FALSE;
1835
1836 if (r->r_extern)
1837 {
1838
1839 /* The relocation refers to a symbol -- we won't use a
1840 target thread. If the symbol is a 16:16 symbol, we
1841 set far16 to true to generate a 16:16 fixup. */
1842
1843 threadp = NULL;
1844 if (sym_more[r->r_symbolnum].flags & SF_FAR16)
1845 far16 = TRUE;
1846 }
1847 else if (r->r_pcrel && (r->r_symbolnum & ~N_EXT) == seg_type)
1848 {
1849 ok = FALSE;
1850 if (warning_level > 0)
1851 warning ("Internal PC-relative relocation ignored");
1852 }
1853 else
1854 {
1855
1856 /* The relocation does not refer to a symbol -- we use
1857 an appropriate target thread. The target thread
1858 number is taken from or stored to *threadp.
1859 target_index is the OMF segment index. */
1860
1861 switch (r->r_symbolnum & ~N_EXT)
1862 {
1863 case N_TEXT:
1864 threadp = &text_thread;
1865 target_index = text_index;
1866 break;
1867 case N_DATA:
1868 threadp = &data_thread;
1869 target_index = udat_index;
1870 break;
1871 case N_BSS:
1872 threadp = &bss_thread;
1873 target_index = bss_index;
1874 break;
1875 case N_ABS:
1876 default:
1877 ok = FALSE;
1878 break;
1879 }
1880 }
1881
1882 if (ok)
1883 {
1884
1885 /* Now we build the FIXUPP record. */
1886
1887 if (started && !fits (32))
1888 {
1889 write_rec ();
1890 started = FALSE;
1891 }
1892 if (!started)
1893 {
1894 init_rec (FIXUPP|REC32);
1895 started = TRUE;
1896 }
1897
1898 /* If no frame thread has been defined for the FLAT
1899 group, define it now. */
1900
1901 if (flat_thread < 0 && !far16)
1902 {
1903 if (frame_thread_index >= 4)
1904 error ("Too many frame threads");
1905 /* THREAD: D=1, METHOD=F1 */
1906 put_8 (0x44 | frame_thread_index);
1907 put_idx (flat_index);
1908 flat_thread = frame_thread_index++;
1909 }
1910
1911 /* If we want to use a target thread and the target
1912 thread is not yet defined, define it now. */
1913
1914 if (threadp != NULL && *threadp < 0)
1915 {
1916 if (target_thread_index >= 4)
1917 error ("Too many target threads");
1918 /* THREAD: D=0, METHOD=T4 */
1919 put_8 (0x10 | target_thread_index);
1920 put_idx (target_index);
1921 *threadp = target_thread_index++;
1922 }
1923
1924 /* Compute and write the locat word. */
1925
1926 data_off = r->r_address - off;
1927 if (far16)
1928 locat = 0x8c; /* Method 3: 16:16 far pointer */
1929 else if (sst_flag && r->r_length == 1)
1930 locat = 0x88; /* Method 2: selector */
1931 else
1932 locat = 0xa4; /* Method 9: 32-bit offset */
1933 locat |= ((data_off >> 8) & 0x03);
1934 if (!r->r_pcrel)
1935 locat |= 0x40;
1936 put_8 (locat);
1937 put_8 (data_off);
1938
1939 /* Write the rest of the FIXUP subrecord. */
1940
1941 if (far16)
1942 {
1943 /* F=0, FRAME=F2, T=0, P=1, TARGT=T2 */
1944 put_8 (0x26);
1945 put_idx (sym_more[r->r_symbolnum].index);
1946 put_idx (sym_more[r->r_symbolnum].index);
1947 }
1948 else if (r->r_extern)
1949 {
1950 /* F=1, FRAME=F1, T=0, P=1, TARGT=T2 */
1951 put_8 (0x86 | (flat_thread << 4));
1952 put_idx (sym_more[r->r_symbolnum].index);
1953 }
1954 else
1955 {
1956 /* F=1, FRAME=F1, T=1, P=1, TARGT=T4 */
1957 put_8 (0x8c | (flat_thread << 4) | *threadp);
1958 }
1959 }
1960 ++reloc_idx; ++r;
1961 }
1962 if (started)
1963 write_rec ();
1964
1965 /* Adjust pointers and counters for the next chunk. */
1966
1967 src += n; off += n; seg_size -= n;
1968 }
1969
1970 /* Deallocate the sorted relocation table. */
1971
1972 free (reloc_tab);
1973}
1974
1975
1976/* Write a default library request record to the output file. The
1977 linker will search the library NAME to resolve external
1978 references. Create a COMENT record of class 0x9f. The name is
1979 stored without leading byte count, the linker gets the length of
1980 the name from the record length. */
1981
1982static void request_lib (const char *name)
1983{
1984 init_rec (COMENT);
1985 put_8 (0x40);
1986 put_8 (0x9f);
1987 put_mem (name, strlen (name));
1988 write_rec ();
1989}
1990
1991
1992/* Write default library request records for all the -i options. The
1993 library names are stored in a list. libreq_head points to the head
1994 of the list. */
1995
1996static void write_libs (void)
1997{
1998 struct libreq *p;
1999
2000 for (p = libreq_head; p != NULL; p = p->next)
2001 request_lib (p->name);
2002}
2003
2004
2005/* Write a record identifying the debug information style to the
2006 output file. The style we use is called HLL version 3. Create a
2007 COMENT record of class 0xa1. */
2008
2009static void write_debug_style (void)
2010{
2011 if (strip_symbols || !a_out_h->a_syms)
2012 return;
2013 init_rec (COMENT);
2014 put_8 (0x80);
2015 put_8 (0xa1); /* Debug info style */
2016 put_8 (hll_version); /* Version */
2017 put_mem ("HL", 2); /* HLL style debug tables */
2018 write_rec ();
2019}
2020
2021
2022/* Write a link pass separator to the output file. The linker makes
2023 two passes through the object modules. The first pass stops when
2024 encountering the link pass separator. This is used for improving
2025 linking speed. The second pass ignores the link pass separator.
2026 The following records must precede the link pass separator: ALIAS,
2027 CEXTDEF COMDEF, EXTDEF, GRPDEF, LCOMDEF, LEXTDEF, LNAMES, LPUBDEF,
2028 PUBDEF, SEGDEF, TYPDEF, and most of the COMENT classes. Create a
2029 COMENT record of class 0xa2. */
2030
2031static void write_pass2 (void)
2032{
2033 init_rec (COMENT);
2034 put_8 (0x40);
2035 put_8 (0xa2); /* Link pass separator */
2036 put_8 (0x01);
2037 write_rec ();
2038}
2039
2040
2041/* Create segment names for all the sets. It is here where sets are
2042 created. See write_set_data() for details. */
2043
2044static void define_set_names (void)
2045{
2046 int i, j;
2047 struct set *set_ptr;
2048 char tmp[512];
2049 const char *name;
2050 byte type;
2051
2052 /* Loop through the symbol table. */
2053
2054 for (i = 0; i < sym_count; ++i)
2055 {
2056 type = sym_ptr[i].n_type & ~N_EXT;
2057 if ((type == N_SETA && sym_ptr[i].n_value == 0xffffffff)
2058 || type == N_SETT || type == N_SETD)
2059 {
2060
2061 /* This is a set element. If type is N_SETA the symbol is
2062 the head of the set, otherwise it is an ordinary set
2063 element. Search the table of sets to find out whether
2064 this set is already known. */
2065
2066 name = (const char *)(str_ptr + sym_ptr[i].n_un.n_strx);
2067 for (set_ptr = sets; set_ptr != NULL; set_ptr = set_ptr->next)
2068 if (strcmp (set_ptr->name, name) == 0)
2069 break;
2070 if (set_ptr == NULL)
2071 {
2072
2073 /* The set is not yet known. Create a new table
2074 entry. */
2075
2076 set_ptr = xmalloc (sizeof (struct set));
2077 set_ptr->name = xstrdup (name);
2078 for (j = 0; j < 3; ++j)
2079 {
2080 set_ptr->seg_name[j] = -1;
2081 set_ptr->seg_index[j] = -1;
2082 }
2083 set_ptr->count = 0;
2084 set_ptr->data = NULL;
2085 set_ptr->seg = NULL;
2086 set_ptr->def = 0;
2087 set_ptr->next = NULL;
2088 *set_add = set_ptr;
2089 set_add = &set_ptr->next;
2090 }
2091 else if (type == N_SETA && set_ptr->def)
2092 error ("Set `%s' defined more than once", name);
2093
2094 if (type == N_SETA)
2095 set_ptr->def = 1; /* Write SET1 and SET3 segments */
2096 else
2097 {
2098
2099 /* Add the element to the set. */
2100
2101 ++set_ptr->count;
2102 set_ptr->data = xrealloc (set_ptr->data, set_ptr->count * 4);
2103 set_ptr->seg = xrealloc (set_ptr->seg, set_ptr->count);
2104 set_ptr->data[set_ptr->count-1] = sym_ptr[i].n_value;
2105 set_ptr->seg[set_ptr->count-1]
2106 = (type == N_SETT ? N_TEXT : N_DATA);
2107 }
2108
2109 /* Define the OMF segment names for this set, if not yet
2110 done. */
2111
2112 if (set_ptr->seg_name[0] < 0)
2113 {
2114 strcpy (tmp, "SET#");
2115 strcat (tmp, name);
2116 for (j = 0; j < 3; ++j)
2117 {
2118 tmp[3] = (char)('1' + j);
2119 set_ptr->seg_name[j] = find_lname (tmp);
2120 }
2121 }
2122 }
2123 }
2124}
2125
2126
2127/* Define three segments for each set. The segment names have already
2128 been defined, now write the SEGDEF records. */
2129
2130static void write_set_segs (void)
2131{
2132 int j;
2133 struct set *set_ptr;
2134
2135 for (set_ptr = sets; set_ptr != NULL; set_ptr = set_ptr->next)
2136 for (j = 0; j < 3; ++j)
2137 set_ptr->seg_index[j] =
2138 seg_def (set_ptr->seg_name[j], data_class_name,
2139 4 * (j == 1 ? set_ptr->count : set_ptr->def), FALSE, TRUE);
2140}
2141
2142
2143/* Write the PUBDEF records for all the sets. One PUBDEF record is
2144 generated for each set, it defines the set name. */
2145
2146static void write_set_pub (void)
2147{
2148 struct set *set_ptr;
2149
2150 for (set_ptr = sets; set_ptr != NULL; set_ptr = set_ptr->next)
2151 if (set_ptr->def)
2152 {
2153 init_rec (force_big ? PUBDEF|REC32 : PUBDEF);
2154 put_idx (flat_index);
2155 put_idx (set_ptr->seg_index[0]);
2156 put_sym (set_ptr->name);
2157 if (force_big)
2158 put_32 (0);
2159 else
2160 put_16 (0);
2161 put_idx (0); /* Type index */
2162 write_rec ();
2163 }
2164}
2165
2166
2167/* Write the segment contents for all the sets. One or three segments
2168 are written for each set XXX:
2169
2170 SET1XXX long start = -2
2171 SET2XXX long table[]
2172 SET3XXX long end = 0
2173
2174 SET1XXX and SET3XXX are written only if there is a N_SETA symbol
2175 for the set. The N_SETA symbol defines the start of the set and
2176 must have a value of -1 (see crt0.s). SET2XXX is written for all
2177 modules which contain N_SETT or N_SETD symbols. All three segments
2178 belong to the group GROUPXXX. The linker combines all the segments
2179 of GROUPXXX into a single object. SET1XXX comes first, followed by
2180 the SET2XXX segments of all modules of the program, followed by
2181 SET3XXX. That way, we obtain a table of all set elements of a
2182 given set, preceded by -2 and terminated by 0. A symbol XXX is
2183 defined which points to the start of SET1XXX. See
2184 /emx/lib/gcc/main.c for code which uses sets. */
2185
2186static void write_set_data (void)
2187{
2188 struct set *set_ptr;
2189 dword x;
2190 int i, max_count;
2191 dword *buf;
2192 struct relocation_info *reloc_tab;
2193
2194 max_count = 0; buf = NULL; reloc_tab = NULL;
2195 for (set_ptr = sets; set_ptr != NULL; set_ptr = set_ptr->next)
2196 {
2197
2198 /* Write the first segment. It consists of a 32-bit word
2199 containing the number -2. This is used by the startup code
2200 to detect a delimited set. */
2201
2202 if (set_ptr->def)
2203 {
2204 x = 0xfffffffe;
2205 write_seg (set_ptr->seg_index[0], set_ptr->seg_name[0],
2206 (byte *)&x, sizeof (x), NULL, 0, FALSE, NULL, 0, -1);
2207 }
2208
2209 /* Write the second segment. It consists of the set elements as
2210 taken from the a.out module. The elements are assumed to be
2211 pointers into the text segment. */
2212
2213 if (set_ptr->count >= 1)
2214 {
2215
2216 /* Enlarge the relocation table, if required. */
2217
2218 if (set_ptr->count > max_count)
2219 {
2220 max_count = set_ptr->count;
2221 buf = xrealloc (buf, 4 * max_count);
2222 memset (buf, 0, 4 * max_count);
2223 reloc_tab = xrealloc (reloc_tab,
2224 max_count * sizeof (struct relocation_info));
2225 }
2226
2227 /* Create one relocation table entry for each set
2228 element. */
2229
2230 for (i = 0; i < set_ptr->count; ++i)
2231 {
2232 buf[i] = set_ptr->data[i];
2233 reloc_tab[i].r_address = i * 4;
2234 reloc_tab[i].r_symbolnum = set_ptr->seg[i];
2235 reloc_tab[i].r_pcrel = 0;
2236 reloc_tab[i].r_length = 2;
2237 reloc_tab[i].r_extern = 0;
2238 reloc_tab[i].r_pad = 0;
2239 }
2240
2241 /* Write the segment data and fixups. */
2242
2243 write_seg (set_ptr->seg_index[1], set_ptr->seg_name[1],
2244 (byte *)buf, set_ptr->count * 4, reloc_tab,
2245 set_ptr->count * sizeof (struct relocation_info), FALSE, NULL, 0,
2246 -1);
2247 }
2248
2249 /* Write the third segment. It consists of a 32-bit word
2250 containing the value 0, marking the end of the table. */
2251
2252 if (set_ptr->def)
2253 {
2254 x = 0;
2255 write_seg (set_ptr->seg_index[2], set_ptr->seg_name[2],
2256 (byte *)&x, sizeof (x), NULL, 0, FALSE, NULL, 0, -1);
2257 }
2258 }
2259 if (buf != NULL)
2260 free (buf);
2261}
2262
2263
2264/* Find a relocation table entry by fixup address. */
2265
2266static const struct relocation_info *find_reloc_fixup (const struct relocation_info *rel,
2267 long rel_size, dword addr)
2268{
2269 int i, count;
2270
2271 count = rel_size / sizeof (struct relocation_info);
2272 for (i = 0; i < count; ++i)
2273 if (rel[i].r_address == addr)
2274 return &rel[i];
2275 return NULL;
2276}
2277
2278
2279static void free_modstr_cache (void)
2280{
2281 struct modstr *p1, *p2;
2282
2283 for (p1 = modstr_cache; p1 != NULL; p1 = p2)
2284 {
2285 p2 = p1->next;
2286 free (p1->symbol);
2287 free (p1->str);
2288 free (p1);
2289 }
2290 modstr_cache = NULL;
2291}
2292
2293
2294/* Fetch a null-terminated string from a module. REL points to the
2295 relocation table entry of the pointer, ADDR is the pointer. Copy
2296 the string to DST, a buffer of DST_SIZE bytes. Return TRUE if
2297 successful, FALSE on failure. */
2298
2299static int fetch_modstr (const struct relocation_info *rel, dword addr,
2300 char *dst, size_t dst_size)
2301{
2302 const byte *seg_ptr;
2303 dword seg_size;
2304
2305 if (rel == NULL) return FALSE;
2306 if (rel->r_extern)
2307 {
2308 struct modstr *p;
2309 byte *buf;
2310 const char *sym_name;
2311 const struct nlist *m_sym = NULL;
2312 const struct exec *m_ao = NULL;
2313
2314 /* We have to take the string from another module. First try to
2315 get the string from the cache. */
2316
2317 sym_name = (const char *)(str_ptr + sym_ptr[rel->r_symbolnum].n_un.n_strx);
2318 for (p = modstr_cache; p != NULL; p = p->next)
2319 if (strcmp (p->symbol, sym_name) == 0)
2320 break;
2321 if (p == NULL)
2322 {
2323 long pos, size, m_str_size;
2324 struct ar_hdr ar;
2325 byte *t;
2326 size_t buf_size, len;
2327 const byte *m_str;
2328 int i, m_sym_count, found;
2329
2330 /* Search all modules until finding the symbol. */
2331
2332 buf = NULL; buf_size = 0; found = FALSE;
2333 pos = SARMAG;
2334 while (ar_read_header (&ar, pos))
2335 {
2336 size = ar_member_size (&ar);
2337 pos += (sizeof (ar) + size + 1) & -2;
2338 if (strcmp (ar.ar_name, "__.SYMDEF") == 0
2339 || strcmp (ar.ar_name, "__.IMPORT") == 0
2340 || memcmp (ar.ar_name, "IMPORT#", 7) == 0)
2341 continue;
2342 if (size > buf_size)
2343 {
2344 if (buf != NULL) free (buf);
2345 buf_size = size;
2346 buf = xmalloc (buf_size);
2347 }
2348 size = fread (buf, 1, size, inp_file);
2349 if (ferror (inp_file))
2350 error ("Cannot read `%s'", inp_fname);
2351 m_ao = (const struct exec *)buf;
2352 if (size < sizeof (struct exec) || N_MAGIC(*m_ao) != OMAGIC)
2353 break;
2354 t = buf + sizeof (struct exec);
2355 t += m_ao->a_text; t += m_ao->a_data;
2356 t += m_ao->a_trsize; t += m_ao->a_drsize;
2357 m_sym = (const struct nlist *)t; t += m_ao->a_syms;
2358 m_str = t;
2359 if (m_str + 4 - buf > size)
2360 break;
2361 m_str_size = *(long *)m_str;
2362 m_sym_count = m_ao->a_syms / sizeof (struct nlist);
2363 if (m_str + m_str_size - buf > size)
2364 break;
2365 for (i = 0; i < m_sym_count; ++i)
2366 switch (m_sym[i].n_type)
2367 {
2368 case N_TEXT|N_EXT:
2369 case N_DATA|N_EXT:
2370 if (strcmp ((const char *)(m_str + m_sym[i].n_un.n_strx), sym_name) == 0)
2371 {
2372 m_sym += i; found = TRUE; break;
2373 }
2374 }
2375 if (found)
2376 break;
2377 }
2378 if (!found)
2379 error ("Symbol `%s' not found", sym_name);
2380
2381 addr = m_sym->n_value;
2382 switch (m_sym->n_type)
2383 {
2384 case N_TEXT|N_EXT:
2385 seg_ptr = buf + sizeof (struct exec);
2386 seg_size = m_ao->a_text;
2387 break;
2388 case N_DATA|N_EXT:
2389 seg_ptr = buf + sizeof (struct exec) + m_ao->a_text;
2390 seg_size = m_ao->a_data;
2391 break;
2392 default:
2393 abort ();
2394 }
2395
2396 len = 0;
2397 for (;;)
2398 {
2399 if (addr + len >= seg_size)
2400 error ("String extends beyond end of segment");
2401 if (seg_ptr[addr + len] == 0)
2402 break;
2403 ++len;
2404 }
2405
2406 p = xmalloc (sizeof (struct modstr));
2407 p->symbol = xstrdup (sym_name);
2408 p->str = xmalloc (len + 1);
2409 memcpy (p->str, seg_ptr + addr, len + 1);
2410 p->next = modstr_cache;
2411 modstr_cache = p;
2412 if (buf != NULL) free (buf);
2413 }
2414 if (strlen (p->str) >= dst_size)
2415 return FALSE;
2416 strcpy (dst, p->str);
2417 return TRUE;
2418 }
2419 else
2420 {
2421 dword si;
2422
2423 switch (rel->r_symbolnum)
2424 {
2425 case N_TEXT:
2426 seg_ptr = text_ptr;
2427 seg_size = text_size;
2428 break;
2429 case N_DATA:
2430 seg_ptr = data_ptr;
2431 seg_size = data_size;
2432 break;
2433 default:
2434 return FALSE;
2435 }
2436 for (si = 0; addr + si < seg_size && si < dst_size; ++si)
2437 {
2438 dst[si] = seg_ptr[addr + si];
2439 if (seg_ptr[addr + si] == 0)
2440 return TRUE;
2441 }
2442 return FALSE;
2443 }
2444}
2445
2446
2447/* Create an import record and a PUBDEF record. */
2448
2449static void make_import (const char *pub_name, const char *proc_name,
2450 long ord, const char *mod)
2451{
2452 char szPubName[256];
2453 int cchPubName;
2454
2455 /* Skip a leading underscore character if present. */
2456
2457 if (strip_underscore (pub_name))
2458 ++pub_name;
2459 cchPubName = make_nstr (pub_name, strlen (pub_name), szPubName);
2460
2461 /* Make the symbol public in the output library. */
2462
2463 if (omflib_add_pub (out_lib, szPubName, mod_page, lib_errmsg) != 0)
2464 error (lib_errmsg);
2465
2466 /* Write the import definition record. */
2467
2468 init_rec (COMENT);
2469 put_8 (0x00);
2470 put_8 (IMPDEF_CLASS);
2471 put_8 (IMPDEF_SUBTYPE);
2472 put_8 (proc_name == NULL ? 0x01 : 0x00); /* Import by ordinal or by name */
2473 put_8 (cchPubName);
2474 put_mem (szPubName, cchPubName);
2475 put_str (mod);
2476 if (proc_name == NULL)
2477 put_16 (ord);
2478 else if (strcmp (proc_name, pub_name) == 0)
2479 put_8 (0);
2480 else {
2481 put_str (proc_name);
2482 }
2483 write_rec ();
2484 init_rec (MODEND|REC32);
2485 put_8 (0x00); /* Non-main module without start address */
2486 write_rec ();
2487}
2488
2489
2490/* If the input file is an import module (method (I2) as created by
2491 emximp), create an OMF-style import module and return TRUE.
2492 Otherwise, return FALSE. */
2493
2494static int handle_import_i2 (void)
2495{
2496 int i, len1, mod_len;
2497 long ord;
2498 const char *name1, *name2, *proc_name, *p;
2499 char mod[256], *q;
2500
2501 /* Search the symbol table for N_IMP1 and N_IMP2 symbols. These are
2502 unique to import modules. */
2503
2504 name1 = NULL; name2 = NULL;
2505 for (i = 0; i < sym_count; ++i)
2506 switch (sym_ptr[i].n_type)
2507 {
2508 case N_IMP1|N_EXT:
2509 name1 = (const char *)(str_ptr + sym_ptr[i].n_un.n_strx);
2510 break;
2511 case N_IMP2|N_EXT:
2512 name2 = (const char *)(str_ptr + sym_ptr[i].n_un.n_strx);
2513 break;
2514 default:
2515 return FALSE;
2516 }
2517
2518 /* If no N_IMP1 and N_IMP2 symbols have been found, the module is
2519 not an import module. */
2520
2521 if (name1 == NULL || name2 == NULL)
2522 return FALSE;
2523
2524 /* Parse the special symbols into module name and ordinal number.
2525 name2 should look like
2526
2527 SYMBOL=MODULE.ORDINAL
2528
2529 where SYMBOL is name1, MODULE is the module name and ORDINAL is
2530 the ordinal number. */
2531
2532 len1 = strlen (name1);
2533 if (memcmp (name1, name2, len1) != 0)
2534 error ("Invalid import record: names don't match");
2535 name2 += len1;
2536 if (*name2 != '=')
2537 error ("Invalid import record: missing `='");
2538 ++name2;
2539 p = strchr (name2, '.');
2540 if (p == NULL)
2541 error ("Invalid import record: missing `.'");
2542 mod_len = p - name2;
2543 memcpy (mod, name2, mod_len);
2544 mod[mod_len] = 0;
2545 proc_name = NULL;
2546 errno = 0;
2547 ord = strtol (p + 1, &q, 10);
2548 if (q != p + 1 && *q == 0 && errno == 0)
2549 {
2550 if (ord < 1 || ord > 65535)
2551 error ("Invalid import record: invalid ordinal");
2552 }
2553 else
2554 {
2555 ord = -1;
2556 proc_name = p + 1;
2557 if (*proc_name == 0)
2558 error ("Invalid import record: invalid name");
2559 }
2560
2561 make_import (name1, proc_name, ord, mod);
2562 return TRUE;
2563}
2564
2565/* Convert import entries. */
2566static void write_import_i2 (void)
2567{
2568 int i;
2569 const char *name1, *name2;
2570
2571 /* Search the symbol table for N_IMP1 and N_IMP2 symbols. These are
2572 unique to import modules. */
2573
2574 name1 = NULL; name2 = NULL;
2575 for (i = 0; i < sym_count; ++i)
2576 {
2577 switch (sym_ptr[i].n_type)
2578 {
2579 case N_IMP1|N_EXT:
2580 name1 = (const char *)(str_ptr + sym_ptr[i].n_un.n_strx);
2581 break;
2582 case N_IMP2|N_EXT:
2583 name2 = (const char *)(str_ptr + sym_ptr[i].n_un.n_strx);
2584 break;
2585 }
2586 if (name1 && name2)
2587 {
2588 int len1, mod_len;
2589 long ord;
2590 const char *proc_name, *p;
2591 char mod[256], *q;
2592
2593 /* Parse the special symbols into module name and ordinal number.
2594 name2 should look like
2595
2596 SYMBOL=MODULE.ORDINAL
2597
2598 where SYMBOL is name1, MODULE is the module name and ORDINAL is
2599 the ordinal number. */
2600
2601 len1 = strlen (name1);
2602 if (memcmp (name1, name2, len1) != 0)
2603 error ("Invalid import record: names don't match");
2604 name2 += len1;
2605 if (*name2 != '=')
2606 error ("Invalid import record: missing `='");
2607 ++name2;
2608 p = strchr (name2, '.');
2609 if (p == NULL)
2610 error ("Invalid import record: missing `.'");
2611 mod_len = p - name2;
2612 memcpy (mod, name2, mod_len);
2613 mod[mod_len] = '\0';
2614 proc_name = NULL;
2615 errno = 0;
2616 ord = strtol (p + 1, &q, 10);
2617 if (q != p + 1 && *q == 0 && errno == 0)
2618 {
2619 if (ord < 1 || ord > 65535)
2620 error ("Invalid import record: invalid ordinal");
2621 }
2622 else
2623 {
2624 ord = -1;
2625 proc_name = p + 1;
2626 if (*proc_name == 0)
2627 error ("Invalid import record: invalid name");
2628 }
2629
2630 /* Write the import definition record. */
2631
2632 init_rec (COMENT);
2633 put_8 (0x00);
2634 put_8 (IMPDEF_CLASS);
2635 put_8 (IMPDEF_SUBTYPE);
2636 put_8 (proc_name == NULL ? 0x01 : 0x00); /* Import by ordinal or by name */
2637 put_str (name1); /* Underscore already removed above */
2638 put_str (mod);
2639 if (proc_name == NULL)
2640 put_16 (ord);
2641 else if (strcmp (proc_name, name1) == 0)
2642 put_8 (0);
2643 else
2644 put_str (proc_name);
2645 write_rec ();
2646
2647 name1 = NULL;
2648 name2 = NULL;
2649 }
2650 }
2651}
2652
2653
2654/* If the input file is an import module (method (I1) as created by
2655 emximp), create an OMF-style import module and return TRUE.
2656 Otherwise, return FALSE. */
2657
2658static int handle_import_i1 (void)
2659{
2660 int i;
2661 const char *pub_name;
2662 char proc_name[257], dll_name[257];
2663 long table_off, ord, off;
2664 long *table;
2665 const struct relocation_info *rel;
2666
2667 /* There must be exactly one public symbol (which must defined for
2668 N_TEXT), otherwise we cannot safely eliminate all the code.
2669 Moreover, there must be an N_SETT|N_EXT entry for `__os2dll'. */
2670
2671 pub_name = NULL; table_off = -1;
2672 for (i = 0; i < sym_count; ++i)
2673 switch (sym_ptr[i].n_type)
2674 {
2675 case N_TEXT|N_EXT:
2676 if (pub_name != NULL) return FALSE;
2677 pub_name = (const char *)(str_ptr + sym_ptr[i].n_un.n_strx);
2678 break;
2679
2680 case N_DATA|N_EXT:
2681 case N_BSS|N_EXT:
2682 return FALSE;
2683
2684 case N_SETT|N_EXT:
2685 if (strcmp ((const char *)(str_ptr + sym_ptr[i].n_un.n_strx), "__os2dll") != 0)
2686 return FALSE;
2687 table_off = sym_ptr[i].n_value;
2688 break;
2689 }
2690
2691 if (pub_name == NULL || table_off == -1)
2692 return FALSE;
2693
2694 /* The table must be completely present. */
2695
2696 if (table_off < 0 || table_off + 4 * 4 > text_size)
2697 error ("Invalid import table: beyond end of segment");
2698
2699 /* Fetch the procedure name or the ordinal. */
2700
2701 table = (long *)(text_ptr + table_off);
2702 if (table[0] == 0)
2703 {
2704 ord = 0;
2705
2706 /* Check and fetch the procedure name. */
2707
2708 rel = find_reloc_fixup (text_rel, a_out_h->a_trsize, table_off + 3 * 4);
2709 if (!fetch_modstr (rel, table[3], proc_name, sizeof (proc_name)))
2710 error ("Invalid import table: invalid pointer to procedure name");
2711 }
2712 else if (table[0] == 1)
2713 {
2714 ord = table[3];
2715 if (ord < 1 || ord > 65535)
2716 error ("Invalid import table: invalid ordinal number");
2717 }
2718 else
2719 error ("Invalid import table: invalid flag");
2720
2721 /* Check the fixup address -- there must be a JMP instruction. */
2722
2723 off = table[1];
2724 if (off < 1 || off + 4 > text_size)
2725 error ("Invalid import table: invalid fixup address");
2726 if (text_ptr[off-1] != 0xe9)
2727 error ("Invalid import table: fixup does not belong to a JMP instruction");
2728
2729 /* Check and fetch the module name. */
2730
2731 rel = find_reloc_fixup (text_rel, a_out_h->a_trsize, table_off + 2 * 4);
2732 if (!fetch_modstr (rel, table[2], dll_name, sizeof (dll_name)))
2733 error ("Invalid import table: invalid pointer to module name");
2734
2735 make_import (pub_name, ord != 0 ? NULL : proc_name, ord, dll_name);
2736 return TRUE;
2737}
2738
2739/**
2740 * Emits a OMF export record if the symbols is defined in this module.
2741 */
2742static void make_export(const char *pszSymbol, size_t cchSymbol,
2743 const char *pszExpName, size_t cchExpName, unsigned iOrdinal)
2744{
2745 const struct nlist *pSym;
2746 char *pszSym = alloca(cchSymbol + 1);
2747 memcpy(pszSym, pszSymbol, cchSymbol);
2748 pszSym[cchSymbol] = '\0';
2749
2750 pSym = find_symbol(pszSym);
2751 if (pSym)
2752 {
2753 /*
2754 * Write the export definition record.
2755 */
2756 uint8_t fFlags = 0;
2757 if (iOrdinal)
2758 fFlags |= 1 << 7; /* have ordinal */
2759 if (cchExpName && !iOrdinal)
2760 fFlags |= 1 << 6; /* resident name */
2761
2762 init_rec(COMENT);
2763 put_8(0x00);
2764 put_8(CLASS_OMFEXT);
2765 put_8(OMFEXT_EXPDEF);
2766 put_8(fFlags);
2767 put_nstr(pszExpName, cchExpName);
2768 put_nstr(pszSymbol, cchSymbol);
2769 if (iOrdinal)
2770 put_16(iOrdinal);
2771 write_rec();
2772 }
2773}
2774
2775
2776/* Convert export entries.
2777
2778 The exports are encoded as N_EXT (0x6c) stab entries. The value is -42,
2779 and the symbol name is on the form: "<exportname>,<ordinal>=<symbol>,code|data"
2780 The exportname can be empty if ordinal is not 0. Ordinal 0 means not exported by
2781 any special ordinal number.
2782
2783 Export entries for symbols which are not defined in the object are ignored. */
2784static void write_export (void)
2785{
2786 int i;
2787
2788 /* Search the symbol table for N_IMP1 and N_IMP2 symbols. These are
2789 unique to import modules. */
2790
2791 for (i = 0; i < sym_count; ++i)
2792 {
2793 const char *pszName;
2794 size_t cchName;
2795 const char *pszOrdinal;
2796 const char *pszSymbol;
2797 size_t cchSymbol;
2798 const char *pszType;
2799 int iOrdinal;
2800 char *pszOrdinalEnd;
2801 if (sym_ptr[i].n_type != N_EXP)
2802 continue;
2803 pszName = (const char *)(str_ptr + sym_ptr[i].n_un.n_strx);
2804
2805 /*
2806 * Parse it.
2807 */
2808 /* find equal sign first, we'll use this for validating the ordinal. */
2809 pszSymbol = strchr(pszName, '=');
2810 if (!pszSymbol)
2811 error("Invalid export record: missing `='. \nstabs: %s", pszName);
2812
2813 /* ordinal */
2814 pszOrdinal = strchr(pszName, ',');
2815 if (!pszOrdinal || pszOrdinal >= pszSymbol)
2816 error("Invalid export record: missing ordinal.\nstabs: %s", pszName);
2817 cchName = pszOrdinal - pszName;
2818 pszOrdinal++;
2819 iOrdinal = strtol(pszOrdinal, &pszOrdinalEnd, 0);
2820 if (iOrdinal < 0 || iOrdinal >= 0x10000)
2821 error("Invalid export record: ordinal value is out of range (0-65k): %d\nstabs:%s",
2822 iOrdinal, pszName);
2823 if (pszOrdinalEnd != pszSymbol)
2824 error("Invalid export record: ordinal field doesn't end at `=.\nstabs:%s", pszName);
2825
2826 /* type and symbol */
2827 pszSymbol++;
2828 pszType = strchr(pszSymbol, ',');
2829 if (!pszType)
2830 error("Invalid export record: Symbol type is missing\nstabs:%s", pszName);
2831 cchSymbol = pszType - pszSymbol;
2832 pszType++;
2833 if (strcmp(pszType, "code") && strcmp(pszType, "data") && strcmp(pszType, "bss") && strcmp(pszType, "common"))
2834 error("Invalid export record: Invalid symbol type: %s\nstabs:%s", pszType, pszName);
2835 if (!cchSymbol)
2836 error("Invalid export record: No (internal) symbol name.\nstabs:%s", pszName);
2837
2838 /*
2839 * Hand it on to the worker which looks up the symbol
2840 * and emits the OMF export record if found.
2841 */
2842 make_export(pszSymbol, cchSymbol, pszName, cchName, iOrdinal);
2843 }
2844}
2845
2846
2847/* Convert a filename from Unix format to OS/2 format. All that has
2848 to be done is replacing slashes with backslashes as IPMD doesn't
2849 like slashes in file names. The conversion is done in place. */
2850
2851static void convert_filename (char *name)
2852{
2853 while (*name != 0)
2854 {
2855 if (*name == '/')
2856 *name = '\\';
2857 ++name;
2858 }
2859}
2860
2861#if 0
2862/* Converts dashed filenames to somewhat absolute ones assuming that
2863 the current directory is what they're relative to. */
2864
2865static int abspath_filename(char *dst, const char *src, int size)
2866{
2867 int rc = -1;
2868 char *psz;
2869
2870 if (src[1] != ':' && src[0] != '\\' && src[0] != '/')
2871 rc = _abspath(dst, src, size);
2872 if (rc)
2873 {
2874 *dst = '\0';
2875 strncat(dst, src, size);
2876 }
2877
2878 for (psz = dst; *psz; psz++)
2879 if (*psz == '/')
2880 *psz = '\\';
2881 return psz - dst;
2882}
2883#endif
2884
2885/* Derive the module name and store it in the mod_name variable.
2886 Derive the current director and store it in the base_dir variable.
2887
2888 Search the symbol table for N_SO symbols. There are two kinds, base dir
2889 and main source file name. The base dir one ends with a slash.
2890
2891 We assume that the base dir name comes first, and that is it's prefect
2892 but maybe for a drive letter.
2893
2894 If there is no such symbol, use the output file name. */
2895
2896static void get_mod_name (void)
2897{
2898 int i, len, ok;
2899 const char *p1, *p2;
2900
2901 base_dir[0] = '\0';
2902 ok = FALSE;
2903 for (i = 0; i < sym_count; ++i)
2904 if (sym_ptr[i].n_type == N_SO)
2905 {
2906 p1 = (const char *)(str_ptr + sym_ptr[i].n_un.n_strx);
2907 len = strlen (p1);
2908 if (len > 0 && p1[len-1] == '/' )
2909 {
2910 if (!base_dir[0])
2911 {
2912 _strncpy (base_dir, p1, sizeof(base_dir));
2913 convert_filename (base_dir);
2914 }
2915 }
2916 else if (len > 0)
2917 {
2918 ok = TRUE;
2919 _strncpy (mod_name, p1, sizeof (mod_name));
2920 convert_filename (mod_name);
2921 /* The base dir doesn't currently have any drive letter.
2922 steal that from the source filename if possible.
2923 ASSUME: that it's more like that source is right than curdir
2924 bacause of stuff like makeomflibs.cmd and autoconv. */
2925 if ( (base_dir[0] == '\\' || base_dir[0] == '/')
2926 && base_dir[1] != '\\' && base_dir[1] != '/' /* unc */
2927 && mod_name[1] == ':')
2928 {
2929 len = strlen(base_dir) + 1;
2930 memmove(base_dir + 2, base_dir, len);
2931 base_dir[0] = mod_name[0];
2932 base_dir[1] = mod_name[1];
2933 }
2934 break;
2935 }
2936 }
2937 if (!ok && out_lib == NULL)
2938 {
2939 p1 = out_fname;
2940 for (p2 = p1; *p2 != 0; ++p2)
2941 if (*p2 == '/' || *p2 == '\\' || *p2 == ':')
2942 p1 = p2 + 1;
2943 _strncpy (mod_name, p1, sizeof (mod_name));
2944 }
2945
2946 /* make sure we have base_dir and that it's an abspath */
2947 if (!base_dir[0])
2948 {
2949 getcwd(base_dir, sizeof(base_dir));
2950 len = strlen(base_dir);
2951 base_dir[len++] = '\\';
2952 base_dir[len] = '\0';
2953 }
2954 else if ( (base_dir[0] == '\\' || base_dir[0] == '/')
2955 && base_dir[1] != '\\' && base_dir[1] != '/') /* unc */
2956 { /* make it absolute using current drive */
2957 len = strlen(base_dir) + 1;
2958 memmove(base_dir + 2, base_dir, len);
2959 base_dir[0] = _getdrive();
2960 base_dir[1] = ':';
2961 }
2962}
2963
2964
2965/* Write the translator module header record. When creating a .LIB
2966 file, this function does nothing. Otherwise, the module name is
2967 expected in the mod_name variable. */
2968
2969static void write_theadr (void)
2970{
2971 if (out_lib == NULL)
2972 {
2973 init_rec (THEADR);
2974 put_str (mod_name);
2975 write_rec ();
2976 }
2977}
2978
2979/* Tell LINK386 what identifier manipulator DLL to call. The name of
2980 the DLL is given by `idmdll_name', the default value of which is
2981 GPPDEMID. The name can be changed with the -I option. If -I- is
2982 given, no IDMDLL record will be written. The IDMDLL record will
2983 also be suppressed if the program hasn't been compiled by the GNU
2984 C++ compiler. */
2985
2986static void write_idmdll ()
2987{
2988 /* kso #465 2003-06-04: This test doesn't work any longer, sorry.
2989 * Pretend everything is C++ */
2990 #if 1
2991 if (idmdll_name != NULL)
2992 #else
2993 if (idmdll_name != NULL && find_symbol ("__gnu_compiled_cplusplus") != NULL)
2994 #endif
2995 {
2996 init_rec (COMENT);
2997 put_8 (0x00);
2998 put_8 (CLASS_IDMDLL);
2999 put_str (idmdll_name);
3000 put_str (""); /* Initialization parameter */
3001 write_rec ();
3002 }
3003}
3004
3005
3006/* Tell ilink which TIS (Tools I Standard) version we follow.
3007 (At least that's what I think this comment record is good for). */
3008static void write_tis ()
3009{
3010 unsigned short ver = 0;
3011 char *type = getenv ("EMXOMFLD_TYPE");
3012 if (type && !stricmp (type, "VAC308"))
3013 ver = 0x0100;
3014 else if (!type || !stricmp (type, "VAC365"))
3015 ver = 0x0101;
3016 /* else: no TIS record for link386! */
3017
3018 if (ver)
3019 {
3020 init_rec (COMENT);
3021 put_8 (0x00);
3022 put_8 (CLASS_TIS);
3023 put_mem ("TIS", 3);
3024 put_16 (ver);
3025 write_rec ();
3026 }
3027}
3028
3029
3030/* Tell ilink which dll to use when /DBGPACK is specificed. The dllname
3031 is given without extension. */
3032static void write_dbgpack ()
3033{
3034 const char *name = dbgpack_name;
3035 if (strip_symbols || !a_out_h->a_syms)
3036 return;
3037 if (!name)
3038 {
3039 char *type = getenv ("EMXOMFLD_TYPE");
3040 if (type && !stricmp (type, "VAC308"))
3041 name = "LNKOH410";
3042 else if (!type || !stricmp (type, "VAC365"))
3043 name = NULL /* hll_version == 4 ? "CPPLH436" : "CPPLH636"
3044 - this linker figures it out by it self. */;
3045 /* no DLL for link386! */
3046 }
3047
3048 if (name)
3049 {
3050 init_rec (COMENT);
3051 put_8 (0x80);
3052 put_8 (CLASS_DBGPACK);
3053 put_str (name);
3054 write_rec ();
3055 }
3056}
3057
3058
3059/* Find a file name for creating line number information. */
3060
3061static int file_find (const char *name)
3062{
3063 int i;
3064 char *psz;
3065
3066 /* canonize the filename - slashes and possibly abs path. */
3067 if (name[0] != '/' && name[0] != '\\' && name[1] != ':')
3068 { /* need to add base_dir. */
3069 int cch1 = strlen(base_dir);
3070 int cch2 = strlen(name) + 1;
3071 psz = xmalloc(cch1 + cch2);
3072 memcpy(psz, base_dir, cch1);
3073 memcpy(psz + cch1, name, cch2);
3074 }
3075 else
3076 psz = xstrdup(name);
3077 convert_filename(psz);
3078
3079 /* search for previous instances */
3080 for (i = 0; i < file_grow.count; ++i)
3081 if (!strcmp(file_list[i], psz))
3082 {
3083 free(psz);
3084 return i;
3085 }
3086
3087 /* new source file, add it if possible. */
3088 if (hll_version <= 3 && file_grow.count >= 255)
3089 {
3090 warning ("Too many source files, cannot convert line number info");
3091 free(psz);
3092 return file_grow.count;
3093 }
3094 grow_by (&file_grow, 1);
3095 i = file_grow.count++;
3096 file_list[i] = psz;
3097 return i;
3098}
3099
3100
3101/* This function is passed to qsort() for sorting line numbers. X1
3102 and X2 point to struct line structures. Line number entries are
3103 sorted by address, file and line number. */
3104
3105static int line_compare (const void *x1, const void *x2)
3106{
3107 dword a1, a2;
3108 int i1, i2;
3109
3110 a1 = ((const struct line *)x1)->addr;
3111 a2 = ((const struct line *)x2)->addr;
3112 if (a1 < a2)
3113 return -1;
3114 else if (a1 > a2)
3115 return 1;
3116 i1 = ((const struct line *)x1)->file_index;
3117 i2 = ((const struct line *)x2)->file_index;
3118 if (i1 < i2)
3119 return -1;
3120 else if (i1 > i2)
3121 return 1;
3122 i1 = ((const struct line *)x1)->line;
3123 i2 = ((const struct line *)x2)->line;
3124 if (i1 < i2)
3125 return -1;
3126 else if (i1 > i2)
3127 return 1;
3128 return 0;
3129}
3130
3131/* Write linenumber fixups for HLL v4 records
3132 * We need fixups for segment idx and offset in the special
3133 * first entry. */
3134static void write_linenumfixup(void)
3135{
3136 /* ASSUME! flat_thread is defined. */
3137 /* ASSUME! base seg idx of linnum rec < 128. */
3138 init_rec (FIXUPP|REC32);
3139 /* LOC=16-bit sel;I=1;M=1; */
3140 put_8 (0xc8);
3141 /* offset 6 (segment number). */
3142 put_8 (0x06);
3143 /* F=1;Frame=flat_thread;T=0;P=1;TARGT=0; */
3144 put_8 (0x84 | (flat_thread << 4));
3145 /* target seg index? */
3146 put_8 (text_index);
3147
3148 /* LOC=32-offset sel;I=1;M=1; */
3149 put_8 (0xe4);
3150 /* offset 8 (offset). */
3151 put_8 (0x08);
3152 /* F=1;Frame=flat_thread;T=0;P=1;TARGT=0; */
3153 put_8 (0x84 | (flat_thread << 4));
3154 /* target seg index? */
3155 put_8 (text_index);
3156 write_rec ();
3157}
3158
3159
3160/* Write line number information to the output file. Unfortunately,
3161 the line number information format currently used by IPMD is not
3162 documented. This code is based on experimentation. */
3163
3164static void write_linnum (void)
3165{
3166 int i, started, len, file_index;
3167 int valid_lines;
3168 struct line *line_list;
3169 struct grow line_grow;
3170 char buf[256];
3171
3172 /* Initialize growing arrays for file names and line numbers. */
3173
3174 grow_init (&file_grow, &file_list, sizeof (*file_list), 8);
3175 grow_init (&line_grow, &line_list, sizeof (*line_list), 64);
3176
3177 /* Define file index for main source file. */
3178
3179 file_index = file_find (mod_name);
3180 started = FALSE;
3181
3182 /* Go through the symbol table, defining line numbers and additional
3183 source files. */
3184
3185 for (i = 0; i < sym_count; ++i)
3186 switch (sym_ptr[i].n_type)
3187 {
3188 case N_SOL:
3189 file_index = file_find ((const char *)(str_ptr + sym_ptr[i].n_un.n_strx));
3190 break;
3191 case N_SLINE:
3192 grow_by (&line_grow, 1);
3193 line_list[line_grow.count].file_index = file_index;
3194 line_list[line_grow.count].line = sym_ptr[i].n_desc;
3195 line_list[line_grow.count].addr = sym_ptr[i].n_value;
3196 ++line_grow.count;
3197 }
3198
3199 /* Sort the line numbers by address, file and line number. */
3200
3201 qsort (line_list, line_grow.count, sizeof (*line_list), line_compare);
3202
3203 /* If there are multiple line numbers assigned to the same address,
3204 keep but the last line number. Delete line numbers by setting
3205 the line number to -1. */
3206
3207 for (i = 0; i < line_grow.count - 1; ++i)
3208 if (line_list[i].line >= 0 && line_list[i+1].line >= 0
3209 && line_list[i].addr == line_list[i+1].addr)
3210 line_list[i].line = -1;
3211
3212 /* Count the number of valid line numbers, that is, non-negative
3213 line numbers. */
3214
3215 valid_lines = 0;
3216 for (i = 0; i < line_grow.count; ++i)
3217 if (line_list[i].line >= 0)
3218 ++valid_lines;
3219
3220
3221 /*
3222 * If no lines or no files, we don't want to issue any LINNUM records.
3223 */
3224 if (valid_lines <= 0 || file_grow.count <= 0)
3225 return;
3226
3227 /* Compute the size of the file names table. */
3228
3229 len = 3 * 4;
3230 for (i = 0; i < file_grow.count; ++i)
3231 len += 1 + strlen (file_list[i]);
3232
3233 /*
3234 * This is the VAC way, too bad link386 doesn't fancy it.
3235 */
3236 if (hll_version >= 4)
3237 {
3238 int first_linnum;
3239 /* Filename table first - a first entry like visual age does it and does hints on */
3240
3241 init_rec (LINNUM|REC32);
3242 started = TRUE;
3243 put_idx (0); /* Base Group */
3244 put_idx (0); /* Base Segment */
3245
3246 put_16 (0); /* Line number = 0 (special entry) */
3247 put_8 (3); /* Entry type: some visual age stuff I believe */
3248 put_8 (0); /* Reserved */
3249 put_16 (file_grow.count); /* Count of line number entries */
3250 put_16 (0); /* Segment number */
3251 put_32 (len); /* Size of file names table */
3252 /* no linenumber */
3253 put_32 (0); /* First column */
3254 put_32 (0); /* Number of columns */
3255 put_32 (file_grow.count); /* Number of source and listing files */
3256
3257 for (i = 0; i < file_grow.count; ++i)
3258 {
3259 len = strlen(file_list[i]);
3260 if (started && !fits (1 + len))
3261 {
3262 write_rec ();
3263 started = FALSE;
3264 }
3265 if (!started)
3266 {
3267 init_rec (LINNUM|REC32);
3268 put_idx (0); /* Base Group */
3269 put_idx (text_index); /* Base Segment */
3270 started = TRUE;
3271 }
3272 put_8 (len);
3273 put_mem (file_list[i], len);
3274 }
3275
3276 if (started)
3277 write_rec ();
3278
3279
3280 /* Write the line number table. */
3281 first_linnum = 1;
3282 init_rec (LINNUM|REC32);
3283 started = TRUE;
3284 put_idx (0); /* Base Group */
3285 put_idx (text_index); /* Base Segment */
3286
3287 put_16 (0); /* Line number = 0 (special entry) */
3288 put_8 (0); /* Entry type: source and offset */
3289 put_8 (0); /* Reserved */
3290 put_16 (valid_lines); /* Count of line number entries */
3291 put_16 (0); /* Segment number - Fixup required */
3292 put_32 (0); /* Segment offset - Fixup required */
3293
3294 for (i = 0; i < line_grow.count; ++i)
3295 if (line_list[i].line >= 0)
3296 {
3297 if (started && !fits (8))
3298 {
3299 write_rec ();
3300 started = FALSE;
3301 if (first_linnum)
3302 {
3303 first_linnum = 0;
3304 write_linenumfixup();
3305 }
3306 }
3307 if (!started)
3308 {
3309 init_rec (LINNUM|REC32);
3310 put_idx (0); /* Base Group */
3311 put_idx (text_index); /* Base Segment */
3312 started = TRUE;
3313 }
3314 put_16 (line_list[i].line);
3315 put_16 (line_list[i].file_index + 1);
3316 put_32 (line_list[i].addr);
3317 }
3318
3319 if (started)
3320 {
3321 write_rec ();
3322 if (first_linnum)
3323 write_linenumfixup();
3324 }
3325 }
3326 else
3327 { /* hll version 3 */
3328 /* Write the line number table. */
3329
3330 init_rec (LINNUM|REC32);
3331 started = TRUE;
3332 put_idx (0); /* Base Group */
3333 put_idx (text_index); /* Base Segment */
3334
3335 put_16 (0); /* Line number = 0 (special entry) */
3336 put_8 (0); /* Entry type: source and offset */
3337 put_8 (0); /* Reserved */
3338 put_16 (valid_lines); /* Count of line number entries */
3339 put_16 (0); /* Segment number */
3340 put_32 (len); /* Size of file names table */
3341
3342 for (i = 0; i < line_grow.count; ++i)
3343 if (line_list[i].line >= 0)
3344 {
3345 if (started && !fits (8))
3346 {
3347 write_rec ();
3348 started = FALSE;
3349 }
3350 if (!started)
3351 {
3352 init_rec (LINNUM|REC32);
3353 put_idx (0); /* Base Group */
3354 put_idx (text_index); /* Base Segment */
3355 started = TRUE;
3356 }
3357 put_16 (line_list[i].line);
3358 put_16(line_list[i].file_index + 1);
3359 put_32 (line_list[i].addr);
3360 }
3361
3362 /* Now write the file names table. */
3363
3364 if (started && !fits (12))
3365 {
3366 write_rec ();
3367 started = FALSE;
3368 }
3369 if (!started)
3370 {
3371 init_rec (LINNUM|REC32);
3372 put_idx (0); /* Base Group */
3373 put_idx (text_index); /* Base Segment */
3374 started = TRUE;
3375 }
3376 put_32 (0); /* First column */
3377 put_32 (0); /* Number of columns */
3378 put_32 (file_grow.count); /* Number of source and listing files */
3379
3380 for (i = 0; i < file_grow.count; ++i)
3381 {
3382 len = strlen (file_list[i]);
3383 if (len > sizeof (buf) - 1)
3384 len = sizeof (buf) - 1;
3385 memcpy (buf, file_list[i], len);
3386 buf[len] = 0;
3387 convert_filename (buf);
3388 if (started && !fits (1 + len))
3389 {
3390 write_rec ();
3391 started = FALSE;
3392 }
3393 if (!started)
3394 {
3395 init_rec (LINNUM|REC32);
3396 put_idx (0); /* Base Group */
3397 put_idx (text_index); /* Base Segment */
3398 started = TRUE;
3399 }
3400 put_8 (len);
3401 put_mem (buf, len);
3402 }
3403
3404 if (started)
3405 write_rec ();
3406 }
3407
3408 grow_free (&line_grow);
3409 grow_free (&file_grow);
3410}
3411
3412
3413/* Print unknown symbol table entries (-u option). */
3414
3415static void list_unknown_stabs (void)
3416{
3417 int i;
3418
3419 for (i = 0; i < sym_count; ++i)
3420 switch (sym_ptr[i].n_type)
3421 {
3422 case 0: case 0 |N_EXT:
3423 case N_ABS: case N_ABS |N_EXT:
3424 case N_TEXT: case N_TEXT|N_EXT:
3425 case N_DATA: case N_DATA|N_EXT:
3426 case N_BSS: case N_BSS |N_EXT:
3427 case N_INDR|N_EXT:
3428 case N_WEAKU:
3429 case N_WEAKA:
3430 case N_WEAKT:
3431 case N_WEAKD:
3432 case N_WEAKB:
3433 case N_SETA: case N_SETA|N_EXT:
3434 case N_SETT: case N_SETT|N_EXT:
3435 case N_SETD: case N_SETD|N_EXT:
3436 case N_GSYM:
3437 case N_FUN:
3438 case N_STSYM:
3439 case N_LCSYM:
3440 case N_RSYM:
3441 case N_SLINE:
3442 case N_SO:
3443 case N_IMP1|N_EXT:
3444 case N_IMP2|N_EXT:
3445 case N_EXP: case N_EXP|N_EXT:
3446 case N_LSYM:
3447 case N_SOL:
3448 case N_PSYM:
3449 case N_LBRAC:
3450 case N_RBRAC:
3451 break;
3452 default:
3453 fprintf (stderr, "Unknown symbol table entry: 0x%.2x \"%s\"\n",
3454 sym_ptr[i].n_type, str_ptr + sym_ptr[i].n_un.n_strx);
3455 break;
3456 }
3457}
3458
3459/* Convert an a.out module to an OMF module. SIZE is the number of
3460 bytes in the input file inp_file. */
3461
3462static void o_to_omf (long size)
3463{
3464 byte *t;
3465 const struct nlist *entry_symbol;
3466 struct set *set_ptr;
3467 int j;
3468
3469 /* Simplify things by reading the complete a.out module into
3470 memory. */
3471
3472 inp_buf = xmalloc (size);
3473 size = fread (inp_buf, 1, size, inp_file);
3474 if (ferror (inp_file))
3475 goto read_error;
3476
3477 /* Set up pointers to various sections of the module read into
3478 memory. */
3479
3480 a_out_h = (struct exec *)inp_buf;
3481 if (size < sizeof (struct exec) || N_MAGIC(*a_out_h) != OMAGIC)
3482 error ("Input file `%s' is not an a.out file", error_fname);
3483 text_size = a_out_h->a_text;
3484 data_size = a_out_h->a_data;
3485 t = inp_buf + sizeof (struct exec);
3486 text_ptr = t; t += text_size;
3487 data_ptr = t; t += data_size;
3488 text_rel = (const struct relocation_info *)t; t += a_out_h->a_trsize;
3489 data_rel = (const struct relocation_info *)t; t += a_out_h->a_drsize;
3490 sym_ptr = (const struct nlist *)t; t += a_out_h->a_syms;
3491 str_ptr = t;
3492 if (a_out_h->a_syms == 0)
3493 str_size = 0;
3494 else
3495 {
3496 if (str_ptr + 4 - inp_buf > size)
3497 goto invalid;
3498 str_size = *(long *)str_ptr;
3499 }
3500 sym_count = a_out_h->a_syms / sizeof (struct nlist);
3501 if (str_ptr + str_size - inp_buf > size)
3502 goto invalid;
3503
3504 /* Build the complementary array of symbol data. */
3505
3506 sym_more = xmalloc (sym_count * sizeof (struct symbol));
3507 memset(sym_more, 0, sym_count * sizeof (struct symbol));
3508
3509 /* Print unknown symbol table entries if the -u option is given. */
3510
3511 if (unknown_stabs)
3512 list_unknown_stabs ();
3513
3514 /* Find the start symbol if converting a main module. */
3515
3516 if (entry_name != NULL)
3517 {
3518 entry_symbol = find_symbol (entry_name);
3519 if (entry_symbol == NULL)
3520 error ("Entry symbol not found");
3521 if ((entry_symbol->n_type & ~N_EXT) != N_TEXT)
3522 error ("Entry symbol not in text segment");
3523 }
3524 else
3525 entry_symbol = NULL; /* keep the compiler happy */
3526
3527 /* Initialize variables for a new OMF module. */
3528
3529 init_obj ();
3530
3531 /* If the a.out module is an import module as created by emximp,
3532 create an OMF import module. Everything is done by
3533 handle_import_i2() or handle_import_i1() in that case, therefore
3534 we can simply return. */
3535
3536 if (out_lib != NULL && (handle_import_i2 () || handle_import_i1 ()))
3537 return;
3538
3539 /* Initialize growing arrays for debug information conversion.
3540 These two arrays contain indices at which the $$SYMBOLS and
3541 $$TYPES segments, respectively, can be split into LEDATA records
3542 by write_seg(). */
3543
3544 grow_init (&sst_boundary_grow, &sst_boundary, sizeof (*sst_boundary), 32);
3545 grow_init (&tt_boundary_grow, &tt_boundary, sizeof (*tt_boundary), 32);
3546
3547 /* Create some OMF names. */
3548
3549 ovl_name = find_lname ("");
3550 text_seg_name = find_lname ("TEXT32");
3551 data_seg_name = find_lname ("DATA32");
3552 bss_seg_name = find_lname ("BSS32");
3553 if (udat_seg_string != NULL)
3554 udat_seg_name = find_lname (udat_seg_string);
3555 else
3556 udat_seg_name = data_seg_name;
3557 if (!strip_symbols && a_out_h->a_syms)
3558 {
3559 symbols_seg_name = find_lname ("$$SYMBOLS");
3560 types_seg_name = find_lname ("$$TYPES");
3561 }
3562 code_class_name = find_lname ("CODE");
3563 data_class_name = find_lname ("DATA");
3564 bss_class_name = find_lname ("BSS");
3565 if (!strip_symbols && a_out_h->a_syms)
3566 {
3567 debsym_class_name = find_lname ("DEBSYM");
3568 debtyp_class_name = find_lname ("DEBTYP");
3569 }
3570 define_set_names ();
3571 if (mod_type == MT_MAIN)
3572 {
3573 stack_seg_name = find_lname ("STACK");
3574 stack_class_name = find_lname ("STACK");
3575 }
3576 flat_group_name = find_lname ("FLAT");
3577 dgroup_group_name = find_lname ("DGROUP");
3578
3579 /* Write the THREADR record. */
3580
3581 get_mod_name ();
3582 write_theadr ();
3583
3584 /* Tell ilink what TIS standard we follow. */
3585
3586 write_tis ();
3587
3588 /* Write default library requests and the debug information style
3589 record (COMENT records). */
3590
3591 write_libs ();
3592 write_debug_style ();
3593
3594 /* Tell ilink what DBGPACK DLL to use. */
3595
3596 write_dbgpack ();
3597
3598 /* Tell LINK386 what identifier manipulator DLL to use. */
3599
3600 write_idmdll ();
3601
3602 /* Define all the OMF names (LNAMES record). Of course, we must not
3603 define new OMF names after this point. */
3604
3605 write_lnames ();
3606
3607 /* Define segments (SEGDEF records). This must be done after
3608 defining the names and before defining the groups. */
3609
3610 text_index = seg_def (text_seg_name, code_class_name, text_size,
3611 FALSE, FALSE);
3612 if (udat_seg_string != NULL)
3613 udat_index = seg_def (udat_seg_name, data_class_name, data_size,
3614 FALSE, FALSE);
3615 data_index = seg_def (data_seg_name, data_class_name,
3616 (udat_seg_string == NULL ? data_size : 0),
3617 FALSE, FALSE);
3618 if (udat_seg_string == NULL)
3619 udat_index = data_index;
3620
3621 write_set_segs ();
3622
3623 bss_index = seg_def (bss_seg_name, bss_class_name, a_out_h->a_bss,
3624 FALSE, FALSE);
3625
3626 if (mod_type == MT_MAIN)
3627 stack_index = seg_def (stack_seg_name, stack_class_name, 0x8000, TRUE, FALSE);
3628
3629 if (!strip_symbols && a_out_h->a_syms)
3630 {
3631 convert_debug (); /* After seg_def of text, data & bss */
3632 symbols_index = seg_def (symbols_seg_name, debsym_class_name,
3633 sst.size, FALSE, FALSE);
3634 types_index = seg_def (types_seg_name, debtyp_class_name,
3635 tt.size, FALSE, FALSE);
3636 }
3637
3638 /* Define groups (GRPDEF records). This must be done after defining
3639 segments.
3640 We lazily assumes that the number of sets will not make the GRPDEF
3641 record too big. Rather safe unless a hundred setvectors are used... */
3642
3643 flat_index = group_index++;
3644 init_rec (GRPDEF);
3645 put_idx (flat_group_name);
3646 write_rec ();
3647
3648 dgroup_index = group_index++;
3649 init_rec (GRPDEF);
3650 put_idx (dgroup_group_name);
3651 put_8 (0xff); put_idx (bss_index);
3652 put_8 (0xff); put_idx (data_index);
3653 for (set_ptr = sets; set_ptr != NULL; set_ptr = set_ptr->next)
3654 for (j = 0; j < 3; ++j)
3655 {
3656 put_8 (0xff); put_idx (set_ptr->seg_index[j]);
3657 }
3658 write_rec ();
3659
3660 /* Convert imports and exports. These show up very early in VAC
3661 generated OMF files. */
3662 write_import_i2 ();
3663 write_export ();
3664
3665 /* Define external, communal and public symbols (EXTDEF, WKEXT,
3666 COMDEF, PUBDEF, and ALIAS records). This must be done after
3667 defining the groups. */
3668
3669 write_extdef ();
3670 write_wkext ();
3671 write_comdef ();
3672 write_pubdef ();
3673 write_set_pub ();
3674 write_alias ();
3675
3676 /* Write link pass separator. */
3677
3678 write_pass2 ();
3679
3680 /* Write segment contents (LEDATA and FIXUPP records) and line
3681 number information (LINNUM record). */
3682
3683 write_seg (text_index, text_seg_name, text_ptr, text_size,
3684 text_rel, a_out_h->a_trsize, FALSE, NULL, 0, N_TEXT);
3685 write_seg (udat_index, udat_seg_name, data_ptr, data_size,
3686 data_rel, a_out_h->a_drsize, FALSE, NULL, 0, N_DATA);
3687
3688 write_set_data ();
3689
3690 if (!strip_symbols && a_out_h->a_syms)
3691 {
3692 write_seg (types_index, types_seg_name, tt.buf, tt.size, NULL, 0, FALSE,
3693 tt_boundary, tt_boundary_grow.count, -1);
3694 write_seg (symbols_index, symbols_seg_name, sst.buf, sst.size,
3695 (const struct relocation_info *)sst_reloc.buf, sst_reloc.size, TRUE,
3696 sst_boundary, sst_boundary_grow.count, -1);
3697 write_linnum ();
3698 }
3699
3700 /* End of module. */
3701
3702 init_rec (MODEND|REC32);
3703 if (entry_name != NULL)
3704 {
3705 put_8 (0xc1); /* Main module with start address */
3706 put_8 (0x50); /* ENDDAT: F5, T0 */
3707 put_idx (text_index);
3708 put_32 (entry_symbol->n_value);
3709 }
3710 else
3711 put_8 (0x00); /* Non-main module without start address */
3712 write_rec ();
3713
3714 /* Clean up memory. */
3715
3716 free_lnames ();
3717 free (inp_buf);
3718 free (sym_more);
3719 buffer_free (&tt);
3720 buffer_free (&sst);
3721 buffer_free (&sst_reloc);
3722 grow_free (&sst_boundary_grow);
3723 grow_free (&tt_boundary_grow);
3724 return;
3725
3726read_error:
3727 error ("Cannot read `%s'", error_fname);
3728
3729invalid:
3730 error ("Malformed a.out file `%s'", error_fname);
3731}
3732
3733
3734/* Display some hints on using this program, then quit. */
3735
3736static void usage (void)
3737{
3738 puts ("emxomf " VERSION INNOTEK_VERSION " -- Copyright (c) 1992-1995 by Eberhard Mattes\n");
3739 puts ("Usage:");
3740 puts (" emxomf [-dgqs] [-l[<symbol>]] [-m <symbol>] [-p <page_size>]");
3741 puts (" [-i <default_lib>] [-I <idmdll>] [-D <dataseg>]");
3742 puts (" -o <output_file> <input_file>");
3743 puts (" emxomf [-dgqsx] [-l[<symbol>]] [-m <symbol>] [-p <page_size>]");
3744 puts (" [-O <directory>] [-r|R <response_file>] [-i <default_lib>]");
3745 puts (" [-I <idmdll>] [-D <dataseg>] <input_file>...");
3746 puts ("\nOptions:");
3747 puts (" -d Delete input files except for archives");
3748 puts (" -i <default_lib> Add default library request");
3749 puts (" -l[<symbol>] Convert library modules, with optional entrypoint");
3750 puts (" -m <symbol> Convert main module with entrypoint <symbol>");
3751 puts (" -o <output_file> Write output to <output_file>");
3752 puts (" -p <page_size> Set page size for LIB files");
3753 puts (" -q Suppress certain warnings");
3754 puts (" -r <response_file> Write response file for adding modules");
3755 puts (" -R <response_file> Write response file for replacing modules");
3756 puts (" -s Strip debugging information");
3757 puts (" -u List symbol table entries unknown to emxomf");
3758 puts (" -x Extract archive members");
3759 puts (" -D <dataseg> Change the name of the data segment");
3760 puts (" -I <idmdll> Name the identifier manipulation DLL");
3761 puts (" -O <directory> Extract files to <directory>");
3762 puts (" -z Remove underscores from all symbol names");
3763 puts (" -P <dbgpackdll> Name the dbgpack DLL (ilink)");
3764 exit (1);
3765}
3766
3767
3768/* Create the output file. If the -r or -R option is used, create the
3769 LIB resonse file. */
3770
3771static void open_output (void)
3772{
3773 char *tmp, *p;
3774
3775 out_file = fopen (out_fname, "wb");
3776 if (out_file == NULL)
3777 error ("Cannot create output file `%s'", out_fname);
3778 if (response_file != NULL)
3779 {
3780 if (response_first)
3781 response_first = FALSE;
3782 else
3783 fprintf (response_file, " &\n");
3784 tmp = alloca (strlen (out_fname) + 1);
3785 strcpy (tmp, out_fname);
3786 for (p = tmp; *p != 0; ++p)
3787 if (*p == '/')
3788 *p = '\\';
3789 fprintf (response_file, "%s %s", (response_replace ? "-+" : "+"), tmp);
3790 }
3791}
3792
3793
3794/* Close the output file. Display an error message and quit on
3795 failure. */
3796
3797static void close_output (void)
3798{
3799 if (fflush (out_file) != 0 || fclose (out_file) != 0)
3800 {
3801 out_file = NULL;
3802 error ("Write error on output file `%s'", out_fname);
3803 }
3804 out_file = NULL;
3805}
3806
3807
3808/* Define or build the name of the output file. If DST_FNAME is not
3809 NULL, use it as name of the output file. Otherwise, build the name
3810 from INP_FNAME (the input file name) and EXT (the extension). If
3811 an output directory has been specified with the -O option, remove
3812 the directory part of INP_FNAME and use output_dir instead. */
3813
3814static void make_out_fname (const char *dst_fname, const char *inp_fname,
3815 const char *ext)
3816{
3817 static char tmp1[MAXPATHLEN+3];
3818 char tmp2[MAXPATHLEN+3];
3819
3820 if (dst_fname == NULL)
3821 {
3822 if (*output_dir != 0)
3823 _splitpath (inp_fname, NULL, NULL, tmp2, NULL);
3824 else
3825 _strncpy (tmp2, inp_fname, MAXPATHLEN);
3826 if (strlen (output_dir) + strlen (tmp2) + 5 > MAXPATHLEN)
3827 error ("File name `%s' too long", inp_fname);
3828 strcpy (tmp1, output_dir);
3829 strcat (tmp1, tmp2);
3830 _remext (tmp1);
3831 strcat (tmp1, ext);
3832 out_fname = tmp1;
3833 }
3834 else
3835 out_fname = dst_fname;
3836}
3837
3838
3839/* Read the header of an archive member at file position POS. Return
3840 FALSE when reaching the end of the file. */
3841
3842static int ar_read_header (struct ar_hdr *dst, long pos)
3843{
3844 int size, i;
3845
3846 fseek (inp_file, pos, SEEK_SET);
3847 size = fread (dst, 1, sizeof (struct ar_hdr), inp_file);
3848 if (size == 0)
3849 return FALSE;
3850 else if (size != sizeof (struct ar_hdr))
3851 error ("Malformed archive `%s'", inp_fname);
3852
3853 /* Remove trailing blanks from the member name. */
3854
3855 i = sizeof (dst->ar_name) - 1;
3856 while (i > 0 && dst->ar_name[i-1] == ' ')
3857 --i;
3858 dst->ar_name[i] = 0;
3859 return TRUE;
3860}
3861
3862
3863/* Retrieve the size from the header of an archive member. */
3864
3865static long ar_member_size (const struct ar_hdr *p)
3866{
3867 long size;
3868 char *e;
3869
3870 errno = 0;
3871 size = strtol (p->ar_size, &e, 10);
3872 if (e == p->ar_size || errno != 0 || size <= 0 || *e != ' ')
3873 error ("Malformed archive header in `%s'", inp_fname);
3874 return size;
3875}
3876
3877
3878/* Convert the a.out file SRC_FNAME to an OMF file named DST_FNAME.
3879 If DST_FNAME is NULL, the output file name is derived from
3880 SRC_FNAME. */
3881
3882static void convert (const char *src_fname, const char *dst_fname)
3883{
3884 char tmp1[MAXPATHLEN+3], tmp2[MAXPATHLEN+3];
3885 char *p = NULL, *name, *end;
3886 long size, index;
3887 static char ar_magic[SARMAG+1] = ARMAG;
3888 char ar_test[SARMAG];
3889 struct ar_hdr ar;
3890 long ar_pos;
3891 struct delete *del;
3892 char *long_names = NULL;
3893 size_t long_names_size = 0;
3894
3895 inp_fname = src_fname;
3896 error_fname = inp_fname;
3897 mod_name[0] = 0;
3898 inp_file = fopen (inp_fname, "rb");
3899 if (inp_file == NULL)
3900 error ("Cannot open input file `%s'", inp_fname);
3901
3902 /* Read some bytes from the start of the file to find out whether
3903 this is an archive (.a) file or not. */
3904
3905 if (fread (ar_test, sizeof (ar_test), 1, inp_file) != 1)
3906 error ("Cannot read input file `%s'", inp_fname);
3907
3908 /* Create a LIB response file if requested and not yet done. */
3909
3910 if (response_fname != NULL && response_file == NULL)
3911 {
3912 response_file = fopen (response_fname, "wt");
3913 if (response_file == NULL)
3914 error ("Cannot create response file `%s'", response_fname);
3915 }
3916
3917 /* The rest of this function (save closing the input file) depends
3918 on whether the input file is an archive or not. */
3919
3920 if (memcmp (ar_test, ar_magic, SARMAG) == 0)
3921 {
3922
3923 /* The input file is an archive. We cannot procede if the user
3924 has specified an output file name and wants one OMF file to
3925 be written for each module in the archive (well, we could do
3926 it if there's exactly one module in the archive, but we
3927 don't). */
3928
3929 if (dst_fname != NULL && opt_x)
3930 error ("Cannot process archive if -o and -x are used");
3931 ar_pos = SARMAG;
3932
3933 /* Create an OMF library file (.LIB file) if the -x option is
3934 not given. */
3935
3936 if (!opt_x)
3937 {
3938 /* calculate a page size based on the size of the aout library.
3939 Since we don't yet know the number of files it contains, we'll
3940 assum the converted library isn't more than the double it's size.
3941 Or at least we can hope it's not... */
3942 struct stat s;
3943 int calculated_page_size = page_size;
3944 if (calculated_page_size <= 0)
3945 {
3946 /* For a better calculation we would need the file count. */
3947 calculated_page_size = 16;
3948 if (!stat(src_fname, &s))
3949 {
3950 int cbPage = (s.st_size * 2) / 65536;
3951 /* Don't allow page size larger than 32K since omflib
3952 won't allow that ... */
3953 while ((calculated_page_size < cbPage)
3954 && (calculated_page_size <= 16384))
3955 calculated_page_size <<= 1;
3956 }
3957 }
3958
3959 make_out_fname (dst_fname, inp_fname, ".lib");
3960 out_lib = omflib_create (out_fname, calculated_page_size, lib_errmsg);
3961 if (out_lib == NULL)
3962 error (lib_errmsg);
3963 if (omflib_header (out_lib, lib_errmsg) != 0)
3964 error (lib_errmsg);
3965 }
3966
3967 /* Loop over all the members of the archive. */
3968
3969 while (ar_read_header (&ar, ar_pos))
3970 {
3971 /* Decode the header. */
3972
3973 size = ar_member_size (&ar);
3974 ar_pos += (sizeof (ar) + size + 1) & -2;
3975
3976 if (strcmp (ar.ar_name, "ARFILENAMES/") == 0)
3977 {
3978 size_t i;
3979
3980 /* The "ARFILENAMES/" member contains the long file
3981 names, each one is terminated with a newline
3982 character. Member names starting with a space are
3983 also considered long file names because a leading
3984 space is used for names pointing into the
3985 "ARFILENAMES/" table. Read the "ARFILENAMES/" member
3986 to LONG_NAMES. */
3987
3988 if (size != 0)
3989 {
3990 long_names_size = (size_t)size;
3991 long_names = xmalloc (long_names_size);
3992 size = fread (long_names, 1, long_names_size, inp_file);
3993 if (ferror (inp_file))
3994 error ("Cannot read `%s'", inp_fname);
3995 if (size != long_names_size)
3996 error ("%s: ARFILENAMES/ member is truncated", inp_fname);
3997
3998 /* Replace the newlines with nulls to make
3999 processing a bit more convenient. */
4000
4001 for (i = 0; i < long_names_size; ++i)
4002 if (long_names[i] == '\n')
4003 long_names[i] = 0;
4004 if (long_names[long_names_size-1] != 0)
4005 error ("%s: ARFILENAMES/ member corrupt", inp_fname);
4006 }
4007 }
4008
4009 /* Ignore the __.SYMDEF and __.IMPORT members. Ignore
4010 import modules unless creating a library file. */
4011
4012 else if (strcmp (ar.ar_name, "__.SYMDEF") != 0
4013 && strcmp (ar.ar_name, "__.IMPORT") != 0
4014 && (memcmp (ar.ar_name, "IMPORT#", 7) != 0 || !opt_x))
4015 {
4016
4017 /* Convert the current member to OMF. First, fetch the
4018 name of the member. If the ar_name starts with a
4019 space, the decimal number following that space is an
4020 offset into the "ARFILENAMES/" member. The number
4021 may be followed by a space and a substring of the
4022 long file name. */
4023
4024 name = ar.ar_name;
4025 if (name[0] == ' ' && long_names != NULL
4026 && (index = strtol (name + 1, &end, 10)) >= 0
4027 && index < long_names_size - 1
4028 && (*end == 0 || *end == ' ')
4029 && (index == 0 || long_names[index-1] == 0))
4030 name = long_names + index;
4031
4032 /* Extract the base name of the member. */
4033
4034 _splitpath (name, NULL, NULL, tmp2, NULL);
4035 if (strlen (output_dir) + strlen (tmp2) + 5 > MAXPATHLEN)
4036 error ("File name `%s' too long", tmp2);
4037
4038 /* Provide for informative error message. Memory leak. */
4039
4040 p = xmalloc (strlen (inp_fname) + 3 + strlen (name));
4041 sprintf (p, "%s(%s)", inp_fname, name);
4042 error_fname = p;
4043
4044 /* Construct the module name for the THREADR record
4045 etc. */
4046
4047 _strncpy (mod_name, tmp2, sizeof (mod_name));
4048 strcat (tmp2, ".obj");
4049
4050 /* Create the output file (-x option) or add a new
4051 module to the output library (no -x option). */
4052
4053 if (opt_x)
4054 {
4055 strcpy (tmp1, output_dir);
4056 strcat (tmp1, tmp2);
4057 out_fname = tmp1;
4058 open_output ();
4059 }
4060 else
4061 {
4062 if (omflib_write_module (out_lib, tmp2, &mod_page,
4063 lib_errmsg) != 0)
4064 error (lib_errmsg);
4065 }
4066
4067 /* Convert the member and close the output file. */
4068
4069 o_to_omf (size);
4070 if (opt_x)
4071 close_output ();
4072 }
4073 if (p != NULL) free (p);
4074 }
4075
4076 /* Finish and close the library library if creating a library
4077 file. */
4078
4079 if (!opt_x)
4080 {
4081 if (omflib_finish (out_lib, lib_errmsg) != 0
4082 || omflib_close (out_lib, lib_errmsg) != 0)
4083 error (lib_errmsg);
4084 out_lib = NULL;
4085 }
4086 }
4087 else
4088 {
4089
4090 /* The input file is not an archive. We assume it being an
4091 a.out object file. Get the size of the file for
4092 o_to_omf(). */
4093
4094 if (fseek (inp_file, 0L, SEEK_END) != 0)
4095 error ("Input file `%s' is not seekable", inp_fname);
4096 size = ftell (inp_file);
4097 fseek (inp_file, 0L, SEEK_SET);
4098
4099 /* Convert the file. */
4100
4101 make_out_fname (dst_fname, inp_fname, ".obj");
4102 open_output ();
4103 o_to_omf (size);
4104 close_output ();
4105
4106 /* If input files are to be deleted (-d option), add the current
4107 input file to the list of files to be deleted. */
4108
4109 if (delete_input_files)
4110 {
4111 del = xmalloc (sizeof (struct delete));
4112 del->name = xstrdup (inp_fname);
4113 del->next = files_to_delete;
4114 files_to_delete = del;
4115 }
4116 }
4117 fclose (inp_file);
4118 free_modstr_cache ();
4119 if (long_names != NULL)
4120 free (long_names);
4121}
4122
4123
4124/* Delete all the files stored in the FILES_TO_DELETE list. While
4125 deleting the files, the list elements are deallocated. */
4126
4127static void delete_files (void)
4128{
4129 struct delete *p, *q;
4130
4131 for (p = files_to_delete; p != NULL; p = q)
4132 {
4133 q = p->next;
4134 remove (p->name);
4135 free (p->name);
4136 free (p);
4137 }
4138}
4139
4140
4141/* Main function of emxomf. Parse the command line and perform the
4142 requested actions. */
4143
4144int main (int argc, char *argv[])
4145{
4146 int c, i;
4147 char *opt_o, *opt_O, *tmp;
4148 struct libreq *lrp;
4149
4150 /* Keep emxomf in memory for the number of minutes indicated by the
4151 GCCLOAD environment variable. */
4152
4153 _emxload_env ("GCCLOAD");
4154
4155 /* Get options from the EMXOMFOPT environment variable, expand
4156 response files (@filename) and wildcard (*.o) on the command
4157 line. */
4158
4159 _envargs (&argc, &argv, "EMXOMFOPT");
4160 _response (&argc, &argv);
4161 _wildcard (&argc, &argv);
4162
4163 /* Set default values of some options. */
4164
4165 opt_o = NULL; opt_O = NULL;
4166 opterr = FALSE;
4167
4168 tmp = getenv("EMXOMFLD_TYPE");
4169 if (tmp)
4170 {
4171 if (!stricmp (tmp, "VAC308"))
4172 hll_version = 4;
4173 else if (!stricmp (tmp, "LINK386"))
4174 hll_version = 3;
4175 }
4176
4177 /* Parse the command line options. */
4178
4179 while ((c = getopt_long (argc, argv, "bdD:h:i:jI:m:l::o:P:p:qO:r:R:tsuxwz", NULL, NULL)) != EOF) /* use long for getting optional -l argument working (FLAG_PERMUTE). */
4180 switch (c)
4181 {
4182 case 'b':
4183 force_big = TRUE;
4184 break;
4185 case 'd':
4186 delete_input_files = TRUE;
4187 break;
4188 case 'D':
4189 udat_seg_string = optarg;
4190 break;
4191 case 'h':
4192 hll_version = optarg ? atoi(optarg) : 4;
4193 if (hll_version != 4 && hll_version != 3 && hll_version != 6)
4194 {
4195 printf ("syntax error: Invalid HLL version specified (%d)\n", hll_version);
4196 usage ();
4197 }
4198 break;
4199 case 'i':
4200 lrp = xmalloc (sizeof (*lrp));
4201 lrp->next = NULL;
4202 lrp->name = xstrdup (optarg);
4203 *libreq_add = lrp;
4204 libreq_add = &lrp->next;
4205 break;
4206 case 'I':
4207 if (strcmp (optarg, "-") == 0)
4208 idmdll_name = NULL;
4209 else
4210 idmdll_name = optarg;
4211 break;
4212 case 'l':
4213 if (mod_type != MT_MODULE)
4214 usage ();
4215 mod_type = MT_LIB;
4216 entry_name = optarg;
4217 break;
4218 case 'm':
4219 if (mod_type != MT_MODULE)
4220 usage ();
4221 mod_type = MT_MAIN;
4222 entry_name = optarg;
4223 break;
4224 case 'o':
4225 if (opt_o != NULL || opt_O != NULL)
4226 usage ();
4227 opt_o = optarg;
4228 break;
4229 case 'P':
4230 if (strcmp (optarg, "-") == 0)
4231 dbgpack_name = NULL;
4232 else
4233 dbgpack_name = optarg;
4234 break;
4235 case 'p':
4236 errno = 0;
4237 page_size = (int)strtol (optarg, &tmp, 0);
4238 if (tmp == optarg || errno != 0 || *tmp != 0
4239 || page_size < 16 || page_size > 32768
4240 || (page_size & (page_size - 1)) != 0)
4241 usage ();
4242 break;
4243 case 'q':
4244 warning_level--;
4245 break;
4246 case 'O':
4247 if (opt_o != NULL || opt_O != NULL)
4248 usage ();
4249 opt_O = optarg;
4250 break;
4251 case 'r':
4252 case 'R':
4253 if (response_fname != NULL)
4254 usage ();
4255 response_fname = optarg;
4256 response_replace = (c == 'R');
4257 break;
4258 case 's':
4259 strip_symbols = TRUE;
4260 break;
4261 case 'u':
4262 unknown_stabs = TRUE;
4263 break;
4264 case 'v':
4265 warning_level++;
4266 break;
4267 case 'x':
4268 opt_x = TRUE;
4269 break;
4270 case 'z':
4271 opt_rmunder = TRUE;
4272 break;
4273 default:
4274 usage ();
4275 }
4276
4277 /* Check for non-option arguments. */
4278
4279 if (argc - optind == 0)
4280 usage ();
4281
4282 if (opt_o != NULL)
4283 {
4284 /* If the -o option is used, there must be exactly one input
4285 file name. */
4286
4287 if (argc - optind != 1)
4288 usage ();
4289 convert (argv[optind], opt_o);
4290 }
4291 else
4292 {
4293
4294 /* The -o option is not used. If the -O option is used, set up
4295 output_dir. */
4296
4297 if (opt_O != NULL)
4298 {
4299 i = strlen (opt_O);
4300 tmp = xmalloc (i + 2);
4301 strcpy (tmp, opt_O);
4302 if (i > 0 && strchr (":\\/", tmp[i-1]) == NULL)
4303 strcat (tmp, "/");
4304 output_dir = tmp;
4305 }
4306
4307 /* Convert all the files named on the command line. */
4308
4309 for (i = optind; i < argc; ++i)
4310 convert (argv[i], NULL);
4311 }
4312
4313 /* If a LIB response file has been created, finish and close it. */
4314
4315 if (response_file != NULL)
4316 {
4317 if (!response_first)
4318 fprintf (response_file, "\n");
4319 if (fflush (response_file) != 0 || fclose (response_file) != 0)
4320 error ("Write error on response file `%s'", response_fname);
4321 }
4322
4323 /* If the user wants input files to be deleted, delete them now. */
4324
4325 if (delete_input_files)
4326 delete_files ();
4327 return 0;
4328}
Note: See TracBrowser for help on using the repository browser.