1 /* dlltool.c -- tool to generate stuff for PE style DLLs
2 Copyright (C) 1995 Free Software Foundation, Inc.
4 This file is part of GNU Binutils.
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
22 This program allows you to build the files necessary to create
23 DLLs to run on a system which understands PE format image files.
26 A DLL contains an export table which contains the information
27 which the runtime loader needs to tie up references from a
30 The export table is generated by this program by reading
31 in a .DEF file or scanning the .a and .o files which will be in the
32 DLL. A .o file can contain information in special ".drective" sections
33 with export information.
35 A DEF file contains any number of the following commands:
38 NAME <name> [ , <base> ]
39 The result is going to be <name>.EXE
41 LIBRARY <name> [ , <base> ]
42 The result is going to be <name>.DLL
44 EXPORTS ( <name1> [ = <name2> ] [ @ <integer> ] [ NONAME ] [CONSTANT] ) *
45 Declares name1 as an exported symbol from the
46 DLL, with optional ordinal number <integer>
48 IMPORTS ( [ <name> = ] <name> . <name> ) *
49 Ignored for compatibility
52 Puts <string> into output .exp file in the .rdata section
54 [STACKSIZE|HEAPSIZE] <number-reserve> [ , <number-commit> ]
55 Generates --stack|--heap <number-reserve>,<number-commit>
56 in the output .drective section. The linker will
57 see this and act upon it.
60 SECTIONS ( <sectionname> <attr>+ )*
61 <attr> = READ | WRITE | EXECUTE | SHARED
62 Generates --attr <sectionname> <attr> in the output
63 .drective section. The linker will see this and act
67 A -export:<name> in a .drective section in an input .o or .a
68 file to this program is equivalent to a EXPORTS <name>
73 The program generates output files with the prefix supplied
74 on the command line, or in the def file, or taken from the first
77 The .exp.s file contains the information necessary to export
78 the routines in the DLL. The .lib.s file contains the information
79 necessary to use the DLL's routines from a referencing program.
86 asm (".section .drectve");
87 asm (".ascii \"-export:adef\"");
91 printf("hello from the dll %s\n",s);
96 printf("hello from the dll and the other entry point %s\n",s);
100 asm (".section .drectve");
101 asm (".ascii \"-export:cdef\"");
102 asm (".ascii \"-export:ddef\"");
105 printf("hello from the dll %s\n",s);
110 printf("hello from the dll and the other entry point %s\n",s);
128 HEAPSIZE 0x40000, 0x2000
132 SECTIONS donkey READ WRITE
136 # compile up the parts of the dll
141 # put them in a library (you don't have to, you
142 # could name all the .os on the dlltool line)
144 ar qcv thedll.in file1.o file2.o
147 # run this tool over the library and the def file
148 ./dlltool --def thedll.def --output-exp thedll.o --output-lib thedll.a
150 # build the dll with the library with file1.o, file2.o and the export table
151 ld -o thedll.dll thedll.o thedll.in
156 # link the executable with the import library
157 ld -e main -Tthemain.ld -o themain.exe themain.o thedll.a
161 #define PAGE_SIZE 4096
162 #define PAGE_MASK (-PAGE_SIZE)
170 char *ar_name = "ar";
171 char *as_name = "as";
172 char *ranlib_name = "ranlib";
178 int dontdeltemps = 0;
194 static char *mname = "arm";
198 static char *mname = "i386";
200 #define PATHMAX 250 /* What's the right name for this ? */
202 char outfile[PATHMAX];
214 char *how_align_short;
222 "arm", ".byte", ".short", ".long", ".asciz", "@", "ldr\tip,[pc]\n\tldr\tpc,[ip]\n\t.long", ".global", ".space", ".align\t2",
227 "i386", ".byte", ".short", ".long", ".asciz", "#", "jmp *", ".global", ".space", ".align\t2",
235 char *rvaafter (machine)
247 char *rvabefore (machine)
258 #define ASM_BYTE mtable[machine].how_byte
259 #define ASM_SHORT mtable[machine].how_short
260 #define ASM_LONG mtable[machine].how_long
261 #define ASM_TEXT mtable[machine].how_asciz
262 #define ASM_C mtable[machine].how_comment
263 #define ASM_JUMP mtable[machine].how_jump
264 #define ASM_GLOBAL mtable[machine].how_global
265 #define ASM_SPACE mtable[machine].how_space
266 #define ASM_ALIGN_SHORT mtable[machine].how_align_short
267 #define ASM_RVA_BEFORE rvabefore(machine)
268 #define ASM_RVA_AFTER rvaafter(machine)
274 FILE *yyin; /* communications with flex */
275 extern int linenumber;
277 process_def_file (name)
280 FILE *f = fopen (name, "r");
283 fprintf (stderr, "%s: Can't open def file %s\n", program_name, name);
292 /**********************************************************************/
294 /* Communications with the parser */
304 typedef struct export
315 static char *d_name; /* Arg to NAME or LIBRARY */
316 static int d_nfuncs; /* Number of functions exported */
317 static int d_ord; /* Base ordinal index */
318 static export_type *d_exports; /*list of exported functions */
319 static dlist_type *d_list; /* Descriptions */
320 static dlist_type *a_list; /* Stuff to go in directives */
327 fprintf (stderr, "%s: Syntax error in def file %s:%d\n",
328 program_name, def_file, linenumber);
332 def_exports (name, internal_name, ordinal, noname, constant)
339 struct export *p = (struct export *) xmalloc (sizeof (*p));
342 p->internal_name = internal_name ? internal_name : name;
343 p->ordinal = ordinal;
344 p->constant = constant;
353 def_name (name, base)
358 fprintf (stderr, "%s NAME %s base %x\n", program_name, name, base);
361 fprintf (stderr, "Can't have LIBRARY and NAME\n");
368 def_library (name, base)
373 printf ("%s: LIBRARY %s base %x\n", program_name, name, base);
376 fprintf (stderr, "%s: Can't have LIBRARY and NAME\n", program_name);
383 def_description (desc)
386 dlist_type *d = (dlist_type *) xmalloc (sizeof (dlist_type));
387 d->text = strdup (desc);
396 dlist_type *d = (dlist_type *) xmalloc (sizeof (dlist_type));
397 d->text = strdup (dir);
403 def_stacksize (reserve, commit)
409 sprintf (b, "-stack 0x%x,0x%x ", reserve, commit);
411 sprintf (b, "-stack 0x%x ", reserve);
412 new_directive (strdup (b));
416 def_heapsize (reserve, commit)
422 sprintf (b, "-heap 0x%x,0x%x ", reserve, commit);
424 sprintf (b, "-heap 0x%x ", reserve);
425 new_directive (strdup (b));
430 def_import (internal, module, entry)
436 fprintf (stderr, "%s: IMPORTS are ignored", program_name);
440 def_version (major, minor)
442 printf ("VERSION %d.%d\n", major, minor);
447 def_section (name, attr)
464 sprintf (buf, "-attr %s %s", name, atts);
465 new_directive (strdup (buf));
472 def_section ("CODE", attr);
479 def_section ("DATA", attr);
483 /**********************************************************************/
494 extern char **environ;
496 fprintf (stderr, "%s %s\n", what, args);
500 for (s = args; *s ; s++)
504 argv = alloca (sizeof (char *) * (i + 3));
510 while (*s != ' ' && *s != 0)
523 fprintf (stderr, "%s: can't exec %s\n", program_name, what);
529 fprintf (stderr, "%s: vfork failed, %d\n", program_name, errno);
535 waitpid (pid, &status, 0);
538 if (WIFSIGNALED (status))
540 fprintf (stderr, "%s: %s %s terminated with signal %d\n",
541 program_name, what, args, WTERMSIG (status));
545 if (WIFEXITED (status))
547 fprintf (stderr, "%s: %s %s terminated with exit status %d\n",
548 program_name, what, args, WEXITSTATUS (status));
555 /* read in and block out the base relocations */
567 scan_open_obj_file (abfd)
570 /* Look for .drectives */
571 asection *s = bfd_get_section_by_name (abfd, ".drectve");
574 int size = bfd_get_section_size_before_reloc (s);
575 char *buf = xmalloc (size);
578 bfd_get_section_contents (abfd, s, buf, 0, size);
580 fprintf (stderr, "%s: Sucking in info from %s\n",
582 bfd_get_filename (abfd));
584 /* Search for -export: strings */
590 && strncmp (p, "-export:", 8) == 0)
596 while (*p != ' ' && *p != '-' && p < e)
598 c = xmalloc (p - name + 1);
599 memcpy (c, name, p - name);
601 def_exports (c, 0, -1, 0);
612 fprintf (stderr, "%s: Done readin\n",
619 scan_obj_file (filename)
622 bfd *f = bfd_openr (filename, 0);
626 fprintf (stderr, "%s: Unable to open object file %s\n",
631 if (bfd_check_format (f, bfd_archive))
633 bfd *arfile = bfd_openr_next_archived_file (f, 0);
636 if (bfd_check_format (arfile, bfd_object))
637 scan_open_obj_file (arfile);
639 arfile = bfd_openr_next_archived_file (f, arfile);
643 if (bfd_check_format (f, bfd_object))
645 scan_open_obj_file (f);
651 /**********************************************************************/
654 /* return the bit of the name before the last . */
661 char *res = strdup (name);
662 char *p = strrchr (res, '.');
674 fprintf (f, "%s ", ASM_C);
675 for (i = 0; oav[i]; i++)
676 fprintf (f, "%s ", oav[i]);
678 for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
680 fprintf (f, "%s %d = %s %s @ %d %s%s\n",
686 exp->noname ? "NONAME " : "",
687 exp->constant ? "CONSTANT" : "");
690 /* Generate the .exp file */
703 flush_page (f, need, page_addr, on_page)
710 /* Flush this page */
711 fprintf (f, "\t%s\t0x%08x\t%s Starting RVA for chunk\n",
715 fprintf (f, "\t%s\t0x%x\t%s Size of block\n",
717 (on_page * 2) + (on_page & 1) * 2 + 8,
719 for (i = 0; i < on_page; i++)
721 fprintf (f, "\t%s\t0x%x\n", ASM_SHORT, need[i] - page_addr | 0x3000);
725 fprintf (f, "\t%s\t0x%x\n", ASM_SHORT, 0 | 0x0000);
739 sprintf (outfile, "t%s", exp_name);
742 fprintf (stderr, "%s: Generate exp file %s\n",
743 program_name, exp_name);
745 f = fopen (outfile, "w");
748 fprintf (stderr, "%s: Unable to open output file %s\n", program_name, outfile);
753 fprintf (stderr, "%s: Opened file %s\n",
754 program_name, outfile);
759 fprintf (f, "\t.section .edata\n\n");
760 fprintf (f, "\t%s 0 %s Allways 0\n", ASM_LONG, ASM_C);
761 fprintf (f, "\t%s %d %s Time and date\n", ASM_LONG, time (0), ASM_C);
762 fprintf (f, "\t%s 0 %s Major and Minor version\n", ASM_LONG, ASM_C);
763 fprintf (f, "\t%sname%s%s Ptr to name of dll\n", ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C);
764 fprintf (f, "\t%s %d %s Starting ordinal of exports\n", ASM_LONG, d_ord, ASM_C);
765 fprintf (f, "\t%s The next field is documented as being the number of functions\n", ASM_C);
766 fprintf (f, "\t%s yet it doesn't look like that in real PE dlls\n", ASM_C);
767 fprintf (f, "\t%s But it shouldn't be a problem, causes there's\n", ASM_C);
768 fprintf (f, "\t%s always the number of names field\n", ASM_C);
769 fprintf (f, "\t%s %d %s Number of functions\n", ASM_LONG, d_nfuncs, ASM_C);
770 fprintf (f, "\t%s %d %s Number of names\n", ASM_LONG, d_nfuncs, ASM_C);
771 fprintf (f, "\t%safuncs%s %s Address of functions\n", ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C);
772 fprintf (f, "\t%sanames%s %s Address of names\n", ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C);
773 fprintf (f, "\t%sanords%s %s Address of ordinals\n", ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C);
775 fprintf (f, "name: %s \"%s\"\n", ASM_TEXT, dll_name);
777 fprintf (f, "afuncs:\n");
779 for (exp = d_exports; exp; exp = exp->next)
782 /* This seems necessary in the doc, but in real
783 life it's not used.. */
784 if (exp->ordinal != i)
786 fprintf (f, "%s\t%s\t%d\t@ %d..%d missing\n", ASM_C, ASM_SPACE,
787 (exp->ordinal - i) * 4,
788 i, exp->ordinal - 1);
792 fprintf (f, "\t%s%s%s%s %d\n",ASM_RVA_BEFORE,
793 exp->internal_name, ASM_RVA_AFTER, ASM_C, exp->ordinal);
798 fprintf (f, "anames:\n");
799 for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
804 fprintf (f, "\t%s nNoname\n", ASM_LONG, ASM_C);
808 fprintf (f, "\t%sn%d%s\n", ASM_RVA_BEFORE, i, ASM_RVA_AFTER);
812 fprintf (f, "anords:\n");
813 for (exp = d_exports; exp; exp = exp->next)
814 fprintf (f, "\t%s %d\n", ASM_SHORT, exp->ordinal - d_ord);
816 for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
818 fprintf (f, "@n%d: %s \"%s\"\n", i, ASM_TEXT, exp->name);
820 fprintf (f, "n%d: %s \"%s\"\n", i, ASM_TEXT, exp->name);
823 fprintf (f, "nNoname: %s \"__noname__\"\n", ASM_TEXT);
827 fprintf (f, "\t.section .drectve\n");
828 for (dl = a_list; dl; dl = dl->next)
830 fprintf (f, "\t%s\t\"%s\"\n", ASM_TEXT, dl->text);
835 fprintf (f, "\t.section .rdata\n");
836 for (dl = d_list; dl; dl = dl->next)
840 /* We dont output as ascii 'cause there can
841 be quote characters in the string */
844 for (p = dl->text; *p; p++)
847 fprintf (f, "\t%s\t", ASM_BYTE);
850 fprintf (f, "%d", *p);
866 /* Dump the reloc section if a base file is provided */
870 long need[PAGE_SIZE];
877 fprintf (f,"\t.section\t.init\n");
878 fprintf (f,"lab:\n");
879 fprintf (f, "\t.section\t.reloc\n");
880 fseek (base_file, 0, SEEK_END);
881 numbytes = ftell (base_file);
882 fseek (base_file, 0, SEEK_SET);
883 copy = malloc (numbytes);
884 fread (copy, 1, numbytes, base_file);
885 num_entries = numbytes / sizeof (long);
887 qsort (copy, num_entries, sizeof (long), sfunc);
890 page_addr = addr & PAGE_MASK; /* work out the page addr */
892 for (j = 0; j < num_entries; j++)
895 if ((addr & PAGE_MASK) != page_addr)
897 flush_page (f, need, page_addr, on_page);
899 page_addr = addr & PAGE_MASK;
901 need[on_page++] = addr;
903 flush_page (f, need, page_addr, on_page);
905 fprintf (f, "\t%s\t0,0\t%s End\n", ASM_LONG, ASM_C);
910 /* assemble the file */
911 sprintf (outfile,"-o %s t%s", exp_name, exp_name);
912 run (as_name, outfile);
915 sprintf (outfile,"t%s", exp_name);
932 p = strchr (name, '@');
940 /**********************************************************************/
947 char *output_filename;
948 char prefix[PATHMAX];
950 sprintf (outfile, "%s", imp_name);
951 output_filename = strdup (outfile);
953 unlink (output_filename);
955 strcpy (prefix, "d");
956 sprintf (outfile, "%sh.s", prefix);
958 f = fopen (outfile, "w");
960 fprintf (f, "%s IMAGE_IMPORT_DESCRIPTOR\n", ASM_C);
961 fprintf (f, "\t.section .idata$2\n");
963 fprintf (f, "\t%s\t__%s_head\n", ASM_GLOBAL, imp_name);
964 fprintf (f, "__%s_head:\n", imp_name);
966 fprintf (f, "\t%shname%s\t%sPtr to image import by name list\n",
967 ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C);
968 fprintf (f, "\t%sthis should be the timestamp, but NT sometimes\n", ASM_C);
969 fprintf (f, "\t%sdoesn't load DLLs when this is set.\n", ASM_C);
970 fprintf (f, "\t%s\t0\t%s time\n", ASM_LONG, ASM_C);
971 fprintf (f, "\t%s\t0\t%s Forwarder chain\n", ASM_LONG, ASM_C);
972 fprintf (f, "\t%s__%s_iname%s\t%s imported dll's name\n",
977 fprintf (f, "\t%sfthunk%s\t%s pointer to firstthunk\n",
979 ASM_RVA_AFTER, ASM_C);
981 fprintf (f, "%sStuff for compatibility\n", ASM_C);
982 fprintf (f, "\t.section\t.idata$5\n");
983 fprintf (f, "\t%s\t0\n", ASM_LONG);
984 fprintf (f, "fthunk:\n");
985 fprintf (f, "\t.section\t.idata$4\n");
986 fprintf (f, "\t%s\t0\n", ASM_LONG);
987 fprintf (f, "\t.section .idata$4\n");
988 fprintf (f, "hname:\n");
992 sprintf (outfile, "-o %sh.o %sh.s", prefix, prefix);
993 run (as_name, outfile);
995 for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
997 sprintf (outfile, "%ss%d.s", prefix, i);
998 f = fopen (outfile, "w");
999 fprintf (f, "\n\n\n%s ********************* \n", ASM_C);
1000 fprintf (f, "\t.text\n");
1001 fprintf (f, "\t%s\t%s\n", ASM_GLOBAL, exp->name);
1002 fprintf (f, "\t%s\t__imp_%s\n", ASM_GLOBAL, exp->name);
1003 fprintf (f, "%s:\n\t%s\t__imp_%s\n", exp->name, ASM_JUMP, exp->name);
1005 fprintf (f, "\t.section\t.idata$7\t%s To force loading of head\n", ASM_C);
1006 fprintf (f, "\t%s\t__%s_head\n", ASM_LONG, imp_name);
1007 fprintf (f, "\t.section .idata$5\n");
1010 fprintf (f, "__imp_%s:\n", exp->name);
1011 fprintf (f, "\t%sID%d%s\n",
1016 fprintf (f, "\n%s Hint name array\n", ASM_C);
1017 fprintf (f, "\t.section .idata$4\n");
1018 fprintf (f, "\t%sID%d%s\n", ASM_RVA_BEFORE,
1022 fprintf (f, "%s Hint/name array storage and import dll name\n", ASM_C);
1023 fprintf (f, "\t.section .idata$6\n");
1025 fprintf (f, "\t%s\n", ASM_ALIGN_SHORT);
1026 fprintf (f, "ID%d:\t%s\t%d\n", i, ASM_SHORT, exp->ordinal);
1027 fprintf (f, "\t%s\t\"%s\"\n", ASM_TEXT, xlate (exp->name));
1031 sprintf (outfile, "-o %ss%d.o %ss%d.s", prefix, i, prefix, i);
1032 run (as_name, outfile);
1035 sprintf (outfile, "%st.s", prefix);
1036 f = fopen (outfile, "w");
1037 fprintf (f, "\t.section .idata$7\n");
1038 fprintf (f, "\t%s\t__%s_iname\n", ASM_GLOBAL, imp_name);
1039 fprintf (f, "__%s_iname:\t%s\t\"%s\"\n",
1040 imp_name, ASM_TEXT, dll_name);
1043 fprintf (f, "\t.section .idata$4\n");
1044 fprintf (f, "\t%s\t0\n", ASM_LONG);
1046 fprintf (f, "\t.section .idata$5\n");
1047 fprintf (f, "\t%s\t0\n", ASM_LONG);
1050 sprintf (outfile, "-o %st.o %st.s", prefix, prefix);
1051 run (as_name, outfile);
1053 /* Now stick them all into the archive */
1056 sprintf (outfile, "crs %s %sh.o %st.o", output_filename, prefix, prefix);
1057 run (ar_name, outfile);
1059 /* Do the rest in groups of however many fit into a command line */
1061 for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
1065 sol = sprintf (outfile, "crs %s", output_filename);
1068 sol += sprintf (outfile + sol, " %ss%d.o", prefix, i);
1072 run (ar_name, outfile);
1078 run (ar_name, outfile);
1080 /* Delete all the temp files */
1082 if (dontdeltemps == 0)
1084 sprintf (outfile, "%sh.o", prefix);
1086 sprintf (outfile, "%sh.s", prefix);
1088 sprintf (outfile, "%st.o", prefix);
1090 sprintf (outfile, "%st.s", prefix);
1094 if (dontdeltemps < 2)
1095 for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
1097 sprintf (outfile, "%ss%d.o", prefix, i);
1099 sprintf (outfile, "%ss%d.s", prefix, i);
1104 /**********************************************************************/
1106 /* Run through the information gathered from the .o files and the
1107 .def file and work out the best stuff */
1113 export_type *ap = *(export_type **) a;
1114 export_type *bp = *(export_type **) b;
1115 if (ap->ordinal == bp->ordinal)
1118 /* unset ordinals go to the bottom */
1119 if (ap->ordinal == -1)
1121 if (bp->ordinal == -1)
1123 return (ap->ordinal - bp->ordinal);
1132 export_type *ap = *(export_type **) a;
1133 export_type *bp = *(export_type **) b;
1135 return (strcmp (ap->name, bp->name));
1140 remove_null_names (ptr)
1145 for (dst = src = 0; src < d_nfuncs; src++)
1149 ptr[dst] = ptr[src];
1162 for (i = 0; i < d_nfuncs; i++)
1166 printf ("%d %s @ %d %s%s\n",
1167 i, ptr[i]->name, ptr[i]->ordinal,
1168 ptr[i]->noname ? "NONAME " : "",
1169 ptr[i]->constant ? "CONSTANT" : "");
1178 process_duplicates (d_export_vec)
1179 export_type **d_export_vec;
1186 /* Remove duplicates */
1187 qsort (d_export_vec, d_nfuncs, sizeof (export_type *), nfunc);
1189 dtab (d_export_vec);
1190 for (i = 0; i < d_nfuncs - 1; i++)
1192 if (strcmp (d_export_vec[i]->name,
1193 d_export_vec[i + 1]->name) == 0)
1196 export_type *a = d_export_vec[i];
1197 export_type *b = d_export_vec[i + 1];
1201 fprintf (stderr, "Warning, ignoring duplicate EXPORT %s %d,%d\n",
1205 if (a->ordinal != -1
1206 && b->ordinal != -1)
1209 fprintf (stderr, "Error, duplicate EXPORT with oridinals %s\n",
1213 /* Merge attributes */
1214 b->ordinal = a->ordinal > 0 ? a->ordinal : b->ordinal;
1215 b->constant |= a->constant;
1216 b->noname |= a->noname;
1217 d_export_vec[i] = 0;
1220 dtab (d_export_vec);
1221 remove_null_names (d_export_vec);
1222 dtab (d_export_vec);
1228 fill_ordinals (d_export_vec)
1229 export_type **d_export_vec;
1234 qsort (d_export_vec, d_nfuncs, sizeof (export_type *), pfunc);
1236 /* fill in the unset ordinals with ones from our range */
1238 ptr = (char *) malloc (65536);
1240 memset (ptr, 65536, 0);
1242 /* Mark in our large vector all the numbers that are taken */
1243 for (i = 0; i < d_nfuncs; i++)
1245 if (d_export_vec[i]->ordinal != -1)
1247 ptr[d_export_vec[i]->ordinal] = 1;
1249 lowest = d_export_vec[i]->ordinal;
1253 for (i = 0; i < d_nfuncs; i++)
1255 if (d_export_vec[i]->ordinal == -1)
1258 for (j = lowest; j < 65536; j++)
1262 d_export_vec[i]->ordinal = j;
1266 for (j = 1; j < lowest; j++)
1270 d_export_vec[i]->ordinal = j;
1282 qsort (d_export_vec, d_nfuncs, sizeof (export_type *), pfunc);
1284 /* Work out the lowest ordinal number */
1285 if (d_export_vec[0])
1286 d_ord = d_export_vec[0]->ordinal;
1291 /* First work out the minimum ordinal chosen */
1296 export_type **d_export_vec
1297 = (export_type **) xmalloc (sizeof (export_type *) * d_nfuncs);
1299 for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
1301 d_export_vec[i] = exp;
1304 process_duplicates (d_export_vec);
1305 fill_ordinals (d_export_vec);
1307 /* Put back the list in the new order */
1309 for (i = d_nfuncs - 1; i >= 0; i--)
1311 d_export_vec[i]->next = d_exports;
1312 d_exports = d_export_vec[i];
1318 /* Work out exec prefix from the name of this file */
1325 /* See if we're running in a devo tree */
1326 for (p = program_name; *p; p++)
1328 if (*p == '/' || *p == '\\')
1335 if (ps && strncmp (ps, "/binutils", 9) == 0)
1337 /* running in the binutils directory, the other
1338 executables will be surrounding it in the usual places. */
1339 int len = ps - program_name;
1340 ar_name = xmalloc (len + strlen ("/binutils/ar") + 1);
1341 ranlib_name = xmalloc (len + strlen ("/binutils/ranlib") + 1);
1342 as_name = xmalloc (len + strlen ("/gas/as.new") + 1);
1344 memcpy (ar_name, program_name, len);
1345 strcpy (ar_name + len, "/binutils/ar");
1346 memcpy (ranlib_name, program_name, len);
1347 strcpy (ranlib_name + len, "/binutils/ranlib");
1348 memcpy (as_name, program_name, len);
1349 strcpy (as_name + len, "/gas/as.new");
1353 /* Otherwise chop off any prefix and use it for the rest of the progs,
1354 so i386-win32-dll generates i386-win32-ranlib etc etc */
1356 for (p = program_name; *p; p++)
1358 if (strncmp (p, "dlltool", 7) == 0)
1360 int len = p - program_name;
1361 ar_name = xmalloc (len + strlen ("ar") +1);
1362 ranlib_name = xmalloc (len + strlen ("ranlib")+1);
1363 as_name = xmalloc (len + strlen ("as")+1);
1365 memcpy (ar_name, program_name, len);
1366 strcpy (ar_name + len, "ar");
1367 memcpy (ranlib_name, program_name, len);
1368 strcpy (ranlib_name + len, "ranlib");
1369 memcpy (as_name, program_name, len);
1370 strcpy (as_name + len, "as");
1377 /**********************************************************************/
1380 usage (file, status)
1384 fprintf (file, "Usage %s <options> <object-files>\n", program_name);
1385 fprintf (file, " --machine <machine>\n");
1386 fprintf (file, " --output-exp <outname> Generate export file.\n");
1387 fprintf (file, " --output-lib <outname> Generate input library.\n");
1388 fprintf (file, " --dllname <name> Name of input dll to put into output lib.\n");
1389 fprintf (file, " --def <deffile> Name input .def file\n");
1390 fprintf (file, " --base-file <basefile> Read linker generated base file\n");
1391 fprintf (file, " -v Verbose\n");
1392 fprintf (file, " -u Remove leading underscore from .lib\n");
1393 fprintf (file, " -k Kill @<n> from exported names\n");
1394 fprintf (file, " --nodelete Keep temp files.\n");
1398 static struct option long_options[] =
1400 {"nodelete", no_argument, NULL,'n'},
1401 {"dllname", required_argument, NULL,'D'},
1402 {"output-exp", required_argument, NULL, 'e'},
1403 {"output-lib", required_argument, NULL, 'l'},
1404 {"def", required_argument, NULL, 'd'},
1405 {"underscore", no_argument, NULL, 'u'},
1406 {"killat", no_argument, NULL, 'k'},
1407 {"help", no_argument, NULL, 'h'},
1408 {"machine", required_argument, NULL, 'm'},
1409 {"rva", required_argument, NULL, 'r'},
1410 /* {"image-base", required_argument, NULL, 'i'},*/
1411 {"base-file", required_argument, NULL, 'b'},
1424 program_name = av[0];
1427 while ((c = getopt_long (ac, av, "D:l:e:nr:kvbuh?m:yd:", long_options, 0)) != EOF)
1466 base_file = fopen (optarg, "r");
1469 fprintf (stderr, "%s: Unable to open base-file %s\n",
1481 for (i = 0; mtable[i].type; i++)
1483 if (strcmp (mtable[i].type, mname) == 0)
1487 if (!mtable[i].type)
1489 fprintf (stderr, "Machine not supported\n");
1495 if (!dll_name && exp_name)
1497 char len = strlen (exp_name) + 5;
1498 dll_name = xmalloc (len);
1499 strcpy (dll_name, exp_name);
1500 strcat (dll_name, ".dll");
1507 process_def_file (def_file);
1512 firstarg = av[optind];
1513 scan_obj_file (av[optind]);