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 ".drectve" 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 .drectve 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 .drectve section. The linker will see this and act
67 A -export:<name> in a .drectve 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 add_indirect = 0;
180 int dontdeltemps = 0;
196 static char *mname = "arm";
200 static char *mname = "i386";
202 #define PATHMAX 250 /* What's the right name for this ? */
204 char outfile[PATHMAX];
216 char *how_align_short;
223 "arm", ".byte", ".short", ".long", ".asciz", "@", "ldr\tip,[pc]\n\tldr\tpc,[ip]\n\t.long", ".global", ".space", ".align\t2",
228 "i386", ".byte", ".short", ".long", ".asciz", "#", "jmp *", ".global", ".space", ".align\t2",
235 char *rvaafter (machine)
247 char *rvabefore (machine)
259 char *asm_prefix (machine)
269 #define ASM_BYTE mtable[machine].how_byte
270 #define ASM_SHORT mtable[machine].how_short
271 #define ASM_LONG mtable[machine].how_long
272 #define ASM_TEXT mtable[machine].how_asciz
273 #define ASM_C mtable[machine].how_comment
274 #define ASM_JUMP mtable[machine].how_jump
275 #define ASM_GLOBAL mtable[machine].how_global
276 #define ASM_SPACE mtable[machine].how_space
277 #define ASM_ALIGN_SHORT mtable[machine].how_align_short
278 #define ASM_RVA_BEFORE rvabefore(machine)
279 #define ASM_RVA_AFTER rvaafter(machine)
280 #define ASM_PREFIX asm_prefix(machine)
285 FILE *yyin; /* communications with flex */
286 extern int linenumber;
288 process_def_file (name)
291 FILE *f = fopen (name, "r");
294 fprintf (stderr, "%s: Can't open def file %s\n", program_name, name);
303 /**********************************************************************/
305 /* Communications with the parser */
315 typedef struct export
326 static char *d_name; /* Arg to NAME or LIBRARY */
327 static int d_nfuncs; /* Number of functions exported */
328 static int d_ord; /* Base ordinal index */
329 static export_type *d_exports; /*list of exported functions */
330 static dlist_type *d_list; /* Descriptions */
331 static dlist_type *a_list; /* Stuff to go in directives */
338 fprintf (stderr, "%s: Syntax error in def file %s:%d\n",
339 program_name, def_file, linenumber);
343 def_exports (name, internal_name, ordinal, noname, constant)
350 struct export *p = (struct export *) xmalloc (sizeof (*p));
353 p->internal_name = internal_name ? internal_name : name;
354 p->ordinal = ordinal;
355 p->constant = constant;
364 def_name (name, base)
369 fprintf (stderr, "%s NAME %s base %x\n", program_name, name, base);
372 fprintf (stderr, "Can't have LIBRARY and NAME\n");
379 def_library (name, base)
384 printf ("%s: LIBRARY %s base %x\n", program_name, name, base);
387 fprintf (stderr, "%s: Can't have LIBRARY and NAME\n", program_name);
394 def_description (desc)
397 dlist_type *d = (dlist_type *) xmalloc (sizeof (dlist_type));
398 d->text = strdup (desc);
407 dlist_type *d = (dlist_type *) xmalloc (sizeof (dlist_type));
408 d->text = strdup (dir);
414 def_stacksize (reserve, commit)
420 sprintf (b, "-stack 0x%x,0x%x ", reserve, commit);
422 sprintf (b, "-stack 0x%x ", reserve);
423 new_directive (strdup (b));
427 def_heapsize (reserve, commit)
433 sprintf (b, "-heap 0x%x,0x%x ", reserve, commit);
435 sprintf (b, "-heap 0x%x ", reserve);
436 new_directive (strdup (b));
441 def_import (internal, module, entry)
447 fprintf (stderr, "%s: IMPORTS are ignored", program_name);
451 def_version (major, minor)
453 printf ("VERSION %d.%d\n", major, minor);
458 def_section (name, attr)
475 sprintf (buf, "-attr %s %s", name, atts);
476 new_directive (strdup (buf));
483 def_section ("CODE", attr);
490 def_section ("DATA", attr);
494 /**********************************************************************/
505 extern char **environ;
507 fprintf (stderr, "%s %s\n", what, args);
511 for (s = args; *s ; s++)
515 argv = alloca (sizeof (char *) * (i + 3));
521 while (*s != ' ' && *s != 0)
534 fprintf (stderr, "%s: can't exec %s\n", program_name, what);
540 fprintf (stderr, "%s: vfork failed, %d\n", program_name, errno);
546 waitpid (pid, &status, 0);
549 if (WIFSIGNALED (status))
551 fprintf (stderr, "%s: %s %s terminated with signal %d\n",
552 program_name, what, args, WTERMSIG (status));
556 if (WIFEXITED (status))
558 fprintf (stderr, "%s: %s %s terminated with exit status %d\n",
559 program_name, what, args, WEXITSTATUS (status));
566 /* read in and block out the base relocations */
578 scan_open_obj_file (abfd)
581 /* Look for .drectve's */
582 asection *s = bfd_get_section_by_name (abfd, ".drectve");
585 int size = bfd_get_section_size_before_reloc (s);
586 char *buf = xmalloc (size);
589 bfd_get_section_contents (abfd, s, buf, 0, size);
591 fprintf (stderr, "%s: Sucking in info from %s\n",
593 bfd_get_filename (abfd));
595 /* Search for -export: strings */
601 && strncmp (p, "-export:", 8) == 0)
607 while (*p != ' ' && *p != '-' && p < e)
609 c = xmalloc (p - name + 1);
610 memcpy (c, name, p - name);
612 def_exports (c, 0, -1, 0);
623 fprintf (stderr, "%s: Done readin\n",
630 scan_obj_file (filename)
633 bfd *f = bfd_openr (filename, 0);
637 fprintf (stderr, "%s: Unable to open object file %s\n",
642 if (bfd_check_format (f, bfd_archive))
644 bfd *arfile = bfd_openr_next_archived_file (f, 0);
647 if (bfd_check_format (arfile, bfd_object))
648 scan_open_obj_file (arfile);
650 arfile = bfd_openr_next_archived_file (f, arfile);
654 if (bfd_check_format (f, bfd_object))
656 scan_open_obj_file (f);
662 /**********************************************************************/
665 /* return the bit of the name before the last . */
672 char *res = strdup (name);
673 char *p = strrchr (res, '.');
685 fprintf (f, "%s ", ASM_C);
686 for (i = 0; oav[i]; i++)
687 fprintf (f, "%s ", oav[i]);
689 for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
691 fprintf (f, "%s %d = %s %s @ %d %s%s\n",
697 exp->noname ? "NONAME " : "",
698 exp->constant ? "CONSTANT" : "");
701 /* Generate the .exp file */
714 flush_page (f, need, page_addr, on_page)
721 /* Flush this page */
722 fprintf (f, "\t%s\t0x%08x\t%s Starting RVA for chunk\n",
726 fprintf (f, "\t%s\t0x%x\t%s Size of block\n",
728 (on_page * 2) + (on_page & 1) * 2 + 8,
730 for (i = 0; i < on_page; i++)
732 fprintf (f, "\t%s\t0x%x\n", ASM_SHORT, need[i] - page_addr | 0x3000);
736 fprintf (f, "\t%s\t0x%x\n", ASM_SHORT, 0 | 0x0000);
750 sprintf (outfile, "t%s", exp_name);
753 fprintf (stderr, "%s: Generate exp file %s\n",
754 program_name, exp_name);
756 f = fopen (outfile, "w");
759 fprintf (stderr, "%s: Unable to open output file %s\n", program_name, outfile);
764 fprintf (stderr, "%s: Opened file %s\n",
765 program_name, outfile);
770 fprintf (f, "\t.section .edata\n\n");
771 fprintf (f, "\t%s 0 %s Allways 0\n", ASM_LONG, ASM_C);
772 fprintf (f, "\t%s 0 %s Time and date\n", ASM_LONG, ASM_C);
773 fprintf (f, "\t%s 0 %s Major and Minor version\n", ASM_LONG, ASM_C);
774 fprintf (f, "\t%sname%s %s Ptr to name of dll\n", ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C);
775 fprintf (f, "\t%s %d %s Starting ordinal of exports\n", ASM_LONG, d_ord, ASM_C);
776 fprintf (f, "\t%s The next field is documented as being the number of functions\n", ASM_C);
777 fprintf (f, "\t%s yet it doesn't look like that in real PE dlls\n", ASM_C);
778 fprintf (f, "\t%s But it shouldn't be a problem, causes there's\n", ASM_C);
779 fprintf (f, "\t%s always the number of names field\n", ASM_C);
780 fprintf (f, "\t%s %d %s Number of functions\n", ASM_LONG, d_nfuncs, ASM_C);
781 fprintf (f, "\t%s %d %s Number of names\n", ASM_LONG, d_nfuncs, ASM_C);
782 fprintf (f, "\t%safuncs%s %s Address of functions\n", ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C);
783 fprintf (f, "\t%sanames%s %s Address of names\n", ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C);
784 fprintf (f, "\t%sanords%s %s Address of ordinals\n", ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C);
786 fprintf (f, "name: %s \"%s\"\n", ASM_TEXT, dll_name);
788 fprintf (f, "afuncs:\n");
790 for (exp = d_exports; exp; exp = exp->next)
793 /* This seems necessary in the doc, but in real
794 life it's not used.. */
795 if (exp->ordinal != i)
797 fprintf (f, "%s\t%s\t%d\t@ %d..%d missing\n", ASM_C, ASM_SPACE,
798 (exp->ordinal - i) * 4,
799 i, exp->ordinal - 1);
803 fprintf (f, "\t%s%s%s%s\t%s %d\n",ASM_RVA_BEFORE,
805 exp->internal_name, ASM_RVA_AFTER, ASM_C, exp->ordinal);
810 fprintf (f, "anames:\n");
811 for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
816 fprintf (f, "\t%s nNoname\n", ASM_LONG, ASM_C);
820 fprintf (f, "\t%sn%d%s\n", ASM_RVA_BEFORE, i, ASM_RVA_AFTER);
824 fprintf (f, "anords:\n");
825 for (exp = d_exports; exp; exp = exp->next)
826 fprintf (f, "\t%s %d\n", ASM_SHORT, exp->ordinal - d_ord);
828 for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
830 fprintf (f, "@n%d: %s \"%s\"\n", i, ASM_TEXT, exp->name);
832 fprintf (f, "n%d: %s \"%s\"\n", i, ASM_TEXT, exp->name);
835 fprintf (f, "nNoname: %s \"__noname__\"\n", ASM_TEXT);
839 fprintf (f, "\t.section .drectve\n");
840 for (dl = a_list; dl; dl = dl->next)
842 fprintf (f, "\t%s\t\"%s\"\n", ASM_TEXT, dl->text);
847 fprintf (f, "\t.section .rdata\n");
848 for (dl = d_list; dl; dl = dl->next)
852 /* We dont output as ascii 'cause there can
853 be quote characters in the string */
856 for (p = dl->text; *p; p++)
859 fprintf (f, "\t%s\t", ASM_BYTE);
862 fprintf (f, "%d", *p);
879 /* Add to the output file a way of getting to the exported names
880 without using the import library. */
883 fprintf (f,"\t.section\t.rdata\n");
884 for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
886 fprintf (f, "\t%s\t__imp_%s\n", ASM_GLOBAL, exp->name);
887 fprintf (f, "__imp_%s:\n", exp->name);
888 fprintf (f,"\t%s\t%s\n", ASM_LONG, exp->name);
892 /* Dump the reloc section if a base file is provided */
896 long need[PAGE_SIZE];
903 fprintf (f,"\t.section\t.init\n");
904 fprintf (f,"lab:\n");
906 fseek (base_file, 0, SEEK_END);
907 numbytes = ftell (base_file);
908 fseek (base_file, 0, SEEK_SET);
909 copy = malloc (numbytes);
910 fread (copy, 1, numbytes, base_file);
911 num_entries = numbytes / sizeof (long);
914 fprintf (f, "\t.section\t.reloc\n");
915 qsort (copy, num_entries, sizeof (long), sfunc);
918 page_addr = addr & PAGE_MASK; /* work out the page addr */
920 for (j = 0; j < num_entries; j++)
923 if ((addr & PAGE_MASK) != page_addr)
925 flush_page (f, need, page_addr, on_page);
927 page_addr = addr & PAGE_MASK;
929 need[on_page++] = addr;
931 flush_page (f, need, page_addr, on_page);
933 fprintf (f, "\t%s\t0,0\t%s End\n", ASM_LONG, ASM_C);
939 /* assemble the file */
940 sprintf (outfile,"-o %s t%s", exp_name, exp_name);
941 run (as_name, outfile);
944 sprintf (outfile,"t%s", exp_name);
961 p = strchr (name, '@');
968 /**********************************************************************/
976 char *output_filename;
977 char prefix[PATHMAX];
979 sprintf (outfile, "%s", imp_name);
980 output_filename = strdup (outfile);
982 unlink (output_filename);
984 strcpy (prefix, "d");
985 sprintf (outfile, "%sh.s", prefix);
987 f = fopen (outfile, "w");
989 fprintf (f, "%s IMAGE_IMPORT_DESCRIPTOR\n", ASM_C);
990 fprintf (f, "\t.section .idata$2\n");
992 fprintf (f, "\t%s\t__%s_head\n", ASM_GLOBAL, imp_name);
993 fprintf (f, "__%s_head:\n", imp_name);
995 fprintf (f, "\t%shname%s\t%sPtr to image import by name list\n",
996 ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C);
998 fprintf (f, "\t%sthis should be the timestamp, but NT sometimes\n", ASM_C);
999 fprintf (f, "\t%sdoesn't load DLLs when this is set.\n", ASM_C);
1000 fprintf (f, "\t%s\t0\t%s loaded time\n", ASM_LONG, ASM_C);
1001 fprintf (f, "\t%s\t0\t%s Forwarder chain\n", ASM_LONG, ASM_C);
1002 fprintf (f, "\t%s__%s_iname%s\t%s imported dll's name\n",
1007 fprintf (f, "\t%sfthunk%s\t%s pointer to firstthunk\n",
1009 ASM_RVA_AFTER, ASM_C);
1011 fprintf (f, "%sStuff for compatibility\n", ASM_C);
1012 fprintf (f, "\t.section\t.idata$5\n");
1013 fprintf (f, "\t%s\t0\n", ASM_LONG);
1014 fprintf (f, "fthunk:\n");
1015 fprintf (f, "\t.section\t.idata$4\n");
1016 fprintf (f, "\t%s\t0\n", ASM_LONG);
1017 fprintf (f, "\t.section .idata$4\n");
1018 fprintf (f, "hname:\n");
1022 sprintf (outfile, "-o %sh.o %sh.s", prefix, prefix);
1023 run (as_name, outfile);
1025 for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
1027 sprintf (outfile, "%ss%d.s", prefix, i);
1028 f = fopen (outfile, "w");
1029 fprintf (f, "\t.text\n");
1030 fprintf (f, "\t%s\t%s%s\n", ASM_GLOBAL, ASM_PREFIX, exp->name);
1031 fprintf (f, "\t%s\t__imp_%s\n", ASM_GLOBAL, exp->name);
1032 fprintf (f, "%s%s:\n\t%s\t__imp_%s\n", ASM_PREFIX,
1033 exp->name, ASM_JUMP, exp->name);
1035 fprintf (f, "\t.section\t.idata$7\t%s To force loading of head\n", ASM_C);
1036 fprintf (f, "\t%s\t__%s_head\n", ASM_LONG, imp_name);
1037 fprintf (f, "\t.section .idata$5\n");
1040 fprintf (f, "__imp_%s:\n", exp->name);
1041 fprintf (f, "\t%sID%d%s\n",
1046 fprintf (f, "\n%s Hint name array\n", ASM_C);
1047 fprintf (f, "\t.section .idata$4\n");
1048 fprintf (f, "\t%sID%d%s\n", ASM_RVA_BEFORE,
1052 fprintf (f, "%s Hint/name array storage and import dll name\n", ASM_C);
1053 fprintf (f, "\t.section .idata$6\n");
1055 fprintf (f, "\t%s\n", ASM_ALIGN_SHORT);
1056 fprintf (f, "ID%d:\t%s\t%d\n", i, ASM_SHORT, exp->ordinal);
1057 fprintf (f, "\t%s\t\"%s\"\n", ASM_TEXT, xlate (exp->name));
1061 sprintf (outfile, "-o %ss%d.o %ss%d.s", prefix, i, prefix, i);
1062 run (as_name, outfile);
1065 sprintf (outfile, "%st.s", prefix);
1066 f = fopen (outfile, "w");
1067 fprintf (f, "\t.section .idata$7\n");
1068 fprintf (f, "\t%s\t__%s_iname\n", ASM_GLOBAL, imp_name);
1069 fprintf (f, "__%s_iname:\t%s\t\"%s\"\n",
1070 imp_name, ASM_TEXT, dll_name);
1073 fprintf (f, "\t.section .idata$4\n");
1074 fprintf (f, "\t%s\t0\n", ASM_LONG);
1076 fprintf (f, "\t.section .idata$5\n");
1077 fprintf (f, "\t%s\t0\n", ASM_LONG);
1080 sprintf (outfile, "-o %st.o %st.s", prefix, prefix);
1081 run (as_name, outfile);
1083 /* Now stick them all into the archive */
1086 sprintf (outfile, "crs %s %sh.o %st.o", output_filename, prefix, prefix);
1087 run (ar_name, outfile);
1089 /* Do the rest in groups of however many fit into a command line */
1091 for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
1095 sol = sprintf (outfile, "crs %s", output_filename);
1098 sol += sprintf (outfile + sol, " %ss%d.o", prefix, i);
1102 run (ar_name, outfile);
1108 run (ar_name, outfile);
1110 /* Delete all the temp files */
1112 if (dontdeltemps == 0)
1114 sprintf (outfile, "%sh.o", prefix);
1116 sprintf (outfile, "%sh.s", prefix);
1118 sprintf (outfile, "%st.o", prefix);
1120 sprintf (outfile, "%st.s", prefix);
1124 if (dontdeltemps < 2)
1125 for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
1127 sprintf (outfile, "%ss%d.o", prefix, i);
1129 sprintf (outfile, "%ss%d.s", prefix, i);
1134 /**********************************************************************/
1136 /* Run through the information gathered from the .o files and the
1137 .def file and work out the best stuff */
1143 export_type *ap = *(export_type **) a;
1144 export_type *bp = *(export_type **) b;
1145 if (ap->ordinal == bp->ordinal)
1148 /* unset ordinals go to the bottom */
1149 if (ap->ordinal == -1)
1151 if (bp->ordinal == -1)
1153 return (ap->ordinal - bp->ordinal);
1162 export_type *ap = *(export_type **) a;
1163 export_type *bp = *(export_type **) b;
1165 return (strcmp (ap->name, bp->name));
1170 remove_null_names (ptr)
1175 for (dst = src = 0; src < d_nfuncs; src++)
1179 ptr[dst] = ptr[src];
1192 for (i = 0; i < d_nfuncs; i++)
1196 printf ("%d %s @ %d %s%s\n",
1197 i, ptr[i]->name, ptr[i]->ordinal,
1198 ptr[i]->noname ? "NONAME " : "",
1199 ptr[i]->constant ? "CONSTANT" : "");
1208 process_duplicates (d_export_vec)
1209 export_type **d_export_vec;
1216 /* Remove duplicates */
1217 qsort (d_export_vec, d_nfuncs, sizeof (export_type *), nfunc);
1219 dtab (d_export_vec);
1220 for (i = 0; i < d_nfuncs - 1; i++)
1222 if (strcmp (d_export_vec[i]->name,
1223 d_export_vec[i + 1]->name) == 0)
1226 export_type *a = d_export_vec[i];
1227 export_type *b = d_export_vec[i + 1];
1231 fprintf (stderr, "Warning, ignoring duplicate EXPORT %s %d,%d\n",
1235 if (a->ordinal != -1
1236 && b->ordinal != -1)
1239 fprintf (stderr, "Error, duplicate EXPORT with oridinals %s\n",
1243 /* Merge attributes */
1244 b->ordinal = a->ordinal > 0 ? a->ordinal : b->ordinal;
1245 b->constant |= a->constant;
1246 b->noname |= a->noname;
1247 d_export_vec[i] = 0;
1250 dtab (d_export_vec);
1251 remove_null_names (d_export_vec);
1252 dtab (d_export_vec);
1258 fill_ordinals (d_export_vec)
1259 export_type **d_export_vec;
1264 qsort (d_export_vec, d_nfuncs, sizeof (export_type *), pfunc);
1266 /* fill in the unset ordinals with ones from our range */
1268 ptr = (char *) malloc (65536);
1270 memset (ptr, 65536, 0);
1272 /* Mark in our large vector all the numbers that are taken */
1273 for (i = 0; i < d_nfuncs; i++)
1275 if (d_export_vec[i]->ordinal != -1)
1277 ptr[d_export_vec[i]->ordinal] = 1;
1279 lowest = d_export_vec[i]->ordinal;
1283 for (i = 0; i < d_nfuncs; i++)
1285 if (d_export_vec[i]->ordinal == -1)
1288 for (j = lowest; j < 65536; j++)
1292 d_export_vec[i]->ordinal = j;
1296 for (j = 1; j < lowest; j++)
1300 d_export_vec[i]->ordinal = j;
1312 qsort (d_export_vec, d_nfuncs, sizeof (export_type *), pfunc);
1314 /* Work out the lowest ordinal number */
1315 if (d_export_vec[0])
1316 d_ord = d_export_vec[0]->ordinal;
1321 /* First work out the minimum ordinal chosen */
1326 export_type **d_export_vec
1327 = (export_type **) xmalloc (sizeof (export_type *) * d_nfuncs);
1329 for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
1331 d_export_vec[i] = exp;
1334 process_duplicates (d_export_vec);
1335 fill_ordinals (d_export_vec);
1337 /* Put back the list in the new order */
1339 for (i = d_nfuncs - 1; i >= 0; i--)
1341 d_export_vec[i]->next = d_exports;
1342 d_exports = d_export_vec[i];
1348 /* Work out exec prefix from the name of this file */
1355 /* See if we're running in a devo tree */
1356 for (p = program_name; *p; p++)
1358 if (*p == '/' || *p == '\\')
1365 if (ps && strncmp (ps, "/binutils", 9) == 0)
1367 /* running in the binutils directory, the other
1368 executables will be surrounding it in the usual places. */
1369 int len = ps - program_name;
1370 ar_name = xmalloc (len + strlen ("/binutils/ar") + 1);
1371 ranlib_name = xmalloc (len + strlen ("/binutils/ranlib") + 1);
1372 as_name = xmalloc (len + strlen ("/gas/as.new") + 1);
1374 memcpy (ar_name, program_name, len);
1375 strcpy (ar_name + len, "/binutils/ar");
1376 memcpy (ranlib_name, program_name, len);
1377 strcpy (ranlib_name + len, "/binutils/ranlib");
1378 memcpy (as_name, program_name, len);
1379 strcpy (as_name + len, "/gas/as.new");
1383 /* Otherwise chop off any prefix and use it for the rest of the progs,
1384 so i386-win32-dll generates i386-win32-ranlib etc etc */
1386 for (p = program_name; *p; p++)
1388 if (strncmp (p, "dlltool", 7) == 0)
1390 int len = p - program_name;
1391 ar_name = xmalloc (len + strlen ("ar") +1);
1392 ranlib_name = xmalloc (len + strlen ("ranlib")+1);
1393 as_name = xmalloc (len + strlen ("as")+1);
1395 memcpy (ar_name, program_name, len);
1396 strcpy (ar_name + len, "ar");
1397 memcpy (ranlib_name, program_name, len);
1398 strcpy (ranlib_name + len, "ranlib");
1399 memcpy (as_name, program_name, len);
1400 strcpy (as_name + len, "as");
1407 /**********************************************************************/
1410 usage (file, status)
1414 fprintf (file, "Usage %s <options> <object-files>\n", program_name);
1415 fprintf (file, " --machine <machine>\n");
1416 fprintf (file, " --output-exp <outname> Generate export file.\n");
1417 fprintf (file, " --output-lib <outname> Generate input library.\n");
1418 fprintf (file, " --add-indirect Add dll indirects to export file.\n");
1419 fprintf (file, " --dllname <name> Name of input dll to put into output lib.\n");
1420 fprintf (file, " --def <deffile> Name input .def file\n");
1421 fprintf (file, " --base-file <basefile> Read linker generated base file\n");
1422 fprintf (file, " -v Verbose\n");
1423 fprintf (file, " -u Remove leading underscore from .lib\n");
1424 fprintf (file, " -k Kill @<n> from exported names\n");
1425 fprintf (file, " --nodelete Keep temp files.\n");
1429 static struct option long_options[] =
1431 {"nodelete", no_argument, NULL,'n'},
1432 {"dllname", required_argument, NULL,'D'},
1433 {"output-exp", required_argument, NULL, 'e'},
1434 {"output-lib", required_argument, NULL, 'l'},
1435 {"def", required_argument, NULL, 'd'},
1436 {"underscore", no_argument, NULL, 'u'},
1437 {"killat", no_argument, NULL, 'k'},
1438 {"help", no_argument, NULL, 'h'},
1439 {"machine", required_argument, NULL, 'm'},
1440 {"add-indirect", no_argument, NULL, 'a'},
1441 {"base-file", required_argument, NULL, 'b'},
1454 program_name = av[0];
1457 while ((c = getopt_long (ac, av, "aD:l:e:nkvbuh?m:yd:", long_options, 0)) != EOF)
1499 base_file = fopen (optarg, "r");
1502 fprintf (stderr, "%s: Unable to open base-file %s\n",
1514 for (i = 0; mtable[i].type; i++)
1516 if (strcmp (mtable[i].type, mname) == 0)
1520 if (!mtable[i].type)
1522 fprintf (stderr, "Machine not supported\n");
1528 if (!dll_name && exp_name)
1530 char len = strlen (exp_name) + 5;
1531 dll_name = xmalloc (len);
1532 strcpy (dll_name, exp_name);
1533 strcat (dll_name, ".dll");
1540 process_def_file (def_file);
1545 firstarg = av[optind];
1546 scan_obj_file (av[optind]);