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

Subversion Repositories open8_urisc

[/] [open8_urisc/] [trunk/] [gnu/] [binutils/] [binutils/] [dlltool.c] - Blame information for rev 284

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

Line No. Rev Author Line
1 15 khays
/* dlltool.c -- tool to generate stuff for PE style DLLs
2
   Copyright 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
3 166 khays
   2005, 2006, 2007, 2008, 2009, 2011, 2012 Free Software Foundation, Inc.
4 15 khays
 
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
#include "sysdep.h"
236
#include "bfd.h"
237
#include "libiberty.h"
238
#include "getopt.h"
239
#include "demangle.h"
240
#include "dyn-string.h"
241
#include "bucomm.h"
242
#include "dlltool.h"
243
#include "safe-ctype.h"
244
 
245
#include <time.h>
246
#include <assert.h>
247
 
248
#ifdef DLLTOOL_ARM
249
#include "coff/arm.h"
250
#include "coff/internal.h"
251
#endif
252
#ifdef DLLTOOL_DEFAULT_MX86_64
253
#include "coff/x86_64.h"
254
#endif
255
#ifdef DLLTOOL_DEFAULT_I386
256
#include "coff/i386.h"
257
#endif
258
 
259
#ifndef COFF_PAGE_SIZE
260
#define COFF_PAGE_SIZE ((bfd_vma) 4096)
261
#endif
262
 
263
#ifndef PAGE_MASK
264
#define PAGE_MASK ((bfd_vma) (- COFF_PAGE_SIZE))
265
#endif
266
 
267
/* Get current BFD error message.  */
268
#define bfd_get_errmsg() (bfd_errmsg (bfd_get_error ()))
269
 
270
/* Forward references.  */
271
static char *look_for_prog (const char *, const char *, int);
272
static char *deduce_name (const char *);
273
 
274
#ifdef DLLTOOL_MCORE_ELF
275
static void mcore_elf_cache_filename (const char *);
276
static void mcore_elf_gen_out_file (void);
277
#endif
278
 
279
#ifdef HAVE_SYS_WAIT_H
280
#include <sys/wait.h>
281
#else /* ! HAVE_SYS_WAIT_H */
282
#if ! defined (_WIN32) || defined (__CYGWIN32__)
283
#ifndef WIFEXITED
284
#define WIFEXITED(w)    (((w) & 0377) == 0)
285
#endif
286
#ifndef WIFSIGNALED
287
#define WIFSIGNALED(w)  (((w) & 0377) != 0177 && ((w) & ~0377) == 0)
288
#endif
289
#ifndef WTERMSIG
290
#define WTERMSIG(w)     ((w) & 0177)
291
#endif
292
#ifndef WEXITSTATUS
293
#define WEXITSTATUS(w)  (((w) >> 8) & 0377)
294
#endif
295
#else /* defined (_WIN32) && ! defined (__CYGWIN32__) */
296
#ifndef WIFEXITED
297
#define WIFEXITED(w)    (((w) & 0xff) == 0)
298
#endif
299
#ifndef WIFSIGNALED
300
#define WIFSIGNALED(w)  (((w) & 0xff) != 0 && ((w) & 0xff) != 0x7f)
301
#endif
302
#ifndef WTERMSIG
303
#define WTERMSIG(w)     ((w) & 0x7f)
304
#endif
305
#ifndef WEXITSTATUS
306
#define WEXITSTATUS(w)  (((w) & 0xff00) >> 8)
307
#endif
308
#endif /* defined (_WIN32) && ! defined (__CYGWIN32__) */
309
#endif /* ! HAVE_SYS_WAIT_H */
310
 
311 166 khays
#define show_allnames 0
312
 
313 15 khays
/* ifunc and ihead data structures: ttk@cygnus.com 1997
314
 
315
   When IMPORT declarations are encountered in a .def file the
316
   function import information is stored in a structure referenced by
317
   the global variable IMPORT_LIST.  The structure is a linked list
318
   containing the names of the dll files each function is imported
319
   from and a linked list of functions being imported from that dll
320
   file.  This roughly parallels the structure of the .idata section
321
   in the PE object file.
322
 
323
   The contents of .def file are interpreted from within the
324
   process_def_file function.  Every time an IMPORT declaration is
325
   encountered, it is broken up into its component parts and passed to
326
   def_import.  IMPORT_LIST is initialized to NULL in function main.  */
327
 
328
typedef struct ifunct
329
{
330
  char *         name;   /* Name of function being imported.  */
331
  char *     its_name;   /* Optional import table symbol name.  */
332
  int            ord;    /* Two-byte ordinal value associated with function.  */
333
  struct ifunct *next;
334
} ifunctype;
335
 
336
typedef struct iheadt
337
{
338
  char *         dllname;  /* Name of dll file imported from.  */
339
  long           nfuncs;   /* Number of functions in list.  */
340
  struct ifunct *funchead; /* First function in list.  */
341
  struct ifunct *functail; /* Last  function in list.  */
342
  struct iheadt *next;     /* Next dll file in list.  */
343
} iheadtype;
344
 
345
/* Structure containing all import information as defined in .def file
346
   (qv "ihead structure").  */
347
 
348
static iheadtype *import_list = NULL;
349
static char *as_name = NULL;
350
static char * as_flags = "";
351
static char *tmp_prefix;
352
static int no_idata4;
353
static int no_idata5;
354
static char *exp_name;
355
static char *imp_name;
356
static char *delayimp_name;
357
static char *identify_imp_name;
358
static bfd_boolean identify_strict;
359
 
360
/* Types used to implement a linked list of dllnames associated
361
   with the specified import lib. Used by the identify_* code.
362
   The head entry is acts as a sentinal node and is always empty
363
   (head->dllname is NULL).  */
364
typedef struct dll_name_list_node_t
365
{
366
  char *                        dllname;
367
  struct dll_name_list_node_t * next;
368
} dll_name_list_node_type;
369
 
370
typedef struct dll_name_list_t
371
{
372
  dll_name_list_node_type * head;
373
  dll_name_list_node_type * tail;
374
} dll_name_list_type;
375
 
376
/* Types used to pass data to iterator functions.  */
377
typedef struct symname_search_data_t
378
{
379
  const char * symname;
380
  bfd_boolean  found;
381
} symname_search_data_type;
382
 
383
typedef struct identify_data_t
384
{
385
   dll_name_list_type * list;
386
   bfd_boolean          ms_style_implib;
387
} identify_data_type;
388
 
389
 
390
static char *head_label;
391
static char *imp_name_lab;
392
static char *dll_name;
393
static int dll_name_set_by_exp_name;
394
static int add_indirect = 0;
395
static int add_underscore = 0;
396
static int add_stdcall_underscore = 0;
397
/* This variable can hold three different values. The value
398
   -1 (default) means that default underscoring should be used,
399
   zero means that no underscoring should be done, and one
400
   indicates that underscoring should be done.  */
401
static int leading_underscore = -1;
402
static int dontdeltemps = 0;
403
 
404
/* TRUE if we should export all symbols.  Otherwise, we only export
405
   symbols listed in .drectve sections or in the def file.  */
406
static bfd_boolean export_all_symbols;
407
 
408
/* TRUE if we should exclude the symbols in DEFAULT_EXCLUDES when
409
   exporting all symbols.  */
410
static bfd_boolean do_default_excludes = TRUE;
411
 
412
static bfd_boolean use_nul_prefixed_import_tables = FALSE;
413
 
414
/* Default symbols to exclude when exporting all the symbols.  */
415
static const char *default_excludes = "DllMain@12,DllEntryPoint@0,impure_ptr";
416
 
417
/* TRUE if we should add __imp_<SYMBOL> to import libraries for backward
418
   compatibility to old Cygwin releases.  */
419
static bfd_boolean create_compat_implib;
420
 
421
/* TRUE if we have to write PE+ import libraries.  */
422
static bfd_boolean create_for_pep;
423
 
424
static char *def_file;
425
 
426
extern char * program_name;
427
 
428
static int machine;
429
static int killat;
430
static int add_stdcall_alias;
431
static const char *ext_prefix_alias;
432
static int verbose;
433
static FILE *output_def;
434
static FILE *base_file;
435
 
436
#ifdef DLLTOOL_DEFAULT_ARM
437
static const char *mname = "arm";
438
#endif
439
 
440
#ifdef DLLTOOL_DEFAULT_ARM_EPOC
441
static const char *mname = "arm-epoc";
442
#endif
443
 
444
#ifdef DLLTOOL_DEFAULT_ARM_WINCE
445
static const char *mname = "arm-wince";
446
#endif
447
 
448
#ifdef DLLTOOL_DEFAULT_I386
449
static const char *mname = "i386";
450
#endif
451
 
452
#ifdef DLLTOOL_DEFAULT_MX86_64
453
static const char *mname = "i386:x86-64";
454
#endif
455
 
456
#ifdef DLLTOOL_DEFAULT_PPC
457
static const char *mname = "ppc";
458
#endif
459
 
460
#ifdef DLLTOOL_DEFAULT_SH
461
static const char *mname = "sh";
462
#endif
463
 
464
#ifdef DLLTOOL_DEFAULT_MIPS
465
static const char *mname = "mips";
466
#endif
467
 
468
#ifdef DLLTOOL_DEFAULT_MCORE
469
static const char * mname = "mcore-le";
470
#endif
471
 
472
#ifdef DLLTOOL_DEFAULT_MCORE_ELF
473
static const char * mname = "mcore-elf";
474
static char * mcore_elf_out_file = NULL;
475
static char * mcore_elf_linker   = NULL;
476
static char * mcore_elf_linker_flags = NULL;
477
 
478
#define DRECTVE_SECTION_NAME ((machine == MMCORE_ELF || machine == MMCORE_ELF_LE) ? ".exports" : ".drectve")
479
#endif
480
 
481
#ifndef DRECTVE_SECTION_NAME
482
#define DRECTVE_SECTION_NAME ".drectve"
483
#endif
484
 
485
/* What's the right name for this ?  */
486
#define PATHMAX 250             
487
 
488
/* External name alias numbering starts here.  */
489
#define PREFIX_ALIAS_BASE       20000
490
 
491
char *tmp_asm_buf;
492
char *tmp_head_s_buf;
493
char *tmp_head_o_buf;
494
char *tmp_tail_s_buf;
495
char *tmp_tail_o_buf;
496
char *tmp_stub_buf;
497
 
498
#define TMP_ASM         dlltmp (&tmp_asm_buf, "%sc.s")
499
#define TMP_HEAD_S      dlltmp (&tmp_head_s_buf, "%sh.s")
500
#define TMP_HEAD_O      dlltmp (&tmp_head_o_buf, "%sh.o")
501
#define TMP_TAIL_S      dlltmp (&tmp_tail_s_buf, "%st.s")
502
#define TMP_TAIL_O      dlltmp (&tmp_tail_o_buf, "%st.o")
503
#define TMP_STUB        dlltmp (&tmp_stub_buf, "%ss")
504
 
505
/* This bit of assembly does jmp * ....  */
506
static const unsigned char i386_jtab[] =
507
{
508
  0xff, 0x25, 0x00, 0x00, 0x00, 0x00, 0x90, 0x90
509
};
510
 
511
static const unsigned char i386_dljtab[] =
512
{
513
  0xFF, 0x25, 0x00, 0x00, 0x00, 0x00, /* jmp __imp__function             */
514
  0xB8, 0x00, 0x00, 0x00, 0x00,       /* mov eax, offset __imp__function */
515
  0xE9, 0x00, 0x00, 0x00, 0x00        /* jmp __tailMerge__dllname        */
516
};
517
 
518 166 khays
static const unsigned char i386_x64_dljtab[] =
519
{
520
  0xFF, 0x25, 0x00, 0x00, 0x00, 0x00, /* jmp __imp__function             */
521
  0x48, 0x8d, 0x05,                   /* leaq rax, (__imp__function) */
522
        0x00, 0x00, 0x00, 0x00,
523
  0xE9, 0x00, 0x00, 0x00, 0x00        /* jmp __tailMerge__dllname        */
524
};
525
 
526 15 khays
static const unsigned char arm_jtab[] =
527
{
528
  0x00, 0xc0, 0x9f, 0xe5,       /* ldr  ip, [pc] */
529
  0x00, 0xf0, 0x9c, 0xe5,       /* ldr  pc, [ip] */
530
  0,    0,    0,    0
531
};
532
 
533
static const unsigned char arm_interwork_jtab[] =
534
{
535
  0x04, 0xc0, 0x9f, 0xe5,       /* ldr  ip, [pc] */
536
  0x00, 0xc0, 0x9c, 0xe5,       /* ldr  ip, [ip] */
537
  0x1c, 0xff, 0x2f, 0xe1,       /* bx   ip       */
538
  0,    0,    0,    0
539
};
540
 
541
static const unsigned char thumb_jtab[] =
542
{
543
  0x40, 0xb4,           /* push {r6}         */
544
  0x02, 0x4e,           /* ldr  r6, [pc, #8] */
545
  0x36, 0x68,           /* ldr  r6, [r6]     */
546
  0xb4, 0x46,           /* mov  ip, r6       */
547
  0x40, 0xbc,           /* pop  {r6}         */
548
  0x60, 0x47,           /* bx   ip           */
549
  0,    0,    0,    0
550
};
551
 
552
static const unsigned char mcore_be_jtab[] =
553
{
554
  0x71, 0x02,            /* lrw r1,2       */
555
  0x81, 0x01,            /* ld.w r1,(r1,0) */
556
  0x00, 0xC1,            /* jmp r1         */
557
  0x12, 0x00,            /* nop            */
558
  0x00, 0x00, 0x00, 0x00 /* <address>      */
559
};
560
 
561
static const unsigned char mcore_le_jtab[] =
562
{
563
  0x02, 0x71,            /* lrw r1,2       */
564
  0x01, 0x81,            /* ld.w r1,(r1,0) */
565
  0xC1, 0x00,            /* jmp r1         */
566
  0x00, 0x12,            /* nop            */
567
  0x00, 0x00, 0x00, 0x00 /* <address>      */
568
};
569
 
570
/* This is the glue sequence for PowerPC PE. There is a
571
   tocrel16-tocdefn reloc against the first instruction.
572
   We also need a IMGLUE reloc against the glue function
573
   to restore the toc saved by the third instruction in
574
   the glue.  */
575
static const unsigned char ppc_jtab[] =
576
{
577
  0x00, 0x00, 0x62, 0x81, /* lwz r11,0(r2)               */
578
                          /*   Reloc TOCREL16 __imp_xxx  */
579
  0x00, 0x00, 0x8B, 0x81, /* lwz r12,0(r11)              */
580
  0x04, 0x00, 0x41, 0x90, /* stw r2,4(r1)                */
581
  0xA6, 0x03, 0x89, 0x7D, /* mtctr r12                   */
582
  0x04, 0x00, 0x4B, 0x80, /* lwz r2,4(r11)               */
583
  0x20, 0x04, 0x80, 0x4E  /* bctr                        */
584
};
585
 
586
#ifdef DLLTOOL_PPC
587
/* The glue instruction, picks up the toc from the stw in
588
   the above code: "lwz r2,4(r1)".  */
589
static bfd_vma ppc_glue_insn = 0x80410004;
590
#endif
591
 
592
static const char i386_trampoline[] =
593
  "\tpushl %%ecx\n"
594
  "\tpushl %%edx\n"
595
  "\tpushl %%eax\n"
596
  "\tpushl $__DELAY_IMPORT_DESCRIPTOR_%s\n"
597
  "\tcall ___delayLoadHelper2@8\n"
598
  "\tpopl %%edx\n"
599
  "\tpopl %%ecx\n"
600
  "\tjmp *%%eax\n";
601
 
602 166 khays
static const char i386_x64_trampoline[] =
603
  "\tpushq %%rcx\n"
604
  "\tpushq %%rdx\n"
605
  "\tpushq %%r8\n"
606
  "\tpushq %%r9\n"
607
  "\tsubq  $40, %%rsp\n"
608
  "\tmovq  %%rax, %%rdx\n"
609
  "\tleaq  __DELAY_IMPORT_DESCRIPTOR_%s(%%rip), %%rcx\n"
610
  "\tcall __delayLoadHelper2\n"
611
  "\taddq  $40, %%rsp\n"
612
  "\tpopq %%r9\n"
613
  "\tpopq %%r8\n"
614
  "\tpopq %%rdx\n"
615
  "\tpopq %%rcx\n"
616
  "\tjmp *%%rax\n";
617
 
618 15 khays
struct mac
619
{
620
  const char *type;
621
  const char *how_byte;
622
  const char *how_short;
623
  const char *how_long;
624
  const char *how_asciz;
625
  const char *how_comment;
626
  const char *how_jump;
627
  const char *how_global;
628
  const char *how_space;
629
  const char *how_align_short;
630
  const char *how_align_long;
631
  const char *how_default_as_switches;
632
  const char *how_bfd_target;
633
  enum bfd_architecture how_bfd_arch;
634
  const unsigned char *how_jtab;
635
  int how_jtab_size; /* Size of the jtab entry.  */
636
  int how_jtab_roff; /* Offset into it for the ind 32 reloc into idata 5.  */
637
  const unsigned char *how_dljtab;
638
  int how_dljtab_size; /* Size of the dljtab entry.  */
639
  int how_dljtab_roff1; /* Offset for the ind 32 reloc into idata 5.  */
640
  int how_dljtab_roff2; /* Offset for the ind 32 reloc into idata 5.  */
641
  int how_dljtab_roff3; /* Offset for the ind 32 reloc into idata 5.  */
642
  const char *trampoline;
643
};
644
 
645
static const struct mac
646
mtable[] =
647
{
648
  {
649
#define MARM 0
650
    "arm", ".byte", ".short", ".long", ".asciz", "@",
651
    "ldr\tip,[pc]\n\tldr\tpc,[ip]\n\t.long",
652
    ".global", ".space", ".align\t2",".align\t4", "-mapcs-32",
653
    "pe-arm-little", bfd_arch_arm,
654
    arm_jtab, sizeof (arm_jtab), 8,
655
    0, 0, 0, 0, 0, 0
656
  }
657
  ,
658
  {
659
#define M386 1
660
    "i386", ".byte", ".short", ".long", ".asciz", "#",
661
    "jmp *", ".global", ".space", ".align\t2",".align\t4", "",
662
    "pe-i386",bfd_arch_i386,
663
    i386_jtab, sizeof (i386_jtab), 2,
664
    i386_dljtab, sizeof (i386_dljtab), 2, 7, 12, i386_trampoline
665
  }
666
  ,
667
  {
668
#define MPPC 2
669
    "ppc", ".byte", ".short", ".long", ".asciz", "#",
670
    "jmp *", ".global", ".space", ".align\t2",".align\t4", "",
671
    "pe-powerpcle",bfd_arch_powerpc,
672
    ppc_jtab, sizeof (ppc_jtab), 0,
673
    0, 0, 0, 0, 0, 0
674
  }
675
  ,
676
  {
677
#define MTHUMB 3
678
    "thumb", ".byte", ".short", ".long", ".asciz", "@",
679
    "push\t{r6}\n\tldr\tr6, [pc, #8]\n\tldr\tr6, [r6]\n\tmov\tip, r6\n\tpop\t{r6}\n\tbx\tip",
680
    ".global", ".space", ".align\t2",".align\t4", "-mthumb-interwork",
681
    "pe-arm-little", bfd_arch_arm,
682
    thumb_jtab, sizeof (thumb_jtab), 12,
683
    0, 0, 0, 0, 0, 0
684
  }
685
  ,
686
#define MARM_INTERWORK 4
687
  {
688
    "arm_interwork", ".byte", ".short", ".long", ".asciz", "@",
689
    "ldr\tip,[pc]\n\tldr\tip,[ip]\n\tbx\tip\n\t.long",
690
    ".global", ".space", ".align\t2",".align\t4", "-mthumb-interwork",
691
    "pe-arm-little", bfd_arch_arm,
692
    arm_interwork_jtab, sizeof (arm_interwork_jtab), 12,
693
    0, 0, 0, 0, 0, 0
694
  }
695
  ,
696
  {
697
#define MMCORE_BE 5
698
    "mcore-be", ".byte", ".short", ".long", ".asciz", "//",
699
    "lrw r1,[1f]\n\tld.w r1,(r1,0)\n\tjmp r1\n\tnop\n1:.long",
700
    ".global", ".space", ".align\t2",".align\t4", "",
701
    "pe-mcore-big", bfd_arch_mcore,
702
    mcore_be_jtab, sizeof (mcore_be_jtab), 8,
703
    0, 0, 0, 0, 0, 0
704
  }
705
  ,
706
  {
707
#define MMCORE_LE 6
708
    "mcore-le", ".byte", ".short", ".long", ".asciz", "//",
709
    "lrw r1,[1f]\n\tld.w r1,(r1,0)\n\tjmp r1\n\tnop\n1:.long",
710
    ".global", ".space", ".align\t2",".align\t4", "-EL",
711
    "pe-mcore-little", bfd_arch_mcore,
712
    mcore_le_jtab, sizeof (mcore_le_jtab), 8,
713
    0, 0, 0, 0, 0, 0
714
  }
715
  ,
716
  {
717
#define MMCORE_ELF 7
718
    "mcore-elf-be", ".byte", ".short", ".long", ".asciz", "//",
719
    "lrw r1,[1f]\n\tld.w r1,(r1,0)\n\tjmp r1\n\tnop\n1:.long",
720
    ".global", ".space", ".align\t2",".align\t4", "",
721
    "elf32-mcore-big", bfd_arch_mcore,
722
    mcore_be_jtab, sizeof (mcore_be_jtab), 8,
723
    0, 0, 0, 0, 0, 0
724
  }
725
  ,
726
  {
727
#define MMCORE_ELF_LE 8
728
    "mcore-elf-le", ".byte", ".short", ".long", ".asciz", "//",
729
    "lrw r1,[1f]\n\tld.w r1,(r1,0)\n\tjmp r1\n\tnop\n1:.long",
730
    ".global", ".space", ".align\t2",".align\t4", "-EL",
731
    "elf32-mcore-little", bfd_arch_mcore,
732
    mcore_le_jtab, sizeof (mcore_le_jtab), 8,
733
    0, 0, 0, 0, 0, 0
734
  }
735
  ,
736
  {
737
#define MARM_EPOC 9
738
    "arm-epoc", ".byte", ".short", ".long", ".asciz", "@",
739
    "ldr\tip,[pc]\n\tldr\tpc,[ip]\n\t.long",
740
    ".global", ".space", ".align\t2",".align\t4", "",
741
    "epoc-pe-arm-little", bfd_arch_arm,
742
    arm_jtab, sizeof (arm_jtab), 8,
743
    0, 0, 0, 0, 0, 0
744
  }
745
  ,
746
  {
747
#define MARM_WINCE 10
748
    "arm-wince", ".byte", ".short", ".long", ".asciz", "@",
749
    "ldr\tip,[pc]\n\tldr\tpc,[ip]\n\t.long",
750
    ".global", ".space", ".align\t2",".align\t4", "-mapcs-32",
751
    "pe-arm-wince-little", bfd_arch_arm,
752
    arm_jtab, sizeof (arm_jtab), 8,
753
    0, 0, 0, 0, 0, 0
754
  }
755
  ,
756
  {
757
#define MX86 11
758
    "i386:x86-64", ".byte", ".short", ".long", ".asciz", "#",
759
    "jmp *", ".global", ".space", ".align\t2",".align\t4", "",
760
    "pe-x86-64",bfd_arch_i386,
761
    i386_jtab, sizeof (i386_jtab), 2,
762 166 khays
    i386_x64_dljtab, sizeof (i386_x64_dljtab), 2, 9, 14, i386_x64_trampoline
763 15 khays
  }
764
  ,
765
  { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
766
};
767
 
768
typedef struct dlist
769
{
770
  char *text;
771
  struct dlist *next;
772
}
773
dlist_type;
774
 
775
typedef struct export
776
{
777
  const char *name;
778
  const char *internal_name;
779
  const char *import_name;
780
  const char *its_name;
781
  int ordinal;
782
  int constant;
783
  int noname;           /* Don't put name in image file.  */
784
  int private;  /* Don't put reference in import lib.  */
785
  int data;
786
  int hint;
787
  int forward;  /* Number of forward label, 0 means no forward.  */
788
  struct export *next;
789
}
790
export_type;
791
 
792
/* A list of symbols which we should not export.  */
793
 
794
struct string_list
795
{
796
  struct string_list *next;
797
  char *string;
798
};
799
 
800
static struct string_list *excludes;
801
 
802
static const char *rvaafter (int);
803
static const char *rvabefore (int);
804
static const char *asm_prefix (int, const char *);
805
static void process_def_file (const char *);
806
static void new_directive (char *);
807
static void append_import (const char *, const char *, int, const char *);
808
static void run (const char *, char *);
809
static void scan_drectve_symbols (bfd *);
810
static void scan_filtered_symbols (bfd *, void *, long, unsigned int);
811
static void add_excludes (const char *);
812
static bfd_boolean match_exclude (const char *);
813
static void set_default_excludes (void);
814
static long filter_symbols (bfd *, void *, long, unsigned int);
815
static void scan_all_symbols (bfd *);
816
static void scan_open_obj_file (bfd *);
817
static void scan_obj_file (const char *);
818
static void dump_def_info (FILE *);
819
static int sfunc (const void *, const void *);
820
static void flush_page (FILE *, bfd_vma *, bfd_vma, int);
821
static void gen_def_file (void);
822
static void generate_idata_ofile (FILE *);
823
static void assemble_file (const char *, const char *);
824
static void gen_exp_file (void);
825
static const char *xlate (const char *);
826
static char *make_label (const char *, const char *);
827
static char *make_imp_label (const char *, const char *);
828
static bfd *make_one_lib_file (export_type *, int, int);
829
static bfd *make_head (void);
830
static bfd *make_tail (void);
831
static bfd *make_delay_head (void);
832
static void gen_lib_file (int);
833
static void dll_name_list_append (dll_name_list_type *, bfd_byte *);
834
static int  dll_name_list_count (dll_name_list_type *);
835
static void dll_name_list_print (dll_name_list_type *);
836
static void dll_name_list_free_contents (dll_name_list_node_type *);
837
static void dll_name_list_free (dll_name_list_type *);
838
static dll_name_list_type * dll_name_list_create (void);
839
static void identify_dll_for_implib (void);
840
static void identify_search_archive
841
  (bfd *, void (*) (bfd *, bfd *, void *),  void *);
842
static void identify_search_member (bfd *, bfd *, void *);
843
static bfd_boolean identify_process_section_p (asection *, bfd_boolean);
844
static void identify_search_section (bfd *, asection *, void *);
845
static void identify_member_contains_symname (bfd *, bfd  *, void *);
846
 
847
static int pfunc (const void *, const void *);
848
static int nfunc (const void *, const void *);
849
static void remove_null_names (export_type **);
850
static void process_duplicates (export_type **);
851
static void fill_ordinals (export_type **);
852
static void mangle_defs (void);
853
static void usage (FILE *, int);
854
static void inform (const char *, ...) ATTRIBUTE_PRINTF_1;
855
static void set_dll_name_from_def (const char *name, char is_dll);
856
 
857
static char *
858
prefix_encode (char *start, unsigned code)
859
{
860
  static char alpha[26] = "abcdefghijklmnopqrstuvwxyz";
861
  static char buf[32];
862
  char *p;
863
  strcpy (buf, start);
864
  p = strchr (buf, '\0');
865
  do
866
    *p++ = alpha[code % sizeof (alpha)];
867
  while ((code /= sizeof (alpha)) != 0);
868
  *p = '\0';
869
  return buf;
870
}
871
 
872
static char *
873
dlltmp (char **buf, const char *fmt)
874
{
875
  if (!*buf)
876
    {
877
      *buf = malloc (strlen (tmp_prefix) + 64);
878
      sprintf (*buf, fmt, tmp_prefix);
879
    }
880
  return *buf;
881
}
882
 
883
static void
884
inform VPARAMS ((const char * message, ...))
885
{
886
  VA_OPEN (args, message);
887
  VA_FIXEDARG (args, const char *, message);
888
 
889
  if (!verbose)
890
    return;
891
 
892
  report (message, args);
893
 
894
  VA_CLOSE (args);
895
}
896
 
897
static const char *
898
rvaafter (int mach)
899
{
900
  switch (mach)
901
    {
902
    case MARM:
903
    case M386:
904
    case MX86:
905
    case MPPC:
906
    case MTHUMB:
907
    case MARM_INTERWORK:
908
    case MMCORE_BE:
909
    case MMCORE_LE:
910
    case MMCORE_ELF:
911
    case MMCORE_ELF_LE:
912
    case MARM_EPOC:
913
    case MARM_WINCE:
914
      break;
915
    default:
916
      /* xgettext:c-format */
917
      fatal (_("Internal error: Unknown machine type: %d"), mach);
918
      break;
919
    }
920
  return "";
921
}
922
 
923
static const char *
924
rvabefore (int mach)
925
{
926
  switch (mach)
927
    {
928
    case MARM:
929
    case M386:
930
    case MX86:
931
    case MPPC:
932
    case MTHUMB:
933
    case MARM_INTERWORK:
934
    case MMCORE_BE:
935
    case MMCORE_LE:
936
    case MMCORE_ELF:
937
    case MMCORE_ELF_LE:
938
    case MARM_EPOC:
939
    case MARM_WINCE:
940
      return ".rva\t";
941
    default:
942
      /* xgettext:c-format */
943
      fatal (_("Internal error: Unknown machine type: %d"), mach);
944
      break;
945
    }
946
  return "";
947
}
948
 
949
static const char *
950
asm_prefix (int mach, const char *name)
951
{
952
  switch (mach)
953
    {
954
    case MARM:
955
    case MPPC:
956
    case MTHUMB:
957
    case MARM_INTERWORK:
958
    case MMCORE_BE:
959
    case MMCORE_LE:
960
    case MMCORE_ELF:
961
    case MMCORE_ELF_LE:
962
    case MARM_EPOC:
963
    case MARM_WINCE:
964
      break;
965
    case M386:
966
    case MX86:
967
      /* Symbol names starting with ? do not have a leading underscore. */
968
      if ((name && *name == '?') || leading_underscore == 0)
969
        break;
970
      else
971
        return "_";
972
    default:
973
      /* xgettext:c-format */
974
      fatal (_("Internal error: Unknown machine type: %d"), mach);
975
      break;
976
    }
977
  return "";
978
}
979
 
980
#define ASM_BYTE                mtable[machine].how_byte
981
#define ASM_SHORT               mtable[machine].how_short
982
#define ASM_LONG                mtable[machine].how_long
983
#define ASM_TEXT                mtable[machine].how_asciz
984
#define ASM_C                   mtable[machine].how_comment
985
#define ASM_JUMP                mtable[machine].how_jump
986
#define ASM_GLOBAL              mtable[machine].how_global
987
#define ASM_SPACE               mtable[machine].how_space
988
#define ASM_ALIGN_SHORT         mtable[machine].how_align_short
989
#define ASM_RVA_BEFORE          rvabefore (machine)
990
#define ASM_RVA_AFTER           rvaafter (machine)
991
#define ASM_PREFIX(NAME)        asm_prefix (machine, (NAME))
992
#define ASM_ALIGN_LONG          mtable[machine].how_align_long
993
#define HOW_BFD_READ_TARGET     0  /* Always default.  */
994
#define HOW_BFD_WRITE_TARGET    mtable[machine].how_bfd_target
995
#define HOW_BFD_ARCH            mtable[machine].how_bfd_arch
996
#define HOW_JTAB                (delay ? mtable[machine].how_dljtab \
997
                                        : mtable[machine].how_jtab)
998
#define HOW_JTAB_SIZE           (delay ? mtable[machine].how_dljtab_size \
999
                                        : mtable[machine].how_jtab_size)
1000
#define HOW_JTAB_ROFF           (delay ? mtable[machine].how_dljtab_roff1 \
1001
                                        : mtable[machine].how_jtab_roff)
1002
#define HOW_JTAB_ROFF2          (delay ? mtable[machine].how_dljtab_roff2 : 0)
1003
#define HOW_JTAB_ROFF3          (delay ? mtable[machine].how_dljtab_roff3 : 0)
1004
#define ASM_SWITCHES            mtable[machine].how_default_as_switches
1005
 
1006
static char **oav;
1007
 
1008
static void
1009
process_def_file (const char *name)
1010
{
1011
  FILE *f = fopen (name, FOPEN_RT);
1012
 
1013
  if (!f)
1014
    /* xgettext:c-format */
1015
    fatal (_("Can't open def file: %s"), name);
1016
 
1017
  yyin = f;
1018
 
1019
  /* xgettext:c-format */
1020
  inform (_("Processing def file: %s"), name);
1021
 
1022
  yyparse ();
1023
 
1024
  inform (_("Processed def file"));
1025
}
1026
 
1027
/**********************************************************************/
1028
 
1029
/* Communications with the parser.  */
1030
 
1031
static int d_nfuncs;            /* Number of functions exported.  */
1032
static int d_named_nfuncs;      /* Number of named functions exported.  */
1033
static int d_low_ord;           /* Lowest ordinal index.  */
1034
static int d_high_ord;          /* Highest ordinal index.  */
1035
static export_type *d_exports;  /* List of exported functions.  */
1036
static export_type **d_exports_lexically;  /* Vector of exported functions in alpha order.  */
1037
static dlist_type *d_list;      /* Descriptions.  */
1038
static dlist_type *a_list;      /* Stuff to go in directives.  */
1039
static int d_nforwards = 0;      /* Number of forwarded exports.  */
1040
 
1041
static int d_is_dll;
1042
static int d_is_exe;
1043
 
1044
int
1045
yyerror (const char * err ATTRIBUTE_UNUSED)
1046
{
1047
  /* xgettext:c-format */
1048
  non_fatal (_("Syntax error in def file %s:%d"), def_file, linenumber);
1049
 
1050
  return 0;
1051
}
1052
 
1053
void
1054
def_exports (const char *name, const char *internal_name, int ordinal,
1055
             int noname, int constant, int data, int private,
1056
             const char *its_name)
1057
{
1058
  struct export *p = (struct export *) xmalloc (sizeof (*p));
1059
 
1060
  p->name = name;
1061
  p->internal_name = internal_name ? internal_name : name;
1062
  p->its_name = its_name;
1063
  p->import_name = name;
1064
  p->ordinal = ordinal;
1065
  p->constant = constant;
1066
  p->noname = noname;
1067
  p->private = private;
1068
  p->data = data;
1069
  p->next = d_exports;
1070
  d_exports = p;
1071
  d_nfuncs++;
1072
 
1073
  if ((internal_name != NULL)
1074
      && (strchr (internal_name, '.') != NULL))
1075
    p->forward = ++d_nforwards;
1076
  else
1077
    p->forward = 0; /* no forward */
1078
}
1079
 
1080
static void
1081
set_dll_name_from_def (const char *name, char is_dll)
1082
{
1083
  const char *image_basename = lbasename (name);
1084
  if (image_basename != name)
1085
    non_fatal (_("%s: Path components stripped from image name, '%s'."),
1086
              def_file, name);
1087
  /* Append the default suffix, if none specified.  */
1088
  if (strchr (image_basename, '.') == 0)
1089
    {
1090
      const char * suffix = is_dll ? ".dll" : ".exe";
1091
 
1092
      dll_name = xmalloc (strlen (image_basename) + strlen (suffix) + 1);
1093
      sprintf (dll_name, "%s%s", image_basename, suffix);
1094
    }
1095
  else
1096
    dll_name = xstrdup (image_basename);
1097
}
1098
 
1099
void
1100
def_name (const char *name, int base)
1101
{
1102
  /* xgettext:c-format */
1103
  inform (_("NAME: %s base: %x"), name, base);
1104
 
1105
  if (d_is_dll)
1106
    non_fatal (_("Can't have LIBRARY and NAME"));
1107
 
1108
  if (dll_name_set_by_exp_name && name && *name != 0)
1109
    {
1110
      dll_name = NULL;
1111
      dll_name_set_by_exp_name = 0;
1112
    }
1113
  /* If --dllname not provided, use the one in the DEF file.
1114
     FIXME: Is this appropriate for executables?  */
1115
  if (!dll_name)
1116
    set_dll_name_from_def (name, 0);
1117
  d_is_exe = 1;
1118
}
1119
 
1120
void
1121
def_library (const char *name, int base)
1122
{
1123
  /* xgettext:c-format */
1124
  inform (_("LIBRARY: %s base: %x"), name, base);
1125
 
1126
  if (d_is_exe)
1127
    non_fatal (_("Can't have LIBRARY and NAME"));
1128
 
1129
  if (dll_name_set_by_exp_name && name && *name != 0)
1130
    {
1131
      dll_name = NULL;
1132
      dll_name_set_by_exp_name = 0;
1133
    }
1134
 
1135
  /* If --dllname not provided, use the one in the DEF file.  */
1136
  if (!dll_name)
1137
    set_dll_name_from_def (name, 1);
1138
  d_is_dll = 1;
1139
}
1140
 
1141
void
1142
def_description (const char *desc)
1143
{
1144
  dlist_type *d = (dlist_type *) xmalloc (sizeof (dlist_type));
1145
  d->text = xstrdup (desc);
1146
  d->next = d_list;
1147
  d_list = d;
1148
}
1149
 
1150
static void
1151
new_directive (char *dir)
1152
{
1153
  dlist_type *d = (dlist_type *) xmalloc (sizeof (dlist_type));
1154
  d->text = xstrdup (dir);
1155
  d->next = a_list;
1156
  a_list = d;
1157
}
1158
 
1159
void
1160
def_heapsize (int reserve, int commit)
1161
{
1162
  char b[200];
1163
  if (commit > 0)
1164
    sprintf (b, "-heap 0x%x,0x%x ", reserve, commit);
1165
  else
1166
    sprintf (b, "-heap 0x%x ", reserve);
1167
  new_directive (xstrdup (b));
1168
}
1169
 
1170
void
1171
def_stacksize (int reserve, int commit)
1172
{
1173
  char b[200];
1174
  if (commit > 0)
1175
    sprintf (b, "-stack 0x%x,0x%x ", reserve, commit);
1176
  else
1177
    sprintf (b, "-stack 0x%x ", reserve);
1178
  new_directive (xstrdup (b));
1179
}
1180
 
1181
/* append_import simply adds the given import definition to the global
1182
   import_list.  It is used by def_import.  */
1183
 
1184
static void
1185
append_import (const char *symbol_name, const char *dllname, int func_ordinal,
1186
               const char *its_name)
1187
{
1188
  iheadtype **pq;
1189
  iheadtype *q;
1190
 
1191
  for (pq = &import_list; *pq != NULL; pq = &(*pq)->next)
1192
    {
1193
      if (strcmp ((*pq)->dllname, dllname) == 0)
1194
        {
1195
          q = *pq;
1196
          q->functail->next = xmalloc (sizeof (ifunctype));
1197
          q->functail = q->functail->next;
1198
          q->functail->ord  = func_ordinal;
1199
          q->functail->name = xstrdup (symbol_name);
1200
          q->functail->its_name = (its_name ? xstrdup (its_name) : NULL);
1201
          q->functail->next = NULL;
1202
          q->nfuncs++;
1203
          return;
1204
        }
1205
    }
1206
 
1207
  q = xmalloc (sizeof (iheadtype));
1208
  q->dllname = xstrdup (dllname);
1209
  q->nfuncs = 1;
1210
  q->funchead = xmalloc (sizeof (ifunctype));
1211
  q->functail = q->funchead;
1212
  q->next = NULL;
1213
  q->functail->name = xstrdup (symbol_name);
1214
  q->functail->its_name = (its_name ? xstrdup (its_name) : NULL);
1215
  q->functail->ord  = func_ordinal;
1216
  q->functail->next = NULL;
1217
 
1218
  *pq = q;
1219
}
1220
 
1221
/* def_import is called from within defparse.y when an IMPORT
1222
   declaration is encountered.  Depending on the form of the
1223
   declaration, the module name may or may not need ".dll" to be
1224
   appended to it, the name of the function may be stored in internal
1225
   or entry, and there may or may not be an ordinal value associated
1226
   with it.  */
1227
 
1228
/* A note regarding the parse modes:
1229
   In defparse.y we have to accept import declarations which follow
1230
   any one of the following forms:
1231
     <func_name_in_app> = <dll_name>.<func_name_in_dll>
1232
     <func_name_in_app> = <dll_name>.<number>
1233
     <dll_name>.<func_name_in_dll>
1234
     <dll_name>.<number>
1235
   Furthermore, the dll's name may or may not end with ".dll", which
1236
   complicates the parsing a little.  Normally the dll's name is
1237
   passed to def_import() in the "module" parameter, but when it ends
1238
   with ".dll" it gets passed in "module" sans ".dll" and that needs
1239
   to be reappended.
1240
 
1241
  def_import gets five parameters:
1242
  APP_NAME - the name of the function in the application, if
1243
             present, or NULL if not present.
1244
  MODULE   - the name of the dll, possibly sans extension (ie, '.dll').
1245
  DLLEXT   - the extension of the dll, if present, NULL if not present.
1246
  ENTRY    - the name of the function in the dll, if present, or NULL.
1247
  ORD_VAL  - the numerical tag of the function in the dll, if present,
1248
             or NULL.  Exactly one of <entry> or <ord_val> must be
1249
             present (i.e., not NULL).  */
1250
 
1251
void
1252
def_import (const char *app_name, const char *module, const char *dllext,
1253
            const char *entry, int ord_val, const char *its_name)
1254
{
1255
  const char *application_name;
1256
  char *buf;
1257
 
1258
  if (entry != NULL)
1259
    application_name = entry;
1260
  else
1261
    {
1262
      if (app_name != NULL)
1263
        application_name = app_name;
1264
      else
1265
        application_name = "";
1266
    }
1267
 
1268
  if (dllext != NULL)
1269
    {
1270
      buf = (char *) alloca (strlen (module) + strlen (dllext) + 2);
1271
      sprintf (buf, "%s.%s", module, dllext);
1272
      module = buf;
1273
    }
1274
 
1275
  append_import (application_name, module, ord_val, its_name);
1276
}
1277
 
1278
void
1279
def_version (int major, int minor)
1280
{
1281 163 khays
  printf (_("VERSION %d.%d\n"), major, minor);
1282 15 khays
}
1283
 
1284
void
1285
def_section (const char *name, int attr)
1286
{
1287
  char buf[200];
1288
  char atts[5];
1289
  char *d = atts;
1290
  if (attr & 1)
1291
    *d++ = 'R';
1292
 
1293
  if (attr & 2)
1294
    *d++ = 'W';
1295
  if (attr & 4)
1296
    *d++ = 'X';
1297
  if (attr & 8)
1298
    *d++ = 'S';
1299
  *d++ = 0;
1300
  sprintf (buf, "-attr %s %s", name, atts);
1301
  new_directive (xstrdup (buf));
1302
}
1303
 
1304
void
1305
def_code (int attr)
1306
{
1307
 
1308
  def_section ("CODE", attr);
1309
}
1310
 
1311
void
1312
def_data (int attr)
1313
{
1314
  def_section ("DATA", attr);
1315
}
1316
 
1317
/**********************************************************************/
1318
 
1319
static void
1320
run (const char *what, char *args)
1321
{
1322
  char *s;
1323
  int pid, wait_status;
1324
  int i;
1325
  const char **argv;
1326
  char *errmsg_fmt, *errmsg_arg;
1327
  char *temp_base = choose_temp_base ();
1328
 
1329 163 khays
  inform (_("run: %s %s"), what, args);
1330 15 khays
 
1331
  /* Count the args */
1332
  i = 0;
1333
  for (s = args; *s; s++)
1334
    if (*s == ' ')
1335
      i++;
1336
  i++;
1337
  argv = alloca (sizeof (char *) * (i + 3));
1338
  i = 0;
1339
  argv[i++] = what;
1340
  s = args;
1341
  while (1)
1342
    {
1343
      while (*s == ' ')
1344
        ++s;
1345
      argv[i++] = s;
1346
      while (*s != ' ' && *s != 0)
1347
        s++;
1348
      if (*s == 0)
1349
        break;
1350
      *s++ = 0;
1351
    }
1352
  argv[i++] = NULL;
1353
 
1354
  pid = pexecute (argv[0], (char * const *) argv, program_name, temp_base,
1355
                  &errmsg_fmt, &errmsg_arg, PEXECUTE_ONE | PEXECUTE_SEARCH);
1356
 
1357
  if (pid == -1)
1358
    {
1359
      inform ("%s", strerror (errno));
1360
 
1361
      fatal (errmsg_fmt, errmsg_arg);
1362
    }
1363
 
1364
  pid = pwait (pid, & wait_status, 0);
1365
 
1366
  if (pid == -1)
1367
    {
1368
      /* xgettext:c-format */
1369
      fatal (_("wait: %s"), strerror (errno));
1370
    }
1371
  else if (WIFSIGNALED (wait_status))
1372
    {
1373
      /* xgettext:c-format */
1374
      fatal (_("subprocess got fatal signal %d"), WTERMSIG (wait_status));
1375
    }
1376
  else if (WIFEXITED (wait_status))
1377
    {
1378
      if (WEXITSTATUS (wait_status) != 0)
1379
        /* xgettext:c-format */
1380
        non_fatal (_("%s exited with status %d"),
1381
                   what, WEXITSTATUS (wait_status));
1382
    }
1383
  else
1384
    abort ();
1385
}
1386
 
1387
/* Look for a list of symbols to export in the .drectve section of
1388
   ABFD.  Pass each one to def_exports.  */
1389
 
1390
static void
1391
scan_drectve_symbols (bfd *abfd)
1392
{
1393
  asection * s;
1394
  int        size;
1395
  char *     buf;
1396
  char *     p;
1397
  char *     e;
1398
 
1399
  /* Look for .drectve's */
1400
  s = bfd_get_section_by_name (abfd, DRECTVE_SECTION_NAME);
1401
 
1402
  if (s == NULL)
1403
    return;
1404
 
1405
  size = bfd_get_section_size (s);
1406
  buf  = xmalloc (size);
1407
 
1408
  bfd_get_section_contents (abfd, s, buf, 0, size);
1409
 
1410
  /* xgettext:c-format */
1411
  inform (_("Sucking in info from %s section in %s"),
1412
          DRECTVE_SECTION_NAME, bfd_get_filename (abfd));
1413
 
1414
  /* Search for -export: strings. The exported symbols can optionally
1415
     have type tags (eg., -export:foo,data), so handle those as well.
1416
     Currently only data tag is supported.  */
1417
  p = buf;
1418
  e = buf + size;
1419
  while (p < e)
1420
    {
1421
      if (p[0] == '-'
1422
          && CONST_STRNEQ (p, "-export:"))
1423
        {
1424
          char * name;
1425
          char * c;
1426
          flagword flags = BSF_FUNCTION;
1427
 
1428
          p += 8;
1429
          /* Do we have a quoted export?  */
1430
          if (*p == '"')
1431
            {
1432
              p++;
1433
              name = p;
1434
              while (p < e && *p != '"')
1435
                ++p;
1436
            }
1437
          else
1438
            {
1439
              name = p;
1440
              while (p < e && *p != ',' && *p != ' ' && *p != '-')
1441
                p++;
1442
            }
1443
          c = xmalloc (p - name + 1);
1444
          memcpy (c, name, p - name);
1445
          c[p - name] = 0;
1446
          /* Advance over trailing quote.  */
1447
          if (p < e && *p == '"')
1448
            ++p;
1449
          if (p < e && *p == ',')       /* found type tag.  */
1450
            {
1451
              char *tag_start = ++p;
1452
              while (p < e && *p != ' ' && *p != '-')
1453
                p++;
1454
              if (CONST_STRNEQ (tag_start, "data"))
1455
                flags &= ~BSF_FUNCTION;
1456
            }
1457
 
1458
          /* FIXME: The 5th arg is for the `constant' field.
1459
             What should it be?  Not that it matters since it's not
1460
             currently useful.  */
1461
          def_exports (c, 0, -1, 0, 0, ! (flags & BSF_FUNCTION), 0, NULL);
1462
 
1463
          if (add_stdcall_alias && strchr (c, '@'))
1464
            {
1465
              int lead_at = (*c == '@') ;
1466
              char *exported_name = xstrdup (c + lead_at);
1467
              char *atsym = strchr (exported_name, '@');
1468
              *atsym = '\0';
1469
              /* Note: stdcall alias symbols can never be data.  */
1470
              def_exports (exported_name, xstrdup (c), -1, 0, 0, 0, 0, NULL);
1471
            }
1472
        }
1473
      else
1474
        p++;
1475
    }
1476
  free (buf);
1477
}
1478
 
1479
/* Look through the symbols in MINISYMS, and add each one to list of
1480
   symbols to export.  */
1481
 
1482
static void
1483
scan_filtered_symbols (bfd *abfd, void *minisyms, long symcount,
1484
                       unsigned int size)
1485
{
1486
  asymbol *store;
1487
  bfd_byte *from, *fromend;
1488
 
1489
  store = bfd_make_empty_symbol (abfd);
1490
  if (store == NULL)
1491
    bfd_fatal (bfd_get_filename (abfd));
1492
 
1493
  from = (bfd_byte *) minisyms;
1494
  fromend = from + symcount * size;
1495
  for (; from < fromend; from += size)
1496
    {
1497
      asymbol *sym;
1498
      const char *symbol_name;
1499
 
1500
      sym = bfd_minisymbol_to_symbol (abfd, FALSE, from, store);
1501
      if (sym == NULL)
1502
        bfd_fatal (bfd_get_filename (abfd));
1503
 
1504
      symbol_name = bfd_asymbol_name (sym);
1505
      if (bfd_get_symbol_leading_char (abfd) == symbol_name[0])
1506
        ++symbol_name;
1507
 
1508
      def_exports (xstrdup (symbol_name) , 0, -1, 0, 0,
1509
                   ! (sym->flags & BSF_FUNCTION), 0, NULL);
1510
 
1511
      if (add_stdcall_alias && strchr (symbol_name, '@'))
1512
        {
1513
          int lead_at = (*symbol_name == '@');
1514
          char *exported_name = xstrdup (symbol_name + lead_at);
1515
          char *atsym = strchr (exported_name, '@');
1516
          *atsym = '\0';
1517
          /* Note: stdcall alias symbols can never be data.  */
1518
          def_exports (exported_name, xstrdup (symbol_name), -1, 0, 0, 0, 0, NULL);
1519
        }
1520
    }
1521
}
1522
 
1523
/* Add a list of symbols to exclude.  */
1524
 
1525
static void
1526
add_excludes (const char *new_excludes)
1527
{
1528
  char *local_copy;
1529
  char *exclude_string;
1530
 
1531
  local_copy = xstrdup (new_excludes);
1532
 
1533
  exclude_string = strtok (local_copy, ",:");
1534
  for (; exclude_string; exclude_string = strtok (NULL, ",:"))
1535
    {
1536
      struct string_list *new_exclude;
1537
 
1538
      new_exclude = ((struct string_list *)
1539
                     xmalloc (sizeof (struct string_list)));
1540
      new_exclude->string = (char *) xmalloc (strlen (exclude_string) + 2);
1541
      /* Don't add a leading underscore for fastcall symbols.  */
1542
      if (*exclude_string == '@')
1543
        sprintf (new_exclude->string, "%s", exclude_string);
1544
      else
1545
        sprintf (new_exclude->string, "%s%s", (!leading_underscore ? "" : "_"),
1546
                 exclude_string);
1547
      new_exclude->next = excludes;
1548
      excludes = new_exclude;
1549
 
1550
      /* xgettext:c-format */
1551
      inform (_("Excluding symbol: %s"), exclude_string);
1552
    }
1553
 
1554
  free (local_copy);
1555
}
1556
 
1557
/* See if STRING is on the list of symbols to exclude.  */
1558
 
1559
static bfd_boolean
1560
match_exclude (const char *string)
1561
{
1562
  struct string_list *excl_item;
1563
 
1564
  for (excl_item = excludes; excl_item; excl_item = excl_item->next)
1565
    if (strcmp (string, excl_item->string) == 0)
1566
      return TRUE;
1567
  return FALSE;
1568
}
1569
 
1570
/* Add the default list of symbols to exclude.  */
1571
 
1572
static void
1573
set_default_excludes (void)
1574
{
1575
  add_excludes (default_excludes);
1576
}
1577
 
1578
/* Choose which symbols to export.  */
1579
 
1580
static long
1581
filter_symbols (bfd *abfd, void *minisyms, long symcount, unsigned int size)
1582
{
1583
  bfd_byte *from, *fromend, *to;
1584
  asymbol *store;
1585
 
1586
  store = bfd_make_empty_symbol (abfd);
1587
  if (store == NULL)
1588
    bfd_fatal (bfd_get_filename (abfd));
1589
 
1590
  from = (bfd_byte *) minisyms;
1591
  fromend = from + symcount * size;
1592
  to = (bfd_byte *) minisyms;
1593
 
1594
  for (; from < fromend; from += size)
1595
    {
1596
      int keep = 0;
1597
      asymbol *sym;
1598
 
1599
      sym = bfd_minisymbol_to_symbol (abfd, FALSE, (const void *) from, store);
1600
      if (sym == NULL)
1601
        bfd_fatal (bfd_get_filename (abfd));
1602
 
1603
      /* Check for external and defined only symbols.  */
1604
      keep = (((sym->flags & BSF_GLOBAL) != 0
1605
               || (sym->flags & BSF_WEAK) != 0
1606
               || bfd_is_com_section (sym->section))
1607
              && ! bfd_is_und_section (sym->section));
1608
 
1609
      keep = keep && ! match_exclude (sym->name);
1610
 
1611
      if (keep)
1612
        {
1613
          memcpy (to, from, size);
1614
          to += size;
1615
        }
1616
    }
1617
 
1618
  return (to - (bfd_byte *) minisyms) / size;
1619
}
1620
 
1621
/* Export all symbols in ABFD, except for ones we were told not to
1622
   export.  */
1623
 
1624
static void
1625
scan_all_symbols (bfd *abfd)
1626
{
1627
  long symcount;
1628
  void *minisyms;
1629
  unsigned int size;
1630
 
1631
  /* Ignore bfds with an import descriptor table.  We assume that any
1632
     such BFD contains symbols which are exported from another DLL,
1633
     and we don't want to reexport them from here.  */
1634
  if (bfd_get_section_by_name (abfd, ".idata$4"))
1635
    return;
1636
 
1637
  if (! (bfd_get_file_flags (abfd) & HAS_SYMS))
1638
    {
1639
      /* xgettext:c-format */
1640
      non_fatal (_("%s: no symbols"), bfd_get_filename (abfd));
1641
      return;
1642
    }
1643
 
1644
  symcount = bfd_read_minisymbols (abfd, FALSE, &minisyms, &size);
1645
  if (symcount < 0)
1646
    bfd_fatal (bfd_get_filename (abfd));
1647
 
1648
  if (symcount == 0)
1649
    {
1650
      /* xgettext:c-format */
1651
      non_fatal (_("%s: no symbols"), bfd_get_filename (abfd));
1652
      return;
1653
    }
1654
 
1655
  /* Discard the symbols we don't want to export.  It's OK to do this
1656
     in place; we'll free the storage anyway.  */
1657
 
1658
  symcount = filter_symbols (abfd, minisyms, symcount, size);
1659
  scan_filtered_symbols (abfd, minisyms, symcount, size);
1660
 
1661
  free (minisyms);
1662
}
1663
 
1664
/* Look at the object file to decide which symbols to export.  */
1665
 
1666
static void
1667
scan_open_obj_file (bfd *abfd)
1668
{
1669
  if (export_all_symbols)
1670
    scan_all_symbols (abfd);
1671
  else
1672
    scan_drectve_symbols (abfd);
1673
 
1674
  /* FIXME: we ought to read in and block out the base relocations.  */
1675
 
1676
  /* xgettext:c-format */
1677
  inform (_("Done reading %s"), bfd_get_filename (abfd));
1678
}
1679
 
1680
static void
1681
scan_obj_file (const char *filename)
1682
{
1683
  bfd * f = bfd_openr (filename, 0);
1684
 
1685
  if (!f)
1686
    /* xgettext:c-format */
1687
    fatal (_("Unable to open object file: %s: %s"), filename, bfd_get_errmsg ());
1688
 
1689
  /* xgettext:c-format */
1690
  inform (_("Scanning object file %s"), filename);
1691
 
1692
  if (bfd_check_format (f, bfd_archive))
1693
    {
1694
      bfd *arfile = bfd_openr_next_archived_file (f, 0);
1695
      while (arfile)
1696
        {
1697
          if (bfd_check_format (arfile, bfd_object))
1698
            scan_open_obj_file (arfile);
1699
          bfd_close (arfile);
1700
          arfile = bfd_openr_next_archived_file (f, arfile);
1701
        }
1702
 
1703
#ifdef DLLTOOL_MCORE_ELF
1704
      if (mcore_elf_out_file)
1705
        inform (_("Cannot produce mcore-elf dll from archive file: %s"), filename);
1706
#endif
1707
    }
1708
  else if (bfd_check_format (f, bfd_object))
1709
    {
1710
      scan_open_obj_file (f);
1711
 
1712
#ifdef DLLTOOL_MCORE_ELF
1713
      if (mcore_elf_out_file)
1714
        mcore_elf_cache_filename (filename);
1715
#endif
1716
    }
1717
 
1718
  bfd_close (f);
1719
}
1720
 
1721
 
1722
 
1723
static void
1724
dump_def_info (FILE *f)
1725
{
1726
  int i;
1727
  export_type *exp;
1728
  fprintf (f, "%s ", ASM_C);
1729
  for (i = 0; oav[i]; i++)
1730
    fprintf (f, "%s ", oav[i]);
1731
  fprintf (f, "\n");
1732
  for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
1733
    {
1734
      fprintf (f, "%s  %d = %s %s @ %d %s%s%s%s%s%s\n",
1735
               ASM_C,
1736
               i,
1737
               exp->name,
1738
               exp->internal_name,
1739
               exp->ordinal,
1740
               exp->noname ? "NONAME " : "",
1741
               exp->private ? "PRIVATE " : "",
1742
               exp->constant ? "CONSTANT" : "",
1743
               exp->data ? "DATA" : "",
1744
               exp->its_name ? " ==" : "",
1745
               exp->its_name ? exp->its_name : "");
1746
    }
1747
}
1748
 
1749
/* Generate the .exp file.  */
1750
 
1751
static int
1752
sfunc (const void *a, const void *b)
1753
{
1754
  if (*(const bfd_vma *) a == *(const bfd_vma *) b)
1755
    return 0;
1756
 
1757
  return ((*(const bfd_vma *) a > *(const bfd_vma *) b) ? 1 : -1);
1758
}
1759
 
1760
static void
1761
flush_page (FILE *f, bfd_vma *need, bfd_vma page_addr, int on_page)
1762
{
1763
  int i;
1764
 
1765
  /* Flush this page.  */
1766
  fprintf (f, "\t%s\t0x%08x\t%s Starting RVA for chunk\n",
1767
           ASM_LONG,
1768
           (int) page_addr,
1769
           ASM_C);
1770
  fprintf (f, "\t%s\t0x%x\t%s Size of block\n",
1771
           ASM_LONG,
1772
           (on_page * 2) + (on_page & 1) * 2 + 8,
1773
           ASM_C);
1774
 
1775
  for (i = 0; i < on_page; i++)
1776
    {
1777
      bfd_vma needed = need[i];
1778
 
1779
      if (needed)
1780
        {
1781
          if (!create_for_pep)
1782
            {
1783
              /* Relocation via HIGHLOW.  */
1784
              needed = ((needed - page_addr) | 0x3000) & 0xffff;
1785
            }
1786
          else
1787
            {
1788
              /* Relocation via DIR64.  */
1789
              needed = ((needed - page_addr) | 0xa000) & 0xffff;
1790
            }
1791
        }
1792
 
1793
      fprintf (f, "\t%s\t0x%lx\n", ASM_SHORT, (long) needed);
1794
    }
1795
 
1796
  /* And padding */
1797
  if (on_page & 1)
1798
    fprintf (f, "\t%s\t0x%x\n", ASM_SHORT, 0 | 0x0000);
1799
}
1800
 
1801
static void
1802
gen_def_file (void)
1803
{
1804
  int i;
1805
  export_type *exp;
1806
 
1807
  inform (_("Adding exports to output file"));
1808
 
1809
  fprintf (output_def, ";");
1810
  for (i = 0; oav[i]; i++)
1811
    fprintf (output_def, " %s", oav[i]);
1812
 
1813
  fprintf (output_def, "\nEXPORTS\n");
1814
 
1815
  for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
1816
    {
1817
      char *quote = strchr (exp->name, '.') ? "\"" : "";
1818
      char *res = cplus_demangle (exp->internal_name, DMGL_ANSI | DMGL_PARAMS);
1819
 
1820
      if (res)
1821
        {
1822
          fprintf (output_def,";\t%s\n", res);
1823
          free (res);
1824
        }
1825
 
1826
      if (strcmp (exp->name, exp->internal_name) == 0)
1827
        {
1828
          fprintf (output_def, "\t%s%s%s @ %d%s%s%s%s%s\n",
1829
                   quote,
1830
                   exp->name,
1831
                   quote,
1832
                   exp->ordinal,
1833
                   exp->noname ? " NONAME" : "",
1834
                   exp->private ? "PRIVATE " : "",
1835
                   exp->data ? " DATA" : "",
1836
                   exp->its_name ? " ==" : "",
1837
                   exp->its_name ? exp->its_name : "");
1838
        }
1839
      else
1840
        {
1841
          char * quote1 = strchr (exp->internal_name, '.') ? "\"" : "";
1842
          /* char *alias =  */
1843
          fprintf (output_def, "\t%s%s%s = %s%s%s @ %d%s%s%s%s%s\n",
1844
                   quote,
1845
                   exp->name,
1846
                   quote,
1847
                   quote1,
1848
                   exp->internal_name,
1849
                   quote1,
1850
                   exp->ordinal,
1851
                   exp->noname ? " NONAME" : "",
1852
                   exp->private ? "PRIVATE " : "",
1853
                   exp->data ? " DATA" : "",
1854
                   exp->its_name ? " ==" : "",
1855
                   exp->its_name ? exp->its_name : "");
1856
        }
1857
    }
1858
 
1859
  inform (_("Added exports to output file"));
1860
}
1861
 
1862
/* generate_idata_ofile generates the portable assembly source code
1863
   for the idata sections.  It appends the source code to the end of
1864
   the file.  */
1865
 
1866
static void
1867
generate_idata_ofile (FILE *filvar)
1868
{
1869
  iheadtype *headptr;
1870
  ifunctype *funcptr;
1871
  int        headindex;
1872
  int        funcindex;
1873
  int        nheads;
1874
 
1875
  if (import_list == NULL)
1876
    return;
1877
 
1878
  fprintf (filvar, "%s Import data sections\n", ASM_C);
1879
  fprintf (filvar, "\n\t.section\t.idata$2\n");
1880
  fprintf (filvar, "\t%s\tdoi_idata\n", ASM_GLOBAL);
1881
  fprintf (filvar, "doi_idata:\n");
1882
 
1883
  nheads = 0;
1884
  for (headptr = import_list; headptr != NULL; headptr = headptr->next)
1885
    {
1886
      fprintf (filvar, "\t%slistone%d%s\t%s %s\n",
1887
               ASM_RVA_BEFORE, nheads, ASM_RVA_AFTER,
1888
               ASM_C, headptr->dllname);
1889
      fprintf (filvar, "\t%s\t0\n", ASM_LONG);
1890
      fprintf (filvar, "\t%s\t0\n", ASM_LONG);
1891
      fprintf (filvar, "\t%sdllname%d%s\n",
1892
               ASM_RVA_BEFORE, nheads, ASM_RVA_AFTER);
1893
      fprintf (filvar, "\t%slisttwo%d%s\n\n",
1894
               ASM_RVA_BEFORE, nheads, ASM_RVA_AFTER);
1895
      nheads++;
1896
    }
1897
 
1898
  fprintf (filvar, "\t%s\t0\n", ASM_LONG); /* NULL record at */
1899
  fprintf (filvar, "\t%s\t0\n", ASM_LONG); /* end of idata$2 */
1900
  fprintf (filvar, "\t%s\t0\n", ASM_LONG); /* section        */
1901
  fprintf (filvar, "\t%s\t0\n", ASM_LONG);
1902
  fprintf (filvar, "\t%s\t0\n", ASM_LONG);
1903
 
1904
  fprintf (filvar, "\n\t.section\t.idata$4\n");
1905
  headindex = 0;
1906
  for (headptr = import_list; headptr != NULL; headptr = headptr->next)
1907
    {
1908
      fprintf (filvar, "listone%d:\n", headindex);
1909
      for (funcindex = 0; funcindex < headptr->nfuncs; funcindex++)
1910
        {
1911
          if (create_for_pep)
1912
            fprintf (filvar, "\t%sfuncptr%d_%d%s\n%s\t0\n",
1913
                     ASM_RVA_BEFORE, headindex, funcindex, ASM_RVA_AFTER,
1914
                     ASM_LONG);
1915
          else
1916
            fprintf (filvar, "\t%sfuncptr%d_%d%s\n",
1917
                     ASM_RVA_BEFORE, headindex, funcindex, ASM_RVA_AFTER);
1918
        }
1919
      if (create_for_pep)
1920
        fprintf (filvar, "\t%s\t0\n\t%s\t0\n", ASM_LONG, ASM_LONG);
1921
      else
1922
        fprintf (filvar, "\t%s\t0\n", ASM_LONG); /* NULL terminating list.  */
1923
      headindex++;
1924
    }
1925
 
1926
  fprintf (filvar, "\n\t.section\t.idata$5\n");
1927
  headindex = 0;
1928
  for (headptr = import_list; headptr != NULL; headptr = headptr->next)
1929
    {
1930
      fprintf (filvar, "listtwo%d:\n", headindex);
1931
      for (funcindex = 0; funcindex < headptr->nfuncs; funcindex++)
1932
        {
1933
          if (create_for_pep)
1934
            fprintf (filvar, "\t%sfuncptr%d_%d%s\n%s\t0\n",
1935
                     ASM_RVA_BEFORE, headindex, funcindex, ASM_RVA_AFTER,
1936
                     ASM_LONG);
1937
          else
1938
            fprintf (filvar, "\t%sfuncptr%d_%d%s\n",
1939
                     ASM_RVA_BEFORE, headindex, funcindex, ASM_RVA_AFTER);
1940
        }
1941
      if (create_for_pep)
1942
        fprintf (filvar, "\t%s\t0\n\t%s\t0\n", ASM_LONG, ASM_LONG);
1943
      else
1944
        fprintf (filvar, "\t%s\t0\n", ASM_LONG); /* NULL terminating list.  */
1945
      headindex++;
1946
    }
1947
 
1948
  fprintf (filvar, "\n\t.section\t.idata$6\n");
1949
  headindex = 0;
1950
  for (headptr = import_list; headptr != NULL; headptr = headptr->next)
1951
    {
1952
      funcindex = 0;
1953
      for (funcptr = headptr->funchead; funcptr != NULL;
1954
           funcptr = funcptr->next)
1955
        {
1956
          fprintf (filvar,"funcptr%d_%d:\n", headindex, funcindex);
1957
          fprintf (filvar,"\t%s\t%d\n", ASM_SHORT,
1958
                   ((funcptr->ord) & 0xFFFF));
1959
          fprintf (filvar,"\t%s\t\"%s\"\n", ASM_TEXT,
1960
            (funcptr->its_name ? funcptr->its_name : funcptr->name));
1961
          fprintf (filvar,"\t%s\t0\n", ASM_BYTE);
1962
          funcindex++;
1963
        }
1964
      headindex++;
1965
    }
1966
 
1967
  fprintf (filvar, "\n\t.section\t.idata$7\n");
1968
  headindex = 0;
1969
  for (headptr = import_list; headptr != NULL; headptr = headptr->next)
1970
    {
1971
      fprintf (filvar,"dllname%d:\n", headindex);
1972
      fprintf (filvar,"\t%s\t\"%s\"\n", ASM_TEXT, headptr->dllname);
1973
      fprintf (filvar,"\t%s\t0\n", ASM_BYTE);
1974
      headindex++;
1975
    }
1976
}
1977
 
1978
/* Assemble the specified file.  */
1979
static void
1980
assemble_file (const char * source, const char * dest)
1981
{
1982
  char * cmd;
1983
 
1984
  cmd = (char *) alloca (strlen (ASM_SWITCHES) + strlen (as_flags)
1985
                         + strlen (source) + strlen (dest) + 50);
1986
 
1987
  sprintf (cmd, "%s %s -o %s %s", ASM_SWITCHES, as_flags, dest, source);
1988
 
1989
  run (as_name, cmd);
1990
}
1991
 
1992
static void
1993
gen_exp_file (void)
1994
{
1995
  FILE *f;
1996
  int i;
1997
  export_type *exp;
1998
  dlist_type *dl;
1999
 
2000
  /* xgettext:c-format */
2001
  inform (_("Generating export file: %s"), exp_name);
2002
 
2003
  f = fopen (TMP_ASM, FOPEN_WT);
2004
  if (!f)
2005
    /* xgettext:c-format */
2006
    fatal (_("Unable to open temporary assembler file: %s"), TMP_ASM);
2007
 
2008
  /* xgettext:c-format */
2009
  inform (_("Opened temporary file: %s"), TMP_ASM);
2010
 
2011
  dump_def_info (f);
2012
 
2013
  if (d_exports)
2014
    {
2015
      fprintf (f, "\t.section   .edata\n\n");
2016
      fprintf (f, "\t%s 0        %s Allways 0\n", ASM_LONG, ASM_C);
2017
      fprintf (f, "\t%s 0x%lx   %s Time and date\n", ASM_LONG,
2018
               (unsigned long) time(0), ASM_C);
2019
      fprintf (f, "\t%s 0        %s Major and Minor version\n", ASM_LONG, ASM_C);
2020
      fprintf (f, "\t%sname%s   %s Ptr to name of dll\n", ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C);
2021
      fprintf (f, "\t%s %d      %s Starting ordinal of exports\n", ASM_LONG, d_low_ord, ASM_C);
2022
 
2023
 
2024
      fprintf (f, "\t%s %d      %s Number of functions\n", ASM_LONG, d_high_ord - d_low_ord + 1, ASM_C);
2025
      fprintf(f,"\t%s named funcs %d, low ord %d, high ord %d\n",
2026
              ASM_C,
2027
              d_named_nfuncs, d_low_ord, d_high_ord);
2028
      fprintf (f, "\t%s %d      %s Number of names\n", ASM_LONG,
2029
               show_allnames ? d_high_ord - d_low_ord + 1 : d_named_nfuncs, ASM_C);
2030
      fprintf (f, "\t%safuncs%s  %s Address of functions\n", ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C);
2031
 
2032
      fprintf (f, "\t%sanames%s %s Address of Name Pointer Table\n",
2033
               ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C);
2034
 
2035
      fprintf (f, "\t%sanords%s %s Address of ordinals\n", ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C);
2036
 
2037
      fprintf (f, "name:        %s      \"%s\"\n", ASM_TEXT, dll_name);
2038
 
2039
 
2040
      fprintf(f,"%s Export address Table\n", ASM_C);
2041
      fprintf(f,"\t%s\n", ASM_ALIGN_LONG);
2042
      fprintf (f, "afuncs:\n");
2043
      i = d_low_ord;
2044
 
2045
      for (exp = d_exports; exp; exp = exp->next)
2046
        {
2047
          if (exp->ordinal != i)
2048
            {
2049
              while (i < exp->ordinal)
2050
                {
2051
                  fprintf(f,"\t%s\t0\n", ASM_LONG);
2052
                  i++;
2053
                }
2054
            }
2055
 
2056
          if (exp->forward == 0)
2057
            {
2058
              if (exp->internal_name[0] == '@')
2059
                fprintf (f, "\t%s%s%s\t%s %d\n", ASM_RVA_BEFORE,
2060
                         exp->internal_name, ASM_RVA_AFTER, ASM_C, exp->ordinal);
2061
              else
2062
                fprintf (f, "\t%s%s%s%s\t%s %d\n", ASM_RVA_BEFORE,
2063
                         ASM_PREFIX (exp->internal_name),
2064
                         exp->internal_name, ASM_RVA_AFTER, ASM_C, exp->ordinal);
2065
            }
2066
          else
2067
            fprintf (f, "\t%sf%d%s\t%s %d\n", ASM_RVA_BEFORE,
2068
                     exp->forward, ASM_RVA_AFTER, ASM_C, exp->ordinal);
2069
          i++;
2070
        }
2071
 
2072
      fprintf (f,"%s Export Name Pointer Table\n", ASM_C);
2073
      fprintf (f, "anames:\n");
2074
 
2075
      for (i = 0; (exp = d_exports_lexically[i]); i++)
2076
        {
2077
          if (!exp->noname || show_allnames)
2078
            fprintf (f, "\t%sn%d%s\n",
2079
                     ASM_RVA_BEFORE, exp->ordinal, ASM_RVA_AFTER);
2080
        }
2081
 
2082
      fprintf (f,"%s Export Ordinal Table\n", ASM_C);
2083
      fprintf (f, "anords:\n");
2084
      for (i = 0; (exp = d_exports_lexically[i]); i++)
2085
        {
2086
          if (!exp->noname || show_allnames)
2087
            fprintf (f, "\t%s   %d\n", ASM_SHORT, exp->ordinal - d_low_ord);
2088
        }
2089
 
2090
      fprintf(f,"%s Export Name Table\n", ASM_C);
2091
      for (i = 0; (exp = d_exports_lexically[i]); i++)
2092
        {
2093
          if (!exp->noname || show_allnames)
2094
            fprintf (f, "n%d:   %s      \"%s\"\n",
2095
                     exp->ordinal, ASM_TEXT,
2096
                     (exp->its_name ? exp->its_name : xlate (exp->name)));
2097
          if (exp->forward != 0)
2098
            fprintf (f, "f%d:   %s      \"%s\"\n",
2099
                     exp->forward, ASM_TEXT, exp->internal_name);
2100
        }
2101
 
2102
      if (a_list)
2103
        {
2104
          fprintf (f, "\t.section %s\n", DRECTVE_SECTION_NAME);
2105
          for (dl = a_list; dl; dl = dl->next)
2106
            {
2107
              fprintf (f, "\t%s\t\"%s\"\n", ASM_TEXT, dl->text);
2108
            }
2109
        }
2110
 
2111
      if (d_list)
2112
        {
2113
          fprintf (f, "\t.section .rdata\n");
2114
          for (dl = d_list; dl; dl = dl->next)
2115
            {
2116
              char *p;
2117
              int l;
2118
 
2119
              /* We don't output as ascii because there can
2120
                 be quote characters in the string.  */
2121
              l = 0;
2122
              for (p = dl->text; *p; p++)
2123
                {
2124
                  if (l == 0)
2125
                    fprintf (f, "\t%s\t", ASM_BYTE);
2126
                  else
2127
                    fprintf (f, ",");
2128
                  fprintf (f, "%d", *p);
2129
                  if (p[1] == 0)
2130
                    {
2131
                      fprintf (f, ",0\n");
2132
                      break;
2133
                    }
2134
                  if (++l == 10)
2135
                    {
2136
                      fprintf (f, "\n");
2137
                      l = 0;
2138
                    }
2139
                }
2140
            }
2141
        }
2142
    }
2143
 
2144
 
2145
  /* Add to the output file a way of getting to the exported names
2146
     without using the import library.  */
2147
  if (add_indirect)
2148
    {
2149
      fprintf (f, "\t.section\t.rdata\n");
2150
      for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
2151
        if (!exp->noname || show_allnames)
2152
          {
2153
            /* We use a single underscore for MS compatibility, and a
2154
               double underscore for backward compatibility with old
2155
               cygwin releases.  */
2156
            if (create_compat_implib)
2157
              fprintf (f, "\t%s\t__imp_%s\n", ASM_GLOBAL, exp->name);
2158
            fprintf (f, "\t%s\t_imp_%s%s\n", ASM_GLOBAL,
2159
                     (!leading_underscore ? "" : "_"), exp->name);
2160
            if (create_compat_implib)
2161
              fprintf (f, "__imp_%s:\n", exp->name);
2162
            fprintf (f, "_imp_%s%s:\n", (!leading_underscore ? "" : "_"), exp->name);
2163
            fprintf (f, "\t%s\t%s\n", ASM_LONG, exp->name);
2164
          }
2165
    }
2166
 
2167
  /* Dump the reloc section if a base file is provided.  */
2168
  if (base_file)
2169
    {
2170
      bfd_vma addr;
2171
      bfd_vma need[COFF_PAGE_SIZE];
2172
      bfd_vma page_addr;
2173
      bfd_size_type numbytes;
2174
      int num_entries;
2175
      bfd_vma *copy;
2176
      int j;
2177
      int on_page;
2178
      fprintf (f, "\t.section\t.init\n");
2179
      fprintf (f, "lab:\n");
2180
 
2181
      fseek (base_file, 0, SEEK_END);
2182
      numbytes = ftell (base_file);
2183
      fseek (base_file, 0, SEEK_SET);
2184
      copy = xmalloc (numbytes);
2185
      if (fread (copy, 1, numbytes, base_file) < numbytes)
2186
        fatal (_("failed to read the number of entries from base file"));
2187
      num_entries = numbytes / sizeof (bfd_vma);
2188
 
2189
 
2190
      fprintf (f, "\t.section\t.reloc\n");
2191
      if (num_entries)
2192
        {
2193
          int src;
2194
          int dst = 0;
2195
          bfd_vma last = (bfd_vma) -1;
2196
          qsort (copy, num_entries, sizeof (bfd_vma), sfunc);
2197
          /* Delete duplicates */
2198
          for (src = 0; src < num_entries; src++)
2199
            {
2200
              if (last != copy[src])
2201
                last = copy[dst++] = copy[src];
2202
            }
2203
          num_entries = dst;
2204
          addr = copy[0];
2205
          page_addr = addr & PAGE_MASK;         /* work out the page addr */
2206
          on_page = 0;
2207
          for (j = 0; j < num_entries; j++)
2208
            {
2209
              addr = copy[j];
2210
              if ((addr & PAGE_MASK) != page_addr)
2211
                {
2212
                  flush_page (f, need, page_addr, on_page);
2213
                  on_page = 0;
2214
                  page_addr = addr & PAGE_MASK;
2215
                }
2216
              need[on_page++] = addr;
2217
            }
2218
          flush_page (f, need, page_addr, on_page);
2219
 
2220
/*        fprintf (f, "\t%s\t0,0\t%s End\n", ASM_LONG, ASM_C);*/
2221
        }
2222
    }
2223
 
2224
  generate_idata_ofile (f);
2225
 
2226
  fclose (f);
2227
 
2228
  /* Assemble the file.  */
2229
  assemble_file (TMP_ASM, exp_name);
2230
 
2231
  if (dontdeltemps == 0)
2232
    unlink (TMP_ASM);
2233
 
2234
  inform (_("Generated exports file"));
2235
}
2236
 
2237
static const char *
2238
xlate (const char *name)
2239
{
2240
  int lead_at = (*name == '@');
2241
  int is_stdcall = (!lead_at && strchr (name, '@') != NULL);
2242
 
2243
  if (!lead_at && (add_underscore
2244
                   || (add_stdcall_underscore && is_stdcall)))
2245
    {
2246
      char *copy = xmalloc (strlen (name) + 2);
2247
 
2248
      copy[0] = '_';
2249
      strcpy (copy + 1, name);
2250
      name = copy;
2251
    }
2252
 
2253
  if (killat)
2254
    {
2255
      char *p;
2256
 
2257
      name += lead_at;
2258
      /* PR 9766: Look for the last @ sign in the name.  */
2259
      p = strrchr (name, '@');
2260
      if (p && ISDIGIT (p[1]))
2261
        *p = 0;
2262
    }
2263
  return name;
2264
}
2265
 
2266
typedef struct
2267
{
2268
  int id;
2269
  const char *name;
2270
  int flags;
2271
  int align;
2272
  asection *sec;
2273
  asymbol *sym;
2274
  asymbol **sympp;
2275
  int size;
2276
  unsigned char *data;
2277
} sinfo;
2278
 
2279
#ifndef DLLTOOL_PPC
2280
 
2281
#define TEXT 0
2282
#define DATA 1
2283
#define BSS 2
2284
#define IDATA7 3
2285
#define IDATA5 4
2286
#define IDATA4 5
2287
#define IDATA6 6
2288
 
2289
#define NSECS 7
2290
 
2291
#define TEXT_SEC_FLAGS   \
2292
        (SEC_ALLOC | SEC_LOAD | SEC_CODE | SEC_READONLY | SEC_HAS_CONTENTS)
2293
#define DATA_SEC_FLAGS   (SEC_ALLOC | SEC_LOAD | SEC_DATA)
2294
#define BSS_SEC_FLAGS     SEC_ALLOC
2295
 
2296
#define INIT_SEC_DATA(id, name, flags, align) \
2297
        { id, name, flags, align, NULL, NULL, NULL, 0, NULL }
2298
static sinfo secdata[NSECS] =
2299
{
2300
  INIT_SEC_DATA (TEXT,   ".text",    TEXT_SEC_FLAGS,   2),
2301
  INIT_SEC_DATA (DATA,   ".data",    DATA_SEC_FLAGS,   2),
2302
  INIT_SEC_DATA (BSS,    ".bss",     BSS_SEC_FLAGS,    2),
2303
  INIT_SEC_DATA (IDATA7, ".idata$7", SEC_HAS_CONTENTS, 2),
2304
  INIT_SEC_DATA (IDATA5, ".idata$5", SEC_HAS_CONTENTS, 2),
2305
  INIT_SEC_DATA (IDATA4, ".idata$4", SEC_HAS_CONTENTS, 2),
2306
  INIT_SEC_DATA (IDATA6, ".idata$6", SEC_HAS_CONTENTS, 1)
2307
};
2308
 
2309
#else
2310
 
2311
/* Sections numbered to make the order the same as other PowerPC NT
2312
   compilers. This also keeps funny alignment thingies from happening.  */
2313
#define TEXT   0
2314
#define PDATA  1
2315
#define RDATA  2
2316
#define IDATA5 3
2317
#define IDATA4 4
2318
#define IDATA6 5
2319
#define IDATA7 6
2320
#define DATA   7
2321
#define BSS    8
2322
 
2323
#define NSECS 9
2324
 
2325
static sinfo secdata[NSECS] =
2326
{
2327
  { TEXT,   ".text",    SEC_CODE | SEC_HAS_CONTENTS, 3},
2328
  { PDATA,  ".pdata",   SEC_HAS_CONTENTS,            2},
2329
  { RDATA,  ".reldata", SEC_HAS_CONTENTS,            2},
2330
  { IDATA5, ".idata$5", SEC_HAS_CONTENTS,            2},
2331
  { IDATA4, ".idata$4", SEC_HAS_CONTENTS,            2},
2332
  { IDATA6, ".idata$6", SEC_HAS_CONTENTS,            1},
2333
  { IDATA7, ".idata$7", SEC_HAS_CONTENTS,            2},
2334
  { DATA,   ".data",    SEC_DATA,                    2},
2335
  { BSS,    ".bss",     0,                           2}
2336
};
2337
 
2338
#endif
2339
 
2340
/* This is what we're trying to make.  We generate the imp symbols with
2341
   both single and double underscores, for compatibility.
2342
 
2343
        .text
2344
        .global _GetFileVersionInfoSizeW@8
2345
        .global __imp_GetFileVersionInfoSizeW@8
2346
_GetFileVersionInfoSizeW@8:
2347
        jmp *   __imp_GetFileVersionInfoSizeW@8
2348
        .section        .idata$7        # To force loading of head
2349
        .long   __version_a_head
2350
# Import Address Table
2351
        .section        .idata$5
2352
__imp_GetFileVersionInfoSizeW@8:
2353
        .rva    ID2
2354
 
2355
# Import Lookup Table
2356
        .section        .idata$4
2357
        .rva    ID2
2358
# Hint/Name table
2359
        .section        .idata$6
2360
ID2:    .short  2
2361
        .asciz  "GetFileVersionInfoSizeW"
2362
 
2363
 
2364
   For the PowerPC, here's the variation on the above scheme:
2365
 
2366
# Rather than a simple "jmp *", the code to get to the dll function
2367
# looks like:
2368
         .text
2369
         lwz    r11,[tocv]__imp_function_name(r2)
2370
#                  RELOC: 00000000 TOCREL16,TOCDEFN __imp_function_name
2371
         lwz    r12,0(r11)
2372
         stw    r2,4(r1)
2373
         mtctr  r12
2374
         lwz    r2,4(r11)
2375
         bctr  */
2376
 
2377
static char *
2378
make_label (const char *prefix, const char *name)
2379
{
2380
  int len = strlen (ASM_PREFIX (name)) + strlen (prefix) + strlen (name);
2381
  char *copy = xmalloc (len + 1);
2382
 
2383
  strcpy (copy, ASM_PREFIX (name));
2384
  strcat (copy, prefix);
2385
  strcat (copy, name);
2386
  return copy;
2387
}
2388
 
2389
static char *
2390
make_imp_label (const char *prefix, const char *name)
2391
{
2392
  int len;
2393
  char *copy;
2394
 
2395
  if (name[0] == '@')
2396
    {
2397
      len = strlen (prefix) + strlen (name);
2398
      copy = xmalloc (len + 1);
2399
      strcpy (copy, prefix);
2400
      strcat (copy, name);
2401
    }
2402
  else
2403
    {
2404
      len = strlen (ASM_PREFIX (name)) + strlen (prefix) + strlen (name);
2405
      copy = xmalloc (len + 1);
2406
      strcpy (copy, prefix);
2407
      strcat (copy, ASM_PREFIX (name));
2408
      strcat (copy, name);
2409
    }
2410
  return copy;
2411
}
2412
 
2413
static bfd *
2414
make_one_lib_file (export_type *exp, int i, int delay)
2415
{
2416
  bfd *      abfd;
2417
  asymbol *  exp_label;
2418
  asymbol *  iname = 0;
2419
  asymbol *  iname2;
2420
  asymbol *  iname_lab;
2421
  asymbol ** iname_lab_pp;
2422
  asymbol ** iname_pp;
2423
#ifdef DLLTOOL_PPC
2424
  asymbol ** fn_pp;
2425
  asymbol ** toc_pp;
2426
#define EXTRA    2
2427
#endif
2428
#ifndef EXTRA
2429
#define EXTRA    0
2430
#endif
2431
  asymbol *  ptrs[NSECS + 4 + EXTRA + 1];
2432
  flagword   applicable;
2433
  char *     outname = xmalloc (strlen (TMP_STUB) + 10);
2434
  int        oidx = 0;
2435
 
2436
 
2437
  sprintf (outname, "%s%05d.o", TMP_STUB, i);
2438
 
2439
  abfd = bfd_openw (outname, HOW_BFD_WRITE_TARGET);
2440
 
2441
  if (!abfd)
2442
    /* xgettext:c-format */
2443
    fatal (_("bfd_open failed open stub file: %s: %s"),
2444
           outname, bfd_get_errmsg ());
2445
 
2446
  /* xgettext:c-format */
2447
  inform (_("Creating stub file: %s"), outname);
2448
 
2449
  bfd_set_format (abfd, bfd_object);
2450
  bfd_set_arch_mach (abfd, HOW_BFD_ARCH, 0);
2451
 
2452
#ifdef DLLTOOL_ARM
2453
  if (machine == MARM_INTERWORK || machine == MTHUMB)
2454
    bfd_set_private_flags (abfd, F_INTERWORK);
2455
#endif
2456
 
2457
  applicable = bfd_applicable_section_flags (abfd);
2458
 
2459
  /* First make symbols for the sections.  */
2460
  for (i = 0; i < NSECS; i++)
2461
    {
2462
      sinfo *si = secdata + i;
2463
 
2464
      if (si->id != i)
2465
        abort ();
2466
      si->sec = bfd_make_section_old_way (abfd, si->name);
2467
      bfd_set_section_flags (abfd,
2468
                             si->sec,
2469
                             si->flags & applicable);
2470
 
2471
      bfd_set_section_alignment(abfd, si->sec, si->align);
2472
      si->sec->output_section = si->sec;
2473
      si->sym = bfd_make_empty_symbol(abfd);
2474
      si->sym->name = si->sec->name;
2475
      si->sym->section = si->sec;
2476
      si->sym->flags = BSF_LOCAL;
2477
      si->sym->value = 0;
2478
      ptrs[oidx] = si->sym;
2479
      si->sympp = ptrs + oidx;
2480
      si->size = 0;
2481
      si->data = NULL;
2482
 
2483
      oidx++;
2484
    }
2485
 
2486
  if (! exp->data)
2487
    {
2488
      exp_label = bfd_make_empty_symbol (abfd);
2489
      exp_label->name = make_imp_label ("", exp->name);
2490
 
2491
      /* On PowerPC, the function name points to a descriptor in
2492
         the rdata section, the first element of which is a
2493
         pointer to the code (..function_name), and the second
2494
         points to the .toc.  */
2495
#ifdef DLLTOOL_PPC
2496
      if (machine == MPPC)
2497
        exp_label->section = secdata[RDATA].sec;
2498
      else
2499
#endif
2500
        exp_label->section = secdata[TEXT].sec;
2501
 
2502
      exp_label->flags = BSF_GLOBAL;
2503
      exp_label->value = 0;
2504
 
2505
#ifdef DLLTOOL_ARM
2506
      if (machine == MTHUMB)
2507
        bfd_coff_set_symbol_class (abfd, exp_label, C_THUMBEXTFUNC);
2508
#endif
2509
      ptrs[oidx++] = exp_label;
2510
    }
2511
 
2512
  /* Generate imp symbols with one underscore for Microsoft
2513
     compatibility, and with two underscores for backward
2514
     compatibility with old versions of cygwin.  */
2515
  if (create_compat_implib)
2516
    {
2517
      iname = bfd_make_empty_symbol (abfd);
2518
      iname->name = make_imp_label ("___imp", exp->name);
2519
      iname->section = secdata[IDATA5].sec;
2520
      iname->flags = BSF_GLOBAL;
2521
      iname->value = 0;
2522
    }
2523
 
2524
  iname2 = bfd_make_empty_symbol (abfd);
2525
  iname2->name = make_imp_label ("__imp_", exp->name);
2526
  iname2->section = secdata[IDATA5].sec;
2527
  iname2->flags = BSF_GLOBAL;
2528
  iname2->value = 0;
2529
 
2530
  iname_lab = bfd_make_empty_symbol (abfd);
2531
 
2532
  iname_lab->name = head_label;
2533
  iname_lab->section = (asection *) &bfd_und_section;
2534
  iname_lab->flags = 0;
2535
  iname_lab->value = 0;
2536
 
2537
  iname_pp = ptrs + oidx;
2538
  if (create_compat_implib)
2539
    ptrs[oidx++] = iname;
2540
  ptrs[oidx++] = iname2;
2541
 
2542
  iname_lab_pp = ptrs + oidx;
2543
  ptrs[oidx++] = iname_lab;
2544
 
2545
#ifdef DLLTOOL_PPC
2546
  /* The symbol referring to the code (.text).  */
2547
  {
2548
    asymbol *function_name;
2549
 
2550
    function_name = bfd_make_empty_symbol(abfd);
2551
    function_name->name = make_label ("..", exp->name);
2552
    function_name->section = secdata[TEXT].sec;
2553
    function_name->flags = BSF_GLOBAL;
2554
    function_name->value = 0;
2555
 
2556
    fn_pp = ptrs + oidx;
2557
    ptrs[oidx++] = function_name;
2558
  }
2559
 
2560
  /* The .toc symbol.  */
2561
  {
2562
    asymbol *toc_symbol;
2563
 
2564
    toc_symbol = bfd_make_empty_symbol (abfd);
2565
    toc_symbol->name = make_label (".", "toc");
2566
    toc_symbol->section = (asection *)&bfd_und_section;
2567
    toc_symbol->flags = BSF_GLOBAL;
2568
    toc_symbol->value = 0;
2569
 
2570
    toc_pp = ptrs + oidx;
2571
    ptrs[oidx++] = toc_symbol;
2572
  }
2573
#endif
2574
 
2575
  ptrs[oidx] = 0;
2576
 
2577
  for (i = 0; i < NSECS; i++)
2578
    {
2579
      sinfo *si = secdata + i;
2580
      asection *sec = si->sec;
2581
      arelent *rel, *rel2 = 0, *rel3 = 0;
2582
      arelent **rpp;
2583
 
2584
      switch (i)
2585
        {
2586
        case TEXT:
2587
          if (! exp->data)
2588
            {
2589
              si->size = HOW_JTAB_SIZE;
2590
              si->data = xmalloc (HOW_JTAB_SIZE);
2591
              memcpy (si->data, HOW_JTAB, HOW_JTAB_SIZE);
2592
 
2593
              /* Add the reloc into idata$5.  */
2594
              rel = xmalloc (sizeof (arelent));
2595
 
2596
              rpp = xmalloc (sizeof (arelent *) * (delay ? 4 : 2));
2597
              rpp[0] = rel;
2598
              rpp[1] = 0;
2599
 
2600
              rel->address = HOW_JTAB_ROFF;
2601
              rel->addend = 0;
2602
 
2603
              if (delay)
2604
                {
2605
                  rel2 = xmalloc (sizeof (arelent));
2606
                  rpp[1] = rel2;
2607
                  rel2->address = HOW_JTAB_ROFF2;
2608
                  rel2->addend = 0;
2609
                  rel3 = xmalloc (sizeof (arelent));
2610
                  rpp[2] = rel3;
2611
                  rel3->address = HOW_JTAB_ROFF3;
2612
                  rel3->addend = 0;
2613
                  rpp[3] = 0;
2614
                }
2615
 
2616
              if (machine == MPPC)
2617
                {
2618
                  rel->howto = bfd_reloc_type_lookup (abfd,
2619
                                                      BFD_RELOC_16_GOTOFF);
2620
                  rel->sym_ptr_ptr = iname_pp;
2621
                }
2622
              else if (machine == MX86)
2623
                {
2624
                  rel->howto = bfd_reloc_type_lookup (abfd,
2625
                                                      BFD_RELOC_32_PCREL);
2626
                  rel->sym_ptr_ptr = iname_pp;
2627
                }
2628
              else
2629
                {
2630
                  rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_32);
2631
                  rel->sym_ptr_ptr = secdata[IDATA5].sympp;
2632
                }
2633
 
2634
              if (delay)
2635
                {
2636 166 khays
                  if (machine == MX86)
2637
                   rel2->howto = bfd_reloc_type_lookup (abfd,
2638
                                                        BFD_RELOC_32_PCREL);
2639
                  else
2640
                    rel2->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_32);
2641 15 khays
                  rel2->sym_ptr_ptr = rel->sym_ptr_ptr;
2642 166 khays
                  rel3->howto = bfd_reloc_type_lookup (abfd,
2643
                                                       BFD_RELOC_32_PCREL);
2644 15 khays
                  rel3->sym_ptr_ptr = iname_lab_pp;
2645
                }
2646
 
2647
              sec->orelocation = rpp;
2648
              sec->reloc_count = delay ? 3 : 1;
2649
            }
2650
          break;
2651
 
2652
        case IDATA5:
2653
          if (delay)
2654
            {
2655 166 khays
              si->size = create_for_pep ? 8 : 4;
2656
              si->data = xmalloc (si->size);
2657 15 khays
              sec->reloc_count = 1;
2658
              memset (si->data, 0, si->size);
2659 166 khays
              /* Point after jmp [__imp_...] instruction.  */
2660 15 khays
              si->data[0] = 6;
2661
              rel = xmalloc (sizeof (arelent));
2662
              rpp = xmalloc (sizeof (arelent *) * 2);
2663
              rpp[0] = rel;
2664
              rpp[1] = 0;
2665
              rel->address = 0;
2666
              rel->addend = 0;
2667 166 khays
              if (create_for_pep)
2668
                rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_64);
2669
              else
2670
                rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_32);
2671 15 khays
              rel->sym_ptr_ptr = secdata[TEXT].sympp;
2672
              sec->orelocation = rpp;
2673
              break;
2674
            }
2675
          /* else fall through */
2676
        case IDATA4:
2677
          /* An idata$4 or idata$5 is one word long, and has an
2678
             rva to idata$6.  */
2679
 
2680
          if (create_for_pep)
2681
            {
2682
              si->data = xmalloc (8);
2683
              si->size = 8;
2684
              if (exp->noname)
2685
                {
2686
                  si->data[0] = exp->ordinal ;
2687
                  si->data[1] = exp->ordinal >> 8;
2688
                  si->data[2] = exp->ordinal >> 16;
2689
                  si->data[3] = exp->ordinal >> 24;
2690
                  si->data[4] = 0;
2691
                  si->data[5] = 0;
2692
                  si->data[6] = 0;
2693
                  si->data[7] = 0x80;
2694
                }
2695
              else
2696
                {
2697
                  sec->reloc_count = 1;
2698
                  memset (si->data, 0, si->size);
2699
                  rel = xmalloc (sizeof (arelent));
2700
                  rpp = xmalloc (sizeof (arelent *) * 2);
2701
                  rpp[0] = rel;
2702
                  rpp[1] = 0;
2703
                  rel->address = 0;
2704
                  rel->addend = 0;
2705
                  rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_RVA);
2706
                  rel->sym_ptr_ptr = secdata[IDATA6].sympp;
2707
                  sec->orelocation = rpp;
2708
                }
2709
            }
2710
          else
2711
            {
2712
              si->data = xmalloc (4);
2713
              si->size = 4;
2714
 
2715
              if (exp->noname)
2716
                {
2717
                  si->data[0] = exp->ordinal ;
2718
                  si->data[1] = exp->ordinal >> 8;
2719
                  si->data[2] = exp->ordinal >> 16;
2720
                  si->data[3] = 0x80;
2721
                }
2722
              else
2723
                {
2724
                  sec->reloc_count = 1;
2725
                  memset (si->data, 0, si->size);
2726
                  rel = xmalloc (sizeof (arelent));
2727
                  rpp = xmalloc (sizeof (arelent *) * 2);
2728
                  rpp[0] = rel;
2729
                  rpp[1] = 0;
2730
                  rel->address = 0;
2731
                  rel->addend = 0;
2732
                  rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_RVA);
2733
                  rel->sym_ptr_ptr = secdata[IDATA6].sympp;
2734
                  sec->orelocation = rpp;
2735
              }
2736
            }
2737
          break;
2738
 
2739
        case IDATA6:
2740
          if (!exp->noname)
2741
            {
2742
              /* This used to add 1 to exp->hint.  I don't know
2743
                 why it did that, and it does not match what I see
2744
                 in programs compiled with the MS tools.  */
2745
              int idx = exp->hint;
2746
              if (exp->its_name)
2747
                si->size = strlen (exp->its_name) + 3;
2748
              else
2749
                si->size = strlen (xlate (exp->import_name)) + 3;
2750
              si->data = xmalloc (si->size);
2751
              si->data[0] = idx & 0xff;
2752
              si->data[1] = idx >> 8;
2753
              if (exp->its_name)
2754
                strcpy ((char *) si->data + 2, exp->its_name);
2755
              else
2756
                strcpy ((char *) si->data + 2, xlate (exp->import_name));
2757
            }
2758
          break;
2759
        case IDATA7:
2760
          if (delay)
2761
            break;
2762
          si->size = 4;
2763
          si->data = xmalloc (4);
2764
          memset (si->data, 0, si->size);
2765
          rel = xmalloc (sizeof (arelent));
2766
          rpp = xmalloc (sizeof (arelent *) * 2);
2767
          rpp[0] = rel;
2768
          rel->address = 0;
2769
          rel->addend = 0;
2770
          rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_RVA);
2771
          rel->sym_ptr_ptr = iname_lab_pp;
2772
          sec->orelocation = rpp;
2773
          sec->reloc_count = 1;
2774
          break;
2775
 
2776
#ifdef DLLTOOL_PPC
2777
        case PDATA:
2778
          {
2779
            /* The .pdata section is 5 words long.
2780
               Think of it as:
2781
               struct
2782
               {
2783
               bfd_vma BeginAddress,     [0x00]
2784
               EndAddress,       [0x04]
2785
               ExceptionHandler, [0x08]
2786
               HandlerData,      [0x0c]
2787
               PrologEndAddress; [0x10]
2788
               };  */
2789
 
2790
            /* So this pdata section setups up this as a glue linkage to
2791
               a dll routine. There are a number of house keeping things
2792
               we need to do:
2793
 
2794
               1. In the name of glue trickery, the ADDR32 relocs for 0,
2795
               4, and 0x10 are set to point to the same place:
2796
               "..function_name".
2797
               2. There is one more reloc needed in the pdata section.
2798
               The actual glue instruction to restore the toc on
2799
               return is saved as the offset in an IMGLUE reloc.
2800
               So we need a total of four relocs for this section.
2801
 
2802
               3. Lastly, the HandlerData field is set to 0x03, to indicate
2803
               that this is a glue routine.  */
2804
            arelent *imglue, *ba_rel, *ea_rel, *pea_rel;
2805
 
2806
            /* Alignment must be set to 2**2 or you get extra stuff.  */
2807
            bfd_set_section_alignment(abfd, sec, 2);
2808
 
2809
            si->size = 4 * 5;
2810
            si->data = xmalloc (si->size);
2811
            memset (si->data, 0, si->size);
2812
            rpp = xmalloc (sizeof (arelent *) * 5);
2813
            rpp[0] = imglue  = xmalloc (sizeof (arelent));
2814
            rpp[1] = ba_rel  = xmalloc (sizeof (arelent));
2815
            rpp[2] = ea_rel  = xmalloc (sizeof (arelent));
2816
            rpp[3] = pea_rel = xmalloc (sizeof (arelent));
2817
            rpp[4] = 0;
2818
 
2819
            /* Stick the toc reload instruction in the glue reloc.  */
2820
            bfd_put_32(abfd, ppc_glue_insn, (char *) &imglue->address);
2821
 
2822
            imglue->addend = 0;
2823
            imglue->howto = bfd_reloc_type_lookup (abfd,
2824
                                                   BFD_RELOC_32_GOTOFF);
2825
            imglue->sym_ptr_ptr = fn_pp;
2826
 
2827
            ba_rel->address = 0;
2828
            ba_rel->addend = 0;
2829
            ba_rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_32);
2830
            ba_rel->sym_ptr_ptr = fn_pp;
2831
 
2832
            bfd_put_32 (abfd, 0x18, si->data + 0x04);
2833
            ea_rel->address = 4;
2834
            ea_rel->addend = 0;
2835
            ea_rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_32);
2836
            ea_rel->sym_ptr_ptr = fn_pp;
2837
 
2838
            /* Mark it as glue.  */
2839
            bfd_put_32 (abfd, 0x03, si->data + 0x0c);
2840
 
2841
            /* Mark the prolog end address.  */
2842
            bfd_put_32 (abfd, 0x0D, si->data + 0x10);
2843
            pea_rel->address = 0x10;
2844
            pea_rel->addend = 0;
2845
            pea_rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_32);
2846
            pea_rel->sym_ptr_ptr = fn_pp;
2847
 
2848
            sec->orelocation = rpp;
2849
            sec->reloc_count = 4;
2850
            break;
2851
          }
2852
        case RDATA:
2853
          /* Each external function in a PowerPC PE file has a two word
2854
             descriptor consisting of:
2855
             1. The address of the code.
2856
             2. The address of the appropriate .toc
2857
             We use relocs to build this.  */
2858
          si->size = 8;
2859
          si->data = xmalloc (8);
2860
          memset (si->data, 0, si->size);
2861
 
2862
          rpp = xmalloc (sizeof (arelent *) * 3);
2863
          rpp[0] = rel = xmalloc (sizeof (arelent));
2864
          rpp[1] = xmalloc (sizeof (arelent));
2865
          rpp[2] = 0;
2866
 
2867
          rel->address = 0;
2868
          rel->addend = 0;
2869
          rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_32);
2870
          rel->sym_ptr_ptr = fn_pp;
2871
 
2872
          rel = rpp[1];
2873
 
2874
          rel->address = 4;
2875
          rel->addend = 0;
2876
          rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_32);
2877
          rel->sym_ptr_ptr = toc_pp;
2878
 
2879
          sec->orelocation = rpp;
2880
          sec->reloc_count = 2;
2881
          break;
2882
#endif /* DLLTOOL_PPC */
2883
        }
2884
    }
2885
 
2886
  {
2887
    bfd_vma vma = 0;
2888
    /* Size up all the sections.  */
2889
    for (i = 0; i < NSECS; i++)
2890
      {
2891
        sinfo *si = secdata + i;
2892
 
2893
        bfd_set_section_size (abfd, si->sec, si->size);
2894
        bfd_set_section_vma (abfd, si->sec, vma);
2895
      }
2896
  }
2897
  /* Write them out.  */
2898
  for (i = 0; i < NSECS; i++)
2899
    {
2900
      sinfo *si = secdata + i;
2901
 
2902
      if (i == IDATA5 && no_idata5)
2903
        continue;
2904
 
2905
      if (i == IDATA4 && no_idata4)
2906
        continue;
2907
 
2908
      bfd_set_section_contents (abfd, si->sec,
2909
                                si->data, 0,
2910
                                si->size);
2911
    }
2912
 
2913
  bfd_set_symtab (abfd, ptrs, oidx);
2914
  bfd_close (abfd);
2915
  abfd = bfd_openr (outname, HOW_BFD_READ_TARGET);
2916
  if (!abfd)
2917
    /* xgettext:c-format */
2918
    fatal (_("bfd_open failed reopen stub file: %s: %s"),
2919
           outname, bfd_get_errmsg ());
2920
 
2921
  return abfd;
2922
}
2923
 
2924
static bfd *
2925
make_head (void)
2926
{
2927
  FILE *f = fopen (TMP_HEAD_S, FOPEN_WT);
2928
  bfd *abfd;
2929
 
2930
  if (f == NULL)
2931
    {
2932
      fatal (_("failed to open temporary head file: %s"), TMP_HEAD_S);
2933
      return NULL;
2934
    }
2935
 
2936
  fprintf (f, "%s IMAGE_IMPORT_DESCRIPTOR\n", ASM_C);
2937
  fprintf (f, "\t.section\t.idata$2\n");
2938
 
2939
  fprintf (f,"\t%s\t%s\n", ASM_GLOBAL, head_label);
2940
 
2941
  fprintf (f, "%s:\n", head_label);
2942
 
2943
  fprintf (f, "\t%shname%s\t%sPtr to image import by name list\n",
2944
           ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C);
2945
 
2946
  fprintf (f, "\t%sthis should be the timestamp, but NT sometimes\n", ASM_C);
2947
  fprintf (f, "\t%sdoesn't load DLLs when this is set.\n", ASM_C);
2948
  fprintf (f, "\t%s\t0\t%s loaded time\n", ASM_LONG, ASM_C);
2949
  fprintf (f, "\t%s\t0\t%s Forwarder chain\n", ASM_LONG, ASM_C);
2950
  fprintf (f, "\t%s__%s_iname%s\t%s imported dll's name\n",
2951
           ASM_RVA_BEFORE,
2952
           imp_name_lab,
2953
           ASM_RVA_AFTER,
2954
           ASM_C);
2955
  fprintf (f, "\t%sfthunk%s\t%s pointer to firstthunk\n",
2956
           ASM_RVA_BEFORE,
2957
           ASM_RVA_AFTER, ASM_C);
2958
 
2959
  fprintf (f, "%sStuff for compatibility\n", ASM_C);
2960
 
2961
  if (!no_idata5)
2962
    {
2963
      fprintf (f, "\t.section\t.idata$5\n");
2964
      if (use_nul_prefixed_import_tables)
2965
        {
2966
          if (create_for_pep)
2967
            fprintf (f,"\t%s\t0\n\t%s\t0\n", ASM_LONG, ASM_LONG);
2968
          else
2969
            fprintf (f,"\t%s\t0\n", ASM_LONG);
2970
        }
2971
      fprintf (f, "fthunk:\n");
2972
    }
2973
 
2974
  if (!no_idata4)
2975
    {
2976
      fprintf (f, "\t.section\t.idata$4\n");
2977
      if (use_nul_prefixed_import_tables)
2978
        {
2979
          if (create_for_pep)
2980
            fprintf (f,"\t%s\t0\n\t%s\t0\n", ASM_LONG, ASM_LONG);
2981
          else
2982
            fprintf (f,"\t%s\t0\n", ASM_LONG);
2983
        }
2984
      fprintf (f, "hname:\n");
2985
    }
2986
 
2987
  fclose (f);
2988
 
2989
  assemble_file (TMP_HEAD_S, TMP_HEAD_O);
2990
 
2991
  abfd = bfd_openr (TMP_HEAD_O, HOW_BFD_READ_TARGET);
2992
  if (abfd == NULL)
2993
    /* xgettext:c-format */
2994
    fatal (_("failed to open temporary head file: %s: %s"),
2995
           TMP_HEAD_O, bfd_get_errmsg ());
2996
 
2997
  return abfd;
2998
}
2999
 
3000
bfd *
3001
make_delay_head (void)
3002
{
3003
  FILE *f = fopen (TMP_HEAD_S, FOPEN_WT);
3004
  bfd *abfd;
3005
 
3006
  if (f == NULL)
3007
    {
3008
      fatal (_("failed to open temporary head file: %s"), TMP_HEAD_S);
3009
      return NULL;
3010
    }
3011
 
3012
  /* Output the __tailMerge__xxx function */
3013
  fprintf (f, "%s Import trampoline\n", ASM_C);
3014
  fprintf (f, "\t.section\t.text\n");
3015
  fprintf(f,"\t%s\t%s\n", ASM_GLOBAL, head_label);
3016
  fprintf (f, "%s:\n", head_label);
3017
  fprintf (f, mtable[machine].trampoline, imp_name_lab);
3018
 
3019
  /* Output the delay import descriptor */
3020
  fprintf (f, "\n%s DELAY_IMPORT_DESCRIPTOR\n", ASM_C);
3021
  fprintf (f, ".section\t.text$2\n");
3022
  fprintf (f,"%s __DELAY_IMPORT_DESCRIPTOR_%s\n", ASM_GLOBAL,imp_name_lab);
3023
  fprintf (f, "__DELAY_IMPORT_DESCRIPTOR_%s:\n", imp_name_lab);
3024
  fprintf (f, "\t%s 1\t%s grAttrs\n", ASM_LONG, ASM_C);
3025
  fprintf (f, "\t%s__%s_iname%s\t%s rvaDLLName\n",
3026
           ASM_RVA_BEFORE, imp_name_lab, ASM_RVA_AFTER, ASM_C);
3027
  fprintf (f, "\t%s__DLL_HANDLE_%s%s\t%s rvaHmod\n",
3028
           ASM_RVA_BEFORE, imp_name_lab, ASM_RVA_AFTER, ASM_C);
3029
  fprintf (f, "\t%s__IAT_%s%s\t%s rvaIAT\n",
3030
           ASM_RVA_BEFORE, imp_name_lab, ASM_RVA_AFTER, ASM_C);
3031
  fprintf (f, "\t%s__INT_%s%s\t%s rvaINT\n",
3032
           ASM_RVA_BEFORE, imp_name_lab, ASM_RVA_AFTER, ASM_C);
3033
  fprintf (f, "\t%s\t0\t%s rvaBoundIAT\n", ASM_LONG, ASM_C);
3034
  fprintf (f, "\t%s\t0\t%s rvaUnloadIAT\n", ASM_LONG, ASM_C);
3035
  fprintf (f, "\t%s\t0\t%s dwTimeStamp\n", ASM_LONG, ASM_C);
3036
 
3037
  /* Output the dll_handle */
3038
  fprintf (f, "\n.section .data\n");
3039
  fprintf (f, "__DLL_HANDLE_%s:\n", imp_name_lab);
3040
  fprintf (f, "\t%s\t0\t%s Handle\n", ASM_LONG, ASM_C);
3041 166 khays
  if (create_for_pep)
3042
    fprintf (f, "\t%s\t0\n", ASM_LONG);
3043 15 khays
  fprintf (f, "\n");
3044
 
3045
  fprintf (f, "%sStuff for compatibility\n", ASM_C);
3046
 
3047
  if (!no_idata5)
3048
    {
3049
      fprintf (f, "\t.section\t.idata$5\n");
3050
      /* NULL terminating list.  */
3051 166 khays
      if (create_for_pep)
3052
        fprintf (f,"\t%s\t0\n\t%s\t0\n", ASM_LONG, ASM_LONG);
3053
      else
3054
        fprintf (f,"\t%s\t0\n", ASM_LONG);
3055 15 khays
      fprintf (f, "__IAT_%s:\n", imp_name_lab);
3056
    }
3057
 
3058
  if (!no_idata4)
3059
    {
3060
      fprintf (f, "\t.section\t.idata$4\n");
3061
      fprintf (f, "\t%s\t0\n", ASM_LONG);
3062 166 khays
      if (create_for_pep)
3063
        fprintf (f, "\t%s\t0\n", ASM_LONG);
3064 15 khays
      fprintf (f, "\t.section\t.idata$4\n");
3065
      fprintf (f, "__INT_%s:\n", imp_name_lab);
3066
    }
3067
 
3068
  fprintf (f, "\t.section\t.idata$2\n");
3069
 
3070
  fclose (f);
3071
 
3072
  assemble_file (TMP_HEAD_S, TMP_HEAD_O);
3073
 
3074
  abfd = bfd_openr (TMP_HEAD_O, HOW_BFD_READ_TARGET);
3075
  if (abfd == NULL)
3076
    /* xgettext:c-format */
3077
    fatal (_("failed to open temporary head file: %s: %s"),
3078
           TMP_HEAD_O, bfd_get_errmsg ());
3079
 
3080
  return abfd;
3081
}
3082
 
3083
static bfd *
3084
make_tail (void)
3085
{
3086
  FILE *f = fopen (TMP_TAIL_S, FOPEN_WT);
3087
  bfd *abfd;
3088
 
3089
  if (f == NULL)
3090
    {
3091
      fatal (_("failed to open temporary tail file: %s"), TMP_TAIL_S);
3092
      return NULL;
3093
    }
3094
 
3095
  if (!no_idata4)
3096
    {
3097
      fprintf (f, "\t.section\t.idata$4\n");
3098
      if (create_for_pep)
3099
        fprintf (f,"\t%s\t0\n\t%s\t0\n", ASM_LONG, ASM_LONG);
3100
      else
3101
        fprintf (f,"\t%s\t0\n", ASM_LONG); /* NULL terminating list.  */
3102
    }
3103
 
3104
  if (!no_idata5)
3105
    {
3106
      fprintf (f, "\t.section\t.idata$5\n");
3107
      if (create_for_pep)
3108
        fprintf (f,"\t%s\t0\n\t%s\t0\n", ASM_LONG, ASM_LONG);
3109
      else
3110
        fprintf (f,"\t%s\t0\n", ASM_LONG); /* NULL terminating list.  */
3111
    }
3112
 
3113
#ifdef DLLTOOL_PPC
3114
  /* Normally, we need to see a null descriptor built in idata$3 to
3115
     act as the terminator for the list. The ideal way, I suppose,
3116
     would be to mark this section as a comdat type 2 section, so
3117
     only one would appear in the final .exe (if our linker supported
3118
     comdat, that is) or cause it to be inserted by something else (say
3119
     crt0).  */
3120
 
3121
  fprintf (f, "\t.section\t.idata$3\n");
3122
  fprintf (f, "\t%s\t0\n", ASM_LONG);
3123
  fprintf (f, "\t%s\t0\n", ASM_LONG);
3124
  fprintf (f, "\t%s\t0\n", ASM_LONG);
3125
  fprintf (f, "\t%s\t0\n", ASM_LONG);
3126
  fprintf (f, "\t%s\t0\n", ASM_LONG);
3127
#endif
3128
 
3129
#ifdef DLLTOOL_PPC
3130
  /* Other PowerPC NT compilers use idata$6 for the dllname, so I
3131
     do too. Original, huh?  */
3132
  fprintf (f, "\t.section\t.idata$6\n");
3133
#else
3134
  fprintf (f, "\t.section\t.idata$7\n");
3135
#endif
3136
 
3137
  fprintf (f, "\t%s\t__%s_iname\n", ASM_GLOBAL, imp_name_lab);
3138
  fprintf (f, "__%s_iname:\t%s\t\"%s\"\n",
3139
           imp_name_lab, ASM_TEXT, dll_name);
3140
 
3141
  fclose (f);
3142
 
3143
  assemble_file (TMP_TAIL_S, TMP_TAIL_O);
3144
 
3145
  abfd = bfd_openr (TMP_TAIL_O, HOW_BFD_READ_TARGET);
3146
  if (abfd == NULL)
3147
    /* xgettext:c-format */
3148
    fatal (_("failed to open temporary tail file: %s: %s"),
3149
           TMP_TAIL_O, bfd_get_errmsg ());
3150
 
3151
  return abfd;
3152
}
3153
 
3154
static void
3155
gen_lib_file (int delay)
3156
{
3157
  int i;
3158
  export_type *exp;
3159
  bfd *ar_head;
3160
  bfd *ar_tail;
3161
  bfd *outarch;
3162
  bfd * head  = 0;
3163
 
3164
  unlink (imp_name);
3165
 
3166
  outarch = bfd_openw (imp_name, HOW_BFD_WRITE_TARGET);
3167
 
3168
  if (!outarch)
3169
    /* xgettext:c-format */
3170
    fatal (_("Can't create .lib file: %s: %s"),
3171
           imp_name, bfd_get_errmsg ());
3172
 
3173
  /* xgettext:c-format */
3174
  inform (_("Creating library file: %s"), imp_name);
3175
 
3176
  bfd_set_format (outarch, bfd_archive);
3177
  outarch->has_armap = 1;
3178
  outarch->is_thin_archive = 0;
3179
 
3180
  /* Work out a reasonable size of things to put onto one line.  */
3181
  if (delay)
3182
    {
3183
      ar_head = make_delay_head ();
3184
    }
3185
  else
3186
    {
3187
      ar_head = make_head ();
3188
    }
3189
  ar_tail = make_tail();
3190
 
3191
  if (ar_head == NULL || ar_tail == NULL)
3192
    return;
3193
 
3194
  for (i = 0; (exp = d_exports_lexically[i]); i++)
3195
    {
3196
      bfd *n;
3197
      /* Don't add PRIVATE entries to import lib.  */
3198
      if (exp->private)
3199
        continue;
3200
      n = make_one_lib_file (exp, i, delay);
3201
      n->archive_next = head;
3202
      head = n;
3203
      if (ext_prefix_alias)
3204
        {
3205
          export_type alias_exp;
3206
 
3207
          assert (i < PREFIX_ALIAS_BASE);
3208
          alias_exp.name = make_imp_label (ext_prefix_alias, exp->name);
3209
          alias_exp.internal_name = exp->internal_name;
3210
          alias_exp.its_name = exp->its_name;
3211
          alias_exp.import_name = exp->name;
3212
          alias_exp.ordinal = exp->ordinal;
3213
          alias_exp.constant = exp->constant;
3214
          alias_exp.noname = exp->noname;
3215
          alias_exp.private = exp->private;
3216
          alias_exp.data = exp->data;
3217
          alias_exp.hint = exp->hint;
3218
          alias_exp.forward = exp->forward;
3219
          alias_exp.next = exp->next;
3220
          n = make_one_lib_file (&alias_exp, i + PREFIX_ALIAS_BASE, delay);
3221
          n->archive_next = head;
3222
          head = n;
3223
        }
3224
    }
3225
 
3226
  /* Now stick them all into the archive.  */
3227
  ar_head->archive_next = head;
3228
  ar_tail->archive_next = ar_head;
3229
  head = ar_tail;
3230
 
3231
  if (! bfd_set_archive_head (outarch, head))
3232
    bfd_fatal ("bfd_set_archive_head");
3233
 
3234
  if (! bfd_close (outarch))
3235
    bfd_fatal (imp_name);
3236
 
3237
  while (head != NULL)
3238
    {
3239
      bfd *n = head->archive_next;
3240
      bfd_close (head);
3241
      head = n;
3242
    }
3243
 
3244
  /* Delete all the temp files.  */
3245
  if (dontdeltemps == 0)
3246
    {
3247
      unlink (TMP_HEAD_O);
3248
      unlink (TMP_HEAD_S);
3249
      unlink (TMP_TAIL_O);
3250
      unlink (TMP_TAIL_S);
3251
    }
3252
 
3253
  if (dontdeltemps < 2)
3254
    {
3255
      char *name;
3256
 
3257
      name = (char *) alloca (strlen (TMP_STUB) + 10);
3258
      for (i = 0; (exp = d_exports_lexically[i]); i++)
3259
        {
3260
          /* Don't delete non-existent stubs for PRIVATE entries.  */
3261
          if (exp->private)
3262
            continue;
3263
          sprintf (name, "%s%05d.o", TMP_STUB, i);
3264
          if (unlink (name) < 0)
3265
            /* xgettext:c-format */
3266
            non_fatal (_("cannot delete %s: %s"), name, strerror (errno));
3267
          if (ext_prefix_alias)
3268
            {
3269
              sprintf (name, "%s%05d.o", TMP_STUB, i + PREFIX_ALIAS_BASE);
3270
              if (unlink (name) < 0)
3271
                /* xgettext:c-format */
3272
                non_fatal (_("cannot delete %s: %s"), name, strerror (errno));
3273
            }
3274
        }
3275
    }
3276
 
3277
  inform (_("Created lib file"));
3278
}
3279
 
3280
/* Append a copy of data (cast to char *) to list.  */
3281
 
3282
static void
3283
dll_name_list_append (dll_name_list_type * list, bfd_byte * data)
3284
{
3285
  dll_name_list_node_type * entry;
3286
 
3287
  /* Error checking.  */
3288
  if (! list || ! list->tail)
3289
    return;
3290
 
3291
  /* Allocate new node.  */
3292
  entry = ((dll_name_list_node_type *)
3293
           xmalloc (sizeof (dll_name_list_node_type)));
3294
 
3295
  /* Initialize its values.  */
3296
  entry->dllname = xstrdup ((char *) data);
3297
  entry->next = NULL;
3298
 
3299
  /* Add to tail, and move tail.  */
3300
  list->tail->next = entry;
3301
  list->tail = entry;
3302
}
3303
 
3304
/* Count the number of entries in list.  */
3305
 
3306
static int
3307
dll_name_list_count (dll_name_list_type * list)
3308
{
3309
  dll_name_list_node_type * p;
3310
  int count = 0;
3311
 
3312
  /* Error checking.  */
3313
  if (! list || ! list->head)
3314
    return 0;
3315
 
3316
  p = list->head;
3317
 
3318
  while (p && p->next)
3319
    {
3320
      count++;
3321
      p = p->next;
3322
    }
3323
  return count;
3324
}
3325
 
3326
/* Print each entry in list to stdout.  */
3327
 
3328
static void
3329
dll_name_list_print (dll_name_list_type * list)
3330
{
3331
  dll_name_list_node_type * p;
3332
 
3333
  /* Error checking.  */
3334
  if (! list || ! list->head)
3335
    return;
3336
 
3337
  p = list->head;
3338
 
3339
  while (p && p->next && p->next->dllname && *(p->next->dllname))
3340
    {
3341
      printf ("%s\n", p->next->dllname);
3342
      p = p->next;
3343
    }
3344
}
3345
 
3346
/* Free all entries in list, and list itself.  */
3347
 
3348
static void
3349
dll_name_list_free (dll_name_list_type * list)
3350
{
3351
  if (list)
3352
    {
3353
      dll_name_list_free_contents (list->head);
3354
      list->head = NULL;
3355
      list->tail = NULL;
3356
      free (list);
3357
    }
3358
}
3359
 
3360
/* Recursive function to free all nodes entry->next->next...
3361
   as well as entry itself.  */
3362
 
3363
static void
3364
dll_name_list_free_contents (dll_name_list_node_type * entry)
3365
{
3366
  if (entry)
3367
    {
3368
      if (entry->next)
3369
        {
3370
          dll_name_list_free_contents (entry->next);
3371
          entry->next = NULL;
3372
        }
3373
      if (entry->dllname)
3374
        {
3375
          free (entry->dllname);
3376
          entry->dllname = NULL;
3377
        }
3378
      free (entry);
3379
    }
3380
}
3381
 
3382
/* Allocate and initialize a dll_name_list_type object,
3383
   including its sentinel node.  Caller is responsible
3384
   for calling dll_name_list_free when finished with
3385
   the list.  */
3386
 
3387
static dll_name_list_type *
3388
dll_name_list_create (void)
3389
{
3390
  /* Allocate list.  */
3391
  dll_name_list_type * list = xmalloc (sizeof (dll_name_list_type));
3392
 
3393
  /* Allocate and initialize sentinel node.  */
3394
  list->head = xmalloc (sizeof (dll_name_list_node_type));
3395
  list->head->dllname = NULL;
3396
  list->head->next = NULL;
3397
 
3398
  /* Bookkeeping for empty list.  */
3399
  list->tail = list->head;
3400
 
3401
  return list;
3402
}
3403
 
3404
/* Search the symbol table of the suppled BFD for a symbol whose name matches
3405
   OBJ (where obj is cast to const char *).  If found, set global variable
3406
   identify_member_contains_symname_result TRUE.  It is the caller's
3407
   responsibility to set the result variable FALSE before iterating with
3408
   this function.  */
3409
 
3410
static void
3411
identify_member_contains_symname (bfd  * abfd,
3412
                                  bfd  * archive_bfd ATTRIBUTE_UNUSED,
3413
                                  void * obj)
3414
{
3415
  long storage_needed;
3416
  asymbol ** symbol_table;
3417
  long number_of_symbols;
3418
  long i;
3419
  symname_search_data_type * search_data = (symname_search_data_type *) obj;
3420
 
3421
  /* If we already found the symbol in a different member,
3422
     short circuit.  */
3423
  if (search_data->found)
3424
    return;
3425
 
3426
  storage_needed = bfd_get_symtab_upper_bound (abfd);
3427
  if (storage_needed <= 0)
3428
    return;
3429
 
3430
  symbol_table = xmalloc (storage_needed);
3431
  number_of_symbols = bfd_canonicalize_symtab (abfd, symbol_table);
3432
  if (number_of_symbols < 0)
3433
    {
3434
      free (symbol_table);
3435
      return;
3436
    }
3437
 
3438
  for (i = 0; i < number_of_symbols; i++)
3439
    {
3440
      if (strncmp (symbol_table[i]->name,
3441
                   search_data->symname,
3442
                   strlen (search_data->symname)) == 0)
3443
        {
3444
          search_data->found = TRUE;
3445
          break;
3446
        }
3447
    }
3448
  free (symbol_table);
3449
}
3450
 
3451
/* This is the main implementation for the --identify option.
3452
   Given the name of an import library in identify_imp_name, first determine
3453
   if the import library is a GNU binutils-style one (where the DLL name is
3454
   stored in an .idata$7 (.idata$6 on PPC) section, or if it is a MS-style
3455
   one (where the DLL name, along with much other data, is stored in the
3456
   .idata$6 section). We determine the style of import library by searching
3457
   for the DLL-structure symbol inserted by MS tools:
3458
   __NULL_IMPORT_DESCRIPTOR.
3459
 
3460
   Once we know which section to search, evaluate each section for the
3461
   appropriate properties that indicate it may contain the name of the
3462
   associated DLL (this differs depending on the style).  Add the contents
3463
   of all sections which meet the criteria to a linked list of dll names.
3464
 
3465
   Finally, print them all to stdout. (If --identify-strict, an error is
3466
   reported if more than one match was found).  */
3467
 
3468
static void
3469
identify_dll_for_implib (void)
3470
{
3471
  bfd * abfd = NULL;
3472
  int count = 0;
3473
  identify_data_type identify_data;
3474
  symname_search_data_type search_data;
3475
 
3476
  /* Initialize identify_data.  */
3477
  identify_data.list = dll_name_list_create ();
3478
  identify_data.ms_style_implib = FALSE;
3479
 
3480
  /* Initialize search_data.  */
3481
  search_data.symname = "__NULL_IMPORT_DESCRIPTOR";
3482
  search_data.found = FALSE;
3483
 
3484
  bfd_init ();
3485
 
3486
  abfd = bfd_openr (identify_imp_name, 0);
3487
  if (abfd == NULL)
3488
    /* xgettext:c-format */
3489
    fatal (_("Can't open .lib file: %s: %s"),
3490
           identify_imp_name, bfd_get_errmsg ());
3491
 
3492
  if (! bfd_check_format (abfd, bfd_archive))
3493
    {
3494
      if (! bfd_close (abfd))
3495
        bfd_fatal (identify_imp_name);
3496
 
3497
      fatal (_("%s is not a library"), identify_imp_name);
3498
    }
3499
 
3500
  /* Detect if this a Microsoft import library.  */
3501
  identify_search_archive (abfd,
3502
                           identify_member_contains_symname,
3503
                           (void *)(& search_data));
3504
  if (search_data.found)
3505
    identify_data.ms_style_implib = TRUE;
3506
 
3507
  /* Rewind the bfd.  */
3508
  if (! bfd_close (abfd))
3509
    bfd_fatal (identify_imp_name);
3510
  abfd = bfd_openr (identify_imp_name, 0);
3511
  if (abfd == NULL)
3512
    bfd_fatal (identify_imp_name);
3513
 
3514
  if (!bfd_check_format (abfd, bfd_archive))
3515
    {
3516
      if (!bfd_close (abfd))
3517
        bfd_fatal (identify_imp_name);
3518
 
3519
      fatal (_("%s is not a library"), identify_imp_name);
3520
    }
3521
 
3522
  /* Now search for the dll name.  */
3523
  identify_search_archive (abfd,
3524
                           identify_search_member,
3525
                           (void *)(& identify_data));
3526
 
3527
  if (! bfd_close (abfd))
3528
    bfd_fatal (identify_imp_name);
3529
 
3530
  count = dll_name_list_count (identify_data.list);
3531
  if (count > 0)
3532
    {
3533
      if (identify_strict && count > 1)
3534
        {
3535
          dll_name_list_free (identify_data.list);
3536
          identify_data.list = NULL;
3537
          fatal (_("Import library `%s' specifies two or more dlls"),
3538
                 identify_imp_name);
3539
        }
3540
      dll_name_list_print (identify_data.list);
3541
      dll_name_list_free (identify_data.list);
3542
      identify_data.list = NULL;
3543
    }
3544
  else
3545
    {
3546
      dll_name_list_free (identify_data.list);
3547
      identify_data.list = NULL;
3548
      fatal (_("Unable to determine dll name for `%s' (not an import library?)"),
3549
             identify_imp_name);
3550
    }
3551
}
3552
 
3553
/* Loop over all members of the archive, applying the supplied function to
3554
   each member that is a bfd_object.  The function will be called as if:
3555
      func (member_bfd, abfd, user_storage)  */
3556
 
3557
static void
3558
identify_search_archive (bfd * abfd,
3559
                         void (* operation) (bfd *, bfd *, void *),
3560
                         void * user_storage)
3561
{
3562
  bfd *   arfile = NULL;
3563
  bfd *   last_arfile = NULL;
3564
  char ** matching;
3565
 
3566
  while (1)
3567
    {
3568
      arfile = bfd_openr_next_archived_file (abfd, arfile);
3569
 
3570
      if (arfile == NULL)
3571
        {
3572
          if (bfd_get_error () != bfd_error_no_more_archived_files)
3573
            bfd_fatal (bfd_get_filename (abfd));
3574
          break;
3575
        }
3576
 
3577
      if (bfd_check_format_matches (arfile, bfd_object, &matching))
3578
        (*operation) (arfile, abfd, user_storage);
3579
      else
3580
        {
3581
          bfd_nonfatal (bfd_get_filename (arfile));
3582
          free (matching);
3583
        }
3584
 
3585
      if (last_arfile != NULL)
3586
        bfd_close (last_arfile);
3587
 
3588
      last_arfile = arfile;
3589
    }
3590
 
3591
  if (last_arfile != NULL)
3592
    {
3593
      bfd_close (last_arfile);
3594
    }
3595
}
3596
 
3597
/* Call the identify_search_section() function for each section of this
3598
   archive member.  */
3599
 
3600
static void
3601
identify_search_member (bfd  *abfd,
3602
                        bfd  *archive_bfd ATTRIBUTE_UNUSED,
3603
                        void *obj)
3604
{
3605
  bfd_map_over_sections (abfd, identify_search_section, obj);
3606
}
3607
 
3608
/* This predicate returns true if section->name matches the desired value.
3609
   By default, this is .idata$7 (.idata$6 on PPC, or if the import
3610
   library is ms-style).  */
3611
 
3612
static bfd_boolean
3613
identify_process_section_p (asection * section, bfd_boolean ms_style_implib)
3614
{
3615
  static const char * SECTION_NAME =
3616
#ifdef DLLTOOL_PPC
3617
  /* dllname is stored in idata$6 on PPC */
3618
  ".idata$6";
3619
#else
3620
  ".idata$7";
3621
#endif
3622
  static const char * MS_SECTION_NAME = ".idata$6";
3623
 
3624
  const char * section_name =
3625
    (ms_style_implib ? MS_SECTION_NAME : SECTION_NAME);
3626
 
3627
  if (strcmp (section_name, section->name) == 0)
3628
    return TRUE;
3629
  return FALSE;
3630
}
3631
 
3632
/* If *section has contents and its name is .idata$7 (.data$6 on PPC or if
3633
   import lib ms-generated) -- and it satisfies several other constraints
3634
   -- then add the contents of the section to obj->list.  */
3635
 
3636
static void
3637
identify_search_section (bfd * abfd, asection * section, void * obj)
3638
{
3639
  bfd_byte *data = 0;
3640
  bfd_size_type datasize;
3641
  identify_data_type * identify_data = (identify_data_type *)obj;
3642
  bfd_boolean ms_style = identify_data->ms_style_implib;
3643
 
3644
  if ((section->flags & SEC_HAS_CONTENTS) == 0)
3645
    return;
3646
 
3647
  if (! identify_process_section_p (section, ms_style))
3648
    return;
3649
 
3650
  /* Binutils import libs seem distinguish the .idata$7 section that contains
3651
     the DLL name from other .idata$7 sections by the absence of the
3652
     SEC_RELOC flag.  */
3653
  if (!ms_style && ((section->flags & SEC_RELOC) == SEC_RELOC))
3654
    return;
3655
 
3656
  /* MS import libs seem to distinguish the .idata$6 section
3657
     that contains the DLL name from other .idata$6 sections
3658
     by the presence of the SEC_DATA flag.  */
3659
  if (ms_style && ((section->flags & SEC_DATA) == 0))
3660
    return;
3661
 
3662
  if ((datasize = bfd_section_size (abfd, section)) == 0)
3663
    return;
3664
 
3665
  data = (bfd_byte *) xmalloc (datasize + 1);
3666
  data[0] = '\0';
3667
 
3668
  bfd_get_section_contents (abfd, section, data, 0, datasize);
3669
  data[datasize] = '\0';
3670
 
3671
  /* Use a heuristic to determine if data is a dll name.
3672
     Possible to defeat this if (a) the library has MANY
3673
     (more than 0x302f) imports, (b) it is an ms-style
3674
     import library, but (c) it is buggy, in that the SEC_DATA
3675
     flag is set on the "wrong" sections.  This heuristic might
3676
     also fail to record a valid dll name if the dllname uses
3677
     a multibyte or unicode character set (is that valid?).
3678
 
3679
     This heuristic is based on the fact that symbols names in
3680
     the chosen section -- as opposed to the dll name -- begin
3681
     at offset 2 in the data. The first two bytes are a 16bit
3682
     little-endian count, and start at 0x0000. However, the dll
3683
     name begins at offset 0 in the data. We assume that the
3684
     dll name does not contain unprintable characters.   */
3685
  if (data[0] != '\0' && ISPRINT (data[0])
3686
      && ((datasize < 2) || ISPRINT (data[1])))
3687
    dll_name_list_append (identify_data->list, data);
3688
 
3689
  free (data);
3690
}
3691
 
3692
/* Run through the information gathered from the .o files and the
3693
   .def file and work out the best stuff.  */
3694
 
3695
static int
3696
pfunc (const void *a, const void *b)
3697
{
3698
  export_type *ap = *(export_type **) a;
3699
  export_type *bp = *(export_type **) b;
3700
 
3701
  if (ap->ordinal == bp->ordinal)
3702
    return 0;
3703
 
3704
  /* Unset ordinals go to the bottom.  */
3705
  if (ap->ordinal == -1)
3706
    return 1;
3707
  if (bp->ordinal == -1)
3708
    return -1;
3709
  return (ap->ordinal - bp->ordinal);
3710
}
3711
 
3712
static int
3713
nfunc (const void *a, const void *b)
3714
{
3715
  export_type *ap = *(export_type **) a;
3716
  export_type *bp = *(export_type **) b;
3717
  const char *an = ap->name;
3718
  const char *bn = bp->name;
3719
  if (ap->its_name)
3720
    an = ap->its_name;
3721
  if (bp->its_name)
3722
    an = bp->its_name;
3723
  if (killat)
3724
    {
3725
      an = (an[0] == '@') ? an + 1 : an;
3726
      bn = (bn[0] == '@') ? bn + 1 : bn;
3727
    }
3728
 
3729
  return (strcmp (an, bn));
3730
}
3731
 
3732
static void
3733
remove_null_names (export_type **ptr)
3734
{
3735
  int src;
3736
  int dst;
3737
 
3738
  for (dst = src = 0; src < d_nfuncs; src++)
3739
    {
3740
      if (ptr[src])
3741
        {
3742
          ptr[dst] = ptr[src];
3743
          dst++;
3744
        }
3745
    }
3746
  d_nfuncs = dst;
3747
}
3748
 
3749
static void
3750
process_duplicates (export_type **d_export_vec)
3751
{
3752
  int more = 1;
3753
  int i;
3754
 
3755
  while (more)
3756
    {
3757
      more = 0;
3758
      /* Remove duplicates.  */
3759
      qsort (d_export_vec, d_nfuncs, sizeof (export_type *), nfunc);
3760
 
3761
      for (i = 0; i < d_nfuncs - 1; i++)
3762
        {
3763
          if (strcmp (d_export_vec[i]->name,
3764
                      d_export_vec[i + 1]->name) == 0)
3765
            {
3766
              export_type *a = d_export_vec[i];
3767
              export_type *b = d_export_vec[i + 1];
3768
 
3769
              more = 1;
3770
 
3771
              /* xgettext:c-format */
3772
              inform (_("Warning, ignoring duplicate EXPORT %s %d,%d"),
3773
                      a->name, a->ordinal, b->ordinal);
3774
 
3775
              if (a->ordinal != -1
3776
                  && b->ordinal != -1)
3777
                /* xgettext:c-format */
3778
                fatal (_("Error, duplicate EXPORT with ordinals: %s"),
3779
                      a->name);
3780
 
3781
              /* Merge attributes.  */
3782
              b->ordinal = a->ordinal > 0 ? a->ordinal : b->ordinal;
3783
              b->constant |= a->constant;
3784
              b->noname |= a->noname;
3785
              b->data |= a->data;
3786
              d_export_vec[i] = 0;
3787
            }
3788
 
3789
          remove_null_names (d_export_vec);
3790
        }
3791
    }
3792
 
3793
  /* Count the names.  */
3794
  for (i = 0; i < d_nfuncs; i++)
3795
    if (!d_export_vec[i]->noname)
3796
      d_named_nfuncs++;
3797
}
3798
 
3799
static void
3800
fill_ordinals (export_type **d_export_vec)
3801
{
3802
  int lowest = -1;
3803
  int i;
3804
  char *ptr;
3805
  int size = 65536;
3806
 
3807
  qsort (d_export_vec, d_nfuncs, sizeof (export_type *), pfunc);
3808
 
3809
  /* Fill in the unset ordinals with ones from our range.  */
3810
  ptr = (char *) xmalloc (size);
3811
 
3812
  memset (ptr, 0, size);
3813
 
3814
  /* Mark in our large vector all the numbers that are taken.  */
3815
  for (i = 0; i < d_nfuncs; i++)
3816
    {
3817
      if (d_export_vec[i]->ordinal != -1)
3818
        {
3819
          ptr[d_export_vec[i]->ordinal] = 1;
3820
 
3821
          if (lowest == -1 || d_export_vec[i]->ordinal < lowest)
3822
            lowest = d_export_vec[i]->ordinal;
3823
        }
3824
    }
3825
 
3826
  /* Start at 1 for compatibility with MS toolchain.  */
3827
  if (lowest == -1)
3828
    lowest = 1;
3829
 
3830
  /* Now fill in ordinals where the user wants us to choose.  */
3831
  for (i = 0; i < d_nfuncs; i++)
3832
    {
3833
      if (d_export_vec[i]->ordinal == -1)
3834
        {
3835
          int j;
3836
 
3837
          /* First try within or after any user supplied range.  */
3838
          for (j = lowest; j < size; j++)
3839
            if (ptr[j] == 0)
3840
              {
3841
                ptr[j] = 1;
3842
                d_export_vec[i]->ordinal = j;
3843
                goto done;
3844
              }
3845
 
3846
          /* Then try before the range.  */
3847
          for (j = lowest; j >0; j--)
3848
            if (ptr[j] == 0)
3849
              {
3850
                ptr[j] = 1;
3851
                d_export_vec[i]->ordinal = j;
3852
                goto done;
3853
              }
3854
        done:;
3855
        }
3856
    }
3857
 
3858
  free (ptr);
3859
 
3860
  /* And resort.  */
3861
  qsort (d_export_vec, d_nfuncs, sizeof (export_type *), pfunc);
3862
 
3863
  /* Work out the lowest and highest ordinal numbers.  */
3864
  if (d_nfuncs)
3865
    {
3866
      if (d_export_vec[0])
3867
        d_low_ord = d_export_vec[0]->ordinal;
3868
      if (d_export_vec[d_nfuncs-1])
3869
        d_high_ord = d_export_vec[d_nfuncs-1]->ordinal;
3870
    }
3871
}
3872
 
3873
static void
3874
mangle_defs (void)
3875
{
3876
  /* First work out the minimum ordinal chosen.  */
3877
  export_type *exp;
3878
 
3879
  int i;
3880
  int hint = 0;
3881
  export_type **d_export_vec = xmalloc (sizeof (export_type *) * d_nfuncs);
3882
 
3883
  inform (_("Processing definitions"));
3884
 
3885
  for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
3886
    d_export_vec[i] = exp;
3887
 
3888
  process_duplicates (d_export_vec);
3889
  fill_ordinals (d_export_vec);
3890
 
3891
  /* Put back the list in the new order.  */
3892
  d_exports = 0;
3893
  for (i = d_nfuncs - 1; i >= 0; i--)
3894
    {
3895
      d_export_vec[i]->next = d_exports;
3896
      d_exports = d_export_vec[i];
3897
    }
3898
 
3899
  /* Build list in alpha order.  */
3900
  d_exports_lexically = (export_type **)
3901
    xmalloc (sizeof (export_type *) * (d_nfuncs + 1));
3902
 
3903
  for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
3904
    d_exports_lexically[i] = exp;
3905
 
3906
  d_exports_lexically[i] = 0;
3907
 
3908
  qsort (d_exports_lexically, i, sizeof (export_type *), nfunc);
3909
 
3910
  /* Fill exp entries with their hint values.  */
3911
  for (i = 0; i < d_nfuncs; i++)
3912
    if (!d_exports_lexically[i]->noname || show_allnames)
3913
      d_exports_lexically[i]->hint = hint++;
3914
 
3915
  inform (_("Processed definitions"));
3916
}
3917
 
3918
static void
3919
usage (FILE *file, int status)
3920
{
3921
  /* xgetext:c-format */
3922
  fprintf (file, _("Usage %s <option(s)> <object-file(s)>\n"), program_name);
3923
  /* xgetext:c-format */
3924
  fprintf (file, _("   -m --machine <machine>    Create as DLL for <machine>.  [default: %s]\n"), mname);
3925
  fprintf (file, _("        possible <machine>: arm[_interwork], i386, mcore[-elf]{-le|-be}, ppc, thumb\n"));
3926
  fprintf (file, _("   -e --output-exp <outname> Generate an export file.\n"));
3927
  fprintf (file, _("   -l --output-lib <outname> Generate an interface library.\n"));
3928
  fprintf (file, _("   -y --output-delaylib <outname> Create a delay-import library.\n"));
3929
  fprintf (file, _("   -a --add-indirect         Add dll indirects to export file.\n"));
3930
  fprintf (file, _("   -D --dllname <name>       Name of input dll to put into interface lib.\n"));
3931
  fprintf (file, _("   -d --input-def <deffile>  Name of .def file to be read in.\n"));
3932
  fprintf (file, _("   -z --output-def <deffile> Name of .def file to be created.\n"));
3933
  fprintf (file, _("      --export-all-symbols   Export all symbols to .def\n"));
3934
  fprintf (file, _("      --no-export-all-symbols  Only export listed symbols\n"));
3935
  fprintf (file, _("      --exclude-symbols <list> Don't export <list>\n"));
3936
  fprintf (file, _("      --no-default-excludes  Clear default exclude symbols\n"));
3937
  fprintf (file, _("   -b --base-file <basefile> Read linker generated base file.\n"));
3938
  fprintf (file, _("   -x --no-idata4            Don't generate idata$4 section.\n"));
3939
  fprintf (file, _("   -c --no-idata5            Don't generate idata$5 section.\n"));
3940
  fprintf (file, _("      --use-nul-prefixed-import-tables Use zero prefixed idata$4 and idata$5.\n"));
3941
  fprintf (file, _("   -U --add-underscore       Add underscores to all symbols in interface library.\n"));
3942
  fprintf (file, _("      --add-stdcall-underscore Add underscores to stdcall symbols in interface library.\n"));
3943
  fprintf (file, _("      --no-leading-underscore All symbols shouldn't be prefixed by an underscore.\n"));
3944
  fprintf (file, _("      --leading-underscore   All symbols should be prefixed by an underscore.\n"));
3945
  fprintf (file, _("   -k --kill-at              Kill @<n> from exported names.\n"));
3946
  fprintf (file, _("   -A --add-stdcall-alias    Add aliases without @<n>.\n"));
3947
  fprintf (file, _("   -p --ext-prefix-alias <prefix> Add aliases with <prefix>.\n"));
3948
  fprintf (file, _("   -S --as <name>            Use <name> for assembler.\n"));
3949
  fprintf (file, _("   -f --as-flags <flags>     Pass <flags> to the assembler.\n"));
3950
  fprintf (file, _("   -C --compat-implib        Create backward compatible import library.\n"));
3951
  fprintf (file, _("   -n --no-delete            Keep temp files (repeat for extra preservation).\n"));
3952
  fprintf (file, _("   -t --temp-prefix <prefix> Use <prefix> to construct temp file names.\n"));
3953
  fprintf (file, _("   -I --identify <implib>    Report the name of the DLL associated with <implib>.\n"));
3954
  fprintf (file, _("      --identify-strict      Causes --identify to report error when multiple DLLs.\n"));
3955
  fprintf (file, _("   -v --verbose              Be verbose.\n"));
3956
  fprintf (file, _("   -V --version              Display the program version.\n"));
3957
  fprintf (file, _("   -h --help                 Display this information.\n"));
3958
  fprintf (file, _("   @<file>                   Read options from <file>.\n"));
3959
#ifdef DLLTOOL_MCORE_ELF
3960
  fprintf (file, _("   -M --mcore-elf <outname>  Process mcore-elf object files into <outname>.\n"));
3961
  fprintf (file, _("   -L --linker <name>        Use <name> as the linker.\n"));
3962
  fprintf (file, _("   -F --linker-flags <flags> Pass <flags> to the linker.\n"));
3963
#endif
3964
  if (REPORT_BUGS_TO[0] && status == 0)
3965
    fprintf (file, _("Report bugs to %s\n"), REPORT_BUGS_TO);
3966
  exit (status);
3967
}
3968
 
3969
#define OPTION_EXPORT_ALL_SYMS          150
3970
#define OPTION_NO_EXPORT_ALL_SYMS       (OPTION_EXPORT_ALL_SYMS + 1)
3971
#define OPTION_EXCLUDE_SYMS             (OPTION_NO_EXPORT_ALL_SYMS + 1)
3972
#define OPTION_NO_DEFAULT_EXCLUDES      (OPTION_EXCLUDE_SYMS + 1)
3973
#define OPTION_ADD_STDCALL_UNDERSCORE   (OPTION_NO_DEFAULT_EXCLUDES + 1)
3974
#define OPTION_USE_NUL_PREFIXED_IMPORT_TABLES \
3975
  (OPTION_ADD_STDCALL_UNDERSCORE + 1)
3976
#define OPTION_IDENTIFY_STRICT          (OPTION_USE_NUL_PREFIXED_IMPORT_TABLES + 1)
3977
#define OPTION_NO_LEADING_UNDERSCORE    (OPTION_IDENTIFY_STRICT + 1)
3978
#define OPTION_LEADING_UNDERSCORE       (OPTION_NO_LEADING_UNDERSCORE + 1)
3979
 
3980
static const struct option long_options[] =
3981
{
3982
  {"no-delete", no_argument, NULL, 'n'},
3983
  {"dllname", required_argument, NULL, 'D'},
3984
  {"no-idata4", no_argument, NULL, 'x'},
3985
  {"no-idata5", no_argument, NULL, 'c'},
3986
  {"use-nul-prefixed-import-tables", no_argument, NULL,
3987
   OPTION_USE_NUL_PREFIXED_IMPORT_TABLES},
3988
  {"output-exp", required_argument, NULL, 'e'},
3989
  {"output-def", required_argument, NULL, 'z'},
3990
  {"export-all-symbols", no_argument, NULL, OPTION_EXPORT_ALL_SYMS},
3991
  {"no-export-all-symbols", no_argument, NULL, OPTION_NO_EXPORT_ALL_SYMS},
3992
  {"exclude-symbols", required_argument, NULL, OPTION_EXCLUDE_SYMS},
3993
  {"no-default-excludes", no_argument, NULL, OPTION_NO_DEFAULT_EXCLUDES},
3994
  {"output-lib", required_argument, NULL, 'l'},
3995
  {"def", required_argument, NULL, 'd'}, /* for compatibility with older versions */
3996
  {"input-def", required_argument, NULL, 'd'},
3997
  {"add-underscore", no_argument, NULL, 'U'},
3998
  {"add-stdcall-underscore", no_argument, NULL, OPTION_ADD_STDCALL_UNDERSCORE},
3999
  {"no-leading-underscore", no_argument, NULL, OPTION_NO_LEADING_UNDERSCORE},
4000
  {"leading-underscore", no_argument, NULL, OPTION_LEADING_UNDERSCORE},
4001
  {"kill-at", no_argument, NULL, 'k'},
4002
  {"add-stdcall-alias", no_argument, NULL, 'A'},
4003
  {"ext-prefix-alias", required_argument, NULL, 'p'},
4004
  {"identify", required_argument, NULL, 'I'},
4005
  {"identify-strict", no_argument, NULL, OPTION_IDENTIFY_STRICT},
4006
  {"verbose", no_argument, NULL, 'v'},
4007
  {"version", no_argument, NULL, 'V'},
4008
  {"help", no_argument, NULL, 'h'},
4009
  {"machine", required_argument, NULL, 'm'},
4010
  {"add-indirect", no_argument, NULL, 'a'},
4011
  {"base-file", required_argument, NULL, 'b'},
4012
  {"as", required_argument, NULL, 'S'},
4013
  {"as-flags", required_argument, NULL, 'f'},
4014
  {"mcore-elf", required_argument, NULL, 'M'},
4015
  {"compat-implib", no_argument, NULL, 'C'},
4016
  {"temp-prefix", required_argument, NULL, 't'},
4017
  {"output-delaylib", required_argument, NULL, 'y'},
4018
  {NULL,0,NULL,0}
4019
};
4020
 
4021
int main (int, char **);
4022
 
4023
int
4024
main (int ac, char **av)
4025
{
4026
  int c;
4027
  int i;
4028
  char *firstarg = 0;
4029
  program_name = av[0];
4030
  oav = av;
4031
 
4032
#if defined (HAVE_SETLOCALE) && defined (HAVE_LC_MESSAGES)
4033
  setlocale (LC_MESSAGES, "");
4034
#endif
4035
#if defined (HAVE_SETLOCALE)
4036
  setlocale (LC_CTYPE, "");
4037
#endif
4038
  bindtextdomain (PACKAGE, LOCALEDIR);
4039
  textdomain (PACKAGE);
4040
 
4041
  expandargv (&ac, &av);
4042
 
4043
  while ((c = getopt_long (ac, av,
4044
#ifdef DLLTOOL_MCORE_ELF
4045
                           "m:e:l:aD:d:z:b:xp:cCuUkAS:f:nI:vVHhM:L:F:",
4046
#else
4047
                           "m:e:l:y:aD:d:z:b:xp:cCuUkAS:f:nI:vVHh",
4048
#endif
4049
                           long_options, 0))
4050
         != EOF)
4051
    {
4052
      switch (c)
4053
        {
4054
        case OPTION_EXPORT_ALL_SYMS:
4055
          export_all_symbols = TRUE;
4056
          break;
4057
        case OPTION_NO_EXPORT_ALL_SYMS:
4058
          export_all_symbols = FALSE;
4059
          break;
4060
        case OPTION_EXCLUDE_SYMS:
4061
          add_excludes (optarg);
4062
          break;
4063
        case OPTION_NO_DEFAULT_EXCLUDES:
4064
          do_default_excludes = FALSE;
4065
          break;
4066
        case OPTION_USE_NUL_PREFIXED_IMPORT_TABLES:
4067
          use_nul_prefixed_import_tables = TRUE;
4068
          break;
4069
        case OPTION_ADD_STDCALL_UNDERSCORE:
4070
          add_stdcall_underscore = 1;
4071
          break;
4072
        case OPTION_NO_LEADING_UNDERSCORE:
4073
          leading_underscore = 0;
4074
          break;
4075
        case OPTION_LEADING_UNDERSCORE:
4076
          leading_underscore = 1;
4077
          break;
4078
        case OPTION_IDENTIFY_STRICT:
4079
          identify_strict = 1;
4080
          break;
4081
        case 'x':
4082
          no_idata4 = 1;
4083
          break;
4084
        case 'c':
4085
          no_idata5 = 1;
4086
          break;
4087
        case 'S':
4088
          as_name = optarg;
4089
          break;
4090
        case 't':
4091
          tmp_prefix = optarg;
4092
          break;
4093
        case 'f':
4094
          as_flags = optarg;
4095
          break;
4096
 
4097
          /* Ignored for compatibility.  */
4098
        case 'u':
4099
          break;
4100
        case 'a':
4101
          add_indirect = 1;
4102
          break;
4103
        case 'z':
4104
          output_def = fopen (optarg, FOPEN_WT);
4105
          break;
4106
        case 'D':
4107
          dll_name = (char*) lbasename (optarg);
4108
          if (dll_name != optarg)
4109
            non_fatal (_("Path components stripped from dllname, '%s'."),
4110
                         optarg);
4111
          break;
4112
        case 'l':
4113
          imp_name = optarg;
4114
          break;
4115
        case 'e':
4116
          exp_name = optarg;
4117
          break;
4118
        case 'H':
4119
        case 'h':
4120
          usage (stdout, 0);
4121
          break;
4122
        case 'm':
4123
          mname = optarg;
4124
          break;
4125
        case 'I':
4126
          identify_imp_name = optarg;
4127
          break;
4128
        case 'v':
4129
          verbose = 1;
4130
          break;
4131
        case 'V':
4132
          print_version (program_name);
4133
          break;
4134
        case 'U':
4135
          add_underscore = 1;
4136
          break;
4137
        case 'k':
4138
          killat = 1;
4139
          break;
4140
        case 'A':
4141
          add_stdcall_alias = 1;
4142
          break;
4143
        case 'p':
4144
          ext_prefix_alias = optarg;
4145
          break;
4146
        case 'd':
4147
          def_file = optarg;
4148
          break;
4149
        case 'n':
4150
          dontdeltemps++;
4151
          break;
4152
        case 'b':
4153
          base_file = fopen (optarg, FOPEN_RB);
4154
 
4155
          if (!base_file)
4156
            /* xgettext:c-format */
4157
            fatal (_("Unable to open base-file: %s"), optarg);
4158
 
4159
          break;
4160
#ifdef DLLTOOL_MCORE_ELF
4161
        case 'M':
4162
          mcore_elf_out_file = optarg;
4163
          break;
4164
        case 'L':
4165
          mcore_elf_linker = optarg;
4166
          break;
4167
        case 'F':
4168
          mcore_elf_linker_flags = optarg;
4169
          break;
4170
#endif
4171
        case 'C':
4172
          create_compat_implib = 1;
4173
          break;
4174
        case 'y':
4175
          delayimp_name = optarg;
4176
          break;
4177
        default:
4178
          usage (stderr, 1);
4179
          break;
4180
        }
4181
    }
4182
 
4183
  if (!tmp_prefix)
4184
    tmp_prefix = prefix_encode ("d", getpid ());
4185
 
4186
  for (i = 0; mtable[i].type; i++)
4187
    if (strcmp (mtable[i].type, mname) == 0)
4188
      break;
4189
 
4190
  if (!mtable[i].type)
4191
    /* xgettext:c-format */
4192
    fatal (_("Machine '%s' not supported"), mname);
4193
 
4194
  machine = i;
4195
 
4196
  /* Check if we generated PE+.  */
4197
  create_for_pep = strcmp (mname, "i386:x86-64") == 0;
4198
 
4199
  {
4200
    /* Check the default underscore */
4201
    int u = leading_underscore; /* Underscoring mode. -1 for use default.  */
4202
    if (u == -1)
4203
      bfd_get_target_info (mtable[machine].how_bfd_target, NULL,
4204
                           NULL, &u, NULL);
4205
    if (u != -1)
4206
      leading_underscore = (u != 0 ? TRUE : FALSE);
4207
  }
4208
 
4209
  if (!dll_name && exp_name)
4210
    {
4211
      /* If we are inferring dll_name from exp_name,
4212
         strip off any path components, without emitting
4213
         a warning.  */
4214
      const char* exp_basename = lbasename (exp_name);
4215
      const int len = strlen (exp_basename) + 5;
4216
      dll_name = xmalloc (len);
4217
      strcpy (dll_name, exp_basename);
4218
      strcat (dll_name, ".dll");
4219
      dll_name_set_by_exp_name = 1;
4220
    }
4221
 
4222
  if (as_name == NULL)
4223
    as_name = deduce_name ("as");
4224
 
4225
  /* Don't use the default exclude list if we're reading only the
4226
     symbols in the .drectve section.  The default excludes are meant
4227
     to avoid exporting DLL entry point and Cygwin32 impure_ptr.  */
4228
  if (! export_all_symbols)
4229
    do_default_excludes = FALSE;
4230
 
4231
  if (do_default_excludes)
4232
    set_default_excludes ();
4233
 
4234
  if (def_file)
4235
    process_def_file (def_file);
4236
 
4237
  while (optind < ac)
4238
    {
4239
      if (!firstarg)
4240
        firstarg = av[optind];
4241
      scan_obj_file (av[optind]);
4242
      optind++;
4243
    }
4244
 
4245
  mangle_defs ();
4246
 
4247
  if (exp_name)
4248
    gen_exp_file ();
4249
 
4250
  if (imp_name)
4251
    {
4252
      /* Make imp_name safe for use as a label.  */
4253
      char *p;
4254
 
4255
      imp_name_lab = xstrdup (imp_name);
4256
      for (p = imp_name_lab; *p; p++)
4257
        {
4258
          if (!ISALNUM (*p))
4259
            *p = '_';
4260
        }
4261
      head_label = make_label("_head_", imp_name_lab);
4262
      gen_lib_file (0);
4263
    }
4264
 
4265
  if (delayimp_name)
4266
    {
4267
      /* Make delayimp_name safe for use as a label.  */
4268
      char *p;
4269
 
4270
      if (mtable[machine].how_dljtab == 0)
4271
        {
4272
          inform (_("Warning, machine type (%d) not supported for "
4273
                        "delayimport."), machine);
4274
        }
4275
      else
4276
        {
4277
          killat = 1;
4278
          imp_name = delayimp_name;
4279
          imp_name_lab = xstrdup (imp_name);
4280
          for (p = imp_name_lab; *p; p++)
4281
            {
4282
              if (!ISALNUM (*p))
4283
                *p = '_';
4284
            }
4285
          head_label = make_label("__tailMerge_", imp_name_lab);
4286
          gen_lib_file (1);
4287
        }
4288
    }
4289
 
4290
  if (output_def)
4291
    gen_def_file ();
4292
 
4293
  if (identify_imp_name)
4294
    {
4295
      identify_dll_for_implib ();
4296
    }
4297
 
4298
#ifdef DLLTOOL_MCORE_ELF
4299
  if (mcore_elf_out_file)
4300
    mcore_elf_gen_out_file ();
4301
#endif
4302
 
4303
  return 0;
4304
}
4305
 
4306
/* Look for the program formed by concatenating PROG_NAME and the
4307
   string running from PREFIX to END_PREFIX.  If the concatenated
4308
   string contains a '/', try appending EXECUTABLE_SUFFIX if it is
4309
   appropriate.  */
4310
 
4311
static char *
4312
look_for_prog (const char *prog_name, const char *prefix, int end_prefix)
4313
{
4314
  struct stat s;
4315
  char *cmd;
4316
 
4317
  cmd = xmalloc (strlen (prefix)
4318
                 + strlen (prog_name)
4319
#ifdef HAVE_EXECUTABLE_SUFFIX
4320
                 + strlen (EXECUTABLE_SUFFIX)
4321
#endif
4322
                 + 10);
4323
  strcpy (cmd, prefix);
4324
 
4325
  sprintf (cmd + end_prefix, "%s", prog_name);
4326
 
4327
  if (strchr (cmd, '/') != NULL)
4328
    {
4329
      int found;
4330
 
4331
      found = (stat (cmd, &s) == 0
4332
#ifdef HAVE_EXECUTABLE_SUFFIX
4333
               || stat (strcat (cmd, EXECUTABLE_SUFFIX), &s) == 0
4334
#endif
4335
               );
4336
 
4337
      if (! found)
4338
        {
4339
          /* xgettext:c-format */
4340
          inform (_("Tried file: %s"), cmd);
4341
          free (cmd);
4342
          return NULL;
4343
        }
4344
    }
4345
 
4346
  /* xgettext:c-format */
4347
  inform (_("Using file: %s"), cmd);
4348
 
4349
  return cmd;
4350
}
4351
 
4352
/* Deduce the name of the program we are want to invoke.
4353
   PROG_NAME is the basic name of the program we want to run,
4354
   eg "as" or "ld".  The catch is that we might want actually
4355
   run "i386-pe-as" or "ppc-pe-ld".
4356
 
4357
   If argv[0] contains the full path, then try to find the program
4358
   in the same place, with and then without a target-like prefix.
4359
 
4360
   Given, argv[0] = /usr/local/bin/i586-cygwin32-dlltool,
4361
   deduce_name("as") uses the following search order:
4362
 
4363
     /usr/local/bin/i586-cygwin32-as
4364
     /usr/local/bin/as
4365
     as
4366
 
4367
   If there's an EXECUTABLE_SUFFIX, it'll use that as well; for each
4368
   name, it'll try without and then with EXECUTABLE_SUFFIX.
4369
 
4370
   Given, argv[0] = i586-cygwin32-dlltool, it will not even try "as"
4371
   as the fallback, but rather return i586-cygwin32-as.
4372
 
4373
   Oh, and given, argv[0] = dlltool, it'll return "as".
4374
 
4375
   Returns a dynamically allocated string.  */
4376
 
4377
static char *
4378
deduce_name (const char *prog_name)
4379
{
4380
  char *cmd;
4381
  char *dash, *slash, *cp;
4382
 
4383
  dash = NULL;
4384
  slash = NULL;
4385
  for (cp = program_name; *cp != '\0'; ++cp)
4386
    {
4387
      if (*cp == '-')
4388
        dash = cp;
4389
      if (
4390
#if defined(__DJGPP__) || defined (__CYGWIN__) || defined(__WIN32__)
4391
          *cp == ':' || *cp == '\\' ||
4392
#endif
4393
          *cp == '/')
4394
        {
4395
          slash = cp;
4396
          dash = NULL;
4397
        }
4398
    }
4399
 
4400
  cmd = NULL;
4401
 
4402
  if (dash != NULL)
4403
    {
4404
      /* First, try looking for a prefixed PROG_NAME in the
4405
         PROGRAM_NAME directory, with the same prefix as PROGRAM_NAME.  */
4406
      cmd = look_for_prog (prog_name, program_name, dash - program_name + 1);
4407
    }
4408
 
4409
  if (slash != NULL && cmd == NULL)
4410
    {
4411
      /* Next, try looking for a PROG_NAME in the same directory as
4412
         that of this program.  */
4413
      cmd = look_for_prog (prog_name, program_name, slash - program_name + 1);
4414
    }
4415
 
4416
  if (cmd == NULL)
4417
    {
4418
      /* Just return PROG_NAME as is.  */
4419
      cmd = xstrdup (prog_name);
4420
    }
4421
 
4422
  return cmd;
4423
}
4424
 
4425
#ifdef DLLTOOL_MCORE_ELF
4426
typedef struct fname_cache
4427
{
4428
  const char *         filename;
4429
  struct fname_cache * next;
4430
}
4431
fname_cache;
4432
 
4433
static fname_cache fnames;
4434
 
4435
static void
4436
mcore_elf_cache_filename (const char * filename)
4437
{
4438
  fname_cache * ptr;
4439
 
4440
  ptr = & fnames;
4441
 
4442
  while (ptr->next != NULL)
4443
    ptr = ptr->next;
4444
 
4445
  ptr->filename = filename;
4446
  ptr->next     = (fname_cache *) malloc (sizeof (fname_cache));
4447
  if (ptr->next != NULL)
4448
    ptr->next->next = NULL;
4449
}
4450
 
4451
#define MCORE_ELF_TMP_OBJ "mcoreelf.o"
4452
#define MCORE_ELF_TMP_EXP "mcoreelf.exp"
4453
#define MCORE_ELF_TMP_LIB "mcoreelf.lib"
4454
 
4455
static void
4456
mcore_elf_gen_out_file (void)
4457
{
4458
  fname_cache * ptr;
4459
  dyn_string_t ds;
4460
 
4461
  /* Step one.  Run 'ld -r' on the input object files in order to resolve
4462
     any internal references and to generate a single .exports section.  */
4463
  ptr = & fnames;
4464
 
4465
  ds = dyn_string_new (100);
4466
  dyn_string_append_cstr (ds, "-r ");
4467
 
4468
  if (mcore_elf_linker_flags != NULL)
4469
    dyn_string_append_cstr (ds, mcore_elf_linker_flags);
4470
 
4471
  while (ptr->next != NULL)
4472
    {
4473
      dyn_string_append_cstr (ds, ptr->filename);
4474
      dyn_string_append_cstr (ds, " ");
4475
 
4476
      ptr = ptr->next;
4477
    }
4478
 
4479
  dyn_string_append_cstr (ds, "-o ");
4480
  dyn_string_append_cstr (ds, MCORE_ELF_TMP_OBJ);
4481
 
4482
  if (mcore_elf_linker == NULL)
4483
    mcore_elf_linker = deduce_name ("ld");
4484
 
4485
  run (mcore_elf_linker, ds->s);
4486
 
4487
  dyn_string_delete (ds);
4488
 
4489
  /* Step two. Create a .exp file and a .lib file from the temporary file.
4490
     Do this by recursively invoking dlltool...  */
4491
  ds = dyn_string_new (100);
4492
 
4493
  dyn_string_append_cstr (ds, "-S ");
4494
  dyn_string_append_cstr (ds, as_name);
4495
 
4496
  dyn_string_append_cstr (ds, " -e ");
4497
  dyn_string_append_cstr (ds, MCORE_ELF_TMP_EXP);
4498
  dyn_string_append_cstr (ds, " -l ");
4499
  dyn_string_append_cstr (ds, MCORE_ELF_TMP_LIB);
4500
  dyn_string_append_cstr (ds, " " );
4501
  dyn_string_append_cstr (ds, MCORE_ELF_TMP_OBJ);
4502
 
4503
  if (verbose)
4504
    dyn_string_append_cstr (ds, " -v");
4505
 
4506
  if (dontdeltemps)
4507
    {
4508
      dyn_string_append_cstr (ds, " -n");
4509
 
4510
      if (dontdeltemps > 1)
4511
        dyn_string_append_cstr (ds, " -n");
4512
    }
4513
 
4514
  /* XXX - FIME: ought to check/copy other command line options as well.  */
4515
  run (program_name, ds->s);
4516
 
4517
  dyn_string_delete (ds);
4518
 
4519
  /* Step four. Feed the .exp and object files to ld -shared to create the dll.  */
4520
  ds = dyn_string_new (100);
4521
 
4522
  dyn_string_append_cstr (ds, "-shared ");
4523
 
4524
  if (mcore_elf_linker_flags)
4525
    dyn_string_append_cstr (ds, mcore_elf_linker_flags);
4526
 
4527
  dyn_string_append_cstr (ds, " ");
4528
  dyn_string_append_cstr (ds, MCORE_ELF_TMP_EXP);
4529
  dyn_string_append_cstr (ds, " ");
4530
  dyn_string_append_cstr (ds, MCORE_ELF_TMP_OBJ);
4531
  dyn_string_append_cstr (ds, " -o ");
4532
  dyn_string_append_cstr (ds, mcore_elf_out_file);
4533
 
4534
  run (mcore_elf_linker, ds->s);
4535
 
4536
  dyn_string_delete (ds);
4537
 
4538
  if (dontdeltemps == 0)
4539
    unlink (MCORE_ELF_TMP_EXP);
4540
 
4541
  if (dontdeltemps < 2)
4542
    unlink (MCORE_ELF_TMP_OBJ);
4543
}
4544
#endif /* DLLTOOL_MCORE_ELF */

powered by: WebSVN 2.1.0

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