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