1 /* dlltool.c -- tool to generate stuff for PE style DLLs
2 Copyright (C) 1995, 96, 1997 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 02111-1307, USA. */
22 This program allows you to build the files necessary to create
23 DLLs to run on a system which understands PE format image files.
26 See "Peering Inside the PE: A Tour of the Win32 Portable Executable
27 File Format", MSJ 1994, Volume 9 for more information.
28 Also see "Microsoft Portable Executable and Common Object File Format,
29 Specification 4.1" for more information.
31 A DLL contains an export table which contains the information
32 which the runtime loader needs to tie up references from a
35 The export table is generated by this program by reading
36 in a .DEF file or scanning the .a and .o files which will be in the
37 DLL. A .o file can contain information in special ".drectve" sections
38 with export information.
40 A DEF file contains any number of the following commands:
43 NAME <name> [ , <base> ]
44 The result is going to be <name>.EXE
46 LIBRARY <name> [ , <base> ]
47 The result is going to be <name>.DLL
49 EXPORTS ( <name1> [ = <name2> ] [ @ <integer> ] [ NONAME ] [CONSTANT] ) *
50 Declares name1 as an exported symbol from the
51 DLL, with optional ordinal number <integer>
53 IMPORTS ( [ <name> = ] <name> . <name> ) *
54 Ignored for compatibility
57 Puts <string> into output .exp file in the .rdata section
59 [STACKSIZE|HEAPSIZE] <number-reserve> [ , <number-commit> ]
60 Generates --stack|--heap <number-reserve>,<number-commit>
61 in the output .drectve section. The linker will
62 see this and act upon it.
65 SECTIONS ( <sectionname> <attr>+ )*
66 <attr> = READ | WRITE | EXECUTE | SHARED
67 Generates --attr <sectionname> <attr> in the output
68 .drectve section. The linker will see this and act
72 A -export:<name> in a .drectve section in an input .o or .a
73 file to this program is equivalent to a EXPORTS <name>
78 The program generates output files with the prefix supplied
79 on the command line, or in the def file, or taken from the first
82 The .exp.s file contains the information necessary to export
83 the routines in the DLL. The .lib.s file contains the information
84 necessary to use the DLL's routines from a referencing program.
91 asm (".section .drectve");
92 asm (".ascii \"-export:adef\"");
96 printf("hello from the dll %s\n",s);
101 printf("hello from the dll and the other entry point %s\n",s);
105 asm (".section .drectve");
106 asm (".ascii \"-export:cdef\"");
107 asm (".ascii \"-export:ddef\"");
110 printf("hello from the dll %s\n",s);
115 printf("hello from the dll and the other entry point %s\n",s);
133 HEAPSIZE 0x40000, 0x2000
137 SECTIONS donkey READ WRITE
141 # compile up the parts of the dll
146 # put them in a library (you don't have to, you
147 # could name all the .os on the dlltool line)
149 ar qcv thedll.in file1.o file2.o
152 # run this tool over the library and the def file
153 ./dlltool --def thedll.def --output-exp thedll.o --output-lib thedll.a
155 # build the dll with the library with file1.o, file2.o and the export table
156 ld -o thedll.dll thedll.o thedll.in
161 # link the executable with the import library
162 ld -e main -Tthemain.ld -o themain.exe themain.o thedll.a
166 /* .idata section description
168 The .idata section is the import table. It is a collection of several
169 subsections used to keep the pieces for each dll together: .idata$[234567].
170 IE: Each dll's .idata$2's are catenated together, each .idata$3's, etc.
172 .idata$2 = Import Directory Table
173 = array of IMAGE_IMPORT_DESCRIPTOR's.
175 DWORD Characteristics; - pointer to .idata$4
176 DWORD TimeDateStamp; - currently always 0
177 DWORD ForwarderChain; - currently always 0
178 DWORD Name; - pointer to dll's name
179 PIMAGE_THUNK_DATA FirstThunk; - pointer to .idata$5
181 .idata$3 = null terminating entry for .idata$2.
183 .idata$4 = Import Lookup Table
184 = array of array of pointers to hint name table.
185 There is one for each dll being imported from, and each dll's set is
186 terminated by a trailing NULL.
188 .idata$5 = Import Address Table
189 = array of array of pointers to hint name table.
190 There is one for each dll being imported from, and each dll's set is
191 terminated by a trailing NULL.
192 Initially, this table is identical to the Import Lookup Table. However,
193 at load time, the loader overwrites the entries with the address of the
196 .idata$6 = Hint Name Table
197 = Array of { short, asciz } entries, one for each imported function.
198 The `short' is the function's ordinal number.
200 .idata$7 = dll name (eg: "kernel32.dll"). (.idata$6 for ppc)
203 /* AIX requires this to be the first thing in the file. */
210 #define show_allnames 0
212 #define PAGE_SIZE 4096
213 #define PAGE_MASK (-PAGE_SIZE)
215 #include "libiberty.h"
218 #include "demangle.h"
224 #ifdef HAVE_SYS_WAIT_H
225 #include <sys/wait.h>
228 #define WIFEXITED(w) (((w)&0377) == 0)
231 #define WIFSIGNALED(w) (((w)&0377) != 0177 && ((w)&~0377) == 0)
234 #define WTERMSIG(w) ((w) & 0177)
237 #define WEXITSTATUS(w) (((w) >> 8) & 0377)
245 static char *as_name
= "as";
247 static int no_idata4
;
248 static int no_idata5
;
249 static char *exp_name
;
250 static char *imp_name
;
251 static char *head_label
;
252 static char *imp_name_lab
;
253 static char *dll_name
;
255 static int add_indirect
= 0;
256 static int add_underscore
= 0;
257 static int dontdeltemps
= 0;
259 static char *def_file
;
261 static char *program_name
;
266 static FILE *output_def
;
267 static FILE *base_file
;
270 static const char *mname
= "arm";
274 static const char *mname
= "i386";
278 static const char *mname
= "ppc";
281 #define PATHMAX 250 /* What's the right name for this ? */
283 /* This bit of assemly does jmp * ....
284 s set how_jtab_roff to mark where the 32bit abs branch should go */
285 static const unsigned char i386_jtab
[] =
287 0xff, 0x25, 0x00, 0x00, 0x00, 0x00, 0x90, 0x90
290 static const unsigned char arm_jtab
[] =
292 0x00, 0xc0, 0x9f, 0xe5,
293 0x00, 0xf0, 0x9c, 0xe5,
297 /* This is the glue sequence for PowerPC PE. There is a */
298 /* tocrel16-tocdefn reloc against the first instruction. */
299 /* We also need a IMGLUE reloc against the glue function */
300 /* to restore the toc saved by the third instruction in */
302 static const unsigned char ppc_jtab
[] =
304 0x00, 0x00, 0x62, 0x81, /* lwz r11,0(r2) */
305 /* Reloc TOCREL16 __imp_xxx */
306 0x00, 0x00, 0x8B, 0x81, /* lwz r12,0(r11) */
307 0x04, 0x00, 0x41, 0x90, /* stw r2,4(r1) */
308 0xA6, 0x03, 0x89, 0x7D, /* mtctr r12 */
309 0x04, 0x00, 0x4B, 0x80, /* lwz r2,4(r11) */
310 0x20, 0x04, 0x80, 0x4E /* bctr */
314 /* the glue instruction, picks up the toc from the stw in */
315 /* the above code: "lwz r2,4(r1)" */
316 static bfd_vma ppc_glue_insn
= 0x80410004;
319 static char outfile
[PATHMAX
];
324 const char *how_byte
;
325 const char *how_short
;
326 const char *how_long
;
327 const char *how_asciz
;
328 const char *how_comment
;
329 const char *how_jump
;
330 const char *how_global
;
331 const char *how_space
;
332 const char *how_align_short
;
333 const char *how_align_long
;
334 const char *how_bfd_target
;
335 enum bfd_architecture how_bfd_arch
;
336 const unsigned char *how_jtab
;
337 int how_jtab_size
; /* size of the jtab entry */
338 int how_jtab_roff
; /* offset into it for the ind 32 reloc into idata 5 */
341 static const struct mac mtable
[] =
345 "arm", ".byte", ".short", ".long", ".asciz", "@",
346 "ldr\tip,[pc]\n\tldr\tpc,[ip]\n\t.long",
347 ".global", ".space", ".align\t2",".align\t4","pe-arm-little", bfd_arch_arm
,
348 arm_jtab
, sizeof(arm_jtab
),8
353 "i386", ".byte", ".short", ".long", ".asciz", "#", "jmp *", ".global", ".space", ".align\t2",".align\t4","pe-i386",bfd_arch_i386
,
354 i386_jtab
,sizeof(i386_jtab
),2,
359 "ppc", ".byte", ".short", ".long", ".asciz", "#", "jmp *", ".global", ".space", ".align\t2",".align\t4","pe-powerpcle",bfd_arch_powerpc
,
360 ppc_jtab
,sizeof(ppc_jtab
),0,
373 typedef struct export
376 const char *internal_name
;
385 static const char *rvaafter
PARAMS ((int));
386 static const char *rvabefore
PARAMS ((int));
387 static const char *asm_prefix
PARAMS ((int));
388 static void run
PARAMS ((const char *, char *));
389 static void basenames
PARAMS ((bfd
*));
390 static void scan_open_obj_file
PARAMS ((bfd
*));
391 static void scan_obj_file
PARAMS ((const char *));
392 static void dump_def_info
PARAMS ((FILE *));
393 static int sfunc
PARAMS ((const void *, const void *));
394 static void flush_page
PARAMS ((FILE *, long *, int, int));
395 static void gen_def_file
PARAMS ((void));
396 static void gen_exp_file
PARAMS ((void));
397 static const char *xlate
PARAMS ((const char *));
398 static void dump_iat
PARAMS ((FILE *, export_type
*));
399 static char *make_label
PARAMS ((const char *, const char *));
400 static bfd
*make_one_lib_file
PARAMS ((export_type
*, int));
401 static bfd
*make_head
PARAMS ((void));
402 static bfd
*make_tail
PARAMS ((void));
403 static void gen_lib_file
PARAMS ((void));
404 static int pfunc
PARAMS ((const void *, const void *));
405 static int nfunc
PARAMS ((const void *, const void *));
406 static void remove_null_names
PARAMS ((export_type
**));
407 static void dtab
PARAMS ((export_type
**));
408 static void process_duplicates
PARAMS ((export_type
**));
409 static void fill_ordinals
PARAMS ((export_type
**));
410 static int alphafunc
PARAMS ((const void *, const void *));
411 static void mangle_defs
PARAMS ((void));
412 static void usage
PARAMS ((FILE *, int));
462 #define ASM_BYTE mtable[machine].how_byte
463 #define ASM_SHORT mtable[machine].how_short
464 #define ASM_LONG mtable[machine].how_long
465 #define ASM_TEXT mtable[machine].how_asciz
466 #define ASM_C mtable[machine].how_comment
467 #define ASM_JUMP mtable[machine].how_jump
468 #define ASM_GLOBAL mtable[machine].how_global
469 #define ASM_SPACE mtable[machine].how_space
470 #define ASM_ALIGN_SHORT mtable[machine].how_align_short
471 #define ASM_RVA_BEFORE rvabefore(machine)
472 #define ASM_RVA_AFTER rvaafter(machine)
473 #define ASM_PREFIX asm_prefix(machine)
474 #define ASM_ALIGN_LONG mtable[machine].how_align_long
475 #define HOW_BFD_TARGET 0 /* always default*/
476 #define HOW_BFD_ARCH mtable[machine].how_bfd_arch
477 #define HOW_JTAB mtable[machine].how_jtab
478 #define HOW_JTAB_SIZE mtable[machine].how_jtab_size
479 #define HOW_JTAB_ROFF mtable[machine].how_jtab_roff
483 process_def_file (name
)
486 FILE *f
= fopen (name
, FOPEN_RT
);
489 fprintf (stderr
, "%s: Can't open def file %s\n", program_name
, name
);
498 /**********************************************************************/
500 /* Communications with the parser */
502 static const char *d_name
; /* Arg to NAME or LIBRARY */
503 static int d_nfuncs
; /* Number of functions exported */
504 static int d_named_nfuncs
; /* Number of named functions exported */
505 static int d_low_ord
; /* Lowest ordinal index */
506 static int d_high_ord
; /* Highest ordinal index */
507 static export_type
*d_exports
; /*list of exported functions */
508 static export_type
**d_exports_lexically
; /* vector of exported functions in alpha order */
509 static dlist_type
*d_list
; /* Descriptions */
510 static dlist_type
*a_list
; /* Stuff to go in directives */
519 fprintf (stderr
, "%s: Syntax error in def file %s:%d\n",
520 program_name
, def_file
, linenumber
);
525 def_exports (name
, internal_name
, ordinal
, noname
, constant
)
527 const char *internal_name
;
532 struct export
*p
= (struct export
*) xmalloc (sizeof (*p
));
535 p
->internal_name
= internal_name
? internal_name
: name
;
536 p
->ordinal
= ordinal
;
537 p
->constant
= constant
;
545 def_name (name
, base
)
550 fprintf (stderr
, "%s NAME %s base %x\n", program_name
, name
, base
);
553 fprintf (stderr
, "Can't have LIBRARY and NAME\n");
560 def_library (name
, base
)
565 printf ("%s: LIBRARY %s base %x\n", program_name
, name
, base
);
568 fprintf (stderr
, "%s: Can't have LIBRARY and NAME\n", program_name
);
575 def_description (desc
)
578 dlist_type
*d
= (dlist_type
*) xmalloc (sizeof (dlist_type
));
579 d
->text
= xstrdup (desc
);
588 dlist_type
*d
= (dlist_type
*) xmalloc (sizeof (dlist_type
));
589 d
->text
= xstrdup (dir
);
595 def_stacksize (reserve
, commit
)
601 sprintf (b
, "-stack 0x%x,0x%x ", reserve
, commit
);
603 sprintf (b
, "-stack 0x%x ", reserve
);
604 new_directive (xstrdup (b
));
608 def_heapsize (reserve
, commit
)
614 sprintf (b
, "-heap 0x%x,0x%x ", reserve
, commit
);
616 sprintf (b
, "-heap 0x%x ", reserve
);
617 new_directive (xstrdup (b
));
621 def_import (internal
, module
, entry
)
622 const char *internal
;
627 fprintf (stderr
, "%s: IMPORTS are ignored", program_name
);
631 def_version (major
, minor
)
635 printf ("VERSION %d.%d\n", major
, minor
);
639 def_section (name
, attr
)
656 sprintf (buf
, "-attr %s %s", name
, atts
);
657 new_directive (xstrdup (buf
));
665 def_section ("CODE", attr
);
672 def_section ("DATA", attr
);
675 /**********************************************************************/
688 fprintf (stderr
, "%s %s\n", what
, args
);
692 for (s
= args
; *s
; s
++)
696 argv
= alloca (sizeof (char *) * (i
+ 3));
703 while (*s
!= ' ' && *s
!= 0)
715 execvp (what
, (char **) argv
);
716 fprintf (stderr
, "%s: can't exec %s\n", program_name
, what
);
722 fprintf (stderr
, "%s: vfork failed, %d\n", program_name
, errno
);
728 waitpid (pid
, &status
, 0);
731 if (WIFSIGNALED (status
))
733 fprintf (stderr
, "%s: %s %s terminated with signal %d\n",
734 program_name
, what
, args
, WTERMSIG (status
));
738 if (WIFEXITED (status
))
740 fprintf (stderr
, "%s: %s %s terminated with exit status %d\n",
741 program_name
, what
, args
, WEXITSTATUS (status
));
748 /* read in and block out the base relocations */
756 scan_open_obj_file (abfd
)
759 /* Look for .drectve's */
760 asection
*s
= bfd_get_section_by_name (abfd
, ".drectve");
763 int size
= bfd_get_section_size_before_reloc (s
);
764 char *buf
= xmalloc (size
);
767 bfd_get_section_contents (abfd
, s
, buf
, 0, size
);
769 fprintf (stderr
, "%s: Sucking in info from %s\n",
771 bfd_get_filename (abfd
));
773 /* Search for -export: strings */
779 && strncmp (p
, "-export:", 8) == 0)
785 while (p
< e
&& *p
!= ' ' && *p
!= '-')
787 c
= xmalloc (p
- name
+ 1);
788 memcpy (c
, name
, p
- name
);
790 /* FIXME: The 5th arg is for the `constant' field.
791 What should it be? Not that it matters since it's not
793 def_exports (c
, 0, -1, 0, 0);
804 fprintf (stderr
, "%s: Done readin\n",
809 scan_obj_file (filename
)
810 const char *filename
;
812 bfd
*f
= bfd_openr (filename
, 0);
816 fprintf (stderr
, "%s: Unable to open object file %s\n",
821 if (bfd_check_format (f
, bfd_archive
))
823 bfd
*arfile
= bfd_openr_next_archived_file (f
, 0);
826 if (bfd_check_format (arfile
, bfd_object
))
827 scan_open_obj_file (arfile
);
829 arfile
= bfd_openr_next_archived_file (f
, arfile
);
832 else if (bfd_check_format (f
, bfd_object
))
834 scan_open_obj_file (f
);
840 /**********************************************************************/
848 fprintf (f
, "%s ", ASM_C
);
849 for (i
= 0; oav
[i
]; i
++)
850 fprintf (f
, "%s ", oav
[i
]);
852 for (i
= 0, exp
= d_exports
; exp
; i
++, exp
= exp
->next
)
854 fprintf (f
, "%s %d = %s %s @ %d %s%s\n",
860 exp
->noname
? "NONAME " : "",
861 exp
->constant
? "CONSTANT" : "");
865 /* Generate the .exp file */
872 return *(const long *) a
- *(const long *) b
;
876 flush_page (f
, need
, page_addr
, on_page
)
884 /* Flush this page */
885 fprintf (f
, "\t%s\t0x%08x\t%s Starting RVA for chunk\n",
889 fprintf (f
, "\t%s\t0x%x\t%s Size of block\n",
891 (on_page
* 2) + (on_page
& 1) * 2 + 8,
893 for (i
= 0; i
< on_page
; i
++)
895 fprintf (f
, "\t%s\t0x%lx\n", ASM_SHORT
, (need
[i
] - page_addr
) | 0x3000);
899 fprintf (f
, "\t%s\t0x%x\n", ASM_SHORT
, 0 | 0x0000);
908 fprintf (output_def
, ";");
909 for (i
= 0; oav
[i
]; i
++)
910 fprintf (output_def
, " %s", oav
[i
]);
912 fprintf (output_def
, "\nEXPORTS\n");
914 for (i
= 0, exp
= d_exports
; exp
; i
++, exp
= exp
->next
)
916 char *quote
= strchr (exp
->name
, '.') ? "\"" : "";
917 fprintf (output_def
, "\t%s%s%s @ %d%s ; %s\n",
922 exp
->noname
? " NONAME" : "",
923 cplus_demangle (exp
->internal_name
, DMGL_ANSI
| DMGL_PARAMS
));
936 sprintf (outfile
, "t%s", exp_name
);
939 fprintf (stderr
, "%s: Generate exp file %s\n",
940 program_name
, exp_name
);
942 f
= fopen (outfile
, FOPEN_WT
);
945 fprintf (stderr
, "%s: Unable to open output file %s\n", program_name
, outfile
);
950 fprintf (stderr
, "%s: Opened file %s\n",
951 program_name
, outfile
);
957 fprintf (f
, "\t.section .edata\n\n");
958 fprintf (f
, "\t%s 0 %s Allways 0\n", ASM_LONG
, ASM_C
);
959 fprintf (f
, "\t%s 0x%lx %s Time and date\n", ASM_LONG
, (long) time(0),
961 fprintf (f
, "\t%s 0 %s Major and Minor version\n", ASM_LONG
, ASM_C
);
962 fprintf (f
, "\t%sname%s %s Ptr to name of dll\n", ASM_RVA_BEFORE
, ASM_RVA_AFTER
, ASM_C
);
963 fprintf (f
, "\t%s %d %s Starting ordinal of exports\n", ASM_LONG
, d_low_ord
, ASM_C
);
966 fprintf (f
, "\t%s %d %s Number of functions\n", ASM_LONG
, d_high_ord
- d_low_ord
+ 1, ASM_C
);
967 fprintf(f
,"\t%s named funcs %d, low ord %d, high ord %d\n",
969 d_named_nfuncs
, d_low_ord
, d_high_ord
);
970 fprintf (f
, "\t%s %d %s Number of names\n", ASM_LONG
,
971 show_allnames
? d_high_ord
- d_low_ord
+ 1 : d_named_nfuncs
, ASM_C
);
972 fprintf (f
, "\t%safuncs%s %s Address of functions\n", ASM_RVA_BEFORE
, ASM_RVA_AFTER
, ASM_C
);
974 fprintf (f
, "\t%sanames%s %s Address of Name Pointer Table\n",
975 ASM_RVA_BEFORE
, ASM_RVA_AFTER
, ASM_C
);
977 fprintf (f
, "\t%sanords%s %s Address of ordinals\n", ASM_RVA_BEFORE
, ASM_RVA_AFTER
, ASM_C
);
979 fprintf (f
, "name: %s \"%s\"\n", ASM_TEXT
, dll_name
);
982 fprintf(f
,"%s Export address Table\n", ASM_C
);
983 fprintf(f
,"\t%s\n", ASM_ALIGN_LONG
);
984 fprintf (f
, "afuncs:\n");
987 for (exp
= d_exports
; exp
; exp
= exp
->next
)
989 if (exp
->ordinal
!= i
)
992 fprintf (f
, "\t%s\t%d\t%s %d..%d missing\n",
994 (exp
->ordinal
- i
) * 4,
996 i
, exp
->ordinal
- 1);
999 while (i
< exp
->ordinal
)
1001 fprintf(f
,"\t%s\t0\n", ASM_LONG
);
1005 fprintf (f
, "\t%s%s%s%s\t%s %d\n", ASM_RVA_BEFORE
,
1007 exp
->internal_name
, ASM_RVA_AFTER
, ASM_C
, exp
->ordinal
);
1011 fprintf (f
,"%s Export Name Pointer Table\n", ASM_C
);
1012 fprintf (f
, "anames:\n");
1014 for (i
= 0; (exp
= d_exports_lexically
[i
]); i
++)
1016 if (!exp
->noname
|| show_allnames
)
1017 fprintf (f
, "\t%sn%d%s\n", ASM_RVA_BEFORE
, exp
->ordinal
, ASM_RVA_AFTER
);
1020 fprintf (f
,"%s Export Oridinal Table\n", ASM_C
);
1021 fprintf (f
, "anords:\n");
1022 for (i
= 0; (exp
= d_exports_lexically
[i
]); i
++)
1024 if (!exp
->noname
|| show_allnames
)
1025 fprintf (f
, "\t%s %d\n", ASM_SHORT
, exp
->ordinal
- d_low_ord
);
1028 fprintf(f
,"%s Export Name Table\n", ASM_C
);
1029 for (i
= 0; (exp
= d_exports_lexically
[i
]); i
++)
1030 if (!exp
->noname
|| show_allnames
)
1031 fprintf (f
, "n%d: %s \"%s\"\n", exp
->ordinal
, ASM_TEXT
, exp
->name
);
1035 fprintf (f
, "\t.section .drectve\n");
1036 for (dl
= a_list
; dl
; dl
= dl
->next
)
1038 fprintf (f
, "\t%s\t\"%s\"\n", ASM_TEXT
, dl
->text
);
1043 fprintf (f
, "\t.section .rdata\n");
1044 for (dl
= d_list
; dl
; dl
= dl
->next
)
1048 /* We dont output as ascii 'cause there can
1049 be quote characters in the string */
1052 for (p
= dl
->text
; *p
; p
++)
1055 fprintf (f
, "\t%s\t", ASM_BYTE
);
1058 fprintf (f
, "%d", *p
);
1061 fprintf (f
, ",0\n");
1075 /* Add to the output file a way of getting to the exported names
1076 without using the import library. */
1079 fprintf (f
, "\t.section\t.rdata\n");
1080 for (i
= 0, exp
= d_exports
; exp
; i
++, exp
= exp
->next
)
1081 if (!exp
->noname
|| show_allnames
)
1083 fprintf (f
, "\t%s\t__imp_%s\n", ASM_GLOBAL
, exp
->name
);
1084 fprintf (f
, "__imp_%s:\n", exp
->name
);
1085 fprintf (f
, "\t%s\t%s\n", ASM_LONG
, exp
->name
);
1089 /* Dump the reloc section if a base file is provided */
1093 long need
[PAGE_SIZE
];
1100 fprintf (f
, "\t.section\t.init\n");
1101 fprintf (f
, "lab:\n");
1103 fseek (base_file
, 0, SEEK_END
);
1104 numbytes
= ftell (base_file
);
1105 fseek (base_file
, 0, SEEK_SET
);
1106 copy
= xmalloc (numbytes
);
1107 fread (copy
, 1, numbytes
, base_file
);
1108 num_entries
= numbytes
/ sizeof (long);
1111 fprintf (f
, "\t.section\t.reloc\n");
1117 qsort (copy
, num_entries
, sizeof (long), sfunc
);
1118 /* Delete duplcates */
1119 for (src
= 0; src
< num_entries
; src
++)
1121 if (last
!= copy
[src
])
1122 last
= copy
[dst
++] = copy
[src
];
1126 page_addr
= addr
& PAGE_MASK
; /* work out the page addr */
1128 for (j
= 0; j
< num_entries
; j
++)
1131 if ((addr
& PAGE_MASK
) != page_addr
)
1133 flush_page (f
, need
, page_addr
, on_page
);
1135 page_addr
= addr
& PAGE_MASK
;
1137 need
[on_page
++] = addr
;
1139 flush_page (f
, need
, page_addr
, on_page
);
1141 /* fprintf (f, "\t%s\t0,0\t%s End\n", ASM_LONG, ASM_C);*/
1147 /* assemble the file */
1148 sprintf (outfile
, "-o %s t%s", exp_name
, exp_name
);
1149 run (as_name
, outfile
);
1150 if (dontdeltemps
== 0)
1152 sprintf (outfile
, "t%s", exp_name
);
1163 char *copy
= xmalloc (strlen (name
) + 2);
1165 strcpy (copy
+ 1, name
);
1172 p
= strchr (name
, '@');
1179 /**********************************************************************/
1186 if (exp
->noname
&& !show_allnames
)
1188 fprintf (f
, "\t%s\t0x%08x\n",
1190 exp
->ordinal
| 0x80000000); /* hint or orindal ?? */
1194 fprintf (f
, "\t%sID%d%s\n", ASM_RVA_BEFORE
,
1210 unsigned char *data
;
1225 static sinfo secdata
[NSECS
] =
1227 { TEXT
, ".text", SEC_CODE
| SEC_HAS_CONTENTS
, 2},
1228 { DATA
, ".data", SEC_DATA
, 2},
1229 { BSS
, ".bss", 0, 2},
1230 { IDATA7
, ".idata$7", SEC_HAS_CONTENTS
, 2},
1231 { IDATA5
, ".idata$5", SEC_HAS_CONTENTS
, 2},
1232 { IDATA4
, ".idata$4", SEC_HAS_CONTENTS
, 2},
1233 { IDATA6
, ".idata$6", SEC_HAS_CONTENTS
, 1}
1238 /* Sections numbered to make the order the same as other PowerPC NT */
1239 /* compilers. This also keeps funny alignment thingies from happening. */
1252 static sinfo secdata
[NSECS
] =
1254 { TEXT
, ".text", SEC_CODE
| SEC_HAS_CONTENTS
, 3},
1255 { PDATA
, ".pdata", SEC_HAS_CONTENTS
, 2},
1256 { RDATA
, ".reldata", SEC_HAS_CONTENTS
, 2},
1257 { IDATA5
, ".idata$5", SEC_HAS_CONTENTS
, 2},
1258 { IDATA4
, ".idata$4", SEC_HAS_CONTENTS
, 2},
1259 { IDATA6
, ".idata$6", SEC_HAS_CONTENTS
, 1},
1260 { IDATA7
, ".idata$7", SEC_HAS_CONTENTS
, 2},
1261 { DATA
, ".data", SEC_DATA
, 2},
1262 { BSS
, ".bss", 0, 2}
1268 This is what we're trying to make
1271 .global _GetFileVersionInfoSizeW@8
1272 .global __imp_GetFileVersionInfoSizeW@8
1273 _GetFileVersionInfoSizeW@8:
1274 jmp * __imp_GetFileVersionInfoSizeW@8
1275 .section .idata$7 # To force loading of head
1276 .long __version_a_head
1277 # Import Address Table
1279 __imp_GetFileVersionInfoSizeW@8:
1282 # Import Lookup Table
1288 .asciz "GetFileVersionInfoSizeW"
1291 For the PowerPC, here's the variation on the above scheme:
1293 # Rather than a simple "jmp *", the code to get to the dll function
1296 lwz r11,[tocv]__imp_function_name(r2)
1297 # RELOC: 00000000 TOCREL16,TOCDEFN __imp_function_name
1306 make_label (prefix
, name
)
1310 int len
= strlen (ASM_PREFIX
) + strlen (prefix
) + strlen (name
);
1311 char *copy
= xmalloc (len
+1 );
1312 strcpy (copy
, ASM_PREFIX
);
1313 strcat (copy
, prefix
);
1314 strcat (copy
, name
);
1319 make_one_lib_file (exp
, i
)
1327 sprintf (outfile
, "%ss%d.s", prefix
, i
);
1328 f
= fopen (outfile
, FOPEN_WT
);
1329 fprintf (f
, "\t.text\n");
1330 fprintf (f
, "\t%s\t%s%s\n", ASM_GLOBAL
, ASM_PREFIX
, exp
->name
);
1331 fprintf (f
, "\t%s\t__imp_%s\n", ASM_GLOBAL
, exp
->name
);
1332 fprintf (f
, "%s%s:\n\t%s\t__imp_%s\n", ASM_PREFIX
,
1333 exp
->name
, ASM_JUMP
, exp
->name
);
1335 fprintf (f
, "\t.section\t.idata$7\t%s To force loading of head\n", ASM_C
);
1336 fprintf (f
, "\t%s\t%s\n", ASM_LONG
, head_label
);
1339 fprintf (f
,"%s Import Address Table\n", ASM_C
);
1341 fprintf (f
, "\t.section .idata$5\n");
1342 fprintf (f
, "__imp_%s:\n", exp
->name
);
1346 fprintf (f
, "\n%s Import Lookup Table\n", ASM_C
);
1347 fprintf (f
, "\t.section .idata$4\n");
1351 if(!exp
->noname
|| show_allnames
)
1353 fprintf (f
, "%s Hint/Name table\n", ASM_C
);
1354 fprintf (f
, "\t.section .idata$6\n");
1355 fprintf (f
, "ID%d:\t%s\t%d\n", exp
->ordinal
, ASM_SHORT
, exp
->hint
);
1356 fprintf (f
, "\t%s\t\"%s\"\n", ASM_TEXT
, xlate (exp
->name
));
1362 sprintf (outfile
, "-o %ss%d.o %ss%d.s", prefix
, i
, prefix
, i
);
1364 run (as_name
, outfile
);
1375 asymbol
**iname_lab_pp
;
1378 /* Extra Symbols for PPC */
1390 /* one symbol for each section, 2 extra + a null */
1391 asymbol
*ptrs
[NSECS
+3+EXTRA
+1];
1393 char *outname
= xmalloc (10);
1395 sprintf (outname
, "ds%d.o", i
);
1396 abfd
= bfd_openw (outname
, HOW_BFD_TARGET
);
1399 fprintf (stderr
, "%s: bfd_open failed open output file %s\n",
1400 program_name
, outname
);
1404 bfd_set_format (abfd
, bfd_object
);
1405 bfd_set_arch_mach (abfd
, HOW_BFD_ARCH
, 0);
1408 /* First make symbols for the sections */
1409 for (i
= 0; i
< NSECS
; i
++)
1411 sinfo
*si
= secdata
+ i
;
1414 si
->sec
= bfd_make_section_old_way (abfd
, si
->name
);
1415 bfd_set_section_flags (abfd
,
1419 bfd_set_section_alignment(abfd
, si
->sec
, si
->align
);
1420 si
->sec
->output_section
= si
->sec
;
1421 si
->sym
= bfd_make_empty_symbol(abfd
);
1422 si
->sym
->name
= si
->sec
->name
;
1423 si
->sym
->section
= si
->sec
;
1424 si
->sym
->flags
= BSF_LOCAL
;
1426 ptrs
[oidx
] = si
->sym
;
1427 si
->sympp
= ptrs
+ oidx
;
1432 exp_label
= bfd_make_empty_symbol(abfd
);
1433 exp_label
->name
= make_label ("",exp
->name
);
1435 /* On PowerPC, the function name points to a descriptor in the
1436 rdata section, the first element of which is a pointer to the
1437 code (..function_name), and the second points to the .toc
1440 if (machine
== MPPC
)
1441 exp_label
->section
= secdata
[RDATA
].sec
;
1444 exp_label
->section
= secdata
[TEXT
].sec
;
1446 exp_label
->flags
= BSF_GLOBAL
;
1447 exp_label
->value
= 0;
1449 ptrs
[oidx
++] = exp_label
;
1451 iname
= bfd_make_empty_symbol(abfd
);
1452 iname
->name
= make_label ("__imp_", exp
->name
);
1453 iname
->section
= secdata
[IDATA5
].sec
;
1454 iname
->flags
= BSF_GLOBAL
;
1458 iname_lab
= bfd_make_empty_symbol(abfd
);
1460 iname_lab
->name
= head_label
;
1461 iname_lab
->section
= (asection
*)&bfd_und_section
;
1462 iname_lab
->flags
= 0;
1463 iname_lab
->value
= 0;
1466 iname_pp
= ptrs
+ oidx
;
1467 ptrs
[oidx
++] = iname
;
1469 iname_lab_pp
= ptrs
+ oidx
;
1470 ptrs
[oidx
++] = iname_lab
;
1473 /* The symbol refering to the code (.text) */
1475 asymbol
*function_name
;
1477 function_name
= bfd_make_empty_symbol(abfd
);
1478 function_name
->name
= make_label ("..", exp
->name
);
1479 function_name
->section
= secdata
[TEXT
].sec
;
1480 function_name
->flags
= BSF_GLOBAL
;
1481 function_name
->value
= 0;
1483 fn_pp
= ptrs
+ oidx
;
1484 ptrs
[oidx
++] = function_name
;
1487 /* The .toc symbol */
1489 asymbol
*toc_symbol
; /* The .toc symbol */
1491 toc_symbol
= bfd_make_empty_symbol(abfd
);
1492 toc_symbol
->name
= make_label (".", "toc");
1493 toc_symbol
->section
= (asection
*)&bfd_und_section
;
1494 toc_symbol
->flags
= BSF_GLOBAL
;
1495 toc_symbol
->value
= 0;
1497 toc_pp
= ptrs
+ oidx
;
1498 ptrs
[oidx
++] = toc_symbol
;
1504 for (i
= 0; i
< NSECS
; i
++)
1506 sinfo
*si
= secdata
+ i
;
1507 asection
*sec
= si
->sec
;
1514 si
->size
= HOW_JTAB_SIZE
;
1515 si
->data
= xmalloc (HOW_JTAB_SIZE
);
1516 memcpy (si
->data
, HOW_JTAB
, HOW_JTAB_SIZE
);
1518 /* add the reloc into idata$5 */
1519 rel
= xmalloc (sizeof (arelent
));
1520 rpp
= xmalloc (sizeof (arelent
*) * 2);
1523 rel
->address
= HOW_JTAB_ROFF
;
1526 if (machine
== MPPC
)
1528 rel
->howto
= bfd_reloc_type_lookup (abfd
,
1529 BFD_RELOC_16_GOTOFF
);
1530 rel
->sym_ptr_ptr
= iname_pp
;
1534 rel
->howto
= bfd_reloc_type_lookup (abfd
, BFD_RELOC_32
);
1535 rel
->sym_ptr_ptr
= secdata
[IDATA5
].sympp
;
1537 sec
->orelocation
= rpp
;
1538 sec
->reloc_count
= 1;
1542 /* An idata$4 or idata$5 is one word long, and has an
1545 si
->data
= xmalloc (4);
1550 si
->data
[0] = exp
->ordinal
;
1551 si
->data
[1] = exp
->ordinal
>> 8;
1552 si
->data
[2] = exp
->ordinal
>> 16;
1557 sec
->reloc_count
= 1;
1558 memset (si
->data
, 0, si
->size
);
1559 rel
= xmalloc (sizeof (arelent
));
1560 rpp
= xmalloc (sizeof (arelent
*) * 2);
1565 rel
->howto
= bfd_reloc_type_lookup (abfd
, BFD_RELOC_RVA
);
1566 rel
->sym_ptr_ptr
= secdata
[IDATA6
].sympp
;
1567 sec
->orelocation
= rpp
;
1575 int idx
= exp
->hint
+ 1;
1576 si
->size
= strlen (xlate (exp
->name
)) + 3;
1577 si
->data
= xmalloc (si
->size
);
1578 si
->data
[0] = idx
& 0xff;
1579 si
->data
[1] = idx
>> 8;
1580 strcpy (si
->data
+ 2, xlate (exp
->name
));
1585 si
->data
=xmalloc(4);
1586 memset (si
->data
, 0, si
->size
);
1587 rel
= xmalloc (sizeof (arelent
));
1588 rpp
= xmalloc (sizeof (arelent
*) * 2);
1592 rel
->howto
= bfd_reloc_type_lookup (abfd
, BFD_RELOC_RVA
);
1593 rel
->sym_ptr_ptr
= iname_lab_pp
;
1594 sec
->orelocation
= rpp
;
1595 sec
->reloc_count
= 1;
1601 /* The .pdata section is 5 words long. */
1602 /* Think of it as: */
1605 /* bfd_vma BeginAddress, [0x00] */
1606 /* EndAddress, [0x04] */
1607 /* ExceptionHandler, [0x08] */
1608 /* HandlerData, [0x0c] */
1609 /* PrologEndAddress; [0x10] */
1612 /* So this pdata section setups up this as a glue linkage to
1613 a dll routine. There are a number of house keeping things
1616 1. In the name of glue trickery, the ADDR32 relocs for 0,
1617 4, and 0x10 are set to point to the same place:
1619 2. There is one more reloc needed in the pdata section.
1620 The actual glue instruction to restore the toc on
1621 return is saved as the offset in an IMGLUE reloc.
1622 So we need a total of four relocs for this section.
1624 3. Lastly, the HandlerData field is set to 0x03, to indicate
1625 that this is a glue routine.
1627 arelent
*imglue
, *ba_rel
, *ea_rel
, *pea_rel
;
1629 /* alignment must be set to 2**2 or you get extra stuff */
1630 bfd_set_section_alignment(abfd
, sec
, 2);
1633 si
->data
=xmalloc(4 * 5);
1634 memset (si
->data
, 0, si
->size
);
1635 rpp
= xmalloc (sizeof (arelent
*) * 5);
1636 rpp
[0] = imglue
= xmalloc (sizeof (arelent
));
1637 rpp
[1] = ba_rel
= xmalloc (sizeof (arelent
));
1638 rpp
[2] = ea_rel
= xmalloc (sizeof (arelent
));
1639 rpp
[3] = pea_rel
= xmalloc (sizeof (arelent
));
1642 /* stick the toc reload instruction in the glue reloc */
1643 bfd_put_32(abfd
, ppc_glue_insn
, (char *) &imglue
->address
);
1646 imglue
->howto
= bfd_reloc_type_lookup (abfd
,
1647 BFD_RELOC_32_GOTOFF
);
1648 imglue
->sym_ptr_ptr
= fn_pp
;
1650 ba_rel
->address
= 0;
1652 ba_rel
->howto
= bfd_reloc_type_lookup (abfd
, BFD_RELOC_32
);
1653 ba_rel
->sym_ptr_ptr
= fn_pp
;
1655 bfd_put_32(abfd
, 0x18, si
->data
+ 0x04);
1656 ea_rel
->address
= 4;
1658 ea_rel
->howto
= bfd_reloc_type_lookup (abfd
, BFD_RELOC_32
);
1659 ea_rel
->sym_ptr_ptr
= fn_pp
;
1661 /* mark it as glue */
1662 bfd_put_32(abfd
, 0x03, si
->data
+ 0x0c);
1664 /* mark the prolog end address */
1665 bfd_put_32(abfd
, 0x0D, si
->data
+ 0x10);
1666 pea_rel
->address
= 0x10;
1667 pea_rel
->addend
= 0;
1668 pea_rel
->howto
= bfd_reloc_type_lookup (abfd
, BFD_RELOC_32
);
1669 pea_rel
->sym_ptr_ptr
= fn_pp
;
1671 sec
->orelocation
= rpp
;
1672 sec
->reloc_count
= 4;
1676 /* Each external function in a PowerPC PE file has a two word
1677 descriptor consisting of:
1678 1. The address of the code.
1679 2. The address of the appropriate .toc
1680 We use relocs to build this.
1684 si
->data
= xmalloc (8);
1685 memset (si
->data
, 0, si
->size
);
1687 rpp
= xmalloc (sizeof (arelent
*) * 3);
1688 rpp
[0] = rel
= xmalloc (sizeof (arelent
));
1689 rpp
[1] = xmalloc (sizeof (arelent
));
1694 rel
->howto
= bfd_reloc_type_lookup (abfd
, BFD_RELOC_32
);
1695 rel
->sym_ptr_ptr
= fn_pp
;
1701 rel
->howto
= bfd_reloc_type_lookup (abfd
, BFD_RELOC_32
);
1702 rel
->sym_ptr_ptr
= toc_pp
;
1704 sec
->orelocation
= rpp
;
1705 sec
->reloc_count
= 2;
1707 #endif /* DLLTOOL_PPC */
1713 /* Size up all the sections */
1714 for (i
= 0; i
< NSECS
; i
++)
1716 sinfo
*si
= secdata
+ i
;
1718 bfd_set_section_size (abfd
, si
->sec
, si
->size
);
1719 bfd_set_section_vma (abfd
, si
->sec
, vma
);
1721 /* vma += si->size;*/
1724 /* Write them out */
1725 for (i
= 0; i
< NSECS
; i
++)
1727 sinfo
*si
= secdata
+ i
;
1729 if (i
== IDATA5
&& no_idata5
)
1732 if (i
== IDATA4
&& no_idata4
)
1735 bfd_set_section_contents (abfd
, si
->sec
,
1740 bfd_set_symtab (abfd
, ptrs
, oidx
);
1742 abfd
= bfd_openr (outname
, HOW_BFD_TARGET
);
1751 FILE * f
= fopen ("dh.s", FOPEN_WT
);
1753 fprintf (f
, "%s IMAGE_IMPORT_DESCRIPTOR\n", ASM_C
);
1754 fprintf (f
, "\t.section .idata$2\n");
1756 fprintf(f
,"\t%s\t%s\n", ASM_GLOBAL
,head_label
);
1758 fprintf (f
, "%s:\n", head_label
);
1760 fprintf (f
, "\t%shname%s\t%sPtr to image import by name list\n",
1761 ASM_RVA_BEFORE
, ASM_RVA_AFTER
, ASM_C
);
1763 fprintf (f
, "\t%sthis should be the timestamp, but NT sometimes\n", ASM_C
);
1764 fprintf (f
, "\t%sdoesn't load DLLs when this is set.\n", ASM_C
);
1765 fprintf (f
, "\t%s\t0\t%s loaded time\n", ASM_LONG
, ASM_C
);
1766 fprintf (f
, "\t%s\t0\t%s Forwarder chain\n", ASM_LONG
, ASM_C
);
1767 fprintf (f
, "\t%s__%s_iname%s\t%s imported dll's name\n",
1772 fprintf (f
, "\t%sfthunk%s\t%s pointer to firstthunk\n",
1774 ASM_RVA_AFTER
, ASM_C
);
1776 fprintf (f
, "%sStuff for compatibility\n", ASM_C
);
1780 fprintf (f
, "\t.section\t.idata$5\n");
1781 fprintf (f
, "\t%s\t0\n", ASM_LONG
);
1782 fprintf (f
, "fthunk:\n");
1786 fprintf (f
, "\t.section\t.idata$4\n");
1788 fprintf (f
, "\t%s\t0\n", ASM_LONG
);
1789 fprintf (f
, "\t.section .idata$4\n");
1790 fprintf (f
, "hname:\n");
1794 sprintf (outfile
, "-o dh.o dh.s");
1795 run (as_name
, outfile
);
1797 return bfd_openr ("dh.o", HOW_BFD_TARGET
);
1803 FILE * f
= fopen ("dt.s", FOPEN_WT
);
1807 fprintf (f
, "\t.section .idata$4\n");
1808 fprintf (f
, "\t%s\t0\n", ASM_LONG
);
1812 fprintf (f
, "\t.section .idata$5\n");
1813 fprintf (f
, "\t%s\t0\n", ASM_LONG
);
1817 /* Normally, we need to see a null descriptor built in idata$3 to
1818 act as the terminator for the list. The ideal way, I suppose,
1819 would be to mark this section as a comdat type 2 section, so
1820 only one would appear in the final .exe (if our linker supported
1821 comdat, that is) or cause it to be inserted by something else (say
1825 fprintf (f
, "\t.section .idata$3\n");
1826 fprintf (f
, "\t%s\t0\n", ASM_LONG
);
1827 fprintf (f
, "\t%s\t0\n", ASM_LONG
);
1828 fprintf (f
, "\t%s\t0\n", ASM_LONG
);
1829 fprintf (f
, "\t%s\t0\n", ASM_LONG
);
1830 fprintf (f
, "\t%s\t0\n", ASM_LONG
);
1834 /* Other PowerPC NT compilers use idata$6 for the dllname, so I
1835 do too. Original, huh? */
1836 fprintf (f
, "\t.section .idata$6\n");
1838 fprintf (f
, "\t.section .idata$7\n");
1841 fprintf (f
, "\t%s\t__%s_iname\n", ASM_GLOBAL
, imp_name_lab
);
1842 fprintf (f
, "__%s_iname:\t%s\t\"%s\"\n",
1843 imp_name_lab
, ASM_TEXT
, dll_name
);
1847 sprintf (outfile
, "-o dt.o dt.s");
1848 run (as_name
, outfile
);
1849 return bfd_openr ("dt.o", HOW_BFD_TARGET
);
1864 outarch
= bfd_openw (imp_name
, HOW_BFD_TARGET
);
1868 fprintf (stderr
, "%s: Can't open .lib file %s\n", program_name
, imp_name
);
1871 bfd_set_format (outarch
, bfd_archive
);
1872 outarch
->has_armap
= 1;
1874 /* Work out a reasonable size of things to put onto one line. */
1878 ar_head
= make_head ();
1879 ar_tail
= make_tail();
1881 for (i
= 0; (exp
= d_exports_lexically
[i
]); i
++)
1883 bfd
*n
= make_one_lib_file (exp
, i
);
1889 /* Now stick them all into the archive */
1891 ar_head
->next
= head
;
1892 ar_tail
->next
= ar_head
;
1895 bfd_set_archive_head (outarch
, head
);
1896 bfd_close (outarch
);
1898 /* Delete all the temp files */
1900 if (dontdeltemps
== 0)
1902 sprintf (outfile
, "dh.o");
1904 sprintf (outfile
, "dh.s");
1906 sprintf (outfile
, "dt.o");
1908 sprintf (outfile
, "dt.s");
1912 if (dontdeltemps
< 2)
1913 for (i
= 0, exp
= d_exports
; exp
; i
++, exp
= exp
->next
)
1915 sprintf (outfile
, "ds%d.o",i
);
1920 /**********************************************************************/
1922 /* Run through the information gathered from the .o files and the
1923 .def file and work out the best stuff */
1929 export_type
*ap
= *(export_type
**) a
;
1930 export_type
*bp
= *(export_type
**) b
;
1931 if (ap
->ordinal
== bp
->ordinal
)
1934 /* unset ordinals go to the bottom */
1935 if (ap
->ordinal
== -1)
1937 if (bp
->ordinal
== -1)
1939 return (ap
->ordinal
- bp
->ordinal
);
1947 export_type
*ap
= *(export_type
**) a
;
1948 export_type
*bp
= *(export_type
**) b
;
1950 return (strcmp (ap
->name
, bp
->name
));
1954 remove_null_names (ptr
)
1959 for (dst
= src
= 0; src
< d_nfuncs
; src
++)
1963 ptr
[dst
] = ptr
[src
];
1976 for (i
= 0; i
< d_nfuncs
; i
++)
1980 printf ("%d %s @ %d %s%s\n",
1981 i
, ptr
[i
]->name
, ptr
[i
]->ordinal
,
1982 ptr
[i
]->noname
? "NONAME " : "",
1983 ptr
[i
]->constant
? "CONSTANT" : "");
1992 process_duplicates (d_export_vec
)
1993 export_type
**d_export_vec
;
2001 /* Remove duplicates */
2002 qsort (d_export_vec
, d_nfuncs
, sizeof (export_type
*), nfunc
);
2004 dtab (d_export_vec
);
2005 for (i
= 0; i
< d_nfuncs
- 1; i
++)
2007 if (strcmp (d_export_vec
[i
]->name
,
2008 d_export_vec
[i
+ 1]->name
) == 0)
2011 export_type
*a
= d_export_vec
[i
];
2012 export_type
*b
= d_export_vec
[i
+ 1];
2016 fprintf (stderr
, "Warning, ignoring duplicate EXPORT %s %d,%d\n",
2020 if (a
->ordinal
!= -1
2021 && b
->ordinal
!= -1)
2024 fprintf (stderr
, "Error, duplicate EXPORT with oridinals %s\n",
2028 /* Merge attributes */
2029 b
->ordinal
= a
->ordinal
> 0 ? a
->ordinal
: b
->ordinal
;
2030 b
->constant
|= a
->constant
;
2031 b
->noname
|= a
->noname
;
2032 d_export_vec
[i
] = 0;
2035 dtab (d_export_vec
);
2036 remove_null_names (d_export_vec
);
2037 dtab (d_export_vec
);
2042 /* Count the names */
2043 for (i
= 0; i
< d_nfuncs
; i
++)
2045 if (!d_export_vec
[i
]->noname
)
2051 fill_ordinals (d_export_vec
)
2052 export_type
**d_export_vec
;
2059 qsort (d_export_vec
, d_nfuncs
, sizeof (export_type
*), pfunc
);
2061 /* fill in the unset ordinals with ones from our range */
2063 ptr
= (char *) xmalloc (size
);
2065 memset (ptr
, 0, size
);
2067 /* Mark in our large vector all the numbers that are taken */
2068 for (i
= 0; i
< d_nfuncs
; i
++)
2070 if (d_export_vec
[i
]->ordinal
!= -1)
2072 ptr
[d_export_vec
[i
]->ordinal
] = 1;
2073 if (lowest
== -1 || d_export_vec
[i
]->ordinal
< lowest
)
2075 lowest
= d_export_vec
[i
]->ordinal
;
2080 /* Start at 1 for compatibility with MS toolchain. */
2084 /* Now fill in ordinals where the user wants us to choose. */
2085 for (i
= 0; i
< d_nfuncs
; i
++)
2087 if (d_export_vec
[i
]->ordinal
== -1)
2091 /* First try within or after any user supplied range. */
2092 for (j
= lowest
; j
< size
; j
++)
2096 d_export_vec
[i
]->ordinal
= j
;
2100 /* Then try before the range. */
2101 for (j
= lowest
; j
>0; j
--)
2105 d_export_vec
[i
]->ordinal
= j
;
2116 qsort (d_export_vec
, d_nfuncs
, sizeof (export_type
*), pfunc
);
2118 /* Work out the lowest and highest ordinal numbers. */
2121 if (d_export_vec
[0])
2122 d_low_ord
= d_export_vec
[0]->ordinal
;
2123 if (d_export_vec
[d_nfuncs
-1])
2124 d_high_ord
= d_export_vec
[d_nfuncs
-1]->ordinal
;
2133 const export_type
**a
= (const export_type
**) av
;
2134 const export_type
**b
= (const export_type
**) bv
;
2136 return strcmp ((*a
)->name
, (*b
)->name
);
2142 /* First work out the minimum ordinal chosen */
2148 export_type
**d_export_vec
2149 = (export_type
**) xmalloc (sizeof (export_type
*) * d_nfuncs
);
2151 for (i
= 0, exp
= d_exports
; exp
; i
++, exp
= exp
->next
)
2153 d_export_vec
[i
] = exp
;
2156 process_duplicates (d_export_vec
);
2157 fill_ordinals (d_export_vec
);
2159 /* Put back the list in the new order */
2161 for (i
= d_nfuncs
- 1; i
>= 0; i
--)
2163 d_export_vec
[i
]->next
= d_exports
;
2164 d_exports
= d_export_vec
[i
];
2167 /* Build list in alpha order */
2168 d_exports_lexically
= (export_type
**)xmalloc (sizeof(export_type
*)*(d_nfuncs
+1));
2170 for (i
= 0, exp
= d_exports
; exp
; i
++, exp
= exp
->next
)
2172 d_exports_lexically
[i
] = exp
;
2174 d_exports_lexically
[i
] = 0;
2176 qsort (d_exports_lexically
, i
, sizeof (export_type
*), alphafunc
);
2178 /* Fill exp entries with their hint values */
2180 for (i
= 0; i
< d_nfuncs
; i
++)
2182 if (!d_exports_lexically
[i
]->noname
|| show_allnames
)
2183 d_exports_lexically
[i
]->hint
= hint
++;
2188 /**********************************************************************/
2191 usage (file
, status
)
2195 fprintf (file
, "Usage %s <options> <object-files>\n", program_name
);
2196 fprintf (file
, " --machine <machine>\n");
2197 fprintf (file
, " --output-exp <outname> Generate export file.\n");
2198 fprintf (file
, " --output-lib <outname> Generate input library.\n");
2199 fprintf (file
, " --add-indirect Add dll indirects to export file.\n");
2200 fprintf (file
, " --dllname <name> Name of input dll to put into output lib.\n");
2201 fprintf (file
, " --def <deffile> Name input .def file\n");
2202 fprintf (file
, " --output-def <deffile> Name output .def file\n");
2203 fprintf (file
, " --base-file <basefile> Read linker generated base file\n");
2204 fprintf (file
, " --no-idata4 Don't generate idata$4 section\n");
2205 fprintf (file
, " --no-idata5 Don't generate idata$5 section\n");
2206 fprintf (file
, " -v Verbose\n");
2207 fprintf (file
, " -U Add underscores to .lib\n");
2208 fprintf (file
, " -k Kill @<n> from exported names\n");
2209 fprintf (file
, " --as <name> Use <name> for assembler\n");
2210 fprintf (file
, " --nodelete Keep temp files.\n");
2214 #define OPTION_NO_IDATA4 'x'
2215 #define OPTION_NO_IDATA5 'c'
2216 static const struct option long_options
[] =
2218 {"nodelete", no_argument
, NULL
, 'n'},
2219 {"dllname", required_argument
, NULL
, 'D'},
2220 {"no-idata4", no_argument
, NULL
, OPTION_NO_IDATA4
},
2221 {"no-idata5", no_argument
, NULL
, OPTION_NO_IDATA5
},
2222 {"output-exp", required_argument
, NULL
, 'e'},
2223 {"output-def", required_argument
, NULL
, 'z'},
2224 {"output-lib", required_argument
, NULL
, 'l'},
2225 {"def", required_argument
, NULL
, 'd'},
2226 {"add-underscore", no_argument
, NULL
, 'U'},
2227 {"killat", no_argument
, NULL
, 'k'},
2228 {"help", no_argument
, NULL
, 'h'},
2229 {"machine", required_argument
, NULL
, 'm'},
2230 {"add-indirect", no_argument
, NULL
, 'a'},
2231 {"base-file", required_argument
, NULL
, 'b'},
2232 {"as", required_argument
, NULL
, 'S'},
2244 program_name
= av
[0];
2247 while ((c
= getopt_long (ac
, av
, "xcz:S:R:A:puaD:l:e:nkvbUh?m:yd:", long_options
, 0))
2252 case OPTION_NO_IDATA4
:
2255 case OPTION_NO_IDATA5
:
2262 /* ignored for compatibility */
2269 output_def
= fopen (optarg
, FOPEN_WT
);
2292 /* We don't currently define YYDEBUG when building
2310 base_file
= fopen (optarg
, FOPEN_RB
);
2313 fprintf (stderr
, "%s: Unable to open base-file %s\n",
2325 for (i
= 0; mtable
[i
].type
; i
++)
2327 if (strcmp (mtable
[i
].type
, mname
) == 0)
2331 if (!mtable
[i
].type
)
2333 fprintf (stderr
, "Machine not supported\n");
2339 if (!dll_name
&& exp_name
)
2341 char len
= strlen (exp_name
) + 5;
2342 dll_name
= xmalloc (len
);
2343 strcpy (dll_name
, exp_name
);
2344 strcat (dll_name
, ".dll");
2349 process_def_file (def_file
);
2354 firstarg
= av
[optind
];
2355 scan_obj_file (av
[optind
]);
2365 /* Make imp_name safe for use as a label. */
2368 imp_name_lab
= xstrdup (imp_name
);
2369 for (p
= imp_name_lab
; *p
; p
++)
2371 if (!isalpha (*p
) && !isdigit (*p
))
2374 head_label
= make_label("_head_", imp_name_lab
);