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 #define PAGE_SIZE 4096
164 #define PAGE_MASK (-PAGE_SIZE)
166 #include "libiberty.h"
169 #include <sys/types.h>
170 #include "demangle.h"
172 #ifdef HAVE_SYS_WAIT_H
173 #include <sys/wait.h>
176 #define WIFEXITED(w) (((w)&0377) == 0)
179 #define WIFSIGNALED(w) (((w)&0377) != 0177 && ((w)&~0377) == 0)
182 #define WTERMSIG(w) ((w) & 0177)
185 #define WEXITSTATUS(w) (((w) >> 8) & 0377)
190 char *ar_name = "ar";
191 char *as_name = "as";
192 char *ranlib_name = "ranlib";
199 int add_indirect = 0;
200 int add_underscore = 0;
201 int dontdeltemps = 0;
216 static char *mname = "arm";
220 static char *mname = "i386";
222 #define PATHMAX 250 /* What's the right name for this ? */
224 char outfile[PATHMAX];
236 char *how_align_short;
237 char *how_align_long;
244 "arm", ".byte", ".short", ".long", ".asciz", "@", "ldr\tip,[pc]\n\tldr\tpc,[ip]\n\t.long", ".global", ".space", ".align\t2",".align\t4",
249 "i386", ".byte", ".short", ".long", ".asciz", "#", "jmp *", ".global", ".space", ".align\t2",".align\t4"
293 #define ASM_BYTE mtable[machine].how_byte
294 #define ASM_SHORT mtable[machine].how_short
295 #define ASM_LONG mtable[machine].how_long
296 #define ASM_TEXT mtable[machine].how_asciz
297 #define ASM_C mtable[machine].how_comment
298 #define ASM_JUMP mtable[machine].how_jump
299 #define ASM_GLOBAL mtable[machine].how_global
300 #define ASM_SPACE mtable[machine].how_space
301 #define ASM_ALIGN_SHORT mtable[machine].how_align_short
302 #define ASM_RVA_BEFORE rvabefore(machine)
303 #define ASM_RVA_AFTER rvaafter(machine)
304 #define ASM_PREFIX asm_prefix(machine)
305 #define ASM_ALIGN_LONG mtable[machine].how_align_long
309 FILE *yyin; /* communications with flex */
310 extern int linenumber;
312 process_def_file (name)
315 FILE *f = fopen (name, "r");
318 fprintf (stderr, "%s: Can't open def file %s\n", program_name, name);
327 /**********************************************************************/
329 /* Communications with the parser */
339 typedef struct export
351 static char *d_name; /* Arg to NAME or LIBRARY */
352 static int d_nfuncs; /* Number of functions exported */
353 static int d_named_nfuncs; /* Number of named functions exported */
354 static int d_low_ord; /* Lowest ordinal index */
355 static int d_high_ord; /* Highest ordinal index */
356 static export_type *d_exports; /*list of exported functions */
357 static export_type **d_exports_lexically; /* vector of exported functions in alpha order */
358 static dlist_type *d_list; /* Descriptions */
359 static dlist_type *a_list; /* Stuff to go in directives */
366 fprintf (stderr, "%s: Syntax error in def file %s:%d\n",
367 program_name, def_file, linenumber);
371 def_exports (name, internal_name, ordinal, noname, constant)
378 struct export *p = (struct export *) xmalloc (sizeof (*p));
381 p->internal_name = internal_name ? internal_name : name;
382 p->ordinal = ordinal;
383 p->constant = constant;
392 def_name (name, base)
397 fprintf (stderr, "%s NAME %s base %x\n", program_name, name, base);
400 fprintf (stderr, "Can't have LIBRARY and NAME\n");
407 def_library (name, base)
412 printf ("%s: LIBRARY %s base %x\n", program_name, name, base);
415 fprintf (stderr, "%s: Can't have LIBRARY and NAME\n", program_name);
422 def_description (desc)
425 dlist_type *d = (dlist_type *) xmalloc (sizeof (dlist_type));
426 d->text = strdup (desc);
435 dlist_type *d = (dlist_type *) xmalloc (sizeof (dlist_type));
436 d->text = strdup (dir);
442 def_stacksize (reserve, commit)
448 sprintf (b, "-stack 0x%x,0x%x ", reserve, commit);
450 sprintf (b, "-stack 0x%x ", reserve);
451 new_directive (strdup (b));
455 def_heapsize (reserve, commit)
461 sprintf (b, "-heap 0x%x,0x%x ", reserve, commit);
463 sprintf (b, "-heap 0x%x ", reserve);
464 new_directive (strdup (b));
469 def_import (internal, module, entry)
475 fprintf (stderr, "%s: IMPORTS are ignored", program_name);
479 def_version (major, minor)
481 printf ("VERSION %d.%d\n", major, minor);
486 def_section (name, attr)
503 sprintf (buf, "-attr %s %s", name, atts);
504 new_directive (strdup (buf));
511 def_section ("CODE", attr);
518 def_section ("DATA", attr);
522 /**********************************************************************/
533 extern char **environ;
535 fprintf (stderr, "%s %s\n", what, args);
539 for (s = args; *s; s++)
543 argv = alloca (sizeof (char *) * (i + 3));
550 while (*s != ' ' && *s != 0)
563 fprintf (stderr, "%s: can't exec %s\n", program_name, what);
569 fprintf (stderr, "%s: vfork failed, %d\n", program_name, errno);
575 waitpid (pid, &status, 0);
578 if (WIFSIGNALED (status))
580 fprintf (stderr, "%s: %s %s terminated with signal %d\n",
581 program_name, what, args, WTERMSIG (status));
585 if (WIFEXITED (status))
587 fprintf (stderr, "%s: %s %s terminated with exit status %d\n",
588 program_name, what, args, WEXITSTATUS (status));
595 /* read in and block out the base relocations */
607 scan_open_obj_file (abfd)
610 /* Look for .drectve's */
611 asection *s = bfd_get_section_by_name (abfd, ".drectve");
614 int size = bfd_get_section_size_before_reloc (s);
615 char *buf = xmalloc (size);
618 bfd_get_section_contents (abfd, s, buf, 0, size);
620 fprintf (stderr, "%s: Sucking in info from %s\n",
622 bfd_get_filename (abfd));
624 /* Search for -export: strings */
630 && strncmp (p, "-export:", 8) == 0)
636 while (*p != ' ' && *p != '-' && p < e)
638 c = xmalloc (p - name + 1);
639 memcpy (c, name, p - name);
641 def_exports (c, 0, -1, 0);
652 fprintf (stderr, "%s: Done readin\n",
659 scan_obj_file (filename)
662 bfd *f = bfd_openr (filename, 0);
666 fprintf (stderr, "%s: Unable to open object file %s\n",
671 if (bfd_check_format (f, bfd_archive))
673 bfd *arfile = bfd_openr_next_archived_file (f, 0);
676 if (bfd_check_format (arfile, bfd_object))
677 scan_open_obj_file (arfile);
679 arfile = bfd_openr_next_archived_file (f, arfile);
683 if (bfd_check_format (f, bfd_object))
685 scan_open_obj_file (f);
691 /**********************************************************************/
694 /* return the bit of the name before the last . */
701 char *res = strdup (name);
702 char *p = strrchr (res, '.');
714 fprintf (f, "%s ", ASM_C);
715 for (i = 0; oav[i]; i++)
716 fprintf (f, "%s ", oav[i]);
718 for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
720 fprintf (f, "%s %d = %s %s @ %d %s%s\n",
726 exp->noname ? "NONAME " : "",
727 exp->constant ? "CONSTANT" : "");
730 /* Generate the .exp file */
743 flush_page (f, need, page_addr, on_page)
751 /* Flush this page */
752 fprintf (f, "\t%s\t0x%08x\t%s Starting RVA for chunk\n",
756 fprintf (f, "\t%s\t0x%x\t%s Size of block\n",
758 (on_page * 2) + (on_page & 1) * 2 + 8,
760 for (i = 0; i < on_page; i++)
762 fprintf (f, "\t%s\t0x%x\n", ASM_SHORT, need[i] - page_addr | 0x3000);
766 fprintf (f, "\t%s\t0x%x\n", ASM_SHORT, 0 | 0x0000);
776 fprintf (output_def, ";");
777 for (i = 0; oav[i]; i++)
778 fprintf (output_def, " %s", oav[i]);
780 fprintf (output_def, "\nEXPORTS\n");
781 for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
783 fprintf (output_def, "\t%s @ %d; %s\n",
786 cplus_demangle (exp->internal_name, DMGL_ANSI | DMGL_PARAMS));
798 sprintf (outfile, "t%s", exp_name);
801 fprintf (stderr, "%s: Generate exp file %s\n",
802 program_name, exp_name);
804 f = fopen (outfile, "w");
807 fprintf (stderr, "%s: Unable to open output file %s\n", program_name, outfile);
812 fprintf (stderr, "%s: Opened file %s\n",
813 program_name, outfile);
819 fprintf (f, "\t.section .edata\n\n");
820 fprintf (f, "\t%s 0 %s Allways 0\n", ASM_LONG, ASM_C);
821 fprintf (f, "\t%s 0 %s Time and date\n", ASM_LONG, ASM_C);
822 fprintf (f, "\t%s 0 %s Major and Minor version\n", ASM_LONG, ASM_C);
823 fprintf (f, "\t%sname%s %s Ptr to name of dll\n", ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C);
824 fprintf (f, "\t%s %d %s Starting ordinal of exports\n", ASM_LONG, d_low_ord, ASM_C);
827 fprintf (f, "\t%s %d %s Number of functions\n", ASM_LONG, d_high_ord - d_low_ord + 1, ASM_C);
828 fprintf(f,"\t%s named funcs %d, low ord %d, high ord %d\n",
830 d_named_nfuncs, d_low_ord, d_high_ord);
831 fprintf (f, "\t%s %d %s Number of names\n", ASM_LONG,
832 show_allnames ? d_high_ord - d_low_ord + 1 : d_named_nfuncs, ASM_C);
833 fprintf (f, "\t%safuncs%s %s Address of functions\n", ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C);
835 fprintf (f, "\t%sanames%s %s Address of Name Pointer Table\n",
836 ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C);
838 fprintf (f, "\t%sanords%s %s Address of ordinals\n", ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C);
840 fprintf (f, "name: %s \"%s\"\n", ASM_TEXT, dll_name);
843 fprintf(f,"%s Export address Table\n", ASM_C);
844 fprintf(f,"\t%s\n", ASM_ALIGN_LONG);
845 fprintf (f, "afuncs:\n");
848 for (exp = d_exports; exp; exp = exp->next)
850 if (exp->ordinal != i)
853 fprintf (f, "\t%s\t%d\t%s %d..%d missing\n",
855 (exp->ordinal - i) * 4,
857 i, exp->ordinal - 1);
860 while (i < exp->ordinal)
862 fprintf(f,"\t%s\t0\n", ASM_LONG);
866 fprintf (f, "\t%s%s%s%s\t%s %d\n", ASM_RVA_BEFORE,
868 exp->internal_name, ASM_RVA_AFTER, ASM_C, exp->ordinal);
872 fprintf (f,"%s Export Name Pointer Table\n", ASM_C);
873 fprintf (f, "anames:\n");
875 for (i = 0; exp = d_exports_lexically[i]; i++)
877 if (!exp->noname || show_allnames)
878 fprintf (f, "\t%sn%d%s\n", ASM_RVA_BEFORE, exp->ordinal, ASM_RVA_AFTER);
881 fprintf (f,"%s Export Oridinal Table\n", ASM_C);
882 fprintf (f, "anords:\n");
883 for (i = 0; exp = d_exports_lexically[i]; i++)
885 if (!exp->noname || show_allnames)
886 fprintf (f, "\t%s %d\n", ASM_SHORT, exp->ordinal - d_low_ord);
889 fprintf(f,"%s Export Name Table\n", ASM_C);
890 for (i = 0; exp = d_exports_lexically[i]; i++)
891 if (!exp->noname || show_allnames)
892 fprintf (f, "n%d: %s \"%s\"\n", exp->ordinal, ASM_TEXT, exp->name);
896 fprintf (f, "\t.section .drectve\n");
897 for (dl = a_list; dl; dl = dl->next)
899 fprintf (f, "\t%s\t\"%s\"\n", ASM_TEXT, dl->text);
904 fprintf (f, "\t.section .rdata\n");
905 for (dl = d_list; dl; dl = dl->next)
909 /* We dont output as ascii 'cause there can
910 be quote characters in the string */
913 for (p = dl->text; *p; p++)
916 fprintf (f, "\t%s\t", ASM_BYTE);
919 fprintf (f, "%d", *p);
936 /* Add to the output file a way of getting to the exported names
937 without using the import library. */
940 fprintf (f, "\t.section\t.rdata\n");
941 for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
942 if (!exp->noname || show_allnames)
944 fprintf (f, "\t%s\t__imp_%s\n", ASM_GLOBAL, exp->name);
945 fprintf (f, "__imp_%s:\n", exp->name);
946 fprintf (f, "\t%s\t%s\n", ASM_LONG, exp->name);
950 /* Dump the reloc section if a base file is provided */
954 long need[PAGE_SIZE];
961 fprintf (f, "\t.section\t.init\n");
962 fprintf (f, "lab:\n");
964 fseek (base_file, 0, SEEK_END);
965 numbytes = ftell (base_file);
966 fseek (base_file, 0, SEEK_SET);
967 copy = malloc (numbytes);
968 fread (copy, 1, numbytes, base_file);
969 num_entries = numbytes / sizeof (long);
972 fprintf (f, "\t.section\t.reloc\n");
979 qsort (copy, num_entries, sizeof (long), sfunc);
980 /* Delete duplcates */
981 for (src = 0; src < num_entries; src++)
983 if (last != copy[src])
984 last = copy[dst++] = copy[src];
988 page_addr = addr & PAGE_MASK; /* work out the page addr */
990 for (j = 0; j < num_entries; j++)
993 if ((addr & PAGE_MASK) != page_addr)
995 flush_page (f, need, page_addr, on_page);
997 page_addr = addr & PAGE_MASK;
999 need[on_page++] = addr;
1001 flush_page (f, need, page_addr, on_page);
1003 fprintf (f, "\t%s\t0,0\t%s End\n", ASM_LONG, ASM_C);
1009 /* assemble the file */
1010 sprintf (outfile, "-o %s t%s", exp_name, exp_name);
1011 run (as_name, outfile);
1012 if (dontdeltemps == 0)
1014 sprintf (outfile, "t%s", exp_name);
1024 char *copy = malloc (strlen (name) + 2);
1026 strcpy (copy + 1, name);
1033 p = strchr (name, '@');
1040 /**********************************************************************/
1042 static void dump_iat (f, exp)
1046 if (exp->noname && !show_allnames )
1048 fprintf (f, "\t%s\t0x%08x\n",
1050 exp->ordinal | 0x80000000); /* hint or orindal ?? */
1054 fprintf (f, "\t%sID%d%s\n", ASM_RVA_BEFORE,
1066 char *output_filename;
1067 char prefix[PATHMAX];
1069 sprintf (outfile, "%s", imp_name);
1070 output_filename = strdup (outfile);
1072 unlink (output_filename);
1074 strcpy (prefix, "d");
1075 sprintf (outfile, "%sh.s", prefix);
1077 f = fopen (outfile, "w");
1079 fprintf (f, "%s IMAGE_IMPORT_DESCRIPTOR\n", ASM_C);
1080 fprintf (f, "\t.section .idata$2\n");
1082 fprintf (f, "\t%s\t__%s_head\n", ASM_GLOBAL, imp_name_lab);
1083 fprintf (f, "__%s_head:\n", imp_name_lab);
1085 fprintf (f, "\t%shname%s\t%sPtr to image import by name list\n",
1086 ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C);
1088 fprintf (f, "\t%sthis should be the timestamp, but NT sometimes\n", ASM_C);
1089 fprintf (f, "\t%sdoesn't load DLLs when this is set.\n", ASM_C);
1090 fprintf (f, "\t%s\t0\t%s loaded time\n", ASM_LONG, ASM_C);
1091 fprintf (f, "\t%s\t0\t%s Forwarder chain\n", ASM_LONG, ASM_C);
1092 fprintf (f, "\t%s__%s_iname%s\t%s imported dll's name\n",
1097 fprintf (f, "\t%sfthunk%s\t%s pointer to firstthunk\n",
1099 ASM_RVA_AFTER, ASM_C);
1101 fprintf (f, "%sStuff for compatibility\n", ASM_C);
1102 fprintf (f, "\t.section\t.idata$5\n");
1103 fprintf (f, "\t%s\t0\n", ASM_LONG);
1104 fprintf (f, "fthunk:\n");
1105 fprintf (f, "\t.section\t.idata$4\n");
1107 fprintf (f, "\t%s\t0\n", ASM_LONG);
1108 fprintf (f, "\t.section .idata$4\n");
1109 fprintf (f, "hname:\n");
1113 sprintf (outfile, "-o %sh.o %sh.s", prefix, prefix);
1114 run (as_name, outfile);
1116 for (i = 0; exp = d_exports_lexically[i]; i++)
1118 sprintf (outfile, "%ss%d.s", prefix, i);
1119 f = fopen (outfile, "w");
1120 fprintf (f, "\t.text\n");
1121 fprintf (f, "\t%s\t%s%s\n", ASM_GLOBAL, ASM_PREFIX, exp->name);
1122 fprintf (f, "\t%s\t__imp_%s\n", ASM_GLOBAL, exp->name);
1123 fprintf (f, "%s%s:\n\t%s\t__imp_%s\n", ASM_PREFIX,
1124 exp->name, ASM_JUMP, exp->name);
1126 fprintf (f, "\t.section\t.idata$7\t%s To force loading of head\n", ASM_C);
1127 fprintf (f, "\t%s\t__%s_head\n", ASM_LONG, imp_name_lab);
1130 fprintf (f,"%s Import Address Table\n", ASM_C);
1132 fprintf (f, "\t.section .idata$5\n");
1133 fprintf (f, "__imp_%s:\n", exp->name);
1137 fprintf (f, "\n%s Import Lookup Table\n", ASM_C);
1138 fprintf (f, "\t.section .idata$4\n");
1142 if(!exp->noname || show_allnames)
1144 fprintf (f, "%s Hint/Name table\n", ASM_C);
1145 fprintf (f, "\t.section .idata$6\n");
1146 fprintf (f, "ID%d:\t%s\t%d\n", exp->ordinal, ASM_SHORT, exp->hint);
1147 fprintf (f, "\t%s\t\"%s\"\n", ASM_TEXT, xlate (exp->name));
1153 sprintf (outfile, "-o %ss%d.o %ss%d.s", prefix, i, prefix, i);
1154 run (as_name, outfile);
1157 sprintf (outfile, "%st.s", prefix);
1158 f = fopen (outfile, "w");
1159 fprintf (f, "\t.section .idata$7\n");
1160 fprintf (f, "\t%s\t__%s_iname\n", ASM_GLOBAL, imp_name_lab);
1161 fprintf (f, "__%s_iname:\t%s\t\"%s\"\n",
1162 imp_name_lab, ASM_TEXT, dll_name);
1165 fprintf (f, "\t.section .idata$4\n");
1166 fprintf (f, "\t%s\t0\n", ASM_LONG);
1168 fprintf (f, "\t.section .idata$5\n");
1169 fprintf (f, "\t%s\t0\n", ASM_LONG);
1172 sprintf (outfile, "-o %st.o %st.s", prefix, prefix);
1173 run (as_name, outfile);
1175 /* Now stick them all into the archive */
1178 sprintf (outfile, "crs %s %sh.o %st.o", output_filename, prefix, prefix);
1179 run (ar_name, outfile);
1181 /* Do the rest in groups of however many fit into a command line */
1183 for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
1187 sprintf (outfile, "crs %s", output_filename);
1188 sol = strlen (outfile);
1191 sprintf (outfile + sol, " %ss%d.o", prefix, i);
1192 sol = strlen (outfile);
1196 run (ar_name, outfile);
1202 run (ar_name, outfile);
1204 /* Delete all the temp files */
1206 if (dontdeltemps == 0)
1208 sprintf (outfile, "%sh.o", prefix);
1210 sprintf (outfile, "%sh.s", prefix);
1212 sprintf (outfile, "%st.o", prefix);
1214 sprintf (outfile, "%st.s", prefix);
1218 if (dontdeltemps < 2)
1219 for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
1221 sprintf (outfile, "%ss%d.o", prefix, i);
1223 sprintf (outfile, "%ss%d.s", prefix, i);
1228 /**********************************************************************/
1230 /* Run through the information gathered from the .o files and the
1231 .def file and work out the best stuff */
1237 export_type *ap = *(export_type **) a;
1238 export_type *bp = *(export_type **) b;
1239 if (ap->ordinal == bp->ordinal)
1242 /* unset ordinals go to the bottom */
1243 if (ap->ordinal == -1)
1245 if (bp->ordinal == -1)
1247 return (ap->ordinal - bp->ordinal);
1256 export_type *ap = *(export_type **) a;
1257 export_type *bp = *(export_type **) b;
1259 return (strcmp (ap->name, bp->name));
1264 remove_null_names (ptr)
1269 for (dst = src = 0; src < d_nfuncs; src++)
1273 ptr[dst] = ptr[src];
1286 for (i = 0; i < d_nfuncs; i++)
1290 printf ("%d %s @ %d %s%s\n",
1291 i, ptr[i]->name, ptr[i]->ordinal,
1292 ptr[i]->noname ? "NONAME " : "",
1293 ptr[i]->constant ? "CONSTANT" : "");
1302 process_duplicates (d_export_vec)
1303 export_type **d_export_vec;
1311 /* Remove duplicates */
1312 qsort (d_export_vec, d_nfuncs, sizeof (export_type *), nfunc);
1314 dtab (d_export_vec);
1315 for (i = 0; i < d_nfuncs - 1; i++)
1317 if (strcmp (d_export_vec[i]->name,
1318 d_export_vec[i + 1]->name) == 0)
1321 export_type *a = d_export_vec[i];
1322 export_type *b = d_export_vec[i + 1];
1326 fprintf (stderr, "Warning, ignoring duplicate EXPORT %s %d,%d\n",
1330 if (a->ordinal != -1
1331 && b->ordinal != -1)
1334 fprintf (stderr, "Error, duplicate EXPORT with oridinals %s\n",
1338 /* Merge attributes */
1339 b->ordinal = a->ordinal > 0 ? a->ordinal : b->ordinal;
1340 b->constant |= a->constant;
1341 b->noname |= a->noname;
1342 d_export_vec[i] = 0;
1345 dtab (d_export_vec);
1346 remove_null_names (d_export_vec);
1347 dtab (d_export_vec);
1352 /* Count the names */
1353 for (i = 0; i < d_nfuncs; i++)
1355 if (!d_export_vec[i]->noname)
1361 fill_ordinals (d_export_vec)
1362 export_type **d_export_vec;
1369 qsort (d_export_vec, d_nfuncs, sizeof (export_type *), pfunc);
1371 /* fill in the unset ordinals with ones from our range */
1373 ptr = (char *) malloc (65536);
1375 memset (ptr, 65536, 0);
1377 /* Mark in our large vector all the numbers that are taken */
1378 for (i = 0; i < d_nfuncs; i++)
1380 if (d_export_vec[i]->ordinal != -1)
1382 ptr[d_export_vec[i]->ordinal] = 1;
1384 lowest = d_export_vec[i]->ordinal;
1388 for (i = 0; i < d_nfuncs; i++)
1390 if (d_export_vec[i]->ordinal == -1)
1393 for (j = lowest; j < 65536; j++)
1397 d_export_vec[i]->ordinal = j;
1401 for (j = 1; j < lowest; j++)
1405 d_export_vec[i]->ordinal = j;
1417 qsort (d_export_vec, d_nfuncs, sizeof (export_type *), pfunc);
1420 /* Work out the lowest ordinal number */
1421 if (d_export_vec[0])
1422 d_low_ord = d_export_vec[0]->ordinal;
1424 if (d_export_vec[d_nfuncs-1])
1425 d_high_ord = d_export_vec[d_nfuncs-1]->ordinal;
1429 int alphafunc(av,bv)
1433 export_type **a = av;
1434 export_type **b = bv;
1436 return strcmp ((*a)->name, (*b)->name);
1442 /* First work out the minimum ordinal chosen */
1448 export_type **d_export_vec
1449 = (export_type **) xmalloc (sizeof (export_type *) * d_nfuncs);
1451 for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
1453 d_export_vec[i] = exp;
1456 process_duplicates (d_export_vec);
1457 fill_ordinals (d_export_vec);
1459 /* Put back the list in the new order */
1461 for (i = d_nfuncs - 1; i >= 0; i--)
1463 d_export_vec[i]->next = d_exports;
1464 d_exports = d_export_vec[i];
1467 /* Build list in alpha order */
1468 d_exports_lexically = (export_type **)xmalloc (sizeof(export_type *)*(d_nfuncs+1));
1470 for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
1472 d_exports_lexically[i] = exp;
1474 d_exports_lexically[i] = 0;
1476 qsort (d_exports_lexically, i, sizeof (export_type *), alphafunc);
1478 /* Fill exp entries with their hint values */
1480 for (i = 0; i < d_nfuncs; i++)
1482 if (!d_exports_lexically[i]->noname || show_allnames)
1483 d_exports_lexically[i]->hint = hint++;
1490 /* Work out exec prefix from the name of this file */
1497 /* See if we're running in a devo tree */
1498 for (p = program_name; *p; p++)
1500 if (*p == '/' || *p == '\\')
1507 if (ps && strncmp (ps, "/binutils", 9) == 0)
1509 /* running in the binutils directory, the other
1510 executables will be surrounding it in the usual places. */
1511 int len = ps - program_name;
1512 ar_name = xmalloc (len + strlen ("/binutils/ar") + 1);
1513 ranlib_name = xmalloc (len + strlen ("/binutils/ranlib") + 1);
1514 as_name = xmalloc (len + strlen ("/gas/as.new") + 1);
1516 memcpy (ar_name, program_name, len);
1517 strcpy (ar_name + len, "/binutils/ar");
1518 memcpy (ranlib_name, program_name, len);
1519 strcpy (ranlib_name + len, "/binutils/ranlib");
1520 memcpy (as_name, program_name, len);
1521 strcpy (as_name + len, "/gas/as.new");
1525 /* Otherwise chop off any prefix and use it for the rest of the progs,
1526 so i386-win32-dll generates i386-win32-ranlib etc etc */
1528 for (p = program_name; *p; p++)
1530 if (strncmp (p, "dlltool", 7) == 0)
1532 int len = p - program_name;
1533 ar_name = xmalloc (len + strlen ("ar") + 1);
1534 ranlib_name = xmalloc (len + strlen ("ranlib") + 1);
1535 as_name = xmalloc (len + strlen ("as") + 1);
1537 memcpy (ar_name, program_name, len);
1538 strcpy (ar_name + len, "ar");
1539 memcpy (ranlib_name, program_name, len);
1540 strcpy (ranlib_name + len, "ranlib");
1541 memcpy (as_name, program_name, len);
1542 strcpy (as_name + len, "as");
1549 /**********************************************************************/
1552 usage (file, status)
1556 fprintf (file, "Usage %s <options> <object-files>\n", program_name);
1557 fprintf (file, " --machine <machine>\n");
1558 fprintf (file, " --output-exp <outname> Generate export file.\n");
1559 fprintf (file, " --output-lib <outname> Generate input library.\n");
1560 fprintf (file, " --add-indirect Add dll indirects to export file.\n");
1561 fprintf (file, " --dllname <name> Name of input dll to put into output lib.\n");
1562 fprintf (file, " --def <deffile> Name input .def file\n");
1563 fprintf (file, " --output-def <deffile> Name output .def file\n");
1564 fprintf (file, " --base-file <basefile> Read linker generated base file\n");
1565 fprintf (file, " -v Verbose\n");
1566 fprintf (file, " -U Add underscores to .lib\n");
1567 fprintf (file, " -k Kill @<n> from exported names\n");
1568 fprintf (file, " --nodelete Keep temp files.\n");
1572 static struct option long_options[] =
1574 {"nodelete", no_argument, NULL, 'n'},
1575 {"dllname", required_argument, NULL, 'D'},
1576 {"output-exp", required_argument, NULL, 'e'},
1577 {"output-def", required_argument, NULL, 'z'},
1578 {"output-lib", required_argument, NULL, 'l'},
1579 {"def", required_argument, NULL, 'd'},
1580 {"add-underscore", no_argument, NULL, 'U'},
1581 {"killat", no_argument, NULL, 'k'},
1582 {"help", no_argument, NULL, 'h'},
1583 {"machine", required_argument, NULL, 'm'},
1584 {"add-indirect", no_argument, NULL, 'a'},
1585 {"base-file", required_argument, NULL, 'b'},
1599 program_name = av[0];
1602 while ((c = getopt_long (ac, av, "uaD:l:e:nkvbUh?m:yd:", long_options, 0)) != EOF)
1606 /* ignored for compatibility */
1613 output_def = fopen (optarg, "w");
1650 base_file = fopen (optarg, "r");
1653 fprintf (stderr, "%s: Unable to open base-file %s\n",
1665 for (i = 0; mtable[i].type; i++)
1667 if (strcmp (mtable[i].type, mname) == 0)
1671 if (!mtable[i].type)
1673 fprintf (stderr, "Machine not supported\n");
1679 if (!dll_name && exp_name)
1681 char len = strlen (exp_name) + 5;
1682 dll_name = xmalloc (len);
1683 strcpy (dll_name, exp_name);
1684 strcat (dll_name, ".dll");
1691 process_def_file (def_file);
1696 firstarg = av[optind];
1697 scan_obj_file (av[optind]);
1708 /* Make imp_name safe for use as a label. */
1710 imp_name_lab = strdup (imp_name);
1711 for (p = imp_name_lab; *p; *p++)
1713 if (!isalpha (*p) && !isdigit (*p))