Back to index

cell-binutils  2.17cvs20070401
dlltool.c
Go to the documentation of this file.
00001 /* dlltool.c -- tool to generate stuff for PE style DLLs
00002    Copyright 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
00003    2005, 2006, 2007 Free Software Foundation, Inc.
00004 
00005    This file is part of GNU Binutils.
00006 
00007    This program is free software; you can redistribute it and/or modify
00008    it under the terms of the GNU General Public License as published by
00009    the Free Software Foundation; either version 2 of the License, or
00010    (at your option) any later version.
00011 
00012    This program is distributed in the hope that it will be useful,
00013    but WITHOUT ANY WARRANTY; without even the implied warranty of
00014    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015    GNU General Public License for more details.
00016 
00017    You should have received a copy of the GNU General Public License
00018    along with this program; if not, write to the Free Software
00019    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
00020    02110-1301, USA.  */
00021 
00022 
00023 /* This program allows you to build the files necessary to create
00024    DLLs to run on a system which understands PE format image files.
00025    (eg, Windows NT)
00026 
00027    See "Peering Inside the PE: A Tour of the Win32 Portable Executable
00028    File Format", MSJ 1994, Volume 9 for more information.
00029    Also see "Microsoft Portable Executable and Common Object File Format,
00030    Specification 4.1" for more information.
00031 
00032    A DLL contains an export table which contains the information
00033    which the runtime loader needs to tie up references from a
00034    referencing program.
00035 
00036    The export table is generated by this program by reading
00037    in a .DEF file or scanning the .a and .o files which will be in the
00038    DLL.  A .o file can contain information in special  ".drectve" sections
00039    with export information.
00040 
00041    A DEF file contains any number of the following commands:
00042 
00043 
00044    NAME <name> [ , <base> ]
00045    The result is going to be <name>.EXE
00046 
00047    LIBRARY <name> [ , <base> ]
00048    The result is going to be <name>.DLL
00049 
00050    EXPORTS  ( (  ( <name1> [ = <name2> ] )
00051                | ( <name1> = <module-name> . <external-name>))
00052             [ @ <integer> ] [ NONAME ] [CONSTANT] [DATA] [PRIVATE] ) *
00053    Declares name1 as an exported symbol from the
00054    DLL, with optional ordinal number <integer>.
00055    Or declares name1 as an alias (forward) of the function <external-name>
00056    in the DLL <module-name>.
00057 
00058    IMPORTS  (  (   <internal-name> =   <module-name> . <integer> )
00059              | ( [ <internal-name> = ] <module-name> . <external-name> )) *
00060    Declares that <external-name> or the exported function whose ordinal number
00061    is <integer> is to be imported from the file <module-name>.  If
00062    <internal-name> is specified then this is the name that the imported
00063    function will be refereed to in the body of the DLL.
00064 
00065    DESCRIPTION <string>
00066    Puts <string> into output .exp file in the .rdata section
00067 
00068    [STACKSIZE|HEAPSIZE] <number-reserve> [ , <number-commit> ]
00069    Generates --stack|--heap <number-reserve>,<number-commit>
00070    in the output .drectve section.  The linker will
00071    see this and act upon it.
00072 
00073    [CODE|DATA] <attr>+
00074    SECTIONS ( <sectionname> <attr>+ )*
00075    <attr> = READ | WRITE | EXECUTE | SHARED
00076    Generates --attr <sectionname> <attr> in the output
00077    .drectve section.  The linker will see this and act
00078    upon it.
00079 
00080 
00081    A -export:<name> in a .drectve section in an input .o or .a
00082    file to this program is equivalent to a EXPORTS <name>
00083    in a .DEF file.
00084 
00085 
00086 
00087    The program generates output files with the prefix supplied
00088    on the command line, or in the def file, or taken from the first
00089    supplied argument.
00090 
00091    The .exp.s file contains the information necessary to export
00092    the routines in the DLL.  The .lib.s file contains the information
00093    necessary to use the DLL's routines from a referencing program.
00094 
00095 
00096 
00097    Example:
00098 
00099  file1.c:
00100    asm (".section .drectve");
00101    asm (".ascii \"-export:adef\"");
00102 
00103    void adef (char * s)
00104    {
00105      printf ("hello from the dll %s\n", s);
00106    }
00107 
00108    void bdef (char * s)
00109    {
00110      printf ("hello from the dll and the other entry point %s\n", s);
00111    }
00112 
00113  file2.c:
00114    asm (".section .drectve");
00115    asm (".ascii \"-export:cdef\"");
00116    asm (".ascii \"-export:ddef\"");
00117 
00118    void cdef (char * s)
00119    {
00120      printf ("hello from the dll %s\n", s);
00121    }
00122 
00123    void ddef (char * s)
00124    {
00125      printf ("hello from the dll and the other entry point %s\n", s);
00126    }
00127 
00128    int printf (void)
00129    {
00130      return 9;
00131    }
00132 
00133  themain.c:
00134    int main (void)
00135    {
00136      cdef ();
00137      return 0;
00138    }
00139 
00140  thedll.def
00141 
00142    LIBRARY thedll
00143    HEAPSIZE 0x40000, 0x2000
00144    EXPORTS bdef @ 20
00145            cdef @ 30 NONAME
00146 
00147    SECTIONS donkey READ WRITE
00148    aardvark EXECUTE
00149 
00150  # Compile up the parts of the dll and the program
00151 
00152    gcc -c file1.c file2.c themain.c
00153 
00154  # Optional: put the dll objects into a library
00155  # (you don't have to, you could name all the object
00156  # files on the dlltool line)
00157 
00158    ar  qcv thedll.in file1.o file2.o
00159    ranlib thedll.in
00160 
00161  # Run this tool over the DLL's .def file and generate an exports
00162  # file (thedll.o) and an imports file (thedll.a).
00163  # (You may have to use -S to tell dlltool where to find the assembler).
00164 
00165    dlltool --def thedll.def --output-exp thedll.o --output-lib thedll.a
00166 
00167  # Build the dll with the library and the export table
00168 
00169    ld -o thedll.dll thedll.o thedll.in
00170 
00171  # Link the executable with the import library
00172 
00173    gcc -o themain.exe themain.o thedll.a
00174 
00175  This example can be extended if relocations are needed in the DLL:
00176 
00177  # Compile up the parts of the dll and the program
00178 
00179    gcc -c file1.c file2.c themain.c
00180 
00181  # Run this tool over the DLL's .def file and generate an imports file.
00182 
00183    dlltool --def thedll.def --output-lib thedll.lib
00184 
00185  # Link the executable with the import library and generate a base file
00186  # at the same time
00187 
00188    gcc -o themain.exe themain.o thedll.lib -Wl,--base-file -Wl,themain.base
00189 
00190  # Run this tool over the DLL's .def file and generate an exports file
00191  # which includes the relocations from the base file.
00192 
00193    dlltool --def thedll.def --base-file themain.base --output-exp thedll.exp
00194 
00195  # Build the dll with file1.o, file2.o and the export table
00196 
00197    ld -o thedll.dll thedll.exp file1.o file2.o  */
00198 
00199 /* .idata section description
00200 
00201    The .idata section is the import table.  It is a collection of several
00202    subsections used to keep the pieces for each dll together: .idata$[234567].
00203    IE: Each dll's .idata$2's are catenated together, each .idata$3's, etc.
00204 
00205    .idata$2 = Import Directory Table
00206    = array of IMAGE_IMPORT_DESCRIPTOR's.
00207 
00208        DWORD   Import Lookup Table;  - pointer to .idata$4
00209        DWORD   TimeDateStamp;        - currently always 0
00210        DWORD   ForwarderChain;       - currently always 0
00211        DWORD   Name;                 - pointer to dll's name
00212        PIMAGE_THUNK_DATA FirstThunk; - pointer to .idata$5
00213 
00214    .idata$3 = null terminating entry for .idata$2.
00215 
00216    .idata$4 = Import Lookup Table
00217    = array of array of pointers to hint name table.
00218    There is one for each dll being imported from, and each dll's set is
00219    terminated by a trailing NULL.
00220 
00221    .idata$5 = Import Address Table
00222    = array of array of pointers to hint name table.
00223    There is one for each dll being imported from, and each dll's set is
00224    terminated by a trailing NULL.
00225    Initially, this table is identical to the Import Lookup Table.  However,
00226    at load time, the loader overwrites the entries with the address of the
00227    function.
00228 
00229    .idata$6 = Hint Name Table
00230    = Array of { short, asciz } entries, one for each imported function.
00231    The `short' is the function's ordinal number.
00232 
00233    .idata$7 = dll name (eg: "kernel32.dll"). (.idata$6 for ppc).  */
00234 
00235 /* AIX requires this to be the first thing in the file.  */
00236 #ifndef __GNUC__
00237 # ifdef _AIX
00238  #pragma alloca
00239 #endif
00240 #endif
00241 
00242 #define show_allnames 0
00243 
00244 #define PAGE_SIZE 4096
00245 #define PAGE_MASK (-PAGE_SIZE)
00246 #include "bfd.h"
00247 #include "libiberty.h"
00248 #include "bucomm.h"
00249 #include "getopt.h"
00250 #include "demangle.h"
00251 #include "dyn-string.h"
00252 #include "dlltool.h"
00253 #include "safe-ctype.h"
00254 
00255 #include <time.h>
00256 #include <sys/stat.h>
00257 #include <stdarg.h>
00258 #include <assert.h>
00259 
00260 #ifdef DLLTOOL_ARM
00261 #include "coff/arm.h"
00262 #include "coff/internal.h"
00263 #endif
00264 #ifdef DLLTOOL_MX86_64
00265 #include "coff/x86_64.h"
00266 #endif
00267 
00268 /* Forward references.  */
00269 static char *look_for_prog (const char *, const char *, int);
00270 static char *deduce_name (const char *);
00271 
00272 #ifdef DLLTOOL_MCORE_ELF
00273 static void mcore_elf_cache_filename (char *);
00274 static void mcore_elf_gen_out_file (void);
00275 #endif
00276 
00277 #ifdef HAVE_SYS_WAIT_H
00278 #include <sys/wait.h>
00279 #else /* ! HAVE_SYS_WAIT_H */
00280 #if ! defined (_WIN32) || defined (__CYGWIN32__)
00281 #ifndef WIFEXITED
00282 #define WIFEXITED(w) (((w) & 0377) == 0)
00283 #endif
00284 #ifndef WIFSIGNALED
00285 #define WIFSIGNALED(w)      (((w) & 0377) != 0177 && ((w) & ~0377) == 0)
00286 #endif
00287 #ifndef WTERMSIG
00288 #define WTERMSIG(w)  ((w) & 0177)
00289 #endif
00290 #ifndef WEXITSTATUS
00291 #define WEXITSTATUS(w)      (((w) >> 8) & 0377)
00292 #endif
00293 #else /* defined (_WIN32) && ! defined (__CYGWIN32__) */
00294 #ifndef WIFEXITED
00295 #define WIFEXITED(w) (((w) & 0xff) == 0)
00296 #endif
00297 #ifndef WIFSIGNALED
00298 #define WIFSIGNALED(w)      (((w) & 0xff) != 0 && ((w) & 0xff) != 0x7f)
00299 #endif
00300 #ifndef WTERMSIG
00301 #define WTERMSIG(w)  ((w) & 0x7f)
00302 #endif
00303 #ifndef WEXITSTATUS
00304 #define WEXITSTATUS(w)      (((w) & 0xff00) >> 8)
00305 #endif
00306 #endif /* defined (_WIN32) && ! defined (__CYGWIN32__) */
00307 #endif /* ! HAVE_SYS_WAIT_H */
00308 
00309 /* ifunc and ihead data structures: ttk@cygnus.com 1997
00310 
00311    When IMPORT declarations are encountered in a .def file the
00312    function import information is stored in a structure referenced by
00313    the global variable IMPORT_LIST.  The structure is a linked list
00314    containing the names of the dll files each function is imported
00315    from and a linked list of functions being imported from that dll
00316    file.  This roughly parallels the structure of the .idata section
00317    in the PE object file.
00318 
00319    The contents of .def file are interpreted from within the
00320    process_def_file function.  Every time an IMPORT declaration is
00321    encountered, it is broken up into its component parts and passed to
00322    def_import.  IMPORT_LIST is initialized to NULL in function main.  */
00323 
00324 typedef struct ifunct
00325 {
00326   char *         name;   /* Name of function being imported.  */
00327   int            ord;    /* Two-byte ordinal value associated with function.  */
00328   struct ifunct *next;
00329 } ifunctype;
00330 
00331 typedef struct iheadt
00332 {
00333   char          *dllname;  /* Name of dll file imported from.  */
00334   long           nfuncs;   /* Number of functions in list.  */
00335   struct ifunct *funchead; /* First function in list.  */
00336   struct ifunct *functail; /* Last  function in list.  */
00337   struct iheadt *next;     /* Next dll file in list.  */
00338 } iheadtype;
00339 
00340 /* Structure containing all import information as defined in .def file
00341    (qv "ihead structure").  */
00342 
00343 static iheadtype *import_list = NULL;
00344 
00345 static char *as_name = NULL;
00346 static char * as_flags = "";
00347 
00348 static char *tmp_prefix;
00349 
00350 static int no_idata4;
00351 static int no_idata5;
00352 static char *exp_name;
00353 static char *imp_name;
00354 static char *head_label;
00355 static char *imp_name_lab;
00356 static char *dll_name;
00357 
00358 static int add_indirect = 0;
00359 static int add_underscore = 0;
00360 static int add_stdcall_underscore = 0;
00361 static int dontdeltemps = 0;
00362 
00363 /* TRUE if we should export all symbols.  Otherwise, we only export
00364    symbols listed in .drectve sections or in the def file.  */
00365 static bfd_boolean export_all_symbols;
00366 
00367 /* TRUE if we should exclude the symbols in DEFAULT_EXCLUDES when
00368    exporting all symbols.  */
00369 static bfd_boolean do_default_excludes = TRUE;
00370 
00371 /* Default symbols to exclude when exporting all the symbols.  */
00372 static const char *default_excludes = "DllMain@12,DllEntryPoint@0,impure_ptr";
00373 
00374 /* TRUE if we should add __imp_<SYMBOL> to import libraries for backward
00375    compatibility to old Cygwin releases.  */
00376 static bfd_boolean create_compat_implib;
00377 
00378 static char *def_file;
00379 
00380 extern char * program_name;
00381 
00382 static int machine;
00383 static int killat;
00384 static int add_stdcall_alias;
00385 static const char *ext_prefix_alias;
00386 static int verbose;
00387 static FILE *output_def;
00388 static FILE *base_file;
00389 
00390 #ifdef DLLTOOL_DEFAULT_ARM
00391 static const char *mname = "arm";
00392 #endif
00393 
00394 #ifdef DLLTOOL_DEFAULT_ARM_EPOC
00395 static const char *mname = "arm-epoc";
00396 #endif
00397 
00398 #ifdef DLLTOOL_DEFAULT_ARM_WINCE
00399 static const char *mname = "arm-wince";
00400 #endif
00401 
00402 #ifdef DLLTOOL_DEFAULT_I386
00403 static const char *mname = "i386";
00404 #endif
00405 
00406 #ifdef DLLTOOL_DEFAULT_MX86_64
00407 static const char *mname = "i386:x86-64";
00408 #endif
00409 
00410 #ifdef DLLTOOL_DEFAULT_PPC
00411 static const char *mname = "ppc";
00412 #endif
00413 
00414 #ifdef DLLTOOL_DEFAULT_SH
00415 static const char *mname = "sh";
00416 #endif
00417 
00418 #ifdef DLLTOOL_DEFAULT_MIPS
00419 static const char *mname = "mips";
00420 #endif
00421 
00422 #ifdef DLLTOOL_DEFAULT_MCORE
00423 static const char * mname = "mcore-le";
00424 #endif
00425 
00426 #ifdef DLLTOOL_DEFAULT_MCORE_ELF
00427 static const char * mname = "mcore-elf";
00428 static char * mcore_elf_out_file = NULL;
00429 static char * mcore_elf_linker   = NULL;
00430 static char * mcore_elf_linker_flags = NULL;
00431 
00432 #define DRECTVE_SECTION_NAME ((machine == MMCORE_ELF || machine == MMCORE_ELF_LE) ? ".exports" : ".drectve")
00433 #endif
00434 
00435 #ifndef DRECTVE_SECTION_NAME
00436 #define DRECTVE_SECTION_NAME ".drectve"
00437 #endif
00438 
00439 /* What's the right name for this ?  */
00440 #define PATHMAX 250         
00441 
00442 /* External name alias numbering starts here.  */
00443 #define PREFIX_ALIAS_BASE   20000
00444 
00445 char *tmp_asm_buf;
00446 char *tmp_head_s_buf;
00447 char *tmp_head_o_buf;
00448 char *tmp_tail_s_buf;
00449 char *tmp_tail_o_buf;
00450 char *tmp_stub_buf;
00451 
00452 #define TMP_ASM             dlltmp (&tmp_asm_buf, "%sc.s")
00453 #define TMP_HEAD_S   dlltmp (&tmp_head_s_buf, "%sh.s")
00454 #define TMP_HEAD_O   dlltmp (&tmp_head_o_buf, "%sh.o")
00455 #define TMP_TAIL_S   dlltmp (&tmp_tail_s_buf, "%st.s")
00456 #define TMP_TAIL_O   dlltmp (&tmp_tail_o_buf, "%st.o")
00457 #define TMP_STUB     dlltmp (&tmp_stub_buf, "%ss")
00458 
00459 /* This bit of assembly does jmp * ....  */
00460 static const unsigned char i386_jtab[] =
00461 {
00462   0xff, 0x25, 0x00, 0x00, 0x00, 0x00, 0x90, 0x90
00463 };
00464 
00465 static const unsigned char arm_jtab[] =
00466 {
00467   0x00, 0xc0, 0x9f, 0xe5,   /* ldr  ip, [pc] */
00468   0x00, 0xf0, 0x9c, 0xe5,   /* ldr  pc, [ip] */
00469   0,    0,    0,    0
00470 };
00471 
00472 static const unsigned char arm_interwork_jtab[] =
00473 {
00474   0x04, 0xc0, 0x9f, 0xe5,   /* ldr  ip, [pc] */
00475   0x00, 0xc0, 0x9c, 0xe5,   /* ldr  ip, [ip] */
00476   0x1c, 0xff, 0x2f, 0xe1,   /* bx   ip       */
00477   0,    0,    0,    0
00478 };
00479 
00480 static const unsigned char thumb_jtab[] =
00481 {
00482   0x40, 0xb4,           /* push {r6}         */
00483   0x02, 0x4e,           /* ldr  r6, [pc, #8] */
00484   0x36, 0x68,           /* ldr  r6, [r6]     */
00485   0xb4, 0x46,           /* mov  ip, r6       */
00486   0x40, 0xbc,           /* pop  {r6}         */
00487   0x60, 0x47,           /* bx   ip           */
00488   0,    0,    0,    0
00489 };
00490 
00491 static const unsigned char mcore_be_jtab[] =
00492 {
00493   0x71, 0x02,            /* lrw r1,2       */
00494   0x81, 0x01,            /* ld.w r1,(r1,0) */
00495   0x00, 0xC1,            /* jmp r1         */
00496   0x12, 0x00,            /* nop            */
00497   0x00, 0x00, 0x00, 0x00 /* <address>      */
00498 };
00499 
00500 static const unsigned char mcore_le_jtab[] =
00501 {
00502   0x02, 0x71,            /* lrw r1,2       */
00503   0x01, 0x81,            /* ld.w r1,(r1,0) */
00504   0xC1, 0x00,            /* jmp r1         */
00505   0x00, 0x12,            /* nop            */
00506   0x00, 0x00, 0x00, 0x00 /* <address>      */
00507 };
00508 
00509 /* This is the glue sequence for PowerPC PE. There is a
00510    tocrel16-tocdefn reloc against the first instruction.
00511    We also need a IMGLUE reloc against the glue function
00512    to restore the toc saved by the third instruction in
00513    the glue.  */
00514 static const unsigned char ppc_jtab[] =
00515 {
00516   0x00, 0x00, 0x62, 0x81, /* lwz r11,0(r2)               */
00517                           /*   Reloc TOCREL16 __imp_xxx  */
00518   0x00, 0x00, 0x8B, 0x81, /* lwz r12,0(r11)              */
00519   0x04, 0x00, 0x41, 0x90, /* stw r2,4(r1)                */
00520   0xA6, 0x03, 0x89, 0x7D, /* mtctr r12                   */
00521   0x04, 0x00, 0x4B, 0x80, /* lwz r2,4(r11)               */
00522   0x20, 0x04, 0x80, 0x4E  /* bctr                        */
00523 };
00524 
00525 #ifdef DLLTOOL_PPC
00526 /* The glue instruction, picks up the toc from the stw in
00527    the above code: "lwz r2,4(r1)".  */
00528 static bfd_vma ppc_glue_insn = 0x80410004;
00529 #endif
00530 
00531 struct mac
00532   {
00533     const char *type;
00534     const char *how_byte;
00535     const char *how_short;
00536     const char *how_long;
00537     const char *how_asciz;
00538     const char *how_comment;
00539     const char *how_jump;
00540     const char *how_global;
00541     const char *how_space;
00542     const char *how_align_short;
00543     const char *how_align_long;
00544     const char *how_default_as_switches;
00545     const char *how_bfd_target;
00546     enum bfd_architecture how_bfd_arch;
00547     const unsigned char *how_jtab;
00548     int how_jtab_size; /* Size of the jtab entry.  */
00549     int how_jtab_roff; /* Offset into it for the ind 32 reloc into idata 5.  */
00550   };
00551 
00552 static const struct mac
00553 mtable[] =
00554 {
00555   {
00556 #define MARM 0
00557     "arm", ".byte", ".short", ".long", ".asciz", "@",
00558     "ldr\tip,[pc]\n\tldr\tpc,[ip]\n\t.long",
00559     ".global", ".space", ".align\t2",".align\t4", "-mapcs-32",
00560     "pe-arm-little", bfd_arch_arm,
00561     arm_jtab, sizeof (arm_jtab), 8
00562   }
00563   ,
00564   {
00565 #define M386 1
00566     "i386", ".byte", ".short", ".long", ".asciz", "#",
00567     "jmp *", ".global", ".space", ".align\t2",".align\t4", "",
00568     "pe-i386",bfd_arch_i386,
00569     i386_jtab, sizeof (i386_jtab), 2
00570   }
00571   ,
00572   {
00573 #define MPPC 2
00574     "ppc", ".byte", ".short", ".long", ".asciz", "#",
00575     "jmp *", ".global", ".space", ".align\t2",".align\t4", "",
00576     "pe-powerpcle",bfd_arch_powerpc,
00577     ppc_jtab, sizeof (ppc_jtab), 0
00578   }
00579   ,
00580   {
00581 #define MTHUMB 3
00582     "thumb", ".byte", ".short", ".long", ".asciz", "@",
00583     "push\t{r6}\n\tldr\tr6, [pc, #8]\n\tldr\tr6, [r6]\n\tmov\tip, r6\n\tpop\t{r6}\n\tbx\tip",
00584     ".global", ".space", ".align\t2",".align\t4", "-mthumb-interwork",
00585     "pe-arm-little", bfd_arch_arm,
00586     thumb_jtab, sizeof (thumb_jtab), 12
00587   }
00588   ,
00589 #define MARM_INTERWORK 4
00590   {
00591     "arm_interwork", ".byte", ".short", ".long", ".asciz", "@",
00592     "ldr\tip,[pc]\n\tldr\tip,[ip]\n\tbx\tip\n\t.long",
00593     ".global", ".space", ".align\t2",".align\t4", "-mthumb-interwork",
00594     "pe-arm-little", bfd_arch_arm,
00595     arm_interwork_jtab, sizeof (arm_interwork_jtab), 12
00596   }
00597   ,
00598   {
00599 #define MMCORE_BE 5
00600     "mcore-be", ".byte", ".short", ".long", ".asciz", "//",
00601     "lrw r1,[1f]\n\tld.w r1,(r1,0)\n\tjmp r1\n\tnop\n1:.long",
00602     ".global", ".space", ".align\t2",".align\t4", "",
00603     "pe-mcore-big", bfd_arch_mcore,
00604     mcore_be_jtab, sizeof (mcore_be_jtab), 8
00605   }
00606   ,
00607   {
00608 #define MMCORE_LE 6
00609     "mcore-le", ".byte", ".short", ".long", ".asciz", "//",
00610     "lrw r1,[1f]\n\tld.w r1,(r1,0)\n\tjmp r1\n\tnop\n1:.long",
00611     ".global", ".space", ".align\t2",".align\t4", "-EL",
00612     "pe-mcore-little", bfd_arch_mcore,
00613     mcore_le_jtab, sizeof (mcore_le_jtab), 8
00614   }
00615   ,
00616   {
00617 #define MMCORE_ELF 7
00618     "mcore-elf-be", ".byte", ".short", ".long", ".asciz", "//",
00619     "lrw r1,[1f]\n\tld.w r1,(r1,0)\n\tjmp r1\n\tnop\n1:.long",
00620     ".global", ".space", ".align\t2",".align\t4", "",
00621     "elf32-mcore-big", bfd_arch_mcore,
00622     mcore_be_jtab, sizeof (mcore_be_jtab), 8
00623   }
00624   ,
00625   {
00626 #define MMCORE_ELF_LE 8
00627     "mcore-elf-le", ".byte", ".short", ".long", ".asciz", "//",
00628     "lrw r1,[1f]\n\tld.w r1,(r1,0)\n\tjmp r1\n\tnop\n1:.long",
00629     ".global", ".space", ".align\t2",".align\t4", "-EL",
00630     "elf32-mcore-little", bfd_arch_mcore,
00631     mcore_le_jtab, sizeof (mcore_le_jtab), 8
00632   }
00633   ,
00634   {
00635 #define MARM_EPOC 9
00636     "arm-epoc", ".byte", ".short", ".long", ".asciz", "@",
00637     "ldr\tip,[pc]\n\tldr\tpc,[ip]\n\t.long",
00638     ".global", ".space", ".align\t2",".align\t4", "",
00639     "epoc-pe-arm-little", bfd_arch_arm,
00640     arm_jtab, sizeof (arm_jtab), 8
00641   }
00642   ,
00643   {
00644 #define MARM_WINCE 10
00645     "arm-wince", ".byte", ".short", ".long", ".asciz", "@",
00646     "ldr\tip,[pc]\n\tldr\tpc,[ip]\n\t.long",
00647     ".global", ".space", ".align\t2",".align\t4", "-mapcs-32",
00648     "pe-arm-wince-little", bfd_arch_arm,
00649     arm_jtab, sizeof (arm_jtab), 8
00650   }
00651   ,
00652   {
00653 #define MX86 11
00654     "i386:x86-64", ".byte", ".short", ".long", ".asciz", "#",
00655     "jmp *", ".global", ".space", ".align\t2",".align\t4", "",
00656     "pe-x86-64",bfd_arch_i386,
00657     i386_jtab, sizeof (i386_jtab), 2
00658   }
00659   ,
00660   { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
00661 };
00662 
00663 typedef struct dlist
00664 {
00665   char *text;
00666   struct dlist *next;
00667 }
00668 dlist_type;
00669 
00670 typedef struct export
00671   {
00672     const char *name;
00673     const char *internal_name;
00674     const char *import_name;
00675     int ordinal;
00676     int constant;
00677     int noname;             /* Don't put name in image file.  */
00678     int private;     /* Don't put reference in import lib.  */
00679     int data;
00680     int hint;
00681     int forward;     /* Number of forward label, 0 means no forward.  */
00682     struct export *next;
00683   }
00684 export_type;
00685 
00686 /* A list of symbols which we should not export.  */
00687 
00688 struct string_list
00689 {
00690   struct string_list *next;
00691   char *string;
00692 };
00693 
00694 static struct string_list *excludes;
00695 
00696 static const char *rvaafter (int);
00697 static const char *rvabefore (int);
00698 static const char *asm_prefix (int, const char *);
00699 static void process_def_file (const char *);
00700 static void new_directive (char *);
00701 static void append_import (const char *, const char *, int);
00702 static void run (const char *, char *);
00703 static void scan_drectve_symbols (bfd *);
00704 static void scan_filtered_symbols (bfd *, void *, long, unsigned int);
00705 static void add_excludes (const char *);
00706 static bfd_boolean match_exclude (const char *);
00707 static void set_default_excludes (void);
00708 static long filter_symbols (bfd *, void *, long, unsigned int);
00709 static void scan_all_symbols (bfd *);
00710 static void scan_open_obj_file (bfd *);
00711 static void scan_obj_file (const char *);
00712 static void dump_def_info (FILE *);
00713 static int sfunc (const void *, const void *);
00714 static void flush_page (FILE *, long *, int, int);
00715 static void gen_def_file (void);
00716 static void generate_idata_ofile (FILE *);
00717 static void assemble_file (const char *, const char *);
00718 static void gen_exp_file (void);
00719 static const char *xlate (const char *);
00720 static char *make_label (const char *, const char *);
00721 static char *make_imp_label (const char *, const char *);
00722 static bfd *make_one_lib_file (export_type *, int);
00723 static bfd *make_head (void);
00724 static bfd *make_tail (void);
00725 static void gen_lib_file (void);
00726 static int pfunc (const void *, const void *);
00727 static int nfunc (const void *, const void *);
00728 static void remove_null_names (export_type **);
00729 static void process_duplicates (export_type **);
00730 static void fill_ordinals (export_type **);
00731 static void mangle_defs (void);
00732 static void usage (FILE *, int);
00733 static void inform (const char *, ...) ATTRIBUTE_PRINTF_1;
00734 static void set_dll_name_from_def (const char *);
00735 
00736 static char *
00737 prefix_encode (char *start, unsigned code)
00738 {
00739   static char alpha[26] = "abcdefghijklmnopqrstuvwxyz";
00740   static char buf[32];
00741   char *p;
00742   strcpy (buf, start);
00743   p = strchr (buf, '\0');
00744   do
00745     *p++ = alpha[code % sizeof (alpha)];
00746   while ((code /= sizeof (alpha)) != 0);
00747   *p = '\0';
00748   return buf;
00749 }
00750 
00751 static char *
00752 dlltmp (char **buf, const char *fmt)
00753 {
00754   if (!*buf)
00755     {
00756       *buf = malloc (strlen (tmp_prefix) + 64);
00757       sprintf (*buf, fmt, tmp_prefix);
00758     }
00759   return *buf;
00760 }
00761 
00762 static void
00763 inform VPARAMS ((const char * message, ...))
00764 {
00765   VA_OPEN (args, message);
00766   VA_FIXEDARG (args, const char *, message);
00767 
00768   if (!verbose)
00769     return;
00770 
00771   report (message, args);
00772 
00773   VA_CLOSE (args);
00774 }
00775 
00776 static const char *
00777 rvaafter (int machine)
00778 {
00779   switch (machine)
00780     {
00781     case MARM:
00782     case M386:
00783     case MX86:
00784     case MPPC:
00785     case MTHUMB:
00786     case MARM_INTERWORK:
00787     case MMCORE_BE:
00788     case MMCORE_LE:
00789     case MMCORE_ELF:
00790     case MMCORE_ELF_LE:
00791     case MARM_EPOC:
00792     case MARM_WINCE:
00793       break;
00794     default:
00795       /* xgettext:c-format */
00796       fatal (_("Internal error: Unknown machine type: %d"), machine);
00797       break;
00798     }
00799   return "";
00800 }
00801 
00802 static const char *
00803 rvabefore (int machine)
00804 {
00805   switch (machine)
00806     {
00807     case MARM:
00808     case M386:
00809     case MX86:
00810     case MPPC:
00811     case MTHUMB:
00812     case MARM_INTERWORK:
00813     case MMCORE_BE:
00814     case MMCORE_LE:
00815     case MMCORE_ELF:
00816     case MMCORE_ELF_LE:
00817     case MARM_EPOC:
00818     case MARM_WINCE:
00819       return ".rva\t";
00820     default:
00821       /* xgettext:c-format */
00822       fatal (_("Internal error: Unknown machine type: %d"), machine);
00823       break;
00824     }
00825   return "";
00826 }
00827 
00828 static const char *
00829 asm_prefix (int machine, const char *name)
00830 {
00831   switch (machine)
00832     {
00833     case MARM:
00834     case MPPC:
00835     case MTHUMB:
00836     case MARM_INTERWORK:
00837     case MMCORE_BE:
00838     case MMCORE_LE:
00839     case MMCORE_ELF:
00840     case MMCORE_ELF_LE:
00841     case MARM_EPOC:
00842     case MARM_WINCE:
00843       break;
00844     case M386:
00845     case MX86:
00846       /* Symbol names starting with ? do not have a leading underscore. */
00847       if (name && *name == '?')
00848         break;
00849       else
00850         return "_";
00851     default:
00852       /* xgettext:c-format */
00853       fatal (_("Internal error: Unknown machine type: %d"), machine);
00854       break;
00855     }
00856   return "";
00857 }
00858 
00859 #define ASM_BYTE            mtable[machine].how_byte
00860 #define ASM_SHORT           mtable[machine].how_short
00861 #define ASM_LONG            mtable[machine].how_long
00862 #define ASM_TEXT            mtable[machine].how_asciz
00863 #define ASM_C               mtable[machine].how_comment
00864 #define ASM_JUMP            mtable[machine].how_jump
00865 #define ASM_GLOBAL          mtable[machine].how_global
00866 #define ASM_SPACE           mtable[machine].how_space
00867 #define ASM_ALIGN_SHORT            mtable[machine].how_align_short
00868 #define ASM_RVA_BEFORE             rvabefore (machine)
00869 #define ASM_RVA_AFTER              rvaafter (machine)
00870 #define ASM_PREFIX(NAME)    asm_prefix (machine, (NAME))
00871 #define ASM_ALIGN_LONG      mtable[machine].how_align_long
00872 #define HOW_BFD_READ_TARGET 0  /* Always default.  */
00873 #define HOW_BFD_WRITE_TARGET       mtable[machine].how_bfd_target
00874 #define HOW_BFD_ARCH        mtable[machine].how_bfd_arch
00875 #define HOW_JTAB            mtable[machine].how_jtab
00876 #define HOW_JTAB_SIZE              mtable[machine].how_jtab_size
00877 #define HOW_JTAB_ROFF              mtable[machine].how_jtab_roff
00878 #define ASM_SWITCHES        mtable[machine].how_default_as_switches
00879 
00880 static char **oav;
00881 
00882 static void
00883 process_def_file (const char *name)
00884 {
00885   FILE *f = fopen (name, FOPEN_RT);
00886 
00887   if (!f)
00888     /* xgettext:c-format */
00889     fatal (_("Can't open def file: %s"), name);
00890 
00891   yyin = f;
00892 
00893   /* xgettext:c-format */
00894   inform (_("Processing def file: %s"), name);
00895 
00896   yyparse ();
00897 
00898   inform (_("Processed def file"));
00899 }
00900 
00901 /**********************************************************************/
00902 
00903 /* Communications with the parser.  */
00904 
00905 static int d_nfuncs;        /* Number of functions exported.  */
00906 static int d_named_nfuncs;  /* Number of named functions exported.  */
00907 static int d_low_ord;              /* Lowest ordinal index.  */
00908 static int d_high_ord;             /* Highest ordinal index.  */
00909 static export_type *d_exports;     /* List of exported functions.  */
00910 static export_type **d_exports_lexically;  /* Vector of exported functions in alpha order.  */
00911 static dlist_type *d_list;  /* Descriptions.  */
00912 static dlist_type *a_list;  /* Stuff to go in directives.  */
00913 static int d_nforwards = 0; /* Number of forwarded exports.  */
00914 
00915 static int d_is_dll;
00916 static int d_is_exe;
00917 
00918 int
00919 yyerror (const char * err ATTRIBUTE_UNUSED)
00920 {
00921   /* xgettext:c-format */
00922   non_fatal (_("Syntax error in def file %s:%d"), def_file, linenumber);
00923 
00924   return 0;
00925 }
00926 
00927 void
00928 def_exports (const char *name, const char *internal_name, int ordinal,
00929             int noname, int constant, int data, int private)
00930 {
00931   struct export *p = (struct export *) xmalloc (sizeof (*p));
00932 
00933   p->name = name;
00934   p->internal_name = internal_name ? internal_name : name;
00935   p->import_name = name;
00936   p->ordinal = ordinal;
00937   p->constant = constant;
00938   p->noname = noname;
00939   p->private = private;
00940   p->data = data;
00941   p->next = d_exports;
00942   d_exports = p;
00943   d_nfuncs++;
00944 
00945   if ((internal_name != NULL)
00946       && (strchr (internal_name, '.') != NULL))
00947     p->forward = ++d_nforwards;
00948   else
00949     p->forward = 0; /* no forward */
00950 }
00951 
00952 static void
00953 set_dll_name_from_def (const char * name)
00954 {
00955   const char* image_basename = lbasename (name);
00956   if (image_basename != name)
00957     non_fatal (_("%s: Path components stripped from image name, '%s'."),
00958              def_file, name);
00959   dll_name = xstrdup (image_basename);
00960 }
00961 
00962 void
00963 def_name (const char *name, int base)
00964 {
00965   /* xgettext:c-format */
00966   inform (_("NAME: %s base: %x"), name, base);
00967 
00968   if (d_is_dll)
00969     non_fatal (_("Can't have LIBRARY and NAME"));
00970 
00971   /* If --dllname not provided, use the one in the DEF file.
00972      FIXME: Is this appropriate for executables?  */
00973   if (! dll_name)
00974     set_dll_name_from_def (name);
00975   d_is_exe = 1;
00976 }
00977 
00978 void
00979 def_library (const char *name, int base)
00980 {
00981   /* xgettext:c-format */
00982   inform (_("LIBRARY: %s base: %x"), name, base);
00983 
00984   if (d_is_exe)
00985     non_fatal (_("Can't have LIBRARY and NAME"));
00986 
00987   /* If --dllname not provided, use the one in the DEF file.  */
00988   if (! dll_name)
00989     set_dll_name_from_def (name);
00990   d_is_dll = 1;
00991 }
00992 
00993 void
00994 def_description (const char *desc)
00995 {
00996   dlist_type *d = (dlist_type *) xmalloc (sizeof (dlist_type));
00997   d->text = xstrdup (desc);
00998   d->next = d_list;
00999   d_list = d;
01000 }
01001 
01002 static void
01003 new_directive (char *dir)
01004 {
01005   dlist_type *d = (dlist_type *) xmalloc (sizeof (dlist_type));
01006   d->text = xstrdup (dir);
01007   d->next = a_list;
01008   a_list = d;
01009 }
01010 
01011 void
01012 def_heapsize (int reserve, int commit)
01013 {
01014   char b[200];
01015   if (commit > 0)
01016     sprintf (b, "-heap 0x%x,0x%x ", reserve, commit);
01017   else
01018     sprintf (b, "-heap 0x%x ", reserve);
01019   new_directive (xstrdup (b));
01020 }
01021 
01022 void
01023 def_stacksize (int reserve, int commit)
01024 {
01025   char b[200];
01026   if (commit > 0)
01027     sprintf (b, "-stack 0x%x,0x%x ", reserve, commit);
01028   else
01029     sprintf (b, "-stack 0x%x ", reserve);
01030   new_directive (xstrdup (b));
01031 }
01032 
01033 /* append_import simply adds the given import definition to the global
01034    import_list.  It is used by def_import.  */
01035 
01036 static void
01037 append_import (const char *symbol_name, const char *dll_name, int func_ordinal)
01038 {
01039   iheadtype **pq;
01040   iheadtype *q;
01041 
01042   for (pq = &import_list; *pq != NULL; pq = &(*pq)->next)
01043     {
01044       if (strcmp ((*pq)->dllname, dll_name) == 0)
01045        {
01046          q = *pq;
01047          q->functail->next = xmalloc (sizeof (ifunctype));
01048          q->functail = q->functail->next;
01049          q->functail->ord  = func_ordinal;
01050          q->functail->name = xstrdup (symbol_name);
01051          q->functail->next = NULL;
01052          q->nfuncs++;
01053          return;
01054        }
01055     }
01056 
01057   q = xmalloc (sizeof (iheadtype));
01058   q->dllname = xstrdup (dll_name);
01059   q->nfuncs = 1;
01060   q->funchead = xmalloc (sizeof (ifunctype));
01061   q->functail = q->funchead;
01062   q->next = NULL;
01063   q->functail->name = xstrdup (symbol_name);
01064   q->functail->ord  = func_ordinal;
01065   q->functail->next = NULL;
01066 
01067   *pq = q;
01068 }
01069 
01070 /* def_import is called from within defparse.y when an IMPORT
01071    declaration is encountered.  Depending on the form of the
01072    declaration, the module name may or may not need ".dll" to be
01073    appended to it, the name of the function may be stored in internal
01074    or entry, and there may or may not be an ordinal value associated
01075    with it.  */
01076 
01077 /* A note regarding the parse modes:
01078    In defparse.y we have to accept import declarations which follow
01079    any one of the following forms:
01080      <func_name_in_app> = <dll_name>.<func_name_in_dll>
01081      <func_name_in_app> = <dll_name>.<number>
01082      <dll_name>.<func_name_in_dll>
01083      <dll_name>.<number>
01084    Furthermore, the dll's name may or may not end with ".dll", which
01085    complicates the parsing a little.  Normally the dll's name is
01086    passed to def_import() in the "module" parameter, but when it ends
01087    with ".dll" it gets passed in "module" sans ".dll" and that needs
01088    to be reappended.
01089 
01090   def_import gets five parameters:
01091   APP_NAME - the name of the function in the application, if
01092              present, or NULL if not present.
01093   MODULE   - the name of the dll, possibly sans extension (ie, '.dll').
01094   DLLEXT   - the extension of the dll, if present, NULL if not present.
01095   ENTRY    - the name of the function in the dll, if present, or NULL.
01096   ORD_VAL  - the numerical tag of the function in the dll, if present,
01097              or NULL.  Exactly one of <entry> or <ord_val> must be
01098              present (i.e., not NULL).  */
01099 
01100 void
01101 def_import (const char *app_name, const char *module, const char *dllext,
01102            const char *entry, int ord_val)
01103 {
01104   const char *application_name;
01105   char *buf;
01106 
01107   if (entry != NULL)
01108     application_name = entry;
01109   else
01110     {
01111       if (app_name != NULL)
01112        application_name = app_name;
01113       else
01114        application_name = "";
01115     }
01116 
01117   if (dllext != NULL)
01118     {
01119       buf = (char *) alloca (strlen (module) + strlen (dllext) + 2);
01120       sprintf (buf, "%s.%s", module, dllext);
01121       module = buf;
01122     }
01123 
01124   append_import (application_name, module, ord_val);
01125 }
01126 
01127 void
01128 def_version (int major, int minor)
01129 {
01130   printf ("VERSION %d.%d\n", major, minor);
01131 }
01132 
01133 void
01134 def_section (const char *name, int attr)
01135 {
01136   char buf[200];
01137   char atts[5];
01138   char *d = atts;
01139   if (attr & 1)
01140     *d++ = 'R';
01141 
01142   if (attr & 2)
01143     *d++ = 'W';
01144   if (attr & 4)
01145     *d++ = 'X';
01146   if (attr & 8)
01147     *d++ = 'S';
01148   *d++ = 0;
01149   sprintf (buf, "-attr %s %s", name, atts);
01150   new_directive (xstrdup (buf));
01151 }
01152 
01153 void
01154 def_code (int attr)
01155 {
01156 
01157   def_section ("CODE", attr);
01158 }
01159 
01160 void
01161 def_data (int attr)
01162 {
01163   def_section ("DATA", attr);
01164 }
01165 
01166 /**********************************************************************/
01167 
01168 static void
01169 run (const char *what, char *args)
01170 {
01171   char *s;
01172   int pid, wait_status;
01173   int i;
01174   const char **argv;
01175   char *errmsg_fmt, *errmsg_arg;
01176   char *temp_base = choose_temp_base ();
01177 
01178   inform ("run: %s %s", what, args);
01179 
01180   /* Count the args */
01181   i = 0;
01182   for (s = args; *s; s++)
01183     if (*s == ' ')
01184       i++;
01185   i++;
01186   argv = alloca (sizeof (char *) * (i + 3));
01187   i = 0;
01188   argv[i++] = what;
01189   s = args;
01190   while (1)
01191     {
01192       while (*s == ' ')
01193        ++s;
01194       argv[i++] = s;
01195       while (*s != ' ' && *s != 0)
01196        s++;
01197       if (*s == 0)
01198        break;
01199       *s++ = 0;
01200     }
01201   argv[i++] = NULL;
01202 
01203   pid = pexecute (argv[0], (char * const *) argv, program_name, temp_base,
01204                 &errmsg_fmt, &errmsg_arg, PEXECUTE_ONE | PEXECUTE_SEARCH);
01205 
01206   if (pid == -1)
01207     {
01208       inform (strerror (errno));
01209 
01210       fatal (errmsg_fmt, errmsg_arg);
01211     }
01212 
01213   pid = pwait (pid, & wait_status, 0);
01214 
01215   if (pid == -1)
01216     {
01217       /* xgettext:c-format */
01218       fatal (_("wait: %s"), strerror (errno));
01219     }
01220   else if (WIFSIGNALED (wait_status))
01221     {
01222       /* xgettext:c-format */
01223       fatal (_("subprocess got fatal signal %d"), WTERMSIG (wait_status));
01224     }
01225   else if (WIFEXITED (wait_status))
01226     {
01227       if (WEXITSTATUS (wait_status) != 0)
01228        /* xgettext:c-format */
01229        non_fatal (_("%s exited with status %d"),
01230                  what, WEXITSTATUS (wait_status));
01231     }
01232   else
01233     abort ();
01234 }
01235 
01236 /* Look for a list of symbols to export in the .drectve section of
01237    ABFD.  Pass each one to def_exports.  */
01238 
01239 static void
01240 scan_drectve_symbols (bfd *abfd)
01241 {
01242   asection * s;
01243   int        size;
01244   char *     buf;
01245   char *     p;
01246   char *     e;
01247 
01248   /* Look for .drectve's */
01249   s = bfd_get_section_by_name (abfd, DRECTVE_SECTION_NAME);
01250 
01251   if (s == NULL)
01252     return;
01253 
01254   size = bfd_get_section_size (s);
01255   buf  = xmalloc (size);
01256 
01257   bfd_get_section_contents (abfd, s, buf, 0, size);
01258 
01259   /* xgettext:c-format */
01260   inform (_("Sucking in info from %s section in %s"),
01261          DRECTVE_SECTION_NAME, bfd_get_filename (abfd));
01262 
01263   /* Search for -export: strings. The exported symbols can optionally
01264      have type tags (eg., -export:foo,data), so handle those as well.
01265      Currently only data tag is supported.  */
01266   p = buf;
01267   e = buf + size;
01268   while (p < e)
01269     {
01270       if (p[0] == '-'
01271          && CONST_STRNEQ (p, "-export:"))
01272        {
01273          char * name;
01274          char * c;
01275          flagword flags = BSF_FUNCTION;
01276 
01277          p += 8;
01278          name = p;
01279          while (p < e && *p != ',' && *p != ' ' && *p != '-')
01280            p++;
01281          c = xmalloc (p - name + 1);
01282          memcpy (c, name, p - name);
01283          c[p - name] = 0;
01284          if (p < e && *p == ',')       /* found type tag.  */
01285            {
01286              char *tag_start = ++p;
01287              while (p < e && *p != ' ' && *p != '-')
01288               p++;
01289              if (CONST_STRNEQ (tag_start, "data"))
01290               flags &= ~BSF_FUNCTION;
01291            }
01292 
01293          /* FIXME: The 5th arg is for the `constant' field.
01294             What should it be?  Not that it matters since it's not
01295             currently useful.  */
01296          def_exports (c, 0, -1, 0, 0, ! (flags & BSF_FUNCTION), 0);
01297 
01298          if (add_stdcall_alias && strchr (c, '@'))
01299            {
01300              int lead_at = (*c == '@') ;
01301              char *exported_name = xstrdup (c + lead_at);
01302              char *atsym = strchr (exported_name, '@');
01303              *atsym = '\0';
01304              /* Note: stdcall alias symbols can never be data.  */
01305              def_exports (exported_name, xstrdup (c), -1, 0, 0, 0, 0);
01306            }
01307        }
01308       else
01309        p++;
01310     }
01311   free (buf);
01312 }
01313 
01314 /* Look through the symbols in MINISYMS, and add each one to list of
01315    symbols to export.  */
01316 
01317 static void
01318 scan_filtered_symbols (bfd *abfd, void *minisyms, long symcount,
01319                      unsigned int size)
01320 {
01321   asymbol *store;
01322   bfd_byte *from, *fromend;
01323 
01324   store = bfd_make_empty_symbol (abfd);
01325   if (store == NULL)
01326     bfd_fatal (bfd_get_filename (abfd));
01327 
01328   from = (bfd_byte *) minisyms;
01329   fromend = from + symcount * size;
01330   for (; from < fromend; from += size)
01331     {
01332       asymbol *sym;
01333       const char *symbol_name;
01334 
01335       sym = bfd_minisymbol_to_symbol (abfd, FALSE, from, store);
01336       if (sym == NULL)
01337        bfd_fatal (bfd_get_filename (abfd));
01338 
01339       symbol_name = bfd_asymbol_name (sym);
01340       if (bfd_get_symbol_leading_char (abfd) == symbol_name[0])
01341        ++symbol_name;
01342 
01343       def_exports (xstrdup (symbol_name) , 0, -1, 0, 0,
01344                  ! (sym->flags & BSF_FUNCTION), 0);
01345 
01346       if (add_stdcall_alias && strchr (symbol_name, '@'))
01347         {
01348          int lead_at = (*symbol_name == '@');
01349          char *exported_name = xstrdup (symbol_name + lead_at);
01350          char *atsym = strchr (exported_name, '@');
01351          *atsym = '\0';
01352          /* Note: stdcall alias symbols can never be data.  */
01353          def_exports (exported_name, xstrdup (symbol_name), -1, 0, 0, 0, 0);
01354        }
01355     }
01356 }
01357 
01358 /* Add a list of symbols to exclude.  */
01359 
01360 static void
01361 add_excludes (const char *new_excludes)
01362 {
01363   char *local_copy;
01364   char *exclude_string;
01365 
01366   local_copy = xstrdup (new_excludes);
01367 
01368   exclude_string = strtok (local_copy, ",:");
01369   for (; exclude_string; exclude_string = strtok (NULL, ",:"))
01370     {
01371       struct string_list *new_exclude;
01372 
01373       new_exclude = ((struct string_list *)
01374                    xmalloc (sizeof (struct string_list)));
01375       new_exclude->string = (char *) xmalloc (strlen (exclude_string) + 2);
01376       /* Don't add a leading underscore for fastcall symbols.  */
01377       if (*exclude_string == '@')
01378        sprintf (new_exclude->string, "%s", exclude_string);
01379       else
01380        sprintf (new_exclude->string, "_%s", exclude_string);
01381       new_exclude->next = excludes;
01382       excludes = new_exclude;
01383 
01384       /* xgettext:c-format */
01385       inform (_("Excluding symbol: %s"), exclude_string);
01386     }
01387 
01388   free (local_copy);
01389 }
01390 
01391 /* See if STRING is on the list of symbols to exclude.  */
01392 
01393 static bfd_boolean
01394 match_exclude (const char *string)
01395 {
01396   struct string_list *excl_item;
01397 
01398   for (excl_item = excludes; excl_item; excl_item = excl_item->next)
01399     if (strcmp (string, excl_item->string) == 0)
01400       return TRUE;
01401   return FALSE;
01402 }
01403 
01404 /* Add the default list of symbols to exclude.  */
01405 
01406 static void
01407 set_default_excludes (void)
01408 {
01409   add_excludes (default_excludes);
01410 }
01411 
01412 /* Choose which symbols to export.  */
01413 
01414 static long
01415 filter_symbols (bfd *abfd, void *minisyms, long symcount, unsigned int size)
01416 {
01417   bfd_byte *from, *fromend, *to;
01418   asymbol *store;
01419 
01420   store = bfd_make_empty_symbol (abfd);
01421   if (store == NULL)
01422     bfd_fatal (bfd_get_filename (abfd));
01423 
01424   from = (bfd_byte *) minisyms;
01425   fromend = from + symcount * size;
01426   to = (bfd_byte *) minisyms;
01427 
01428   for (; from < fromend; from += size)
01429     {
01430       int keep = 0;
01431       asymbol *sym;
01432 
01433       sym = bfd_minisymbol_to_symbol (abfd, FALSE, (const void *) from, store);
01434       if (sym == NULL)
01435        bfd_fatal (bfd_get_filename (abfd));
01436 
01437       /* Check for external and defined only symbols.  */
01438       keep = (((sym->flags & BSF_GLOBAL) != 0
01439               || (sym->flags & BSF_WEAK) != 0
01440               || bfd_is_com_section (sym->section))
01441              && ! bfd_is_und_section (sym->section));
01442 
01443       keep = keep && ! match_exclude (sym->name);
01444 
01445       if (keep)
01446        {
01447          memcpy (to, from, size);
01448          to += size;
01449        }
01450     }
01451 
01452   return (to - (bfd_byte *) minisyms) / size;
01453 }
01454 
01455 /* Export all symbols in ABFD, except for ones we were told not to
01456    export.  */
01457 
01458 static void
01459 scan_all_symbols (bfd *abfd)
01460 {
01461   long symcount;
01462   void *minisyms;
01463   unsigned int size;
01464 
01465   /* Ignore bfds with an import descriptor table.  We assume that any
01466      such BFD contains symbols which are exported from another DLL,
01467      and we don't want to reexport them from here.  */
01468   if (bfd_get_section_by_name (abfd, ".idata$4"))
01469     return;
01470 
01471   if (! (bfd_get_file_flags (abfd) & HAS_SYMS))
01472     {
01473       /* xgettext:c-format */
01474       non_fatal (_("%s: no symbols"), bfd_get_filename (abfd));
01475       return;
01476     }
01477 
01478   symcount = bfd_read_minisymbols (abfd, FALSE, &minisyms, &size);
01479   if (symcount < 0)
01480     bfd_fatal (bfd_get_filename (abfd));
01481 
01482   if (symcount == 0)
01483     {
01484       /* xgettext:c-format */
01485       non_fatal (_("%s: no symbols"), bfd_get_filename (abfd));
01486       return;
01487     }
01488 
01489   /* Discard the symbols we don't want to export.  It's OK to do this
01490      in place; we'll free the storage anyway.  */
01491 
01492   symcount = filter_symbols (abfd, minisyms, symcount, size);
01493   scan_filtered_symbols (abfd, minisyms, symcount, size);
01494 
01495   free (minisyms);
01496 }
01497 
01498 /* Look at the object file to decide which symbols to export.  */
01499 
01500 static void
01501 scan_open_obj_file (bfd *abfd)
01502 {
01503   if (export_all_symbols)
01504     scan_all_symbols (abfd);
01505   else
01506     scan_drectve_symbols (abfd);
01507 
01508   /* FIXME: we ought to read in and block out the base relocations.  */
01509 
01510   /* xgettext:c-format */
01511   inform (_("Done reading %s"), bfd_get_filename (abfd));
01512 }
01513 
01514 static void
01515 scan_obj_file (const char *filename)
01516 {
01517   bfd * f = bfd_openr (filename, 0);
01518 
01519   if (!f)
01520     /* xgettext:c-format */
01521     fatal (_("Unable to open object file: %s"), filename);
01522 
01523   /* xgettext:c-format */
01524   inform (_("Scanning object file %s"), filename);
01525 
01526   if (bfd_check_format (f, bfd_archive))
01527     {
01528       bfd *arfile = bfd_openr_next_archived_file (f, 0);
01529       while (arfile)
01530        {
01531          if (bfd_check_format (arfile, bfd_object))
01532            scan_open_obj_file (arfile);
01533          bfd_close (arfile);
01534          arfile = bfd_openr_next_archived_file (f, arfile);
01535        }
01536 
01537 #ifdef DLLTOOL_MCORE_ELF
01538       if (mcore_elf_out_file)
01539        inform (_("Cannot produce mcore-elf dll from archive file: %s"), filename);
01540 #endif
01541     }
01542   else if (bfd_check_format (f, bfd_object))
01543     {
01544       scan_open_obj_file (f);
01545 
01546 #ifdef DLLTOOL_MCORE_ELF
01547       if (mcore_elf_out_file)
01548        mcore_elf_cache_filename ((char *) filename);
01549 #endif
01550     }
01551 
01552   bfd_close (f);
01553 }
01554 
01555 /**********************************************************************/
01556 
01557 static void
01558 dump_def_info (FILE *f)
01559 {
01560   int i;
01561   export_type *exp;
01562   fprintf (f, "%s ", ASM_C);
01563   for (i = 0; oav[i]; i++)
01564     fprintf (f, "%s ", oav[i]);
01565   fprintf (f, "\n");
01566   for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
01567     {
01568       fprintf (f, "%s  %d = %s %s @ %d %s%s%s%s\n",
01569               ASM_C,
01570               i,
01571               exp->name,
01572               exp->internal_name,
01573               exp->ordinal,
01574               exp->noname ? "NONAME " : "",
01575               exp->private ? "PRIVATE " : "",
01576               exp->constant ? "CONSTANT" : "",
01577               exp->data ? "DATA" : "");
01578     }
01579 }
01580 
01581 /* Generate the .exp file.  */
01582 
01583 static int
01584 sfunc (const void *a, const void *b)
01585 {
01586   return *(const long *) a - *(const long *) b;
01587 }
01588 
01589 static void
01590 flush_page (FILE *f, long *need, int page_addr, int on_page)
01591 {
01592   int i;
01593 
01594   /* Flush this page.  */
01595   fprintf (f, "\t%s\t0x%08x\t%s Starting RVA for chunk\n",
01596           ASM_LONG,
01597           page_addr,
01598           ASM_C);
01599   fprintf (f, "\t%s\t0x%x\t%s Size of block\n",
01600           ASM_LONG,
01601           (on_page * 2) + (on_page & 1) * 2 + 8,
01602           ASM_C);
01603 
01604   for (i = 0; i < on_page; i++)
01605     {
01606       long needed = need[i];
01607 
01608       if (needed)
01609        needed = ((needed - page_addr) | 0x3000) & 0xffff;
01610 
01611       fprintf (f, "\t%s\t0x%lx\n", ASM_SHORT, needed);
01612     }
01613 
01614   /* And padding */
01615   if (on_page & 1)
01616     fprintf (f, "\t%s\t0x%x\n", ASM_SHORT, 0 | 0x0000);
01617 }
01618 
01619 static void
01620 gen_def_file (void)
01621 {
01622   int i;
01623   export_type *exp;
01624 
01625   inform (_("Adding exports to output file"));
01626 
01627   fprintf (output_def, ";");
01628   for (i = 0; oav[i]; i++)
01629     fprintf (output_def, " %s", oav[i]);
01630 
01631   fprintf (output_def, "\nEXPORTS\n");
01632 
01633   for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
01634     {
01635       char *quote = strchr (exp->name, '.') ? "\"" : "";
01636       char *res = cplus_demangle (exp->internal_name, DMGL_ANSI | DMGL_PARAMS);
01637 
01638       if (res)
01639        {
01640          fprintf (output_def,";\t%s\n", res);
01641          free (res);
01642        }
01643 
01644       if (strcmp (exp->name, exp->internal_name) == 0)
01645        {
01646          fprintf (output_def, "\t%s%s%s @ %d%s%s%s\n",
01647                  quote,
01648                  exp->name,
01649                  quote,
01650                  exp->ordinal,
01651                  exp->noname ? " NONAME" : "",
01652                  exp->private ? "PRIVATE " : "",
01653                  exp->data ? " DATA" : "");
01654        }
01655       else
01656        {
01657          char * quote1 = strchr (exp->internal_name, '.') ? "\"" : "";
01658          /* char *alias =  */
01659          fprintf (output_def, "\t%s%s%s = %s%s%s @ %d%s%s%s\n",
01660                  quote,
01661                  exp->name,
01662                  quote,
01663                  quote1,
01664                  exp->internal_name,
01665                  quote1,
01666                  exp->ordinal,
01667                  exp->noname ? " NONAME" : "",
01668                  exp->private ? "PRIVATE " : "",
01669                  exp->data ? " DATA" : "");
01670        }
01671     }
01672 
01673   inform (_("Added exports to output file"));
01674 }
01675 
01676 /* generate_idata_ofile generates the portable assembly source code
01677    for the idata sections.  It appends the source code to the end of
01678    the file.  */
01679 
01680 static void
01681 generate_idata_ofile (FILE *filvar)
01682 {
01683   iheadtype *headptr;
01684   ifunctype *funcptr;
01685   int        headindex;
01686   int        funcindex;
01687   int       nheads;
01688 
01689   if (import_list == NULL)
01690     return;
01691 
01692   fprintf (filvar, "%s Import data sections\n", ASM_C);
01693   fprintf (filvar, "\n\t.section\t.idata$2\n");
01694   fprintf (filvar, "\t%s\tdoi_idata\n", ASM_GLOBAL);
01695   fprintf (filvar, "doi_idata:\n");
01696 
01697   nheads = 0;
01698   for (headptr = import_list; headptr != NULL; headptr = headptr->next)
01699     {
01700       fprintf (filvar, "\t%slistone%d%s\t%s %s\n",
01701               ASM_RVA_BEFORE, nheads, ASM_RVA_AFTER,
01702               ASM_C, headptr->dllname);
01703       fprintf (filvar, "\t%s\t0\n", ASM_LONG);
01704       fprintf (filvar, "\t%s\t0\n", ASM_LONG);
01705       fprintf (filvar, "\t%sdllname%d%s\n",
01706               ASM_RVA_BEFORE, nheads, ASM_RVA_AFTER);
01707       fprintf (filvar, "\t%slisttwo%d%s\n\n",
01708               ASM_RVA_BEFORE, nheads, ASM_RVA_AFTER);
01709       nheads++;
01710     }
01711 
01712   fprintf (filvar, "\t%s\t0\n", ASM_LONG); /* NULL record at */
01713   fprintf (filvar, "\t%s\t0\n", ASM_LONG); /* end of idata$2 */
01714   fprintf (filvar, "\t%s\t0\n", ASM_LONG); /* section        */
01715   fprintf (filvar, "\t%s\t0\n", ASM_LONG);
01716   fprintf (filvar, "\t%s\t0\n", ASM_LONG);
01717 
01718   fprintf (filvar, "\n\t.section\t.idata$4\n");
01719   headindex = 0;
01720   for (headptr = import_list; headptr != NULL; headptr = headptr->next)
01721     {
01722       fprintf (filvar, "listone%d:\n", headindex);
01723       for (funcindex = 0; funcindex < headptr->nfuncs; funcindex++)
01724 #ifdef DLLTOOL_MX86_64
01725        fprintf (filvar, "\t%sfuncptr%d_%d%s\n%s\t0\n",
01726                ASM_RVA_BEFORE, headindex, funcindex, ASM_RVA_AFTER,ASM_LONG);
01727 #else
01728        fprintf (filvar, "\t%sfuncptr%d_%d%s\n",
01729                ASM_RVA_BEFORE, headindex, funcindex, ASM_RVA_AFTER);
01730 #endif
01731 #ifdef DLLTOOL_MX86_64
01732       fprintf (filvar, "\t%s\t0\n\t%s\t0\n", ASM_LONG, ASM_LONG); /* NULL terminating list.  */
01733 #else
01734       fprintf (filvar, "\t%s\t0\n", ASM_LONG); /* NULL terminating list.  */
01735 #endif
01736       headindex++;
01737     }
01738 
01739   fprintf (filvar, "\n\t.section\t.idata$5\n");
01740   headindex = 0;
01741   for (headptr = import_list; headptr != NULL; headptr = headptr->next)
01742     {
01743       fprintf (filvar, "listtwo%d:\n", headindex);
01744       for (funcindex = 0; funcindex < headptr->nfuncs; funcindex++)
01745 #ifdef DLLTOOL_MX86_64
01746        fprintf (filvar, "\t%sfuncptr%d_%d%s\n%s\t0\n",
01747                ASM_RVA_BEFORE, headindex, funcindex, ASM_RVA_AFTER,ASM_LONG);
01748 #else
01749        fprintf (filvar, "\t%sfuncptr%d_%d%s\n",
01750                ASM_RVA_BEFORE, headindex, funcindex, ASM_RVA_AFTER);
01751 #endif
01752 #ifdef DLLTOOL_MX86_64
01753       fprintf (filvar, "\t%s\t0\n\t%s\t0\n", ASM_LONG, ASM_LONG); /* NULL terminating list.  */
01754 #else
01755       fprintf (filvar, "\t%s\t0\n", ASM_LONG); /* NULL terminating list.  */
01756 #endif
01757       headindex++;
01758     }
01759 
01760   fprintf (filvar, "\n\t.section\t.idata$6\n");
01761   headindex = 0;
01762   for (headptr = import_list; headptr != NULL; headptr = headptr->next)
01763     {
01764       funcindex = 0;
01765       for (funcptr = headptr->funchead; funcptr != NULL;
01766           funcptr = funcptr->next)
01767        {
01768          fprintf (filvar,"funcptr%d_%d:\n", headindex, funcindex);
01769          fprintf (filvar,"\t%s\t%d\n", ASM_SHORT,
01770                  ((funcptr->ord) & 0xFFFF));
01771          fprintf (filvar,"\t%s\t\"%s\"\n", ASM_TEXT, funcptr->name);
01772          fprintf (filvar,"\t%s\t0\n", ASM_BYTE);
01773          funcindex++;
01774        }
01775       headindex++;
01776     }
01777 
01778   fprintf (filvar, "\n\t.section\t.idata$7\n");
01779   headindex = 0;
01780   for (headptr = import_list; headptr != NULL; headptr = headptr->next)
01781     {
01782       fprintf (filvar,"dllname%d:\n", headindex);
01783       fprintf (filvar,"\t%s\t\"%s\"\n", ASM_TEXT, headptr->dllname);
01784       fprintf (filvar,"\t%s\t0\n", ASM_BYTE);
01785       headindex++;
01786     }
01787 }
01788 
01789 /* Assemble the specified file.  */
01790 static void
01791 assemble_file (const char * source, const char * dest)
01792 {
01793   char * cmd;
01794 
01795   cmd = (char *) alloca (strlen (ASM_SWITCHES) + strlen (as_flags)
01796                       + strlen (source) + strlen (dest) + 50);
01797 
01798   sprintf (cmd, "%s %s -o %s %s", ASM_SWITCHES, as_flags, dest, source);
01799 
01800   run (as_name, cmd);
01801 }
01802 
01803 static void
01804 gen_exp_file (void)
01805 {
01806   FILE *f;
01807   int i;
01808   export_type *exp;
01809   dlist_type *dl;
01810 
01811   /* xgettext:c-format */
01812   inform (_("Generating export file: %s"), exp_name);
01813 
01814   f = fopen (TMP_ASM, FOPEN_WT);
01815   if (!f)
01816     /* xgettext:c-format */
01817     fatal (_("Unable to open temporary assembler file: %s"), TMP_ASM);
01818 
01819   /* xgettext:c-format */
01820   inform (_("Opened temporary file: %s"), TMP_ASM);
01821 
01822   dump_def_info (f);
01823 
01824   if (d_exports)
01825     {
01826       fprintf (f, "\t.section      .edata\n\n");
01827       fprintf (f, "\t%s     0      %s Allways 0\n", ASM_LONG, ASM_C);
01828       fprintf (f, "\t%s     0x%lx  %s Time and date\n", ASM_LONG, (long) time(0),
01829               ASM_C);
01830       fprintf (f, "\t%s     0      %s Major and Minor version\n", ASM_LONG, ASM_C);
01831       fprintf (f, "\t%sname%s      %s Ptr to name of dll\n", ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C);
01832       fprintf (f, "\t%s     %d     %s Starting ordinal of exports\n", ASM_LONG, d_low_ord, ASM_C);
01833 
01834 
01835       fprintf (f, "\t%s     %d     %s Number of functions\n", ASM_LONG, d_high_ord - d_low_ord + 1, ASM_C);
01836       fprintf(f,"\t%s named funcs %d, low ord %d, high ord %d\n",
01837              ASM_C,
01838              d_named_nfuncs, d_low_ord, d_high_ord);
01839       fprintf (f, "\t%s     %d     %s Number of names\n", ASM_LONG,
01840               show_allnames ? d_high_ord - d_low_ord + 1 : d_named_nfuncs, ASM_C);
01841       fprintf (f, "\t%safuncs%s  %s Address of functions\n", ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C);
01842 
01843       fprintf (f, "\t%sanames%s    %s Address of Name Pointer Table\n",
01844               ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C);
01845 
01846       fprintf (f, "\t%sanords%s    %s Address of ordinals\n", ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C);
01847 
01848       fprintf (f, "name:    %s     \"%s\"\n", ASM_TEXT, dll_name);
01849 
01850 
01851       fprintf(f,"%s Export address Table\n", ASM_C);
01852       fprintf(f,"\t%s\n", ASM_ALIGN_LONG);
01853       fprintf (f, "afuncs:\n");
01854       i = d_low_ord;
01855 
01856       for (exp = d_exports; exp; exp = exp->next)
01857        {
01858          if (exp->ordinal != i)
01859            {
01860              while (i < exp->ordinal)
01861               {
01862                 fprintf(f,"\t%s\t0\n", ASM_LONG);
01863                 i++;
01864               }
01865            }
01866 
01867          if (exp->forward == 0)
01868            {
01869              if (exp->internal_name[0] == '@')
01870               fprintf (f, "\t%s%s%s\t%s %d\n", ASM_RVA_BEFORE,
01871                       exp->internal_name, ASM_RVA_AFTER, ASM_C, exp->ordinal);
01872              else
01873               fprintf (f, "\t%s%s%s%s\t%s %d\n", ASM_RVA_BEFORE,
01874                       ASM_PREFIX (exp->internal_name),
01875                       exp->internal_name, ASM_RVA_AFTER, ASM_C, exp->ordinal);
01876            }
01877          else
01878            fprintf (f, "\t%sf%d%s\t%s %d\n", ASM_RVA_BEFORE,
01879                    exp->forward, ASM_RVA_AFTER, ASM_C, exp->ordinal);
01880          i++;
01881        }
01882 
01883       fprintf (f,"%s Export Name Pointer Table\n", ASM_C);
01884       fprintf (f, "anames:\n");
01885 
01886       for (i = 0; (exp = d_exports_lexically[i]); i++)
01887        {
01888          if (!exp->noname || show_allnames)
01889            fprintf (f, "\t%sn%d%s\n",
01890                    ASM_RVA_BEFORE, exp->ordinal, ASM_RVA_AFTER);
01891        }
01892 
01893       fprintf (f,"%s Export Oridinal Table\n", ASM_C);
01894       fprintf (f, "anords:\n");
01895       for (i = 0; (exp = d_exports_lexically[i]); i++)
01896        {
01897          if (!exp->noname || show_allnames)
01898            fprintf (f, "\t%s       %d\n", ASM_SHORT, exp->ordinal - d_low_ord);
01899        }
01900 
01901       fprintf(f,"%s Export Name Table\n", ASM_C);
01902       for (i = 0; (exp = d_exports_lexically[i]); i++)
01903        {
01904          if (!exp->noname || show_allnames)
01905            fprintf (f, "n%d:       %s     \"%s\"\n",
01906                    exp->ordinal, ASM_TEXT, xlate (exp->name));
01907          if (exp->forward != 0)
01908            fprintf (f, "f%d:       %s     \"%s\"\n",
01909                    exp->forward, ASM_TEXT, exp->internal_name);
01910        }
01911 
01912       if (a_list)
01913        {
01914          fprintf (f, "\t.section %s\n", DRECTVE_SECTION_NAME);
01915          for (dl = a_list; dl; dl = dl->next)
01916            {
01917              fprintf (f, "\t%s\t\"%s\"\n", ASM_TEXT, dl->text);
01918            }
01919        }
01920 
01921       if (d_list)
01922        {
01923          fprintf (f, "\t.section .rdata\n");
01924          for (dl = d_list; dl; dl = dl->next)
01925            {
01926              char *p;
01927              int l;
01928 
01929              /* We don't output as ascii because there can
01930                 be quote characters in the string.  */
01931              l = 0;
01932              for (p = dl->text; *p; p++)
01933               {
01934                 if (l == 0)
01935                   fprintf (f, "\t%s\t", ASM_BYTE);
01936                 else
01937                   fprintf (f, ",");
01938                 fprintf (f, "%d", *p);
01939                 if (p[1] == 0)
01940                   {
01941                     fprintf (f, ",0\n");
01942                     break;
01943                   }
01944                 if (++l == 10)
01945                   {
01946                     fprintf (f, "\n");
01947                     l = 0;
01948                   }
01949               }
01950            }
01951        }
01952     }
01953 
01954 
01955   /* Add to the output file a way of getting to the exported names
01956      without using the import library.  */
01957   if (add_indirect)
01958     {
01959       fprintf (f, "\t.section\t.rdata\n");
01960       for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
01961        if (!exp->noname || show_allnames)
01962          {
01963            /* We use a single underscore for MS compatibility, and a
01964                double underscore for backward compatibility with old
01965                cygwin releases.  */
01966            if (create_compat_implib)
01967              fprintf (f, "\t%s\t__imp_%s\n", ASM_GLOBAL, exp->name);
01968            fprintf (f, "\t%s\t_imp__%s\n", ASM_GLOBAL, exp->name);
01969            if (create_compat_implib)
01970              fprintf (f, "__imp_%s:\n", exp->name);
01971            fprintf (f, "_imp__%s:\n", exp->name);
01972            fprintf (f, "\t%s\t%s\n", ASM_LONG, exp->name);
01973          }
01974     }
01975 
01976   /* Dump the reloc section if a base file is provided.  */
01977   if (base_file)
01978     {
01979       int addr;
01980       long need[PAGE_SIZE];
01981       long page_addr;
01982       int numbytes;
01983       int num_entries;
01984       long *copy;
01985       int j;
01986       int on_page;
01987       fprintf (f, "\t.section\t.init\n");
01988       fprintf (f, "lab:\n");
01989 
01990       fseek (base_file, 0, SEEK_END);
01991       numbytes = ftell (base_file);
01992       fseek (base_file, 0, SEEK_SET);
01993       copy = xmalloc (numbytes);
01994       fread (copy, 1, numbytes, base_file);
01995       num_entries = numbytes / sizeof (long);
01996 
01997 
01998       fprintf (f, "\t.section\t.reloc\n");
01999       if (num_entries)
02000        {
02001          int src;
02002          int dst = 0;
02003          int last = -1;
02004          qsort (copy, num_entries, sizeof (long), sfunc);
02005          /* Delete duplicates */
02006          for (src = 0; src < num_entries; src++)
02007            {
02008              if (last != copy[src])
02009               last = copy[dst++] = copy[src];
02010            }
02011          num_entries = dst;
02012          addr = copy[0];
02013          page_addr = addr & PAGE_MASK;           /* work out the page addr */
02014          on_page = 0;
02015          for (j = 0; j < num_entries; j++)
02016            {
02017              addr = copy[j];
02018              if ((addr & PAGE_MASK) != page_addr)
02019               {
02020                 flush_page (f, need, page_addr, on_page);
02021                 on_page = 0;
02022                 page_addr = addr & PAGE_MASK;
02023               }
02024              need[on_page++] = addr;
02025            }
02026          flush_page (f, need, page_addr, on_page);
02027 
02028 /*       fprintf (f, "\t%s\t0,0\t%s End\n", ASM_LONG, ASM_C);*/
02029        }
02030     }
02031 
02032   generate_idata_ofile (f);
02033 
02034   fclose (f);
02035 
02036   /* Assemble the file.  */
02037   assemble_file (TMP_ASM, exp_name);
02038 
02039   if (dontdeltemps == 0)
02040     unlink (TMP_ASM);
02041 
02042   inform (_("Generated exports file"));
02043 }
02044 
02045 static const char *
02046 xlate (const char *name)
02047 {
02048   int lead_at = (*name == '@');
02049 
02050   if (!lead_at && (add_underscore
02051                  || (add_stdcall_underscore
02052                      && strchr (name, '@'))))
02053     {
02054       char *copy = xmalloc (strlen (name) + 2);
02055 
02056       copy[0] = '_';
02057       strcpy (copy + 1, name);
02058       name = copy;
02059     }
02060 
02061   if (killat)
02062     {
02063       char *p;
02064 
02065       name += lead_at;
02066       p = strchr (name, '@');
02067       if (p)
02068        *p = 0;
02069     }
02070   return name;
02071 }
02072 
02073 typedef struct
02074 {
02075   int id;
02076   const char *name;
02077   int flags;
02078   int align;
02079   asection *sec;
02080   asymbol *sym;
02081   asymbol **sympp;
02082   int size;
02083   unsigned char *data;
02084 } sinfo;
02085 
02086 #ifndef DLLTOOL_PPC
02087 
02088 #define TEXT 0
02089 #define DATA 1
02090 #define BSS 2
02091 #define IDATA7 3
02092 #define IDATA5 4
02093 #define IDATA4 5
02094 #define IDATA6 6
02095 
02096 #define NSECS 7
02097 
02098 #define TEXT_SEC_FLAGS   \
02099         (SEC_ALLOC | SEC_LOAD | SEC_CODE | SEC_READONLY | SEC_HAS_CONTENTS)
02100 #define DATA_SEC_FLAGS   (SEC_ALLOC | SEC_LOAD | SEC_DATA)
02101 #define BSS_SEC_FLAGS     SEC_ALLOC
02102 
02103 #define INIT_SEC_DATA(id, name, flags, align) \
02104         { id, name, flags, align, NULL, NULL, NULL, 0, NULL }
02105 static sinfo secdata[NSECS] =
02106 {
02107   INIT_SEC_DATA (TEXT,   ".text",    TEXT_SEC_FLAGS,   2),
02108   INIT_SEC_DATA (DATA,   ".data",    DATA_SEC_FLAGS,   2),
02109   INIT_SEC_DATA (BSS,    ".bss",     BSS_SEC_FLAGS,    2),
02110   INIT_SEC_DATA (IDATA7, ".idata$7", SEC_HAS_CONTENTS, 2),
02111   INIT_SEC_DATA (IDATA5, ".idata$5", SEC_HAS_CONTENTS, 2),
02112   INIT_SEC_DATA (IDATA4, ".idata$4", SEC_HAS_CONTENTS, 2),
02113   INIT_SEC_DATA (IDATA6, ".idata$6", SEC_HAS_CONTENTS, 1)
02114 };
02115 
02116 #else
02117 
02118 /* Sections numbered to make the order the same as other PowerPC NT
02119    compilers. This also keeps funny alignment thingies from happening.  */
02120 #define TEXT   0
02121 #define PDATA  1
02122 #define RDATA  2
02123 #define IDATA5 3
02124 #define IDATA4 4
02125 #define IDATA6 5
02126 #define IDATA7 6
02127 #define DATA   7
02128 #define BSS    8
02129 
02130 #define NSECS 9
02131 
02132 static sinfo secdata[NSECS] =
02133 {
02134   { TEXT,   ".text",    SEC_CODE | SEC_HAS_CONTENTS, 3},
02135   { PDATA,  ".pdata",   SEC_HAS_CONTENTS,            2},
02136   { RDATA,  ".reldata", SEC_HAS_CONTENTS,            2},
02137   { IDATA5, ".idata$5", SEC_HAS_CONTENTS,            2},
02138   { IDATA4, ".idata$4", SEC_HAS_CONTENTS,            2},
02139   { IDATA6, ".idata$6", SEC_HAS_CONTENTS,            1},
02140   { IDATA7, ".idata$7", SEC_HAS_CONTENTS,            2},
02141   { DATA,   ".data",    SEC_DATA,                    2},
02142   { BSS,    ".bss",     0,                           2}
02143 };
02144 
02145 #endif
02146 
02147 /* This is what we're trying to make.  We generate the imp symbols with
02148    both single and double underscores, for compatibility.
02149 
02150        .text
02151        .global       _GetFileVersionInfoSizeW@8
02152        .global       __imp_GetFileVersionInfoSizeW@8
02153 _GetFileVersionInfoSizeW@8:
02154        jmp *  __imp_GetFileVersionInfoSizeW@8
02155        .section      .idata$7      # To force loading of head
02156        .long  __version_a_head
02157 # Import Address Table
02158        .section      .idata$5
02159 __imp_GetFileVersionInfoSizeW@8:
02160        .rva   ID2
02161 
02162 # Import Lookup Table
02163        .section      .idata$4
02164        .rva   ID2
02165 # Hint/Name table
02166        .section      .idata$6
02167 ID2:   .short 2
02168        .asciz "GetFileVersionInfoSizeW"
02169 
02170 
02171    For the PowerPC, here's the variation on the above scheme:
02172 
02173 # Rather than a simple "jmp *", the code to get to the dll function
02174 # looks like:
02175          .text
02176          lwz  r11,[tocv]__imp_function_name(r2)
02177 #                RELOC: 00000000 TOCREL16,TOCDEFN __imp_function_name
02178          lwz  r12,0(r11)
02179         stw   r2,4(r1)
02180         mtctr r12
02181         lwz   r2,4(r11)
02182         bctr  */
02183 
02184 static char *
02185 make_label (const char *prefix, const char *name)
02186 {
02187   int len = strlen (ASM_PREFIX (name)) + strlen (prefix) + strlen (name);
02188   char *copy = xmalloc (len + 1);
02189 
02190   strcpy (copy, ASM_PREFIX (name));
02191   strcat (copy, prefix);
02192   strcat (copy, name);
02193   return copy;
02194 }
02195 
02196 static char *
02197 make_imp_label (const char *prefix, const char *name)
02198 {
02199   int len;
02200   char *copy;
02201 
02202   if (name[0] == '@')
02203     {
02204       len = strlen (prefix) + strlen (name);
02205       copy = xmalloc (len + 1);
02206       strcpy (copy, prefix);
02207       strcat (copy, name);
02208     }
02209   else
02210     {
02211       len = strlen (ASM_PREFIX (name)) + strlen (prefix) + strlen (name);
02212       copy = xmalloc (len + 1);
02213       strcpy (copy, prefix);
02214       strcat (copy, ASM_PREFIX (name));
02215       strcat (copy, name);
02216     }
02217   return copy;
02218 }
02219 
02220 static bfd *
02221 make_one_lib_file (export_type *exp, int i)
02222 {
02223   bfd *      abfd;
02224   asymbol *  exp_label;
02225   asymbol *  iname = 0;
02226   asymbol *  iname2;
02227   asymbol *  iname_lab;
02228   asymbol ** iname_lab_pp;
02229   asymbol ** iname_pp;
02230 #ifdef DLLTOOL_PPC
02231   asymbol ** fn_pp;
02232   asymbol ** toc_pp;
02233 #define EXTRA  2
02234 #endif
02235 #ifndef EXTRA
02236 #define EXTRA    0
02237 #endif
02238   asymbol *  ptrs[NSECS + 4 + EXTRA + 1];
02239   flagword   applicable;
02240   char *     outname = xmalloc (strlen (TMP_STUB) + 10);
02241   int        oidx = 0;
02242 
02243 
02244   sprintf (outname, "%s%05d.o", TMP_STUB, i);
02245 
02246   abfd = bfd_openw (outname, HOW_BFD_WRITE_TARGET);
02247 
02248   if (!abfd)
02249     /* xgettext:c-format */
02250     fatal (_("bfd_open failed open stub file: %s"), outname);
02251 
02252   /* xgettext:c-format */
02253   inform (_("Creating stub file: %s"), outname);
02254 
02255   bfd_set_format (abfd, bfd_object);
02256   bfd_set_arch_mach (abfd, HOW_BFD_ARCH, 0);
02257 
02258 #ifdef DLLTOOL_ARM
02259   if (machine == MARM_INTERWORK || machine == MTHUMB)
02260     bfd_set_private_flags (abfd, F_INTERWORK);
02261 #endif
02262 
02263   applicable = bfd_applicable_section_flags (abfd);
02264 
02265   /* First make symbols for the sections.  */
02266   for (i = 0; i < NSECS; i++)
02267     {
02268       sinfo *si = secdata + i;
02269 
02270       if (si->id != i)
02271        abort();
02272       si->sec = bfd_make_section_old_way (abfd, si->name);
02273       bfd_set_section_flags (abfd,
02274                           si->sec,
02275                           si->flags & applicable);
02276 
02277       bfd_set_section_alignment(abfd, si->sec, si->align);
02278       si->sec->output_section = si->sec;
02279       si->sym = bfd_make_empty_symbol(abfd);
02280       si->sym->name = si->sec->name;
02281       si->sym->section = si->sec;
02282       si->sym->flags = BSF_LOCAL;
02283       si->sym->value = 0;
02284       ptrs[oidx] = si->sym;
02285       si->sympp = ptrs + oidx;
02286       si->size = 0;
02287       si->data = NULL;
02288 
02289       oidx++;
02290     }
02291 
02292   if (! exp->data)
02293     {
02294       exp_label = bfd_make_empty_symbol (abfd);
02295       exp_label->name = make_imp_label ("", exp->name);
02296 
02297       /* On PowerPC, the function name points to a descriptor in
02298         the rdata section, the first element of which is a
02299         pointer to the code (..function_name), and the second
02300         points to the .toc.  */
02301 #ifdef DLLTOOL_PPC
02302       if (machine == MPPC)
02303        exp_label->section = secdata[RDATA].sec;
02304       else
02305 #endif
02306        exp_label->section = secdata[TEXT].sec;
02307 
02308       exp_label->flags = BSF_GLOBAL;
02309       exp_label->value = 0;
02310 
02311 #ifdef DLLTOOL_ARM
02312       if (machine == MTHUMB)
02313        bfd_coff_set_symbol_class (abfd, exp_label, C_THUMBEXTFUNC);
02314 #endif
02315       ptrs[oidx++] = exp_label;
02316     }
02317 
02318   /* Generate imp symbols with one underscore for Microsoft
02319      compatibility, and with two underscores for backward
02320      compatibility with old versions of cygwin.  */
02321   if (create_compat_implib)
02322     {
02323       iname = bfd_make_empty_symbol (abfd);
02324       iname->name = make_imp_label ("___imp", exp->name);
02325       iname->section = secdata[IDATA5].sec;
02326       iname->flags = BSF_GLOBAL;
02327       iname->value = 0;
02328     }
02329 
02330   iname2 = bfd_make_empty_symbol (abfd);
02331   iname2->name = make_imp_label ("__imp_", exp->name);
02332   iname2->section = secdata[IDATA5].sec;
02333   iname2->flags = BSF_GLOBAL;
02334   iname2->value = 0;
02335 
02336   iname_lab = bfd_make_empty_symbol (abfd);
02337 
02338   iname_lab->name = head_label;
02339   iname_lab->section = (asection *) &bfd_und_section;
02340   iname_lab->flags = 0;
02341   iname_lab->value = 0;
02342 
02343   iname_pp = ptrs + oidx;
02344   if (create_compat_implib)
02345     ptrs[oidx++] = iname;
02346   ptrs[oidx++] = iname2;
02347 
02348   iname_lab_pp = ptrs + oidx;
02349   ptrs[oidx++] = iname_lab;
02350 
02351 #ifdef DLLTOOL_PPC
02352   /* The symbol referring to the code (.text).  */
02353   {
02354     asymbol *function_name;
02355 
02356     function_name = bfd_make_empty_symbol(abfd);
02357     function_name->name = make_label ("..", exp->name);
02358     function_name->section = secdata[TEXT].sec;
02359     function_name->flags = BSF_GLOBAL;
02360     function_name->value = 0;
02361 
02362     fn_pp = ptrs + oidx;
02363     ptrs[oidx++] = function_name;
02364   }
02365 
02366   /* The .toc symbol.  */
02367   {
02368     asymbol *toc_symbol;
02369 
02370     toc_symbol = bfd_make_empty_symbol (abfd);
02371     toc_symbol->name = make_label (".", "toc");
02372     toc_symbol->section = (asection *)&bfd_und_section;
02373     toc_symbol->flags = BSF_GLOBAL;
02374     toc_symbol->value = 0;
02375 
02376     toc_pp = ptrs + oidx;
02377     ptrs[oidx++] = toc_symbol;
02378   }
02379 #endif
02380 
02381   ptrs[oidx] = 0;
02382 
02383   for (i = 0; i < NSECS; i++)
02384     {
02385       sinfo *si = secdata + i;
02386       asection *sec = si->sec;
02387       arelent *rel;
02388       arelent **rpp;
02389 
02390       switch (i)
02391        {
02392        case TEXT:
02393          if (! exp->data)
02394            {
02395              si->size = HOW_JTAB_SIZE;
02396              si->data = xmalloc (HOW_JTAB_SIZE);
02397              memcpy (si->data, HOW_JTAB, HOW_JTAB_SIZE);
02398 
02399              /* Add the reloc into idata$5.  */
02400              rel = xmalloc (sizeof (arelent));
02401 
02402              rpp = xmalloc (sizeof (arelent *) * 2);
02403              rpp[0] = rel;
02404              rpp[1] = 0;
02405 
02406              rel->address = HOW_JTAB_ROFF;
02407              rel->addend = 0;
02408 
02409              if (machine == MPPC)
02410               {
02411                 rel->howto = bfd_reloc_type_lookup (abfd,
02412                                                 BFD_RELOC_16_GOTOFF);
02413                 rel->sym_ptr_ptr = iname_pp;
02414               }
02415              else if (machine == MX86)
02416               {
02417                 rel->howto = bfd_reloc_type_lookup (abfd,
02418                                                 BFD_RELOC_32_PCREL);
02419                 rel->sym_ptr_ptr = iname_pp;
02420               }
02421              else
02422               {
02423                 rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_32);
02424                 rel->sym_ptr_ptr = secdata[IDATA5].sympp;
02425               }
02426              sec->orelocation = rpp;
02427              sec->reloc_count = 1;
02428            }
02429          break;
02430        case IDATA4:
02431        case IDATA5:
02432          /* An idata$4 or idata$5 is one word long, and has an
02433             rva to idata$6.  */
02434 
02435 #ifdef DLLTOOL_MX86_64
02436          si->data = xmalloc (8);
02437          si->size = 8;
02438 
02439          if (exp->noname)
02440            {
02441              si->data[0] = exp->ordinal ;
02442              si->data[1] = exp->ordinal >> 8;
02443              si->data[2] = exp->ordinal >> 16;
02444              si->data[3] = exp->ordinal >> 24;
02445              si->data[4] = 0;
02446              si->data[5] = 0;
02447              si->data[6] = 0;
02448              si->data[7] = 0x80;
02449            }
02450          else
02451            {
02452              sec->reloc_count = 1;
02453              memset (si->data, 0, si->size);
02454              rel = xmalloc (sizeof (arelent));
02455              rpp = xmalloc (sizeof (arelent *) * 2);
02456              rpp[0] = rel;
02457              rpp[1] = 0;
02458              rel->address = 0;
02459              rel->addend = 0;
02460              rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_RVA);
02461              rel->sym_ptr_ptr = secdata[IDATA6].sympp;
02462              sec->orelocation = rpp;
02463            }
02464 #else
02465          si->data = xmalloc (4);
02466          si->size = 4;
02467 
02468          if (exp->noname)
02469            {
02470              si->data[0] = exp->ordinal ;
02471              si->data[1] = exp->ordinal >> 8;
02472              si->data[2] = exp->ordinal >> 16;
02473              si->data[3] = 0x80;
02474            }
02475          else
02476            {
02477              sec->reloc_count = 1;
02478              memset (si->data, 0, si->size);
02479              rel = xmalloc (sizeof (arelent));
02480              rpp = xmalloc (sizeof (arelent *) * 2);
02481              rpp[0] = rel;
02482              rpp[1] = 0;
02483              rel->address = 0;
02484              rel->addend = 0;
02485              rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_RVA);
02486              rel->sym_ptr_ptr = secdata[IDATA6].sympp;
02487              sec->orelocation = rpp;
02488            }
02489 #endif
02490          break;
02491 
02492        case IDATA6:
02493          if (!exp->noname)
02494            {
02495              /* This used to add 1 to exp->hint.  I don't know
02496                why it did that, and it does not match what I see
02497                in programs compiled with the MS tools.  */
02498              int idx = exp->hint;
02499              si->size = strlen (xlate (exp->import_name)) + 3;
02500              si->data = xmalloc (si->size);
02501              si->data[0] = idx & 0xff;
02502              si->data[1] = idx >> 8;
02503              strcpy ((char *) si->data + 2, xlate (exp->import_name));
02504            }
02505          break;
02506        case IDATA7:
02507          si->size = 4;
02508          si->data = xmalloc (4);
02509          memset (si->data, 0, si->size);
02510          rel = xmalloc (sizeof (arelent));
02511          rpp = xmalloc (sizeof (arelent *) * 2);
02512          rpp[0] = rel;
02513          rel->address = 0;
02514          rel->addend = 0;
02515          rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_RVA);
02516          rel->sym_ptr_ptr = iname_lab_pp;
02517          sec->orelocation = rpp;
02518          sec->reloc_count = 1;
02519          break;
02520 
02521 #ifdef DLLTOOL_PPC
02522        case PDATA:
02523          {
02524            /* The .pdata section is 5 words long.
02525               Think of it as:
02526               struct
02527               {
02528               bfd_vma BeginAddress,     [0x00]
02529               EndAddress,       [0x04]
02530               ExceptionHandler, [0x08]
02531               HandlerData,      [0x0c]
02532               PrologEndAddress; [0x10]
02533               };  */
02534 
02535            /* So this pdata section setups up this as a glue linkage to
02536               a dll routine. There are a number of house keeping things
02537               we need to do:
02538 
02539               1. In the name of glue trickery, the ADDR32 relocs for 0,
02540               4, and 0x10 are set to point to the same place:
02541               "..function_name".
02542               2. There is one more reloc needed in the pdata section.
02543               The actual glue instruction to restore the toc on
02544               return is saved as the offset in an IMGLUE reloc.
02545               So we need a total of four relocs for this section.
02546 
02547               3. Lastly, the HandlerData field is set to 0x03, to indicate
02548               that this is a glue routine.  */
02549            arelent *imglue, *ba_rel, *ea_rel, *pea_rel;
02550 
02551            /* Alignment must be set to 2**2 or you get extra stuff.  */
02552            bfd_set_section_alignment(abfd, sec, 2);
02553 
02554            si->size = 4 * 5;
02555            si->data = xmalloc (si->size);
02556            memset (si->data, 0, si->size);
02557            rpp = xmalloc (sizeof (arelent *) * 5);
02558            rpp[0] = imglue  = xmalloc (sizeof (arelent));
02559            rpp[1] = ba_rel  = xmalloc (sizeof (arelent));
02560            rpp[2] = ea_rel  = xmalloc (sizeof (arelent));
02561            rpp[3] = pea_rel = xmalloc (sizeof (arelent));
02562            rpp[4] = 0;
02563 
02564            /* Stick the toc reload instruction in the glue reloc.  */
02565            bfd_put_32(abfd, ppc_glue_insn, (char *) &imglue->address);
02566 
02567            imglue->addend = 0;
02568            imglue->howto = bfd_reloc_type_lookup (abfd,
02569                                              BFD_RELOC_32_GOTOFF);
02570            imglue->sym_ptr_ptr = fn_pp;
02571 
02572            ba_rel->address = 0;
02573            ba_rel->addend = 0;
02574            ba_rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_32);
02575            ba_rel->sym_ptr_ptr = fn_pp;
02576 
02577            bfd_put_32 (abfd, 0x18, si->data + 0x04);
02578            ea_rel->address = 4;
02579            ea_rel->addend = 0;
02580            ea_rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_32);
02581            ea_rel->sym_ptr_ptr = fn_pp;
02582 
02583            /* Mark it as glue.  */
02584            bfd_put_32 (abfd, 0x03, si->data + 0x0c);
02585 
02586            /* Mark the prolog end address.  */
02587            bfd_put_32 (abfd, 0x0D, si->data + 0x10);
02588            pea_rel->address = 0x10;
02589            pea_rel->addend = 0;
02590            pea_rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_32);
02591            pea_rel->sym_ptr_ptr = fn_pp;
02592 
02593            sec->orelocation = rpp;
02594            sec->reloc_count = 4;
02595            break;
02596          }
02597        case RDATA:
02598          /* Each external function in a PowerPC PE file has a two word
02599             descriptor consisting of:
02600             1. The address of the code.
02601             2. The address of the appropriate .toc
02602             We use relocs to build this.  */
02603          si->size = 8;
02604          si->data = xmalloc (8);
02605          memset (si->data, 0, si->size);
02606 
02607          rpp = xmalloc (sizeof (arelent *) * 3);
02608          rpp[0] = rel = xmalloc (sizeof (arelent));
02609          rpp[1] = xmalloc (sizeof (arelent));
02610          rpp[2] = 0;
02611 
02612          rel->address = 0;
02613          rel->addend = 0;
02614          rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_32);
02615          rel->sym_ptr_ptr = fn_pp;
02616 
02617          rel = rpp[1];
02618 
02619          rel->address = 4;
02620          rel->addend = 0;
02621          rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_32);
02622          rel->sym_ptr_ptr = toc_pp;
02623 
02624          sec->orelocation = rpp;
02625          sec->reloc_count = 2;
02626          break;
02627 #endif /* DLLTOOL_PPC */
02628        }
02629     }
02630 
02631   {
02632     bfd_vma vma = 0;
02633     /* Size up all the sections.  */
02634     for (i = 0; i < NSECS; i++)
02635       {
02636        sinfo *si = secdata + i;
02637 
02638        bfd_set_section_size (abfd, si->sec, si->size);
02639        bfd_set_section_vma (abfd, si->sec, vma);
02640       }
02641   }
02642   /* Write them out.  */
02643   for (i = 0; i < NSECS; i++)
02644     {
02645       sinfo *si = secdata + i;
02646 
02647       if (i == IDATA5 && no_idata5)
02648        continue;
02649 
02650       if (i == IDATA4 && no_idata4)
02651        continue;
02652 
02653       bfd_set_section_contents (abfd, si->sec,
02654                             si->data, 0,
02655                             si->size);
02656     }
02657 
02658   bfd_set_symtab (abfd, ptrs, oidx);
02659   bfd_close (abfd);
02660   abfd = bfd_openr (outname, HOW_BFD_READ_TARGET);
02661   return abfd;
02662 }
02663 
02664 static bfd *
02665 make_head (void)
02666 {
02667   FILE *f = fopen (TMP_HEAD_S, FOPEN_WT);
02668 
02669   if (f == NULL)
02670     {
02671       fatal (_("failed to open temporary head file: %s"), TMP_HEAD_S);
02672       return NULL;
02673     }
02674 
02675   fprintf (f, "%s IMAGE_IMPORT_DESCRIPTOR\n", ASM_C);
02676   fprintf (f, "\t.section   .idata$2\n");
02677 
02678   fprintf(f,"\t%s\t%s\n", ASM_GLOBAL,head_label);
02679 
02680   fprintf (f, "%s:\n", head_label);
02681 
02682   fprintf (f, "\t%shname%s\t%sPtr to image import by name list\n",
02683           ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C);
02684 
02685   fprintf (f, "\t%sthis should be the timestamp, but NT sometimes\n", ASM_C);
02686   fprintf (f, "\t%sdoesn't load DLLs when this is set.\n", ASM_C);
02687   fprintf (f, "\t%s\t0\t%s loaded time\n", ASM_LONG, ASM_C);
02688   fprintf (f, "\t%s\t0\t%s Forwarder chain\n", ASM_LONG, ASM_C);
02689   fprintf (f, "\t%s__%s_iname%s\t%s imported dll's name\n",
02690           ASM_RVA_BEFORE,
02691           imp_name_lab,
02692           ASM_RVA_AFTER,
02693           ASM_C);
02694   fprintf (f, "\t%sfthunk%s\t%s pointer to firstthunk\n",
02695           ASM_RVA_BEFORE,
02696           ASM_RVA_AFTER, ASM_C);
02697 
02698   fprintf (f, "%sStuff for compatibility\n", ASM_C);
02699 
02700   if (!no_idata5)
02701     {
02702       fprintf (f, "\t.section\t.idata$5\n");
02703 #ifdef DLLTOOL_MX86_64
02704       fprintf (f,"\t%s\t0\n\t%s\t0\n", ASM_LONG, ASM_LONG); /* NULL terminating list.  */
02705 #else
02706       fprintf (f,"\t%s\t0\n", ASM_LONG); /* NULL terminating list.  */
02707 #endif
02708       fprintf (f, "fthunk:\n");
02709     }
02710 
02711   if (!no_idata4)
02712     {
02713       fprintf (f, "\t.section\t.idata$4\n");
02714       fprintf (f, "\t%s\t0\n", ASM_LONG);
02715       fprintf (f, "\t.section      .idata$4\n");
02716       fprintf (f, "hname:\n");
02717     }
02718 
02719   fclose (f);
02720 
02721   assemble_file (TMP_HEAD_S, TMP_HEAD_O);
02722 
02723   return bfd_openr (TMP_HEAD_O, HOW_BFD_READ_TARGET);
02724 }
02725 
02726 static bfd *
02727 make_tail (void)
02728 {
02729   FILE *f = fopen (TMP_TAIL_S, FOPEN_WT);
02730 
02731   if (f == NULL)
02732     {
02733       fatal (_("failed to open temporary tail file: %s"), TMP_TAIL_S);
02734       return NULL;
02735     }
02736 
02737   if (!no_idata4)
02738     {
02739       fprintf (f, "\t.section      .idata$4\n");
02740 #ifdef DLLTOOL_MX86_64
02741       fprintf (f,"\t%s\t0\n\t%s\t0\n", ASM_LONG, ASM_LONG); /* NULL terminating list.  */
02742 #else
02743       fprintf (f,"\t%s\t0\n", ASM_LONG); /* NULL terminating list.  */
02744 #endif
02745     }
02746 
02747   if (!no_idata5)
02748     {
02749       fprintf (f, "\t.section      .idata$5\n");
02750 #ifdef DLLTOOL_MX86_64
02751       fprintf (f,"\t%s\t0\n\t%s\t0\n", ASM_LONG, ASM_LONG); /* NULL terminating list.  */
02752 #else
02753       fprintf (f,"\t%s\t0\n", ASM_LONG); /* NULL terminating list.  */
02754 #endif
02755     }
02756 
02757 #ifdef DLLTOOL_PPC
02758   /* Normally, we need to see a null descriptor built in idata$3 to
02759      act as the terminator for the list. The ideal way, I suppose,
02760      would be to mark this section as a comdat type 2 section, so
02761      only one would appear in the final .exe (if our linker supported
02762      comdat, that is) or cause it to be inserted by something else (say
02763      crt0).  */
02764 
02765   fprintf (f, "\t.section   .idata$3\n");
02766   fprintf (f, "\t%s\t0\n", ASM_LONG);
02767   fprintf (f, "\t%s\t0\n", ASM_LONG);
02768   fprintf (f, "\t%s\t0\n", ASM_LONG);
02769   fprintf (f, "\t%s\t0\n", ASM_LONG);
02770   fprintf (f, "\t%s\t0\n", ASM_LONG);
02771 #endif
02772 
02773 #ifdef DLLTOOL_PPC
02774   /* Other PowerPC NT compilers use idata$6 for the dllname, so I
02775      do too. Original, huh?  */
02776   fprintf (f, "\t.section   .idata$6\n");
02777 #else
02778   fprintf (f, "\t.section   .idata$7\n");
02779 #endif
02780 
02781   fprintf (f, "\t%s\t__%s_iname\n", ASM_GLOBAL, imp_name_lab);
02782   fprintf (f, "__%s_iname:\t%s\t\"%s\"\n",
02783           imp_name_lab, ASM_TEXT, dll_name);
02784 
02785   fclose (f);
02786 
02787   assemble_file (TMP_TAIL_S, TMP_TAIL_O);
02788 
02789   return bfd_openr (TMP_TAIL_O, HOW_BFD_READ_TARGET);
02790 }
02791 
02792 static void
02793 gen_lib_file (void)
02794 {
02795   int i;
02796   export_type *exp;
02797   bfd *ar_head;
02798   bfd *ar_tail;
02799   bfd *outarch;
02800   bfd * head  = 0;
02801 
02802   unlink (imp_name);
02803 
02804   outarch = bfd_openw (imp_name, HOW_BFD_WRITE_TARGET);
02805 
02806   if (!outarch)
02807     /* xgettext:c-format */
02808     fatal (_("Can't open .lib file: %s"), imp_name);
02809 
02810   /* xgettext:c-format */
02811   inform (_("Creating library file: %s"), imp_name);
02812 
02813   bfd_set_format (outarch, bfd_archive);
02814   outarch->has_armap = 1;
02815 
02816   /* Work out a reasonable size of things to put onto one line.  */
02817   ar_head = make_head ();
02818   ar_tail = make_tail();
02819 
02820   if (ar_head == NULL || ar_tail == NULL)
02821     return;
02822 
02823   for (i = 0; (exp = d_exports_lexically[i]); i++)
02824     {
02825       bfd *n;
02826       /* Don't add PRIVATE entries to import lib.  */
02827       if (exp->private)
02828        continue;
02829       n = make_one_lib_file (exp, i);
02830       n->next = head;
02831       head = n;
02832       if (ext_prefix_alias)
02833        {
02834          export_type alias_exp;
02835 
02836          assert (i < PREFIX_ALIAS_BASE);
02837          alias_exp.name = make_imp_label (ext_prefix_alias, exp->name);
02838          alias_exp.internal_name = exp->internal_name;
02839          alias_exp.import_name = exp->name;
02840          alias_exp.ordinal = exp->ordinal;
02841          alias_exp.constant = exp->constant;
02842          alias_exp.noname = exp->noname;
02843          alias_exp.private = exp->private;
02844          alias_exp.data = exp->data;
02845          alias_exp.hint = exp->hint;
02846          alias_exp.forward = exp->forward;
02847          alias_exp.next = exp->next;
02848          n = make_one_lib_file (&alias_exp, i + PREFIX_ALIAS_BASE);
02849          n->next = head;
02850          head = n;
02851        }
02852     }
02853 
02854   /* Now stick them all into the archive.  */
02855   ar_head->next = head;
02856   ar_tail->next = ar_head;
02857   head = ar_tail;
02858 
02859   if (! bfd_set_archive_head (outarch, head))
02860     bfd_fatal ("bfd_set_archive_head");
02861 
02862   if (! bfd_close (outarch))
02863     bfd_fatal (imp_name);
02864 
02865   while (head != NULL)
02866     {
02867       bfd *n = head->next;
02868       bfd_close (head);
02869       head = n;
02870     }
02871 
02872   /* Delete all the temp files.  */
02873   if (dontdeltemps == 0)
02874     {
02875       unlink (TMP_HEAD_O);
02876       unlink (TMP_HEAD_S);
02877       unlink (TMP_TAIL_O);
02878       unlink (TMP_TAIL_S);
02879     }
02880 
02881   if (dontdeltemps < 2)
02882     {
02883       char *name;
02884 
02885       name = (char *) alloca (strlen (TMP_STUB) + 10);
02886       for (i = 0; (exp = d_exports_lexically[i]); i++)
02887        {
02888          /* Don't delete non-existent stubs for PRIVATE entries.  */
02889           if (exp->private)
02890            continue;
02891          sprintf (name, "%s%05d.o", TMP_STUB, i);
02892          if (unlink (name) < 0)
02893            /* xgettext:c-format */
02894            non_fatal (_("cannot delete %s: %s"), name, strerror (errno));
02895          if (ext_prefix_alias)
02896            {
02897              sprintf (name, "%s%05d.o", TMP_STUB, i + PREFIX_ALIAS_BASE);
02898              if (unlink (name) < 0)
02899               /* xgettext:c-format */
02900               non_fatal (_("cannot delete %s: %s"), name, strerror (errno));
02901            }
02902        }
02903     }
02904 
02905   inform (_("Created lib file"));
02906 }
02907 
02908 /* Run through the information gathered from the .o files and the
02909    .def file and work out the best stuff.  */
02910 
02911 static int
02912 pfunc (const void *a, const void *b)
02913 {
02914   export_type *ap = *(export_type **) a;
02915   export_type *bp = *(export_type **) b;
02916   if (ap->ordinal == bp->ordinal)
02917     return 0;
02918 
02919   /* Unset ordinals go to the bottom.  */
02920   if (ap->ordinal == -1)
02921     return 1;
02922   if (bp->ordinal == -1)
02923     return -1;
02924   return (ap->ordinal - bp->ordinal);
02925 }
02926 
02927 static int
02928 nfunc (const void *a, const void *b)
02929 {
02930   export_type *ap = *(export_type **) a;
02931   export_type *bp = *(export_type **) b;
02932   const char *an = ap->name;
02933   const char *bn = bp->name;
02934 
02935   if (killat)
02936     {
02937       an = (an[0] == '@') ? an + 1 : an;
02938       bn = (bn[0] == '@') ? bn + 1 : bn;
02939     }
02940 
02941   return (strcmp (an, bn));
02942 }
02943 
02944 static void
02945 remove_null_names (export_type **ptr)
02946 {
02947   int src;
02948   int dst;
02949 
02950   for (dst = src = 0; src < d_nfuncs; src++)
02951     {
02952       if (ptr[src])
02953        {
02954          ptr[dst] = ptr[src];
02955          dst++;
02956        }
02957     }
02958   d_nfuncs = dst;
02959 }
02960 
02961 static void
02962 process_duplicates (export_type **d_export_vec)
02963 {
02964   int more = 1;
02965   int i;
02966 
02967   while (more)
02968     {
02969       more = 0;
02970       /* Remove duplicates.  */
02971       qsort (d_export_vec, d_nfuncs, sizeof (export_type *), nfunc);
02972 
02973       for (i = 0; i < d_nfuncs - 1; i++)
02974        {
02975          if (strcmp (d_export_vec[i]->name,
02976                     d_export_vec[i + 1]->name) == 0)
02977            {
02978              export_type *a = d_export_vec[i];
02979              export_type *b = d_export_vec[i + 1];
02980 
02981              more = 1;
02982 
02983              /* xgettext:c-format */
02984              inform (_("Warning, ignoring duplicate EXPORT %s %d,%d"),
02985                     a->name, a->ordinal, b->ordinal);
02986 
02987              if (a->ordinal != -1
02988                 && b->ordinal != -1)
02989               /* xgettext:c-format */
02990               fatal (_("Error, duplicate EXPORT with oridinals: %s"),
02991                     a->name);
02992 
02993              /* Merge attributes.  */
02994              b->ordinal = a->ordinal > 0 ? a->ordinal : b->ordinal;
02995              b->constant |= a->constant;
02996              b->noname |= a->noname;
02997              b->data |= a->data;
02998              d_export_vec[i] = 0;
02999            }
03000 
03001          remove_null_names (d_export_vec);
03002        }
03003     }
03004 
03005   /* Count the names.  */
03006   for (i = 0; i < d_nfuncs; i++)
03007     if (!d_export_vec[i]->noname)
03008       d_named_nfuncs++;
03009 }
03010 
03011 static void
03012 fill_ordinals (export_type **d_export_vec)
03013 {
03014   int lowest = -1;
03015   int i;
03016   char *ptr;
03017   int size = 65536;
03018 
03019   qsort (d_export_vec, d_nfuncs, sizeof (export_type *), pfunc);
03020 
03021   /* Fill in the unset ordinals with ones from our range.  */
03022   ptr = (char *) xmalloc (size);
03023 
03024   memset (ptr, 0, size);
03025 
03026   /* Mark in our large vector all the numbers that are taken.  */
03027   for (i = 0; i < d_nfuncs; i++)
03028     {
03029       if (d_export_vec[i]->ordinal != -1)
03030        {
03031          ptr[d_export_vec[i]->ordinal] = 1;
03032 
03033          if (lowest == -1 || d_export_vec[i]->ordinal < lowest)
03034            lowest = d_export_vec[i]->ordinal;
03035        }
03036     }
03037 
03038   /* Start at 1 for compatibility with MS toolchain.  */
03039   if (lowest == -1)
03040     lowest = 1;
03041 
03042   /* Now fill in ordinals where the user wants us to choose.  */
03043   for (i = 0; i < d_nfuncs; i++)
03044     {
03045       if (d_export_vec[i]->ordinal == -1)
03046        {
03047          int j;
03048 
03049          /* First try within or after any user supplied range.  */
03050          for (j = lowest; j < size; j++)
03051            if (ptr[j] == 0)
03052              {
03053               ptr[j] = 1;
03054               d_export_vec[i]->ordinal = j;
03055               goto done;
03056              }
03057 
03058          /* Then try before the range.  */
03059          for (j = lowest; j >0; j--)
03060            if (ptr[j] == 0)
03061              {
03062               ptr[j] = 1;
03063               d_export_vec[i]->ordinal = j;
03064               goto done;
03065              }
03066        done:;
03067        }
03068     }
03069 
03070   free (ptr);
03071 
03072   /* And resort.  */
03073   qsort (d_export_vec, d_nfuncs, sizeof (export_type *), pfunc);
03074 
03075   /* Work out the lowest and highest ordinal numbers.  */
03076   if (d_nfuncs)
03077     {
03078       if (d_export_vec[0])
03079        d_low_ord = d_export_vec[0]->ordinal;
03080       if (d_export_vec[d_nfuncs-1])
03081        d_high_ord = d_export_vec[d_nfuncs-1]->ordinal;
03082     }
03083 }
03084 
03085 static void
03086 mangle_defs (void)
03087 {
03088   /* First work out the minimum ordinal chosen.  */
03089   export_type *exp;
03090 
03091   int i;
03092   int hint = 0;
03093   export_type **d_export_vec = xmalloc (sizeof (export_type *) * d_nfuncs);
03094 
03095   inform (_("Processing definitions"));
03096 
03097   for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
03098     d_export_vec[i] = exp;
03099 
03100   process_duplicates (d_export_vec);
03101   fill_ordinals (d_export_vec);
03102 
03103   /* Put back the list in the new order.  */
03104   d_exports = 0;
03105   for (i = d_nfuncs - 1; i >= 0; i--)
03106     {
03107       d_export_vec[i]->next = d_exports;
03108       d_exports = d_export_vec[i];
03109     }
03110 
03111   /* Build list in alpha order.  */
03112   d_exports_lexically = (export_type **)
03113     xmalloc (sizeof (export_type *) * (d_nfuncs + 1));
03114 
03115   for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
03116     d_exports_lexically[i] = exp;
03117 
03118   d_exports_lexically[i] = 0;
03119 
03120   qsort (d_exports_lexically, i, sizeof (export_type *), nfunc);
03121 
03122   /* Fill exp entries with their hint values.  */
03123   for (i = 0; i < d_nfuncs; i++)
03124     if (!d_exports_lexically[i]->noname || show_allnames)
03125       d_exports_lexically[i]->hint = hint++;
03126 
03127   inform (_("Processed definitions"));
03128 }
03129 
03130 static void
03131 usage (FILE *file, int status)
03132 {
03133   /* xgetext:c-format */
03134   fprintf (file, _("Usage %s <option(s)> <object-file(s)>\n"), program_name);
03135   /* xgetext:c-format */
03136   fprintf (file, _("   -m --machine <machine>    Create as DLL for <machine>.  [default: %s]\n"), mname);
03137   fprintf (file, _("        possible <machine>: arm[_interwork], i386, mcore[-elf]{-le|-be}, ppc, thumb\n"));
03138   fprintf (file, _("   -e --output-exp <outname> Generate an export file.\n"));
03139   fprintf (file, _("   -l --output-lib <outname> Generate an interface library.\n"));
03140   fprintf (file, _("   -a --add-indirect         Add dll indirects to export file.\n"));
03141   fprintf (file, _("   -D --dllname <name>       Name of input dll to put into interface lib.\n"));
03142   fprintf (file, _("   -d --input-def <deffile>  Name of .def file to be read in.\n"));
03143   fprintf (file, _("   -z --output-def <deffile> Name of .def file to be created.\n"));
03144   fprintf (file, _("      --export-all-symbols   Export all symbols to .def\n"));
03145   fprintf (file, _("      --no-export-all-symbols  Only export listed symbols\n"));
03146   fprintf (file, _("      --exclude-symbols <list> Don't export <list>\n"));
03147   fprintf (file, _("      --no-default-excludes  Clear default exclude symbols\n"));
03148   fprintf (file, _("   -b --base-file <basefile> Read linker generated base file.\n"));
03149   fprintf (file, _("   -x --no-idata4            Don't generate idata$4 section.\n"));
03150   fprintf (file, _("   -c --no-idata5            Don't generate idata$5 section.\n"));
03151   fprintf (file, _("   -U --add-underscore       Add underscores to all symbols in interface library.\n"));
03152   fprintf (file, _("      --add-stdcall-underscore Add underscores to stdcall symbols in interface library.\n"));
03153   fprintf (file, _("   -k --kill-at              Kill @<n> from exported names.\n"));
03154   fprintf (file, _("   -A --add-stdcall-alias    Add aliases without @<n>.\n"));
03155   fprintf (file, _("   -p --ext-prefix-alias <prefix> Add aliases with <prefix>.\n"));
03156   fprintf (file, _("   -S --as <name>            Use <name> for assembler.\n"));
03157   fprintf (file, _("   -f --as-flags <flags>     Pass <flags> to the assembler.\n"));
03158   fprintf (file, _("   -C --compat-implib        Create backward compatible import library.\n"));
03159   fprintf (file, _("   -n --no-delete            Keep temp files (repeat for extra preservation).\n"));
03160   fprintf (file, _("   -t --temp-prefix <prefix> Use <prefix> to construct temp file names.\n"));
03161   fprintf (file, _("   -v --verbose              Be verbose.\n"));
03162   fprintf (file, _("   -V --version              Display the program version.\n"));
03163   fprintf (file, _("   -h --help                 Display this information.\n"));
03164   fprintf (file, _("   @<file>                   Read options from <file>.\n"));
03165 #ifdef DLLTOOL_MCORE_ELF
03166   fprintf (file, _("   -M --mcore-elf <outname>  Process mcore-elf object files into <outname>.\n"));
03167   fprintf (file, _("   -L --linker <name>        Use <name> as the linker.\n"));
03168   fprintf (file, _("   -F --linker-flags <flags> Pass <flags> to the linker.\n"));
03169 #endif
03170   if (REPORT_BUGS_TO[0] && status == 0)
03171     fprintf (file, _("Report bugs to %s\n"), REPORT_BUGS_TO);
03172   exit (status);
03173 }
03174 
03175 #define OPTION_EXPORT_ALL_SYMS            150
03176 #define OPTION_NO_EXPORT_ALL_SYMS  (OPTION_EXPORT_ALL_SYMS + 1)
03177 #define OPTION_EXCLUDE_SYMS        (OPTION_NO_EXPORT_ALL_SYMS + 1)
03178 #define OPTION_NO_DEFAULT_EXCLUDES (OPTION_EXCLUDE_SYMS + 1)
03179 #define OPTION_ADD_STDCALL_UNDERSCORE     (OPTION_NO_DEFAULT_EXCLUDES + 1)
03180 
03181 static const struct option long_options[] =
03182 {
03183   {"no-delete", no_argument, NULL, 'n'},
03184   {"dllname", required_argument, NULL, 'D'},
03185   {"no-idata4", no_argument, NULL, 'x'},
03186   {"no-idata5", no_argument, NULL, 'c'},
03187   {"output-exp", required_argument, NULL, 'e'},
03188   {"output-def", required_argument, NULL, 'z'},
03189   {"export-all-symbols", no_argument, NULL, OPTION_EXPORT_ALL_SYMS},
03190   {"no-export-all-symbols", no_argument, NULL, OPTION_NO_EXPORT_ALL_SYMS},
03191   {"exclude-symbols", required_argument, NULL, OPTION_EXCLUDE_SYMS},
03192   {"no-default-excludes", no_argument, NULL, OPTION_NO_DEFAULT_EXCLUDES},
03193   {"output-lib", required_argument, NULL, 'l'},
03194   {"def", required_argument, NULL, 'd'}, /* for compatibility with older versions */
03195   {"input-def", required_argument, NULL, 'd'},
03196   {"add-underscore", no_argument, NULL, 'U'},
03197   {"add-stdcall-underscore", no_argument, NULL, OPTION_ADD_STDCALL_UNDERSCORE},
03198   {"kill-at", no_argument, NULL, 'k'},
03199   {"add-stdcall-alias", no_argument, NULL, 'A'},
03200   {"ext-prefix-alias", required_argument, NULL, 'p'},
03201   {"verbose", no_argument, NULL, 'v'},
03202   {"version", no_argument, NULL, 'V'},
03203   {"help", no_argument, NULL, 'h'},
03204   {"machine", required_argument, NULL, 'm'},
03205   {"add-indirect", no_argument, NULL, 'a'},
03206   {"base-file", required_argument, NULL, 'b'},
03207   {"as", required_argument, NULL, 'S'},
03208   {"as-flags", required_argument, NULL, 'f'},
03209   {"mcore-elf", required_argument, NULL, 'M'},
03210   {"compat-implib", no_argument, NULL, 'C'},
03211   {"temp-prefix", required_argument, NULL, 't'},
03212   {NULL,0,NULL,0}
03213 };
03214 
03215 int main (int, char **);
03216 
03217 int
03218 main (int ac, char **av)
03219 {
03220   int c;
03221   int i;
03222   char *firstarg = 0;
03223   program_name = av[0];
03224   oav = av;
03225 
03226 #if defined (HAVE_SETLOCALE) && defined (HAVE_LC_MESSAGES)
03227   setlocale (LC_MESSAGES, "");
03228 #endif
03229 #if defined (HAVE_SETLOCALE)
03230   setlocale (LC_CTYPE, "");
03231 #endif
03232   bindtextdomain (PACKAGE, LOCALEDIR);
03233   textdomain (PACKAGE);
03234 
03235   expandargv (&ac, &av);
03236 
03237   while ((c = getopt_long (ac, av,
03238 #ifdef DLLTOOL_MCORE_ELF
03239                         "m:e:l:aD:d:z:b:xp:cCuUkAS:f:nvVHhM:L:F:",
03240 #else
03241                         "m:e:l:aD:d:z:b:xp:cCuUkAS:f:nvVHh",
03242 #endif
03243                         long_options, 0))
03244         != EOF)
03245     {
03246       switch (c)
03247        {
03248        case OPTION_EXPORT_ALL_SYMS:
03249          export_all_symbols = TRUE;
03250          break;
03251        case OPTION_NO_EXPORT_ALL_SYMS:
03252          export_all_symbols = FALSE;
03253          break;
03254        case OPTION_EXCLUDE_SYMS:
03255          add_excludes (optarg);
03256          break;
03257        case OPTION_NO_DEFAULT_EXCLUDES:
03258          do_default_excludes = FALSE;
03259          break;
03260        case OPTION_ADD_STDCALL_UNDERSCORE:
03261          add_stdcall_underscore = 1;
03262          break;
03263        case 'x':
03264          no_idata4 = 1;
03265          break;
03266        case 'c':
03267          no_idata5 = 1;
03268          break;
03269        case 'S':
03270          as_name = optarg;
03271          break;
03272        case 't':
03273          tmp_prefix = optarg;
03274          break;
03275        case 'f':
03276          as_flags = optarg;
03277          break;
03278 
03279          /* Ignored for compatibility.  */
03280        case 'u':
03281          break;
03282        case 'a':
03283          add_indirect = 1;
03284          break;
03285        case 'z':
03286          output_def = fopen (optarg, FOPEN_WT);
03287          break;
03288        case 'D':
03289          dll_name = (char*) lbasename (optarg);
03290          if (dll_name != optarg)
03291            non_fatal (_("Path components stripped from dllname, '%s'."),
03292                       optarg);
03293          break;
03294        case 'l':
03295          imp_name = optarg;
03296          break;
03297        case 'e':
03298          exp_name = optarg;
03299          break;
03300        case 'H':
03301        case 'h':
03302          usage (stdout, 0);
03303          break;
03304        case 'm':
03305          mname = optarg;
03306          break;
03307        case 'v':
03308          verbose = 1;
03309          break;
03310        case 'V':
03311          print_version (program_name);
03312          break;
03313        case 'U':
03314          add_underscore = 1;
03315          break;
03316        case 'k':
03317          killat = 1;
03318          break;
03319        case 'A':
03320          add_stdcall_alias = 1;
03321          break;
03322        case 'p':
03323          ext_prefix_alias = optarg;
03324          break;
03325        case 'd':
03326          def_file = optarg;
03327          break;
03328        case 'n':
03329          dontdeltemps++;
03330          break;
03331        case 'b':
03332          base_file = fopen (optarg, FOPEN_RB);
03333 
03334          if (!base_file)
03335            /* xgettext:c-format */
03336            fatal (_("Unable to open base-file: %s"), optarg);
03337 
03338          break;
03339 #ifdef DLLTOOL_MCORE_ELF
03340        case 'M':
03341          mcore_elf_out_file = optarg;
03342          break;
03343        case 'L':
03344          mcore_elf_linker = optarg;
03345          break;
03346        case 'F':
03347          mcore_elf_linker_flags = optarg;
03348          break;
03349 #endif
03350        case 'C':
03351          create_compat_implib = 1;
03352          break;
03353        default:
03354          usage (stderr, 1);
03355          break;
03356        }
03357     }
03358 
03359   if (!tmp_prefix)
03360     tmp_prefix = prefix_encode ("d", getpid ());
03361 
03362   for (i = 0; mtable[i].type; i++)
03363     if (strcmp (mtable[i].type, mname) == 0)
03364       break;
03365 
03366   if (!mtable[i].type)
03367     /* xgettext:c-format */
03368     fatal (_("Machine '%s' not supported"), mname);
03369 
03370   machine = i;
03371 
03372   if (!dll_name && exp_name)
03373     {
03374       /* If we are inferring dll_name from exp_name,
03375          strip off any path components, without emitting
03376          a warning.  */  
03377       const char* exp_basename = lbasename (exp_name); 
03378       const int len = strlen (exp_basename) + 5;
03379       dll_name = xmalloc (len);
03380       strcpy (dll_name, exp_basename);
03381       strcat (dll_name, ".dll");
03382     }
03383 
03384   if (as_name == NULL)
03385     as_name = deduce_name ("as");
03386 
03387   /* Don't use the default exclude list if we're reading only the
03388      symbols in the .drectve section.  The default excludes are meant
03389      to avoid exporting DLL entry point and Cygwin32 impure_ptr.  */
03390   if (! export_all_symbols)
03391     do_default_excludes = FALSE;
03392 
03393   if (do_default_excludes)
03394     set_default_excludes ();
03395 
03396   if (def_file)
03397     process_def_file (def_file);
03398 
03399   while (optind < ac)
03400     {
03401       if (!firstarg)
03402        firstarg = av[optind];
03403       scan_obj_file (av[optind]);
03404       optind++;
03405     }
03406 
03407   mangle_defs ();
03408 
03409   if (exp_name)
03410     gen_exp_file ();
03411 
03412   if (imp_name)
03413     {
03414       /* Make imp_name safe for use as a label.  */
03415       char *p;
03416 
03417       imp_name_lab = xstrdup (imp_name);
03418       for (p = imp_name_lab; *p; p++)
03419        {
03420          if (!ISALNUM (*p))
03421            *p = '_';
03422        }
03423       head_label = make_label("_head_", imp_name_lab);
03424       gen_lib_file ();
03425     }
03426 
03427   if (output_def)
03428     gen_def_file ();
03429 
03430 #ifdef DLLTOOL_MCORE_ELF
03431   if (mcore_elf_out_file)
03432     mcore_elf_gen_out_file ();
03433 #endif
03434 
03435   return 0;
03436 }
03437 
03438 /* Look for the program formed by concatenating PROG_NAME and the
03439    string running from PREFIX to END_PREFIX.  If the concatenated
03440    string contains a '/', try appending EXECUTABLE_SUFFIX if it is
03441    appropriate.  */
03442 
03443 static char *
03444 look_for_prog (const char *prog_name, const char *prefix, int end_prefix)
03445 {
03446   struct stat s;
03447   char *cmd;
03448 
03449   cmd = xmalloc (strlen (prefix)
03450                + strlen (prog_name)
03451 #ifdef HAVE_EXECUTABLE_SUFFIX
03452                + strlen (EXECUTABLE_SUFFIX)
03453 #endif
03454                + 10);
03455   strcpy (cmd, prefix);
03456 
03457   sprintf (cmd + end_prefix, "%s", prog_name);
03458 
03459   if (strchr (cmd, '/') != NULL)
03460     {
03461       int found;
03462 
03463       found = (stat (cmd, &s) == 0
03464 #ifdef HAVE_EXECUTABLE_SUFFIX
03465               || stat (strcat (cmd, EXECUTABLE_SUFFIX), &s) == 0
03466 #endif
03467               );
03468 
03469       if (! found)
03470        {
03471          /* xgettext:c-format */
03472          inform (_("Tried file: %s"), cmd);
03473          free (cmd);
03474          return NULL;
03475        }
03476     }
03477 
03478   /* xgettext:c-format */
03479   inform (_("Using file: %s"), cmd);
03480 
03481   return cmd;
03482 }
03483 
03484 /* Deduce the name of the program we are want to invoke.
03485    PROG_NAME is the basic name of the program we want to run,
03486    eg "as" or "ld".  The catch is that we might want actually
03487    run "i386-pe-as" or "ppc-pe-ld".
03488 
03489    If argv[0] contains the full path, then try to find the program
03490    in the same place, with and then without a target-like prefix.
03491 
03492    Given, argv[0] = /usr/local/bin/i586-cygwin32-dlltool,
03493    deduce_name("as") uses the following search order:
03494 
03495      /usr/local/bin/i586-cygwin32-as
03496      /usr/local/bin/as
03497      as
03498 
03499    If there's an EXECUTABLE_SUFFIX, it'll use that as well; for each
03500    name, it'll try without and then with EXECUTABLE_SUFFIX.
03501 
03502    Given, argv[0] = i586-cygwin32-dlltool, it will not even try "as"
03503    as the fallback, but rather return i586-cygwin32-as.
03504 
03505    Oh, and given, argv[0] = dlltool, it'll return "as".
03506 
03507    Returns a dynamically allocated string.  */
03508 
03509 static char *
03510 deduce_name (const char *prog_name)
03511 {
03512   char *cmd;
03513   char *dash, *slash, *cp;
03514 
03515   dash = NULL;
03516   slash = NULL;
03517   for (cp = program_name; *cp != '\0'; ++cp)
03518     {
03519       if (*cp == '-')
03520        dash = cp;
03521       if (
03522 #if defined(__DJGPP__) || defined (__CYGWIN__) || defined(__WIN32__)
03523          *cp == ':' || *cp == '\\' ||
03524 #endif
03525          *cp == '/')
03526        {
03527          slash = cp;
03528          dash = NULL;
03529        }
03530     }
03531 
03532   cmd = NULL;
03533 
03534   if (dash != NULL)
03535     {
03536       /* First, try looking for a prefixed PROG_NAME in the
03537          PROGRAM_NAME directory, with the same prefix as PROGRAM_NAME.  */
03538       cmd = look_for_prog (prog_name, program_name, dash - program_name + 1);
03539     }
03540 
03541   if (slash != NULL && cmd == NULL)
03542     {
03543       /* Next, try looking for a PROG_NAME in the same directory as
03544          that of this program.  */
03545       cmd = look_for_prog (prog_name, program_name, slash - program_name + 1);
03546     }
03547 
03548   if (cmd == NULL)
03549     {
03550       /* Just return PROG_NAME as is.  */
03551       cmd = xstrdup (prog_name);
03552     }
03553 
03554   return cmd;
03555 }
03556 
03557 #ifdef DLLTOOL_MCORE_ELF
03558 typedef struct fname_cache
03559 {
03560   char *               filename;
03561   struct fname_cache * next;
03562 }
03563 fname_cache;
03564 
03565 static fname_cache fnames;
03566 
03567 static void
03568 mcore_elf_cache_filename (char * filename)
03569 {
03570   fname_cache * ptr;
03571 
03572   ptr = & fnames;
03573 
03574   while (ptr->next != NULL)
03575     ptr = ptr->next;
03576 
03577   ptr->filename = filename;
03578   ptr->next     = (fname_cache *) malloc (sizeof (fname_cache));
03579   if (ptr->next != NULL)
03580     ptr->next->next = NULL;
03581 }
03582 
03583 #define MCORE_ELF_TMP_OBJ "mcoreelf.o"
03584 #define MCORE_ELF_TMP_EXP "mcoreelf.exp"
03585 #define MCORE_ELF_TMP_LIB "mcoreelf.lib"
03586 
03587 static void
03588 mcore_elf_gen_out_file (void)
03589 {
03590   fname_cache * ptr;
03591   dyn_string_t ds;
03592 
03593   /* Step one.  Run 'ld -r' on the input object files in order to resolve
03594      any internal references and to generate a single .exports section.  */
03595   ptr = & fnames;
03596 
03597   ds = dyn_string_new (100);
03598   dyn_string_append_cstr (ds, "-r ");
03599 
03600   if (mcore_elf_linker_flags != NULL)
03601     dyn_string_append_cstr (ds, mcore_elf_linker_flags);
03602 
03603   while (ptr->next != NULL)
03604     {
03605       dyn_string_append_cstr (ds, ptr->filename);
03606       dyn_string_append_cstr (ds, " ");
03607 
03608       ptr = ptr->next;
03609     }
03610 
03611   dyn_string_append_cstr (ds, "-o ");
03612   dyn_string_append_cstr (ds, MCORE_ELF_TMP_OBJ);
03613 
03614   if (mcore_elf_linker == NULL)
03615     mcore_elf_linker = deduce_name ("ld");
03616 
03617   run (mcore_elf_linker, ds->s);
03618 
03619   dyn_string_delete (ds);
03620 
03621   /* Step two. Create a .exp file and a .lib file from the temporary file.
03622      Do this by recursively invoking dlltool...  */
03623   ds = dyn_string_new (100);
03624 
03625   dyn_string_append_cstr (ds, "-S ");
03626   dyn_string_append_cstr (ds, as_name);
03627 
03628   dyn_string_append_cstr (ds, " -e ");
03629   dyn_string_append_cstr (ds, MCORE_ELF_TMP_EXP);
03630   dyn_string_append_cstr (ds, " -l ");
03631   dyn_string_append_cstr (ds, MCORE_ELF_TMP_LIB);
03632   dyn_string_append_cstr (ds, " " );
03633   dyn_string_append_cstr (ds, MCORE_ELF_TMP_OBJ);
03634 
03635   if (verbose)
03636     dyn_string_append_cstr (ds, " -v");
03637 
03638   if (dontdeltemps)
03639     {
03640       dyn_string_append_cstr (ds, " -n");
03641 
03642       if (dontdeltemps > 1)
03643        dyn_string_append_cstr (ds, " -n");
03644     }
03645 
03646   /* XXX - FIME: ought to check/copy other command line options as well.  */
03647   run (program_name, ds->s);
03648 
03649   dyn_string_delete (ds);
03650 
03651   /* Step four. Feed the .exp and object files to ld -shared to create the dll.  */
03652   ds = dyn_string_new (100);
03653 
03654   dyn_string_append_cstr (ds, "-shared ");
03655 
03656   if (mcore_elf_linker_flags)
03657     dyn_string_append_cstr (ds, mcore_elf_linker_flags);
03658 
03659   dyn_string_append_cstr (ds, " ");
03660   dyn_string_append_cstr (ds, MCORE_ELF_TMP_EXP);
03661   dyn_string_append_cstr (ds, " ");
03662   dyn_string_append_cstr (ds, MCORE_ELF_TMP_OBJ);
03663   dyn_string_append_cstr (ds, " -o ");
03664   dyn_string_append_cstr (ds, mcore_elf_out_file);
03665 
03666   run (mcore_elf_linker, ds->s);
03667 
03668   dyn_string_delete (ds);
03669 
03670   if (dontdeltemps == 0)
03671     unlink (MCORE_ELF_TMP_EXP);
03672 
03673   if (dontdeltemps < 2)
03674     unlink (MCORE_ELF_TMP_OBJ);
03675 }
03676 #endif /* DLLTOOL_MCORE_ELF */