* debug.c (debug_make_undefined_tagged_type): Make sure we are
[deliverable/binutils-gdb.git] / binutils / dlltool.c
... / ...
CommitLineData
1#define show_allnames 0
2
3/* dlltool.c -- tool to generate stuff for PE style DLLs
4 Copyright (C) 1995 Free Software Foundation, Inc.
5
6 This file is part of GNU Binutils.
7
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.
12
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.
17
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. */
21
22
23/*
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.
26 (eg, Windows NT)
27
28 A DLL contains an export table which contains the information
29 which the runtime loader needs to tie up references from a
30 referencing program.
31
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.
36
37 A DEF file contains any number of the following commands:
38
39
40 NAME <name> [ , <base> ]
41 The result is going to be <name>.EXE
42
43 LIBRARY <name> [ , <base> ]
44 The result is going to be <name>.DLL
45
46 EXPORTS ( <name1> [ = <name2> ] [ @ <integer> ] [ NONAME ] [CONSTANT] ) *
47 Declares name1 as an exported symbol from the
48 DLL, with optional ordinal number <integer>
49
50 IMPORTS ( [ <name> = ] <name> . <name> ) *
51 Ignored for compatibility
52
53 DESCRIPTION <string>
54 Puts <string> into output .exp file in the .rdata section
55
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.
60
61 [CODE|DATA] <attr>+
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
66 upon it.
67
68
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>
71 in a .DEF file.
72
73
74
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
77 supplied argument.
78
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.
82
83
84
85 Example:
86
87 file1.c:
88 asm (".section .drectve");
89 asm (".ascii \"-export:adef\"");
90
91 adef(char *s)
92 {
93 printf("hello from the dll %s\n",s);
94 }
95
96 bdef(char *s)
97 {
98 printf("hello from the dll and the other entry point %s\n",s);
99 }
100
101 file2.c:
102 asm (".section .drectve");
103 asm (".ascii \"-export:cdef\"");
104 asm (".ascii \"-export:ddef\"");
105 cdef(char *s)
106 {
107 printf("hello from the dll %s\n",s);
108 }
109
110 ddef(char *s)
111 {
112 printf("hello from the dll and the other entry point %s\n",s);
113 }
114
115 printf()
116 {
117 return 9;
118 }
119
120 main.c
121
122 main()
123 {
124 cdef();
125 }
126
127 thedll.def
128
129 LIBRARY thedll
130 HEAPSIZE 0x40000, 0x2000
131 EXPORTS bdef @ 20
132 cdef @ 30 NONAME
133
134 SECTIONS donkey READ WRITE
135 aardvark EXECUTE
136
137
138 # compile up the parts of the dll
139
140 gcc -c file1.c
141 gcc -c file2.c
142
143 # put them in a library (you don't have to, you
144 # could name all the .os on the dlltool line)
145
146 ar qcv thedll.in file1.o file2.o
147 ranlib thedll.in
148
149 # run this tool over the library and the def file
150 ./dlltool --def thedll.def --output-exp thedll.o --output-lib thedll.a
151
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
154
155 # build the mainline
156 gcc -c themain.c
157
158 # link the executable with the import library
159 ld -e main -Tthemain.ld -o themain.exe themain.o thedll.a
160
161 */
162
163/* .idata section description
164
165 The .idata section is the import table. It is a collection of several
166 subsections used to keep the pieces for each dll together: .idata$[234567].
167 IE: Each dll's .idata$2's are catenated together, each .idata$3's, etc.
168
169 .idata$2 = Import Directory Table
170 = array of IMAGE_IMPORT_DESCRIPTOR's.
171
172 DWORD Characteristics; - pointer to .idata$4
173 DWORD TimeDateStamp; - currently always 0
174 DWORD ForwarderChain; - currently always 0
175 DWORD Name; - pointer to dll's name
176 PIMAGE_THUNK_DATA FirstThunk; - pointer to .idata$5
177
178 .idata$3 = null terminating entry for .idata$2.
179
180 .idata$4 = Import Lookup Table
181 = array of array of pointers to hint name table.
182 There is one for each dll being imported from, and each dll's set is
183 terminated by a trailing NULL.
184
185 .idata$5 = Import Address Table
186 = array of array of pointers to hint name table.
187 There is one for each dll being imported from, and each dll's set is
188 terminated by a trailing NULL.
189 Initially, this table is identical to the Import Lookup Table. However,
190 at load time, the loader overwrites the entries with the address of the
191 function.
192
193 .idata$6 = Hint Name Table
194 = Array of { short, asciz } entries, one for each imported function.
195 The `short' is the function's ordinal number.
196
197 .idata$7 = dll name (eg: "kernel32.dll"). (.idata$6 for ppc)
198*/
199
200#define PAGE_SIZE 4096
201#define PAGE_MASK (-PAGE_SIZE)
202#include "bfd.h"
203#include "libiberty.h"
204#include "bucomm.h"
205#include "getopt.h"
206#include "demangle.h"
207#include <ctype.h>
208#ifdef HAVE_SYS_WAIT_H
209#include <sys/wait.h>
210#else
211#ifndef WIFEXITED
212#define WIFEXITED(w) (((w)&0377) == 0)
213#endif
214#ifndef WIFSIGNALED
215#define WIFSIGNALED(w) (((w)&0377) != 0177 && ((w)&~0377) == 0)
216#endif
217#ifndef WTERMSIG
218#define WTERMSIG(w) ((w) & 0177)
219#endif
220#ifndef WEXITSTATUS
221#define WEXITSTATUS(w) (((w) >> 8) & 0377)
222#endif
223#endif
224
225
226
227char *as_name = "as";
228
229static int no_idata4;
230static int no_idata5;
231static char *exp_name;
232static char *imp_name;
233static char *head_label;
234static char *imp_name_lab;
235static char *dll_name;
236
237static int add_indirect = 0;
238static int add_underscore = 0;
239static int dontdeltemps = 0;
240
241int yyparse();
242int yydebug;
243static char *def_file;
244
245static char *program_name;
246char *strrchr ();
247char *strdup ();
248
249static int machine;
250int killat;
251static int verbose;
252FILE *output_def;
253FILE *base_file;
254
255#ifdef DLLTOOL_ARM
256static char *mname = "arm";
257#endif
258
259#ifdef DLLTOOL_I386
260static char *mname = "i386";
261#endif
262
263#ifdef DLLTOOL_PPC
264static char *mname = "ppc";
265#endif
266
267#define PATHMAX 250 /* What's the right name for this ? */
268
269/* This bit of assemly does jmp * ....
270s set how_jtab_roff to mark where the 32bit abs branch should go */
271unsigned char i386_jtab[] = { 0xff, 0x25, 0x00, 0x00, 0x00, 0x00, 0x90, 0x90};
272
273
274unsigned char arm_jtab[] = { 0x00, 0xc0, 0x9f, 0xe5,
275 0x00, 0xf0, 0x9c, 0xe5,
276 0, 0, 0, 0};
277
278/* This is the glue sequence for PowerPC PE. There is a */
279/* tocrel16-tocdefn reloc against the first instruction. */
280/* We also need a IMGLUE reloc against the glue function */
281/* to restore the toc saved by the third instruction in */
282/* the glue. */
283unsigned char ppc_jtab[] =
284{
285 0x00, 0x00, 0x62, 0x81, /* lwz r11,0(r2) */
286 /* Reloc TOCREL16 __imp_xxx */
287 0x00, 0x00, 0x8B, 0x81, /* lwz r12,0(r11) */
288 0x04, 0x00, 0x41, 0x90, /* stw r2,4(r1) */
289 0xA6, 0x03, 0x89, 0x7D, /* mtctr r12 */
290 0x04, 0x00, 0x4B, 0x80, /* lwz r2,4(r11) */
291 0x20, 0x04, 0x80, 0x4E /* bctr */
292};
293
294/* the glue instruction, picks up the toc from the stw in */
295/* the above code: "lwz r2,4(r1)" */
296bfd_vma ppc_glue_insn = 0x80410004;
297
298
299char outfile[PATHMAX];
300struct mac
301 {
302 char *type;
303 char *how_byte;
304 char *how_short;
305 char *how_long;
306 char *how_asciz;
307 char *how_comment;
308 char *how_jump;
309 char *how_global;
310 char *how_space;
311 char *how_align_short;
312 char *how_align_long;
313 char *how_bfd_target;
314 enum bfd_architecture how_bfd_arch;
315 unsigned char *how_jtab;
316 int how_jtab_size; /* size of the jtab entry */
317 int how_jtab_roff; /* offset into it for the ind 32 reloc into idata 5 */
318 }
319mtable[]
320=
321{
322 {
323#define MARM 0
324 "arm", ".byte", ".short", ".long", ".asciz", "@",
325 "ldr\tip,[pc]\n\tldr\tpc,[ip]\n\t.long",
326 ".global", ".space", ".align\t2",".align\t4","pe-arm-little", bfd_arch_arm,
327 arm_jtab, sizeof(arm_jtab),8
328 }
329 ,
330 {
331#define M386 1
332 "i386", ".byte", ".short", ".long", ".asciz", "#", "jmp *", ".global", ".space", ".align\t2",".align\t4","pe-i386",bfd_arch_i386,
333 i386_jtab,sizeof(i386_jtab),2,
334 }
335 ,
336 {
337#define MPPC 2
338 "ppc", ".byte", ".short", ".long", ".asciz", "#", "jmp *", ".global", ".space", ".align\t2",".align\t4","pe-powerpcle",bfd_arch_powerpc,
339 ppc_jtab,sizeof(ppc_jtab),0,
340 }
341 ,
342{ 0}
343};
344
345
346char *
347rvaafter (machine)
348 int machine;
349{
350 switch (machine)
351 {
352 case MARM:
353 return "";
354 case M386:
355 return "";
356 case MPPC:
357 return "";
358 }
359return "";
360}
361
362char *
363rvabefore (machine)
364 int machine;
365{
366 switch (machine)
367 {
368 case MARM:
369 return ".rva\t";
370 case M386:
371 return ".rva\t";
372 case MPPC:
373 return ".rva\t";
374 }
375return "";
376}
377
378char *
379asm_prefix (machine)
380int machine;
381{
382 switch (machine)
383 {
384 case MARM:
385 return "";
386 case M386:
387 return "_";
388 case MPPC:
389 return "";
390 }
391return "";
392}
393#define ASM_BYTE mtable[machine].how_byte
394#define ASM_SHORT mtable[machine].how_short
395#define ASM_LONG mtable[machine].how_long
396#define ASM_TEXT mtable[machine].how_asciz
397#define ASM_C mtable[machine].how_comment
398#define ASM_JUMP mtable[machine].how_jump
399#define ASM_GLOBAL mtable[machine].how_global
400#define ASM_SPACE mtable[machine].how_space
401#define ASM_ALIGN_SHORT mtable[machine].how_align_short
402#define ASM_RVA_BEFORE rvabefore(machine)
403#define ASM_RVA_AFTER rvaafter(machine)
404#define ASM_PREFIX asm_prefix(machine)
405#define ASM_ALIGN_LONG mtable[machine].how_align_long
406#define HOW_BFD_TARGET 0 /* always default*/
407#define HOW_BFD_ARCH mtable[machine].how_bfd_arch
408#define HOW_JTAB mtable[machine].how_jtab
409#define HOW_JTAB_SIZE mtable[machine].how_jtab_size
410#define HOW_JTAB_ROFF mtable[machine].how_jtab_roff
411static char **oav;
412
413
414FILE *yyin; /* communications with flex */
415extern int linenumber;
416void
417process_def_file (name)
418 char *name;
419{
420 FILE *f = fopen (name, FOPEN_RT);
421 if (!f)
422 {
423 fprintf (stderr, "%s: Can't open def file %s\n", program_name, name);
424 exit (1);
425 }
426
427 yyin = f;
428
429 yyparse ();
430}
431
432/**********************************************************************/
433
434/* Communications with the parser */
435
436
437typedef struct dlist
438{
439 char *text;
440 struct dlist *next;
441}
442dlist_type;
443
444typedef struct export
445 {
446 char *name;
447 char *internal_name;
448 int ordinal;
449 int constant;
450 int noname;
451 int hint;
452 struct export *next;
453 }
454export_type;
455
456static char *d_name; /* Arg to NAME or LIBRARY */
457static int d_nfuncs; /* Number of functions exported */
458static int d_named_nfuncs; /* Number of named functions exported */
459static int d_low_ord; /* Lowest ordinal index */
460static int d_high_ord; /* Highest ordinal index */
461static export_type *d_exports; /*list of exported functions */
462static export_type **d_exports_lexically; /* vector of exported functions in alpha order */
463static dlist_type *d_list; /* Descriptions */
464static dlist_type *a_list; /* Stuff to go in directives */
465
466static int d_is_dll;
467static int d_is_exe;
468
469int
470yyerror ()
471{
472 fprintf (stderr, "%s: Syntax error in def file %s:%d\n",
473 program_name, def_file, linenumber);
474 return 0;
475}
476
477void
478def_exports (name, internal_name, ordinal, noname, constant)
479 char *name;
480 char *internal_name;
481 int ordinal;
482 int noname;
483 int constant;
484{
485 struct export *p = (struct export *) xmalloc (sizeof (*p));
486
487 p->name = name;
488 p->internal_name = internal_name ? internal_name : name;
489 p->ordinal = ordinal;
490 p->constant = constant;
491 p->noname = noname;
492 p->next = d_exports;
493 d_exports = p;
494 d_nfuncs++;
495}
496
497
498void
499def_name (name, base)
500 char *name;
501 int base;
502{
503 if (verbose)
504 fprintf (stderr, "%s NAME %s base %x\n", program_name, name, base);
505 if (d_is_dll)
506 {
507 fprintf (stderr, "Can't have LIBRARY and NAME\n");
508 }
509 d_name = name;
510 d_is_exe = 1;
511}
512
513void
514def_library (name, base)
515 char *name;
516 int base;
517{
518 if (verbose)
519 printf ("%s: LIBRARY %s base %x\n", program_name, name, base);
520 if (d_is_exe)
521 {
522 fprintf (stderr, "%s: Can't have LIBRARY and NAME\n", program_name);
523 }
524 d_name = name;
525 d_is_dll = 1;
526}
527
528void
529def_description (desc)
530 char *desc;
531{
532 dlist_type *d = (dlist_type *) xmalloc (sizeof (dlist_type));
533 d->text = strdup (desc);
534 d->next = d_list;
535 d_list = d;
536}
537
538void
539new_directive (dir)
540 char *dir;
541{
542 dlist_type *d = (dlist_type *) xmalloc (sizeof (dlist_type));
543 d->text = strdup (dir);
544 d->next = a_list;
545 a_list = d;
546}
547
548void
549def_stacksize (reserve, commit)
550 int reserve;
551 int commit;
552{
553 char b[200];
554 if (commit > 0)
555 sprintf (b, "-stack 0x%x,0x%x ", reserve, commit);
556 else
557 sprintf (b, "-stack 0x%x ", reserve);
558 new_directive (strdup (b));
559}
560
561void
562def_heapsize (reserve, commit)
563 int reserve;
564 int commit;
565{
566 char b[200];
567 if (commit > 0)
568 sprintf (b, "-heap 0x%x,0x%x ", reserve, commit);
569 else
570 sprintf (b, "-heap 0x%x ", reserve);
571 new_directive (strdup (b));
572}
573
574
575void
576def_import (internal, module, entry)
577 char *internal;
578 char *module;
579 char *entry;
580{
581 if (verbose)
582 fprintf (stderr, "%s: IMPORTS are ignored", program_name);
583}
584
585void
586def_version (major, minor)
587int major;
588int minor;
589{
590 printf ("VERSION %d.%d\n", major, minor);
591}
592
593
594void
595def_section (name, attr)
596 char *name;
597 int attr;
598{
599 char buf[200];
600 char atts[5];
601 char *d = atts;
602 if (attr & 1)
603 *d++ = 'R';
604
605 if (attr & 2)
606 *d++ = 'W';
607 if (attr & 4)
608 *d++ = 'X';
609 if (attr & 8)
610 *d++ = 'S';
611 *d++ = 0;
612 sprintf (buf, "-attr %s %s", name, atts);
613 new_directive (strdup (buf));
614}
615void
616def_code (attr)
617 int attr;
618{
619
620 def_section ("CODE", attr);
621}
622
623void
624def_data (attr)
625 int attr;
626{
627 def_section ("DATA", attr);
628}
629
630
631/**********************************************************************/
632
633void
634run (what, args)
635 char *what;
636 char *args;
637{
638 char *s;
639 int pid;
640 int i;
641 char **argv;
642 extern char **environ;
643 if (verbose)
644 fprintf (stderr, "%s %s\n", what, args);
645
646 /* Count the args */
647 i = 0;
648 for (s = args; *s; s++)
649 if (*s == ' ')
650 i++;
651 i++;
652 argv = alloca (sizeof (char *) * (i + 3));
653 i = 0;
654 argv[i++] = what;
655 s = args;
656 while (1)
657 {
658 argv[i++] = s;
659 while (*s != ' ' && *s != 0)
660 s++;
661 if (*s == 0)
662 break;
663 *s++ = 0;
664 }
665 argv[i++] = 0;
666
667
668 pid = vfork ();
669
670 if (pid == 0)
671 {
672 execvp (what, argv);
673 fprintf (stderr, "%s: can't exec %s\n", program_name, what);
674 exit (1);
675 }
676 else if (pid == -1)
677 {
678 extern int errno;
679 fprintf (stderr, "%s: vfork failed, %d\n", program_name, errno);
680 exit (1);
681 }
682 else
683 {
684 int status;
685 waitpid (pid, &status, 0);
686 if (status)
687 {
688 if (WIFSIGNALED (status))
689 {
690 fprintf (stderr, "%s: %s %s terminated with signal %d\n",
691 program_name, what, args, WTERMSIG (status));
692 exit (1);
693 }
694
695 if (WIFEXITED (status))
696 {
697 fprintf (stderr, "%s: %s %s terminated with exit status %d\n",
698 program_name, what, args, WEXITSTATUS (status));
699 exit (1);
700 }
701 }
702 }
703}
704
705/* read in and block out the base relocations */
706static void
707basenames (abfd)
708 bfd *abfd;
709{
710
711
712
713
714}
715
716void
717scan_open_obj_file (abfd)
718 bfd *abfd;
719{
720 /* Look for .drectve's */
721 asection *s = bfd_get_section_by_name (abfd, ".drectve");
722 if (s)
723 {
724 int size = bfd_get_section_size_before_reloc (s);
725 char *buf = xmalloc (size);
726 char *p;
727 char *e;
728 bfd_get_section_contents (abfd, s, buf, 0, size);
729 if (verbose)
730 fprintf (stderr, "%s: Sucking in info from %s\n",
731 program_name,
732 bfd_get_filename (abfd));
733
734 /* Search for -export: strings */
735 p = buf;
736 e = buf + size;
737 while (p < e)
738 {
739 if (p[0] == '-'
740 && strncmp (p, "-export:", 8) == 0)
741 {
742 char *name;
743 char *c;
744 p += 8;
745 name = p;
746 while (*p != ' ' && *p != '-' && p < e)
747 p++;
748 c = xmalloc (p - name + 1);
749 memcpy (c, name, p - name);
750 c[p - name] = 0;
751 def_exports (c, 0, -1, 0);
752 }
753 else
754 p++;
755 }
756 free (buf);
757 }
758
759 basenames (abfd);
760
761 if (verbose)
762 fprintf (stderr, "%s: Done readin\n",
763 program_name);
764
765}
766
767
768void
769scan_obj_file (filename)
770 char *filename;
771{
772 bfd *f = bfd_openr (filename, 0);
773
774 if (!f)
775 {
776 fprintf (stderr, "%s: Unable to open object file %s\n",
777 program_name,
778 filename);
779 exit (1);
780 }
781 if (bfd_check_format (f, bfd_archive))
782 {
783 bfd *arfile = bfd_openr_next_archived_file (f, 0);
784 while (arfile)
785 {
786 if (bfd_check_format (arfile, bfd_object))
787 scan_open_obj_file (arfile);
788 bfd_close (arfile);
789 arfile = bfd_openr_next_archived_file (f, arfile);
790 }
791 }
792 else if (bfd_check_format (f, bfd_object))
793 {
794 scan_open_obj_file (f);
795 }
796
797 bfd_close (f);
798}
799
800/**********************************************************************/
801
802
803
804void
805dump_def_info (f)
806 FILE *f;
807{
808 int i;
809 export_type *exp;
810 fprintf (f, "%s ", ASM_C);
811 for (i = 0; oav[i]; i++)
812 fprintf (f, "%s ", oav[i]);
813 fprintf (f, "\n");
814 for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
815 {
816 fprintf (f, "%s %d = %s %s @ %d %s%s\n",
817 ASM_C,
818 i,
819 exp->name,
820 exp->internal_name,
821 exp->ordinal,
822 exp->noname ? "NONAME " : "",
823 exp->constant ? "CONSTANT" : "");
824 }
825}
826/* Generate the .exp file */
827
828int
829sfunc (a, b)
830 long *a;
831 long *b;
832{
833 return *a - *b;
834}
835
836
837
838static void
839flush_page (f, need, page_addr, on_page)
840 FILE *f;
841 int *need;
842 int page_addr;
843 int on_page;
844{
845 int i;
846
847 /* Flush this page */
848 fprintf (f, "\t%s\t0x%08x\t%s Starting RVA for chunk\n",
849 ASM_LONG,
850 page_addr,
851 ASM_C);
852 fprintf (f, "\t%s\t0x%x\t%s Size of block\n",
853 ASM_LONG,
854 (on_page * 2) + (on_page & 1) * 2 + 8,
855 ASM_C);
856 for (i = 0; i < on_page; i++)
857 {
858 fprintf (f, "\t%s\t0x%x\n", ASM_SHORT, (need[i] - page_addr) | 0x3000);
859 }
860 /* And padding */
861 if (on_page & 1)
862 fprintf (f, "\t%s\t0x%x\n", ASM_SHORT, 0 | 0x0000);
863
864}
865
866
867void
868gen_def_file ()
869{
870 int i;
871 export_type *exp;
872
873 fprintf (output_def, ";");
874 for (i = 0; oav[i]; i++)
875 fprintf (output_def, " %s", oav[i]);
876
877 fprintf (output_def, "\nEXPORTS\n");
878
879 for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
880 {
881 char *quote = strchr (exp->name, '.') ? "\"" : "";
882 fprintf (output_def, "\t%s%s%s @ %d%s ; %s\n",
883 quote,
884 exp->name,
885 quote,
886 exp->ordinal,
887 exp->noname ? " NONAME" : "",
888 cplus_demangle (exp->internal_name, DMGL_ANSI | DMGL_PARAMS));
889 }
890}
891void
892gen_exp_file ()
893{
894 FILE *f;
895 int i;
896 export_type *exp;
897 dlist_type *dl;
898
899
900 sprintf (outfile, "t%s", exp_name);
901
902 if (verbose)
903 fprintf (stderr, "%s: Generate exp file %s\n",
904 program_name, exp_name);
905
906 f = fopen (outfile, FOPEN_WT);
907 if (!f)
908 {
909 fprintf (stderr, "%s: Unable to open output file %s\n", program_name, outfile);
910 exit (1);
911 }
912 if (verbose)
913 {
914 fprintf (stderr, "%s: Opened file %s\n",
915 program_name, outfile);
916 }
917
918 dump_def_info (f);
919 if (d_exports)
920 {
921 fprintf (f, "\t.section .edata\n\n");
922 fprintf (f, "\t%s 0 %s Allways 0\n", ASM_LONG, ASM_C);
923 fprintf (f, "\t%s 0x%x %s Time and date\n", ASM_LONG, time(0),ASM_C);
924 fprintf (f, "\t%s 0 %s Major and Minor version\n", ASM_LONG, ASM_C);
925 fprintf (f, "\t%sname%s %s Ptr to name of dll\n", ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C);
926 fprintf (f, "\t%s %d %s Starting ordinal of exports\n", ASM_LONG, d_low_ord, ASM_C);
927
928
929 fprintf (f, "\t%s %d %s Number of functions\n", ASM_LONG, d_high_ord - d_low_ord + 1, ASM_C);
930 fprintf(f,"\t%s named funcs %d, low ord %d, high ord %d\n",
931 ASM_C,
932 d_named_nfuncs, d_low_ord, d_high_ord);
933 fprintf (f, "\t%s %d %s Number of names\n", ASM_LONG,
934 show_allnames ? d_high_ord - d_low_ord + 1 : d_named_nfuncs, ASM_C);
935 fprintf (f, "\t%safuncs%s %s Address of functions\n", ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C);
936
937 fprintf (f, "\t%sanames%s %s Address of Name Pointer Table\n",
938 ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C);
939
940 fprintf (f, "\t%sanords%s %s Address of ordinals\n", ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C);
941
942 fprintf (f, "name: %s \"%s\"\n", ASM_TEXT, dll_name);
943
944
945 fprintf(f,"%s Export address Table\n", ASM_C);
946 fprintf(f,"\t%s\n", ASM_ALIGN_LONG);
947 fprintf (f, "afuncs:\n");
948 i = d_low_ord;
949
950 for (exp = d_exports; exp; exp = exp->next)
951 {
952 if (exp->ordinal != i)
953 {
954#if 0
955 fprintf (f, "\t%s\t%d\t%s %d..%d missing\n",
956 ASM_SPACE,
957 (exp->ordinal - i) * 4,
958 ASM_C,
959 i, exp->ordinal - 1);
960 i = exp->ordinal;
961#endif
962 while (i < exp->ordinal)
963 {
964 fprintf(f,"\t%s\t0\n", ASM_LONG);
965 i++;
966 }
967 }
968 fprintf (f, "\t%s%s%s%s\t%s %d\n", ASM_RVA_BEFORE,
969 ASM_PREFIX,
970 exp->internal_name, ASM_RVA_AFTER, ASM_C, exp->ordinal);
971 i++;
972 }
973
974 fprintf (f,"%s Export Name Pointer Table\n", ASM_C);
975 fprintf (f, "anames:\n");
976
977 for (i = 0; (exp = d_exports_lexically[i]); i++)
978 {
979 if (!exp->noname || show_allnames)
980 fprintf (f, "\t%sn%d%s\n", ASM_RVA_BEFORE, exp->ordinal, ASM_RVA_AFTER);
981 }
982
983 fprintf (f,"%s Export Oridinal Table\n", ASM_C);
984 fprintf (f, "anords:\n");
985 for (i = 0; (exp = d_exports_lexically[i]); i++)
986 {
987 if (!exp->noname || show_allnames)
988 fprintf (f, "\t%s %d\n", ASM_SHORT, exp->ordinal - d_low_ord);
989 }
990
991 fprintf(f,"%s Export Name Table\n", ASM_C);
992 for (i = 0; (exp = d_exports_lexically[i]); i++)
993 if (!exp->noname || show_allnames)
994 fprintf (f, "n%d: %s \"%s\"\n", exp->ordinal, ASM_TEXT, exp->name);
995
996 if (a_list)
997 {
998 fprintf (f, "\t.section .drectve\n");
999 for (dl = a_list; dl; dl = dl->next)
1000 {
1001 fprintf (f, "\t%s\t\"%s\"\n", ASM_TEXT, dl->text);
1002 }
1003 }
1004 if (d_list)
1005 {
1006 fprintf (f, "\t.section .rdata\n");
1007 for (dl = d_list; dl; dl = dl->next)
1008 {
1009 char *p;
1010 int l;
1011 /* We dont output as ascii 'cause there can
1012 be quote characters in the string */
1013
1014 l = 0;
1015 for (p = dl->text; *p; p++)
1016 {
1017 if (l == 0)
1018 fprintf (f, "\t%s\t", ASM_BYTE);
1019 else
1020 fprintf (f, ",");
1021 fprintf (f, "%d", *p);
1022 if (p[1] == 0)
1023 {
1024 fprintf (f, ",0\n");
1025 break;
1026 }
1027 if (++l == 10)
1028 {
1029 fprintf (f, "\n");
1030 l = 0;
1031 }
1032 }
1033 }
1034 }
1035 }
1036
1037
1038 /* Add to the output file a way of getting to the exported names
1039 without using the import library. */
1040 if (add_indirect)
1041 {
1042 fprintf (f, "\t.section\t.rdata\n");
1043 for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
1044 if (!exp->noname || show_allnames)
1045 {
1046 fprintf (f, "\t%s\t__imp_%s\n", ASM_GLOBAL, exp->name);
1047 fprintf (f, "__imp_%s:\n", exp->name);
1048 fprintf (f, "\t%s\t%s\n", ASM_LONG, exp->name);
1049 }
1050 }
1051
1052 /* Dump the reloc section if a base file is provided */
1053 if (base_file)
1054 {
1055 int addr;
1056 long need[PAGE_SIZE];
1057 long page_addr;
1058 int numbytes;
1059 int num_entries;
1060 long *copy;
1061 int j;
1062 int on_page;
1063 fprintf (f, "\t.section\t.init\n");
1064 fprintf (f, "lab:\n");
1065
1066 fseek (base_file, 0, SEEK_END);
1067 numbytes = ftell (base_file);
1068 fseek (base_file, 0, SEEK_SET);
1069 copy = malloc (numbytes);
1070 fread (copy, 1, numbytes, base_file);
1071 num_entries = numbytes / sizeof (long);
1072
1073
1074 fprintf (f, "\t.section\t.reloc\n");
1075 if (num_entries)
1076 {
1077
1078 int src;
1079 int dst = 0;
1080 int last = -1;
1081 qsort (copy, num_entries, sizeof (long), sfunc);
1082 /* Delete duplcates */
1083 for (src = 0; src < num_entries; src++)
1084 {
1085 if (last != copy[src])
1086 last = copy[dst++] = copy[src];
1087 }
1088 num_entries = dst;
1089 addr = copy[0];
1090 page_addr = addr & PAGE_MASK; /* work out the page addr */
1091 on_page = 0;
1092 for (j = 0; j < num_entries; j++)
1093 {
1094 addr = copy[j];
1095 if ((addr & PAGE_MASK) != page_addr)
1096 {
1097 flush_page (f, need, page_addr, on_page);
1098 on_page = 0;
1099 page_addr = addr & PAGE_MASK;
1100 }
1101 need[on_page++] = addr;
1102 }
1103 flush_page (f, need, page_addr, on_page);
1104
1105/* fprintf (f, "\t%s\t0,0\t%s End\n", ASM_LONG, ASM_C);*/
1106 }
1107 }
1108
1109 fclose (f);
1110
1111 /* assemble the file */
1112 sprintf (outfile, "-o %s t%s", exp_name, exp_name);
1113 run (as_name, outfile);
1114 if (dontdeltemps == 0)
1115 {
1116 sprintf (outfile, "t%s", exp_name);
1117 unlink (outfile);
1118 }
1119}
1120
1121static char *
1122xlate (char *name)
1123{
1124 if (add_underscore)
1125 {
1126 char *copy = malloc (strlen (name) + 2);
1127 copy[0] = '_';
1128 strcpy (copy + 1, name);
1129 name = copy;
1130 }
1131
1132 if (killat)
1133 {
1134 char *p;
1135 p = strchr (name, '@');
1136 if (p)
1137 *p = 0;
1138 }
1139 return name;
1140}
1141
1142/**********************************************************************/
1143
1144static void dump_iat (f, exp)
1145FILE *f;
1146export_type *exp;
1147{
1148 if (exp->noname && !show_allnames )
1149 {
1150 fprintf (f, "\t%s\t0x%08x\n",
1151 ASM_LONG,
1152 exp->ordinal | 0x80000000); /* hint or orindal ?? */
1153 }
1154 else
1155 {
1156 fprintf (f, "\t%sID%d%s\n", ASM_RVA_BEFORE,
1157 exp->ordinal,
1158 ASM_RVA_AFTER);
1159 }
1160}
1161
1162
1163
1164typedef struct
1165{
1166 int id;
1167 const char *name;
1168 int flags;
1169 int align;
1170 asection *sec;
1171 asymbol *sym;
1172 asymbol **sympp;
1173 int size;
1174 unsigned char *data;
1175} sinfo;
1176
1177
1178#ifndef DLLTOOL_PPC
1179
1180#define TEXT 0
1181#define DATA 1
1182#define BSS 2
1183#define IDATA7 3
1184#define IDATA5 4
1185#define IDATA4 5
1186#define IDATA6 6
1187#define PDATA 7
1188#define RDATA 8
1189
1190#define NSECS 7
1191
1192
1193static sinfo secdata[NSECS] =
1194{
1195 { TEXT, ".text", SEC_CODE | SEC_HAS_CONTENTS, 3},
1196 { DATA, ".data", SEC_DATA, 2},
1197 { BSS, ".bss", 0, 2},
1198 { IDATA7, ".idata$7", SEC_HAS_CONTENTS, 2},
1199 { IDATA5, ".idata$5", SEC_HAS_CONTENTS, 2},
1200 { IDATA4, ".idata$4", SEC_HAS_CONTENTS, 2},
1201 { IDATA6, ".idata$6", SEC_HAS_CONTENTS, 1}
1202};
1203
1204#else
1205
1206/* Sections numbered to make the order the same as other PowerPC NT */
1207/* compilers. This also keeps funny alignment thingies from happening. */
1208#define TEXT 0
1209#define PDATA 1
1210#define RDATA 2
1211#define IDATA5 3
1212#define IDATA4 4
1213#define IDATA6 5
1214#define IDATA7 6
1215#define DATA 7
1216#define BSS 8
1217
1218#define NSECS 9
1219
1220static sinfo secdata[NSECS] =
1221{
1222 { TEXT, ".text", SEC_CODE | SEC_HAS_CONTENTS, 3},
1223 { PDATA, ".pdata", SEC_HAS_CONTENTS, 2},
1224 { RDATA, ".rdata", SEC_HAS_CONTENTS, 2},
1225 { IDATA5, ".idata$5", SEC_HAS_CONTENTS, 2},
1226 { IDATA4, ".idata$4", SEC_HAS_CONTENTS, 2},
1227 { IDATA6, ".idata$6", SEC_HAS_CONTENTS, 1},
1228 { IDATA7, ".idata$7", SEC_HAS_CONTENTS, 2},
1229 { DATA, ".data", SEC_DATA, 2},
1230 { BSS, ".bss", 0, 2}
1231};
1232
1233#endif
1234
1235/*
1236This is what we're trying to make
1237
1238 .text
1239 .global _GetFileVersionInfoSizeW@8
1240 .global __imp_GetFileVersionInfoSizeW@8
1241_GetFileVersionInfoSizeW@8:
1242 jmp * __imp_GetFileVersionInfoSizeW@8
1243 .section .idata$7 # To force loading of head
1244 .long __version_a_head
1245# Import Address Table
1246 .section .idata$5
1247__imp_GetFileVersionInfoSizeW@8:
1248 .rva ID2
1249
1250# Import Lookup Table
1251 .section .idata$4
1252 .rva ID2
1253# Hint/Name table
1254 .section .idata$6
1255ID2: .short 2
1256 .asciz "GetFileVersionInfoSizeW"
1257
1258
1259For the PowerPC, here's the variation on the above scheme:
1260
1261# Rather than a simple "jmp *", the code to get to the dll function
1262# looks like:
1263 .text
1264 lwz r11,[tocv]__imp_function_name(r2)
1265# RELOC: 00000000 TOCREL16,TOCDEFN __imp_function_name
1266 lwz r12,0(r11)
1267 stw r2,4(r1)
1268 mtctr r12
1269 lwz r2,4(r11)
1270 bctr
1271*/
1272
1273static char *
1274make_label (prefix, name)
1275 const char *prefix;
1276 const char *name;
1277{
1278 int len = strlen (ASM_PREFIX) + strlen (prefix) + strlen (name);
1279 char *copy = xmalloc (len +1 );
1280 strcpy (copy, ASM_PREFIX);
1281 strcat (copy, prefix);
1282 strcat (copy, name);
1283 return copy;
1284}
1285
1286static bfd *
1287make_one_lib_file (exp, i)
1288 export_type *exp;
1289 int i;
1290{
1291 if (0)
1292 {
1293 FILE *f;
1294 char *prefix="d";
1295 sprintf (outfile, "%ss%d.s", prefix, i);
1296 f = fopen (outfile, FOPEN_WT);
1297 fprintf (f, "\t.text\n");
1298 fprintf (f, "\t%s\t%s%s\n", ASM_GLOBAL, ASM_PREFIX, exp->name);
1299 fprintf (f, "\t%s\t__imp_%s\n", ASM_GLOBAL, exp->name);
1300 fprintf (f, "%s%s:\n\t%s\t__imp_%s\n", ASM_PREFIX,
1301 exp->name, ASM_JUMP, exp->name);
1302
1303 fprintf (f, "\t.section\t.idata$7\t%s To force loading of head\n", ASM_C);
1304 fprintf (f, "\t%s\t%s\n", ASM_LONG, head_label);
1305
1306
1307 fprintf (f,"%s Import Address Table\n", ASM_C);
1308
1309 fprintf (f, "\t.section .idata$5\n");
1310 fprintf (f, "__imp_%s:\n", exp->name);
1311
1312 dump_iat (f, exp);
1313
1314 fprintf (f, "\n%s Import Lookup Table\n", ASM_C);
1315 fprintf (f, "\t.section .idata$4\n");
1316
1317 dump_iat (f, exp);
1318
1319 if(!exp->noname || show_allnames)
1320 {
1321 fprintf (f, "%s Hint/Name table\n", ASM_C);
1322 fprintf (f, "\t.section .idata$6\n");
1323 fprintf (f, "ID%d:\t%s\t%d\n", exp->ordinal, ASM_SHORT, exp->hint);
1324 fprintf (f, "\t%s\t\"%s\"\n", ASM_TEXT, xlate (exp->name));
1325 }
1326
1327 fclose (f);
1328
1329
1330 sprintf (outfile, "-o %ss%d.o %ss%d.s", prefix, i, prefix, i);
1331
1332 run (as_name, outfile);
1333
1334 }
1335 else
1336 {
1337
1338 bfd *abfd;
1339
1340 asymbol *exp_label;
1341 asymbol *iname;
1342 asymbol *iname_lab;
1343 asymbol **iname_lab_pp;
1344 asymbol **iname_pp;
1345
1346 /* Extra Symbols for PPC */
1347#ifdef DLLTOOL_PPC
1348#define EXTRA 2
1349#else
1350#define EXTRA 0
1351#endif
1352
1353 asymbol *function_name; /* ".." functionName */
1354 asymbol **fn_pp;
1355 asymbol *toc_symbol; /* The .toc symbol */
1356 asymbol **toc_pp;
1357
1358 /* one symbol for each section, 2 extra + a null */
1359 asymbol *ptrs[NSECS+3+EXTRA+1];
1360
1361 char *outname = xmalloc (10);
1362 int oidx = 0;
1363 sprintf (outname, "ds%d.o", i);
1364 abfd = bfd_openw (outname, HOW_BFD_TARGET);
1365 if (!abfd)
1366 {
1367 fprintf (stderr, "%s: bfd_open failed open output file %s\n",
1368 program_name, outname);
1369 exit (1);
1370 }
1371
1372 bfd_set_format (abfd, bfd_object);
1373 bfd_set_arch_mach (abfd, HOW_BFD_ARCH, 0);
1374
1375
1376 /* First make symbols for the sections */
1377 for (i = 0; i < NSECS; i++)
1378 {
1379 sinfo *si = secdata + i;
1380 if (si->id != i)
1381 abort();
1382 si->sec = bfd_make_section_old_way (abfd, si->name);
1383 bfd_set_section_flags (abfd,
1384 si->sec,
1385 si->flags);
1386
1387 bfd_set_section_alignment(abfd, si->sec, si->align);
1388 si->sec->output_section = si->sec;
1389 si->sym = bfd_make_empty_symbol(abfd);
1390 si->sym->name = si->sec->name;
1391 si->sym->section = si->sec;
1392 si->sym->flags = BSF_LOCAL;
1393 si->sym->value = 0;
1394 ptrs[oidx] = si->sym;
1395 si->sympp = ptrs + oidx;
1396
1397 oidx++;
1398 }
1399
1400 exp_label = bfd_make_empty_symbol(abfd);
1401 exp_label->name = make_label ("",exp->name);
1402
1403 /* On PowerPC, the function name points to a descriptor in the
1404 rdata section, the first element of which is a pointer to the
1405 code (..function_name), and the second points to the .toc
1406 */
1407 if (machine == MPPC)
1408 exp_label->section = secdata[RDATA].sec;
1409 else
1410 exp_label->section = secdata[TEXT].sec;
1411
1412 exp_label->flags = BSF_GLOBAL;
1413 exp_label->value = 0;
1414
1415 ptrs[oidx++] = exp_label;
1416
1417 iname = bfd_make_empty_symbol(abfd);
1418 iname->name = make_label ("__imp_", exp->name);
1419 iname->section = secdata[IDATA5].sec;
1420 iname->flags = BSF_GLOBAL;
1421 iname->value = 0;
1422
1423
1424 iname_lab = bfd_make_empty_symbol(abfd);
1425
1426 iname_lab->name = head_label;
1427 iname_lab->section = (asection *)&bfd_und_section;
1428 iname_lab->flags = 0;
1429 iname_lab->value = 0;
1430
1431
1432 iname_pp = ptrs + oidx;
1433 ptrs[oidx++] = iname;
1434
1435 iname_lab_pp = ptrs + oidx;
1436 ptrs[oidx++] = iname_lab;
1437
1438#ifdef DLLTOOL_PPC
1439 /* The symbol refering to the code (.text) */
1440 function_name = bfd_make_empty_symbol(abfd);
1441 function_name->name = make_label ("..", exp->name);
1442 function_name->section = secdata[TEXT].sec;
1443 function_name->flags = BSF_GLOBAL;
1444 function_name->value = 0;
1445
1446 fn_pp = ptrs + oidx;
1447 ptrs[oidx++] = function_name;
1448
1449 /* The .toc symbol */
1450 toc_symbol = bfd_make_empty_symbol(abfd);
1451 toc_symbol->name = make_label (".", "toc");
1452 toc_symbol->section = (asection *)&bfd_und_section;
1453 toc_symbol->flags = BSF_GLOBAL;
1454 toc_symbol->value = 0;
1455
1456 toc_pp = ptrs + oidx;
1457 ptrs[oidx++] = toc_symbol;
1458#endif
1459
1460 ptrs[oidx] = 0;
1461
1462 for (i = 0; i < NSECS; i++)
1463 {
1464 sinfo *si = secdata + i;
1465 asection *sec = si->sec;
1466 arelent *rel;
1467 arelent **rpp;
1468
1469 switch (i)
1470 {
1471 case TEXT:
1472 si->size = HOW_JTAB_SIZE;
1473 si->data = xmalloc (HOW_JTAB_SIZE);
1474 memcpy (si->data, HOW_JTAB, HOW_JTAB_SIZE);
1475
1476 /* add the reloc into idata$5 */
1477 rel = xmalloc (sizeof (arelent));
1478 rpp = xmalloc (sizeof (arelent *) * 2);
1479 rpp[0] = rel;
1480 rpp[1] = 0;
1481 rel->address = HOW_JTAB_ROFF;
1482 rel->addend = 0;
1483
1484 if (machine == MPPC)
1485 {
1486 rel->howto = bfd_reloc_type_lookup (abfd,
1487 BFD_RELOC_16_GOTOFF);
1488 rel->sym_ptr_ptr = iname_pp;
1489 }
1490 else
1491 {
1492 rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_32);
1493 rel->sym_ptr_ptr = secdata[IDATA5].sympp;
1494 }
1495 sec->orelocation = rpp;
1496 sec->reloc_count = 1;
1497 break;
1498 case IDATA4:
1499 case IDATA5:
1500 /* An idata$4 or idata$5 is one word long, and has an
1501 rva to idata$6 */
1502
1503 si->data = xmalloc (4);
1504 si->size = 4;
1505
1506 if (exp->noname)
1507 {
1508 si->data[0] = exp->ordinal ;
1509 si->data[1] = exp->ordinal >> 8;
1510 si->data[2] = exp->ordinal >> 16;
1511 si->data[3] = 0x80;
1512 }
1513 else
1514 {
1515 sec->reloc_count = 1;
1516 memset (si->data, 0, si->size);
1517 rel = xmalloc (sizeof (arelent));
1518 rpp = xmalloc (sizeof (arelent *) * 2);
1519 rpp[0] = rel;
1520 rpp[1] = 0;
1521 rel->address = 0;
1522 rel->addend = 0;
1523 rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_RVA);
1524 rel->sym_ptr_ptr = secdata[IDATA6].sympp;
1525 sec->orelocation = rpp;
1526 }
1527
1528 break;
1529
1530 case IDATA6:
1531 if (!exp->noname)
1532 {
1533 int idx = exp->hint + 1;
1534 si->size = strlen (xlate (exp->name)) + 3;
1535 si->data = xmalloc (si->size);
1536 si->data[0] = idx & 0xff;
1537 si->data[1] = idx >> 8;
1538 strcpy (si->data + 2, xlate (exp->name));
1539 }
1540 break;
1541 case IDATA7:
1542 si->size = 4;
1543 si->data =xmalloc(4);
1544 memset (si->data, 0, si->size);
1545 rel = xmalloc (sizeof (arelent));
1546 rpp = xmalloc (sizeof (arelent *) * 2);
1547 rpp[0] = rel;
1548 rel->address = 0;
1549 rel->addend = 0;
1550 rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_32);
1551 rel->sym_ptr_ptr = iname_lab_pp;
1552 sec->orelocation = rpp;
1553 sec->reloc_count = 1;
1554 break;
1555
1556 case PDATA:
1557 {
1558 /* The .pdata section is 5 words long. */
1559 /* Think of it as: */
1560 /* struct */
1561 /* { */
1562 /* bfd_vma BeginAddress, [0x00] */
1563 /* EndAddress, [0x04] */
1564 /* ExceptionHandler, [0x08] */
1565 /* HandlerData, [0x0c] */
1566 /* PrologEndAddress; [0x10] */
1567 /* }; */
1568
1569 /* So this pdata section setups up this as a glue linkage to
1570 a dll routine. There are a number of house keeping things
1571 we need to do:
1572
1573 1. In the name of glue trickery, the ADDR32 relocs for 0,
1574 4, and 0x10 are set to point to the same place:
1575 "..function_name".
1576 2. There is one more reloc needed in the pdata section.
1577 The actual glue instruction to restore the toc on
1578 return is saved as the offset in an IMGLUE reloc.
1579 So we need a total of four relocs for this section.
1580
1581 3. Lastly, the HandlerData field is set to 0x03, to indicate
1582 that this is a glue routine.
1583 */
1584 arelent *imglue, *ba_rel, *ea_rel, *pea_rel;
1585
1586 /* alignment must be set to 2**2 or you get extra stuff */
1587 bfd_set_section_alignment(abfd, sec, 2);
1588
1589 si->size = 4 * 5;
1590 si->data =xmalloc(4 * 5);
1591 memset (si->data, 0, si->size);
1592 rpp = xmalloc (sizeof (arelent *) * 5);
1593 rpp[0] = imglue = xmalloc (sizeof (arelent));
1594 rpp[1] = ba_rel = xmalloc (sizeof (arelent));
1595 rpp[2] = ea_rel = xmalloc (sizeof (arelent));
1596 rpp[3] = pea_rel = xmalloc (sizeof (arelent));
1597 rpp[4] = 0;
1598
1599 /* stick the toc reload instruction in the glue reloc */
1600 bfd_put_32(abfd, ppc_glue_insn, (char *) &imglue->address);
1601
1602 imglue->addend = 0;
1603 imglue->howto = bfd_reloc_type_lookup (abfd,
1604 BFD_RELOC_32_GOTOFF);
1605 imglue->sym_ptr_ptr = fn_pp;
1606
1607 ba_rel->address = 0;
1608 ba_rel->addend = 0;
1609 ba_rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_32);
1610 ba_rel->sym_ptr_ptr = fn_pp;
1611
1612 bfd_put_32(abfd, 0x18, si->data + 0x04);
1613 ea_rel->address = 4;
1614 ea_rel->addend = 0;
1615 ea_rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_32);
1616 ea_rel->sym_ptr_ptr = fn_pp;
1617
1618 /* mark it as glue */
1619 bfd_put_32(abfd, 0x03, si->data + 0x0c);
1620
1621 /* mark the prolog end address */
1622 bfd_put_32(abfd, 0x0D, si->data + 0x10);
1623 pea_rel->address = 0x10;
1624 pea_rel->addend = 0;
1625 pea_rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_32);
1626 pea_rel->sym_ptr_ptr = fn_pp;
1627
1628 sec->orelocation = rpp;
1629 sec->reloc_count = 4;
1630 break;
1631 }
1632 case RDATA:
1633 /* Each external function in a PowerPC PE file has a two word
1634 descriptor consisting of:
1635 1. The address of the code.
1636 2. The address of the appropriate .toc
1637 We use relocs to build this.
1638 */
1639
1640 si->size = 8;
1641 si->data =xmalloc(8);
1642 memset (si->data, 0, si->size);
1643
1644 rpp = xmalloc (sizeof (arelent *) * 3);
1645 rpp[0] = rel = xmalloc (sizeof (arelent));
1646 rpp[1] = xmalloc (sizeof (arelent));
1647 rpp[2] = 0;
1648
1649 rel->address = 0;
1650 rel->addend = 0;
1651 rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_32);
1652 rel->sym_ptr_ptr = fn_pp;
1653
1654 rel = rpp[1];
1655
1656 rel->address = 4;
1657 rel->addend = 0;
1658 rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_32);
1659 rel->sym_ptr_ptr = toc_pp;
1660
1661 sec->orelocation = rpp;
1662 sec->reloc_count = 2;
1663 break;
1664 }
1665 }
1666
1667 {
1668 bfd_vma vma = 0;
1669 /* Size up all the sections */
1670 for (i = 0; i < NSECS; i++)
1671 {
1672 sinfo *si = secdata + i;
1673
1674 bfd_set_section_size (abfd, si->sec, si->size);
1675 bfd_set_section_vma (abfd, si->sec, vma);
1676
1677/* vma += si->size;*/
1678 }
1679 }
1680 /* Write them out */
1681 for (i = 0; i < NSECS; i++)
1682 {
1683 sinfo *si = secdata + i;
1684
1685 if (i == IDATA5 && no_idata5)
1686 continue;
1687
1688 if (i == IDATA4 && no_idata4)
1689 continue;
1690
1691 bfd_set_section_contents (abfd, si->sec,
1692 si->data, 0,
1693 si->size);
1694 }
1695
1696 bfd_set_symtab (abfd, ptrs, oidx);
1697 bfd_close (abfd);
1698 abfd = bfd_openr (outname, HOW_BFD_TARGET);
1699 return abfd;
1700 }
1701
1702}
1703
1704
1705static bfd *
1706make_head()
1707{
1708 FILE * f = fopen ("dh.s", FOPEN_WT);
1709
1710 fprintf (f, "%s IMAGE_IMPORT_DESCRIPTOR\n", ASM_C);
1711 fprintf (f, "\t.section .idata$2\n");
1712
1713 fprintf(f,"\t%s\t%s\n", ASM_GLOBAL,head_label);
1714
1715 fprintf (f, "%s:\n", head_label);
1716
1717 fprintf (f, "\t%shname%s\t%sPtr to image import by name list\n",
1718 ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C);
1719
1720 fprintf (f, "\t%sthis should be the timestamp, but NT sometimes\n", ASM_C);
1721 fprintf (f, "\t%sdoesn't load DLLs when this is set.\n", ASM_C);
1722 fprintf (f, "\t%s\t0\t%s loaded time\n", ASM_LONG, ASM_C);
1723 fprintf (f, "\t%s\t0\t%s Forwarder chain\n", ASM_LONG, ASM_C);
1724 fprintf (f, "\t%s__%s_iname%s\t%s imported dll's name\n",
1725 ASM_RVA_BEFORE,
1726 imp_name_lab,
1727 ASM_RVA_AFTER,
1728 ASM_C);
1729 fprintf (f, "\t%sfthunk%s\t%s pointer to firstthunk\n",
1730 ASM_RVA_BEFORE,
1731 ASM_RVA_AFTER, ASM_C);
1732
1733 fprintf (f, "%sStuff for compatibility\n", ASM_C);
1734
1735 if (!no_idata5)
1736 {
1737 fprintf (f, "\t.section\t.idata$5\n");
1738 fprintf (f, "\t%s\t0\n", ASM_LONG);
1739 fprintf (f, "fthunk:\n");
1740 }
1741 if (!no_idata4)
1742 {
1743 fprintf (f, "\t.section\t.idata$4\n");
1744
1745 fprintf (f, "\t%s\t0\n", ASM_LONG);
1746 fprintf (f, "\t.section .idata$4\n");
1747 fprintf (f, "hname:\n");
1748 }
1749 fclose (f);
1750
1751 sprintf (outfile, "-o dh.o dh.s");
1752 run (as_name, outfile);
1753
1754 return bfd_openr ("dh.o", HOW_BFD_TARGET);
1755}
1756
1757static bfd *
1758make_tail()
1759{
1760 FILE * f = fopen ("dt.s", FOPEN_WT);
1761
1762#ifdef DLLTOOL_PPC
1763 /* Other PowerPC NT compilers use idata$6 for the dllname, so I
1764 do too. Original, huh? */
1765 fprintf (f, "\t.section .idata$6\n");
1766#else
1767 fprintf (f, "\t.section .idata$7\n");
1768#endif
1769
1770 fprintf (f, "\t%s\t__%s_iname\n", ASM_GLOBAL, imp_name_lab);
1771 fprintf (f, "__%s_iname:\t%s\t\"%s\"\n",
1772 imp_name_lab, ASM_TEXT, dll_name);
1773
1774 if (!no_idata4)
1775 {
1776 fprintf (f, "\t.section .idata$4\n");
1777 fprintf (f, "\t%s\t0\n", ASM_LONG);
1778 }
1779 if (!no_idata5)
1780 {
1781 fprintf (f, "\t.section .idata$5\n");
1782 fprintf (f, "\t%s\t0\n", ASM_LONG);
1783 }
1784
1785
1786#ifdef DLLTOOL_PPC
1787 /* Normally, we need to see a null descriptor built in idata$3 to
1788 act as the terminator for the list. The ideal way, I suppose,
1789 would be to mark this section as a comdat type 2 section, so
1790 only one would appear in the final .exe (if our linker supported
1791 comdat, that is) or cause it to be inserted by something else (say
1792 crt0)
1793 */
1794
1795 fprintf (f, "\t.section .idata$3\n");
1796 fprintf (f, "\t%s\t0\n", ASM_LONG);
1797 fprintf (f, "\t%s\t0\n", ASM_LONG);
1798 fprintf (f, "\t%s\t0\n", ASM_LONG);
1799 fprintf (f, "\t%s\t0\n", ASM_LONG);
1800 fprintf (f, "\t%s\t0\n", ASM_LONG);
1801#endif
1802
1803 fclose (f);
1804
1805 sprintf (outfile, "-o dt.o dt.s");
1806 run (as_name, outfile);
1807 return bfd_openr ("dt.o", HOW_BFD_TARGET);
1808}
1809
1810static void
1811gen_lib_file ()
1812{
1813 int i;
1814 export_type *exp;
1815 bfd *ar_head;
1816 bfd *ar_tail;
1817 bfd *outarch;
1818 bfd * head = 0;
1819
1820 unlink (imp_name);
1821
1822 outarch = bfd_openw (imp_name, HOW_BFD_TARGET);
1823
1824 if (!outarch)
1825 {
1826 fprintf (stderr, "%s: Can't open .lib file %s\n", program_name, imp_name);
1827 exit (1);
1828 }
1829 bfd_set_format (outarch, bfd_archive);
1830 outarch->has_armap = 1;
1831
1832 /* Work out a reasonable size of things to put onto one line. */
1833
1834
1835
1836 ar_head = make_head ();
1837 ar_tail = make_tail();
1838
1839 for (i = 0; (exp = d_exports_lexically[i]); i++)
1840 {
1841 bfd *n = make_one_lib_file (exp, i);
1842 n->next = head;
1843 head = n;
1844 }
1845
1846
1847 /* Now stick them all into the archive */
1848
1849 ar_head->next = head;
1850 ar_tail->next = ar_head;
1851 head = ar_tail;
1852
1853 bfd_set_archive_head (outarch, head);
1854 bfd_close (outarch);
1855
1856 /* Delete all the temp files */
1857
1858 if (dontdeltemps == 0)
1859 {
1860 sprintf (outfile, "dh.o");
1861 unlink (outfile);
1862 sprintf (outfile, "dh.s");
1863 unlink (outfile);
1864 sprintf (outfile, "dt.o");
1865 unlink (outfile);
1866 sprintf (outfile, "dt.s");
1867 unlink (outfile);
1868 }
1869
1870 if (dontdeltemps < 2)
1871 for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
1872 {
1873 sprintf (outfile, "ds%d.o",i);
1874 unlink (outfile);
1875 }
1876
1877}
1878/**********************************************************************/
1879
1880/* Run through the information gathered from the .o files and the
1881 .def file and work out the best stuff */
1882int
1883pfunc (a, b)
1884 void *a;
1885 void *b;
1886{
1887 export_type *ap = *(export_type **) a;
1888 export_type *bp = *(export_type **) b;
1889 if (ap->ordinal == bp->ordinal)
1890 return 0;
1891
1892 /* unset ordinals go to the bottom */
1893 if (ap->ordinal == -1)
1894 return 1;
1895 if (bp->ordinal == -1)
1896 return -1;
1897 return (ap->ordinal - bp->ordinal);
1898}
1899
1900
1901int
1902nfunc (a, b)
1903 void *a;
1904 void *b;
1905{
1906 export_type *ap = *(export_type **) a;
1907 export_type *bp = *(export_type **) b;
1908
1909 return (strcmp (ap->name, bp->name));
1910}
1911
1912static
1913void
1914remove_null_names (ptr)
1915 export_type **ptr;
1916{
1917 int src;
1918 int dst;
1919 for (dst = src = 0; src < d_nfuncs; src++)
1920 {
1921 if (ptr[src])
1922 {
1923 ptr[dst] = ptr[src];
1924 dst++;
1925 }
1926 }
1927 d_nfuncs = dst;
1928}
1929
1930static void
1931dtab (ptr)
1932 export_type **ptr;
1933{
1934#ifdef SACDEBUG
1935 int i;
1936 for (i = 0; i < d_nfuncs; i++)
1937 {
1938 if (ptr[i])
1939 {
1940 printf ("%d %s @ %d %s%s\n",
1941 i, ptr[i]->name, ptr[i]->ordinal,
1942 ptr[i]->noname ? "NONAME " : "",
1943 ptr[i]->constant ? "CONSTANT" : "");
1944 }
1945 else
1946 printf ("empty\n");
1947 }
1948#endif
1949}
1950
1951static void
1952process_duplicates (d_export_vec)
1953 export_type **d_export_vec;
1954{
1955 int more = 1;
1956 int i;
1957 while (more)
1958 {
1959
1960 more = 0;
1961 /* Remove duplicates */
1962 qsort (d_export_vec, d_nfuncs, sizeof (export_type *), nfunc);
1963
1964 dtab (d_export_vec);
1965 for (i = 0; i < d_nfuncs - 1; i++)
1966 {
1967 if (strcmp (d_export_vec[i]->name,
1968 d_export_vec[i + 1]->name) == 0)
1969 {
1970
1971 export_type *a = d_export_vec[i];
1972 export_type *b = d_export_vec[i + 1];
1973
1974 more = 1;
1975 if (verbose)
1976 fprintf (stderr, "Warning, ignoring duplicate EXPORT %s %d,%d\n",
1977 a->name,
1978 a->ordinal,
1979 b->ordinal);
1980 if (a->ordinal != -1
1981 && b->ordinal != -1)
1982 {
1983
1984 fprintf (stderr, "Error, duplicate EXPORT with oridinals %s\n",
1985 a->name);
1986 exit (1);
1987 }
1988 /* Merge attributes */
1989 b->ordinal = a->ordinal > 0 ? a->ordinal : b->ordinal;
1990 b->constant |= a->constant;
1991 b->noname |= a->noname;
1992 d_export_vec[i] = 0;
1993 }
1994
1995 dtab (d_export_vec);
1996 remove_null_names (d_export_vec);
1997 dtab (d_export_vec);
1998 }
1999 }
2000
2001
2002 /* Count the names */
2003 for (i = 0; i < d_nfuncs; i++)
2004 {
2005 if (!d_export_vec[i]->noname)
2006 d_named_nfuncs++;
2007 }
2008}
2009
2010static void
2011fill_ordinals (d_export_vec)
2012 export_type **d_export_vec;
2013{
2014 int lowest = 0;
2015
2016 int i;
2017 char *ptr;
2018 qsort (d_export_vec, d_nfuncs, sizeof (export_type *), pfunc);
2019
2020 /* fill in the unset ordinals with ones from our range */
2021
2022 ptr = (char *) malloc (65536);
2023
2024 memset (ptr, 0, 65536);
2025
2026 /* Mark in our large vector all the numbers that are taken */
2027 for (i = 0; i < d_nfuncs; i++)
2028 {
2029 if (d_export_vec[i]->ordinal != -1)
2030 {
2031 ptr[d_export_vec[i]->ordinal] = 1;
2032 if (lowest == 0)
2033 lowest = d_export_vec[i]->ordinal;
2034 }
2035 }
2036
2037 /* Start at 1 for compatibility with MS toolchain. */
2038 if (lowest == 0)
2039 lowest = 1;
2040
2041 for (i = 0; i < d_nfuncs; i++)
2042 {
2043 if (d_export_vec[i]->ordinal == -1)
2044 {
2045 int j;
2046 for (j = lowest; j < 65536; j++)
2047 if (ptr[j] == 0)
2048 {
2049 ptr[j] = 1;
2050 d_export_vec[i]->ordinal = j;
2051 goto done;
2052 }
2053
2054 for (j = 1; j < lowest; j++)
2055 if (ptr[j] == 0)
2056 {
2057 ptr[j] = 1;
2058 d_export_vec[i]->ordinal = j;
2059 goto done;
2060 }
2061 done:;
2062
2063 }
2064 }
2065
2066 free (ptr);
2067
2068 /* And resort */
2069
2070 qsort (d_export_vec, d_nfuncs, sizeof (export_type *), pfunc);
2071
2072 /* Work out the lowest and highest ordinal numbers. */
2073 if (d_nfuncs)
2074 {
2075 if (d_export_vec[0])
2076 d_low_ord = d_export_vec[0]->ordinal;
2077 if (d_export_vec[d_nfuncs-1])
2078 d_high_ord = d_export_vec[d_nfuncs-1]->ordinal;
2079 }
2080}
2081
2082int alphafunc(av,bv)
2083void *av;
2084void *bv;
2085{
2086 export_type **a = av;
2087 export_type **b = bv;
2088
2089 return strcmp ((*a)->name, (*b)->name);
2090}
2091
2092void
2093mangle_defs ()
2094{
2095 /* First work out the minimum ordinal chosen */
2096
2097 export_type *exp;
2098
2099 int i;
2100 int hint = 0;
2101 export_type **d_export_vec
2102 = (export_type **) xmalloc (sizeof (export_type *) * d_nfuncs);
2103
2104 for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
2105 {
2106 d_export_vec[i] = exp;
2107 }
2108
2109 process_duplicates (d_export_vec);
2110 fill_ordinals (d_export_vec);
2111
2112 /* Put back the list in the new order */
2113 d_exports = 0;
2114 for (i = d_nfuncs - 1; i >= 0; i--)
2115 {
2116 d_export_vec[i]->next = d_exports;
2117 d_exports = d_export_vec[i];
2118 }
2119
2120 /* Build list in alpha order */
2121 d_exports_lexically = (export_type **)xmalloc (sizeof(export_type *)*(d_nfuncs+1));
2122
2123 for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
2124 {
2125 d_exports_lexically[i] = exp;
2126 }
2127 d_exports_lexically[i] = 0;
2128
2129 qsort (d_exports_lexically, i, sizeof (export_type *), alphafunc);
2130
2131 /* Fill exp entries with their hint values */
2132
2133 for (i = 0; i < d_nfuncs; i++)
2134 {
2135 if (!d_exports_lexically[i]->noname || show_allnames)
2136 d_exports_lexically[i]->hint = hint++;
2137 }
2138
2139}
2140
2141
2142
2143
2144
2145
2146/**********************************************************************/
2147
2148void
2149usage (file, status)
2150 FILE *file;
2151 int status;
2152{
2153 fprintf (file, "Usage %s <options> <object-files>\n", program_name);
2154 fprintf (file, " --machine <machine>\n");
2155 fprintf (file, " --output-exp <outname> Generate export file.\n");
2156 fprintf (file, " --output-lib <outname> Generate input library.\n");
2157 fprintf (file, " --add-indirect Add dll indirects to export file.\n");
2158 fprintf (file, " --dllname <name> Name of input dll to put into output lib.\n");
2159 fprintf (file, " --def <deffile> Name input .def file\n");
2160 fprintf (file, " --output-def <deffile> Name output .def file\n");
2161 fprintf (file, " --base-file <basefile> Read linker generated base file\n");
2162 fprintf (file, " --no-idata4 Don't generate idata$4 section\n");
2163 fprintf (file, " --no-idata5 Don't generate idata$5 section\n");
2164 fprintf (file, " -v Verbose\n");
2165 fprintf (file, " -U Add underscores to .lib\n");
2166 fprintf (file, " -k Kill @<n> from exported names\n");
2167 fprintf (file, " --as <name> Use <name> for assembler\n");
2168 fprintf (file, " --nodelete Keep temp files.\n");
2169 exit (status);
2170}
2171
2172#define OPTION_NO_IDATA4 'x'
2173#define OPTION_NO_IDATA5 'c'
2174static struct option long_options[] =
2175{
2176 {"nodelete", no_argument, NULL, 'n'},
2177 {"dllname", required_argument, NULL, 'D'},
2178 {"no-idata4", no_argument, NULL, OPTION_NO_IDATA4},
2179 {"no-idata5", no_argument, NULL, OPTION_NO_IDATA5},
2180 {"output-exp", required_argument, NULL, 'e'},
2181 {"output-def", required_argument, NULL, 'z'},
2182 {"output-lib", required_argument, NULL, 'l'},
2183 {"def", required_argument, NULL, 'd'},
2184 {"add-underscore", no_argument, NULL, 'U'},
2185 {"killat", no_argument, NULL, 'k'},
2186 {"help", no_argument, NULL, 'h'},
2187 {"machine", required_argument, NULL, 'm'},
2188 {"add-indirect", no_argument, NULL, 'a'},
2189 {"base-file", required_argument, NULL, 'b'},
2190 {"as", required_argument, NULL, 'S'},
2191 {0}
2192};
2193
2194
2195
2196int
2197main (ac, av)
2198 int ac;
2199 char **av;
2200{
2201 int c;
2202 int i;
2203 char *firstarg = 0;
2204 program_name = av[0];
2205 oav = av;
2206
2207 while ((c = getopt_long (ac, av, "xcz:S:R:A:puaD:l:e:nkvbUh?m:yd:", long_options, 0))
2208 != EOF)
2209 {
2210 switch (c)
2211 {
2212 case OPTION_NO_IDATA4:
2213 no_idata4 = 1;
2214 break;
2215 case OPTION_NO_IDATA5:
2216 no_idata5 = 1;
2217 break;
2218 case 'S':
2219 as_name = optarg;
2220 break;
2221
2222 /* ignored for compatibility */
2223 case 'u':
2224 break;
2225 case 'a':
2226 add_indirect = 1;
2227 break;
2228 case 'z':
2229 output_def = fopen (optarg, FOPEN_WT);
2230 break;
2231 case 'D':
2232 dll_name = optarg;
2233 break;
2234 case 'l':
2235 imp_name = optarg;
2236 break;
2237 case 'e':
2238 exp_name = optarg;
2239 break;
2240 case 'h':
2241 case '?':
2242 usage (stderr, 0);
2243 break;
2244 case 'm':
2245 mname = optarg;
2246 break;
2247 case 'v':
2248 verbose = 1;
2249 break;
2250 case 'y':
2251 yydebug = 1;
2252 break;
2253 case 'U':
2254 add_underscore = 1;
2255 break;
2256 case 'k':
2257 killat = 1;
2258 break;
2259 case 'd':
2260 def_file = optarg;
2261 break;
2262 case 'n':
2263 dontdeltemps++;
2264 break;
2265 case 'b':
2266 base_file = fopen (optarg, FOPEN_RB);
2267 if (!base_file)
2268 {
2269 fprintf (stderr, "%s: Unable to open base-file %s\n",
2270 av[0],
2271 optarg);
2272 exit (1);
2273 }
2274 break;
2275 default:
2276 usage (stderr, 1);
2277 }
2278 }
2279
2280
2281 for (i = 0; mtable[i].type; i++)
2282 {
2283 if (strcmp (mtable[i].type, mname) == 0)
2284 break;
2285 }
2286
2287 if (!mtable[i].type)
2288 {
2289 fprintf (stderr, "Machine not supported\n");
2290 exit (1);
2291 }
2292 machine = i;
2293
2294
2295 if (!dll_name && exp_name)
2296 {
2297 char len = strlen (exp_name) + 5;
2298 dll_name = xmalloc (len);
2299 strcpy (dll_name, exp_name);
2300 strcat (dll_name, ".dll");
2301 }
2302
2303 if (def_file)
2304 {
2305 process_def_file (def_file);
2306 }
2307 while (optind < ac)
2308 {
2309 if (!firstarg)
2310 firstarg = av[optind];
2311 scan_obj_file (av[optind]);
2312 optind++;
2313 }
2314
2315
2316 mangle_defs ();
2317
2318 if (exp_name)
2319 gen_exp_file ();
2320 if (imp_name)
2321 {
2322 /* Make imp_name safe for use as a label. */
2323 char *p;
2324 imp_name_lab = strdup (imp_name);
2325 for (p = imp_name_lab; *p; *p++)
2326 {
2327 if (!isalpha (*p) && !isdigit (*p))
2328 *p = '_';
2329 }
2330 head_label = make_label("_head_", imp_name_lab);
2331 gen_lib_file ();
2332 }
2333 if (output_def)
2334 gen_def_file ();
2335
2336 return 0;
2337}
This page took 0.032666 seconds and 4 git commands to generate.