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.
172 DWORD Characteristics; - pointer to .idata$4
173 DWORD TimeDateStamp; - currently always 0
174 DWORD ForwarderChain; - currently always 0
175 DWORD Name; - pointer to dll's name
176 PIMAGE_THUNK_DATA FirstThunk; - pointer to .idata$5
178 .idata$3 = null terminating entry for .idata$2.
180 .idata$4 = Import Lookup Table
181 = array of array of pointers to hint name table.
182 There is one for each dll being imported from, and each dll's set is
183 terminated by a trailing NULL.
185 .idata$5 = Import Address Table
186 = array of array of pointers to hint name table.
187 There is one for each dll being imported from, and each dll's set is
188 terminated by a trailing NULL.
189 Initially, this table is identical to the Import Lookup Table. However,
190 at load time, the loader overwrites the entries with the address of the
193 .idata$6 = Hint Name Table
194 = Array of { short, asciz } entries, one for each imported function.
195 The `short' is the function's ordinal number.
197 .idata$7 = dll name (eg: "kernel32.dll"). (.idata$6 for ppc)
200 #define PAGE_SIZE 4096
201 #define PAGE_MASK (-PAGE_SIZE)
203 #include "libiberty.h"
206 #include "demangle.h"
208 #ifdef HAVE_SYS_WAIT_H
209 #include <sys/wait.h>
212 #define WIFEXITED(w) (((w)&0377) == 0)
215 #define WIFSIGNALED(w) (((w)&0377) != 0177 && ((w)&~0377) == 0)
218 #define WTERMSIG(w) ((w) & 0177)
221 #define WEXITSTATUS(w) (((w) >> 8) & 0377)
227 char *as_name = "as";
229 static int no_idata4;
230 static int no_idata5;
231 static char *exp_name;
232 static char *imp_name;
233 static char *head_label;
234 static char *imp_name_lab;
235 static char *dll_name;
237 static int add_indirect = 0;
238 static int add_underscore = 0;
239 static int dontdeltemps = 0;
243 static char *def_file;
245 static char *program_name;
256 static char *mname = "arm";
260 static char *mname = "i386";
264 static char *mname = "ppc";
267 #define PATHMAX 250 /* What's the right name for this ? */
269 /* This bit of assemly does jmp * ....
270 s set how_jtab_roff to mark where the 32bit abs branch should go */
271 unsigned char i386_jtab[] = { 0xff, 0x25, 0x00, 0x00, 0x00, 0x00, 0x90, 0x90};
274 unsigned char arm_jtab[] = { 0x00, 0xc0, 0x9f, 0xe5,
275 0x00, 0xf0, 0x9c, 0xe5,
278 /* This is the glue sequence for PowerPC PE. There is a */
279 /* tocrel16-tocdefn reloc against the first instruction. */
280 /* We also need a IMGLUE reloc against the glue function */
281 /* to restore the toc saved by the third instruction in */
283 unsigned char ppc_jtab[] =
285 0x00, 0x00, 0x62, 0x81, /* lwz r11,0(r2) */
286 /* Reloc TOCREL16 __imp_xxx */
287 0x00, 0x00, 0x8B, 0x81, /* lwz r12,0(r11) */
288 0x04, 0x00, 0x41, 0x90, /* stw r2,4(r1) */
289 0xA6, 0x03, 0x89, 0x7D, /* mtctr r12 */
290 0x04, 0x00, 0x4B, 0x80, /* lwz r2,4(r11) */
291 0x20, 0x04, 0x80, 0x4E /* bctr */
294 /* the glue instruction, picks up the toc from the stw in */
295 /* the above code: "lwz r2,4(r1)" */
296 bfd_vma ppc_glue_insn = 0x80410004;
299 char outfile[PATHMAX];
311 char *how_align_short;
312 char *how_align_long;
313 char *how_bfd_target;
314 enum bfd_architecture how_bfd_arch;
315 unsigned char *how_jtab;
316 int how_jtab_size; /* size of the jtab entry */
317 int how_jtab_roff; /* offset into it for the ind 32 reloc into idata 5 */
324 "arm", ".byte", ".short", ".long", ".asciz", "@",
325 "ldr\tip,[pc]\n\tldr\tpc,[ip]\n\t.long",
326 ".global", ".space", ".align\t2",".align\t4","pe-arm-little", bfd_arch_arm,
327 arm_jtab, sizeof(arm_jtab),8
332 "i386", ".byte", ".short", ".long", ".asciz", "#", "jmp *", ".global", ".space", ".align\t2",".align\t4","pe-i386",bfd_arch_i386,
333 i386_jtab,sizeof(i386_jtab),2,
338 "ppc", ".byte", ".short", ".long", ".asciz", "#", "jmp *", ".global", ".space", ".align\t2",".align\t4","pe-powerpcle",bfd_arch_powerpc,
339 ppc_jtab,sizeof(ppc_jtab),0,
393 #define ASM_BYTE mtable[machine].how_byte
394 #define ASM_SHORT mtable[machine].how_short
395 #define ASM_LONG mtable[machine].how_long
396 #define ASM_TEXT mtable[machine].how_asciz
397 #define ASM_C mtable[machine].how_comment
398 #define ASM_JUMP mtable[machine].how_jump
399 #define ASM_GLOBAL mtable[machine].how_global
400 #define ASM_SPACE mtable[machine].how_space
401 #define ASM_ALIGN_SHORT mtable[machine].how_align_short
402 #define ASM_RVA_BEFORE rvabefore(machine)
403 #define ASM_RVA_AFTER rvaafter(machine)
404 #define ASM_PREFIX asm_prefix(machine)
405 #define ASM_ALIGN_LONG mtable[machine].how_align_long
406 #define HOW_BFD_TARGET 0 /* always default*/
407 #define HOW_BFD_ARCH mtable[machine].how_bfd_arch
408 #define HOW_JTAB mtable[machine].how_jtab
409 #define HOW_JTAB_SIZE mtable[machine].how_jtab_size
410 #define HOW_JTAB_ROFF mtable[machine].how_jtab_roff
414 FILE *yyin; /* communications with flex */
415 extern int linenumber;
417 process_def_file (name)
420 FILE *f = fopen (name, FOPEN_RT);
423 fprintf (stderr, "%s: Can't open def file %s\n", program_name, name);
432 /**********************************************************************/
434 /* Communications with the parser */
444 typedef struct export
456 static char *d_name; /* Arg to NAME or LIBRARY */
457 static int d_nfuncs; /* Number of functions exported */
458 static int d_named_nfuncs; /* Number of named functions exported */
459 static int d_low_ord; /* Lowest ordinal index */
460 static int d_high_ord; /* Highest ordinal index */
461 static export_type *d_exports; /*list of exported functions */
462 static export_type **d_exports_lexically; /* vector of exported functions in alpha order */
463 static dlist_type *d_list; /* Descriptions */
464 static dlist_type *a_list; /* Stuff to go in directives */
472 fprintf (stderr, "%s: Syntax error in def file %s:%d\n",
473 program_name, def_file, linenumber);
478 def_exports (name, internal_name, ordinal, noname, constant)
485 struct export *p = (struct export *) xmalloc (sizeof (*p));
488 p->internal_name = internal_name ? internal_name : name;
489 p->ordinal = ordinal;
490 p->constant = constant;
499 def_name (name, base)
504 fprintf (stderr, "%s NAME %s base %x\n", program_name, name, base);
507 fprintf (stderr, "Can't have LIBRARY and NAME\n");
514 def_library (name, base)
519 printf ("%s: LIBRARY %s base %x\n", program_name, name, base);
522 fprintf (stderr, "%s: Can't have LIBRARY and NAME\n", program_name);
529 def_description (desc)
532 dlist_type *d = (dlist_type *) xmalloc (sizeof (dlist_type));
533 d->text = strdup (desc);
542 dlist_type *d = (dlist_type *) xmalloc (sizeof (dlist_type));
543 d->text = strdup (dir);
549 def_stacksize (reserve, commit)
555 sprintf (b, "-stack 0x%x,0x%x ", reserve, commit);
557 sprintf (b, "-stack 0x%x ", reserve);
558 new_directive (strdup (b));
562 def_heapsize (reserve, commit)
568 sprintf (b, "-heap 0x%x,0x%x ", reserve, commit);
570 sprintf (b, "-heap 0x%x ", reserve);
571 new_directive (strdup (b));
576 def_import (internal, module, entry)
582 fprintf (stderr, "%s: IMPORTS are ignored", program_name);
586 def_version (major, minor)
590 printf ("VERSION %d.%d\n", major, minor);
595 def_section (name, attr)
612 sprintf (buf, "-attr %s %s", name, atts);
613 new_directive (strdup (buf));
620 def_section ("CODE", attr);
627 def_section ("DATA", attr);
631 /**********************************************************************/
642 extern char **environ;
644 fprintf (stderr, "%s %s\n", what, args);
648 for (s = args; *s; s++)
652 argv = alloca (sizeof (char *) * (i + 3));
659 while (*s != ' ' && *s != 0)
673 fprintf (stderr, "%s: can't exec %s\n", program_name, what);
679 fprintf (stderr, "%s: vfork failed, %d\n", program_name, errno);
685 waitpid (pid, &status, 0);
688 if (WIFSIGNALED (status))
690 fprintf (stderr, "%s: %s %s terminated with signal %d\n",
691 program_name, what, args, WTERMSIG (status));
695 if (WIFEXITED (status))
697 fprintf (stderr, "%s: %s %s terminated with exit status %d\n",
698 program_name, what, args, WEXITSTATUS (status));
705 /* read in and block out the base relocations */
717 scan_open_obj_file (abfd)
720 /* Look for .drectve's */
721 asection *s = bfd_get_section_by_name (abfd, ".drectve");
724 int size = bfd_get_section_size_before_reloc (s);
725 char *buf = xmalloc (size);
728 bfd_get_section_contents (abfd, s, buf, 0, size);
730 fprintf (stderr, "%s: Sucking in info from %s\n",
732 bfd_get_filename (abfd));
734 /* Search for -export: strings */
740 && strncmp (p, "-export:", 8) == 0)
746 while (*p != ' ' && *p != '-' && p < e)
748 c = xmalloc (p - name + 1);
749 memcpy (c, name, p - name);
751 def_exports (c, 0, -1, 0);
762 fprintf (stderr, "%s: Done readin\n",
769 scan_obj_file (filename)
772 bfd *f = bfd_openr (filename, 0);
776 fprintf (stderr, "%s: Unable to open object file %s\n",
781 if (bfd_check_format (f, bfd_archive))
783 bfd *arfile = bfd_openr_next_archived_file (f, 0);
786 if (bfd_check_format (arfile, bfd_object))
787 scan_open_obj_file (arfile);
789 arfile = bfd_openr_next_archived_file (f, arfile);
792 else if (bfd_check_format (f, bfd_object))
794 scan_open_obj_file (f);
800 /**********************************************************************/
810 fprintf (f, "%s ", ASM_C);
811 for (i = 0; oav[i]; i++)
812 fprintf (f, "%s ", oav[i]);
814 for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
816 fprintf (f, "%s %d = %s %s @ %d %s%s\n",
822 exp->noname ? "NONAME " : "",
823 exp->constant ? "CONSTANT" : "");
826 /* Generate the .exp file */
839 flush_page (f, need, page_addr, on_page)
847 /* Flush this page */
848 fprintf (f, "\t%s\t0x%08x\t%s Starting RVA for chunk\n",
852 fprintf (f, "\t%s\t0x%x\t%s Size of block\n",
854 (on_page * 2) + (on_page & 1) * 2 + 8,
856 for (i = 0; i < on_page; i++)
858 fprintf (f, "\t%s\t0x%x\n", ASM_SHORT, (need[i] - page_addr) | 0x3000);
862 fprintf (f, "\t%s\t0x%x\n", ASM_SHORT, 0 | 0x0000);
873 fprintf (output_def, ";");
874 for (i = 0; oav[i]; i++)
875 fprintf (output_def, " %s", oav[i]);
877 fprintf (output_def, "\nEXPORTS\n");
879 for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
881 char *quote = strchr (exp->name, '.') ? "\"" : "";
882 fprintf (output_def, "\t%s%s%s @ %d%s ; %s\n",
887 exp->noname ? " NONAME" : "",
888 cplus_demangle (exp->internal_name, DMGL_ANSI | DMGL_PARAMS));
900 sprintf (outfile, "t%s", exp_name);
903 fprintf (stderr, "%s: Generate exp file %s\n",
904 program_name, exp_name);
906 f = fopen (outfile, FOPEN_WT);
909 fprintf (stderr, "%s: Unable to open output file %s\n", program_name, outfile);
914 fprintf (stderr, "%s: Opened file %s\n",
915 program_name, outfile);
921 fprintf (f, "\t.section .edata\n\n");
922 fprintf (f, "\t%s 0 %s Allways 0\n", ASM_LONG, ASM_C);
923 fprintf (f, "\t%s 0x%x %s Time and date\n", ASM_LONG, time(0),ASM_C);
924 fprintf (f, "\t%s 0 %s Major and Minor version\n", ASM_LONG, ASM_C);
925 fprintf (f, "\t%sname%s %s Ptr to name of dll\n", ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C);
926 fprintf (f, "\t%s %d %s Starting ordinal of exports\n", ASM_LONG, d_low_ord, ASM_C);
929 fprintf (f, "\t%s %d %s Number of functions\n", ASM_LONG, d_high_ord - d_low_ord + 1, ASM_C);
930 fprintf(f,"\t%s named funcs %d, low ord %d, high ord %d\n",
932 d_named_nfuncs, d_low_ord, d_high_ord);
933 fprintf (f, "\t%s %d %s Number of names\n", ASM_LONG,
934 show_allnames ? d_high_ord - d_low_ord + 1 : d_named_nfuncs, ASM_C);
935 fprintf (f, "\t%safuncs%s %s Address of functions\n", ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C);
937 fprintf (f, "\t%sanames%s %s Address of Name Pointer Table\n",
938 ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C);
940 fprintf (f, "\t%sanords%s %s Address of ordinals\n", ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C);
942 fprintf (f, "name: %s \"%s\"\n", ASM_TEXT, dll_name);
945 fprintf(f,"%s Export address Table\n", ASM_C);
946 fprintf(f,"\t%s\n", ASM_ALIGN_LONG);
947 fprintf (f, "afuncs:\n");
950 for (exp = d_exports; exp; exp = exp->next)
952 if (exp->ordinal != i)
955 fprintf (f, "\t%s\t%d\t%s %d..%d missing\n",
957 (exp->ordinal - i) * 4,
959 i, exp->ordinal - 1);
962 while (i < exp->ordinal)
964 fprintf(f,"\t%s\t0\n", ASM_LONG);
968 fprintf (f, "\t%s%s%s%s\t%s %d\n", ASM_RVA_BEFORE,
970 exp->internal_name, ASM_RVA_AFTER, ASM_C, exp->ordinal);
974 fprintf (f,"%s Export Name Pointer Table\n", ASM_C);
975 fprintf (f, "anames:\n");
977 for (i = 0; (exp = d_exports_lexically[i]); i++)
979 if (!exp->noname || show_allnames)
980 fprintf (f, "\t%sn%d%s\n", ASM_RVA_BEFORE, exp->ordinal, ASM_RVA_AFTER);
983 fprintf (f,"%s Export Oridinal Table\n", ASM_C);
984 fprintf (f, "anords:\n");
985 for (i = 0; (exp = d_exports_lexically[i]); i++)
987 if (!exp->noname || show_allnames)
988 fprintf (f, "\t%s %d\n", ASM_SHORT, exp->ordinal - d_low_ord);
991 fprintf(f,"%s Export Name Table\n", ASM_C);
992 for (i = 0; (exp = d_exports_lexically[i]); i++)
993 if (!exp->noname || show_allnames)
994 fprintf (f, "n%d: %s \"%s\"\n", exp->ordinal, ASM_TEXT, exp->name);
998 fprintf (f, "\t.section .drectve\n");
999 for (dl = a_list; dl; dl = dl->next)
1001 fprintf (f, "\t%s\t\"%s\"\n", ASM_TEXT, dl->text);
1006 fprintf (f, "\t.section .rdata\n");
1007 for (dl = d_list; dl; dl = dl->next)
1011 /* We dont output as ascii 'cause there can
1012 be quote characters in the string */
1015 for (p = dl->text; *p; p++)
1018 fprintf (f, "\t%s\t", ASM_BYTE);
1021 fprintf (f, "%d", *p);
1024 fprintf (f, ",0\n");
1038 /* Add to the output file a way of getting to the exported names
1039 without using the import library. */
1042 fprintf (f, "\t.section\t.rdata\n");
1043 for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
1044 if (!exp->noname || show_allnames)
1046 fprintf (f, "\t%s\t__imp_%s\n", ASM_GLOBAL, exp->name);
1047 fprintf (f, "__imp_%s:\n", exp->name);
1048 fprintf (f, "\t%s\t%s\n", ASM_LONG, exp->name);
1052 /* Dump the reloc section if a base file is provided */
1056 long need[PAGE_SIZE];
1063 fprintf (f, "\t.section\t.init\n");
1064 fprintf (f, "lab:\n");
1066 fseek (base_file, 0, SEEK_END);
1067 numbytes = ftell (base_file);
1068 fseek (base_file, 0, SEEK_SET);
1069 copy = malloc (numbytes);
1070 fread (copy, 1, numbytes, base_file);
1071 num_entries = numbytes / sizeof (long);
1074 fprintf (f, "\t.section\t.reloc\n");
1081 qsort (copy, num_entries, sizeof (long), sfunc);
1082 /* Delete duplcates */
1083 for (src = 0; src < num_entries; src++)
1085 if (last != copy[src])
1086 last = copy[dst++] = copy[src];
1090 page_addr = addr & PAGE_MASK; /* work out the page addr */
1092 for (j = 0; j < num_entries; j++)
1095 if ((addr & PAGE_MASK) != page_addr)
1097 flush_page (f, need, page_addr, on_page);
1099 page_addr = addr & PAGE_MASK;
1101 need[on_page++] = addr;
1103 flush_page (f, need, page_addr, on_page);
1105 /* fprintf (f, "\t%s\t0,0\t%s End\n", ASM_LONG, ASM_C);*/
1111 /* assemble the file */
1112 sprintf (outfile, "-o %s t%s", exp_name, exp_name);
1113 run (as_name, outfile);
1114 if (dontdeltemps == 0)
1116 sprintf (outfile, "t%s", exp_name);
1126 char *copy = malloc (strlen (name) + 2);
1128 strcpy (copy + 1, name);
1135 p = strchr (name, '@');
1142 /**********************************************************************/
1144 static void dump_iat (f, exp)
1148 if (exp->noname && !show_allnames )
1150 fprintf (f, "\t%s\t0x%08x\n",
1152 exp->ordinal | 0x80000000); /* hint or orindal ?? */
1156 fprintf (f, "\t%sID%d%s\n", ASM_RVA_BEFORE,
1174 unsigned char *data;
1193 static sinfo secdata[NSECS] =
1195 { TEXT, ".text", SEC_CODE | SEC_HAS_CONTENTS, 3},
1196 { DATA, ".data", SEC_DATA, 2},
1197 { BSS, ".bss", 0, 2},
1198 { IDATA7, ".idata$7", SEC_HAS_CONTENTS, 2},
1199 { IDATA5, ".idata$5", SEC_HAS_CONTENTS, 2},
1200 { IDATA4, ".idata$4", SEC_HAS_CONTENTS, 2},
1201 { IDATA6, ".idata$6", SEC_HAS_CONTENTS, 1}
1206 /* Sections numbered to make the order the same as other PowerPC NT */
1207 /* compilers. This also keeps funny alignment thingies from happening. */
1220 static sinfo secdata[NSECS] =
1222 { TEXT, ".text", SEC_CODE | SEC_HAS_CONTENTS, 3},
1223 { PDATA, ".pdata", SEC_HAS_CONTENTS, 2},
1224 { RDATA, ".rdata", SEC_HAS_CONTENTS, 2},
1225 { IDATA5, ".idata$5", SEC_HAS_CONTENTS, 2},
1226 { IDATA4, ".idata$4", SEC_HAS_CONTENTS, 2},
1227 { IDATA6, ".idata$6", SEC_HAS_CONTENTS, 1},
1228 { IDATA7, ".idata$7", SEC_HAS_CONTENTS, 2},
1229 { DATA, ".data", SEC_DATA, 2},
1230 { BSS, ".bss", 0, 2}
1236 This is what we're trying to make
1239 .global _GetFileVersionInfoSizeW@8
1240 .global __imp_GetFileVersionInfoSizeW@8
1241 _GetFileVersionInfoSizeW@8:
1242 jmp * __imp_GetFileVersionInfoSizeW@8
1243 .section .idata$7 # To force loading of head
1244 .long __version_a_head
1245 # Import Address Table
1247 __imp_GetFileVersionInfoSizeW@8:
1250 # Import Lookup Table
1256 .asciz "GetFileVersionInfoSizeW"
1259 For the PowerPC, here's the variation on the above scheme:
1261 # Rather than a simple "jmp *", the code to get to the dll function
1264 lwz r11,[tocv]__imp_function_name(r2)
1265 # RELOC: 00000000 TOCREL16,TOCDEFN __imp_function_name
1274 make_label (prefix, name)
1278 int len = strlen (ASM_PREFIX) + strlen (prefix) + strlen (name);
1279 char *copy = xmalloc (len +1 );
1280 strcpy (copy, ASM_PREFIX);
1281 strcat (copy, prefix);
1282 strcat (copy, name);
1287 make_one_lib_file (exp, i)
1295 sprintf (outfile, "%ss%d.s", prefix, i);
1296 f = fopen (outfile, FOPEN_WT);
1297 fprintf (f, "\t.text\n");
1298 fprintf (f, "\t%s\t%s%s\n", ASM_GLOBAL, ASM_PREFIX, exp->name);
1299 fprintf (f, "\t%s\t__imp_%s\n", ASM_GLOBAL, exp->name);
1300 fprintf (f, "%s%s:\n\t%s\t__imp_%s\n", ASM_PREFIX,
1301 exp->name, ASM_JUMP, exp->name);
1303 fprintf (f, "\t.section\t.idata$7\t%s To force loading of head\n", ASM_C);
1304 fprintf (f, "\t%s\t%s\n", ASM_LONG, head_label);
1307 fprintf (f,"%s Import Address Table\n", ASM_C);
1309 fprintf (f, "\t.section .idata$5\n");
1310 fprintf (f, "__imp_%s:\n", exp->name);
1314 fprintf (f, "\n%s Import Lookup Table\n", ASM_C);
1315 fprintf (f, "\t.section .idata$4\n");
1319 if(!exp->noname || show_allnames)
1321 fprintf (f, "%s Hint/Name table\n", ASM_C);
1322 fprintf (f, "\t.section .idata$6\n");
1323 fprintf (f, "ID%d:\t%s\t%d\n", exp->ordinal, ASM_SHORT, exp->hint);
1324 fprintf (f, "\t%s\t\"%s\"\n", ASM_TEXT, xlate (exp->name));
1330 sprintf (outfile, "-o %ss%d.o %ss%d.s", prefix, i, prefix, i);
1332 run (as_name, outfile);
1343 asymbol **iname_lab_pp;
1346 /* Extra Symbols for PPC */
1353 asymbol *function_name; /* ".." functionName */
1355 asymbol *toc_symbol; /* The .toc symbol */
1358 /* one symbol for each section, 2 extra + a null */
1359 asymbol *ptrs[NSECS+3+EXTRA+1];
1361 char *outname = xmalloc (10);
1363 sprintf (outname, "ds%d.o", i);
1364 abfd = bfd_openw (outname, HOW_BFD_TARGET);
1367 fprintf (stderr, "%s: bfd_open failed open output file %s\n",
1368 program_name, outname);
1372 bfd_set_format (abfd, bfd_object);
1373 bfd_set_arch_mach (abfd, HOW_BFD_ARCH, 0);
1376 /* First make symbols for the sections */
1377 for (i = 0; i < NSECS; i++)
1379 sinfo *si = secdata + i;
1382 si->sec = bfd_make_section_old_way (abfd, si->name);
1383 bfd_set_section_flags (abfd,
1387 bfd_set_section_alignment(abfd, si->sec, si->align);
1388 si->sec->output_section = si->sec;
1389 si->sym = bfd_make_empty_symbol(abfd);
1390 si->sym->name = si->sec->name;
1391 si->sym->section = si->sec;
1392 si->sym->flags = BSF_LOCAL;
1394 ptrs[oidx] = si->sym;
1395 si->sympp = ptrs + oidx;
1400 exp_label = bfd_make_empty_symbol(abfd);
1401 exp_label->name = make_label ("",exp->name);
1403 /* On PowerPC, the function name points to a descriptor in the
1404 rdata section, the first element of which is a pointer to the
1405 code (..function_name), and the second points to the .toc
1407 if (machine == MPPC)
1408 exp_label->section = secdata[RDATA].sec;
1410 exp_label->section = secdata[TEXT].sec;
1412 exp_label->flags = BSF_GLOBAL;
1413 exp_label->value = 0;
1415 ptrs[oidx++] = exp_label;
1417 iname = bfd_make_empty_symbol(abfd);
1418 iname->name = make_label ("__imp_", exp->name);
1419 iname->section = secdata[IDATA5].sec;
1420 iname->flags = BSF_GLOBAL;
1424 iname_lab = bfd_make_empty_symbol(abfd);
1426 iname_lab->name = head_label;
1427 iname_lab->section = (asection *)&bfd_und_section;
1428 iname_lab->flags = 0;
1429 iname_lab->value = 0;
1432 iname_pp = ptrs + oidx;
1433 ptrs[oidx++] = iname;
1435 iname_lab_pp = ptrs + oidx;
1436 ptrs[oidx++] = iname_lab;
1439 /* The symbol refering to the code (.text) */
1440 function_name = bfd_make_empty_symbol(abfd);
1441 function_name->name = make_label ("..", exp->name);
1442 function_name->section = secdata[TEXT].sec;
1443 function_name->flags = BSF_GLOBAL;
1444 function_name->value = 0;
1446 fn_pp = ptrs + oidx;
1447 ptrs[oidx++] = function_name;
1449 /* The .toc symbol */
1450 toc_symbol = bfd_make_empty_symbol(abfd);
1451 toc_symbol->name = make_label (".", "toc");
1452 toc_symbol->section = (asection *)&bfd_und_section;
1453 toc_symbol->flags = BSF_GLOBAL;
1454 toc_symbol->value = 0;
1456 toc_pp = ptrs + oidx;
1457 ptrs[oidx++] = toc_symbol;
1462 for (i = 0; i < NSECS; i++)
1464 sinfo *si = secdata + i;
1465 asection *sec = si->sec;
1472 si->size = HOW_JTAB_SIZE;
1473 si->data = xmalloc (HOW_JTAB_SIZE);
1474 memcpy (si->data, HOW_JTAB, HOW_JTAB_SIZE);
1476 /* add the reloc into idata$5 */
1477 rel = xmalloc (sizeof (arelent));
1478 rpp = xmalloc (sizeof (arelent *) * 2);
1481 rel->address = HOW_JTAB_ROFF;
1484 if (machine == MPPC)
1486 rel->howto = bfd_reloc_type_lookup (abfd,
1487 BFD_RELOC_16_GOTOFF);
1488 rel->sym_ptr_ptr = iname_pp;
1492 rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_32);
1493 rel->sym_ptr_ptr = secdata[IDATA5].sympp;
1495 sec->orelocation = rpp;
1496 sec->reloc_count = 1;
1500 /* An idata$4 or idata$5 is one word long, and has an
1503 si->data = xmalloc (4);
1508 si->data[0] = exp->ordinal ;
1509 si->data[1] = exp->ordinal >> 8;
1510 si->data[2] = exp->ordinal >> 16;
1515 sec->reloc_count = 1;
1516 memset (si->data, 0, si->size);
1517 rel = xmalloc (sizeof (arelent));
1518 rpp = xmalloc (sizeof (arelent *) * 2);
1523 rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_RVA);
1524 rel->sym_ptr_ptr = secdata[IDATA6].sympp;
1525 sec->orelocation = rpp;
1533 int idx = exp->hint + 1;
1534 si->size = strlen (xlate (exp->name)) + 3;
1535 si->data = xmalloc (si->size);
1536 si->data[0] = idx & 0xff;
1537 si->data[1] = idx >> 8;
1538 strcpy (si->data + 2, xlate (exp->name));
1543 si->data =xmalloc(4);
1544 memset (si->data, 0, si->size);
1545 rel = xmalloc (sizeof (arelent));
1546 rpp = xmalloc (sizeof (arelent *) * 2);
1550 rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_32);
1551 rel->sym_ptr_ptr = iname_lab_pp;
1552 sec->orelocation = rpp;
1553 sec->reloc_count = 1;
1558 /* The .pdata section is 5 words long. */
1559 /* Think of it as: */
1562 /* bfd_vma BeginAddress, [0x00] */
1563 /* EndAddress, [0x04] */
1564 /* ExceptionHandler, [0x08] */
1565 /* HandlerData, [0x0c] */
1566 /* PrologEndAddress; [0x10] */
1569 /* So this pdata section setups up this as a glue linkage to
1570 a dll routine. There are a number of house keeping things
1573 1. In the name of glue trickery, the ADDR32 relocs for 0,
1574 4, and 0x10 are set to point to the same place:
1576 2. There is one more reloc needed in the pdata section.
1577 The actual glue instruction to restore the toc on
1578 return is saved as the offset in an IMGLUE reloc.
1579 So we need a total of four relocs for this section.
1581 3. Lastly, the HandlerData field is set to 0x03, to indicate
1582 that this is a glue routine.
1584 arelent *imglue, *ba_rel, *ea_rel, *pea_rel;
1586 /* alignment must be set to 2**2 or you get extra stuff */
1587 bfd_set_section_alignment(abfd, sec, 2);
1590 si->data =xmalloc(4 * 5);
1591 memset (si->data, 0, si->size);
1592 rpp = xmalloc (sizeof (arelent *) * 5);
1593 rpp[0] = imglue = xmalloc (sizeof (arelent));
1594 rpp[1] = ba_rel = xmalloc (sizeof (arelent));
1595 rpp[2] = ea_rel = xmalloc (sizeof (arelent));
1596 rpp[3] = pea_rel = xmalloc (sizeof (arelent));
1599 /* stick the toc reload instruction in the glue reloc */
1600 bfd_put_32(abfd, ppc_glue_insn, (char *) &imglue->address);
1603 imglue->howto = bfd_reloc_type_lookup (abfd,
1604 BFD_RELOC_32_GOTOFF);
1605 imglue->sym_ptr_ptr = fn_pp;
1607 ba_rel->address = 0;
1609 ba_rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_32);
1610 ba_rel->sym_ptr_ptr = fn_pp;
1612 bfd_put_32(abfd, 0x18, si->data + 0x04);
1613 ea_rel->address = 4;
1615 ea_rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_32);
1616 ea_rel->sym_ptr_ptr = fn_pp;
1618 /* mark it as glue */
1619 bfd_put_32(abfd, 0x03, si->data + 0x0c);
1621 /* mark the prolog end address */
1622 bfd_put_32(abfd, 0x0D, si->data + 0x10);
1623 pea_rel->address = 0x10;
1624 pea_rel->addend = 0;
1625 pea_rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_32);
1626 pea_rel->sym_ptr_ptr = fn_pp;
1628 sec->orelocation = rpp;
1629 sec->reloc_count = 4;
1633 /* Each external function in a PowerPC PE file has a two word
1634 descriptor consisting of:
1635 1. The address of the code.
1636 2. The address of the appropriate .toc
1637 We use relocs to build this.
1641 si->data =xmalloc(8);
1642 memset (si->data, 0, si->size);
1644 rpp = xmalloc (sizeof (arelent *) * 3);
1645 rpp[0] = rel = xmalloc (sizeof (arelent));
1646 rpp[1] = xmalloc (sizeof (arelent));
1651 rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_32);
1652 rel->sym_ptr_ptr = fn_pp;
1658 rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_32);
1659 rel->sym_ptr_ptr = toc_pp;
1661 sec->orelocation = rpp;
1662 sec->reloc_count = 2;
1669 /* Size up all the sections */
1670 for (i = 0; i < NSECS; i++)
1672 sinfo *si = secdata + i;
1674 bfd_set_section_size (abfd, si->sec, si->size);
1675 bfd_set_section_vma (abfd, si->sec, vma);
1677 /* vma += si->size;*/
1680 /* Write them out */
1681 for (i = 0; i < NSECS; i++)
1683 sinfo *si = secdata + i;
1685 if (i == IDATA5 && no_idata5)
1688 if (i == IDATA4 && no_idata4)
1691 bfd_set_section_contents (abfd, si->sec,
1696 bfd_set_symtab (abfd, ptrs, oidx);
1698 abfd = bfd_openr (outname, HOW_BFD_TARGET);
1708 FILE * f = fopen ("dh.s", FOPEN_WT);
1710 fprintf (f, "%s IMAGE_IMPORT_DESCRIPTOR\n", ASM_C);
1711 fprintf (f, "\t.section .idata$2\n");
1713 fprintf(f,"\t%s\t%s\n", ASM_GLOBAL,head_label);
1715 fprintf (f, "%s:\n", head_label);
1717 fprintf (f, "\t%shname%s\t%sPtr to image import by name list\n",
1718 ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C);
1720 fprintf (f, "\t%sthis should be the timestamp, but NT sometimes\n", ASM_C);
1721 fprintf (f, "\t%sdoesn't load DLLs when this is set.\n", ASM_C);
1722 fprintf (f, "\t%s\t0\t%s loaded time\n", ASM_LONG, ASM_C);
1723 fprintf (f, "\t%s\t0\t%s Forwarder chain\n", ASM_LONG, ASM_C);
1724 fprintf (f, "\t%s__%s_iname%s\t%s imported dll's name\n",
1729 fprintf (f, "\t%sfthunk%s\t%s pointer to firstthunk\n",
1731 ASM_RVA_AFTER, ASM_C);
1733 fprintf (f, "%sStuff for compatibility\n", ASM_C);
1737 fprintf (f, "\t.section\t.idata$5\n");
1738 fprintf (f, "\t%s\t0\n", ASM_LONG);
1739 fprintf (f, "fthunk:\n");
1743 fprintf (f, "\t.section\t.idata$4\n");
1745 fprintf (f, "\t%s\t0\n", ASM_LONG);
1746 fprintf (f, "\t.section .idata$4\n");
1747 fprintf (f, "hname:\n");
1751 sprintf (outfile, "-o dh.o dh.s");
1752 run (as_name, outfile);
1754 return bfd_openr ("dh.o", HOW_BFD_TARGET);
1760 FILE * f = fopen ("dt.s", FOPEN_WT);
1763 /* Other PowerPC NT compilers use idata$6 for the dllname, so I
1764 do too. Original, huh? */
1765 fprintf (f, "\t.section .idata$6\n");
1767 fprintf (f, "\t.section .idata$7\n");
1770 fprintf (f, "\t%s\t__%s_iname\n", ASM_GLOBAL, imp_name_lab);
1771 fprintf (f, "__%s_iname:\t%s\t\"%s\"\n",
1772 imp_name_lab, ASM_TEXT, dll_name);
1776 fprintf (f, "\t.section .idata$4\n");
1777 fprintf (f, "\t%s\t0\n", ASM_LONG);
1781 fprintf (f, "\t.section .idata$5\n");
1782 fprintf (f, "\t%s\t0\n", ASM_LONG);
1787 /* Normally, we need to see a null descriptor built in idata$3 to
1788 act as the terminator for the list. The ideal way, I suppose,
1789 would be to mark this section as a comdat type 2 section, so
1790 only one would appear in the final .exe (if our linker supported
1791 comdat, that is) or cause it to be inserted by something else (say
1795 fprintf (f, "\t.section .idata$3\n");
1796 fprintf (f, "\t%s\t0\n", ASM_LONG);
1797 fprintf (f, "\t%s\t0\n", ASM_LONG);
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);
1805 sprintf (outfile, "-o dt.o dt.s");
1806 run (as_name, outfile);
1807 return bfd_openr ("dt.o", HOW_BFD_TARGET);
1822 outarch = bfd_openw (imp_name, HOW_BFD_TARGET);
1826 fprintf (stderr, "%s: Can't open .lib file %s\n", program_name, imp_name);
1829 bfd_set_format (outarch, bfd_archive);
1830 outarch->has_armap = 1;
1832 /* Work out a reasonable size of things to put onto one line. */
1836 ar_head = make_head ();
1837 ar_tail = make_tail();
1839 for (i = 0; (exp = d_exports_lexically[i]); i++)
1841 bfd *n = make_one_lib_file (exp, i);
1847 /* Now stick them all into the archive */
1849 ar_head->next = head;
1850 ar_tail->next = ar_head;
1853 bfd_set_archive_head (outarch, head);
1854 bfd_close (outarch);
1856 /* Delete all the temp files */
1858 if (dontdeltemps == 0)
1860 sprintf (outfile, "dh.o");
1862 sprintf (outfile, "dh.s");
1864 sprintf (outfile, "dt.o");
1866 sprintf (outfile, "dt.s");
1870 if (dontdeltemps < 2)
1871 for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
1873 sprintf (outfile, "ds%d.o",i);
1878 /**********************************************************************/
1880 /* Run through the information gathered from the .o files and the
1881 .def file and work out the best stuff */
1887 export_type *ap = *(export_type **) a;
1888 export_type *bp = *(export_type **) b;
1889 if (ap->ordinal == bp->ordinal)
1892 /* unset ordinals go to the bottom */
1893 if (ap->ordinal == -1)
1895 if (bp->ordinal == -1)
1897 return (ap->ordinal - bp->ordinal);
1906 export_type *ap = *(export_type **) a;
1907 export_type *bp = *(export_type **) b;
1909 return (strcmp (ap->name, bp->name));
1914 remove_null_names (ptr)
1919 for (dst = src = 0; src < d_nfuncs; src++)
1923 ptr[dst] = ptr[src];
1936 for (i = 0; i < d_nfuncs; i++)
1940 printf ("%d %s @ %d %s%s\n",
1941 i, ptr[i]->name, ptr[i]->ordinal,
1942 ptr[i]->noname ? "NONAME " : "",
1943 ptr[i]->constant ? "CONSTANT" : "");
1952 process_duplicates (d_export_vec)
1953 export_type **d_export_vec;
1961 /* Remove duplicates */
1962 qsort (d_export_vec, d_nfuncs, sizeof (export_type *), nfunc);
1964 dtab (d_export_vec);
1965 for (i = 0; i < d_nfuncs - 1; i++)
1967 if (strcmp (d_export_vec[i]->name,
1968 d_export_vec[i + 1]->name) == 0)
1971 export_type *a = d_export_vec[i];
1972 export_type *b = d_export_vec[i + 1];
1976 fprintf (stderr, "Warning, ignoring duplicate EXPORT %s %d,%d\n",
1980 if (a->ordinal != -1
1981 && b->ordinal != -1)
1984 fprintf (stderr, "Error, duplicate EXPORT with oridinals %s\n",
1988 /* Merge attributes */
1989 b->ordinal = a->ordinal > 0 ? a->ordinal : b->ordinal;
1990 b->constant |= a->constant;
1991 b->noname |= a->noname;
1992 d_export_vec[i] = 0;
1995 dtab (d_export_vec);
1996 remove_null_names (d_export_vec);
1997 dtab (d_export_vec);
2002 /* Count the names */
2003 for (i = 0; i < d_nfuncs; i++)
2005 if (!d_export_vec[i]->noname)
2011 fill_ordinals (d_export_vec)
2012 export_type **d_export_vec;
2018 qsort (d_export_vec, d_nfuncs, sizeof (export_type *), pfunc);
2020 /* fill in the unset ordinals with ones from our range */
2022 ptr = (char *) malloc (65536);
2024 memset (ptr, 0, 65536);
2026 /* Mark in our large vector all the numbers that are taken */
2027 for (i = 0; i < d_nfuncs; i++)
2029 if (d_export_vec[i]->ordinal != -1)
2031 ptr[d_export_vec[i]->ordinal] = 1;
2033 lowest = d_export_vec[i]->ordinal;
2037 /* Start at 1 for compatibility with MS toolchain. */
2041 for (i = 0; i < d_nfuncs; i++)
2043 if (d_export_vec[i]->ordinal == -1)
2046 for (j = lowest; j < 65536; j++)
2050 d_export_vec[i]->ordinal = j;
2054 for (j = 1; j < lowest; j++)
2058 d_export_vec[i]->ordinal = j;
2070 qsort (d_export_vec, d_nfuncs, sizeof (export_type *), pfunc);
2072 /* Work out the lowest and highest ordinal numbers. */
2075 if (d_export_vec[0])
2076 d_low_ord = d_export_vec[0]->ordinal;
2077 if (d_export_vec[d_nfuncs-1])
2078 d_high_ord = d_export_vec[d_nfuncs-1]->ordinal;
2082 int alphafunc(av,bv)
2086 export_type **a = av;
2087 export_type **b = bv;
2089 return strcmp ((*a)->name, (*b)->name);
2095 /* First work out the minimum ordinal chosen */
2101 export_type **d_export_vec
2102 = (export_type **) xmalloc (sizeof (export_type *) * d_nfuncs);
2104 for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
2106 d_export_vec[i] = exp;
2109 process_duplicates (d_export_vec);
2110 fill_ordinals (d_export_vec);
2112 /* Put back the list in the new order */
2114 for (i = d_nfuncs - 1; i >= 0; i--)
2116 d_export_vec[i]->next = d_exports;
2117 d_exports = d_export_vec[i];
2120 /* Build list in alpha order */
2121 d_exports_lexically = (export_type **)xmalloc (sizeof(export_type *)*(d_nfuncs+1));
2123 for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
2125 d_exports_lexically[i] = exp;
2127 d_exports_lexically[i] = 0;
2129 qsort (d_exports_lexically, i, sizeof (export_type *), alphafunc);
2131 /* Fill exp entries with their hint values */
2133 for (i = 0; i < d_nfuncs; i++)
2135 if (!d_exports_lexically[i]->noname || show_allnames)
2136 d_exports_lexically[i]->hint = hint++;
2146 /**********************************************************************/
2149 usage (file, status)
2153 fprintf (file, "Usage %s <options> <object-files>\n", program_name);
2154 fprintf (file, " --machine <machine>\n");
2155 fprintf (file, " --output-exp <outname> Generate export file.\n");
2156 fprintf (file, " --output-lib <outname> Generate input library.\n");
2157 fprintf (file, " --add-indirect Add dll indirects to export file.\n");
2158 fprintf (file, " --dllname <name> Name of input dll to put into output lib.\n");
2159 fprintf (file, " --def <deffile> Name input .def file\n");
2160 fprintf (file, " --output-def <deffile> Name output .def file\n");
2161 fprintf (file, " --base-file <basefile> Read linker generated base file\n");
2162 fprintf (file, " --no-idata4 Don't generate idata$4 section\n");
2163 fprintf (file, " --no-idata5 Don't generate idata$5 section\n");
2164 fprintf (file, " -v Verbose\n");
2165 fprintf (file, " -U Add underscores to .lib\n");
2166 fprintf (file, " -k Kill @<n> from exported names\n");
2167 fprintf (file, " --as <name> Use <name> for assembler\n");
2168 fprintf (file, " --nodelete Keep temp files.\n");
2172 #define OPTION_NO_IDATA4 'x'
2173 #define OPTION_NO_IDATA5 'c'
2174 static struct option long_options[] =
2176 {"nodelete", no_argument, NULL, 'n'},
2177 {"dllname", required_argument, NULL, 'D'},
2178 {"no-idata4", no_argument, NULL, OPTION_NO_IDATA4},
2179 {"no-idata5", no_argument, NULL, OPTION_NO_IDATA5},
2180 {"output-exp", required_argument, NULL, 'e'},
2181 {"output-def", required_argument, NULL, 'z'},
2182 {"output-lib", required_argument, NULL, 'l'},
2183 {"def", required_argument, NULL, 'd'},
2184 {"add-underscore", no_argument, NULL, 'U'},
2185 {"killat", no_argument, NULL, 'k'},
2186 {"help", no_argument, NULL, 'h'},
2187 {"machine", required_argument, NULL, 'm'},
2188 {"add-indirect", no_argument, NULL, 'a'},
2189 {"base-file", required_argument, NULL, 'b'},
2190 {"as", required_argument, NULL, 'S'},
2204 program_name = av[0];
2207 while ((c = getopt_long (ac, av, "xcz:S:R:A:puaD:l:e:nkvbUh?m:yd:", long_options, 0))
2212 case OPTION_NO_IDATA4:
2215 case OPTION_NO_IDATA5:
2222 /* ignored for compatibility */
2229 output_def = fopen (optarg, FOPEN_WT);
2266 base_file = fopen (optarg, FOPEN_RB);
2269 fprintf (stderr, "%s: Unable to open base-file %s\n",
2281 for (i = 0; mtable[i].type; i++)
2283 if (strcmp (mtable[i].type, mname) == 0)
2287 if (!mtable[i].type)
2289 fprintf (stderr, "Machine not supported\n");
2295 if (!dll_name && exp_name)
2297 char len = strlen (exp_name) + 5;
2298 dll_name = xmalloc (len);
2299 strcpy (dll_name, exp_name);
2300 strcat (dll_name, ".dll");
2305 process_def_file (def_file);
2310 firstarg = av[optind];
2311 scan_obj_file (av[optind]);
2322 /* Make imp_name safe for use as a label. */
2324 imp_name_lab = strdup (imp_name);
2325 for (p = imp_name_lab; *p; *p++)
2327 if (!isalpha (*p) && !isdigit (*p))
2330 head_label = make_label("_head_", imp_name_lab);