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