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)
164 #include "libiberty.h"
167 #include <sys/types.h>
168 #include "demangle.h"
170 #ifdef HAVE_SYS_WAIT_H
171 #include <sys/wait.h>
174 #define WIFEXITED(w) (((w)&0377) == 0)
177 #define WIFSIGNALED(w) (((w)&0377) != 0177 && ((w)&~0377) == 0)
180 #define WTERMSIG(w) ((w) & 0177)
183 #define WEXITSTATUS(w) (((w) >> 8) & 0377)
188 char *ar_name = "ar";
189 char *as_name = "as";
190 char *ranlib_name = "ranlib";
197 int add_indirect = 0;
198 int add_underscore = 0;
199 int dontdeltemps = 0;
214 static char *mname = "arm";
218 static char *mname = "i386";
220 #define PATHMAX 250 /* What's the right name for this ? */
222 char outfile[PATHMAX];
234 char *how_align_short;
241 "arm", ".byte", ".short", ".long", ".asciz", "@", "ldr\tip,[pc]\n\tldr\tpc,[ip]\n\t.long", ".global", ".space", ".align\t2",
246 "i386", ".byte", ".short", ".long", ".asciz", "#", "jmp *", ".global", ".space", ".align\t2",
290 #define ASM_BYTE mtable[machine].how_byte
291 #define ASM_SHORT mtable[machine].how_short
292 #define ASM_LONG mtable[machine].how_long
293 #define ASM_TEXT mtable[machine].how_asciz
294 #define ASM_C mtable[machine].how_comment
295 #define ASM_JUMP mtable[machine].how_jump
296 #define ASM_GLOBAL mtable[machine].how_global
297 #define ASM_SPACE mtable[machine].how_space
298 #define ASM_ALIGN_SHORT mtable[machine].how_align_short
299 #define ASM_RVA_BEFORE rvabefore(machine)
300 #define ASM_RVA_AFTER rvaafter(machine)
301 #define ASM_PREFIX asm_prefix(machine)
306 FILE *yyin; /* communications with flex */
307 extern int linenumber;
309 process_def_file (name)
312 FILE *f = fopen (name, "r");
315 fprintf (stderr, "%s: Can't open def file %s\n", program_name, name);
324 /**********************************************************************/
326 /* Communications with the parser */
336 typedef struct export
347 static char *d_name; /* Arg to NAME or LIBRARY */
348 static int d_nfuncs; /* Number of functions exported */
349 static int d_ord; /* Base ordinal index */
350 static export_type *d_exports; /*list of exported functions */
351 static dlist_type *d_list; /* Descriptions */
352 static dlist_type *a_list; /* Stuff to go in directives */
359 fprintf (stderr, "%s: Syntax error in def file %s:%d\n",
360 program_name, def_file, linenumber);
364 def_exports (name, internal_name, ordinal, noname, constant)
371 struct export *p = (struct export *) xmalloc (sizeof (*p));
374 p->internal_name = internal_name ? internal_name : name;
375 p->ordinal = ordinal;
376 p->constant = constant;
385 def_name (name, base)
390 fprintf (stderr, "%s NAME %s base %x\n", program_name, name, base);
393 fprintf (stderr, "Can't have LIBRARY and NAME\n");
400 def_library (name, base)
405 printf ("%s: LIBRARY %s base %x\n", program_name, name, base);
408 fprintf (stderr, "%s: Can't have LIBRARY and NAME\n", program_name);
415 def_description (desc)
418 dlist_type *d = (dlist_type *) xmalloc (sizeof (dlist_type));
419 d->text = strdup (desc);
428 dlist_type *d = (dlist_type *) xmalloc (sizeof (dlist_type));
429 d->text = strdup (dir);
435 def_stacksize (reserve, commit)
441 sprintf (b, "-stack 0x%x,0x%x ", reserve, commit);
443 sprintf (b, "-stack 0x%x ", reserve);
444 new_directive (strdup (b));
448 def_heapsize (reserve, commit)
454 sprintf (b, "-heap 0x%x,0x%x ", reserve, commit);
456 sprintf (b, "-heap 0x%x ", reserve);
457 new_directive (strdup (b));
462 def_import (internal, module, entry)
468 fprintf (stderr, "%s: IMPORTS are ignored", program_name);
472 def_version (major, minor)
474 printf ("VERSION %d.%d\n", major, minor);
479 def_section (name, attr)
496 sprintf (buf, "-attr %s %s", name, atts);
497 new_directive (strdup (buf));
504 def_section ("CODE", attr);
511 def_section ("DATA", attr);
515 /**********************************************************************/
526 extern char **environ;
528 fprintf (stderr, "%s %s\n", what, args);
532 for (s = args; *s; s++)
536 argv = alloca (sizeof (char *) * (i + 3));
543 while (*s != ' ' && *s != 0)
556 fprintf (stderr, "%s: can't exec %s\n", program_name, what);
562 fprintf (stderr, "%s: vfork failed, %d\n", program_name, errno);
568 waitpid (pid, &status, 0);
571 if (WIFSIGNALED (status))
573 fprintf (stderr, "%s: %s %s terminated with signal %d\n",
574 program_name, what, args, WTERMSIG (status));
578 if (WIFEXITED (status))
580 fprintf (stderr, "%s: %s %s terminated with exit status %d\n",
581 program_name, what, args, WEXITSTATUS (status));
588 /* read in and block out the base relocations */
600 scan_open_obj_file (abfd)
603 /* Look for .drectve's */
604 asection *s = bfd_get_section_by_name (abfd, ".drectve");
607 int size = bfd_get_section_size_before_reloc (s);
608 char *buf = xmalloc (size);
611 bfd_get_section_contents (abfd, s, buf, 0, size);
613 fprintf (stderr, "%s: Sucking in info from %s\n",
615 bfd_get_filename (abfd));
617 /* Search for -export: strings */
623 && strncmp (p, "-export:", 8) == 0)
629 while (*p != ' ' && *p != '-' && p < e)
631 c = xmalloc (p - name + 1);
632 memcpy (c, name, p - name);
634 def_exports (c, 0, -1, 0);
645 fprintf (stderr, "%s: Done readin\n",
652 scan_obj_file (filename)
655 bfd *f = bfd_openr (filename, 0);
659 fprintf (stderr, "%s: Unable to open object file %s\n",
664 if (bfd_check_format (f, bfd_archive))
666 bfd *arfile = bfd_openr_next_archived_file (f, 0);
669 if (bfd_check_format (arfile, bfd_object))
670 scan_open_obj_file (arfile);
672 arfile = bfd_openr_next_archived_file (f, arfile);
676 if (bfd_check_format (f, bfd_object))
678 scan_open_obj_file (f);
684 /**********************************************************************/
687 /* return the bit of the name before the last . */
694 char *res = strdup (name);
695 char *p = strrchr (res, '.');
707 fprintf (f, "%s ", ASM_C);
708 for (i = 0; oav[i]; i++)
709 fprintf (f, "%s ", oav[i]);
711 for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
713 fprintf (f, "%s %d = %s %s @ %d %s%s\n",
719 exp->noname ? "NONAME " : "",
720 exp->constant ? "CONSTANT" : "");
723 /* Generate the .exp file */
736 flush_page (f, need, page_addr, on_page)
743 /* Flush this page */
744 fprintf (f, "\t%s\t0x%08x\t%s Starting RVA for chunk\n",
748 fprintf (f, "\t%s\t0x%x\t%s Size of block\n",
750 (on_page * 2) + (on_page & 1) * 2 + 8,
752 for (i = 0; i < on_page; i++)
754 fprintf (f, "\t%s\t0x%x\n", ASM_SHORT, need[i] - page_addr | 0x3000);
758 fprintf (f, "\t%s\t0x%x\n", ASM_SHORT, 0 | 0x0000);
768 fprintf (output_def, ";");
769 for (i = 0; oav[i]; i++)
770 fprintf (output_def, " %s", oav[i]);
772 fprintf (output_def, "\nEXPORTS\n");
773 for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
775 fprintf (output_def, "\t%s @ %d; %s\n",
778 cplus_demangle (exp->internal_name, DMGL_ANSI | DMGL_PARAMS));
790 sprintf (outfile, "t%s", exp_name);
793 fprintf (stderr, "%s: Generate exp file %s\n",
794 program_name, exp_name);
796 f = fopen (outfile, "w");
799 fprintf (stderr, "%s: Unable to open output file %s\n", program_name, outfile);
804 fprintf (stderr, "%s: Opened file %s\n",
805 program_name, outfile);
811 fprintf (f, "\t.section .edata\n\n");
812 fprintf (f, "\t%s 0 %s Allways 0\n", ASM_LONG, ASM_C);
813 fprintf (f, "\t%s 0 %s Time and date\n", ASM_LONG, ASM_C);
814 fprintf (f, "\t%s 0 %s Major and Minor version\n", ASM_LONG, ASM_C);
815 fprintf (f, "\t%sname%s %s Ptr to name of dll\n", ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C);
816 fprintf (f, "\t%s %d %s Starting ordinal of exports\n", ASM_LONG, d_ord, ASM_C);
817 fprintf (f, "\t%s The next field is documented as being the number of functions\n", ASM_C);
818 fprintf (f, "\t%s yet it doesn't look like that in real PE dlls\n", ASM_C);
819 fprintf (f, "\t%s But it shouldn't be a problem, causes there's\n", ASM_C);
820 fprintf (f, "\t%s always the number of names field\n", ASM_C);
821 fprintf (f, "\t%s %d %s Number of functions\n", ASM_LONG, d_nfuncs, ASM_C);
822 fprintf (f, "\t%s %d %s Number of names\n", ASM_LONG, d_nfuncs, ASM_C);
823 fprintf (f, "\t%safuncs%s %s Address of functions\n", ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C);
824 fprintf (f, "\t%sanames%s %s Address of names\n", ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C);
825 fprintf (f, "\t%sanords%s %s Address of ordinals\n", ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C);
827 fprintf (f, "name: %s \"%s\"\n", ASM_TEXT, dll_name);
829 fprintf (f, "afuncs:\n");
831 for (exp = d_exports; exp; exp = exp->next)
834 /* This seems necessary in the doc, but in real
835 life it's not used.. */
836 if (exp->ordinal != i)
838 fprintf (f, "%s\t%s\t%d\t@ %d..%d missing\n", ASM_C, ASM_SPACE,
839 (exp->ordinal - i) * 4,
840 i, exp->ordinal - 1);
844 fprintf (f, "\t%s%s%s%s\t%s %d\n", ASM_RVA_BEFORE,
846 exp->internal_name, ASM_RVA_AFTER, ASM_C, exp->ordinal);
851 fprintf (f, "anames:\n");
852 for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
857 fprintf (f, "\t%s nNoname\n", ASM_LONG, ASM_C);
861 fprintf (f, "\t%sn%d%s\n", ASM_RVA_BEFORE, i, ASM_RVA_AFTER);
865 fprintf (f, "anords:\n");
866 for (exp = d_exports; exp; exp = exp->next)
867 fprintf (f, "\t%s %d\n", ASM_SHORT, exp->ordinal - d_ord);
869 for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
871 fprintf (f, "@n%d: %s \"%s\"\n", i, ASM_TEXT, exp->name);
873 fprintf (f, "n%d: %s \"%s\"\n", i, ASM_TEXT, exp->name);
876 fprintf (f, "nNoname: %s \"__noname__\"\n", ASM_TEXT);
880 fprintf (f, "\t.section .drectve\n");
881 for (dl = a_list; dl; dl = dl->next)
883 fprintf (f, "\t%s\t\"%s\"\n", ASM_TEXT, dl->text);
888 fprintf (f, "\t.section .rdata\n");
889 for (dl = d_list; dl; dl = dl->next)
893 /* We dont output as ascii 'cause there can
894 be quote characters in the string */
897 for (p = dl->text; *p; p++)
900 fprintf (f, "\t%s\t", ASM_BYTE);
903 fprintf (f, "%d", *p);
920 /* Add to the output file a way of getting to the exported names
921 without using the import library. */
924 fprintf (f, "\t.section\t.rdata\n");
925 for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
928 fprintf (f, "\t%s\t__imp_%s\n", ASM_GLOBAL, exp->name);
929 fprintf (f, "__imp_%s:\n", exp->name);
930 fprintf (f, "\t%s\t%s\n", ASM_LONG, exp->name);
934 /* Dump the reloc section if a base file is provided */
938 long need[PAGE_SIZE];
945 fprintf (f, "\t.section\t.init\n");
946 fprintf (f, "lab:\n");
948 fseek (base_file, 0, SEEK_END);
949 numbytes = ftell (base_file);
950 fseek (base_file, 0, SEEK_SET);
951 copy = malloc (numbytes);
952 fread (copy, 1, numbytes, base_file);
953 num_entries = numbytes / sizeof (long);
956 fprintf (f, "\t.section\t.reloc\n");
959 qsort (copy, num_entries, sizeof (long), sfunc);
962 page_addr = addr & PAGE_MASK; /* work out the page addr */
964 for (j = 0; j < num_entries; j++)
967 if ((addr & PAGE_MASK) != page_addr)
969 flush_page (f, need, page_addr, on_page);
971 page_addr = addr & PAGE_MASK;
973 need[on_page++] = addr;
975 flush_page (f, need, page_addr, on_page);
977 fprintf (f, "\t%s\t0,0\t%s End\n", ASM_LONG, ASM_C);
983 /* assemble the file */
984 sprintf (outfile, "-o %s t%s", exp_name, exp_name);
985 run (as_name, outfile);
986 if (dontdeltemps == 0)
988 sprintf (outfile, "t%s", exp_name);
998 char *copy = malloc (strlen (name) + 2);
1000 strcpy (copy + 1, name);
1007 p = strchr (name, '@');
1014 /**********************************************************************/
1022 char *output_filename;
1023 char prefix[PATHMAX];
1025 sprintf (outfile, "%s", imp_name);
1026 output_filename = strdup (outfile);
1028 unlink (output_filename);
1030 strcpy (prefix, "d");
1031 sprintf (outfile, "%sh.s", prefix);
1033 f = fopen (outfile, "w");
1035 fprintf (f, "%s IMAGE_IMPORT_DESCRIPTOR\n", ASM_C);
1036 fprintf (f, "\t.section .idata$2\n");
1038 fprintf (f, "\t%s\t__%s_head\n", ASM_GLOBAL, imp_name_lab);
1039 fprintf (f, "__%s_head:\n", imp_name_lab);
1041 fprintf (f, "\t%shname%s\t%sPtr to image import by name list\n",
1042 ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C);
1044 fprintf (f, "\t%sthis should be the timestamp, but NT sometimes\n", ASM_C);
1045 fprintf (f, "\t%sdoesn't load DLLs when this is set.\n", ASM_C);
1046 fprintf (f, "\t%s\t0\t%s loaded time\n", ASM_LONG, ASM_C);
1047 fprintf (f, "\t%s\t0\t%s Forwarder chain\n", ASM_LONG, ASM_C);
1048 fprintf (f, "\t%s__%s_iname%s\t%s imported dll's name\n",
1053 fprintf (f, "\t%sfthunk%s\t%s pointer to firstthunk\n",
1055 ASM_RVA_AFTER, ASM_C);
1057 fprintf (f, "%sStuff for compatibility\n", ASM_C);
1058 fprintf (f, "\t.section\t.idata$5\n");
1059 fprintf (f, "\t%s\t0\n", ASM_LONG);
1060 fprintf (f, "fthunk:\n");
1061 fprintf (f, "\t.section\t.idata$4\n");
1062 fprintf (f, "\t%s\t0\n", ASM_LONG);
1063 fprintf (f, "\t.section .idata$4\n");
1064 fprintf (f, "hname:\n");
1068 sprintf (outfile, "-o %sh.o %sh.s", prefix, prefix);
1069 run (as_name, outfile);
1071 for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
1073 sprintf (outfile, "%ss%d.s", prefix, i);
1074 f = fopen (outfile, "w");
1075 fprintf (f, "\t.text\n");
1076 fprintf (f, "\t%s\t%s%s\n", ASM_GLOBAL, ASM_PREFIX, exp->name);
1077 fprintf (f, "\t%s\t__imp_%s\n", ASM_GLOBAL, exp->name);
1078 fprintf (f, "%s%s:\n\t%s\t__imp_%s\n", ASM_PREFIX,
1079 exp->name, ASM_JUMP, exp->name);
1081 fprintf (f, "\t.section\t.idata$7\t%s To force loading of head\n", ASM_C);
1082 fprintf (f, "\t%s\t__%s_head\n", ASM_LONG, imp_name_lab);
1083 fprintf (f, "\t.section .idata$5\n");
1086 fprintf (f, "__imp_%s:\n", exp->name);
1087 fprintf (f, "\t%sID%d%s\n",
1092 fprintf (f, "\n%s Hint name array\n", ASM_C);
1093 fprintf (f, "\t.section .idata$4\n");
1094 fprintf (f, "\t%sID%d%s\n", ASM_RVA_BEFORE,
1098 fprintf (f, "%s Hint/name array storage and import dll name\n", ASM_C);
1099 fprintf (f, "\t.section .idata$6\n");
1101 fprintf (f, "\t%s\n", ASM_ALIGN_SHORT);
1102 fprintf (f, "ID%d:\t%s\t%d\n", i, ASM_SHORT, exp->ordinal);
1103 fprintf (f, "\t%s\t\"%s\"\n", ASM_TEXT, xlate (exp->name));
1107 sprintf (outfile, "-o %ss%d.o %ss%d.s", prefix, i, prefix, i);
1108 run (as_name, outfile);
1111 sprintf (outfile, "%st.s", prefix);
1112 f = fopen (outfile, "w");
1113 fprintf (f, "\t.section .idata$7\n");
1114 fprintf (f, "\t%s\t__%s_iname\n", ASM_GLOBAL, imp_name_lab);
1115 fprintf (f, "__%s_iname:\t%s\t\"%s\"\n",
1116 imp_name_lab, ASM_TEXT, dll_name);
1119 fprintf (f, "\t.section .idata$4\n");
1120 fprintf (f, "\t%s\t0\n", ASM_LONG);
1122 fprintf (f, "\t.section .idata$5\n");
1123 fprintf (f, "\t%s\t0\n", ASM_LONG);
1126 sprintf (outfile, "-o %st.o %st.s", prefix, prefix);
1127 run (as_name, outfile);
1129 /* Now stick them all into the archive */
1132 sprintf (outfile, "crs %s %sh.o %st.o", output_filename, prefix, prefix);
1133 run (ar_name, outfile);
1135 /* Do the rest in groups of however many fit into a command line */
1137 for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
1141 sprintf (outfile, "crs %s", output_filename);
1142 sol = strlen (outfile);
1145 sprintf (outfile + sol, " %ss%d.o", prefix, i);
1146 sol = strlen (outfile);
1150 run (ar_name, outfile);
1156 run (ar_name, outfile);
1158 /* Delete all the temp files */
1160 if (dontdeltemps == 0)
1162 sprintf (outfile, "%sh.o", prefix);
1164 sprintf (outfile, "%sh.s", prefix);
1166 sprintf (outfile, "%st.o", prefix);
1168 sprintf (outfile, "%st.s", prefix);
1172 if (dontdeltemps < 2)
1173 for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
1175 sprintf (outfile, "%ss%d.o", prefix, i);
1177 sprintf (outfile, "%ss%d.s", prefix, i);
1182 /**********************************************************************/
1184 /* Run through the information gathered from the .o files and the
1185 .def file and work out the best stuff */
1191 export_type *ap = *(export_type **) a;
1192 export_type *bp = *(export_type **) b;
1193 if (ap->ordinal == bp->ordinal)
1196 /* unset ordinals go to the bottom */
1197 if (ap->ordinal == -1)
1199 if (bp->ordinal == -1)
1201 return (ap->ordinal - bp->ordinal);
1210 export_type *ap = *(export_type **) a;
1211 export_type *bp = *(export_type **) b;
1213 return (strcmp (ap->name, bp->name));
1218 remove_null_names (ptr)
1223 for (dst = src = 0; src < d_nfuncs; src++)
1227 ptr[dst] = ptr[src];
1240 for (i = 0; i < d_nfuncs; i++)
1244 printf ("%d %s @ %d %s%s\n",
1245 i, ptr[i]->name, ptr[i]->ordinal,
1246 ptr[i]->noname ? "NONAME " : "",
1247 ptr[i]->constant ? "CONSTANT" : "");
1256 process_duplicates (d_export_vec)
1257 export_type **d_export_vec;
1264 /* Remove duplicates */
1265 qsort (d_export_vec, d_nfuncs, sizeof (export_type *), nfunc);
1267 dtab (d_export_vec);
1268 for (i = 0; i < d_nfuncs - 1; i++)
1270 if (strcmp (d_export_vec[i]->name,
1271 d_export_vec[i + 1]->name) == 0)
1274 export_type *a = d_export_vec[i];
1275 export_type *b = d_export_vec[i + 1];
1279 fprintf (stderr, "Warning, ignoring duplicate EXPORT %s %d,%d\n",
1283 if (a->ordinal != -1
1284 && b->ordinal != -1)
1287 fprintf (stderr, "Error, duplicate EXPORT with oridinals %s\n",
1291 /* Merge attributes */
1292 b->ordinal = a->ordinal > 0 ? a->ordinal : b->ordinal;
1293 b->constant |= a->constant;
1294 b->noname |= a->noname;
1295 d_export_vec[i] = 0;
1298 dtab (d_export_vec);
1299 remove_null_names (d_export_vec);
1300 dtab (d_export_vec);
1306 fill_ordinals (d_export_vec)
1307 export_type **d_export_vec;
1312 qsort (d_export_vec, d_nfuncs, sizeof (export_type *), pfunc);
1314 /* fill in the unset ordinals with ones from our range */
1316 ptr = (char *) malloc (65536);
1318 memset (ptr, 65536, 0);
1320 /* Mark in our large vector all the numbers that are taken */
1321 for (i = 0; i < d_nfuncs; i++)
1323 if (d_export_vec[i]->ordinal != -1)
1325 ptr[d_export_vec[i]->ordinal] = 1;
1327 lowest = d_export_vec[i]->ordinal;
1331 for (i = 0; i < d_nfuncs; i++)
1333 if (d_export_vec[i]->ordinal == -1)
1336 for (j = lowest; j < 65536; j++)
1340 d_export_vec[i]->ordinal = j;
1344 for (j = 1; j < lowest; j++)
1348 d_export_vec[i]->ordinal = j;
1360 qsort (d_export_vec, d_nfuncs, sizeof (export_type *), pfunc);
1362 /* Work out the lowest ordinal number */
1363 if (d_export_vec[0])
1364 d_ord = d_export_vec[0]->ordinal;
1369 /* First work out the minimum ordinal chosen */
1374 export_type **d_export_vec
1375 = (export_type **) xmalloc (sizeof (export_type *) * d_nfuncs);
1377 for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
1379 d_export_vec[i] = exp;
1382 process_duplicates (d_export_vec);
1383 fill_ordinals (d_export_vec);
1385 /* Put back the list in the new order */
1387 for (i = d_nfuncs - 1; i >= 0; i--)
1389 d_export_vec[i]->next = d_exports;
1390 d_exports = d_export_vec[i];
1396 /* Work out exec prefix from the name of this file */
1403 /* See if we're running in a devo tree */
1404 for (p = program_name; *p; p++)
1406 if (*p == '/' || *p == '\\')
1413 if (ps && strncmp (ps, "/binutils", 9) == 0)
1415 /* running in the binutils directory, the other
1416 executables will be surrounding it in the usual places. */
1417 int len = ps - program_name;
1418 ar_name = xmalloc (len + strlen ("/binutils/ar") + 1);
1419 ranlib_name = xmalloc (len + strlen ("/binutils/ranlib") + 1);
1420 as_name = xmalloc (len + strlen ("/gas/as.new") + 1);
1422 memcpy (ar_name, program_name, len);
1423 strcpy (ar_name + len, "/binutils/ar");
1424 memcpy (ranlib_name, program_name, len);
1425 strcpy (ranlib_name + len, "/binutils/ranlib");
1426 memcpy (as_name, program_name, len);
1427 strcpy (as_name + len, "/gas/as.new");
1431 /* Otherwise chop off any prefix and use it for the rest of the progs,
1432 so i386-win32-dll generates i386-win32-ranlib etc etc */
1434 for (p = program_name; *p; p++)
1436 if (strncmp (p, "dlltool", 7) == 0)
1438 int len = p - program_name;
1439 ar_name = xmalloc (len + strlen ("ar") + 1);
1440 ranlib_name = xmalloc (len + strlen ("ranlib") + 1);
1441 as_name = xmalloc (len + strlen ("as") + 1);
1443 memcpy (ar_name, program_name, len);
1444 strcpy (ar_name + len, "ar");
1445 memcpy (ranlib_name, program_name, len);
1446 strcpy (ranlib_name + len, "ranlib");
1447 memcpy (as_name, program_name, len);
1448 strcpy (as_name + len, "as");
1455 /**********************************************************************/
1458 usage (file, status)
1462 fprintf (file, "Usage %s <options> <object-files>\n", program_name);
1463 fprintf (file, " --machine <machine>\n");
1464 fprintf (file, " --output-exp <outname> Generate export file.\n");
1465 fprintf (file, " --output-lib <outname> Generate input library.\n");
1466 fprintf (file, " --add-indirect Add dll indirects to export file.\n");
1467 fprintf (file, " --dllname <name> Name of input dll to put into output lib.\n");
1468 fprintf (file, " --def <deffile> Name input .def file\n");
1469 fprintf (file, " --output-def <deffile> Name output .def file\n");
1470 fprintf (file, " --base-file <basefile> Read linker generated base file\n");
1471 fprintf (file, " -v Verbose\n");
1472 fprintf (file, " -U Add underscores to .lib\n");
1473 fprintf (file, " -k Kill @<n> from exported names\n");
1474 fprintf (file, " --nodelete Keep temp files.\n");
1478 static struct option long_options[] =
1480 {"nodelete", no_argument, NULL, 'n'},
1481 {"dllname", required_argument, NULL, 'D'},
1482 {"output-exp", required_argument, NULL, 'e'},
1483 {"output-def", required_argument, NULL, 'z'},
1484 {"output-lib", required_argument, NULL, 'l'},
1485 {"def", required_argument, NULL, 'd'},
1486 {"add-underscore", no_argument, NULL, 'U'},
1487 {"killat", no_argument, NULL, 'k'},
1488 {"help", no_argument, NULL, 'h'},
1489 {"machine", required_argument, NULL, 'm'},
1490 {"add-indirect", no_argument, NULL, 'a'},
1491 {"base-file", required_argument, NULL, 'b'},
1504 program_name = av[0];
1507 while ((c = getopt_long (ac, av, "uaD:l:e:nkvbUh?m:yd:", long_options, 0)) != EOF)
1511 /* ignored for compatibility */
1518 output_def = fopen (optarg, "w");
1555 base_file = fopen (optarg, "r");
1558 fprintf (stderr, "%s: Unable to open base-file %s\n",
1570 for (i = 0; mtable[i].type; i++)
1572 if (strcmp (mtable[i].type, mname) == 0)
1576 if (!mtable[i].type)
1578 fprintf (stderr, "Machine not supported\n");
1584 if (!dll_name && exp_name)
1586 char len = strlen (exp_name) + 5;
1587 dll_name = xmalloc (len);
1588 strcpy (dll_name, exp_name);
1589 strcat (dll_name, ".dll");
1596 process_def_file (def_file);
1601 firstarg = av[optind];
1602 scan_obj_file (av[optind]);
1613 /* Make imp_name safe for use as a label. */
1615 imp_name_lab = strdup (imp_name);
1616 for (p = imp_name_lab; *p; *p++)
1618 if (!isalpha (*p) && !isdigit (*p))