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

Last change on this file since 3729 was 3729, checked in by bird, 14 years ago

emxomf.c: applied emxomf-03-fix-symbol-too-long.diff with modifications and a fix (import lib). References #220.

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