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;
218 static char *mname = "arm";
222 static char *mname = "i386";
224 #define PATHMAX 250 /* What's the right name for this ? */
226 /* This bit of assemly does jmp * ....
227 s set how_jtab_roff to mark where the 32bit abs branch should go */
228 unsigned char i386_jtab[] = { 0xff, 0x25, 0x00, 0x00, 0x00, 0x00, 0x90, 0x90};
231 unsigned char arm_jtab[] = { 0x00, 0xc0, 0x9f, 0xe5,
232 0x00, 0xf0, 0x9c, 0xe5,
234 char outfile[PATHMAX];
246 char *how_align_short;
247 char *how_align_long;
248 char *how_bfd_target;
249 enum bfd_architecture how_bfd_arch;
250 unsigned char *how_jtab;
251 int how_jtab_size; /* size of the jtab entry */
252 int how_jtab_roff; /* offset into it for the ind 32 reloc into idata 5 */
259 "arm", ".byte", ".short", ".long", ".asciz", "@",
260 "ldr\tip,[pc]\n\tldr\tpc,[ip]\n\t.long",
261 ".global", ".space", ".align\t2",".align\t4","pe-arm-little", bfd_arch_arm,
262 arm_jtab, sizeof(arm_jtab),8
267 "i386", ".byte", ".short", ".long", ".asciz", "#", "jmp *", ".global", ".space", ".align\t2",".align\t4","pe-i386",bfd_arch_i386,
268 i386_jtab,sizeof(i386_jtab),2,
316 #define ASM_BYTE mtable[machine].how_byte
317 #define ASM_SHORT mtable[machine].how_short
318 #define ASM_LONG mtable[machine].how_long
319 #define ASM_TEXT mtable[machine].how_asciz
320 #define ASM_C mtable[machine].how_comment
321 #define ASM_JUMP mtable[machine].how_jump
322 #define ASM_GLOBAL mtable[machine].how_global
323 #define ASM_SPACE mtable[machine].how_space
324 #define ASM_ALIGN_SHORT mtable[machine].how_align_short
325 #define ASM_RVA_BEFORE rvabefore(machine)
326 #define ASM_RVA_AFTER rvaafter(machine)
327 #define ASM_PREFIX asm_prefix(machine)
328 #define ASM_ALIGN_LONG mtable[machine].how_align_long
329 #define HOW_BFD_TARGET 0 /* always default*/
330 #define HOW_BFD_ARCH mtable[machine].how_bfd_arch
331 #define HOW_JTAB mtable[machine].how_jtab
332 #define HOW_JTAB_SIZE mtable[machine].how_jtab_size
333 #define HOW_JTAB_ROFF mtable[machine].how_jtab_roff
337 FILE *yyin; /* communications with flex */
338 extern int linenumber;
340 process_def_file (name)
343 FILE *f = fopen (name, "r");
346 fprintf (stderr, "%s: Can't open def file %s\n", program_name, name);
355 /**********************************************************************/
357 /* Communications with the parser */
367 typedef struct export
379 static char *d_name; /* Arg to NAME or LIBRARY */
380 static int d_nfuncs; /* Number of functions exported */
381 static int d_named_nfuncs; /* Number of named functions exported */
382 static int d_low_ord; /* Lowest ordinal index */
383 static int d_high_ord; /* Highest ordinal index */
384 static export_type *d_exports; /*list of exported functions */
385 static export_type **d_exports_lexically; /* vector of exported functions in alpha order */
386 static dlist_type *d_list; /* Descriptions */
387 static dlist_type *a_list; /* Stuff to go in directives */
395 fprintf (stderr, "%s: Syntax error in def file %s:%d\n",
396 program_name, def_file, linenumber);
401 def_exports (name, internal_name, ordinal, noname, constant)
408 struct export *p = (struct export *) xmalloc (sizeof (*p));
411 p->internal_name = internal_name ? internal_name : name;
412 p->ordinal = ordinal;
413 p->constant = constant;
422 def_name (name, base)
427 fprintf (stderr, "%s NAME %s base %x\n", program_name, name, base);
430 fprintf (stderr, "Can't have LIBRARY and NAME\n");
437 def_library (name, base)
442 printf ("%s: LIBRARY %s base %x\n", program_name, name, base);
445 fprintf (stderr, "%s: Can't have LIBRARY and NAME\n", program_name);
452 def_description (desc)
455 dlist_type *d = (dlist_type *) xmalloc (sizeof (dlist_type));
456 d->text = strdup (desc);
465 dlist_type *d = (dlist_type *) xmalloc (sizeof (dlist_type));
466 d->text = strdup (dir);
472 def_stacksize (reserve, commit)
478 sprintf (b, "-stack 0x%x,0x%x ", reserve, commit);
480 sprintf (b, "-stack 0x%x ", reserve);
481 new_directive (strdup (b));
485 def_heapsize (reserve, commit)
491 sprintf (b, "-heap 0x%x,0x%x ", reserve, commit);
493 sprintf (b, "-heap 0x%x ", reserve);
494 new_directive (strdup (b));
499 def_import (internal, module, entry)
505 fprintf (stderr, "%s: IMPORTS are ignored", program_name);
509 def_version (major, minor)
513 printf ("VERSION %d.%d\n", major, minor);
518 def_section (name, attr)
535 sprintf (buf, "-attr %s %s", name, atts);
536 new_directive (strdup (buf));
543 def_section ("CODE", attr);
550 def_section ("DATA", attr);
554 /**********************************************************************/
565 extern char **environ;
567 fprintf (stderr, "%s %s\n", what, args);
571 for (s = args; *s; s++)
575 argv = alloca (sizeof (char *) * (i + 3));
582 while (*s != ' ' && *s != 0)
596 fprintf (stderr, "%s: can't exec %s\n", program_name, what);
602 fprintf (stderr, "%s: vfork failed, %d\n", program_name, errno);
608 waitpid (pid, &status, 0);
611 if (WIFSIGNALED (status))
613 fprintf (stderr, "%s: %s %s terminated with signal %d\n",
614 program_name, what, args, WTERMSIG (status));
618 if (WIFEXITED (status))
620 fprintf (stderr, "%s: %s %s terminated with exit status %d\n",
621 program_name, what, args, WEXITSTATUS (status));
628 /* read in and block out the base relocations */
640 scan_open_obj_file (abfd)
643 /* Look for .drectve's */
644 asection *s = bfd_get_section_by_name (abfd, ".drectve");
647 int size = bfd_get_section_size_before_reloc (s);
648 char *buf = xmalloc (size);
651 bfd_get_section_contents (abfd, s, buf, 0, size);
653 fprintf (stderr, "%s: Sucking in info from %s\n",
655 bfd_get_filename (abfd));
657 /* Search for -export: strings */
663 && strncmp (p, "-export:", 8) == 0)
669 while (*p != ' ' && *p != '-' && p < e)
671 c = xmalloc (p - name + 1);
672 memcpy (c, name, p - name);
674 def_exports (c, 0, -1, 0);
685 fprintf (stderr, "%s: Done readin\n",
692 scan_obj_file (filename)
695 bfd *f = bfd_openr (filename, 0);
699 fprintf (stderr, "%s: Unable to open object file %s\n",
704 if (bfd_check_format (f, bfd_archive))
706 bfd *arfile = bfd_openr_next_archived_file (f, 0);
709 if (bfd_check_format (arfile, bfd_object))
710 scan_open_obj_file (arfile);
712 arfile = bfd_openr_next_archived_file (f, arfile);
715 else if (bfd_check_format (f, bfd_object))
717 scan_open_obj_file (f);
723 /**********************************************************************/
733 fprintf (f, "%s ", ASM_C);
734 for (i = 0; oav[i]; i++)
735 fprintf (f, "%s ", oav[i]);
737 for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
739 fprintf (f, "%s %d = %s %s @ %d %s%s\n",
745 exp->noname ? "NONAME " : "",
746 exp->constant ? "CONSTANT" : "");
749 /* Generate the .exp file */
762 flush_page (f, need, page_addr, on_page)
770 /* Flush this page */
771 fprintf (f, "\t%s\t0x%08x\t%s Starting RVA for chunk\n",
775 fprintf (f, "\t%s\t0x%x\t%s Size of block\n",
777 (on_page * 2) + (on_page & 1) * 2 + 8,
779 for (i = 0; i < on_page; i++)
781 fprintf (f, "\t%s\t0x%x\n", ASM_SHORT, (need[i] - page_addr) | 0x3000);
785 fprintf (f, "\t%s\t0x%x\n", ASM_SHORT, 0 | 0x0000);
796 fprintf (output_def, ";");
797 for (i = 0; oav[i]; i++)
798 fprintf (output_def, " %s", oav[i]);
800 fprintf (output_def, "\nEXPORTS\n");
802 for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
804 char *quote = strchr (exp->name, '.') ? "\"" : "";
805 fprintf (output_def, "\t%s%s%s @ %d%s ; %s\n",
810 exp->noname ? " NONAME" : "",
811 cplus_demangle (exp->internal_name, DMGL_ANSI | DMGL_PARAMS));
823 sprintf (outfile, "t%s", exp_name);
826 fprintf (stderr, "%s: Generate exp file %s\n",
827 program_name, exp_name);
829 f = fopen (outfile, "w");
832 fprintf (stderr, "%s: Unable to open output file %s\n", program_name, outfile);
837 fprintf (stderr, "%s: Opened file %s\n",
838 program_name, outfile);
844 fprintf (f, "\t.section .edata\n\n");
845 fprintf (f, "\t%s 0 %s Allways 0\n", ASM_LONG, ASM_C);
846 fprintf (f, "\t%s 0x%x %s Time and date\n", ASM_LONG, time(0),ASM_C);
847 fprintf (f, "\t%s 0 %s Major and Minor version\n", ASM_LONG, ASM_C);
848 fprintf (f, "\t%sname%s %s Ptr to name of dll\n", ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C);
849 fprintf (f, "\t%s %d %s Starting ordinal of exports\n", ASM_LONG, d_low_ord, ASM_C);
852 fprintf (f, "\t%s %d %s Number of functions\n", ASM_LONG, d_high_ord - d_low_ord + 1, ASM_C);
853 fprintf(f,"\t%s named funcs %d, low ord %d, high ord %d\n",
855 d_named_nfuncs, d_low_ord, d_high_ord);
856 fprintf (f, "\t%s %d %s Number of names\n", ASM_LONG,
857 show_allnames ? d_high_ord - d_low_ord + 1 : d_named_nfuncs, ASM_C);
858 fprintf (f, "\t%safuncs%s %s Address of functions\n", ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C);
860 fprintf (f, "\t%sanames%s %s Address of Name Pointer Table\n",
861 ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C);
863 fprintf (f, "\t%sanords%s %s Address of ordinals\n", ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C);
865 fprintf (f, "name: %s \"%s\"\n", ASM_TEXT, dll_name);
868 fprintf(f,"%s Export address Table\n", ASM_C);
869 fprintf(f,"\t%s\n", ASM_ALIGN_LONG);
870 fprintf (f, "afuncs:\n");
873 for (exp = d_exports; exp; exp = exp->next)
875 if (exp->ordinal != i)
878 fprintf (f, "\t%s\t%d\t%s %d..%d missing\n",
880 (exp->ordinal - i) * 4,
882 i, exp->ordinal - 1);
885 while (i < exp->ordinal)
887 fprintf(f,"\t%s\t0\n", ASM_LONG);
891 fprintf (f, "\t%s%s%s%s\t%s %d\n", ASM_RVA_BEFORE,
893 exp->internal_name, ASM_RVA_AFTER, ASM_C, exp->ordinal);
897 fprintf (f,"%s Export Name Pointer Table\n", ASM_C);
898 fprintf (f, "anames:\n");
900 for (i = 0; (exp = d_exports_lexically[i]); i++)
902 if (!exp->noname || show_allnames)
903 fprintf (f, "\t%sn%d%s\n", ASM_RVA_BEFORE, exp->ordinal, ASM_RVA_AFTER);
906 fprintf (f,"%s Export Oridinal Table\n", ASM_C);
907 fprintf (f, "anords:\n");
908 for (i = 0; (exp = d_exports_lexically[i]); i++)
910 if (!exp->noname || show_allnames)
911 fprintf (f, "\t%s %d\n", ASM_SHORT, exp->ordinal - d_low_ord);
914 fprintf(f,"%s Export Name Table\n", ASM_C);
915 for (i = 0; (exp = d_exports_lexically[i]); i++)
916 if (!exp->noname || show_allnames)
917 fprintf (f, "n%d: %s \"%s\"\n", exp->ordinal, ASM_TEXT, exp->name);
921 fprintf (f, "\t.section .drectve\n");
922 for (dl = a_list; dl; dl = dl->next)
924 fprintf (f, "\t%s\t\"%s\"\n", ASM_TEXT, dl->text);
929 fprintf (f, "\t.section .rdata\n");
930 for (dl = d_list; dl; dl = dl->next)
934 /* We dont output as ascii 'cause there can
935 be quote characters in the string */
938 for (p = dl->text; *p; p++)
941 fprintf (f, "\t%s\t", ASM_BYTE);
944 fprintf (f, "%d", *p);
961 /* Add to the output file a way of getting to the exported names
962 without using the import library. */
965 fprintf (f, "\t.section\t.rdata\n");
966 for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
967 if (!exp->noname || show_allnames)
969 fprintf (f, "\t%s\t__imp_%s\n", ASM_GLOBAL, exp->name);
970 fprintf (f, "__imp_%s:\n", exp->name);
971 fprintf (f, "\t%s\t%s\n", ASM_LONG, exp->name);
975 /* Dump the reloc section if a base file is provided */
979 long need[PAGE_SIZE];
986 fprintf (f, "\t.section\t.init\n");
987 fprintf (f, "lab:\n");
989 fseek (base_file, 0, SEEK_END);
990 numbytes = ftell (base_file);
991 fseek (base_file, 0, SEEK_SET);
992 copy = malloc (numbytes);
993 fread (copy, 1, numbytes, base_file);
994 num_entries = numbytes / sizeof (long);
997 fprintf (f, "\t.section\t.reloc\n");
1004 qsort (copy, num_entries, sizeof (long), sfunc);
1005 /* Delete duplcates */
1006 for (src = 0; src < num_entries; src++)
1008 if (last != copy[src])
1009 last = copy[dst++] = copy[src];
1013 page_addr = addr & PAGE_MASK; /* work out the page addr */
1015 for (j = 0; j < num_entries; j++)
1018 if ((addr & PAGE_MASK) != page_addr)
1020 flush_page (f, need, page_addr, on_page);
1022 page_addr = addr & PAGE_MASK;
1024 need[on_page++] = addr;
1026 flush_page (f, need, page_addr, on_page);
1028 /* fprintf (f, "\t%s\t0,0\t%s End\n", ASM_LONG, ASM_C);*/
1034 /* assemble the file */
1035 sprintf (outfile, "-o %s t%s", exp_name, exp_name);
1036 run (as_name, outfile);
1037 if (dontdeltemps == 0)
1039 sprintf (outfile, "t%s", exp_name);
1049 char *copy = malloc (strlen (name) + 2);
1051 strcpy (copy + 1, name);
1058 p = strchr (name, '@');
1065 /**********************************************************************/
1067 static void dump_iat (f, exp)
1071 if (exp->noname && !show_allnames )
1073 fprintf (f, "\t%s\t0x%08x\n",
1075 exp->ordinal | 0x80000000); /* hint or orindal ?? */
1079 fprintf (f, "\t%sID%d%s\n", ASM_RVA_BEFORE,
1096 unsigned char *data;
1109 static sinfo secdata[NSECS] =
1111 { TEXT, ".text", SEC_CODE | SEC_HAS_CONTENTS},
1112 { DATA, ".data", SEC_DATA},
1114 { IDATA7, ".idata$7",SEC_HAS_CONTENTS},
1115 { IDATA5, ".idata$5", SEC_HAS_CONTENTS},
1116 { IDATA4, ".idata$4", SEC_HAS_CONTENTS},
1117 { IDATA6,".idata$6", SEC_HAS_CONTENTS}
1122 This is what we're trying to make
1125 .global _GetFileVersionInfoSizeW@8
1126 .global __imp_GetFileVersionInfoSizeW@8
1127 _GetFileVersionInfoSizeW@8:
1128 jmp * __imp_GetFileVersionInfoSizeW@8
1129 .section .idata$7 # To force loading of head
1130 .long __version_a_head
1131 # Import Address Table
1133 __imp_GetFileVersionInfoSizeW@8:
1136 # Import Lookup Table
1142 .asciz "GetFileVersionInfoSizeW"
1146 static char *make_label (prefix, name)
1150 int len = strlen (ASM_PREFIX) + strlen (prefix) + strlen (name);
1151 char *copy = xmalloc (len +1 );
1152 strcpy (copy, ASM_PREFIX);
1153 strcat (copy, prefix);
1154 strcat (copy, name);
1158 make_one_lib_file (exp, i)
1166 sprintf (outfile, "%ss%d.s", prefix, i);
1167 f = fopen (outfile, "w");
1168 fprintf (f, "\t.text\n");
1169 fprintf (f, "\t%s\t%s%s\n", ASM_GLOBAL, ASM_PREFIX, exp->name);
1170 fprintf (f, "\t%s\t__imp_%s\n", ASM_GLOBAL, exp->name);
1171 fprintf (f, "%s%s:\n\t%s\t__imp_%s\n", ASM_PREFIX,
1172 exp->name, ASM_JUMP, exp->name);
1174 fprintf (f, "\t.section\t.idata$7\t%s To force loading of head\n", ASM_C);
1175 fprintf (f, "\t%s\t%s\n", ASM_LONG, head_label);
1178 fprintf (f,"%s Import Address Table\n", ASM_C);
1180 fprintf (f, "\t.section .idata$5\n");
1181 fprintf (f, "__imp_%s:\n", exp->name);
1185 fprintf (f, "\n%s Import Lookup Table\n", ASM_C);
1186 fprintf (f, "\t.section .idata$4\n");
1190 if(!exp->noname || show_allnames)
1192 fprintf (f, "%s Hint/Name table\n", ASM_C);
1193 fprintf (f, "\t.section .idata$6\n");
1194 fprintf (f, "ID%d:\t%s\t%d\n", exp->ordinal, ASM_SHORT, exp->hint);
1195 fprintf (f, "\t%s\t\"%s\"\n", ASM_TEXT, xlate (exp->name));
1201 sprintf (outfile, "-o %ss%d.o %ss%d.s", prefix, i, prefix, i);
1203 run (as_name, outfile);
1214 asymbol **iname_lab_pp;
1215 asymbol *ptrs[NSECS+3+1]; /* one symbol for each section, 2 extra + a null */
1217 char *outname = xmalloc (10);
1219 sprintf (outname, "ds%d.o", i);
1220 abfd = bfd_openw (outname, HOW_BFD_TARGET);
1223 fprintf (stderr, "%s: bfd_open failed open output file %s\n", program_name, outname);
1227 bfd_set_format (abfd, bfd_object);
1228 bfd_set_arch_mach (abfd, HOW_BFD_ARCH, 0);
1231 for (i = 0; i < NSECS; i++)
1233 sinfo *si = secdata + i;
1236 si->sec = bfd_make_section_old_way (abfd, si->name);
1237 bfd_set_section_flags (abfd,
1240 si->sec->output_section = si->sec;
1241 si->sym = bfd_make_empty_symbol(abfd);
1242 si->sym->name = si->sec->name;
1243 si->sym->section = si->sec;
1244 si->sym->flags = BSF_LOCAL;
1246 ptrs[oidx] = si->sym;
1247 si->sympp = ptrs + oidx;
1252 exp_label = bfd_make_empty_symbol(abfd);
1253 exp_label->name = make_label ("",exp->name);
1254 exp_label->section = secdata[TEXT].sec;
1255 exp_label->flags = BSF_GLOBAL;
1256 exp_label->value = 0;
1258 ptrs[oidx++] = exp_label;
1260 iname = bfd_make_empty_symbol(abfd);
1262 iname->name = make_label ("__imp_", exp->name);
1264 iname->section = secdata[IDATA5].sec;
1265 iname->flags = BSF_GLOBAL;
1269 iname_lab = bfd_make_empty_symbol(abfd);
1271 iname_lab->name = head_label;
1272 iname_lab->section = (asection *)&bfd_und_section;
1273 iname_lab->flags = 0;
1274 iname_lab->value = 0;
1277 ptrs[oidx++] = iname;
1278 iname_lab_pp = ptrs + oidx;
1279 ptrs[oidx++] = iname_lab;
1282 for (i = 0; i < NSECS; i++)
1284 sinfo *si = secdata + i;
1285 asection *sec = si->sec;
1292 si->size = HOW_JTAB_SIZE;
1293 si->data = xmalloc (HOW_JTAB_SIZE);
1294 memcpy (si->data, HOW_JTAB, HOW_JTAB_SIZE);
1296 /* add the reloc into idata$5 */
1297 rel = xmalloc (sizeof (arelent));
1298 rpp = xmalloc (sizeof (arelent *) * 2);
1301 rel->address = HOW_JTAB_ROFF;
1303 rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_32);
1304 rel->sym_ptr_ptr = secdata[IDATA5].sympp;
1305 sec->orelocation = rpp;
1306 sec->reloc_count = 1;
1310 /* An idata$4 or idata$5 is one word long, and has an
1314 si->data = xmalloc (4);
1319 si->data[0] = exp->ordinal ;
1320 si->data[1] = exp->ordinal >> 8;
1321 si->data[2] = exp->ordinal >> 16;
1326 sec->reloc_count = 1;
1327 memset (si->data, 0, si->size);
1328 rel = xmalloc (sizeof (arelent));
1329 rpp = xmalloc (sizeof (arelent *) * 2);
1334 rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_RVA);
1335 rel->sym_ptr_ptr = secdata[IDATA6].sympp;
1336 sec->orelocation = rpp;
1344 int idx = exp->hint + 1;
1345 si->size = strlen (xlate (exp->name)) + 3;
1346 si->data = xmalloc (si->size);
1347 si->data[0] = idx & 0xff;
1348 si->data[1] = idx >> 8;
1349 strcpy (si->data + 2, xlate (exp->name));
1354 si->data =xmalloc(4);
1355 memset (si->data, 0, si->size);
1356 rel = xmalloc (sizeof (arelent));
1357 rpp = xmalloc (sizeof (arelent *) * 2);
1361 rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_32);
1362 rel->sym_ptr_ptr = iname_lab_pp;
1363 sec->orelocation = rpp;
1364 sec->reloc_count = 1;
1371 /* Size up all the sections */
1372 for (i = 0; i < NSECS; i++)
1374 sinfo *si = secdata + i;
1375 bfd_set_section_size (abfd, si->sec, si->size);
1376 bfd_set_section_vma (abfd, si->sec, vma);
1377 /* vma += si->size;*/
1380 /* Write them out */
1381 for (i = 0; i < NSECS; i++)
1383 sinfo *si = secdata + i;
1384 if (i == IDATA5 && no_idata5)
1387 if (i == IDATA4 && no_idata4)
1390 bfd_set_section_contents (abfd, si->sec,
1395 bfd_set_symtab (abfd, ptrs, oidx);
1397 abfd = bfd_openr (outname, HOW_BFD_TARGET);
1408 FILE * f = fopen ("dh.s", "w");
1410 fprintf (f, "%s IMAGE_IMPORT_DESCRIPTOR\n", ASM_C);
1411 fprintf (f, "\t.section .idata$2\n");
1413 fprintf(f,"\t%s\t%s\n", ASM_GLOBAL,head_label);
1415 fprintf (f, "%s:\n", head_label);
1417 fprintf (f, "\t%shname%s\t%sPtr to image import by name list\n",
1418 ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C);
1420 fprintf (f, "\t%sthis should be the timestamp, but NT sometimes\n", ASM_C);
1421 fprintf (f, "\t%sdoesn't load DLLs when this is set.\n", ASM_C);
1422 fprintf (f, "\t%s\t0\t%s loaded time\n", ASM_LONG, ASM_C);
1423 fprintf (f, "\t%s\t0\t%s Forwarder chain\n", ASM_LONG, ASM_C);
1424 fprintf (f, "\t%s__%s_iname%s\t%s imported dll's name\n",
1429 fprintf (f, "\t%sfthunk%s\t%s pointer to firstthunk\n",
1431 ASM_RVA_AFTER, ASM_C);
1433 fprintf (f, "%sStuff for compatibility\n", ASM_C);
1437 fprintf (f, "\t.section\t.idata$5\n");
1438 fprintf (f, "\t%s\t0\n", ASM_LONG);
1439 fprintf (f, "fthunk:\n");
1443 fprintf (f, "\t.section\t.idata$4\n");
1445 fprintf (f, "\t%s\t0\n", ASM_LONG);
1446 fprintf (f, "\t.section .idata$4\n");
1447 fprintf (f, "hname:\n");
1451 sprintf (outfile, "-o dh.o dh.s");
1452 run (as_name, outfile);
1454 return bfd_openr ("dh.o", HOW_BFD_TARGET);
1460 FILE * f = fopen ("dt.s", "w");
1461 fprintf (f, "\t.section .idata$7\n");
1462 fprintf (f, "\t%s\t__%s_iname\n", ASM_GLOBAL, imp_name_lab);
1463 fprintf (f, "__%s_iname:\t%s\t\"%s\"\n",
1464 imp_name_lab, ASM_TEXT, dll_name);
1468 fprintf (f, "\t.section .idata$4\n");
1469 fprintf (f, "\t%s\t0\n", ASM_LONG);
1473 fprintf (f, "\t.section .idata$5\n");
1474 fprintf (f, "\t%s\t0\n", ASM_LONG);
1478 sprintf (outfile, "-o dt.o dt.s");
1479 run (as_name, outfile);
1480 return bfd_openr ("dt.o", HOW_BFD_TARGET);
1495 outarch = bfd_openw (imp_name, HOW_BFD_TARGET);
1499 fprintf (stderr, "%s: Can't open .lib file %s\n", program_name, imp_name);
1502 bfd_set_format (outarch, bfd_archive);
1503 outarch->has_armap = 1;
1505 /* Work out a reasonable size of things to put onto one line. */
1509 ar_head = make_head ();
1510 ar_tail = make_tail();
1512 for (i = 0; (exp = d_exports_lexically[i]); i++)
1514 bfd *n = make_one_lib_file (exp, i);
1520 /* Now stick them all into the archive */
1522 ar_head->next = head;
1523 ar_tail->next = ar_head;
1526 bfd_set_archive_head (outarch, head);
1527 bfd_close (outarch);
1529 /* Delete all the temp files */
1531 if (dontdeltemps == 0)
1533 sprintf (outfile, "dh.o");
1535 sprintf (outfile, "dh.s");
1537 sprintf (outfile, "dt.o");
1539 sprintf (outfile, "dt.s");
1543 if (dontdeltemps < 2)
1544 for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
1546 sprintf (outfile, "ds%d.o",i);
1551 /**********************************************************************/
1553 /* Run through the information gathered from the .o files and the
1554 .def file and work out the best stuff */
1560 export_type *ap = *(export_type **) a;
1561 export_type *bp = *(export_type **) b;
1562 if (ap->ordinal == bp->ordinal)
1565 /* unset ordinals go to the bottom */
1566 if (ap->ordinal == -1)
1568 if (bp->ordinal == -1)
1570 return (ap->ordinal - bp->ordinal);
1579 export_type *ap = *(export_type **) a;
1580 export_type *bp = *(export_type **) b;
1582 return (strcmp (ap->name, bp->name));
1587 remove_null_names (ptr)
1592 for (dst = src = 0; src < d_nfuncs; src++)
1596 ptr[dst] = ptr[src];
1609 for (i = 0; i < d_nfuncs; i++)
1613 printf ("%d %s @ %d %s%s\n",
1614 i, ptr[i]->name, ptr[i]->ordinal,
1615 ptr[i]->noname ? "NONAME " : "",
1616 ptr[i]->constant ? "CONSTANT" : "");
1625 process_duplicates (d_export_vec)
1626 export_type **d_export_vec;
1634 /* Remove duplicates */
1635 qsort (d_export_vec, d_nfuncs, sizeof (export_type *), nfunc);
1637 dtab (d_export_vec);
1638 for (i = 0; i < d_nfuncs - 1; i++)
1640 if (strcmp (d_export_vec[i]->name,
1641 d_export_vec[i + 1]->name) == 0)
1644 export_type *a = d_export_vec[i];
1645 export_type *b = d_export_vec[i + 1];
1649 fprintf (stderr, "Warning, ignoring duplicate EXPORT %s %d,%d\n",
1653 if (a->ordinal != -1
1654 && b->ordinal != -1)
1657 fprintf (stderr, "Error, duplicate EXPORT with oridinals %s\n",
1661 /* Merge attributes */
1662 b->ordinal = a->ordinal > 0 ? a->ordinal : b->ordinal;
1663 b->constant |= a->constant;
1664 b->noname |= a->noname;
1665 d_export_vec[i] = 0;
1668 dtab (d_export_vec);
1669 remove_null_names (d_export_vec);
1670 dtab (d_export_vec);
1675 /* Count the names */
1676 for (i = 0; i < d_nfuncs; i++)
1678 if (!d_export_vec[i]->noname)
1684 fill_ordinals (d_export_vec)
1685 export_type **d_export_vec;
1691 qsort (d_export_vec, d_nfuncs, sizeof (export_type *), pfunc);
1693 /* fill in the unset ordinals with ones from our range */
1695 ptr = (char *) malloc (65536);
1697 memset (ptr, 65536, 0);
1699 /* Mark in our large vector all the numbers that are taken */
1700 for (i = 0; i < d_nfuncs; i++)
1702 if (d_export_vec[i]->ordinal != -1)
1704 ptr[d_export_vec[i]->ordinal] = 1;
1706 lowest = d_export_vec[i]->ordinal;
1710 for (i = 0; i < d_nfuncs; i++)
1712 if (d_export_vec[i]->ordinal == -1)
1715 for (j = lowest; j < 65536; j++)
1719 d_export_vec[i]->ordinal = j;
1723 for (j = 1; j < lowest; j++)
1727 d_export_vec[i]->ordinal = j;
1739 qsort (d_export_vec, d_nfuncs, sizeof (export_type *), pfunc);
1742 /* Work out the lowest ordinal number */
1743 if (d_export_vec[0])
1744 d_low_ord = d_export_vec[0]->ordinal;
1747 if (d_export_vec[d_nfuncs-1])
1748 d_high_ord = d_export_vec[d_nfuncs-1]->ordinal;
1752 int alphafunc(av,bv)
1756 export_type **a = av;
1757 export_type **b = bv;
1759 return strcmp ((*a)->name, (*b)->name);
1765 /* First work out the minimum ordinal chosen */
1771 export_type **d_export_vec
1772 = (export_type **) xmalloc (sizeof (export_type *) * d_nfuncs);
1774 for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
1776 d_export_vec[i] = exp;
1779 process_duplicates (d_export_vec);
1780 fill_ordinals (d_export_vec);
1782 /* Put back the list in the new order */
1784 for (i = d_nfuncs - 1; i >= 0; i--)
1786 d_export_vec[i]->next = d_exports;
1787 d_exports = d_export_vec[i];
1790 /* Build list in alpha order */
1791 d_exports_lexically = (export_type **)xmalloc (sizeof(export_type *)*(d_nfuncs+1));
1793 for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
1795 d_exports_lexically[i] = exp;
1797 d_exports_lexically[i] = 0;
1799 qsort (d_exports_lexically, i, sizeof (export_type *), alphafunc);
1801 /* Fill exp entries with their hint values */
1803 for (i = 0; i < d_nfuncs; i++)
1805 if (!d_exports_lexically[i]->noname || show_allnames)
1806 d_exports_lexically[i]->hint = hint++;
1816 /**********************************************************************/
1819 usage (file, status)
1823 fprintf (file, "Usage %s <options> <object-files>\n", program_name);
1824 fprintf (file, " --machine <machine>\n");
1825 fprintf (file, " --output-exp <outname> Generate export file.\n");
1826 fprintf (file, " --output-lib <outname> Generate input library.\n");
1827 fprintf (file, " --add-indirect Add dll indirects to export file.\n");
1828 fprintf (file, " --dllname <name> Name of input dll to put into output lib.\n");
1829 fprintf (file, " --def <deffile> Name input .def file\n");
1830 fprintf (file, " --output-def <deffile> Name output .def file\n");
1831 fprintf (file, " --base-file <basefile> Read linker generated base file\n");
1832 fprintf (file, " --no-idata4 Don't generate idata$4 section\n");
1833 fprintf (file, " --no-idata5 Don't generate idata$5 section\n");
1834 fprintf (file, " -v Verbose\n");
1835 fprintf (file, " -U Add underscores to .lib\n");
1836 fprintf (file, " -k Kill @<n> from exported names\n");
1837 fprintf (file, " --as <name> Use <name> for assembler\n");
1838 fprintf (file, " --nodelete Keep temp files.\n");
1842 #define OPTION_NO_IDATA4 'x'
1843 #define OPTION_NO_IDATA5 'c'
1844 static struct option long_options[] =
1846 {"nodelete", no_argument, NULL, 'n'},
1847 {"dllname", required_argument, NULL, 'D'},
1848 {"no-idata4", no_argument, NULL, OPTION_NO_IDATA4},
1849 {"no-idata5", no_argument, NULL, OPTION_NO_IDATA5},
1850 {"output-exp", required_argument, NULL, 'e'},
1851 {"output-def", required_argument, NULL, 'z'},
1852 {"output-lib", required_argument, NULL, 'l'},
1853 {"def", required_argument, NULL, 'd'},
1854 {"add-underscore", no_argument, NULL, 'U'},
1855 {"killat", no_argument, NULL, 'k'},
1856 {"help", no_argument, NULL, 'h'},
1857 {"machine", required_argument, NULL, 'm'},
1858 {"add-indirect", no_argument, NULL, 'a'},
1859 {"base-file", required_argument, NULL, 'b'},
1860 {"as", required_argument, NULL, 'S'},
1874 program_name = av[0];
1877 while ((c = getopt_long (ac, av, "xcz:S:R:A:puaD:l:e:nkvbUh?m:yd:", long_options, 0))
1882 case OPTION_NO_IDATA4:
1885 case OPTION_NO_IDATA5:
1892 /* ignored for compatibility */
1899 output_def = fopen (optarg, "w");
1936 base_file = fopen (optarg, "r");
1939 fprintf (stderr, "%s: Unable to open base-file %s\n",
1951 for (i = 0; mtable[i].type; i++)
1953 if (strcmp (mtable[i].type, mname) == 0)
1957 if (!mtable[i].type)
1959 fprintf (stderr, "Machine not supported\n");
1965 if (!dll_name && exp_name)
1967 char len = strlen (exp_name) + 5;
1968 dll_name = xmalloc (len);
1969 strcpy (dll_name, exp_name);
1970 strcat (dll_name, ".dll");
1975 process_def_file (def_file);
1980 firstarg = av[optind];
1981 scan_obj_file (av[optind]);
1992 /* Make imp_name safe for use as a label. */
1994 imp_name_lab = strdup (imp_name);
1995 for (p = imp_name_lab; *p; *p++)
1997 if (!isalpha (*p) && !isdigit (*p))
2000 head_label = make_label("_head_", imp_name_lab);