1 #define show_allnames 0
3 /* dlltool.c -- tool to generate stuff for PE style DLLs
4 Copyright (C) 1995 Free Software Foundation, Inc.
6 This file is part of GNU Binutils.
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
24 This program allows you to build the files necessary to create
25 DLLs to run on a system which understands PE format image files.
28 A DLL contains an export table which contains the information
29 which the runtime loader needs to tie up references from a
32 The export table is generated by this program by reading
33 in a .DEF file or scanning the .a and .o files which will be in the
34 DLL. A .o file can contain information in special ".drectve" sections
35 with export information.
37 A DEF file contains any number of the following commands:
40 NAME <name> [ , <base> ]
41 The result is going to be <name>.EXE
43 LIBRARY <name> [ , <base> ]
44 The result is going to be <name>.DLL
46 EXPORTS ( <name1> [ = <name2> ] [ @ <integer> ] [ NONAME ] [CONSTANT] ) *
47 Declares name1 as an exported symbol from the
48 DLL, with optional ordinal number <integer>
50 IMPORTS ( [ <name> = ] <name> . <name> ) *
51 Ignored for compatibility
54 Puts <string> into output .exp file in the .rdata section
56 [STACKSIZE|HEAPSIZE] <number-reserve> [ , <number-commit> ]
57 Generates --stack|--heap <number-reserve>,<number-commit>
58 in the output .drectve section. The linker will
59 see this and act upon it.
62 SECTIONS ( <sectionname> <attr>+ )*
63 <attr> = READ | WRITE | EXECUTE | SHARED
64 Generates --attr <sectionname> <attr> in the output
65 .drectve section. The linker will see this and act
69 A -export:<name> in a .drectve section in an input .o or .a
70 file to this program is equivalent to a EXPORTS <name>
75 The program generates output files with the prefix supplied
76 on the command line, or in the def file, or taken from the first
79 The .exp.s file contains the information necessary to export
80 the routines in the DLL. The .lib.s file contains the information
81 necessary to use the DLL's routines from a referencing program.
88 asm (".section .drectve");
89 asm (".ascii \"-export:adef\"");
93 printf("hello from the dll %s\n",s);
98 printf("hello from the dll and the other entry point %s\n",s);
102 asm (".section .drectve");
103 asm (".ascii \"-export:cdef\"");
104 asm (".ascii \"-export:ddef\"");
107 printf("hello from the dll %s\n",s);
112 printf("hello from the dll and the other entry point %s\n",s);
130 HEAPSIZE 0x40000, 0x2000
134 SECTIONS donkey READ WRITE
138 # compile up the parts of the dll
143 # put them in a library (you don't have to, you
144 # could name all the .os on the dlltool line)
146 ar qcv thedll.in file1.o file2.o
149 # run this tool over the library and the def file
150 ./dlltool --def thedll.def --output-exp thedll.o --output-lib thedll.a
152 # build the dll with the library with file1.o, file2.o and the export table
153 ld -o thedll.dll thedll.o thedll.in
158 # link the executable with the import library
159 ld -e main -Tthemain.ld -o themain.exe themain.o thedll.a
163 #define PAGE_SIZE 4096
164 #define PAGE_MASK (-PAGE_SIZE)
166 #include "libiberty.h"
169 #include <sys/types.h>
170 #include "demangle.h"
172 #ifdef HAVE_SYS_WAIT_H
173 #include <sys/wait.h>
176 #define WIFEXITED(w) (((w)&0377) == 0)
179 #define WIFSIGNALED(w) (((w)&0377) != 0177 && ((w)&~0377) == 0)
182 #define WTERMSIG(w) ((w) & 0177)
185 #define WEXITSTATUS(w) (((w) >> 8) & 0377)
191 char *as_name
= "as";
193 static int no_idata4
;
194 static int no_idata5
;
195 static char *exp_name
;
196 static char *imp_name
;
197 static char *head_label
;
198 static char *imp_name_lab
;
199 static char *dll_name
;
201 static int add_indirect
= 0;
202 static int add_underscore
= 0;
203 static int dontdeltemps
= 0;
207 static char *def_file
;
209 static char *program_name
;
219 static char *mname
= "arm";
223 static char *mname
= "i386";
225 #define PATHMAX 250 /* What's the right name for this ? */
227 /* This bit of assemly does jmp * ....
228 s set how_jtab_roff to mark where the 32bit abs branch should go */
229 unsigned char i386_jtab
[] = { 0xff, 0x25, 0x00, 0x00, 0x00, 0x00, 0x90, 0x90};
232 unsigned char arm_jtab
[] = { 0x00, 0xc0, 0x9f, 0xe5,
233 0x00, 0xf0, 0x9c, 0xe5,
235 char outfile
[PATHMAX
];
247 char *how_align_short
;
248 char *how_align_long
;
249 char *how_bfd_target
;
250 enum bfd_architecture how_bfd_arch
;
251 unsigned char *how_jtab
;
252 int how_jtab_size
; /* size of the jtab entry */
253 int how_jtab_roff
; /* offset into it for the ind 32 reloc into idata 5 */
260 "arm", ".byte", ".short", ".long", ".asciz", "@",
261 "ldr\tip,[pc]\n\tldr\tpc,[ip]\n\t.long",
262 ".global", ".space", ".align\t2",".align\t4","pe-arm-little", bfd_arch_arm
,
263 arm_jtab
, sizeof(arm_jtab
),8
268 "i386", ".byte", ".short", ".long", ".asciz", "#", "jmp *", ".global", ".space", ".align\t2",".align\t4","pe-i386",bfd_arch_i386
,
269 i386_jtab
,sizeof(i386_jtab
),2,
317 #define ASM_BYTE mtable[machine].how_byte
318 #define ASM_SHORT mtable[machine].how_short
319 #define ASM_LONG mtable[machine].how_long
320 #define ASM_TEXT mtable[machine].how_asciz
321 #define ASM_C mtable[machine].how_comment
322 #define ASM_JUMP mtable[machine].how_jump
323 #define ASM_GLOBAL mtable[machine].how_global
324 #define ASM_SPACE mtable[machine].how_space
325 #define ASM_ALIGN_SHORT mtable[machine].how_align_short
326 #define ASM_RVA_BEFORE rvabefore(machine)
327 #define ASM_RVA_AFTER rvaafter(machine)
328 #define ASM_PREFIX asm_prefix(machine)
329 #define ASM_ALIGN_LONG mtable[machine].how_align_long
330 #define HOW_BFD_TARGET 0 /* always default*/
331 #define HOW_BFD_ARCH mtable[machine].how_bfd_arch
332 #define HOW_JTAB mtable[machine].how_jtab
333 #define HOW_JTAB_SIZE mtable[machine].how_jtab_size
334 #define HOW_JTAB_ROFF mtable[machine].how_jtab_roff
338 FILE *yyin
; /* communications with flex */
339 extern int linenumber
;
341 process_def_file (name
)
344 FILE *f
= fopen (name
, "r");
347 fprintf (stderr
, "%s: Can't open def file %s\n", program_name
, name
);
356 /**********************************************************************/
358 /* Communications with the parser */
368 typedef struct export
380 static char *d_name
; /* Arg to NAME or LIBRARY */
381 static int d_nfuncs
; /* Number of functions exported */
382 static int d_named_nfuncs
; /* Number of named functions exported */
383 static int d_low_ord
; /* Lowest ordinal index */
384 static int d_high_ord
; /* Highest ordinal index */
385 static export_type
*d_exports
; /*list of exported functions */
386 static export_type
**d_exports_lexically
; /* vector of exported functions in alpha order */
387 static dlist_type
*d_list
; /* Descriptions */
388 static dlist_type
*a_list
; /* Stuff to go in directives */
396 fprintf (stderr
, "%s: Syntax error in def file %s:%d\n",
397 program_name
, def_file
, linenumber
);
402 def_exports (name
, internal_name
, ordinal
, noname
, constant
)
409 struct export
*p
= (struct export
*) xmalloc (sizeof (*p
));
412 p
->internal_name
= internal_name
? internal_name
: name
;
413 p
->ordinal
= ordinal
;
414 p
->constant
= constant
;
423 def_name (name
, base
)
428 fprintf (stderr
, "%s NAME %s base %x\n", program_name
, name
, base
);
431 fprintf (stderr
, "Can't have LIBRARY and NAME\n");
438 def_library (name
, base
)
443 printf ("%s: LIBRARY %s base %x\n", program_name
, name
, base
);
446 fprintf (stderr
, "%s: Can't have LIBRARY and NAME\n", program_name
);
453 def_description (desc
)
456 dlist_type
*d
= (dlist_type
*) xmalloc (sizeof (dlist_type
));
457 d
->text
= strdup (desc
);
466 dlist_type
*d
= (dlist_type
*) xmalloc (sizeof (dlist_type
));
467 d
->text
= strdup (dir
);
473 def_stacksize (reserve
, commit
)
479 sprintf (b
, "-stack 0x%x,0x%x ", reserve
, commit
);
481 sprintf (b
, "-stack 0x%x ", reserve
);
482 new_directive (strdup (b
));
486 def_heapsize (reserve
, commit
)
492 sprintf (b
, "-heap 0x%x,0x%x ", reserve
, commit
);
494 sprintf (b
, "-heap 0x%x ", reserve
);
495 new_directive (strdup (b
));
500 def_import (internal
, module
, entry
)
506 fprintf (stderr
, "%s: IMPORTS are ignored", program_name
);
510 def_version (major
, minor
)
514 printf ("VERSION %d.%d\n", major
, minor
);
519 def_section (name
, attr
)
536 sprintf (buf
, "-attr %s %s", name
, atts
);
537 new_directive (strdup (buf
));
544 def_section ("CODE", attr
);
551 def_section ("DATA", attr
);
555 /**********************************************************************/
566 extern char **environ
;
568 fprintf (stderr
, "%s %s\n", what
, args
);
572 for (s
= args
; *s
; s
++)
576 argv
= alloca (sizeof (char *) * (i
+ 3));
583 while (*s
!= ' ' && *s
!= 0)
597 fprintf (stderr
, "%s: can't exec %s\n", program_name
, what
);
603 fprintf (stderr
, "%s: vfork failed, %d\n", program_name
, errno
);
609 waitpid (pid
, &status
, 0);
612 if (WIFSIGNALED (status
))
614 fprintf (stderr
, "%s: %s %s terminated with signal %d\n",
615 program_name
, what
, args
, WTERMSIG (status
));
619 if (WIFEXITED (status
))
621 fprintf (stderr
, "%s: %s %s terminated with exit status %d\n",
622 program_name
, what
, args
, WEXITSTATUS (status
));
629 /* read in and block out the base relocations */
641 scan_open_obj_file (abfd
)
644 /* Look for .drectve's */
645 asection
*s
= bfd_get_section_by_name (abfd
, ".drectve");
648 int size
= bfd_get_section_size_before_reloc (s
);
649 char *buf
= xmalloc (size
);
652 bfd_get_section_contents (abfd
, s
, buf
, 0, size
);
654 fprintf (stderr
, "%s: Sucking in info from %s\n",
656 bfd_get_filename (abfd
));
658 /* Search for -export: strings */
664 && strncmp (p
, "-export:", 8) == 0)
670 while (*p
!= ' ' && *p
!= '-' && p
< e
)
672 c
= xmalloc (p
- name
+ 1);
673 memcpy (c
, name
, p
- name
);
675 def_exports (c
, 0, -1, 0);
686 fprintf (stderr
, "%s: Done readin\n",
693 scan_obj_file (filename
)
696 bfd
*f
= bfd_openr (filename
, 0);
700 fprintf (stderr
, "%s: Unable to open object file %s\n",
705 if (bfd_check_format (f
, bfd_archive
))
707 bfd
*arfile
= bfd_openr_next_archived_file (f
, 0);
710 if (bfd_check_format (arfile
, bfd_object
))
711 scan_open_obj_file (arfile
);
713 arfile
= bfd_openr_next_archived_file (f
, arfile
);
716 else if (bfd_check_format (f
, bfd_object
))
718 scan_open_obj_file (f
);
724 /**********************************************************************/
734 fprintf (f
, "%s ", ASM_C
);
735 for (i
= 0; oav
[i
]; i
++)
736 fprintf (f
, "%s ", oav
[i
]);
738 for (i
= 0, exp
= d_exports
; exp
; i
++, exp
= exp
->next
)
740 fprintf (f
, "%s %d = %s %s @ %d %s%s\n",
746 exp
->noname
? "NONAME " : "",
747 exp
->constant
? "CONSTANT" : "");
750 /* Generate the .exp file */
763 flush_page (f
, need
, page_addr
, on_page
)
771 /* Flush this page */
772 fprintf (f
, "\t%s\t0x%08x\t%s Starting RVA for chunk\n",
776 fprintf (f
, "\t%s\t0x%x\t%s Size of block\n",
778 (on_page
* 2) + (on_page
& 1) * 2 + 8,
780 for (i
= 0; i
< on_page
; i
++)
782 fprintf (f
, "\t%s\t0x%x\n", ASM_SHORT
, (need
[i
] - page_addr
) | 0x3000);
786 fprintf (f
, "\t%s\t0x%x\n", ASM_SHORT
, 0 | 0x0000);
797 fprintf (output_def
, ";");
798 for (i
= 0; oav
[i
]; i
++)
799 fprintf (output_def
, " %s", oav
[i
]);
801 fprintf (output_def
, "\nEXPORTS\n");
803 for (i
= 0, exp
= d_exports
; exp
; i
++, exp
= exp
->next
)
805 char *quote
= strchr (exp
->name
, '.') ? "\"" : "";
806 fprintf (output_def
, "\t%s%s%s @ %d%s ; %s\n",
811 exp
->noname
? " NONAME" : "",
812 cplus_demangle (exp
->internal_name
, DMGL_ANSI
| DMGL_PARAMS
));
824 sprintf (outfile
, "t%s", exp_name
);
827 fprintf (stderr
, "%s: Generate exp file %s\n",
828 program_name
, exp_name
);
830 f
= fopen (outfile
, "w");
833 fprintf (stderr
, "%s: Unable to open output file %s\n", program_name
, outfile
);
838 fprintf (stderr
, "%s: Opened file %s\n",
839 program_name
, outfile
);
845 fprintf (f
, "\t.section .edata\n\n");
846 fprintf (f
, "\t%s 0 %s Allways 0\n", ASM_LONG
, ASM_C
);
847 fprintf (f
, "\t%s 0x%x %s Time and date\n", ASM_LONG
, time(0),ASM_C
);
848 fprintf (f
, "\t%s 0 %s Major and Minor version\n", ASM_LONG
, ASM_C
);
849 fprintf (f
, "\t%sname%s %s Ptr to name of dll\n", ASM_RVA_BEFORE
, ASM_RVA_AFTER
, ASM_C
);
850 fprintf (f
, "\t%s %d %s Starting ordinal of exports\n", ASM_LONG
, d_low_ord
, ASM_C
);
853 fprintf (f
, "\t%s %d %s Number of functions\n", ASM_LONG
, d_high_ord
- d_low_ord
+ 1, ASM_C
);
854 fprintf(f
,"\t%s named funcs %d, low ord %d, high ord %d\n",
856 d_named_nfuncs
, d_low_ord
, d_high_ord
);
857 fprintf (f
, "\t%s %d %s Number of names\n", ASM_LONG
,
858 show_allnames
? d_high_ord
- d_low_ord
+ 1 : d_named_nfuncs
, ASM_C
);
859 fprintf (f
, "\t%safuncs%s %s Address of functions\n", ASM_RVA_BEFORE
, ASM_RVA_AFTER
, ASM_C
);
861 fprintf (f
, "\t%sanames%s %s Address of Name Pointer Table\n",
862 ASM_RVA_BEFORE
, ASM_RVA_AFTER
, ASM_C
);
864 fprintf (f
, "\t%sanords%s %s Address of ordinals\n", ASM_RVA_BEFORE
, ASM_RVA_AFTER
, ASM_C
);
866 fprintf (f
, "name: %s \"%s\"\n", ASM_TEXT
, dll_name
);
869 fprintf(f
,"%s Export address Table\n", ASM_C
);
870 fprintf(f
,"\t%s\n", ASM_ALIGN_LONG
);
871 fprintf (f
, "afuncs:\n");
874 for (exp
= d_exports
; exp
; exp
= exp
->next
)
876 if (exp
->ordinal
!= i
)
879 fprintf (f
, "\t%s\t%d\t%s %d..%d missing\n",
881 (exp
->ordinal
- i
) * 4,
883 i
, exp
->ordinal
- 1);
886 while (i
< exp
->ordinal
)
888 fprintf(f
,"\t%s\t0\n", ASM_LONG
);
892 fprintf (f
, "\t%s%s%s%s\t%s %d\n", ASM_RVA_BEFORE
,
894 exp
->internal_name
, ASM_RVA_AFTER
, ASM_C
, exp
->ordinal
);
898 fprintf (f
,"%s Export Name Pointer Table\n", ASM_C
);
899 fprintf (f
, "anames:\n");
901 for (i
= 0; (exp
= d_exports_lexically
[i
]); i
++)
903 if (!exp
->noname
|| show_allnames
)
904 fprintf (f
, "\t%sn%d%s\n", ASM_RVA_BEFORE
, exp
->ordinal
, ASM_RVA_AFTER
);
907 fprintf (f
,"%s Export Oridinal Table\n", ASM_C
);
908 fprintf (f
, "anords:\n");
909 for (i
= 0; (exp
= d_exports_lexically
[i
]); i
++)
911 if (!exp
->noname
|| show_allnames
)
912 fprintf (f
, "\t%s %d\n", ASM_SHORT
, exp
->ordinal
- d_low_ord
);
915 fprintf(f
,"%s Export Name Table\n", ASM_C
);
916 for (i
= 0; (exp
= d_exports_lexically
[i
]); i
++)
917 if (!exp
->noname
|| show_allnames
)
918 fprintf (f
, "n%d: %s \"%s\"\n", exp
->ordinal
, ASM_TEXT
, exp
->name
);
922 fprintf (f
, "\t.section .drectve\n");
923 for (dl
= a_list
; dl
; dl
= dl
->next
)
925 fprintf (f
, "\t%s\t\"%s\"\n", ASM_TEXT
, dl
->text
);
930 fprintf (f
, "\t.section .rdata\n");
931 for (dl
= d_list
; dl
; dl
= dl
->next
)
935 /* We dont output as ascii 'cause there can
936 be quote characters in the string */
939 for (p
= dl
->text
; *p
; p
++)
942 fprintf (f
, "\t%s\t", ASM_BYTE
);
945 fprintf (f
, "%d", *p
);
962 /* Add to the output file a way of getting to the exported names
963 without using the import library. */
966 fprintf (f
, "\t.section\t.rdata\n");
967 for (i
= 0, exp
= d_exports
; exp
; i
++, exp
= exp
->next
)
968 if (!exp
->noname
|| show_allnames
)
970 fprintf (f
, "\t%s\t__imp_%s\n", ASM_GLOBAL
, exp
->name
);
971 fprintf (f
, "__imp_%s:\n", exp
->name
);
972 fprintf (f
, "\t%s\t%s\n", ASM_LONG
, exp
->name
);
976 /* Dump the reloc section if a base file is provided */
980 long need
[PAGE_SIZE
];
987 fprintf (f
, "\t.section\t.init\n");
988 fprintf (f
, "lab:\n");
990 fseek (base_file
, 0, SEEK_END
);
991 numbytes
= ftell (base_file
);
992 fseek (base_file
, 0, SEEK_SET
);
993 copy
= malloc (numbytes
);
994 fread (copy
, 1, numbytes
, base_file
);
995 num_entries
= numbytes
/ sizeof (long);
998 fprintf (f
, "\t.section\t.reloc\n");
1005 qsort (copy
, num_entries
, sizeof (long), sfunc
);
1006 /* Delete duplcates */
1007 for (src
= 0; src
< num_entries
; src
++)
1009 if (last
!= copy
[src
])
1010 last
= copy
[dst
++] = copy
[src
];
1014 page_addr
= addr
& PAGE_MASK
; /* work out the page addr */
1016 for (j
= 0; j
< num_entries
; j
++)
1019 if ((addr
& PAGE_MASK
) != page_addr
)
1021 flush_page (f
, need
, page_addr
, on_page
);
1023 page_addr
= addr
& PAGE_MASK
;
1025 need
[on_page
++] = addr
;
1027 flush_page (f
, need
, page_addr
, on_page
);
1029 /* fprintf (f, "\t%s\t0,0\t%s End\n", ASM_LONG, ASM_C);*/
1035 /* assemble the file */
1036 sprintf (outfile
, "-o %s t%s", exp_name
, exp_name
);
1037 run (as_name
, outfile
);
1038 if (dontdeltemps
== 0)
1040 sprintf (outfile
, "t%s", exp_name
);
1050 char *copy
= malloc (strlen (name
) + 2);
1052 strcpy (copy
+ 1, name
);
1059 p
= strchr (name
, '@');
1066 /**********************************************************************/
1068 static void dump_iat (f
, exp
)
1072 if (exp
->noname
&& !show_allnames
)
1074 fprintf (f
, "\t%s\t0x%08x\n",
1076 exp
->ordinal
| 0x80000000); /* hint or orindal ?? */
1080 fprintf (f
, "\t%sID%d%s\n", ASM_RVA_BEFORE
,
1097 unsigned char *data
;
1110 static sinfo secdata
[NSECS
] =
1112 { TEXT
, ".text", SEC_CODE
| SEC_HAS_CONTENTS
},
1113 { DATA
, ".data", SEC_DATA
},
1115 { IDATA7
, ".idata$7",SEC_HAS_CONTENTS
},
1116 { IDATA5
, ".idata$5", SEC_HAS_CONTENTS
},
1117 { IDATA4
, ".idata$4", SEC_HAS_CONTENTS
},
1118 { IDATA6
,".idata$6", SEC_HAS_CONTENTS
}
1123 This is what we're trying to make
1126 .global _GetFileVersionInfoSizeW@8
1127 .global __imp_GetFileVersionInfoSizeW@8
1128 _GetFileVersionInfoSizeW@8:
1129 jmp * __imp_GetFileVersionInfoSizeW@8
1130 .section .idata$7 # To force loading of head
1131 .long __version_a_head
1132 # Import Address Table
1134 __imp_GetFileVersionInfoSizeW@8:
1137 # Import Lookup Table
1143 .asciz "GetFileVersionInfoSizeW"
1147 static char *make_label (prefix
, name
)
1151 int len
= strlen (ASM_PREFIX
) + strlen (prefix
) + strlen (name
);
1152 char *copy
= xmalloc (len
+1 );
1153 strcpy (copy
, ASM_PREFIX
);
1154 strcat (copy
, prefix
);
1155 strcat (copy
, name
);
1159 make_one_lib_file (exp
, i
)
1167 sprintf (outfile
, "%ss%d.s", prefix
, i
);
1168 f
= fopen (outfile
, "w");
1169 fprintf (f
, "\t.text\n");
1170 fprintf (f
, "\t%s\t%s%s\n", ASM_GLOBAL
, ASM_PREFIX
, exp
->name
);
1171 fprintf (f
, "\t%s\t__imp_%s\n", ASM_GLOBAL
, exp
->name
);
1172 fprintf (f
, "%s%s:\n\t%s\t__imp_%s\n", ASM_PREFIX
,
1173 exp
->name
, ASM_JUMP
, exp
->name
);
1175 fprintf (f
, "\t.section\t.idata$7\t%s To force loading of head\n", ASM_C
);
1176 fprintf (f
, "\t%s\t%s\n", ASM_LONG
, head_label
);
1179 fprintf (f
,"%s Import Address Table\n", ASM_C
);
1181 fprintf (f
, "\t.section .idata$5\n");
1182 fprintf (f
, "__imp_%s:\n", exp
->name
);
1186 fprintf (f
, "\n%s Import Lookup Table\n", ASM_C
);
1187 fprintf (f
, "\t.section .idata$4\n");
1191 if(!exp
->noname
|| show_allnames
)
1193 fprintf (f
, "%s Hint/Name table\n", ASM_C
);
1194 fprintf (f
, "\t.section .idata$6\n");
1195 fprintf (f
, "ID%d:\t%s\t%d\n", exp
->ordinal
, ASM_SHORT
, exp
->hint
);
1196 fprintf (f
, "\t%s\t\"%s\"\n", ASM_TEXT
, xlate (exp
->name
));
1202 sprintf (outfile
, "-o %ss%d.o %ss%d.s", prefix
, i
, prefix
, i
);
1204 run (as_name
, outfile
);
1215 asymbol
**iname_lab_pp
;
1216 asymbol
*ptrs
[NSECS
+3+1]; /* one symbol for each section, 2 extra + a null */
1218 char *outname
= xmalloc (10);
1220 sprintf (outname
, "ds%d.o", i
);
1221 abfd
= bfd_openw (outname
, HOW_BFD_TARGET
);
1224 fprintf (stderr
, "%s: bfd_open failed open output file %s\n", program_name
, outname
);
1228 bfd_set_format (abfd
, bfd_object
);
1229 bfd_set_arch_mach (abfd
, HOW_BFD_ARCH
, 0);
1232 for (i
= 0; i
< NSECS
; i
++)
1234 sinfo
*si
= secdata
+ i
;
1237 si
->sec
= bfd_make_section_old_way (abfd
, si
->name
);
1238 bfd_set_section_flags (abfd
,
1241 si
->sec
->output_section
= si
->sec
;
1242 si
->sym
= bfd_make_empty_symbol(abfd
);
1243 si
->sym
->name
= si
->sec
->name
;
1244 si
->sym
->section
= si
->sec
;
1245 si
->sym
->flags
= BSF_LOCAL
;
1247 ptrs
[oidx
] = si
->sym
;
1248 si
->sympp
= ptrs
+ oidx
;
1253 exp_label
= bfd_make_empty_symbol(abfd
);
1254 exp_label
->name
= make_label ("",exp
->name
);
1255 exp_label
->section
= secdata
[TEXT
].sec
;
1256 exp_label
->flags
= BSF_GLOBAL
;
1257 exp_label
->value
= 0;
1259 ptrs
[oidx
++] = exp_label
;
1261 iname
= bfd_make_empty_symbol(abfd
);
1263 iname
->name
= make_label ("__imp_", exp
->name
);
1265 iname
->section
= secdata
[IDATA5
].sec
;
1266 iname
->flags
= BSF_GLOBAL
;
1270 iname_lab
= bfd_make_empty_symbol(abfd
);
1272 iname_lab
->name
= head_label
;
1273 iname_lab
->section
= (asection
*)&bfd_und_section
;
1274 iname_lab
->flags
= 0;
1275 iname_lab
->value
= 0;
1278 ptrs
[oidx
++] = iname
;
1279 iname_lab_pp
= ptrs
+ oidx
;
1280 ptrs
[oidx
++] = iname_lab
;
1283 for (i
= 0; i
< NSECS
; i
++)
1285 sinfo
*si
= secdata
+ i
;
1286 asection
*sec
= si
->sec
;
1293 si
->size
= HOW_JTAB_SIZE
;
1294 si
->data
= xmalloc (HOW_JTAB_SIZE
);
1295 memcpy (si
->data
, HOW_JTAB
, HOW_JTAB_SIZE
);
1297 /* add the reloc into idata$5 */
1298 rel
= xmalloc (sizeof (arelent
));
1299 rpp
= xmalloc (sizeof (arelent
*) * 2);
1302 rel
->address
= HOW_JTAB_ROFF
;
1304 rel
->howto
= bfd_reloc_type_lookup (abfd
, BFD_RELOC_32
);
1305 rel
->sym_ptr_ptr
= secdata
[IDATA5
].sympp
;
1306 sec
->orelocation
= rpp
;
1307 sec
->reloc_count
= 1;
1311 /* An idata$4 or idata$5 is one word long, and has an
1315 si
->data
= xmalloc (4);
1320 si
->data
[0] = exp
->ordinal
;
1321 si
->data
[1] = exp
->ordinal
>> 8;
1322 si
->data
[2] = exp
->ordinal
>> 16;
1327 sec
->reloc_count
= 1;
1328 memset (si
->data
, 0, si
->size
);
1329 rel
= xmalloc (sizeof (arelent
));
1330 rpp
= xmalloc (sizeof (arelent
*) * 2);
1335 rel
->howto
= bfd_reloc_type_lookup (abfd
, BFD_RELOC_RVA
);
1336 rel
->sym_ptr_ptr
= secdata
[IDATA6
].sympp
;
1337 sec
->orelocation
= rpp
;
1345 int idx
= exp
->hint
+ 1;
1346 si
->size
= strlen (xlate (exp
->name
)) + 3;
1347 si
->data
= xmalloc (si
->size
);
1348 si
->data
[0] = idx
& 0xff;
1349 si
->data
[1] = idx
>> 8;
1350 strcpy (si
->data
+ 2, xlate (exp
->name
));
1355 si
->data
=xmalloc(4);
1356 memset (si
->data
, 0, si
->size
);
1357 rel
= xmalloc (sizeof (arelent
));
1358 rpp
= xmalloc (sizeof (arelent
*) * 2);
1362 rel
->howto
= bfd_reloc_type_lookup (abfd
, BFD_RELOC_32
);
1363 rel
->sym_ptr_ptr
= iname_lab_pp
;
1364 sec
->orelocation
= rpp
;
1365 sec
->reloc_count
= 1;
1372 /* Size up all the sections */
1373 for (i
= 0; i
< NSECS
; i
++)
1375 sinfo
*si
= secdata
+ i
;
1376 bfd_set_section_size (abfd
, si
->sec
, si
->size
);
1377 bfd_set_section_vma (abfd
, si
->sec
, vma
);
1378 /* vma += si->size;*/
1381 /* Write them out */
1382 for (i
= 0; i
< NSECS
; i
++)
1384 sinfo
*si
= secdata
+ i
;
1385 if (i
== IDATA5
&& no_idata5
)
1388 if (i
== IDATA4
&& no_idata4
)
1391 bfd_set_section_contents (abfd
, si
->sec
,
1396 bfd_set_symtab (abfd
, ptrs
, oidx
);
1398 abfd
= bfd_openr (outname
, HOW_BFD_TARGET
);
1409 FILE * f
= fopen ("dh.s", "w");
1411 fprintf (f
, "%s IMAGE_IMPORT_DESCRIPTOR\n", ASM_C
);
1412 fprintf (f
, "\t.section .idata$2\n");
1414 fprintf(f
,"\t%s\t%s\n", ASM_GLOBAL
,head_label
);
1416 fprintf (f
, "%s:\n", head_label
);
1418 fprintf (f
, "\t%shname%s\t%sPtr to image import by name list\n",
1419 ASM_RVA_BEFORE
, ASM_RVA_AFTER
, ASM_C
);
1421 fprintf (f
, "\t%sthis should be the timestamp, but NT sometimes\n", ASM_C
);
1422 fprintf (f
, "\t%sdoesn't load DLLs when this is set.\n", ASM_C
);
1423 fprintf (f
, "\t%s\t0\t%s loaded time\n", ASM_LONG
, ASM_C
);
1424 fprintf (f
, "\t%s\t0\t%s Forwarder chain\n", ASM_LONG
, ASM_C
);
1425 fprintf (f
, "\t%s__%s_iname%s\t%s imported dll's name\n",
1430 fprintf (f
, "\t%sfthunk%s\t%s pointer to firstthunk\n",
1432 ASM_RVA_AFTER
, ASM_C
);
1434 fprintf (f
, "%sStuff for compatibility\n", ASM_C
);
1438 fprintf (f
, "\t.section\t.idata$5\n");
1439 fprintf (f
, "\t%s\t0\n", ASM_LONG
);
1440 fprintf (f
, "fthunk:\n");
1444 fprintf (f
, "\t.section\t.idata$4\n");
1446 fprintf (f
, "\t%s\t0\n", ASM_LONG
);
1447 fprintf (f
, "\t.section .idata$4\n");
1448 fprintf (f
, "hname:\n");
1452 sprintf (outfile
, "-o dh.o dh.s");
1453 run (as_name
, outfile
);
1455 return bfd_openr ("dh.o", HOW_BFD_TARGET
);
1461 FILE * f
= fopen ("dt.s", "w");
1462 fprintf (f
, "\t.section .idata$7\n");
1463 fprintf (f
, "\t%s\t__%s_iname\n", ASM_GLOBAL
, imp_name_lab
);
1464 fprintf (f
, "__%s_iname:\t%s\t\"%s\"\n",
1465 imp_name_lab
, ASM_TEXT
, dll_name
);
1469 fprintf (f
, "\t.section .idata$4\n");
1470 fprintf (f
, "\t%s\t0\n", ASM_LONG
);
1474 fprintf (f
, "\t.section .idata$5\n");
1475 fprintf (f
, "\t%s\t0\n", ASM_LONG
);
1479 sprintf (outfile
, "-o dt.o dt.s");
1480 run (as_name
, outfile
);
1481 return bfd_openr ("dt.o", HOW_BFD_TARGET
);
1496 outarch
= bfd_openw (imp_name
, HOW_BFD_TARGET
);
1500 fprintf (stderr
, "%s: Can't open .lib file %s\n", program_name
, imp_name
);
1503 bfd_set_format (outarch
, bfd_archive
);
1504 outarch
->has_armap
= 1;
1506 /* Work out a reasonable size of things to put onto one line. */
1510 ar_head
= make_head ();
1511 ar_tail
= make_tail();
1513 for (i
= 0; (exp
= d_exports_lexically
[i
]); i
++)
1515 bfd
*n
= make_one_lib_file (exp
, i
);
1521 /* Now stick them all into the archive */
1523 ar_head
->next
= head
;
1524 ar_tail
->next
= ar_head
;
1527 bfd_set_archive_head (outarch
, head
);
1528 bfd_close (outarch
);
1530 /* Delete all the temp files */
1532 if (dontdeltemps
== 0)
1534 sprintf (outfile
, "dh.o");
1536 sprintf (outfile
, "dh.s");
1538 sprintf (outfile
, "dt.o");
1540 sprintf (outfile
, "dt.s");
1544 if (dontdeltemps
< 2)
1545 for (i
= 0, exp
= d_exports
; exp
; i
++, exp
= exp
->next
)
1547 sprintf (outfile
, "ds%d.o",i
);
1552 /**********************************************************************/
1554 /* Run through the information gathered from the .o files and the
1555 .def file and work out the best stuff */
1561 export_type
*ap
= *(export_type
**) a
;
1562 export_type
*bp
= *(export_type
**) b
;
1563 if (ap
->ordinal
== bp
->ordinal
)
1566 /* unset ordinals go to the bottom */
1567 if (ap
->ordinal
== -1)
1569 if (bp
->ordinal
== -1)
1571 return (ap
->ordinal
- bp
->ordinal
);
1580 export_type
*ap
= *(export_type
**) a
;
1581 export_type
*bp
= *(export_type
**) b
;
1583 return (strcmp (ap
->name
, bp
->name
));
1588 remove_null_names (ptr
)
1593 for (dst
= src
= 0; src
< d_nfuncs
; src
++)
1597 ptr
[dst
] = ptr
[src
];
1610 for (i
= 0; i
< d_nfuncs
; i
++)
1614 printf ("%d %s @ %d %s%s\n",
1615 i
, ptr
[i
]->name
, ptr
[i
]->ordinal
,
1616 ptr
[i
]->noname
? "NONAME " : "",
1617 ptr
[i
]->constant
? "CONSTANT" : "");
1626 process_duplicates (d_export_vec
)
1627 export_type
**d_export_vec
;
1635 /* Remove duplicates */
1636 qsort (d_export_vec
, d_nfuncs
, sizeof (export_type
*), nfunc
);
1638 dtab (d_export_vec
);
1639 for (i
= 0; i
< d_nfuncs
- 1; i
++)
1641 if (strcmp (d_export_vec
[i
]->name
,
1642 d_export_vec
[i
+ 1]->name
) == 0)
1645 export_type
*a
= d_export_vec
[i
];
1646 export_type
*b
= d_export_vec
[i
+ 1];
1650 fprintf (stderr
, "Warning, ignoring duplicate EXPORT %s %d,%d\n",
1654 if (a
->ordinal
!= -1
1655 && b
->ordinal
!= -1)
1658 fprintf (stderr
, "Error, duplicate EXPORT with oridinals %s\n",
1662 /* Merge attributes */
1663 b
->ordinal
= a
->ordinal
> 0 ? a
->ordinal
: b
->ordinal
;
1664 b
->constant
|= a
->constant
;
1665 b
->noname
|= a
->noname
;
1666 d_export_vec
[i
] = 0;
1669 dtab (d_export_vec
);
1670 remove_null_names (d_export_vec
);
1671 dtab (d_export_vec
);
1676 /* Count the names */
1677 for (i
= 0; i
< d_nfuncs
; i
++)
1679 if (!d_export_vec
[i
]->noname
)
1685 fill_ordinals (d_export_vec
)
1686 export_type
**d_export_vec
;
1692 qsort (d_export_vec
, d_nfuncs
, sizeof (export_type
*), pfunc
);
1694 /* fill in the unset ordinals with ones from our range */
1696 ptr
= (char *) malloc (65536);
1698 memset (ptr
, 65536, 0);
1700 /* Mark in our large vector all the numbers that are taken */
1701 for (i
= 0; i
< d_nfuncs
; i
++)
1703 if (d_export_vec
[i
]->ordinal
!= -1)
1705 ptr
[d_export_vec
[i
]->ordinal
] = 1;
1707 lowest
= d_export_vec
[i
]->ordinal
;
1711 for (i
= 0; i
< d_nfuncs
; i
++)
1713 if (d_export_vec
[i
]->ordinal
== -1)
1716 for (j
= lowest
; j
< 65536; j
++)
1720 d_export_vec
[i
]->ordinal
= j
;
1724 for (j
= 1; j
< lowest
; j
++)
1728 d_export_vec
[i
]->ordinal
= j
;
1740 qsort (d_export_vec
, d_nfuncs
, sizeof (export_type
*), pfunc
);
1743 /* Work out the lowest ordinal number */
1744 if (d_export_vec
[0])
1745 d_low_ord
= d_export_vec
[0]->ordinal
;
1748 if (d_export_vec
[d_nfuncs
-1])
1749 d_high_ord
= d_export_vec
[d_nfuncs
-1]->ordinal
;
1753 int alphafunc(av
,bv
)
1757 export_type
**a
= av
;
1758 export_type
**b
= bv
;
1760 return strcmp ((*a
)->name
, (*b
)->name
);
1766 /* First work out the minimum ordinal chosen */
1772 export_type
**d_export_vec
1773 = (export_type
**) xmalloc (sizeof (export_type
*) * d_nfuncs
);
1775 for (i
= 0, exp
= d_exports
; exp
; i
++, exp
= exp
->next
)
1777 d_export_vec
[i
] = exp
;
1780 process_duplicates (d_export_vec
);
1781 fill_ordinals (d_export_vec
);
1783 /* Put back the list in the new order */
1785 for (i
= d_nfuncs
- 1; i
>= 0; i
--)
1787 d_export_vec
[i
]->next
= d_exports
;
1788 d_exports
= d_export_vec
[i
];
1791 /* Build list in alpha order */
1792 d_exports_lexically
= (export_type
**)xmalloc (sizeof(export_type
*)*(d_nfuncs
+1));
1794 for (i
= 0, exp
= d_exports
; exp
; i
++, exp
= exp
->next
)
1796 d_exports_lexically
[i
] = exp
;
1798 d_exports_lexically
[i
] = 0;
1800 qsort (d_exports_lexically
, i
, sizeof (export_type
*), alphafunc
);
1802 /* Fill exp entries with their hint values */
1804 for (i
= 0; i
< d_nfuncs
; i
++)
1806 if (!d_exports_lexically
[i
]->noname
|| show_allnames
)
1807 d_exports_lexically
[i
]->hint
= hint
++;
1817 /**********************************************************************/
1820 usage (file
, status
)
1824 fprintf (file
, "Usage %s <options> <object-files>\n", program_name
);
1825 fprintf (file
, " --machine <machine>\n");
1826 fprintf (file
, " --output-exp <outname> Generate export file.\n");
1827 fprintf (file
, " --output-lib <outname> Generate input library.\n");
1828 fprintf (file
, " --add-indirect Add dll indirects to export file.\n");
1829 fprintf (file
, " --dllname <name> Name of input dll to put into output lib.\n");
1830 fprintf (file
, " --def <deffile> Name input .def file\n");
1831 fprintf (file
, " --output-def <deffile> Name output .def file\n");
1832 fprintf (file
, " --base-file <basefile> Read linker generated base file\n");
1833 fprintf (file
, " --no-idata4 Don't generate idata$4 section\n");
1834 fprintf (file
, " --no-idata5 Don't generate idata$5 section\n");
1835 fprintf (file
, " -v Verbose\n");
1836 fprintf (file
, " -U Add underscores to .lib\n");
1837 fprintf (file
, " -k Kill @<n> from exported names\n");
1838 fprintf (file
, " --as <name> Use <name> for assembler\n");
1839 fprintf (file
, " --nodelete Keep temp files.\n");
1843 #define OPTION_NO_IDATA4 'x'
1844 #define OPTION_NO_IDATA5 'c'
1845 static struct option long_options
[] =
1847 {"nodelete", no_argument
, NULL
, 'n'},
1848 {"dllname", required_argument
, NULL
, 'D'},
1849 {"no-idata4", no_argument
, NULL
, OPTION_NO_IDATA4
},
1850 {"no-idata5", no_argument
, NULL
, OPTION_NO_IDATA5
},
1851 {"output-exp", required_argument
, NULL
, 'e'},
1852 {"output-def", required_argument
, NULL
, 'z'},
1853 {"output-lib", required_argument
, NULL
, 'l'},
1854 {"def", required_argument
, NULL
, 'd'},
1855 {"add-underscore", no_argument
, NULL
, 'U'},
1856 {"killat", no_argument
, NULL
, 'k'},
1857 {"help", no_argument
, NULL
, 'h'},
1858 {"machine", required_argument
, NULL
, 'm'},
1859 {"add-indirect", no_argument
, NULL
, 'a'},
1860 {"base-file", required_argument
, NULL
, 'b'},
1861 {"as", required_argument
, NULL
, 'S'},
1875 program_name
= av
[0];
1878 while ((c
= getopt_long (ac
, av
, "xcz:S:R:A:puaD:l:e:nkvbUh?m:yd:", long_options
, 0))
1883 case OPTION_NO_IDATA4
:
1886 case OPTION_NO_IDATA5
:
1893 /* ignored for compatibility */
1900 output_def
= fopen (optarg
, "w");
1937 base_file
= fopen (optarg
, "r");
1940 fprintf (stderr
, "%s: Unable to open base-file %s\n",
1952 for (i
= 0; mtable
[i
].type
; i
++)
1954 if (strcmp (mtable
[i
].type
, mname
) == 0)
1958 if (!mtable
[i
].type
)
1960 fprintf (stderr
, "Machine not supported\n");
1966 if (!dll_name
&& exp_name
)
1968 char len
= strlen (exp_name
) + 5;
1969 dll_name
= xmalloc (len
);
1970 strcpy (dll_name
, exp_name
);
1971 strcat (dll_name
, ".dll");
1976 process_def_file (def_file
);
1981 firstarg
= av
[optind
];
1982 scan_obj_file (av
[optind
]);
1993 /* Make imp_name safe for use as a label. */
1995 imp_name_lab
= strdup (imp_name
);
1996 for (p
= imp_name_lab
; *p
; *p
++)
1998 if (!isalpha (*p
) && !isdigit (*p
))
2001 head_label
= make_label("_head_", imp_name_lab
);