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