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