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 ".drective" 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 .drective 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 .drective section. The linker will see this and act
67 A -export:<name> in a .drective 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)
170 char *ar_name
= "ar";
171 char *as_name
= "as";
172 char *ranlib_name
= "ranlib";
196 static char *mname
= "arm";
200 static char *mname
= "i386";
202 #define PATHMAX 250 /* What's the right name for this ? */
204 char outfile
[PATHMAX
];
216 char *how_align_short
;
222 "arm", ".byte", ".short", ".long", ".asciz", "@", "ldr\tip,[pc]\n\tldr\tpc,[ip]\n\t.long", ".global", ".space", ".align\t2",
226 "i386", ".byte", ".short", ".long", ".asciz", "#", "jmp *", ".global", ".space", ".align\t2",
234 char *rvaafter (machine
)
238 sprintf(b
,")-0x%x", rva
);
242 char *rvabefore (machine
)
247 #define ASM_BYTE mtable[machine].how_byte
248 #define ASM_SHORT mtable[machine].how_short
249 #define ASM_LONG mtable[machine].how_long
250 #define ASM_TEXT mtable[machine].how_asciz
251 #define ASM_C mtable[machine].how_comment
252 #define ASM_JUMP mtable[machine].how_jump
253 #define ASM_GLOBAL mtable[machine].how_global
254 #define ASM_SPACE mtable[machine].how_space
255 #define ASM_ALIGN_SHORT mtable[machine].how_align_short
256 #define ASM_RVA_BEFORE rvabefore(machine)
257 #define ASM_RVA_AFTER rvaafter(machine)
263 FILE *yyin
; /* communications with flex */
264 extern int linenumber
;
266 process_def_file (name
)
269 FILE *f
= fopen (name
, "r");
272 fprintf (stderr
, "%s: Can't open def file %s\n", program_name
, name
);
281 /**********************************************************************/
283 /* Communications with the parser */
293 typedef struct export
304 static char *d_name
; /* Arg to NAME or LIBRARY */
305 static int d_nfuncs
; /* Number of functions exported */
306 static int d_ord
; /* Base ordinal index */
307 static export_type
*d_exports
; /*list of exported functions */
308 static dlist_type
*d_list
; /* Descriptions */
309 static dlist_type
*a_list
; /* Stuff to go in directives */
316 fprintf (stderr
, "%s: Syntax error in def file %s:%d\n",
317 program_name
, def_file
, linenumber
);
321 def_exports (name
, internal_name
, ordinal
, noname
, constant
)
328 struct export
*p
= (struct export
*) xmalloc (sizeof (*p
));
331 p
->internal_name
= internal_name
? internal_name
: name
;
332 p
->ordinal
= ordinal
;
333 p
->constant
= constant
;
342 def_name (name
, base
)
347 fprintf (stderr
, "%s NAME %s base %x\n", program_name
, name
, base
);
350 fprintf (stderr
, "Can't have LIBRARY and NAME\n");
357 def_library (name
, base
)
362 printf ("%s: LIBRARY %s base %x\n", program_name
, name
, base
);
365 fprintf (stderr
, "%s: Can't have LIBRARY and NAME\n", program_name
);
372 def_description (desc
)
375 dlist_type
*d
= (dlist_type
*) xmalloc (sizeof (dlist_type
));
376 d
->text
= strdup (desc
);
385 dlist_type
*d
= (dlist_type
*) xmalloc (sizeof (dlist_type
));
386 d
->text
= strdup (dir
);
392 def_stacksize (reserve
, commit
)
398 sprintf (b
, "-stack 0x%x,0x%x ", reserve
, commit
);
400 sprintf (b
, "-stack 0x%x ", reserve
);
401 new_directive (strdup (b
));
405 def_heapsize (reserve
, commit
)
411 sprintf (b
, "-heap 0x%x,0x%x ", reserve
, commit
);
413 sprintf (b
, "-heap 0x%x ", reserve
);
414 new_directive (strdup (b
));
419 def_import (internal
, module
, entry
)
425 fprintf (stderr
, "%s: IMPORTS are ignored", program_name
);
429 def_version (major
, minor
)
431 printf ("VERSION %d.%d\n", major
, minor
);
436 def_section (name
, attr
)
453 sprintf (buf
, "-attr %s %s", name
, atts
);
454 new_directive (strdup (buf
));
461 def_section ("CODE", attr
);
468 def_section ("DATA", attr
);
472 /**********************************************************************/
483 extern char **environ
;
485 fprintf (stderr
, "%s %s\n", what
, args
);
489 for (s
= args
; *s
; s
++)
493 argv
= alloca (sizeof (char *) * (i
+ 3));
499 while (*s
!= ' ' && *s
!= 0)
512 fprintf (stderr
, "%s: can't exec %s\n", program_name
, what
);
518 fprintf (stderr
, "%s: vfork failed, %d\n", program_name
, errno
);
524 waitpid (pid
, &status
);
527 if (WIFSIGNALED (status
))
529 fprintf (stderr
, "%s: %s %s terminated with signal %d\n",
530 program_name
, what
, args
, WTERMSIG (status
));
534 if (WIFEXITED (status
))
536 fprintf (stderr
, "%s: %s %s terminated with exit status %d\n",
537 program_name
, what
, args
, WEXITSTATUS (status
));
544 /* read in and block out the base relocations */
556 scan_open_obj_file (abfd
)
559 /* Look for .drectives */
560 asection
*s
= bfd_get_section_by_name (abfd
, ".drectve");
563 int size
= bfd_get_section_size_before_reloc (s
);
564 char *buf
= xmalloc (size
);
567 bfd_get_section_contents (abfd
, s
, buf
, 0, size
);
569 fprintf (stderr
, "%s: Sucking in info from %s\n",
571 bfd_get_filename (abfd
));
573 /* Search for -export: strings */
579 && strncmp (p
, "-export:", 8) == 0)
585 while (*p
!= ' ' && *p
!= '-' && p
< e
)
587 c
= xmalloc (p
- name
+ 1);
588 memcpy (c
, name
, p
- name
);
590 def_exports (c
, 0, -1, 0);
601 fprintf (stderr
, "%s: Done readin\n",
608 scan_obj_file (filename
)
611 bfd
*f
= bfd_openr (filename
, 0);
615 fprintf (stderr
, "%s: Unable to open object file %s\n",
620 if (bfd_check_format (f
, bfd_archive
))
622 bfd
*arfile
= bfd_openr_next_archived_file (f
, 0);
625 if (bfd_check_format (arfile
, bfd_object
))
626 scan_open_obj_file (arfile
);
628 arfile
= bfd_openr_next_archived_file (f
, arfile
);
632 if (bfd_check_format (f
, bfd_object
))
634 scan_open_obj_file (f
);
640 /**********************************************************************/
643 /* return the bit of the name before the last . */
650 char *res
= strdup (name
);
651 char *p
= strrchr (res
, '.');
663 fprintf (f
, "%s ", ASM_C
);
664 for (i
= 0; oav
[i
]; i
++)
665 fprintf (f
, "%s ", oav
[i
]);
667 for (i
= 0, exp
= d_exports
; exp
; i
++, exp
= exp
->next
)
669 fprintf (f
, "%s %d = %s %s @ %d %s%s\n",
675 exp
->noname
? "NONAME " : "",
676 exp
->constant
? "CONSTANT" : "");
679 /* Generate the .exp file */
692 flush_page (f
, need
, page_addr
, on_page
)
699 /* Flush this page */
700 fprintf (f
, "\t%s\t%s0x%08x%s\t%s Starting RVA for chunk\n",
706 fprintf (f
, "\t%s\t0x%x\t%s Size of block\n",
708 (on_page
* 2) + (on_page
& 1) * 2 + 8,
710 for (i
= 0; i
< on_page
; i
++)
712 fprintf (f
, "\t%s\t0x%x\n", ASM_SHORT
, need
[i
] - page_addr
| 0x3000);
716 fprintf (f
, "\t%s\t0x%x\n", ASM_SHORT
, 0 | 0x0000);
730 sprintf (outfile
, "t%s", exp_name
);
733 fprintf (stderr
, "%s: Generate exp file %s\n",
734 program_name
, exp_name
);
736 f
= fopen (outfile
, "w");
739 fprintf (stderr
, "%s: Unable to open output file %s\n", program_name
, outfile
);
744 fprintf (stderr
, "%s: Opened file %s\n",
745 program_name
, outfile
);
749 fprintf (f
, "\t.section .edata\n\n");
750 fprintf (f
, "\t%s 0 %s Allways 0\n", ASM_LONG
, ASM_C
);
751 fprintf (f
, "\t%s %d %s Time and date\n", ASM_LONG
, time (0), ASM_C
);
752 fprintf (f
, "\t%s 0 %s Major and Minor version\n", ASM_LONG
, ASM_C
);
753 fprintf (f
, "\t%s %sname%s%s Ptr to name of dll\n", ASM_LONG
, ASM_RVA_BEFORE
,
754 ASM_RVA_AFTER
, ASM_C
);
755 fprintf (f
, "\t%s %d %s Starting ordinal of exports\n", ASM_LONG
, d_ord
, ASM_C
);
756 fprintf (f
, "\t%s The next field is documented as being the number of functions\n", ASM_C
);
757 fprintf (f
, "\t%s yet it doesn't look like that in real PE dlls\n", ASM_C
);
758 fprintf (f
, "\t%s But it shouldn't be a problem, causes there's\n", ASM_C
);
759 fprintf (f
, "\t%s always the number of names field\n", ASM_C
);
760 fprintf (f
, "\t%s %d %s Number of functions\n", ASM_LONG
, d_nfuncs
, ASM_C
);
761 fprintf (f
, "\t%s %d %s Number of names\n", ASM_LONG
, d_nfuncs
, ASM_C
);
762 fprintf (f
, "\t%s %safuncs%s %s Address of functions\n", ASM_LONG
,
763 ASM_RVA_BEFORE
, ASM_RVA_AFTER
, ASM_C
);
764 fprintf (f
, "\t%s %sanames%s %s Address of names\n", ASM_LONG
,
765 ASM_RVA_BEFORE
, ASM_RVA_AFTER
, ASM_C
);
766 fprintf (f
, "\t%s %sanords%s %s Address of ordinals\n", ASM_LONG
,
767 ASM_RVA_BEFORE
, ASM_RVA_AFTER
, ASM_C
);
769 fprintf (f
, "name: %s \"%s\"\n", ASM_TEXT
, dll_name
);
771 fprintf (f
, "afuncs:\n");
773 for (exp
= d_exports
; exp
; exp
= exp
->next
)
776 /* This seems necessary in the doc, but in real
777 life it's not used.. */
778 if (exp
->ordinal
!= i
)
780 fprintf (f
, "%s\t%s\t%d\t@ %d..%d missing\n", ASM_C
, ASM_SPACE
,
781 (exp
->ordinal
- i
) * 4,
782 i
, exp
->ordinal
- 1);
786 fprintf (f
, "\t%s\t%s%s%s%s %d\n", ASM_LONG
, ASM_RVA_BEFORE
,
787 exp
->internal_name
, ASM_RVA_AFTER
, ASM_C
, exp
->ordinal
);
792 fprintf (f
, "anames:\n");
793 for (i
= 0, exp
= d_exports
; exp
; i
++, exp
= exp
->next
)
798 fprintf (f
, "\t%s nNoname\n", ASM_LONG
, ASM_C
);
802 fprintf (f
, "\t%s %sn%d%s\n", ASM_LONG
, ASM_RVA_BEFORE
, i
, ASM_RVA_AFTER
);
806 fprintf (f
, "anords:\n");
807 for (exp
= d_exports
; exp
; exp
= exp
->next
)
808 fprintf (f
, "\t%s %d\n", ASM_SHORT
, exp
->ordinal
- d_ord
);
810 for (i
= 0, exp
= d_exports
; exp
; i
++, exp
= exp
->next
)
812 fprintf (f
, "@n%d: %s \"%s\"\n", i
, ASM_TEXT
, exp
->name
);
814 fprintf (f
, "n%d: %s \"%s\"\n", i
, ASM_TEXT
, exp
->name
);
817 fprintf (f
, "nNoname: %s \"__noname__\"\n", ASM_TEXT
);
821 fprintf (f
, "\t.section .drectve\n");
822 for (dl
= a_list
; dl
; dl
= dl
->next
)
824 fprintf (f
, "\t%s\t\"%s\"\n", ASM_TEXT
, dl
->text
);
829 fprintf (f
, "\t.section .rdata\n");
830 for (dl
= d_list
; dl
; dl
= dl
->next
)
834 /* We dont output as ascii 'cause there can
835 be quote characters in the string */
838 for (p
= dl
->text
; *p
; p
++)
841 fprintf (f
, "\t%s\t", ASM_BYTE
);
844 fprintf (f
, "%d", *p
);
859 /* Dump the reloc section if a base file is provided */
863 long need
[PAGE_SIZE
];
870 fprintf (f
, "\t.section\t.reloc\n");
871 fseek (base_file
, 0, SEEK_END
);
872 numbytes
= ftell (base_file
);
873 fseek (base_file
, 0, SEEK_SET
);
874 copy
= malloc (numbytes
);
875 fread (copy
, 1, numbytes
, base_file
);
876 num_entries
= numbytes
/ sizeof (long);
878 qsort (copy
, num_entries
, sizeof (long), sfunc
);
881 page_addr
= addr
& PAGE_MASK
; /* work out the page addr */
883 for (j
= 0; j
< num_entries
; j
++)
886 if ((addr
& PAGE_MASK
) != page_addr
)
888 flush_page (f
, need
, page_addr
, on_page
);
890 page_addr
= addr
& PAGE_MASK
;
892 need
[on_page
++] = addr
;
894 flush_page (f
, need
, page_addr
, on_page
);
896 fprintf (f
, "\t%s\t0,0\t%s End\n", ASM_LONG
, ASM_C
);
901 /* assemble the file */
902 sprintf (outfile
,"-o %s t%s", exp_name
, exp_name
);
903 run (as_name
, outfile
);
906 sprintf (outfile
,"t%s", exp_name
);
923 p
= strchr (name
, '@');
931 /**********************************************************************/
938 char *output_filename
;
939 char prefix
[PATHMAX
];
941 sprintf (outfile
, "%s", imp_name
);
942 output_filename
= strdup (outfile
);
944 unlink (output_filename
);
946 strcpy (prefix
, "d");
947 sprintf (outfile
, "%sh.s", prefix
);
949 f
= fopen (outfile
, "w");
951 fprintf (f
, "%s IMAGE_IMPORT_DESCRIPTOR\n", ASM_C
);
952 fprintf (f
, "\t.section .idata$2\n");
954 fprintf (f
, "\t%s\t__%s_head\n", ASM_GLOBAL
, imp_name
);
955 fprintf (f
, "__%s_head:\n", imp_name
);
957 fprintf (f
, "\t%s\t%shname%s\t%sPtr to image import by name list\n", ASM_LONG
,
958 ASM_RVA_BEFORE
, ASM_RVA_AFTER
, ASM_C
);
959 fprintf (f
, "\t%s\t%d\t%s time\n", ASM_LONG
, time (0), ASM_C
);
960 fprintf (f
, "\t%s\t0\t%s Forwarder chain\n", ASM_LONG
, ASM_C
);
961 fprintf (f
, "\t%s\t%s__%s_iname%s\t%s imported dll's name\n", ASM_LONG
,
966 fprintf (f
, "\t%s\t%sfthunk%s\t%s pointer to firstthunk\n", ASM_LONG
,
968 ASM_RVA_AFTER
, ASM_C
);
970 fprintf (f
, "%sStuff for compatibility\n", ASM_C
);
971 fprintf (f
, "\t.section\t.idata$5\n");
972 fprintf (f
, "\t%s\t0\n", ASM_LONG
);
973 fprintf (f
, "fthunk:\n");
974 fprintf (f
, "\t.section\t.idata$4\n");
975 fprintf (f
, "\t%s\t0\n", ASM_LONG
);
976 fprintf (f
, "\t.section .idata$4\n");
977 fprintf (f
, "hname:\n");
981 sprintf (outfile
, "-o %sh.o %sh.s", prefix
, prefix
);
982 run (as_name
, outfile
);
984 for (i
= 0, exp
= d_exports
; exp
; i
++, exp
= exp
->next
)
986 sprintf (outfile
, "%ss%d.s", prefix
, i
);
987 f
= fopen (outfile
, "w");
988 fprintf (f
, "\n\n\n%s ********************* \n", ASM_C
);
989 fprintf (f
, "\t.text\n");
990 fprintf (f
, "\t%s\t%s\n", ASM_GLOBAL
, exp
->name
);
991 fprintf (f
, "%s:\n\t%s\t__imp_%s\n", exp
->name
, ASM_JUMP
, exp
->name
);
993 fprintf (f
, "\t.section\t.idata$7\t%s To force loading of head and tail\n", ASM_C
);
994 fprintf (f
, "\t%s\t__%s_head\n", ASM_LONG
, imp_name
);
995 fprintf (f
, "\t%s\t__%s_tail\n", ASM_LONG
, imp_name
);
997 fprintf (f
, "\t.section .idata$5\n");
1000 fprintf (f
, "__imp_%s:\n", exp
->name
);
1001 fprintf (f
, "\t%s\t%sID%d%s\n", ASM_LONG
,
1006 fprintf (f
, "\n%s Hint name array\n", ASM_C
);
1007 fprintf (f
, "\t.section .idata$4\n");
1008 fprintf (f
, "\t%s\t%sID%d%s\n", ASM_LONG
, ASM_RVA_BEFORE
,
1012 fprintf (f
, "%s Hint/name array storage and import dll name\n", ASM_C
);
1013 fprintf (f
, "\t.section .idata$6\n");
1015 fprintf (f
, "\t%s\n", ASM_ALIGN_SHORT
);
1016 fprintf (f
, "ID%d:\t%s\t%d\n", i
, ASM_SHORT
, exp
->ordinal
);
1017 fprintf (f
, "\t%s\t\"%s\"\n", ASM_TEXT
, xlate (exp
->name
));
1021 sprintf (outfile
, "-o %ss%d.o %ss%d.s", prefix
, i
, prefix
, i
);
1022 run (as_name
, outfile
);
1025 sprintf (outfile
, "%st.s", prefix
);
1026 f
= fopen (outfile
, "w");
1028 fprintf (f
, "\t%s\t__%s_tail\n", ASM_GLOBAL
, imp_name
);
1029 fprintf (f
, "\t%s\t__%s_iname\n", ASM_GLOBAL
, imp_name
);
1030 fprintf (f
, "__%s_tail:\n", imp_name
);
1032 fprintf (f
, "\t%s\t0\n", ASM_LONG
);
1033 fprintf (f
, "__%s_iname:\t%s\t\"%s\"\n",
1034 imp_name
, ASM_TEXT
, dll_name
);
1037 fprintf (f
, "\t.section .idata$4\n");
1038 fprintf (f
, "\t%s\t0\n", ASM_LONG
);
1040 fprintf (f
, "\t.section .idata$5\n");
1041 fprintf (f
, "\t%s\t0\n", ASM_LONG
);
1044 sprintf (outfile
, "-o %st.o %st.s", prefix
, prefix
);
1045 run (as_name
, outfile
);
1047 /* Now stick them all into the archive */
1050 sprintf (outfile
, "crs %s %sh.o %st.o", output_filename
, prefix
, prefix
);
1051 run (ar_name
, outfile
);
1053 /* Do the rest in groups of however many fit into a command line */
1055 for (i
= 0, exp
= d_exports
; exp
; i
++, exp
= exp
->next
)
1059 sol
= sprintf (outfile
, "crs %s", output_filename
);
1062 sol
+= sprintf (outfile
+ sol
, " %ss%d.o", prefix
, i
);
1066 run (ar_name
, outfile
);
1072 run (ar_name
, outfile
);
1074 /* Delete all the temp files */
1078 sprintf (outfile
, "%sh.o", prefix
);
1080 sprintf (outfile
, "%sh.s", prefix
);
1082 sprintf (outfile
, "%st.o", prefix
);
1084 sprintf (outfile
, "%st.s", prefix
);
1087 /* Always delete these */
1088 for (i
= 0, exp
= d_exports
; exp
; i
++, exp
= exp
->next
)
1090 sprintf (outfile
, "%ss%d.o", prefix
, i
);
1092 sprintf (outfile
, "%ss%d.s", prefix
, i
);
1097 /**********************************************************************/
1099 /* Run through the information gathered from the .o files and the
1100 .def file and work out the best stuff */
1106 export_type
*ap
= *(export_type
**) a
;
1107 export_type
*bp
= *(export_type
**) b
;
1108 if (ap
->ordinal
== bp
->ordinal
)
1111 /* unset ordinals go to the bottom */
1112 if (ap
->ordinal
== -1)
1114 if (bp
->ordinal
== -1)
1116 return (ap
->ordinal
- bp
->ordinal
);
1125 export_type
*ap
= *(export_type
**) a
;
1126 export_type
*bp
= *(export_type
**) b
;
1128 return (strcmp (ap
->name
, bp
->name
));
1133 remove_null_names (ptr
)
1138 for (dst
= src
= 0; src
< d_nfuncs
; src
++)
1142 ptr
[dst
] = ptr
[src
];
1155 for (i
= 0; i
< d_nfuncs
; i
++)
1159 printf ("%d %s @ %d %s%s\n",
1160 i
, ptr
[i
]->name
, ptr
[i
]->ordinal
,
1161 ptr
[i
]->noname
? "NONAME " : "",
1162 ptr
[i
]->constant
? "CONSTANT" : "");
1171 process_duplicates (d_export_vec
)
1172 export_type
**d_export_vec
;
1179 /* Remove duplicates */
1180 qsort (d_export_vec
, d_nfuncs
, sizeof (export_type
*), nfunc
);
1182 dtab (d_export_vec
);
1183 for (i
= 0; i
< d_nfuncs
- 1; i
++)
1185 if (strcmp (d_export_vec
[i
]->name
,
1186 d_export_vec
[i
+ 1]->name
) == 0)
1189 export_type
*a
= d_export_vec
[i
];
1190 export_type
*b
= d_export_vec
[i
+ 1];
1194 fprintf (stderr
, "Warning, ignoring duplicate EXPORT %s %d,%d\n",
1198 if (a
->ordinal
!= -1
1199 && b
->ordinal
!= -1)
1202 fprintf (stderr
, "Error, duplicate EXPORT with oridinals %s\n",
1206 /* Merge attributes */
1207 b
->ordinal
= a
->ordinal
> 0 ? a
->ordinal
: b
->ordinal
;
1208 b
->constant
|= a
->constant
;
1209 b
->noname
|= a
->noname
;
1210 d_export_vec
[i
] = 0;
1213 dtab (d_export_vec
);
1214 remove_null_names (d_export_vec
);
1215 dtab (d_export_vec
);
1221 fill_ordinals (d_export_vec
)
1222 export_type
**d_export_vec
;
1227 qsort (d_export_vec
, d_nfuncs
, sizeof (export_type
*), pfunc
);
1229 /* fill in the unset ordinals with ones from our range */
1231 ptr
= (char *) malloc (65536);
1233 memset (ptr
, 65536, 0);
1235 /* Mark in our large vector all the numbers that are taken */
1236 for (i
= 0; i
< d_nfuncs
; i
++)
1238 if (d_export_vec
[i
]->ordinal
!= -1)
1240 ptr
[d_export_vec
[i
]->ordinal
] = 1;
1242 lowest
= d_export_vec
[i
]->ordinal
;
1246 for (i
= 0; i
< d_nfuncs
; i
++)
1248 if (d_export_vec
[i
]->ordinal
== -1)
1251 for (j
= lowest
; j
< 65536; j
++)
1255 d_export_vec
[i
]->ordinal
= j
;
1259 for (j
= 1; j
< lowest
; j
++)
1263 d_export_vec
[i
]->ordinal
= j
;
1275 qsort (d_export_vec
, d_nfuncs
, sizeof (export_type
*), pfunc
);
1277 /* Work out the lowest ordinal number */
1278 if (d_export_vec
[0])
1279 d_ord
= d_export_vec
[0]->ordinal
;
1284 /* First work out the minimum ordinal chosen */
1289 export_type
**d_export_vec
1290 = (export_type
**) xmalloc (sizeof (export_type
*) * d_nfuncs
);
1292 for (i
= 0, exp
= d_exports
; exp
; i
++, exp
= exp
->next
)
1294 d_export_vec
[i
] = exp
;
1297 process_duplicates (d_export_vec
);
1298 fill_ordinals (d_export_vec
);
1300 /* Put back the list in the new order */
1302 for (i
= d_nfuncs
- 1; i
>= 0; i
--)
1304 d_export_vec
[i
]->next
= d_exports
;
1305 d_exports
= d_export_vec
[i
];
1311 /* Work out exec prefix from the name of this file */
1318 /* See if we're running in a devo tree */
1319 for (p
= program_name
; *p
; p
++)
1321 if (*p
== '/' || *p
== '\\')
1328 if (ps
&& strncmp (ps
, "/binutils", 9) == 0)
1330 /* running in the binutils directory, the other
1331 executables will be surrounding it in the usual places. */
1332 int len
= ps
- program_name
;
1333 ar_name
= xmalloc (len
+ strlen ("/binutils/ar") + 1);
1334 ranlib_name
= xmalloc (len
+ strlen ("/binutils/ranlib") + 1);
1335 as_name
= xmalloc (len
+ strlen ("/gas/as.new") + 1);
1337 strncpy (ar_name
, program_name
, len
);
1338 strcat (ar_name
, "/binutils/ar");
1339 strncpy (ranlib_name
, program_name
, len
);
1340 strcat (ranlib_name
, "/binutils/ranlib");
1341 strncpy (as_name
, program_name
, len
);
1342 strcat (as_name
, "/gas/as.new");
1346 /* Otherwise chop off any prefix and use it for the rest of the progs,
1347 so i386-win32-dll generates i386-win32-ranlib etc etc */
1349 for (p
= program_name
; *p
; p
++)
1351 if (strncmp (p
, "dlltool", 7) == 0)
1353 int len
= p
- program_name
;
1354 ar_name
= xmalloc (len
+ strlen ("ar") +1);
1355 ranlib_name
= xmalloc (len
+ strlen ("ranlib")+1);
1356 as_name
= xmalloc (len
+ strlen ("as")+1);
1358 strncpy (ar_name
, program_name
, len
);
1359 strcat (ar_name
, "ar");
1360 strncpy (ranlib_name
, program_name
, len
);
1361 strcat (ranlib_name
, "ranlib");
1362 strncpy (as_name
, program_name
, len
);
1363 strcat (as_name
, "as");
1370 /**********************************************************************/
1373 usage (file
, status
)
1377 fprintf (file
, "Usage %s <options> <object-files>\n", program_name
);
1378 fprintf (file
, "\t -m <machine> Generate code for <machine>\n");
1379 fprintf (file
, "\t --machine <machine>\n");
1380 fprintf (file
, "\t --output-exp <outname> Generate export file.\n");
1381 fprintf (file
, "\t -e <outname>\n");
1382 fprintf (file
, "\t --output-lib <outname> Generate input library.\n");
1383 fprintf (file
, "\t -l <outname>");
1384 fprintf (file
, "\t --dllname <name> Name of input dll to put into output lib.\n");
1385 fprintf (file
, "\t --def <deffile> Name input .def file\n");
1386 fprintf (file
, "\t --base-file <basefile> Read linker generated base file\n");
1387 fprintf (file
, "\t -b <basefile> \n");
1388 fprintf (file
, "\t -v Verbose\n");
1389 fprintf (file
, "\t -u Remove leading underscore from .lib\n");
1390 fprintf (file
, "\t -k Kill @<n> from exported names\n");
1391 fprintf (file
, "\t --rva <value> Set the RVA from the default of 0x400000\n");
1392 fprintf (file
, "\t -image-base <value> ..ditto..\n");
1393 fprintf (file
, "\t -r <value>\n");
1394 fprintf (file
, "\t --nodelete Keep temp files.\n");
1395 fprintf (file
, "\t -n \n");
1399 static struct option long_options
[] =
1401 {"nodelete", no_argument
, NULL
,'n'},
1402 {"dllname", required_argument
, NULL
,'D'},
1403 {"output-exp", required_argument
, NULL
, 'e'},
1404 {"output-lib", required_argument
, NULL
, 'l'},
1405 {"def", required_argument
, NULL
, 'd'},
1406 {"underscore", no_argument
, NULL
, 'u'},
1407 {"killat", no_argument
, NULL
, 'k'},
1408 {"help", no_argument
, NULL
, 'h'},
1409 {"machine", required_argument
, NULL
, 'm'},
1410 {"rva", required_argument
, NULL
, 'r'},
1411 {"image-base", required_argument
, NULL
, 'r'},
1412 {"base-file", required_argument
, NULL
, 'b'},
1425 program_name
= av
[0];
1428 while ((c
= getopt_long (ac
, av
, "D:l:e:nr:kvbuh?m:yd:", long_options
, 0)) != EOF
)
1449 rva
= strtoul (optarg
, 0,0);
1470 base_file
= fopen (optarg
, "r");
1473 fprintf (stderr
, "%s: Unable to open base-file %s\n",
1485 for (i
= 0; mtable
[i
].type
; i
++)
1487 if (strcmp (mtable
[i
].type
, mname
) == 0)
1491 if (!mtable
[i
].type
)
1493 fprintf (stderr
, "Machine not supported\n");
1499 if (!dll_name
&& exp_name
)
1501 char len
= strlen (exp_name
) + 5;
1502 dll_name
= xmalloc (len
);
1503 strcpy (dll_name
, exp_name
);
1504 strcat (dll_name
, ".dll");
1511 process_def_file (def_file
);
1516 firstarg
= av
[optind
];
1517 scan_obj_file (av
[optind
]);
This page took 0.088294 seconds and 4 git commands to generate.