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