160484Sobrien/* dlltool.c -- tool to generate stuff for PE style DLLs 2218822Sdim Copyright 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 3218822Sdim 2005, 2006, 2007 Free Software Foundation, Inc. 433965Sjdp 533965Sjdp This file is part of GNU Binutils. 633965Sjdp 733965Sjdp This program is free software; you can redistribute it and/or modify 833965Sjdp it under the terms of the GNU General Public License as published by 933965Sjdp the Free Software Foundation; either version 2 of the License, or 1033965Sjdp (at your option) any later version. 1133965Sjdp 1233965Sjdp This program is distributed in the hope that it will be useful, 1333965Sjdp but WITHOUT ANY WARRANTY; without even the implied warranty of 1433965Sjdp MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1533965Sjdp GNU General Public License for more details. 1633965Sjdp 1733965Sjdp You should have received a copy of the GNU General Public License 1833965Sjdp along with this program; if not, write to the Free Software 19218822Sdim Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 20218822Sdim 02110-1301, USA. */ 2133965Sjdp 2233965Sjdp 23130561Sobrien/* This program allows you to build the files necessary to create 2433965Sjdp DLLs to run on a system which understands PE format image files. 2533965Sjdp (eg, Windows NT) 2633965Sjdp 2733965Sjdp See "Peering Inside the PE: A Tour of the Win32 Portable Executable 2833965Sjdp File Format", MSJ 1994, Volume 9 for more information. 2933965Sjdp Also see "Microsoft Portable Executable and Common Object File Format, 3033965Sjdp Specification 4.1" for more information. 3133965Sjdp 3233965Sjdp A DLL contains an export table which contains the information 3333965Sjdp which the runtime loader needs to tie up references from a 3460484Sobrien referencing program. 3533965Sjdp 3633965Sjdp The export table is generated by this program by reading 3733965Sjdp in a .DEF file or scanning the .a and .o files which will be in the 3833965Sjdp DLL. A .o file can contain information in special ".drectve" sections 3960484Sobrien with export information. 4033965Sjdp 4133965Sjdp A DEF file contains any number of the following commands: 4233965Sjdp 4333965Sjdp 4460484Sobrien NAME <name> [ , <base> ] 4533965Sjdp The result is going to be <name>.EXE 4633965Sjdp 4760484Sobrien LIBRARY <name> [ , <base> ] 4833965Sjdp The result is going to be <name>.DLL 4933965Sjdp 5089857Sobrien EXPORTS ( ( ( <name1> [ = <name2> ] ) 5189857Sobrien | ( <name1> = <module-name> . <external-name>)) 52130561Sobrien [ @ <integer> ] [ NONAME ] [CONSTANT] [DATA] [PRIVATE] ) * 5333965Sjdp Declares name1 as an exported symbol from the 5489857Sobrien DLL, with optional ordinal number <integer>. 5589857Sobrien Or declares name1 as an alias (forward) of the function <external-name> 5689857Sobrien in the DLL <module-name>. 5733965Sjdp 5860484Sobrien IMPORTS ( ( <internal-name> = <module-name> . <integer> ) 5960484Sobrien | ( [ <internal-name> = ] <module-name> . <external-name> )) * 60218822Sdim Declares that <external-name> or the exported function whose ordinal number 6160484Sobrien is <integer> is to be imported from the file <module-name>. If 6260484Sobrien <internal-name> is specified then this is the name that the imported 63130561Sobrien function will be refereed to in the body of the DLL. 6433965Sjdp 6533965Sjdp DESCRIPTION <string> 6633965Sjdp Puts <string> into output .exp file in the .rdata section 6733965Sjdp 6833965Sjdp [STACKSIZE|HEAPSIZE] <number-reserve> [ , <number-commit> ] 6933965Sjdp Generates --stack|--heap <number-reserve>,<number-commit> 7033965Sjdp in the output .drectve section. The linker will 7133965Sjdp see this and act upon it. 7233965Sjdp 7333965Sjdp [CODE|DATA] <attr>+ 7433965Sjdp SECTIONS ( <sectionname> <attr>+ )* 7533965Sjdp <attr> = READ | WRITE | EXECUTE | SHARED 7633965Sjdp Generates --attr <sectionname> <attr> in the output 7733965Sjdp .drectve section. The linker will see this and act 7833965Sjdp upon it. 7933965Sjdp 8033965Sjdp 8133965Sjdp A -export:<name> in a .drectve section in an input .o or .a 8233965Sjdp file to this program is equivalent to a EXPORTS <name> 8333965Sjdp in a .DEF file. 8433965Sjdp 8533965Sjdp 8633965Sjdp 8733965Sjdp The program generates output files with the prefix supplied 8860484Sobrien on the command line, or in the def file, or taken from the first 8933965Sjdp supplied argument. 9033965Sjdp 9133965Sjdp The .exp.s file contains the information necessary to export 9233965Sjdp the routines in the DLL. The .lib.s file contains the information 9333965Sjdp necessary to use the DLL's routines from a referencing program. 9433965Sjdp 9533965Sjdp 9633965Sjdp 9733965Sjdp Example: 9833965Sjdp 9960484Sobrien file1.c: 10060484Sobrien asm (".section .drectve"); 10133965Sjdp asm (".ascii \"-export:adef\""); 10233965Sjdp 10360484Sobrien void adef (char * s) 10433965Sjdp { 10560484Sobrien printf ("hello from the dll %s\n", s); 10633965Sjdp } 10733965Sjdp 10860484Sobrien void bdef (char * s) 10933965Sjdp { 11060484Sobrien printf ("hello from the dll and the other entry point %s\n", s); 11133965Sjdp } 11233965Sjdp 11360484Sobrien file2.c: 11433965Sjdp asm (".section .drectve"); 11533965Sjdp asm (".ascii \"-export:cdef\""); 11633965Sjdp asm (".ascii \"-export:ddef\""); 117104834Sobrien 11860484Sobrien void cdef (char * s) 11933965Sjdp { 12060484Sobrien printf ("hello from the dll %s\n", s); 12133965Sjdp } 12233965Sjdp 12360484Sobrien void ddef (char * s) 12433965Sjdp { 12560484Sobrien printf ("hello from the dll and the other entry point %s\n", s); 12633965Sjdp } 12733965Sjdp 12860484Sobrien int printf (void) 12933965Sjdp { 13060484Sobrien return 9; 13133965Sjdp } 13233965Sjdp 13360484Sobrien themain.c: 13460484Sobrien int main (void) 13533965Sjdp { 13660484Sobrien cdef (); 13760484Sobrien return 0; 13833965Sjdp } 13933965Sjdp 14060484Sobrien thedll.def 14133965Sjdp 14233965Sjdp LIBRARY thedll 14333965Sjdp HEAPSIZE 0x40000, 0x2000 14433965Sjdp EXPORTS bdef @ 20 14560484Sobrien cdef @ 30 NONAME 14633965Sjdp 14733965Sjdp SECTIONS donkey READ WRITE 14833965Sjdp aardvark EXECUTE 14933965Sjdp 15060484Sobrien # Compile up the parts of the dll and the program 15133965Sjdp 15260484Sobrien gcc -c file1.c file2.c themain.c 15333965Sjdp 15460484Sobrien # Optional: put the dll objects into a library 15560484Sobrien # (you don't have to, you could name all the object 15660484Sobrien # files on the dlltool line) 15733965Sjdp 15833965Sjdp ar qcv thedll.in file1.o file2.o 15933965Sjdp ranlib thedll.in 16033965Sjdp 16160484Sobrien # Run this tool over the DLL's .def file and generate an exports 16260484Sobrien # file (thedll.o) and an imports file (thedll.a). 16360484Sobrien # (You may have to use -S to tell dlltool where to find the assembler). 164104834Sobrien 16560484Sobrien dlltool --def thedll.def --output-exp thedll.o --output-lib thedll.a 16633965Sjdp 16760484Sobrien # Build the dll with the library and the export table 168104834Sobrien 16933965Sjdp ld -o thedll.dll thedll.o thedll.in 17033965Sjdp 17160484Sobrien # Link the executable with the import library 172104834Sobrien 17360484Sobrien gcc -o themain.exe themain.o thedll.a 17433965Sjdp 17560484Sobrien This example can be extended if relocations are needed in the DLL: 17633965Sjdp 17760484Sobrien # Compile up the parts of the dll and the program 17860484Sobrien 17960484Sobrien gcc -c file1.c file2.c themain.c 18060484Sobrien 18160484Sobrien # Run this tool over the DLL's .def file and generate an imports file. 182104834Sobrien 18360484Sobrien dlltool --def thedll.def --output-lib thedll.lib 18460484Sobrien 18560484Sobrien # Link the executable with the import library and generate a base file 18660484Sobrien # at the same time 187104834Sobrien 18860484Sobrien gcc -o themain.exe themain.o thedll.lib -Wl,--base-file -Wl,themain.base 18960484Sobrien 19060484Sobrien # Run this tool over the DLL's .def file and generate an exports file 19160484Sobrien # which includes the relocations from the base file. 192104834Sobrien 19360484Sobrien dlltool --def thedll.def --base-file themain.base --output-exp thedll.exp 19460484Sobrien 19560484Sobrien # Build the dll with file1.o, file2.o and the export table 196104834Sobrien 197130561Sobrien ld -o thedll.dll thedll.exp file1.o file2.o */ 19833965Sjdp 19933965Sjdp/* .idata section description 20033965Sjdp 20133965Sjdp The .idata section is the import table. It is a collection of several 20233965Sjdp subsections used to keep the pieces for each dll together: .idata$[234567]. 20333965Sjdp IE: Each dll's .idata$2's are catenated together, each .idata$3's, etc. 20433965Sjdp 20533965Sjdp .idata$2 = Import Directory Table 20633965Sjdp = array of IMAGE_IMPORT_DESCRIPTOR's. 20733965Sjdp 20860484Sobrien DWORD Import Lookup Table; - pointer to .idata$4 20933965Sjdp DWORD TimeDateStamp; - currently always 0 21033965Sjdp DWORD ForwarderChain; - currently always 0 21133965Sjdp DWORD Name; - pointer to dll's name 21233965Sjdp PIMAGE_THUNK_DATA FirstThunk; - pointer to .idata$5 21333965Sjdp 21433965Sjdp .idata$3 = null terminating entry for .idata$2. 21533965Sjdp 21633965Sjdp .idata$4 = Import Lookup Table 21733965Sjdp = array of array of pointers to hint name table. 21833965Sjdp There is one for each dll being imported from, and each dll's set is 21933965Sjdp terminated by a trailing NULL. 22033965Sjdp 22133965Sjdp .idata$5 = Import Address Table 22233965Sjdp = array of array of pointers to hint name table. 22333965Sjdp There is one for each dll being imported from, and each dll's set is 22433965Sjdp terminated by a trailing NULL. 22533965Sjdp Initially, this table is identical to the Import Lookup Table. However, 22633965Sjdp at load time, the loader overwrites the entries with the address of the 22733965Sjdp function. 22833965Sjdp 22933965Sjdp .idata$6 = Hint Name Table 23033965Sjdp = Array of { short, asciz } entries, one for each imported function. 23133965Sjdp The `short' is the function's ordinal number. 23233965Sjdp 233130561Sobrien .idata$7 = dll name (eg: "kernel32.dll"). (.idata$6 for ppc). */ 23433965Sjdp 23533965Sjdp/* AIX requires this to be the first thing in the file. */ 23633965Sjdp#ifndef __GNUC__ 23733965Sjdp# ifdef _AIX 23833965Sjdp #pragma alloca 23933965Sjdp#endif 24033965Sjdp#endif 24133965Sjdp 24233965Sjdp#define show_allnames 0 24333965Sjdp 24433965Sjdp#define PAGE_SIZE 4096 24533965Sjdp#define PAGE_MASK (-PAGE_SIZE) 246218822Sdim#include "sysdep.h" 24733965Sjdp#include "bfd.h" 24833965Sjdp#include "libiberty.h" 24933965Sjdp#include "getopt.h" 25033965Sjdp#include "demangle.h" 25160484Sobrien#include "dyn-string.h" 252218822Sdim#include "bucomm.h" 25338889Sjdp#include "dlltool.h" 25489857Sobrien#include "safe-ctype.h" 25538889Sjdp 25638889Sjdp#include <time.h> 25760484Sobrien#include <sys/stat.h> 25860484Sobrien#include <stdarg.h> 259218822Sdim#include <assert.h> 26060484Sobrien 26160484Sobrien#ifdef DLLTOOL_ARM 26260484Sobrien#include "coff/arm.h" 26360484Sobrien#include "coff/internal.h" 26460484Sobrien#endif 265218822Sdim#ifdef DLLTOOL_MX86_64 266218822Sdim#include "coff/x86_64.h" 267218822Sdim#endif 26860484Sobrien 26960484Sobrien/* Forward references. */ 270130561Sobrienstatic char *look_for_prog (const char *, const char *, int); 271130561Sobrienstatic char *deduce_name (const char *); 27260484Sobrien 27360484Sobrien#ifdef DLLTOOL_MCORE_ELF 27460484Sobrienstatic void mcore_elf_cache_filename (char *); 27560484Sobrienstatic void mcore_elf_gen_out_file (void); 27660484Sobrien#endif 277104834Sobrien 27833965Sjdp#ifdef HAVE_SYS_WAIT_H 27933965Sjdp#include <sys/wait.h> 28038889Sjdp#else /* ! HAVE_SYS_WAIT_H */ 28138889Sjdp#if ! defined (_WIN32) || defined (__CYGWIN32__) 28233965Sjdp#ifndef WIFEXITED 283130561Sobrien#define WIFEXITED(w) (((w) & 0377) == 0) 28433965Sjdp#endif 28533965Sjdp#ifndef WIFSIGNALED 286130561Sobrien#define WIFSIGNALED(w) (((w) & 0377) != 0177 && ((w) & ~0377) == 0) 28733965Sjdp#endif 28833965Sjdp#ifndef WTERMSIG 28933965Sjdp#define WTERMSIG(w) ((w) & 0177) 29033965Sjdp#endif 29133965Sjdp#ifndef WEXITSTATUS 29233965Sjdp#define WEXITSTATUS(w) (((w) >> 8) & 0377) 29333965Sjdp#endif 29438889Sjdp#else /* defined (_WIN32) && ! defined (__CYGWIN32__) */ 29538889Sjdp#ifndef WIFEXITED 29638889Sjdp#define WIFEXITED(w) (((w) & 0xff) == 0) 29733965Sjdp#endif 29838889Sjdp#ifndef WIFSIGNALED 29938889Sjdp#define WIFSIGNALED(w) (((w) & 0xff) != 0 && ((w) & 0xff) != 0x7f) 30033965Sjdp#endif 30138889Sjdp#ifndef WTERMSIG 30238889Sjdp#define WTERMSIG(w) ((w) & 0x7f) 30338889Sjdp#endif 30438889Sjdp#ifndef WEXITSTATUS 30538889Sjdp#define WEXITSTATUS(w) (((w) & 0xff00) >> 8) 30638889Sjdp#endif 30738889Sjdp#endif /* defined (_WIN32) && ! defined (__CYGWIN32__) */ 30838889Sjdp#endif /* ! HAVE_SYS_WAIT_H */ 30933965Sjdp 31060484Sobrien/* ifunc and ihead data structures: ttk@cygnus.com 1997 31133965Sjdp 31260484Sobrien When IMPORT declarations are encountered in a .def file the 31360484Sobrien function import information is stored in a structure referenced by 31460484Sobrien the global variable IMPORT_LIST. The structure is a linked list 31560484Sobrien containing the names of the dll files each function is imported 31660484Sobrien from and a linked list of functions being imported from that dll 31760484Sobrien file. This roughly parallels the structure of the .idata section 31860484Sobrien in the PE object file. 31960484Sobrien 32060484Sobrien The contents of .def file are interpreted from within the 32160484Sobrien process_def_file function. Every time an IMPORT declaration is 32260484Sobrien encountered, it is broken up into its component parts and passed to 32360484Sobrien def_import. IMPORT_LIST is initialized to NULL in function main. */ 32460484Sobrien 32560484Sobrientypedef struct ifunct 32660484Sobrien{ 327130561Sobrien char * name; /* Name of function being imported. */ 328130561Sobrien int ord; /* Two-byte ordinal value associated with function. */ 32960484Sobrien struct ifunct *next; 33060484Sobrien} ifunctype; 33160484Sobrien 33260484Sobrientypedef struct iheadt 33360484Sobrien{ 334130561Sobrien char *dllname; /* Name of dll file imported from. */ 335130561Sobrien long nfuncs; /* Number of functions in list. */ 336130561Sobrien struct ifunct *funchead; /* First function in list. */ 337130561Sobrien struct ifunct *functail; /* Last function in list. */ 338130561Sobrien struct iheadt *next; /* Next dll file in list. */ 33960484Sobrien} iheadtype; 34060484Sobrien 34160484Sobrien/* Structure containing all import information as defined in .def file 34260484Sobrien (qv "ihead structure"). */ 34360484Sobrien 34460484Sobrienstatic iheadtype *import_list = NULL; 34560484Sobrien 34660484Sobrienstatic char *as_name = NULL; 34760484Sobrienstatic char * as_flags = ""; 34860484Sobrien 349130561Sobrienstatic char *tmp_prefix; 350130561Sobrien 35133965Sjdpstatic int no_idata4; 35233965Sjdpstatic int no_idata5; 35333965Sjdpstatic char *exp_name; 35433965Sjdpstatic char *imp_name; 35533965Sjdpstatic char *head_label; 35633965Sjdpstatic char *imp_name_lab; 35733965Sjdpstatic char *dll_name; 35833965Sjdp 35933965Sjdpstatic int add_indirect = 0; 36033965Sjdpstatic int add_underscore = 0; 361218822Sdimstatic int add_stdcall_underscore = 0; 36233965Sjdpstatic int dontdeltemps = 0; 36333965Sjdp 364130561Sobrien/* TRUE if we should export all symbols. Otherwise, we only export 36560484Sobrien symbols listed in .drectve sections or in the def file. */ 366130561Sobrienstatic bfd_boolean export_all_symbols; 36760484Sobrien 368130561Sobrien/* TRUE if we should exclude the symbols in DEFAULT_EXCLUDES when 36960484Sobrien exporting all symbols. */ 370130561Sobrienstatic bfd_boolean do_default_excludes = TRUE; 37160484Sobrien 37260484Sobrien/* Default symbols to exclude when exporting all the symbols. */ 37360484Sobrienstatic const char *default_excludes = "DllMain@12,DllEntryPoint@0,impure_ptr"; 37460484Sobrien 375130561Sobrien/* TRUE if we should add __imp_<SYMBOL> to import libraries for backward 37660484Sobrien compatibility to old Cygwin releases. */ 377130561Sobrienstatic bfd_boolean create_compat_implib; 37860484Sobrien 37933965Sjdpstatic char *def_file; 38033965Sjdp 38160484Sobrienextern char * program_name; 38233965Sjdp 38333965Sjdpstatic int machine; 38438889Sjdpstatic int killat; 38560484Sobrienstatic int add_stdcall_alias; 386218822Sdimstatic const char *ext_prefix_alias; 38733965Sjdpstatic int verbose; 38838889Sjdpstatic FILE *output_def; 38938889Sjdpstatic FILE *base_file; 39033965Sjdp 391218822Sdim#ifdef DLLTOOL_DEFAULT_ARM 39238889Sjdpstatic const char *mname = "arm"; 39333965Sjdp#endif 394218822Sdim 395218822Sdim#ifdef DLLTOOL_DEFAULT_ARM_EPOC 396218822Sdimstatic const char *mname = "arm-epoc"; 39777298Sobrien#endif 39833965Sjdp 399218822Sdim#ifdef DLLTOOL_DEFAULT_ARM_WINCE 400218822Sdimstatic const char *mname = "arm-wince"; 401218822Sdim#endif 402218822Sdim 403218822Sdim#ifdef DLLTOOL_DEFAULT_I386 40438889Sjdpstatic const char *mname = "i386"; 40533965Sjdp#endif 40633965Sjdp 407218822Sdim#ifdef DLLTOOL_DEFAULT_MX86_64 408218822Sdimstatic const char *mname = "i386:x86-64"; 409218822Sdim#endif 410218822Sdim 411218822Sdim#ifdef DLLTOOL_DEFAULT_PPC 41238889Sjdpstatic const char *mname = "ppc"; 41333965Sjdp#endif 41433965Sjdp 415218822Sdim#ifdef DLLTOOL_DEFAULT_SH 41660484Sobrienstatic const char *mname = "sh"; 41760484Sobrien#endif 41860484Sobrien 419218822Sdim#ifdef DLLTOOL_DEFAULT_MIPS 42060484Sobrienstatic const char *mname = "mips"; 42160484Sobrien#endif 42260484Sobrien 423218822Sdim#ifdef DLLTOOL_DEFAULT_MCORE 42460484Sobrienstatic const char * mname = "mcore-le"; 42560484Sobrien#endif 42660484Sobrien 427218822Sdim#ifdef DLLTOOL_DEFAULT_MCORE_ELF 42860484Sobrienstatic const char * mname = "mcore-elf"; 42960484Sobrienstatic char * mcore_elf_out_file = NULL; 43060484Sobrienstatic char * mcore_elf_linker = NULL; 43160484Sobrienstatic char * mcore_elf_linker_flags = NULL; 43260484Sobrien 43360484Sobrien#define DRECTVE_SECTION_NAME ((machine == MMCORE_ELF || machine == MMCORE_ELF_LE) ? ".exports" : ".drectve") 43460484Sobrien#endif 43560484Sobrien 43660484Sobrien#ifndef DRECTVE_SECTION_NAME 43760484Sobrien#define DRECTVE_SECTION_NAME ".drectve" 43860484Sobrien#endif 43960484Sobrien 440218822Sdim/* What's the right name for this ? */ 441218822Sdim#define PATHMAX 250 44233965Sjdp 443218822Sdim/* External name alias numbering starts here. */ 444218822Sdim#define PREFIX_ALIAS_BASE 20000 445218822Sdim 446130561Sobrienchar *tmp_asm_buf; 447130561Sobrienchar *tmp_head_s_buf; 448130561Sobrienchar *tmp_head_o_buf; 449130561Sobrienchar *tmp_tail_s_buf; 450130561Sobrienchar *tmp_tail_o_buf; 451130561Sobrienchar *tmp_stub_buf; 45260484Sobrien 453130561Sobrien#define TMP_ASM dlltmp (&tmp_asm_buf, "%sc.s") 454130561Sobrien#define TMP_HEAD_S dlltmp (&tmp_head_s_buf, "%sh.s") 455130561Sobrien#define TMP_HEAD_O dlltmp (&tmp_head_o_buf, "%sh.o") 456130561Sobrien#define TMP_TAIL_S dlltmp (&tmp_tail_s_buf, "%st.s") 457130561Sobrien#define TMP_TAIL_O dlltmp (&tmp_tail_o_buf, "%st.o") 458130561Sobrien#define TMP_STUB dlltmp (&tmp_stub_buf, "%ss") 459130561Sobrien 460130561Sobrien/* This bit of assembly does jmp * .... */ 46138889Sjdpstatic const unsigned char i386_jtab[] = 46238889Sjdp{ 46338889Sjdp 0xff, 0x25, 0x00, 0x00, 0x00, 0x00, 0x90, 0x90 46438889Sjdp}; 46533965Sjdp 46638889Sjdpstatic const unsigned char arm_jtab[] = 46738889Sjdp{ 46860484Sobrien 0x00, 0xc0, 0x9f, 0xe5, /* ldr ip, [pc] */ 46960484Sobrien 0x00, 0xf0, 0x9c, 0xe5, /* ldr pc, [ip] */ 47038889Sjdp 0, 0, 0, 0 47138889Sjdp}; 47233965Sjdp 47360484Sobrienstatic const unsigned char arm_interwork_jtab[] = 47460484Sobrien{ 47560484Sobrien 0x04, 0xc0, 0x9f, 0xe5, /* ldr ip, [pc] */ 47660484Sobrien 0x00, 0xc0, 0x9c, 0xe5, /* ldr ip, [ip] */ 47760484Sobrien 0x1c, 0xff, 0x2f, 0xe1, /* bx ip */ 47860484Sobrien 0, 0, 0, 0 47960484Sobrien}; 48060484Sobrien 48160484Sobrienstatic const unsigned char thumb_jtab[] = 48260484Sobrien{ 48360484Sobrien 0x40, 0xb4, /* push {r6} */ 48460484Sobrien 0x02, 0x4e, /* ldr r6, [pc, #8] */ 48560484Sobrien 0x36, 0x68, /* ldr r6, [r6] */ 48660484Sobrien 0xb4, 0x46, /* mov ip, r6 */ 48760484Sobrien 0x40, 0xbc, /* pop {r6} */ 48860484Sobrien 0x60, 0x47, /* bx ip */ 48960484Sobrien 0, 0, 0, 0 49060484Sobrien}; 49160484Sobrien 49260484Sobrienstatic const unsigned char mcore_be_jtab[] = 49360484Sobrien{ 49460484Sobrien 0x71, 0x02, /* lrw r1,2 */ 495104834Sobrien 0x81, 0x01, /* ld.w r1,(r1,0) */ 49660484Sobrien 0x00, 0xC1, /* jmp r1 */ 49760484Sobrien 0x12, 0x00, /* nop */ 498104834Sobrien 0x00, 0x00, 0x00, 0x00 /* <address> */ 49960484Sobrien}; 50060484Sobrien 50160484Sobrienstatic const unsigned char mcore_le_jtab[] = 50260484Sobrien{ 50360484Sobrien 0x02, 0x71, /* lrw r1,2 */ 504104834Sobrien 0x01, 0x81, /* ld.w r1,(r1,0) */ 50560484Sobrien 0xC1, 0x00, /* jmp r1 */ 50660484Sobrien 0x00, 0x12, /* nop */ 507104834Sobrien 0x00, 0x00, 0x00, 0x00 /* <address> */ 50860484Sobrien}; 50960484Sobrien 510130561Sobrien/* This is the glue sequence for PowerPC PE. There is a 511130561Sobrien tocrel16-tocdefn reloc against the first instruction. 512130561Sobrien We also need a IMGLUE reloc against the glue function 513130561Sobrien to restore the toc saved by the third instruction in 514130561Sobrien the glue. */ 51560484Sobrienstatic const unsigned char ppc_jtab[] = 51660484Sobrien{ 51733965Sjdp 0x00, 0x00, 0x62, 0x81, /* lwz r11,0(r2) */ 51833965Sjdp /* Reloc TOCREL16 __imp_xxx */ 51933965Sjdp 0x00, 0x00, 0x8B, 0x81, /* lwz r12,0(r11) */ 52033965Sjdp 0x04, 0x00, 0x41, 0x90, /* stw r2,4(r1) */ 52133965Sjdp 0xA6, 0x03, 0x89, 0x7D, /* mtctr r12 */ 52233965Sjdp 0x04, 0x00, 0x4B, 0x80, /* lwz r2,4(r11) */ 52333965Sjdp 0x20, 0x04, 0x80, 0x4E /* bctr */ 52433965Sjdp}; 52533965Sjdp 52638889Sjdp#ifdef DLLTOOL_PPC 527130561Sobrien/* The glue instruction, picks up the toc from the stw in 528130561Sobrien the above code: "lwz r2,4(r1)". */ 52938889Sjdpstatic bfd_vma ppc_glue_insn = 0x80410004; 53038889Sjdp#endif 53133965Sjdp 53233965Sjdpstruct mac 53333965Sjdp { 53438889Sjdp const char *type; 53538889Sjdp const char *how_byte; 53638889Sjdp const char *how_short; 53738889Sjdp const char *how_long; 53838889Sjdp const char *how_asciz; 53938889Sjdp const char *how_comment; 54038889Sjdp const char *how_jump; 54138889Sjdp const char *how_global; 54238889Sjdp const char *how_space; 54338889Sjdp const char *how_align_short; 54438889Sjdp const char *how_align_long; 54560484Sobrien const char *how_default_as_switches; 54638889Sjdp const char *how_bfd_target; 54733965Sjdp enum bfd_architecture how_bfd_arch; 54838889Sjdp const unsigned char *how_jtab; 549130561Sobrien int how_jtab_size; /* Size of the jtab entry. */ 550130561Sobrien int how_jtab_roff; /* Offset into it for the ind 32 reloc into idata 5. */ 55138889Sjdp }; 55238889Sjdp 55360484Sobrienstatic const struct mac 55460484Sobrienmtable[] = 55533965Sjdp{ 55633965Sjdp { 55733965Sjdp#define MARM 0 55860484Sobrien "arm", ".byte", ".short", ".long", ".asciz", "@", 55933965Sjdp "ldr\tip,[pc]\n\tldr\tpc,[ip]\n\t.long", 56060484Sobrien ".global", ".space", ".align\t2",".align\t4", "-mapcs-32", 56160484Sobrien "pe-arm-little", bfd_arch_arm, 56260484Sobrien arm_jtab, sizeof (arm_jtab), 8 56333965Sjdp } 56433965Sjdp , 56533965Sjdp { 56633965Sjdp#define M386 1 56760484Sobrien "i386", ".byte", ".short", ".long", ".asciz", "#", 56860484Sobrien "jmp *", ".global", ".space", ".align\t2",".align\t4", "", 56960484Sobrien "pe-i386",bfd_arch_i386, 57060484Sobrien i386_jtab, sizeof (i386_jtab), 2 57133965Sjdp } 57233965Sjdp , 57333965Sjdp { 57433965Sjdp#define MPPC 2 57560484Sobrien "ppc", ".byte", ".short", ".long", ".asciz", "#", 57660484Sobrien "jmp *", ".global", ".space", ".align\t2",".align\t4", "", 57760484Sobrien "pe-powerpcle",bfd_arch_powerpc, 57860484Sobrien ppc_jtab, sizeof (ppc_jtab), 0 57933965Sjdp } 58033965Sjdp , 58160484Sobrien { 58260484Sobrien#define MTHUMB 3 58360484Sobrien "thumb", ".byte", ".short", ".long", ".asciz", "@", 58460484Sobrien "push\t{r6}\n\tldr\tr6, [pc, #8]\n\tldr\tr6, [r6]\n\tmov\tip, r6\n\tpop\t{r6}\n\tbx\tip", 58560484Sobrien ".global", ".space", ".align\t2",".align\t4", "-mthumb-interwork", 58660484Sobrien "pe-arm-little", bfd_arch_arm, 58760484Sobrien thumb_jtab, sizeof (thumb_jtab), 12 58860484Sobrien } 58960484Sobrien , 59060484Sobrien#define MARM_INTERWORK 4 59160484Sobrien { 59260484Sobrien "arm_interwork", ".byte", ".short", ".long", ".asciz", "@", 59360484Sobrien "ldr\tip,[pc]\n\tldr\tip,[ip]\n\tbx\tip\n\t.long", 59460484Sobrien ".global", ".space", ".align\t2",".align\t4", "-mthumb-interwork", 59560484Sobrien "pe-arm-little", bfd_arch_arm, 59660484Sobrien arm_interwork_jtab, sizeof (arm_interwork_jtab), 12 59760484Sobrien } 59860484Sobrien , 59960484Sobrien { 60060484Sobrien#define MMCORE_BE 5 60160484Sobrien "mcore-be", ".byte", ".short", ".long", ".asciz", "//", 60260484Sobrien "lrw r1,[1f]\n\tld.w r1,(r1,0)\n\tjmp r1\n\tnop\n1:.long", 60360484Sobrien ".global", ".space", ".align\t2",".align\t4", "", 60460484Sobrien "pe-mcore-big", bfd_arch_mcore, 60560484Sobrien mcore_be_jtab, sizeof (mcore_be_jtab), 8 60660484Sobrien } 60760484Sobrien , 60860484Sobrien { 60960484Sobrien#define MMCORE_LE 6 61060484Sobrien "mcore-le", ".byte", ".short", ".long", ".asciz", "//", 61160484Sobrien "lrw r1,[1f]\n\tld.w r1,(r1,0)\n\tjmp r1\n\tnop\n1:.long", 61260484Sobrien ".global", ".space", ".align\t2",".align\t4", "-EL", 61360484Sobrien "pe-mcore-little", bfd_arch_mcore, 61460484Sobrien mcore_le_jtab, sizeof (mcore_le_jtab), 8 61560484Sobrien } 61660484Sobrien , 61760484Sobrien { 61860484Sobrien#define MMCORE_ELF 7 61960484Sobrien "mcore-elf-be", ".byte", ".short", ".long", ".asciz", "//", 62060484Sobrien "lrw r1,[1f]\n\tld.w r1,(r1,0)\n\tjmp r1\n\tnop\n1:.long", 62160484Sobrien ".global", ".space", ".align\t2",".align\t4", "", 62260484Sobrien "elf32-mcore-big", bfd_arch_mcore, 62360484Sobrien mcore_be_jtab, sizeof (mcore_be_jtab), 8 62460484Sobrien } 62560484Sobrien , 62660484Sobrien { 62760484Sobrien#define MMCORE_ELF_LE 8 62860484Sobrien "mcore-elf-le", ".byte", ".short", ".long", ".asciz", "//", 62960484Sobrien "lrw r1,[1f]\n\tld.w r1,(r1,0)\n\tjmp r1\n\tnop\n1:.long", 63060484Sobrien ".global", ".space", ".align\t2",".align\t4", "-EL", 63160484Sobrien "elf32-mcore-little", bfd_arch_mcore, 63260484Sobrien mcore_le_jtab, sizeof (mcore_le_jtab), 8 63360484Sobrien } 63460484Sobrien , 63560484Sobrien { 63660484Sobrien#define MARM_EPOC 9 63777298Sobrien "arm-epoc", ".byte", ".short", ".long", ".asciz", "@", 63860484Sobrien "ldr\tip,[pc]\n\tldr\tpc,[ip]\n\t.long", 63960484Sobrien ".global", ".space", ".align\t2",".align\t4", "", 64060484Sobrien "epoc-pe-arm-little", bfd_arch_arm, 64160484Sobrien arm_jtab, sizeof (arm_jtab), 8 64260484Sobrien } 64360484Sobrien , 644218822Sdim { 645218822Sdim#define MARM_WINCE 10 646218822Sdim "arm-wince", ".byte", ".short", ".long", ".asciz", "@", 647218822Sdim "ldr\tip,[pc]\n\tldr\tpc,[ip]\n\t.long", 648218822Sdim ".global", ".space", ".align\t2",".align\t4", "-mapcs-32", 649218822Sdim "pe-arm-wince-little", bfd_arch_arm, 650218822Sdim arm_jtab, sizeof (arm_jtab), 8 651218822Sdim } 652218822Sdim , 653218822Sdim { 654218822Sdim#define MX86 11 655218822Sdim "i386:x86-64", ".byte", ".short", ".long", ".asciz", "#", 656218822Sdim "jmp *", ".global", ".space", ".align\t2",".align\t4", "", 657218822Sdim "pe-x86-64",bfd_arch_i386, 658218822Sdim i386_jtab, sizeof (i386_jtab), 2 659218822Sdim } 660218822Sdim , 66160484Sobrien { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } 66233965Sjdp}; 66333965Sjdp 66438889Sjdptypedef struct dlist 66538889Sjdp{ 66638889Sjdp char *text; 66738889Sjdp struct dlist *next; 66838889Sjdp} 66938889Sjdpdlist_type; 67033965Sjdp 67138889Sjdptypedef struct export 67238889Sjdp { 67338889Sjdp const char *name; 67438889Sjdp const char *internal_name; 675218822Sdim const char *import_name; 67638889Sjdp int ordinal; 67738889Sjdp int constant; 678130561Sobrien int noname; /* Don't put name in image file. */ 679130561Sobrien int private; /* Don't put reference in import lib. */ 68038889Sjdp int data; 68138889Sjdp int hint; 682130561Sobrien int forward; /* Number of forward label, 0 means no forward. */ 68338889Sjdp struct export *next; 68438889Sjdp } 68538889Sjdpexport_type; 68638889Sjdp 68760484Sobrien/* A list of symbols which we should not export. */ 688104834Sobrien 68960484Sobrienstruct string_list 69060484Sobrien{ 69160484Sobrien struct string_list *next; 69260484Sobrien char *string; 69360484Sobrien}; 69460484Sobrien 69560484Sobrienstatic struct string_list *excludes; 69660484Sobrien 697130561Sobrienstatic const char *rvaafter (int); 698130561Sobrienstatic const char *rvabefore (int); 699218822Sdimstatic const char *asm_prefix (int, const char *); 700130561Sobrienstatic void process_def_file (const char *); 701130561Sobrienstatic void new_directive (char *); 702130561Sobrienstatic void append_import (const char *, const char *, int); 703130561Sobrienstatic void run (const char *, char *); 704130561Sobrienstatic void scan_drectve_symbols (bfd *); 705130561Sobrienstatic void scan_filtered_symbols (bfd *, void *, long, unsigned int); 706130561Sobrienstatic void add_excludes (const char *); 707130561Sobrienstatic bfd_boolean match_exclude (const char *); 708130561Sobrienstatic void set_default_excludes (void); 709130561Sobrienstatic long filter_symbols (bfd *, void *, long, unsigned int); 710130561Sobrienstatic void scan_all_symbols (bfd *); 711130561Sobrienstatic void scan_open_obj_file (bfd *); 712130561Sobrienstatic void scan_obj_file (const char *); 713130561Sobrienstatic void dump_def_info (FILE *); 714130561Sobrienstatic int sfunc (const void *, const void *); 715130561Sobrienstatic void flush_page (FILE *, long *, int, int); 716130561Sobrienstatic void gen_def_file (void); 717130561Sobrienstatic void generate_idata_ofile (FILE *); 718130561Sobrienstatic void assemble_file (const char *, const char *); 719130561Sobrienstatic void gen_exp_file (void); 720130561Sobrienstatic const char *xlate (const char *); 721130561Sobrienstatic char *make_label (const char *, const char *); 722130561Sobrienstatic char *make_imp_label (const char *, const char *); 723130561Sobrienstatic bfd *make_one_lib_file (export_type *, int); 724130561Sobrienstatic bfd *make_head (void); 725130561Sobrienstatic bfd *make_tail (void); 726130561Sobrienstatic void gen_lib_file (void); 727130561Sobrienstatic int pfunc (const void *, const void *); 728130561Sobrienstatic int nfunc (const void *, const void *); 729130561Sobrienstatic void remove_null_names (export_type **); 730130561Sobrienstatic void process_duplicates (export_type **); 731130561Sobrienstatic void fill_ordinals (export_type **); 732130561Sobrienstatic void mangle_defs (void); 733130561Sobrienstatic void usage (FILE *, int); 734218822Sdimstatic void inform (const char *, ...) ATTRIBUTE_PRINTF_1; 735218822Sdimstatic void set_dll_name_from_def (const char *); 73638889Sjdp 737130561Sobrienstatic char * 738130561Sobrienprefix_encode (char *start, unsigned code) 739130561Sobrien{ 740130561Sobrien static char alpha[26] = "abcdefghijklmnopqrstuvwxyz"; 741130561Sobrien static char buf[32]; 742130561Sobrien char *p; 743130561Sobrien strcpy (buf, start); 744130561Sobrien p = strchr (buf, '\0'); 745130561Sobrien do 746130561Sobrien *p++ = alpha[code % sizeof (alpha)]; 747130561Sobrien while ((code /= sizeof (alpha)) != 0); 748130561Sobrien *p = '\0'; 749130561Sobrien return buf; 750130561Sobrien} 75160484Sobrien 752130561Sobrienstatic char * 753130561Sobriendlltmp (char **buf, const char *fmt) 754130561Sobrien{ 755130561Sobrien if (!*buf) 756130561Sobrien { 757130561Sobrien *buf = malloc (strlen (tmp_prefix) + 64); 758130561Sobrien sprintf (*buf, fmt, tmp_prefix); 759130561Sobrien } 760130561Sobrien return *buf; 761130561Sobrien} 762130561Sobrien 76360484Sobrienstatic void 764130561Sobrieninform VPARAMS ((const char * message, ...)) 76560484Sobrien{ 76699461Sobrien VA_OPEN (args, message); 76799461Sobrien VA_FIXEDARG (args, const char *, message); 76899461Sobrien 76960484Sobrien if (!verbose) 77060484Sobrien return; 77160484Sobrien 77299461Sobrien report (message, args); 77360484Sobrien 77499461Sobrien VA_CLOSE (args); 77560484Sobrien} 77660484Sobrien 77738889Sjdpstatic const char * 778130561Sobrienrvaafter (int machine) 77933965Sjdp{ 78033965Sjdp switch (machine) 78133965Sjdp { 78233965Sjdp case MARM: 78333965Sjdp case M386: 784218822Sdim case MX86: 78533965Sjdp case MPPC: 78660484Sobrien case MTHUMB: 78760484Sobrien case MARM_INTERWORK: 78860484Sobrien case MMCORE_BE: 78960484Sobrien case MMCORE_LE: 79060484Sobrien case MMCORE_ELF: 79160484Sobrien case MMCORE_ELF_LE: 79277298Sobrien case MARM_EPOC: 793218822Sdim case MARM_WINCE: 79460484Sobrien break; 79560484Sobrien default: 79660484Sobrien /* xgettext:c-format */ 79760484Sobrien fatal (_("Internal error: Unknown machine type: %d"), machine); 79860484Sobrien break; 79933965Sjdp } 80038889Sjdp return ""; 80133965Sjdp} 80233965Sjdp 80338889Sjdpstatic const char * 804130561Sobrienrvabefore (int machine) 80533965Sjdp{ 80633965Sjdp switch (machine) 80733965Sjdp { 80833965Sjdp case MARM: 80933965Sjdp case M386: 810218822Sdim case MX86: 81133965Sjdp case MPPC: 81260484Sobrien case MTHUMB: 81360484Sobrien case MARM_INTERWORK: 81460484Sobrien case MMCORE_BE: 81560484Sobrien case MMCORE_LE: 81660484Sobrien case MMCORE_ELF: 81760484Sobrien case MMCORE_ELF_LE: 81877298Sobrien case MARM_EPOC: 819218822Sdim case MARM_WINCE: 82033965Sjdp return ".rva\t"; 82160484Sobrien default: 82260484Sobrien /* xgettext:c-format */ 82360484Sobrien fatal (_("Internal error: Unknown machine type: %d"), machine); 82460484Sobrien break; 82533965Sjdp } 82638889Sjdp return ""; 82733965Sjdp} 82833965Sjdp 82938889Sjdpstatic const char * 830218822Sdimasm_prefix (int machine, const char *name) 83133965Sjdp{ 83233965Sjdp switch (machine) 83333965Sjdp { 83433965Sjdp case MARM: 83560484Sobrien case MPPC: 83660484Sobrien case MTHUMB: 83760484Sobrien case MARM_INTERWORK: 83860484Sobrien case MMCORE_BE: 83960484Sobrien case MMCORE_LE: 84060484Sobrien case MMCORE_ELF: 84160484Sobrien case MMCORE_ELF_LE: 84277298Sobrien case MARM_EPOC: 843218822Sdim case MARM_WINCE: 84460484Sobrien break; 84533965Sjdp case M386: 846218822Sdim case MX86: 847218822Sdim /* Symbol names starting with ? do not have a leading underscore. */ 848218822Sdim if (name && *name == '?') 849218822Sdim break; 850218822Sdim else 851218822Sdim return "_"; 85260484Sobrien default: 85360484Sobrien /* xgettext:c-format */ 85460484Sobrien fatal (_("Internal error: Unknown machine type: %d"), machine); 85560484Sobrien break; 85633965Sjdp } 85738889Sjdp return ""; 85833965Sjdp} 85938889Sjdp 860218822Sdim#define ASM_BYTE mtable[machine].how_byte 861218822Sdim#define ASM_SHORT mtable[machine].how_short 862218822Sdim#define ASM_LONG mtable[machine].how_long 863218822Sdim#define ASM_TEXT mtable[machine].how_asciz 864218822Sdim#define ASM_C mtable[machine].how_comment 865218822Sdim#define ASM_JUMP mtable[machine].how_jump 866218822Sdim#define ASM_GLOBAL mtable[machine].how_global 867218822Sdim#define ASM_SPACE mtable[machine].how_space 868218822Sdim#define ASM_ALIGN_SHORT mtable[machine].how_align_short 869218822Sdim#define ASM_RVA_BEFORE rvabefore (machine) 870218822Sdim#define ASM_RVA_AFTER rvaafter (machine) 871218822Sdim#define ASM_PREFIX(NAME) asm_prefix (machine, (NAME)) 872218822Sdim#define ASM_ALIGN_LONG mtable[machine].how_align_long 873218822Sdim#define HOW_BFD_READ_TARGET 0 /* Always default. */ 874218822Sdim#define HOW_BFD_WRITE_TARGET mtable[machine].how_bfd_target 875218822Sdim#define HOW_BFD_ARCH mtable[machine].how_bfd_arch 876218822Sdim#define HOW_JTAB mtable[machine].how_jtab 877218822Sdim#define HOW_JTAB_SIZE mtable[machine].how_jtab_size 878218822Sdim#define HOW_JTAB_ROFF mtable[machine].how_jtab_roff 879218822Sdim#define ASM_SWITCHES mtable[machine].how_default_as_switches 88060484Sobrien 88133965Sjdpstatic char **oav; 88233965Sjdp 88399461Sobrienstatic void 884130561Sobrienprocess_def_file (const char *name) 88533965Sjdp{ 88633965Sjdp FILE *f = fopen (name, FOPEN_RT); 887104834Sobrien 88833965Sjdp if (!f) 88960484Sobrien /* xgettext:c-format */ 89060484Sobrien fatal (_("Can't open def file: %s"), name); 89133965Sjdp 89233965Sjdp yyin = f; 89333965Sjdp 89460484Sobrien /* xgettext:c-format */ 89560484Sobrien inform (_("Processing def file: %s"), name); 896104834Sobrien 89733965Sjdp yyparse (); 89860484Sobrien 89960484Sobrien inform (_("Processed def file")); 90033965Sjdp} 90133965Sjdp 90233965Sjdp/**********************************************************************/ 90333965Sjdp 904130561Sobrien/* Communications with the parser. */ 90533965Sjdp 906130561Sobrienstatic int d_nfuncs; /* Number of functions exported. */ 907130561Sobrienstatic int d_named_nfuncs; /* Number of named functions exported. */ 908130561Sobrienstatic int d_low_ord; /* Lowest ordinal index. */ 909130561Sobrienstatic int d_high_ord; /* Highest ordinal index. */ 910130561Sobrienstatic export_type *d_exports; /* List of exported functions. */ 911130561Sobrienstatic export_type **d_exports_lexically; /* Vector of exported functions in alpha order. */ 912130561Sobrienstatic dlist_type *d_list; /* Descriptions. */ 913130561Sobrienstatic dlist_type *a_list; /* Stuff to go in directives. */ 914130561Sobrienstatic int d_nforwards = 0; /* Number of forwarded exports. */ 91533965Sjdp 91633965Sjdpstatic int d_is_dll; 91733965Sjdpstatic int d_is_exe; 91833965Sjdp 91960484Sobrienint 920130561Sobrienyyerror (const char * err ATTRIBUTE_UNUSED) 92133965Sjdp{ 92260484Sobrien /* xgettext:c-format */ 92360484Sobrien non_fatal (_("Syntax error in def file %s:%d"), def_file, linenumber); 924104834Sobrien 92533965Sjdp return 0; 92633965Sjdp} 92733965Sjdp 92833965Sjdpvoid 929130561Sobriendef_exports (const char *name, const char *internal_name, int ordinal, 930130561Sobrien int noname, int constant, int data, int private) 93133965Sjdp{ 93233965Sjdp struct export *p = (struct export *) xmalloc (sizeof (*p)); 93333965Sjdp 93433965Sjdp p->name = name; 93533965Sjdp p->internal_name = internal_name ? internal_name : name; 936218822Sdim p->import_name = name; 93733965Sjdp p->ordinal = ordinal; 93833965Sjdp p->constant = constant; 93933965Sjdp p->noname = noname; 940130561Sobrien p->private = private; 94138889Sjdp p->data = data; 94233965Sjdp p->next = d_exports; 94333965Sjdp d_exports = p; 94433965Sjdp d_nfuncs++; 945104834Sobrien 946104834Sobrien if ((internal_name != NULL) 94789857Sobrien && (strchr (internal_name, '.') != NULL)) 94889857Sobrien p->forward = ++d_nforwards; 94989857Sobrien else 95089857Sobrien p->forward = 0; /* no forward */ 95133965Sjdp} 95233965Sjdp 953218822Sdimstatic void 954218822Sdimset_dll_name_from_def (const char * name) 955218822Sdim{ 956218822Sdim const char* image_basename = lbasename (name); 957218822Sdim if (image_basename != name) 958218822Sdim non_fatal (_("%s: Path components stripped from image name, '%s'."), 959218822Sdim def_file, name); 960218822Sdim dll_name = xstrdup (image_basename); 961218822Sdim} 962218822Sdim 96333965Sjdpvoid 964130561Sobriendef_name (const char *name, int base) 96533965Sjdp{ 96660484Sobrien /* xgettext:c-format */ 96760484Sobrien inform (_("NAME: %s base: %x"), name, base); 968104834Sobrien 96933965Sjdp if (d_is_dll) 97060484Sobrien non_fatal (_("Can't have LIBRARY and NAME")); 971104834Sobrien 972130561Sobrien /* If --dllname not provided, use the one in the DEF file. 973130561Sobrien FIXME: Is this appropriate for executables? */ 97460484Sobrien if (! dll_name) 975218822Sdim set_dll_name_from_def (name); 97633965Sjdp d_is_exe = 1; 97733965Sjdp} 97833965Sjdp 97933965Sjdpvoid 980130561Sobriendef_library (const char *name, int base) 98133965Sjdp{ 98260484Sobrien /* xgettext:c-format */ 98360484Sobrien inform (_("LIBRARY: %s base: %x"), name, base); 984104834Sobrien 98533965Sjdp if (d_is_exe) 98660484Sobrien non_fatal (_("Can't have LIBRARY and NAME")); 987104834Sobrien 988130561Sobrien /* If --dllname not provided, use the one in the DEF file. */ 98960484Sobrien if (! dll_name) 990218822Sdim set_dll_name_from_def (name); 99133965Sjdp d_is_dll = 1; 99233965Sjdp} 99333965Sjdp 99433965Sjdpvoid 995130561Sobriendef_description (const char *desc) 99633965Sjdp{ 99733965Sjdp dlist_type *d = (dlist_type *) xmalloc (sizeof (dlist_type)); 99838889Sjdp d->text = xstrdup (desc); 99933965Sjdp d->next = d_list; 100033965Sjdp d_list = d; 100133965Sjdp} 100233965Sjdp 100399461Sobrienstatic void 1004130561Sobriennew_directive (char *dir) 100533965Sjdp{ 100633965Sjdp dlist_type *d = (dlist_type *) xmalloc (sizeof (dlist_type)); 100738889Sjdp d->text = xstrdup (dir); 100833965Sjdp d->next = a_list; 100933965Sjdp a_list = d; 101033965Sjdp} 101133965Sjdp 101233965Sjdpvoid 1013130561Sobriendef_heapsize (int reserve, int commit) 101433965Sjdp{ 101533965Sjdp char b[200]; 101633965Sjdp if (commit > 0) 101760484Sobrien sprintf (b, "-heap 0x%x,0x%x ", reserve, commit); 101833965Sjdp else 101960484Sobrien sprintf (b, "-heap 0x%x ", reserve); 102038889Sjdp new_directive (xstrdup (b)); 102133965Sjdp} 102233965Sjdp 102333965Sjdpvoid 1024130561Sobriendef_stacksize (int reserve, int commit) 102533965Sjdp{ 102633965Sjdp char b[200]; 102733965Sjdp if (commit > 0) 102860484Sobrien sprintf (b, "-stack 0x%x,0x%x ", reserve, commit); 102933965Sjdp else 103060484Sobrien sprintf (b, "-stack 0x%x ", reserve); 103138889Sjdp new_directive (xstrdup (b)); 103233965Sjdp} 103333965Sjdp 103460484Sobrien/* append_import simply adds the given import definition to the global 103560484Sobrien import_list. It is used by def_import. */ 103660484Sobrien 103760484Sobrienstatic void 1038130561Sobrienappend_import (const char *symbol_name, const char *dll_name, int func_ordinal) 103960484Sobrien{ 104060484Sobrien iheadtype **pq; 104160484Sobrien iheadtype *q; 104260484Sobrien 104360484Sobrien for (pq = &import_list; *pq != NULL; pq = &(*pq)->next) 104460484Sobrien { 104560484Sobrien if (strcmp ((*pq)->dllname, dll_name) == 0) 104660484Sobrien { 104760484Sobrien q = *pq; 104860484Sobrien q->functail->next = xmalloc (sizeof (ifunctype)); 104960484Sobrien q->functail = q->functail->next; 105060484Sobrien q->functail->ord = func_ordinal; 105160484Sobrien q->functail->name = xstrdup (symbol_name); 105260484Sobrien q->functail->next = NULL; 105360484Sobrien q->nfuncs++; 105460484Sobrien return; 105560484Sobrien } 105660484Sobrien } 105760484Sobrien 105860484Sobrien q = xmalloc (sizeof (iheadtype)); 105960484Sobrien q->dllname = xstrdup (dll_name); 106060484Sobrien q->nfuncs = 1; 106160484Sobrien q->funchead = xmalloc (sizeof (ifunctype)); 106260484Sobrien q->functail = q->funchead; 106360484Sobrien q->next = NULL; 106460484Sobrien q->functail->name = xstrdup (symbol_name); 106560484Sobrien q->functail->ord = func_ordinal; 106660484Sobrien q->functail->next = NULL; 106760484Sobrien 106860484Sobrien *pq = q; 106960484Sobrien} 107060484Sobrien 107160484Sobrien/* def_import is called from within defparse.y when an IMPORT 107260484Sobrien declaration is encountered. Depending on the form of the 107360484Sobrien declaration, the module name may or may not need ".dll" to be 107460484Sobrien appended to it, the name of the function may be stored in internal 107560484Sobrien or entry, and there may or may not be an ordinal value associated 107660484Sobrien with it. */ 107760484Sobrien 107860484Sobrien/* A note regarding the parse modes: 107960484Sobrien In defparse.y we have to accept import declarations which follow 108060484Sobrien any one of the following forms: 108160484Sobrien <func_name_in_app> = <dll_name>.<func_name_in_dll> 108260484Sobrien <func_name_in_app> = <dll_name>.<number> 108360484Sobrien <dll_name>.<func_name_in_dll> 108460484Sobrien <dll_name>.<number> 108560484Sobrien Furthermore, the dll's name may or may not end with ".dll", which 108660484Sobrien complicates the parsing a little. Normally the dll's name is 108760484Sobrien passed to def_import() in the "module" parameter, but when it ends 108860484Sobrien with ".dll" it gets passed in "module" sans ".dll" and that needs 108960484Sobrien to be reappended. 109060484Sobrien 109160484Sobrien def_import gets five parameters: 109260484Sobrien APP_NAME - the name of the function in the application, if 109360484Sobrien present, or NULL if not present. 109460484Sobrien MODULE - the name of the dll, possibly sans extension (ie, '.dll'). 109560484Sobrien DLLEXT - the extension of the dll, if present, NULL if not present. 109660484Sobrien ENTRY - the name of the function in the dll, if present, or NULL. 109760484Sobrien ORD_VAL - the numerical tag of the function in the dll, if present, 109860484Sobrien or NULL. Exactly one of <entry> or <ord_val> must be 109960484Sobrien present (i.e., not NULL). */ 110060484Sobrien 110133965Sjdpvoid 1102130561Sobriendef_import (const char *app_name, const char *module, const char *dllext, 1103130561Sobrien const char *entry, int ord_val) 110433965Sjdp{ 110560484Sobrien const char *application_name; 110660484Sobrien char *buf; 110760484Sobrien 110860484Sobrien if (entry != NULL) 110960484Sobrien application_name = entry; 111060484Sobrien else 111160484Sobrien { 111260484Sobrien if (app_name != NULL) 111360484Sobrien application_name = app_name; 111460484Sobrien else 111560484Sobrien application_name = ""; 111660484Sobrien } 1117104834Sobrien 111860484Sobrien if (dllext != NULL) 111960484Sobrien { 112060484Sobrien buf = (char *) alloca (strlen (module) + strlen (dllext) + 2); 112160484Sobrien sprintf (buf, "%s.%s", module, dllext); 112260484Sobrien module = buf; 112360484Sobrien } 112460484Sobrien 112560484Sobrien append_import (application_name, module, ord_val); 112633965Sjdp} 112733965Sjdp 112833965Sjdpvoid 1129130561Sobriendef_version (int major, int minor) 113033965Sjdp{ 113133965Sjdp printf ("VERSION %d.%d\n", major, minor); 113233965Sjdp} 113333965Sjdp 113433965Sjdpvoid 1135130561Sobriendef_section (const char *name, int attr) 113633965Sjdp{ 113733965Sjdp char buf[200]; 113833965Sjdp char atts[5]; 113933965Sjdp char *d = atts; 114033965Sjdp if (attr & 1) 114133965Sjdp *d++ = 'R'; 114233965Sjdp 114333965Sjdp if (attr & 2) 114433965Sjdp *d++ = 'W'; 114533965Sjdp if (attr & 4) 114633965Sjdp *d++ = 'X'; 114733965Sjdp if (attr & 8) 114833965Sjdp *d++ = 'S'; 114933965Sjdp *d++ = 0; 115033965Sjdp sprintf (buf, "-attr %s %s", name, atts); 115138889Sjdp new_directive (xstrdup (buf)); 115233965Sjdp} 115338889Sjdp 115433965Sjdpvoid 1155130561Sobriendef_code (int attr) 115633965Sjdp{ 115733965Sjdp 115833965Sjdp def_section ("CODE", attr); 115933965Sjdp} 116033965Sjdp 116133965Sjdpvoid 1162130561Sobriendef_data (int attr) 116333965Sjdp{ 116433965Sjdp def_section ("DATA", attr); 116533965Sjdp} 116633965Sjdp 116733965Sjdp/**********************************************************************/ 116833965Sjdp 116938889Sjdpstatic void 1170130561Sobrienrun (const char *what, char *args) 117133965Sjdp{ 117233965Sjdp char *s; 117338889Sjdp int pid, wait_status; 117433965Sjdp int i; 117538889Sjdp const char **argv; 117638889Sjdp char *errmsg_fmt, *errmsg_arg; 117738889Sjdp char *temp_base = choose_temp_base (); 117838889Sjdp 117960484Sobrien inform ("run: %s %s", what, args); 118033965Sjdp 118133965Sjdp /* Count the args */ 118233965Sjdp i = 0; 118333965Sjdp for (s = args; *s; s++) 118433965Sjdp if (*s == ' ') 118533965Sjdp i++; 118633965Sjdp i++; 118733965Sjdp argv = alloca (sizeof (char *) * (i + 3)); 118833965Sjdp i = 0; 118933965Sjdp argv[i++] = what; 119033965Sjdp s = args; 119133965Sjdp while (1) 119233965Sjdp { 119360484Sobrien while (*s == ' ') 119460484Sobrien ++s; 119533965Sjdp argv[i++] = s; 119633965Sjdp while (*s != ' ' && *s != 0) 119733965Sjdp s++; 119833965Sjdp if (*s == 0) 119933965Sjdp break; 120033965Sjdp *s++ = 0; 120133965Sjdp } 120238889Sjdp argv[i++] = NULL; 120333965Sjdp 120438889Sjdp pid = pexecute (argv[0], (char * const *) argv, program_name, temp_base, 120538889Sjdp &errmsg_fmt, &errmsg_arg, PEXECUTE_ONE | PEXECUTE_SEARCH); 120633965Sjdp 120738889Sjdp if (pid == -1) 120838889Sjdp { 120960484Sobrien inform (strerror (errno)); 1210104834Sobrien 121160484Sobrien fatal (errmsg_fmt, errmsg_arg); 121238889Sjdp } 121338889Sjdp 121460484Sobrien pid = pwait (pid, & wait_status, 0); 1215104834Sobrien 121638889Sjdp if (pid == -1) 121733965Sjdp { 121860484Sobrien /* xgettext:c-format */ 121960484Sobrien fatal (_("wait: %s"), strerror (errno)); 122033965Sjdp } 122138889Sjdp else if (WIFSIGNALED (wait_status)) 122233965Sjdp { 122360484Sobrien /* xgettext:c-format */ 122460484Sobrien fatal (_("subprocess got fatal signal %d"), WTERMSIG (wait_status)); 122533965Sjdp } 122638889Sjdp else if (WIFEXITED (wait_status)) 122733965Sjdp { 122838889Sjdp if (WEXITSTATUS (wait_status) != 0) 122960484Sobrien /* xgettext:c-format */ 123060484Sobrien non_fatal (_("%s exited with status %d"), 123160484Sobrien what, WEXITSTATUS (wait_status)); 123233965Sjdp } 123338889Sjdp else 123438889Sjdp abort (); 123533965Sjdp} 123633965Sjdp 123760484Sobrien/* Look for a list of symbols to export in the .drectve section of 123860484Sobrien ABFD. Pass each one to def_exports. */ 123960484Sobrien 124033965Sjdpstatic void 1241130561Sobrienscan_drectve_symbols (bfd *abfd) 124233965Sjdp{ 124360484Sobrien asection * s; 124460484Sobrien int size; 124560484Sobrien char * buf; 124660484Sobrien char * p; 124760484Sobrien char * e; 124833965Sjdp 124933965Sjdp /* Look for .drectve's */ 125060484Sobrien s = bfd_get_section_by_name (abfd, DRECTVE_SECTION_NAME); 1251104834Sobrien 125260484Sobrien if (s == NULL) 125360484Sobrien return; 1254104834Sobrien 1255218822Sdim size = bfd_get_section_size (s); 125660484Sobrien buf = xmalloc (size); 125760484Sobrien 125860484Sobrien bfd_get_section_contents (abfd, s, buf, 0, size); 1259104834Sobrien 126060484Sobrien /* xgettext:c-format */ 126160484Sobrien inform (_("Sucking in info from %s section in %s"), 126260484Sobrien DRECTVE_SECTION_NAME, bfd_get_filename (abfd)); 126360484Sobrien 126460484Sobrien /* Search for -export: strings. The exported symbols can optionally 126560484Sobrien have type tags (eg., -export:foo,data), so handle those as well. 126660484Sobrien Currently only data tag is supported. */ 126760484Sobrien p = buf; 126860484Sobrien e = buf + size; 126960484Sobrien while (p < e) 127033965Sjdp { 127160484Sobrien if (p[0] == '-' 1272218822Sdim && CONST_STRNEQ (p, "-export:")) 127333965Sjdp { 127460484Sobrien char * name; 127560484Sobrien char * c; 127660484Sobrien flagword flags = BSF_FUNCTION; 1277104834Sobrien 127860484Sobrien p += 8; 127960484Sobrien name = p; 128060484Sobrien while (p < e && *p != ',' && *p != ' ' && *p != '-') 128160484Sobrien p++; 128260484Sobrien c = xmalloc (p - name + 1); 128360484Sobrien memcpy (c, name, p - name); 128460484Sobrien c[p - name] = 0; 1285104834Sobrien if (p < e && *p == ',') /* found type tag. */ 128633965Sjdp { 128760484Sobrien char *tag_start = ++p; 128833965Sjdp while (p < e && *p != ' ' && *p != '-') 128933965Sjdp p++; 1290218822Sdim if (CONST_STRNEQ (tag_start, "data")) 129160484Sobrien flags &= ~BSF_FUNCTION; 129233965Sjdp } 129360484Sobrien 129460484Sobrien /* FIXME: The 5th arg is for the `constant' field. 129560484Sobrien What should it be? Not that it matters since it's not 129660484Sobrien currently useful. */ 1297130561Sobrien def_exports (c, 0, -1, 0, 0, ! (flags & BSF_FUNCTION), 0); 129860484Sobrien 129960484Sobrien if (add_stdcall_alias && strchr (c, '@')) 130060484Sobrien { 1301130561Sobrien int lead_at = (*c == '@') ; 1302130561Sobrien char *exported_name = xstrdup (c + lead_at); 130360484Sobrien char *atsym = strchr (exported_name, '@'); 130460484Sobrien *atsym = '\0'; 130560484Sobrien /* Note: stdcall alias symbols can never be data. */ 1306130561Sobrien def_exports (exported_name, xstrdup (c), -1, 0, 0, 0, 0); 130760484Sobrien } 130833965Sjdp } 130960484Sobrien else 131060484Sobrien p++; 131133965Sjdp } 131260484Sobrien free (buf); 131360484Sobrien} 131433965Sjdp 131560484Sobrien/* Look through the symbols in MINISYMS, and add each one to list of 131660484Sobrien symbols to export. */ 131733965Sjdp 131860484Sobrienstatic void 1319130561Sobrienscan_filtered_symbols (bfd *abfd, void *minisyms, long symcount, 1320130561Sobrien unsigned int size) 132160484Sobrien{ 132260484Sobrien asymbol *store; 132360484Sobrien bfd_byte *from, *fromend; 132460484Sobrien 132560484Sobrien store = bfd_make_empty_symbol (abfd); 132660484Sobrien if (store == NULL) 132760484Sobrien bfd_fatal (bfd_get_filename (abfd)); 132860484Sobrien 132960484Sobrien from = (bfd_byte *) minisyms; 133060484Sobrien fromend = from + symcount * size; 133160484Sobrien for (; from < fromend; from += size) 133260484Sobrien { 133360484Sobrien asymbol *sym; 133460484Sobrien const char *symbol_name; 133560484Sobrien 1336130561Sobrien sym = bfd_minisymbol_to_symbol (abfd, FALSE, from, store); 133760484Sobrien if (sym == NULL) 133860484Sobrien bfd_fatal (bfd_get_filename (abfd)); 133960484Sobrien 134060484Sobrien symbol_name = bfd_asymbol_name (sym); 134160484Sobrien if (bfd_get_symbol_leading_char (abfd) == symbol_name[0]) 134260484Sobrien ++symbol_name; 134360484Sobrien 134460484Sobrien def_exports (xstrdup (symbol_name) , 0, -1, 0, 0, 1345130561Sobrien ! (sym->flags & BSF_FUNCTION), 0); 134660484Sobrien 134760484Sobrien if (add_stdcall_alias && strchr (symbol_name, '@')) 134860484Sobrien { 1349130561Sobrien int lead_at = (*symbol_name == '@'); 1350130561Sobrien char *exported_name = xstrdup (symbol_name + lead_at); 135160484Sobrien char *atsym = strchr (exported_name, '@'); 135260484Sobrien *atsym = '\0'; 1353104834Sobrien /* Note: stdcall alias symbols can never be data. */ 1354130561Sobrien def_exports (exported_name, xstrdup (symbol_name), -1, 0, 0, 0, 0); 135560484Sobrien } 135660484Sobrien } 135733965Sjdp} 135833965Sjdp 135960484Sobrien/* Add a list of symbols to exclude. */ 136060484Sobrien 136138889Sjdpstatic void 1362130561Sobrienadd_excludes (const char *new_excludes) 136360484Sobrien{ 136460484Sobrien char *local_copy; 136560484Sobrien char *exclude_string; 136660484Sobrien 136760484Sobrien local_copy = xstrdup (new_excludes); 136860484Sobrien 136960484Sobrien exclude_string = strtok (local_copy, ",:"); 137060484Sobrien for (; exclude_string; exclude_string = strtok (NULL, ",:")) 137160484Sobrien { 137260484Sobrien struct string_list *new_exclude; 1373104834Sobrien 137460484Sobrien new_exclude = ((struct string_list *) 137560484Sobrien xmalloc (sizeof (struct string_list))); 137660484Sobrien new_exclude->string = (char *) xmalloc (strlen (exclude_string) + 2); 1377130561Sobrien /* Don't add a leading underscore for fastcall symbols. */ 1378130561Sobrien if (*exclude_string == '@') 1379130561Sobrien sprintf (new_exclude->string, "%s", exclude_string); 1380130561Sobrien else 1381130561Sobrien sprintf (new_exclude->string, "_%s", exclude_string); 138260484Sobrien new_exclude->next = excludes; 138360484Sobrien excludes = new_exclude; 138460484Sobrien 138560484Sobrien /* xgettext:c-format */ 138660484Sobrien inform (_("Excluding symbol: %s"), exclude_string); 138760484Sobrien } 138860484Sobrien 138960484Sobrien free (local_copy); 139060484Sobrien} 139160484Sobrien 139260484Sobrien/* See if STRING is on the list of symbols to exclude. */ 139360484Sobrien 1394130561Sobrienstatic bfd_boolean 1395130561Sobrienmatch_exclude (const char *string) 139660484Sobrien{ 139760484Sobrien struct string_list *excl_item; 139860484Sobrien 139960484Sobrien for (excl_item = excludes; excl_item; excl_item = excl_item->next) 140060484Sobrien if (strcmp (string, excl_item->string) == 0) 1401130561Sobrien return TRUE; 1402130561Sobrien return FALSE; 140360484Sobrien} 140460484Sobrien 140560484Sobrien/* Add the default list of symbols to exclude. */ 140660484Sobrien 140760484Sobrienstatic void 140860484Sobrienset_default_excludes (void) 140960484Sobrien{ 141060484Sobrien add_excludes (default_excludes); 141160484Sobrien} 141260484Sobrien 141360484Sobrien/* Choose which symbols to export. */ 141460484Sobrien 141560484Sobrienstatic long 1416130561Sobrienfilter_symbols (bfd *abfd, void *minisyms, long symcount, unsigned int size) 141760484Sobrien{ 141860484Sobrien bfd_byte *from, *fromend, *to; 141960484Sobrien asymbol *store; 142060484Sobrien 142160484Sobrien store = bfd_make_empty_symbol (abfd); 142260484Sobrien if (store == NULL) 142360484Sobrien bfd_fatal (bfd_get_filename (abfd)); 142460484Sobrien 142560484Sobrien from = (bfd_byte *) minisyms; 142660484Sobrien fromend = from + symcount * size; 142760484Sobrien to = (bfd_byte *) minisyms; 142860484Sobrien 142960484Sobrien for (; from < fromend; from += size) 143060484Sobrien { 143160484Sobrien int keep = 0; 143260484Sobrien asymbol *sym; 143360484Sobrien 1434130561Sobrien sym = bfd_minisymbol_to_symbol (abfd, FALSE, (const void *) from, store); 143560484Sobrien if (sym == NULL) 143660484Sobrien bfd_fatal (bfd_get_filename (abfd)); 143760484Sobrien 143860484Sobrien /* Check for external and defined only symbols. */ 143960484Sobrien keep = (((sym->flags & BSF_GLOBAL) != 0 144060484Sobrien || (sym->flags & BSF_WEAK) != 0 144160484Sobrien || bfd_is_com_section (sym->section)) 144260484Sobrien && ! bfd_is_und_section (sym->section)); 1443104834Sobrien 144460484Sobrien keep = keep && ! match_exclude (sym->name); 144560484Sobrien 144660484Sobrien if (keep) 144760484Sobrien { 144860484Sobrien memcpy (to, from, size); 144960484Sobrien to += size; 145060484Sobrien } 145160484Sobrien } 145260484Sobrien 145360484Sobrien return (to - (bfd_byte *) minisyms) / size; 145460484Sobrien} 145560484Sobrien 145660484Sobrien/* Export all symbols in ABFD, except for ones we were told not to 145760484Sobrien export. */ 145860484Sobrien 145960484Sobrienstatic void 1460130561Sobrienscan_all_symbols (bfd *abfd) 146160484Sobrien{ 146260484Sobrien long symcount; 1463130561Sobrien void *minisyms; 146460484Sobrien unsigned int size; 146560484Sobrien 146660484Sobrien /* Ignore bfds with an import descriptor table. We assume that any 146760484Sobrien such BFD contains symbols which are exported from another DLL, 146860484Sobrien and we don't want to reexport them from here. */ 146960484Sobrien if (bfd_get_section_by_name (abfd, ".idata$4")) 147060484Sobrien return; 147160484Sobrien 147260484Sobrien if (! (bfd_get_file_flags (abfd) & HAS_SYMS)) 147360484Sobrien { 147460484Sobrien /* xgettext:c-format */ 147560484Sobrien non_fatal (_("%s: no symbols"), bfd_get_filename (abfd)); 147660484Sobrien return; 147760484Sobrien } 147860484Sobrien 1479130561Sobrien symcount = bfd_read_minisymbols (abfd, FALSE, &minisyms, &size); 148060484Sobrien if (symcount < 0) 148160484Sobrien bfd_fatal (bfd_get_filename (abfd)); 148260484Sobrien 148360484Sobrien if (symcount == 0) 148460484Sobrien { 148560484Sobrien /* xgettext:c-format */ 148660484Sobrien non_fatal (_("%s: no symbols"), bfd_get_filename (abfd)); 148760484Sobrien return; 148860484Sobrien } 148960484Sobrien 149060484Sobrien /* Discard the symbols we don't want to export. It's OK to do this 149160484Sobrien in place; we'll free the storage anyway. */ 149260484Sobrien 149360484Sobrien symcount = filter_symbols (abfd, minisyms, symcount, size); 149460484Sobrien scan_filtered_symbols (abfd, minisyms, symcount, size); 149560484Sobrien 149660484Sobrien free (minisyms); 149760484Sobrien} 149860484Sobrien 149960484Sobrien/* Look at the object file to decide which symbols to export. */ 150060484Sobrien 150160484Sobrienstatic void 1502130561Sobrienscan_open_obj_file (bfd *abfd) 150360484Sobrien{ 150460484Sobrien if (export_all_symbols) 150560484Sobrien scan_all_symbols (abfd); 150660484Sobrien else 150760484Sobrien scan_drectve_symbols (abfd); 1508104834Sobrien 1509130561Sobrien /* FIXME: we ought to read in and block out the base relocations. */ 151060484Sobrien 151160484Sobrien /* xgettext:c-format */ 151260484Sobrien inform (_("Done reading %s"), bfd_get_filename (abfd)); 151360484Sobrien} 151460484Sobrien 151560484Sobrienstatic void 1516130561Sobrienscan_obj_file (const char *filename) 151733965Sjdp{ 151860484Sobrien bfd * f = bfd_openr (filename, 0); 151933965Sjdp 152033965Sjdp if (!f) 152160484Sobrien /* xgettext:c-format */ 152260484Sobrien fatal (_("Unable to open object file: %s"), filename); 152360484Sobrien 152460484Sobrien /* xgettext:c-format */ 152560484Sobrien inform (_("Scanning object file %s"), filename); 1526104834Sobrien 152733965Sjdp if (bfd_check_format (f, bfd_archive)) 152833965Sjdp { 152933965Sjdp bfd *arfile = bfd_openr_next_archived_file (f, 0); 153033965Sjdp while (arfile) 153133965Sjdp { 153233965Sjdp if (bfd_check_format (arfile, bfd_object)) 153333965Sjdp scan_open_obj_file (arfile); 153433965Sjdp bfd_close (arfile); 153533965Sjdp arfile = bfd_openr_next_archived_file (f, arfile); 153633965Sjdp } 1537104834Sobrien 153860484Sobrien#ifdef DLLTOOL_MCORE_ELF 153960484Sobrien if (mcore_elf_out_file) 154060484Sobrien inform (_("Cannot produce mcore-elf dll from archive file: %s"), filename); 154160484Sobrien#endif 154233965Sjdp } 154333965Sjdp else if (bfd_check_format (f, bfd_object)) 154433965Sjdp { 154533965Sjdp scan_open_obj_file (f); 154660484Sobrien 154760484Sobrien#ifdef DLLTOOL_MCORE_ELF 154860484Sobrien if (mcore_elf_out_file) 154960484Sobrien mcore_elf_cache_filename ((char *) filename); 155060484Sobrien#endif 155133965Sjdp } 155233965Sjdp 155333965Sjdp bfd_close (f); 155433965Sjdp} 155533965Sjdp 155633965Sjdp/**********************************************************************/ 155733965Sjdp 155838889Sjdpstatic void 1559130561Sobriendump_def_info (FILE *f) 156033965Sjdp{ 156133965Sjdp int i; 156233965Sjdp export_type *exp; 156333965Sjdp fprintf (f, "%s ", ASM_C); 156433965Sjdp for (i = 0; oav[i]; i++) 156533965Sjdp fprintf (f, "%s ", oav[i]); 156633965Sjdp fprintf (f, "\n"); 156733965Sjdp for (i = 0, exp = d_exports; exp; i++, exp = exp->next) 156833965Sjdp { 1569130561Sobrien fprintf (f, "%s %d = %s %s @ %d %s%s%s%s\n", 157033965Sjdp ASM_C, 157133965Sjdp i, 157233965Sjdp exp->name, 157333965Sjdp exp->internal_name, 157433965Sjdp exp->ordinal, 157533965Sjdp exp->noname ? "NONAME " : "", 1576130561Sobrien exp->private ? "PRIVATE " : "", 157738889Sjdp exp->constant ? "CONSTANT" : "", 157838889Sjdp exp->data ? "DATA" : ""); 157933965Sjdp } 158033965Sjdp} 158138889Sjdp 1582130561Sobrien/* Generate the .exp file. */ 158333965Sjdp 158438889Sjdpstatic int 1585130561Sobriensfunc (const void *a, const void *b) 158633965Sjdp{ 158738889Sjdp return *(const long *) a - *(const long *) b; 158833965Sjdp} 158933965Sjdp 159033965Sjdpstatic void 1591130561Sobrienflush_page (FILE *f, long *need, int page_addr, int on_page) 159233965Sjdp{ 159333965Sjdp int i; 159433965Sjdp 1595130561Sobrien /* Flush this page. */ 159633965Sjdp fprintf (f, "\t%s\t0x%08x\t%s Starting RVA for chunk\n", 159733965Sjdp ASM_LONG, 159833965Sjdp page_addr, 159933965Sjdp ASM_C); 160033965Sjdp fprintf (f, "\t%s\t0x%x\t%s Size of block\n", 160133965Sjdp ASM_LONG, 160233965Sjdp (on_page * 2) + (on_page & 1) * 2 + 8, 160333965Sjdp ASM_C); 1604104834Sobrien 160533965Sjdp for (i = 0; i < on_page; i++) 160633965Sjdp { 160760484Sobrien long needed = need[i]; 1608104834Sobrien 160960484Sobrien if (needed) 161060484Sobrien needed = ((needed - page_addr) | 0x3000) & 0xffff; 1611104834Sobrien 161260484Sobrien fprintf (f, "\t%s\t0x%lx\n", ASM_SHORT, needed); 161333965Sjdp } 1614104834Sobrien 161533965Sjdp /* And padding */ 161633965Sjdp if (on_page & 1) 161733965Sjdp fprintf (f, "\t%s\t0x%x\n", ASM_SHORT, 0 | 0x0000); 161833965Sjdp} 161933965Sjdp 162038889Sjdpstatic void 1621130561Sobriengen_def_file (void) 162233965Sjdp{ 162333965Sjdp int i; 162433965Sjdp export_type *exp; 162533965Sjdp 162660484Sobrien inform (_("Adding exports to output file")); 1627104834Sobrien 162833965Sjdp fprintf (output_def, ";"); 162933965Sjdp for (i = 0; oav[i]; i++) 163033965Sjdp fprintf (output_def, " %s", oav[i]); 163133965Sjdp 163233965Sjdp fprintf (output_def, "\nEXPORTS\n"); 163333965Sjdp 163433965Sjdp for (i = 0, exp = d_exports; exp; i++, exp = exp->next) 163533965Sjdp { 163633965Sjdp char *quote = strchr (exp->name, '.') ? "\"" : ""; 163760484Sobrien char *res = cplus_demangle (exp->internal_name, DMGL_ANSI | DMGL_PARAMS); 163860484Sobrien 1639130561Sobrien if (res) 1640130561Sobrien { 1641130561Sobrien fprintf (output_def,";\t%s\n", res); 1642130561Sobrien free (res); 1643130561Sobrien } 1644130561Sobrien 164560484Sobrien if (strcmp (exp->name, exp->internal_name) == 0) 1646104834Sobrien { 1647130561Sobrien fprintf (output_def, "\t%s%s%s @ %d%s%s%s\n", 164860484Sobrien quote, 164960484Sobrien exp->name, 165060484Sobrien quote, 165160484Sobrien exp->ordinal, 165260484Sobrien exp->noname ? " NONAME" : "", 1653130561Sobrien exp->private ? "PRIVATE " : "", 1654130561Sobrien exp->data ? " DATA" : ""); 165560484Sobrien } 1656104834Sobrien else 1657104834Sobrien { 1658130561Sobrien char * quote1 = strchr (exp->internal_name, '.') ? "\"" : ""; 165960484Sobrien /* char *alias = */ 1660130561Sobrien fprintf (output_def, "\t%s%s%s = %s%s%s @ %d%s%s%s\n", 166160484Sobrien quote, 166260484Sobrien exp->name, 166360484Sobrien quote, 166460484Sobrien quote1, 166560484Sobrien exp->internal_name, 166660484Sobrien quote1, 166760484Sobrien exp->ordinal, 166860484Sobrien exp->noname ? " NONAME" : "", 1669130561Sobrien exp->private ? "PRIVATE " : "", 1670130561Sobrien exp->data ? " DATA" : ""); 167160484Sobrien } 167233965Sjdp } 1673104834Sobrien 167460484Sobrien inform (_("Added exports to output file")); 167533965Sjdp} 167638889Sjdp 167760484Sobrien/* generate_idata_ofile generates the portable assembly source code 167860484Sobrien for the idata sections. It appends the source code to the end of 167960484Sobrien the file. */ 168060484Sobrien 168138889Sjdpstatic void 1682130561Sobriengenerate_idata_ofile (FILE *filvar) 168333965Sjdp{ 168460484Sobrien iheadtype *headptr; 168560484Sobrien ifunctype *funcptr; 168660484Sobrien int headindex; 168760484Sobrien int funcindex; 168860484Sobrien int nheads; 168933965Sjdp 169060484Sobrien if (import_list == NULL) 169160484Sobrien return; 169233965Sjdp 169360484Sobrien fprintf (filvar, "%s Import data sections\n", ASM_C); 169460484Sobrien fprintf (filvar, "\n\t.section\t.idata$2\n"); 169560484Sobrien fprintf (filvar, "\t%s\tdoi_idata\n", ASM_GLOBAL); 169660484Sobrien fprintf (filvar, "doi_idata:\n"); 169733965Sjdp 169860484Sobrien nheads = 0; 169960484Sobrien for (headptr = import_list; headptr != NULL; headptr = headptr->next) 170060484Sobrien { 170160484Sobrien fprintf (filvar, "\t%slistone%d%s\t%s %s\n", 170260484Sobrien ASM_RVA_BEFORE, nheads, ASM_RVA_AFTER, 170360484Sobrien ASM_C, headptr->dllname); 170460484Sobrien fprintf (filvar, "\t%s\t0\n", ASM_LONG); 170560484Sobrien fprintf (filvar, "\t%s\t0\n", ASM_LONG); 170660484Sobrien fprintf (filvar, "\t%sdllname%d%s\n", 170760484Sobrien ASM_RVA_BEFORE, nheads, ASM_RVA_AFTER); 170860484Sobrien fprintf (filvar, "\t%slisttwo%d%s\n\n", 170960484Sobrien ASM_RVA_BEFORE, nheads, ASM_RVA_AFTER); 171060484Sobrien nheads++; 171160484Sobrien } 171233965Sjdp 171360484Sobrien fprintf (filvar, "\t%s\t0\n", ASM_LONG); /* NULL record at */ 171460484Sobrien fprintf (filvar, "\t%s\t0\n", ASM_LONG); /* end of idata$2 */ 171560484Sobrien fprintf (filvar, "\t%s\t0\n", ASM_LONG); /* section */ 171660484Sobrien fprintf (filvar, "\t%s\t0\n", ASM_LONG); 171760484Sobrien fprintf (filvar, "\t%s\t0\n", ASM_LONG); 171860484Sobrien 171960484Sobrien fprintf (filvar, "\n\t.section\t.idata$4\n"); 172060484Sobrien headindex = 0; 172160484Sobrien for (headptr = import_list; headptr != NULL; headptr = headptr->next) 172233965Sjdp { 172360484Sobrien fprintf (filvar, "listone%d:\n", headindex); 1724218822Sdim for (funcindex = 0; funcindex < headptr->nfuncs; funcindex++) 1725218822Sdim#ifdef DLLTOOL_MX86_64 1726218822Sdim fprintf (filvar, "\t%sfuncptr%d_%d%s\n%s\t0\n", 1727218822Sdim ASM_RVA_BEFORE, headindex, funcindex, ASM_RVA_AFTER,ASM_LONG); 1728218822Sdim#else 172960484Sobrien fprintf (filvar, "\t%sfuncptr%d_%d%s\n", 173060484Sobrien ASM_RVA_BEFORE, headindex, funcindex, ASM_RVA_AFTER); 1731218822Sdim#endif 1732218822Sdim#ifdef DLLTOOL_MX86_64 1733218822Sdim fprintf (filvar, "\t%s\t0\n\t%s\t0\n", ASM_LONG, ASM_LONG); /* NULL terminating list. */ 1734218822Sdim#else 1735218822Sdim fprintf (filvar, "\t%s\t0\n", ASM_LONG); /* NULL terminating list. */ 1736218822Sdim#endif 173760484Sobrien headindex++; 173833965Sjdp } 173960484Sobrien 174060484Sobrien fprintf (filvar, "\n\t.section\t.idata$5\n"); 174160484Sobrien headindex = 0; 174260484Sobrien for (headptr = import_list; headptr != NULL; headptr = headptr->next) 174333965Sjdp { 174460484Sobrien fprintf (filvar, "listtwo%d:\n", headindex); 1745218822Sdim for (funcindex = 0; funcindex < headptr->nfuncs; funcindex++) 1746218822Sdim#ifdef DLLTOOL_MX86_64 1747218822Sdim fprintf (filvar, "\t%sfuncptr%d_%d%s\n%s\t0\n", 1748218822Sdim ASM_RVA_BEFORE, headindex, funcindex, ASM_RVA_AFTER,ASM_LONG); 1749218822Sdim#else 175060484Sobrien fprintf (filvar, "\t%sfuncptr%d_%d%s\n", 175160484Sobrien ASM_RVA_BEFORE, headindex, funcindex, ASM_RVA_AFTER); 1752218822Sdim#endif 1753218822Sdim#ifdef DLLTOOL_MX86_64 1754218822Sdim fprintf (filvar, "\t%s\t0\n\t%s\t0\n", ASM_LONG, ASM_LONG); /* NULL terminating list. */ 1755218822Sdim#else 1756218822Sdim fprintf (filvar, "\t%s\t0\n", ASM_LONG); /* NULL terminating list. */ 1757218822Sdim#endif 175860484Sobrien headindex++; 175933965Sjdp } 176033965Sjdp 176160484Sobrien fprintf (filvar, "\n\t.section\t.idata$6\n"); 176260484Sobrien headindex = 0; 176360484Sobrien for (headptr = import_list; headptr != NULL; headptr = headptr->next) 176460484Sobrien { 176560484Sobrien funcindex = 0; 176660484Sobrien for (funcptr = headptr->funchead; funcptr != NULL; 176760484Sobrien funcptr = funcptr->next) 176860484Sobrien { 176960484Sobrien fprintf (filvar,"funcptr%d_%d:\n", headindex, funcindex); 177060484Sobrien fprintf (filvar,"\t%s\t%d\n", ASM_SHORT, 177160484Sobrien ((funcptr->ord) & 0xFFFF)); 177260484Sobrien fprintf (filvar,"\t%s\t\"%s\"\n", ASM_TEXT, funcptr->name); 177360484Sobrien fprintf (filvar,"\t%s\t0\n", ASM_BYTE); 177460484Sobrien funcindex++; 177560484Sobrien } 177660484Sobrien headindex++; 177760484Sobrien } 177860484Sobrien 177960484Sobrien fprintf (filvar, "\n\t.section\t.idata$7\n"); 178060484Sobrien headindex = 0; 178160484Sobrien for (headptr = import_list; headptr != NULL; headptr = headptr->next) 178260484Sobrien { 178360484Sobrien fprintf (filvar,"dllname%d:\n", headindex); 178460484Sobrien fprintf (filvar,"\t%s\t\"%s\"\n", ASM_TEXT, headptr->dllname); 178560484Sobrien fprintf (filvar,"\t%s\t0\n", ASM_BYTE); 178660484Sobrien headindex++; 178760484Sobrien } 178860484Sobrien} 178960484Sobrien 1790104834Sobrien/* Assemble the specified file. */ 179160484Sobrienstatic void 1792130561Sobrienassemble_file (const char * source, const char * dest) 179360484Sobrien{ 179460484Sobrien char * cmd; 1795104834Sobrien 179660484Sobrien cmd = (char *) alloca (strlen (ASM_SWITCHES) + strlen (as_flags) 179760484Sobrien + strlen (source) + strlen (dest) + 50); 179860484Sobrien 179960484Sobrien sprintf (cmd, "%s %s -o %s %s", ASM_SWITCHES, as_flags, dest, source); 180060484Sobrien 180160484Sobrien run (as_name, cmd); 180260484Sobrien} 180360484Sobrien 180460484Sobrienstatic void 1805130561Sobriengen_exp_file (void) 180660484Sobrien{ 180760484Sobrien FILE *f; 180860484Sobrien int i; 180960484Sobrien export_type *exp; 181060484Sobrien dlist_type *dl; 181160484Sobrien 181260484Sobrien /* xgettext:c-format */ 181360484Sobrien inform (_("Generating export file: %s"), exp_name); 1814104834Sobrien 181560484Sobrien f = fopen (TMP_ASM, FOPEN_WT); 181660484Sobrien if (!f) 181760484Sobrien /* xgettext:c-format */ 181860484Sobrien fatal (_("Unable to open temporary assembler file: %s"), TMP_ASM); 1819104834Sobrien 182060484Sobrien /* xgettext:c-format */ 182160484Sobrien inform (_("Opened temporary file: %s"), TMP_ASM); 182260484Sobrien 182333965Sjdp dump_def_info (f); 1824104834Sobrien 182533965Sjdp if (d_exports) 182633965Sjdp { 182733965Sjdp fprintf (f, "\t.section .edata\n\n"); 182833965Sjdp fprintf (f, "\t%s 0 %s Allways 0\n", ASM_LONG, ASM_C); 182938889Sjdp fprintf (f, "\t%s 0x%lx %s Time and date\n", ASM_LONG, (long) time(0), 183038889Sjdp ASM_C); 183133965Sjdp fprintf (f, "\t%s 0 %s Major and Minor version\n", ASM_LONG, ASM_C); 183233965Sjdp fprintf (f, "\t%sname%s %s Ptr to name of dll\n", ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C); 183333965Sjdp fprintf (f, "\t%s %d %s Starting ordinal of exports\n", ASM_LONG, d_low_ord, ASM_C); 183433965Sjdp 183533965Sjdp 183633965Sjdp fprintf (f, "\t%s %d %s Number of functions\n", ASM_LONG, d_high_ord - d_low_ord + 1, ASM_C); 183733965Sjdp fprintf(f,"\t%s named funcs %d, low ord %d, high ord %d\n", 183833965Sjdp ASM_C, 183933965Sjdp d_named_nfuncs, d_low_ord, d_high_ord); 184033965Sjdp fprintf (f, "\t%s %d %s Number of names\n", ASM_LONG, 184133965Sjdp show_allnames ? d_high_ord - d_low_ord + 1 : d_named_nfuncs, ASM_C); 184233965Sjdp fprintf (f, "\t%safuncs%s %s Address of functions\n", ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C); 184333965Sjdp 184460484Sobrien fprintf (f, "\t%sanames%s %s Address of Name Pointer Table\n", 184533965Sjdp ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C); 184633965Sjdp 184733965Sjdp fprintf (f, "\t%sanords%s %s Address of ordinals\n", ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C); 184833965Sjdp 184933965Sjdp fprintf (f, "name: %s \"%s\"\n", ASM_TEXT, dll_name); 185033965Sjdp 185133965Sjdp 185233965Sjdp fprintf(f,"%s Export address Table\n", ASM_C); 185333965Sjdp fprintf(f,"\t%s\n", ASM_ALIGN_LONG); 185433965Sjdp fprintf (f, "afuncs:\n"); 185533965Sjdp i = d_low_ord; 185633965Sjdp 185733965Sjdp for (exp = d_exports; exp; exp = exp->next) 185833965Sjdp { 185933965Sjdp if (exp->ordinal != i) 186033965Sjdp { 186133965Sjdp while (i < exp->ordinal) 186233965Sjdp { 186333965Sjdp fprintf(f,"\t%s\t0\n", ASM_LONG); 186433965Sjdp i++; 186533965Sjdp } 186633965Sjdp } 186789857Sobrien 186889857Sobrien if (exp->forward == 0) 1869130561Sobrien { 1870130561Sobrien if (exp->internal_name[0] == '@') 1871130561Sobrien fprintf (f, "\t%s%s%s\t%s %d\n", ASM_RVA_BEFORE, 1872130561Sobrien exp->internal_name, ASM_RVA_AFTER, ASM_C, exp->ordinal); 1873130561Sobrien else 1874130561Sobrien fprintf (f, "\t%s%s%s%s\t%s %d\n", ASM_RVA_BEFORE, 1875218822Sdim ASM_PREFIX (exp->internal_name), 1876130561Sobrien exp->internal_name, ASM_RVA_AFTER, ASM_C, exp->ordinal); 1877130561Sobrien } 187889857Sobrien else 187989857Sobrien fprintf (f, "\t%sf%d%s\t%s %d\n", ASM_RVA_BEFORE, 188089857Sobrien exp->forward, ASM_RVA_AFTER, ASM_C, exp->ordinal); 188133965Sjdp i++; 188233965Sjdp } 188333965Sjdp 188433965Sjdp fprintf (f,"%s Export Name Pointer Table\n", ASM_C); 188533965Sjdp fprintf (f, "anames:\n"); 188633965Sjdp 188733965Sjdp for (i = 0; (exp = d_exports_lexically[i]); i++) 188833965Sjdp { 188933965Sjdp if (!exp->noname || show_allnames) 189060484Sobrien fprintf (f, "\t%sn%d%s\n", 189160484Sobrien ASM_RVA_BEFORE, exp->ordinal, ASM_RVA_AFTER); 189233965Sjdp } 189333965Sjdp 189433965Sjdp fprintf (f,"%s Export Oridinal Table\n", ASM_C); 189533965Sjdp fprintf (f, "anords:\n"); 189633965Sjdp for (i = 0; (exp = d_exports_lexically[i]); i++) 189733965Sjdp { 189833965Sjdp if (!exp->noname || show_allnames) 189933965Sjdp fprintf (f, "\t%s %d\n", ASM_SHORT, exp->ordinal - d_low_ord); 190033965Sjdp } 190133965Sjdp 190233965Sjdp fprintf(f,"%s Export Name Table\n", ASM_C); 190333965Sjdp for (i = 0; (exp = d_exports_lexically[i]); i++) 1904130561Sobrien { 1905130561Sobrien if (!exp->noname || show_allnames) 190689857Sobrien fprintf (f, "n%d: %s \"%s\"\n", 190799461Sobrien exp->ordinal, ASM_TEXT, xlate (exp->name)); 1908130561Sobrien if (exp->forward != 0) 1909130561Sobrien fprintf (f, "f%d: %s \"%s\"\n", 1910130561Sobrien exp->forward, ASM_TEXT, exp->internal_name); 1911130561Sobrien } 191233965Sjdp 191333965Sjdp if (a_list) 191433965Sjdp { 191560484Sobrien fprintf (f, "\t.section %s\n", DRECTVE_SECTION_NAME); 191633965Sjdp for (dl = a_list; dl; dl = dl->next) 191733965Sjdp { 191833965Sjdp fprintf (f, "\t%s\t\"%s\"\n", ASM_TEXT, dl->text); 191933965Sjdp } 192033965Sjdp } 1921104834Sobrien 192233965Sjdp if (d_list) 192333965Sjdp { 192433965Sjdp fprintf (f, "\t.section .rdata\n"); 192533965Sjdp for (dl = d_list; dl; dl = dl->next) 192633965Sjdp { 192733965Sjdp char *p; 192833965Sjdp int l; 1929104834Sobrien 193060484Sobrien /* We don't output as ascii because there can 193160484Sobrien be quote characters in the string. */ 193233965Sjdp l = 0; 193333965Sjdp for (p = dl->text; *p; p++) 193433965Sjdp { 193533965Sjdp if (l == 0) 193633965Sjdp fprintf (f, "\t%s\t", ASM_BYTE); 193733965Sjdp else 193833965Sjdp fprintf (f, ","); 193933965Sjdp fprintf (f, "%d", *p); 194033965Sjdp if (p[1] == 0) 194133965Sjdp { 194233965Sjdp fprintf (f, ",0\n"); 194333965Sjdp break; 194433965Sjdp } 194533965Sjdp if (++l == 10) 194633965Sjdp { 194733965Sjdp fprintf (f, "\n"); 194833965Sjdp l = 0; 194933965Sjdp } 195033965Sjdp } 195133965Sjdp } 195233965Sjdp } 195333965Sjdp } 195433965Sjdp 195533965Sjdp 195633965Sjdp /* Add to the output file a way of getting to the exported names 195760484Sobrien without using the import library. */ 195833965Sjdp if (add_indirect) 195933965Sjdp { 196033965Sjdp fprintf (f, "\t.section\t.rdata\n"); 196133965Sjdp for (i = 0, exp = d_exports; exp; i++, exp = exp->next) 196233965Sjdp if (!exp->noname || show_allnames) 196333965Sjdp { 196438889Sjdp /* We use a single underscore for MS compatibility, and a 196538889Sjdp double underscore for backward compatibility with old 196638889Sjdp cygwin releases. */ 196760484Sobrien if (create_compat_implib) 196860484Sobrien fprintf (f, "\t%s\t__imp_%s\n", ASM_GLOBAL, exp->name); 196938889Sjdp fprintf (f, "\t%s\t_imp__%s\n", ASM_GLOBAL, exp->name); 197060484Sobrien if (create_compat_implib) 197160484Sobrien fprintf (f, "__imp_%s:\n", exp->name); 197238889Sjdp fprintf (f, "_imp__%s:\n", exp->name); 197333965Sjdp fprintf (f, "\t%s\t%s\n", ASM_LONG, exp->name); 197433965Sjdp } 197533965Sjdp } 197633965Sjdp 1977130561Sobrien /* Dump the reloc section if a base file is provided. */ 197833965Sjdp if (base_file) 197933965Sjdp { 198033965Sjdp int addr; 198133965Sjdp long need[PAGE_SIZE]; 198233965Sjdp long page_addr; 198333965Sjdp int numbytes; 198433965Sjdp int num_entries; 198533965Sjdp long *copy; 198633965Sjdp int j; 198733965Sjdp int on_page; 198833965Sjdp fprintf (f, "\t.section\t.init\n"); 198933965Sjdp fprintf (f, "lab:\n"); 199033965Sjdp 199133965Sjdp fseek (base_file, 0, SEEK_END); 199233965Sjdp numbytes = ftell (base_file); 199333965Sjdp fseek (base_file, 0, SEEK_SET); 199433965Sjdp copy = xmalloc (numbytes); 199533965Sjdp fread (copy, 1, numbytes, base_file); 199633965Sjdp num_entries = numbytes / sizeof (long); 199733965Sjdp 199833965Sjdp 199933965Sjdp fprintf (f, "\t.section\t.reloc\n"); 200033965Sjdp if (num_entries) 200133965Sjdp { 200233965Sjdp int src; 200333965Sjdp int dst = 0; 200433965Sjdp int last = -1; 200533965Sjdp qsort (copy, num_entries, sizeof (long), sfunc); 2006130561Sobrien /* Delete duplicates */ 200733965Sjdp for (src = 0; src < num_entries; src++) 200833965Sjdp { 200960484Sobrien if (last != copy[src]) 201033965Sjdp last = copy[dst++] = copy[src]; 201133965Sjdp } 201233965Sjdp num_entries = dst; 201333965Sjdp addr = copy[0]; 201433965Sjdp page_addr = addr & PAGE_MASK; /* work out the page addr */ 201533965Sjdp on_page = 0; 201633965Sjdp for (j = 0; j < num_entries; j++) 201733965Sjdp { 201833965Sjdp addr = copy[j]; 201933965Sjdp if ((addr & PAGE_MASK) != page_addr) 202033965Sjdp { 202133965Sjdp flush_page (f, need, page_addr, on_page); 202233965Sjdp on_page = 0; 202333965Sjdp page_addr = addr & PAGE_MASK; 202433965Sjdp } 202533965Sjdp need[on_page++] = addr; 202633965Sjdp } 202733965Sjdp flush_page (f, need, page_addr, on_page); 202833965Sjdp 202933965Sjdp/* fprintf (f, "\t%s\t0,0\t%s End\n", ASM_LONG, ASM_C);*/ 203033965Sjdp } 203133965Sjdp } 203233965Sjdp 203360484Sobrien generate_idata_ofile (f); 203460484Sobrien 203533965Sjdp fclose (f); 203633965Sjdp 2037130561Sobrien /* Assemble the file. */ 203860484Sobrien assemble_file (TMP_ASM, exp_name); 203960484Sobrien 204033965Sjdp if (dontdeltemps == 0) 204160484Sobrien unlink (TMP_ASM); 2042104834Sobrien 204360484Sobrien inform (_("Generated exports file")); 204433965Sjdp} 204533965Sjdp 204638889Sjdpstatic const char * 2047130561Sobrienxlate (const char *name) 204833965Sjdp{ 2049130561Sobrien int lead_at = (*name == '@'); 2050130561Sobrien 2051218822Sdim if (!lead_at && (add_underscore 2052218822Sdim || (add_stdcall_underscore 2053218822Sdim && strchr (name, '@')))) 205433965Sjdp { 205533965Sjdp char *copy = xmalloc (strlen (name) + 2); 2056130561Sobrien 205733965Sjdp copy[0] = '_'; 205833965Sjdp strcpy (copy + 1, name); 205933965Sjdp name = copy; 206033965Sjdp } 206133965Sjdp 206233965Sjdp if (killat) 206333965Sjdp { 206433965Sjdp char *p; 2065130561Sobrien 2066130561Sobrien name += lead_at; 206733965Sjdp p = strchr (name, '@'); 206833965Sjdp if (p) 206933965Sjdp *p = 0; 207033965Sjdp } 207133965Sjdp return name; 207233965Sjdp} 207333965Sjdp 207460484Sobrientypedef struct 207533965Sjdp{ 207633965Sjdp int id; 207733965Sjdp const char *name; 207833965Sjdp int flags; 207933965Sjdp int align; 208033965Sjdp asection *sec; 208133965Sjdp asymbol *sym; 208233965Sjdp asymbol **sympp; 208333965Sjdp int size; 2084130561Sobrien unsigned char *data; 208533965Sjdp} sinfo; 208633965Sjdp 208733965Sjdp#ifndef DLLTOOL_PPC 208833965Sjdp 208933965Sjdp#define TEXT 0 209033965Sjdp#define DATA 1 209133965Sjdp#define BSS 2 209233965Sjdp#define IDATA7 3 209333965Sjdp#define IDATA5 4 209433965Sjdp#define IDATA4 5 209533965Sjdp#define IDATA6 6 209633965Sjdp 209733965Sjdp#define NSECS 7 209833965Sjdp 209989857Sobrien#define TEXT_SEC_FLAGS \ 210089857Sobrien (SEC_ALLOC | SEC_LOAD | SEC_CODE | SEC_READONLY | SEC_HAS_CONTENTS) 210189857Sobrien#define DATA_SEC_FLAGS (SEC_ALLOC | SEC_LOAD | SEC_DATA) 210289857Sobrien#define BSS_SEC_FLAGS SEC_ALLOC 210389857Sobrien 210489857Sobrien#define INIT_SEC_DATA(id, name, flags, align) \ 210589857Sobrien { id, name, flags, align, NULL, NULL, NULL, 0, NULL } 210660484Sobrienstatic sinfo secdata[NSECS] = 210733965Sjdp{ 210889857Sobrien INIT_SEC_DATA (TEXT, ".text", TEXT_SEC_FLAGS, 2), 210989857Sobrien INIT_SEC_DATA (DATA, ".data", DATA_SEC_FLAGS, 2), 211089857Sobrien INIT_SEC_DATA (BSS, ".bss", BSS_SEC_FLAGS, 2), 211189857Sobrien INIT_SEC_DATA (IDATA7, ".idata$7", SEC_HAS_CONTENTS, 2), 211289857Sobrien INIT_SEC_DATA (IDATA5, ".idata$5", SEC_HAS_CONTENTS, 2), 211389857Sobrien INIT_SEC_DATA (IDATA4, ".idata$4", SEC_HAS_CONTENTS, 2), 211489857Sobrien INIT_SEC_DATA (IDATA6, ".idata$6", SEC_HAS_CONTENTS, 1) 211533965Sjdp}; 211633965Sjdp 211760484Sobrien#else 211833965Sjdp 2119130561Sobrien/* Sections numbered to make the order the same as other PowerPC NT 2120130561Sobrien compilers. This also keeps funny alignment thingies from happening. */ 212133965Sjdp#define TEXT 0 212233965Sjdp#define PDATA 1 212333965Sjdp#define RDATA 2 212433965Sjdp#define IDATA5 3 212533965Sjdp#define IDATA4 4 212633965Sjdp#define IDATA6 5 212733965Sjdp#define IDATA7 6 212833965Sjdp#define DATA 7 212933965Sjdp#define BSS 8 213033965Sjdp 213133965Sjdp#define NSECS 9 213233965Sjdp 213360484Sobrienstatic sinfo secdata[NSECS] = 213433965Sjdp{ 213533965Sjdp { TEXT, ".text", SEC_CODE | SEC_HAS_CONTENTS, 3}, 213633965Sjdp { PDATA, ".pdata", SEC_HAS_CONTENTS, 2}, 213733965Sjdp { RDATA, ".reldata", SEC_HAS_CONTENTS, 2}, 213833965Sjdp { IDATA5, ".idata$5", SEC_HAS_CONTENTS, 2}, 213933965Sjdp { IDATA4, ".idata$4", SEC_HAS_CONTENTS, 2}, 214033965Sjdp { IDATA6, ".idata$6", SEC_HAS_CONTENTS, 1}, 214133965Sjdp { IDATA7, ".idata$7", SEC_HAS_CONTENTS, 2}, 214233965Sjdp { DATA, ".data", SEC_DATA, 2}, 214333965Sjdp { BSS, ".bss", 0, 2} 214433965Sjdp}; 214533965Sjdp 214633965Sjdp#endif 214733965Sjdp 2148130561Sobrien/* This is what we're trying to make. We generate the imp symbols with 2149130561Sobrien both single and double underscores, for compatibility. 215033965Sjdp 215133965Sjdp .text 215233965Sjdp .global _GetFileVersionInfoSizeW@8 215333965Sjdp .global __imp_GetFileVersionInfoSizeW@8 215433965Sjdp_GetFileVersionInfoSizeW@8: 215533965Sjdp jmp * __imp_GetFileVersionInfoSizeW@8 215633965Sjdp .section .idata$7 # To force loading of head 215733965Sjdp .long __version_a_head 215833965Sjdp# Import Address Table 215933965Sjdp .section .idata$5 216033965Sjdp__imp_GetFileVersionInfoSizeW@8: 216133965Sjdp .rva ID2 216233965Sjdp 216333965Sjdp# Import Lookup Table 216433965Sjdp .section .idata$4 216533965Sjdp .rva ID2 216633965Sjdp# Hint/Name table 216733965Sjdp .section .idata$6 216833965SjdpID2: .short 2 216933965Sjdp .asciz "GetFileVersionInfoSizeW" 217033965Sjdp 217133965Sjdp 2172130561Sobrien For the PowerPC, here's the variation on the above scheme: 217333965Sjdp 217460484Sobrien# Rather than a simple "jmp *", the code to get to the dll function 217533965Sjdp# looks like: 217633965Sjdp .text 217733965Sjdp lwz r11,[tocv]__imp_function_name(r2) 217833965Sjdp# RELOC: 00000000 TOCREL16,TOCDEFN __imp_function_name 217933965Sjdp lwz r12,0(r11) 218033965Sjdp stw r2,4(r1) 218133965Sjdp mtctr r12 218233965Sjdp lwz r2,4(r11) 2183130561Sobrien bctr */ 218433965Sjdp 218533965Sjdpstatic char * 2186130561Sobrienmake_label (const char *prefix, const char *name) 218733965Sjdp{ 2188218822Sdim int len = strlen (ASM_PREFIX (name)) + strlen (prefix) + strlen (name); 2189218822Sdim char *copy = xmalloc (len + 1); 2190130561Sobrien 2191218822Sdim strcpy (copy, ASM_PREFIX (name)); 219233965Sjdp strcat (copy, prefix); 219333965Sjdp strcat (copy, name); 219433965Sjdp return copy; 219533965Sjdp} 219633965Sjdp 2197130561Sobrienstatic char * 2198130561Sobrienmake_imp_label (const char *prefix, const char *name) 2199130561Sobrien{ 2200130561Sobrien int len; 2201130561Sobrien char *copy; 2202130561Sobrien 2203130561Sobrien if (name[0] == '@') 2204130561Sobrien { 2205130561Sobrien len = strlen (prefix) + strlen (name); 2206130561Sobrien copy = xmalloc (len + 1); 2207130561Sobrien strcpy (copy, prefix); 2208130561Sobrien strcat (copy, name); 2209130561Sobrien } 2210130561Sobrien else 2211130561Sobrien { 2212218822Sdim len = strlen (ASM_PREFIX (name)) + strlen (prefix) + strlen (name); 2213130561Sobrien copy = xmalloc (len + 1); 2214130561Sobrien strcpy (copy, prefix); 2215218822Sdim strcat (copy, ASM_PREFIX (name)); 2216130561Sobrien strcat (copy, name); 2217130561Sobrien } 2218130561Sobrien return copy; 2219130561Sobrien} 2220130561Sobrien 222133965Sjdpstatic bfd * 2222130561Sobrienmake_one_lib_file (export_type *exp, int i) 222333965Sjdp{ 2224218822Sdim bfd * abfd; 2225218822Sdim asymbol * exp_label; 2226218822Sdim asymbol * iname = 0; 2227218822Sdim asymbol * iname2; 2228218822Sdim asymbol * iname_lab; 2229218822Sdim asymbol ** iname_lab_pp; 2230218822Sdim asymbol ** iname_pp; 223133965Sjdp#ifdef DLLTOOL_PPC 2232218822Sdim asymbol ** fn_pp; 2233218822Sdim asymbol ** toc_pp; 223460484Sobrien#define EXTRA 2 223533965Sjdp#endif 223660484Sobrien#ifndef EXTRA 223760484Sobrien#define EXTRA 0 223838889Sjdp#endif 2239218822Sdim asymbol * ptrs[NSECS + 4 + EXTRA + 1]; 2240218822Sdim flagword applicable; 2241218822Sdim char * outname = xmalloc (strlen (TMP_STUB) + 10); 2242218822Sdim int oidx = 0; 224333965Sjdp 224433965Sjdp 2245218822Sdim sprintf (outname, "%s%05d.o", TMP_STUB, i); 2246104834Sobrien 2247218822Sdim abfd = bfd_openw (outname, HOW_BFD_WRITE_TARGET); 2248104834Sobrien 2249218822Sdim if (!abfd) 2250218822Sdim /* xgettext:c-format */ 2251218822Sdim fatal (_("bfd_open failed open stub file: %s"), outname); 2252104834Sobrien 2253218822Sdim /* xgettext:c-format */ 2254218822Sdim inform (_("Creating stub file: %s"), outname); 225533965Sjdp 2256218822Sdim bfd_set_format (abfd, bfd_object); 2257218822Sdim bfd_set_arch_mach (abfd, HOW_BFD_ARCH, 0); 2258104834Sobrien 225960484Sobrien#ifdef DLLTOOL_ARM 2260218822Sdim if (machine == MARM_INTERWORK || machine == MTHUMB) 2261218822Sdim bfd_set_private_flags (abfd, F_INTERWORK); 226260484Sobrien#endif 2263104834Sobrien 2264218822Sdim applicable = bfd_applicable_section_flags (abfd); 2265104834Sobrien 2266218822Sdim /* First make symbols for the sections. */ 2267218822Sdim for (i = 0; i < NSECS; i++) 2268218822Sdim { 2269218822Sdim sinfo *si = secdata + i; 227060484Sobrien 2271218822Sdim if (si->id != i) 2272218822Sdim abort(); 2273218822Sdim si->sec = bfd_make_section_old_way (abfd, si->name); 2274218822Sdim bfd_set_section_flags (abfd, 2275218822Sdim si->sec, 2276218822Sdim si->flags & applicable); 227733965Sjdp 2278218822Sdim bfd_set_section_alignment(abfd, si->sec, si->align); 2279218822Sdim si->sec->output_section = si->sec; 2280218822Sdim si->sym = bfd_make_empty_symbol(abfd); 2281218822Sdim si->sym->name = si->sec->name; 2282218822Sdim si->sym->section = si->sec; 2283218822Sdim si->sym->flags = BSF_LOCAL; 2284218822Sdim si->sym->value = 0; 2285218822Sdim ptrs[oidx] = si->sym; 2286218822Sdim si->sympp = ptrs + oidx; 2287218822Sdim si->size = 0; 2288218822Sdim si->data = NULL; 228933965Sjdp 2290218822Sdim oidx++; 2291218822Sdim } 229233965Sjdp 2293218822Sdim if (! exp->data) 2294218822Sdim { 2295218822Sdim exp_label = bfd_make_empty_symbol (abfd); 2296218822Sdim exp_label->name = make_imp_label ("", exp->name); 2297218822Sdim 2298218822Sdim /* On PowerPC, the function name points to a descriptor in 2299218822Sdim the rdata section, the first element of which is a 2300218822Sdim pointer to the code (..function_name), and the second 2301218822Sdim points to the .toc. */ 230238889Sjdp#ifdef DLLTOOL_PPC 2303218822Sdim if (machine == MPPC) 2304218822Sdim exp_label->section = secdata[RDATA].sec; 2305218822Sdim else 230638889Sjdp#endif 2307218822Sdim exp_label->section = secdata[TEXT].sec; 230833965Sjdp 2309218822Sdim exp_label->flags = BSF_GLOBAL; 2310218822Sdim exp_label->value = 0; 231133965Sjdp 231260484Sobrien#ifdef DLLTOOL_ARM 2313218822Sdim if (machine == MTHUMB) 2314218822Sdim bfd_coff_set_symbol_class (abfd, exp_label, C_THUMBEXTFUNC); 231560484Sobrien#endif 2316218822Sdim ptrs[oidx++] = exp_label; 2317218822Sdim } 231833965Sjdp 2319218822Sdim /* Generate imp symbols with one underscore for Microsoft 2320218822Sdim compatibility, and with two underscores for backward 2321218822Sdim compatibility with old versions of cygwin. */ 2322218822Sdim if (create_compat_implib) 2323218822Sdim { 2324218822Sdim iname = bfd_make_empty_symbol (abfd); 2325218822Sdim iname->name = make_imp_label ("___imp", exp->name); 2326218822Sdim iname->section = secdata[IDATA5].sec; 2327218822Sdim iname->flags = BSF_GLOBAL; 2328218822Sdim iname->value = 0; 2329218822Sdim } 233033965Sjdp 2331218822Sdim iname2 = bfd_make_empty_symbol (abfd); 2332218822Sdim iname2->name = make_imp_label ("__imp_", exp->name); 2333218822Sdim iname2->section = secdata[IDATA5].sec; 2334218822Sdim iname2->flags = BSF_GLOBAL; 2335218822Sdim iname2->value = 0; 233633965Sjdp 2337218822Sdim iname_lab = bfd_make_empty_symbol (abfd); 233833965Sjdp 2339218822Sdim iname_lab->name = head_label; 2340218822Sdim iname_lab->section = (asection *) &bfd_und_section; 2341218822Sdim iname_lab->flags = 0; 2342218822Sdim iname_lab->value = 0; 234333965Sjdp 2344218822Sdim iname_pp = ptrs + oidx; 2345218822Sdim if (create_compat_implib) 2346218822Sdim ptrs[oidx++] = iname; 2347218822Sdim ptrs[oidx++] = iname2; 234833965Sjdp 2349218822Sdim iname_lab_pp = ptrs + oidx; 2350218822Sdim ptrs[oidx++] = iname_lab; 235133965Sjdp 235233965Sjdp#ifdef DLLTOOL_PPC 2353218822Sdim /* The symbol referring to the code (.text). */ 2354218822Sdim { 2355218822Sdim asymbol *function_name; 235633965Sjdp 2357218822Sdim function_name = bfd_make_empty_symbol(abfd); 2358218822Sdim function_name->name = make_label ("..", exp->name); 2359218822Sdim function_name->section = secdata[TEXT].sec; 2360218822Sdim function_name->flags = BSF_GLOBAL; 2361218822Sdim function_name->value = 0; 236233965Sjdp 2363218822Sdim fn_pp = ptrs + oidx; 2364218822Sdim ptrs[oidx++] = function_name; 2365218822Sdim } 236638889Sjdp 2367218822Sdim /* The .toc symbol. */ 2368218822Sdim { 2369218822Sdim asymbol *toc_symbol; 237033965Sjdp 2371218822Sdim toc_symbol = bfd_make_empty_symbol (abfd); 2372218822Sdim toc_symbol->name = make_label (".", "toc"); 2373218822Sdim toc_symbol->section = (asection *)&bfd_und_section; 2374218822Sdim toc_symbol->flags = BSF_GLOBAL; 2375218822Sdim toc_symbol->value = 0; 237638889Sjdp 2377218822Sdim toc_pp = ptrs + oidx; 2378218822Sdim ptrs[oidx++] = toc_symbol; 2379218822Sdim } 238033965Sjdp#endif 2381104834Sobrien 2382218822Sdim ptrs[oidx] = 0; 238333965Sjdp 2384218822Sdim for (i = 0; i < NSECS; i++) 2385218822Sdim { 2386218822Sdim sinfo *si = secdata + i; 2387218822Sdim asection *sec = si->sec; 2388218822Sdim arelent *rel; 2389218822Sdim arelent **rpp; 2390218822Sdim 2391218822Sdim switch (i) 239233965Sjdp { 2393218822Sdim case TEXT: 2394218822Sdim if (! exp->data) 239533965Sjdp { 2396218822Sdim si->size = HOW_JTAB_SIZE; 2397218822Sdim si->data = xmalloc (HOW_JTAB_SIZE); 2398218822Sdim memcpy (si->data, HOW_JTAB, HOW_JTAB_SIZE); 239960484Sobrien 2400218822Sdim /* Add the reloc into idata$5. */ 2401218822Sdim rel = xmalloc (sizeof (arelent)); 2402104834Sobrien 2403218822Sdim rpp = xmalloc (sizeof (arelent *) * 2); 2404218822Sdim rpp[0] = rel; 2405218822Sdim rpp[1] = 0; 2406104834Sobrien 2407218822Sdim rel->address = HOW_JTAB_ROFF; 2408218822Sdim rel->addend = 0; 240933965Sjdp 2410218822Sdim if (machine == MPPC) 2411218822Sdim { 2412218822Sdim rel->howto = bfd_reloc_type_lookup (abfd, 2413218822Sdim BFD_RELOC_16_GOTOFF); 2414218822Sdim rel->sym_ptr_ptr = iname_pp; 241533965Sjdp } 2416218822Sdim else if (machine == MX86) 241733965Sjdp { 2418218822Sdim rel->howto = bfd_reloc_type_lookup (abfd, 2419218822Sdim BFD_RELOC_32_PCREL); 2420218822Sdim rel->sym_ptr_ptr = iname_pp; 242133965Sjdp } 242260484Sobrien else 242333965Sjdp { 2424218822Sdim rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_32); 2425218822Sdim rel->sym_ptr_ptr = secdata[IDATA5].sympp; 242633965Sjdp } 2427218822Sdim sec->orelocation = rpp; 2428218822Sdim sec->reloc_count = 1; 2429218822Sdim } 2430218822Sdim break; 2431218822Sdim case IDATA4: 2432218822Sdim case IDATA5: 2433218822Sdim /* An idata$4 or idata$5 is one word long, and has an 2434218822Sdim rva to idata$6. */ 243533965Sjdp 2436218822Sdim#ifdef DLLTOOL_MX86_64 2437218822Sdim si->data = xmalloc (8); 2438218822Sdim si->size = 8; 243933965Sjdp 2440218822Sdim if (exp->noname) 2441218822Sdim { 2442218822Sdim si->data[0] = exp->ordinal ; 2443218822Sdim si->data[1] = exp->ordinal >> 8; 2444218822Sdim si->data[2] = exp->ordinal >> 16; 2445218822Sdim si->data[3] = exp->ordinal >> 24; 2446218822Sdim si->data[4] = 0; 2447218822Sdim si->data[5] = 0; 2448218822Sdim si->data[6] = 0; 2449218822Sdim si->data[7] = 0x80; 2450218822Sdim } 2451218822Sdim else 2452218822Sdim { 2453218822Sdim sec->reloc_count = 1; 245433965Sjdp memset (si->data, 0, si->size); 245533965Sjdp rel = xmalloc (sizeof (arelent)); 245633965Sjdp rpp = xmalloc (sizeof (arelent *) * 2); 245733965Sjdp rpp[0] = rel; 2458218822Sdim rpp[1] = 0; 245933965Sjdp rel->address = 0; 246033965Sjdp rel->addend = 0; 246133965Sjdp rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_RVA); 2462218822Sdim rel->sym_ptr_ptr = secdata[IDATA6].sympp; 246333965Sjdp sec->orelocation = rpp; 2464218822Sdim } 2465218822Sdim#else 2466218822Sdim si->data = xmalloc (4); 2467218822Sdim si->size = 4; 2468218822Sdim 2469218822Sdim if (exp->noname) 2470218822Sdim { 2471218822Sdim si->data[0] = exp->ordinal ; 2472218822Sdim si->data[1] = exp->ordinal >> 8; 2473218822Sdim si->data[2] = exp->ordinal >> 16; 2474218822Sdim si->data[3] = 0x80; 2475218822Sdim } 2476218822Sdim else 2477218822Sdim { 247833965Sjdp sec->reloc_count = 1; 2479218822Sdim memset (si->data, 0, si->size); 2480218822Sdim rel = xmalloc (sizeof (arelent)); 2481218822Sdim rpp = xmalloc (sizeof (arelent *) * 2); 2482218822Sdim rpp[0] = rel; 2483218822Sdim rpp[1] = 0; 2484218822Sdim rel->address = 0; 2485218822Sdim rel->addend = 0; 2486218822Sdim rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_RVA); 2487218822Sdim rel->sym_ptr_ptr = secdata[IDATA6].sympp; 2488218822Sdim sec->orelocation = rpp; 2489218822Sdim } 2490218822Sdim#endif 2491218822Sdim break; 249233965Sjdp 2493218822Sdim case IDATA6: 2494218822Sdim if (!exp->noname) 2495218822Sdim { 2496218822Sdim /* This used to add 1 to exp->hint. I don't know 2497218822Sdim why it did that, and it does not match what I see 2498218822Sdim in programs compiled with the MS tools. */ 2499218822Sdim int idx = exp->hint; 2500218822Sdim si->size = strlen (xlate (exp->import_name)) + 3; 2501218822Sdim si->data = xmalloc (si->size); 2502218822Sdim si->data[0] = idx & 0xff; 2503218822Sdim si->data[1] = idx >> 8; 2504218822Sdim strcpy ((char *) si->data + 2, xlate (exp->import_name)); 2505218822Sdim } 2506218822Sdim break; 2507218822Sdim case IDATA7: 2508218822Sdim si->size = 4; 2509218822Sdim si->data = xmalloc (4); 2510218822Sdim memset (si->data, 0, si->size); 2511218822Sdim rel = xmalloc (sizeof (arelent)); 2512218822Sdim rpp = xmalloc (sizeof (arelent *) * 2); 2513218822Sdim rpp[0] = rel; 2514218822Sdim rel->address = 0; 2515218822Sdim rel->addend = 0; 2516218822Sdim rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_RVA); 2517218822Sdim rel->sym_ptr_ptr = iname_lab_pp; 2518218822Sdim sec->orelocation = rpp; 2519218822Sdim sec->reloc_count = 1; 2520218822Sdim break; 2521218822Sdim 252238889Sjdp#ifdef DLLTOOL_PPC 2523218822Sdim case PDATA: 2524218822Sdim { 2525218822Sdim /* The .pdata section is 5 words long. 2526218822Sdim Think of it as: 2527218822Sdim struct 2528218822Sdim { 2529218822Sdim bfd_vma BeginAddress, [0x00] 2530218822Sdim EndAddress, [0x04] 2531218822Sdim ExceptionHandler, [0x08] 2532218822Sdim HandlerData, [0x0c] 2533218822Sdim PrologEndAddress; [0x10] 2534218822Sdim }; */ 253533965Sjdp 2536218822Sdim /* So this pdata section setups up this as a glue linkage to 2537218822Sdim a dll routine. There are a number of house keeping things 2538218822Sdim we need to do: 253933965Sjdp 2540218822Sdim 1. In the name of glue trickery, the ADDR32 relocs for 0, 2541218822Sdim 4, and 0x10 are set to point to the same place: 2542218822Sdim "..function_name". 2543218822Sdim 2. There is one more reloc needed in the pdata section. 2544218822Sdim The actual glue instruction to restore the toc on 2545218822Sdim return is saved as the offset in an IMGLUE reloc. 2546218822Sdim So we need a total of four relocs for this section. 254733965Sjdp 2548218822Sdim 3. Lastly, the HandlerData field is set to 0x03, to indicate 2549218822Sdim that this is a glue routine. */ 2550218822Sdim arelent *imglue, *ba_rel, *ea_rel, *pea_rel; 255133965Sjdp 2552218822Sdim /* Alignment must be set to 2**2 or you get extra stuff. */ 2553218822Sdim bfd_set_section_alignment(abfd, sec, 2); 255433965Sjdp 2555218822Sdim si->size = 4 * 5; 2556218822Sdim si->data = xmalloc (si->size); 2557218822Sdim memset (si->data, 0, si->size); 2558218822Sdim rpp = xmalloc (sizeof (arelent *) * 5); 2559218822Sdim rpp[0] = imglue = xmalloc (sizeof (arelent)); 2560218822Sdim rpp[1] = ba_rel = xmalloc (sizeof (arelent)); 2561218822Sdim rpp[2] = ea_rel = xmalloc (sizeof (arelent)); 2562218822Sdim rpp[3] = pea_rel = xmalloc (sizeof (arelent)); 2563218822Sdim rpp[4] = 0; 256433965Sjdp 2565218822Sdim /* Stick the toc reload instruction in the glue reloc. */ 2566218822Sdim bfd_put_32(abfd, ppc_glue_insn, (char *) &imglue->address); 256733965Sjdp 2568218822Sdim imglue->addend = 0; 2569218822Sdim imglue->howto = bfd_reloc_type_lookup (abfd, 2570218822Sdim BFD_RELOC_32_GOTOFF); 2571218822Sdim imglue->sym_ptr_ptr = fn_pp; 257233965Sjdp 2573218822Sdim ba_rel->address = 0; 2574218822Sdim ba_rel->addend = 0; 2575218822Sdim ba_rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_32); 2576218822Sdim ba_rel->sym_ptr_ptr = fn_pp; 257733965Sjdp 2578218822Sdim bfd_put_32 (abfd, 0x18, si->data + 0x04); 2579218822Sdim ea_rel->address = 4; 2580218822Sdim ea_rel->addend = 0; 2581218822Sdim ea_rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_32); 2582218822Sdim ea_rel->sym_ptr_ptr = fn_pp; 258333965Sjdp 2584218822Sdim /* Mark it as glue. */ 2585218822Sdim bfd_put_32 (abfd, 0x03, si->data + 0x0c); 258633965Sjdp 2587218822Sdim /* Mark the prolog end address. */ 2588218822Sdim bfd_put_32 (abfd, 0x0D, si->data + 0x10); 2589218822Sdim pea_rel->address = 0x10; 2590218822Sdim pea_rel->addend = 0; 2591218822Sdim pea_rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_32); 2592218822Sdim pea_rel->sym_ptr_ptr = fn_pp; 259333965Sjdp 2594218822Sdim sec->orelocation = rpp; 2595218822Sdim sec->reloc_count = 4; 2596218822Sdim break; 2597218822Sdim } 2598218822Sdim case RDATA: 2599218822Sdim /* Each external function in a PowerPC PE file has a two word 2600218822Sdim descriptor consisting of: 2601218822Sdim 1. The address of the code. 2602218822Sdim 2. The address of the appropriate .toc 2603218822Sdim We use relocs to build this. */ 2604218822Sdim si->size = 8; 2605218822Sdim si->data = xmalloc (8); 2606218822Sdim memset (si->data, 0, si->size); 260733965Sjdp 2608218822Sdim rpp = xmalloc (sizeof (arelent *) * 3); 2609218822Sdim rpp[0] = rel = xmalloc (sizeof (arelent)); 2610218822Sdim rpp[1] = xmalloc (sizeof (arelent)); 2611218822Sdim rpp[2] = 0; 261233965Sjdp 2613218822Sdim rel->address = 0; 2614218822Sdim rel->addend = 0; 2615218822Sdim rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_32); 2616218822Sdim rel->sym_ptr_ptr = fn_pp; 261733965Sjdp 2618218822Sdim rel = rpp[1]; 261933965Sjdp 2620218822Sdim rel->address = 4; 2621218822Sdim rel->addend = 0; 2622218822Sdim rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_32); 2623218822Sdim rel->sym_ptr_ptr = toc_pp; 262433965Sjdp 2625218822Sdim sec->orelocation = rpp; 2626218822Sdim sec->reloc_count = 2; 2627218822Sdim break; 262838889Sjdp#endif /* DLLTOOL_PPC */ 262933965Sjdp } 2630218822Sdim } 263133965Sjdp 2632218822Sdim { 2633218822Sdim bfd_vma vma = 0; 2634218822Sdim /* Size up all the sections. */ 2635218822Sdim for (i = 0; i < NSECS; i++) 263633965Sjdp { 2637218822Sdim sinfo *si = secdata + i; 263833965Sjdp 2639218822Sdim bfd_set_section_size (abfd, si->sec, si->size); 2640218822Sdim bfd_set_section_vma (abfd, si->sec, vma); 264133965Sjdp } 2642218822Sdim } 2643218822Sdim /* Write them out. */ 2644218822Sdim for (i = 0; i < NSECS; i++) 2645218822Sdim { 2646218822Sdim sinfo *si = secdata + i; 264733965Sjdp 2648218822Sdim if (i == IDATA5 && no_idata5) 2649218822Sdim continue; 265033965Sjdp 2651218822Sdim if (i == IDATA4 && no_idata4) 2652218822Sdim continue; 265333965Sjdp 2654218822Sdim bfd_set_section_contents (abfd, si->sec, 2655218822Sdim si->data, 0, 2656218822Sdim si->size); 2657218822Sdim } 265833965Sjdp 2659218822Sdim bfd_set_symtab (abfd, ptrs, oidx); 2660218822Sdim bfd_close (abfd); 2661218822Sdim abfd = bfd_openr (outname, HOW_BFD_READ_TARGET); 2662218822Sdim return abfd; 266333965Sjdp} 266433965Sjdp 266533965Sjdpstatic bfd * 2666130561Sobrienmake_head (void) 266733965Sjdp{ 266860484Sobrien FILE *f = fopen (TMP_HEAD_S, FOPEN_WT); 266933965Sjdp 267060484Sobrien if (f == NULL) 267160484Sobrien { 267260484Sobrien fatal (_("failed to open temporary head file: %s"), TMP_HEAD_S); 267360484Sobrien return NULL; 267460484Sobrien } 2675104834Sobrien 267633965Sjdp fprintf (f, "%s IMAGE_IMPORT_DESCRIPTOR\n", ASM_C); 267733965Sjdp fprintf (f, "\t.section .idata$2\n"); 267833965Sjdp 267933965Sjdp fprintf(f,"\t%s\t%s\n", ASM_GLOBAL,head_label); 268033965Sjdp 268133965Sjdp fprintf (f, "%s:\n", head_label); 268233965Sjdp 268333965Sjdp fprintf (f, "\t%shname%s\t%sPtr to image import by name list\n", 268433965Sjdp ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C); 268533965Sjdp 268633965Sjdp fprintf (f, "\t%sthis should be the timestamp, but NT sometimes\n", ASM_C); 268733965Sjdp fprintf (f, "\t%sdoesn't load DLLs when this is set.\n", ASM_C); 268833965Sjdp fprintf (f, "\t%s\t0\t%s loaded time\n", ASM_LONG, ASM_C); 268933965Sjdp fprintf (f, "\t%s\t0\t%s Forwarder chain\n", ASM_LONG, ASM_C); 269033965Sjdp fprintf (f, "\t%s__%s_iname%s\t%s imported dll's name\n", 269133965Sjdp ASM_RVA_BEFORE, 269233965Sjdp imp_name_lab, 269333965Sjdp ASM_RVA_AFTER, 269433965Sjdp ASM_C); 269533965Sjdp fprintf (f, "\t%sfthunk%s\t%s pointer to firstthunk\n", 269633965Sjdp ASM_RVA_BEFORE, 269733965Sjdp ASM_RVA_AFTER, ASM_C); 269833965Sjdp 269933965Sjdp fprintf (f, "%sStuff for compatibility\n", ASM_C); 270033965Sjdp 270160484Sobrien if (!no_idata5) 270233965Sjdp { 270333965Sjdp fprintf (f, "\t.section\t.idata$5\n"); 2704218822Sdim#ifdef DLLTOOL_MX86_64 2705218822Sdim fprintf (f,"\t%s\t0\n\t%s\t0\n", ASM_LONG, ASM_LONG); /* NULL terminating list. */ 2706218822Sdim#else 2707218822Sdim fprintf (f,"\t%s\t0\n", ASM_LONG); /* NULL terminating list. */ 2708218822Sdim#endif 270933965Sjdp fprintf (f, "fthunk:\n"); 271033965Sjdp } 2711104834Sobrien 271260484Sobrien if (!no_idata4) 271333965Sjdp { 271433965Sjdp fprintf (f, "\t.section\t.idata$4\n"); 271533965Sjdp fprintf (f, "\t%s\t0\n", ASM_LONG); 271633965Sjdp fprintf (f, "\t.section .idata$4\n"); 271733965Sjdp fprintf (f, "hname:\n"); 271833965Sjdp } 2719104834Sobrien 272033965Sjdp fclose (f); 272133965Sjdp 272260484Sobrien assemble_file (TMP_HEAD_S, TMP_HEAD_O); 272333965Sjdp 272460484Sobrien return bfd_openr (TMP_HEAD_O, HOW_BFD_READ_TARGET); 272533965Sjdp} 272633965Sjdp 272760484Sobrienstatic bfd * 2728130561Sobrienmake_tail (void) 272933965Sjdp{ 273060484Sobrien FILE *f = fopen (TMP_TAIL_S, FOPEN_WT); 273133965Sjdp 273260484Sobrien if (f == NULL) 273333965Sjdp { 273460484Sobrien fatal (_("failed to open temporary tail file: %s"), TMP_TAIL_S); 273560484Sobrien return NULL; 273660484Sobrien } 2737104834Sobrien 273860484Sobrien if (!no_idata4) 273960484Sobrien { 274033965Sjdp fprintf (f, "\t.section .idata$4\n"); 2741218822Sdim#ifdef DLLTOOL_MX86_64 2742218822Sdim fprintf (f,"\t%s\t0\n\t%s\t0\n", ASM_LONG, ASM_LONG); /* NULL terminating list. */ 2743218822Sdim#else 2744218822Sdim fprintf (f,"\t%s\t0\n", ASM_LONG); /* NULL terminating list. */ 2745218822Sdim#endif 274633965Sjdp } 2747104834Sobrien 274860484Sobrien if (!no_idata5) 274933965Sjdp { 275033965Sjdp fprintf (f, "\t.section .idata$5\n"); 2751218822Sdim#ifdef DLLTOOL_MX86_64 2752218822Sdim fprintf (f,"\t%s\t0\n\t%s\t0\n", ASM_LONG, ASM_LONG); /* NULL terminating list. */ 2753218822Sdim#else 2754218822Sdim fprintf (f,"\t%s\t0\n", ASM_LONG); /* NULL terminating list. */ 2755218822Sdim#endif 275633965Sjdp } 275733965Sjdp 275833965Sjdp#ifdef DLLTOOL_PPC 275933965Sjdp /* Normally, we need to see a null descriptor built in idata$3 to 276033965Sjdp act as the terminator for the list. The ideal way, I suppose, 276133965Sjdp would be to mark this section as a comdat type 2 section, so 276233965Sjdp only one would appear in the final .exe (if our linker supported 276333965Sjdp comdat, that is) or cause it to be inserted by something else (say 2764130561Sobrien crt0). */ 276533965Sjdp 276633965Sjdp fprintf (f, "\t.section .idata$3\n"); 276733965Sjdp fprintf (f, "\t%s\t0\n", ASM_LONG); 276833965Sjdp fprintf (f, "\t%s\t0\n", ASM_LONG); 276933965Sjdp fprintf (f, "\t%s\t0\n", ASM_LONG); 277033965Sjdp fprintf (f, "\t%s\t0\n", ASM_LONG); 277133965Sjdp fprintf (f, "\t%s\t0\n", ASM_LONG); 277233965Sjdp#endif 277333965Sjdp 277433965Sjdp#ifdef DLLTOOL_PPC 277533965Sjdp /* Other PowerPC NT compilers use idata$6 for the dllname, so I 2776130561Sobrien do too. Original, huh? */ 277733965Sjdp fprintf (f, "\t.section .idata$6\n"); 277833965Sjdp#else 277933965Sjdp fprintf (f, "\t.section .idata$7\n"); 278033965Sjdp#endif 278133965Sjdp 278233965Sjdp fprintf (f, "\t%s\t__%s_iname\n", ASM_GLOBAL, imp_name_lab); 278333965Sjdp fprintf (f, "__%s_iname:\t%s\t\"%s\"\n", 278433965Sjdp imp_name_lab, ASM_TEXT, dll_name); 278533965Sjdp 278633965Sjdp fclose (f); 278733965Sjdp 278860484Sobrien assemble_file (TMP_TAIL_S, TMP_TAIL_O); 2789104834Sobrien 2790130561Sobrien return bfd_openr (TMP_TAIL_O, HOW_BFD_READ_TARGET); 279133965Sjdp} 279233965Sjdp 279333965Sjdpstatic void 2794130561Sobriengen_lib_file (void) 279533965Sjdp{ 279633965Sjdp int i; 279733965Sjdp export_type *exp; 279833965Sjdp bfd *ar_head; 279933965Sjdp bfd *ar_tail; 280033965Sjdp bfd *outarch; 280133965Sjdp bfd * head = 0; 280233965Sjdp 280333965Sjdp unlink (imp_name); 280433965Sjdp 280560484Sobrien outarch = bfd_openw (imp_name, HOW_BFD_WRITE_TARGET); 280633965Sjdp 280733965Sjdp if (!outarch) 280860484Sobrien /* xgettext:c-format */ 280960484Sobrien fatal (_("Can't open .lib file: %s"), imp_name); 281060484Sobrien 281160484Sobrien /* xgettext:c-format */ 281260484Sobrien inform (_("Creating library file: %s"), imp_name); 2813104834Sobrien 281433965Sjdp bfd_set_format (outarch, bfd_archive); 281533965Sjdp outarch->has_armap = 1; 281633965Sjdp 2817104834Sobrien /* Work out a reasonable size of things to put onto one line. */ 281833965Sjdp ar_head = make_head (); 281933965Sjdp ar_tail = make_tail(); 282033965Sjdp 282160484Sobrien if (ar_head == NULL || ar_tail == NULL) 282260484Sobrien return; 2823104834Sobrien 282433965Sjdp for (i = 0; (exp = d_exports_lexically[i]); i++) 282533965Sjdp { 2826130561Sobrien bfd *n; 2827130561Sobrien /* Don't add PRIVATE entries to import lib. */ 2828130561Sobrien if (exp->private) 2829130561Sobrien continue; 2830130561Sobrien n = make_one_lib_file (exp, i); 2831218822Sdim n->archive_next = head; 283233965Sjdp head = n; 2833218822Sdim if (ext_prefix_alias) 2834218822Sdim { 2835218822Sdim export_type alias_exp; 2836218822Sdim 2837218822Sdim assert (i < PREFIX_ALIAS_BASE); 2838218822Sdim alias_exp.name = make_imp_label (ext_prefix_alias, exp->name); 2839218822Sdim alias_exp.internal_name = exp->internal_name; 2840218822Sdim alias_exp.import_name = exp->name; 2841218822Sdim alias_exp.ordinal = exp->ordinal; 2842218822Sdim alias_exp.constant = exp->constant; 2843218822Sdim alias_exp.noname = exp->noname; 2844218822Sdim alias_exp.private = exp->private; 2845218822Sdim alias_exp.data = exp->data; 2846218822Sdim alias_exp.hint = exp->hint; 2847218822Sdim alias_exp.forward = exp->forward; 2848218822Sdim alias_exp.next = exp->next; 2849218822Sdim n = make_one_lib_file (&alias_exp, i + PREFIX_ALIAS_BASE); 2850218822Sdim n->archive_next = head; 2851218822Sdim head = n; 2852218822Sdim } 285333965Sjdp } 285433965Sjdp 2855130561Sobrien /* Now stick them all into the archive. */ 2856218822Sdim ar_head->archive_next = head; 2857218822Sdim ar_tail->archive_next = ar_head; 285833965Sjdp head = ar_tail; 285933965Sjdp 286038889Sjdp if (! bfd_set_archive_head (outarch, head)) 286138889Sjdp bfd_fatal ("bfd_set_archive_head"); 2862104834Sobrien 286338889Sjdp if (! bfd_close (outarch)) 286438889Sjdp bfd_fatal (imp_name); 286533965Sjdp 286638889Sjdp while (head != NULL) 286738889Sjdp { 2868218822Sdim bfd *n = head->archive_next; 286938889Sjdp bfd_close (head); 287038889Sjdp head = n; 287138889Sjdp } 287238889Sjdp 2873130561Sobrien /* Delete all the temp files. */ 287433965Sjdp if (dontdeltemps == 0) 287533965Sjdp { 287660484Sobrien unlink (TMP_HEAD_O); 287760484Sobrien unlink (TMP_HEAD_S); 287860484Sobrien unlink (TMP_TAIL_O); 287960484Sobrien unlink (TMP_TAIL_S); 288033965Sjdp } 288133965Sjdp 288233965Sjdp if (dontdeltemps < 2) 288338889Sjdp { 288460484Sobrien char *name; 288560484Sobrien 2886130561Sobrien name = (char *) alloca (strlen (TMP_STUB) + 10); 2887130561Sobrien for (i = 0; (exp = d_exports_lexically[i]); i++) 288838889Sjdp { 2889130561Sobrien /* Don't delete non-existent stubs for PRIVATE entries. */ 2890130561Sobrien if (exp->private) 2891130561Sobrien continue; 289260484Sobrien sprintf (name, "%s%05d.o", TMP_STUB, i); 289360484Sobrien if (unlink (name) < 0) 289460484Sobrien /* xgettext:c-format */ 289560484Sobrien non_fatal (_("cannot delete %s: %s"), name, strerror (errno)); 2896218822Sdim if (ext_prefix_alias) 2897218822Sdim { 2898218822Sdim sprintf (name, "%s%05d.o", TMP_STUB, i + PREFIX_ALIAS_BASE); 2899218822Sdim if (unlink (name) < 0) 2900218822Sdim /* xgettext:c-format */ 2901218822Sdim non_fatal (_("cannot delete %s: %s"), name, strerror (errno)); 2902218822Sdim } 290338889Sjdp } 290438889Sjdp } 2905104834Sobrien 290660484Sobrien inform (_("Created lib file")); 290738889Sjdp} 290833965Sjdp 2909130561Sobrien/* Run through the information gathered from the .o files and the 2910130561Sobrien .def file and work out the best stuff. */ 291133965Sjdp 291238889Sjdpstatic int 2913130561Sobrienpfunc (const void *a, const void *b) 291433965Sjdp{ 291533965Sjdp export_type *ap = *(export_type **) a; 291633965Sjdp export_type *bp = *(export_type **) b; 291733965Sjdp if (ap->ordinal == bp->ordinal) 291833965Sjdp return 0; 291933965Sjdp 2920130561Sobrien /* Unset ordinals go to the bottom. */ 292133965Sjdp if (ap->ordinal == -1) 292233965Sjdp return 1; 292333965Sjdp if (bp->ordinal == -1) 292433965Sjdp return -1; 292533965Sjdp return (ap->ordinal - bp->ordinal); 292633965Sjdp} 292733965Sjdp 292838889Sjdpstatic int 2929130561Sobriennfunc (const void *a, const void *b) 293033965Sjdp{ 293133965Sjdp export_type *ap = *(export_type **) a; 293233965Sjdp export_type *bp = *(export_type **) b; 2933218822Sdim const char *an = ap->name; 2934218822Sdim const char *bn = bp->name; 293533965Sjdp 2936218822Sdim if (killat) 2937218822Sdim { 2938218822Sdim an = (an[0] == '@') ? an + 1 : an; 2939218822Sdim bn = (bn[0] == '@') ? bn + 1 : bn; 2940218822Sdim } 2941218822Sdim 2942218822Sdim return (strcmp (an, bn)); 294333965Sjdp} 294433965Sjdp 294538889Sjdpstatic void 2946130561Sobrienremove_null_names (export_type **ptr) 294733965Sjdp{ 294833965Sjdp int src; 294933965Sjdp int dst; 2950130561Sobrien 295133965Sjdp for (dst = src = 0; src < d_nfuncs; src++) 295233965Sjdp { 295333965Sjdp if (ptr[src]) 295433965Sjdp { 295533965Sjdp ptr[dst] = ptr[src]; 295633965Sjdp dst++; 295733965Sjdp } 295833965Sjdp } 295933965Sjdp d_nfuncs = dst; 296033965Sjdp} 296133965Sjdp 296233965Sjdpstatic void 2963130561Sobrienprocess_duplicates (export_type **d_export_vec) 296433965Sjdp{ 296533965Sjdp int more = 1; 296660484Sobrien int i; 2967130561Sobrien 296833965Sjdp while (more) 296933965Sjdp { 297033965Sjdp more = 0; 2971130561Sobrien /* Remove duplicates. */ 297233965Sjdp qsort (d_export_vec, d_nfuncs, sizeof (export_type *), nfunc); 297333965Sjdp 297433965Sjdp for (i = 0; i < d_nfuncs - 1; i++) 297533965Sjdp { 297633965Sjdp if (strcmp (d_export_vec[i]->name, 297733965Sjdp d_export_vec[i + 1]->name) == 0) 297833965Sjdp { 297933965Sjdp export_type *a = d_export_vec[i]; 298033965Sjdp export_type *b = d_export_vec[i + 1]; 298133965Sjdp 298233965Sjdp more = 1; 2983104834Sobrien 298460484Sobrien /* xgettext:c-format */ 298560484Sobrien inform (_("Warning, ignoring duplicate EXPORT %s %d,%d"), 298660484Sobrien a->name, a->ordinal, b->ordinal); 2987104834Sobrien 298833965Sjdp if (a->ordinal != -1 298933965Sjdp && b->ordinal != -1) 299060484Sobrien /* xgettext:c-format */ 299160484Sobrien fatal (_("Error, duplicate EXPORT with oridinals: %s"), 299260484Sobrien a->name); 299333965Sjdp 2994130561Sobrien /* Merge attributes. */ 299533965Sjdp b->ordinal = a->ordinal > 0 ? a->ordinal : b->ordinal; 299633965Sjdp b->constant |= a->constant; 299733965Sjdp b->noname |= a->noname; 299838889Sjdp b->data |= a->data; 299933965Sjdp d_export_vec[i] = 0; 300033965Sjdp } 300133965Sjdp 300233965Sjdp remove_null_names (d_export_vec); 300333965Sjdp } 300433965Sjdp } 300533965Sjdp 3006130561Sobrien /* Count the names. */ 300733965Sjdp for (i = 0; i < d_nfuncs; i++) 3008130561Sobrien if (!d_export_vec[i]->noname) 3009130561Sobrien d_named_nfuncs++; 301033965Sjdp} 301133965Sjdp 301233965Sjdpstatic void 3013130561Sobrienfill_ordinals (export_type **d_export_vec) 301433965Sjdp{ 301533965Sjdp int lowest = -1; 301633965Sjdp int i; 301733965Sjdp char *ptr; 301833965Sjdp int size = 65536; 301933965Sjdp 302033965Sjdp qsort (d_export_vec, d_nfuncs, sizeof (export_type *), pfunc); 302133965Sjdp 3022130561Sobrien /* Fill in the unset ordinals with ones from our range. */ 302333965Sjdp ptr = (char *) xmalloc (size); 302433965Sjdp 302533965Sjdp memset (ptr, 0, size); 302633965Sjdp 3027130561Sobrien /* Mark in our large vector all the numbers that are taken. */ 302833965Sjdp for (i = 0; i < d_nfuncs; i++) 302933965Sjdp { 303033965Sjdp if (d_export_vec[i]->ordinal != -1) 303133965Sjdp { 303233965Sjdp ptr[d_export_vec[i]->ordinal] = 1; 3033130561Sobrien 303433965Sjdp if (lowest == -1 || d_export_vec[i]->ordinal < lowest) 3035130561Sobrien lowest = d_export_vec[i]->ordinal; 303633965Sjdp } 303733965Sjdp } 303833965Sjdp 303933965Sjdp /* Start at 1 for compatibility with MS toolchain. */ 304033965Sjdp if (lowest == -1) 304133965Sjdp lowest = 1; 304233965Sjdp 3043104834Sobrien /* Now fill in ordinals where the user wants us to choose. */ 304433965Sjdp for (i = 0; i < d_nfuncs; i++) 304533965Sjdp { 304633965Sjdp if (d_export_vec[i]->ordinal == -1) 304733965Sjdp { 3048130561Sobrien int j; 304933965Sjdp 3050104834Sobrien /* First try within or after any user supplied range. */ 305133965Sjdp for (j = lowest; j < size; j++) 305233965Sjdp if (ptr[j] == 0) 305333965Sjdp { 305433965Sjdp ptr[j] = 1; 305533965Sjdp d_export_vec[i]->ordinal = j; 305633965Sjdp goto done; 305733965Sjdp } 305833965Sjdp 3059104834Sobrien /* Then try before the range. */ 306033965Sjdp for (j = lowest; j >0; j--) 306133965Sjdp if (ptr[j] == 0) 306233965Sjdp { 306333965Sjdp ptr[j] = 1; 306433965Sjdp d_export_vec[i]->ordinal = j; 306533965Sjdp goto done; 306633965Sjdp } 306733965Sjdp done:; 306833965Sjdp } 306933965Sjdp } 307033965Sjdp 307133965Sjdp free (ptr); 307233965Sjdp 3073130561Sobrien /* And resort. */ 307433965Sjdp qsort (d_export_vec, d_nfuncs, sizeof (export_type *), pfunc); 307533965Sjdp 307633965Sjdp /* Work out the lowest and highest ordinal numbers. */ 307760484Sobrien if (d_nfuncs) 307833965Sjdp { 307933965Sjdp if (d_export_vec[0]) 308033965Sjdp d_low_ord = d_export_vec[0]->ordinal; 308133965Sjdp if (d_export_vec[d_nfuncs-1]) 308233965Sjdp d_high_ord = d_export_vec[d_nfuncs-1]->ordinal; 308333965Sjdp } 308433965Sjdp} 308533965Sjdp 308638889Sjdpstatic void 3087130561Sobrienmangle_defs (void) 308833965Sjdp{ 3089130561Sobrien /* First work out the minimum ordinal chosen. */ 309033965Sjdp export_type *exp; 309133965Sjdp 309233965Sjdp int i; 309333965Sjdp int hint = 0; 3094130561Sobrien export_type **d_export_vec = xmalloc (sizeof (export_type *) * d_nfuncs); 309533965Sjdp 309660484Sobrien inform (_("Processing definitions")); 3097104834Sobrien 309833965Sjdp for (i = 0, exp = d_exports; exp; i++, exp = exp->next) 3099130561Sobrien d_export_vec[i] = exp; 310033965Sjdp 310133965Sjdp process_duplicates (d_export_vec); 310233965Sjdp fill_ordinals (d_export_vec); 310333965Sjdp 3104130561Sobrien /* Put back the list in the new order. */ 310533965Sjdp d_exports = 0; 310633965Sjdp for (i = d_nfuncs - 1; i >= 0; i--) 310733965Sjdp { 310833965Sjdp d_export_vec[i]->next = d_exports; 310933965Sjdp d_exports = d_export_vec[i]; 311033965Sjdp } 311133965Sjdp 3112130561Sobrien /* Build list in alpha order. */ 311360484Sobrien d_exports_lexically = (export_type **) 311460484Sobrien xmalloc (sizeof (export_type *) * (d_nfuncs + 1)); 311533965Sjdp 311633965Sjdp for (i = 0, exp = d_exports; exp; i++, exp = exp->next) 3117130561Sobrien d_exports_lexically[i] = exp; 3118130561Sobrien 311933965Sjdp d_exports_lexically[i] = 0; 312033965Sjdp 3121218822Sdim qsort (d_exports_lexically, i, sizeof (export_type *), nfunc); 312233965Sjdp 3123130561Sobrien /* Fill exp entries with their hint values. */ 312433965Sjdp for (i = 0; i < d_nfuncs; i++) 3125130561Sobrien if (!d_exports_lexically[i]->noname || show_allnames) 3126130561Sobrien d_exports_lexically[i]->hint = hint++; 3127104834Sobrien 312860484Sobrien inform (_("Processed definitions")); 312933965Sjdp} 313033965Sjdp 313138889Sjdpstatic void 3132130561Sobrienusage (FILE *file, int status) 313333965Sjdp{ 313460484Sobrien /* xgetext:c-format */ 313589857Sobrien fprintf (file, _("Usage %s <option(s)> <object-file(s)>\n"), program_name); 313660484Sobrien /* xgetext:c-format */ 313760484Sobrien fprintf (file, _(" -m --machine <machine> Create as DLL for <machine>. [default: %s]\n"), mname); 313860484Sobrien fprintf (file, _(" possible <machine>: arm[_interwork], i386, mcore[-elf]{-le|-be}, ppc, thumb\n")); 313960484Sobrien fprintf (file, _(" -e --output-exp <outname> Generate an export file.\n")); 314060484Sobrien fprintf (file, _(" -l --output-lib <outname> Generate an interface library.\n")); 314160484Sobrien fprintf (file, _(" -a --add-indirect Add dll indirects to export file.\n")); 314260484Sobrien fprintf (file, _(" -D --dllname <name> Name of input dll to put into interface lib.\n")); 314360484Sobrien fprintf (file, _(" -d --input-def <deffile> Name of .def file to be read in.\n")); 314460484Sobrien fprintf (file, _(" -z --output-def <deffile> Name of .def file to be created.\n")); 314560484Sobrien fprintf (file, _(" --export-all-symbols Export all symbols to .def\n")); 314660484Sobrien fprintf (file, _(" --no-export-all-symbols Only export listed symbols\n")); 314760484Sobrien fprintf (file, _(" --exclude-symbols <list> Don't export <list>\n")); 314860484Sobrien fprintf (file, _(" --no-default-excludes Clear default exclude symbols\n")); 314960484Sobrien fprintf (file, _(" -b --base-file <basefile> Read linker generated base file.\n")); 315060484Sobrien fprintf (file, _(" -x --no-idata4 Don't generate idata$4 section.\n")); 315160484Sobrien fprintf (file, _(" -c --no-idata5 Don't generate idata$5 section.\n")); 3152218822Sdim fprintf (file, _(" -U --add-underscore Add underscores to all symbols in interface library.\n")); 3153218822Sdim fprintf (file, _(" --add-stdcall-underscore Add underscores to stdcall symbols in interface library.\n")); 315460484Sobrien fprintf (file, _(" -k --kill-at Kill @<n> from exported names.\n")); 315560484Sobrien fprintf (file, _(" -A --add-stdcall-alias Add aliases without @<n>.\n")); 3156218822Sdim fprintf (file, _(" -p --ext-prefix-alias <prefix> Add aliases with <prefix>.\n")); 315760484Sobrien fprintf (file, _(" -S --as <name> Use <name> for assembler.\n")); 315860484Sobrien fprintf (file, _(" -f --as-flags <flags> Pass <flags> to the assembler.\n")); 315960484Sobrien fprintf (file, _(" -C --compat-implib Create backward compatible import library.\n")); 316060484Sobrien fprintf (file, _(" -n --no-delete Keep temp files (repeat for extra preservation).\n")); 3161130561Sobrien fprintf (file, _(" -t --temp-prefix <prefix> Use <prefix> to construct temp file names.\n")); 316260484Sobrien fprintf (file, _(" -v --verbose Be verbose.\n")); 316360484Sobrien fprintf (file, _(" -V --version Display the program version.\n")); 316460484Sobrien fprintf (file, _(" -h --help Display this information.\n")); 3165218822Sdim fprintf (file, _(" @<file> Read options from <file>.\n")); 316660484Sobrien#ifdef DLLTOOL_MCORE_ELF 316760484Sobrien fprintf (file, _(" -M --mcore-elf <outname> Process mcore-elf object files into <outname>.\n")); 316860484Sobrien fprintf (file, _(" -L --linker <name> Use <name> as the linker.\n")); 316960484Sobrien fprintf (file, _(" -F --linker-flags <flags> Pass <flags> to the linker.\n")); 317060484Sobrien#endif 3171218822Sdim if (REPORT_BUGS_TO[0] && status == 0) 3172218822Sdim fprintf (file, _("Report bugs to %s\n"), REPORT_BUGS_TO); 317333965Sjdp exit (status); 317433965Sjdp} 317533965Sjdp 317660484Sobrien#define OPTION_EXPORT_ALL_SYMS 150 317760484Sobrien#define OPTION_NO_EXPORT_ALL_SYMS (OPTION_EXPORT_ALL_SYMS + 1) 317860484Sobrien#define OPTION_EXCLUDE_SYMS (OPTION_NO_EXPORT_ALL_SYMS + 1) 317960484Sobrien#define OPTION_NO_DEFAULT_EXCLUDES (OPTION_EXCLUDE_SYMS + 1) 3180218822Sdim#define OPTION_ADD_STDCALL_UNDERSCORE (OPTION_NO_DEFAULT_EXCLUDES + 1) 318160484Sobrien 318238889Sjdpstatic const struct option long_options[] = 318333965Sjdp{ 318460484Sobrien {"no-delete", no_argument, NULL, 'n'}, 318533965Sjdp {"dllname", required_argument, NULL, 'D'}, 318660484Sobrien {"no-idata4", no_argument, NULL, 'x'}, 318760484Sobrien {"no-idata5", no_argument, NULL, 'c'}, 318833965Sjdp {"output-exp", required_argument, NULL, 'e'}, 318933965Sjdp {"output-def", required_argument, NULL, 'z'}, 319060484Sobrien {"export-all-symbols", no_argument, NULL, OPTION_EXPORT_ALL_SYMS}, 319160484Sobrien {"no-export-all-symbols", no_argument, NULL, OPTION_NO_EXPORT_ALL_SYMS}, 319260484Sobrien {"exclude-symbols", required_argument, NULL, OPTION_EXCLUDE_SYMS}, 319360484Sobrien {"no-default-excludes", no_argument, NULL, OPTION_NO_DEFAULT_EXCLUDES}, 319433965Sjdp {"output-lib", required_argument, NULL, 'l'}, 3195130561Sobrien {"def", required_argument, NULL, 'd'}, /* for compatibility with older versions */ 319660484Sobrien {"input-def", required_argument, NULL, 'd'}, 319733965Sjdp {"add-underscore", no_argument, NULL, 'U'}, 3198218822Sdim {"add-stdcall-underscore", no_argument, NULL, OPTION_ADD_STDCALL_UNDERSCORE}, 319960484Sobrien {"kill-at", no_argument, NULL, 'k'}, 320060484Sobrien {"add-stdcall-alias", no_argument, NULL, 'A'}, 3201218822Sdim {"ext-prefix-alias", required_argument, NULL, 'p'}, 320260484Sobrien {"verbose", no_argument, NULL, 'v'}, 320360484Sobrien {"version", no_argument, NULL, 'V'}, 320433965Sjdp {"help", no_argument, NULL, 'h'}, 320533965Sjdp {"machine", required_argument, NULL, 'm'}, 320633965Sjdp {"add-indirect", no_argument, NULL, 'a'}, 320733965Sjdp {"base-file", required_argument, NULL, 'b'}, 320833965Sjdp {"as", required_argument, NULL, 'S'}, 320960484Sobrien {"as-flags", required_argument, NULL, 'f'}, 321060484Sobrien {"mcore-elf", required_argument, NULL, 'M'}, 321160484Sobrien {"compat-implib", no_argument, NULL, 'C'}, 3212130561Sobrien {"temp-prefix", required_argument, NULL, 't'}, 321360484Sobrien {NULL,0,NULL,0} 321433965Sjdp}; 321533965Sjdp 3216130561Sobrienint main (int, char **); 321799461Sobrien 321833965Sjdpint 3219130561Sobrienmain (int ac, char **av) 322033965Sjdp{ 322133965Sjdp int c; 322233965Sjdp int i; 322333965Sjdp char *firstarg = 0; 322433965Sjdp program_name = av[0]; 322533965Sjdp oav = av; 322633965Sjdp 322760484Sobrien#if defined (HAVE_SETLOCALE) && defined (HAVE_LC_MESSAGES) 322860484Sobrien setlocale (LC_MESSAGES, ""); 322960484Sobrien#endif 323089857Sobrien#if defined (HAVE_SETLOCALE) 323189857Sobrien setlocale (LC_CTYPE, ""); 323289857Sobrien#endif 323360484Sobrien bindtextdomain (PACKAGE, LOCALEDIR); 323460484Sobrien textdomain (PACKAGE); 323560484Sobrien 3236218822Sdim expandargv (&ac, &av); 3237218822Sdim 323860484Sobrien while ((c = getopt_long (ac, av, 3239104834Sobrien#ifdef DLLTOOL_MCORE_ELF 3240218822Sdim "m:e:l:aD:d:z:b:xp:cCuUkAS:f:nvVHhM:L:F:", 324160484Sobrien#else 3242218822Sdim "m:e:l:aD:d:z:b:xp:cCuUkAS:f:nvVHh", 324360484Sobrien#endif 324460484Sobrien long_options, 0)) 324533965Sjdp != EOF) 324633965Sjdp { 324733965Sjdp switch (c) 324833965Sjdp { 324960484Sobrien case OPTION_EXPORT_ALL_SYMS: 3250130561Sobrien export_all_symbols = TRUE; 325160484Sobrien break; 325260484Sobrien case OPTION_NO_EXPORT_ALL_SYMS: 3253130561Sobrien export_all_symbols = FALSE; 325460484Sobrien break; 325560484Sobrien case OPTION_EXCLUDE_SYMS: 325660484Sobrien add_excludes (optarg); 325760484Sobrien break; 325860484Sobrien case OPTION_NO_DEFAULT_EXCLUDES: 3259130561Sobrien do_default_excludes = FALSE; 326060484Sobrien break; 3261218822Sdim case OPTION_ADD_STDCALL_UNDERSCORE: 3262218822Sdim add_stdcall_underscore = 1; 3263218822Sdim break; 326460484Sobrien case 'x': 326533965Sjdp no_idata4 = 1; 326633965Sjdp break; 326760484Sobrien case 'c': 326833965Sjdp no_idata5 = 1; 326933965Sjdp break; 327033965Sjdp case 'S': 327133965Sjdp as_name = optarg; 327233965Sjdp break; 3273130561Sobrien case 't': 3274130561Sobrien tmp_prefix = optarg; 3275130561Sobrien break; 327660484Sobrien case 'f': 327760484Sobrien as_flags = optarg; 327860484Sobrien break; 327933965Sjdp 3280130561Sobrien /* Ignored for compatibility. */ 328133965Sjdp case 'u': 328233965Sjdp break; 328333965Sjdp case 'a': 328433965Sjdp add_indirect = 1; 328533965Sjdp break; 328633965Sjdp case 'z': 328733965Sjdp output_def = fopen (optarg, FOPEN_WT); 328833965Sjdp break; 328933965Sjdp case 'D': 3290218822Sdim dll_name = (char*) lbasename (optarg); 3291218822Sdim if (dll_name != optarg) 3292218822Sdim non_fatal (_("Path components stripped from dllname, '%s'."), 3293218822Sdim optarg); 329433965Sjdp break; 329533965Sjdp case 'l': 329633965Sjdp imp_name = optarg; 329733965Sjdp break; 329833965Sjdp case 'e': 329933965Sjdp exp_name = optarg; 330033965Sjdp break; 330189857Sobrien case 'H': 330233965Sjdp case 'h': 330360484Sobrien usage (stdout, 0); 330433965Sjdp break; 330533965Sjdp case 'm': 330633965Sjdp mname = optarg; 330733965Sjdp break; 330833965Sjdp case 'v': 330933965Sjdp verbose = 1; 331033965Sjdp break; 331160484Sobrien case 'V': 331260484Sobrien print_version (program_name); 331333965Sjdp break; 331433965Sjdp case 'U': 331533965Sjdp add_underscore = 1; 331633965Sjdp break; 331733965Sjdp case 'k': 331833965Sjdp killat = 1; 331933965Sjdp break; 332060484Sobrien case 'A': 332160484Sobrien add_stdcall_alias = 1; 332260484Sobrien break; 3323218822Sdim case 'p': 3324218822Sdim ext_prefix_alias = optarg; 3325218822Sdim break; 332633965Sjdp case 'd': 332733965Sjdp def_file = optarg; 332833965Sjdp break; 332933965Sjdp case 'n': 333033965Sjdp dontdeltemps++; 333133965Sjdp break; 333233965Sjdp case 'b': 333333965Sjdp base_file = fopen (optarg, FOPEN_RB); 3334104834Sobrien 333533965Sjdp if (!base_file) 333660484Sobrien /* xgettext:c-format */ 333760484Sobrien fatal (_("Unable to open base-file: %s"), optarg); 333860484Sobrien 333933965Sjdp break; 334060484Sobrien#ifdef DLLTOOL_MCORE_ELF 334160484Sobrien case 'M': 334260484Sobrien mcore_elf_out_file = optarg; 334360484Sobrien break; 334460484Sobrien case 'L': 334560484Sobrien mcore_elf_linker = optarg; 334660484Sobrien break; 334760484Sobrien case 'F': 334860484Sobrien mcore_elf_linker_flags = optarg; 334960484Sobrien break; 335060484Sobrien#endif 335160484Sobrien case 'C': 335260484Sobrien create_compat_implib = 1; 335360484Sobrien break; 335433965Sjdp default: 335533965Sjdp usage (stderr, 1); 335660484Sobrien break; 335733965Sjdp } 335833965Sjdp } 335933965Sjdp 3360130561Sobrien if (!tmp_prefix) 3361130561Sobrien tmp_prefix = prefix_encode ("d", getpid ()); 3362130561Sobrien 336333965Sjdp for (i = 0; mtable[i].type; i++) 336460484Sobrien if (strcmp (mtable[i].type, mname) == 0) 336560484Sobrien break; 336633965Sjdp 336733965Sjdp if (!mtable[i].type) 336860484Sobrien /* xgettext:c-format */ 336960484Sobrien fatal (_("Machine '%s' not supported"), mname); 337060484Sobrien 337133965Sjdp machine = i; 337233965Sjdp 337333965Sjdp if (!dll_name && exp_name) 337433965Sjdp { 3375218822Sdim /* If we are inferring dll_name from exp_name, 3376218822Sdim strip off any path components, without emitting 3377218822Sdim a warning. */ 3378218822Sdim const char* exp_basename = lbasename (exp_name); 3379218822Sdim const int len = strlen (exp_basename) + 5; 338033965Sjdp dll_name = xmalloc (len); 3381218822Sdim strcpy (dll_name, exp_basename); 338233965Sjdp strcat (dll_name, ".dll"); 338333965Sjdp } 338433965Sjdp 338560484Sobrien if (as_name == NULL) 338660484Sobrien as_name = deduce_name ("as"); 3387104834Sobrien 338860484Sobrien /* Don't use the default exclude list if we're reading only the 338960484Sobrien symbols in the .drectve section. The default excludes are meant 339060484Sobrien to avoid exporting DLL entry point and Cygwin32 impure_ptr. */ 339160484Sobrien if (! export_all_symbols) 3392130561Sobrien do_default_excludes = FALSE; 3393104834Sobrien 339460484Sobrien if (do_default_excludes) 339560484Sobrien set_default_excludes (); 339660484Sobrien 339733965Sjdp if (def_file) 339860484Sobrien process_def_file (def_file); 339960484Sobrien 340033965Sjdp while (optind < ac) 340133965Sjdp { 340233965Sjdp if (!firstarg) 340333965Sjdp firstarg = av[optind]; 340433965Sjdp scan_obj_file (av[optind]); 340533965Sjdp optind++; 340633965Sjdp } 340733965Sjdp 340833965Sjdp mangle_defs (); 340933965Sjdp 341033965Sjdp if (exp_name) 341133965Sjdp gen_exp_file (); 3412104834Sobrien 341333965Sjdp if (imp_name) 341433965Sjdp { 3415104834Sobrien /* Make imp_name safe for use as a label. */ 341633965Sjdp char *p; 341738889Sjdp 341838889Sjdp imp_name_lab = xstrdup (imp_name); 341938889Sjdp for (p = imp_name_lab; *p; p++) 342033965Sjdp { 342189857Sobrien if (!ISALNUM (*p)) 342233965Sjdp *p = '_'; 342333965Sjdp } 342433965Sjdp head_label = make_label("_head_", imp_name_lab); 342533965Sjdp gen_lib_file (); 342633965Sjdp } 3427104834Sobrien 342833965Sjdp if (output_def) 342933965Sjdp gen_def_file (); 3430104834Sobrien 343160484Sobrien#ifdef DLLTOOL_MCORE_ELF 343260484Sobrien if (mcore_elf_out_file) 343360484Sobrien mcore_elf_gen_out_file (); 343460484Sobrien#endif 3435104834Sobrien 343633965Sjdp return 0; 343733965Sjdp} 343860484Sobrien 343960484Sobrien/* Look for the program formed by concatenating PROG_NAME and the 344060484Sobrien string running from PREFIX to END_PREFIX. If the concatenated 344160484Sobrien string contains a '/', try appending EXECUTABLE_SUFFIX if it is 344260484Sobrien appropriate. */ 344360484Sobrien 344460484Sobrienstatic char * 3445130561Sobrienlook_for_prog (const char *prog_name, const char *prefix, int end_prefix) 344660484Sobrien{ 344760484Sobrien struct stat s; 344860484Sobrien char *cmd; 344960484Sobrien 3450104834Sobrien cmd = xmalloc (strlen (prefix) 3451104834Sobrien + strlen (prog_name) 345260484Sobrien#ifdef HAVE_EXECUTABLE_SUFFIX 3453104834Sobrien + strlen (EXECUTABLE_SUFFIX) 345460484Sobrien#endif 345560484Sobrien + 10); 345660484Sobrien strcpy (cmd, prefix); 345760484Sobrien 345860484Sobrien sprintf (cmd + end_prefix, "%s", prog_name); 345960484Sobrien 346060484Sobrien if (strchr (cmd, '/') != NULL) 346160484Sobrien { 346260484Sobrien int found; 346360484Sobrien 346460484Sobrien found = (stat (cmd, &s) == 0 346560484Sobrien#ifdef HAVE_EXECUTABLE_SUFFIX 3466104834Sobrien || stat (strcat (cmd, EXECUTABLE_SUFFIX), &s) == 0 346760484Sobrien#endif 346860484Sobrien ); 346960484Sobrien 347060484Sobrien if (! found) 3471104834Sobrien { 347260484Sobrien /* xgettext:c-format */ 347360484Sobrien inform (_("Tried file: %s"), cmd); 347460484Sobrien free (cmd); 347560484Sobrien return NULL; 347660484Sobrien } 347760484Sobrien } 347860484Sobrien 347960484Sobrien /* xgettext:c-format */ 348060484Sobrien inform (_("Using file: %s"), cmd); 348160484Sobrien 348260484Sobrien return cmd; 348360484Sobrien} 348460484Sobrien 348560484Sobrien/* Deduce the name of the program we are want to invoke. 348660484Sobrien PROG_NAME is the basic name of the program we want to run, 348760484Sobrien eg "as" or "ld". The catch is that we might want actually 3488104834Sobrien run "i386-pe-as" or "ppc-pe-ld". 348960484Sobrien 349060484Sobrien If argv[0] contains the full path, then try to find the program 349160484Sobrien in the same place, with and then without a target-like prefix. 349260484Sobrien 349360484Sobrien Given, argv[0] = /usr/local/bin/i586-cygwin32-dlltool, 3494104834Sobrien deduce_name("as") uses the following search order: 349560484Sobrien 349660484Sobrien /usr/local/bin/i586-cygwin32-as 349760484Sobrien /usr/local/bin/as 349860484Sobrien as 3499104834Sobrien 350060484Sobrien If there's an EXECUTABLE_SUFFIX, it'll use that as well; for each 350160484Sobrien name, it'll try without and then with EXECUTABLE_SUFFIX. 350260484Sobrien 350360484Sobrien Given, argv[0] = i586-cygwin32-dlltool, it will not even try "as" 350460484Sobrien as the fallback, but rather return i586-cygwin32-as. 3505104834Sobrien 350660484Sobrien Oh, and given, argv[0] = dlltool, it'll return "as". 350760484Sobrien 350860484Sobrien Returns a dynamically allocated string. */ 350960484Sobrien 351060484Sobrienstatic char * 3511130561Sobriendeduce_name (const char *prog_name) 351260484Sobrien{ 351360484Sobrien char *cmd; 351460484Sobrien char *dash, *slash, *cp; 351560484Sobrien 351660484Sobrien dash = NULL; 351760484Sobrien slash = NULL; 351860484Sobrien for (cp = program_name; *cp != '\0'; ++cp) 351960484Sobrien { 352060484Sobrien if (*cp == '-') 352160484Sobrien dash = cp; 352260484Sobrien if ( 352360484Sobrien#if defined(__DJGPP__) || defined (__CYGWIN__) || defined(__WIN32__) 352460484Sobrien *cp == ':' || *cp == '\\' || 352560484Sobrien#endif 352660484Sobrien *cp == '/') 352760484Sobrien { 352860484Sobrien slash = cp; 352960484Sobrien dash = NULL; 353060484Sobrien } 353160484Sobrien } 353260484Sobrien 353360484Sobrien cmd = NULL; 353460484Sobrien 353560484Sobrien if (dash != NULL) 353660484Sobrien { 353760484Sobrien /* First, try looking for a prefixed PROG_NAME in the 353860484Sobrien PROGRAM_NAME directory, with the same prefix as PROGRAM_NAME. */ 353960484Sobrien cmd = look_for_prog (prog_name, program_name, dash - program_name + 1); 354060484Sobrien } 354160484Sobrien 354260484Sobrien if (slash != NULL && cmd == NULL) 354360484Sobrien { 354460484Sobrien /* Next, try looking for a PROG_NAME in the same directory as 354560484Sobrien that of this program. */ 354660484Sobrien cmd = look_for_prog (prog_name, program_name, slash - program_name + 1); 354760484Sobrien } 354860484Sobrien 354960484Sobrien if (cmd == NULL) 355060484Sobrien { 355160484Sobrien /* Just return PROG_NAME as is. */ 355260484Sobrien cmd = xstrdup (prog_name); 355360484Sobrien } 355460484Sobrien 355560484Sobrien return cmd; 355660484Sobrien} 355760484Sobrien 355860484Sobrien#ifdef DLLTOOL_MCORE_ELF 355960484Sobrientypedef struct fname_cache 356060484Sobrien{ 356160484Sobrien char * filename; 356260484Sobrien struct fname_cache * next; 356360484Sobrien} 356460484Sobrienfname_cache; 356560484Sobrien 356660484Sobrienstatic fname_cache fnames; 356760484Sobrien 356860484Sobrienstatic void 356960484Sobrienmcore_elf_cache_filename (char * filename) 357060484Sobrien{ 357160484Sobrien fname_cache * ptr; 357260484Sobrien 357360484Sobrien ptr = & fnames; 357460484Sobrien 357560484Sobrien while (ptr->next != NULL) 357660484Sobrien ptr = ptr->next; 357760484Sobrien 357860484Sobrien ptr->filename = filename; 357960484Sobrien ptr->next = (fname_cache *) malloc (sizeof (fname_cache)); 358060484Sobrien if (ptr->next != NULL) 358160484Sobrien ptr->next->next = NULL; 358260484Sobrien} 358360484Sobrien 358460484Sobrien#define MCORE_ELF_TMP_OBJ "mcoreelf.o" 358560484Sobrien#define MCORE_ELF_TMP_EXP "mcoreelf.exp" 358660484Sobrien#define MCORE_ELF_TMP_LIB "mcoreelf.lib" 358760484Sobrien 358860484Sobrienstatic void 358960484Sobrienmcore_elf_gen_out_file (void) 359060484Sobrien{ 359160484Sobrien fname_cache * ptr; 359260484Sobrien dyn_string_t ds; 359360484Sobrien 359460484Sobrien /* Step one. Run 'ld -r' on the input object files in order to resolve 359560484Sobrien any internal references and to generate a single .exports section. */ 359660484Sobrien ptr = & fnames; 359760484Sobrien 359860484Sobrien ds = dyn_string_new (100); 3599130561Sobrien dyn_string_append_cstr (ds, "-r "); 360060484Sobrien 360160484Sobrien if (mcore_elf_linker_flags != NULL) 3602130561Sobrien dyn_string_append_cstr (ds, mcore_elf_linker_flags); 3603104834Sobrien 360460484Sobrien while (ptr->next != NULL) 360560484Sobrien { 3606130561Sobrien dyn_string_append_cstr (ds, ptr->filename); 3607130561Sobrien dyn_string_append_cstr (ds, " "); 360860484Sobrien 360960484Sobrien ptr = ptr->next; 361060484Sobrien } 361160484Sobrien 3612130561Sobrien dyn_string_append_cstr (ds, "-o "); 3613130561Sobrien dyn_string_append_cstr (ds, MCORE_ELF_TMP_OBJ); 361460484Sobrien 361560484Sobrien if (mcore_elf_linker == NULL) 361660484Sobrien mcore_elf_linker = deduce_name ("ld"); 3617104834Sobrien 361860484Sobrien run (mcore_elf_linker, ds->s); 361960484Sobrien 362060484Sobrien dyn_string_delete (ds); 362160484Sobrien 3622104834Sobrien /* Step two. Create a .exp file and a .lib file from the temporary file. 3623130561Sobrien Do this by recursively invoking dlltool... */ 362460484Sobrien ds = dyn_string_new (100); 362560484Sobrien 3626130561Sobrien dyn_string_append_cstr (ds, "-S "); 3627130561Sobrien dyn_string_append_cstr (ds, as_name); 3628104834Sobrien 3629130561Sobrien dyn_string_append_cstr (ds, " -e "); 3630130561Sobrien dyn_string_append_cstr (ds, MCORE_ELF_TMP_EXP); 3631130561Sobrien dyn_string_append_cstr (ds, " -l "); 3632130561Sobrien dyn_string_append_cstr (ds, MCORE_ELF_TMP_LIB); 3633130561Sobrien dyn_string_append_cstr (ds, " " ); 3634130561Sobrien dyn_string_append_cstr (ds, MCORE_ELF_TMP_OBJ); 363560484Sobrien 363660484Sobrien if (verbose) 3637130561Sobrien dyn_string_append_cstr (ds, " -v"); 3638104834Sobrien 363960484Sobrien if (dontdeltemps) 364060484Sobrien { 3641130561Sobrien dyn_string_append_cstr (ds, " -n"); 3642104834Sobrien 364360484Sobrien if (dontdeltemps > 1) 3644130561Sobrien dyn_string_append_cstr (ds, " -n"); 364560484Sobrien } 364660484Sobrien 364760484Sobrien /* XXX - FIME: ought to check/copy other command line options as well. */ 364860484Sobrien run (program_name, ds->s); 364960484Sobrien 365060484Sobrien dyn_string_delete (ds); 365160484Sobrien 365260484Sobrien /* Step four. Feed the .exp and object files to ld -shared to create the dll. */ 365360484Sobrien ds = dyn_string_new (100); 365460484Sobrien 3655130561Sobrien dyn_string_append_cstr (ds, "-shared "); 365660484Sobrien 365760484Sobrien if (mcore_elf_linker_flags) 3658130561Sobrien dyn_string_append_cstr (ds, mcore_elf_linker_flags); 365960484Sobrien 3660130561Sobrien dyn_string_append_cstr (ds, " "); 3661130561Sobrien dyn_string_append_cstr (ds, MCORE_ELF_TMP_EXP); 3662130561Sobrien dyn_string_append_cstr (ds, " "); 3663130561Sobrien dyn_string_append_cstr (ds, MCORE_ELF_TMP_OBJ); 3664130561Sobrien dyn_string_append_cstr (ds, " -o "); 3665130561Sobrien dyn_string_append_cstr (ds, mcore_elf_out_file); 366660484Sobrien 366760484Sobrien run (mcore_elf_linker, ds->s); 366860484Sobrien 366960484Sobrien dyn_string_delete (ds); 367060484Sobrien 367160484Sobrien if (dontdeltemps == 0) 367260484Sobrien unlink (MCORE_ELF_TMP_EXP); 367360484Sobrien 367460484Sobrien if (dontdeltemps < 2) 367560484Sobrien unlink (MCORE_ELF_TMP_OBJ); 367660484Sobrien} 367760484Sobrien#endif /* DLLTOOL_MCORE_ELF */ 3678