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