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