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