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