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