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 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] [DATA] ) *
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)
241 static char *as_name
= "as";
243 static int no_idata4
;
244 static int no_idata5
;
245 static char *exp_name
;
246 static char *imp_name
;
247 static char *head_label
;
248 static char *imp_name_lab
;
249 static char *dll_name
;
251 static int add_indirect
= 0;
252 static int add_underscore
= 0;
253 static int dontdeltemps
= 0;
255 static char *def_file
;
257 static char *program_name
;
262 static FILE *output_def
;
263 static FILE *base_file
;
266 static const char *mname
= "arm";
270 static const char *mname
= "i386";
274 static const char *mname
= "ppc";
277 #define PATHMAX 250 /* What's the right name for this ? */
279 /* This bit of assemly does jmp * ....
280 s set how_jtab_roff to mark where the 32bit abs branch should go */
281 static const unsigned char i386_jtab
[] =
283 0xff, 0x25, 0x00, 0x00, 0x00, 0x00, 0x90, 0x90
286 static const unsigned char arm_jtab
[] =
288 0x00, 0xc0, 0x9f, 0xe5,
289 0x00, 0xf0, 0x9c, 0xe5,
293 /* This is the glue sequence for PowerPC PE. There is a */
294 /* tocrel16-tocdefn reloc against the first instruction. */
295 /* We also need a IMGLUE reloc against the glue function */
296 /* to restore the toc saved by the third instruction in */
298 static const unsigned char ppc_jtab
[] =
300 0x00, 0x00, 0x62, 0x81, /* lwz r11,0(r2) */
301 /* Reloc TOCREL16 __imp_xxx */
302 0x00, 0x00, 0x8B, 0x81, /* lwz r12,0(r11) */
303 0x04, 0x00, 0x41, 0x90, /* stw r2,4(r1) */
304 0xA6, 0x03, 0x89, 0x7D, /* mtctr r12 */
305 0x04, 0x00, 0x4B, 0x80, /* lwz r2,4(r11) */
306 0x20, 0x04, 0x80, 0x4E /* bctr */
310 /* the glue instruction, picks up the toc from the stw in */
311 /* the above code: "lwz r2,4(r1)" */
312 static bfd_vma ppc_glue_insn
= 0x80410004;
315 static char outfile
[PATHMAX
];
320 const char *how_byte
;
321 const char *how_short
;
322 const char *how_long
;
323 const char *how_asciz
;
324 const char *how_comment
;
325 const char *how_jump
;
326 const char *how_global
;
327 const char *how_space
;
328 const char *how_align_short
;
329 const char *how_align_long
;
330 const char *how_bfd_target
;
331 enum bfd_architecture how_bfd_arch
;
332 const unsigned char *how_jtab
;
333 int how_jtab_size
; /* size of the jtab entry */
334 int how_jtab_roff
; /* offset into it for the ind 32 reloc into idata 5 */
337 static const struct mac mtable
[] =
341 "arm", ".byte", ".short", ".long", ".asciz", "@",
342 "ldr\tip,[pc]\n\tldr\tpc,[ip]\n\t.long",
343 ".global", ".space", ".align\t2",".align\t4","pe-arm-little", bfd_arch_arm
,
344 arm_jtab
, sizeof(arm_jtab
),8
349 "i386", ".byte", ".short", ".long", ".asciz", "#", "jmp *", ".global", ".space", ".align\t2",".align\t4","pe-i386",bfd_arch_i386
,
350 i386_jtab
,sizeof(i386_jtab
),2,
355 "ppc", ".byte", ".short", ".long", ".asciz", "#", "jmp *", ".global", ".space", ".align\t2",".align\t4","pe-powerpcle",bfd_arch_powerpc
,
356 ppc_jtab
,sizeof(ppc_jtab
),0,
369 typedef struct export
372 const char *internal_name
;
382 static const char *rvaafter
PARAMS ((int));
383 static const char *rvabefore
PARAMS ((int));
384 static const char *asm_prefix
PARAMS ((int));
385 static void run
PARAMS ((const char *, char *));
386 static void basenames
PARAMS ((bfd
*));
387 static void scan_open_obj_file
PARAMS ((bfd
*));
388 static void scan_obj_file
PARAMS ((const char *));
389 static void dump_def_info
PARAMS ((FILE *));
390 static int sfunc
PARAMS ((const void *, const void *));
391 static void flush_page
PARAMS ((FILE *, long *, int, int));
392 static void gen_def_file
PARAMS ((void));
393 static void gen_exp_file
PARAMS ((void));
394 static const char *xlate
PARAMS ((const char *));
395 static void dump_iat
PARAMS ((FILE *, export_type
*));
396 static char *make_label
PARAMS ((const char *, const char *));
397 static bfd
*make_one_lib_file
PARAMS ((export_type
*, int));
398 static bfd
*make_head
PARAMS ((void));
399 static bfd
*make_tail
PARAMS ((void));
400 static void gen_lib_file
PARAMS ((void));
401 static int pfunc
PARAMS ((const void *, const void *));
402 static int nfunc
PARAMS ((const void *, const void *));
403 static void remove_null_names
PARAMS ((export_type
**));
404 static void dtab
PARAMS ((export_type
**));
405 static void process_duplicates
PARAMS ((export_type
**));
406 static void fill_ordinals
PARAMS ((export_type
**));
407 static int alphafunc
PARAMS ((const void *, const void *));
408 static void mangle_defs
PARAMS ((void));
409 static void usage
PARAMS ((FILE *, int));
459 #define ASM_BYTE mtable[machine].how_byte
460 #define ASM_SHORT mtable[machine].how_short
461 #define ASM_LONG mtable[machine].how_long
462 #define ASM_TEXT mtable[machine].how_asciz
463 #define ASM_C mtable[machine].how_comment
464 #define ASM_JUMP mtable[machine].how_jump
465 #define ASM_GLOBAL mtable[machine].how_global
466 #define ASM_SPACE mtable[machine].how_space
467 #define ASM_ALIGN_SHORT mtable[machine].how_align_short
468 #define ASM_RVA_BEFORE rvabefore(machine)
469 #define ASM_RVA_AFTER rvaafter(machine)
470 #define ASM_PREFIX asm_prefix(machine)
471 #define ASM_ALIGN_LONG mtable[machine].how_align_long
472 #define HOW_BFD_TARGET 0 /* always default*/
473 #define HOW_BFD_ARCH mtable[machine].how_bfd_arch
474 #define HOW_JTAB mtable[machine].how_jtab
475 #define HOW_JTAB_SIZE mtable[machine].how_jtab_size
476 #define HOW_JTAB_ROFF mtable[machine].how_jtab_roff
480 process_def_file (name
)
483 FILE *f
= fopen (name
, FOPEN_RT
);
486 fprintf (stderr
, "%s: Can't open def file %s\n", program_name
, name
);
495 /**********************************************************************/
497 /* Communications with the parser */
499 static const char *d_name
; /* Arg to NAME or LIBRARY */
500 static int d_nfuncs
; /* Number of functions exported */
501 static int d_named_nfuncs
; /* Number of named functions exported */
502 static int d_low_ord
; /* Lowest ordinal index */
503 static int d_high_ord
; /* Highest ordinal index */
504 static export_type
*d_exports
; /*list of exported functions */
505 static export_type
**d_exports_lexically
; /* vector of exported functions in alpha order */
506 static dlist_type
*d_list
; /* Descriptions */
507 static dlist_type
*a_list
; /* Stuff to go in directives */
516 fprintf (stderr
, "%s: Syntax error in def file %s:%d\n",
517 program_name
, def_file
, linenumber
);
522 def_exports (name
, internal_name
, ordinal
, noname
, constant
, data
)
524 const char *internal_name
;
530 struct export
*p
= (struct export
*) xmalloc (sizeof (*p
));
533 p
->internal_name
= internal_name
? internal_name
: name
;
534 p
->ordinal
= ordinal
;
535 p
->constant
= constant
;
544 def_name (name
, base
)
549 fprintf (stderr
, "%s NAME %s base %x\n", program_name
, name
, base
);
552 fprintf (stderr
, "Can't have LIBRARY and NAME\n");
559 def_library (name
, base
)
564 printf ("%s: LIBRARY %s base %x\n", program_name
, name
, base
);
567 fprintf (stderr
, "%s: Can't have LIBRARY and NAME\n", program_name
);
574 def_description (desc
)
577 dlist_type
*d
= (dlist_type
*) xmalloc (sizeof (dlist_type
));
578 d
->text
= xstrdup (desc
);
587 dlist_type
*d
= (dlist_type
*) xmalloc (sizeof (dlist_type
));
588 d
->text
= xstrdup (dir
);
594 def_stacksize (reserve
, commit
)
600 sprintf (b
, "-stack 0x%x,0x%x ", reserve
, commit
);
602 sprintf (b
, "-stack 0x%x ", reserve
);
603 new_directive (xstrdup (b
));
607 def_heapsize (reserve
, commit
)
613 sprintf (b
, "-heap 0x%x,0x%x ", reserve
, commit
);
615 sprintf (b
, "-heap 0x%x ", reserve
);
616 new_directive (xstrdup (b
));
620 def_import (internal
, module
, entry
)
621 const char *internal
;
626 fprintf (stderr
, "%s: IMPORTS are ignored", program_name
);
630 def_version (major
, minor
)
634 printf ("VERSION %d.%d\n", major
, minor
);
638 def_section (name
, attr
)
655 sprintf (buf
, "-attr %s %s", name
, atts
);
656 new_directive (xstrdup (buf
));
664 def_section ("CODE", attr
);
671 def_section ("DATA", attr
);
674 /**********************************************************************/
682 int pid
, wait_status
;
685 char *errmsg_fmt
, *errmsg_arg
;
686 char *temp_base
= choose_temp_base ();
689 fprintf (stderr
, "%s %s\n", what
, args
);
693 for (s
= args
; *s
; s
++)
697 argv
= alloca (sizeof (char *) * (i
+ 3));
704 while (*s
!= ' ' && *s
!= 0)
712 pid
= pexecute (argv
[0], (char * const *) argv
, program_name
, temp_base
,
713 &errmsg_fmt
, &errmsg_arg
, PEXECUTE_ONE
| PEXECUTE_SEARCH
);
717 int errno_val
= errno
;
719 fprintf (stderr
, "%s: ", program_name
);
720 fprintf (stderr
, errmsg_fmt
, errmsg_arg
);
721 fprintf (stderr
, ": %s\n", strerror (errno_val
));
725 pid
= pwait (pid
, &wait_status
, 0);
728 fprintf (stderr
, "%s: wait: %s\n", program_name
, strerror (errno
));
731 else if (WIFSIGNALED (wait_status
))
733 fprintf (stderr
, "%s: subprocess got fatal signal %d\n",
734 program_name
, WTERMSIG (wait_status
));
737 else if (WIFEXITED (wait_status
))
739 if (WEXITSTATUS (wait_status
) != 0)
740 fprintf (stderr
, "%s: %s exited with status %d\n",
741 program_name
, what
, WEXITSTATUS (wait_status
));
747 /* read in and block out the base relocations */
755 scan_open_obj_file (abfd
)
758 /* Look for .drectve's */
759 asection
*s
= bfd_get_section_by_name (abfd
, ".drectve");
762 int size
= bfd_get_section_size_before_reloc (s
);
763 char *buf
= xmalloc (size
);
766 bfd_get_section_contents (abfd
, s
, buf
, 0, size
);
768 fprintf (stderr
, "%s: Sucking in info from %s\n",
770 bfd_get_filename (abfd
));
772 /* Search for -export: strings */
778 && strncmp (p
, "-export:", 8) == 0)
784 while (p
< e
&& *p
!= ' ' && *p
!= '-')
786 c
= xmalloc (p
- name
+ 1);
787 memcpy (c
, name
, p
- name
);
789 /* FIXME: The 5th arg is for the `constant' field.
790 What should it be? Not that it matters since it's not
792 def_exports (c
, 0, -1, 0, 0, 0);
803 fprintf (stderr
, "%s: Done readin\n",
808 scan_obj_file (filename
)
809 const char *filename
;
811 bfd
*f
= bfd_openr (filename
, 0);
815 fprintf (stderr
, "%s: Unable to open object file %s\n",
820 if (bfd_check_format (f
, bfd_archive
))
822 bfd
*arfile
= bfd_openr_next_archived_file (f
, 0);
825 if (bfd_check_format (arfile
, bfd_object
))
826 scan_open_obj_file (arfile
);
828 arfile
= bfd_openr_next_archived_file (f
, arfile
);
831 else if (bfd_check_format (f
, bfd_object
))
833 scan_open_obj_file (f
);
839 /**********************************************************************/
847 fprintf (f
, "%s ", ASM_C
);
848 for (i
= 0; oav
[i
]; i
++)
849 fprintf (f
, "%s ", oav
[i
]);
851 for (i
= 0, exp
= d_exports
; exp
; i
++, exp
= exp
->next
)
853 fprintf (f
, "%s %d = %s %s @ %d %s%s%s\n",
859 exp
->noname
? "NONAME " : "",
860 exp
->constant
? "CONSTANT" : "",
861 exp
->data
? "DATA" : "");
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 ; %s\n",
922 exp
->noname
? " NONAME" : "",
923 exp
->data
? " DATA" : "",
924 cplus_demangle (exp
->internal_name
, DMGL_ANSI
| DMGL_PARAMS
));
937 sprintf (outfile
, "t%s", exp_name
);
940 fprintf (stderr
, "%s: Generate exp file %s\n",
941 program_name
, exp_name
);
943 f
= fopen (outfile
, FOPEN_WT
);
946 fprintf (stderr
, "%s: Unable to open output file %s\n", program_name
, outfile
);
951 fprintf (stderr
, "%s: Opened file %s\n",
952 program_name
, outfile
);
958 fprintf (f
, "\t.section .edata\n\n");
959 fprintf (f
, "\t%s 0 %s Allways 0\n", ASM_LONG
, ASM_C
);
960 fprintf (f
, "\t%s 0x%lx %s Time and date\n", ASM_LONG
, (long) time(0),
962 fprintf (f
, "\t%s 0 %s Major and Minor version\n", ASM_LONG
, ASM_C
);
963 fprintf (f
, "\t%sname%s %s Ptr to name of dll\n", ASM_RVA_BEFORE
, ASM_RVA_AFTER
, ASM_C
);
964 fprintf (f
, "\t%s %d %s Starting ordinal of exports\n", ASM_LONG
, d_low_ord
, ASM_C
);
967 fprintf (f
, "\t%s %d %s Number of functions\n", ASM_LONG
, d_high_ord
- d_low_ord
+ 1, ASM_C
);
968 fprintf(f
,"\t%s named funcs %d, low ord %d, high ord %d\n",
970 d_named_nfuncs
, d_low_ord
, d_high_ord
);
971 fprintf (f
, "\t%s %d %s Number of names\n", ASM_LONG
,
972 show_allnames
? d_high_ord
- d_low_ord
+ 1 : d_named_nfuncs
, ASM_C
);
973 fprintf (f
, "\t%safuncs%s %s Address of functions\n", ASM_RVA_BEFORE
, ASM_RVA_AFTER
, ASM_C
);
975 fprintf (f
, "\t%sanames%s %s Address of Name Pointer Table\n",
976 ASM_RVA_BEFORE
, ASM_RVA_AFTER
, ASM_C
);
978 fprintf (f
, "\t%sanords%s %s Address of ordinals\n", ASM_RVA_BEFORE
, ASM_RVA_AFTER
, ASM_C
);
980 fprintf (f
, "name: %s \"%s\"\n", ASM_TEXT
, dll_name
);
983 fprintf(f
,"%s Export address Table\n", ASM_C
);
984 fprintf(f
,"\t%s\n", ASM_ALIGN_LONG
);
985 fprintf (f
, "afuncs:\n");
988 for (exp
= d_exports
; exp
; exp
= exp
->next
)
990 if (exp
->ordinal
!= i
)
993 fprintf (f
, "\t%s\t%d\t%s %d..%d missing\n",
995 (exp
->ordinal
- i
) * 4,
997 i
, exp
->ordinal
- 1);
1000 while (i
< exp
->ordinal
)
1002 fprintf(f
,"\t%s\t0\n", ASM_LONG
);
1006 fprintf (f
, "\t%s%s%s%s\t%s %d\n", ASM_RVA_BEFORE
,
1008 exp
->internal_name
, ASM_RVA_AFTER
, ASM_C
, exp
->ordinal
);
1012 fprintf (f
,"%s Export Name Pointer Table\n", ASM_C
);
1013 fprintf (f
, "anames:\n");
1015 for (i
= 0; (exp
= d_exports_lexically
[i
]); i
++)
1017 if (!exp
->noname
|| show_allnames
)
1018 fprintf (f
, "\t%sn%d%s\n", ASM_RVA_BEFORE
, exp
->ordinal
, ASM_RVA_AFTER
);
1021 fprintf (f
,"%s Export Oridinal Table\n", ASM_C
);
1022 fprintf (f
, "anords:\n");
1023 for (i
= 0; (exp
= d_exports_lexically
[i
]); i
++)
1025 if (!exp
->noname
|| show_allnames
)
1026 fprintf (f
, "\t%s %d\n", ASM_SHORT
, exp
->ordinal
- d_low_ord
);
1029 fprintf(f
,"%s Export Name Table\n", ASM_C
);
1030 for (i
= 0; (exp
= d_exports_lexically
[i
]); i
++)
1031 if (!exp
->noname
|| show_allnames
)
1032 fprintf (f
, "n%d: %s \"%s\"\n", exp
->ordinal
, ASM_TEXT
, exp
->name
);
1036 fprintf (f
, "\t.section .drectve\n");
1037 for (dl
= a_list
; dl
; dl
= dl
->next
)
1039 fprintf (f
, "\t%s\t\"%s\"\n", ASM_TEXT
, dl
->text
);
1044 fprintf (f
, "\t.section .rdata\n");
1045 for (dl
= d_list
; dl
; dl
= dl
->next
)
1049 /* We dont output as ascii 'cause there can
1050 be quote characters in the string */
1053 for (p
= dl
->text
; *p
; p
++)
1056 fprintf (f
, "\t%s\t", ASM_BYTE
);
1059 fprintf (f
, "%d", *p
);
1062 fprintf (f
, ",0\n");
1076 /* Add to the output file a way of getting to the exported names
1077 without using the import library. */
1080 fprintf (f
, "\t.section\t.rdata\n");
1081 for (i
= 0, exp
= d_exports
; exp
; i
++, exp
= exp
->next
)
1082 if (!exp
->noname
|| show_allnames
)
1084 fprintf (f
, "\t%s\t__imp_%s\n", ASM_GLOBAL
, exp
->name
);
1085 fprintf (f
, "__imp_%s:\n", exp
->name
);
1086 fprintf (f
, "\t%s\t%s\n", ASM_LONG
, exp
->name
);
1090 /* Dump the reloc section if a base file is provided */
1094 long need
[PAGE_SIZE
];
1101 fprintf (f
, "\t.section\t.init\n");
1102 fprintf (f
, "lab:\n");
1104 fseek (base_file
, 0, SEEK_END
);
1105 numbytes
= ftell (base_file
);
1106 fseek (base_file
, 0, SEEK_SET
);
1107 copy
= xmalloc (numbytes
);
1108 fread (copy
, 1, numbytes
, base_file
);
1109 num_entries
= numbytes
/ sizeof (long);
1112 fprintf (f
, "\t.section\t.reloc\n");
1118 qsort (copy
, num_entries
, sizeof (long), sfunc
);
1119 /* Delete duplcates */
1120 for (src
= 0; src
< num_entries
; src
++)
1122 if (last
!= copy
[src
])
1123 last
= copy
[dst
++] = copy
[src
];
1127 page_addr
= addr
& PAGE_MASK
; /* work out the page addr */
1129 for (j
= 0; j
< num_entries
; j
++)
1132 if ((addr
& PAGE_MASK
) != page_addr
)
1134 flush_page (f
, need
, page_addr
, on_page
);
1136 page_addr
= addr
& PAGE_MASK
;
1138 need
[on_page
++] = addr
;
1140 flush_page (f
, need
, page_addr
, on_page
);
1142 /* fprintf (f, "\t%s\t0,0\t%s End\n", ASM_LONG, ASM_C);*/
1148 /* assemble the file */
1149 sprintf (outfile
, "-o %s t%s", exp_name
, exp_name
);
1150 run (as_name
, outfile
);
1151 if (dontdeltemps
== 0)
1153 sprintf (outfile
, "t%s", exp_name
);
1164 char *copy
= xmalloc (strlen (name
) + 2);
1166 strcpy (copy
+ 1, name
);
1173 p
= strchr (name
, '@');
1180 /**********************************************************************/
1187 if (exp
->noname
&& !show_allnames
)
1189 fprintf (f
, "\t%s\t0x%08x\n",
1191 exp
->ordinal
| 0x80000000); /* hint or orindal ?? */
1195 fprintf (f
, "\t%sID%d%s\n", ASM_RVA_BEFORE
,
1211 unsigned char *data
;
1226 static sinfo secdata
[NSECS
] =
1228 { TEXT
, ".text", SEC_CODE
| SEC_HAS_CONTENTS
, 2},
1229 { DATA
, ".data", SEC_DATA
, 2},
1230 { BSS
, ".bss", 0, 2},
1231 { IDATA7
, ".idata$7", SEC_HAS_CONTENTS
, 2},
1232 { IDATA5
, ".idata$5", SEC_HAS_CONTENTS
, 2},
1233 { IDATA4
, ".idata$4", SEC_HAS_CONTENTS
, 2},
1234 { IDATA6
, ".idata$6", SEC_HAS_CONTENTS
, 1}
1239 /* Sections numbered to make the order the same as other PowerPC NT */
1240 /* compilers. This also keeps funny alignment thingies from happening. */
1253 static sinfo secdata
[NSECS
] =
1255 { TEXT
, ".text", SEC_CODE
| SEC_HAS_CONTENTS
, 3},
1256 { PDATA
, ".pdata", SEC_HAS_CONTENTS
, 2},
1257 { RDATA
, ".reldata", SEC_HAS_CONTENTS
, 2},
1258 { IDATA5
, ".idata$5", SEC_HAS_CONTENTS
, 2},
1259 { IDATA4
, ".idata$4", SEC_HAS_CONTENTS
, 2},
1260 { IDATA6
, ".idata$6", SEC_HAS_CONTENTS
, 1},
1261 { IDATA7
, ".idata$7", SEC_HAS_CONTENTS
, 2},
1262 { DATA
, ".data", SEC_DATA
, 2},
1263 { BSS
, ".bss", 0, 2}
1269 This is what we're trying to make
1272 .global _GetFileVersionInfoSizeW@8
1273 .global __imp_GetFileVersionInfoSizeW@8
1274 _GetFileVersionInfoSizeW@8:
1275 jmp * __imp_GetFileVersionInfoSizeW@8
1276 .section .idata$7 # To force loading of head
1277 .long __version_a_head
1278 # Import Address Table
1280 __imp_GetFileVersionInfoSizeW@8:
1283 # Import Lookup Table
1289 .asciz "GetFileVersionInfoSizeW"
1292 For the PowerPC, here's the variation on the above scheme:
1294 # Rather than a simple "jmp *", the code to get to the dll function
1297 lwz r11,[tocv]__imp_function_name(r2)
1298 # RELOC: 00000000 TOCREL16,TOCDEFN __imp_function_name
1307 make_label (prefix
, name
)
1311 int len
= strlen (ASM_PREFIX
) + strlen (prefix
) + strlen (name
);
1312 char *copy
= xmalloc (len
+1 );
1313 strcpy (copy
, ASM_PREFIX
);
1314 strcat (copy
, prefix
);
1315 strcat (copy
, name
);
1320 make_one_lib_file (exp
, i
)
1328 sprintf (outfile
, "%ss%d.s", prefix
, i
);
1329 f
= fopen (outfile
, FOPEN_WT
);
1330 fprintf (f
, "\t.text\n");
1331 fprintf (f
, "\t%s\t%s%s\n", ASM_GLOBAL
, ASM_PREFIX
, exp
->name
);
1332 fprintf (f
, "\t%s\t__imp_%s\n", ASM_GLOBAL
, exp
->name
);
1333 fprintf (f
, "%s%s:\n\t%s\t__imp_%s\n", ASM_PREFIX
,
1334 exp
->name
, ASM_JUMP
, exp
->name
);
1336 fprintf (f
, "\t.section\t.idata$7\t%s To force loading of head\n", ASM_C
);
1337 fprintf (f
, "\t%s\t%s\n", ASM_LONG
, head_label
);
1340 fprintf (f
,"%s Import Address Table\n", ASM_C
);
1342 fprintf (f
, "\t.section .idata$5\n");
1343 fprintf (f
, "__imp_%s:\n", exp
->name
);
1347 fprintf (f
, "\n%s Import Lookup Table\n", ASM_C
);
1348 fprintf (f
, "\t.section .idata$4\n");
1352 if(!exp
->noname
|| show_allnames
)
1354 fprintf (f
, "%s Hint/Name table\n", ASM_C
);
1355 fprintf (f
, "\t.section .idata$6\n");
1356 fprintf (f
, "ID%d:\t%s\t%d\n", exp
->ordinal
, ASM_SHORT
, exp
->hint
);
1357 fprintf (f
, "\t%s\t\"%s\"\n", ASM_TEXT
, xlate (exp
->name
));
1363 sprintf (outfile
, "-o %ss%d.o %ss%d.s", prefix
, i
, prefix
, i
);
1365 run (as_name
, outfile
);
1376 asymbol
**iname_lab_pp
;
1379 /* Extra Symbols for PPC */
1391 /* one symbol for each section, 2 extra + a null */
1392 asymbol
*ptrs
[NSECS
+3+EXTRA
+1];
1394 char *outname
= xmalloc (10);
1396 sprintf (outname
, "ds%d.o", i
);
1397 abfd
= bfd_openw (outname
, HOW_BFD_TARGET
);
1400 fprintf (stderr
, "%s: bfd_open failed open output file %s\n",
1401 program_name
, outname
);
1405 bfd_set_format (abfd
, bfd_object
);
1406 bfd_set_arch_mach (abfd
, HOW_BFD_ARCH
, 0);
1409 /* First make symbols for the sections */
1410 for (i
= 0; i
< NSECS
; i
++)
1412 sinfo
*si
= secdata
+ i
;
1415 si
->sec
= bfd_make_section_old_way (abfd
, si
->name
);
1416 bfd_set_section_flags (abfd
,
1420 bfd_set_section_alignment(abfd
, si
->sec
, si
->align
);
1421 si
->sec
->output_section
= si
->sec
;
1422 si
->sym
= bfd_make_empty_symbol(abfd
);
1423 si
->sym
->name
= si
->sec
->name
;
1424 si
->sym
->section
= si
->sec
;
1425 si
->sym
->flags
= BSF_LOCAL
;
1427 ptrs
[oidx
] = si
->sym
;
1428 si
->sympp
= ptrs
+ oidx
;
1437 exp_label
= bfd_make_empty_symbol (abfd
);
1438 exp_label
->name
= make_label ("", exp
->name
);
1440 /* On PowerPC, the function name points to a descriptor in
1441 the rdata section, the first element of which is a
1442 pointer to the code (..function_name), and the second
1443 points to the .toc */
1445 if (machine
== MPPC
)
1446 exp_label
->section
= secdata
[RDATA
].sec
;
1449 exp_label
->section
= secdata
[TEXT
].sec
;
1451 exp_label
->flags
= BSF_GLOBAL
;
1452 exp_label
->value
= 0;
1454 ptrs
[oidx
++] = exp_label
;
1457 iname
= bfd_make_empty_symbol(abfd
);
1458 iname
->name
= make_label ("__imp_", exp
->name
);
1459 iname
->section
= secdata
[IDATA5
].sec
;
1460 iname
->flags
= BSF_GLOBAL
;
1464 iname_lab
= bfd_make_empty_symbol(abfd
);
1466 iname_lab
->name
= head_label
;
1467 iname_lab
->section
= (asection
*)&bfd_und_section
;
1468 iname_lab
->flags
= 0;
1469 iname_lab
->value
= 0;
1472 iname_pp
= ptrs
+ oidx
;
1473 ptrs
[oidx
++] = iname
;
1475 iname_lab_pp
= ptrs
+ oidx
;
1476 ptrs
[oidx
++] = iname_lab
;
1479 /* The symbol refering to the code (.text) */
1481 asymbol
*function_name
;
1483 function_name
= bfd_make_empty_symbol(abfd
);
1484 function_name
->name
= make_label ("..", exp
->name
);
1485 function_name
->section
= secdata
[TEXT
].sec
;
1486 function_name
->flags
= BSF_GLOBAL
;
1487 function_name
->value
= 0;
1489 fn_pp
= ptrs
+ oidx
;
1490 ptrs
[oidx
++] = function_name
;
1493 /* The .toc symbol */
1495 asymbol
*toc_symbol
; /* The .toc symbol */
1497 toc_symbol
= bfd_make_empty_symbol(abfd
);
1498 toc_symbol
->name
= make_label (".", "toc");
1499 toc_symbol
->section
= (asection
*)&bfd_und_section
;
1500 toc_symbol
->flags
= BSF_GLOBAL
;
1501 toc_symbol
->value
= 0;
1503 toc_pp
= ptrs
+ oidx
;
1504 ptrs
[oidx
++] = toc_symbol
;
1510 for (i
= 0; i
< NSECS
; i
++)
1512 sinfo
*si
= secdata
+ i
;
1513 asection
*sec
= si
->sec
;
1522 si
->size
= HOW_JTAB_SIZE
;
1523 si
->data
= xmalloc (HOW_JTAB_SIZE
);
1524 memcpy (si
->data
, HOW_JTAB
, HOW_JTAB_SIZE
);
1526 /* add the reloqc into idata$5 */
1527 rel
= xmalloc (sizeof (arelent
));
1528 rpp
= xmalloc (sizeof (arelent
*) * 2);
1531 rel
->address
= HOW_JTAB_ROFF
;
1534 if (machine
== MPPC
)
1536 rel
->howto
= bfd_reloc_type_lookup (abfd
,
1537 BFD_RELOC_16_GOTOFF
);
1538 rel
->sym_ptr_ptr
= iname_pp
;
1542 rel
->howto
= bfd_reloc_type_lookup (abfd
, BFD_RELOC_32
);
1543 rel
->sym_ptr_ptr
= secdata
[IDATA5
].sympp
;
1545 sec
->orelocation
= rpp
;
1546 sec
->reloc_count
= 1;
1551 /* An idata$4 or idata$5 is one word long, and has an
1554 si
->data
= xmalloc (4);
1559 si
->data
[0] = exp
->ordinal
;
1560 si
->data
[1] = exp
->ordinal
>> 8;
1561 si
->data
[2] = exp
->ordinal
>> 16;
1566 sec
->reloc_count
= 1;
1567 memset (si
->data
, 0, si
->size
);
1568 rel
= xmalloc (sizeof (arelent
));
1569 rpp
= xmalloc (sizeof (arelent
*) * 2);
1574 rel
->howto
= bfd_reloc_type_lookup (abfd
, BFD_RELOC_RVA
);
1575 rel
->sym_ptr_ptr
= secdata
[IDATA6
].sympp
;
1576 sec
->orelocation
= rpp
;
1584 int idx
= exp
->hint
+ 1;
1585 si
->size
= strlen (xlate (exp
->name
)) + 3;
1586 si
->data
= xmalloc (si
->size
);
1587 si
->data
[0] = idx
& 0xff;
1588 si
->data
[1] = idx
>> 8;
1589 strcpy (si
->data
+ 2, xlate (exp
->name
));
1594 si
->data
=xmalloc(4);
1595 memset (si
->data
, 0, si
->size
);
1596 rel
= xmalloc (sizeof (arelent
));
1597 rpp
= xmalloc (sizeof (arelent
*) * 2);
1601 rel
->howto
= bfd_reloc_type_lookup (abfd
, BFD_RELOC_RVA
);
1602 rel
->sym_ptr_ptr
= iname_lab_pp
;
1603 sec
->orelocation
= rpp
;
1604 sec
->reloc_count
= 1;
1610 /* The .pdata section is 5 words long. */
1611 /* Think of it as: */
1614 /* bfd_vma BeginAddress, [0x00] */
1615 /* EndAddress, [0x04] */
1616 /* ExceptionHandler, [0x08] */
1617 /* HandlerData, [0x0c] */
1618 /* PrologEndAddress; [0x10] */
1621 /* So this pdata section setups up this as a glue linkage to
1622 a dll routine. There are a number of house keeping things
1625 1. In the name of glue trickery, the ADDR32 relocs for 0,
1626 4, and 0x10 are set to point to the same place:
1628 2. There is one more reloc needed in the pdata section.
1629 The actual glue instruction to restore the toc on
1630 return is saved as the offset in an IMGLUE reloc.
1631 So we need a total of four relocs for this section.
1633 3. Lastly, the HandlerData field is set to 0x03, to indicate
1634 that this is a glue routine.
1636 arelent
*imglue
, *ba_rel
, *ea_rel
, *pea_rel
;
1638 /* alignment must be set to 2**2 or you get extra stuff */
1639 bfd_set_section_alignment(abfd
, sec
, 2);
1642 si
->data
=xmalloc(4 * 5);
1643 memset (si
->data
, 0, si
->size
);
1644 rpp
= xmalloc (sizeof (arelent
*) * 5);
1645 rpp
[0] = imglue
= xmalloc (sizeof (arelent
));
1646 rpp
[1] = ba_rel
= xmalloc (sizeof (arelent
));
1647 rpp
[2] = ea_rel
= xmalloc (sizeof (arelent
));
1648 rpp
[3] = pea_rel
= xmalloc (sizeof (arelent
));
1651 /* stick the toc reload instruction in the glue reloc */
1652 bfd_put_32(abfd
, ppc_glue_insn
, (char *) &imglue
->address
);
1655 imglue
->howto
= bfd_reloc_type_lookup (abfd
,
1656 BFD_RELOC_32_GOTOFF
);
1657 imglue
->sym_ptr_ptr
= fn_pp
;
1659 ba_rel
->address
= 0;
1661 ba_rel
->howto
= bfd_reloc_type_lookup (abfd
, BFD_RELOC_32
);
1662 ba_rel
->sym_ptr_ptr
= fn_pp
;
1664 bfd_put_32(abfd
, 0x18, si
->data
+ 0x04);
1665 ea_rel
->address
= 4;
1667 ea_rel
->howto
= bfd_reloc_type_lookup (abfd
, BFD_RELOC_32
);
1668 ea_rel
->sym_ptr_ptr
= fn_pp
;
1670 /* mark it as glue */
1671 bfd_put_32(abfd
, 0x03, si
->data
+ 0x0c);
1673 /* mark the prolog end address */
1674 bfd_put_32(abfd
, 0x0D, si
->data
+ 0x10);
1675 pea_rel
->address
= 0x10;
1676 pea_rel
->addend
= 0;
1677 pea_rel
->howto
= bfd_reloc_type_lookup (abfd
, BFD_RELOC_32
);
1678 pea_rel
->sym_ptr_ptr
= fn_pp
;
1680 sec
->orelocation
= rpp
;
1681 sec
->reloc_count
= 4;
1685 /* Each external function in a PowerPC PE file has a two word
1686 descriptor consisting of:
1687 1. The address of the code.
1688 2. The address of the appropriate .toc
1689 We use relocs to build this.
1693 si
->data
= xmalloc (8);
1694 memset (si
->data
, 0, si
->size
);
1696 rpp
= xmalloc (sizeof (arelent
*) * 3);
1697 rpp
[0] = rel
= xmalloc (sizeof (arelent
));
1698 rpp
[1] = xmalloc (sizeof (arelent
));
1703 rel
->howto
= bfd_reloc_type_lookup (abfd
, BFD_RELOC_32
);
1704 rel
->sym_ptr_ptr
= fn_pp
;
1710 rel
->howto
= bfd_reloc_type_lookup (abfd
, BFD_RELOC_32
);
1711 rel
->sym_ptr_ptr
= toc_pp
;
1713 sec
->orelocation
= rpp
;
1714 sec
->reloc_count
= 2;
1716 #endif /* DLLTOOL_PPC */
1722 /* Size up all the sections */
1723 for (i
= 0; i
< NSECS
; i
++)
1725 sinfo
*si
= secdata
+ i
;
1727 bfd_set_section_size (abfd
, si
->sec
, si
->size
);
1728 bfd_set_section_vma (abfd
, si
->sec
, vma
);
1730 /* vma += si->size;*/
1733 /* Write them out */
1734 for (i
= 0; i
< NSECS
; i
++)
1736 sinfo
*si
= secdata
+ i
;
1738 if (i
== IDATA5
&& no_idata5
)
1741 if (i
== IDATA4
&& no_idata4
)
1744 bfd_set_section_contents (abfd
, si
->sec
,
1749 bfd_set_symtab (abfd
, ptrs
, oidx
);
1751 abfd
= bfd_openr (outname
, HOW_BFD_TARGET
);
1760 FILE * f
= fopen ("dh.s", FOPEN_WT
);
1762 fprintf (f
, "%s IMAGE_IMPORT_DESCRIPTOR\n", ASM_C
);
1763 fprintf (f
, "\t.section .idata$2\n");
1765 fprintf(f
,"\t%s\t%s\n", ASM_GLOBAL
,head_label
);
1767 fprintf (f
, "%s:\n", head_label
);
1769 fprintf (f
, "\t%shname%s\t%sPtr to image import by name list\n",
1770 ASM_RVA_BEFORE
, ASM_RVA_AFTER
, ASM_C
);
1772 fprintf (f
, "\t%sthis should be the timestamp, but NT sometimes\n", ASM_C
);
1773 fprintf (f
, "\t%sdoesn't load DLLs when this is set.\n", ASM_C
);
1774 fprintf (f
, "\t%s\t0\t%s loaded time\n", ASM_LONG
, ASM_C
);
1775 fprintf (f
, "\t%s\t0\t%s Forwarder chain\n", ASM_LONG
, ASM_C
);
1776 fprintf (f
, "\t%s__%s_iname%s\t%s imported dll's name\n",
1781 fprintf (f
, "\t%sfthunk%s\t%s pointer to firstthunk\n",
1783 ASM_RVA_AFTER
, ASM_C
);
1785 fprintf (f
, "%sStuff for compatibility\n", ASM_C
);
1789 fprintf (f
, "\t.section\t.idata$5\n");
1790 fprintf (f
, "\t%s\t0\n", ASM_LONG
);
1791 fprintf (f
, "fthunk:\n");
1795 fprintf (f
, "\t.section\t.idata$4\n");
1797 fprintf (f
, "\t%s\t0\n", ASM_LONG
);
1798 fprintf (f
, "\t.section .idata$4\n");
1799 fprintf (f
, "hname:\n");
1803 sprintf (outfile
, "-o dh.o dh.s");
1804 run (as_name
, outfile
);
1806 return bfd_openr ("dh.o", HOW_BFD_TARGET
);
1812 FILE * f
= fopen ("dt.s", FOPEN_WT
);
1816 fprintf (f
, "\t.section .idata$4\n");
1817 fprintf (f
, "\t%s\t0\n", ASM_LONG
);
1821 fprintf (f
, "\t.section .idata$5\n");
1822 fprintf (f
, "\t%s\t0\n", ASM_LONG
);
1826 /* Normally, we need to see a null descriptor built in idata$3 to
1827 act as the terminator for the list. The ideal way, I suppose,
1828 would be to mark this section as a comdat type 2 section, so
1829 only one would appear in the final .exe (if our linker supported
1830 comdat, that is) or cause it to be inserted by something else (say
1834 fprintf (f
, "\t.section .idata$3\n");
1835 fprintf (f
, "\t%s\t0\n", ASM_LONG
);
1836 fprintf (f
, "\t%s\t0\n", ASM_LONG
);
1837 fprintf (f
, "\t%s\t0\n", ASM_LONG
);
1838 fprintf (f
, "\t%s\t0\n", ASM_LONG
);
1839 fprintf (f
, "\t%s\t0\n", ASM_LONG
);
1843 /* Other PowerPC NT compilers use idata$6 for the dllname, so I
1844 do too. Original, huh? */
1845 fprintf (f
, "\t.section .idata$6\n");
1847 fprintf (f
, "\t.section .idata$7\n");
1850 fprintf (f
, "\t%s\t__%s_iname\n", ASM_GLOBAL
, imp_name_lab
);
1851 fprintf (f
, "__%s_iname:\t%s\t\"%s\"\n",
1852 imp_name_lab
, ASM_TEXT
, dll_name
);
1856 sprintf (outfile
, "-o dt.o dt.s");
1857 run (as_name
, outfile
);
1858 return bfd_openr ("dt.o", HOW_BFD_TARGET
);
1873 outarch
= bfd_openw (imp_name
, HOW_BFD_TARGET
);
1877 fprintf (stderr
, "%s: Can't open .lib file %s\n", program_name
, imp_name
);
1880 bfd_set_format (outarch
, bfd_archive
);
1881 outarch
->has_armap
= 1;
1883 /* Work out a reasonable size of things to put onto one line. */
1887 ar_head
= make_head ();
1888 ar_tail
= make_tail();
1890 for (i
= 0; (exp
= d_exports_lexically
[i
]); i
++)
1892 bfd
*n
= make_one_lib_file (exp
, i
);
1898 /* Now stick them all into the archive */
1900 ar_head
->next
= head
;
1901 ar_tail
->next
= ar_head
;
1904 if (! bfd_set_archive_head (outarch
, head
))
1905 bfd_fatal ("bfd_set_archive_head");
1906 if (! bfd_close (outarch
))
1907 bfd_fatal (imp_name
);
1909 while (head
!= NULL
)
1911 bfd
*n
= head
->next
;
1916 /* Delete all the temp files */
1918 if (dontdeltemps
== 0)
1920 sprintf (outfile
, "dh.o");
1922 sprintf (outfile
, "dh.s");
1924 sprintf (outfile
, "dt.o");
1926 sprintf (outfile
, "dt.s");
1930 if (dontdeltemps
< 2)
1931 for (i
= 0, exp
= d_exports
; exp
; i
++, exp
= exp
->next
)
1933 sprintf (outfile
, "ds%d.o",i
);
1938 /**********************************************************************/
1940 /* Run through the information gathered from the .o files and the
1941 .def file and work out the best stuff */
1947 export_type
*ap
= *(export_type
**) a
;
1948 export_type
*bp
= *(export_type
**) b
;
1949 if (ap
->ordinal
== bp
->ordinal
)
1952 /* unset ordinals go to the bottom */
1953 if (ap
->ordinal
== -1)
1955 if (bp
->ordinal
== -1)
1957 return (ap
->ordinal
- bp
->ordinal
);
1965 export_type
*ap
= *(export_type
**) a
;
1966 export_type
*bp
= *(export_type
**) b
;
1968 return (strcmp (ap
->name
, bp
->name
));
1972 remove_null_names (ptr
)
1977 for (dst
= src
= 0; src
< d_nfuncs
; src
++)
1981 ptr
[dst
] = ptr
[src
];
1994 for (i
= 0; i
< d_nfuncs
; i
++)
1998 printf ("%d %s @ %d %s%s%s\n",
1999 i
, ptr
[i
]->name
, ptr
[i
]->ordinal
,
2000 ptr
[i
]->noname
? "NONAME " : "",
2001 ptr
[i
]->constant
? "CONSTANT" : "",
2002 ptr
[i
]->data
? "DATA" : "");
2011 process_duplicates (d_export_vec
)
2012 export_type
**d_export_vec
;
2020 /* Remove duplicates */
2021 qsort (d_export_vec
, d_nfuncs
, sizeof (export_type
*), nfunc
);
2023 dtab (d_export_vec
);
2024 for (i
= 0; i
< d_nfuncs
- 1; i
++)
2026 if (strcmp (d_export_vec
[i
]->name
,
2027 d_export_vec
[i
+ 1]->name
) == 0)
2030 export_type
*a
= d_export_vec
[i
];
2031 export_type
*b
= d_export_vec
[i
+ 1];
2035 fprintf (stderr
, "Warning, ignoring duplicate EXPORT %s %d,%d\n",
2039 if (a
->ordinal
!= -1
2040 && b
->ordinal
!= -1)
2043 fprintf (stderr
, "Error, duplicate EXPORT with oridinals %s\n",
2047 /* Merge attributes */
2048 b
->ordinal
= a
->ordinal
> 0 ? a
->ordinal
: b
->ordinal
;
2049 b
->constant
|= a
->constant
;
2050 b
->noname
|= a
->noname
;
2052 d_export_vec
[i
] = 0;
2055 dtab (d_export_vec
);
2056 remove_null_names (d_export_vec
);
2057 dtab (d_export_vec
);
2062 /* Count the names */
2063 for (i
= 0; i
< d_nfuncs
; i
++)
2065 if (!d_export_vec
[i
]->noname
)
2071 fill_ordinals (d_export_vec
)
2072 export_type
**d_export_vec
;
2079 qsort (d_export_vec
, d_nfuncs
, sizeof (export_type
*), pfunc
);
2081 /* fill in the unset ordinals with ones from our range */
2083 ptr
= (char *) xmalloc (size
);
2085 memset (ptr
, 0, size
);
2087 /* Mark in our large vector all the numbers that are taken */
2088 for (i
= 0; i
< d_nfuncs
; i
++)
2090 if (d_export_vec
[i
]->ordinal
!= -1)
2092 ptr
[d_export_vec
[i
]->ordinal
] = 1;
2093 if (lowest
== -1 || d_export_vec
[i
]->ordinal
< lowest
)
2095 lowest
= d_export_vec
[i
]->ordinal
;
2100 /* Start at 1 for compatibility with MS toolchain. */
2104 /* Now fill in ordinals where the user wants us to choose. */
2105 for (i
= 0; i
< d_nfuncs
; i
++)
2107 if (d_export_vec
[i
]->ordinal
== -1)
2111 /* First try within or after any user supplied range. */
2112 for (j
= lowest
; j
< size
; j
++)
2116 d_export_vec
[i
]->ordinal
= j
;
2120 /* Then try before the range. */
2121 for (j
= lowest
; j
>0; j
--)
2125 d_export_vec
[i
]->ordinal
= j
;
2136 qsort (d_export_vec
, d_nfuncs
, sizeof (export_type
*), pfunc
);
2138 /* Work out the lowest and highest ordinal numbers. */
2141 if (d_export_vec
[0])
2142 d_low_ord
= d_export_vec
[0]->ordinal
;
2143 if (d_export_vec
[d_nfuncs
-1])
2144 d_high_ord
= d_export_vec
[d_nfuncs
-1]->ordinal
;
2153 const export_type
**a
= (const export_type
**) av
;
2154 const export_type
**b
= (const export_type
**) bv
;
2156 return strcmp ((*a
)->name
, (*b
)->name
);
2162 /* First work out the minimum ordinal chosen */
2168 export_type
**d_export_vec
2169 = (export_type
**) xmalloc (sizeof (export_type
*) * d_nfuncs
);
2171 for (i
= 0, exp
= d_exports
; exp
; i
++, exp
= exp
->next
)
2173 d_export_vec
[i
] = exp
;
2176 process_duplicates (d_export_vec
);
2177 fill_ordinals (d_export_vec
);
2179 /* Put back the list in the new order */
2181 for (i
= d_nfuncs
- 1; i
>= 0; i
--)
2183 d_export_vec
[i
]->next
= d_exports
;
2184 d_exports
= d_export_vec
[i
];
2187 /* Build list in alpha order */
2188 d_exports_lexically
= (export_type
**)xmalloc (sizeof(export_type
*)*(d_nfuncs
+1));
2190 for (i
= 0, exp
= d_exports
; exp
; i
++, exp
= exp
->next
)
2192 d_exports_lexically
[i
] = exp
;
2194 d_exports_lexically
[i
] = 0;
2196 qsort (d_exports_lexically
, i
, sizeof (export_type
*), alphafunc
);
2198 /* Fill exp entries with their hint values */
2200 for (i
= 0; i
< d_nfuncs
; i
++)
2202 if (!d_exports_lexically
[i
]->noname
|| show_allnames
)
2203 d_exports_lexically
[i
]->hint
= hint
++;
2208 /**********************************************************************/
2211 usage (file
, status
)
2215 fprintf (file
, "Usage %s <options> <object-files>\n", program_name
);
2216 fprintf (file
, " --machine <machine>\n");
2217 fprintf (file
, " --output-exp <outname> Generate export file.\n");
2218 fprintf (file
, " --output-lib <outname> Generate input library.\n");
2219 fprintf (file
, " --add-indirect Add dll indirects to export file.\n");
2220 fprintf (file
, " --dllname <name> Name of input dll to put into output lib.\n");
2221 fprintf (file
, " --def <deffile> Name input .def file\n");
2222 fprintf (file
, " --output-def <deffile> Name output .def file\n");
2223 fprintf (file
, " --base-file <basefile> Read linker generated base file\n");
2224 fprintf (file
, " --no-idata4 Don't generate idata$4 section\n");
2225 fprintf (file
, " --no-idata5 Don't generate idata$5 section\n");
2226 fprintf (file
, " -v Verbose\n");
2227 fprintf (file
, " -U Add underscores to .lib\n");
2228 fprintf (file
, " -k Kill @<n> from exported names\n");
2229 fprintf (file
, " --as <name> Use <name> for assembler\n");
2230 fprintf (file
, " --nodelete Keep temp files.\n");
2234 #define OPTION_NO_IDATA4 'x'
2235 #define OPTION_NO_IDATA5 'c'
2236 static const struct option long_options
[] =
2238 {"nodelete", no_argument
, NULL
, 'n'},
2239 {"dllname", required_argument
, NULL
, 'D'},
2240 {"no-idata4", no_argument
, NULL
, OPTION_NO_IDATA4
},
2241 {"no-idata5", no_argument
, NULL
, OPTION_NO_IDATA5
},
2242 {"output-exp", required_argument
, NULL
, 'e'},
2243 {"output-def", required_argument
, NULL
, 'z'},
2244 {"output-lib", required_argument
, NULL
, 'l'},
2245 {"def", required_argument
, NULL
, 'd'},
2246 {"add-underscore", no_argument
, NULL
, 'U'},
2247 {"killat", no_argument
, NULL
, 'k'},
2248 {"help", no_argument
, NULL
, 'h'},
2249 {"machine", required_argument
, NULL
, 'm'},
2250 {"add-indirect", no_argument
, NULL
, 'a'},
2251 {"base-file", required_argument
, NULL
, 'b'},
2252 {"as", required_argument
, NULL
, 'S'},
2264 program_name
= av
[0];
2267 while ((c
= getopt_long (ac
, av
, "xcz:S:R:A:puaD:l:e:nkvbUh?m:yd:", long_options
, 0))
2272 case OPTION_NO_IDATA4
:
2275 case OPTION_NO_IDATA5
:
2282 /* ignored for compatibility */
2289 output_def
= fopen (optarg
, FOPEN_WT
);
2312 /* We don't currently define YYDEBUG when building
2330 base_file
= fopen (optarg
, FOPEN_RB
);
2333 fprintf (stderr
, "%s: Unable to open base-file %s\n",
2345 for (i
= 0; mtable
[i
].type
; i
++)
2347 if (strcmp (mtable
[i
].type
, mname
) == 0)
2351 if (!mtable
[i
].type
)
2353 fprintf (stderr
, "Machine not supported\n");
2359 if (!dll_name
&& exp_name
)
2361 char len
= strlen (exp_name
) + 5;
2362 dll_name
= xmalloc (len
);
2363 strcpy (dll_name
, exp_name
);
2364 strcat (dll_name
, ".dll");
2369 process_def_file (def_file
);
2374 firstarg
= av
[optind
];
2375 scan_obj_file (av
[optind
]);
2385 /* Make imp_name safe for use as a label. */
2388 imp_name_lab
= xstrdup (imp_name
);
2389 for (p
= imp_name_lab
; *p
; p
++)
2391 if (!isalpha (*p
) && !isdigit (*p
))
2394 head_label
= make_label("_head_", imp_name_lab
);