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 /* .idata section description
165 The .idata section is the import table. It is a collection of several
166 subsections used to keep the pieces for each dll together: .idata$[234567].
167 IE: Each dll's .idata$2's are catenated together, each .idata$3's, etc.
169 .idata$2 = Import Directory Table
170 = array of IMAGE_IMPORT_DESCRIPTOR's.
171 There is one for each dll imported from plus a trailing null copy.
173 DWORD Characteristics; - pointer to .idata$4
174 DWORD TimeDateStamp; - currently always 0
175 DWORD ForwarderChain; - currently always 0
176 DWORD Name; - pointer to dll's name
177 PIMAGE_THUNK_DATA FirstThunk; - pointer to .idata$5
179 .idata$3 = ppc's way of null terminating .idata$2. Jeepers creepers,
180 can we have some consistency here???
182 .idata$4 = Import Lookup Table
183 = array of array of pointers to hint name table.
184 There is one for each dll being imported from, and each dll's set is
185 terminated by a trailing NULL.
187 .idata$5 = Import Address Table
188 = array of array of pointers to hint name table.
189 There is one for each dll being imported from, and each dll's set is
190 terminated by a trailing NULL.
191 Initially, this table is identical to the Import Lookup Table. However,
192 at load time, the loader overwrites the entries with the address of the
195 .idata$6 = Hint Name Table
196 = Array of { short, asciz } entries, one for each imported function.
197 The `short' is the function's ordinal number.
199 .idata$7 = dll name (eg: "kernel32.dll"). (.idata$6 for ppc)
202 #define PAGE_SIZE 4096
203 #define PAGE_MASK (-PAGE_SIZE)
205 #include "libiberty.h"
208 #include "demangle.h"
210 #ifdef HAVE_SYS_WAIT_H
211 #include <sys/wait.h>
214 #define WIFEXITED(w) (((w)&0377) == 0)
217 #define WIFSIGNALED(w) (((w)&0377) != 0177 && ((w)&~0377) == 0)
220 #define WTERMSIG(w) ((w) & 0177)
223 #define WEXITSTATUS(w) (((w) >> 8) & 0377)
229 char *as_name
= "as";
231 static int no_idata4
;
232 static int no_idata5
;
233 static char *exp_name
;
234 static char *imp_name
;
235 static char *head_label
;
236 static char *imp_name_lab
;
237 static char *dll_name
;
239 static int add_indirect
= 0;
240 static int add_underscore
= 0;
241 static int dontdeltemps
= 0;
245 static char *def_file
;
247 static char *program_name
;
258 static char *mname
= "arm";
262 static char *mname
= "i386";
266 static char *mname
= "ppc";
269 #define PATHMAX 250 /* What's the right name for this ? */
271 /* This bit of assemly does jmp * ....
272 s set how_jtab_roff to mark where the 32bit abs branch should go */
273 unsigned char i386_jtab
[] = { 0xff, 0x25, 0x00, 0x00, 0x00, 0x00, 0x90, 0x90};
276 unsigned char arm_jtab
[] = { 0x00, 0xc0, 0x9f, 0xe5,
277 0x00, 0xf0, 0x9c, 0xe5,
280 /* This is the glue sequence for PowerPC PE. There is a */
281 /* tocrel16-tocdefn reloc against the first instruction. */
282 /* We also need a IMGLUE reloc against the glue function */
283 /* to restore the toc saved by the third instruction in */
285 unsigned char ppc_jtab
[] =
287 0x00, 0x00, 0x62, 0x81, /* lwz r11,0(r2) */
288 /* Reloc TOCREL16 __imp_xxx */
289 0x00, 0x00, 0x8B, 0x81, /* lwz r12,0(r11) */
290 0x04, 0x00, 0x41, 0x90, /* stw r2,4(r1) */
291 0xA6, 0x03, 0x89, 0x7D, /* mtctr r12 */
292 0x04, 0x00, 0x4B, 0x80, /* lwz r2,4(r11) */
293 0x20, 0x04, 0x80, 0x4E /* bctr */
296 /* the glue instruction, picks up the toc from the stw in */
297 /* the above code: "lwz r2,4(r1)" */
298 bfd_vma ppc_glue_insn
= 0x80410004;
301 char outfile
[PATHMAX
];
313 char *how_align_short
;
314 char *how_align_long
;
315 char *how_bfd_target
;
316 enum bfd_architecture how_bfd_arch
;
317 unsigned char *how_jtab
;
318 int how_jtab_size
; /* size of the jtab entry */
319 int how_jtab_roff
; /* offset into it for the ind 32 reloc into idata 5 */
326 "arm", ".byte", ".short", ".long", ".asciz", "@",
327 "ldr\tip,[pc]\n\tldr\tpc,[ip]\n\t.long",
328 ".global", ".space", ".align\t2",".align\t4","pe-arm-little", bfd_arch_arm
,
329 arm_jtab
, sizeof(arm_jtab
),8
334 "i386", ".byte", ".short", ".long", ".asciz", "#", "jmp *", ".global", ".space", ".align\t2",".align\t4","pe-i386",bfd_arch_i386
,
335 i386_jtab
,sizeof(i386_jtab
),2,
340 "ppc", ".byte", ".short", ".long", ".asciz", "#", "jmp *", ".global", ".space", ".align\t2",".align\t4","pe-powerpcle",bfd_arch_powerpc
,
341 ppc_jtab
,sizeof(ppc_jtab
),0,
395 #define ASM_BYTE mtable[machine].how_byte
396 #define ASM_SHORT mtable[machine].how_short
397 #define ASM_LONG mtable[machine].how_long
398 #define ASM_TEXT mtable[machine].how_asciz
399 #define ASM_C mtable[machine].how_comment
400 #define ASM_JUMP mtable[machine].how_jump
401 #define ASM_GLOBAL mtable[machine].how_global
402 #define ASM_SPACE mtable[machine].how_space
403 #define ASM_ALIGN_SHORT mtable[machine].how_align_short
404 #define ASM_RVA_BEFORE rvabefore(machine)
405 #define ASM_RVA_AFTER rvaafter(machine)
406 #define ASM_PREFIX asm_prefix(machine)
407 #define ASM_ALIGN_LONG mtable[machine].how_align_long
408 #define HOW_BFD_TARGET 0 /* always default*/
409 #define HOW_BFD_ARCH mtable[machine].how_bfd_arch
410 #define HOW_JTAB mtable[machine].how_jtab
411 #define HOW_JTAB_SIZE mtable[machine].how_jtab_size
412 #define HOW_JTAB_ROFF mtable[machine].how_jtab_roff
416 FILE *yyin
; /* communications with flex */
417 extern int linenumber
;
419 process_def_file (name
)
422 FILE *f
= fopen (name
, FOPEN_RT
);
425 fprintf (stderr
, "%s: Can't open def file %s\n", program_name
, name
);
434 /**********************************************************************/
436 /* Communications with the parser */
446 typedef struct export
458 static char *d_name
; /* Arg to NAME or LIBRARY */
459 static int d_nfuncs
; /* Number of functions exported */
460 static int d_named_nfuncs
; /* Number of named functions exported */
461 static int d_low_ord
; /* Lowest ordinal index */
462 static int d_high_ord
; /* Highest ordinal index */
463 static export_type
*d_exports
; /*list of exported functions */
464 static export_type
**d_exports_lexically
; /* vector of exported functions in alpha order */
465 static dlist_type
*d_list
; /* Descriptions */
466 static dlist_type
*a_list
; /* Stuff to go in directives */
474 fprintf (stderr
, "%s: Syntax error in def file %s:%d\n",
475 program_name
, def_file
, linenumber
);
480 def_exports (name
, internal_name
, ordinal
, noname
, constant
)
487 struct export
*p
= (struct export
*) xmalloc (sizeof (*p
));
490 p
->internal_name
= internal_name
? internal_name
: name
;
491 p
->ordinal
= ordinal
;
492 p
->constant
= constant
;
501 def_name (name
, base
)
506 fprintf (stderr
, "%s NAME %s base %x\n", program_name
, name
, base
);
509 fprintf (stderr
, "Can't have LIBRARY and NAME\n");
516 def_library (name
, base
)
521 printf ("%s: LIBRARY %s base %x\n", program_name
, name
, base
);
524 fprintf (stderr
, "%s: Can't have LIBRARY and NAME\n", program_name
);
531 def_description (desc
)
534 dlist_type
*d
= (dlist_type
*) xmalloc (sizeof (dlist_type
));
535 d
->text
= strdup (desc
);
544 dlist_type
*d
= (dlist_type
*) xmalloc (sizeof (dlist_type
));
545 d
->text
= strdup (dir
);
551 def_stacksize (reserve
, commit
)
557 sprintf (b
, "-stack 0x%x,0x%x ", reserve
, commit
);
559 sprintf (b
, "-stack 0x%x ", reserve
);
560 new_directive (strdup (b
));
564 def_heapsize (reserve
, commit
)
570 sprintf (b
, "-heap 0x%x,0x%x ", reserve
, commit
);
572 sprintf (b
, "-heap 0x%x ", reserve
);
573 new_directive (strdup (b
));
578 def_import (internal
, module
, entry
)
584 fprintf (stderr
, "%s: IMPORTS are ignored", program_name
);
588 def_version (major
, minor
)
592 printf ("VERSION %d.%d\n", major
, minor
);
597 def_section (name
, attr
)
614 sprintf (buf
, "-attr %s %s", name
, atts
);
615 new_directive (strdup (buf
));
622 def_section ("CODE", attr
);
629 def_section ("DATA", attr
);
633 /**********************************************************************/
644 extern char **environ
;
646 fprintf (stderr
, "%s %s\n", what
, args
);
650 for (s
= args
; *s
; s
++)
654 argv
= alloca (sizeof (char *) * (i
+ 3));
661 while (*s
!= ' ' && *s
!= 0)
675 fprintf (stderr
, "%s: can't exec %s\n", program_name
, what
);
681 fprintf (stderr
, "%s: vfork failed, %d\n", program_name
, errno
);
687 waitpid (pid
, &status
, 0);
690 if (WIFSIGNALED (status
))
692 fprintf (stderr
, "%s: %s %s terminated with signal %d\n",
693 program_name
, what
, args
, WTERMSIG (status
));
697 if (WIFEXITED (status
))
699 fprintf (stderr
, "%s: %s %s terminated with exit status %d\n",
700 program_name
, what
, args
, WEXITSTATUS (status
));
707 /* read in and block out the base relocations */
719 scan_open_obj_file (abfd
)
722 /* Look for .drectve's */
723 asection
*s
= bfd_get_section_by_name (abfd
, ".drectve");
726 int size
= bfd_get_section_size_before_reloc (s
);
727 char *buf
= xmalloc (size
);
730 bfd_get_section_contents (abfd
, s
, buf
, 0, size
);
732 fprintf (stderr
, "%s: Sucking in info from %s\n",
734 bfd_get_filename (abfd
));
736 /* Search for -export: strings */
742 && strncmp (p
, "-export:", 8) == 0)
748 while (*p
!= ' ' && *p
!= '-' && p
< e
)
750 c
= xmalloc (p
- name
+ 1);
751 memcpy (c
, name
, p
- name
);
753 def_exports (c
, 0, -1, 0);
764 fprintf (stderr
, "%s: Done readin\n",
771 scan_obj_file (filename
)
774 bfd
*f
= bfd_openr (filename
, 0);
778 fprintf (stderr
, "%s: Unable to open object file %s\n",
783 if (bfd_check_format (f
, bfd_archive
))
785 bfd
*arfile
= bfd_openr_next_archived_file (f
, 0);
788 if (bfd_check_format (arfile
, bfd_object
))
789 scan_open_obj_file (arfile
);
791 arfile
= bfd_openr_next_archived_file (f
, arfile
);
794 else if (bfd_check_format (f
, bfd_object
))
796 scan_open_obj_file (f
);
802 /**********************************************************************/
812 fprintf (f
, "%s ", ASM_C
);
813 for (i
= 0; oav
[i
]; i
++)
814 fprintf (f
, "%s ", oav
[i
]);
816 for (i
= 0, exp
= d_exports
; exp
; i
++, exp
= exp
->next
)
818 fprintf (f
, "%s %d = %s %s @ %d %s%s\n",
824 exp
->noname
? "NONAME " : "",
825 exp
->constant
? "CONSTANT" : "");
828 /* Generate the .exp file */
841 flush_page (f
, need
, page_addr
, on_page
)
849 /* Flush this page */
850 fprintf (f
, "\t%s\t0x%08x\t%s Starting RVA for chunk\n",
854 fprintf (f
, "\t%s\t0x%x\t%s Size of block\n",
856 (on_page
* 2) + (on_page
& 1) * 2 + 8,
858 for (i
= 0; i
< on_page
; i
++)
860 fprintf (f
, "\t%s\t0x%x\n", ASM_SHORT
, (need
[i
] - page_addr
) | 0x3000);
864 fprintf (f
, "\t%s\t0x%x\n", ASM_SHORT
, 0 | 0x0000);
875 fprintf (output_def
, ";");
876 for (i
= 0; oav
[i
]; i
++)
877 fprintf (output_def
, " %s", oav
[i
]);
879 fprintf (output_def
, "\nEXPORTS\n");
881 for (i
= 0, exp
= d_exports
; exp
; i
++, exp
= exp
->next
)
883 char *quote
= strchr (exp
->name
, '.') ? "\"" : "";
884 fprintf (output_def
, "\t%s%s%s @ %d%s ; %s\n",
889 exp
->noname
? " NONAME" : "",
890 cplus_demangle (exp
->internal_name
, DMGL_ANSI
| DMGL_PARAMS
));
902 sprintf (outfile
, "t%s", exp_name
);
905 fprintf (stderr
, "%s: Generate exp file %s\n",
906 program_name
, exp_name
);
908 f
= fopen (outfile
, FOPEN_WT
);
911 fprintf (stderr
, "%s: Unable to open output file %s\n", program_name
, outfile
);
916 fprintf (stderr
, "%s: Opened file %s\n",
917 program_name
, outfile
);
923 fprintf (f
, "\t.section .edata\n\n");
924 fprintf (f
, "\t%s 0 %s Allways 0\n", ASM_LONG
, ASM_C
);
925 fprintf (f
, "\t%s 0x%x %s Time and date\n", ASM_LONG
, time(0),ASM_C
);
926 fprintf (f
, "\t%s 0 %s Major and Minor version\n", ASM_LONG
, ASM_C
);
927 fprintf (f
, "\t%sname%s %s Ptr to name of dll\n", ASM_RVA_BEFORE
, ASM_RVA_AFTER
, ASM_C
);
928 fprintf (f
, "\t%s %d %s Starting ordinal of exports\n", ASM_LONG
, d_low_ord
, ASM_C
);
931 fprintf (f
, "\t%s %d %s Number of functions\n", ASM_LONG
, d_high_ord
- d_low_ord
+ 1, ASM_C
);
932 fprintf(f
,"\t%s named funcs %d, low ord %d, high ord %d\n",
934 d_named_nfuncs
, d_low_ord
, d_high_ord
);
935 fprintf (f
, "\t%s %d %s Number of names\n", ASM_LONG
,
936 show_allnames
? d_high_ord
- d_low_ord
+ 1 : d_named_nfuncs
, ASM_C
);
937 fprintf (f
, "\t%safuncs%s %s Address of functions\n", ASM_RVA_BEFORE
, ASM_RVA_AFTER
, ASM_C
);
939 fprintf (f
, "\t%sanames%s %s Address of Name Pointer Table\n",
940 ASM_RVA_BEFORE
, ASM_RVA_AFTER
, ASM_C
);
942 fprintf (f
, "\t%sanords%s %s Address of ordinals\n", ASM_RVA_BEFORE
, ASM_RVA_AFTER
, ASM_C
);
944 fprintf (f
, "name: %s \"%s\"\n", ASM_TEXT
, dll_name
);
947 fprintf(f
,"%s Export address Table\n", ASM_C
);
948 fprintf(f
,"\t%s\n", ASM_ALIGN_LONG
);
949 fprintf (f
, "afuncs:\n");
952 for (exp
= d_exports
; exp
; exp
= exp
->next
)
954 if (exp
->ordinal
!= i
)
957 fprintf (f
, "\t%s\t%d\t%s %d..%d missing\n",
959 (exp
->ordinal
- i
) * 4,
961 i
, exp
->ordinal
- 1);
964 while (i
< exp
->ordinal
)
966 fprintf(f
,"\t%s\t0\n", ASM_LONG
);
970 fprintf (f
, "\t%s%s%s%s\t%s %d\n", ASM_RVA_BEFORE
,
972 exp
->internal_name
, ASM_RVA_AFTER
, ASM_C
, exp
->ordinal
);
976 fprintf (f
,"%s Export Name Pointer Table\n", ASM_C
);
977 fprintf (f
, "anames:\n");
979 for (i
= 0; (exp
= d_exports_lexically
[i
]); i
++)
981 if (!exp
->noname
|| show_allnames
)
982 fprintf (f
, "\t%sn%d%s\n", ASM_RVA_BEFORE
, exp
->ordinal
, ASM_RVA_AFTER
);
985 fprintf (f
,"%s Export Oridinal Table\n", ASM_C
);
986 fprintf (f
, "anords:\n");
987 for (i
= 0; (exp
= d_exports_lexically
[i
]); i
++)
989 if (!exp
->noname
|| show_allnames
)
990 fprintf (f
, "\t%s %d\n", ASM_SHORT
, exp
->ordinal
- d_low_ord
);
993 fprintf(f
,"%s Export Name Table\n", ASM_C
);
994 for (i
= 0; (exp
= d_exports_lexically
[i
]); i
++)
995 if (!exp
->noname
|| show_allnames
)
996 fprintf (f
, "n%d: %s \"%s\"\n", exp
->ordinal
, ASM_TEXT
, exp
->name
);
1000 fprintf (f
, "\t.section .drectve\n");
1001 for (dl
= a_list
; dl
; dl
= dl
->next
)
1003 fprintf (f
, "\t%s\t\"%s\"\n", ASM_TEXT
, dl
->text
);
1008 fprintf (f
, "\t.section .rdata\n");
1009 for (dl
= d_list
; dl
; dl
= dl
->next
)
1013 /* We dont output as ascii 'cause there can
1014 be quote characters in the string */
1017 for (p
= dl
->text
; *p
; p
++)
1020 fprintf (f
, "\t%s\t", ASM_BYTE
);
1023 fprintf (f
, "%d", *p
);
1026 fprintf (f
, ",0\n");
1040 /* Add to the output file a way of getting to the exported names
1041 without using the import library. */
1044 fprintf (f
, "\t.section\t.rdata\n");
1045 for (i
= 0, exp
= d_exports
; exp
; i
++, exp
= exp
->next
)
1046 if (!exp
->noname
|| show_allnames
)
1048 fprintf (f
, "\t%s\t__imp_%s\n", ASM_GLOBAL
, exp
->name
);
1049 fprintf (f
, "__imp_%s:\n", exp
->name
);
1050 fprintf (f
, "\t%s\t%s\n", ASM_LONG
, exp
->name
);
1054 /* Dump the reloc section if a base file is provided */
1058 long need
[PAGE_SIZE
];
1065 fprintf (f
, "\t.section\t.init\n");
1066 fprintf (f
, "lab:\n");
1068 fseek (base_file
, 0, SEEK_END
);
1069 numbytes
= ftell (base_file
);
1070 fseek (base_file
, 0, SEEK_SET
);
1071 copy
= malloc (numbytes
);
1072 fread (copy
, 1, numbytes
, base_file
);
1073 num_entries
= numbytes
/ sizeof (long);
1076 fprintf (f
, "\t.section\t.reloc\n");
1083 qsort (copy
, num_entries
, sizeof (long), sfunc
);
1084 /* Delete duplcates */
1085 for (src
= 0; src
< num_entries
; src
++)
1087 if (last
!= copy
[src
])
1088 last
= copy
[dst
++] = copy
[src
];
1092 page_addr
= addr
& PAGE_MASK
; /* work out the page addr */
1094 for (j
= 0; j
< num_entries
; j
++)
1097 if ((addr
& PAGE_MASK
) != page_addr
)
1099 flush_page (f
, need
, page_addr
, on_page
);
1101 page_addr
= addr
& PAGE_MASK
;
1103 need
[on_page
++] = addr
;
1105 flush_page (f
, need
, page_addr
, on_page
);
1107 /* fprintf (f, "\t%s\t0,0\t%s End\n", ASM_LONG, ASM_C);*/
1113 /* assemble the file */
1114 sprintf (outfile
, "-o %s t%s", exp_name
, exp_name
);
1115 run (as_name
, outfile
);
1116 if (dontdeltemps
== 0)
1118 sprintf (outfile
, "t%s", exp_name
);
1128 char *copy
= malloc (strlen (name
) + 2);
1130 strcpy (copy
+ 1, name
);
1137 p
= strchr (name
, '@');
1144 /**********************************************************************/
1146 static void dump_iat (f
, exp
)
1150 if (exp
->noname
&& !show_allnames
)
1152 fprintf (f
, "\t%s\t0x%08x\n",
1154 exp
->ordinal
| 0x80000000); /* hint or orindal ?? */
1158 fprintf (f
, "\t%sID%d%s\n", ASM_RVA_BEFORE
,
1176 unsigned char *data
;
1195 static sinfo secdata
[NSECS
] =
1197 { TEXT
, ".text", SEC_CODE
| SEC_HAS_CONTENTS
, 3},
1198 { DATA
, ".data", SEC_DATA
, 2},
1199 { BSS
, ".bss", 0, 2},
1200 { IDATA7
, ".idata$7", SEC_HAS_CONTENTS
, 2},
1201 { IDATA5
, ".idata$5", SEC_HAS_CONTENTS
, 2},
1202 { IDATA4
, ".idata$4", SEC_HAS_CONTENTS
, 2},
1203 { IDATA6
, ".idata$6", SEC_HAS_CONTENTS
, 1}
1208 /* Sections numbered to make the order the same as other PowerPC NT */
1209 /* compilers. This also keeps funny alignment thingies from happening. */
1222 static sinfo secdata
[NSECS
] =
1224 { TEXT
, ".text", SEC_CODE
| SEC_HAS_CONTENTS
, 3},
1225 { PDATA
, ".pdata", SEC_HAS_CONTENTS
, 2},
1226 { RDATA
, ".rdata", SEC_HAS_CONTENTS
, 2},
1227 { IDATA5
, ".idata$5", SEC_HAS_CONTENTS
, 2},
1228 { IDATA4
, ".idata$4", SEC_HAS_CONTENTS
, 2},
1229 { IDATA6
, ".idata$6", SEC_HAS_CONTENTS
, 1},
1230 { IDATA7
, ".idata$7", SEC_HAS_CONTENTS
, 2},
1231 { DATA
, ".data", SEC_DATA
, 2},
1232 { BSS
, ".bss", 0, 2}
1238 This is what we're trying to make
1241 .global _GetFileVersionInfoSizeW@8
1242 .global __imp_GetFileVersionInfoSizeW@8
1243 _GetFileVersionInfoSizeW@8:
1244 jmp * __imp_GetFileVersionInfoSizeW@8
1245 .section .idata$7 # To force loading of head
1246 .long __version_a_head
1247 # Import Address Table
1249 __imp_GetFileVersionInfoSizeW@8:
1252 # Import Lookup Table
1258 .asciz "GetFileVersionInfoSizeW"
1261 For the PowerPC, here's the variation on the above scheme:
1263 # Rather than a simple "jmp *", the code to get to the dll function
1266 lwz r11,[tocv]__imp_function_name(r2)
1267 # RELOC: 00000000 TOCREL16,TOCDEFN __imp_function_name
1276 make_label (prefix
, name
)
1280 int len
= strlen (ASM_PREFIX
) + strlen (prefix
) + strlen (name
);
1281 char *copy
= xmalloc (len
+1 );
1282 strcpy (copy
, ASM_PREFIX
);
1283 strcat (copy
, prefix
);
1284 strcat (copy
, name
);
1289 make_one_lib_file (exp
, i
)
1297 sprintf (outfile
, "%ss%d.s", prefix
, i
);
1298 f
= fopen (outfile
, FOPEN_WT
);
1299 fprintf (f
, "\t.text\n");
1300 fprintf (f
, "\t%s\t%s%s\n", ASM_GLOBAL
, ASM_PREFIX
, exp
->name
);
1301 fprintf (f
, "\t%s\t__imp_%s\n", ASM_GLOBAL
, exp
->name
);
1302 fprintf (f
, "%s%s:\n\t%s\t__imp_%s\n", ASM_PREFIX
,
1303 exp
->name
, ASM_JUMP
, exp
->name
);
1305 fprintf (f
, "\t.section\t.idata$7\t%s To force loading of head\n", ASM_C
);
1306 fprintf (f
, "\t%s\t%s\n", ASM_LONG
, head_label
);
1309 fprintf (f
,"%s Import Address Table\n", ASM_C
);
1311 fprintf (f
, "\t.section .idata$5\n");
1312 fprintf (f
, "__imp_%s:\n", exp
->name
);
1316 fprintf (f
, "\n%s Import Lookup Table\n", ASM_C
);
1317 fprintf (f
, "\t.section .idata$4\n");
1321 if(!exp
->noname
|| show_allnames
)
1323 fprintf (f
, "%s Hint/Name table\n", ASM_C
);
1324 fprintf (f
, "\t.section .idata$6\n");
1325 fprintf (f
, "ID%d:\t%s\t%d\n", exp
->ordinal
, ASM_SHORT
, exp
->hint
);
1326 fprintf (f
, "\t%s\t\"%s\"\n", ASM_TEXT
, xlate (exp
->name
));
1332 sprintf (outfile
, "-o %ss%d.o %ss%d.s", prefix
, i
, prefix
, i
);
1334 run (as_name
, outfile
);
1345 asymbol
**iname_lab_pp
;
1348 /* Extra Symbols for PPC */
1355 asymbol
*function_name
; /* ".." functionName */
1357 asymbol
*toc_symbol
; /* The .toc symbol */
1360 /* one symbol for each section, 2 extra + a null */
1361 asymbol
*ptrs
[NSECS
+3+EXTRA
+1];
1363 char *outname
= xmalloc (10);
1365 sprintf (outname
, "ds%d.o", i
);
1366 abfd
= bfd_openw (outname
, HOW_BFD_TARGET
);
1369 fprintf (stderr
, "%s: bfd_open failed open output file %s\n",
1370 program_name
, outname
);
1374 bfd_set_format (abfd
, bfd_object
);
1375 bfd_set_arch_mach (abfd
, HOW_BFD_ARCH
, 0);
1378 /* First make symbols for the sections */
1379 for (i
= 0; i
< NSECS
; i
++)
1381 sinfo
*si
= secdata
+ i
;
1384 si
->sec
= bfd_make_section_old_way (abfd
, si
->name
);
1385 bfd_set_section_flags (abfd
,
1389 bfd_set_section_alignment(abfd
, si
->sec
, si
->align
);
1390 si
->sec
->output_section
= si
->sec
;
1391 si
->sym
= bfd_make_empty_symbol(abfd
);
1392 si
->sym
->name
= si
->sec
->name
;
1393 si
->sym
->section
= si
->sec
;
1394 si
->sym
->flags
= BSF_LOCAL
;
1396 ptrs
[oidx
] = si
->sym
;
1397 si
->sympp
= ptrs
+ oidx
;
1402 exp_label
= bfd_make_empty_symbol(abfd
);
1403 exp_label
->name
= make_label ("",exp
->name
);
1405 /* On PowerPC, the function name points to a descriptor in the
1406 rdata section, the first element of which is a pointer to the
1407 code (..function_name), and the second points to the .toc
1409 if (machine
== MPPC
)
1410 exp_label
->section
= secdata
[RDATA
].sec
;
1412 exp_label
->section
= secdata
[TEXT
].sec
;
1414 exp_label
->flags
= BSF_GLOBAL
;
1415 exp_label
->value
= 0;
1417 ptrs
[oidx
++] = exp_label
;
1419 iname
= bfd_make_empty_symbol(abfd
);
1420 iname
->name
= make_label ("__imp_", exp
->name
);
1421 iname
->section
= secdata
[IDATA5
].sec
;
1422 iname
->flags
= BSF_GLOBAL
;
1426 iname_lab
= bfd_make_empty_symbol(abfd
);
1428 iname_lab
->name
= head_label
;
1429 iname_lab
->section
= (asection
*)&bfd_und_section
;
1430 iname_lab
->flags
= 0;
1431 iname_lab
->value
= 0;
1434 iname_pp
= ptrs
+ oidx
;
1435 ptrs
[oidx
++] = iname
;
1437 iname_lab_pp
= ptrs
+ oidx
;
1438 ptrs
[oidx
++] = iname_lab
;
1441 /* The symbol refering to the code (.text) */
1442 function_name
= bfd_make_empty_symbol(abfd
);
1443 function_name
->name
= make_label ("..", exp
->name
);
1444 function_name
->section
= secdata
[TEXT
].sec
;
1445 function_name
->flags
= BSF_GLOBAL
;
1446 function_name
->value
= 0;
1448 fn_pp
= ptrs
+ oidx
;
1449 ptrs
[oidx
++] = function_name
;
1451 /* The .toc symbol */
1452 toc_symbol
= bfd_make_empty_symbol(abfd
);
1453 toc_symbol
->name
= make_label (".", "toc");
1454 toc_symbol
->section
= (asection
*)&bfd_und_section
;
1455 toc_symbol
->flags
= BSF_GLOBAL
;
1456 toc_symbol
->value
= 0;
1458 toc_pp
= ptrs
+ oidx
;
1459 ptrs
[oidx
++] = toc_symbol
;
1464 for (i
= 0; i
< NSECS
; i
++)
1466 sinfo
*si
= secdata
+ i
;
1467 asection
*sec
= si
->sec
;
1474 si
->size
= HOW_JTAB_SIZE
;
1475 si
->data
= xmalloc (HOW_JTAB_SIZE
);
1476 memcpy (si
->data
, HOW_JTAB
, HOW_JTAB_SIZE
);
1478 /* add the reloc into idata$5 */
1479 rel
= xmalloc (sizeof (arelent
));
1480 rpp
= xmalloc (sizeof (arelent
*) * 2);
1483 rel
->address
= HOW_JTAB_ROFF
;
1486 if (machine
== MPPC
)
1488 rel
->howto
= bfd_reloc_type_lookup (abfd
,
1489 BFD_RELOC_16_GOTOFF
);
1490 rel
->sym_ptr_ptr
= iname_pp
;
1494 rel
->howto
= bfd_reloc_type_lookup (abfd
, BFD_RELOC_32
);
1495 rel
->sym_ptr_ptr
= secdata
[IDATA5
].sympp
;
1497 sec
->orelocation
= rpp
;
1498 sec
->reloc_count
= 1;
1502 /* An idata$4 or idata$5 is one word long, and has an
1505 si
->data
= xmalloc (4);
1510 si
->data
[0] = exp
->ordinal
;
1511 si
->data
[1] = exp
->ordinal
>> 8;
1512 si
->data
[2] = exp
->ordinal
>> 16;
1517 sec
->reloc_count
= 1;
1518 memset (si
->data
, 0, si
->size
);
1519 rel
= xmalloc (sizeof (arelent
));
1520 rpp
= xmalloc (sizeof (arelent
*) * 2);
1525 rel
->howto
= bfd_reloc_type_lookup (abfd
, BFD_RELOC_RVA
);
1526 rel
->sym_ptr_ptr
= secdata
[IDATA6
].sympp
;
1527 sec
->orelocation
= rpp
;
1535 int idx
= exp
->hint
+ 1;
1536 si
->size
= strlen (xlate (exp
->name
)) + 3;
1537 si
->data
= xmalloc (si
->size
);
1538 si
->data
[0] = idx
& 0xff;
1539 si
->data
[1] = idx
>> 8;
1540 strcpy (si
->data
+ 2, xlate (exp
->name
));
1545 si
->data
=xmalloc(4);
1546 memset (si
->data
, 0, si
->size
);
1547 rel
= xmalloc (sizeof (arelent
));
1548 rpp
= xmalloc (sizeof (arelent
*) * 2);
1552 rel
->howto
= bfd_reloc_type_lookup (abfd
, BFD_RELOC_32
);
1553 rel
->sym_ptr_ptr
= iname_lab_pp
;
1554 sec
->orelocation
= rpp
;
1555 sec
->reloc_count
= 1;
1560 /* The .pdata section is 5 words long. */
1561 /* Think of it as: */
1564 /* bfd_vma BeginAddress, [0x00] */
1565 /* EndAddress, [0x04] */
1566 /* ExceptionHandler, [0x08] */
1567 /* HandlerData, [0x0c] */
1568 /* PrologEndAddress; [0x10] */
1571 /* So this pdata section setups up this as a glue linkage to
1572 a dll routine. There are a number of house keeping things
1575 1. In the name of glue trickery, the ADDR32 relocs for 0,
1576 4, and 0x10 are set to point to the same place:
1578 2. There is one more reloc needed in the pdata section.
1579 The actual glue instruction to restore the toc on
1580 return is saved as the offset in an IMGLUE reloc.
1581 So we need a total of four relocs for this section.
1583 3. Lastly, the HandlerData field is set to 0x03, to indicate
1584 that this is a glue routine.
1586 arelent
*imglue
, *ba_rel
, *ea_rel
, *pea_rel
;
1588 /* alignment must be set to 2**2 or you get extra stuff */
1589 bfd_set_section_alignment(abfd
, sec
, 2);
1592 si
->data
=xmalloc(4 * 5);
1593 memset (si
->data
, 0, si
->size
);
1594 rpp
= xmalloc (sizeof (arelent
*) * 5);
1595 rpp
[0] = imglue
= xmalloc (sizeof (arelent
));
1596 rpp
[1] = ba_rel
= xmalloc (sizeof (arelent
));
1597 rpp
[2] = ea_rel
= xmalloc (sizeof (arelent
));
1598 rpp
[3] = pea_rel
= xmalloc (sizeof (arelent
));
1601 /* stick the toc reload instruction in the glue reloc */
1602 bfd_put_32(abfd
, ppc_glue_insn
, (char *) &imglue
->address
);
1605 imglue
->howto
= bfd_reloc_type_lookup (abfd
,
1606 BFD_RELOC_32_GOTOFF
);
1607 imglue
->sym_ptr_ptr
= fn_pp
;
1609 ba_rel
->address
= 0;
1611 ba_rel
->howto
= bfd_reloc_type_lookup (abfd
, BFD_RELOC_32
);
1612 ba_rel
->sym_ptr_ptr
= fn_pp
;
1614 bfd_put_32(abfd
, 0x18, si
->data
+ 0x04);
1615 ea_rel
->address
= 4;
1617 ea_rel
->howto
= bfd_reloc_type_lookup (abfd
, BFD_RELOC_32
);
1618 ea_rel
->sym_ptr_ptr
= fn_pp
;
1620 /* mark it as glue */
1621 bfd_put_32(abfd
, 0x03, si
->data
+ 0x0c);
1623 /* mark the prolog end address */
1624 bfd_put_32(abfd
, 0x0D, si
->data
+ 0x10);
1625 pea_rel
->address
= 0x10;
1626 pea_rel
->addend
= 0;
1627 pea_rel
->howto
= bfd_reloc_type_lookup (abfd
, BFD_RELOC_32
);
1628 pea_rel
->sym_ptr_ptr
= fn_pp
;
1630 sec
->orelocation
= rpp
;
1631 sec
->reloc_count
= 4;
1635 /* Each external function in a PowerPC PE file has a two word
1636 descriptor consisting of:
1637 1. The address of the code.
1638 2. The address of the appropriate .toc
1639 We use relocs to build this.
1643 si
->data
=xmalloc(8);
1644 memset (si
->data
, 0, si
->size
);
1646 rpp
= xmalloc (sizeof (arelent
*) * 3);
1647 rpp
[0] = rel
= xmalloc (sizeof (arelent
));
1648 rpp
[1] = xmalloc (sizeof (arelent
));
1653 rel
->howto
= bfd_reloc_type_lookup (abfd
, BFD_RELOC_32
);
1654 rel
->sym_ptr_ptr
= fn_pp
;
1660 rel
->howto
= bfd_reloc_type_lookup (abfd
, BFD_RELOC_32
);
1661 rel
->sym_ptr_ptr
= toc_pp
;
1663 sec
->orelocation
= rpp
;
1664 sec
->reloc_count
= 2;
1671 /* Size up all the sections */
1672 for (i
= 0; i
< NSECS
; i
++)
1674 sinfo
*si
= secdata
+ i
;
1676 bfd_set_section_size (abfd
, si
->sec
, si
->size
);
1677 bfd_set_section_vma (abfd
, si
->sec
, vma
);
1679 /* vma += si->size;*/
1682 /* Write them out */
1683 for (i
= 0; i
< NSECS
; i
++)
1685 sinfo
*si
= secdata
+ i
;
1687 if (i
== IDATA5
&& no_idata5
)
1690 if (i
== IDATA4
&& no_idata4
)
1693 bfd_set_section_contents (abfd
, si
->sec
,
1698 bfd_set_symtab (abfd
, ptrs
, oidx
);
1700 abfd
= bfd_openr (outname
, HOW_BFD_TARGET
);
1710 FILE * f
= fopen ("dh.s", FOPEN_WT
);
1712 fprintf (f
, "%s IMAGE_IMPORT_DESCRIPTOR\n", ASM_C
);
1713 fprintf (f
, "\t.section .idata$2\n");
1715 fprintf(f
,"\t%s\t%s\n", ASM_GLOBAL
,head_label
);
1717 fprintf (f
, "%s:\n", head_label
);
1719 fprintf (f
, "\t%shname%s\t%sPtr to image import by name list\n",
1720 ASM_RVA_BEFORE
, ASM_RVA_AFTER
, ASM_C
);
1722 fprintf (f
, "\t%sthis should be the timestamp, but NT sometimes\n", ASM_C
);
1723 fprintf (f
, "\t%sdoesn't load DLLs when this is set.\n", ASM_C
);
1724 fprintf (f
, "\t%s\t0\t%s loaded time\n", ASM_LONG
, ASM_C
);
1725 fprintf (f
, "\t%s\t0\t%s Forwarder chain\n", ASM_LONG
, ASM_C
);
1726 fprintf (f
, "\t%s__%s_iname%s\t%s imported dll's name\n",
1731 fprintf (f
, "\t%sfthunk%s\t%s pointer to firstthunk\n",
1733 ASM_RVA_AFTER
, ASM_C
);
1735 fprintf (f
, "%sStuff for compatibility\n", ASM_C
);
1739 fprintf (f
, "\t.section\t.idata$5\n");
1740 fprintf (f
, "\t%s\t0\n", ASM_LONG
);
1741 fprintf (f
, "fthunk:\n");
1745 fprintf (f
, "\t.section\t.idata$4\n");
1747 fprintf (f
, "\t%s\t0\n", ASM_LONG
);
1748 fprintf (f
, "\t.section .idata$4\n");
1749 fprintf (f
, "hname:\n");
1753 sprintf (outfile
, "-o dh.o dh.s");
1754 run (as_name
, outfile
);
1756 return bfd_openr ("dh.o", HOW_BFD_TARGET
);
1762 FILE * f
= fopen ("dt.s", FOPEN_WT
);
1765 /* Other PowerPC NT compilers use idata$6 for the dllname, so I
1766 do too. Original, huh? */
1767 fprintf (f
, "\t.section .idata$6\n");
1769 fprintf (f
, "\t.section .idata$7\n");
1772 fprintf (f
, "\t%s\t__%s_iname\n", ASM_GLOBAL
, imp_name_lab
);
1773 fprintf (f
, "__%s_iname:\t%s\t\"%s\"\n",
1774 imp_name_lab
, ASM_TEXT
, dll_name
);
1778 fprintf (f
, "\t.section .idata$4\n");
1779 fprintf (f
, "\t%s\t0\n", ASM_LONG
);
1783 fprintf (f
, "\t.section .idata$5\n");
1784 fprintf (f
, "\t%s\t0\n", ASM_LONG
);
1789 /* Normally, we need to see a null descriptor built in idata$3 to
1790 act as the terminator for the list. The ideal way, I suppose,
1791 would be to mark this section as a comdat type 2 section, so
1792 only one would appear in the final .exe (if our linker supported
1793 comdat, that is) or cause it to be inserted by something else (say
1797 fprintf (f
, "\t.section .idata$3\n");
1798 fprintf (f
, "\t%s\t0\n", ASM_LONG
);
1799 fprintf (f
, "\t%s\t0\n", ASM_LONG
);
1800 fprintf (f
, "\t%s\t0\n", ASM_LONG
);
1801 fprintf (f
, "\t%s\t0\n", ASM_LONG
);
1802 fprintf (f
, "\t%s\t0\n", ASM_LONG
);
1807 sprintf (outfile
, "-o dt.o dt.s");
1808 run (as_name
, outfile
);
1809 return bfd_openr ("dt.o", HOW_BFD_TARGET
);
1824 outarch
= bfd_openw (imp_name
, HOW_BFD_TARGET
);
1828 fprintf (stderr
, "%s: Can't open .lib file %s\n", program_name
, imp_name
);
1831 bfd_set_format (outarch
, bfd_archive
);
1832 outarch
->has_armap
= 1;
1834 /* Work out a reasonable size of things to put onto one line. */
1838 ar_head
= make_head ();
1839 ar_tail
= make_tail();
1841 for (i
= 0; (exp
= d_exports_lexically
[i
]); i
++)
1843 bfd
*n
= make_one_lib_file (exp
, i
);
1849 /* Now stick them all into the archive */
1851 ar_head
->next
= head
;
1852 ar_tail
->next
= ar_head
;
1855 bfd_set_archive_head (outarch
, head
);
1856 bfd_close (outarch
);
1858 /* Delete all the temp files */
1860 if (dontdeltemps
== 0)
1862 sprintf (outfile
, "dh.o");
1864 sprintf (outfile
, "dh.s");
1866 sprintf (outfile
, "dt.o");
1868 sprintf (outfile
, "dt.s");
1872 if (dontdeltemps
< 2)
1873 for (i
= 0, exp
= d_exports
; exp
; i
++, exp
= exp
->next
)
1875 sprintf (outfile
, "ds%d.o",i
);
1880 /**********************************************************************/
1882 /* Run through the information gathered from the .o files and the
1883 .def file and work out the best stuff */
1889 export_type
*ap
= *(export_type
**) a
;
1890 export_type
*bp
= *(export_type
**) b
;
1891 if (ap
->ordinal
== bp
->ordinal
)
1894 /* unset ordinals go to the bottom */
1895 if (ap
->ordinal
== -1)
1897 if (bp
->ordinal
== -1)
1899 return (ap
->ordinal
- bp
->ordinal
);
1908 export_type
*ap
= *(export_type
**) a
;
1909 export_type
*bp
= *(export_type
**) b
;
1911 return (strcmp (ap
->name
, bp
->name
));
1916 remove_null_names (ptr
)
1921 for (dst
= src
= 0; src
< d_nfuncs
; src
++)
1925 ptr
[dst
] = ptr
[src
];
1938 for (i
= 0; i
< d_nfuncs
; i
++)
1942 printf ("%d %s @ %d %s%s\n",
1943 i
, ptr
[i
]->name
, ptr
[i
]->ordinal
,
1944 ptr
[i
]->noname
? "NONAME " : "",
1945 ptr
[i
]->constant
? "CONSTANT" : "");
1954 process_duplicates (d_export_vec
)
1955 export_type
**d_export_vec
;
1963 /* Remove duplicates */
1964 qsort (d_export_vec
, d_nfuncs
, sizeof (export_type
*), nfunc
);
1966 dtab (d_export_vec
);
1967 for (i
= 0; i
< d_nfuncs
- 1; i
++)
1969 if (strcmp (d_export_vec
[i
]->name
,
1970 d_export_vec
[i
+ 1]->name
) == 0)
1973 export_type
*a
= d_export_vec
[i
];
1974 export_type
*b
= d_export_vec
[i
+ 1];
1978 fprintf (stderr
, "Warning, ignoring duplicate EXPORT %s %d,%d\n",
1982 if (a
->ordinal
!= -1
1983 && b
->ordinal
!= -1)
1986 fprintf (stderr
, "Error, duplicate EXPORT with oridinals %s\n",
1990 /* Merge attributes */
1991 b
->ordinal
= a
->ordinal
> 0 ? a
->ordinal
: b
->ordinal
;
1992 b
->constant
|= a
->constant
;
1993 b
->noname
|= a
->noname
;
1994 d_export_vec
[i
] = 0;
1997 dtab (d_export_vec
);
1998 remove_null_names (d_export_vec
);
1999 dtab (d_export_vec
);
2004 /* Count the names */
2005 for (i
= 0; i
< d_nfuncs
; i
++)
2007 if (!d_export_vec
[i
]->noname
)
2013 fill_ordinals (d_export_vec
)
2014 export_type
**d_export_vec
;
2020 qsort (d_export_vec
, d_nfuncs
, sizeof (export_type
*), pfunc
);
2022 /* fill in the unset ordinals with ones from our range */
2024 ptr
= (char *) malloc (65536);
2026 memset (ptr
, 0, 65536);
2028 /* Mark in our large vector all the numbers that are taken */
2029 for (i
= 0; i
< d_nfuncs
; i
++)
2031 if (d_export_vec
[i
]->ordinal
!= -1)
2033 ptr
[d_export_vec
[i
]->ordinal
] = 1;
2035 lowest
= d_export_vec
[i
]->ordinal
;
2039 /* Start at 1 for compatibility with MS toolchain. */
2043 for (i
= 0; i
< d_nfuncs
; i
++)
2045 if (d_export_vec
[i
]->ordinal
== -1)
2048 for (j
= lowest
; j
< 65536; j
++)
2052 d_export_vec
[i
]->ordinal
= j
;
2056 for (j
= 1; j
< lowest
; j
++)
2060 d_export_vec
[i
]->ordinal
= j
;
2072 qsort (d_export_vec
, d_nfuncs
, sizeof (export_type
*), pfunc
);
2074 /* Work out the lowest and highest ordinal numbers. */
2077 if (d_export_vec
[0])
2078 d_low_ord
= d_export_vec
[0]->ordinal
;
2079 if (d_export_vec
[d_nfuncs
-1])
2080 d_high_ord
= d_export_vec
[d_nfuncs
-1]->ordinal
;
2084 int alphafunc(av
,bv
)
2088 export_type
**a
= av
;
2089 export_type
**b
= bv
;
2091 return strcmp ((*a
)->name
, (*b
)->name
);
2097 /* First work out the minimum ordinal chosen */
2103 export_type
**d_export_vec
2104 = (export_type
**) xmalloc (sizeof (export_type
*) * d_nfuncs
);
2106 for (i
= 0, exp
= d_exports
; exp
; i
++, exp
= exp
->next
)
2108 d_export_vec
[i
] = exp
;
2111 process_duplicates (d_export_vec
);
2112 fill_ordinals (d_export_vec
);
2114 /* Put back the list in the new order */
2116 for (i
= d_nfuncs
- 1; i
>= 0; i
--)
2118 d_export_vec
[i
]->next
= d_exports
;
2119 d_exports
= d_export_vec
[i
];
2122 /* Build list in alpha order */
2123 d_exports_lexically
= (export_type
**)xmalloc (sizeof(export_type
*)*(d_nfuncs
+1));
2125 for (i
= 0, exp
= d_exports
; exp
; i
++, exp
= exp
->next
)
2127 d_exports_lexically
[i
] = exp
;
2129 d_exports_lexically
[i
] = 0;
2131 qsort (d_exports_lexically
, i
, sizeof (export_type
*), alphafunc
);
2133 /* Fill exp entries with their hint values */
2135 for (i
= 0; i
< d_nfuncs
; i
++)
2137 if (!d_exports_lexically
[i
]->noname
|| show_allnames
)
2138 d_exports_lexically
[i
]->hint
= hint
++;
2148 /**********************************************************************/
2151 usage (file
, status
)
2155 fprintf (file
, "Usage %s <options> <object-files>\n", program_name
);
2156 fprintf (file
, " --machine <machine>\n");
2157 fprintf (file
, " --output-exp <outname> Generate export file.\n");
2158 fprintf (file
, " --output-lib <outname> Generate input library.\n");
2159 fprintf (file
, " --add-indirect Add dll indirects to export file.\n");
2160 fprintf (file
, " --dllname <name> Name of input dll to put into output lib.\n");
2161 fprintf (file
, " --def <deffile> Name input .def file\n");
2162 fprintf (file
, " --output-def <deffile> Name output .def file\n");
2163 fprintf (file
, " --base-file <basefile> Read linker generated base file\n");
2164 fprintf (file
, " --no-idata4 Don't generate idata$4 section\n");
2165 fprintf (file
, " --no-idata5 Don't generate idata$5 section\n");
2166 fprintf (file
, " -v Verbose\n");
2167 fprintf (file
, " -U Add underscores to .lib\n");
2168 fprintf (file
, " -k Kill @<n> from exported names\n");
2169 fprintf (file
, " --as <name> Use <name> for assembler\n");
2170 fprintf (file
, " --nodelete Keep temp files.\n");
2174 #define OPTION_NO_IDATA4 'x'
2175 #define OPTION_NO_IDATA5 'c'
2176 static struct option long_options
[] =
2178 {"nodelete", no_argument
, NULL
, 'n'},
2179 {"dllname", required_argument
, NULL
, 'D'},
2180 {"no-idata4", no_argument
, NULL
, OPTION_NO_IDATA4
},
2181 {"no-idata5", no_argument
, NULL
, OPTION_NO_IDATA5
},
2182 {"output-exp", required_argument
, NULL
, 'e'},
2183 {"output-def", required_argument
, NULL
, 'z'},
2184 {"output-lib", required_argument
, NULL
, 'l'},
2185 {"def", required_argument
, NULL
, 'd'},
2186 {"add-underscore", no_argument
, NULL
, 'U'},
2187 {"killat", no_argument
, NULL
, 'k'},
2188 {"help", no_argument
, NULL
, 'h'},
2189 {"machine", required_argument
, NULL
, 'm'},
2190 {"add-indirect", no_argument
, NULL
, 'a'},
2191 {"base-file", required_argument
, NULL
, 'b'},
2192 {"as", required_argument
, NULL
, 'S'},
2206 program_name
= av
[0];
2209 while ((c
= getopt_long (ac
, av
, "xcz:S:R:A:puaD:l:e:nkvbUh?m:yd:", long_options
, 0))
2214 case OPTION_NO_IDATA4
:
2217 case OPTION_NO_IDATA5
:
2224 /* ignored for compatibility */
2231 output_def
= fopen (optarg
, FOPEN_WT
);
2268 base_file
= fopen (optarg
, FOPEN_RB
);
2271 fprintf (stderr
, "%s: Unable to open base-file %s\n",
2283 for (i
= 0; mtable
[i
].type
; i
++)
2285 if (strcmp (mtable
[i
].type
, mname
) == 0)
2289 if (!mtable
[i
].type
)
2291 fprintf (stderr
, "Machine not supported\n");
2297 if (!dll_name
&& exp_name
)
2299 char len
= strlen (exp_name
) + 5;
2300 dll_name
= xmalloc (len
);
2301 strcpy (dll_name
, exp_name
);
2302 strcat (dll_name
, ".dll");
2307 process_def_file (def_file
);
2312 firstarg
= av
[optind
];
2313 scan_obj_file (av
[optind
]);
2324 /* Make imp_name safe for use as a label. */
2326 imp_name_lab
= strdup (imp_name
);
2327 for (p
= imp_name_lab
; *p
; *p
++)
2329 if (!isalpha (*p
) && !isdigit (*p
))
2332 head_label
= make_label("_head_", imp_name_lab
);