]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - binutils/dlltool.c
* config/sh/tm-sh.h (BELIEVE_PCC_PROMOTION): Define, so that
[thirdparty/binutils-gdb.git] / binutils / dlltool.c
CommitLineData
c027e8b0 1/* dlltool.c -- tool to generate stuff for PE style DLLs
c336631b 2 Copyright (C) 1995, 96, 97, 1998 Free Software Foundation, Inc.
765e60a9
SC
3
4 This file is part of GNU Binutils.
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
9d04d618
TT
18 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
19 02111-1307, USA. */
765e60a9
SC
20
21
22/*
23 This program allows you to build the files necessary to create
24 DLLs to run on a system which understands PE format image files.
25 (eg, Windows NT)
26
a33f7359
ILT
27 See "Peering Inside the PE: A Tour of the Win32 Portable Executable
28 File Format", MSJ 1994, Volume 9 for more information.
29 Also see "Microsoft Portable Executable and Common Object File Format,
30 Specification 4.1" for more information.
31
765e60a9
SC
32 A DLL contains an export table which contains the information
33 which the runtime loader needs to tie up references from a
c027e8b0 34 referencing program.
765e60a9
SC
35
36 The export table is generated by this program by reading
37 in a .DEF file or scanning the .a and .o files which will be in the
199f5217 38 DLL. A .o file can contain information in special ".drectve" sections
c027e8b0 39 with export information.
765e60a9
SC
40
41 A DEF file contains any number of the following commands:
42
43
c027e8b0 44 NAME <name> [ , <base> ]
6f2d3212 45 The result is going to be <name>.EXE
765e60a9 46
c027e8b0 47 LIBRARY <name> [ , <base> ]
6f2d3212 48 The result is going to be <name>.DLL
765e60a9 49
c336631b 50 EXPORTS ( <name1> [ = <name2> ] [ @ <integer> ] [ NONAME ] [CONSTANT] [DATA] ) *
6f2d3212
SC
51 Declares name1 as an exported symbol from the
52 DLL, with optional ordinal number <integer>
765e60a9 53
061ed861
NC
54 IMPORTS ( ( <internal-name> = <module-name> . <integer> )
55 | ( [ <internal-name> = ] <module-name> . <external-name> )) *
56 Declares that <external-name> or the exported function whoes ordinal number
57 is <integer> is to be imported from the file <module-name>. If
58 <internal-name> is specified then this is the name that the imported
59 function will be refered to in the body of the DLL.
765e60a9
SC
60
61 DESCRIPTION <string>
6f2d3212 62 Puts <string> into output .exp file in the .rdata section
765e60a9
SC
63
64 [STACKSIZE|HEAPSIZE] <number-reserve> [ , <number-commit> ]
6f2d3212 65 Generates --stack|--heap <number-reserve>,<number-commit>
199f5217 66 in the output .drectve section. The linker will
6f2d3212 67 see this and act upon it.
765e60a9
SC
68
69 [CODE|DATA] <attr>+
70 SECTIONS ( <sectionname> <attr>+ )*
6f2d3212
SC
71 <attr> = READ | WRITE | EXECUTE | SHARED
72 Generates --attr <sectionname> <attr> in the output
199f5217 73 .drectve section. The linker will see this and act
6f2d3212 74 upon it.
765e60a9
SC
75
76
199f5217 77 A -export:<name> in a .drectve section in an input .o or .a
765e60a9
SC
78 file to this program is equivalent to a EXPORTS <name>
79 in a .DEF file.
80
81
82
6f2d3212 83 The program generates output files with the prefix supplied
c027e8b0 84 on the command line, or in the def file, or taken from the first
6f2d3212 85 supplied argument.
765e60a9 86
6f2d3212
SC
87 The .exp.s file contains the information necessary to export
88 the routines in the DLL. The .lib.s file contains the information
89 necessary to use the DLL's routines from a referencing program.
765e60a9
SC
90
91
92
6f2d3212 93 Example:
765e60a9 94
061ed861 95 file1.c:
c027e8b0 96 asm (".section .drectve");
6f2d3212 97 asm (".ascii \"-export:adef\"");
765e60a9 98
061ed861 99 void adef (char * s)
6f2d3212 100 {
061ed861 101 printf ("hello from the dll %s\n", s);
6f2d3212 102 }
765e60a9 103
061ed861 104 void bdef (char * s)
6f2d3212 105 {
061ed861 106 printf ("hello from the dll and the other entry point %s\n", s);
6f2d3212 107 }
765e60a9 108
061ed861 109 file2.c:
6f2d3212
SC
110 asm (".section .drectve");
111 asm (".ascii \"-export:cdef\"");
112 asm (".ascii \"-export:ddef\"");
061ed861
NC
113
114 void cdef (char * s)
6f2d3212 115 {
061ed861 116 printf ("hello from the dll %s\n", s);
6f2d3212 117 }
765e60a9 118
061ed861 119 void ddef (char * s)
6f2d3212 120 {
061ed861 121 printf ("hello from the dll and the other entry point %s\n", s);
6f2d3212 122 }
765e60a9 123
6f2d3212
SC
124 printf()
125 {
061ed861 126 return 9;
6f2d3212 127 }
765e60a9 128
061ed861 129 main.c
765e60a9 130
061ed861 131 void main()
6f2d3212 132 {
061ed861 133 cdef();
6f2d3212 134 }
765e60a9 135
061ed861 136 thedll.def
765e60a9 137
6f2d3212
SC
138 LIBRARY thedll
139 HEAPSIZE 0x40000, 0x2000
140 EXPORTS bdef @ 20
061ed861 141 cdef @ 30 NONAME
765e60a9 142
6f2d3212
SC
143 SECTIONS donkey READ WRITE
144 aardvark EXECUTE
765e60a9 145
061ed861 146 # compile up the parts of the dll
765e60a9 147
c027e8b0 148 gcc -c file1.c
6f2d3212 149 gcc -c file2.c
765e60a9 150
061ed861
NC
151 # put them in a library (you don't have to, you
152 # could name all the .os on the dlltool line)
765e60a9 153
6f2d3212
SC
154 ar qcv thedll.in file1.o file2.o
155 ranlib thedll.in
765e60a9 156
061ed861 157 # run this tool over the library and the def file
2757dc25 158 ./dlltool --def thedll.def --output-exp thedll.o --output-lib thedll.a
765e60a9 159
061ed861 160 # build the dll with the library with file1.o, file2.o and the export table
2757dc25 161 ld -o thedll.dll thedll.o thedll.in
765e60a9 162
061ed861 163 # build the mainline
c027e8b0 164 gcc -c themain.c
765e60a9 165
061ed861 166 # link the executable with the import library
2757dc25 167 ld -e main -Tthemain.ld -o themain.exe themain.o thedll.a
765e60a9 168
6f2d3212 169 */
765e60a9 170
e503032e
DE
171/* .idata section description
172
173 The .idata section is the import table. It is a collection of several
174 subsections used to keep the pieces for each dll together: .idata$[234567].
175 IE: Each dll's .idata$2's are catenated together, each .idata$3's, etc.
176
177 .idata$2 = Import Directory Table
178 = array of IMAGE_IMPORT_DESCRIPTOR's.
e503032e 179
061ed861 180 DWORD Import Lookup Table; - pointer to .idata$4
e503032e
DE
181 DWORD TimeDateStamp; - currently always 0
182 DWORD ForwarderChain; - currently always 0
183 DWORD Name; - pointer to dll's name
184 PIMAGE_THUNK_DATA FirstThunk; - pointer to .idata$5
185
eedc864a 186 .idata$3 = null terminating entry for .idata$2.
e503032e
DE
187
188 .idata$4 = Import Lookup Table
189 = array of array of pointers to hint name table.
190 There is one for each dll being imported from, and each dll's set is
191 terminated by a trailing NULL.
192
193 .idata$5 = Import Address Table
194 = array of array of pointers to hint name table.
195 There is one for each dll being imported from, and each dll's set is
196 terminated by a trailing NULL.
197 Initially, this table is identical to the Import Lookup Table. However,
198 at load time, the loader overwrites the entries with the address of the
199 function.
200
201 .idata$6 = Hint Name Table
202 = Array of { short, asciz } entries, one for each imported function.
203 The `short' is the function's ordinal number.
204
205 .idata$7 = dll name (eg: "kernel32.dll"). (.idata$6 for ppc)
206*/
207
a33f7359
ILT
208/* AIX requires this to be the first thing in the file. */
209#ifndef __GNUC__
210# ifdef _AIX
211 #pragma alloca
212#endif
213#endif
214
215#define show_allnames 0
216
6f2d3212
SC
217#define PAGE_SIZE 4096
218#define PAGE_MASK (-PAGE_SIZE)
765e60a9 219#include "bfd.h"
27fca56f
ILT
220#include "libiberty.h"
221#include "bucomm.h"
222#include "getopt.h"
531f86b4 223#include "demangle.h"
a33f7359
ILT
224#include "dlltool.h"
225
356c68ff 226#include <ctype.h>
a33f7359 227#include <time.h>
061ed861
NC
228#ifdef __STDC__
229#include <stdarg.h>
230#else
231#include <varargs.h>
232#endif
233
234#ifdef DLLTOOL_ARM
235#include "coff/arm.h"
236#include "coff/internal.h"
237#endif
a33f7359 238
27fca56f
ILT
239#ifdef HAVE_SYS_WAIT_H
240#include <sys/wait.h>
9d04d618
TT
241#else /* ! HAVE_SYS_WAIT_H */
242#if ! defined (_WIN32) || defined (__CYGWIN32__)
27fca56f
ILT
243#ifndef WIFEXITED
244#define WIFEXITED(w) (((w)&0377) == 0)
245#endif
246#ifndef WIFSIGNALED
247#define WIFSIGNALED(w) (((w)&0377) != 0177 && ((w)&~0377) == 0)
248#endif
249#ifndef WTERMSIG
250#define WTERMSIG(w) ((w) & 0177)
251#endif
252#ifndef WEXITSTATUS
253#define WEXITSTATUS(w) (((w) >> 8) & 0377)
254#endif
9d04d618
TT
255#else /* defined (_WIN32) && ! defined (__CYGWIN32__) */
256#ifndef WIFEXITED
257#define WIFEXITED(w) (((w) & 0xff) == 0)
27fca56f 258#endif
9d04d618
TT
259#ifndef WIFSIGNALED
260#define WIFSIGNALED(w) (((w) & 0xff) != 0 && ((w) & 0xff) != 0x7f)
261#endif
262#ifndef WTERMSIG
263#define WTERMSIG(w) ((w) & 0x7f)
264#endif
265#ifndef WEXITSTATUS
266#define WEXITSTATUS(w) (((w) & 0xff00) >> 8)
267#endif
268#endif /* defined (_WIN32) && ! defined (__CYGWIN32__) */
269#endif /* ! HAVE_SYS_WAIT_H */
2757dc25 270
c027e8b0 271/* ifunc and ihead data structures: ttk@cygnus.com 1997
a4e5fd18 272
c027e8b0
ILT
273 When IMPORT declarations are encountered in a .def file the
274 function import information is stored in a structure referenced by
275 the global variable IMPORT_LIST. The structure is a linked list
276 containing the names of the dll files each function is imported
277 from and a linked list of functions being imported from that dll
278 file. This roughly parallels the structure of the .idata section
279 in the PE object file.
280
281 The contents of .def file are interpreted from within the
282 process_def_file function. Every time an IMPORT declaration is
283 encountered, it is broken up into its component parts and passed to
284 def_import. IMPORT_LIST is initialized to NULL in function main. */
285
286typedef struct ifunct
287{
288 char *name; /* name of function being imported */
289 int ord; /* two-byte ordinal value associated with function */
290 struct ifunct *next;
291} ifunctype;
292
293typedef struct iheadt
294{
295 char *dllname; /* name of dll file imported from */
296 long nfuncs; /* number of functions in list */
297 struct ifunct *funchead; /* first function in list */
298 struct ifunct *functail; /* last function in list */
299 struct iheadt *next; /* next dll file in list */
300} iheadtype;
301
302/* Structure containing all import information as defined in .def file
303 (qv "ihead structure"). */
a4e5fd18 304
c027e8b0 305static iheadtype *import_list = NULL;
a4e5fd18 306
a33f7359 307static char *as_name = "as";
061ed861 308static char * as_flags = "";
fb257042 309
356c68ff
SC
310static int no_idata4;
311static int no_idata5;
312static char *exp_name;
313static char *imp_name;
314static char *head_label;
315static char *imp_name_lab;
316static char *dll_name;
2757dc25 317
356c68ff
SC
318static int add_indirect = 0;
319static int add_underscore = 0;
320static int dontdeltemps = 0;
fb257042 321
061ed861
NC
322#ifdef DLLTOOL_ARM
323static int interwork = 0;
324#endif
325
faad4b47
ILT
326/* True if we should export all symbols. Otherwise, we only export
327 symbols listed in .drectve sections or in the def file. */
328static boolean export_all_symbols;
329
330/* True if we should exclude the symbols in DEFAULT_EXCLUDES when
331 exporting all symbols. */
332static boolean do_default_excludes;
333
334/* Default symbols to exclude when exporting all the symbols. */
335static const char *default_excludes = "DllMain@12,DllEntryPoint@0,impure_ptr";
336
356c68ff 337static char *def_file;
2757dc25 338
061ed861 339extern char * program_name;
765e60a9
SC
340
341static int machine;
a33f7359 342static int killat;
6f2d3212 343static int verbose;
a33f7359
ILT
344static FILE *output_def;
345static FILE *base_file;
6d93c360 346
765e60a9 347#ifdef DLLTOOL_ARM
a33f7359 348static const char *mname = "arm";
765e60a9
SC
349#endif
350
351#ifdef DLLTOOL_I386
a33f7359 352static const char *mname = "i386";
765e60a9 353#endif
6d93c360
ILT
354
355#ifdef DLLTOOL_PPC
a33f7359 356static const char *mname = "ppc";
6d93c360
ILT
357#endif
358
6f2d3212 359#define PATHMAX 250 /* What's the right name for this ? */
765e60a9 360
061ed861
NC
361#define TMP_ASM "dc.s"
362#define TMP_HEAD_S "dh.s"
363#define TMP_HEAD_O "dh.o"
364#define TMP_TAIL_S "dt.s"
365#define TMP_TAIL_O "dt.o"
366#define TMP_STUB "ds"
367
356c68ff
SC
368/* This bit of assemly does jmp * ....
369s set how_jtab_roff to mark where the 32bit abs branch should go */
a33f7359
ILT
370static const unsigned char i386_jtab[] =
371{
372 0xff, 0x25, 0x00, 0x00, 0x00, 0x00, 0x90, 0x90
373};
356c68ff 374
a33f7359
ILT
375static const unsigned char arm_jtab[] =
376{
377 0x00, 0xc0, 0x9f, 0xe5,
378 0x00, 0xf0, 0x9c, 0xe5,
379 0, 0, 0, 0
380};
6d93c360 381
061ed861
NC
382static const unsigned char thumb_jtab[] =
383{
384 0xc0, 0xb4,
385 0x02, 0x4e,
386 0x36, 0x68,
387 0x01, 0x96,
388 0x40, 0xbd,
389 0xc0, 0x46,
390 0, 0, 0, 0
391};
392
b10f8e5e
KK
393/* This is the glue sequence for PowerPC PE. There is a */
394/* tocrel16-tocdefn reloc against the first instruction. */
395/* We also need a IMGLUE reloc against the glue function */
396/* to restore the toc saved by the third instruction in */
397/* the glue. */
c027e8b0
ILT
398static const unsigned char ppc_jtab[] =
399{
b10f8e5e
KK
400 0x00, 0x00, 0x62, 0x81, /* lwz r11,0(r2) */
401 /* Reloc TOCREL16 __imp_xxx */
402 0x00, 0x00, 0x8B, 0x81, /* lwz r12,0(r11) */
403 0x04, 0x00, 0x41, 0x90, /* stw r2,4(r1) */
404 0xA6, 0x03, 0x89, 0x7D, /* mtctr r12 */
405 0x04, 0x00, 0x4B, 0x80, /* lwz r2,4(r11) */
406 0x20, 0x04, 0x80, 0x4E /* bctr */
407};
408
a33f7359 409#ifdef DLLTOOL_PPC
b10f8e5e
KK
410/* the glue instruction, picks up the toc from the stw in */
411/* the above code: "lwz r2,4(r1)" */
a33f7359
ILT
412static bfd_vma ppc_glue_insn = 0x80410004;
413#endif
b10f8e5e 414
061ed861
NC
415/* The outfile array must be big enough to contain a fully
416 qualified path name, plus an arbitary series of command
417 line switches. We hope that PATH_MAX times two will be
418 enough. */
419static char outfile [PATHMAX * 2];
6d93c360 420
765e60a9 421struct mac
6f2d3212 422 {
a33f7359
ILT
423 const char *type;
424 const char *how_byte;
425 const char *how_short;
426 const char *how_long;
427 const char *how_asciz;
428 const char *how_comment;
429 const char *how_jump;
430 const char *how_global;
431 const char *how_space;
432 const char *how_align_short;
433 const char *how_align_long;
434 const char *how_bfd_target;
356c68ff 435 enum bfd_architecture how_bfd_arch;
a33f7359 436 const unsigned char *how_jtab;
356c68ff
SC
437 int how_jtab_size; /* size of the jtab entry */
438 int how_jtab_roff; /* offset into it for the ind 32 reloc into idata 5 */
a33f7359
ILT
439 };
440
061ed861
NC
441static const struct mac
442mtable[] =
765e60a9 443{
6f2d3212 444 {
f88ebc68 445#define MARM 0
c027e8b0 446 "arm", ".byte", ".short", ".long", ".asciz", "@",
356c68ff
SC
447 "ldr\tip,[pc]\n\tldr\tpc,[ip]\n\t.long",
448 ".global", ".space", ".align\t2",".align\t4","pe-arm-little", bfd_arch_arm,
061ed861 449 arm_jtab, sizeof (arm_jtab), 8
6f2d3212
SC
450 }
451 ,
452 {
f88ebc68 453#define M386 1
356c68ff 454 "i386", ".byte", ".short", ".long", ".asciz", "#", "jmp *", ".global", ".space", ".align\t2",".align\t4","pe-i386",bfd_arch_i386,
061ed861 455 i386_jtab, sizeof (i386_jtab), 2
6f2d3212
SC
456 }
457 ,
6d93c360
ILT
458 {
459#define MPPC 2
460 "ppc", ".byte", ".short", ".long", ".asciz", "#", "jmp *", ".global", ".space", ".align\t2",".align\t4","pe-powerpcle",bfd_arch_powerpc,
061ed861
NC
461 ppc_jtab, sizeof (ppc_jtab), 0
462 }
463 ,
464 {
465#define MTHUMB 3
466 "thumb", ".byte", ".short", ".long", ".asciz", "@",
467 "push\t{r6, r7}\n\tldr\tr6, [pc, #8]\n\tldr\tr6, [r6]\n\tstr\tr6, [sp, #4]\n\tpop\t{r6, pc}\n\tnop",
468 ".global", ".space", ".align\t2",".align\t4","pe-arm-little", bfd_arch_arm,
469 thumb_jtab, sizeof (thumb_jtab), 12
6d93c360
ILT
470 }
471 ,
356c68ff 472{ 0}
6f2d3212 473};
765e60a9 474
a33f7359
ILT
475typedef struct dlist
476{
477 char *text;
478 struct dlist *next;
479}
480dlist_type;
2757dc25 481
a33f7359
ILT
482typedef struct export
483 {
484 const char *name;
485 const char *internal_name;
486 int ordinal;
487 int constant;
488 int noname;
c336631b 489 int data;
a33f7359
ILT
490 int hint;
491 struct export *next;
492 }
493export_type;
494
faad4b47
ILT
495/* A list of symbols which we should not export. */
496
497struct string_list
498{
499 struct string_list *next;
500 char *string;
501};
502
503static struct string_list *excludes;
504
a33f7359
ILT
505static const char *rvaafter PARAMS ((int));
506static const char *rvabefore PARAMS ((int));
507static const char *asm_prefix PARAMS ((int));
c027e8b0 508static void append_import PARAMS ((const char *, const char *, int));
a33f7359 509static void run PARAMS ((const char *, char *));
faad4b47
ILT
510static void scan_drectve_symbols PARAMS ((bfd *));
511static void scan_filtered_symbols PARAMS ((bfd *, PTR, long, unsigned int));
512static void add_excludes PARAMS ((const char *));
513static boolean match_exclude PARAMS ((const char *));
514static void set_default_excludes PARAMS ((void));
515static long filter_symbols PARAMS ((bfd *, PTR, long, unsigned int));
516static void scan_all_symbols PARAMS ((bfd *));
a33f7359
ILT
517static void scan_open_obj_file PARAMS ((bfd *));
518static void scan_obj_file PARAMS ((const char *));
519static void dump_def_info PARAMS ((FILE *));
520static int sfunc PARAMS ((const void *, const void *));
521static void flush_page PARAMS ((FILE *, long *, int, int));
522static void gen_def_file PARAMS ((void));
c027e8b0 523static void generate_idata_ofile PARAMS ((FILE *));
a33f7359
ILT
524static void gen_exp_file PARAMS ((void));
525static const char *xlate PARAMS ((const char *));
faad4b47 526#if 0
a33f7359 527static void dump_iat PARAMS ((FILE *, export_type *));
faad4b47 528#endif
a33f7359
ILT
529static char *make_label PARAMS ((const char *, const char *));
530static bfd *make_one_lib_file PARAMS ((export_type *, int));
531static bfd *make_head PARAMS ((void));
532static bfd *make_tail PARAMS ((void));
533static void gen_lib_file PARAMS ((void));
534static int pfunc PARAMS ((const void *, const void *));
535static int nfunc PARAMS ((const void *, const void *));
536static void remove_null_names PARAMS ((export_type **));
537static void dtab PARAMS ((export_type **));
538static void process_duplicates PARAMS ((export_type **));
539static void fill_ordinals PARAMS ((export_type **));
540static int alphafunc PARAMS ((const void *, const void *));
541static void mangle_defs PARAMS ((void));
faad4b47
ILT
542static void usage PARAMS ((FILE *, int));
543static void display PARAMS ((const char *, va_list));
061ed861
NC
544static void inform PARAMS ((const char *, ...));
545static void warn PARAMS ((const char *, ...));
546
547static void
faad4b47 548display (message, args)
061ed861
NC
549 const char * message;
550 va_list args;
551{
552 if (program_name != NULL)
553 fprintf (stderr, "%s: ", program_name);
554
555 vfprintf (stderr, message, args);
556
557 if (message [strlen (message) - 1] != '\n')
558 fputc ('\n', stderr);
559}
560
561
562static void
563#ifdef __STDC__
564inform (const char * message, ...)
565#else
566inform (message, va_alist)
567 const char * message;
568 va_dcl
569#endif
570{
571 va_list args;
572
573 if (!verbose)
574 return;
575
576#ifdef __STDC__
577 va_start (args, message);
578#else
579 va_start (args);
580#endif
581
faad4b47 582 display (message, args);
061ed861
NC
583
584 va_end (args);
585}
586
587static void
588#ifdef __STDC__
589warn (const char * message, ...)
590#else
591warn (message, va_alist)
592 const char * message;
593 va_dcl
594#endif
595{
596 va_list args;
597
598#ifdef __STDC__
599 va_start (args, message);
600#else
601 va_start (args);
602#endif
603
faad4b47 604 display (message, args);
061ed861
NC
605
606 va_end (args);
607}
a33f7359
ILT
608
609static const char *
531f86b4
SC
610rvaafter (machine)
611 int machine;
2757dc25 612{
f88ebc68
SC
613 switch (machine)
614 {
615 case MARM:
f88ebc68 616 case M386:
6d93c360 617 case MPPC:
061ed861
NC
618 case MTHUMB:
619 break;
620 default:
621 /* xgettext:c-format */
622 fatal (_("Internal error: Unknown machine type: %d\n"), machine);
623 break;
f88ebc68 624 }
a33f7359 625 return "";
2757dc25
SC
626}
627
a33f7359 628static const char *
531f86b4
SC
629rvabefore (machine)
630 int machine;
2757dc25 631{
f88ebc68
SC
632 switch (machine)
633 {
634 case MARM:
f88ebc68 635 case M386:
6d93c360 636 case MPPC:
061ed861 637 case MTHUMB:
6d93c360 638 return ".rva\t";
061ed861
NC
639 default:
640 /* xgettext:c-format */
641 fatal (_("Internal error: Unknown machine type: %d\n"), machine);
642 break;
f88ebc68 643 }
a33f7359 644 return "";
2757dc25 645}
199f5217 646
a33f7359 647static const char *
531f86b4 648asm_prefix (machine)
a33f7359 649 int machine;
199f5217
DE
650{
651 switch (machine)
652 {
653 case MARM:
061ed861
NC
654 case MPPC:
655 case MTHUMB:
656 break;
199f5217
DE
657 case M386:
658 return "_";
061ed861
NC
659 default:
660 /* xgettext:c-format */
661 fatal (_("Internal error: Unknown machine type: %d\n"), machine);
662 break;
199f5217 663 }
a33f7359 664 return "";
199f5217 665}
a33f7359 666
765e60a9
SC
667#define ASM_BYTE mtable[machine].how_byte
668#define ASM_SHORT mtable[machine].how_short
669#define ASM_LONG mtable[machine].how_long
670#define ASM_TEXT mtable[machine].how_asciz
671#define ASM_C mtable[machine].how_comment
672#define ASM_JUMP mtable[machine].how_jump
673#define ASM_GLOBAL mtable[machine].how_global
674#define ASM_SPACE mtable[machine].how_space
fb257042 675#define ASM_ALIGN_SHORT mtable[machine].how_align_short
2757dc25
SC
676#define ASM_RVA_BEFORE rvabefore(machine)
677#define ASM_RVA_AFTER rvaafter(machine)
199f5217 678#define ASM_PREFIX asm_prefix(machine)
f051e1b0 679#define ASM_ALIGN_LONG mtable[machine].how_align_long
356c68ff
SC
680#define HOW_BFD_TARGET 0 /* always default*/
681#define HOW_BFD_ARCH mtable[machine].how_bfd_arch
682#define HOW_JTAB mtable[machine].how_jtab
683#define HOW_JTAB_SIZE mtable[machine].how_jtab_size
684#define HOW_JTAB_ROFF mtable[machine].how_jtab_roff
765e60a9
SC
685static char **oav;
686
765e60a9
SC
687void
688process_def_file (name)
a33f7359 689 const char *name;
765e60a9 690{
20dec772 691 FILE *f = fopen (name, FOPEN_RT);
061ed861 692
765e60a9 693 if (!f)
061ed861
NC
694 /* xgettext:c-format */
695 fatal (_("Can't open def file: %s"), name);
765e60a9
SC
696
697 yyin = f;
698
061ed861
NC
699 /* xgettext:c-format */
700 inform (_("Processing def file: %s"), name);
701
765e60a9 702 yyparse ();
061ed861
NC
703
704 inform (_("Processed def file"));
765e60a9
SC
705}
706
707/**********************************************************************/
708
709/* Communications with the parser */
710
a33f7359 711static const char *d_name; /* Arg to NAME or LIBRARY */
765e60a9 712static int d_nfuncs; /* Number of functions exported */
f051e1b0
SC
713static int d_named_nfuncs; /* Number of named functions exported */
714static int d_low_ord; /* Lowest ordinal index */
715static int d_high_ord; /* Highest ordinal index */
765e60a9 716static export_type *d_exports; /*list of exported functions */
f051e1b0 717static export_type **d_exports_lexically; /* vector of exported functions in alpha order */
6f2d3212
SC
718static dlist_type *d_list; /* Descriptions */
719static dlist_type *a_list; /* Stuff to go in directives */
765e60a9
SC
720
721static int d_is_dll;
722static int d_is_exe;
723
c027e8b0 724int
a33f7359
ILT
725yyerror (err)
726 const char *err;
765e60a9 727{
061ed861
NC
728 /* xgettext:c-format */
729 warn (_("Syntax error in def file %s:%d\n"), def_file, linenumber);
730
356c68ff 731 return 0;
765e60a9
SC
732}
733
734void
c336631b 735def_exports (name, internal_name, ordinal, noname, constant, data)
a33f7359
ILT
736 const char *name;
737 const char *internal_name;
765e60a9
SC
738 int ordinal;
739 int noname;
740 int constant;
c336631b 741 int data;
765e60a9
SC
742{
743 struct export *p = (struct export *) xmalloc (sizeof (*p));
744
745 p->name = name;
b990c244 746 p->internal_name = internal_name ? internal_name : name;
765e60a9
SC
747 p->ordinal = ordinal;
748 p->constant = constant;
749 p->noname = noname;
c336631b 750 p->data = data;
765e60a9
SC
751 p->next = d_exports;
752 d_exports = p;
753 d_nfuncs++;
765e60a9
SC
754}
755
756void
757def_name (name, base)
a33f7359 758 const char *name;
765e60a9
SC
759 int base;
760{
061ed861
NC
761 /* xgettext:c-format */
762 inform (_("NAME: %s base: %x"), name, base);
763
765e60a9 764 if (d_is_dll)
061ed861
NC
765 warn (_("Can't have LIBRARY and NAME\n"));
766
765e60a9 767 d_name = name;
765e60a9
SC
768 d_is_exe = 1;
769}
770
771void
772def_library (name, base)
a33f7359 773 const char *name;
765e60a9
SC
774 int base;
775{
061ed861
NC
776 /* xgettext:c-format */
777 inform (_("LIBRARY: %s base: %x"), name, base);
778
765e60a9 779 if (d_is_exe)
061ed861
NC
780 warn (_("%s: Can't have LIBRARY and NAME\n"), program_name);
781
765e60a9 782 d_name = name;
765e60a9
SC
783 d_is_dll = 1;
784}
785
786void
787def_description (desc)
a33f7359 788 const char *desc;
765e60a9 789{
6f2d3212 790 dlist_type *d = (dlist_type *) xmalloc (sizeof (dlist_type));
a33f7359 791 d->text = xstrdup (desc);
765e60a9
SC
792 d->next = d_list;
793 d_list = d;
794}
795
2757dc25 796void
6f2d3212
SC
797new_directive (dir)
798 char *dir;
765e60a9 799{
6f2d3212 800 dlist_type *d = (dlist_type *) xmalloc (sizeof (dlist_type));
a33f7359 801 d->text = xstrdup (dir);
765e60a9
SC
802 d->next = a_list;
803 a_list = d;
804}
805
806void
a4e5fd18 807def_heapsize (reserve, commit)
765e60a9
SC
808 int reserve;
809 int commit;
810{
811 char b[200];
6f2d3212 812 if (commit > 0)
a4e5fd18 813 sprintf (b, "-heap 0x%x,0x%x ", reserve, commit);
6f2d3212 814 else
a4e5fd18 815 sprintf (b, "-heap 0x%x ", reserve);
a33f7359 816 new_directive (xstrdup (b));
765e60a9
SC
817}
818
819void
a4e5fd18 820def_stacksize (reserve, commit)
765e60a9
SC
821 int reserve;
822 int commit;
823{
824 char b[200];
6f2d3212 825 if (commit > 0)
a4e5fd18 826 sprintf (b, "-stack 0x%x,0x%x ", reserve, commit);
6f2d3212 827 else
a4e5fd18 828 sprintf (b, "-stack 0x%x ", reserve);
a33f7359 829 new_directive (xstrdup (b));
765e60a9
SC
830}
831
c027e8b0
ILT
832/* append_import simply adds the given import definition to the global
833 import_list. It is used by def_import. */
834
835static void
a4e5fd18 836append_import (symbol_name, dll_name, func_ordinal)
c027e8b0
ILT
837 const char *symbol_name;
838 const char *dll_name;
839 int func_ordinal;
840{
841 iheadtype **pq;
842 iheadtype *q;
843
844 for (pq = &import_list; *pq != NULL; pq = &(*pq)->next)
845 {
846 if (strcmp ((*pq)->dllname, dll_name) == 0)
847 {
848 q = *pq;
849 q->functail->next = xmalloc (sizeof (ifunctype));
850 q->functail = q->functail->next;
851 q->functail->ord = func_ordinal;
852 q->functail->name = xstrdup (symbol_name);
853 q->functail->next = NULL;
854 q->nfuncs++;
855 return;
856 }
857 }
858
859 q = xmalloc (sizeof (iheadtype));
860 q->dllname = xstrdup (dll_name);
861 q->nfuncs = 1;
862 q->funchead = xmalloc (sizeof (ifunctype));
863 q->functail = q->funchead;
864 q->next = NULL;
865 q->functail->name = xstrdup (symbol_name);
866 q->functail->ord = func_ordinal;
867 q->functail->next = NULL;
868
869 *pq = q;
870}
871
872/* def_import is called from within defparse.y when an IMPORT
873 declaration is encountered. Depending on the form of the
874 declaration, the module name may or may not need ".dll" to be
875 appended to it, the name of the function may be stored in internal
876 or entry, and there may or may not be an ordinal value associated
877 with it. */
a4e5fd18
BM
878
879/* A note regarding the parse modes:
c027e8b0
ILT
880 In defparse.y we have to accept import declarations which follow
881 any one of the following forms:
a4e5fd18
BM
882 <func_name_in_app> = <dll_name>.<func_name_in_dll>
883 <func_name_in_app> = <dll_name>.<number>
884 <dll_name>.<func_name_in_dll>
885 <dll_name>.<number>
c027e8b0
ILT
886 Furthermore, the dll's name may or may not end with ".dll", which
887 complicates the parsing a little. Normally the dll's name is
888 passed to def_import() in the "module" parameter, but when it ends
889 with ".dll" it gets passed in "module" sans ".dll" and that needs
890 to be reappended.
891
892 def_import gets five parameters:
893 APP_NAME - the name of the function in the application, if
a4e5fd18 894 present, or NULL if not present.
c027e8b0
ILT
895 MODULE - the name of the dll, possibly sans extension (ie, '.dll').
896 DLLEXT - the extension of the dll, if present, NULL if not present.
897 ENTRY - the name of the function in the dll, if present, or NULL.
898 ORD_VAL - the numerical tag of the function in the dll, if present,
899 or NULL. Exactly one of <entry> or <ord_val> must be
900 present (i.e., not NULL). */
a4e5fd18 901
c027e8b0 902void
a4e5fd18 903def_import (app_name, module, dllext, entry, ord_val)
c027e8b0
ILT
904 const char *app_name;
905 const char *module;
906 const char *dllext;
907 const char *entry;
908 int ord_val;
909{
910 const char *application_name;
911 char *buf;
912
913 if (entry != NULL)
914 application_name = entry;
915 else
916 {
917 if (app_name != NULL)
918 application_name = app_name;
a4e5fd18 919 else
c027e8b0
ILT
920 application_name = "";
921 }
061ed861 922
c027e8b0
ILT
923 if (dllext != NULL)
924 {
925 buf = (char *) alloca (strlen (module) + strlen (dllext) + 2);
926 sprintf (buf, "%s.%s", module, dllext);
927 module = buf;
928 }
929
930 append_import (application_name, module, ord_val);
931}
765e60a9
SC
932
933void
934def_version (major, minor)
a33f7359
ILT
935 int major;
936 int minor;
765e60a9
SC
937{
938 printf ("VERSION %d.%d\n", major, minor);
939}
940
765e60a9
SC
941void
942def_section (name, attr)
a33f7359 943 const char *name;
765e60a9
SC
944 int attr;
945{
946 char buf[200];
6f2d3212 947 char atts[5];
765e60a9
SC
948 char *d = atts;
949 if (attr & 1)
6f2d3212 950 *d++ = 'R';
765e60a9
SC
951
952 if (attr & 2)
953 *d++ = 'W';
954 if (attr & 4)
955 *d++ = 'X';
956 if (attr & 8)
957 *d++ = 'S';
958 *d++ = 0;
959 sprintf (buf, "-attr %s %s", name, atts);
a33f7359 960 new_directive (xstrdup (buf));
765e60a9 961}
a33f7359 962
765e60a9
SC
963void
964def_code (attr)
965 int attr;
966{
967
6f2d3212 968 def_section ("CODE", attr);
765e60a9
SC
969}
970
971void
972def_data (attr)
973 int attr;
974{
6f2d3212 975 def_section ("DATA", attr);
765e60a9
SC
976}
977
765e60a9
SC
978/**********************************************************************/
979
a33f7359 980static void
2757dc25 981run (what, args)
a33f7359 982 const char *what;
2757dc25
SC
983 char *args;
984{
985 char *s;
c336631b 986 int pid, wait_status;
2757dc25 987 int i;
a33f7359 988 const char **argv;
c336631b
ILT
989 char *errmsg_fmt, *errmsg_arg;
990 char *temp_base = choose_temp_base ();
a33f7359 991
061ed861 992 inform ("run: %s %s\n", what, args);
2757dc25
SC
993
994 /* Count the args */
995 i = 0;
531f86b4 996 for (s = args; *s; s++)
2757dc25
SC
997 if (*s == ' ')
998 i++;
999 i++;
531f86b4 1000 argv = alloca (sizeof (char *) * (i + 3));
2757dc25
SC
1001 i = 0;
1002 argv[i++] = what;
1003 s = args;
531f86b4
SC
1004 while (1)
1005 {
061ed861
NC
1006 while (*s == ' ')
1007 ++s;
531f86b4
SC
1008 argv[i++] = s;
1009 while (*s != ' ' && *s != 0)
1010 s++;
1011 if (*s == 0)
1012 break;
1013 *s++ = 0;
1014 }
a33f7359 1015 argv[i++] = NULL;
2757dc25 1016
c336631b
ILT
1017 pid = pexecute (argv[0], (char * const *) argv, program_name, temp_base,
1018 &errmsg_fmt, &errmsg_arg, PEXECUTE_ONE | PEXECUTE_SEARCH);
356c68ff 1019
c336631b 1020 if (pid == -1)
2757dc25 1021 {
061ed861
NC
1022 inform (strerror (errno));
1023
1024 fatal (errmsg_fmt, errmsg_arg);
2757dc25 1025 }
c336631b 1026
061ed861
NC
1027 pid = pwait (pid, & wait_status, 0);
1028
c336631b 1029 if (pid == -1)
2757dc25 1030 {
061ed861
NC
1031 /* xgettext:c-format */
1032 fatal (_("wait: %s"), strerror (errno));
2757dc25 1033 }
c336631b 1034 else if (WIFSIGNALED (wait_status))
2757dc25 1035 {
061ed861
NC
1036 /* xgettext:c-format */
1037 fatal (_("subprocess got fatal signal %d"), WTERMSIG (wait_status));
c336631b
ILT
1038 }
1039 else if (WIFEXITED (wait_status))
1040 {
1041 if (WEXITSTATUS (wait_status) != 0)
061ed861
NC
1042 /* xgettext:c-format */
1043 warn (_("%s exited with status %d\n"),
1044 what, WEXITSTATUS (wait_status));
2757dc25 1045 }
c336631b
ILT
1046 else
1047 abort ();
2757dc25
SC
1048}
1049
faad4b47
ILT
1050/* Look for a list of symbols to export in the .drectve section of
1051 ABFD. Pass each one to def_exports. */
1052
a33f7359 1053static void
faad4b47 1054scan_drectve_symbols (abfd)
765e60a9
SC
1055 bfd *abfd;
1056{
061ed861
NC
1057 asection * s;
1058 int size;
1059 char * buf;
1060 char * p;
1061 char * e;
1062
199f5217 1063 /* Look for .drectve's */
061ed861
NC
1064 s = bfd_get_section_by_name (abfd, ".drectve");
1065
1066 if (s == NULL)
1067 return;
1068
1069 size = bfd_get_section_size_before_reloc (s);
1070 buf = xmalloc (size);
1071
1072 bfd_get_section_contents (abfd, s, buf, 0, size);
1073
1074 /* xgettext:c-format */
1075 inform (_("Sucking in info from .drective section in %s\n"),
1076 bfd_get_filename (abfd));
1077
1078 /* Search for -export: strings */
1079 p = buf;
1080 e = buf + size;
1081 while (p < e)
1082 {
1083 if (p[0] == '-'
1084 && strncmp (p, "-export:", 8) == 0)
765e60a9 1085 {
061ed861
NC
1086 char * name;
1087 char * c;
1088
1089 p += 8;
1090 name = p;
1091 while (p < e && *p != ' ' && *p != '-')
765e60a9 1092 p++;
061ed861
NC
1093 c = xmalloc (p - name + 1);
1094 memcpy (c, name, p - name);
1095 c[p - name] = 0;
1096 /* FIXME: The 5th arg is for the `constant' field.
1097 What should it be? Not that it matters since it's not
1098 currently useful. */
1099 def_exports (c, 0, -1, 0, 0, 0);
765e60a9 1100 }
061ed861
NC
1101 else
1102 p++;
765e60a9 1103 }
061ed861 1104 free (buf);
faad4b47
ILT
1105}
1106
1107/* Look through the symbols in MINISYMS, and add each one to list of
1108 symbols to export. */
1109
1110static void
1111scan_filtered_symbols (abfd, minisyms, symcount, size)
1112 bfd *abfd;
1113 PTR minisyms;
1114 long symcount;
1115 unsigned int size;
1116{
1117 asymbol *store;
1118 bfd_byte *from, *fromend;
1119
1120 store = bfd_make_empty_symbol (abfd);
1121 if (store == NULL)
1122 bfd_fatal (bfd_get_filename (abfd));
1123
1124 from = (bfd_byte *) minisyms;
1125 fromend = from + symcount * size;
1126 for (; from < fromend; from += size)
1127 {
1128 asymbol *sym;
1129 const char *symbol_name;
1130
1131 sym = bfd_minisymbol_to_symbol (abfd, false, from, store);
1132 if (sym == NULL)
1133 bfd_fatal (bfd_get_filename (abfd));
1134
1135 symbol_name = bfd_asymbol_name (sym);
1136 if (bfd_get_symbol_leading_char (abfd) == symbol_name[0])
1137 ++symbol_name;
1138
1139 def_exports (xstrdup (symbol_name), 0, -1, 0, 0, 0);
1140 }
1141}
1142
1143/* Add a list of symbols to exclude. */
6f2d3212 1144
faad4b47
ILT
1145static void
1146add_excludes (new_excludes)
1147 const char *new_excludes;
1148{
1149 char *local_copy;
1150 char *exclude_string;
1151
1152 local_copy = xstrdup (new_excludes);
1153
1154 exclude_string = strtok (local_copy, ",:");
1155 for (; exclude_string; exclude_string = strtok (NULL, ",:"))
1156 {
1157 struct string_list *new_exclude;
1158
1159 new_exclude = ((struct string_list *)
1160 xmalloc (sizeof (struct string_list)));
1161 new_exclude->string = (char *) xmalloc (strlen (exclude_string) + 2);
1162 /* FIXME: Is it always right to add a leading underscore? */
1163 sprintf (new_exclude->string, "_%s", exclude_string);
1164 new_exclude->next = excludes;
1165 excludes = new_exclude;
1166
1167 /* xgettext:c-format */
1168 inform (_("Excluding symbol: %s\n"), exclude_string);
1169 }
1170
1171 free (local_copy);
1172}
1173
1174/* See if STRING is on the list of symbols to exclude. */
1175
1176static boolean
1177match_exclude (string)
1178 const char *string;
1179{
1180 struct string_list *excl_item;
1181
1182 for (excl_item = excludes; excl_item; excl_item = excl_item->next)
1183 if (strcmp (string, excl_item->string) == 0)
1184 return true;
1185 return false;
1186}
1187
1188/* Add the default list of symbols to exclude. */
1189
1190static void
1191set_default_excludes (void)
1192{
1193 add_excludes (default_excludes);
1194}
1195
1196/* Choose which symbols to export. */
1197
1198static long
1199filter_symbols (abfd, minisyms, symcount, size)
1200 bfd *abfd;
1201 PTR minisyms;
1202 long symcount;
1203 unsigned int size;
1204{
1205 bfd_byte *from, *fromend, *to;
1206 asymbol *store;
1207
1208 store = bfd_make_empty_symbol (abfd);
1209 if (store == NULL)
1210 bfd_fatal (bfd_get_filename (abfd));
1211
1212 from = (bfd_byte *) minisyms;
1213 fromend = from + symcount * size;
1214 to = (bfd_byte *) minisyms;
1215
1216 for (; from < fromend; from += size)
1217 {
1218 int keep = 0;
1219 asymbol *sym;
1220
1221 sym = bfd_minisymbol_to_symbol (abfd, false, (const PTR) from, store);
1222 if (sym == NULL)
1223 bfd_fatal (bfd_get_filename (abfd));
1224
1225 /* Check for external and defined only symbols. */
1226 keep = (((sym->flags & BSF_GLOBAL) != 0
1227 || (sym->flags & BSF_WEAK) != 0
1228 || bfd_is_com_section (sym->section))
1229 && ! bfd_is_und_section (sym->section));
1230
1231 keep = keep && ! match_exclude (sym->name);
1232
1233 if (keep)
1234 {
1235 memcpy (to, from, size);
1236 to += size;
1237 }
1238 }
1239
1240 return (to - (bfd_byte *) minisyms) / size;
1241}
1242
1243/* Export all symbols in ABFD, except for ones we were told not to
1244 export. */
1245
1246static void
1247scan_all_symbols (abfd)
1248 bfd *abfd;
1249{
1250 long symcount;
1251 PTR minisyms;
1252 unsigned int size;
1253
d5556e2a
GN
1254 /* Ignore bfds with an import descriptor table. We assume that any
1255 such BFD contains symbols which are exported from another DLL,
1256 and we don't want to reexport them from here. */
1257 if (bfd_get_section_by_name (abfd, ".idata$4"))
1258 return;
1259
faad4b47
ILT
1260 if (! (bfd_get_file_flags (abfd) & HAS_SYMS))
1261 {
1262 /* xgettext:c-format */
1263 warn (_("%s: no symbols\n"), bfd_get_filename (abfd));
1264 return;
1265 }
1266
1267 symcount = bfd_read_minisymbols (abfd, false, &minisyms, &size);
1268 if (symcount < 0)
1269 bfd_fatal (bfd_get_filename (abfd));
1270
1271 if (symcount == 0)
1272 {
1273 /* xgettext:c-format */
1274 warn (_("%s: no symbols\n"), bfd_get_filename (abfd));
1275 return;
1276 }
1277
1278 /* Discard the symbols we don't want to export. It's OK to do this
1279 in place; we'll free the storage anyway. */
1280
1281 symcount = filter_symbols (abfd, minisyms, symcount, size);
1282 scan_filtered_symbols (abfd, minisyms, symcount, size);
1283
1284 free (minisyms);
1285}
1286
1287/* Look at the object file to decide which symbols to export. */
1288
1289static void
1290scan_open_obj_file (abfd)
1291 bfd *abfd;
1292{
1293 if (export_all_symbols)
1294 scan_all_symbols (abfd);
1295 else
1296 scan_drectve_symbols (abfd);
1297
061ed861 1298 /* FIXME: we ought to read in and block out the base relocations */
6f2d3212 1299
faad4b47
ILT
1300 /* xgettext:c-format */
1301 inform (_("%s: Done reading %s\n"), bfd_get_filename (abfd));
765e60a9
SC
1302}
1303
a33f7359 1304static void
765e60a9 1305scan_obj_file (filename)
a33f7359 1306 const char *filename;
765e60a9 1307{
061ed861 1308 bfd * f = bfd_openr (filename, 0);
765e60a9
SC
1309
1310 if (!f)
061ed861
NC
1311 /* xgettext:c-format */
1312 fatal (_("Unable to open object file: %s"), filename);
1313
1314 /* xgettext:c-format */
1315 inform (_("Scanning object file %s"), filename);
1316
765e60a9
SC
1317 if (bfd_check_format (f, bfd_archive))
1318 {
1319 bfd *arfile = bfd_openr_next_archived_file (f, 0);
1320 while (arfile)
1321 {
1322 if (bfd_check_format (arfile, bfd_object))
1323 scan_open_obj_file (arfile);
1324 bfd_close (arfile);
1325 arfile = bfd_openr_next_archived_file (f, arfile);
1326 }
1327 }
356c68ff 1328 else if (bfd_check_format (f, bfd_object))
765e60a9
SC
1329 {
1330 scan_open_obj_file (f);
1331 }
1332
1333 bfd_close (f);
1334}
1335
1336/**********************************************************************/
1337
a33f7359 1338static void
765e60a9 1339dump_def_info (f)
6f2d3212 1340 FILE *f;
765e60a9
SC
1341{
1342 int i;
1343 export_type *exp;
6f2d3212
SC
1344 fprintf (f, "%s ", ASM_C);
1345 for (i = 0; oav[i]; i++)
1346 fprintf (f, "%s ", oav[i]);
1347 fprintf (f, "\n");
765e60a9
SC
1348 for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
1349 {
c336631b 1350 fprintf (f, "%s %d = %s %s @ %d %s%s%s\n",
765e60a9
SC
1351 ASM_C,
1352 i,
6f2d3212
SC
1353 exp->name,
1354 exp->internal_name,
b990c244 1355 exp->ordinal,
765e60a9 1356 exp->noname ? "NONAME " : "",
c336631b
ILT
1357 exp->constant ? "CONSTANT" : "",
1358 exp->data ? "DATA" : "");
765e60a9
SC
1359 }
1360}
a33f7359 1361
765e60a9
SC
1362/* Generate the .exp file */
1363
a33f7359 1364static int
6f2d3212 1365sfunc (a, b)
a33f7359
ILT
1366 const void *a;
1367 const void *b;
6f2d3212 1368{
a33f7359 1369 return *(const long *) a - *(const long *) b;
6f2d3212
SC
1370}
1371
2757dc25 1372static void
6f2d3212
SC
1373flush_page (f, need, page_addr, on_page)
1374 FILE *f;
a33f7359 1375 long *need;
356c68ff 1376 int page_addr;
6f2d3212
SC
1377 int on_page;
1378{
1379 int i;
f051e1b0 1380
6f2d3212 1381 /* Flush this page */
4828cdba
DE
1382 fprintf (f, "\t%s\t0x%08x\t%s Starting RVA for chunk\n",
1383 ASM_LONG,
ee473c97 1384 page_addr,
6f2d3212
SC
1385 ASM_C);
1386 fprintf (f, "\t%s\t0x%x\t%s Size of block\n",
1387 ASM_LONG,
1388 (on_page * 2) + (on_page & 1) * 2 + 8,
1389 ASM_C);
1390 for (i = 0; i < on_page; i++)
1391 {
a33f7359 1392 fprintf (f, "\t%s\t0x%lx\n", ASM_SHORT, (need[i] - page_addr) | 0x3000);
6f2d3212
SC
1393 }
1394 /* And padding */
1395 if (on_page & 1)
1396 fprintf (f, "\t%s\t0x%x\n", ASM_SHORT, 0 | 0x0000);
6f2d3212
SC
1397}
1398
a33f7359 1399static void
531f86b4
SC
1400gen_def_file ()
1401{
1402 int i;
1403 export_type *exp;
356c68ff 1404
061ed861
NC
1405 inform (_("Adding exports to output file"));
1406
531f86b4
SC
1407 fprintf (output_def, ";");
1408 for (i = 0; oav[i]; i++)
1409 fprintf (output_def, " %s", oav[i]);
1410
1411 fprintf (output_def, "\nEXPORTS\n");
356c68ff 1412
531f86b4
SC
1413 for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
1414 {
356c68ff 1415 char *quote = strchr (exp->name, '.') ? "\"" : "";
faad4b47
ILT
1416 char *res = cplus_demangle (exp->internal_name, DMGL_ANSI | DMGL_PARAMS);
1417
c336631b 1418 fprintf (output_def, "\t%s%s%s @ %d%s%s ; %s\n",
356c68ff 1419 quote,
531f86b4 1420 exp->name,
356c68ff 1421 quote,
531f86b4 1422 exp->ordinal,
356c68ff 1423 exp->noname ? " NONAME" : "",
c336631b 1424 exp->data ? " DATA" : "",
faad4b47
ILT
1425 res ? res : "");
1426 if (res)
1427 free (res);
531f86b4 1428 }
061ed861
NC
1429
1430 inform (_("Added exports to output file"));
531f86b4 1431}
a33f7359 1432
c027e8b0
ILT
1433/* generate_idata_ofile generates the portable assembly source code
1434 for the idata sections. It appends the source code to the end of
1435 the file. */
1436
1437static void
1438generate_idata_ofile (filvar)
1439 FILE *filvar;
1440{
1441 iheadtype *headptr;
1442 ifunctype *funcptr;
1443 int headindex;
1444 int funcindex;
1445 int nheads;
1446
1447 if (import_list == NULL)
1448 return;
1449
1450 fprintf (filvar, "%s Import data sections\n", ASM_C);
1451 fprintf (filvar, "\n\t.section\t.idata$2\n");
1452 fprintf (filvar, "\t%s\tdoi_idata\n", ASM_GLOBAL);
1453 fprintf (filvar, "doi_idata:\n");
1454
1455 nheads = 0;
1456 for (headptr = import_list; headptr != NULL; headptr = headptr->next)
1457 {
1458 fprintf (filvar, "\t%slistone%d%s\t%s %s\n",
1459 ASM_RVA_BEFORE, nheads, ASM_RVA_AFTER,
1460 ASM_C, headptr->dllname);
1461 fprintf (filvar, "\t%s\t0\n", ASM_LONG);
1462 fprintf (filvar, "\t%s\t0\n", ASM_LONG);
1463 fprintf (filvar, "\t%sdllname%d%s\n",
1464 ASM_RVA_BEFORE, nheads, ASM_RVA_AFTER);
1465 fprintf (filvar, "\t%slisttwo%d%s\n\n",
1466 ASM_RVA_BEFORE, nheads, ASM_RVA_AFTER);
1467 nheads++;
1468 }
1469
1470 fprintf (filvar, "\t%s\t0\n", ASM_LONG); /* NULL record at */
1471 fprintf (filvar, "\t%s\t0\n", ASM_LONG); /* end of idata$2 */
1472 fprintf (filvar, "\t%s\t0\n", ASM_LONG); /* section */
1473 fprintf (filvar, "\t%s\t0\n", ASM_LONG);
1474 fprintf (filvar, "\t%s\t0\n", ASM_LONG);
1475
1476 fprintf (filvar, "\n\t.section\t.idata$4\n");
1477 headindex = 0;
1478 for (headptr = import_list; headptr != NULL; headptr = headptr->next)
1479 {
1480 fprintf (filvar, "listone%d:\n", headindex);
1481 for ( funcindex = 0; funcindex < headptr->nfuncs; funcindex++ )
1482 fprintf (filvar, "\t%sfuncptr%d_%d%s\n",
1483 ASM_RVA_BEFORE, headindex, funcindex, ASM_RVA_AFTER);
1484 fprintf (filvar,"\t%s\t0\n", ASM_LONG); /* NULL terminating list */
1485 headindex++;
1486 }
1487
1488 fprintf (filvar, "\n\t.section\t.idata$5\n");
1489 headindex = 0;
1490 for (headptr = import_list; headptr != NULL; headptr = headptr->next)
1491 {
1492 fprintf (filvar, "listtwo%d:\n", headindex);
1493 for ( funcindex = 0; funcindex < headptr->nfuncs; funcindex++ )
1494 fprintf (filvar, "\t%sfuncptr%d_%d%s\n",
1495 ASM_RVA_BEFORE, headindex, funcindex, ASM_RVA_AFTER);
1496 fprintf (filvar, "\t%s\t0\n", ASM_LONG); /* NULL terminating list */
1497 headindex++;
1498 }
1499
1500 fprintf (filvar, "\n\t.section\t.idata$6\n");
1501 headindex = 0;
1502 for (headptr = import_list; headptr != NULL; headptr = headptr->next)
1503 {
1504 funcindex = 0;
1505 for (funcptr = headptr->funchead; funcptr != NULL;
1506 funcptr = funcptr->next)
1507 {
1508 fprintf (filvar,"funcptr%d_%d:\n", headindex, funcindex);
1509 fprintf (filvar,"\t%s\t%d\n", ASM_SHORT,
1510 ((funcptr->ord) & 0xFFFF));
1511 fprintf (filvar,"\t%s\t\"%s\"\n", ASM_TEXT, funcptr->name);
1512 fprintf (filvar,"\t%s\t0\n", ASM_BYTE);
1513 funcindex++;
1514 }
1515 headindex++;
1516 }
1517
1518 fprintf (filvar, "\n\t.section\t.idata$7\n");
1519 headindex = 0;
1520 for (headptr = import_list; headptr != NULL; headptr = headptr->next)
1521 {
1522 fprintf (filvar,"dllname%d:\n", headindex);
1523 fprintf (filvar,"\t%s\t\"%s\"\n", ASM_TEXT, headptr->dllname);
1524 fprintf (filvar,"\t%s\t0\n", ASM_BYTE);
1525 headindex++;
1526 }
1527}
a4e5fd18 1528
a33f7359 1529static void
765e60a9
SC
1530gen_exp_file ()
1531{
1532 FILE *f;
765e60a9
SC
1533 int i;
1534 export_type *exp;
1535 dlist_type *dl;
356c68ff 1536
061ed861
NC
1537 /* xgettext:c-format */
1538 inform (_("Generating export file: %s\n"), exp_name);
1539
1540 f = fopen (TMP_ASM, FOPEN_WT);
765e60a9 1541 if (!f)
061ed861
NC
1542 /* xgettext:c-format */
1543 fatal (_("Unable to open temporary assembler file: %s"), TMP_ASM);
1544
1545 /* xgettext:c-format */
1546 inform (_("Opened temporary file: %s"), TMP_ASM);
6f2d3212 1547
765e60a9 1548 dump_def_info (f);
061ed861 1549
531f86b4
SC
1550 if (d_exports)
1551 {
1552 fprintf (f, "\t.section .edata\n\n");
1553 fprintf (f, "\t%s 0 %s Allways 0\n", ASM_LONG, ASM_C);
a33f7359
ILT
1554 fprintf (f, "\t%s 0x%lx %s Time and date\n", ASM_LONG, (long) time(0),
1555 ASM_C);
531f86b4
SC
1556 fprintf (f, "\t%s 0 %s Major and Minor version\n", ASM_LONG, ASM_C);
1557 fprintf (f, "\t%sname%s %s Ptr to name of dll\n", ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C);
f051e1b0
SC
1558 fprintf (f, "\t%s %d %s Starting ordinal of exports\n", ASM_LONG, d_low_ord, ASM_C);
1559
1560
1561 fprintf (f, "\t%s %d %s Number of functions\n", ASM_LONG, d_high_ord - d_low_ord + 1, ASM_C);
1562 fprintf(f,"\t%s named funcs %d, low ord %d, high ord %d\n",
1563 ASM_C,
1564 d_named_nfuncs, d_low_ord, d_high_ord);
1565 fprintf (f, "\t%s %d %s Number of names\n", ASM_LONG,
1566 show_allnames ? d_high_ord - d_low_ord + 1 : d_named_nfuncs, ASM_C);
531f86b4 1567 fprintf (f, "\t%safuncs%s %s Address of functions\n", ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C);
f051e1b0 1568
c027e8b0 1569 fprintf (f, "\t%sanames%s %s Address of Name Pointer Table\n",
f051e1b0
SC
1570 ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C);
1571
531f86b4
SC
1572 fprintf (f, "\t%sanords%s %s Address of ordinals\n", ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C);
1573
1574 fprintf (f, "name: %s \"%s\"\n", ASM_TEXT, dll_name);
1575
f051e1b0
SC
1576
1577 fprintf(f,"%s Export address Table\n", ASM_C);
1578 fprintf(f,"\t%s\n", ASM_ALIGN_LONG);
531f86b4 1579 fprintf (f, "afuncs:\n");
f051e1b0
SC
1580 i = d_low_ord;
1581
531f86b4
SC
1582 for (exp = d_exports; exp; exp = exp->next)
1583 {
531f86b4
SC
1584 if (exp->ordinal != i)
1585 {
c027e8b0 1586#if 0
f051e1b0
SC
1587 fprintf (f, "\t%s\t%d\t%s %d..%d missing\n",
1588 ASM_SPACE,
531f86b4 1589 (exp->ordinal - i) * 4,
f051e1b0 1590 ASM_C,
531f86b4
SC
1591 i, exp->ordinal - 1);
1592 i = exp->ordinal;
6f2d3212 1593#endif
f051e1b0
SC
1594 while (i < exp->ordinal)
1595 {
1596 fprintf(f,"\t%s\t0\n", ASM_LONG);
1597 i++;
1598 }
1599 }
531f86b4
SC
1600 fprintf (f, "\t%s%s%s%s\t%s %d\n", ASM_RVA_BEFORE,
1601 ASM_PREFIX,
1602 exp->internal_name, ASM_RVA_AFTER, ASM_C, exp->ordinal);
1603 i++;
1604 }
f88ebc68 1605
f051e1b0 1606 fprintf (f,"%s Export Name Pointer Table\n", ASM_C);
531f86b4 1607 fprintf (f, "anames:\n");
f051e1b0 1608
356c68ff 1609 for (i = 0; (exp = d_exports_lexically[i]); i++)
531f86b4 1610 {
f051e1b0 1611 if (!exp->noname || show_allnames)
061ed861
NC
1612 fprintf (f, "\t%sn%d%s\n",
1613 ASM_RVA_BEFORE, exp->ordinal, ASM_RVA_AFTER);
531f86b4 1614 }
f88ebc68 1615
f051e1b0 1616 fprintf (f,"%s Export Oridinal Table\n", ASM_C);
531f86b4 1617 fprintf (f, "anords:\n");
356c68ff 1618 for (i = 0; (exp = d_exports_lexically[i]); i++)
f051e1b0
SC
1619 {
1620 if (!exp->noname || show_allnames)
1621 fprintf (f, "\t%s %d\n", ASM_SHORT, exp->ordinal - d_low_ord);
1622 }
f88ebc68 1623
f051e1b0 1624 fprintf(f,"%s Export Name Table\n", ASM_C);
356c68ff 1625 for (i = 0; (exp = d_exports_lexically[i]); i++)
f051e1b0 1626 if (!exp->noname || show_allnames)
061ed861
NC
1627 fprintf (f, "n%d: %s \"%s\"\n",
1628 exp->ordinal, ASM_TEXT, exp->name);
f88ebc68 1629
531f86b4
SC
1630 if (a_list)
1631 {
1632 fprintf (f, "\t.section .drectve\n");
1633 for (dl = a_list; dl; dl = dl->next)
1634 {
1635 fprintf (f, "\t%s\t\"%s\"\n", ASM_TEXT, dl->text);
1636 }
1637 }
1638 if (d_list)
1639 {
1640 fprintf (f, "\t.section .rdata\n");
1641 for (dl = d_list; dl; dl = dl->next)
1642 {
1643 char *p;
1644 int l;
1645 /* We dont output as ascii 'cause there can
1646 be quote characters in the string */
f88ebc68 1647
531f86b4
SC
1648 l = 0;
1649 for (p = dl->text; *p; p++)
1650 {
1651 if (l == 0)
1652 fprintf (f, "\t%s\t", ASM_BYTE);
1653 else
1654 fprintf (f, ",");
1655 fprintf (f, "%d", *p);
1656 if (p[1] == 0)
1657 {
1658 fprintf (f, ",0\n");
1659 break;
1660 }
1661 if (++l == 10)
1662 {
1663 fprintf (f, "\n");
1664 l = 0;
1665 }
1666 }
1667 }
1668 }
1669 }
199f5217
DE
1670
1671
1672 /* Add to the output file a way of getting to the exported names
1673 without using the import library. */
1674 if (add_indirect)
1675 {
531f86b4 1676 fprintf (f, "\t.section\t.rdata\n");
199f5217 1677 for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
f051e1b0 1678 if (!exp->noname || show_allnames)
531f86b4 1679 {
9d04d618
TT
1680 /* We use a single underscore for MS compatibility, and a
1681 double underscore for backward compatibility with old
1682 cygwin releases. */
531f86b4 1683 fprintf (f, "\t%s\t__imp_%s\n", ASM_GLOBAL, exp->name);
9d04d618 1684 fprintf (f, "\t%s\t_imp__%s\n", ASM_GLOBAL, exp->name);
531f86b4 1685 fprintf (f, "__imp_%s:\n", exp->name);
9d04d618 1686 fprintf (f, "_imp__%s:\n", exp->name);
531f86b4
SC
1687 fprintf (f, "\t%s\t%s\n", ASM_LONG, exp->name);
1688 }
199f5217
DE
1689 }
1690
6f2d3212
SC
1691 /* Dump the reloc section if a base file is provided */
1692 if (base_file)
1693 {
1694 int addr;
1695 long need[PAGE_SIZE];
1696 long page_addr;
1697 int numbytes;
1698 int num_entries;
1699 long *copy;
1700 int j;
1701 int on_page;
531f86b4
SC
1702 fprintf (f, "\t.section\t.init\n");
1703 fprintf (f, "lab:\n");
199f5217 1704
6f2d3212
SC
1705 fseek (base_file, 0, SEEK_END);
1706 numbytes = ftell (base_file);
1707 fseek (base_file, 0, SEEK_SET);
a33f7359 1708 copy = xmalloc (numbytes);
6f2d3212
SC
1709 fread (copy, 1, numbytes, base_file);
1710 num_entries = numbytes / sizeof (long);
1711
6f2d3212 1712
531f86b4
SC
1713 fprintf (f, "\t.section\t.reloc\n");
1714 if (num_entries)
1715 {
f051e1b0 1716 int src;
356c68ff 1717 int dst = 0;
f051e1b0
SC
1718 int last = -1;
1719 qsort (copy, num_entries, sizeof (long), sfunc);
1720 /* Delete duplcates */
1721 for (src = 0; src < num_entries; src++)
1722 {
c027e8b0 1723 if (last != copy[src])
f051e1b0
SC
1724 last = copy[dst++] = copy[src];
1725 }
1726 num_entries = dst;
531f86b4
SC
1727 addr = copy[0];
1728 page_addr = addr & PAGE_MASK; /* work out the page addr */
1729 on_page = 0;
1730 for (j = 0; j < num_entries; j++)
1731 {
1732 addr = copy[j];
1733 if ((addr & PAGE_MASK) != page_addr)
1734 {
1735 flush_page (f, need, page_addr, on_page);
1736 on_page = 0;
1737 page_addr = addr & PAGE_MASK;
1738 }
1739 need[on_page++] = addr;
1740 }
1741 flush_page (f, need, page_addr, on_page);
1742
356c68ff 1743/* fprintf (f, "\t%s\t0,0\t%s End\n", ASM_LONG, ASM_C);*/
531f86b4 1744 }
765e60a9 1745 }
6f2d3212 1746
c027e8b0 1747 generate_idata_ofile (f);
a4e5fd18 1748
765e60a9 1749 fclose (f);
2757dc25
SC
1750
1751 /* assemble the file */
061ed861
NC
1752 sprintf (outfile, "%s -o %s %s", as_flags, exp_name, TMP_ASM);
1753
1754#ifdef DLLTOOL_ARM
1755 if (interwork)
1756 strcat (outfile, " -mthumb-interwork");
1757#endif
1758
2757dc25 1759 run (as_name, outfile);
061ed861 1760
531f86b4 1761 if (dontdeltemps == 0)
061ed861
NC
1762 unlink (TMP_ASM);
1763
1764 inform (_("Generated exports file"));
765e60a9
SC
1765}
1766
a33f7359
ILT
1767static const char *
1768xlate (name)
1769 const char *name;
6f2d3212 1770{
531f86b4
SC
1771 if (add_underscore)
1772 {
a33f7359 1773 char *copy = xmalloc (strlen (name) + 2);
531f86b4
SC
1774 copy[0] = '_';
1775 strcpy (copy + 1, name);
1776 name = copy;
1777 }
00289839 1778
2757dc25
SC
1779 if (killat)
1780 {
1781 char *p;
1782 p = strchr (name, '@');
1783 if (p)
1784 *p = 0;
1785 }
6f2d3212
SC
1786 return name;
1787}
1788
765e60a9 1789/**********************************************************************/
f051e1b0 1790
faad4b47
ILT
1791#if 0
1792
a33f7359
ILT
1793static void
1794dump_iat (f, exp)
1795 FILE *f;
1796 export_type *exp;
f051e1b0 1797{
c027e8b0 1798 if (exp->noname && !show_allnames )
f051e1b0
SC
1799 {
1800 fprintf (f, "\t%s\t0x%08x\n",
1801 ASM_LONG,
1802 exp->ordinal | 0x80000000); /* hint or orindal ?? */
1803 }
1804 else
1805 {
1806 fprintf (f, "\t%sID%d%s\n", ASM_RVA_BEFORE,
1807 exp->ordinal,
1808 ASM_RVA_AFTER);
1809 }
1810}
765e60a9 1811
faad4b47
ILT
1812#endif
1813
c027e8b0 1814typedef struct
356c68ff
SC
1815{
1816 int id;
1817 const char *name;
1818 int flags;
b10f8e5e 1819 int align;
356c68ff
SC
1820 asection *sec;
1821 asymbol *sym;
1822 asymbol **sympp;
1823 int size;
1824 unsigned char *data;
1825} sinfo;
1826
b10f8e5e
KK
1827#ifndef DLLTOOL_PPC
1828
356c68ff
SC
1829#define TEXT 0
1830#define DATA 1
1831#define BSS 2
1832#define IDATA7 3
1833#define IDATA5 4
1834#define IDATA4 5
1835#define IDATA6 6
b10f8e5e 1836
356c68ff
SC
1837#define NSECS 7
1838
c027e8b0 1839static sinfo secdata[NSECS] =
356c68ff 1840{
a33f7359 1841 { TEXT, ".text", SEC_CODE | SEC_HAS_CONTENTS, 2},
b10f8e5e
KK
1842 { DATA, ".data", SEC_DATA, 2},
1843 { BSS, ".bss", 0, 2},
1844 { IDATA7, ".idata$7", SEC_HAS_CONTENTS, 2},
1845 { IDATA5, ".idata$5", SEC_HAS_CONTENTS, 2},
1846 { IDATA4, ".idata$4", SEC_HAS_CONTENTS, 2},
1847 { IDATA6, ".idata$6", SEC_HAS_CONTENTS, 1}
1848};
1849
c027e8b0 1850#else
b10f8e5e
KK
1851
1852/* Sections numbered to make the order the same as other PowerPC NT */
1853/* compilers. This also keeps funny alignment thingies from happening. */
1854#define TEXT 0
1855#define PDATA 1
1856#define RDATA 2
1857#define IDATA5 3
1858#define IDATA4 4
1859#define IDATA6 5
1860#define IDATA7 6
1861#define DATA 7
1862#define BSS 8
2757dc25 1863
b10f8e5e 1864#define NSECS 9
6f2d3212 1865
c027e8b0 1866static sinfo secdata[NSECS] =
b10f8e5e
KK
1867{
1868 { TEXT, ".text", SEC_CODE | SEC_HAS_CONTENTS, 3},
1869 { PDATA, ".pdata", SEC_HAS_CONTENTS, 2},
a33f7359 1870 { RDATA, ".reldata", SEC_HAS_CONTENTS, 2},
b10f8e5e
KK
1871 { IDATA5, ".idata$5", SEC_HAS_CONTENTS, 2},
1872 { IDATA4, ".idata$4", SEC_HAS_CONTENTS, 2},
1873 { IDATA6, ".idata$6", SEC_HAS_CONTENTS, 1},
1874 { IDATA7, ".idata$7", SEC_HAS_CONTENTS, 2},
1875 { DATA, ".data", SEC_DATA, 2},
1876 { BSS, ".bss", 0, 2}
356c68ff 1877};
b10f8e5e
KK
1878
1879#endif
1880
356c68ff 1881/*
9d04d618
TT
1882This is what we're trying to make. We generate the imp symbols with
1883both single and double underscores, for compatibility.
356c68ff
SC
1884
1885 .text
1886 .global _GetFileVersionInfoSizeW@8
1887 .global __imp_GetFileVersionInfoSizeW@8
1888_GetFileVersionInfoSizeW@8:
1889 jmp * __imp_GetFileVersionInfoSizeW@8
1890 .section .idata$7 # To force loading of head
1891 .long __version_a_head
1892# Import Address Table
1893 .section .idata$5
1894__imp_GetFileVersionInfoSizeW@8:
1895 .rva ID2
1896
1897# Import Lookup Table
1898 .section .idata$4
1899 .rva ID2
1900# Hint/Name table
1901 .section .idata$6
1902ID2: .short 2
1903 .asciz "GetFileVersionInfoSizeW"
1904
b10f8e5e
KK
1905
1906For the PowerPC, here's the variation on the above scheme:
1907
c027e8b0 1908# Rather than a simple "jmp *", the code to get to the dll function
b10f8e5e
KK
1909# looks like:
1910 .text
1911 lwz r11,[tocv]__imp_function_name(r2)
1912# RELOC: 00000000 TOCREL16,TOCDEFN __imp_function_name
1913 lwz r12,0(r11)
1914 stw r2,4(r1)
1915 mtctr r12
1916 lwz r2,4(r11)
1917 bctr
356c68ff
SC
1918*/
1919
b10f8e5e
KK
1920static char *
1921make_label (prefix, name)
1922 const char *prefix;
1923 const char *name;
356c68ff
SC
1924{
1925 int len = strlen (ASM_PREFIX) + strlen (prefix) + strlen (name);
1926 char *copy = xmalloc (len +1 );
1927 strcpy (copy, ASM_PREFIX);
1928 strcat (copy, prefix);
1929 strcat (copy, name);
1930 return copy;
1931}
b10f8e5e 1932
356c68ff
SC
1933static bfd *
1934make_one_lib_file (exp, i)
b10f8e5e
KK
1935 export_type *exp;
1936 int i;
356c68ff 1937{
061ed861 1938#if 0
765e60a9 1939 {
356c68ff
SC
1940 FILE *f;
1941 char *prefix="d";
2757dc25 1942 sprintf (outfile, "%ss%d.s", prefix, i);
20dec772 1943 f = fopen (outfile, FOPEN_WT);
2757dc25 1944 fprintf (f, "\t.text\n");
199f5217 1945 fprintf (f, "\t%s\t%s%s\n", ASM_GLOBAL, ASM_PREFIX, exp->name);
f88ebc68 1946 fprintf (f, "\t%s\t__imp_%s\n", ASM_GLOBAL, exp->name);
9d04d618 1947 fprintf (f, "\t%s\t_imp__%s\n", ASM_GLOBAL, exp->name);
199f5217
DE
1948 fprintf (f, "%s%s:\n\t%s\t__imp_%s\n", ASM_PREFIX,
1949 exp->name, ASM_JUMP, exp->name);
2757dc25 1950
f88ebc68 1951 fprintf (f, "\t.section\t.idata$7\t%s To force loading of head\n", ASM_C);
356c68ff 1952 fprintf (f, "\t%s\t%s\n", ASM_LONG, head_label);
2757dc25
SC
1953
1954
f051e1b0
SC
1955 fprintf (f,"%s Import Address Table\n", ASM_C);
1956
1957 fprintf (f, "\t.section .idata$5\n");
6f2d3212 1958 fprintf (f, "__imp_%s:\n", exp->name);
9d04d618 1959 fprintf (f, "_imp__%s:\n", exp->name);
2757dc25 1960
f051e1b0
SC
1961 dump_iat (f, exp);
1962
1963 fprintf (f, "\n%s Import Lookup Table\n", ASM_C);
2757dc25 1964 fprintf (f, "\t.section .idata$4\n");
2757dc25 1965
f051e1b0
SC
1966 dump_iat (f, exp);
1967
c027e8b0 1968 if(!exp->noname || show_allnames)
f051e1b0
SC
1969 {
1970 fprintf (f, "%s Hint/Name table\n", ASM_C);
1971 fprintf (f, "\t.section .idata$6\n");
c027e8b0 1972 fprintf (f, "ID%d:\t%s\t%d\n", exp->ordinal, ASM_SHORT, exp->hint);
f051e1b0
SC
1973 fprintf (f, "\t%s\t\"%s\"\n", ASM_TEXT, xlate (exp->name));
1974 }
2757dc25 1975
2757dc25
SC
1976 fclose (f);
1977
061ed861
NC
1978 sprintf (outfile, "%s -o %ss%d.o %ss%d.s",
1979 as_flags, prefix, i, prefix, i);
2757dc25 1980
061ed861
NC
1981#ifdef DLLTOOL_ARM
1982 if (interwork)
1983 strcat (outfile, " -mthumb-interwork");
1984#endif
1985
2757dc25 1986 run (as_name, outfile);
765e60a9 1987 }
061ed861 1988#else /* if 0 */
356c68ff 1989 {
061ed861
NC
1990 bfd * abfd;
1991 asymbol * exp_label;
1992 asymbol * iname;
1993 asymbol * iname2;
1994 asymbol * iname_lab;
1995 asymbol ** iname_lab_pp;
1996 asymbol ** iname_pp;
b10f8e5e 1997#ifdef DLLTOOL_PPC
061ed861
NC
1998 asymbol ** fn_pp;
1999 asymbol ** toc_pp;
2000#define EXTRA 2
b10f8e5e 2001#endif
061ed861
NC
2002#ifndef EXTRA
2003#define EXTRA 0
a33f7359 2004#endif
061ed861 2005 asymbol * ptrs[NSECS + 4 + EXTRA + 1];
b10f8e5e 2006
061ed861
NC
2007 char * outname = xmalloc (10);
2008 int oidx = 0;
356c68ff 2009
061ed861
NC
2010
2011 sprintf (outname, "%s%d.o", TMP_STUB, i);
2012
356c68ff 2013 abfd = bfd_openw (outname, HOW_BFD_TARGET);
061ed861 2014
356c68ff 2015 if (!abfd)
061ed861
NC
2016 /* xgettext:c-format */
2017 fatal (_("bfd_open failed open stub file: %s"), outname);
356c68ff 2018
061ed861
NC
2019 /* xgettext:c-format */
2020 inform (_("Creating stub file: %s"), outname);
2021
356c68ff
SC
2022 bfd_set_format (abfd, bfd_object);
2023 bfd_set_arch_mach (abfd, HOW_BFD_ARCH, 0);
2024
061ed861
NC
2025#ifdef DLLTOOL_ARM
2026 if (interwork)
2027 bfd_set_private_flags (abfd, F_INTERWORK);
2028#endif
2029
b10f8e5e 2030 /* First make symbols for the sections */
356c68ff
SC
2031 for (i = 0; i < NSECS; i++)
2032 {
2033 sinfo *si = secdata + i;
2034 if (si->id != i)
2035 abort();
2036 si->sec = bfd_make_section_old_way (abfd, si->name);
c027e8b0 2037 bfd_set_section_flags (abfd,
356c68ff
SC
2038 si->sec,
2039 si->flags);
c027e8b0 2040
b10f8e5e 2041 bfd_set_section_alignment(abfd, si->sec, si->align);
356c68ff 2042 si->sec->output_section = si->sec;
b10f8e5e 2043 si->sym = bfd_make_empty_symbol(abfd);
356c68ff
SC
2044 si->sym->name = si->sec->name;
2045 si->sym->section = si->sec;
2046 si->sym->flags = BSF_LOCAL;
2047 si->sym->value = 0;
2048 ptrs[oidx] = si->sym;
2049 si->sympp = ptrs + oidx;
c336631b
ILT
2050 si->size = 0;
2051 si->data = NULL;
356c68ff
SC
2052
2053 oidx++;
2054 }
2055
c336631b
ILT
2056 if (! exp->data)
2057 {
2058 exp_label = bfd_make_empty_symbol (abfd);
2059 exp_label->name = make_label ("", exp->name);
b10f8e5e 2060
c336631b
ILT
2061 /* On PowerPC, the function name points to a descriptor in
2062 the rdata section, the first element of which is a
2063 pointer to the code (..function_name), and the second
2064 points to the .toc */
a33f7359 2065#ifdef DLLTOOL_PPC
c336631b
ILT
2066 if (machine == MPPC)
2067 exp_label->section = secdata[RDATA].sec;
2068 else
a33f7359 2069#endif
c336631b 2070 exp_label->section = secdata[TEXT].sec;
b10f8e5e 2071
c336631b
ILT
2072 exp_label->flags = BSF_GLOBAL;
2073 exp_label->value = 0;
356c68ff 2074
061ed861
NC
2075#ifdef DLLTOOL_ARM
2076 if (machine == MTHUMB)
2077 bfd_coff_set_symbol_class (abfd, exp_label, C_THUMBEXT);
2078#endif
c336631b
ILT
2079 ptrs[oidx++] = exp_label;
2080 }
356c68ff 2081
9d04d618
TT
2082 /* Generate imp symbols with one underscore for Microsoft
2083 compatibility, and with two underscores for backward
2084 compatibility with old versions of cygwin. */
356c68ff 2085 iname = bfd_make_empty_symbol(abfd);
356c68ff 2086 iname->name = make_label ("__imp_", exp->name);
356c68ff
SC
2087 iname->section = secdata[IDATA5].sec;
2088 iname->flags = BSF_GLOBAL;
2089 iname->value = 0;
2090
9d04d618
TT
2091 iname2 = bfd_make_empty_symbol(abfd);
2092 iname2->name = make_label ("_imp__", exp->name);
2093 iname2->section = secdata[IDATA5].sec;
2094 iname2->flags = BSF_GLOBAL;
2095 iname2->value = 0;
356c68ff
SC
2096
2097 iname_lab = bfd_make_empty_symbol(abfd);
2098
2099 iname_lab->name = head_label;
2100 iname_lab->section = (asection *)&bfd_und_section;
2101 iname_lab->flags = 0;
2102 iname_lab->value = 0;
2103
2104
b10f8e5e 2105 iname_pp = ptrs + oidx;
356c68ff 2106 ptrs[oidx++] = iname;
9d04d618 2107 ptrs[oidx++] = iname2;
b10f8e5e 2108
356c68ff
SC
2109 iname_lab_pp = ptrs + oidx;
2110 ptrs[oidx++] = iname_lab;
b10f8e5e
KK
2111
2112#ifdef DLLTOOL_PPC
2113 /* The symbol refering to the code (.text) */
a33f7359
ILT
2114 {
2115 asymbol *function_name;
b10f8e5e 2116
a33f7359
ILT
2117 function_name = bfd_make_empty_symbol(abfd);
2118 function_name->name = make_label ("..", exp->name);
2119 function_name->section = secdata[TEXT].sec;
2120 function_name->flags = BSF_GLOBAL;
2121 function_name->value = 0;
2122
2123 fn_pp = ptrs + oidx;
2124 ptrs[oidx++] = function_name;
2125 }
b10f8e5e
KK
2126
2127 /* The .toc symbol */
a33f7359
ILT
2128 {
2129 asymbol *toc_symbol; /* The .toc symbol */
2130
061ed861 2131 toc_symbol = bfd_make_empty_symbol (abfd);
a33f7359
ILT
2132 toc_symbol->name = make_label (".", "toc");
2133 toc_symbol->section = (asection *)&bfd_und_section;
2134 toc_symbol->flags = BSF_GLOBAL;
2135 toc_symbol->value = 0;
2136
2137 toc_pp = ptrs + oidx;
2138 ptrs[oidx++] = toc_symbol;
2139 }
b10f8e5e 2140#endif
061ed861 2141
356c68ff
SC
2142 ptrs[oidx] = 0;
2143
2144 for (i = 0; i < NSECS; i++)
2145 {
2146 sinfo *si = secdata + i;
2147 asection *sec = si->sec;
2148 arelent *rel;
2149 arelent **rpp;
2150
c027e8b0 2151 switch (i)
356c68ff
SC
2152 {
2153 case TEXT:
c336631b
ILT
2154 if (! exp->data)
2155 {
2156 si->size = HOW_JTAB_SIZE;
2157 si->data = xmalloc (HOW_JTAB_SIZE);
2158 memcpy (si->data, HOW_JTAB, HOW_JTAB_SIZE);
c027e8b0 2159
061ed861 2160 /* add the reloc into idata$5 */
c336631b 2161 rel = xmalloc (sizeof (arelent));
061ed861 2162
c336631b
ILT
2163 rpp = xmalloc (sizeof (arelent *) * 2);
2164 rpp[0] = rel;
2165 rpp[1] = 0;
061ed861 2166
c336631b
ILT
2167 rel->address = HOW_JTAB_ROFF;
2168 rel->addend = 0;
b10f8e5e 2169
c336631b
ILT
2170 if (machine == MPPC)
2171 {
c027e8b0 2172 rel->howto = bfd_reloc_type_lookup (abfd,
c336631b
ILT
2173 BFD_RELOC_16_GOTOFF);
2174 rel->sym_ptr_ptr = iname_pp;
2175 }
2176 else
2177 {
2178 rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_32);
2179 rel->sym_ptr_ptr = secdata[IDATA5].sympp;
2180 }
2181 sec->orelocation = rpp;
2182 sec->reloc_count = 1;
b10f8e5e 2183 }
356c68ff
SC
2184 break;
2185 case IDATA4:
2186 case IDATA5:
2187 /* An idata$4 or idata$5 is one word long, and has an
2188 rva to idata$6 */
c027e8b0 2189
356c68ff
SC
2190 si->data = xmalloc (4);
2191 si->size = 4;
2192
2193 if (exp->noname)
2194 {
2195 si->data[0] = exp->ordinal ;
2196 si->data[1] = exp->ordinal >> 8;
2197 si->data[2] = exp->ordinal >> 16;
2198 si->data[3] = 0x80;
2199 }
c027e8b0 2200 else
356c68ff
SC
2201 {
2202 sec->reloc_count = 1;
2203 memset (si->data, 0, si->size);
2204 rel = xmalloc (sizeof (arelent));
2205 rpp = xmalloc (sizeof (arelent *) * 2);
2206 rpp[0] = rel;
2207 rpp[1] = 0;
2208 rel->address = 0;
2209 rel->addend = 0;
2210 rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_RVA);
2211 rel->sym_ptr_ptr = secdata[IDATA6].sympp;
2212 sec->orelocation = rpp;
2213 }
2214
2215 break;
2216
2217 case IDATA6:
c027e8b0 2218 if (!exp->noname)
356c68ff 2219 {
9d04d618
TT
2220 /* This used to add 1 to exp->hint. I don't know
2221 why it did that, and it does not match what I see
2222 in programs compiled with the MS tools. */
2223 int idx = exp->hint;
356c68ff
SC
2224 si->size = strlen (xlate (exp->name)) + 3;
2225 si->data = xmalloc (si->size);
2226 si->data[0] = idx & 0xff;
2227 si->data[1] = idx >> 8;
2228 strcpy (si->data + 2, xlate (exp->name));
2229 }
2230 break;
2231 case IDATA7:
2232 si->size = 4;
2233 si->data =xmalloc(4);
2234 memset (si->data, 0, si->size);
2235 rel = xmalloc (sizeof (arelent));
2236 rpp = xmalloc (sizeof (arelent *) * 2);
2237 rpp[0] = rel;
2238 rel->address = 0;
2239 rel->addend = 0;
a33f7359 2240 rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_RVA);
356c68ff
SC
2241 rel->sym_ptr_ptr = iname_lab_pp;
2242 sec->orelocation = rpp;
2243 sec->reloc_count = 1;
2244 break;
b10f8e5e 2245
a33f7359 2246#ifdef DLLTOOL_PPC
b10f8e5e
KK
2247 case PDATA:
2248 {
2249 /* The .pdata section is 5 words long. */
2250 /* Think of it as: */
2251 /* struct */
2252 /* { */
2253 /* bfd_vma BeginAddress, [0x00] */
2254 /* EndAddress, [0x04] */
2255 /* ExceptionHandler, [0x08] */
2256 /* HandlerData, [0x0c] */
2257 /* PrologEndAddress; [0x10] */
2258 /* }; */
2259
2260 /* So this pdata section setups up this as a glue linkage to
2261 a dll routine. There are a number of house keeping things
2262 we need to do:
2263
c027e8b0
ILT
2264 1. In the name of glue trickery, the ADDR32 relocs for 0,
2265 4, and 0x10 are set to point to the same place:
2266 "..function_name".
2267 2. There is one more reloc needed in the pdata section.
2268 The actual glue instruction to restore the toc on
b10f8e5e
KK
2269 return is saved as the offset in an IMGLUE reloc.
2270 So we need a total of four relocs for this section.
2271
2272 3. Lastly, the HandlerData field is set to 0x03, to indicate
2273 that this is a glue routine.
2274 */
2275 arelent *imglue, *ba_rel, *ea_rel, *pea_rel;
2276
2277 /* alignment must be set to 2**2 or you get extra stuff */
2278 bfd_set_section_alignment(abfd, sec, 2);
2279
2280 si->size = 4 * 5;
2281 si->data =xmalloc(4 * 5);
2282 memset (si->data, 0, si->size);
2283 rpp = xmalloc (sizeof (arelent *) * 5);
2284 rpp[0] = imglue = xmalloc (sizeof (arelent));
2285 rpp[1] = ba_rel = xmalloc (sizeof (arelent));
2286 rpp[2] = ea_rel = xmalloc (sizeof (arelent));
2287 rpp[3] = pea_rel = xmalloc (sizeof (arelent));
2288 rpp[4] = 0;
2289
2290 /* stick the toc reload instruction in the glue reloc */
2291 bfd_put_32(abfd, ppc_glue_insn, (char *) &imglue->address);
2292
2293 imglue->addend = 0;
c027e8b0 2294 imglue->howto = bfd_reloc_type_lookup (abfd,
b10f8e5e
KK
2295 BFD_RELOC_32_GOTOFF);
2296 imglue->sym_ptr_ptr = fn_pp;
2297
2298 ba_rel->address = 0;
2299 ba_rel->addend = 0;
2300 ba_rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_32);
2301 ba_rel->sym_ptr_ptr = fn_pp;
2302
2303 bfd_put_32(abfd, 0x18, si->data + 0x04);
2304 ea_rel->address = 4;
2305 ea_rel->addend = 0;
2306 ea_rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_32);
2307 ea_rel->sym_ptr_ptr = fn_pp;
2308
2309 /* mark it as glue */
2310 bfd_put_32(abfd, 0x03, si->data + 0x0c);
2311
2312 /* mark the prolog end address */
2313 bfd_put_32(abfd, 0x0D, si->data + 0x10);
2314 pea_rel->address = 0x10;
2315 pea_rel->addend = 0;
2316 pea_rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_32);
2317 pea_rel->sym_ptr_ptr = fn_pp;
2318
2319 sec->orelocation = rpp;
2320 sec->reloc_count = 4;
2321 break;
2322 }
2323 case RDATA:
2324 /* Each external function in a PowerPC PE file has a two word
2325 descriptor consisting of:
2326 1. The address of the code.
2327 2. The address of the appropriate .toc
2328 We use relocs to build this.
2329 */
2330
2331 si->size = 8;
a33f7359 2332 si->data = xmalloc (8);
b10f8e5e
KK
2333 memset (si->data, 0, si->size);
2334
2335 rpp = xmalloc (sizeof (arelent *) * 3);
2336 rpp[0] = rel = xmalloc (sizeof (arelent));
2337 rpp[1] = xmalloc (sizeof (arelent));
2338 rpp[2] = 0;
2339
2340 rel->address = 0;
2341 rel->addend = 0;
2342 rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_32);
2343 rel->sym_ptr_ptr = fn_pp;
2344
2345 rel = rpp[1];
2346
2347 rel->address = 4;
2348 rel->addend = 0;
2349 rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_32);
2350 rel->sym_ptr_ptr = toc_pp;
2351
2352 sec->orelocation = rpp;
2353 sec->reloc_count = 2;
2354 break;
a33f7359 2355#endif /* DLLTOOL_PPC */
356c68ff
SC
2356 }
2357 }
2358
2359 {
2360 bfd_vma vma = 0;
2361 /* Size up all the sections */
2362 for (i = 0; i < NSECS; i++)
2363 {
2364 sinfo *si = secdata + i;
b10f8e5e 2365
356c68ff
SC
2366 bfd_set_section_size (abfd, si->sec, si->size);
2367 bfd_set_section_vma (abfd, si->sec, vma);
b10f8e5e 2368
356c68ff
SC
2369/* vma += si->size;*/
2370 }
2371 }
2372 /* Write them out */
2373 for (i = 0; i < NSECS; i++)
2374 {
2375 sinfo *si = secdata + i;
b10f8e5e 2376
356c68ff
SC
2377 if (i == IDATA5 && no_idata5)
2378 continue;
2379
2380 if (i == IDATA4 && no_idata4)
2381 continue;
2382
c027e8b0 2383 bfd_set_section_contents (abfd, si->sec,
356c68ff
SC
2384 si->data, 0,
2385 si->size);
2386 }
2387
2388 bfd_set_symtab (abfd, ptrs, oidx);
2389 bfd_close (abfd);
2390 abfd = bfd_openr (outname, HOW_BFD_TARGET);
2391 return abfd;
2392 }
061ed861 2393#endif
356c68ff
SC
2394}
2395
b10f8e5e 2396static bfd *
a33f7359 2397make_head ()
356c68ff 2398{
061ed861 2399 FILE * f = fopen (TMP_HEAD_S, FOPEN_WT);
356c68ff
SC
2400
2401 fprintf (f, "%s IMAGE_IMPORT_DESCRIPTOR\n", ASM_C);
2402 fprintf (f, "\t.section .idata$2\n");
2403
2404 fprintf(f,"\t%s\t%s\n", ASM_GLOBAL,head_label);
2405
2406 fprintf (f, "%s:\n", head_label);
2407
2408 fprintf (f, "\t%shname%s\t%sPtr to image import by name list\n",
2409 ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C);
2410
2411 fprintf (f, "\t%sthis should be the timestamp, but NT sometimes\n", ASM_C);
2412 fprintf (f, "\t%sdoesn't load DLLs when this is set.\n", ASM_C);
2413 fprintf (f, "\t%s\t0\t%s loaded time\n", ASM_LONG, ASM_C);
2414 fprintf (f, "\t%s\t0\t%s Forwarder chain\n", ASM_LONG, ASM_C);
2415 fprintf (f, "\t%s__%s_iname%s\t%s imported dll's name\n",
2416 ASM_RVA_BEFORE,
2417 imp_name_lab,
2418 ASM_RVA_AFTER,
2419 ASM_C);
2420 fprintf (f, "\t%sfthunk%s\t%s pointer to firstthunk\n",
2421 ASM_RVA_BEFORE,
2422 ASM_RVA_AFTER, ASM_C);
2423
2424 fprintf (f, "%sStuff for compatibility\n", ASM_C);
2425
c027e8b0 2426 if (!no_idata5)
356c68ff
SC
2427 {
2428 fprintf (f, "\t.section\t.idata$5\n");
2429 fprintf (f, "\t%s\t0\n", ASM_LONG);
2430 fprintf (f, "fthunk:\n");
2431 }
c027e8b0 2432 if (!no_idata4)
356c68ff
SC
2433 {
2434 fprintf (f, "\t.section\t.idata$4\n");
2435
2436 fprintf (f, "\t%s\t0\n", ASM_LONG);
2437 fprintf (f, "\t.section .idata$4\n");
2438 fprintf (f, "hname:\n");
2439 }
2440 fclose (f);
2441
061ed861
NC
2442 sprintf (outfile, "%s -o %s %s", as_flags, TMP_HEAD_O, TMP_HEAD_S);
2443
2444#ifdef DLLTOOL_ARM
2445 if (interwork)
2446 strcat (outfile, " -mthumb-interwork");
2447#endif
2448
356c68ff
SC
2449 run (as_name, outfile);
2450
061ed861 2451 return bfd_openr (TMP_HEAD_O, HOW_BFD_TARGET);
356c68ff
SC
2452}
2453
c027e8b0 2454static bfd *
a33f7359 2455make_tail ()
356c68ff 2456{
061ed861 2457 FILE * f = fopen (TMP_TAIL_S, FOPEN_WT);
b10f8e5e 2458
c027e8b0 2459 if (!no_idata4)
356c68ff
SC
2460 {
2461 fprintf (f, "\t.section .idata$4\n");
2462 fprintf (f, "\t%s\t0\n", ASM_LONG);
2463 }
c027e8b0 2464 if (!no_idata5)
356c68ff
SC
2465 {
2466 fprintf (f, "\t.section .idata$5\n");
2467 fprintf (f, "\t%s\t0\n", ASM_LONG);
2468 }
b10f8e5e 2469
b10f8e5e
KK
2470#ifdef DLLTOOL_PPC
2471 /* Normally, we need to see a null descriptor built in idata$3 to
2472 act as the terminator for the list. The ideal way, I suppose,
2473 would be to mark this section as a comdat type 2 section, so
2474 only one would appear in the final .exe (if our linker supported
2475 comdat, that is) or cause it to be inserted by something else (say
2476 crt0)
2477 */
2478
2479 fprintf (f, "\t.section .idata$3\n");
2480 fprintf (f, "\t%s\t0\n", ASM_LONG);
2481 fprintf (f, "\t%s\t0\n", ASM_LONG);
2482 fprintf (f, "\t%s\t0\n", ASM_LONG);
2483 fprintf (f, "\t%s\t0\n", ASM_LONG);
2484 fprintf (f, "\t%s\t0\n", ASM_LONG);
2485#endif
2486
a33f7359
ILT
2487#ifdef DLLTOOL_PPC
2488 /* Other PowerPC NT compilers use idata$6 for the dllname, so I
2489 do too. Original, huh? */
2490 fprintf (f, "\t.section .idata$6\n");
2491#else
2492 fprintf (f, "\t.section .idata$7\n");
2493#endif
2494
2495 fprintf (f, "\t%s\t__%s_iname\n", ASM_GLOBAL, imp_name_lab);
2496 fprintf (f, "__%s_iname:\t%s\t\"%s\"\n",
2497 imp_name_lab, ASM_TEXT, dll_name);
2498
2757dc25
SC
2499 fclose (f);
2500
061ed861
NC
2501 sprintf (outfile, "%s -o %s %s", as_flags, TMP_TAIL_O, TMP_TAIL_S);
2502
2503#ifdef DLLTOOL_ARM
2504 if (interwork)
2505 strcat (outfile, " -mthumb-interwork");
2506#endif
2507
2757dc25 2508 run (as_name, outfile);
061ed861
NC
2509
2510 return bfd_openr (TMP_TAIL_O, HOW_BFD_TARGET);
356c68ff 2511}
2757dc25 2512
356c68ff
SC
2513static void
2514gen_lib_file ()
2515{
2516 int i;
2517 export_type *exp;
2518 bfd *ar_head;
2519 bfd *ar_tail;
2520 bfd *outarch;
2521 bfd * head = 0;
2757dc25 2522
356c68ff 2523 unlink (imp_name);
2757dc25 2524
356c68ff 2525 outarch = bfd_openw (imp_name, HOW_BFD_TARGET);
2757dc25 2526
356c68ff 2527 if (!outarch)
061ed861
NC
2528 /* xgettext:c-format */
2529 fatal (_("Can't open .lib file: %s"), imp_name);
2530
2531 /* xgettext:c-format */
2532 inform (_("Creating library file: %s\n"), imp_name);
2533
356c68ff
SC
2534 bfd_set_format (outarch, bfd_archive);
2535 outarch->has_armap = 1;
2536
2537 /* Work out a reasonable size of things to put onto one line. */
2757dc25 2538
356c68ff
SC
2539 ar_head = make_head ();
2540 ar_tail = make_tail();
2541
061ed861
NC
2542 if (ar_head == NULL || ar_tail == NULL)
2543 return;
2544
356c68ff
SC
2545 for (i = 0; (exp = d_exports_lexically[i]); i++)
2546 {
2547 bfd *n = make_one_lib_file (exp, i);
2548 n->next = head;
2549 head = n;
765e60a9 2550 }
356c68ff 2551
356c68ff
SC
2552 /* Now stick them all into the archive */
2553
2554 ar_head->next = head;
2555 ar_tail->next = ar_head;
2556 head = ar_tail;
2557
c336631b
ILT
2558 if (! bfd_set_archive_head (outarch, head))
2559 bfd_fatal ("bfd_set_archive_head");
061ed861 2560
c336631b
ILT
2561 if (! bfd_close (outarch))
2562 bfd_fatal (imp_name);
2563
2564 while (head != NULL)
2565 {
2566 bfd *n = head->next;
2567 bfd_close (head);
2568 head = n;
2569 }
765e60a9 2570
2757dc25 2571 /* Delete all the temp files */
765e60a9 2572
f88ebc68 2573 if (dontdeltemps == 0)
2757dc25 2574 {
061ed861
NC
2575 unlink (TMP_HEAD_O);
2576 unlink (TMP_HEAD_S);
2577 unlink (TMP_TAIL_O);
2578 unlink (TMP_TAIL_S);
2757dc25 2579 }
f88ebc68 2580
199f5217 2581 if (dontdeltemps < 2)
9d04d618
TT
2582 {
2583 for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
2584 {
061ed861 2585 sprintf (outfile, "%s%d.o", TMP_STUB, i);
9d04d618 2586 if (unlink (outfile) < 0)
061ed861
NC
2587 /* xgettext:c-format */
2588 warn (_("cannot delete %s: %s\n"), outfile, strerror (errno));
9d04d618
TT
2589 }
2590 }
061ed861
NC
2591
2592 inform (_("Created lib file"));
765e60a9 2593}
9d04d618 2594
765e60a9
SC
2595/**********************************************************************/
2596
2597/* Run through the information gathered from the .o files and the
2598 .def file and work out the best stuff */
a33f7359 2599static int
765e60a9 2600pfunc (a, b)
a33f7359
ILT
2601 const void *a;
2602 const void *b;
765e60a9
SC
2603{
2604 export_type *ap = *(export_type **) a;
2605 export_type *bp = *(export_type **) b;
2606 if (ap->ordinal == bp->ordinal)
2607 return 0;
2608
2609 /* unset ordinals go to the bottom */
2610 if (ap->ordinal == -1)
2611 return 1;
2612 if (bp->ordinal == -1)
2613 return -1;
2614 return (ap->ordinal - bp->ordinal);
2615}
2616
a33f7359 2617static int
765e60a9 2618nfunc (a, b)
a33f7359
ILT
2619 const void *a;
2620 const void *b;
765e60a9
SC
2621{
2622 export_type *ap = *(export_type **) a;
2623 export_type *bp = *(export_type **) b;
2624
2625 return (strcmp (ap->name, bp->name));
2626}
2627
a33f7359 2628static void
765e60a9
SC
2629remove_null_names (ptr)
2630 export_type **ptr;
2631{
2632 int src;
2633 int dst;
2634 for (dst = src = 0; src < d_nfuncs; src++)
2635 {
2636 if (ptr[src])
2637 {
2638 ptr[dst] = ptr[src];
2639 dst++;
2640 }
2641 }
2642 d_nfuncs = dst;
2643}
2644
2645static void
2646dtab (ptr)
2647 export_type **ptr;
2648{
2649#ifdef SACDEBUG
2650 int i;
2651 for (i = 0; i < d_nfuncs; i++)
2652 {
2653 if (ptr[i])
2654 {
c336631b 2655 printf ("%d %s @ %d %s%s%s\n",
765e60a9
SC
2656 i, ptr[i]->name, ptr[i]->ordinal,
2657 ptr[i]->noname ? "NONAME " : "",
c336631b
ILT
2658 ptr[i]->constant ? "CONSTANT" : "",
2659 ptr[i]->data ? "DATA" : "");
765e60a9
SC
2660 }
2661 else
2662 printf ("empty\n");
2663 }
2664#endif
2665}
2666
2667static void
2668process_duplicates (d_export_vec)
2669 export_type **d_export_vec;
2670{
2671 int more = 1;
c027e8b0 2672 int i;
765e60a9
SC
2673 while (more)
2674 {
f051e1b0 2675
765e60a9
SC
2676 more = 0;
2677 /* Remove duplicates */
2678 qsort (d_export_vec, d_nfuncs, sizeof (export_type *), nfunc);
2679
2680 dtab (d_export_vec);
2681 for (i = 0; i < d_nfuncs - 1; i++)
2682 {
2683 if (strcmp (d_export_vec[i]->name,
2684 d_export_vec[i + 1]->name) == 0)
2685 {
2686
2687 export_type *a = d_export_vec[i];
2688 export_type *b = d_export_vec[i + 1];
2689
2690 more = 1;
061ed861
NC
2691
2692 /* xgettext:c-format */
2693 inform (_("Warning, ignoring duplicate EXPORT %s %d,%d\n"),
2694 a->name, a->ordinal, b->ordinal);
2695
765e60a9
SC
2696 if (a->ordinal != -1
2697 && b->ordinal != -1)
061ed861
NC
2698 /* xgettext:c-format */
2699 fatal (_("Error, duplicate EXPORT with oridinals: %s"),
2700 a->name);
765e60a9 2701
765e60a9
SC
2702 /* Merge attributes */
2703 b->ordinal = a->ordinal > 0 ? a->ordinal : b->ordinal;
2704 b->constant |= a->constant;
2705 b->noname |= a->noname;
c336631b 2706 b->data |= a->data;
765e60a9
SC
2707 d_export_vec[i] = 0;
2708 }
2709
2710 dtab (d_export_vec);
2711 remove_null_names (d_export_vec);
2712 dtab (d_export_vec);
2713 }
2714 }
f051e1b0
SC
2715
2716
2717 /* Count the names */
2718 for (i = 0; i < d_nfuncs; i++)
2719 {
2720 if (!d_export_vec[i]->noname)
2721 d_named_nfuncs++;
2722 }
765e60a9
SC
2723}
2724
2725static void
2726fill_ordinals (d_export_vec)
2727 export_type **d_export_vec;
2728{
a33f7359 2729 int lowest = -1;
f051e1b0 2730 int i;
6f2d3212 2731 char *ptr;
a33f7359
ILT
2732 int size = 65536;
2733
765e60a9
SC
2734 qsort (d_export_vec, d_nfuncs, sizeof (export_type *), pfunc);
2735
6f2d3212
SC
2736 /* fill in the unset ordinals with ones from our range */
2737
a33f7359 2738 ptr = (char *) xmalloc (size);
6f2d3212 2739
a33f7359 2740 memset (ptr, 0, size);
6f2d3212
SC
2741
2742 /* Mark in our large vector all the numbers that are taken */
765e60a9
SC
2743 for (i = 0; i < d_nfuncs; i++)
2744 {
6f2d3212 2745 if (d_export_vec[i]->ordinal != -1)
765e60a9 2746 {
6f2d3212 2747 ptr[d_export_vec[i]->ordinal] = 1;
a33f7359
ILT
2748 if (lowest == -1 || d_export_vec[i]->ordinal < lowest)
2749 {
2750 lowest = d_export_vec[i]->ordinal;
2751 }
765e60a9 2752 }
6f2d3212
SC
2753 }
2754
20dec772 2755 /* Start at 1 for compatibility with MS toolchain. */
a33f7359 2756 if (lowest == -1)
20dec772
ILT
2757 lowest = 1;
2758
a33f7359 2759 /* Now fill in ordinals where the user wants us to choose. */
6f2d3212
SC
2760 for (i = 0; i < d_nfuncs; i++)
2761 {
2762 if (d_export_vec[i]->ordinal == -1)
765e60a9 2763 {
a33f7359
ILT
2764 register int j;
2765
2766 /* First try within or after any user supplied range. */
2767 for (j = lowest; j < size; j++)
6f2d3212
SC
2768 if (ptr[j] == 0)
2769 {
2770 ptr[j] = 1;
2771 d_export_vec[i]->ordinal = j;
2772 goto done;
2773 }
2774
a33f7359
ILT
2775 /* Then try before the range. */
2776 for (j = lowest; j >0; j--)
6f2d3212
SC
2777 if (ptr[j] == 0)
2778 {
2779 ptr[j] = 1;
2780 d_export_vec[i]->ordinal = j;
2781 goto done;
2782 }
2783 done:;
765e60a9
SC
2784 }
2785 }
2786
6f2d3212
SC
2787 free (ptr);
2788
2789 /* And resort */
2790
2791 qsort (d_export_vec, d_nfuncs, sizeof (export_type *), pfunc);
2792
799de4c4 2793 /* Work out the lowest and highest ordinal numbers. */
c027e8b0 2794 if (d_nfuncs)
356c68ff 2795 {
799de4c4
DE
2796 if (d_export_vec[0])
2797 d_low_ord = d_export_vec[0]->ordinal;
356c68ff
SC
2798 if (d_export_vec[d_nfuncs-1])
2799 d_high_ord = d_export_vec[d_nfuncs-1]->ordinal;
2800 }
f051e1b0
SC
2801}
2802
a33f7359
ILT
2803static int
2804alphafunc (av,bv)
2805 const void *av;
2806 const void *bv;
f051e1b0 2807{
a33f7359
ILT
2808 const export_type **a = (const export_type **) av;
2809 const export_type **b = (const export_type **) bv;
f051e1b0
SC
2810
2811 return strcmp ((*a)->name, (*b)->name);
765e60a9 2812}
f051e1b0 2813
a33f7359 2814static void
765e60a9
SC
2815mangle_defs ()
2816{
2817 /* First work out the minimum ordinal chosen */
2818
2819 export_type *exp;
356c68ff 2820
765e60a9 2821 int i;
f051e1b0 2822 int hint = 0;
765e60a9
SC
2823 export_type **d_export_vec
2824 = (export_type **) xmalloc (sizeof (export_type *) * d_nfuncs);
2825
061ed861
NC
2826 inform (_("Processing definitions"));
2827
765e60a9
SC
2828 for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
2829 {
2830 d_export_vec[i] = exp;
2831 }
2832
2833 process_duplicates (d_export_vec);
2834 fill_ordinals (d_export_vec);
2835
2836 /* Put back the list in the new order */
2837 d_exports = 0;
2838 for (i = d_nfuncs - 1; i >= 0; i--)
2839 {
2840 d_export_vec[i]->next = d_exports;
2841 d_exports = d_export_vec[i];
2842 }
f051e1b0
SC
2843
2844 /* Build list in alpha order */
061ed861
NC
2845 d_exports_lexically = (export_type **)
2846 xmalloc (sizeof (export_type *) * (d_nfuncs + 1));
f051e1b0
SC
2847
2848 for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
2849 {
2850 d_exports_lexically[i] = exp;
2851 }
2852 d_exports_lexically[i] = 0;
2853
2854 qsort (d_exports_lexically, i, sizeof (export_type *), alphafunc);
2855
2856 /* Fill exp entries with their hint values */
c027e8b0 2857
f051e1b0
SC
2858 for (i = 0; i < d_nfuncs; i++)
2859 {
2860 if (!d_exports_lexically[i]->noname || show_allnames)
2861 d_exports_lexically[i]->hint = hint++;
2862 }
061ed861
NC
2863
2864 inform (_("Processed definitions"));
765e60a9
SC
2865}
2866
765e60a9
SC
2867/**********************************************************************/
2868
a33f7359 2869static void
faad4b47
ILT
2870usage (file, status)
2871 FILE *file;
765e60a9
SC
2872 int status;
2873{
061ed861 2874 /* xgetext:c-format */
faad4b47 2875 fprintf (file, _("Usage %s <options> <object-files>\n"), program_name);
061ed861 2876 /* xgetext:c-format */
faad4b47
ILT
2877 fprintf (file, _(" -m --machine <machine> Create {arm, i386, ppc, thumb} DLL. [default: %s]\n"), mname);
2878 fprintf (file, _(" -e --output-exp <outname> Generate an export file.\n"));
2879 fprintf (file, _(" -l --output-lib <outname> Generate an interface library.\n"));
2880 fprintf (file, _(" -a --add-indirect Add dll indirects to export file.\n"));
2881 fprintf (file, _(" -D --dllname <name> Name of input dll to put into interface lib.\n"));
2882 fprintf (file, _(" -d --input-def <deffile> Name of .def file to be read in.\n"));
2883 fprintf (file, _(" -z --output-def <deffile> Name of .def file to be created.\n"));
2884 fprintf (file, _(" --export-all-symbols Export all symbols to .def\n"));
2885 fprintf (file, _(" --no-export-all-symbols Only export listed symbols\n"));
2886 fprintf (file, _(" --exclude-symbols <list> Don't export <list>\n"));
2887 fprintf (file, _(" --no-default-excludes Clear default exclude symbols\n"));
2888 fprintf (file, _(" -b --base-file <basefile> Read linker generated base file.\n"));
2889 fprintf (file, _(" -x --no-idata4 Don't generate idata$4 section.\n"));
2890 fprintf (file, _(" -c --no-idata5 Don't generate idata$5 section.\n"));
2891 fprintf (file, _(" -U --add-underscore Add underscores to symbols in interface library.\n"));
2892 fprintf (file, _(" -k --kill-at Kill @<n> from exported names.\n"));
2893 fprintf (file, _(" -S --as <name> Use <name> for assembler.\n"));
2894 fprintf (file, _(" -f --as-flags <flags> Pass <flags> to the assembler.\n"));
061ed861 2895#ifdef DLLTOOL_ARM
faad4b47 2896 fprintf (file, _(" -i --interwork Support ARM/Thumb interworking.\n"));
061ed861 2897#endif
faad4b47
ILT
2898 fprintf (file, _(" -n --no-delete Keep temp files (repeat for extra preservation).\n"));
2899 fprintf (file, _(" -v --verbose Be verbose.\n"));
2900 fprintf (file, _(" -V --version Display the program version.\n"));
2901 fprintf (file, _(" -h --help Display this information.\n"));
061ed861 2902
765e60a9
SC
2903 exit (status);
2904}
2905
faad4b47
ILT
2906#define OPTION_EXPORT_ALL_SYMS 150
2907#define OPTION_NO_EXPORT_ALL_SYMS (OPTION_EXPORT_ALL_SYMS + 1)
2908#define OPTION_EXCLUDE_SYMS (OPTION_NO_EXPORT_ALL_SYMS + 1)
2909#define OPTION_NO_DEFAULT_EXCLUDES (OPTION_EXCLUDE_SYMS + 1)
2910#define OPTION_NO_IDATA4 'x'
2911#define OPTION_NO_IDATA5 'c'
2912
a33f7359 2913static const struct option long_options[] =
765e60a9 2914{
061ed861 2915 {"no-delete", no_argument, NULL, 'n'},
531f86b4 2916 {"dllname", required_argument, NULL, 'D'},
356c68ff
SC
2917 {"no-idata4", no_argument, NULL, OPTION_NO_IDATA4},
2918 {"no-idata5", no_argument, NULL, OPTION_NO_IDATA5},
2757dc25 2919 {"output-exp", required_argument, NULL, 'e'},
531f86b4 2920 {"output-def", required_argument, NULL, 'z'},
faad4b47
ILT
2921 {"export-all-symbols", no_argument, NULL, OPTION_EXPORT_ALL_SYMS},
2922 {"no-export-all-symbols", no_argument, NULL, OPTION_NO_EXPORT_ALL_SYMS},
2923 {"exclude-symbols", required_argument, NULL, OPTION_EXCLUDE_SYMS},
2924 {"no-default-excludes", no_argument, NULL, OPTION_NO_DEFAULT_EXCLUDES},
2757dc25 2925 {"output-lib", required_argument, NULL, 'l'},
061ed861
NC
2926 {"def", required_argument, NULL, 'd'}, /* for compatiblity with older versions */
2927 {"input-def", required_argument, NULL, 'd'},
531f86b4 2928 {"add-underscore", no_argument, NULL, 'U'},
061ed861
NC
2929 {"kill-at", no_argument, NULL, 'k'},
2930 {"verbose", no_argument, NULL, 'v'},
2931 {"version", no_argument, NULL, 'V'},
765e60a9
SC
2932 {"help", no_argument, NULL, 'h'},
2933 {"machine", required_argument, NULL, 'm'},
199f5217 2934 {"add-indirect", no_argument, NULL, 'a'},
6f2d3212 2935 {"base-file", required_argument, NULL, 'b'},
356c68ff 2936 {"as", required_argument, NULL, 'S'},
061ed861
NC
2937 {"as-flags", required_argument, NULL, 'f'},
2938#ifdef DLLTOOL_ARM
2939 {"interwork", no_argument, NULL, 'i'},
2940#endif
356c68ff 2941 {0}
765e60a9
SC
2942};
2943
2944int
2945main (ac, av)
2946 int ac;
2947 char **av;
2948{
2949 int c;
f051e1b0 2950 int i;
765e60a9
SC
2951 char *firstarg = 0;
2952 program_name = av[0];
2953 oav = av;
6f2d3212 2954
061ed861 2955#ifdef HAVE_SETLOCALE
19ac4b08 2956 setlocale (LC_MESSAGES, "");
061ed861 2957#endif
19ac4b08
TT
2958 bindtextdomain (PACKAGE, LOCALEDIR);
2959 textdomain (PACKAGE);
2960
061ed861
NC
2961 while ((c = getopt_long (ac, av, "xcz:S:aD:l:e:nkvVb:Uh?m:d:f:i",
2962 long_options, 0))
356c68ff 2963 != EOF)
765e60a9
SC
2964 {
2965 switch (c)
2966 {
356c68ff
SC
2967 case OPTION_NO_IDATA4:
2968 no_idata4 = 1;
2969 break;
2970 case OPTION_NO_IDATA5:
2971 no_idata5 = 1;
2972 break;
faad4b47
ILT
2973 case OPTION_EXPORT_ALL_SYMS:
2974 export_all_symbols = true;
2975 break;
2976 case OPTION_NO_EXPORT_ALL_SYMS:
2977 export_all_symbols = false;
2978 break;
2979 case OPTION_EXCLUDE_SYMS:
2980 add_excludes (optarg);
2981 break;
2982 case OPTION_NO_DEFAULT_EXCLUDES:
2983 do_default_excludes = false;
2984 break;
356c68ff
SC
2985 case 'S':
2986 as_name = optarg;
2987 break;
061ed861
NC
2988 case 'f':
2989 as_flags = optarg;
2990 break;
356c68ff 2991
531f86b4
SC
2992 /* ignored for compatibility */
2993 case 'u':
2994 break;
199f5217
DE
2995 case 'a':
2996 add_indirect = 1;
2997 break;
531f86b4 2998 case 'z':
20dec772 2999 output_def = fopen (optarg, FOPEN_WT);
531f86b4 3000 break;
2757dc25
SC
3001 case 'D':
3002 dll_name = optarg;
3003 break;
3004 case 'l':
3005 imp_name = optarg;
3006 break;
3007 case 'e':
3008 exp_name = optarg;
3009 break;
765e60a9 3010 case 'h':
faad4b47 3011 usage (stdout, 0);
765e60a9
SC
3012 break;
3013 case 'm':
3014 mname = optarg;
3015 break;
6f2d3212
SC
3016 case 'v':
3017 verbose = 1;
3018 break;
061ed861
NC
3019 case 'V':
3020 print_version (program_name);
3021 break;
3022#ifdef DLLTOOL_ARM
3023 case 'i':
3024 interwork = 1;
3025 break;
3026#endif
2757dc25 3027 case 'y':
a33f7359
ILT
3028#if 0
3029 /* We don't currently define YYDEBUG when building
3030 defparse.y. */
765e60a9 3031 yydebug = 1;
a33f7359 3032#endif
765e60a9 3033 break;
531f86b4
SC
3034 case 'U':
3035 add_underscore = 1;
6f2d3212 3036 break;
00289839
SC
3037 case 'k':
3038 killat = 1;
3039 break;
765e60a9
SC
3040 case 'd':
3041 def_file = optarg;
3042 break;
2757dc25 3043 case 'n':
f88ebc68 3044 dontdeltemps++;
2757dc25 3045 break;
6f2d3212 3046 case 'b':
20dec772 3047 base_file = fopen (optarg, FOPEN_RB);
061ed861 3048
6f2d3212 3049 if (!base_file)
061ed861
NC
3050 /* xgettext:c-format */
3051 fatal (_("Unable to open base-file: %s"), optarg);
3052
6f2d3212 3053 break;
765e60a9 3054 default:
faad4b47
ILT
3055 usage (stderr, 1);
3056 break;
765e60a9
SC
3057 }
3058 }
3059
6f2d3212 3060 for (i = 0; mtable[i].type; i++)
765e60a9
SC
3061 {
3062 if (strcmp (mtable[i].type, mname) == 0)
3063 break;
3064 }
3065
6f2d3212 3066 if (!mtable[i].type)
061ed861
NC
3067 /* xgettext:c-format */
3068 fatal (_("Machine '%s' not supported"), mname);
765e60a9 3069
061ed861 3070 machine = i;
765e60a9 3071
061ed861
NC
3072#ifdef DLLTOOL_ARM
3073 /* Always enable interworking for Thumb targets. */
3074 if (machine == MTHUMB && (! interwork))
3075 interwork = 1;
3076#endif
3077
2757dc25
SC
3078 if (!dll_name && exp_name)
3079 {
a4e5fd18 3080 int len = strlen (exp_name) + 5;
2757dc25
SC
3081 dll_name = xmalloc (len);
3082 strcpy (dll_name, exp_name);
3083 strcat (dll_name, ".dll");
3084 }
2757dc25 3085
faad4b47
ILT
3086 /* Don't use the default exclude list if we're reading only the
3087 symbols in the .drectve section. The default excludes are meant
3088 to avoid exporting DLL entry point and Cygwin32 impure_ptr. */
3089 if (! export_all_symbols)
3090 do_default_excludes = false;
3091
3092 if (do_default_excludes)
3093 set_default_excludes ();
3094
765e60a9 3095 if (def_file)
061ed861
NC
3096 process_def_file (def_file);
3097
765e60a9
SC
3098 while (optind < ac)
3099 {
3100 if (!firstarg)
3101 firstarg = av[optind];
3102 scan_obj_file (av[optind]);
3103 optind++;
3104 }
3105
765e60a9 3106 mangle_defs ();
6f2d3212 3107
2757dc25
SC
3108 if (exp_name)
3109 gen_exp_file ();
061ed861 3110
2757dc25 3111 if (imp_name)
531f86b4
SC
3112 {
3113 /* Make imp_name safe for use as a label. */
3114 char *p;
a33f7359
ILT
3115
3116 imp_name_lab = xstrdup (imp_name);
3117 for (p = imp_name_lab; *p; p++)
531f86b4 3118 {
c027e8b0 3119 if (!isalpha ((unsigned char) *p) && !isdigit ((unsigned char) *p))
531f86b4
SC
3120 *p = '_';
3121 }
356c68ff 3122 head_label = make_label("_head_", imp_name_lab);
531f86b4
SC
3123 gen_lib_file ();
3124 }
061ed861 3125
531f86b4
SC
3126 if (output_def)
3127 gen_def_file ();
6f2d3212 3128
765e60a9
SC
3129 return 0;
3130}