1 /* dlltool.c -- tool to generate stuff for PE style DLLs
2 Copyright 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002
3 Free Software Foundation, Inc.
5 This file is part of GNU Binutils.
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.
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.
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
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.
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.
32 A DLL contains an export table which contains the information
33 which the runtime loader needs to tie up references from a
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.
41 A DEF file contains any number of the following commands:
44 NAME <name> [ , <base> ]
45 The result is going to be <name>.EXE
47 LIBRARY <name> [ , <base> ]
48 The result is going to be <name>.DLL
50 EXPORTS ( ( ( <name1> [ = <name2> ] )
51 | ( <name1> = <module-name> . <external-name>))
52 [ @ <integer> ] [ NONAME ] [CONSTANT] [DATA] ) *
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>.
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 refered to in the body of the DLL.
66 Puts <string> into output .exp file in the .rdata section
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.
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
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>
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
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.
100 asm (".section .drectve");
101 asm (".ascii \"-export:adef\"");
105 printf ("hello from the dll %s\n", s);
110 printf ("hello from the dll and the other entry point %s\n", s);
114 asm (".section .drectve");
115 asm (".ascii \"-export:cdef\"");
116 asm (".ascii \"-export:ddef\"");
120 printf ("hello from the dll %s\n", s);
125 printf ("hello from the dll and the other entry point %s\n", s);
143 HEAPSIZE 0x40000, 0x2000
147 SECTIONS donkey READ WRITE
150 # Compile up the parts of the dll and the program
152 gcc -c file1.c file2.c themain.c
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)
158 ar qcv thedll.in file1.o file2.o
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).
165 dlltool --def thedll.def --output-exp thedll.o --output-lib thedll.a
167 # Build the dll with the library and the export table
169 ld -o thedll.dll thedll.o thedll.in
171 # Link the executable with the import library
173 gcc -o themain.exe themain.o thedll.a
175 This example can be extended if relocations are needed in the DLL:
177 # Compile up the parts of the dll and the program
179 gcc -c file1.c file2.c themain.c
181 # Run this tool over the DLL's .def file and generate an imports file.
183 dlltool --def thedll.def --output-lib thedll.lib
185 # Link the executable with the import library and generate a base file
188 gcc -o themain.exe themain.o thedll.lib -Wl,--base-file -Wl,themain.base
190 # Run this tool over the DLL's .def file and generate an exports file
191 # which includes the relocations from the base file.
193 dlltool --def thedll.def --base-file themain.base --output-exp thedll.exp
195 # Build the dll with file1.o, file2.o and the export table
197 ld -o thedll.dll thedll.exp file1.o file2.o */
199 /* .idata section description
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.
205 .idata$2 = Import Directory Table
206 = array of IMAGE_IMPORT_DESCRIPTOR's.
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
214 .idata$3 = null terminating entry for .idata$2.
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.
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
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.
233 .idata$7 = dll name (eg: "kernel32.dll"). (.idata$6 for ppc). */
235 /* AIX requires this to be the first thing in the file. */
242 #define show_allnames 0
244 #define PAGE_SIZE 4096
245 #define PAGE_MASK (-PAGE_SIZE)
247 #include "libiberty.h"
250 #include "demangle.h"
251 #include "dyn-string.h"
253 #include "safe-ctype.h"
256 #include <sys/stat.h>
258 #ifdef ANSI_PROTOTYPES
265 #include "coff/arm.h"
266 #include "coff/internal.h"
269 /* Forward references. */
270 static char *look_for_prog
271 PARAMS ((const char *, const char *, int));
272 static char *deduce_name
273 PARAMS ((const char *));
275 #ifdef DLLTOOL_MCORE_ELF
276 static void mcore_elf_cache_filename
278 static void mcore_elf_gen_out_file
282 #ifdef HAVE_SYS_WAIT_H
283 #include <sys/wait.h>
284 #else /* ! HAVE_SYS_WAIT_H */
285 #if ! defined (_WIN32) || defined (__CYGWIN32__)
287 #define WIFEXITED(w) (((w) & 0377) == 0)
290 #define WIFSIGNALED(w) (((w) & 0377) != 0177 && ((w) & ~0377) == 0)
293 #define WTERMSIG(w) ((w) & 0177)
296 #define WEXITSTATUS(w) (((w) >> 8) & 0377)
298 #else /* defined (_WIN32) && ! defined (__CYGWIN32__) */
300 #define WIFEXITED(w) (((w) & 0xff) == 0)
303 #define WIFSIGNALED(w) (((w) & 0xff) != 0 && ((w) & 0xff) != 0x7f)
306 #define WTERMSIG(w) ((w) & 0x7f)
309 #define WEXITSTATUS(w) (((w) & 0xff00) >> 8)
311 #endif /* defined (_WIN32) && ! defined (__CYGWIN32__) */
312 #endif /* ! HAVE_SYS_WAIT_H */
314 /* ifunc and ihead data structures: ttk@cygnus.com 1997
316 When IMPORT declarations are encountered in a .def file the
317 function import information is stored in a structure referenced by
318 the global variable IMPORT_LIST. The structure is a linked list
319 containing the names of the dll files each function is imported
320 from and a linked list of functions being imported from that dll
321 file. This roughly parallels the structure of the .idata section
322 in the PE object file.
324 The contents of .def file are interpreted from within the
325 process_def_file function. Every time an IMPORT declaration is
326 encountered, it is broken up into its component parts and passed to
327 def_import. IMPORT_LIST is initialized to NULL in function main. */
329 typedef struct ifunct
331 char * name
; /* Name of function being imported. */
332 int ord
; /* Two-byte ordinal value associated with function. */
336 typedef struct iheadt
338 char *dllname
; /* Name of dll file imported from. */
339 long nfuncs
; /* Number of functions in list. */
340 struct ifunct
*funchead
; /* First function in list. */
341 struct ifunct
*functail
; /* Last function in list. */
342 struct iheadt
*next
; /* Next dll file in list. */
345 /* Structure containing all import information as defined in .def file
346 (qv "ihead structure"). */
348 static iheadtype
*import_list
= NULL
;
350 static char *as_name
= NULL
;
351 static char * as_flags
= "";
353 static char *tmp_prefix
;
355 static int no_idata4
;
356 static int no_idata5
;
357 static char *exp_name
;
358 static char *imp_name
;
359 static char *head_label
;
360 static char *imp_name_lab
;
361 static char *dll_name
;
363 static int add_indirect
= 0;
364 static int add_underscore
= 0;
365 static int dontdeltemps
= 0;
367 /* TRUE if we should export all symbols. Otherwise, we only export
368 symbols listed in .drectve sections or in the def file. */
369 static bfd_boolean export_all_symbols
;
371 /* TRUE if we should exclude the symbols in DEFAULT_EXCLUDES when
372 exporting all symbols. */
373 static bfd_boolean do_default_excludes
= TRUE
;
375 /* Default symbols to exclude when exporting all the symbols. */
376 static const char *default_excludes
= "DllMain@12,DllEntryPoint@0,impure_ptr";
378 /* TRUE if we should add __imp_<SYMBOL> to import libraries for backward
379 compatibility to old Cygwin releases. */
380 static bfd_boolean create_compat_implib
;
382 static char *def_file
;
384 extern char * program_name
;
388 static int add_stdcall_alias
;
390 static FILE *output_def
;
391 static FILE *base_file
;
394 #ifdef DLLTOOL_ARM_EPOC
395 static const char *mname
= "arm-epoc";
397 static const char *mname
= "arm";
402 static const char *mname
= "i386";
406 static const char *mname
= "ppc";
410 static const char *mname
= "sh";
414 static const char *mname
= "mips";
418 static const char * mname
= "mcore-le";
421 #ifdef DLLTOOL_MCORE_ELF
422 static const char * mname
= "mcore-elf";
423 static char * mcore_elf_out_file
= NULL
;
424 static char * mcore_elf_linker
= NULL
;
425 static char * mcore_elf_linker_flags
= NULL
;
427 #define DRECTVE_SECTION_NAME ((machine == MMCORE_ELF || machine == MMCORE_ELF_LE) ? ".exports" : ".drectve")
430 #ifndef DRECTVE_SECTION_NAME
431 #define DRECTVE_SECTION_NAME ".drectve"
434 #define PATHMAX 250 /* What's the right name for this ? */
437 char *tmp_head_s_buf
;
438 char *tmp_head_o_buf
;
439 char *tmp_tail_s_buf
;
440 char *tmp_tail_o_buf
;
443 #define TMP_ASM dlltmp (&tmp_asm_buf, "%sc.s")
444 #define TMP_HEAD_S dlltmp (&tmp_head_s_buf, "%sh.s")
445 #define TMP_HEAD_O dlltmp (&tmp_head_o_buf, "%sh.o")
446 #define TMP_TAIL_S dlltmp (&tmp_tail_s_buf, "%st.s")
447 #define TMP_TAIL_O dlltmp (&tmp_tail_o_buf, "%st.o")
448 #define TMP_STUB dlltmp (&tmp_stub_buf, "%ss")
450 /* This bit of assemly does jmp * .... */
451 static const unsigned char i386_jtab
[] =
453 0xff, 0x25, 0x00, 0x00, 0x00, 0x00, 0x90, 0x90
456 static const unsigned char arm_jtab
[] =
458 0x00, 0xc0, 0x9f, 0xe5, /* ldr ip, [pc] */
459 0x00, 0xf0, 0x9c, 0xe5, /* ldr pc, [ip] */
463 static const unsigned char arm_interwork_jtab
[] =
465 0x04, 0xc0, 0x9f, 0xe5, /* ldr ip, [pc] */
466 0x00, 0xc0, 0x9c, 0xe5, /* ldr ip, [ip] */
467 0x1c, 0xff, 0x2f, 0xe1, /* bx ip */
471 static const unsigned char thumb_jtab
[] =
473 0x40, 0xb4, /* push {r6} */
474 0x02, 0x4e, /* ldr r6, [pc, #8] */
475 0x36, 0x68, /* ldr r6, [r6] */
476 0xb4, 0x46, /* mov ip, r6 */
477 0x40, 0xbc, /* pop {r6} */
478 0x60, 0x47, /* bx ip */
482 static const unsigned char mcore_be_jtab
[] =
484 0x71, 0x02, /* lrw r1,2 */
485 0x81, 0x01, /* ld.w r1,(r1,0) */
486 0x00, 0xC1, /* jmp r1 */
487 0x12, 0x00, /* nop */
488 0x00, 0x00, 0x00, 0x00 /* <address> */
491 static const unsigned char mcore_le_jtab
[] =
493 0x02, 0x71, /* lrw r1,2 */
494 0x01, 0x81, /* ld.w r1,(r1,0) */
495 0xC1, 0x00, /* jmp r1 */
496 0x00, 0x12, /* nop */
497 0x00, 0x00, 0x00, 0x00 /* <address> */
500 /* This is the glue sequence for PowerPC PE. There is a
501 tocrel16-tocdefn reloc against the first instruction.
502 We also need a IMGLUE reloc against the glue function
503 to restore the toc saved by the third instruction in
505 static const unsigned char ppc_jtab
[] =
507 0x00, 0x00, 0x62, 0x81, /* lwz r11,0(r2) */
508 /* Reloc TOCREL16 __imp_xxx */
509 0x00, 0x00, 0x8B, 0x81, /* lwz r12,0(r11) */
510 0x04, 0x00, 0x41, 0x90, /* stw r2,4(r1) */
511 0xA6, 0x03, 0x89, 0x7D, /* mtctr r12 */
512 0x04, 0x00, 0x4B, 0x80, /* lwz r2,4(r11) */
513 0x20, 0x04, 0x80, 0x4E /* bctr */
517 /* The glue instruction, picks up the toc from the stw in
518 the above code: "lwz r2,4(r1)". */
519 static bfd_vma ppc_glue_insn
= 0x80410004;
525 const char *how_byte
;
526 const char *how_short
;
527 const char *how_long
;
528 const char *how_asciz
;
529 const char *how_comment
;
530 const char *how_jump
;
531 const char *how_global
;
532 const char *how_space
;
533 const char *how_align_short
;
534 const char *how_align_long
;
535 const char *how_default_as_switches
;
536 const char *how_bfd_target
;
537 enum bfd_architecture how_bfd_arch
;
538 const unsigned char *how_jtab
;
539 int how_jtab_size
; /* Size of the jtab entry. */
540 int how_jtab_roff
; /* Offset into it for the ind 32 reloc into idata 5. */
543 static const struct mac
548 "arm", ".byte", ".short", ".long", ".asciz", "@",
549 "ldr\tip,[pc]\n\tldr\tpc,[ip]\n\t.long",
550 ".global", ".space", ".align\t2",".align\t4", "-mapcs-32",
551 "pe-arm-little", bfd_arch_arm
,
552 arm_jtab
, sizeof (arm_jtab
), 8
557 "i386", ".byte", ".short", ".long", ".asciz", "#",
558 "jmp *", ".global", ".space", ".align\t2",".align\t4", "",
559 "pe-i386",bfd_arch_i386
,
560 i386_jtab
, sizeof (i386_jtab
), 2
565 "ppc", ".byte", ".short", ".long", ".asciz", "#",
566 "jmp *", ".global", ".space", ".align\t2",".align\t4", "",
567 "pe-powerpcle",bfd_arch_powerpc
,
568 ppc_jtab
, sizeof (ppc_jtab
), 0
573 "thumb", ".byte", ".short", ".long", ".asciz", "@",
574 "push\t{r6}\n\tldr\tr6, [pc, #8]\n\tldr\tr6, [r6]\n\tmov\tip, r6\n\tpop\t{r6}\n\tbx\tip",
575 ".global", ".space", ".align\t2",".align\t4", "-mthumb-interwork",
576 "pe-arm-little", bfd_arch_arm
,
577 thumb_jtab
, sizeof (thumb_jtab
), 12
580 #define MARM_INTERWORK 4
582 "arm_interwork", ".byte", ".short", ".long", ".asciz", "@",
583 "ldr\tip,[pc]\n\tldr\tip,[ip]\n\tbx\tip\n\t.long",
584 ".global", ".space", ".align\t2",".align\t4", "-mthumb-interwork",
585 "pe-arm-little", bfd_arch_arm
,
586 arm_interwork_jtab
, sizeof (arm_interwork_jtab
), 12
591 "mcore-be", ".byte", ".short", ".long", ".asciz", "//",
592 "lrw r1,[1f]\n\tld.w r1,(r1,0)\n\tjmp r1\n\tnop\n1:.long",
593 ".global", ".space", ".align\t2",".align\t4", "",
594 "pe-mcore-big", bfd_arch_mcore
,
595 mcore_be_jtab
, sizeof (mcore_be_jtab
), 8
600 "mcore-le", ".byte", ".short", ".long", ".asciz", "//",
601 "lrw r1,[1f]\n\tld.w r1,(r1,0)\n\tjmp r1\n\tnop\n1:.long",
602 ".global", ".space", ".align\t2",".align\t4", "-EL",
603 "pe-mcore-little", bfd_arch_mcore
,
604 mcore_le_jtab
, sizeof (mcore_le_jtab
), 8
609 "mcore-elf-be", ".byte", ".short", ".long", ".asciz", "//",
610 "lrw r1,[1f]\n\tld.w r1,(r1,0)\n\tjmp r1\n\tnop\n1:.long",
611 ".global", ".space", ".align\t2",".align\t4", "",
612 "elf32-mcore-big", bfd_arch_mcore
,
613 mcore_be_jtab
, sizeof (mcore_be_jtab
), 8
617 #define MMCORE_ELF_LE 8
618 "mcore-elf-le", ".byte", ".short", ".long", ".asciz", "//",
619 "lrw r1,[1f]\n\tld.w r1,(r1,0)\n\tjmp r1\n\tnop\n1:.long",
620 ".global", ".space", ".align\t2",".align\t4", "-EL",
621 "elf32-mcore-little", bfd_arch_mcore
,
622 mcore_le_jtab
, sizeof (mcore_le_jtab
), 8
627 "arm-epoc", ".byte", ".short", ".long", ".asciz", "@",
628 "ldr\tip,[pc]\n\tldr\tpc,[ip]\n\t.long",
629 ".global", ".space", ".align\t2",".align\t4", "",
630 "epoc-pe-arm-little", bfd_arch_arm
,
631 arm_jtab
, sizeof (arm_jtab
), 8
634 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
644 typedef struct export
647 const char *internal_name
;
653 int forward
; /* Number of forward label, 0 means no forward. */
658 /* A list of symbols which we should not export. */
662 struct string_list
*next
;
666 static struct string_list
*excludes
;
668 static const char *rvaafter
670 static const char *rvabefore
672 static const char *asm_prefix
674 static void process_def_file
675 PARAMS ((const char *));
676 static void new_directive
678 static void append_import
679 PARAMS ((const char *, const char *, int));
681 PARAMS ((const char *, char *));
682 static void scan_drectve_symbols
684 static void scan_filtered_symbols
685 PARAMS ((bfd
*, PTR
, long, unsigned int));
686 static void add_excludes
687 PARAMS ((const char *));
688 static bfd_boolean match_exclude
689 PARAMS ((const char *));
690 static void set_default_excludes
692 static long filter_symbols
693 PARAMS ((bfd
*, PTR
, long, unsigned int));
694 static void scan_all_symbols
696 static void scan_open_obj_file
698 static void scan_obj_file
699 PARAMS ((const char *));
700 static void dump_def_info
703 PARAMS ((const void *, const void *));
704 static void flush_page
705 PARAMS ((FILE *, long *, int, int));
706 static void gen_def_file
708 static void generate_idata_ofile
710 static void assemble_file
711 PARAMS ((const char *, const char *));
712 static void gen_exp_file
714 static const char *xlate
715 PARAMS ((const char *));
718 PARAMS ((FILE *, export_type
*));
720 static char *make_label
721 PARAMS ((const char *, const char *));
722 static char *make_imp_label
723 PARAMS ((const char *, const char *));
724 static bfd
*make_one_lib_file
725 PARAMS ((export_type
*, int));
726 static bfd
*make_head
728 static bfd
*make_tail
730 static void gen_lib_file
733 PARAMS ((const void *, const void *));
735 PARAMS ((const void *, const void *));
736 static void remove_null_names
737 PARAMS ((export_type
**));
739 PARAMS ((export_type
**));
740 static void process_duplicates
741 PARAMS ((export_type
**));
742 static void fill_ordinals
743 PARAMS ((export_type
**));
745 PARAMS ((const void *, const void *));
746 static void mangle_defs
749 PARAMS ((FILE *, int));
751 PARAMS ((const char *, ...));
754 prefix_encode
PARAMS ((char *start
, unsigned code
))
756 static char alpha
[26] = "abcdefghijklmnopqrstuvwxyz";
760 p
= strchr (buf
, '\0');
762 *p
++ = alpha
[code
% sizeof (alpha
)];
763 while ((code
/= sizeof (alpha
)) != 0);
769 dlltmp
PARAMS ((char **buf
, const char *fmt
))
773 *buf
= malloc (strlen (tmp_prefix
) + 64);
774 sprintf (*buf
, fmt
, tmp_prefix
);
780 inform
VPARAMS ((const char * message
, ...))
782 VA_OPEN (args
, message
);
783 VA_FIXEDARG (args
, const char *, message
);
788 report (message
, args
);
811 /* xgettext:c-format */
812 fatal (_("Internal error: Unknown machine type: %d"), machine
);
836 /* xgettext:c-format */
837 fatal (_("Internal error: Unknown machine type: %d"), machine
);
862 /* xgettext:c-format */
863 fatal (_("Internal error: Unknown machine type: %d"), machine
);
869 #define ASM_BYTE mtable[machine].how_byte
870 #define ASM_SHORT mtable[machine].how_short
871 #define ASM_LONG mtable[machine].how_long
872 #define ASM_TEXT mtable[machine].how_asciz
873 #define ASM_C mtable[machine].how_comment
874 #define ASM_JUMP mtable[machine].how_jump
875 #define ASM_GLOBAL mtable[machine].how_global
876 #define ASM_SPACE mtable[machine].how_space
877 #define ASM_ALIGN_SHORT mtable[machine].how_align_short
878 #define ASM_RVA_BEFORE rvabefore(machine)
879 #define ASM_RVA_AFTER rvaafter(machine)
880 #define ASM_PREFIX asm_prefix(machine)
881 #define ASM_ALIGN_LONG mtable[machine].how_align_long
882 #define HOW_BFD_READ_TARGET 0 /* always default*/
883 #define HOW_BFD_WRITE_TARGET mtable[machine].how_bfd_target
884 #define HOW_BFD_ARCH mtable[machine].how_bfd_arch
885 #define HOW_JTAB mtable[machine].how_jtab
886 #define HOW_JTAB_SIZE mtable[machine].how_jtab_size
887 #define HOW_JTAB_ROFF mtable[machine].how_jtab_roff
888 #define ASM_SWITCHES mtable[machine].how_default_as_switches
893 process_def_file (name
)
896 FILE *f
= fopen (name
, FOPEN_RT
);
899 /* xgettext:c-format */
900 fatal (_("Can't open def file: %s"), name
);
904 /* xgettext:c-format */
905 inform (_("Processing def file: %s"), name
);
909 inform (_("Processed def file"));
912 /**********************************************************************/
914 /* Communications with the parser. */
916 static const char *d_name
; /* Arg to NAME or LIBRARY. */
917 static int d_nfuncs
; /* Number of functions exported. */
918 static int d_named_nfuncs
; /* Number of named functions exported. */
919 static int d_low_ord
; /* Lowest ordinal index. */
920 static int d_high_ord
; /* Highest ordinal index. */
921 static export_type
*d_exports
; /* List of exported functions. */
922 static export_type
**d_exports_lexically
; /* Vector of exported functions in alpha order. */
923 static dlist_type
*d_list
; /* Descriptions. */
924 static dlist_type
*a_list
; /* Stuff to go in directives. */
925 static int d_nforwards
= 0; /* Number of forwarded exports. */
932 const char * err ATTRIBUTE_UNUSED
;
934 /* xgettext:c-format */
935 non_fatal (_("Syntax error in def file %s:%d"), def_file
, linenumber
);
941 def_exports (name
, internal_name
, ordinal
, noname
, constant
, data
)
943 const char *internal_name
;
949 struct export
*p
= (struct export
*) xmalloc (sizeof (*p
));
952 p
->internal_name
= internal_name
? internal_name
: name
;
953 p
->ordinal
= ordinal
;
954 p
->constant
= constant
;
961 if ((internal_name
!= NULL
)
962 && (strchr (internal_name
, '.') != NULL
))
963 p
->forward
= ++d_nforwards
;
965 p
->forward
= 0; /* no forward */
969 def_name (name
, base
)
973 /* xgettext:c-format */
974 inform (_("NAME: %s base: %x"), name
, base
);
977 non_fatal (_("Can't have LIBRARY and NAME"));
980 /* If --dllname not provided, use the one in the DEF file.
981 FIXME: Is this appropriate for executables? */
983 dll_name
= xstrdup (name
);
988 def_library (name
, base
)
992 /* xgettext:c-format */
993 inform (_("LIBRARY: %s base: %x"), name
, base
);
996 non_fatal (_("Can't have LIBRARY and NAME"));
999 /* If --dllname not provided, use the one in the DEF file. */
1001 dll_name
= xstrdup (name
);
1006 def_description (desc
)
1009 dlist_type
*d
= (dlist_type
*) xmalloc (sizeof (dlist_type
));
1010 d
->text
= xstrdup (desc
);
1019 dlist_type
*d
= (dlist_type
*) xmalloc (sizeof (dlist_type
));
1020 d
->text
= xstrdup (dir
);
1026 def_heapsize (reserve
, commit
)
1032 sprintf (b
, "-heap 0x%x,0x%x ", reserve
, commit
);
1034 sprintf (b
, "-heap 0x%x ", reserve
);
1035 new_directive (xstrdup (b
));
1039 def_stacksize (reserve
, commit
)
1045 sprintf (b
, "-stack 0x%x,0x%x ", reserve
, commit
);
1047 sprintf (b
, "-stack 0x%x ", reserve
);
1048 new_directive (xstrdup (b
));
1051 /* append_import simply adds the given import definition to the global
1052 import_list. It is used by def_import. */
1055 append_import (symbol_name
, dll_name
, func_ordinal
)
1056 const char *symbol_name
;
1057 const char *dll_name
;
1063 for (pq
= &import_list
; *pq
!= NULL
; pq
= &(*pq
)->next
)
1065 if (strcmp ((*pq
)->dllname
, dll_name
) == 0)
1068 q
->functail
->next
= xmalloc (sizeof (ifunctype
));
1069 q
->functail
= q
->functail
->next
;
1070 q
->functail
->ord
= func_ordinal
;
1071 q
->functail
->name
= xstrdup (symbol_name
);
1072 q
->functail
->next
= NULL
;
1078 q
= xmalloc (sizeof (iheadtype
));
1079 q
->dllname
= xstrdup (dll_name
);
1081 q
->funchead
= xmalloc (sizeof (ifunctype
));
1082 q
->functail
= q
->funchead
;
1084 q
->functail
->name
= xstrdup (symbol_name
);
1085 q
->functail
->ord
= func_ordinal
;
1086 q
->functail
->next
= NULL
;
1091 /* def_import is called from within defparse.y when an IMPORT
1092 declaration is encountered. Depending on the form of the
1093 declaration, the module name may or may not need ".dll" to be
1094 appended to it, the name of the function may be stored in internal
1095 or entry, and there may or may not be an ordinal value associated
1098 /* A note regarding the parse modes:
1099 In defparse.y we have to accept import declarations which follow
1100 any one of the following forms:
1101 <func_name_in_app> = <dll_name>.<func_name_in_dll>
1102 <func_name_in_app> = <dll_name>.<number>
1103 <dll_name>.<func_name_in_dll>
1105 Furthermore, the dll's name may or may not end with ".dll", which
1106 complicates the parsing a little. Normally the dll's name is
1107 passed to def_import() in the "module" parameter, but when it ends
1108 with ".dll" it gets passed in "module" sans ".dll" and that needs
1111 def_import gets five parameters:
1112 APP_NAME - the name of the function in the application, if
1113 present, or NULL if not present.
1114 MODULE - the name of the dll, possibly sans extension (ie, '.dll').
1115 DLLEXT - the extension of the dll, if present, NULL if not present.
1116 ENTRY - the name of the function in the dll, if present, or NULL.
1117 ORD_VAL - the numerical tag of the function in the dll, if present,
1118 or NULL. Exactly one of <entry> or <ord_val> must be
1119 present (i.e., not NULL). */
1122 def_import (app_name
, module
, dllext
, entry
, ord_val
)
1123 const char *app_name
;
1129 const char *application_name
;
1133 application_name
= entry
;
1136 if (app_name
!= NULL
)
1137 application_name
= app_name
;
1139 application_name
= "";
1144 buf
= (char *) alloca (strlen (module
) + strlen (dllext
) + 2);
1145 sprintf (buf
, "%s.%s", module
, dllext
);
1149 append_import (application_name
, module
, ord_val
);
1153 def_version (major
, minor
)
1157 printf ("VERSION %d.%d\n", major
, minor
);
1161 def_section (name
, attr
)
1178 sprintf (buf
, "-attr %s %s", name
, atts
);
1179 new_directive (xstrdup (buf
));
1187 def_section ("CODE", attr
);
1194 def_section ("DATA", attr
);
1197 /**********************************************************************/
1205 int pid
, wait_status
;
1208 char *errmsg_fmt
, *errmsg_arg
;
1209 char *temp_base
= choose_temp_base ();
1211 inform ("run: %s %s", what
, args
);
1213 /* Count the args */
1215 for (s
= args
; *s
; s
++)
1219 argv
= alloca (sizeof (char *) * (i
+ 3));
1228 while (*s
!= ' ' && *s
!= 0)
1236 pid
= pexecute (argv
[0], (char * const *) argv
, program_name
, temp_base
,
1237 &errmsg_fmt
, &errmsg_arg
, PEXECUTE_ONE
| PEXECUTE_SEARCH
);
1241 inform (strerror (errno
));
1243 fatal (errmsg_fmt
, errmsg_arg
);
1246 pid
= pwait (pid
, & wait_status
, 0);
1250 /* xgettext:c-format */
1251 fatal (_("wait: %s"), strerror (errno
));
1253 else if (WIFSIGNALED (wait_status
))
1255 /* xgettext:c-format */
1256 fatal (_("subprocess got fatal signal %d"), WTERMSIG (wait_status
));
1258 else if (WIFEXITED (wait_status
))
1260 if (WEXITSTATUS (wait_status
) != 0)
1261 /* xgettext:c-format */
1262 non_fatal (_("%s exited with status %d"),
1263 what
, WEXITSTATUS (wait_status
));
1269 /* Look for a list of symbols to export in the .drectve section of
1270 ABFD. Pass each one to def_exports. */
1273 scan_drectve_symbols (abfd
)
1282 /* Look for .drectve's */
1283 s
= bfd_get_section_by_name (abfd
, DRECTVE_SECTION_NAME
);
1288 size
= bfd_get_section_size_before_reloc (s
);
1289 buf
= xmalloc (size
);
1291 bfd_get_section_contents (abfd
, s
, buf
, 0, size
);
1293 /* xgettext:c-format */
1294 inform (_("Sucking in info from %s section in %s"),
1295 DRECTVE_SECTION_NAME
, bfd_get_filename (abfd
));
1297 /* Search for -export: strings. The exported symbols can optionally
1298 have type tags (eg., -export:foo,data), so handle those as well.
1299 Currently only data tag is supported. */
1305 && strncmp (p
, "-export:", 8) == 0)
1309 flagword flags
= BSF_FUNCTION
;
1313 while (p
< e
&& *p
!= ',' && *p
!= ' ' && *p
!= '-')
1315 c
= xmalloc (p
- name
+ 1);
1316 memcpy (c
, name
, p
- name
);
1318 if (p
< e
&& *p
== ',') /* found type tag. */
1320 char *tag_start
= ++p
;
1321 while (p
< e
&& *p
!= ' ' && *p
!= '-')
1323 if (strncmp (tag_start
, "data", 4) == 0)
1324 flags
&= ~BSF_FUNCTION
;
1327 /* FIXME: The 5th arg is for the `constant' field.
1328 What should it be? Not that it matters since it's not
1329 currently useful. */
1330 def_exports (c
, 0, -1, 0, 0, ! (flags
& BSF_FUNCTION
));
1332 if (add_stdcall_alias
&& strchr (c
, '@'))
1334 int lead_at
= (*c
== '@') ;
1335 char *exported_name
= xstrdup (c
+ lead_at
);
1336 char *atsym
= strchr (exported_name
, '@');
1338 /* Note: stdcall alias symbols can never be data. */
1339 def_exports (exported_name
, xstrdup (c
), -1, 0, 0, 0);
1348 /* Look through the symbols in MINISYMS, and add each one to list of
1349 symbols to export. */
1352 scan_filtered_symbols (abfd
, minisyms
, symcount
, size
)
1359 bfd_byte
*from
, *fromend
;
1361 store
= bfd_make_empty_symbol (abfd
);
1363 bfd_fatal (bfd_get_filename (abfd
));
1365 from
= (bfd_byte
*) minisyms
;
1366 fromend
= from
+ symcount
* size
;
1367 for (; from
< fromend
; from
+= size
)
1370 const char *symbol_name
;
1372 sym
= bfd_minisymbol_to_symbol (abfd
, FALSE
, from
, store
);
1374 bfd_fatal (bfd_get_filename (abfd
));
1376 symbol_name
= bfd_asymbol_name (sym
);
1377 if (bfd_get_symbol_leading_char (abfd
) == symbol_name
[0])
1380 def_exports (xstrdup (symbol_name
) , 0, -1, 0, 0,
1381 ! (sym
->flags
& BSF_FUNCTION
));
1383 if (add_stdcall_alias
&& strchr (symbol_name
, '@'))
1385 int lead_at
= (*symbol_name
== '@');
1386 char *exported_name
= xstrdup (symbol_name
+ lead_at
);
1387 char *atsym
= strchr (exported_name
, '@');
1389 /* Note: stdcall alias symbols can never be data. */
1390 def_exports (exported_name
, xstrdup (symbol_name
), -1, 0, 0, 0);
1395 /* Add a list of symbols to exclude. */
1398 add_excludes (new_excludes
)
1399 const char *new_excludes
;
1402 char *exclude_string
;
1404 local_copy
= xstrdup (new_excludes
);
1406 exclude_string
= strtok (local_copy
, ",:");
1407 for (; exclude_string
; exclude_string
= strtok (NULL
, ",:"))
1409 struct string_list
*new_exclude
;
1411 new_exclude
= ((struct string_list
*)
1412 xmalloc (sizeof (struct string_list
)));
1413 new_exclude
->string
= (char *) xmalloc (strlen (exclude_string
) + 2);
1414 /* Don't add a leading underscore for fastcall symbols. */
1415 if (*exclude_string
== '@')
1416 sprintf (new_exclude
->string
, "%s", exclude_string
);
1418 sprintf (new_exclude
->string
, "_%s", exclude_string
);
1419 new_exclude
->next
= excludes
;
1420 excludes
= new_exclude
;
1422 /* xgettext:c-format */
1423 inform (_("Excluding symbol: %s"), exclude_string
);
1429 /* See if STRING is on the list of symbols to exclude. */
1432 match_exclude (string
)
1435 struct string_list
*excl_item
;
1437 for (excl_item
= excludes
; excl_item
; excl_item
= excl_item
->next
)
1438 if (strcmp (string
, excl_item
->string
) == 0)
1443 /* Add the default list of symbols to exclude. */
1446 set_default_excludes (void)
1448 add_excludes (default_excludes
);
1451 /* Choose which symbols to export. */
1454 filter_symbols (abfd
, minisyms
, symcount
, size
)
1460 bfd_byte
*from
, *fromend
, *to
;
1463 store
= bfd_make_empty_symbol (abfd
);
1465 bfd_fatal (bfd_get_filename (abfd
));
1467 from
= (bfd_byte
*) minisyms
;
1468 fromend
= from
+ symcount
* size
;
1469 to
= (bfd_byte
*) minisyms
;
1471 for (; from
< fromend
; from
+= size
)
1476 sym
= bfd_minisymbol_to_symbol (abfd
, FALSE
, (const PTR
) from
, store
);
1478 bfd_fatal (bfd_get_filename (abfd
));
1480 /* Check for external and defined only symbols. */
1481 keep
= (((sym
->flags
& BSF_GLOBAL
) != 0
1482 || (sym
->flags
& BSF_WEAK
) != 0
1483 || bfd_is_com_section (sym
->section
))
1484 && ! bfd_is_und_section (sym
->section
));
1486 keep
= keep
&& ! match_exclude (sym
->name
);
1490 memcpy (to
, from
, size
);
1495 return (to
- (bfd_byte
*) minisyms
) / size
;
1498 /* Export all symbols in ABFD, except for ones we were told not to
1502 scan_all_symbols (abfd
)
1509 /* Ignore bfds with an import descriptor table. We assume that any
1510 such BFD contains symbols which are exported from another DLL,
1511 and we don't want to reexport them from here. */
1512 if (bfd_get_section_by_name (abfd
, ".idata$4"))
1515 if (! (bfd_get_file_flags (abfd
) & HAS_SYMS
))
1517 /* xgettext:c-format */
1518 non_fatal (_("%s: no symbols"), bfd_get_filename (abfd
));
1522 symcount
= bfd_read_minisymbols (abfd
, FALSE
, &minisyms
, &size
);
1524 bfd_fatal (bfd_get_filename (abfd
));
1528 /* xgettext:c-format */
1529 non_fatal (_("%s: no symbols"), bfd_get_filename (abfd
));
1533 /* Discard the symbols we don't want to export. It's OK to do this
1534 in place; we'll free the storage anyway. */
1536 symcount
= filter_symbols (abfd
, minisyms
, symcount
, size
);
1537 scan_filtered_symbols (abfd
, minisyms
, symcount
, size
);
1542 /* Look at the object file to decide which symbols to export. */
1545 scan_open_obj_file (abfd
)
1548 if (export_all_symbols
)
1549 scan_all_symbols (abfd
);
1551 scan_drectve_symbols (abfd
);
1553 /* FIXME: we ought to read in and block out the base relocations. */
1555 /* xgettext:c-format */
1556 inform (_("Done reading %s"), bfd_get_filename (abfd
));
1560 scan_obj_file (filename
)
1561 const char *filename
;
1563 bfd
* f
= bfd_openr (filename
, 0);
1566 /* xgettext:c-format */
1567 fatal (_("Unable to open object file: %s"), filename
);
1569 /* xgettext:c-format */
1570 inform (_("Scanning object file %s"), filename
);
1572 if (bfd_check_format (f
, bfd_archive
))
1574 bfd
*arfile
= bfd_openr_next_archived_file (f
, 0);
1577 if (bfd_check_format (arfile
, bfd_object
))
1578 scan_open_obj_file (arfile
);
1580 arfile
= bfd_openr_next_archived_file (f
, arfile
);
1583 #ifdef DLLTOOL_MCORE_ELF
1584 if (mcore_elf_out_file
)
1585 inform (_("Cannot produce mcore-elf dll from archive file: %s"), filename
);
1588 else if (bfd_check_format (f
, bfd_object
))
1590 scan_open_obj_file (f
);
1592 #ifdef DLLTOOL_MCORE_ELF
1593 if (mcore_elf_out_file
)
1594 mcore_elf_cache_filename ((char *) filename
);
1601 /**********************************************************************/
1609 fprintf (f
, "%s ", ASM_C
);
1610 for (i
= 0; oav
[i
]; i
++)
1611 fprintf (f
, "%s ", oav
[i
]);
1613 for (i
= 0, exp
= d_exports
; exp
; i
++, exp
= exp
->next
)
1615 fprintf (f
, "%s %d = %s %s @ %d %s%s%s\n",
1621 exp
->noname
? "NONAME " : "",
1622 exp
->constant
? "CONSTANT" : "",
1623 exp
->data
? "DATA" : "");
1627 /* Generate the .exp file. */
1634 return *(const long *) a
- *(const long *) b
;
1638 flush_page (f
, need
, page_addr
, on_page
)
1646 /* Flush this page. */
1647 fprintf (f
, "\t%s\t0x%08x\t%s Starting RVA for chunk\n",
1651 fprintf (f
, "\t%s\t0x%x\t%s Size of block\n",
1653 (on_page
* 2) + (on_page
& 1) * 2 + 8,
1656 for (i
= 0; i
< on_page
; i
++)
1658 long needed
= need
[i
];
1661 needed
= ((needed
- page_addr
) | 0x3000) & 0xffff;
1663 fprintf (f
, "\t%s\t0x%lx\n", ASM_SHORT
, needed
);
1668 fprintf (f
, "\t%s\t0x%x\n", ASM_SHORT
, 0 | 0x0000);
1677 inform (_("Adding exports to output file"));
1679 fprintf (output_def
, ";");
1680 for (i
= 0; oav
[i
]; i
++)
1681 fprintf (output_def
, " %s", oav
[i
]);
1683 fprintf (output_def
, "\nEXPORTS\n");
1685 for (i
= 0, exp
= d_exports
; exp
; i
++, exp
= exp
->next
)
1687 char *quote
= strchr (exp
->name
, '.') ? "\"" : "";
1688 char *res
= cplus_demangle (exp
->internal_name
, DMGL_ANSI
| DMGL_PARAMS
);
1692 fprintf (output_def
,";\t%s\n", res
);
1696 if (strcmp (exp
->name
, exp
->internal_name
) == 0)
1699 fprintf (output_def
, "\t%s%s%s @ %d%s%s\n",
1704 exp
->noname
? " NONAME" : "",
1705 exp
->data
? " DATA" : "");
1709 char *quote1
= strchr (exp
->internal_name
, '.') ? "\"" : "";
1711 fprintf (output_def
, "\t%s%s%s = %s%s%s @ %d%s%s\n",
1719 exp
->noname
? " NONAME" : "",
1720 exp
->data
? " DATA" : "");
1724 inform (_("Added exports to output file"));
1727 /* generate_idata_ofile generates the portable assembly source code
1728 for the idata sections. It appends the source code to the end of
1732 generate_idata_ofile (filvar
)
1741 if (import_list
== NULL
)
1744 fprintf (filvar
, "%s Import data sections\n", ASM_C
);
1745 fprintf (filvar
, "\n\t.section\t.idata$2\n");
1746 fprintf (filvar
, "\t%s\tdoi_idata\n", ASM_GLOBAL
);
1747 fprintf (filvar
, "doi_idata:\n");
1750 for (headptr
= import_list
; headptr
!= NULL
; headptr
= headptr
->next
)
1752 fprintf (filvar
, "\t%slistone%d%s\t%s %s\n",
1753 ASM_RVA_BEFORE
, nheads
, ASM_RVA_AFTER
,
1754 ASM_C
, headptr
->dllname
);
1755 fprintf (filvar
, "\t%s\t0\n", ASM_LONG
);
1756 fprintf (filvar
, "\t%s\t0\n", ASM_LONG
);
1757 fprintf (filvar
, "\t%sdllname%d%s\n",
1758 ASM_RVA_BEFORE
, nheads
, ASM_RVA_AFTER
);
1759 fprintf (filvar
, "\t%slisttwo%d%s\n\n",
1760 ASM_RVA_BEFORE
, nheads
, ASM_RVA_AFTER
);
1764 fprintf (filvar
, "\t%s\t0\n", ASM_LONG
); /* NULL record at */
1765 fprintf (filvar
, "\t%s\t0\n", ASM_LONG
); /* end of idata$2 */
1766 fprintf (filvar
, "\t%s\t0\n", ASM_LONG
); /* section */
1767 fprintf (filvar
, "\t%s\t0\n", ASM_LONG
);
1768 fprintf (filvar
, "\t%s\t0\n", ASM_LONG
);
1770 fprintf (filvar
, "\n\t.section\t.idata$4\n");
1772 for (headptr
= import_list
; headptr
!= NULL
; headptr
= headptr
->next
)
1774 fprintf (filvar
, "listone%d:\n", headindex
);
1775 for ( funcindex
= 0; funcindex
< headptr
->nfuncs
; funcindex
++ )
1776 fprintf (filvar
, "\t%sfuncptr%d_%d%s\n",
1777 ASM_RVA_BEFORE
, headindex
, funcindex
, ASM_RVA_AFTER
);
1778 fprintf (filvar
,"\t%s\t0\n", ASM_LONG
); /* NULL terminating list */
1782 fprintf (filvar
, "\n\t.section\t.idata$5\n");
1784 for (headptr
= import_list
; headptr
!= NULL
; headptr
= headptr
->next
)
1786 fprintf (filvar
, "listtwo%d:\n", headindex
);
1787 for ( funcindex
= 0; funcindex
< headptr
->nfuncs
; funcindex
++ )
1788 fprintf (filvar
, "\t%sfuncptr%d_%d%s\n",
1789 ASM_RVA_BEFORE
, headindex
, funcindex
, ASM_RVA_AFTER
);
1790 fprintf (filvar
, "\t%s\t0\n", ASM_LONG
); /* NULL terminating list */
1794 fprintf (filvar
, "\n\t.section\t.idata$6\n");
1796 for (headptr
= import_list
; headptr
!= NULL
; headptr
= headptr
->next
)
1799 for (funcptr
= headptr
->funchead
; funcptr
!= NULL
;
1800 funcptr
= funcptr
->next
)
1802 fprintf (filvar
,"funcptr%d_%d:\n", headindex
, funcindex
);
1803 fprintf (filvar
,"\t%s\t%d\n", ASM_SHORT
,
1804 ((funcptr
->ord
) & 0xFFFF));
1805 fprintf (filvar
,"\t%s\t\"%s\"\n", ASM_TEXT
, funcptr
->name
);
1806 fprintf (filvar
,"\t%s\t0\n", ASM_BYTE
);
1812 fprintf (filvar
, "\n\t.section\t.idata$7\n");
1814 for (headptr
= import_list
; headptr
!= NULL
; headptr
= headptr
->next
)
1816 fprintf (filvar
,"dllname%d:\n", headindex
);
1817 fprintf (filvar
,"\t%s\t\"%s\"\n", ASM_TEXT
, headptr
->dllname
);
1818 fprintf (filvar
,"\t%s\t0\n", ASM_BYTE
);
1823 /* Assemble the specified file. */
1825 assemble_file (source
, dest
)
1826 const char * source
;
1831 cmd
= (char *) alloca (strlen (ASM_SWITCHES
) + strlen (as_flags
)
1832 + strlen (source
) + strlen (dest
) + 50);
1834 sprintf (cmd
, "%s %s -o %s %s", ASM_SWITCHES
, as_flags
, dest
, source
);
1847 /* xgettext:c-format */
1848 inform (_("Generating export file: %s"), exp_name
);
1850 f
= fopen (TMP_ASM
, FOPEN_WT
);
1852 /* xgettext:c-format */
1853 fatal (_("Unable to open temporary assembler file: %s"), TMP_ASM
);
1855 /* xgettext:c-format */
1856 inform (_("Opened temporary file: %s"), TMP_ASM
);
1862 fprintf (f
, "\t.section .edata\n\n");
1863 fprintf (f
, "\t%s 0 %s Allways 0\n", ASM_LONG
, ASM_C
);
1864 fprintf (f
, "\t%s 0x%lx %s Time and date\n", ASM_LONG
, (long) time(0),
1866 fprintf (f
, "\t%s 0 %s Major and Minor version\n", ASM_LONG
, ASM_C
);
1867 fprintf (f
, "\t%sname%s %s Ptr to name of dll\n", ASM_RVA_BEFORE
, ASM_RVA_AFTER
, ASM_C
);
1868 fprintf (f
, "\t%s %d %s Starting ordinal of exports\n", ASM_LONG
, d_low_ord
, ASM_C
);
1871 fprintf (f
, "\t%s %d %s Number of functions\n", ASM_LONG
, d_high_ord
- d_low_ord
+ 1, ASM_C
);
1872 fprintf(f
,"\t%s named funcs %d, low ord %d, high ord %d\n",
1874 d_named_nfuncs
, d_low_ord
, d_high_ord
);
1875 fprintf (f
, "\t%s %d %s Number of names\n", ASM_LONG
,
1876 show_allnames
? d_high_ord
- d_low_ord
+ 1 : d_named_nfuncs
, ASM_C
);
1877 fprintf (f
, "\t%safuncs%s %s Address of functions\n", ASM_RVA_BEFORE
, ASM_RVA_AFTER
, ASM_C
);
1879 fprintf (f
, "\t%sanames%s %s Address of Name Pointer Table\n",
1880 ASM_RVA_BEFORE
, ASM_RVA_AFTER
, ASM_C
);
1882 fprintf (f
, "\t%sanords%s %s Address of ordinals\n", ASM_RVA_BEFORE
, ASM_RVA_AFTER
, ASM_C
);
1884 fprintf (f
, "name: %s \"%s\"\n", ASM_TEXT
, dll_name
);
1887 fprintf(f
,"%s Export address Table\n", ASM_C
);
1888 fprintf(f
,"\t%s\n", ASM_ALIGN_LONG
);
1889 fprintf (f
, "afuncs:\n");
1892 for (exp
= d_exports
; exp
; exp
= exp
->next
)
1894 if (exp
->ordinal
!= i
)
1897 fprintf (f
, "\t%s\t%d\t%s %d..%d missing\n",
1899 (exp
->ordinal
- i
) * 4,
1901 i
, exp
->ordinal
- 1);
1904 while (i
< exp
->ordinal
)
1906 fprintf(f
,"\t%s\t0\n", ASM_LONG
);
1911 if (exp
->forward
== 0)
1913 if (exp
->internal_name
[0] == '@')
1914 fprintf (f
, "\t%s%s%s\t%s %d\n", ASM_RVA_BEFORE
,
1915 exp
->internal_name
, ASM_RVA_AFTER
, ASM_C
, exp
->ordinal
);
1917 fprintf (f
, "\t%s%s%s%s\t%s %d\n", ASM_RVA_BEFORE
,
1919 exp
->internal_name
, ASM_RVA_AFTER
, ASM_C
, exp
->ordinal
);
1922 fprintf (f
, "\t%sf%d%s\t%s %d\n", ASM_RVA_BEFORE
,
1923 exp
->forward
, ASM_RVA_AFTER
, ASM_C
, exp
->ordinal
);
1927 fprintf (f
,"%s Export Name Pointer Table\n", ASM_C
);
1928 fprintf (f
, "anames:\n");
1930 for (i
= 0; (exp
= d_exports_lexically
[i
]); i
++)
1932 if (!exp
->noname
|| show_allnames
)
1933 fprintf (f
, "\t%sn%d%s\n",
1934 ASM_RVA_BEFORE
, exp
->ordinal
, ASM_RVA_AFTER
);
1937 fprintf (f
,"%s Export Oridinal Table\n", ASM_C
);
1938 fprintf (f
, "anords:\n");
1939 for (i
= 0; (exp
= d_exports_lexically
[i
]); i
++)
1941 if (!exp
->noname
|| show_allnames
)
1942 fprintf (f
, "\t%s %d\n", ASM_SHORT
, exp
->ordinal
- d_low_ord
);
1945 fprintf(f
,"%s Export Name Table\n", ASM_C
);
1946 for (i
= 0; (exp
= d_exports_lexically
[i
]); i
++)
1947 if (!exp
->noname
|| show_allnames
)
1949 fprintf (f
, "n%d: %s \"%s\"\n",
1950 exp
->ordinal
, ASM_TEXT
, xlate (exp
->name
));
1951 if (exp
->forward
!= 0)
1952 fprintf (f
, "f%d: %s \"%s\"\n",
1953 exp
->forward
, ASM_TEXT
, exp
->internal_name
);
1958 fprintf (f
, "\t.section %s\n", DRECTVE_SECTION_NAME
);
1959 for (dl
= a_list
; dl
; dl
= dl
->next
)
1961 fprintf (f
, "\t%s\t\"%s\"\n", ASM_TEXT
, dl
->text
);
1967 fprintf (f
, "\t.section .rdata\n");
1968 for (dl
= d_list
; dl
; dl
= dl
->next
)
1973 /* We don't output as ascii because there can
1974 be quote characters in the string. */
1976 for (p
= dl
->text
; *p
; p
++)
1979 fprintf (f
, "\t%s\t", ASM_BYTE
);
1982 fprintf (f
, "%d", *p
);
1985 fprintf (f
, ",0\n");
1999 /* Add to the output file a way of getting to the exported names
2000 without using the import library. */
2003 fprintf (f
, "\t.section\t.rdata\n");
2004 for (i
= 0, exp
= d_exports
; exp
; i
++, exp
= exp
->next
)
2005 if (!exp
->noname
|| show_allnames
)
2007 /* We use a single underscore for MS compatibility, and a
2008 double underscore for backward compatibility with old
2010 if (create_compat_implib
)
2011 fprintf (f
, "\t%s\t__imp_%s\n", ASM_GLOBAL
, exp
->name
);
2012 fprintf (f
, "\t%s\t_imp__%s\n", ASM_GLOBAL
, exp
->name
);
2013 if (create_compat_implib
)
2014 fprintf (f
, "__imp_%s:\n", exp
->name
);
2015 fprintf (f
, "_imp__%s:\n", exp
->name
);
2016 fprintf (f
, "\t%s\t%s\n", ASM_LONG
, exp
->name
);
2020 /* Dump the reloc section if a base file is provided. */
2024 long need
[PAGE_SIZE
];
2031 fprintf (f
, "\t.section\t.init\n");
2032 fprintf (f
, "lab:\n");
2034 fseek (base_file
, 0, SEEK_END
);
2035 numbytes
= ftell (base_file
);
2036 fseek (base_file
, 0, SEEK_SET
);
2037 copy
= xmalloc (numbytes
);
2038 fread (copy
, 1, numbytes
, base_file
);
2039 num_entries
= numbytes
/ sizeof (long);
2042 fprintf (f
, "\t.section\t.reloc\n");
2048 qsort (copy
, num_entries
, sizeof (long), sfunc
);
2049 /* Delete duplcates */
2050 for (src
= 0; src
< num_entries
; src
++)
2052 if (last
!= copy
[src
])
2053 last
= copy
[dst
++] = copy
[src
];
2057 page_addr
= addr
& PAGE_MASK
; /* work out the page addr */
2059 for (j
= 0; j
< num_entries
; j
++)
2062 if ((addr
& PAGE_MASK
) != page_addr
)
2064 flush_page (f
, need
, page_addr
, on_page
);
2066 page_addr
= addr
& PAGE_MASK
;
2068 need
[on_page
++] = addr
;
2070 flush_page (f
, need
, page_addr
, on_page
);
2072 /* fprintf (f, "\t%s\t0,0\t%s End\n", ASM_LONG, ASM_C);*/
2076 generate_idata_ofile (f
);
2080 /* Assemble the file. */
2081 assemble_file (TMP_ASM
, exp_name
);
2083 if (dontdeltemps
== 0)
2086 inform (_("Generated exports file"));
2093 int lead_at
= (*name
== '@');
2095 if (add_underscore
&& !lead_at
)
2097 char *copy
= xmalloc (strlen (name
) + 2);
2100 strcpy (copy
+ 1, name
);
2109 p
= strchr (name
, '@');
2116 /**********************************************************************/
2125 if (exp
->noname
&& !show_allnames
)
2127 fprintf (f
, "\t%s\t0x%08x\n",
2129 exp
->ordinal
| 0x80000000); /* hint or orindal ?? */
2133 fprintf (f
, "\t%sID%d%s\n", ASM_RVA_BEFORE
,
2151 unsigned char *data
;
2166 #define TEXT_SEC_FLAGS \
2167 (SEC_ALLOC | SEC_LOAD | SEC_CODE | SEC_READONLY | SEC_HAS_CONTENTS)
2168 #define DATA_SEC_FLAGS (SEC_ALLOC | SEC_LOAD | SEC_DATA)
2169 #define BSS_SEC_FLAGS SEC_ALLOC
2171 #define INIT_SEC_DATA(id, name, flags, align) \
2172 { id, name, flags, align, NULL, NULL, NULL, 0, NULL }
2173 static sinfo secdata
[NSECS
] =
2175 INIT_SEC_DATA (TEXT
, ".text", TEXT_SEC_FLAGS
, 2),
2176 INIT_SEC_DATA (DATA
, ".data", DATA_SEC_FLAGS
, 2),
2177 INIT_SEC_DATA (BSS
, ".bss", BSS_SEC_FLAGS
, 2),
2178 INIT_SEC_DATA (IDATA7
, ".idata$7", SEC_HAS_CONTENTS
, 2),
2179 INIT_SEC_DATA (IDATA5
, ".idata$5", SEC_HAS_CONTENTS
, 2),
2180 INIT_SEC_DATA (IDATA4
, ".idata$4", SEC_HAS_CONTENTS
, 2),
2181 INIT_SEC_DATA (IDATA6
, ".idata$6", SEC_HAS_CONTENTS
, 1)
2186 /* Sections numbered to make the order the same as other PowerPC NT
2187 compilers. This also keeps funny alignment thingies from happening. */
2200 static sinfo secdata
[NSECS
] =
2202 { TEXT
, ".text", SEC_CODE
| SEC_HAS_CONTENTS
, 3},
2203 { PDATA
, ".pdata", SEC_HAS_CONTENTS
, 2},
2204 { RDATA
, ".reldata", SEC_HAS_CONTENTS
, 2},
2205 { IDATA5
, ".idata$5", SEC_HAS_CONTENTS
, 2},
2206 { IDATA4
, ".idata$4", SEC_HAS_CONTENTS
, 2},
2207 { IDATA6
, ".idata$6", SEC_HAS_CONTENTS
, 1},
2208 { IDATA7
, ".idata$7", SEC_HAS_CONTENTS
, 2},
2209 { DATA
, ".data", SEC_DATA
, 2},
2210 { BSS
, ".bss", 0, 2}
2215 /* This is what we're trying to make. We generate the imp symbols with
2216 both single and double underscores, for compatibility.
2219 .global _GetFileVersionInfoSizeW@8
2220 .global __imp_GetFileVersionInfoSizeW@8
2221 _GetFileVersionInfoSizeW@8:
2222 jmp * __imp_GetFileVersionInfoSizeW@8
2223 .section .idata$7 # To force loading of head
2224 .long __version_a_head
2225 # Import Address Table
2227 __imp_GetFileVersionInfoSizeW@8:
2230 # Import Lookup Table
2236 .asciz "GetFileVersionInfoSizeW"
2239 For the PowerPC, here's the variation on the above scheme:
2241 # Rather than a simple "jmp *", the code to get to the dll function
2244 lwz r11,[tocv]__imp_function_name(r2)
2245 # RELOC: 00000000 TOCREL16,TOCDEFN __imp_function_name
2253 make_label (prefix
, name
)
2257 int len
= strlen (ASM_PREFIX
) + strlen (prefix
) + strlen (name
);
2258 char *copy
= xmalloc (len
+1 );
2260 strcpy (copy
, ASM_PREFIX
);
2261 strcat (copy
, prefix
);
2262 strcat (copy
, name
);
2267 make_imp_label (prefix
, name
)
2276 len
= strlen (prefix
) + strlen (name
);
2277 copy
= xmalloc (len
+ 1);
2278 strcpy (copy
, prefix
);
2279 strcat (copy
, name
);
2283 len
= strlen (ASM_PREFIX
) + strlen (prefix
) + strlen (name
);
2284 copy
= xmalloc (len
+ 1);
2285 strcpy (copy
, prefix
);
2286 strcat (copy
, ASM_PREFIX
);
2287 strcat (copy
, name
);
2293 make_one_lib_file (exp
, i
)
2301 const char *prefix
= "d";
2304 name
= (char *) alloca (strlen (prefix
) + 10);
2305 sprintf (name
, "%ss%05d.s", prefix
, i
);
2306 f
= fopen (name
, FOPEN_WT
);
2307 fprintf (f
, "\t.text\n");
2308 fprintf (f
, "\t%s\t%s%s\n", ASM_GLOBAL
, ASM_PREFIX
, exp
->name
);
2309 if (create_compat_implib
)
2310 fprintf (f
, "\t%s\t__imp_%s\n", ASM_GLOBAL
, exp
->name
);
2311 fprintf (f
, "\t%s\t_imp__%s\n", ASM_GLOBAL
, exp
->name
);
2312 if (create_compat_implib
)
2313 fprintf (f
, "%s%s:\n\t%s\t__imp_%s\n", ASM_PREFIX
,
2314 exp
->name
, ASM_JUMP
, exp
->name
);
2316 fprintf (f
, "\t.section\t.idata$7\t%s To force loading of head\n", ASM_C
);
2317 fprintf (f
, "\t%s\t%s\n", ASM_LONG
, head_label
);
2320 fprintf (f
,"%s Import Address Table\n", ASM_C
);
2322 fprintf (f
, "\t.section .idata$5\n");
2323 if (create_compat_implib
)
2324 fprintf (f
, "__imp_%s:\n", exp
->name
);
2325 fprintf (f
, "_imp__%s:\n", exp
->name
);
2329 fprintf (f
, "\n%s Import Lookup Table\n", ASM_C
);
2330 fprintf (f
, "\t.section .idata$4\n");
2334 if(!exp
->noname
|| show_allnames
)
2336 fprintf (f
, "%s Hint/Name table\n", ASM_C
);
2337 fprintf (f
, "\t.section .idata$6\n");
2338 fprintf (f
, "ID%d:\t%s\t%d\n", exp
->ordinal
, ASM_SHORT
, exp
->hint
);
2339 fprintf (f
, "\t%s\t\"%s\"\n", ASM_TEXT
, xlate (exp
->name
));
2344 dest
= (char *) alloca (strlen (prefix
) + 10);
2345 sprintf (dest
, "%ss%05d.o", prefix
, i
);
2346 assemble_file (name
, dest
);
2351 asymbol
* exp_label
;
2352 asymbol
* iname
= 0;
2354 asymbol
* iname_lab
;
2355 asymbol
** iname_lab_pp
;
2356 asymbol
** iname_pp
;
2365 asymbol
* ptrs
[NSECS
+ 4 + EXTRA
+ 1];
2366 flagword applicable
;
2368 char * outname
= xmalloc (strlen (TMP_STUB
) + 10);
2372 sprintf (outname
, "%s%05d.o", TMP_STUB
, i
);
2374 abfd
= bfd_openw (outname
, HOW_BFD_WRITE_TARGET
);
2377 /* xgettext:c-format */
2378 fatal (_("bfd_open failed open stub file: %s"), outname
);
2380 /* xgettext:c-format */
2381 inform (_("Creating stub file: %s"), outname
);
2383 bfd_set_format (abfd
, bfd_object
);
2384 bfd_set_arch_mach (abfd
, HOW_BFD_ARCH
, 0);
2387 if (machine
== MARM_INTERWORK
|| machine
== MTHUMB
)
2388 bfd_set_private_flags (abfd
, F_INTERWORK
);
2391 applicable
= bfd_applicable_section_flags (abfd
);
2393 /* First make symbols for the sections. */
2394 for (i
= 0; i
< NSECS
; i
++)
2396 sinfo
*si
= secdata
+ i
;
2399 si
->sec
= bfd_make_section_old_way (abfd
, si
->name
);
2400 bfd_set_section_flags (abfd
,
2402 si
->flags
& applicable
);
2404 bfd_set_section_alignment(abfd
, si
->sec
, si
->align
);
2405 si
->sec
->output_section
= si
->sec
;
2406 si
->sym
= bfd_make_empty_symbol(abfd
);
2407 si
->sym
->name
= si
->sec
->name
;
2408 si
->sym
->section
= si
->sec
;
2409 si
->sym
->flags
= BSF_LOCAL
;
2411 ptrs
[oidx
] = si
->sym
;
2412 si
->sympp
= ptrs
+ oidx
;
2421 exp_label
= bfd_make_empty_symbol (abfd
);
2422 exp_label
->name
= make_imp_label ("", exp
->name
);
2424 /* On PowerPC, the function name points to a descriptor in
2425 the rdata section, the first element of which is a
2426 pointer to the code (..function_name), and the second
2427 points to the .toc. */
2429 if (machine
== MPPC
)
2430 exp_label
->section
= secdata
[RDATA
].sec
;
2433 exp_label
->section
= secdata
[TEXT
].sec
;
2435 exp_label
->flags
= BSF_GLOBAL
;
2436 exp_label
->value
= 0;
2439 if (machine
== MTHUMB
)
2440 bfd_coff_set_symbol_class (abfd
, exp_label
, C_THUMBEXTFUNC
);
2442 ptrs
[oidx
++] = exp_label
;
2445 /* Generate imp symbols with one underscore for Microsoft
2446 compatibility, and with two underscores for backward
2447 compatibility with old versions of cygwin. */
2448 if (create_compat_implib
)
2450 iname
= bfd_make_empty_symbol (abfd
);
2451 iname
->name
= make_imp_label ("___imp", exp
->name
);
2452 iname
->section
= secdata
[IDATA5
].sec
;
2453 iname
->flags
= BSF_GLOBAL
;
2457 iname2
= bfd_make_empty_symbol (abfd
);
2458 iname2
->name
= make_imp_label ("__imp_", exp
->name
);
2459 iname2
->section
= secdata
[IDATA5
].sec
;
2460 iname2
->flags
= BSF_GLOBAL
;
2463 iname_lab
= bfd_make_empty_symbol(abfd
);
2465 iname_lab
->name
= head_label
;
2466 iname_lab
->section
= (asection
*)&bfd_und_section
;
2467 iname_lab
->flags
= 0;
2468 iname_lab
->value
= 0;
2470 iname_pp
= ptrs
+ oidx
;
2471 if (create_compat_implib
)
2472 ptrs
[oidx
++] = iname
;
2473 ptrs
[oidx
++] = iname2
;
2475 iname_lab_pp
= ptrs
+ oidx
;
2476 ptrs
[oidx
++] = iname_lab
;
2479 /* The symbol refering to the code (.text). */
2481 asymbol
*function_name
;
2483 function_name
= bfd_make_empty_symbol(abfd
);
2484 function_name
->name
= make_label ("..", exp
->name
);
2485 function_name
->section
= secdata
[TEXT
].sec
;
2486 function_name
->flags
= BSF_GLOBAL
;
2487 function_name
->value
= 0;
2489 fn_pp
= ptrs
+ oidx
;
2490 ptrs
[oidx
++] = function_name
;
2493 /* The .toc symbol. */
2495 asymbol
*toc_symbol
;
2497 toc_symbol
= bfd_make_empty_symbol (abfd
);
2498 toc_symbol
->name
= make_label (".", "toc");
2499 toc_symbol
->section
= (asection
*)&bfd_und_section
;
2500 toc_symbol
->flags
= BSF_GLOBAL
;
2501 toc_symbol
->value
= 0;
2503 toc_pp
= ptrs
+ oidx
;
2504 ptrs
[oidx
++] = toc_symbol
;
2510 for (i
= 0; i
< NSECS
; i
++)
2512 sinfo
*si
= secdata
+ i
;
2513 asection
*sec
= si
->sec
;
2522 si
->size
= HOW_JTAB_SIZE
;
2523 si
->data
= xmalloc (HOW_JTAB_SIZE
);
2524 memcpy (si
->data
, HOW_JTAB
, HOW_JTAB_SIZE
);
2526 /* add the reloc into idata$5 */
2527 rel
= xmalloc (sizeof (arelent
));
2529 rpp
= xmalloc (sizeof (arelent
*) * 2);
2533 rel
->address
= HOW_JTAB_ROFF
;
2536 if (machine
== MPPC
)
2538 rel
->howto
= bfd_reloc_type_lookup (abfd
,
2539 BFD_RELOC_16_GOTOFF
);
2540 rel
->sym_ptr_ptr
= iname_pp
;
2544 rel
->howto
= bfd_reloc_type_lookup (abfd
, BFD_RELOC_32
);
2545 rel
->sym_ptr_ptr
= secdata
[IDATA5
].sympp
;
2547 sec
->orelocation
= rpp
;
2548 sec
->reloc_count
= 1;
2553 /* An idata$4 or idata$5 is one word long, and has an
2556 si
->data
= xmalloc (4);
2561 si
->data
[0] = exp
->ordinal
;
2562 si
->data
[1] = exp
->ordinal
>> 8;
2563 si
->data
[2] = exp
->ordinal
>> 16;
2568 sec
->reloc_count
= 1;
2569 memset (si
->data
, 0, si
->size
);
2570 rel
= xmalloc (sizeof (arelent
));
2571 rpp
= xmalloc (sizeof (arelent
*) * 2);
2576 rel
->howto
= bfd_reloc_type_lookup (abfd
, BFD_RELOC_RVA
);
2577 rel
->sym_ptr_ptr
= secdata
[IDATA6
].sympp
;
2578 sec
->orelocation
= rpp
;
2586 /* This used to add 1 to exp->hint. I don't know
2587 why it did that, and it does not match what I see
2588 in programs compiled with the MS tools. */
2589 int idx
= exp
->hint
;
2590 si
->size
= strlen (xlate (exp
->name
)) + 3;
2591 si
->data
= xmalloc (si
->size
);
2592 si
->data
[0] = idx
& 0xff;
2593 si
->data
[1] = idx
>> 8;
2594 strcpy (si
->data
+ 2, xlate (exp
->name
));
2599 si
->data
=xmalloc (4);
2600 memset (si
->data
, 0, si
->size
);
2601 rel
= xmalloc (sizeof (arelent
));
2602 rpp
= xmalloc (sizeof (arelent
*) * 2);
2606 rel
->howto
= bfd_reloc_type_lookup (abfd
, BFD_RELOC_RVA
);
2607 rel
->sym_ptr_ptr
= iname_lab_pp
;
2608 sec
->orelocation
= rpp
;
2609 sec
->reloc_count
= 1;
2615 /* The .pdata section is 5 words long.
2619 bfd_vma BeginAddress, [0x00]
2621 ExceptionHandler, [0x08]
2623 PrologEndAddress; [0x10]
2626 /* So this pdata section setups up this as a glue linkage to
2627 a dll routine. There are a number of house keeping things
2630 1. In the name of glue trickery, the ADDR32 relocs for 0,
2631 4, and 0x10 are set to point to the same place:
2633 2. There is one more reloc needed in the pdata section.
2634 The actual glue instruction to restore the toc on
2635 return is saved as the offset in an IMGLUE reloc.
2636 So we need a total of four relocs for this section.
2638 3. Lastly, the HandlerData field is set to 0x03, to indicate
2639 that this is a glue routine. */
2640 arelent
*imglue
, *ba_rel
, *ea_rel
, *pea_rel
;
2642 /* Alignment must be set to 2**2 or you get extra stuff. */
2643 bfd_set_section_alignment(abfd
, sec
, 2);
2646 si
->data
= xmalloc (si
->size
);
2647 memset (si
->data
, 0, si
->size
);
2648 rpp
= xmalloc (sizeof (arelent
*) * 5);
2649 rpp
[0] = imglue
= xmalloc (sizeof (arelent
));
2650 rpp
[1] = ba_rel
= xmalloc (sizeof (arelent
));
2651 rpp
[2] = ea_rel
= xmalloc (sizeof (arelent
));
2652 rpp
[3] = pea_rel
= xmalloc (sizeof (arelent
));
2655 /* Stick the toc reload instruction in the glue reloc. */
2656 bfd_put_32(abfd
, ppc_glue_insn
, (char *) &imglue
->address
);
2659 imglue
->howto
= bfd_reloc_type_lookup (abfd
,
2660 BFD_RELOC_32_GOTOFF
);
2661 imglue
->sym_ptr_ptr
= fn_pp
;
2663 ba_rel
->address
= 0;
2665 ba_rel
->howto
= bfd_reloc_type_lookup (abfd
, BFD_RELOC_32
);
2666 ba_rel
->sym_ptr_ptr
= fn_pp
;
2668 bfd_put_32 (abfd
, 0x18, si
->data
+ 0x04);
2669 ea_rel
->address
= 4;
2671 ea_rel
->howto
= bfd_reloc_type_lookup (abfd
, BFD_RELOC_32
);
2672 ea_rel
->sym_ptr_ptr
= fn_pp
;
2674 /* Mark it as glue. */
2675 bfd_put_32 (abfd
, 0x03, si
->data
+ 0x0c);
2677 /* Mark the prolog end address. */
2678 bfd_put_32 (abfd
, 0x0D, si
->data
+ 0x10);
2679 pea_rel
->address
= 0x10;
2680 pea_rel
->addend
= 0;
2681 pea_rel
->howto
= bfd_reloc_type_lookup (abfd
, BFD_RELOC_32
);
2682 pea_rel
->sym_ptr_ptr
= fn_pp
;
2684 sec
->orelocation
= rpp
;
2685 sec
->reloc_count
= 4;
2689 /* Each external function in a PowerPC PE file has a two word
2690 descriptor consisting of:
2691 1. The address of the code.
2692 2. The address of the appropriate .toc
2693 We use relocs to build this. */
2695 si
->data
= xmalloc (8);
2696 memset (si
->data
, 0, si
->size
);
2698 rpp
= xmalloc (sizeof (arelent
*) * 3);
2699 rpp
[0] = rel
= xmalloc (sizeof (arelent
));
2700 rpp
[1] = xmalloc (sizeof (arelent
));
2705 rel
->howto
= bfd_reloc_type_lookup (abfd
, BFD_RELOC_32
);
2706 rel
->sym_ptr_ptr
= fn_pp
;
2712 rel
->howto
= bfd_reloc_type_lookup (abfd
, BFD_RELOC_32
);
2713 rel
->sym_ptr_ptr
= toc_pp
;
2715 sec
->orelocation
= rpp
;
2716 sec
->reloc_count
= 2;
2718 #endif /* DLLTOOL_PPC */
2724 /* Size up all the sections. */
2725 for (i
= 0; i
< NSECS
; i
++)
2727 sinfo
*si
= secdata
+ i
;
2729 bfd_set_section_size (abfd
, si
->sec
, si
->size
);
2730 bfd_set_section_vma (abfd
, si
->sec
, vma
);
2732 /* vma += si->size;*/
2735 /* Write them out. */
2736 for (i
= 0; i
< NSECS
; i
++)
2738 sinfo
*si
= secdata
+ i
;
2740 if (i
== IDATA5
&& no_idata5
)
2743 if (i
== IDATA4
&& no_idata4
)
2746 bfd_set_section_contents (abfd
, si
->sec
,
2751 bfd_set_symtab (abfd
, ptrs
, oidx
);
2753 abfd
= bfd_openr (outname
, HOW_BFD_READ_TARGET
);
2762 FILE *f
= fopen (TMP_HEAD_S
, FOPEN_WT
);
2766 fatal (_("failed to open temporary head file: %s"), TMP_HEAD_S
);
2770 fprintf (f
, "%s IMAGE_IMPORT_DESCRIPTOR\n", ASM_C
);
2771 fprintf (f
, "\t.section .idata$2\n");
2773 fprintf(f
,"\t%s\t%s\n", ASM_GLOBAL
,head_label
);
2775 fprintf (f
, "%s:\n", head_label
);
2777 fprintf (f
, "\t%shname%s\t%sPtr to image import by name list\n",
2778 ASM_RVA_BEFORE
, ASM_RVA_AFTER
, ASM_C
);
2780 fprintf (f
, "\t%sthis should be the timestamp, but NT sometimes\n", ASM_C
);
2781 fprintf (f
, "\t%sdoesn't load DLLs when this is set.\n", ASM_C
);
2782 fprintf (f
, "\t%s\t0\t%s loaded time\n", ASM_LONG
, ASM_C
);
2783 fprintf (f
, "\t%s\t0\t%s Forwarder chain\n", ASM_LONG
, ASM_C
);
2784 fprintf (f
, "\t%s__%s_iname%s\t%s imported dll's name\n",
2789 fprintf (f
, "\t%sfthunk%s\t%s pointer to firstthunk\n",
2791 ASM_RVA_AFTER
, ASM_C
);
2793 fprintf (f
, "%sStuff for compatibility\n", ASM_C
);
2797 fprintf (f
, "\t.section\t.idata$5\n");
2798 fprintf (f
, "\t%s\t0\n", ASM_LONG
);
2799 fprintf (f
, "fthunk:\n");
2804 fprintf (f
, "\t.section\t.idata$4\n");
2806 fprintf (f
, "\t%s\t0\n", ASM_LONG
);
2807 fprintf (f
, "\t.section .idata$4\n");
2808 fprintf (f
, "hname:\n");
2813 assemble_file (TMP_HEAD_S
, TMP_HEAD_O
);
2815 return bfd_openr (TMP_HEAD_O
, HOW_BFD_READ_TARGET
);
2821 FILE *f
= fopen (TMP_TAIL_S
, FOPEN_WT
);
2825 fatal (_("failed to open temporary tail file: %s"), TMP_TAIL_S
);
2831 fprintf (f
, "\t.section .idata$4\n");
2832 fprintf (f
, "\t%s\t0\n", ASM_LONG
);
2837 fprintf (f
, "\t.section .idata$5\n");
2838 fprintf (f
, "\t%s\t0\n", ASM_LONG
);
2842 /* Normally, we need to see a null descriptor built in idata$3 to
2843 act as the terminator for the list. The ideal way, I suppose,
2844 would be to mark this section as a comdat type 2 section, so
2845 only one would appear in the final .exe (if our linker supported
2846 comdat, that is) or cause it to be inserted by something else (say
2849 fprintf (f
, "\t.section .idata$3\n");
2850 fprintf (f
, "\t%s\t0\n", ASM_LONG
);
2851 fprintf (f
, "\t%s\t0\n", ASM_LONG
);
2852 fprintf (f
, "\t%s\t0\n", ASM_LONG
);
2853 fprintf (f
, "\t%s\t0\n", ASM_LONG
);
2854 fprintf (f
, "\t%s\t0\n", ASM_LONG
);
2858 /* Other PowerPC NT compilers use idata$6 for the dllname, so I
2859 do too. Original, huh? */
2860 fprintf (f
, "\t.section .idata$6\n");
2862 fprintf (f
, "\t.section .idata$7\n");
2865 fprintf (f
, "\t%s\t__%s_iname\n", ASM_GLOBAL
, imp_name_lab
);
2866 fprintf (f
, "__%s_iname:\t%s\t\"%s\"\n",
2867 imp_name_lab
, ASM_TEXT
, dll_name
);
2871 assemble_file (TMP_TAIL_S
, TMP_TAIL_O
);
2873 return bfd_openr (TMP_TAIL_O
, HOW_BFD_READ_TARGET
);
2888 outarch
= bfd_openw (imp_name
, HOW_BFD_WRITE_TARGET
);
2891 /* xgettext:c-format */
2892 fatal (_("Can't open .lib file: %s"), imp_name
);
2894 /* xgettext:c-format */
2895 inform (_("Creating library file: %s"), imp_name
);
2897 bfd_set_format (outarch
, bfd_archive
);
2898 outarch
->has_armap
= 1;
2900 /* Work out a reasonable size of things to put onto one line. */
2901 ar_head
= make_head ();
2902 ar_tail
= make_tail();
2904 if (ar_head
== NULL
|| ar_tail
== NULL
)
2907 for (i
= 0; (exp
= d_exports_lexically
[i
]); i
++)
2909 bfd
*n
= make_one_lib_file (exp
, i
);
2914 /* Now stick them all into the archive. */
2915 ar_head
->next
= head
;
2916 ar_tail
->next
= ar_head
;
2919 if (! bfd_set_archive_head (outarch
, head
))
2920 bfd_fatal ("bfd_set_archive_head");
2922 if (! bfd_close (outarch
))
2923 bfd_fatal (imp_name
);
2925 while (head
!= NULL
)
2927 bfd
*n
= head
->next
;
2932 /* Delete all the temp files. */
2933 if (dontdeltemps
== 0)
2935 unlink (TMP_HEAD_O
);
2936 unlink (TMP_HEAD_S
);
2937 unlink (TMP_TAIL_O
);
2938 unlink (TMP_TAIL_S
);
2941 if (dontdeltemps
< 2)
2945 name
= (char *) alloca (strlen (TMP_STUB
) + 10);
2946 for (i
= 0, exp
= d_exports
; exp
; i
++, exp
= exp
->next
)
2948 sprintf (name
, "%s%05d.o", TMP_STUB
, i
);
2949 if (unlink (name
) < 0)
2950 /* xgettext:c-format */
2951 non_fatal (_("cannot delete %s: %s"), name
, strerror (errno
));
2955 inform (_("Created lib file"));
2958 /**********************************************************************/
2960 /* Run through the information gathered from the .o files and the
2961 .def file and work out the best stuff. */
2967 export_type
*ap
= *(export_type
**) a
;
2968 export_type
*bp
= *(export_type
**) b
;
2969 if (ap
->ordinal
== bp
->ordinal
)
2972 /* Unset ordinals go to the bottom. */
2973 if (ap
->ordinal
== -1)
2975 if (bp
->ordinal
== -1)
2977 return (ap
->ordinal
- bp
->ordinal
);
2985 export_type
*ap
= *(export_type
**) a
;
2986 export_type
*bp
= *(export_type
**) b
;
2988 return (strcmp (ap
->name
, bp
->name
));
2992 remove_null_names (ptr
)
2998 for (dst
= src
= 0; src
< d_nfuncs
; src
++)
3002 ptr
[dst
] = ptr
[src
];
3019 for (i
= 0; i
< d_nfuncs
; i
++)
3023 printf ("%d %s @ %d %s%s%s\n",
3024 i
, ptr
[i
]->name
, ptr
[i
]->ordinal
,
3025 ptr
[i
]->noname
? "NONAME " : "",
3026 ptr
[i
]->constant
? "CONSTANT" : "",
3027 ptr
[i
]->data
? "DATA" : "");
3036 process_duplicates (d_export_vec
)
3037 export_type
**d_export_vec
;
3046 /* Remove duplicates. */
3047 qsort (d_export_vec
, d_nfuncs
, sizeof (export_type
*), nfunc
);
3049 dtab (d_export_vec
);
3050 for (i
= 0; i
< d_nfuncs
- 1; i
++)
3052 if (strcmp (d_export_vec
[i
]->name
,
3053 d_export_vec
[i
+ 1]->name
) == 0)
3056 export_type
*a
= d_export_vec
[i
];
3057 export_type
*b
= d_export_vec
[i
+ 1];
3061 /* xgettext:c-format */
3062 inform (_("Warning, ignoring duplicate EXPORT %s %d,%d"),
3063 a
->name
, a
->ordinal
, b
->ordinal
);
3065 if (a
->ordinal
!= -1
3066 && b
->ordinal
!= -1)
3067 /* xgettext:c-format */
3068 fatal (_("Error, duplicate EXPORT with oridinals: %s"),
3071 /* Merge attributes. */
3072 b
->ordinal
= a
->ordinal
> 0 ? a
->ordinal
: b
->ordinal
;
3073 b
->constant
|= a
->constant
;
3074 b
->noname
|= a
->noname
;
3076 d_export_vec
[i
] = 0;
3079 dtab (d_export_vec
);
3080 remove_null_names (d_export_vec
);
3081 dtab (d_export_vec
);
3086 /* Count the names. */
3087 for (i
= 0; i
< d_nfuncs
; i
++)
3089 if (!d_export_vec
[i
]->noname
)
3095 fill_ordinals (d_export_vec
)
3096 export_type
**d_export_vec
;
3103 qsort (d_export_vec
, d_nfuncs
, sizeof (export_type
*), pfunc
);
3105 /* Fill in the unset ordinals with ones from our range. */
3106 ptr
= (char *) xmalloc (size
);
3108 memset (ptr
, 0, size
);
3110 /* Mark in our large vector all the numbers that are taken. */
3111 for (i
= 0; i
< d_nfuncs
; i
++)
3113 if (d_export_vec
[i
]->ordinal
!= -1)
3115 ptr
[d_export_vec
[i
]->ordinal
] = 1;
3117 if (lowest
== -1 || d_export_vec
[i
]->ordinal
< lowest
)
3118 lowest
= d_export_vec
[i
]->ordinal
;
3122 /* Start at 1 for compatibility with MS toolchain. */
3126 /* Now fill in ordinals where the user wants us to choose. */
3127 for (i
= 0; i
< d_nfuncs
; i
++)
3129 if (d_export_vec
[i
]->ordinal
== -1)
3133 /* First try within or after any user supplied range. */
3134 for (j
= lowest
; j
< size
; j
++)
3138 d_export_vec
[i
]->ordinal
= j
;
3142 /* Then try before the range. */
3143 for (j
= lowest
; j
>0; j
--)
3147 d_export_vec
[i
]->ordinal
= j
;
3157 qsort (d_export_vec
, d_nfuncs
, sizeof (export_type
*), pfunc
);
3159 /* Work out the lowest and highest ordinal numbers. */
3162 if (d_export_vec
[0])
3163 d_low_ord
= d_export_vec
[0]->ordinal
;
3164 if (d_export_vec
[d_nfuncs
-1])
3165 d_high_ord
= d_export_vec
[d_nfuncs
-1]->ordinal
;
3174 const export_type
**a
= (const export_type
**) av
;
3175 const export_type
**b
= (const export_type
**) bv
;
3177 return strcmp ((*a
)->name
, (*b
)->name
);
3183 /* First work out the minimum ordinal chosen. */
3188 export_type
**d_export_vec
3189 = (export_type
**) xmalloc (sizeof (export_type
*) * d_nfuncs
);
3191 inform (_("Processing definitions"));
3193 for (i
= 0, exp
= d_exports
; exp
; i
++, exp
= exp
->next
)
3194 d_export_vec
[i
] = exp
;
3196 process_duplicates (d_export_vec
);
3197 fill_ordinals (d_export_vec
);
3199 /* Put back the list in the new order. */
3201 for (i
= d_nfuncs
- 1; i
>= 0; i
--)
3203 d_export_vec
[i
]->next
= d_exports
;
3204 d_exports
= d_export_vec
[i
];
3207 /* Build list in alpha order. */
3208 d_exports_lexically
= (export_type
**)
3209 xmalloc (sizeof (export_type
*) * (d_nfuncs
+ 1));
3211 for (i
= 0, exp
= d_exports
; exp
; i
++, exp
= exp
->next
)
3212 d_exports_lexically
[i
] = exp
;
3214 d_exports_lexically
[i
] = 0;
3216 qsort (d_exports_lexically
, i
, sizeof (export_type
*), alphafunc
);
3218 /* Fill exp entries with their hint values. */
3219 for (i
= 0; i
< d_nfuncs
; i
++)
3220 if (!d_exports_lexically
[i
]->noname
|| show_allnames
)
3221 d_exports_lexically
[i
]->hint
= hint
++;
3223 inform (_("Processed definitions"));
3226 /**********************************************************************/
3229 usage (file
, status
)
3233 /* xgetext:c-format */
3234 fprintf (file
, _("Usage %s <option(s)> <object-file(s)>\n"), program_name
);
3235 /* xgetext:c-format */
3236 fprintf (file
, _(" -m --machine <machine> Create as DLL for <machine>. [default: %s]\n"), mname
);
3237 fprintf (file
, _(" possible <machine>: arm[_interwork], i386, mcore[-elf]{-le|-be}, ppc, thumb\n"));
3238 fprintf (file
, _(" -e --output-exp <outname> Generate an export file.\n"));
3239 fprintf (file
, _(" -l --output-lib <outname> Generate an interface library.\n"));
3240 fprintf (file
, _(" -a --add-indirect Add dll indirects to export file.\n"));
3241 fprintf (file
, _(" -D --dllname <name> Name of input dll to put into interface lib.\n"));
3242 fprintf (file
, _(" -d --input-def <deffile> Name of .def file to be read in.\n"));
3243 fprintf (file
, _(" -z --output-def <deffile> Name of .def file to be created.\n"));
3244 fprintf (file
, _(" --export-all-symbols Export all symbols to .def\n"));
3245 fprintf (file
, _(" --no-export-all-symbols Only export listed symbols\n"));
3246 fprintf (file
, _(" --exclude-symbols <list> Don't export <list>\n"));
3247 fprintf (file
, _(" --no-default-excludes Clear default exclude symbols\n"));
3248 fprintf (file
, _(" -b --base-file <basefile> Read linker generated base file.\n"));
3249 fprintf (file
, _(" -x --no-idata4 Don't generate idata$4 section.\n"));
3250 fprintf (file
, _(" -c --no-idata5 Don't generate idata$5 section.\n"));
3251 fprintf (file
, _(" -U --add-underscore Add underscores to symbols in interface library.\n"));
3252 fprintf (file
, _(" -k --kill-at Kill @<n> from exported names.\n"));
3253 fprintf (file
, _(" -A --add-stdcall-alias Add aliases without @<n>.\n"));
3254 fprintf (file
, _(" -S --as <name> Use <name> for assembler.\n"));
3255 fprintf (file
, _(" -f --as-flags <flags> Pass <flags> to the assembler.\n"));
3256 fprintf (file
, _(" -C --compat-implib Create backward compatible import library.\n"));
3257 fprintf (file
, _(" -n --no-delete Keep temp files (repeat for extra preservation).\n"));
3258 fprintf (file
, _(" -v --verbose Be verbose.\n"));
3259 fprintf (file
, _(" -V --version Display the program version.\n"));
3260 fprintf (file
, _(" -h --help Display this information.\n"));
3261 #ifdef DLLTOOL_MCORE_ELF
3262 fprintf (file
, _(" -M --mcore-elf <outname> Process mcore-elf object files into <outname>.\n"));
3263 fprintf (file
, _(" -L --linker <name> Use <name> as the linker.\n"));
3264 fprintf (file
, _(" -F --linker-flags <flags> Pass <flags> to the linker.\n"));
3269 #define OPTION_EXPORT_ALL_SYMS 150
3270 #define OPTION_NO_EXPORT_ALL_SYMS (OPTION_EXPORT_ALL_SYMS + 1)
3271 #define OPTION_EXCLUDE_SYMS (OPTION_NO_EXPORT_ALL_SYMS + 1)
3272 #define OPTION_NO_DEFAULT_EXCLUDES (OPTION_EXCLUDE_SYMS + 1)
3274 static const struct option long_options
[] =
3276 {"no-delete", no_argument
, NULL
, 'n'},
3277 {"dllname", required_argument
, NULL
, 'D'},
3278 {"no-idata4", no_argument
, NULL
, 'x'},
3279 {"no-idata5", no_argument
, NULL
, 'c'},
3280 {"output-exp", required_argument
, NULL
, 'e'},
3281 {"output-def", required_argument
, NULL
, 'z'},
3282 {"export-all-symbols", no_argument
, NULL
, OPTION_EXPORT_ALL_SYMS
},
3283 {"no-export-all-symbols", no_argument
, NULL
, OPTION_NO_EXPORT_ALL_SYMS
},
3284 {"exclude-symbols", required_argument
, NULL
, OPTION_EXCLUDE_SYMS
},
3285 {"no-default-excludes", no_argument
, NULL
, OPTION_NO_DEFAULT_EXCLUDES
},
3286 {"output-lib", required_argument
, NULL
, 'l'},
3287 {"def", required_argument
, NULL
, 'd'}, /* for compatiblity with older versions */
3288 {"input-def", required_argument
, NULL
, 'd'},
3289 {"add-underscore", no_argument
, NULL
, 'U'},
3290 {"kill-at", no_argument
, NULL
, 'k'},
3291 {"add-stdcall-alias", no_argument
, NULL
, 'A'},
3292 {"verbose", no_argument
, NULL
, 'v'},
3293 {"version", no_argument
, NULL
, 'V'},
3294 {"help", no_argument
, NULL
, 'h'},
3295 {"machine", required_argument
, NULL
, 'm'},
3296 {"add-indirect", no_argument
, NULL
, 'a'},
3297 {"base-file", required_argument
, NULL
, 'b'},
3298 {"as", required_argument
, NULL
, 'S'},
3299 {"as-flags", required_argument
, NULL
, 'f'},
3300 {"mcore-elf", required_argument
, NULL
, 'M'},
3301 {"compat-implib", no_argument
, NULL
, 'C'},
3302 {"temp-prefix", required_argument
, NULL
, 't'},
3306 int main
PARAMS ((int, char **));
3316 program_name
= av
[0];
3319 #if defined (HAVE_SETLOCALE) && defined (HAVE_LC_MESSAGES)
3320 setlocale (LC_MESSAGES
, "");
3322 #if defined (HAVE_SETLOCALE)
3323 setlocale (LC_CTYPE
, "");
3325 bindtextdomain (PACKAGE
, LOCALEDIR
);
3326 textdomain (PACKAGE
);
3328 while ((c
= getopt_long (ac
, av
,
3329 #ifdef DLLTOOL_MCORE_ELF
3330 "m:e:l:aD:d:z:b:xcCuUkAS:f:nvVHhM:L:F:",
3332 "m:e:l:aD:d:z:b:xcCuUkAS:f:nvVHh",
3339 case OPTION_EXPORT_ALL_SYMS
:
3340 export_all_symbols
= TRUE
;
3342 case OPTION_NO_EXPORT_ALL_SYMS
:
3343 export_all_symbols
= FALSE
;
3345 case OPTION_EXCLUDE_SYMS
:
3346 add_excludes (optarg
);
3348 case OPTION_NO_DEFAULT_EXCLUDES
:
3349 do_default_excludes
= FALSE
;
3361 tmp_prefix
= optarg
;
3367 /* ignored for compatibility */
3374 output_def
= fopen (optarg
, FOPEN_WT
);
3396 print_version (program_name
);
3405 add_stdcall_alias
= 1;
3414 base_file
= fopen (optarg
, FOPEN_RB
);
3417 /* xgettext:c-format */
3418 fatal (_("Unable to open base-file: %s"), optarg
);
3421 #ifdef DLLTOOL_MCORE_ELF
3423 mcore_elf_out_file
= optarg
;
3426 mcore_elf_linker
= optarg
;
3429 mcore_elf_linker_flags
= optarg
;
3433 create_compat_implib
= 1;
3442 tmp_prefix
= prefix_encode ("d", getpid ());
3444 for (i
= 0; mtable
[i
].type
; i
++)
3445 if (strcmp (mtable
[i
].type
, mname
) == 0)
3448 if (!mtable
[i
].type
)
3449 /* xgettext:c-format */
3450 fatal (_("Machine '%s' not supported"), mname
);
3454 if (!dll_name
&& exp_name
)
3456 int len
= strlen (exp_name
) + 5;
3457 dll_name
= xmalloc (len
);
3458 strcpy (dll_name
, exp_name
);
3459 strcat (dll_name
, ".dll");
3462 if (as_name
== NULL
)
3463 as_name
= deduce_name ("as");
3465 /* Don't use the default exclude list if we're reading only the
3466 symbols in the .drectve section. The default excludes are meant
3467 to avoid exporting DLL entry point and Cygwin32 impure_ptr. */
3468 if (! export_all_symbols
)
3469 do_default_excludes
= FALSE
;
3471 if (do_default_excludes
)
3472 set_default_excludes ();
3475 process_def_file (def_file
);
3480 firstarg
= av
[optind
];
3481 scan_obj_file (av
[optind
]);
3492 /* Make imp_name safe for use as a label. */
3495 imp_name_lab
= xstrdup (imp_name
);
3496 for (p
= imp_name_lab
; *p
; p
++)
3501 head_label
= make_label("_head_", imp_name_lab
);
3508 #ifdef DLLTOOL_MCORE_ELF
3509 if (mcore_elf_out_file
)
3510 mcore_elf_gen_out_file ();
3516 /* Look for the program formed by concatenating PROG_NAME and the
3517 string running from PREFIX to END_PREFIX. If the concatenated
3518 string contains a '/', try appending EXECUTABLE_SUFFIX if it is
3522 look_for_prog (prog_name
, prefix
, end_prefix
)
3523 const char *prog_name
;
3530 cmd
= xmalloc (strlen (prefix
)
3531 + strlen (prog_name
)
3532 #ifdef HAVE_EXECUTABLE_SUFFIX
3533 + strlen (EXECUTABLE_SUFFIX
)
3536 strcpy (cmd
, prefix
);
3538 sprintf (cmd
+ end_prefix
, "%s", prog_name
);
3540 if (strchr (cmd
, '/') != NULL
)
3544 found
= (stat (cmd
, &s
) == 0
3545 #ifdef HAVE_EXECUTABLE_SUFFIX
3546 || stat (strcat (cmd
, EXECUTABLE_SUFFIX
), &s
) == 0
3552 /* xgettext:c-format */
3553 inform (_("Tried file: %s"), cmd
);
3559 /* xgettext:c-format */
3560 inform (_("Using file: %s"), cmd
);
3565 /* Deduce the name of the program we are want to invoke.
3566 PROG_NAME is the basic name of the program we want to run,
3567 eg "as" or "ld". The catch is that we might want actually
3568 run "i386-pe-as" or "ppc-pe-ld".
3570 If argv[0] contains the full path, then try to find the program
3571 in the same place, with and then without a target-like prefix.
3573 Given, argv[0] = /usr/local/bin/i586-cygwin32-dlltool,
3574 deduce_name("as") uses the following search order:
3576 /usr/local/bin/i586-cygwin32-as
3580 If there's an EXECUTABLE_SUFFIX, it'll use that as well; for each
3581 name, it'll try without and then with EXECUTABLE_SUFFIX.
3583 Given, argv[0] = i586-cygwin32-dlltool, it will not even try "as"
3584 as the fallback, but rather return i586-cygwin32-as.
3586 Oh, and given, argv[0] = dlltool, it'll return "as".
3588 Returns a dynamically allocated string. */
3591 deduce_name (prog_name
)
3592 const char *prog_name
;
3595 char *dash
, *slash
, *cp
;
3599 for (cp
= program_name
; *cp
!= '\0'; ++cp
)
3604 #if defined(__DJGPP__) || defined (__CYGWIN__) || defined(__WIN32__)
3605 *cp
== ':' || *cp
== '\\' ||
3618 /* First, try looking for a prefixed PROG_NAME in the
3619 PROGRAM_NAME directory, with the same prefix as PROGRAM_NAME. */
3620 cmd
= look_for_prog (prog_name
, program_name
, dash
- program_name
+ 1);
3623 if (slash
!= NULL
&& cmd
== NULL
)
3625 /* Next, try looking for a PROG_NAME in the same directory as
3626 that of this program. */
3627 cmd
= look_for_prog (prog_name
, program_name
, slash
- program_name
+ 1);
3632 /* Just return PROG_NAME as is. */
3633 cmd
= xstrdup (prog_name
);
3639 #ifdef DLLTOOL_MCORE_ELF
3640 typedef struct fname_cache
3643 struct fname_cache
* next
;
3647 static fname_cache fnames
;
3650 mcore_elf_cache_filename (char * filename
)
3656 while (ptr
->next
!= NULL
)
3659 ptr
->filename
= filename
;
3660 ptr
->next
= (fname_cache
*) malloc (sizeof (fname_cache
));
3661 if (ptr
->next
!= NULL
)
3662 ptr
->next
->next
= NULL
;
3665 #define MCORE_ELF_TMP_OBJ "mcoreelf.o"
3666 #define MCORE_ELF_TMP_EXP "mcoreelf.exp"
3667 #define MCORE_ELF_TMP_LIB "mcoreelf.lib"
3670 mcore_elf_gen_out_file (void)
3675 /* Step one. Run 'ld -r' on the input object files in order to resolve
3676 any internal references and to generate a single .exports section. */
3679 ds
= dyn_string_new (100);
3680 dyn_string_append_cstr (ds
, "-r ");
3682 if (mcore_elf_linker_flags
!= NULL
)
3683 dyn_string_append_cstr (ds
, mcore_elf_linker_flags
);
3685 while (ptr
->next
!= NULL
)
3687 dyn_string_append_cstr (ds
, ptr
->filename
);
3688 dyn_string_append_cstr (ds
, " ");
3693 dyn_string_append_cstr (ds
, "-o ");
3694 dyn_string_append_cstr (ds
, MCORE_ELF_TMP_OBJ
);
3696 if (mcore_elf_linker
== NULL
)
3697 mcore_elf_linker
= deduce_name ("ld");
3699 run (mcore_elf_linker
, ds
->s
);
3701 dyn_string_delete (ds
);
3703 /* Step two. Create a .exp file and a .lib file from the temporary file.
3704 Do this by recursively invoking dlltool... */
3705 ds
= dyn_string_new (100);
3707 dyn_string_append_cstr (ds
, "-S ");
3708 dyn_string_append_cstr (ds
, as_name
);
3710 dyn_string_append_cstr (ds
, " -e ");
3711 dyn_string_append_cstr (ds
, MCORE_ELF_TMP_EXP
);
3712 dyn_string_append_cstr (ds
, " -l ");
3713 dyn_string_append_cstr (ds
, MCORE_ELF_TMP_LIB
);
3714 dyn_string_append_cstr (ds
, " " );
3715 dyn_string_append_cstr (ds
, MCORE_ELF_TMP_OBJ
);
3718 dyn_string_append_cstr (ds
, " -v");
3722 dyn_string_append_cstr (ds
, " -n");
3724 if (dontdeltemps
> 1)
3725 dyn_string_append_cstr (ds
, " -n");
3728 /* XXX - FIME: ought to check/copy other command line options as well. */
3729 run (program_name
, ds
->s
);
3731 dyn_string_delete (ds
);
3733 /* Step four. Feed the .exp and object files to ld -shared to create the dll. */
3734 ds
= dyn_string_new (100);
3736 dyn_string_append_cstr (ds
, "-shared ");
3738 if (mcore_elf_linker_flags
)
3739 dyn_string_append_cstr (ds
, mcore_elf_linker_flags
);
3741 dyn_string_append_cstr (ds
, " ");
3742 dyn_string_append_cstr (ds
, MCORE_ELF_TMP_EXP
);
3743 dyn_string_append_cstr (ds
, " ");
3744 dyn_string_append_cstr (ds
, MCORE_ELF_TMP_OBJ
);
3745 dyn_string_append_cstr (ds
, " -o ");
3746 dyn_string_append_cstr (ds
, mcore_elf_out_file
);
3748 run (mcore_elf_linker
, ds
->s
);
3750 dyn_string_delete (ds
);
3752 if (dontdeltemps
== 0)
3753 unlink (MCORE_ELF_TMP_EXP
);
3755 if (dontdeltemps
< 2)
3756 unlink (MCORE_ELF_TMP_OBJ
);
3758 #endif /* DLLTOOL_MCORE_ELF */