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