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