OpenCores
URL https://opencores.org/ocsvn/openrisc_me/openrisc_me/trunk

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [gnu-src/] [binutils-2.18.50/] [binutils/] [dlltool.c] - Blame information for rev 481

Go to most recent revision | Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.