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