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 "demangle.h"
171 #ifdef HAVE_SYS_WAIT_H
172 #include <sys/wait.h>
175 #define WIFEXITED(w) (((w)&0377) == 0)
178 #define WIFSIGNALED(w) (((w)&0377) != 0177 && ((w)&~0377) == 0)
181 #define WTERMSIG(w) ((w) & 0177)
184 #define WEXITSTATUS(w) (((w) >> 8) & 0377)
190 char *as_name = "as";
192 static int no_idata4;
193 static int no_idata5;
194 static char *exp_name;
195 static char *imp_name;
196 static char *head_label;
197 static char *imp_name_lab;
198 static char *dll_name;
200 static int add_indirect = 0;
201 static int add_underscore = 0;
202 static int dontdeltemps = 0;
206 static char *def_file;
208 static char *program_name;
219 static char *mname = "arm";
223 static char *mname = "i386";
227 static char *mname = "ppc";
230 #define PATHMAX 250 /* What's the right name for this ? */
232 /* This bit of assemly does jmp * ....
233 s set how_jtab_roff to mark where the 32bit abs branch should go */
234 unsigned char i386_jtab[] = { 0xff, 0x25, 0x00, 0x00, 0x00, 0x00, 0x90, 0x90};
237 unsigned char arm_jtab[] = { 0x00, 0xc0, 0x9f, 0xe5,
238 0x00, 0xf0, 0x9c, 0xe5,
240 /* If I understand what is going on here, this will need more for ppc
243 unsigned char ppc_jtab[] = { 0xff, 0x25, 0x00, 0x00, 0x00, 0x00, 0x90, 0x90};
245 char outfile[PATHMAX];
257 char *how_align_short;
258 char *how_align_long;
259 char *how_bfd_target;
260 enum bfd_architecture how_bfd_arch;
261 unsigned char *how_jtab;
262 int how_jtab_size; /* size of the jtab entry */
263 int how_jtab_roff; /* offset into it for the ind 32 reloc into idata 5 */
270 "arm", ".byte", ".short", ".long", ".asciz", "@",
271 "ldr\tip,[pc]\n\tldr\tpc,[ip]\n\t.long",
272 ".global", ".space", ".align\t2",".align\t4","pe-arm-little", bfd_arch_arm,
273 arm_jtab, sizeof(arm_jtab),8
278 "i386", ".byte", ".short", ".long", ".asciz", "#", "jmp *", ".global", ".space", ".align\t2",".align\t4","pe-i386",bfd_arch_i386,
279 i386_jtab,sizeof(i386_jtab),2,
284 "ppc", ".byte", ".short", ".long", ".asciz", "#", "jmp *", ".global", ".space", ".align\t2",".align\t4","pe-powerpcle",bfd_arch_powerpc,
285 ppc_jtab,sizeof(ppc_jtab),2,
339 #define ASM_BYTE mtable[machine].how_byte
340 #define ASM_SHORT mtable[machine].how_short
341 #define ASM_LONG mtable[machine].how_long
342 #define ASM_TEXT mtable[machine].how_asciz
343 #define ASM_C mtable[machine].how_comment
344 #define ASM_JUMP mtable[machine].how_jump
345 #define ASM_GLOBAL mtable[machine].how_global
346 #define ASM_SPACE mtable[machine].how_space
347 #define ASM_ALIGN_SHORT mtable[machine].how_align_short
348 #define ASM_RVA_BEFORE rvabefore(machine)
349 #define ASM_RVA_AFTER rvaafter(machine)
350 #define ASM_PREFIX asm_prefix(machine)
351 #define ASM_ALIGN_LONG mtable[machine].how_align_long
352 #define HOW_BFD_TARGET 0 /* always default*/
353 #define HOW_BFD_ARCH mtable[machine].how_bfd_arch
354 #define HOW_JTAB mtable[machine].how_jtab
355 #define HOW_JTAB_SIZE mtable[machine].how_jtab_size
356 #define HOW_JTAB_ROFF mtable[machine].how_jtab_roff
360 FILE *yyin; /* communications with flex */
361 extern int linenumber;
363 process_def_file (name)
366 FILE *f = fopen (name, FOPEN_RT);
369 fprintf (stderr, "%s: Can't open def file %s\n", program_name, name);
378 /**********************************************************************/
380 /* Communications with the parser */
390 typedef struct export
402 static char *d_name; /* Arg to NAME or LIBRARY */
403 static int d_nfuncs; /* Number of functions exported */
404 static int d_named_nfuncs; /* Number of named functions exported */
405 static int d_low_ord; /* Lowest ordinal index */
406 static int d_high_ord; /* Highest ordinal index */
407 static export_type *d_exports; /*list of exported functions */
408 static export_type **d_exports_lexically; /* vector of exported functions in alpha order */
409 static dlist_type *d_list; /* Descriptions */
410 static dlist_type *a_list; /* Stuff to go in directives */
418 fprintf (stderr, "%s: Syntax error in def file %s:%d\n",
419 program_name, def_file, linenumber);
424 def_exports (name, internal_name, ordinal, noname, constant)
431 struct export *p = (struct export *) xmalloc (sizeof (*p));
434 p->internal_name = internal_name ? internal_name : name;
435 p->ordinal = ordinal;
436 p->constant = constant;
445 def_name (name, base)
450 fprintf (stderr, "%s NAME %s base %x\n", program_name, name, base);
453 fprintf (stderr, "Can't have LIBRARY and NAME\n");
460 def_library (name, base)
465 printf ("%s: LIBRARY %s base %x\n", program_name, name, base);
468 fprintf (stderr, "%s: Can't have LIBRARY and NAME\n", program_name);
475 def_description (desc)
478 dlist_type *d = (dlist_type *) xmalloc (sizeof (dlist_type));
479 d->text = strdup (desc);
488 dlist_type *d = (dlist_type *) xmalloc (sizeof (dlist_type));
489 d->text = strdup (dir);
495 def_stacksize (reserve, commit)
501 sprintf (b, "-stack 0x%x,0x%x ", reserve, commit);
503 sprintf (b, "-stack 0x%x ", reserve);
504 new_directive (strdup (b));
508 def_heapsize (reserve, commit)
514 sprintf (b, "-heap 0x%x,0x%x ", reserve, commit);
516 sprintf (b, "-heap 0x%x ", reserve);
517 new_directive (strdup (b));
522 def_import (internal, module, entry)
528 fprintf (stderr, "%s: IMPORTS are ignored", program_name);
532 def_version (major, minor)
536 printf ("VERSION %d.%d\n", major, minor);
541 def_section (name, attr)
558 sprintf (buf, "-attr %s %s", name, atts);
559 new_directive (strdup (buf));
566 def_section ("CODE", attr);
573 def_section ("DATA", attr);
577 /**********************************************************************/
588 extern char **environ;
590 fprintf (stderr, "%s %s\n", what, args);
594 for (s = args; *s; s++)
598 argv = alloca (sizeof (char *) * (i + 3));
605 while (*s != ' ' && *s != 0)
619 fprintf (stderr, "%s: can't exec %s\n", program_name, what);
625 fprintf (stderr, "%s: vfork failed, %d\n", program_name, errno);
631 waitpid (pid, &status, 0);
634 if (WIFSIGNALED (status))
636 fprintf (stderr, "%s: %s %s terminated with signal %d\n",
637 program_name, what, args, WTERMSIG (status));
641 if (WIFEXITED (status))
643 fprintf (stderr, "%s: %s %s terminated with exit status %d\n",
644 program_name, what, args, WEXITSTATUS (status));
651 /* read in and block out the base relocations */
663 scan_open_obj_file (abfd)
666 /* Look for .drectve's */
667 asection *s = bfd_get_section_by_name (abfd, ".drectve");
670 int size = bfd_get_section_size_before_reloc (s);
671 char *buf = xmalloc (size);
674 bfd_get_section_contents (abfd, s, buf, 0, size);
676 fprintf (stderr, "%s: Sucking in info from %s\n",
678 bfd_get_filename (abfd));
680 /* Search for -export: strings */
686 && strncmp (p, "-export:", 8) == 0)
692 while (*p != ' ' && *p != '-' && p < e)
694 c = xmalloc (p - name + 1);
695 memcpy (c, name, p - name);
697 def_exports (c, 0, -1, 0);
708 fprintf (stderr, "%s: Done readin\n",
715 scan_obj_file (filename)
718 bfd *f = bfd_openr (filename, 0);
722 fprintf (stderr, "%s: Unable to open object file %s\n",
727 if (bfd_check_format (f, bfd_archive))
729 bfd *arfile = bfd_openr_next_archived_file (f, 0);
732 if (bfd_check_format (arfile, bfd_object))
733 scan_open_obj_file (arfile);
735 arfile = bfd_openr_next_archived_file (f, arfile);
738 else if (bfd_check_format (f, bfd_object))
740 scan_open_obj_file (f);
746 /**********************************************************************/
756 fprintf (f, "%s ", ASM_C);
757 for (i = 0; oav[i]; i++)
758 fprintf (f, "%s ", oav[i]);
760 for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
762 fprintf (f, "%s %d = %s %s @ %d %s%s\n",
768 exp->noname ? "NONAME " : "",
769 exp->constant ? "CONSTANT" : "");
772 /* Generate the .exp file */
785 flush_page (f, need, page_addr, on_page)
793 /* Flush this page */
794 fprintf (f, "\t%s\t0x%08x\t%s Starting RVA for chunk\n",
798 fprintf (f, "\t%s\t0x%x\t%s Size of block\n",
800 (on_page * 2) + (on_page & 1) * 2 + 8,
802 for (i = 0; i < on_page; i++)
804 fprintf (f, "\t%s\t0x%x\n", ASM_SHORT, (need[i] - page_addr) | 0x3000);
808 fprintf (f, "\t%s\t0x%x\n", ASM_SHORT, 0 | 0x0000);
819 fprintf (output_def, ";");
820 for (i = 0; oav[i]; i++)
821 fprintf (output_def, " %s", oav[i]);
823 fprintf (output_def, "\nEXPORTS\n");
825 for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
827 char *quote = strchr (exp->name, '.') ? "\"" : "";
828 fprintf (output_def, "\t%s%s%s @ %d%s ; %s\n",
833 exp->noname ? " NONAME" : "",
834 cplus_demangle (exp->internal_name, DMGL_ANSI | DMGL_PARAMS));
846 sprintf (outfile, "t%s", exp_name);
849 fprintf (stderr, "%s: Generate exp file %s\n",
850 program_name, exp_name);
852 f = fopen (outfile, FOPEN_WT);
855 fprintf (stderr, "%s: Unable to open output file %s\n", program_name, outfile);
860 fprintf (stderr, "%s: Opened file %s\n",
861 program_name, outfile);
867 fprintf (f, "\t.section .edata\n\n");
868 fprintf (f, "\t%s 0 %s Allways 0\n", ASM_LONG, ASM_C);
869 fprintf (f, "\t%s 0x%x %s Time and date\n", ASM_LONG, time(0),ASM_C);
870 fprintf (f, "\t%s 0 %s Major and Minor version\n", ASM_LONG, ASM_C);
871 fprintf (f, "\t%sname%s %s Ptr to name of dll\n", ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C);
872 fprintf (f, "\t%s %d %s Starting ordinal of exports\n", ASM_LONG, d_low_ord, ASM_C);
875 fprintf (f, "\t%s %d %s Number of functions\n", ASM_LONG, d_high_ord - d_low_ord + 1, ASM_C);
876 fprintf(f,"\t%s named funcs %d, low ord %d, high ord %d\n",
878 d_named_nfuncs, d_low_ord, d_high_ord);
879 fprintf (f, "\t%s %d %s Number of names\n", ASM_LONG,
880 show_allnames ? d_high_ord - d_low_ord + 1 : d_named_nfuncs, ASM_C);
881 fprintf (f, "\t%safuncs%s %s Address of functions\n", ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C);
883 fprintf (f, "\t%sanames%s %s Address of Name Pointer Table\n",
884 ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C);
886 fprintf (f, "\t%sanords%s %s Address of ordinals\n", ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C);
888 fprintf (f, "name: %s \"%s\"\n", ASM_TEXT, dll_name);
891 fprintf(f,"%s Export address Table\n", ASM_C);
892 fprintf(f,"\t%s\n", ASM_ALIGN_LONG);
893 fprintf (f, "afuncs:\n");
896 for (exp = d_exports; exp; exp = exp->next)
898 if (exp->ordinal != i)
901 fprintf (f, "\t%s\t%d\t%s %d..%d missing\n",
903 (exp->ordinal - i) * 4,
905 i, exp->ordinal - 1);
908 while (i < exp->ordinal)
910 fprintf(f,"\t%s\t0\n", ASM_LONG);
914 fprintf (f, "\t%s%s%s%s\t%s %d\n", ASM_RVA_BEFORE,
916 exp->internal_name, ASM_RVA_AFTER, ASM_C, exp->ordinal);
920 fprintf (f,"%s Export Name Pointer Table\n", ASM_C);
921 fprintf (f, "anames:\n");
923 for (i = 0; (exp = d_exports_lexically[i]); i++)
925 if (!exp->noname || show_allnames)
926 fprintf (f, "\t%sn%d%s\n", ASM_RVA_BEFORE, exp->ordinal, ASM_RVA_AFTER);
929 fprintf (f,"%s Export Oridinal Table\n", ASM_C);
930 fprintf (f, "anords:\n");
931 for (i = 0; (exp = d_exports_lexically[i]); i++)
933 if (!exp->noname || show_allnames)
934 fprintf (f, "\t%s %d\n", ASM_SHORT, exp->ordinal - d_low_ord);
937 fprintf(f,"%s Export Name Table\n", ASM_C);
938 for (i = 0; (exp = d_exports_lexically[i]); i++)
939 if (!exp->noname || show_allnames)
940 fprintf (f, "n%d: %s \"%s\"\n", exp->ordinal, ASM_TEXT, exp->name);
944 fprintf (f, "\t.section .drectve\n");
945 for (dl = a_list; dl; dl = dl->next)
947 fprintf (f, "\t%s\t\"%s\"\n", ASM_TEXT, dl->text);
952 fprintf (f, "\t.section .rdata\n");
953 for (dl = d_list; dl; dl = dl->next)
957 /* We dont output as ascii 'cause there can
958 be quote characters in the string */
961 for (p = dl->text; *p; p++)
964 fprintf (f, "\t%s\t", ASM_BYTE);
967 fprintf (f, "%d", *p);
984 /* Add to the output file a way of getting to the exported names
985 without using the import library. */
988 fprintf (f, "\t.section\t.rdata\n");
989 for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
990 if (!exp->noname || show_allnames)
992 fprintf (f, "\t%s\t__imp_%s\n", ASM_GLOBAL, exp->name);
993 fprintf (f, "__imp_%s:\n", exp->name);
994 fprintf (f, "\t%s\t%s\n", ASM_LONG, exp->name);
998 /* Dump the reloc section if a base file is provided */
1002 long need[PAGE_SIZE];
1009 fprintf (f, "\t.section\t.init\n");
1010 fprintf (f, "lab:\n");
1012 fseek (base_file, 0, SEEK_END);
1013 numbytes = ftell (base_file);
1014 fseek (base_file, 0, SEEK_SET);
1015 copy = malloc (numbytes);
1016 fread (copy, 1, numbytes, base_file);
1017 num_entries = numbytes / sizeof (long);
1020 fprintf (f, "\t.section\t.reloc\n");
1027 qsort (copy, num_entries, sizeof (long), sfunc);
1028 /* Delete duplcates */
1029 for (src = 0; src < num_entries; src++)
1031 if (last != copy[src])
1032 last = copy[dst++] = copy[src];
1036 page_addr = addr & PAGE_MASK; /* work out the page addr */
1038 for (j = 0; j < num_entries; j++)
1041 if ((addr & PAGE_MASK) != page_addr)
1043 flush_page (f, need, page_addr, on_page);
1045 page_addr = addr & PAGE_MASK;
1047 need[on_page++] = addr;
1049 flush_page (f, need, page_addr, on_page);
1051 /* fprintf (f, "\t%s\t0,0\t%s End\n", ASM_LONG, ASM_C);*/
1057 /* assemble the file */
1058 sprintf (outfile, "-o %s t%s", exp_name, exp_name);
1059 run (as_name, outfile);
1060 if (dontdeltemps == 0)
1062 sprintf (outfile, "t%s", exp_name);
1072 char *copy = malloc (strlen (name) + 2);
1074 strcpy (copy + 1, name);
1081 p = strchr (name, '@');
1088 /**********************************************************************/
1090 static void dump_iat (f, exp)
1094 if (exp->noname && !show_allnames )
1096 fprintf (f, "\t%s\t0x%08x\n",
1098 exp->ordinal | 0x80000000); /* hint or orindal ?? */
1102 fprintf (f, "\t%sID%d%s\n", ASM_RVA_BEFORE,
1119 unsigned char *data;
1132 static sinfo secdata[NSECS] =
1134 { TEXT, ".text", SEC_CODE | SEC_HAS_CONTENTS},
1135 { DATA, ".data", SEC_DATA},
1137 { IDATA7, ".idata$7",SEC_HAS_CONTENTS},
1138 { IDATA5, ".idata$5", SEC_HAS_CONTENTS},
1139 { IDATA4, ".idata$4", SEC_HAS_CONTENTS},
1140 { IDATA6,".idata$6", SEC_HAS_CONTENTS}
1145 This is what we're trying to make
1148 .global _GetFileVersionInfoSizeW@8
1149 .global __imp_GetFileVersionInfoSizeW@8
1150 _GetFileVersionInfoSizeW@8:
1151 jmp * __imp_GetFileVersionInfoSizeW@8
1152 .section .idata$7 # To force loading of head
1153 .long __version_a_head
1154 # Import Address Table
1156 __imp_GetFileVersionInfoSizeW@8:
1159 # Import Lookup Table
1165 .asciz "GetFileVersionInfoSizeW"
1169 static char *make_label (prefix, name)
1173 int len = strlen (ASM_PREFIX) + strlen (prefix) + strlen (name);
1174 char *copy = xmalloc (len +1 );
1175 strcpy (copy, ASM_PREFIX);
1176 strcat (copy, prefix);
1177 strcat (copy, name);
1181 make_one_lib_file (exp, i)
1189 sprintf (outfile, "%ss%d.s", prefix, i);
1190 f = fopen (outfile, FOPEN_WT);
1191 fprintf (f, "\t.text\n");
1192 fprintf (f, "\t%s\t%s%s\n", ASM_GLOBAL, ASM_PREFIX, exp->name);
1193 fprintf (f, "\t%s\t__imp_%s\n", ASM_GLOBAL, exp->name);
1194 fprintf (f, "%s%s:\n\t%s\t__imp_%s\n", ASM_PREFIX,
1195 exp->name, ASM_JUMP, exp->name);
1197 fprintf (f, "\t.section\t.idata$7\t%s To force loading of head\n", ASM_C);
1198 fprintf (f, "\t%s\t%s\n", ASM_LONG, head_label);
1201 fprintf (f,"%s Import Address Table\n", ASM_C);
1203 fprintf (f, "\t.section .idata$5\n");
1204 fprintf (f, "__imp_%s:\n", exp->name);
1208 fprintf (f, "\n%s Import Lookup Table\n", ASM_C);
1209 fprintf (f, "\t.section .idata$4\n");
1213 if(!exp->noname || show_allnames)
1215 fprintf (f, "%s Hint/Name table\n", ASM_C);
1216 fprintf (f, "\t.section .idata$6\n");
1217 fprintf (f, "ID%d:\t%s\t%d\n", exp->ordinal, ASM_SHORT, exp->hint);
1218 fprintf (f, "\t%s\t\"%s\"\n", ASM_TEXT, xlate (exp->name));
1224 sprintf (outfile, "-o %ss%d.o %ss%d.s", prefix, i, prefix, i);
1226 run (as_name, outfile);
1237 asymbol **iname_lab_pp;
1238 asymbol *ptrs[NSECS+3+1]; /* one symbol for each section, 2 extra + a null */
1240 char *outname = xmalloc (10);
1242 sprintf (outname, "ds%d.o", i);
1243 abfd = bfd_openw (outname, HOW_BFD_TARGET);
1246 fprintf (stderr, "%s: bfd_open failed open output file %s\n", program_name, outname);
1250 bfd_set_format (abfd, bfd_object);
1251 bfd_set_arch_mach (abfd, HOW_BFD_ARCH, 0);
1254 for (i = 0; i < NSECS; i++)
1256 sinfo *si = secdata + i;
1259 si->sec = bfd_make_section_old_way (abfd, si->name);
1260 bfd_set_section_flags (abfd,
1263 si->sec->output_section = si->sec;
1264 si->sym = bfd_make_empty_symbol(abfd);
1265 si->sym->name = si->sec->name;
1266 si->sym->section = si->sec;
1267 si->sym->flags = BSF_LOCAL;
1269 ptrs[oidx] = si->sym;
1270 si->sympp = ptrs + oidx;
1275 exp_label = bfd_make_empty_symbol(abfd);
1276 exp_label->name = make_label ("",exp->name);
1277 exp_label->section = secdata[TEXT].sec;
1278 exp_label->flags = BSF_GLOBAL;
1279 exp_label->value = 0;
1281 ptrs[oidx++] = exp_label;
1283 iname = bfd_make_empty_symbol(abfd);
1285 iname->name = make_label ("__imp_", exp->name);
1287 iname->section = secdata[IDATA5].sec;
1288 iname->flags = BSF_GLOBAL;
1292 iname_lab = bfd_make_empty_symbol(abfd);
1294 iname_lab->name = head_label;
1295 iname_lab->section = (asection *)&bfd_und_section;
1296 iname_lab->flags = 0;
1297 iname_lab->value = 0;
1300 ptrs[oidx++] = iname;
1301 iname_lab_pp = ptrs + oidx;
1302 ptrs[oidx++] = iname_lab;
1305 for (i = 0; i < NSECS; i++)
1307 sinfo *si = secdata + i;
1308 asection *sec = si->sec;
1315 si->size = HOW_JTAB_SIZE;
1316 si->data = xmalloc (HOW_JTAB_SIZE);
1317 memcpy (si->data, HOW_JTAB, HOW_JTAB_SIZE);
1319 /* add the reloc into idata$5 */
1320 rel = xmalloc (sizeof (arelent));
1321 rpp = xmalloc (sizeof (arelent *) * 2);
1324 rel->address = HOW_JTAB_ROFF;
1326 rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_32);
1327 rel->sym_ptr_ptr = secdata[IDATA5].sympp;
1328 sec->orelocation = rpp;
1329 sec->reloc_count = 1;
1333 /* An idata$4 or idata$5 is one word long, and has an
1337 si->data = xmalloc (4);
1342 si->data[0] = exp->ordinal ;
1343 si->data[1] = exp->ordinal >> 8;
1344 si->data[2] = exp->ordinal >> 16;
1349 sec->reloc_count = 1;
1350 memset (si->data, 0, si->size);
1351 rel = xmalloc (sizeof (arelent));
1352 rpp = xmalloc (sizeof (arelent *) * 2);
1357 rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_RVA);
1358 rel->sym_ptr_ptr = secdata[IDATA6].sympp;
1359 sec->orelocation = rpp;
1367 int idx = exp->hint + 1;
1368 si->size = strlen (xlate (exp->name)) + 3;
1369 si->data = xmalloc (si->size);
1370 si->data[0] = idx & 0xff;
1371 si->data[1] = idx >> 8;
1372 strcpy (si->data + 2, xlate (exp->name));
1377 si->data =xmalloc(4);
1378 memset (si->data, 0, si->size);
1379 rel = xmalloc (sizeof (arelent));
1380 rpp = xmalloc (sizeof (arelent *) * 2);
1384 rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_32);
1385 rel->sym_ptr_ptr = iname_lab_pp;
1386 sec->orelocation = rpp;
1387 sec->reloc_count = 1;
1394 /* Size up all the sections */
1395 for (i = 0; i < NSECS; i++)
1397 sinfo *si = secdata + i;
1398 bfd_set_section_size (abfd, si->sec, si->size);
1399 bfd_set_section_vma (abfd, si->sec, vma);
1400 /* vma += si->size;*/
1403 /* Write them out */
1404 for (i = 0; i < NSECS; i++)
1406 sinfo *si = secdata + i;
1407 if (i == IDATA5 && no_idata5)
1410 if (i == IDATA4 && no_idata4)
1413 bfd_set_section_contents (abfd, si->sec,
1418 bfd_set_symtab (abfd, ptrs, oidx);
1420 abfd = bfd_openr (outname, HOW_BFD_TARGET);
1431 FILE * f = fopen ("dh.s", FOPEN_WT);
1433 fprintf (f, "%s IMAGE_IMPORT_DESCRIPTOR\n", ASM_C);
1434 fprintf (f, "\t.section .idata$2\n");
1436 fprintf(f,"\t%s\t%s\n", ASM_GLOBAL,head_label);
1438 fprintf (f, "%s:\n", head_label);
1440 fprintf (f, "\t%shname%s\t%sPtr to image import by name list\n",
1441 ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C);
1443 fprintf (f, "\t%sthis should be the timestamp, but NT sometimes\n", ASM_C);
1444 fprintf (f, "\t%sdoesn't load DLLs when this is set.\n", ASM_C);
1445 fprintf (f, "\t%s\t0\t%s loaded time\n", ASM_LONG, ASM_C);
1446 fprintf (f, "\t%s\t0\t%s Forwarder chain\n", ASM_LONG, ASM_C);
1447 fprintf (f, "\t%s__%s_iname%s\t%s imported dll's name\n",
1452 fprintf (f, "\t%sfthunk%s\t%s pointer to firstthunk\n",
1454 ASM_RVA_AFTER, ASM_C);
1456 fprintf (f, "%sStuff for compatibility\n", ASM_C);
1460 fprintf (f, "\t.section\t.idata$5\n");
1461 fprintf (f, "\t%s\t0\n", ASM_LONG);
1462 fprintf (f, "fthunk:\n");
1466 fprintf (f, "\t.section\t.idata$4\n");
1468 fprintf (f, "\t%s\t0\n", ASM_LONG);
1469 fprintf (f, "\t.section .idata$4\n");
1470 fprintf (f, "hname:\n");
1474 sprintf (outfile, "-o dh.o dh.s");
1475 run (as_name, outfile);
1477 return bfd_openr ("dh.o", HOW_BFD_TARGET);
1483 FILE * f = fopen ("dt.s", FOPEN_WT);
1484 fprintf (f, "\t.section .idata$7\n");
1485 fprintf (f, "\t%s\t__%s_iname\n", ASM_GLOBAL, imp_name_lab);
1486 fprintf (f, "__%s_iname:\t%s\t\"%s\"\n",
1487 imp_name_lab, ASM_TEXT, dll_name);
1491 fprintf (f, "\t.section .idata$4\n");
1492 fprintf (f, "\t%s\t0\n", ASM_LONG);
1496 fprintf (f, "\t.section .idata$5\n");
1497 fprintf (f, "\t%s\t0\n", ASM_LONG);
1501 sprintf (outfile, "-o dt.o dt.s");
1502 run (as_name, outfile);
1503 return bfd_openr ("dt.o", HOW_BFD_TARGET);
1518 outarch = bfd_openw (imp_name, HOW_BFD_TARGET);
1522 fprintf (stderr, "%s: Can't open .lib file %s\n", program_name, imp_name);
1525 bfd_set_format (outarch, bfd_archive);
1526 outarch->has_armap = 1;
1528 /* Work out a reasonable size of things to put onto one line. */
1532 ar_head = make_head ();
1533 ar_tail = make_tail();
1535 for (i = 0; (exp = d_exports_lexically[i]); i++)
1537 bfd *n = make_one_lib_file (exp, i);
1543 /* Now stick them all into the archive */
1545 ar_head->next = head;
1546 ar_tail->next = ar_head;
1549 bfd_set_archive_head (outarch, head);
1550 bfd_close (outarch);
1552 /* Delete all the temp files */
1554 if (dontdeltemps == 0)
1556 sprintf (outfile, "dh.o");
1558 sprintf (outfile, "dh.s");
1560 sprintf (outfile, "dt.o");
1562 sprintf (outfile, "dt.s");
1566 if (dontdeltemps < 2)
1567 for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
1569 sprintf (outfile, "ds%d.o",i);
1574 /**********************************************************************/
1576 /* Run through the information gathered from the .o files and the
1577 .def file and work out the best stuff */
1583 export_type *ap = *(export_type **) a;
1584 export_type *bp = *(export_type **) b;
1585 if (ap->ordinal == bp->ordinal)
1588 /* unset ordinals go to the bottom */
1589 if (ap->ordinal == -1)
1591 if (bp->ordinal == -1)
1593 return (ap->ordinal - bp->ordinal);
1602 export_type *ap = *(export_type **) a;
1603 export_type *bp = *(export_type **) b;
1605 return (strcmp (ap->name, bp->name));
1610 remove_null_names (ptr)
1615 for (dst = src = 0; src < d_nfuncs; src++)
1619 ptr[dst] = ptr[src];
1632 for (i = 0; i < d_nfuncs; i++)
1636 printf ("%d %s @ %d %s%s\n",
1637 i, ptr[i]->name, ptr[i]->ordinal,
1638 ptr[i]->noname ? "NONAME " : "",
1639 ptr[i]->constant ? "CONSTANT" : "");
1648 process_duplicates (d_export_vec)
1649 export_type **d_export_vec;
1657 /* Remove duplicates */
1658 qsort (d_export_vec, d_nfuncs, sizeof (export_type *), nfunc);
1660 dtab (d_export_vec);
1661 for (i = 0; i < d_nfuncs - 1; i++)
1663 if (strcmp (d_export_vec[i]->name,
1664 d_export_vec[i + 1]->name) == 0)
1667 export_type *a = d_export_vec[i];
1668 export_type *b = d_export_vec[i + 1];
1672 fprintf (stderr, "Warning, ignoring duplicate EXPORT %s %d,%d\n",
1676 if (a->ordinal != -1
1677 && b->ordinal != -1)
1680 fprintf (stderr, "Error, duplicate EXPORT with oridinals %s\n",
1684 /* Merge attributes */
1685 b->ordinal = a->ordinal > 0 ? a->ordinal : b->ordinal;
1686 b->constant |= a->constant;
1687 b->noname |= a->noname;
1688 d_export_vec[i] = 0;
1691 dtab (d_export_vec);
1692 remove_null_names (d_export_vec);
1693 dtab (d_export_vec);
1698 /* Count the names */
1699 for (i = 0; i < d_nfuncs; i++)
1701 if (!d_export_vec[i]->noname)
1707 fill_ordinals (d_export_vec)
1708 export_type **d_export_vec;
1714 qsort (d_export_vec, d_nfuncs, sizeof (export_type *), pfunc);
1716 /* fill in the unset ordinals with ones from our range */
1718 ptr = (char *) malloc (65536);
1720 memset (ptr, 0, 65536);
1722 /* Mark in our large vector all the numbers that are taken */
1723 for (i = 0; i < d_nfuncs; i++)
1725 if (d_export_vec[i]->ordinal != -1)
1727 ptr[d_export_vec[i]->ordinal] = 1;
1729 lowest = d_export_vec[i]->ordinal;
1733 /* Start at 1 for compatibility with MS toolchain. */
1737 for (i = 0; i < d_nfuncs; i++)
1739 if (d_export_vec[i]->ordinal == -1)
1742 for (j = lowest; j < 65536; j++)
1746 d_export_vec[i]->ordinal = j;
1750 for (j = 1; j < lowest; j++)
1754 d_export_vec[i]->ordinal = j;
1766 qsort (d_export_vec, d_nfuncs, sizeof (export_type *), pfunc);
1769 /* Work out the lowest ordinal number */
1770 if (d_export_vec[0])
1771 d_low_ord = d_export_vec[0]->ordinal;
1774 if (d_export_vec[d_nfuncs-1])
1775 d_high_ord = d_export_vec[d_nfuncs-1]->ordinal;
1779 int alphafunc(av,bv)
1783 export_type **a = av;
1784 export_type **b = bv;
1786 return strcmp ((*a)->name, (*b)->name);
1792 /* First work out the minimum ordinal chosen */
1798 export_type **d_export_vec
1799 = (export_type **) xmalloc (sizeof (export_type *) * d_nfuncs);
1801 for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
1803 d_export_vec[i] = exp;
1806 process_duplicates (d_export_vec);
1807 fill_ordinals (d_export_vec);
1809 /* Put back the list in the new order */
1811 for (i = d_nfuncs - 1; i >= 0; i--)
1813 d_export_vec[i]->next = d_exports;
1814 d_exports = d_export_vec[i];
1817 /* Build list in alpha order */
1818 d_exports_lexically = (export_type **)xmalloc (sizeof(export_type *)*(d_nfuncs+1));
1820 for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
1822 d_exports_lexically[i] = exp;
1824 d_exports_lexically[i] = 0;
1826 qsort (d_exports_lexically, i, sizeof (export_type *), alphafunc);
1828 /* Fill exp entries with their hint values */
1830 for (i = 0; i < d_nfuncs; i++)
1832 if (!d_exports_lexically[i]->noname || show_allnames)
1833 d_exports_lexically[i]->hint = hint++;
1843 /**********************************************************************/
1846 usage (file, status)
1850 fprintf (file, "Usage %s <options> <object-files>\n", program_name);
1851 fprintf (file, " --machine <machine>\n");
1852 fprintf (file, " --output-exp <outname> Generate export file.\n");
1853 fprintf (file, " --output-lib <outname> Generate input library.\n");
1854 fprintf (file, " --add-indirect Add dll indirects to export file.\n");
1855 fprintf (file, " --dllname <name> Name of input dll to put into output lib.\n");
1856 fprintf (file, " --def <deffile> Name input .def file\n");
1857 fprintf (file, " --output-def <deffile> Name output .def file\n");
1858 fprintf (file, " --base-file <basefile> Read linker generated base file\n");
1859 fprintf (file, " --no-idata4 Don't generate idata$4 section\n");
1860 fprintf (file, " --no-idata5 Don't generate idata$5 section\n");
1861 fprintf (file, " -v Verbose\n");
1862 fprintf (file, " -U Add underscores to .lib\n");
1863 fprintf (file, " -k Kill @<n> from exported names\n");
1864 fprintf (file, " --as <name> Use <name> for assembler\n");
1865 fprintf (file, " --nodelete Keep temp files.\n");
1869 #define OPTION_NO_IDATA4 'x'
1870 #define OPTION_NO_IDATA5 'c'
1871 static struct option long_options[] =
1873 {"nodelete", no_argument, NULL, 'n'},
1874 {"dllname", required_argument, NULL, 'D'},
1875 {"no-idata4", no_argument, NULL, OPTION_NO_IDATA4},
1876 {"no-idata5", no_argument, NULL, OPTION_NO_IDATA5},
1877 {"output-exp", required_argument, NULL, 'e'},
1878 {"output-def", required_argument, NULL, 'z'},
1879 {"output-lib", required_argument, NULL, 'l'},
1880 {"def", required_argument, NULL, 'd'},
1881 {"add-underscore", no_argument, NULL, 'U'},
1882 {"killat", no_argument, NULL, 'k'},
1883 {"help", no_argument, NULL, 'h'},
1884 {"machine", required_argument, NULL, 'm'},
1885 {"add-indirect", no_argument, NULL, 'a'},
1886 {"base-file", required_argument, NULL, 'b'},
1887 {"as", required_argument, NULL, 'S'},
1901 program_name = av[0];
1904 while ((c = getopt_long (ac, av, "xcz:S:R:A:puaD:l:e:nkvbUh?m:yd:", long_options, 0))
1909 case OPTION_NO_IDATA4:
1912 case OPTION_NO_IDATA5:
1919 /* ignored for compatibility */
1926 output_def = fopen (optarg, FOPEN_WT);
1963 base_file = fopen (optarg, FOPEN_RB);
1966 fprintf (stderr, "%s: Unable to open base-file %s\n",
1978 for (i = 0; mtable[i].type; i++)
1980 if (strcmp (mtable[i].type, mname) == 0)
1984 if (!mtable[i].type)
1986 fprintf (stderr, "Machine not supported\n");
1992 if (!dll_name && exp_name)
1994 char len = strlen (exp_name) + 5;
1995 dll_name = xmalloc (len);
1996 strcpy (dll_name, exp_name);
1997 strcat (dll_name, ".dll");
2002 process_def_file (def_file);
2007 firstarg = av[optind];
2008 scan_obj_file (av[optind]);
2019 /* Make imp_name safe for use as a label. */
2021 imp_name_lab = strdup (imp_name);
2022 for (p = imp_name_lab; *p; *p++)
2024 if (!isalpha (*p) && !isdigit (*p))
2027 head_label = make_label("_head_", imp_name_lab);