Fix gas bugs in SH3e handling of fmac instruction.
[deliverable/binutils-gdb.git] / binutils / dlltool.c
1 /* dlltool.c -- tool to generate stuff for PE style DLLs
2 Copyright (C) 1995 Free Software Foundation, Inc.
3
4 This file is part of GNU Binutils.
5
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.
10
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.
15
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. */
19
20
21 /*
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.
24 (eg, Windows NT)
25
26 A DLL contains an export table which contains the information
27 which the runtime loader needs to tie up references from a
28 referencing program.
29
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.
34
35 A DEF file contains any number of the following commands:
36
37
38 NAME <name> [ , <base> ]
39 The result is going to be <name>.EXE
40
41 LIBRARY <name> [ , <base> ]
42 The result is going to be <name>.DLL
43
44 EXPORTS ( <name1> [ = <name2> ] [ @ <integer> ] [ NONAME ] [CONSTANT] ) *
45 Declares name1 as an exported symbol from the
46 DLL, with optional ordinal number <integer>
47
48 IMPORTS ( [ <name> = ] <name> . <name> ) *
49 Ignored for compatibility
50
51 DESCRIPTION <string>
52 Puts <string> into output .exp file in the .rdata section
53
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.
58
59 [CODE|DATA] <attr>+
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
64 upon it.
65
66
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>
69 in a .DEF file.
70
71
72
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
75 supplied argument.
76
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.
80
81
82
83 Example:
84
85 file1.c:
86 asm (".section .drectve");
87 asm (".ascii \"-export:adef\"");
88
89 adef(char *s)
90 {
91 printf("hello from the dll %s\n",s);
92 }
93
94 bdef(char *s)
95 {
96 printf("hello from the dll and the other entry point %s\n",s);
97 }
98
99 file2.c:
100 asm (".section .drectve");
101 asm (".ascii \"-export:cdef\"");
102 asm (".ascii \"-export:ddef\"");
103 cdef(char *s)
104 {
105 printf("hello from the dll %s\n",s);
106 }
107
108 ddef(char *s)
109 {
110 printf("hello from the dll and the other entry point %s\n",s);
111 }
112
113 printf()
114 {
115 return 9;
116 }
117
118 main.c
119
120 main()
121 {
122 cdef();
123 }
124
125 thedll.def
126
127 LIBRARY thedll
128 HEAPSIZE 0x40000, 0x2000
129 EXPORTS bdef @ 20
130 cdef @ 30 NONAME
131
132 SECTIONS donkey READ WRITE
133 aardvark EXECUTE
134
135
136 # compile up the parts of the dll
137
138 gcc -c file1.c
139 gcc -c file2.c
140
141 # put them in a library (you don't have to, you
142 # could name all the .os on the dlltool line)
143
144 ar qcv thedll.in file1.o file2.o
145 ranlib thedll.in
146
147 # run this tool over the library and the def file
148 ./dlltool --def thedll.def --output-exp thedll.o --output-lib thedll.a
149
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
152
153 # build the mainline
154 gcc -c themain.c
155
156 # link the executable with the import library
157 ld -e main -Tthemain.ld -o themain.exe themain.o thedll.a
158
159 */
160
161 #define PAGE_SIZE 4096
162 #define PAGE_MASK (-PAGE_SIZE)
163 #include <stdio.h>
164 #include <stdlib.h>
165 #include <string.h>
166 #include "getopt.h"
167 #include "bfd.h"
168 #include <wait.h>
169
170 char *ar_name = "ar";
171 char *as_name = "as";
172 char *ranlib_name = "ranlib";
173
174 char *exp_name;
175 char *imp_name;
176 char *dll_name;
177
178 int dontdeltemps = 0;
179
180 int yydebug;
181 char *def_file;
182
183 char *program_name;
184 char *strrchr ();
185 char *xmalloc ();
186 char *strdup ();
187
188 static int machine;
189 int suckunderscore;
190 int killat;
191 static int verbose;
192 FILE *base_file;
193 #ifdef DLLTOOL_ARM
194 static char *mname = "arm";
195 #endif
196
197 #ifdef DLLTOOL_I386
198 static char *mname = "i386";
199 #endif
200 #define PATHMAX 250 /* What's the right name for this ? */
201
202 char outfile[PATHMAX];
203 struct mac
204 {
205 char *type;
206 char *how_byte;
207 char *how_short;
208 char *how_long;
209 char *how_asciz;
210 char *how_comment;
211 char *how_jump;
212 char *how_global;
213 char *how_space;
214 char *how_align_short;
215 }
216 mtable[]
217 =
218 {
219 {
220 #define MARM 0
221
222 "arm", ".byte", ".short", ".long", ".asciz", "@", "ldr\tip,[pc]\n\tldr\tpc,[ip]\n\t.long", ".global", ".space", ".align\t2",
223 }
224 ,
225 {
226 #define M386 1
227 "i386", ".byte", ".short", ".long", ".asciz", "#", "jmp *", ".global", ".space", ".align\t2",
228
229 }
230 ,
231 0
232 };
233
234
235 char *rvaafter (machine)
236 int machine;
237 {
238 switch (machine)
239 {
240 case MARM:
241 return "";
242 case M386:
243 return "";
244 }
245 }
246
247 char *rvabefore (machine)
248 int machine;
249 {
250 switch (machine)
251 {
252 case MARM:
253 return ".rva\t";
254 case M386:
255 return ".rva\t";
256 }
257 }
258 #define ASM_BYTE mtable[machine].how_byte
259 #define ASM_SHORT mtable[machine].how_short
260 #define ASM_LONG mtable[machine].how_long
261 #define ASM_TEXT mtable[machine].how_asciz
262 #define ASM_C mtable[machine].how_comment
263 #define ASM_JUMP mtable[machine].how_jump
264 #define ASM_GLOBAL mtable[machine].how_global
265 #define ASM_SPACE mtable[machine].how_space
266 #define ASM_ALIGN_SHORT mtable[machine].how_align_short
267 #define ASM_RVA_BEFORE rvabefore(machine)
268 #define ASM_RVA_AFTER rvaafter(machine)
269
270 static char **oav;
271
272 int i;
273
274 FILE *yyin; /* communications with flex */
275 extern int linenumber;
276 void
277 process_def_file (name)
278 char *name;
279 {
280 FILE *f = fopen (name, "r");
281 if (!f)
282 {
283 fprintf (stderr, "%s: Can't open def file %s\n", program_name, name);
284 exit (1);
285 }
286
287 yyin = f;
288
289 yyparse ();
290 }
291
292 /**********************************************************************/
293
294 /* Communications with the parser */
295
296
297 typedef struct dlist
298 {
299 char *text;
300 struct dlist *next;
301 }
302 dlist_type;
303
304 typedef struct export
305 {
306 char *name;
307 char *internal_name;
308 int ordinal;
309 int constant;
310 int noname;
311 struct export *next;
312 }
313 export_type;
314
315 static char *d_name; /* Arg to NAME or LIBRARY */
316 static int d_nfuncs; /* Number of functions exported */
317 static int d_ord; /* Base ordinal index */
318 static export_type *d_exports; /*list of exported functions */
319 static dlist_type *d_list; /* Descriptions */
320 static dlist_type *a_list; /* Stuff to go in directives */
321
322 static int d_is_dll;
323 static int d_is_exe;
324
325 yyerror ()
326 {
327 fprintf (stderr, "%s: Syntax error in def file %s:%d\n",
328 program_name, def_file, linenumber);
329 }
330
331 void
332 def_exports (name, internal_name, ordinal, noname, constant)
333 char *name;
334 char *internal_name;
335 int ordinal;
336 int noname;
337 int constant;
338 {
339 struct export *p = (struct export *) xmalloc (sizeof (*p));
340
341 p->name = name;
342 p->internal_name = internal_name ? internal_name : name;
343 p->ordinal = ordinal;
344 p->constant = constant;
345 p->noname = noname;
346 p->next = d_exports;
347 d_exports = p;
348 d_nfuncs++;
349 }
350
351
352 void
353 def_name (name, base)
354 char *name;
355 int base;
356 {
357 if (verbose)
358 fprintf (stderr, "%s NAME %s base %x\n", program_name, name, base);
359 if (d_is_dll)
360 {
361 fprintf (stderr, "Can't have LIBRARY and NAME\n");
362 }
363 d_name = name;
364 d_is_exe = 1;
365 }
366
367 void
368 def_library (name, base)
369 char *name;
370 int base;
371 {
372 if (verbose)
373 printf ("%s: LIBRARY %s base %x\n", program_name, name, base);
374 if (d_is_exe)
375 {
376 fprintf (stderr, "%s: Can't have LIBRARY and NAME\n", program_name);
377 }
378 d_name = name;
379 d_is_dll = 1;
380 }
381
382 void
383 def_description (desc)
384 char *desc;
385 {
386 dlist_type *d = (dlist_type *) xmalloc (sizeof (dlist_type));
387 d->text = strdup (desc);
388 d->next = d_list;
389 d_list = d;
390 }
391
392 void
393 new_directive (dir)
394 char *dir;
395 {
396 dlist_type *d = (dlist_type *) xmalloc (sizeof (dlist_type));
397 d->text = strdup (dir);
398 d->next = a_list;
399 a_list = d;
400 }
401
402 void
403 def_stacksize (reserve, commit)
404 int reserve;
405 int commit;
406 {
407 char b[200];
408 if (commit > 0)
409 sprintf (b, "-stack 0x%x,0x%x ", reserve, commit);
410 else
411 sprintf (b, "-stack 0x%x ", reserve);
412 new_directive (strdup (b));
413 }
414
415 void
416 def_heapsize (reserve, commit)
417 int reserve;
418 int commit;
419 {
420 char b[200];
421 if (commit > 0)
422 sprintf (b, "-heap 0x%x,0x%x ", reserve, commit);
423 else
424 sprintf (b, "-heap 0x%x ", reserve);
425 new_directive (strdup (b));
426 }
427
428
429 void
430 def_import (internal, module, entry)
431 char *internal;
432 char *module;
433 char *entry;
434 {
435 if (verbose)
436 fprintf (stderr, "%s: IMPORTS are ignored", program_name);
437 }
438
439 void
440 def_version (major, minor)
441 {
442 printf ("VERSION %d.%d\n", major, minor);
443 }
444
445
446 void
447 def_section (name, attr)
448 char *name;
449 int attr;
450 {
451 char buf[200];
452 char atts[5];
453 char *d = atts;
454 if (attr & 1)
455 *d++ = 'R';
456
457 if (attr & 2)
458 *d++ = 'W';
459 if (attr & 4)
460 *d++ = 'X';
461 if (attr & 8)
462 *d++ = 'S';
463 *d++ = 0;
464 sprintf (buf, "-attr %s %s", name, atts);
465 new_directive (strdup (buf));
466 }
467 void
468 def_code (attr)
469 int attr;
470 {
471
472 def_section ("CODE", attr);
473 }
474
475 void
476 def_data (attr)
477 int attr;
478 {
479 def_section ("DATA", attr);
480 }
481
482
483 /**********************************************************************/
484
485 void
486 run (what, args)
487 char *what;
488 char *args;
489 {
490 char *s;
491 int pid;
492 int i;
493 char **argv;
494 extern char **environ;
495 if (verbose)
496 fprintf (stderr, "%s %s\n", what, args);
497
498 /* Count the args */
499 i = 0;
500 for (s = args; *s ; s++)
501 if (*s == ' ')
502 i++;
503 i++;
504 argv = alloca (sizeof (char *) * (i + 3));
505 i = 0;
506 argv[i++] = what;
507 s = args;
508 while (1) {
509 argv[i++] = s;
510 while (*s != ' ' && *s != 0)
511 s++;
512 if (*s == 0)
513 break;
514 *s++ = 0;
515 }
516 argv[i++] = 0;
517
518
519 pid = vfork ();
520 if (pid == 0)
521 {
522 execvp (what, argv);
523 fprintf (stderr, "%s: can't exec %s\n", program_name, what);
524 exit (1);
525 }
526 else if (pid == -1)
527 {
528 extern int errno;
529 fprintf (stderr, "%s: vfork failed, %d\n", program_name, errno);
530 exit (1);
531 }
532 else
533 {
534 int status;
535 waitpid (pid, &status, 0);
536 if (status)
537 {
538 if (WIFSIGNALED (status))
539 {
540 fprintf (stderr, "%s: %s %s terminated with signal %d\n",
541 program_name, what, args, WTERMSIG (status));
542 exit (1);
543 }
544
545 if (WIFEXITED (status))
546 {
547 fprintf (stderr, "%s: %s %s terminated with exit status %d\n",
548 program_name, what, args, WEXITSTATUS (status));
549 exit (1);
550 }
551 }
552 }
553 }
554
555 /* read in and block out the base relocations */
556 static void
557 basenames (abfd)
558 bfd *abfd;
559 {
560
561
562
563
564 }
565
566 void
567 scan_open_obj_file (abfd)
568 bfd *abfd;
569 {
570 /* Look for .drectives */
571 asection *s = bfd_get_section_by_name (abfd, ".drectve");
572 if (s)
573 {
574 int size = bfd_get_section_size_before_reloc (s);
575 char *buf = xmalloc (size);
576 char *p;
577 char *e;
578 bfd_get_section_contents (abfd, s, buf, 0, size);
579 if (verbose)
580 fprintf (stderr, "%s: Sucking in info from %s\n",
581 program_name,
582 bfd_get_filename (abfd));
583
584 /* Search for -export: strings */
585 p = buf;
586 e = buf + size;
587 while (p < e)
588 {
589 if (p[0] == '-'
590 && strncmp (p, "-export:", 8) == 0)
591 {
592 char *name;
593 char *c;
594 p += 8;
595 name = p;
596 while (*p != ' ' && *p != '-' && p < e)
597 p++;
598 c = xmalloc (p - name + 1);
599 memcpy (c, name, p - name);
600 c[p - name] = 0;
601 def_exports (c, 0, -1, 0);
602 }
603 else
604 p++;
605 }
606 free (buf);
607 }
608
609 basenames (abfd);
610
611 if (verbose)
612 fprintf (stderr, "%s: Done readin\n",
613 program_name);
614
615 }
616
617
618 void
619 scan_obj_file (filename)
620 char *filename;
621 {
622 bfd *f = bfd_openr (filename, 0);
623
624 if (!f)
625 {
626 fprintf (stderr, "%s: Unable to open object file %s\n",
627 program_name,
628 filename);
629 exit (1);
630 }
631 if (bfd_check_format (f, bfd_archive))
632 {
633 bfd *arfile = bfd_openr_next_archived_file (f, 0);
634 while (arfile)
635 {
636 if (bfd_check_format (arfile, bfd_object))
637 scan_open_obj_file (arfile);
638 bfd_close (arfile);
639 arfile = bfd_openr_next_archived_file (f, arfile);
640 }
641 }
642
643 if (bfd_check_format (f, bfd_object))
644 {
645 scan_open_obj_file (f);
646 }
647
648 bfd_close (f);
649 }
650
651 /**********************************************************************/
652
653
654 /* return the bit of the name before the last . */
655
656 static
657 char *
658 prefix (name)
659 char *name;
660 {
661 char *res = strdup (name);
662 char *p = strrchr (res, '.');
663 if (p)
664 *p = 0;
665 return res;
666 }
667
668 void
669 dump_def_info (f)
670 FILE *f;
671 {
672 int i;
673 export_type *exp;
674 fprintf (f, "%s ", ASM_C);
675 for (i = 0; oav[i]; i++)
676 fprintf (f, "%s ", oav[i]);
677 fprintf (f, "\n");
678 for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
679 {
680 fprintf (f, "%s %d = %s %s @ %d %s%s\n",
681 ASM_C,
682 i,
683 exp->name,
684 exp->internal_name,
685 exp->ordinal,
686 exp->noname ? "NONAME " : "",
687 exp->constant ? "CONSTANT" : "");
688 }
689 }
690 /* Generate the .exp file */
691
692 int
693 sfunc (a, b)
694 long *a;
695 long *b;
696 {
697 return *a - *b;
698 }
699
700
701
702 static void
703 flush_page (f, need, page_addr, on_page)
704 FILE *f;
705 long *need;
706 long page_addr;
707 int on_page;
708 {
709 int i;
710 /* Flush this page */
711 fprintf (f, "\t%s\t0x%08x\t%s Starting RVA for chunk\n",
712 ASM_LONG,
713 page_addr,
714 ASM_C);
715 fprintf (f, "\t%s\t0x%x\t%s Size of block\n",
716 ASM_LONG,
717 (on_page * 2) + (on_page & 1) * 2 + 8,
718 ASM_C);
719 for (i = 0; i < on_page; i++)
720 {
721 fprintf (f, "\t%s\t0x%x\n", ASM_SHORT, need[i] - page_addr | 0x3000);
722 }
723 /* And padding */
724 if (on_page & 1)
725 fprintf (f, "\t%s\t0x%x\n", ASM_SHORT, 0 | 0x0000);
726
727 }
728
729
730 void
731 gen_exp_file ()
732 {
733 FILE *f;
734 int i;
735 export_type *exp;
736 dlist_type *dl;
737 int had_noname = 0;
738
739 sprintf (outfile, "t%s", exp_name);
740
741 if (verbose)
742 fprintf (stderr, "%s: Generate exp file %s\n",
743 program_name, exp_name);
744
745 f = fopen (outfile, "w");
746 if (!f)
747 {
748 fprintf (stderr, "%s: Unable to open output file %s\n", program_name, outfile);
749 exit (1);
750 }
751 if (verbose)
752 {
753 fprintf (stderr, "%s: Opened file %s\n",
754 program_name, outfile);
755 }
756
757 dump_def_info (f);
758 if (d_exports) {
759 fprintf (f, "\t.section .edata\n\n");
760 fprintf (f, "\t%s 0 %s Allways 0\n", ASM_LONG, ASM_C);
761 fprintf (f, "\t%s %d %s Time and date\n", ASM_LONG, time (0), ASM_C);
762 fprintf (f, "\t%s 0 %s Major and Minor version\n", ASM_LONG, ASM_C);
763 fprintf (f, "\t%sname%s%s Ptr to name of dll\n", ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C);
764 fprintf (f, "\t%s %d %s Starting ordinal of exports\n", ASM_LONG, d_ord, ASM_C);
765 fprintf (f, "\t%s The next field is documented as being the number of functions\n", ASM_C);
766 fprintf (f, "\t%s yet it doesn't look like that in real PE dlls\n", ASM_C);
767 fprintf (f, "\t%s But it shouldn't be a problem, causes there's\n", ASM_C);
768 fprintf (f, "\t%s always the number of names field\n", ASM_C);
769 fprintf (f, "\t%s %d %s Number of functions\n", ASM_LONG, d_nfuncs, ASM_C);
770 fprintf (f, "\t%s %d %s Number of names\n", ASM_LONG, d_nfuncs, ASM_C);
771 fprintf (f, "\t%safuncs%s %s Address of functions\n", ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C);
772 fprintf (f, "\t%sanames%s %s Address of names\n", ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C);
773 fprintf (f, "\t%sanords%s %s Address of ordinals\n", ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C);
774
775 fprintf (f, "name: %s \"%s\"\n", ASM_TEXT, dll_name);
776
777 fprintf (f, "afuncs:\n");
778 i = d_ord;
779 for (exp = d_exports; exp; exp = exp->next)
780 {
781 #if 0
782 /* This seems necessary in the doc, but in real
783 life it's not used.. */
784 if (exp->ordinal != i)
785 {
786 fprintf (f, "%s\t%s\t%d\t@ %d..%d missing\n", ASM_C, ASM_SPACE,
787 (exp->ordinal - i) * 4,
788 i, exp->ordinal - 1);
789 i = exp->ordinal;
790 }
791 #endif
792 fprintf (f, "\t%s%s%s%s %d\n",ASM_RVA_BEFORE,
793 exp->internal_name, ASM_RVA_AFTER, ASM_C, exp->ordinal);
794 i++;
795 }
796
797
798 fprintf (f, "anames:\n");
799 for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
800 {
801 if (exp->noname)
802 {
803 had_noname = 1;
804 fprintf (f, "\t%s nNoname\n", ASM_LONG, ASM_C);
805 }
806 else
807 {
808 fprintf (f, "\t%sn%d%s\n", ASM_RVA_BEFORE, i, ASM_RVA_AFTER);
809 }
810 }
811
812 fprintf (f, "anords:\n");
813 for (exp = d_exports; exp; exp = exp->next)
814 fprintf (f, "\t%s %d\n", ASM_SHORT, exp->ordinal - d_ord);
815
816 for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
817 if (exp->noname)
818 fprintf (f, "@n%d: %s \"%s\"\n", i, ASM_TEXT, exp->name);
819 else
820 fprintf (f, "n%d: %s \"%s\"\n", i, ASM_TEXT, exp->name);
821
822 if (had_noname)
823 fprintf (f, "nNoname: %s \"__noname__\"\n", ASM_TEXT);
824
825 if (a_list)
826 {
827 fprintf (f, "\t.section .drectve\n");
828 for (dl = a_list; dl; dl = dl->next)
829 {
830 fprintf (f, "\t%s\t\"%s\"\n", ASM_TEXT, dl->text);
831 }
832 }
833 if (d_list)
834 {
835 fprintf (f, "\t.section .rdata\n");
836 for (dl = d_list; dl; dl = dl->next)
837 {
838 char *p;
839 int l;
840 /* We dont output as ascii 'cause there can
841 be quote characters in the string */
842
843 l = 0;
844 for (p = dl->text; *p; p++)
845 {
846 if (l == 0)
847 fprintf (f, "\t%s\t", ASM_BYTE);
848 else
849 fprintf (f, ",");
850 fprintf (f, "%d", *p);
851 if (p[1] == 0)
852 {
853 fprintf (f, ",0\n");
854 break;
855 }
856 if (++l == 10)
857 {
858 fprintf (f, "\n");
859 l = 0;
860 }
861 }
862 }
863 }
864
865 }
866 /* Dump the reloc section if a base file is provided */
867 if (base_file)
868 {
869 int addr;
870 long need[PAGE_SIZE];
871 long page_addr;
872 int numbytes;
873 int num_entries;
874 long *copy;
875 int j;
876 int on_page;
877 fprintf (f,"\t.section\t.init\n");
878 fprintf (f,"lab:\n");
879 fprintf (f, "\t.section\t.reloc\n");
880 fseek (base_file, 0, SEEK_END);
881 numbytes = ftell (base_file);
882 fseek (base_file, 0, SEEK_SET);
883 copy = malloc (numbytes);
884 fread (copy, 1, numbytes, base_file);
885 num_entries = numbytes / sizeof (long);
886
887 qsort (copy, num_entries, sizeof (long), sfunc);
888
889 addr = copy[0];
890 page_addr = addr & PAGE_MASK; /* work out the page addr */
891 on_page = 0;
892 for (j = 0; j < num_entries; j++)
893 {
894 addr = copy[j];
895 if ((addr & PAGE_MASK) != page_addr)
896 {
897 flush_page (f, need, page_addr, on_page);
898 on_page = 0;
899 page_addr = addr & PAGE_MASK;
900 }
901 need[on_page++] = addr;
902 }
903 flush_page (f, need, page_addr, on_page);
904
905 fprintf (f, "\t%s\t0,0\t%s End\n", ASM_LONG, ASM_C);
906 }
907
908 fclose (f);
909
910 /* assemble the file */
911 sprintf (outfile,"-o %s t%s", exp_name, exp_name);
912 run (as_name, outfile);
913 if (dontdeltemps==0)
914 {
915 sprintf (outfile,"t%s", exp_name);
916 unlink (outfile);
917 }
918 }
919
920 static char *
921 xlate (char *name)
922 {
923
924 if (!suckunderscore)
925 return name;
926
927 if (name[0] == '_')
928 name++;
929 if (killat)
930 {
931 char *p;
932 p = strchr (name, '@');
933 if (p)
934 *p = 0;
935 }
936 return name;
937 }
938
939
940 /**********************************************************************/
941 gen_lib_file ()
942 {
943 int i;
944 int sol;
945 FILE *f;
946 export_type *exp;
947 char *output_filename;
948 char prefix[PATHMAX];
949
950 sprintf (outfile, "%s", imp_name);
951 output_filename = strdup (outfile);
952
953 unlink (output_filename);
954
955 strcpy (prefix, "d");
956 sprintf (outfile, "%sh.s", prefix);
957
958 f = fopen (outfile, "w");
959
960 fprintf (f, "%s IMAGE_IMPORT_DESCRIPTOR\n", ASM_C);
961 fprintf (f, "\t.section .idata$2\n");
962
963 fprintf (f, "\t%s\t__%s_head\n", ASM_GLOBAL, imp_name);
964 fprintf (f, "__%s_head:\n", imp_name);
965
966 fprintf (f, "\t%shname%s\t%sPtr to image import by name list\n",
967 ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C);
968 fprintf (f, "\t%sthis should be the timestamp, but NT sometimes\n", ASM_C);
969 fprintf (f, "\t%sdoesn't load DLLs when this is set.\n", ASM_C);
970 fprintf (f, "\t%s\t0\t%s time\n", ASM_LONG, ASM_C);
971 fprintf (f, "\t%s\t0\t%s Forwarder chain\n", ASM_LONG, ASM_C);
972 fprintf (f, "\t%s__%s_iname%s\t%s imported dll's name\n",
973 ASM_RVA_BEFORE,
974 imp_name,
975 ASM_RVA_AFTER,
976 ASM_C);
977 fprintf (f, "\t%sfthunk%s\t%s pointer to firstthunk\n",
978 ASM_RVA_BEFORE,
979 ASM_RVA_AFTER, ASM_C);
980
981 fprintf (f, "%sStuff for compatibility\n", ASM_C);
982 fprintf (f, "\t.section\t.idata$5\n");
983 fprintf (f, "\t%s\t0\n", ASM_LONG);
984 fprintf (f, "fthunk:\n");
985 fprintf (f, "\t.section\t.idata$4\n");
986 fprintf (f, "\t%s\t0\n", ASM_LONG);
987 fprintf (f, "\t.section .idata$4\n");
988 fprintf (f, "hname:\n");
989
990 fclose (f);
991
992 sprintf (outfile, "-o %sh.o %sh.s", prefix, prefix);
993 run (as_name, outfile);
994
995 for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
996 {
997 sprintf (outfile, "%ss%d.s", prefix, i);
998 f = fopen (outfile, "w");
999 fprintf (f, "\n\n\n%s ********************* \n", ASM_C);
1000 fprintf (f, "\t.text\n");
1001 fprintf (f, "\t%s\t%s\n", ASM_GLOBAL, exp->name);
1002 fprintf (f, "\t%s\t__imp_%s\n", ASM_GLOBAL, exp->name);
1003 fprintf (f, "%s:\n\t%s\t__imp_%s\n", exp->name, ASM_JUMP, exp->name);
1004
1005 fprintf (f, "\t.section\t.idata$7\t%s To force loading of head\n", ASM_C);
1006 fprintf (f, "\t%s\t__%s_head\n", ASM_LONG, imp_name);
1007 fprintf (f, "\t.section .idata$5\n");
1008
1009
1010 fprintf (f, "__imp_%s:\n", exp->name);
1011 fprintf (f, "\t%sID%d%s\n",
1012 ASM_RVA_BEFORE,
1013 i,
1014 ASM_RVA_AFTER);
1015
1016 fprintf (f, "\n%s Hint name array\n", ASM_C);
1017 fprintf (f, "\t.section .idata$4\n");
1018 fprintf (f, "\t%sID%d%s\n", ASM_RVA_BEFORE,
1019 i,
1020 ASM_RVA_AFTER);
1021
1022 fprintf (f, "%s Hint/name array storage and import dll name\n", ASM_C);
1023 fprintf (f, "\t.section .idata$6\n");
1024
1025 fprintf (f, "\t%s\n", ASM_ALIGN_SHORT);
1026 fprintf (f, "ID%d:\t%s\t%d\n", i, ASM_SHORT, exp->ordinal);
1027 fprintf (f, "\t%s\t\"%s\"\n", ASM_TEXT, xlate (exp->name));
1028 fclose (f);
1029
1030
1031 sprintf (outfile, "-o %ss%d.o %ss%d.s", prefix, i, prefix, i);
1032 run (as_name, outfile);
1033 }
1034
1035 sprintf (outfile, "%st.s", prefix);
1036 f = fopen (outfile, "w");
1037 fprintf (f, "\t.section .idata$7\n");
1038 fprintf (f, "\t%s\t__%s_iname\n", ASM_GLOBAL, imp_name);
1039 fprintf (f, "__%s_iname:\t%s\t\"%s\"\n",
1040 imp_name, ASM_TEXT, dll_name);
1041
1042
1043 fprintf (f, "\t.section .idata$4\n");
1044 fprintf (f, "\t%s\t0\n", ASM_LONG);
1045
1046 fprintf (f, "\t.section .idata$5\n");
1047 fprintf (f, "\t%s\t0\n", ASM_LONG);
1048 fclose (f);
1049
1050 sprintf (outfile, "-o %st.o %st.s", prefix, prefix);
1051 run (as_name, outfile);
1052
1053 /* Now stick them all into the archive */
1054
1055
1056 sprintf (outfile, "crs %s %sh.o %st.o", output_filename, prefix, prefix);
1057 run (ar_name, outfile);
1058
1059 /* Do the rest in groups of however many fit into a command line */
1060 sol = 0;
1061 for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
1062 {
1063 if (sol == 0)
1064 {
1065 sol = sprintf (outfile, "crs %s", output_filename);
1066 }
1067
1068 sol += sprintf (outfile + sol, " %ss%d.o", prefix, i);
1069
1070 if (sol >100)
1071 {
1072 run (ar_name, outfile);
1073 sol = 0;
1074 }
1075
1076 }
1077 if (sol)
1078 run (ar_name, outfile);
1079
1080 /* Delete all the temp files */
1081
1082 if (dontdeltemps == 0)
1083 {
1084 sprintf (outfile, "%sh.o", prefix);
1085 unlink (outfile);
1086 sprintf (outfile, "%sh.s", prefix);
1087 unlink (outfile);
1088 sprintf (outfile, "%st.o", prefix);
1089 unlink (outfile);
1090 sprintf (outfile, "%st.s", prefix);
1091 unlink (outfile);
1092 }
1093
1094 if (dontdeltemps < 2)
1095 for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
1096 {
1097 sprintf (outfile, "%ss%d.o", prefix, i);
1098 unlink (outfile);
1099 sprintf (outfile, "%ss%d.s", prefix, i);
1100 unlink (outfile);
1101 }
1102
1103 }
1104 /**********************************************************************/
1105
1106 /* Run through the information gathered from the .o files and the
1107 .def file and work out the best stuff */
1108 int
1109 pfunc (a, b)
1110 void *a;
1111 void *b;
1112 {
1113 export_type *ap = *(export_type **) a;
1114 export_type *bp = *(export_type **) b;
1115 if (ap->ordinal == bp->ordinal)
1116 return 0;
1117
1118 /* unset ordinals go to the bottom */
1119 if (ap->ordinal == -1)
1120 return 1;
1121 if (bp->ordinal == -1)
1122 return -1;
1123 return (ap->ordinal - bp->ordinal);
1124 }
1125
1126
1127 int
1128 nfunc (a, b)
1129 void *a;
1130 void *b;
1131 {
1132 export_type *ap = *(export_type **) a;
1133 export_type *bp = *(export_type **) b;
1134
1135 return (strcmp (ap->name, bp->name));
1136 }
1137
1138 static
1139 void
1140 remove_null_names (ptr)
1141 export_type **ptr;
1142 {
1143 int src;
1144 int dst;
1145 for (dst = src = 0; src < d_nfuncs; src++)
1146 {
1147 if (ptr[src])
1148 {
1149 ptr[dst] = ptr[src];
1150 dst++;
1151 }
1152 }
1153 d_nfuncs = dst;
1154 }
1155
1156 static void
1157 dtab (ptr)
1158 export_type **ptr;
1159 {
1160 #ifdef SACDEBUG
1161 int i;
1162 for (i = 0; i < d_nfuncs; i++)
1163 {
1164 if (ptr[i])
1165 {
1166 printf ("%d %s @ %d %s%s\n",
1167 i, ptr[i]->name, ptr[i]->ordinal,
1168 ptr[i]->noname ? "NONAME " : "",
1169 ptr[i]->constant ? "CONSTANT" : "");
1170 }
1171 else
1172 printf ("empty\n");
1173 }
1174 #endif
1175 }
1176
1177 static void
1178 process_duplicates (d_export_vec)
1179 export_type **d_export_vec;
1180 {
1181 int more = 1;
1182
1183 while (more)
1184 {
1185 more = 0;
1186 /* Remove duplicates */
1187 qsort (d_export_vec, d_nfuncs, sizeof (export_type *), nfunc);
1188
1189 dtab (d_export_vec);
1190 for (i = 0; i < d_nfuncs - 1; i++)
1191 {
1192 if (strcmp (d_export_vec[i]->name,
1193 d_export_vec[i + 1]->name) == 0)
1194 {
1195
1196 export_type *a = d_export_vec[i];
1197 export_type *b = d_export_vec[i + 1];
1198
1199 more = 1;
1200 if (verbose)
1201 fprintf (stderr, "Warning, ignoring duplicate EXPORT %s %d,%d\n",
1202 a->name,
1203 a->ordinal,
1204 b->ordinal);
1205 if (a->ordinal != -1
1206 && b->ordinal != -1)
1207 {
1208
1209 fprintf (stderr, "Error, duplicate EXPORT with oridinals %s\n",
1210 a->name);
1211 exit (1);
1212 }
1213 /* Merge attributes */
1214 b->ordinal = a->ordinal > 0 ? a->ordinal : b->ordinal;
1215 b->constant |= a->constant;
1216 b->noname |= a->noname;
1217 d_export_vec[i] = 0;
1218 }
1219
1220 dtab (d_export_vec);
1221 remove_null_names (d_export_vec);
1222 dtab (d_export_vec);
1223 }
1224 }
1225 }
1226
1227 static void
1228 fill_ordinals (d_export_vec)
1229 export_type **d_export_vec;
1230 {
1231 int lowest = 0;
1232 int unset = 0;
1233 char *ptr;
1234 qsort (d_export_vec, d_nfuncs, sizeof (export_type *), pfunc);
1235
1236 /* fill in the unset ordinals with ones from our range */
1237
1238 ptr = (char *) malloc (65536);
1239
1240 memset (ptr, 65536, 0);
1241
1242 /* Mark in our large vector all the numbers that are taken */
1243 for (i = 0; i < d_nfuncs; i++)
1244 {
1245 if (d_export_vec[i]->ordinal != -1)
1246 {
1247 ptr[d_export_vec[i]->ordinal] = 1;
1248 if (lowest == 0)
1249 lowest = d_export_vec[i]->ordinal;
1250 }
1251 }
1252
1253 for (i = 0; i < d_nfuncs; i++)
1254 {
1255 if (d_export_vec[i]->ordinal == -1)
1256 {
1257 int j;
1258 for (j = lowest; j < 65536; j++)
1259 if (ptr[j] == 0)
1260 {
1261 ptr[j] = 1;
1262 d_export_vec[i]->ordinal = j;
1263 goto done;
1264 }
1265
1266 for (j = 1; j < lowest; j++)
1267 if (ptr[j] == 0)
1268 {
1269 ptr[j] = 1;
1270 d_export_vec[i]->ordinal = j;
1271 goto done;
1272 }
1273 done:;
1274
1275 }
1276 }
1277
1278 free (ptr);
1279
1280 /* And resort */
1281
1282 qsort (d_export_vec, d_nfuncs, sizeof (export_type *), pfunc);
1283
1284 /* Work out the lowest ordinal number */
1285 if (d_export_vec[0])
1286 d_ord = d_export_vec[0]->ordinal;
1287 }
1288 void
1289 mangle_defs ()
1290 {
1291 /* First work out the minimum ordinal chosen */
1292
1293 export_type *exp;
1294 int lowest = 0;
1295 int i;
1296 export_type **d_export_vec
1297 = (export_type **) xmalloc (sizeof (export_type *) * d_nfuncs);
1298
1299 for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
1300 {
1301 d_export_vec[i] = exp;
1302 }
1303
1304 process_duplicates (d_export_vec);
1305 fill_ordinals (d_export_vec);
1306
1307 /* Put back the list in the new order */
1308 d_exports = 0;
1309 for (i = d_nfuncs - 1; i >= 0; i--)
1310 {
1311 d_export_vec[i]->next = d_exports;
1312 d_exports = d_export_vec[i];
1313 }
1314 }
1315
1316
1317
1318 /* Work out exec prefix from the name of this file */
1319 void
1320 workout_prefix ()
1321 {
1322 char *ps = 0;
1323 char *s = 0;
1324 char *p;
1325 /* See if we're running in a devo tree */
1326 for (p = program_name; *p; p++)
1327 {
1328 if (*p == '/' || *p == '\\')
1329 {
1330 ps = s;
1331 s = p;
1332 }
1333 }
1334
1335 if (ps && strncmp (ps, "/binutils", 9) == 0)
1336 {
1337 /* running in the binutils directory, the other
1338 executables will be surrounding it in the usual places. */
1339 int len = ps - program_name;
1340 ar_name = xmalloc (len + strlen ("/binutils/ar") + 1);
1341 ranlib_name = xmalloc (len + strlen ("/binutils/ranlib") + 1);
1342 as_name = xmalloc (len + strlen ("/gas/as.new") + 1);
1343
1344 memcpy (ar_name, program_name, len);
1345 strcpy (ar_name + len, "/binutils/ar");
1346 memcpy (ranlib_name, program_name, len);
1347 strcpy (ranlib_name + len, "/binutils/ranlib");
1348 memcpy (as_name, program_name, len);
1349 strcpy (as_name + len, "/gas/as.new");
1350 }
1351 else
1352 {
1353 /* Otherwise chop off any prefix and use it for the rest of the progs,
1354 so i386-win32-dll generates i386-win32-ranlib etc etc */
1355
1356 for (p = program_name; *p; p++)
1357 {
1358 if (strncmp (p, "dlltool", 7) == 0)
1359 {
1360 int len = p - program_name;
1361 ar_name = xmalloc (len + strlen ("ar") +1);
1362 ranlib_name = xmalloc (len + strlen ("ranlib")+1);
1363 as_name = xmalloc (len + strlen ("as")+1);
1364
1365 memcpy (ar_name, program_name, len);
1366 strcpy (ar_name + len, "ar");
1367 memcpy (ranlib_name, program_name, len);
1368 strcpy (ranlib_name + len, "ranlib");
1369 memcpy (as_name, program_name, len);
1370 strcpy (as_name + len, "as");
1371 }
1372 }
1373 }
1374 }
1375
1376
1377 /**********************************************************************/
1378
1379 void
1380 usage (file, status)
1381 FILE *file;
1382 int status;
1383 {
1384 fprintf (file, "Usage %s <options> <object-files>\n", program_name);
1385 fprintf (file, " --machine <machine>\n");
1386 fprintf (file, " --output-exp <outname> Generate export file.\n");
1387 fprintf (file, " --output-lib <outname> Generate input library.\n");
1388 fprintf (file, " --dllname <name> Name of input dll to put into output lib.\n");
1389 fprintf (file, " --def <deffile> Name input .def file\n");
1390 fprintf (file, " --base-file <basefile> Read linker generated base file\n");
1391 fprintf (file, " -v Verbose\n");
1392 fprintf (file, " -u Remove leading underscore from .lib\n");
1393 fprintf (file, " -k Kill @<n> from exported names\n");
1394 fprintf (file, " --nodelete Keep temp files.\n");
1395 exit (status);
1396 }
1397
1398 static struct option long_options[] =
1399 {
1400 {"nodelete", no_argument, NULL,'n'},
1401 {"dllname", required_argument, NULL,'D'},
1402 {"output-exp", required_argument, NULL, 'e'},
1403 {"output-lib", required_argument, NULL, 'l'},
1404 {"def", required_argument, NULL, 'd'},
1405 {"underscore", no_argument, NULL, 'u'},
1406 {"killat", no_argument, NULL, 'k'},
1407 {"help", no_argument, NULL, 'h'},
1408 {"machine", required_argument, NULL, 'm'},
1409 {"rva", required_argument, NULL, 'r'},
1410 /* {"image-base", required_argument, NULL, 'i'},*/
1411 {"base-file", required_argument, NULL, 'b'},
1412 0
1413 };
1414
1415
1416
1417 int
1418 main (ac, av)
1419 int ac;
1420 char **av;
1421 {
1422 int c;
1423 char *firstarg = 0;
1424 program_name = av[0];
1425 oav = av;
1426
1427 while ((c = getopt_long (ac, av, "D:l:e:nr:kvbuh?m:yd:", long_options, 0)) != EOF)
1428 {
1429 switch (c)
1430 {
1431 case 'D':
1432 dll_name = optarg;
1433 break;
1434 case 'l':
1435 imp_name = optarg;
1436 break;
1437 case 'e':
1438 exp_name = optarg;
1439 break;
1440 case 'h':
1441 case '?':
1442 usage (stderr, 0);
1443 break;
1444 case 'm':
1445 mname = optarg;
1446 break;
1447 case 'v':
1448 verbose = 1;
1449 break;
1450 case 'y':
1451 yydebug = 1;
1452 break;
1453 case 'u':
1454 suckunderscore = 1;
1455 break;
1456 case 'k':
1457 killat = 1;
1458 break;
1459 case 'd':
1460 def_file = optarg;
1461 break;
1462 case 'n':
1463 dontdeltemps++;
1464 break;
1465 case 'b':
1466 base_file = fopen (optarg, "r");
1467 if (!base_file)
1468 {
1469 fprintf (stderr, "%s: Unable to open base-file %s\n",
1470 av[0],
1471 optarg);
1472 exit (1);
1473 }
1474 break;
1475 default:
1476 usage (stderr, 1);
1477 }
1478 }
1479
1480
1481 for (i = 0; mtable[i].type; i++)
1482 {
1483 if (strcmp (mtable[i].type, mname) == 0)
1484 break;
1485 }
1486
1487 if (!mtable[i].type)
1488 {
1489 fprintf (stderr, "Machine not supported\n");
1490 exit (1);
1491 }
1492 machine = i;
1493
1494
1495 if (!dll_name && exp_name)
1496 {
1497 char len = strlen (exp_name) + 5;
1498 dll_name = xmalloc (len);
1499 strcpy (dll_name, exp_name);
1500 strcat (dll_name, ".dll");
1501 }
1502 workout_prefix ();
1503
1504
1505 if (def_file)
1506 {
1507 process_def_file (def_file);
1508 }
1509 while (optind < ac)
1510 {
1511 if (!firstarg)
1512 firstarg = av[optind];
1513 scan_obj_file (av[optind]);
1514 optind++;
1515 }
1516
1517
1518 mangle_defs ();
1519
1520 if (exp_name)
1521 gen_exp_file ();
1522 if (imp_name)
1523 gen_lib_file ();
1524
1525 return 0;
1526 }
1527
This page took 0.060158 seconds and 4 git commands to generate.