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 146

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

powered by: WebSVN 2.1.0

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