]>
git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - binutils/dlltool.c
1 /* dlltool.c -- tool to generate stuff for PE style DLLs
2 Copyright (C) 1995 Free Software Foundation, Inc.
4 This file is part of GNU Binutils.
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
22 This program allows you to build the files necessary to create
23 DLLs to run on a system which understands PE format image files.
26 A DLL contains an export table which contains the information
27 which the runtime loader needs to tie up references from a
30 The export table is generated by this program by reading
31 in a .DEF file or scanning the .a and .o files which will be in the
32 DLL. A .o file can contain information in special ".drectve" sections
33 with export information.
35 A DEF file contains any number of the following commands:
38 NAME <name> [ , <base> ]
39 The result is going to be <name>.EXE
41 LIBRARY <name> [ , <base> ]
42 The result is going to be <name>.DLL
44 EXPORTS ( <name1> [ = <name2> ] [ @ <integer> ] [ NONAME ] [CONSTANT] ) *
45 Declares name1 as an exported symbol from the
46 DLL, with optional ordinal number <integer>
48 IMPORTS ( [ <name> = ] <name> . <name> ) *
49 Ignored for compatibility
52 Puts <string> into output .exp file in the .rdata section
54 [STACKSIZE|HEAPSIZE] <number-reserve> [ , <number-commit> ]
55 Generates --stack|--heap <number-reserve>,<number-commit>
56 in the output .drectve section. The linker will
57 see this and act upon it.
60 SECTIONS ( <sectionname> <attr>+ )*
61 <attr> = READ | WRITE | EXECUTE | SHARED
62 Generates --attr <sectionname> <attr> in the output
63 .drectve section. The linker will see this and act
67 A -export:<name> in a .drectve section in an input .o or .a
68 file to this program is equivalent to a EXPORTS <name>
73 The program generates output files with the prefix supplied
74 on the command line, or in the def file, or taken from the first
77 The .exp.s file contains the information necessary to export
78 the routines in the DLL. The .lib.s file contains the information
79 necessary to use the DLL's routines from a referencing program.
86 asm (".section .drectve");
87 asm (".ascii \"-export:adef\"");
91 printf("hello from the dll %s\n",s);
96 printf("hello from the dll and the other entry point %s\n",s);
100 asm (".section .drectve");
101 asm (".ascii \"-export:cdef\"");
102 asm (".ascii \"-export:ddef\"");
105 printf("hello from the dll %s\n",s);
110 printf("hello from the dll and the other entry point %s\n",s);
128 HEAPSIZE 0x40000, 0x2000
132 SECTIONS donkey READ WRITE
136 # compile up the parts of the dll
141 # put them in a library (you don't have to, you
142 # could name all the .os on the dlltool line)
144 ar qcv thedll.in file1.o file2.o
147 # run this tool over the library and the def file
148 ./dlltool --def thedll.def --output-exp thedll.o --output-lib thedll.a
150 # build the dll with the library with file1.o, file2.o and the export table
151 ld -o thedll.dll thedll.o thedll.in
156 # link the executable with the import library
157 ld -e main -Tthemain.ld -o themain.exe themain.o thedll.a
161 #define PAGE_SIZE 4096
162 #define PAGE_MASK (-PAGE_SIZE)
164 #include "libiberty.h"
168 #include <sys/types.h>
170 #ifdef HAVE_SYS_WAIT_H
171 #include <sys/wait.h>
174 #define WIFEXITED(w) (((w)&0377) == 0)
177 #define WIFSIGNALED(w) (((w)&0377) != 0177 && ((w)&~0377) == 0)
180 #define WTERMSIG(w) ((w) & 0177)
183 #define WEXITSTATUS(w) (((w) >> 8) & 0377)
187 char *ar_name
= "ar";
188 char *as_name
= "as";
189 char *ranlib_name
= "ranlib";
195 int add_indirect
= 0;
197 int dontdeltemps
= 0;
212 static char *mname
= "arm";
216 static char *mname
= "i386";
218 #define PATHMAX 250 /* What's the right name for this ? */
220 char outfile
[PATHMAX
];
232 char *how_align_short
;
239 "arm", ".byte", ".short", ".long", ".asciz", "@", "ldr\tip,[pc]\n\tldr\tpc,[ip]\n\t.long", ".global", ".space", ".align\t2",
244 "i386", ".byte", ".short", ".long", ".asciz", "#", "jmp *", ".global", ".space", ".align\t2",
251 char *rvaafter (machine
)
263 char *rvabefore (machine
)
275 char *asm_prefix (machine
)
285 #define ASM_BYTE mtable[machine].how_byte
286 #define ASM_SHORT mtable[machine].how_short
287 #define ASM_LONG mtable[machine].how_long
288 #define ASM_TEXT mtable[machine].how_asciz
289 #define ASM_C mtable[machine].how_comment
290 #define ASM_JUMP mtable[machine].how_jump
291 #define ASM_GLOBAL mtable[machine].how_global
292 #define ASM_SPACE mtable[machine].how_space
293 #define ASM_ALIGN_SHORT mtable[machine].how_align_short
294 #define ASM_RVA_BEFORE rvabefore(machine)
295 #define ASM_RVA_AFTER rvaafter(machine)
296 #define ASM_PREFIX asm_prefix(machine)
301 FILE *yyin
; /* communications with flex */
302 extern int linenumber
;
304 process_def_file (name
)
307 FILE *f
= fopen (name
, "r");
310 fprintf (stderr
, "%s: Can't open def file %s\n", program_name
, name
);
319 /**********************************************************************/
321 /* Communications with the parser */
331 typedef struct export
342 static char *d_name
; /* Arg to NAME or LIBRARY */
343 static int d_nfuncs
; /* Number of functions exported */
344 static int d_ord
; /* Base ordinal index */
345 static export_type
*d_exports
; /*list of exported functions */
346 static dlist_type
*d_list
; /* Descriptions */
347 static dlist_type
*a_list
; /* Stuff to go in directives */
354 fprintf (stderr
, "%s: Syntax error in def file %s:%d\n",
355 program_name
, def_file
, linenumber
);
359 def_exports (name
, internal_name
, ordinal
, noname
, constant
)
366 struct export
*p
= (struct export
*) xmalloc (sizeof (*p
));
369 p
->internal_name
= internal_name
? internal_name
: name
;
370 p
->ordinal
= ordinal
;
371 p
->constant
= constant
;
380 def_name (name
, base
)
385 fprintf (stderr
, "%s NAME %s base %x\n", program_name
, name
, base
);
388 fprintf (stderr
, "Can't have LIBRARY and NAME\n");
395 def_library (name
, base
)
400 printf ("%s: LIBRARY %s base %x\n", program_name
, name
, base
);
403 fprintf (stderr
, "%s: Can't have LIBRARY and NAME\n", program_name
);
410 def_description (desc
)
413 dlist_type
*d
= (dlist_type
*) xmalloc (sizeof (dlist_type
));
414 d
->text
= strdup (desc
);
423 dlist_type
*d
= (dlist_type
*) xmalloc (sizeof (dlist_type
));
424 d
->text
= strdup (dir
);
430 def_stacksize (reserve
, commit
)
436 sprintf (b
, "-stack 0x%x,0x%x ", reserve
, commit
);
438 sprintf (b
, "-stack 0x%x ", reserve
);
439 new_directive (strdup (b
));
443 def_heapsize (reserve
, commit
)
449 sprintf (b
, "-heap 0x%x,0x%x ", reserve
, commit
);
451 sprintf (b
, "-heap 0x%x ", reserve
);
452 new_directive (strdup (b
));
457 def_import (internal
, module
, entry
)
463 fprintf (stderr
, "%s: IMPORTS are ignored", program_name
);
467 def_version (major
, minor
)
469 printf ("VERSION %d.%d\n", major
, minor
);
474 def_section (name
, attr
)
491 sprintf (buf
, "-attr %s %s", name
, atts
);
492 new_directive (strdup (buf
));
499 def_section ("CODE", attr
);
506 def_section ("DATA", attr
);
510 /**********************************************************************/
521 extern char **environ
;
523 fprintf (stderr
, "%s %s\n", what
, args
);
527 for (s
= args
; *s
; s
++)
531 argv
= alloca (sizeof (char *) * (i
+ 3));
537 while (*s
!= ' ' && *s
!= 0)
550 fprintf (stderr
, "%s: can't exec %s\n", program_name
, what
);
556 fprintf (stderr
, "%s: vfork failed, %d\n", program_name
, errno
);
562 waitpid (pid
, &status
, 0);
565 if (WIFSIGNALED (status
))
567 fprintf (stderr
, "%s: %s %s terminated with signal %d\n",
568 program_name
, what
, args
, WTERMSIG (status
));
572 if (WIFEXITED (status
))
574 fprintf (stderr
, "%s: %s %s terminated with exit status %d\n",
575 program_name
, what
, args
, WEXITSTATUS (status
));
582 /* read in and block out the base relocations */
594 scan_open_obj_file (abfd
)
597 /* Look for .drectve's */
598 asection
*s
= bfd_get_section_by_name (abfd
, ".drectve");
601 int size
= bfd_get_section_size_before_reloc (s
);
602 char *buf
= xmalloc (size
);
605 bfd_get_section_contents (abfd
, s
, buf
, 0, size
);
607 fprintf (stderr
, "%s: Sucking in info from %s\n",
609 bfd_get_filename (abfd
));
611 /* Search for -export: strings */
617 && strncmp (p
, "-export:", 8) == 0)
623 while (*p
!= ' ' && *p
!= '-' && p
< e
)
625 c
= xmalloc (p
- name
+ 1);
626 memcpy (c
, name
, p
- name
);
628 def_exports (c
, 0, -1, 0);
639 fprintf (stderr
, "%s: Done readin\n",
646 scan_obj_file (filename
)
649 bfd
*f
= bfd_openr (filename
, 0);
653 fprintf (stderr
, "%s: Unable to open object file %s\n",
658 if (bfd_check_format (f
, bfd_archive
))
660 bfd
*arfile
= bfd_openr_next_archived_file (f
, 0);
663 if (bfd_check_format (arfile
, bfd_object
))
664 scan_open_obj_file (arfile
);
666 arfile
= bfd_openr_next_archived_file (f
, arfile
);
670 if (bfd_check_format (f
, bfd_object
))
672 scan_open_obj_file (f
);
678 /**********************************************************************/
681 /* return the bit of the name before the last . */
688 char *res
= strdup (name
);
689 char *p
= strrchr (res
, '.');
701 fprintf (f
, "%s ", ASM_C
);
702 for (i
= 0; oav
[i
]; i
++)
703 fprintf (f
, "%s ", oav
[i
]);
705 for (i
= 0, exp
= d_exports
; exp
; i
++, exp
= exp
->next
)
707 fprintf (f
, "%s %d = %s %s @ %d %s%s\n",
713 exp
->noname
? "NONAME " : "",
714 exp
->constant
? "CONSTANT" : "");
717 /* Generate the .exp file */
730 flush_page (f
, need
, page_addr
, on_page
)
737 /* Flush this page */
738 fprintf (f
, "\t%s\t0x%08x\t%s Starting RVA for chunk\n",
742 fprintf (f
, "\t%s\t0x%x\t%s Size of block\n",
744 (on_page
* 2) + (on_page
& 1) * 2 + 8,
746 for (i
= 0; i
< on_page
; i
++)
748 fprintf (f
, "\t%s\t0x%x\n", ASM_SHORT
, need
[i
] - page_addr
| 0x3000);
752 fprintf (f
, "\t%s\t0x%x\n", ASM_SHORT
, 0 | 0x0000);
766 sprintf (outfile
, "t%s", exp_name
);
769 fprintf (stderr
, "%s: Generate exp file %s\n",
770 program_name
, exp_name
);
772 f
= fopen (outfile
, "w");
775 fprintf (stderr
, "%s: Unable to open output file %s\n", program_name
, outfile
);
780 fprintf (stderr
, "%s: Opened file %s\n",
781 program_name
, outfile
);
786 fprintf (f
, "\t.section .edata\n\n");
787 fprintf (f
, "\t%s 0 %s Allways 0\n", ASM_LONG
, ASM_C
);
788 fprintf (f
, "\t%s 0 %s Time and date\n", ASM_LONG
, ASM_C
);
789 fprintf (f
, "\t%s 0 %s Major and Minor version\n", ASM_LONG
, ASM_C
);
790 fprintf (f
, "\t%sname%s %s Ptr to name of dll\n", ASM_RVA_BEFORE
, ASM_RVA_AFTER
, ASM_C
);
791 fprintf (f
, "\t%s %d %s Starting ordinal of exports\n", ASM_LONG
, d_ord
, ASM_C
);
792 fprintf (f
, "\t%s The next field is documented as being the number of functions\n", ASM_C
);
793 fprintf (f
, "\t%s yet it doesn't look like that in real PE dlls\n", ASM_C
);
794 fprintf (f
, "\t%s But it shouldn't be a problem, causes there's\n", ASM_C
);
795 fprintf (f
, "\t%s always the number of names field\n", ASM_C
);
796 fprintf (f
, "\t%s %d %s Number of functions\n", ASM_LONG
, d_nfuncs
, ASM_C
);
797 fprintf (f
, "\t%s %d %s Number of names\n", ASM_LONG
, d_nfuncs
, ASM_C
);
798 fprintf (f
, "\t%safuncs%s %s Address of functions\n", ASM_RVA_BEFORE
, ASM_RVA_AFTER
, ASM_C
);
799 fprintf (f
, "\t%sanames%s %s Address of names\n", ASM_RVA_BEFORE
, ASM_RVA_AFTER
, ASM_C
);
800 fprintf (f
, "\t%sanords%s %s Address of ordinals\n", ASM_RVA_BEFORE
, ASM_RVA_AFTER
, ASM_C
);
802 fprintf (f
, "name: %s \"%s\"\n", ASM_TEXT
, dll_name
);
804 fprintf (f
, "afuncs:\n");
806 for (exp
= d_exports
; exp
; exp
= exp
->next
)
809 /* This seems necessary in the doc, but in real
810 life it's not used.. */
811 if (exp
->ordinal
!= i
)
813 fprintf (f
, "%s\t%s\t%d\t@ %d..%d missing\n", ASM_C
, ASM_SPACE
,
814 (exp
->ordinal
- i
) * 4,
815 i
, exp
->ordinal
- 1);
819 fprintf (f
, "\t%s%s%s%s\t%s %d\n",ASM_RVA_BEFORE
,
821 exp
->internal_name
, ASM_RVA_AFTER
, ASM_C
, exp
->ordinal
);
826 fprintf (f
, "anames:\n");
827 for (i
= 0, exp
= d_exports
; exp
; i
++, exp
= exp
->next
)
832 fprintf (f
, "\t%s nNoname\n", ASM_LONG
, ASM_C
);
836 fprintf (f
, "\t%sn%d%s\n", ASM_RVA_BEFORE
, i
, ASM_RVA_AFTER
);
840 fprintf (f
, "anords:\n");
841 for (exp
= d_exports
; exp
; exp
= exp
->next
)
842 fprintf (f
, "\t%s %d\n", ASM_SHORT
, exp
->ordinal
- d_ord
);
844 for (i
= 0, exp
= d_exports
; exp
; i
++, exp
= exp
->next
)
846 fprintf (f
, "@n%d: %s \"%s\"\n", i
, ASM_TEXT
, exp
->name
);
848 fprintf (f
, "n%d: %s \"%s\"\n", i
, ASM_TEXT
, exp
->name
);
851 fprintf (f
, "nNoname: %s \"__noname__\"\n", ASM_TEXT
);
855 fprintf (f
, "\t.section .drectve\n");
856 for (dl
= a_list
; dl
; dl
= dl
->next
)
858 fprintf (f
, "\t%s\t\"%s\"\n", ASM_TEXT
, dl
->text
);
863 fprintf (f
, "\t.section .rdata\n");
864 for (dl
= d_list
; dl
; dl
= dl
->next
)
868 /* We dont output as ascii 'cause there can
869 be quote characters in the string */
872 for (p
= dl
->text
; *p
; p
++)
875 fprintf (f
, "\t%s\t", ASM_BYTE
);
878 fprintf (f
, "%d", *p
);
895 /* Add to the output file a way of getting to the exported names
896 without using the import library. */
899 fprintf (f
,"\t.section\t.rdata\n");
900 for (i
= 0, exp
= d_exports
; exp
; i
++, exp
= exp
->next
)
902 fprintf (f
, "\t%s\t__imp_%s\n", ASM_GLOBAL
, exp
->name
);
903 fprintf (f
, "__imp_%s:\n", exp
->name
);
904 fprintf (f
,"\t%s\t%s\n", ASM_LONG
, exp
->name
);
908 /* Dump the reloc section if a base file is provided */
912 long need
[PAGE_SIZE
];
919 fprintf (f
,"\t.section\t.init\n");
920 fprintf (f
,"lab:\n");
922 fseek (base_file
, 0, SEEK_END
);
923 numbytes
= ftell (base_file
);
924 fseek (base_file
, 0, SEEK_SET
);
925 copy
= malloc (numbytes
);
926 fread (copy
, 1, numbytes
, base_file
);
927 num_entries
= numbytes
/ sizeof (long);
930 fprintf (f
, "\t.section\t.reloc\n");
931 qsort (copy
, num_entries
, sizeof (long), sfunc
);
934 page_addr
= addr
& PAGE_MASK
; /* work out the page addr */
936 for (j
= 0; j
< num_entries
; j
++)
939 if ((addr
& PAGE_MASK
) != page_addr
)
941 flush_page (f
, need
, page_addr
, on_page
);
943 page_addr
= addr
& PAGE_MASK
;
945 need
[on_page
++] = addr
;
947 flush_page (f
, need
, page_addr
, on_page
);
949 fprintf (f
, "\t%s\t0,0\t%s End\n", ASM_LONG
, ASM_C
);
955 /* assemble the file */
956 sprintf (outfile
,"-o %s t%s", exp_name
, exp_name
);
957 run (as_name
, outfile
);
960 sprintf (outfile
,"t%s", exp_name
);
977 p
= strchr (name
, '@');
984 /**********************************************************************/
992 char *output_filename
;
993 char prefix
[PATHMAX
];
995 sprintf (outfile
, "%s", imp_name
);
996 output_filename
= strdup (outfile
);
998 unlink (output_filename
);
1000 strcpy (prefix
, "d");
1001 sprintf (outfile
, "%sh.s", prefix
);
1003 f
= fopen (outfile
, "w");
1005 fprintf (f
, "%s IMAGE_IMPORT_DESCRIPTOR\n", ASM_C
);
1006 fprintf (f
, "\t.section .idata$2\n");
1008 fprintf (f
, "\t%s\t__%s_head\n", ASM_GLOBAL
, imp_name
);
1009 fprintf (f
, "__%s_head:\n", imp_name
);
1011 fprintf (f
, "\t%shname%s\t%sPtr to image import by name list\n",
1012 ASM_RVA_BEFORE
, ASM_RVA_AFTER
, ASM_C
);
1014 fprintf (f
, "\t%sthis should be the timestamp, but NT sometimes\n", ASM_C
);
1015 fprintf (f
, "\t%sdoesn't load DLLs when this is set.\n", ASM_C
);
1016 fprintf (f
, "\t%s\t0\t%s loaded time\n", ASM_LONG
, ASM_C
);
1017 fprintf (f
, "\t%s\t0\t%s Forwarder chain\n", ASM_LONG
, ASM_C
);
1018 fprintf (f
, "\t%s__%s_iname%s\t%s imported dll's name\n",
1023 fprintf (f
, "\t%sfthunk%s\t%s pointer to firstthunk\n",
1025 ASM_RVA_AFTER
, ASM_C
);
1027 fprintf (f
, "%sStuff for compatibility\n", ASM_C
);
1028 fprintf (f
, "\t.section\t.idata$5\n");
1029 fprintf (f
, "\t%s\t0\n", ASM_LONG
);
1030 fprintf (f
, "fthunk:\n");
1031 fprintf (f
, "\t.section\t.idata$4\n");
1032 fprintf (f
, "\t%s\t0\n", ASM_LONG
);
1033 fprintf (f
, "\t.section .idata$4\n");
1034 fprintf (f
, "hname:\n");
1038 sprintf (outfile
, "-o %sh.o %sh.s", prefix
, prefix
);
1039 run (as_name
, outfile
);
1041 for (i
= 0, exp
= d_exports
; exp
; i
++, exp
= exp
->next
)
1043 sprintf (outfile
, "%ss%d.s", prefix
, i
);
1044 f
= fopen (outfile
, "w");
1045 fprintf (f
, "\t.text\n");
1046 fprintf (f
, "\t%s\t%s%s\n", ASM_GLOBAL
, ASM_PREFIX
, exp
->name
);
1047 fprintf (f
, "\t%s\t__imp_%s\n", ASM_GLOBAL
, exp
->name
);
1048 fprintf (f
, "%s%s:\n\t%s\t__imp_%s\n", ASM_PREFIX
,
1049 exp
->name
, ASM_JUMP
, exp
->name
);
1051 fprintf (f
, "\t.section\t.idata$7\t%s To force loading of head\n", ASM_C
);
1052 fprintf (f
, "\t%s\t__%s_head\n", ASM_LONG
, imp_name
);
1053 fprintf (f
, "\t.section .idata$5\n");
1056 fprintf (f
, "__imp_%s:\n", exp
->name
);
1057 fprintf (f
, "\t%sID%d%s\n",
1062 fprintf (f
, "\n%s Hint name array\n", ASM_C
);
1063 fprintf (f
, "\t.section .idata$4\n");
1064 fprintf (f
, "\t%sID%d%s\n", ASM_RVA_BEFORE
,
1068 fprintf (f
, "%s Hint/name array storage and import dll name\n", ASM_C
);
1069 fprintf (f
, "\t.section .idata$6\n");
1071 fprintf (f
, "\t%s\n", ASM_ALIGN_SHORT
);
1072 fprintf (f
, "ID%d:\t%s\t%d\n", i
, ASM_SHORT
, exp
->ordinal
);
1073 fprintf (f
, "\t%s\t\"%s\"\n", ASM_TEXT
, xlate (exp
->name
));
1077 sprintf (outfile
, "-o %ss%d.o %ss%d.s", prefix
, i
, prefix
, i
);
1078 run (as_name
, outfile
);
1081 sprintf (outfile
, "%st.s", prefix
);
1082 f
= fopen (outfile
, "w");
1083 fprintf (f
, "\t.section .idata$7\n");
1084 fprintf (f
, "\t%s\t__%s_iname\n", ASM_GLOBAL
, imp_name
);
1085 fprintf (f
, "__%s_iname:\t%s\t\"%s\"\n",
1086 imp_name
, ASM_TEXT
, dll_name
);
1089 fprintf (f
, "\t.section .idata$4\n");
1090 fprintf (f
, "\t%s\t0\n", ASM_LONG
);
1092 fprintf (f
, "\t.section .idata$5\n");
1093 fprintf (f
, "\t%s\t0\n", ASM_LONG
);
1096 sprintf (outfile
, "-o %st.o %st.s", prefix
, prefix
);
1097 run (as_name
, outfile
);
1099 /* Now stick them all into the archive */
1102 sprintf (outfile
, "crs %s %sh.o %st.o", output_filename
, prefix
, prefix
);
1103 run (ar_name
, outfile
);
1105 /* Do the rest in groups of however many fit into a command line */
1107 for (i
= 0, exp
= d_exports
; exp
; i
++, exp
= exp
->next
)
1111 sprintf (outfile
, "crs %s", output_filename
);
1112 sol
= strlen (outfile
);
1115 sprintf (outfile
+ sol
, " %ss%d.o", prefix
, i
);
1116 sol
= strlen (outfile
);
1120 run (ar_name
, outfile
);
1126 run (ar_name
, outfile
);
1128 /* Delete all the temp files */
1130 if (dontdeltemps
== 0)
1132 sprintf (outfile
, "%sh.o", prefix
);
1134 sprintf (outfile
, "%sh.s", prefix
);
1136 sprintf (outfile
, "%st.o", prefix
);
1138 sprintf (outfile
, "%st.s", prefix
);
1142 if (dontdeltemps
< 2)
1143 for (i
= 0, exp
= d_exports
; exp
; i
++, exp
= exp
->next
)
1145 sprintf (outfile
, "%ss%d.o", prefix
, i
);
1147 sprintf (outfile
, "%ss%d.s", prefix
, i
);
1152 /**********************************************************************/
1154 /* Run through the information gathered from the .o files and the
1155 .def file and work out the best stuff */
1161 export_type
*ap
= *(export_type
**) a
;
1162 export_type
*bp
= *(export_type
**) b
;
1163 if (ap
->ordinal
== bp
->ordinal
)
1166 /* unset ordinals go to the bottom */
1167 if (ap
->ordinal
== -1)
1169 if (bp
->ordinal
== -1)
1171 return (ap
->ordinal
- bp
->ordinal
);
1180 export_type
*ap
= *(export_type
**) a
;
1181 export_type
*bp
= *(export_type
**) b
;
1183 return (strcmp (ap
->name
, bp
->name
));
1188 remove_null_names (ptr
)
1193 for (dst
= src
= 0; src
< d_nfuncs
; src
++)
1197 ptr
[dst
] = ptr
[src
];
1210 for (i
= 0; i
< d_nfuncs
; i
++)
1214 printf ("%d %s @ %d %s%s\n",
1215 i
, ptr
[i
]->name
, ptr
[i
]->ordinal
,
1216 ptr
[i
]->noname
? "NONAME " : "",
1217 ptr
[i
]->constant
? "CONSTANT" : "");
1226 process_duplicates (d_export_vec
)
1227 export_type
**d_export_vec
;
1234 /* Remove duplicates */
1235 qsort (d_export_vec
, d_nfuncs
, sizeof (export_type
*), nfunc
);
1237 dtab (d_export_vec
);
1238 for (i
= 0; i
< d_nfuncs
- 1; i
++)
1240 if (strcmp (d_export_vec
[i
]->name
,
1241 d_export_vec
[i
+ 1]->name
) == 0)
1244 export_type
*a
= d_export_vec
[i
];
1245 export_type
*b
= d_export_vec
[i
+ 1];
1249 fprintf (stderr
, "Warning, ignoring duplicate EXPORT %s %d,%d\n",
1253 if (a
->ordinal
!= -1
1254 && b
->ordinal
!= -1)
1257 fprintf (stderr
, "Error, duplicate EXPORT with oridinals %s\n",
1261 /* Merge attributes */
1262 b
->ordinal
= a
->ordinal
> 0 ? a
->ordinal
: b
->ordinal
;
1263 b
->constant
|= a
->constant
;
1264 b
->noname
|= a
->noname
;
1265 d_export_vec
[i
] = 0;
1268 dtab (d_export_vec
);
1269 remove_null_names (d_export_vec
);
1270 dtab (d_export_vec
);
1276 fill_ordinals (d_export_vec
)
1277 export_type
**d_export_vec
;
1282 qsort (d_export_vec
, d_nfuncs
, sizeof (export_type
*), pfunc
);
1284 /* fill in the unset ordinals with ones from our range */
1286 ptr
= (char *) malloc (65536);
1288 memset (ptr
, 65536, 0);
1290 /* Mark in our large vector all the numbers that are taken */
1291 for (i
= 0; i
< d_nfuncs
; i
++)
1293 if (d_export_vec
[i
]->ordinal
!= -1)
1295 ptr
[d_export_vec
[i
]->ordinal
] = 1;
1297 lowest
= d_export_vec
[i
]->ordinal
;
1301 for (i
= 0; i
< d_nfuncs
; i
++)
1303 if (d_export_vec
[i
]->ordinal
== -1)
1306 for (j
= lowest
; j
< 65536; j
++)
1310 d_export_vec
[i
]->ordinal
= j
;
1314 for (j
= 1; j
< lowest
; j
++)
1318 d_export_vec
[i
]->ordinal
= j
;
1330 qsort (d_export_vec
, d_nfuncs
, sizeof (export_type
*), pfunc
);
1332 /* Work out the lowest ordinal number */
1333 if (d_export_vec
[0])
1334 d_ord
= d_export_vec
[0]->ordinal
;
1339 /* First work out the minimum ordinal chosen */
1344 export_type
**d_export_vec
1345 = (export_type
**) xmalloc (sizeof (export_type
*) * d_nfuncs
);
1347 for (i
= 0, exp
= d_exports
; exp
; i
++, exp
= exp
->next
)
1349 d_export_vec
[i
] = exp
;
1352 process_duplicates (d_export_vec
);
1353 fill_ordinals (d_export_vec
);
1355 /* Put back the list in the new order */
1357 for (i
= d_nfuncs
- 1; i
>= 0; i
--)
1359 d_export_vec
[i
]->next
= d_exports
;
1360 d_exports
= d_export_vec
[i
];
1366 /* Work out exec prefix from the name of this file */
1373 /* See if we're running in a devo tree */
1374 for (p
= program_name
; *p
; p
++)
1376 if (*p
== '/' || *p
== '\\')
1383 if (ps
&& strncmp (ps
, "/binutils", 9) == 0)
1385 /* running in the binutils directory, the other
1386 executables will be surrounding it in the usual places. */
1387 int len
= ps
- program_name
;
1388 ar_name
= xmalloc (len
+ strlen ("/binutils/ar") + 1);
1389 ranlib_name
= xmalloc (len
+ strlen ("/binutils/ranlib") + 1);
1390 as_name
= xmalloc (len
+ strlen ("/gas/as.new") + 1);
1392 memcpy (ar_name
, program_name
, len
);
1393 strcpy (ar_name
+ len
, "/binutils/ar");
1394 memcpy (ranlib_name
, program_name
, len
);
1395 strcpy (ranlib_name
+ len
, "/binutils/ranlib");
1396 memcpy (as_name
, program_name
, len
);
1397 strcpy (as_name
+ len
, "/gas/as.new");
1401 /* Otherwise chop off any prefix and use it for the rest of the progs,
1402 so i386-win32-dll generates i386-win32-ranlib etc etc */
1404 for (p
= program_name
; *p
; p
++)
1406 if (strncmp (p
, "dlltool", 7) == 0)
1408 int len
= p
- program_name
;
1409 ar_name
= xmalloc (len
+ strlen ("ar") +1);
1410 ranlib_name
= xmalloc (len
+ strlen ("ranlib")+1);
1411 as_name
= xmalloc (len
+ strlen ("as")+1);
1413 memcpy (ar_name
, program_name
, len
);
1414 strcpy (ar_name
+ len
, "ar");
1415 memcpy (ranlib_name
, program_name
, len
);
1416 strcpy (ranlib_name
+ len
, "ranlib");
1417 memcpy (as_name
, program_name
, len
);
1418 strcpy (as_name
+ len
, "as");
1425 /**********************************************************************/
1428 usage (file
, status
)
1432 fprintf (file
, "Usage %s <options> <object-files>\n", program_name
);
1433 fprintf (file
, " --machine <machine>\n");
1434 fprintf (file
, " --output-exp <outname> Generate export file.\n");
1435 fprintf (file
, " --output-lib <outname> Generate input library.\n");
1436 fprintf (file
, " --add-indirect Add dll indirects to export file.\n");
1437 fprintf (file
, " --dllname <name> Name of input dll to put into output lib.\n");
1438 fprintf (file
, " --def <deffile> Name input .def file\n");
1439 fprintf (file
, " --base-file <basefile> Read linker generated base file\n");
1440 fprintf (file
, " -v Verbose\n");
1441 fprintf (file
, " -u Remove leading underscore from .lib\n");
1442 fprintf (file
, " -k Kill @<n> from exported names\n");
1443 fprintf (file
, " --nodelete Keep temp files.\n");
1447 static struct option long_options
[] =
1449 {"nodelete", no_argument
, NULL
,'n'},
1450 {"dllname", required_argument
, NULL
,'D'},
1451 {"output-exp", required_argument
, NULL
, 'e'},
1452 {"output-lib", required_argument
, NULL
, 'l'},
1453 {"def", required_argument
, NULL
, 'd'},
1454 {"underscore", no_argument
, NULL
, 'u'},
1455 {"killat", no_argument
, NULL
, 'k'},
1456 {"help", no_argument
, NULL
, 'h'},
1457 {"machine", required_argument
, NULL
, 'm'},
1458 {"add-indirect", no_argument
, NULL
, 'a'},
1459 {"base-file", required_argument
, NULL
, 'b'},
1472 program_name
= av
[0];
1475 while ((c
= getopt_long (ac
, av
, "aD:l:e:nkvbuh?m:yd:", long_options
, 0)) != EOF
)
1517 base_file
= fopen (optarg
, "r");
1520 fprintf (stderr
, "%s: Unable to open base-file %s\n",
1532 for (i
= 0; mtable
[i
].type
; i
++)
1534 if (strcmp (mtable
[i
].type
, mname
) == 0)
1538 if (!mtable
[i
].type
)
1540 fprintf (stderr
, "Machine not supported\n");
1546 if (!dll_name
&& exp_name
)
1548 char len
= strlen (exp_name
) + 5;
1549 dll_name
= xmalloc (len
);
1550 strcpy (dll_name
, exp_name
);
1551 strcat (dll_name
, ".dll");
1558 process_def_file (def_file
);
1563 firstarg
= av
[optind
];
1564 scan_obj_file (av
[optind
]);