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

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

trunk,0.6: emxomf: Warn once about HLL type indexes we cannot encode in PUBDEF and EXTDEF records and set them to 0 in the sym_more table so we don't die in put_idx and can correctly calculate record lengths. Fixes #293.

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