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