1 /* dlltool.c -- tool to generate stuff for PE style DLLs
2 Copyright (C) 1995, 96, 97, 1998 Free Software Foundation, Inc.
4 This file is part of GNU Binutils.
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 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> ] [ @ <integer> ] [ NONAME ] [CONSTANT] [DATA] ) *
51 Declares name1 as an exported symbol from the
52 DLL, with optional ordinal number <integer>
54 IMPORTS ( [ <name> = ] <name> . <name> ) *
55 Ignored for compatibility
58 Puts <string> into output .exp file in the .rdata section
60 [STACKSIZE|HEAPSIZE] <number-reserve> [ , <number-commit> ]
61 Generates --stack|--heap <number-reserve>,<number-commit>
62 in the output .drectve section. The linker will
63 see this and act upon it.
66 SECTIONS ( <sectionname> <attr>+ )*
67 <attr> = READ | WRITE | EXECUTE | SHARED
68 Generates --attr <sectionname> <attr> in the output
69 .drectve section. The linker will see this and act
73 A -export:<name> in a .drectve section in an input .o or .a
74 file to this program is equivalent to a EXPORTS <name>
79 The program generates output files with the prefix supplied
80 on the command line, or in the def file, or taken from the first
83 The .exp.s file contains the information necessary to export
84 the routines in the DLL. The .lib.s file contains the information
85 necessary to use the DLL's routines from a referencing program.
92 asm (".section .drectve");
93 asm (".ascii \"-export:adef\"");
97 printf("hello from the dll %s\n",s);
102 printf("hello from the dll and the other entry point %s\n",s);
106 asm (".section .drectve");
107 asm (".ascii \"-export:cdef\"");
108 asm (".ascii \"-export:ddef\"");
111 printf("hello from the dll %s\n",s);
116 printf("hello from the dll and the other entry point %s\n",s);
134 HEAPSIZE 0x40000, 0x2000
138 SECTIONS donkey READ WRITE
142 # compile up the parts of the dll
147 # put them in a library (you don't have to, you
148 # could name all the .os on the dlltool line)
150 ar qcv thedll.in file1.o file2.o
153 # run this tool over the library and the def file
154 ./dlltool --def thedll.def --output-exp thedll.o --output-lib thedll.a
156 # build the dll with the library with file1.o, file2.o and the export table
157 ld -o thedll.dll thedll.o thedll.in
162 # link the executable with the import library
163 ld -e main -Tthemain.ld -o themain.exe themain.o thedll.a
167 /* .idata section description
169 The .idata section is the import table. It is a collection of several
170 subsections used to keep the pieces for each dll together: .idata$[234567].
171 IE: Each dll's .idata$2's are catenated together, each .idata$3's, etc.
173 .idata$2 = Import Directory Table
174 = array of IMAGE_IMPORT_DESCRIPTOR's.
176 DWORD Characteristics; - pointer to .idata$4
177 DWORD TimeDateStamp; - currently always 0
178 DWORD ForwarderChain; - currently always 0
179 DWORD Name; - pointer to dll's name
180 PIMAGE_THUNK_DATA FirstThunk; - pointer to .idata$5
182 .idata$3 = null terminating entry for .idata$2.
184 .idata$4 = Import Lookup Table
185 = array of array of pointers to hint name table.
186 There is one for each dll being imported from, and each dll's set is
187 terminated by a trailing NULL.
189 .idata$5 = Import Address Table
190 = array of array of pointers to hint name table.
191 There is one for each dll being imported from, and each dll's set is
192 terminated by a trailing NULL.
193 Initially, this table is identical to the Import Lookup Table. However,
194 at load time, the loader overwrites the entries with the address of the
197 .idata$6 = Hint Name Table
198 = Array of { short, asciz } entries, one for each imported function.
199 The `short' is the function's ordinal number.
201 .idata$7 = dll name (eg: "kernel32.dll"). (.idata$6 for ppc)
204 /* AIX requires this to be the first thing in the file. */
211 #define show_allnames 0
213 #define PAGE_SIZE 4096
214 #define PAGE_MASK (-PAGE_SIZE)
216 #include "libiberty.h"
219 #include "demangle.h"
225 #ifdef HAVE_SYS_WAIT_H
226 #include <sys/wait.h>
227 #else /* ! HAVE_SYS_WAIT_H */
228 #if ! defined (_WIN32) || defined (__CYGWIN32__)
230 #define WIFEXITED(w) (((w)&0377) == 0)
233 #define WIFSIGNALED(w) (((w)&0377) != 0177 && ((w)&~0377) == 0)
236 #define WTERMSIG(w) ((w) & 0177)
239 #define WEXITSTATUS(w) (((w) >> 8) & 0377)
241 #else /* defined (_WIN32) && ! defined (__CYGWIN32__) */
243 #define WIFEXITED(w) (((w) & 0xff) == 0)
246 #define WIFSIGNALED(w) (((w) & 0xff) != 0 && ((w) & 0xff) != 0x7f)
249 #define WTERMSIG(w) ((w) & 0x7f)
252 #define WEXITSTATUS(w) (((w) & 0xff00) >> 8)
254 #endif /* defined (_WIN32) && ! defined (__CYGWIN32__) */
255 #endif /* ! HAVE_SYS_WAIT_H */
257 static char *as_name
= "as";
259 static int no_idata4
;
260 static int no_idata5
;
261 static char *exp_name
;
262 static char *imp_name
;
263 static char *head_label
;
264 static char *imp_name_lab
;
265 static char *dll_name
;
267 static int add_indirect
= 0;
268 static int add_underscore
= 0;
269 static int dontdeltemps
= 0;
271 static char *def_file
;
273 static char *program_name
;
278 static FILE *output_def
;
279 static FILE *base_file
;
282 static const char *mname
= "arm";
286 static const char *mname
= "i386";
290 static const char *mname
= "ppc";
293 #define PATHMAX 250 /* What's the right name for this ? */
295 /* This bit of assemly does jmp * ....
296 s set how_jtab_roff to mark where the 32bit abs branch should go */
297 static const unsigned char i386_jtab
[] =
299 0xff, 0x25, 0x00, 0x00, 0x00, 0x00, 0x90, 0x90
302 static const unsigned char arm_jtab
[] =
304 0x00, 0xc0, 0x9f, 0xe5,
305 0x00, 0xf0, 0x9c, 0xe5,
309 /* This is the glue sequence for PowerPC PE. There is a */
310 /* tocrel16-tocdefn reloc against the first instruction. */
311 /* We also need a IMGLUE reloc against the glue function */
312 /* to restore the toc saved by the third instruction in */
314 static const unsigned char ppc_jtab
[] =
316 0x00, 0x00, 0x62, 0x81, /* lwz r11,0(r2) */
317 /* Reloc TOCREL16 __imp_xxx */
318 0x00, 0x00, 0x8B, 0x81, /* lwz r12,0(r11) */
319 0x04, 0x00, 0x41, 0x90, /* stw r2,4(r1) */
320 0xA6, 0x03, 0x89, 0x7D, /* mtctr r12 */
321 0x04, 0x00, 0x4B, 0x80, /* lwz r2,4(r11) */
322 0x20, 0x04, 0x80, 0x4E /* bctr */
326 /* the glue instruction, picks up the toc from the stw in */
327 /* the above code: "lwz r2,4(r1)" */
328 static bfd_vma ppc_glue_insn
= 0x80410004;
331 static char outfile
[PATHMAX
];
336 const char *how_byte
;
337 const char *how_short
;
338 const char *how_long
;
339 const char *how_asciz
;
340 const char *how_comment
;
341 const char *how_jump
;
342 const char *how_global
;
343 const char *how_space
;
344 const char *how_align_short
;
345 const char *how_align_long
;
346 const char *how_bfd_target
;
347 enum bfd_architecture how_bfd_arch
;
348 const unsigned char *how_jtab
;
349 int how_jtab_size
; /* size of the jtab entry */
350 int how_jtab_roff
; /* offset into it for the ind 32 reloc into idata 5 */
353 static const struct mac mtable
[] =
357 "arm", ".byte", ".short", ".long", ".asciz", "@",
358 "ldr\tip,[pc]\n\tldr\tpc,[ip]\n\t.long",
359 ".global", ".space", ".align\t2",".align\t4","pe-arm-little", bfd_arch_arm
,
360 arm_jtab
, sizeof(arm_jtab
),8
365 "i386", ".byte", ".short", ".long", ".asciz", "#", "jmp *", ".global", ".space", ".align\t2",".align\t4","pe-i386",bfd_arch_i386
,
366 i386_jtab
,sizeof(i386_jtab
),2,
371 "ppc", ".byte", ".short", ".long", ".asciz", "#", "jmp *", ".global", ".space", ".align\t2",".align\t4","pe-powerpcle",bfd_arch_powerpc
,
372 ppc_jtab
,sizeof(ppc_jtab
),0,
385 typedef struct export
388 const char *internal_name
;
398 static const char *rvaafter
PARAMS ((int));
399 static const char *rvabefore
PARAMS ((int));
400 static const char *asm_prefix
PARAMS ((int));
401 static void run
PARAMS ((const char *, char *));
402 static void basenames
PARAMS ((bfd
*));
403 static void scan_open_obj_file
PARAMS ((bfd
*));
404 static void scan_obj_file
PARAMS ((const char *));
405 static void dump_def_info
PARAMS ((FILE *));
406 static int sfunc
PARAMS ((const void *, const void *));
407 static void flush_page
PARAMS ((FILE *, long *, int, int));
408 static void gen_def_file
PARAMS ((void));
409 static void gen_exp_file
PARAMS ((void));
410 static const char *xlate
PARAMS ((const char *));
411 static void dump_iat
PARAMS ((FILE *, export_type
*));
412 static char *make_label
PARAMS ((const char *, const char *));
413 static bfd
*make_one_lib_file
PARAMS ((export_type
*, int));
414 static bfd
*make_head
PARAMS ((void));
415 static bfd
*make_tail
PARAMS ((void));
416 static void gen_lib_file
PARAMS ((void));
417 static int pfunc
PARAMS ((const void *, const void *));
418 static int nfunc
PARAMS ((const void *, const void *));
419 static void remove_null_names
PARAMS ((export_type
**));
420 static void dtab
PARAMS ((export_type
**));
421 static void process_duplicates
PARAMS ((export_type
**));
422 static void fill_ordinals
PARAMS ((export_type
**));
423 static int alphafunc
PARAMS ((const void *, const void *));
424 static void mangle_defs
PARAMS ((void));
425 static void usage
PARAMS ((FILE *, int));
475 #define ASM_BYTE mtable[machine].how_byte
476 #define ASM_SHORT mtable[machine].how_short
477 #define ASM_LONG mtable[machine].how_long
478 #define ASM_TEXT mtable[machine].how_asciz
479 #define ASM_C mtable[machine].how_comment
480 #define ASM_JUMP mtable[machine].how_jump
481 #define ASM_GLOBAL mtable[machine].how_global
482 #define ASM_SPACE mtable[machine].how_space
483 #define ASM_ALIGN_SHORT mtable[machine].how_align_short
484 #define ASM_RVA_BEFORE rvabefore(machine)
485 #define ASM_RVA_AFTER rvaafter(machine)
486 #define ASM_PREFIX asm_prefix(machine)
487 #define ASM_ALIGN_LONG mtable[machine].how_align_long
488 #define HOW_BFD_TARGET 0 /* always default*/
489 #define HOW_BFD_ARCH mtable[machine].how_bfd_arch
490 #define HOW_JTAB mtable[machine].how_jtab
491 #define HOW_JTAB_SIZE mtable[machine].how_jtab_size
492 #define HOW_JTAB_ROFF mtable[machine].how_jtab_roff
496 process_def_file (name
)
499 FILE *f
= fopen (name
, FOPEN_RT
);
502 fprintf (stderr
, _("%s: Can't open def file %s\n"), program_name
, name
);
511 /**********************************************************************/
513 /* Communications with the parser */
515 static const char *d_name
; /* Arg to NAME or LIBRARY */
516 static int d_nfuncs
; /* Number of functions exported */
517 static int d_named_nfuncs
; /* Number of named functions exported */
518 static int d_low_ord
; /* Lowest ordinal index */
519 static int d_high_ord
; /* Highest ordinal index */
520 static export_type
*d_exports
; /*list of exported functions */
521 static export_type
**d_exports_lexically
; /* vector of exported functions in alpha order */
522 static dlist_type
*d_list
; /* Descriptions */
523 static dlist_type
*a_list
; /* Stuff to go in directives */
532 fprintf (stderr
, _("%s: Syntax error in def file %s:%d\n"),
533 program_name
, def_file
, linenumber
);
538 def_exports (name
, internal_name
, ordinal
, noname
, constant
, data
)
540 const char *internal_name
;
546 struct export
*p
= (struct export
*) xmalloc (sizeof (*p
));
549 p
->internal_name
= internal_name
? internal_name
: name
;
550 p
->ordinal
= ordinal
;
551 p
->constant
= constant
;
560 def_name (name
, base
)
565 fprintf (stderr
, _("%s NAME %s base %x\n"), program_name
, name
, base
);
568 fprintf (stderr
, _("Can't have LIBRARY and NAME\n"));
575 def_library (name
, base
)
580 printf (_("%s: LIBRARY %s base %x\n"), program_name
, name
, base
);
583 fprintf (stderr
, _("%s: Can't have LIBRARY and NAME\n"), program_name
);
590 def_description (desc
)
593 dlist_type
*d
= (dlist_type
*) xmalloc (sizeof (dlist_type
));
594 d
->text
= xstrdup (desc
);
603 dlist_type
*d
= (dlist_type
*) xmalloc (sizeof (dlist_type
));
604 d
->text
= xstrdup (dir
);
610 def_stacksize (reserve
, commit
)
616 sprintf (b
, "-stack 0x%x,0x%x ", reserve
, commit
);
618 sprintf (b
, "-stack 0x%x ", reserve
);
619 new_directive (xstrdup (b
));
623 def_heapsize (reserve
, commit
)
629 sprintf (b
, "-heap 0x%x,0x%x ", reserve
, commit
);
631 sprintf (b
, "-heap 0x%x ", reserve
);
632 new_directive (xstrdup (b
));
636 def_import (internal
, module
, entry
)
637 const char *internal
;
642 fprintf (stderr
, _("%s: IMPORTS are ignored"), program_name
);
646 def_version (major
, minor
)
650 printf ("VERSION %d.%d\n", major
, minor
);
654 def_section (name
, attr
)
671 sprintf (buf
, "-attr %s %s", name
, atts
);
672 new_directive (xstrdup (buf
));
680 def_section ("CODE", attr
);
687 def_section ("DATA", attr
);
690 /**********************************************************************/
698 int pid
, wait_status
;
701 char *errmsg_fmt
, *errmsg_arg
;
702 char *temp_base
= choose_temp_base ();
705 fprintf (stderr
, "%s %s\n", what
, args
);
709 for (s
= args
; *s
; s
++)
713 argv
= alloca (sizeof (char *) * (i
+ 3));
720 while (*s
!= ' ' && *s
!= 0)
728 pid
= pexecute (argv
[0], (char * const *) argv
, program_name
, temp_base
,
729 &errmsg_fmt
, &errmsg_arg
, PEXECUTE_ONE
| PEXECUTE_SEARCH
);
733 int errno_val
= errno
;
735 fprintf (stderr
, "%s: ", program_name
);
736 fprintf (stderr
, errmsg_fmt
, errmsg_arg
);
737 fprintf (stderr
, ": %s\n", strerror (errno_val
));
741 pid
= pwait (pid
, &wait_status
, 0);
744 fprintf (stderr
, _("%s: wait: %s\n"), program_name
, strerror (errno
));
747 else if (WIFSIGNALED (wait_status
))
749 fprintf (stderr
, _("%s: subprocess got fatal signal %d\n"),
750 program_name
, WTERMSIG (wait_status
));
753 else if (WIFEXITED (wait_status
))
755 if (WEXITSTATUS (wait_status
) != 0)
756 fprintf (stderr
, _("%s: %s exited with status %d\n"),
757 program_name
, what
, WEXITSTATUS (wait_status
));
763 /* read in and block out the base relocations */
771 scan_open_obj_file (abfd
)
774 /* Look for .drectve's */
775 asection
*s
= bfd_get_section_by_name (abfd
, ".drectve");
778 int size
= bfd_get_section_size_before_reloc (s
);
779 char *buf
= xmalloc (size
);
782 bfd_get_section_contents (abfd
, s
, buf
, 0, size
);
784 fprintf (stderr
, _("%s: Sucking in info from %s\n"),
786 bfd_get_filename (abfd
));
788 /* Search for -export: strings */
794 && strncmp (p
, "-export:", 8) == 0)
800 while (p
< e
&& *p
!= ' ' && *p
!= '-')
802 c
= xmalloc (p
- name
+ 1);
803 memcpy (c
, name
, p
- name
);
805 /* FIXME: The 5th arg is for the `constant' field.
806 What should it be? Not that it matters since it's not
808 def_exports (c
, 0, -1, 0, 0, 0);
819 fprintf (stderr
, _("%s: Done readin\n"),
824 scan_obj_file (filename
)
825 const char *filename
;
827 bfd
*f
= bfd_openr (filename
, 0);
831 fprintf (stderr
, _("%s: Unable to open object file %s\n"),
836 if (bfd_check_format (f
, bfd_archive
))
838 bfd
*arfile
= bfd_openr_next_archived_file (f
, 0);
841 if (bfd_check_format (arfile
, bfd_object
))
842 scan_open_obj_file (arfile
);
844 arfile
= bfd_openr_next_archived_file (f
, arfile
);
847 else if (bfd_check_format (f
, bfd_object
))
849 scan_open_obj_file (f
);
855 /**********************************************************************/
863 fprintf (f
, "%s ", ASM_C
);
864 for (i
= 0; oav
[i
]; i
++)
865 fprintf (f
, "%s ", oav
[i
]);
867 for (i
= 0, exp
= d_exports
; exp
; i
++, exp
= exp
->next
)
869 fprintf (f
, "%s %d = %s %s @ %d %s%s%s\n",
875 exp
->noname
? "NONAME " : "",
876 exp
->constant
? "CONSTANT" : "",
877 exp
->data
? "DATA" : "");
881 /* Generate the .exp file */
888 return *(const long *) a
- *(const long *) b
;
892 flush_page (f
, need
, page_addr
, on_page
)
900 /* Flush this page */
901 fprintf (f
, "\t%s\t0x%08x\t%s Starting RVA for chunk\n",
905 fprintf (f
, "\t%s\t0x%x\t%s Size of block\n",
907 (on_page
* 2) + (on_page
& 1) * 2 + 8,
909 for (i
= 0; i
< on_page
; i
++)
911 fprintf (f
, "\t%s\t0x%lx\n", ASM_SHORT
, (need
[i
] - page_addr
) | 0x3000);
915 fprintf (f
, "\t%s\t0x%x\n", ASM_SHORT
, 0 | 0x0000);
924 fprintf (output_def
, ";");
925 for (i
= 0; oav
[i
]; i
++)
926 fprintf (output_def
, " %s", oav
[i
]);
928 fprintf (output_def
, "\nEXPORTS\n");
930 for (i
= 0, exp
= d_exports
; exp
; i
++, exp
= exp
->next
)
932 char *quote
= strchr (exp
->name
, '.') ? "\"" : "";
933 fprintf (output_def
, "\t%s%s%s @ %d%s%s ; %s\n",
938 exp
->noname
? " NONAME" : "",
939 exp
->data
? " DATA" : "",
940 cplus_demangle (exp
->internal_name
, DMGL_ANSI
| DMGL_PARAMS
));
953 sprintf (outfile
, "t%s", exp_name
);
956 fprintf (stderr
, _("%s: Generate exp file %s\n"),
957 program_name
, exp_name
);
959 f
= fopen (outfile
, FOPEN_WT
);
962 fprintf (stderr
, _("%s: Unable to open output file %s\n"), program_name
, outfile
);
967 fprintf (stderr
, _("%s: Opened file %s\n"),
968 program_name
, outfile
);
974 fprintf (f
, "\t.section .edata\n\n");
975 fprintf (f
, "\t%s 0 %s Allways 0\n", ASM_LONG
, ASM_C
);
976 fprintf (f
, "\t%s 0x%lx %s Time and date\n", ASM_LONG
, (long) time(0),
978 fprintf (f
, "\t%s 0 %s Major and Minor version\n", ASM_LONG
, ASM_C
);
979 fprintf (f
, "\t%sname%s %s Ptr to name of dll\n", ASM_RVA_BEFORE
, ASM_RVA_AFTER
, ASM_C
);
980 fprintf (f
, "\t%s %d %s Starting ordinal of exports\n", ASM_LONG
, d_low_ord
, ASM_C
);
983 fprintf (f
, "\t%s %d %s Number of functions\n", ASM_LONG
, d_high_ord
- d_low_ord
+ 1, ASM_C
);
984 fprintf(f
,"\t%s named funcs %d, low ord %d, high ord %d\n",
986 d_named_nfuncs
, d_low_ord
, d_high_ord
);
987 fprintf (f
, "\t%s %d %s Number of names\n", ASM_LONG
,
988 show_allnames
? d_high_ord
- d_low_ord
+ 1 : d_named_nfuncs
, ASM_C
);
989 fprintf (f
, "\t%safuncs%s %s Address of functions\n", ASM_RVA_BEFORE
, ASM_RVA_AFTER
, ASM_C
);
991 fprintf (f
, "\t%sanames%s %s Address of Name Pointer Table\n",
992 ASM_RVA_BEFORE
, ASM_RVA_AFTER
, ASM_C
);
994 fprintf (f
, "\t%sanords%s %s Address of ordinals\n", ASM_RVA_BEFORE
, ASM_RVA_AFTER
, ASM_C
);
996 fprintf (f
, "name: %s \"%s\"\n", ASM_TEXT
, dll_name
);
999 fprintf(f
,"%s Export address Table\n", ASM_C
);
1000 fprintf(f
,"\t%s\n", ASM_ALIGN_LONG
);
1001 fprintf (f
, "afuncs:\n");
1004 for (exp
= d_exports
; exp
; exp
= exp
->next
)
1006 if (exp
->ordinal
!= i
)
1009 fprintf (f
, "\t%s\t%d\t%s %d..%d missing\n",
1011 (exp
->ordinal
- i
) * 4,
1013 i
, exp
->ordinal
- 1);
1016 while (i
< exp
->ordinal
)
1018 fprintf(f
,"\t%s\t0\n", ASM_LONG
);
1022 fprintf (f
, "\t%s%s%s%s\t%s %d\n", ASM_RVA_BEFORE
,
1024 exp
->internal_name
, ASM_RVA_AFTER
, ASM_C
, exp
->ordinal
);
1028 fprintf (f
,"%s Export Name Pointer Table\n", ASM_C
);
1029 fprintf (f
, "anames:\n");
1031 for (i
= 0; (exp
= d_exports_lexically
[i
]); i
++)
1033 if (!exp
->noname
|| show_allnames
)
1034 fprintf (f
, "\t%sn%d%s\n", ASM_RVA_BEFORE
, exp
->ordinal
, ASM_RVA_AFTER
);
1037 fprintf (f
,"%s Export Oridinal Table\n", ASM_C
);
1038 fprintf (f
, "anords:\n");
1039 for (i
= 0; (exp
= d_exports_lexically
[i
]); i
++)
1041 if (!exp
->noname
|| show_allnames
)
1042 fprintf (f
, "\t%s %d\n", ASM_SHORT
, exp
->ordinal
- d_low_ord
);
1045 fprintf(f
,"%s Export Name Table\n", ASM_C
);
1046 for (i
= 0; (exp
= d_exports_lexically
[i
]); i
++)
1047 if (!exp
->noname
|| show_allnames
)
1048 fprintf (f
, "n%d: %s \"%s\"\n", exp
->ordinal
, ASM_TEXT
, exp
->name
);
1052 fprintf (f
, "\t.section .drectve\n");
1053 for (dl
= a_list
; dl
; dl
= dl
->next
)
1055 fprintf (f
, "\t%s\t\"%s\"\n", ASM_TEXT
, dl
->text
);
1060 fprintf (f
, "\t.section .rdata\n");
1061 for (dl
= d_list
; dl
; dl
= dl
->next
)
1065 /* We dont output as ascii 'cause there can
1066 be quote characters in the string */
1069 for (p
= dl
->text
; *p
; p
++)
1072 fprintf (f
, "\t%s\t", ASM_BYTE
);
1075 fprintf (f
, "%d", *p
);
1078 fprintf (f
, ",0\n");
1092 /* Add to the output file a way of getting to the exported names
1093 without using the import library. */
1096 fprintf (f
, "\t.section\t.rdata\n");
1097 for (i
= 0, exp
= d_exports
; exp
; i
++, exp
= exp
->next
)
1098 if (!exp
->noname
|| show_allnames
)
1100 /* We use a single underscore for MS compatibility, and a
1101 double underscore for backward compatibility with old
1103 fprintf (f
, "\t%s\t__imp_%s\n", ASM_GLOBAL
, exp
->name
);
1104 fprintf (f
, "\t%s\t_imp__%s\n", ASM_GLOBAL
, exp
->name
);
1105 fprintf (f
, "__imp_%s:\n", exp
->name
);
1106 fprintf (f
, "_imp__%s:\n", exp
->name
);
1107 fprintf (f
, "\t%s\t%s\n", ASM_LONG
, exp
->name
);
1111 /* Dump the reloc section if a base file is provided */
1115 long need
[PAGE_SIZE
];
1122 fprintf (f
, "\t.section\t.init\n");
1123 fprintf (f
, "lab:\n");
1125 fseek (base_file
, 0, SEEK_END
);
1126 numbytes
= ftell (base_file
);
1127 fseek (base_file
, 0, SEEK_SET
);
1128 copy
= xmalloc (numbytes
);
1129 fread (copy
, 1, numbytes
, base_file
);
1130 num_entries
= numbytes
/ sizeof (long);
1133 fprintf (f
, "\t.section\t.reloc\n");
1139 qsort (copy
, num_entries
, sizeof (long), sfunc
);
1140 /* Delete duplcates */
1141 for (src
= 0; src
< num_entries
; src
++)
1143 if (last
!= copy
[src
])
1144 last
= copy
[dst
++] = copy
[src
];
1148 page_addr
= addr
& PAGE_MASK
; /* work out the page addr */
1150 for (j
= 0; j
< num_entries
; j
++)
1153 if ((addr
& PAGE_MASK
) != page_addr
)
1155 flush_page (f
, need
, page_addr
, on_page
);
1157 page_addr
= addr
& PAGE_MASK
;
1159 need
[on_page
++] = addr
;
1161 flush_page (f
, need
, page_addr
, on_page
);
1163 /* fprintf (f, "\t%s\t0,0\t%s End\n", ASM_LONG, ASM_C);*/
1169 /* assemble the file */
1170 sprintf (outfile
, "-o %s t%s", exp_name
, exp_name
);
1171 run (as_name
, outfile
);
1172 if (dontdeltemps
== 0)
1174 sprintf (outfile
, "t%s", exp_name
);
1185 char *copy
= xmalloc (strlen (name
) + 2);
1187 strcpy (copy
+ 1, name
);
1194 p
= strchr (name
, '@');
1201 /**********************************************************************/
1208 if (exp
->noname
&& !show_allnames
)
1210 fprintf (f
, "\t%s\t0x%08x\n",
1212 exp
->ordinal
| 0x80000000); /* hint or orindal ?? */
1216 fprintf (f
, "\t%sID%d%s\n", ASM_RVA_BEFORE
,
1232 unsigned char *data
;
1247 static sinfo secdata
[NSECS
] =
1249 { TEXT
, ".text", SEC_CODE
| SEC_HAS_CONTENTS
, 2},
1250 { DATA
, ".data", SEC_DATA
, 2},
1251 { BSS
, ".bss", 0, 2},
1252 { IDATA7
, ".idata$7", SEC_HAS_CONTENTS
, 2},
1253 { IDATA5
, ".idata$5", SEC_HAS_CONTENTS
, 2},
1254 { IDATA4
, ".idata$4", SEC_HAS_CONTENTS
, 2},
1255 { IDATA6
, ".idata$6", SEC_HAS_CONTENTS
, 1}
1260 /* Sections numbered to make the order the same as other PowerPC NT */
1261 /* compilers. This also keeps funny alignment thingies from happening. */
1274 static sinfo secdata
[NSECS
] =
1276 { TEXT
, ".text", SEC_CODE
| SEC_HAS_CONTENTS
, 3},
1277 { PDATA
, ".pdata", SEC_HAS_CONTENTS
, 2},
1278 { RDATA
, ".reldata", SEC_HAS_CONTENTS
, 2},
1279 { IDATA5
, ".idata$5", SEC_HAS_CONTENTS
, 2},
1280 { IDATA4
, ".idata$4", SEC_HAS_CONTENTS
, 2},
1281 { IDATA6
, ".idata$6", SEC_HAS_CONTENTS
, 1},
1282 { IDATA7
, ".idata$7", SEC_HAS_CONTENTS
, 2},
1283 { DATA
, ".data", SEC_DATA
, 2},
1284 { BSS
, ".bss", 0, 2}
1290 This is what we're trying to make. We generate the imp symbols with
1291 both single and double underscores, for compatibility.
1294 .global _GetFileVersionInfoSizeW@8
1295 .global __imp_GetFileVersionInfoSizeW@8
1296 _GetFileVersionInfoSizeW@8:
1297 jmp * __imp_GetFileVersionInfoSizeW@8
1298 .section .idata$7 # To force loading of head
1299 .long __version_a_head
1300 # Import Address Table
1302 __imp_GetFileVersionInfoSizeW@8:
1305 # Import Lookup Table
1311 .asciz "GetFileVersionInfoSizeW"
1314 For the PowerPC, here's the variation on the above scheme:
1316 # Rather than a simple "jmp *", the code to get to the dll function
1319 lwz r11,[tocv]__imp_function_name(r2)
1320 # RELOC: 00000000 TOCREL16,TOCDEFN __imp_function_name
1329 make_label (prefix
, name
)
1333 int len
= strlen (ASM_PREFIX
) + strlen (prefix
) + strlen (name
);
1334 char *copy
= xmalloc (len
+1 );
1335 strcpy (copy
, ASM_PREFIX
);
1336 strcat (copy
, prefix
);
1337 strcat (copy
, name
);
1342 make_one_lib_file (exp
, i
)
1350 sprintf (outfile
, "%ss%d.s", prefix
, i
);
1351 f
= fopen (outfile
, FOPEN_WT
);
1352 fprintf (f
, "\t.text\n");
1353 fprintf (f
, "\t%s\t%s%s\n", ASM_GLOBAL
, ASM_PREFIX
, exp
->name
);
1354 fprintf (f
, "\t%s\t__imp_%s\n", ASM_GLOBAL
, exp
->name
);
1355 fprintf (f
, "\t%s\t_imp__%s\n", ASM_GLOBAL
, exp
->name
);
1356 fprintf (f
, "%s%s:\n\t%s\t__imp_%s\n", ASM_PREFIX
,
1357 exp
->name
, ASM_JUMP
, exp
->name
);
1359 fprintf (f
, "\t.section\t.idata$7\t%s To force loading of head\n", ASM_C
);
1360 fprintf (f
, "\t%s\t%s\n", ASM_LONG
, head_label
);
1363 fprintf (f
,"%s Import Address Table\n", ASM_C
);
1365 fprintf (f
, "\t.section .idata$5\n");
1366 fprintf (f
, "__imp_%s:\n", exp
->name
);
1367 fprintf (f
, "_imp__%s:\n", exp
->name
);
1371 fprintf (f
, "\n%s Import Lookup Table\n", ASM_C
);
1372 fprintf (f
, "\t.section .idata$4\n");
1376 if(!exp
->noname
|| show_allnames
)
1378 fprintf (f
, "%s Hint/Name table\n", ASM_C
);
1379 fprintf (f
, "\t.section .idata$6\n");
1380 fprintf (f
, "ID%d:\t%s\t%d\n", exp
->ordinal
, ASM_SHORT
, exp
->hint
);
1381 fprintf (f
, "\t%s\t\"%s\"\n", ASM_TEXT
, xlate (exp
->name
));
1387 sprintf (outfile
, "-o %ss%d.o %ss%d.s", prefix
, i
, prefix
, i
);
1389 run (as_name
, outfile
);
1398 asymbol
*iname
, *iname2
;
1400 asymbol
**iname_lab_pp
;
1403 /* Extra Symbols for PPC */
1415 asymbol
*ptrs
[NSECS
+ 4 + EXTRA
+ 1];
1417 char *outname
= xmalloc (10);
1419 sprintf (outname
, "ds%d.o", i
);
1420 abfd
= bfd_openw (outname
, HOW_BFD_TARGET
);
1423 fprintf (stderr
, _("%s: bfd_open failed open output file %s\n"),
1424 program_name
, outname
);
1428 bfd_set_format (abfd
, bfd_object
);
1429 bfd_set_arch_mach (abfd
, HOW_BFD_ARCH
, 0);
1432 /* First make symbols for the sections */
1433 for (i
= 0; i
< NSECS
; i
++)
1435 sinfo
*si
= secdata
+ i
;
1438 si
->sec
= bfd_make_section_old_way (abfd
, si
->name
);
1439 bfd_set_section_flags (abfd
,
1443 bfd_set_section_alignment(abfd
, si
->sec
, si
->align
);
1444 si
->sec
->output_section
= si
->sec
;
1445 si
->sym
= bfd_make_empty_symbol(abfd
);
1446 si
->sym
->name
= si
->sec
->name
;
1447 si
->sym
->section
= si
->sec
;
1448 si
->sym
->flags
= BSF_LOCAL
;
1450 ptrs
[oidx
] = si
->sym
;
1451 si
->sympp
= ptrs
+ oidx
;
1460 exp_label
= bfd_make_empty_symbol (abfd
);
1461 exp_label
->name
= make_label ("", exp
->name
);
1463 /* On PowerPC, the function name points to a descriptor in
1464 the rdata section, the first element of which is a
1465 pointer to the code (..function_name), and the second
1466 points to the .toc */
1468 if (machine
== MPPC
)
1469 exp_label
->section
= secdata
[RDATA
].sec
;
1472 exp_label
->section
= secdata
[TEXT
].sec
;
1474 exp_label
->flags
= BSF_GLOBAL
;
1475 exp_label
->value
= 0;
1477 ptrs
[oidx
++] = exp_label
;
1480 /* Generate imp symbols with one underscore for Microsoft
1481 compatibility, and with two underscores for backward
1482 compatibility with old versions of cygwin. */
1483 iname
= bfd_make_empty_symbol(abfd
);
1484 iname
->name
= make_label ("__imp_", exp
->name
);
1485 iname
->section
= secdata
[IDATA5
].sec
;
1486 iname
->flags
= BSF_GLOBAL
;
1489 iname2
= bfd_make_empty_symbol(abfd
);
1490 iname2
->name
= make_label ("_imp__", exp
->name
);
1491 iname2
->section
= secdata
[IDATA5
].sec
;
1492 iname2
->flags
= BSF_GLOBAL
;
1495 iname_lab
= bfd_make_empty_symbol(abfd
);
1497 iname_lab
->name
= head_label
;
1498 iname_lab
->section
= (asection
*)&bfd_und_section
;
1499 iname_lab
->flags
= 0;
1500 iname_lab
->value
= 0;
1503 iname_pp
= ptrs
+ oidx
;
1504 ptrs
[oidx
++] = iname
;
1505 ptrs
[oidx
++] = iname2
;
1507 iname_lab_pp
= ptrs
+ oidx
;
1508 ptrs
[oidx
++] = iname_lab
;
1511 /* The symbol refering to the code (.text) */
1513 asymbol
*function_name
;
1515 function_name
= bfd_make_empty_symbol(abfd
);
1516 function_name
->name
= make_label ("..", exp
->name
);
1517 function_name
->section
= secdata
[TEXT
].sec
;
1518 function_name
->flags
= BSF_GLOBAL
;
1519 function_name
->value
= 0;
1521 fn_pp
= ptrs
+ oidx
;
1522 ptrs
[oidx
++] = function_name
;
1525 /* The .toc symbol */
1527 asymbol
*toc_symbol
; /* The .toc symbol */
1529 toc_symbol
= bfd_make_empty_symbol(abfd
);
1530 toc_symbol
->name
= make_label (".", "toc");
1531 toc_symbol
->section
= (asection
*)&bfd_und_section
;
1532 toc_symbol
->flags
= BSF_GLOBAL
;
1533 toc_symbol
->value
= 0;
1535 toc_pp
= ptrs
+ oidx
;
1536 ptrs
[oidx
++] = toc_symbol
;
1542 for (i
= 0; i
< NSECS
; i
++)
1544 sinfo
*si
= secdata
+ i
;
1545 asection
*sec
= si
->sec
;
1554 si
->size
= HOW_JTAB_SIZE
;
1555 si
->data
= xmalloc (HOW_JTAB_SIZE
);
1556 memcpy (si
->data
, HOW_JTAB
, HOW_JTAB_SIZE
);
1558 /* add the reloqc into idata$5 */
1559 rel
= xmalloc (sizeof (arelent
));
1560 rpp
= xmalloc (sizeof (arelent
*) * 2);
1563 rel
->address
= HOW_JTAB_ROFF
;
1566 if (machine
== MPPC
)
1568 rel
->howto
= bfd_reloc_type_lookup (abfd
,
1569 BFD_RELOC_16_GOTOFF
);
1570 rel
->sym_ptr_ptr
= iname_pp
;
1574 rel
->howto
= bfd_reloc_type_lookup (abfd
, BFD_RELOC_32
);
1575 rel
->sym_ptr_ptr
= secdata
[IDATA5
].sympp
;
1577 sec
->orelocation
= rpp
;
1578 sec
->reloc_count
= 1;
1583 /* An idata$4 or idata$5 is one word long, and has an
1586 si
->data
= xmalloc (4);
1591 si
->data
[0] = exp
->ordinal
;
1592 si
->data
[1] = exp
->ordinal
>> 8;
1593 si
->data
[2] = exp
->ordinal
>> 16;
1598 sec
->reloc_count
= 1;
1599 memset (si
->data
, 0, si
->size
);
1600 rel
= xmalloc (sizeof (arelent
));
1601 rpp
= xmalloc (sizeof (arelent
*) * 2);
1606 rel
->howto
= bfd_reloc_type_lookup (abfd
, BFD_RELOC_RVA
);
1607 rel
->sym_ptr_ptr
= secdata
[IDATA6
].sympp
;
1608 sec
->orelocation
= rpp
;
1616 /* This used to add 1 to exp->hint. I don't know
1617 why it did that, and it does not match what I see
1618 in programs compiled with the MS tools. */
1619 int idx
= exp
->hint
;
1620 si
->size
= strlen (xlate (exp
->name
)) + 3;
1621 si
->data
= xmalloc (si
->size
);
1622 si
->data
[0] = idx
& 0xff;
1623 si
->data
[1] = idx
>> 8;
1624 strcpy (si
->data
+ 2, xlate (exp
->name
));
1629 si
->data
=xmalloc(4);
1630 memset (si
->data
, 0, si
->size
);
1631 rel
= xmalloc (sizeof (arelent
));
1632 rpp
= xmalloc (sizeof (arelent
*) * 2);
1636 rel
->howto
= bfd_reloc_type_lookup (abfd
, BFD_RELOC_RVA
);
1637 rel
->sym_ptr_ptr
= iname_lab_pp
;
1638 sec
->orelocation
= rpp
;
1639 sec
->reloc_count
= 1;
1645 /* The .pdata section is 5 words long. */
1646 /* Think of it as: */
1649 /* bfd_vma BeginAddress, [0x00] */
1650 /* EndAddress, [0x04] */
1651 /* ExceptionHandler, [0x08] */
1652 /* HandlerData, [0x0c] */
1653 /* PrologEndAddress; [0x10] */
1656 /* So this pdata section setups up this as a glue linkage to
1657 a dll routine. There are a number of house keeping things
1660 1. In the name of glue trickery, the ADDR32 relocs for 0,
1661 4, and 0x10 are set to point to the same place:
1663 2. There is one more reloc needed in the pdata section.
1664 The actual glue instruction to restore the toc on
1665 return is saved as the offset in an IMGLUE reloc.
1666 So we need a total of four relocs for this section.
1668 3. Lastly, the HandlerData field is set to 0x03, to indicate
1669 that this is a glue routine.
1671 arelent
*imglue
, *ba_rel
, *ea_rel
, *pea_rel
;
1673 /* alignment must be set to 2**2 or you get extra stuff */
1674 bfd_set_section_alignment(abfd
, sec
, 2);
1677 si
->data
=xmalloc(4 * 5);
1678 memset (si
->data
, 0, si
->size
);
1679 rpp
= xmalloc (sizeof (arelent
*) * 5);
1680 rpp
[0] = imglue
= xmalloc (sizeof (arelent
));
1681 rpp
[1] = ba_rel
= xmalloc (sizeof (arelent
));
1682 rpp
[2] = ea_rel
= xmalloc (sizeof (arelent
));
1683 rpp
[3] = pea_rel
= xmalloc (sizeof (arelent
));
1686 /* stick the toc reload instruction in the glue reloc */
1687 bfd_put_32(abfd
, ppc_glue_insn
, (char *) &imglue
->address
);
1690 imglue
->howto
= bfd_reloc_type_lookup (abfd
,
1691 BFD_RELOC_32_GOTOFF
);
1692 imglue
->sym_ptr_ptr
= fn_pp
;
1694 ba_rel
->address
= 0;
1696 ba_rel
->howto
= bfd_reloc_type_lookup (abfd
, BFD_RELOC_32
);
1697 ba_rel
->sym_ptr_ptr
= fn_pp
;
1699 bfd_put_32(abfd
, 0x18, si
->data
+ 0x04);
1700 ea_rel
->address
= 4;
1702 ea_rel
->howto
= bfd_reloc_type_lookup (abfd
, BFD_RELOC_32
);
1703 ea_rel
->sym_ptr_ptr
= fn_pp
;
1705 /* mark it as glue */
1706 bfd_put_32(abfd
, 0x03, si
->data
+ 0x0c);
1708 /* mark the prolog end address */
1709 bfd_put_32(abfd
, 0x0D, si
->data
+ 0x10);
1710 pea_rel
->address
= 0x10;
1711 pea_rel
->addend
= 0;
1712 pea_rel
->howto
= bfd_reloc_type_lookup (abfd
, BFD_RELOC_32
);
1713 pea_rel
->sym_ptr_ptr
= fn_pp
;
1715 sec
->orelocation
= rpp
;
1716 sec
->reloc_count
= 4;
1720 /* Each external function in a PowerPC PE file has a two word
1721 descriptor consisting of:
1722 1. The address of the code.
1723 2. The address of the appropriate .toc
1724 We use relocs to build this.
1728 si
->data
= xmalloc (8);
1729 memset (si
->data
, 0, si
->size
);
1731 rpp
= xmalloc (sizeof (arelent
*) * 3);
1732 rpp
[0] = rel
= xmalloc (sizeof (arelent
));
1733 rpp
[1] = xmalloc (sizeof (arelent
));
1738 rel
->howto
= bfd_reloc_type_lookup (abfd
, BFD_RELOC_32
);
1739 rel
->sym_ptr_ptr
= fn_pp
;
1745 rel
->howto
= bfd_reloc_type_lookup (abfd
, BFD_RELOC_32
);
1746 rel
->sym_ptr_ptr
= toc_pp
;
1748 sec
->orelocation
= rpp
;
1749 sec
->reloc_count
= 2;
1751 #endif /* DLLTOOL_PPC */
1757 /* Size up all the sections */
1758 for (i
= 0; i
< NSECS
; i
++)
1760 sinfo
*si
= secdata
+ i
;
1762 bfd_set_section_size (abfd
, si
->sec
, si
->size
);
1763 bfd_set_section_vma (abfd
, si
->sec
, vma
);
1765 /* vma += si->size;*/
1768 /* Write them out */
1769 for (i
= 0; i
< NSECS
; i
++)
1771 sinfo
*si
= secdata
+ i
;
1773 if (i
== IDATA5
&& no_idata5
)
1776 if (i
== IDATA4
&& no_idata4
)
1779 bfd_set_section_contents (abfd
, si
->sec
,
1784 bfd_set_symtab (abfd
, ptrs
, oidx
);
1786 abfd
= bfd_openr (outname
, HOW_BFD_TARGET
);
1795 FILE * f
= fopen ("dh.s", FOPEN_WT
);
1797 fprintf (f
, "%s IMAGE_IMPORT_DESCRIPTOR\n", ASM_C
);
1798 fprintf (f
, "\t.section .idata$2\n");
1800 fprintf(f
,"\t%s\t%s\n", ASM_GLOBAL
,head_label
);
1802 fprintf (f
, "%s:\n", head_label
);
1804 fprintf (f
, "\t%shname%s\t%sPtr to image import by name list\n",
1805 ASM_RVA_BEFORE
, ASM_RVA_AFTER
, ASM_C
);
1807 fprintf (f
, "\t%sthis should be the timestamp, but NT sometimes\n", ASM_C
);
1808 fprintf (f
, "\t%sdoesn't load DLLs when this is set.\n", ASM_C
);
1809 fprintf (f
, "\t%s\t0\t%s loaded time\n", ASM_LONG
, ASM_C
);
1810 fprintf (f
, "\t%s\t0\t%s Forwarder chain\n", ASM_LONG
, ASM_C
);
1811 fprintf (f
, "\t%s__%s_iname%s\t%s imported dll's name\n",
1816 fprintf (f
, "\t%sfthunk%s\t%s pointer to firstthunk\n",
1818 ASM_RVA_AFTER
, ASM_C
);
1820 fprintf (f
, "%sStuff for compatibility\n", ASM_C
);
1824 fprintf (f
, "\t.section\t.idata$5\n");
1825 fprintf (f
, "\t%s\t0\n", ASM_LONG
);
1826 fprintf (f
, "fthunk:\n");
1830 fprintf (f
, "\t.section\t.idata$4\n");
1832 fprintf (f
, "\t%s\t0\n", ASM_LONG
);
1833 fprintf (f
, "\t.section .idata$4\n");
1834 fprintf (f
, "hname:\n");
1838 sprintf (outfile
, "-o dh.o dh.s");
1839 run (as_name
, outfile
);
1841 return bfd_openr ("dh.o", HOW_BFD_TARGET
);
1847 FILE * f
= fopen ("dt.s", FOPEN_WT
);
1851 fprintf (f
, "\t.section .idata$4\n");
1852 fprintf (f
, "\t%s\t0\n", ASM_LONG
);
1856 fprintf (f
, "\t.section .idata$5\n");
1857 fprintf (f
, "\t%s\t0\n", ASM_LONG
);
1861 /* Normally, we need to see a null descriptor built in idata$3 to
1862 act as the terminator for the list. The ideal way, I suppose,
1863 would be to mark this section as a comdat type 2 section, so
1864 only one would appear in the final .exe (if our linker supported
1865 comdat, that is) or cause it to be inserted by something else (say
1869 fprintf (f
, "\t.section .idata$3\n");
1870 fprintf (f
, "\t%s\t0\n", ASM_LONG
);
1871 fprintf (f
, "\t%s\t0\n", ASM_LONG
);
1872 fprintf (f
, "\t%s\t0\n", ASM_LONG
);
1873 fprintf (f
, "\t%s\t0\n", ASM_LONG
);
1874 fprintf (f
, "\t%s\t0\n", ASM_LONG
);
1878 /* Other PowerPC NT compilers use idata$6 for the dllname, so I
1879 do too. Original, huh? */
1880 fprintf (f
, "\t.section .idata$6\n");
1882 fprintf (f
, "\t.section .idata$7\n");
1885 fprintf (f
, "\t%s\t__%s_iname\n", ASM_GLOBAL
, imp_name_lab
);
1886 fprintf (f
, "__%s_iname:\t%s\t\"%s\"\n",
1887 imp_name_lab
, ASM_TEXT
, dll_name
);
1891 sprintf (outfile
, "-o dt.o dt.s");
1892 run (as_name
, outfile
);
1893 return bfd_openr ("dt.o", HOW_BFD_TARGET
);
1908 outarch
= bfd_openw (imp_name
, HOW_BFD_TARGET
);
1912 fprintf (stderr
, _("%s: Can't open .lib file %s\n"),
1913 program_name
, imp_name
);
1916 bfd_set_format (outarch
, bfd_archive
);
1917 outarch
->has_armap
= 1;
1919 /* Work out a reasonable size of things to put onto one line. */
1923 ar_head
= make_head ();
1924 ar_tail
= make_tail();
1926 for (i
= 0; (exp
= d_exports_lexically
[i
]); i
++)
1928 bfd
*n
= make_one_lib_file (exp
, i
);
1934 /* Now stick them all into the archive */
1936 ar_head
->next
= head
;
1937 ar_tail
->next
= ar_head
;
1940 if (! bfd_set_archive_head (outarch
, head
))
1941 bfd_fatal ("bfd_set_archive_head");
1942 if (! bfd_close (outarch
))
1943 bfd_fatal (imp_name
);
1945 while (head
!= NULL
)
1947 bfd
*n
= head
->next
;
1952 /* Delete all the temp files */
1954 if (dontdeltemps
== 0)
1956 sprintf (outfile
, "dh.o");
1958 sprintf (outfile
, "dh.s");
1960 sprintf (outfile
, "dt.o");
1962 sprintf (outfile
, "dt.s");
1966 if (dontdeltemps
< 2)
1968 for (i
= 0, exp
= d_exports
; exp
; i
++, exp
= exp
->next
)
1970 sprintf (outfile
, "ds%d.o",i
);
1971 if (unlink (outfile
) < 0)
1972 fprintf (stderr
, _("%s: cannot delete %s: %s\n"), program_name
,
1973 outfile
, strerror (errno
));
1978 /**********************************************************************/
1980 /* Run through the information gathered from the .o files and the
1981 .def file and work out the best stuff */
1987 export_type
*ap
= *(export_type
**) a
;
1988 export_type
*bp
= *(export_type
**) b
;
1989 if (ap
->ordinal
== bp
->ordinal
)
1992 /* unset ordinals go to the bottom */
1993 if (ap
->ordinal
== -1)
1995 if (bp
->ordinal
== -1)
1997 return (ap
->ordinal
- bp
->ordinal
);
2005 export_type
*ap
= *(export_type
**) a
;
2006 export_type
*bp
= *(export_type
**) b
;
2008 return (strcmp (ap
->name
, bp
->name
));
2012 remove_null_names (ptr
)
2017 for (dst
= src
= 0; src
< d_nfuncs
; src
++)
2021 ptr
[dst
] = ptr
[src
];
2034 for (i
= 0; i
< d_nfuncs
; i
++)
2038 printf ("%d %s @ %d %s%s%s\n",
2039 i
, ptr
[i
]->name
, ptr
[i
]->ordinal
,
2040 ptr
[i
]->noname
? "NONAME " : "",
2041 ptr
[i
]->constant
? "CONSTANT" : "",
2042 ptr
[i
]->data
? "DATA" : "");
2051 process_duplicates (d_export_vec
)
2052 export_type
**d_export_vec
;
2060 /* Remove duplicates */
2061 qsort (d_export_vec
, d_nfuncs
, sizeof (export_type
*), nfunc
);
2063 dtab (d_export_vec
);
2064 for (i
= 0; i
< d_nfuncs
- 1; i
++)
2066 if (strcmp (d_export_vec
[i
]->name
,
2067 d_export_vec
[i
+ 1]->name
) == 0)
2070 export_type
*a
= d_export_vec
[i
];
2071 export_type
*b
= d_export_vec
[i
+ 1];
2075 fprintf (stderr
, _("Warning, ignoring duplicate EXPORT %s %d,%d\n"),
2079 if (a
->ordinal
!= -1
2080 && b
->ordinal
!= -1)
2083 fprintf (stderr
, _("Error, duplicate EXPORT with oridinals %s\n"),
2087 /* Merge attributes */
2088 b
->ordinal
= a
->ordinal
> 0 ? a
->ordinal
: b
->ordinal
;
2089 b
->constant
|= a
->constant
;
2090 b
->noname
|= a
->noname
;
2092 d_export_vec
[i
] = 0;
2095 dtab (d_export_vec
);
2096 remove_null_names (d_export_vec
);
2097 dtab (d_export_vec
);
2102 /* Count the names */
2103 for (i
= 0; i
< d_nfuncs
; i
++)
2105 if (!d_export_vec
[i
]->noname
)
2111 fill_ordinals (d_export_vec
)
2112 export_type
**d_export_vec
;
2119 qsort (d_export_vec
, d_nfuncs
, sizeof (export_type
*), pfunc
);
2121 /* fill in the unset ordinals with ones from our range */
2123 ptr
= (char *) xmalloc (size
);
2125 memset (ptr
, 0, size
);
2127 /* Mark in our large vector all the numbers that are taken */
2128 for (i
= 0; i
< d_nfuncs
; i
++)
2130 if (d_export_vec
[i
]->ordinal
!= -1)
2132 ptr
[d_export_vec
[i
]->ordinal
] = 1;
2133 if (lowest
== -1 || d_export_vec
[i
]->ordinal
< lowest
)
2135 lowest
= d_export_vec
[i
]->ordinal
;
2140 /* Start at 1 for compatibility with MS toolchain. */
2144 /* Now fill in ordinals where the user wants us to choose. */
2145 for (i
= 0; i
< d_nfuncs
; i
++)
2147 if (d_export_vec
[i
]->ordinal
== -1)
2151 /* First try within or after any user supplied range. */
2152 for (j
= lowest
; j
< size
; j
++)
2156 d_export_vec
[i
]->ordinal
= j
;
2160 /* Then try before the range. */
2161 for (j
= lowest
; j
>0; j
--)
2165 d_export_vec
[i
]->ordinal
= j
;
2176 qsort (d_export_vec
, d_nfuncs
, sizeof (export_type
*), pfunc
);
2178 /* Work out the lowest and highest ordinal numbers. */
2181 if (d_export_vec
[0])
2182 d_low_ord
= d_export_vec
[0]->ordinal
;
2183 if (d_export_vec
[d_nfuncs
-1])
2184 d_high_ord
= d_export_vec
[d_nfuncs
-1]->ordinal
;
2193 const export_type
**a
= (const export_type
**) av
;
2194 const export_type
**b
= (const export_type
**) bv
;
2196 return strcmp ((*a
)->name
, (*b
)->name
);
2202 /* First work out the minimum ordinal chosen */
2208 export_type
**d_export_vec
2209 = (export_type
**) xmalloc (sizeof (export_type
*) * d_nfuncs
);
2211 for (i
= 0, exp
= d_exports
; exp
; i
++, exp
= exp
->next
)
2213 d_export_vec
[i
] = exp
;
2216 process_duplicates (d_export_vec
);
2217 fill_ordinals (d_export_vec
);
2219 /* Put back the list in the new order */
2221 for (i
= d_nfuncs
- 1; i
>= 0; i
--)
2223 d_export_vec
[i
]->next
= d_exports
;
2224 d_exports
= d_export_vec
[i
];
2227 /* Build list in alpha order */
2228 d_exports_lexically
= (export_type
**)xmalloc (sizeof(export_type
*)*(d_nfuncs
+1));
2230 for (i
= 0, exp
= d_exports
; exp
; i
++, exp
= exp
->next
)
2232 d_exports_lexically
[i
] = exp
;
2234 d_exports_lexically
[i
] = 0;
2236 qsort (d_exports_lexically
, i
, sizeof (export_type
*), alphafunc
);
2238 /* Fill exp entries with their hint values */
2240 for (i
= 0; i
< d_nfuncs
; i
++)
2242 if (!d_exports_lexically
[i
]->noname
|| show_allnames
)
2243 d_exports_lexically
[i
]->hint
= hint
++;
2248 /**********************************************************************/
2251 usage (file
, status
)
2255 fprintf (file
, _("Usage %s <options> <object-files>\n"), program_name
);
2256 fprintf (file
, _(" --machine <machine>\n"));
2257 fprintf (file
, _(" --output-exp <outname> Generate export file.\n"));
2258 fprintf (file
, _(" --output-lib <outname> Generate input library.\n"));
2259 fprintf (file
, _(" --add-indirect Add dll indirects to export file.\n"));
2260 fprintf (file
, _(" --dllname <name> Name of input dll to put into output lib.\n"));
2261 fprintf (file
, _(" --def <deffile> Name input .def file\n"));
2262 fprintf (file
, _(" --output-def <deffile> Name output .def file\n"));
2263 fprintf (file
, _(" --base-file <basefile> Read linker generated base file\n"));
2264 fprintf (file
, _(" --no-idata4 Don't generate idata$4 section\n"));
2265 fprintf (file
, _(" --no-idata5 Don't generate idata$5 section\n"));
2266 fprintf (file
, _(" -v Verbose\n"));
2267 fprintf (file
, _(" -U Add underscores to .lib\n"));
2268 fprintf (file
, _(" -k Kill @<n> from exported names\n"));
2269 fprintf (file
, _(" --as <name> Use <name> for assembler\n"));
2270 fprintf (file
, _(" --nodelete Keep temp files.\n"));
2274 #define OPTION_NO_IDATA4 'x'
2275 #define OPTION_NO_IDATA5 'c'
2276 static const struct option long_options
[] =
2278 {"nodelete", no_argument
, NULL
, 'n'},
2279 {"dllname", required_argument
, NULL
, 'D'},
2280 {"no-idata4", no_argument
, NULL
, OPTION_NO_IDATA4
},
2281 {"no-idata5", no_argument
, NULL
, OPTION_NO_IDATA5
},
2282 {"output-exp", required_argument
, NULL
, 'e'},
2283 {"output-def", required_argument
, NULL
, 'z'},
2284 {"output-lib", required_argument
, NULL
, 'l'},
2285 {"def", required_argument
, NULL
, 'd'},
2286 {"add-underscore", no_argument
, NULL
, 'U'},
2287 {"killat", no_argument
, NULL
, 'k'},
2288 {"help", no_argument
, NULL
, 'h'},
2289 {"machine", required_argument
, NULL
, 'm'},
2290 {"add-indirect", no_argument
, NULL
, 'a'},
2291 {"base-file", required_argument
, NULL
, 'b'},
2292 {"as", required_argument
, NULL
, 'S'},
2304 program_name
= av
[0];
2307 while ((c
= getopt_long (ac
, av
, "xcz:S:R:A:puaD:l:e:nkvbUh?m:yd:", long_options
, 0))
2312 case OPTION_NO_IDATA4
:
2315 case OPTION_NO_IDATA5
:
2322 /* ignored for compatibility */
2329 output_def
= fopen (optarg
, FOPEN_WT
);
2352 /* We don't currently define YYDEBUG when building
2370 base_file
= fopen (optarg
, FOPEN_RB
);
2373 fprintf (stderr
, _("%s: Unable to open base-file %s\n"),
2385 for (i
= 0; mtable
[i
].type
; i
++)
2387 if (strcmp (mtable
[i
].type
, mname
) == 0)
2391 if (!mtable
[i
].type
)
2393 fprintf (stderr
, _("Machine not supported\n"));
2399 if (!dll_name
&& exp_name
)
2401 char len
= strlen (exp_name
) + 5;
2402 dll_name
= xmalloc (len
);
2403 strcpy (dll_name
, exp_name
);
2404 strcat (dll_name
, ".dll");
2409 process_def_file (def_file
);
2414 firstarg
= av
[optind
];
2415 scan_obj_file (av
[optind
]);
2425 /* Make imp_name safe for use as a label. */
2428 imp_name_lab
= xstrdup (imp_name
);
2429 for (p
= imp_name_lab
; *p
; p
++)
2431 if (!isalpha (*p
) && !isdigit (*p
))
2434 head_label
= make_label("_head_", imp_name_lab
);