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

Last change on this file since 3669 was 2984, checked in by bird, 18 years ago

Guard against double truncation. Fixes #137

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