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