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