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