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