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