133965Sjdp# This shell script emits a C file. -*- C -*- 233965Sjdp# It does some substitutions. 3218822Sdimtest -z "${ENTRY}" && ENTRY="_mainCRTStartup" 489857Sobrienif [ -z "$MACHINE" ]; then 589857Sobrien OUTPUT_ARCH=${ARCH} 689857Sobrienelse 789857Sobrien OUTPUT_ARCH=${ARCH}:${MACHINE} 889857Sobrienfi 960484Sobrienrm -f e${EMULATION_NAME}.c 1060484Sobrien(echo;echo;echo;echo;echo)>e${EMULATION_NAME}.c # there, now line numbers match ;-) 1160484Sobriencat >>e${EMULATION_NAME}.c <<EOF 1233965Sjdp/* This file is part of GLD, the Gnu Linker. 13218822Sdim Copyright 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 14218822Sdim 2005, 2006, 2007 Free Software Foundation, Inc. 1533965Sjdp 16130561Sobrien This program is free software; you can redistribute it and/or modify 17130561Sobrien it under the terms of the GNU General Public License as published by 18130561Sobrien the Free Software Foundation; either version 2 of the License, or 19130561Sobrien (at your option) any later version. 2033965Sjdp 21130561Sobrien This program is distributed in the hope that it will be useful, 22130561Sobrien but WITHOUT ANY WARRANTY; without even the implied warranty of 23130561Sobrien MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 24130561Sobrien GNU General Public License for more details. 2533965Sjdp 26130561Sobrien You should have received a copy of the GNU General Public License 27130561Sobrien along with this program; if not, write to the Free Software 28218822Sdim Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ 2933965Sjdp 3033965Sjdp/* For WINDOWS_NT */ 3133965Sjdp/* The original file generated returned different default scripts depending 3233965Sjdp on whether certain switches were set, but these switches pertain to the 3333965Sjdp Linux system and that particular version of coff. In the NT case, we 3433965Sjdp only determine if the subsystem is console or windows in order to select 3589857Sobrien the correct entry point by default. */ 3689857Sobrien 3789857Sobrien#define TARGET_IS_${EMULATION_NAME} 3889857Sobrien 3989857Sobrien/* Do this before including bfd.h, so we prototype the right functions. */ 40218822Sdim 41218822Sdim#if defined(TARGET_IS_armpe) \ 42218822Sdim || defined(TARGET_IS_arm_epoc_pe) \ 43218822Sdim || defined(TARGET_IS_arm_wince_pe) 44218822Sdim#define bfd_arm_allocate_interworking_sections \ 45218822Sdim bfd_${EMULATION_NAME}_allocate_interworking_sections 46218822Sdim#define bfd_arm_get_bfd_for_interworking \ 47218822Sdim bfd_${EMULATION_NAME}_get_bfd_for_interworking 48218822Sdim#define bfd_arm_process_before_allocation \ 49218822Sdim bfd_${EMULATION_NAME}_process_before_allocation 5089857Sobrien#endif 51218822Sdim 52218822Sdim#include "sysdep.h" 5333965Sjdp#include "bfd.h" 5433965Sjdp#include "bfdlink.h" 5533965Sjdp#include "getopt.h" 5633965Sjdp#include "libiberty.h" 5733965Sjdp#include "ld.h" 5833965Sjdp#include "ldmain.h" 5933965Sjdp#include "ldexp.h" 6033965Sjdp#include "ldlang.h" 6177298Sobrien#include "ldfile.h" 6233965Sjdp#include "ldemul.h" 63107492Sobrien#include <ldgram.h> 6433965Sjdp#include "ldlex.h" 6533965Sjdp#include "ldmisc.h" 6633965Sjdp#include "ldctor.h" 6733965Sjdp#include "coff/internal.h" 6860484Sobrien 69218822Sdim/* FIXME: See bfd/peXXigen.c for why we include an architecture specific 70218822Sdim header in generic PE code. */ 71218822Sdim#include "coff/i386.h" 72218822Sdim#include "coff/pe.h" 73218822Sdim 7460484Sobrien/* FIXME: This is a BFD internal header file, and we should not be 7560484Sobrien using it here. */ 7633965Sjdp#include "../bfd/libcoff.h" 7733965Sjdp 7860484Sobrien#include "deffile.h" 7960484Sobrien#include "pe-dll.h" 80130561Sobrien#include "safe-ctype.h" 8160484Sobrien 8260484Sobrien/* Permit the emulation parameters to override the default section 8360484Sobrien alignment by setting OVERRIDE_SECTION_ALIGNMENT. FIXME: This makes 8460484Sobrien it seem that include/coff/internal.h should not define 8560484Sobrien PE_DEF_SECTION_ALIGNMENT. */ 8660484Sobrien#if PE_DEF_SECTION_ALIGNMENT != ${OVERRIDE_SECTION_ALIGNMENT:-PE_DEF_SECTION_ALIGNMENT} 8760484Sobrien#undef PE_DEF_SECTION_ALIGNMENT 8860484Sobrien#define PE_DEF_SECTION_ALIGNMENT ${OVERRIDE_SECTION_ALIGNMENT} 8960484Sobrien#endif 9060484Sobrien 91218822Sdim#if defined(TARGET_IS_i386pe) \ 92218822Sdim || defined(TARGET_IS_shpe) \ 93218822Sdim || defined(TARGET_IS_mipspe) \ 94218822Sdim || defined(TARGET_IS_armpe) \ 95218822Sdim || defined(TARGET_IS_arm_epoc_pe) \ 96218822Sdim || defined(TARGET_IS_arm_wince_pe) 9760484Sobrien#define DLL_SUPPORT 9860484Sobrien#endif 9960484Sobrien 10060484Sobrien#if defined(TARGET_IS_i386pe) || ! defined(DLL_SUPPORT) 10160484Sobrien#define PE_DEF_SUBSYSTEM 3 10260484Sobrien#else 10360484Sobrien#undef NT_EXE_IMAGE_BASE 10460484Sobrien#undef PE_DEF_SECTION_ALIGNMENT 10560484Sobrien#undef PE_DEF_FILE_ALIGNMENT 10660484Sobrien#define NT_EXE_IMAGE_BASE 0x00010000 107218822Sdim 108218822Sdim#if defined(TARGET_IS_armpe) || defined(TARGET_IS_arm_wince_pe) 10960484Sobrien#define PE_DEF_SECTION_ALIGNMENT 0x00001000 11060484Sobrien#define PE_DEF_SUBSYSTEM 9 11160484Sobrien#else 11260484Sobrien#define PE_DEF_SECTION_ALIGNMENT 0x00000400 11360484Sobrien#define PE_DEF_SUBSYSTEM 2 11460484Sobrien#endif 11560484Sobrien#define PE_DEF_FILE_ALIGNMENT 0x00000200 11660484Sobrien#endif 11760484Sobrien 118218822Sdim#define U(S) ${INITIAL_SYMBOL_CHAR} S 11933965Sjdp 12033965Sjdpstatic struct internal_extra_pe_aouthdr pe; 12133965Sjdpstatic int dll; 122218822Sdimstatic flagword real_flags = 0; 12360484Sobrienstatic int support_old_code = 0; 12460484Sobrienstatic char * thumb_entry_symbol = NULL; 12560484Sobrienstatic lang_assignment_statement_type *image_base_statement = 0; 12633965Sjdp 12777298Sobrien#ifdef DLL_SUPPORT 128130561Sobrienstatic int pe_enable_stdcall_fixup = -1; /* 0=disable 1=enable. */ 12977298Sobrienstatic char *pe_out_def_filename = NULL; 13077298Sobrienstatic char *pe_implib_filename = NULL; 13177298Sobrienstatic int pe_enable_auto_image_base = 0; 13277298Sobrienstatic char *pe_dll_search_prefix = NULL; 13360484Sobrien#endif 13460484Sobrien 13533965Sjdpextern const char *output_filename; 13633965Sjdp 13733965Sjdpstatic void 138130561Sobriengld_${EMULATION_NAME}_before_parse (void) 13933965Sjdp{ 140130561Sobrien ldfile_set_output_arch ("${OUTPUT_ARCH}", bfd_arch_`echo ${ARCH} | sed -e 's/:.*//'`); 14160484Sobrien output_filename = "${EXECUTABLE_NAME:-a.exe}"; 14260484Sobrien#ifdef DLL_SUPPORT 143130561Sobrien config.dynamic_link = TRUE; 14460484Sobrien config.has_shared = 1; 145104834Sobrien link_info.pei386_auto_import = -1; 146218822Sdim link_info.pei386_runtime_pseudo_reloc = -1; 14760484Sobrien 14860484Sobrien#if (PE_DEF_SUBSYSTEM == 9) || (PE_DEF_SUBSYSTEM == 2) 149218822Sdim#if defined TARGET_IS_mipspe || defined TARGET_IS_armpe || defined TARGET_IS_arm_wince_pe 150218822Sdim lang_default_entry ("WinMainCRTStartup"); 15160484Sobrien#else 152218822Sdim lang_default_entry ("_WinMainCRTStartup"); 15360484Sobrien#endif 154218822Sdim#else 155218822Sdim lang_default_entry ("${ENTRY}"); 15660484Sobrien#endif 15760484Sobrien#endif 15833965Sjdp} 15933965Sjdp 16033965Sjdp/* PE format extra command line options. */ 16133965Sjdp 162130561Sobrien/* Used for setting flags in the PE header. */ 16333965Sjdp#define OPTION_BASE_FILE (300 + 1) 16433965Sjdp#define OPTION_DLL (OPTION_BASE_FILE + 1) 16533965Sjdp#define OPTION_FILE_ALIGNMENT (OPTION_DLL + 1) 16633965Sjdp#define OPTION_IMAGE_BASE (OPTION_FILE_ALIGNMENT + 1) 16733965Sjdp#define OPTION_MAJOR_IMAGE_VERSION (OPTION_IMAGE_BASE + 1) 16833965Sjdp#define OPTION_MAJOR_OS_VERSION (OPTION_MAJOR_IMAGE_VERSION + 1) 16933965Sjdp#define OPTION_MAJOR_SUBSYSTEM_VERSION (OPTION_MAJOR_OS_VERSION + 1) 17033965Sjdp#define OPTION_MINOR_IMAGE_VERSION (OPTION_MAJOR_SUBSYSTEM_VERSION + 1) 17133965Sjdp#define OPTION_MINOR_OS_VERSION (OPTION_MINOR_IMAGE_VERSION + 1) 17233965Sjdp#define OPTION_MINOR_SUBSYSTEM_VERSION (OPTION_MINOR_OS_VERSION + 1) 17333965Sjdp#define OPTION_SECTION_ALIGNMENT (OPTION_MINOR_SUBSYSTEM_VERSION + 1) 174130561Sobrien#define OPTION_STACK (OPTION_SECTION_ALIGNMENT + 1) 175130561Sobrien#define OPTION_SUBSYSTEM (OPTION_STACK + 1) 17633965Sjdp#define OPTION_HEAP (OPTION_SUBSYSTEM + 1) 17760484Sobrien#define OPTION_SUPPORT_OLD_CODE (OPTION_HEAP + 1) 17860484Sobrien#define OPTION_OUT_DEF (OPTION_SUPPORT_OLD_CODE + 1) 17960484Sobrien#define OPTION_EXPORT_ALL (OPTION_OUT_DEF + 1) 18060484Sobrien#define OPTION_EXCLUDE_SYMBOLS (OPTION_EXPORT_ALL + 1) 18160484Sobrien#define OPTION_KILL_ATS (OPTION_EXCLUDE_SYMBOLS + 1) 18260484Sobrien#define OPTION_STDCALL_ALIASES (OPTION_KILL_ATS + 1) 18360484Sobrien#define OPTION_ENABLE_STDCALL_FIXUP (OPTION_STDCALL_ALIASES + 1) 18460484Sobrien#define OPTION_DISABLE_STDCALL_FIXUP (OPTION_ENABLE_STDCALL_FIXUP + 1) 18560484Sobrien#define OPTION_IMPLIB_FILENAME (OPTION_DISABLE_STDCALL_FIXUP + 1) 18660484Sobrien#define OPTION_THUMB_ENTRY (OPTION_IMPLIB_FILENAME + 1) 18760484Sobrien#define OPTION_WARN_DUPLICATE_EXPORTS (OPTION_THUMB_ENTRY + 1) 18860484Sobrien#define OPTION_IMP_COMPAT (OPTION_WARN_DUPLICATE_EXPORTS + 1) 18977298Sobrien#define OPTION_ENABLE_AUTO_IMAGE_BASE (OPTION_IMP_COMPAT + 1) 19077298Sobrien#define OPTION_DISABLE_AUTO_IMAGE_BASE (OPTION_ENABLE_AUTO_IMAGE_BASE + 1) 19177298Sobrien#define OPTION_DLL_SEARCH_PREFIX (OPTION_DISABLE_AUTO_IMAGE_BASE + 1) 19277298Sobrien#define OPTION_NO_DEFAULT_EXCLUDES (OPTION_DLL_SEARCH_PREFIX + 1) 19389857Sobrien#define OPTION_DLL_ENABLE_AUTO_IMPORT (OPTION_NO_DEFAULT_EXCLUDES + 1) 19489857Sobrien#define OPTION_DLL_DISABLE_AUTO_IMPORT (OPTION_DLL_ENABLE_AUTO_IMPORT + 1) 19589857Sobrien#define OPTION_ENABLE_EXTRA_PE_DEBUG (OPTION_DLL_DISABLE_AUTO_IMPORT + 1) 196104834Sobrien#define OPTION_EXCLUDE_LIBS (OPTION_ENABLE_EXTRA_PE_DEBUG + 1) 197130561Sobrien#define OPTION_DLL_ENABLE_RUNTIME_PSEUDO_RELOC \ 198130561Sobrien (OPTION_EXCLUDE_LIBS + 1) 199130561Sobrien#define OPTION_DLL_DISABLE_RUNTIME_PSEUDO_RELOC \ 200130561Sobrien (OPTION_DLL_ENABLE_RUNTIME_PSEUDO_RELOC + 1) 201218822Sdim#define OPTION_LARGE_ADDRESS_AWARE \ 202218822Sdim (OPTION_DLL_DISABLE_RUNTIME_PSEUDO_RELOC + 1) 20333965Sjdp 204130561Sobrienstatic void 205130561Sobriengld${EMULATION_NAME}_add_options 206130561Sobrien (int ns ATTRIBUTE_UNUSED, char **shortopts ATTRIBUTE_UNUSED, int nl, 207130561Sobrien struct option **longopts, int nrl ATTRIBUTE_UNUSED, 208130561Sobrien struct option **really_longopts ATTRIBUTE_UNUSED) 209130561Sobrien{ 210130561Sobrien static const struct option xtra_long[] = { 211130561Sobrien /* PE options */ 212130561Sobrien {"base-file", required_argument, NULL, OPTION_BASE_FILE}, 213130561Sobrien {"dll", no_argument, NULL, OPTION_DLL}, 214130561Sobrien {"file-alignment", required_argument, NULL, OPTION_FILE_ALIGNMENT}, 215130561Sobrien {"heap", required_argument, NULL, OPTION_HEAP}, 216130561Sobrien {"image-base", required_argument, NULL, OPTION_IMAGE_BASE}, 217130561Sobrien {"major-image-version", required_argument, NULL, OPTION_MAJOR_IMAGE_VERSION}, 218130561Sobrien {"major-os-version", required_argument, NULL, OPTION_MAJOR_OS_VERSION}, 219130561Sobrien {"major-subsystem-version", required_argument, NULL, OPTION_MAJOR_SUBSYSTEM_VERSION}, 220130561Sobrien {"minor-image-version", required_argument, NULL, OPTION_MINOR_IMAGE_VERSION}, 221130561Sobrien {"minor-os-version", required_argument, NULL, OPTION_MINOR_OS_VERSION}, 222130561Sobrien {"minor-subsystem-version", required_argument, NULL, OPTION_MINOR_SUBSYSTEM_VERSION}, 223130561Sobrien {"section-alignment", required_argument, NULL, OPTION_SECTION_ALIGNMENT}, 224130561Sobrien {"stack", required_argument, NULL, OPTION_STACK}, 225130561Sobrien {"subsystem", required_argument, NULL, OPTION_SUBSYSTEM}, 226130561Sobrien {"support-old-code", no_argument, NULL, OPTION_SUPPORT_OLD_CODE}, 227130561Sobrien {"thumb-entry", required_argument, NULL, OPTION_THUMB_ENTRY}, 22860484Sobrien#ifdef DLL_SUPPORT 229130561Sobrien /* getopt allows abbreviations, so we do this to stop it from treating -o 230130561Sobrien as an abbreviation for this option */ 231130561Sobrien {"output-def", required_argument, NULL, OPTION_OUT_DEF}, 232130561Sobrien {"output-def", required_argument, NULL, OPTION_OUT_DEF}, 233130561Sobrien {"export-all-symbols", no_argument, NULL, OPTION_EXPORT_ALL}, 234130561Sobrien {"exclude-symbols", required_argument, NULL, OPTION_EXCLUDE_SYMBOLS}, 235130561Sobrien {"exclude-libs", required_argument, NULL, OPTION_EXCLUDE_LIBS}, 236130561Sobrien {"kill-at", no_argument, NULL, OPTION_KILL_ATS}, 237130561Sobrien {"add-stdcall-alias", no_argument, NULL, OPTION_STDCALL_ALIASES}, 238130561Sobrien {"enable-stdcall-fixup", no_argument, NULL, OPTION_ENABLE_STDCALL_FIXUP}, 239130561Sobrien {"disable-stdcall-fixup", no_argument, NULL, OPTION_DISABLE_STDCALL_FIXUP}, 240130561Sobrien {"out-implib", required_argument, NULL, OPTION_IMPLIB_FILENAME}, 241130561Sobrien {"warn-duplicate-exports", no_argument, NULL, OPTION_WARN_DUPLICATE_EXPORTS}, 242130561Sobrien /* getopt() allows abbreviations, so we do this to stop it from 243130561Sobrien treating -c as an abbreviation for these --compat-implib. */ 244130561Sobrien {"compat-implib", no_argument, NULL, OPTION_IMP_COMPAT}, 245130561Sobrien {"compat-implib", no_argument, NULL, OPTION_IMP_COMPAT}, 246130561Sobrien {"enable-auto-image-base", no_argument, NULL, OPTION_ENABLE_AUTO_IMAGE_BASE}, 247130561Sobrien {"disable-auto-image-base", no_argument, NULL, OPTION_DISABLE_AUTO_IMAGE_BASE}, 248130561Sobrien {"dll-search-prefix", required_argument, NULL, OPTION_DLL_SEARCH_PREFIX}, 249130561Sobrien {"no-default-excludes", no_argument, NULL, OPTION_NO_DEFAULT_EXCLUDES}, 250130561Sobrien {"enable-auto-import", no_argument, NULL, OPTION_DLL_ENABLE_AUTO_IMPORT}, 251130561Sobrien {"disable-auto-import", no_argument, NULL, OPTION_DLL_DISABLE_AUTO_IMPORT}, 252130561Sobrien {"enable-extra-pe-debug", no_argument, NULL, OPTION_ENABLE_EXTRA_PE_DEBUG}, 253130561Sobrien {"enable-runtime-pseudo-reloc", no_argument, NULL, OPTION_DLL_ENABLE_RUNTIME_PSEUDO_RELOC}, 254130561Sobrien {"disable-runtime-pseudo-reloc", no_argument, NULL, OPTION_DLL_DISABLE_RUNTIME_PSEUDO_RELOC}, 25560484Sobrien#endif 256218822Sdim {"large-address-aware", no_argument, NULL, OPTION_LARGE_ADDRESS_AWARE}, 257130561Sobrien {NULL, no_argument, NULL, 0} 258130561Sobrien }; 25933965Sjdp 260130561Sobrien *longopts = (struct option *) 261130561Sobrien xrealloc (*longopts, nl * sizeof (struct option) + sizeof (xtra_long)); 262130561Sobrien memcpy (*longopts + nl, &xtra_long, sizeof (xtra_long)); 263130561Sobrien} 26433965Sjdp 26533965Sjdp/* PE/WIN32; added routines to get the subsystem type, heap and/or stack 266130561Sobrien parameters which may be input from the command line. */ 26733965Sjdp 26860484Sobrientypedef struct 26960484Sobrien{ 27033965Sjdp void *ptr; 27133965Sjdp int size; 27233965Sjdp int value; 27333965Sjdp char *symbol; 27433965Sjdp int inited; 27533965Sjdp} definfo; 27633965Sjdp 27733965Sjdp#define D(field,symbol,def) {&pe.field,sizeof(pe.field), def, symbol,0} 27833965Sjdp 27933965Sjdpstatic definfo init[] = 28033965Sjdp{ 28133965Sjdp /* imagebase must be first */ 28233965Sjdp#define IMAGEBASEOFF 0 28333965Sjdp D(ImageBase,"__image_base__", NT_EXE_IMAGE_BASE), 28433965Sjdp#define DLLOFF 1 28560484Sobrien {&dll, sizeof(dll), 0, "__dll__", 0}, 28633965Sjdp D(SectionAlignment,"__section_alignment__", PE_DEF_SECTION_ALIGNMENT), 28733965Sjdp D(FileAlignment,"__file_alignment__", PE_DEF_FILE_ALIGNMENT), 28833965Sjdp D(MajorOperatingSystemVersion,"__major_os_version__", 4), 28933965Sjdp D(MinorOperatingSystemVersion,"__minor_os_version__", 0), 29033965Sjdp D(MajorImageVersion,"__major_image_version__", 1), 29133965Sjdp D(MinorImageVersion,"__minor_image_version__", 0), 292218822Sdim#if defined(TARGET_IS_armpe) || defined(TARGET_IS_arm_wince_pe) 293218822Sdim D(MajorSubsystemVersion,"__major_subsystem_version__", 3), 29460484Sobrien#else 29533965Sjdp D(MajorSubsystemVersion,"__major_subsystem_version__", 4), 29660484Sobrien#endif 29733965Sjdp D(MinorSubsystemVersion,"__minor_subsystem_version__", 0), 29860484Sobrien D(Subsystem,"__subsystem__", ${SUBSYSTEM}), 29978828Sobrien D(SizeOfStackReserve,"__size_of_stack_reserve__", 0x200000), 30033965Sjdp D(SizeOfStackCommit,"__size_of_stack_commit__", 0x1000), 30133965Sjdp D(SizeOfHeapReserve,"__size_of_heap_reserve__", 0x100000), 30233965Sjdp D(SizeOfHeapCommit,"__size_of_heap_commit__", 0x1000), 30333965Sjdp D(LoaderFlags,"__loader_flags__", 0x0), 30433965Sjdp { NULL, 0, 0, NULL, 0 } 30533965Sjdp}; 30633965Sjdp 307130561Sobrien 30860484Sobrienstatic void 309130561Sobriengld_${EMULATION_NAME}_list_options (FILE *file) 31060484Sobrien{ 31160484Sobrien fprintf (file, _(" --base_file <basefile> Generate a base file for relocatable DLLs\n")); 31260484Sobrien fprintf (file, _(" --dll Set image base to the default for DLLs\n")); 31360484Sobrien fprintf (file, _(" --file-alignment <size> Set file alignment\n")); 31460484Sobrien fprintf (file, _(" --heap <size> Set initial size of the heap\n")); 31560484Sobrien fprintf (file, _(" --image-base <address> Set start address of the executable\n")); 31660484Sobrien fprintf (file, _(" --major-image-version <number> Set version number of the executable\n")); 31760484Sobrien fprintf (file, _(" --major-os-version <number> Set minimum required OS version\n")); 31860484Sobrien fprintf (file, _(" --major-subsystem-version <number> Set minimum required OS subsystem version\n")); 31960484Sobrien fprintf (file, _(" --minor-image-version <number> Set revision number of the executable\n")); 32060484Sobrien fprintf (file, _(" --minor-os-version <number> Set minimum required OS revision\n")); 32160484Sobrien fprintf (file, _(" --minor-subsystem-version <number> Set minimum required OS subsystem revision\n")); 32260484Sobrien fprintf (file, _(" --section-alignment <size> Set section alignment\n")); 32360484Sobrien fprintf (file, _(" --stack <size> Set size of the initial stack\n")); 32460484Sobrien fprintf (file, _(" --subsystem <name>[:<version>] Set required OS subsystem [& version]\n")); 32560484Sobrien fprintf (file, _(" --support-old-code Support interworking with old code\n")); 32660484Sobrien fprintf (file, _(" --thumb-entry=<symbol> Set the entry point to be Thumb <symbol>\n")); 32760484Sobrien#ifdef DLL_SUPPORT 32860484Sobrien fprintf (file, _(" --add-stdcall-alias Export symbols with and without @nn\n")); 32960484Sobrien fprintf (file, _(" --disable-stdcall-fixup Don't link _sym to _sym@nn\n")); 33060484Sobrien fprintf (file, _(" --enable-stdcall-fixup Link _sym to _sym@nn without warnings\n")); 33160484Sobrien fprintf (file, _(" --exclude-symbols sym,sym,... Exclude symbols from automatic export\n")); 332130561Sobrien fprintf (file, _(" --exclude-libs lib,lib,... Exclude libraries from automatic export\n")); 33360484Sobrien fprintf (file, _(" --export-all-symbols Automatically export all globals to DLL\n")); 33460484Sobrien fprintf (file, _(" --kill-at Remove @nn from exported symbols\n")); 33560484Sobrien fprintf (file, _(" --out-implib <file> Generate import library\n")); 33660484Sobrien fprintf (file, _(" --output-def <file> Generate a .DEF file for the built DLL\n")); 33760484Sobrien fprintf (file, _(" --warn-duplicate-exports Warn about duplicate exports.\n")); 33889857Sobrien fprintf (file, _(" --compat-implib Create backward compatible import libs;\n\ 33989857Sobrien create __imp_<SYMBOL> as well.\n")); 34089857Sobrien fprintf (file, _(" --enable-auto-image-base Automatically choose image base for DLLs\n\ 34189857Sobrien unless user specifies one\n")); 34277298Sobrien fprintf (file, _(" --disable-auto-image-base Do not auto-choose image base. (default)\n")); 343130561Sobrien fprintf (file, _(" --dll-search-prefix=<string> When linking dynamically to a dll without\n\ 344130561Sobrien an importlib, use <string><basename>.dll\n\ 34589857Sobrien in preference to lib<basename>.dll \n")); 346130561Sobrien fprintf (file, _(" --enable-auto-import Do sophistcated linking of _sym to\n\ 34789857Sobrien __imp_sym for DATA references\n")); 34889857Sobrien fprintf (file, _(" --disable-auto-import Do not auto-import DATA items from DLLs\n")); 349130561Sobrien fprintf (file, _(" --enable-runtime-pseudo-reloc Work around auto-import limitations by\n\ 350130561Sobrien adding pseudo-relocations resolved at\n\ 351130561Sobrien runtime.\n")); 352130561Sobrien fprintf (file, _(" --disable-runtime-pseudo-reloc Do not add runtime pseudo-relocations for\n\ 353130561Sobrien auto-imported DATA.\n")); 35489857Sobrien fprintf (file, _(" --enable-extra-pe-debug Enable verbose debug output when building\n\ 35589857Sobrien or linking to DLLs (esp. auto-import)\n")); 35660484Sobrien#endif 357218822Sdim fprintf (file, _(" --large-address-aware Executable supports virtual addresses\n\ 358218822Sdim greater than 2 gigabytes\n")); 35960484Sobrien} 36033965Sjdp 361130561Sobrien 36233965Sjdpstatic void 363130561Sobrienset_pe_name (char *name, long val) 36433965Sjdp{ 36533965Sjdp int i; 366130561Sobrien 367130561Sobrien /* Find the name and set it. */ 36833965Sjdp for (i = 0; init[i].ptr; i++) 36933965Sjdp { 37033965Sjdp if (strcmp (name, init[i].symbol) == 0) 37133965Sjdp { 37233965Sjdp init[i].value = val; 37333965Sjdp init[i].inited = 1; 37433965Sjdp return; 37533965Sjdp } 37633965Sjdp } 377130561Sobrien abort (); 37833965Sjdp} 37933965Sjdp 38033965Sjdp 38133965Sjdpstatic void 382130561Sobrienset_pe_subsystem (void) 38333965Sjdp{ 38433965Sjdp const char *sver; 385218822Sdim const char *entry; 386218822Sdim const char *initial_symbol_char; 387218822Sdim char *end; 38833965Sjdp int len; 38933965Sjdp int i; 390218822Sdim int subsystem; 391218822Sdim unsigned long temp_subsystem; 39289857Sobrien static const struct 39333965Sjdp { 39433965Sjdp const char *name; 39533965Sjdp const int value; 39633965Sjdp const char *entry; 39733965Sjdp } 39833965Sjdp v[] = 39933965Sjdp { 400218822Sdim { "native", 1, "NtProcessStartup" }, 40160484Sobrien { "windows", 2, "WinMainCRTStartup" }, 40260484Sobrien { "console", 3, "mainCRTStartup" }, 403218822Sdim { "posix", 7, "__PosixProcessStartup"}, 404218822Sdim { "wince", 9, "WinMainCRTStartup" }, 405218822Sdim { "xbox", 14, "mainCRTStartup" }, 406218822Sdim { NULL, 0, NULL } 40733965Sjdp }; 408218822Sdim /* Entry point name for arbitrary subsystem numbers. */ 409218822Sdim static const char default_entry[] = "mainCRTStartup"; 41033965Sjdp 411218822Sdim /* Check for the presence of a version number. */ 41233965Sjdp sver = strchr (optarg, ':'); 41333965Sjdp if (sver == NULL) 41433965Sjdp len = strlen (optarg); 41533965Sjdp else 41633965Sjdp { 41733965Sjdp len = sver - optarg; 41833965Sjdp set_pe_name ("__major_subsystem_version__", 41933965Sjdp strtoul (sver + 1, &end, 0)); 42033965Sjdp if (*end == '.') 42133965Sjdp set_pe_name ("__minor_subsystem_version__", 42233965Sjdp strtoul (end + 1, &end, 0)); 42333965Sjdp if (*end != '\0') 42460484Sobrien einfo (_("%P: warning: bad version number in -subsystem option\n")); 42533965Sjdp } 42633965Sjdp 427218822Sdim /* Check for numeric subsystem. */ 428218822Sdim temp_subsystem = strtoul (optarg, & end, 0); 429218822Sdim if ((*end == ':' || *end == '\0') && (temp_subsystem < 65536)) 43033965Sjdp { 431218822Sdim /* Search list for a numeric match to use its entry point. */ 432218822Sdim for (i = 0; v[i].name; i++) 433218822Sdim if (v[i].value == (int) temp_subsystem) 434218822Sdim break; 43560484Sobrien 436218822Sdim /* If no match, use the default. */ 437218822Sdim if (v[i].name != NULL) 438218822Sdim entry = v[i].entry; 439218822Sdim else 440218822Sdim entry = default_entry; 44133965Sjdp 442218822Sdim /* Use this subsystem. */ 443218822Sdim subsystem = (int) temp_subsystem; 444218822Sdim } 445218822Sdim else 446218822Sdim { 447218822Sdim /* Search for subsystem by name. */ 448218822Sdim for (i = 0; v[i].name; i++) 449218822Sdim if (strncmp (optarg, v[i].name, len) == 0 450218822Sdim && v[i].name[len] == '\0') 451218822Sdim break; 45233965Sjdp 453218822Sdim if (v[i].name == NULL) 454218822Sdim { 455218822Sdim einfo (_("%P%F: invalid subsystem type %s\n"), optarg); 45633965Sjdp return; 45733965Sjdp } 458218822Sdim 459218822Sdim entry = v[i].entry; 460218822Sdim subsystem = v[i].value; 46133965Sjdp } 46289857Sobrien 463218822Sdim set_pe_name ("__subsystem__", subsystem); 464218822Sdim 465218822Sdim initial_symbol_char = ${INITIAL_SYMBOL_CHAR}; 466218822Sdim if (*initial_symbol_char != '\0') 467218822Sdim { 468218822Sdim char *alc_entry; 469218822Sdim 470218822Sdim /* lang_default_entry expects its argument to be permanently 471218822Sdim allocated, so we don't free this string. */ 472218822Sdim alc_entry = xmalloc (strlen (initial_symbol_char) 473218822Sdim + strlen (entry) 474218822Sdim + 1); 475218822Sdim strcpy (alc_entry, initial_symbol_char); 476218822Sdim strcat (alc_entry, entry); 477218822Sdim entry = alc_entry; 478218822Sdim } 479218822Sdim 480218822Sdim lang_default_entry (entry); 481218822Sdim 482218822Sdim return; 48333965Sjdp} 48433965Sjdp 48533965Sjdp 48633965Sjdpstatic void 487130561Sobrienset_pe_value (char *name) 48833965Sjdp{ 48933965Sjdp char *end; 49089857Sobrien 49133965Sjdp set_pe_name (name, strtoul (optarg, &end, 0)); 49289857Sobrien 49333965Sjdp if (end == optarg) 49460484Sobrien einfo (_("%P%F: invalid hex number for PE parameter '%s'\n"), optarg); 49533965Sjdp 49633965Sjdp optarg = end; 49733965Sjdp} 49833965Sjdp 499130561Sobrien 50033965Sjdpstatic void 501130561Sobrienset_pe_stack_heap (char *resname, char *comname) 50233965Sjdp{ 50333965Sjdp set_pe_value (resname); 50489857Sobrien 50533965Sjdp if (*optarg == ',') 50633965Sjdp { 50733965Sjdp optarg++; 50833965Sjdp set_pe_value (comname); 50933965Sjdp } 51033965Sjdp else if (*optarg) 51160484Sobrien einfo (_("%P%F: strange hex info for PE parameter '%s'\n"), optarg); 51233965Sjdp} 51333965Sjdp 51433965Sjdp 515130561Sobrienstatic bfd_boolean 516130561Sobriengld${EMULATION_NAME}_handle_option (int optc) 51733965Sjdp{ 51833965Sjdp switch (optc) 51933965Sjdp { 52033965Sjdp default: 521130561Sobrien return FALSE; 52233965Sjdp 52333965Sjdp case OPTION_BASE_FILE: 524130561Sobrien link_info.base_file = fopen (optarg, FOPEN_WB); 52533965Sjdp if (link_info.base_file == NULL) 52633965Sjdp { 52760484Sobrien /* xgettext:c-format */ 52860484Sobrien fprintf (stderr, _("%s: Can't open base file %s\n"), 52933965Sjdp program_name, optarg); 53033965Sjdp xexit (1); 53133965Sjdp } 53233965Sjdp break; 53333965Sjdp 534130561Sobrien /* PE options. */ 53589857Sobrien case OPTION_HEAP: 53633965Sjdp set_pe_stack_heap ("__size_of_heap_reserve__", "__size_of_heap_commit__"); 53733965Sjdp break; 53889857Sobrien case OPTION_STACK: 53933965Sjdp set_pe_stack_heap ("__size_of_stack_reserve__", "__size_of_stack_commit__"); 54033965Sjdp break; 54133965Sjdp case OPTION_SUBSYSTEM: 54233965Sjdp set_pe_subsystem (); 54333965Sjdp break; 54433965Sjdp case OPTION_MAJOR_OS_VERSION: 54533965Sjdp set_pe_value ("__major_os_version__"); 54633965Sjdp break; 54733965Sjdp case OPTION_MINOR_OS_VERSION: 54833965Sjdp set_pe_value ("__minor_os_version__"); 54933965Sjdp break; 55033965Sjdp case OPTION_MAJOR_SUBSYSTEM_VERSION: 55133965Sjdp set_pe_value ("__major_subsystem_version__"); 55233965Sjdp break; 55333965Sjdp case OPTION_MINOR_SUBSYSTEM_VERSION: 55433965Sjdp set_pe_value ("__minor_subsystem_version__"); 55533965Sjdp break; 55633965Sjdp case OPTION_MAJOR_IMAGE_VERSION: 55733965Sjdp set_pe_value ("__major_image_version__"); 55833965Sjdp break; 55933965Sjdp case OPTION_MINOR_IMAGE_VERSION: 56033965Sjdp set_pe_value ("__minor_image_version__"); 56133965Sjdp break; 56233965Sjdp case OPTION_FILE_ALIGNMENT: 56333965Sjdp set_pe_value ("__file_alignment__"); 56433965Sjdp break; 56533965Sjdp case OPTION_SECTION_ALIGNMENT: 56633965Sjdp set_pe_value ("__section_alignment__"); 56733965Sjdp break; 56833965Sjdp case OPTION_DLL: 56933965Sjdp set_pe_name ("__dll__", 1); 57033965Sjdp break; 57133965Sjdp case OPTION_IMAGE_BASE: 57233965Sjdp set_pe_value ("__image_base__"); 57333965Sjdp break; 57460484Sobrien case OPTION_SUPPORT_OLD_CODE: 57560484Sobrien support_old_code = 1; 57660484Sobrien break; 57760484Sobrien case OPTION_THUMB_ENTRY: 57860484Sobrien thumb_entry_symbol = optarg; 57960484Sobrien break; 58060484Sobrien#ifdef DLL_SUPPORT 58160484Sobrien case OPTION_OUT_DEF: 58260484Sobrien pe_out_def_filename = xstrdup (optarg); 58360484Sobrien break; 58460484Sobrien case OPTION_EXPORT_ALL: 58560484Sobrien pe_dll_export_everything = 1; 58660484Sobrien break; 58760484Sobrien case OPTION_EXCLUDE_SYMBOLS: 588104834Sobrien pe_dll_add_excludes (optarg, 0); 58960484Sobrien break; 590104834Sobrien case OPTION_EXCLUDE_LIBS: 591104834Sobrien pe_dll_add_excludes (optarg, 1); 592104834Sobrien break; 59360484Sobrien case OPTION_KILL_ATS: 59460484Sobrien pe_dll_kill_ats = 1; 59560484Sobrien break; 59660484Sobrien case OPTION_STDCALL_ALIASES: 59760484Sobrien pe_dll_stdcall_aliases = 1; 59860484Sobrien break; 59960484Sobrien case OPTION_ENABLE_STDCALL_FIXUP: 60060484Sobrien pe_enable_stdcall_fixup = 1; 60160484Sobrien break; 60260484Sobrien case OPTION_DISABLE_STDCALL_FIXUP: 60360484Sobrien pe_enable_stdcall_fixup = 0; 60460484Sobrien break; 60560484Sobrien case OPTION_IMPLIB_FILENAME: 60660484Sobrien pe_implib_filename = xstrdup (optarg); 60760484Sobrien break; 60860484Sobrien case OPTION_WARN_DUPLICATE_EXPORTS: 60960484Sobrien pe_dll_warn_dup_exports = 1; 61060484Sobrien break; 61160484Sobrien case OPTION_IMP_COMPAT: 61260484Sobrien pe_dll_compat_implib = 1; 61360484Sobrien break; 61477298Sobrien case OPTION_ENABLE_AUTO_IMAGE_BASE: 61577298Sobrien pe_enable_auto_image_base = 1; 61677298Sobrien break; 61777298Sobrien case OPTION_DISABLE_AUTO_IMAGE_BASE: 61877298Sobrien pe_enable_auto_image_base = 0; 61977298Sobrien break; 62077298Sobrien case OPTION_DLL_SEARCH_PREFIX: 621130561Sobrien pe_dll_search_prefix = xstrdup (optarg); 62277298Sobrien break; 62377298Sobrien case OPTION_NO_DEFAULT_EXCLUDES: 62477298Sobrien pe_dll_do_default_excludes = 0; 62577298Sobrien break; 62689857Sobrien case OPTION_DLL_ENABLE_AUTO_IMPORT: 627104834Sobrien link_info.pei386_auto_import = 1; 62889857Sobrien break; 62989857Sobrien case OPTION_DLL_DISABLE_AUTO_IMPORT: 630104834Sobrien link_info.pei386_auto_import = 0; 63189857Sobrien break; 632130561Sobrien case OPTION_DLL_ENABLE_RUNTIME_PSEUDO_RELOC: 633130561Sobrien link_info.pei386_runtime_pseudo_reloc = 1; 634130561Sobrien break; 635130561Sobrien case OPTION_DLL_DISABLE_RUNTIME_PSEUDO_RELOC: 636130561Sobrien link_info.pei386_runtime_pseudo_reloc = 0; 637130561Sobrien break; 63889857Sobrien case OPTION_ENABLE_EXTRA_PE_DEBUG: 63989857Sobrien pe_dll_extra_pe_debug = 1; 64089857Sobrien break; 64160484Sobrien#endif 642218822Sdim case OPTION_LARGE_ADDRESS_AWARE: 643218822Sdim real_flags |= IMAGE_FILE_LARGE_ADDRESS_AWARE; 644218822Sdim break; 64533965Sjdp } 646130561Sobrien return TRUE; 64733965Sjdp} 64833965Sjdp 64977298Sobrien 65077298Sobrien#ifdef DLL_SUPPORT 65189857Sobrienstatic unsigned long 65277298Sobrienstrhash (const char *str) 65377298Sobrien{ 65477298Sobrien const unsigned char *s; 65577298Sobrien unsigned long hash; 65677298Sobrien unsigned int c; 65777298Sobrien unsigned int len; 65877298Sobrien 65977298Sobrien hash = 0; 66077298Sobrien len = 0; 66177298Sobrien s = (const unsigned char *) str; 66277298Sobrien while ((c = *s++) != '\0') 66377298Sobrien { 66477298Sobrien hash += c + (c << 17); 66577298Sobrien hash ^= hash >> 2; 66677298Sobrien ++len; 66777298Sobrien } 66877298Sobrien hash += len + (len << 17); 66977298Sobrien hash ^= hash >> 2; 67077298Sobrien 67177298Sobrien return hash; 67277298Sobrien} 67377298Sobrien 674130561Sobrien/* Use the output file to create a image base for relocatable DLLs. */ 675130561Sobrien 67677298Sobrienstatic unsigned long 67777298Sobriencompute_dll_image_base (const char *ofile) 67877298Sobrien{ 67977298Sobrien unsigned long hash = strhash (ofile); 680218822Sdim return 0x61300000 + ((hash << 16) & 0x0FFC0000); 68177298Sobrien} 68277298Sobrien#endif 68377298Sobrien 68438889Sjdp/* Assign values to the special symbols before the linker script is 68538889Sjdp read. */ 68638889Sjdp 68733965Sjdpstatic void 688130561Sobriengld_${EMULATION_NAME}_set_symbols (void) 68933965Sjdp{ 69033965Sjdp /* Run through and invent symbols for all the 691130561Sobrien names and insert the defaults. */ 69233965Sjdp int j; 69333965Sjdp lang_statement_list_type *save; 69433965Sjdp 69533965Sjdp if (!init[IMAGEBASEOFF].inited) 69638889Sjdp { 697130561Sobrien if (link_info.relocatable) 69838889Sjdp init[IMAGEBASEOFF].value = 0; 699218822Sdim else if (init[DLLOFF].value || (link_info.shared && !link_info.pie)) 70077298Sobrien#ifdef DLL_SUPPORT 70177298Sobrien init[IMAGEBASEOFF].value = (pe_enable_auto_image_base) ? 70277298Sobrien compute_dll_image_base (output_filename) : NT_DLL_IMAGE_BASE; 70377298Sobrien#else 70438889Sjdp init[IMAGEBASEOFF].value = NT_DLL_IMAGE_BASE; 70577298Sobrien#endif 70638889Sjdp else 70738889Sjdp init[IMAGEBASEOFF].value = NT_EXE_IMAGE_BASE; 70838889Sjdp } 70933965Sjdp 710130561Sobrien /* Don't do any symbol assignments if this is a relocatable link. */ 711130561Sobrien if (link_info.relocatable) 71238889Sjdp return; 71338889Sjdp 714130561Sobrien /* Glue the assignments into the abs section. */ 71533965Sjdp save = stat_ptr; 71633965Sjdp 71733965Sjdp stat_ptr = &(abs_output_section->children); 71833965Sjdp 71933965Sjdp for (j = 0; init[j].ptr; j++) 72033965Sjdp { 72133965Sjdp long val = init[j].value; 72260484Sobrien lang_assignment_statement_type *rv; 723104834Sobrien rv = lang_add_assignment (exp_assop ('=', init[j].symbol, 724104834Sobrien exp_intop (val))); 725130561Sobrien if (init[j].size == sizeof (short)) 726130561Sobrien *(short *) init[j].ptr = val; 727130561Sobrien else if (init[j].size == sizeof (int)) 728130561Sobrien *(int *) init[j].ptr = val; 729130561Sobrien else if (init[j].size == sizeof (long)) 730130561Sobrien *(long *) init[j].ptr = val; 73133965Sjdp /* This might be a long long or other special type. */ 732130561Sobrien else if (init[j].size == sizeof (bfd_vma)) 733130561Sobrien *(bfd_vma *) init[j].ptr = val; 734130561Sobrien else abort (); 73560484Sobrien if (j == IMAGEBASEOFF) 73660484Sobrien image_base_statement = rv; 73733965Sjdp } 738130561Sobrien /* Restore the pointer. */ 73933965Sjdp stat_ptr = save; 74089857Sobrien 74133965Sjdp if (pe.FileAlignment > 74233965Sjdp pe.SectionAlignment) 74333965Sjdp { 74460484Sobrien einfo (_("%P: warning, file alignment > section alignment.\n")); 74533965Sjdp } 74633965Sjdp} 74733965Sjdp 74860484Sobrien/* This is called after the linker script and the command line options 74960484Sobrien have been read. */ 75060484Sobrien 75133965Sjdpstatic void 752130561Sobriengld_${EMULATION_NAME}_after_parse (void) 75333965Sjdp{ 75460484Sobrien /* The Windows libraries are designed for the linker to treat the 75560484Sobrien entry point as an undefined symbol. Otherwise, the .obj that 75660484Sobrien defines mainCRTStartup is brought in because it is the first 75760484Sobrien encountered in libc.lib and it has other symbols in it which will 75860484Sobrien be pulled in by the link process. To avoid this, we act as 75960484Sobrien though the user specified -u with the entry point symbol. 76033965Sjdp 76160484Sobrien This function is called after the linker script and command line 76260484Sobrien options have been read, so at this point we know the right entry 76360484Sobrien point. This function is called before the input files are 76460484Sobrien opened, so registering the symbol as undefined will make a 76560484Sobrien difference. */ 76633965Sjdp 767130561Sobrien if (! link_info.relocatable && entry_symbol.name != NULL) 768104834Sobrien ldlang_add_undef (entry_symbol.name); 76933965Sjdp} 77033965Sjdp 77189857Sobrien/* pe-dll.c directly accesses pe_data_import_dll, 77289857Sobrien so it must be defined outside of #ifdef DLL_SUPPORT. 77389857Sobrien Note - this variable is deliberately not initialised. 77489857Sobrien This allows it to be treated as a common varaible, and only 77589857Sobrien exist in one incarnation in a multiple target enabled linker. */ 77689857Sobrienchar * pe_data_import_dll; 77789857Sobrien 77877298Sobrien#ifdef DLL_SUPPORT 77960484Sobrienstatic struct bfd_link_hash_entry *pe_undef_found_sym; 78060484Sobrien 781130561Sobrienstatic bfd_boolean 782130561Sobrienpe_undef_cdecl_match (struct bfd_link_hash_entry *h, void *inf) 78333965Sjdp{ 78489857Sobrien int sl; 785130561Sobrien char *string = inf; 786130561Sobrien 787130561Sobrien sl = strlen (string); 78860484Sobrien if (h->type == bfd_link_hash_defined 78960484Sobrien && strncmp (h->root.string, string, sl) == 0 79060484Sobrien && h->root.string[sl] == '@') 79189857Sobrien { 79289857Sobrien pe_undef_found_sym = h; 793130561Sobrien return FALSE; 79489857Sobrien } 795130561Sobrien return TRUE; 79633965Sjdp} 79733965Sjdp 79860484Sobrienstatic void 799130561Sobrienpe_fixup_stdcalls (void) 80033965Sjdp{ 80160484Sobrien static int gave_warning_message = 0; 80260484Sobrien struct bfd_link_hash_entry *undef, *sym; 803130561Sobrien 80489857Sobrien if (pe_dll_extra_pe_debug) 805130561Sobrien printf ("%s\n", __FUNCTION__); 80689857Sobrien 807218822Sdim for (undef = link_info.hash->undefs; undef; undef=undef->u.undef.next) 80860484Sobrien if (undef->type == bfd_link_hash_undefined) 80960484Sobrien { 810130561Sobrien char* at = strchr (undef->root.string, '@'); 811130561Sobrien int lead_at = (*undef->root.string == '@'); 812130561Sobrien /* For now, don't try to fixup fastcall symbols. */ 813130561Sobrien 814130561Sobrien if (at && !lead_at) 815130561Sobrien { 816130561Sobrien /* The symbol is a stdcall symbol, so let's look for a 817130561Sobrien cdecl symbol with the same name and resolve to that. */ 818130561Sobrien char *cname = xstrdup (undef->root.string /* + lead_at */); 819130561Sobrien at = strchr (cname, '@'); 820130561Sobrien *at = 0; 821130561Sobrien sym = bfd_link_hash_lookup (link_info.hash, cname, 0, 0, 1); 822130561Sobrien 823130561Sobrien if (sym && sym->type == bfd_link_hash_defined) 824130561Sobrien { 825130561Sobrien undef->type = bfd_link_hash_defined; 826130561Sobrien undef->u.def.value = sym->u.def.value; 827130561Sobrien undef->u.def.section = sym->u.def.section; 828130561Sobrien 829130561Sobrien if (pe_enable_stdcall_fixup == -1) 830130561Sobrien { 831130561Sobrien einfo (_("Warning: resolving %s by linking to %s\n"), 832130561Sobrien undef->root.string, cname); 833130561Sobrien if (! gave_warning_message) 834130561Sobrien { 835130561Sobrien gave_warning_message = 1; 836130561Sobrien einfo (_("Use --enable-stdcall-fixup to disable these warnings\n")); 837130561Sobrien einfo (_("Use --disable-stdcall-fixup to disable these fixups\n")); 838130561Sobrien } 839130561Sobrien } 840130561Sobrien } 841130561Sobrien } 842130561Sobrien else 843130561Sobrien { 844130561Sobrien /* The symbol is a cdecl symbol, so we look for stdcall 845130561Sobrien symbols - which means scanning the whole symbol table. */ 846130561Sobrien pe_undef_found_sym = 0; 847130561Sobrien bfd_link_hash_traverse (link_info.hash, pe_undef_cdecl_match, 848130561Sobrien (char *) undef->root.string); 849130561Sobrien sym = pe_undef_found_sym; 850130561Sobrien if (sym) 851130561Sobrien { 852130561Sobrien undef->type = bfd_link_hash_defined; 853130561Sobrien undef->u.def.value = sym->u.def.value; 854130561Sobrien undef->u.def.section = sym->u.def.section; 855130561Sobrien 856130561Sobrien if (pe_enable_stdcall_fixup == -1) 857130561Sobrien { 858130561Sobrien einfo (_("Warning: resolving %s by linking to %s\n"), 859130561Sobrien undef->root.string, sym->root.string); 860130561Sobrien if (! gave_warning_message) 861130561Sobrien { 862130561Sobrien gave_warning_message = 1; 863130561Sobrien einfo (_("Use --enable-stdcall-fixup to disable these warnings\n")); 864130561Sobrien einfo (_("Use --disable-stdcall-fixup to disable these fixups\n")); 865130561Sobrien } 866130561Sobrien } 867130561Sobrien } 868130561Sobrien } 86960484Sobrien } 87033965Sjdp} 87189857Sobrien 87289857Sobrienstatic int 873130561Sobrienmake_import_fixup (arelent *rel, asection *s) 87489857Sobrien{ 875130561Sobrien struct bfd_symbol *sym = *rel->sym_ptr_ptr; 876218822Sdim char addend[4]; 87789857Sobrien 87889857Sobrien if (pe_dll_extra_pe_debug) 879130561Sobrien printf ("arelent: %s@%#lx: add=%li\n", sym->name, 880130561Sobrien (long) rel->address, (long) rel->addend); 88189857Sobrien 882218822Sdim if (! bfd_get_section_contents (s->owner, s, addend, rel->address, sizeof (addend))) 883130561Sobrien einfo (_("%C: Cannot get section contents - auto-import exception\n"), 884130561Sobrien s->owner, s, rel->address); 88589857Sobrien 886218822Sdim pe_create_import_fixup (rel, s, bfd_get_32 (s->owner, addend)); 88789857Sobrien 88889857Sobrien return 1; 88989857Sobrien} 89089857Sobrien 89189857Sobrienstatic void 892130561Sobrienpe_find_data_imports (void) 89389857Sobrien{ 89489857Sobrien struct bfd_link_hash_entry *undef, *sym; 895130561Sobrien 896130561Sobrien if (link_info.pei386_auto_import == 0) 897130561Sobrien return; 898130561Sobrien 899218822Sdim for (undef = link_info.hash->undefs; undef; undef=undef->u.undef.next) 90089857Sobrien { 90189857Sobrien if (undef->type == bfd_link_hash_undefined) 902218822Sdim { 903218822Sdim /* C++ symbols are *long*. */ 904218822Sdim char buf[4096]; 905130561Sobrien 906130561Sobrien if (pe_dll_extra_pe_debug) 907130561Sobrien printf ("%s:%s\n", __FUNCTION__, undef->root.string); 908130561Sobrien 909218822Sdim sprintf (buf, "__imp_%s", undef->root.string); 91089857Sobrien 911218822Sdim sym = bfd_link_hash_lookup (link_info.hash, buf, 0, 0, 1); 912130561Sobrien 913218822Sdim if (sym && sym->type == bfd_link_hash_defined) 914218822Sdim { 915130561Sobrien bfd *b = sym->u.def.section->owner; 916130561Sobrien asymbol **symbols; 917130561Sobrien int nsyms, symsize, i; 91889857Sobrien 919130561Sobrien if (link_info.pei386_auto_import == -1) 920130561Sobrien info_msg (_("Info: resolving %s by linking to %s (auto-import)\n"), 921130561Sobrien undef->root.string, buf); 92289857Sobrien 923130561Sobrien symsize = bfd_get_symtab_upper_bound (b); 924130561Sobrien symbols = (asymbol **) xmalloc (symsize); 925130561Sobrien nsyms = bfd_canonicalize_symtab (b, symbols); 92689857Sobrien 927130561Sobrien for (i = 0; i < nsyms; i++) 928130561Sobrien { 929218822Sdim if (! CONST_STRNEQ (symbols[i]->name, U ("_head_"))) 930130561Sobrien continue; 93189857Sobrien 932130561Sobrien if (pe_dll_extra_pe_debug) 933130561Sobrien printf ("->%s\n", symbols[i]->name); 934130561Sobrien 935130561Sobrien pe_data_import_dll = (char*) (symbols[i]->name + 936218822Sdim sizeof (U ("_head_")) - 1); 937130561Sobrien break; 938130561Sobrien } 939130561Sobrien 940130561Sobrien pe_walk_relocs_of_symbol (&link_info, undef->root.string, 941130561Sobrien make_import_fixup); 942130561Sobrien 943130561Sobrien /* Let's differentiate it somehow from defined. */ 944130561Sobrien undef->type = bfd_link_hash_defweak; 945130561Sobrien /* We replace original name with __imp_ prefixed, this 946130561Sobrien 1) may trash memory 2) leads to duplicate symbol generation. 947130561Sobrien Still, IMHO it's better than having name poluted. */ 948130561Sobrien undef->root.string = sym->root.string; 949130561Sobrien undef->u.def.value = sym->u.def.value; 950130561Sobrien undef->u.def.section = sym->u.def.section; 951218822Sdim } 952218822Sdim } 95389857Sobrien } 95489857Sobrien} 95533965Sjdp 956130561Sobrienstatic bfd_boolean 957130561Sobrienpr_sym (struct bfd_hash_entry *h, void *inf ATTRIBUTE_UNUSED) 95889857Sobrien{ 95989857Sobrien if (pe_dll_extra_pe_debug) 960130561Sobrien printf ("+%s\n", h->string); 961130561Sobrien 962130561Sobrien return TRUE; 96389857Sobrien} 964130561Sobrien#endif /* DLL_SUPPORT */ 96589857Sobrien 96689857Sobrien 96760484Sobrienstatic void 968130561Sobriengld_${EMULATION_NAME}_after_open (void) 96933965Sjdp{ 970130561Sobrien#ifdef DLL_SUPPORT 97189857Sobrien if (pe_dll_extra_pe_debug) 97289857Sobrien { 97389857Sobrien bfd *a; 97489857Sobrien struct bfd_link_hash_entry *sym; 975130561Sobrien 97689857Sobrien printf ("%s()\n", __FUNCTION__); 97789857Sobrien 978218822Sdim for (sym = link_info.hash->undefs; sym; sym=sym->u.undef.next) 979218822Sdim printf ("-%s\n", sym->root.string); 980130561Sobrien bfd_hash_traverse (&link_info.hash->table, pr_sym, NULL); 98189857Sobrien 98289857Sobrien for (a = link_info.input_bfds; a; a = a->link_next) 983130561Sobrien printf ("*%s\n",a->filename); 98489857Sobrien } 985130561Sobrien#endif 98689857Sobrien 98760484Sobrien /* Pass the wacky PE command line options into the output bfd. 98860484Sobrien FIXME: This should be done via a function, rather than by 98960484Sobrien including an internal BFD header. */ 99089857Sobrien 99189857Sobrien if (coff_data (output_bfd) == NULL || coff_data (output_bfd)->pe == 0) 992218822Sdim einfo (_("%F%P: cannot perform PE operations on non PE output file '%B'.\n"), output_bfd); 99333965Sjdp 99460484Sobrien pe_data (output_bfd)->pe_opthdr = pe; 99560484Sobrien pe_data (output_bfd)->dll = init[DLLOFF].value; 996218822Sdim pe_data (output_bfd)->real_flags |= real_flags; 99733965Sjdp 99860484Sobrien#ifdef DLL_SUPPORT 99960484Sobrien if (pe_enable_stdcall_fixup) /* -1=warn or 1=disable */ 100060484Sobrien pe_fixup_stdcalls (); 100133965Sjdp 1002130561Sobrien pe_process_import_defs (output_bfd, & link_info); 1003130561Sobrien 100489857Sobrien pe_find_data_imports (); 100589857Sobrien 1006218822Sdim#if defined (TARGET_IS_i386pe) \ 1007218822Sdim || defined (TARGET_IS_armpe) \ 1008218822Sdim || defined (TARGET_IS_arm_epoc_pe) \ 1009218822Sdim || defined (TARGET_IS_arm_wince_pe) 1010130561Sobrien if (!link_info.relocatable) 101160484Sobrien pe_dll_build_sections (output_bfd, &link_info); 101260484Sobrien else 101360484Sobrien pe_exe_build_sections (output_bfd, &link_info); 1014218822Sdim#else 1015218822Sdim if (link_info.shared) 1016218822Sdim pe_dll_build_sections (output_bfd, &link_info); 101760484Sobrien#endif 1018218822Sdim#endif /* DLL_SUPPORT */ 101933965Sjdp 1020218822Sdim#if defined(TARGET_IS_armpe) || defined(TARGET_IS_arm_epoc_pe) || defined(TARGET_IS_arm_wince_pe) 102160484Sobrien if (strstr (bfd_get_target (output_bfd), "arm") == NULL) 102260484Sobrien { 102360484Sobrien /* The arm backend needs special fields in the output hash structure. 102460484Sobrien These will only be created if the output format is an arm format, 102560484Sobrien hence we do not support linking and changing output formats at the 102660484Sobrien same time. Use a link followed by objcopy to change output formats. */ 102760484Sobrien einfo ("%F%X%P: error: cannot change output format whilst linking ARM binaries\n"); 102860484Sobrien return; 102960484Sobrien } 103060484Sobrien { 103160484Sobrien /* Find a BFD that can hold the interworking stubs. */ 103260484Sobrien LANG_FOR_EACH_INPUT_STATEMENT (is) 103360484Sobrien { 1034218822Sdim if (bfd_arm_get_bfd_for_interworking (is->the_bfd, & link_info)) 103560484Sobrien break; 103660484Sobrien } 103760484Sobrien } 103860484Sobrien#endif 103933965Sjdp 104060484Sobrien { 104177298Sobrien /* This next chunk of code tries to detect the case where you have 104277298Sobrien two import libraries for the same DLL (specifically, 104377298Sobrien symbolically linking libm.a and libc.a in cygwin to 104477298Sobrien libcygwin.a). In those cases, it's possible for function 104577298Sobrien thunks from the second implib to be used but without the 104677298Sobrien head/tail objects, causing an improper import table. We detect 104777298Sobrien those cases and rename the "other" import libraries to match 104877298Sobrien the one the head/tail come from, so that the linker will sort 1049130561Sobrien things nicely and produce a valid import table. */ 105077298Sobrien 105177298Sobrien LANG_FOR_EACH_INPUT_STATEMENT (is) 105277298Sobrien { 105377298Sobrien if (is->the_bfd->my_archive) 105477298Sobrien { 105577298Sobrien int idata2 = 0, reloc_count=0, is_imp = 0; 105677298Sobrien asection *sec; 105789857Sobrien 105877298Sobrien /* See if this is an import library thunk. */ 105977298Sobrien for (sec = is->the_bfd->sections; sec; sec = sec->next) 106077298Sobrien { 106177298Sobrien if (strcmp (sec->name, ".idata\$2") == 0) 106277298Sobrien idata2 = 1; 1063218822Sdim if (CONST_STRNEQ (sec->name, ".idata\$")) 106477298Sobrien is_imp = 1; 106577298Sobrien reloc_count += sec->reloc_count; 106677298Sobrien } 106789857Sobrien 106877298Sobrien if (is_imp && !idata2 && reloc_count) 106977298Sobrien { 107077298Sobrien /* It is, look for the reference to head and see if it's 107177298Sobrien from our own library. */ 107277298Sobrien for (sec = is->the_bfd->sections; sec; sec = sec->next) 107377298Sobrien { 107477298Sobrien int i; 107577298Sobrien long symsize; 107677298Sobrien long relsize; 107777298Sobrien asymbol **symbols; 107877298Sobrien arelent **relocs; 107977298Sobrien int nrelocs; 108089857Sobrien 108177298Sobrien symsize = bfd_get_symtab_upper_bound (is->the_bfd); 108277298Sobrien if (symsize < 1) 108377298Sobrien break; 108477298Sobrien relsize = bfd_get_reloc_upper_bound (is->the_bfd, sec); 108577298Sobrien if (relsize < 1) 108677298Sobrien break; 108789857Sobrien 108877298Sobrien symbols = (asymbol **) xmalloc (symsize); 108989857Sobrien symsize = bfd_canonicalize_symtab (is->the_bfd, symbols); 109077298Sobrien if (symsize < 0) 109177298Sobrien { 109277298Sobrien einfo ("%X%P: unable to process symbols: %E"); 109377298Sobrien return; 109477298Sobrien } 109589857Sobrien 109677298Sobrien relocs = (arelent **) xmalloc ((size_t) relsize); 109777298Sobrien nrelocs = bfd_canonicalize_reloc (is->the_bfd, sec, 1098218822Sdim relocs, symbols); 109977298Sobrien if (nrelocs < 0) 110077298Sobrien { 110177298Sobrien free (relocs); 110277298Sobrien einfo ("%X%P: unable to process relocs: %E"); 110377298Sobrien return; 110477298Sobrien } 110589857Sobrien 110677298Sobrien for (i = 0; i < nrelocs; i++) 110777298Sobrien { 1108130561Sobrien struct bfd_symbol *s; 110977298Sobrien struct bfd_link_hash_entry * blhe; 1110218822Sdim char *other_bfd_filename; 111177298Sobrien char *n; 111289857Sobrien 111377298Sobrien s = (relocs[i]->sym_ptr_ptr)[0]; 111489857Sobrien 111577298Sobrien if (s->flags & BSF_LOCAL) 111677298Sobrien continue; 111789857Sobrien 111877298Sobrien /* Thunk section with reloc to another bfd. */ 111977298Sobrien blhe = bfd_link_hash_lookup (link_info.hash, 112077298Sobrien s->name, 1121130561Sobrien FALSE, FALSE, TRUE); 112289857Sobrien 112377298Sobrien if (blhe == NULL 112477298Sobrien || blhe->type != bfd_link_hash_defined) 112577298Sobrien continue; 112689857Sobrien 1127218822Sdim other_bfd_filename 1128218822Sdim = blhe->u.def.section->owner->my_archive 1129218822Sdim ? bfd_get_filename (blhe->u.def.section->owner->my_archive) 1130218822Sdim : bfd_get_filename (blhe->u.def.section->owner); 113189857Sobrien 1132218822Sdim if (strcmp (bfd_get_filename (is->the_bfd->my_archive), 1133218822Sdim other_bfd_filename) == 0) 113477298Sobrien continue; 113589857Sobrien 1136218822Sdim /* Rename this implib to match the other one. */ 1137218822Sdim n = xmalloc (strlen (other_bfd_filename) + 1); 1138218822Sdim strcpy (n, other_bfd_filename); 113977298Sobrien is->the_bfd->my_archive->filename = n; 114077298Sobrien } 114177298Sobrien 114277298Sobrien free (relocs); 114377298Sobrien /* Note - we do not free the symbols, 114477298Sobrien they are now cached in the BFD. */ 114577298Sobrien } 114677298Sobrien } 114777298Sobrien } 114877298Sobrien } 114977298Sobrien } 115077298Sobrien 115177298Sobrien { 115260484Sobrien int is_ms_arch = 0; 115360484Sobrien bfd *cur_arch = 0; 115460484Sobrien lang_input_statement_type *is2; 1155130561Sobrien lang_input_statement_type *is3; 115633965Sjdp 115760484Sobrien /* Careful - this is a shell script. Watch those dollar signs! */ 115860484Sobrien /* Microsoft import libraries have every member named the same, 115960484Sobrien and not in the right order for us to link them correctly. We 116060484Sobrien must detect these and rename the members so that they'll link 116160484Sobrien correctly. There are three types of objects: the head, the 116260484Sobrien thunks, and the sentinel(s). The head is easy; it's the one 116360484Sobrien with idata2. We assume that the sentinels won't have relocs, 116460484Sobrien and the thunks will. It's easier than checking the symbol 116560484Sobrien table for external references. */ 116660484Sobrien LANG_FOR_EACH_INPUT_STATEMENT (is) 116733965Sjdp { 116860484Sobrien if (is->the_bfd->my_archive) 116960484Sobrien { 1170130561Sobrien char *pnt; 117160484Sobrien bfd *arch = is->the_bfd->my_archive; 1172130561Sobrien 117360484Sobrien if (cur_arch != arch) 117460484Sobrien { 117560484Sobrien cur_arch = arch; 117660484Sobrien is_ms_arch = 1; 1177130561Sobrien 1178130561Sobrien for (is3 = is; 1179130561Sobrien is3 && is3->the_bfd->my_archive == arch; 1180130561Sobrien is3 = (lang_input_statement_type *) is3->next) 118160484Sobrien { 1182218822Sdim /* A MS dynamic import library can also contain static 1183130561Sobrien members, so look for the first element with a .dll 1184130561Sobrien extension, and use that for the remainder of the 1185130561Sobrien comparisons. */ 1186130561Sobrien pnt = strrchr (is3->the_bfd->filename, '.'); 1187130561Sobrien if (pnt != NULL && strcmp (pnt, ".dll") == 0) 1188130561Sobrien break; 118960484Sobrien } 1190130561Sobrien 1191130561Sobrien if (is3 == NULL) 1192130561Sobrien is_ms_arch = 0; 1193130561Sobrien else 1194130561Sobrien { 1195130561Sobrien /* OK, found one. Now look to see if the remaining 1196130561Sobrien (dynamic import) members use the same name. */ 1197130561Sobrien for (is2 = is; 1198130561Sobrien is2 && is2->the_bfd->my_archive == arch; 1199130561Sobrien is2 = (lang_input_statement_type *) is2->next) 1200130561Sobrien { 1201130561Sobrien /* Skip static members, ie anything with a .obj 1202130561Sobrien extension. */ 1203130561Sobrien pnt = strrchr (is2->the_bfd->filename, '.'); 1204130561Sobrien if (pnt != NULL && strcmp (pnt, ".obj") == 0) 1205130561Sobrien continue; 1206130561Sobrien 1207130561Sobrien if (strcmp (is3->the_bfd->filename, 1208130561Sobrien is2->the_bfd->filename)) 1209130561Sobrien { 1210130561Sobrien is_ms_arch = 0; 1211130561Sobrien break; 1212130561Sobrien } 1213130561Sobrien } 1214130561Sobrien } 121560484Sobrien } 121633965Sjdp 1217130561Sobrien /* This fragment might have come from an .obj file in a Microsoft 1218130561Sobrien import, and not an actual import record. If this is the case, 1219130561Sobrien then leave the filename alone. */ 1220130561Sobrien pnt = strrchr (is->the_bfd->filename, '.'); 1221130561Sobrien 1222130561Sobrien if (is_ms_arch && (strcmp (pnt, ".dll") == 0)) 122360484Sobrien { 122460484Sobrien int idata2 = 0, reloc_count=0; 122560484Sobrien asection *sec; 122660484Sobrien char *new_name, seq; 122733965Sjdp 122860484Sobrien for (sec = is->the_bfd->sections; sec; sec = sec->next) 122960484Sobrien { 123060484Sobrien if (strcmp (sec->name, ".idata\$2") == 0) 123160484Sobrien idata2 = 1; 123260484Sobrien reloc_count += sec->reloc_count; 123360484Sobrien } 123433965Sjdp 123560484Sobrien if (idata2) /* .idata2 is the TOC */ 123660484Sobrien seq = 'a'; 123760484Sobrien else if (reloc_count > 0) /* thunks */ 123860484Sobrien seq = 'b'; 123960484Sobrien else /* sentinel */ 124060484Sobrien seq = 'c'; 124133965Sjdp 124260484Sobrien new_name = xmalloc (strlen (is->the_bfd->filename) + 3); 124360484Sobrien sprintf (new_name, "%s.%c", is->the_bfd->filename, seq); 124460484Sobrien is->the_bfd->filename = new_name; 124533965Sjdp 124677298Sobrien new_name = xmalloc (strlen (is->filename) + 3); 124760484Sobrien sprintf (new_name, "%s.%c", is->filename, seq); 124860484Sobrien is->filename = new_name; 124960484Sobrien } 125060484Sobrien } 125133965Sjdp } 125260484Sobrien } 1253218822Sdim 1254218822Sdim { 1255218822Sdim /* The following chunk of code tries to identify jump stubs in 1256218822Sdim import libraries which are dead code and eliminates them 1257218822Sdim from the final link. For each exported symbol <sym>, there 1258218822Sdim is a object file in the import library with a .text section 1259218822Sdim and several .idata$* sections. The .text section contains the 1260218822Sdim symbol definition for <sym> which is a jump stub of the form 1261218822Sdim jmp *__imp_<sym>. The .idata$5 contains the symbol definition 1262218822Sdim for __imp_<sym> which is the address of the slot for <sym> in 1263218822Sdim the import address table. When a symbol is imported explicitly 1264218822Sdim using __declspec(dllimport) declaration, the compiler generates 1265218822Sdim a reference to __imp_<sym> which directly resolves to the 1266218822Sdim symbol in .idata$5, in which case the jump stub code is not 1267218822Sdim needed. The following code tries to identify jump stub sections 1268218822Sdim in import libraries which are not referred to by anyone and 1269218822Sdim marks them for exclusion from the final link. */ 1270218822Sdim LANG_FOR_EACH_INPUT_STATEMENT (is) 1271218822Sdim { 1272218822Sdim if (is->the_bfd->my_archive) 1273218822Sdim { 1274218822Sdim int is_imp = 0; 1275218822Sdim asection *sec, *stub_sec = NULL; 1276218822Sdim 1277218822Sdim /* See if this is an import library thunk. */ 1278218822Sdim for (sec = is->the_bfd->sections; sec; sec = sec->next) 1279218822Sdim { 1280218822Sdim if (strncmp (sec->name, ".idata\$", 7) == 0) 1281218822Sdim is_imp = 1; 1282218822Sdim /* The section containing the jmp stub has code 1283218822Sdim and has a reloc. */ 1284218822Sdim if ((sec->flags & SEC_CODE) && sec->reloc_count) 1285218822Sdim stub_sec = sec; 1286218822Sdim } 1287218822Sdim 1288218822Sdim if (is_imp && stub_sec) 1289218822Sdim { 1290218822Sdim long symsize; 1291218822Sdim asymbol **symbols; 1292218822Sdim long src_count; 1293218822Sdim struct bfd_link_hash_entry * blhe; 1294218822Sdim 1295218822Sdim symsize = bfd_get_symtab_upper_bound (is->the_bfd); 1296218822Sdim symbols = xmalloc (symsize); 1297218822Sdim symsize = bfd_canonicalize_symtab (is->the_bfd, symbols); 1298218822Sdim 1299218822Sdim for (src_count = 0; src_count < symsize; src_count++) 1300218822Sdim { 1301218822Sdim if (symbols[src_count]->section->id == stub_sec->id) 1302218822Sdim { 1303218822Sdim /* This symbol belongs to the section containing 1304218822Sdim the stub. */ 1305218822Sdim blhe = bfd_link_hash_lookup (link_info.hash, 1306218822Sdim symbols[src_count]->name, 1307218822Sdim FALSE, FALSE, TRUE); 1308218822Sdim /* If the symbol in the stub section has no other 1309218822Sdim undefined references, exclude the stub section 1310218822Sdim from the final link. */ 1311218822Sdim if (blhe && (blhe->type == bfd_link_hash_defined) 1312218822Sdim && (blhe->u.undef.next == NULL)) 1313218822Sdim stub_sec->flags |= SEC_EXCLUDE; 1314218822Sdim } 1315218822Sdim } 1316218822Sdim free (symbols); 1317218822Sdim } 1318218822Sdim } 1319218822Sdim } 1320218822Sdim } 132133965Sjdp} 132260484Sobrien 132389857Sobrienstatic void 1324130561Sobriengld_${EMULATION_NAME}_before_allocation (void) 132533965Sjdp{ 132633965Sjdp#ifdef TARGET_IS_ppcpe 1327130561Sobrien /* Here we rummage through the found bfds to collect toc information. */ 132833965Sjdp { 132933965Sjdp LANG_FOR_EACH_INPUT_STATEMENT (is) 133033965Sjdp { 133160484Sobrien if (!ppc_process_before_allocation (is->the_bfd, &link_info)) 133233965Sjdp { 133360484Sobrien /* xgettext:c-format */ 133460484Sobrien einfo (_("Errors encountered processing file %s\n"), is->filename); 133533965Sjdp } 133633965Sjdp } 133733965Sjdp } 133833965Sjdp 1339130561Sobrien /* We have seen it all. Allocate it, and carry on. */ 134033965Sjdp ppc_allocate_toc_section (&link_info); 134160484Sobrien#endif /* TARGET_IS_ppcpe */ 134260484Sobrien 1343218822Sdim#if defined(TARGET_IS_armpe) || defined(TARGET_IS_arm_epoc_pe) || defined(TARGET_IS_arm_wince_pe) 134438889Sjdp /* FIXME: we should be able to set the size of the interworking stub 134538889Sjdp section. 134633965Sjdp 134738889Sjdp Here we rummage through the found bfds to collect glue 134838889Sjdp information. FIXME: should this be based on a command line 1349130561Sobrien option? krk@cygnus.com. */ 135038889Sjdp { 135138889Sjdp LANG_FOR_EACH_INPUT_STATEMENT (is) 135238889Sjdp { 1353218822Sdim if (! bfd_arm_process_before_allocation 135460484Sobrien (is->the_bfd, & link_info, support_old_code)) 135538889Sjdp { 135660484Sobrien /* xgettext:c-format */ 135760484Sobrien einfo (_("Errors encountered processing file %s for interworking"), 135860484Sobrien is->filename); 135938889Sjdp } 136038889Sjdp } 136138889Sjdp } 136238889Sjdp 1363130561Sobrien /* We have seen it all. Allocate it, and carry on. */ 1364218822Sdim bfd_arm_allocate_interworking_sections (& link_info); 1365218822Sdim#endif /* TARGET_IS_armpe || TARGET_IS_arm_epoc_pe || TARGET_IS_arm_wince_pe */ 1366218822Sdim 1367218822Sdim before_allocation_default (); 136860484Sobrien} 136960484Sobrien 137077298Sobrien#ifdef DLL_SUPPORT 137160484Sobrien/* This is called when an input file isn't recognized as a BFD. We 1372130561Sobrien check here for .DEF files and pull them in automatically. */ 137377298Sobrien 137460484Sobrienstatic int 1375130561Sobriensaw_option (char *option) 137660484Sobrien{ 137760484Sobrien int i; 1378130561Sobrien 1379130561Sobrien for (i = 0; init[i].ptr; i++) 138060484Sobrien if (strcmp (init[i].symbol, option) == 0) 138160484Sobrien return init[i].inited; 138260484Sobrien return 0; 138333965Sjdp} 138477298Sobrien#endif /* DLL_SUPPORT */ 138560484Sobrien 1386130561Sobrienstatic bfd_boolean 1387130561Sobriengld_${EMULATION_NAME}_unrecognized_file (lang_input_statement_type *entry ATTRIBUTE_UNUSED) 138860484Sobrien{ 138960484Sobrien#ifdef DLL_SUPPORT 139060484Sobrien const char *ext = entry->filename + strlen (entry->filename) - 4; 139160484Sobrien 139260484Sobrien if (strcmp (ext, ".def") == 0 || strcmp (ext, ".DEF") == 0) 139360484Sobrien { 1394218822Sdim pe_def_file = def_file_parse (entry->filename, pe_def_file); 1395130561Sobrien 1396130561Sobrien if (pe_def_file) 139760484Sobrien { 1398130561Sobrien int i, buflen=0, len; 1399130561Sobrien char *buf; 140060484Sobrien 1401130561Sobrien for (i = 0; i < pe_def_file->num_exports; i++) 140260484Sobrien { 1403130561Sobrien len = strlen (pe_def_file->exports[i].internal_name); 1404130561Sobrien if (buflen < len + 2) 1405130561Sobrien buflen = len + 2; 140660484Sobrien } 140760484Sobrien 1408130561Sobrien buf = (char *) xmalloc (buflen); 140960484Sobrien 1410130561Sobrien for (i = 0; i < pe_def_file->num_exports; i++) 1411130561Sobrien { 1412130561Sobrien struct bfd_link_hash_entry *h; 141360484Sobrien 1414218822Sdim sprintf (buf, "%s%s", U (""), pe_def_file->exports[i].internal_name); 1415130561Sobrien 1416130561Sobrien h = bfd_link_hash_lookup (link_info.hash, buf, TRUE, TRUE, TRUE); 1417130561Sobrien if (h == (struct bfd_link_hash_entry *) NULL) 1418130561Sobrien einfo (_("%P%F: bfd_link_hash_lookup failed: %E\n")); 1419130561Sobrien if (h->type == bfd_link_hash_new) 1420130561Sobrien { 1421130561Sobrien h->type = bfd_link_hash_undefined; 1422130561Sobrien h->u.undef.abfd = NULL; 1423130561Sobrien bfd_link_add_undef (link_info.hash, h); 1424130561Sobrien } 1425130561Sobrien } 1426130561Sobrien free (buf); 1427130561Sobrien 1428130561Sobrien /* def_file_print (stdout, pe_def_file); */ 1429130561Sobrien if (pe_def_file->is_dll == 1) 1430130561Sobrien link_info.shared = 1; 1431130561Sobrien 1432130561Sobrien if (pe_def_file->base_address != (bfd_vma)(-1)) 1433130561Sobrien { 1434130561Sobrien pe.ImageBase = 1435130561Sobrien pe_data (output_bfd)->pe_opthdr.ImageBase = 1436130561Sobrien init[IMAGEBASEOFF].value = pe_def_file->base_address; 1437130561Sobrien init[IMAGEBASEOFF].inited = 1; 1438130561Sobrien if (image_base_statement) 1439130561Sobrien image_base_statement->exp = 1440130561Sobrien exp_assop ('=', "__image_base__", exp_intop (pe.ImageBase)); 1441130561Sobrien } 1442130561Sobrien 1443130561Sobrien if (pe_def_file->stack_reserve != -1 1444130561Sobrien && ! saw_option ("__size_of_stack_reserve__")) 1445130561Sobrien { 1446130561Sobrien pe.SizeOfStackReserve = pe_def_file->stack_reserve; 1447130561Sobrien if (pe_def_file->stack_commit != -1) 1448130561Sobrien pe.SizeOfStackCommit = pe_def_file->stack_commit; 1449130561Sobrien } 1450130561Sobrien if (pe_def_file->heap_reserve != -1 1451130561Sobrien && ! saw_option ("__size_of_heap_reserve__")) 1452130561Sobrien { 1453130561Sobrien pe.SizeOfHeapReserve = pe_def_file->heap_reserve; 1454130561Sobrien if (pe_def_file->heap_commit != -1) 1455130561Sobrien pe.SizeOfHeapCommit = pe_def_file->heap_commit; 1456130561Sobrien } 1457130561Sobrien return TRUE; 1458130561Sobrien } 145960484Sobrien } 146060484Sobrien#endif 1461130561Sobrien return FALSE; 146260484Sobrien} 146360484Sobrien 1464130561Sobrienstatic bfd_boolean 1465130561Sobriengld_${EMULATION_NAME}_recognized_file (lang_input_statement_type *entry ATTRIBUTE_UNUSED) 146660484Sobrien{ 146760484Sobrien#ifdef DLL_SUPPORT 146860484Sobrien#ifdef TARGET_IS_i386pe 146960484Sobrien pe_dll_id_target ("pei-i386"); 147060484Sobrien#endif 147160484Sobrien#ifdef TARGET_IS_shpe 147260484Sobrien pe_dll_id_target ("pei-shl"); 147360484Sobrien#endif 147460484Sobrien#ifdef TARGET_IS_mipspe 147560484Sobrien pe_dll_id_target ("pei-mips"); 147660484Sobrien#endif 147760484Sobrien#ifdef TARGET_IS_armpe 147860484Sobrien pe_dll_id_target ("pei-arm-little"); 147960484Sobrien#endif 1480218822Sdim#ifdef TARGET_IS_arm_epoc_pe 1481218822Sdim pe_dll_id_target ("epoc-pei-arm-little"); 148260484Sobrien#endif 1483218822Sdim#ifdef TARGET_IS_arm_wince_pe 1484218822Sdim pe_dll_id_target ("pei-arm-wince-little"); 1485218822Sdim#endif 1486218822Sdim if (pe_bfd_is_dll (entry->the_bfd)) 1487218822Sdim return pe_implied_import_dll (entry->filename); 1488218822Sdim#endif 1489130561Sobrien return FALSE; 149060484Sobrien} 149160484Sobrien 149260484Sobrienstatic void 1493130561Sobriengld_${EMULATION_NAME}_finish (void) 149460484Sobrien{ 1495218822Sdim#if defined(TARGET_IS_armpe) || defined(TARGET_IS_arm_epoc_pe) || defined(TARGET_IS_arm_wince_pe) 149660484Sobrien struct bfd_link_hash_entry * h; 149760484Sobrien 149860484Sobrien if (thumb_entry_symbol != NULL) 149960484Sobrien { 1500130561Sobrien h = bfd_link_hash_lookup (link_info.hash, thumb_entry_symbol, 1501130561Sobrien FALSE, FALSE, TRUE); 150289857Sobrien 150360484Sobrien if (h != (struct bfd_link_hash_entry *) NULL 150460484Sobrien && (h->type == bfd_link_hash_defined 150560484Sobrien || h->type == bfd_link_hash_defweak) 150660484Sobrien && h->u.def.section->output_section != NULL) 150760484Sobrien { 150860484Sobrien static char buffer[32]; 150960484Sobrien bfd_vma val; 151089857Sobrien 151160484Sobrien /* Special procesing is required for a Thumb entry symbol. The 151260484Sobrien bottom bit of its address must be set. */ 151360484Sobrien val = (h->u.def.value 151460484Sobrien + bfd_get_section_vma (output_bfd, 151560484Sobrien h->u.def.section->output_section) 151660484Sobrien + h->u.def.section->output_offset); 151789857Sobrien 151860484Sobrien val |= 1; 151989857Sobrien 152060484Sobrien /* Now convert this value into a string and store it in entry_symbol 152160484Sobrien where the lang_finish() function will pick it up. */ 152260484Sobrien buffer[0] = '0'; 152360484Sobrien buffer[1] = 'x'; 152489857Sobrien 152560484Sobrien sprintf_vma (buffer + 2, val); 152689857Sobrien 1527104834Sobrien if (entry_symbol.name != NULL && entry_from_cmdline) 152860484Sobrien einfo (_("%P: warning: '--thumb-entry %s' is overriding '-e %s'\n"), 1529104834Sobrien thumb_entry_symbol, entry_symbol.name); 1530104834Sobrien entry_symbol.name = buffer; 153160484Sobrien } 153260484Sobrien else 153360484Sobrien einfo (_("%P: warning: connot find thumb start symbol %s\n"), thumb_entry_symbol); 153460484Sobrien } 1535218822Sdim#endif /* defined(TARGET_IS_armpe) || defined(TARGET_IS_arm_epoc_pe) || defined(TARGET_IS_arm_wince_pe) */ 153660484Sobrien 1537218822Sdim finish_default (); 1538218822Sdim 153960484Sobrien#ifdef DLL_SUPPORT 1540130561Sobrien if (link_info.shared 1541130561Sobrien#if !defined(TARGET_IS_shpe) && !defined(TARGET_IS_mipspe) 1542130561Sobrien || (!link_info.relocatable && pe_def_file->num_exports != 0) 1543130561Sobrien#endif 1544130561Sobrien ) 154560484Sobrien { 154660484Sobrien pe_dll_fill_sections (output_bfd, &link_info); 154760484Sobrien if (pe_implib_filename) 154860484Sobrien pe_dll_generate_implib (pe_def_file, pe_implib_filename); 154960484Sobrien } 155060484Sobrien#if defined(TARGET_IS_shpe) || defined(TARGET_IS_mipspe) 155177298Sobrien /* ARM doesn't need relocs. */ 155260484Sobrien else 155360484Sobrien { 155460484Sobrien pe_exe_fill_sections (output_bfd, &link_info); 155560484Sobrien } 155660484Sobrien#endif 155789857Sobrien 155860484Sobrien if (pe_out_def_filename) 155960484Sobrien pe_dll_generate_def_file (pe_out_def_filename); 156077298Sobrien#endif /* DLL_SUPPORT */ 156189857Sobrien 1562130561Sobrien /* I don't know where .idata gets set as code, but it shouldn't be. */ 156389857Sobrien { 156489857Sobrien asection *asec = bfd_get_section_by_name (output_bfd, ".idata"); 1565130561Sobrien 156689857Sobrien if (asec) 156789857Sobrien { 1568218822Sdim asec->flags &= ~SEC_CODE; 1569218822Sdim asec->flags |= SEC_DATA; 157089857Sobrien } 157189857Sobrien } 157260484Sobrien} 157360484Sobrien 157433965Sjdp 157560484Sobrien/* Place an orphan section. 157633965Sjdp 157760484Sobrien We use this to put sections in a reasonable place in the file, and 157860484Sobrien to ensure that they are aligned as required. 157938889Sjdp 158060484Sobrien We handle grouped sections here as well. A section named .foo$nn 158160484Sobrien goes into the output section .foo. All grouped sections are sorted 158260484Sobrien by name. 158360484Sobrien 158460484Sobrien Grouped sections for the default sections are handled by the 158560484Sobrien default linker script using wildcards, and are sorted by 158660484Sobrien sort_sections. */ 158760484Sobrien 1588130561Sobrienstatic bfd_boolean 1589218822Sdimgld_${EMULATION_NAME}_place_orphan (asection *s) 159033965Sjdp{ 159133965Sjdp const char *secname; 1592218822Sdim const char *orig_secname; 159360484Sobrien char *dollar = NULL; 159477298Sobrien lang_output_section_statement_type *os; 159577298Sobrien lang_statement_list_type add_child; 1596218822Sdim lang_statement_union_type **pl; 159733965Sjdp 159833965Sjdp secname = bfd_get_section_name (s->owner, s); 159933965Sjdp 160060484Sobrien /* Look through the script to see where to place this section. */ 1601218822Sdim orig_secname = secname; 1602218822Sdim if (!link_info.relocatable 1603218822Sdim && (dollar = strchr (secname, '$')) != NULL) 160460484Sobrien { 1605218822Sdim size_t len = dollar - orig_secname; 1606218822Sdim char *newname = xmalloc (len + 1); 1607218822Sdim memcpy (newname, orig_secname, len); 1608218822Sdim newname[len] = '\0'; 1609218822Sdim secname = newname; 161060484Sobrien } 161133965Sjdp 1612218822Sdim os = lang_output_section_find (secname); 161360484Sobrien 161477298Sobrien lang_list_init (&add_child); 161577298Sobrien 161677298Sobrien if (os != NULL 161789857Sobrien && (os->bfd_section == NULL 1618218822Sdim || os->bfd_section->flags == 0 161989857Sobrien || ((s->flags ^ os->bfd_section->flags) 162089857Sobrien & (SEC_LOAD | SEC_ALLOC)) == 0)) 162133965Sjdp { 162289857Sobrien /* We already have an output section statement with this 1623218822Sdim name, and its bfd section, if any, has compatible flags. 1624218822Sdim If the section already exists but does not have any flags set, 1625218822Sdim then it has been created by the linker, probably as a result of 1626218822Sdim a --section-start command line switch. */ 1627218822Sdim lang_add_section (&add_child, s, os); 162877298Sobrien } 162977298Sobrien else 163077298Sobrien { 1631218822Sdim static struct orphan_save hold[] = 1632218822Sdim { 1633218822Sdim { ".text", 1634218822Sdim SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_CODE, 1635218822Sdim 0, 0, 0, 0 }, 1636218822Sdim { ".rdata", 1637218822Sdim SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_DATA, 1638218822Sdim 0, 0, 0, 0 }, 1639218822Sdim { ".data", 1640218822Sdim SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_DATA, 1641218822Sdim 0, 0, 0, 0 }, 1642218822Sdim { ".bss", 1643218822Sdim SEC_ALLOC, 1644218822Sdim 0, 0, 0, 0 } 1645218822Sdim }; 1646218822Sdim enum orphan_save_index 1647218822Sdim { 1648218822Sdim orphan_text = 0, 1649218822Sdim orphan_rodata, 1650218822Sdim orphan_data, 1651218822Sdim orphan_bss 1652218822Sdim }; 1653218822Sdim static int orphan_init_done = 0; 165477298Sobrien struct orphan_save *place; 1655218822Sdim lang_output_section_statement_type *after; 165660484Sobrien etree_type *address; 165760484Sobrien 1658218822Sdim if (!orphan_init_done) 1659218822Sdim { 1660218822Sdim struct orphan_save *ho; 1661218822Sdim for (ho = hold; ho < hold + sizeof (hold) / sizeof (hold[0]); ++ho) 1662218822Sdim if (ho->name != NULL) 1663218822Sdim { 1664218822Sdim ho->os = lang_output_section_find (ho->name); 1665218822Sdim if (ho->os != NULL && ho->os->flags == 0) 1666218822Sdim ho->os->flags = ho->flags; 1667218822Sdim } 1668218822Sdim orphan_init_done = 1; 1669218822Sdim } 1670218822Sdim 167160484Sobrien /* Try to put the new output section in a reasonable place based 167260484Sobrien on the section name and section flags. */ 167377298Sobrien 167460484Sobrien place = NULL; 167577298Sobrien if ((s->flags & SEC_ALLOC) == 0) 167677298Sobrien ; 1677218822Sdim else if ((s->flags & (SEC_LOAD | SEC_HAS_CONTENTS)) == 0) 1678218822Sdim place = &hold[orphan_bss]; 1679218822Sdim else if ((s->flags & SEC_READONLY) == 0) 1680218822Sdim place = &hold[orphan_data]; 1681218822Sdim else if ((s->flags & SEC_CODE) == 0) 1682218822Sdim place = &hold[orphan_rodata]; 1683218822Sdim else 1684218822Sdim place = &hold[orphan_text]; 168560484Sobrien 1686218822Sdim after = NULL; 1687218822Sdim if (place != NULL) 168860484Sobrien { 1689218822Sdim if (place->os == NULL) 1690218822Sdim place->os = lang_output_section_find (place->name); 1691218822Sdim after = place->os; 1692218822Sdim if (after == NULL) 1693218822Sdim after = lang_output_section_find_by_flags (s, &place->os, NULL); 1694218822Sdim if (after == NULL) 1695218822Sdim /* *ABS* is always the first output section statement. */ 1696218822Sdim after = (&lang_output_section_statement.head 1697218822Sdim ->output_section_statement); 169860484Sobrien } 169960484Sobrien 1700218822Sdim /* Choose a unique name for the section. This will be needed if the 1701218822Sdim same section name appears in the input file with different 1702218822Sdim loadable or allocatable characteristics. */ 1703218822Sdim if (bfd_get_section_by_name (output_bfd, secname) != NULL) 170477298Sobrien { 1705218822Sdim static int count = 1; 1706218822Sdim secname = bfd_get_unique_section_name (output_bfd, secname, &count); 1707218822Sdim if (secname == NULL) 1708218822Sdim einfo ("%F%P: place_orphan failed: %E\n"); 170977298Sobrien } 171089857Sobrien 1711218822Sdim /* All sections in an executable must be aligned to a page boundary. */ 1712218822Sdim address = exp_unop (ALIGN_K, exp_nameop (NAME, "__section_alignment__")); 1713218822Sdim os = lang_insert_orphan (s, secname, after, place, address, &add_child); 1714218822Sdim } 171560484Sobrien 1716218822Sdim /* If the section name has a '\$', sort it with the other '\$' 1717218822Sdim sections. */ 1718218822Sdim for (pl = &os->children.head; *pl != NULL; pl = &(*pl)->header.next) 1719218822Sdim { 1720218822Sdim lang_input_section_type *ls; 1721218822Sdim const char *lname; 172260484Sobrien 1723218822Sdim if ((*pl)->header.type != lang_input_section_enum) 1724218822Sdim continue; 172560484Sobrien 1726218822Sdim ls = &(*pl)->input_section; 172760484Sobrien 1728218822Sdim lname = bfd_get_section_name (ls->section->owner, ls->section); 1729218822Sdim if (strchr (lname, '\$') != NULL 1730218822Sdim && (dollar == NULL || strcmp (orig_secname, lname) < 0)) 1731218822Sdim break; 1732218822Sdim } 173377298Sobrien 1734218822Sdim if (add_child.head != NULL) 1735218822Sdim { 1736218822Sdim *add_child.tail = *pl; 1737218822Sdim *pl = add_child.head; 173833965Sjdp } 173933965Sjdp 1740130561Sobrien return TRUE; 174133965Sjdp} 174260484Sobrien 1743130561Sobrienstatic bfd_boolean 1744130561Sobriengld_${EMULATION_NAME}_open_dynamic_archive 1745130561Sobrien (const char *arch ATTRIBUTE_UNUSED, search_dirs_type *search, 1746130561Sobrien lang_input_statement_type *entry) 174760484Sobrien{ 1748218822Sdim static const struct 1749218822Sdim { 1750218822Sdim const char * format; 1751218822Sdim bfd_boolean use_prefix; 1752218822Sdim } 1753218822Sdim libname_fmt [] = 1754218822Sdim { 1755218822Sdim /* Preferred explicit import library for dll's. */ 1756218822Sdim { "lib%s.dll.a", FALSE }, 1757218822Sdim /* Alternate explicit import library for dll's. */ 1758218822Sdim { "%s.dll.a", FALSE }, 1759218822Sdim /* "libfoo.a" could be either an import lib or a static lib. 1760218822Sdim For backwards compatibility, libfoo.a needs to precede 1761218822Sdim libfoo.dll and foo.dll in the search. */ 1762218822Sdim { "lib%s.a", FALSE }, 1763218822Sdim /* The 'native' spelling of an import lib name is "foo.lib". */ 1764218822Sdim { "%s.lib", FALSE }, 1765218822Sdim#ifdef DLL_SUPPORT 1766218822Sdim /* Try "<prefix>foo.dll" (preferred dll name, if specified). */ 1767218822Sdim { "%s%s.dll", TRUE }, 1768218822Sdim#endif 1769218822Sdim /* Try "libfoo.dll" (default preferred dll name). */ 1770218822Sdim { "lib%s.dll", FALSE }, 1771218822Sdim /* Finally try 'native' dll name "foo.dll". */ 1772218822Sdim { "%s.dll", FALSE }, 1773218822Sdim /* Note: If adding more formats to this table, make sure to check to 1774218822Sdim see if their length is longer than libname_fmt[0].format, and if 1775218822Sdim so, update the call to xmalloc() below. */ 1776218822Sdim { NULL, FALSE } 1777218822Sdim }; 1778218822Sdim static unsigned int format_max_len = 0; 177977298Sobrien const char * filename; 1780218822Sdim char * full_string; 1781218822Sdim char * base_string; 1782218822Sdim unsigned int i; 178360484Sobrien 1784218822Sdim 178577298Sobrien if (! entry->is_archive) 1786130561Sobrien return FALSE; 178760484Sobrien 178877298Sobrien filename = entry->filename; 178960484Sobrien 1790218822Sdim if (format_max_len == 0) 1791218822Sdim /* We need to allow space in the memory that we are going to allocate 1792218822Sdim for the characters in the format string. Since the format array is 1793218822Sdim static we only need to calculate this information once. In theory 1794218822Sdim this value could also be computed statically, but this introduces 1795218822Sdim the possibility for a discrepancy and hence a possible memory 1796218822Sdim corruption. The lengths we compute here will be too long because 1797218822Sdim they will include any formating characters (%s) in the strings, but 1798218822Sdim this will not matter. */ 1799218822Sdim for (i = 0; libname_fmt[i].format; i++) 1800218822Sdim if (format_max_len < strlen (libname_fmt[i].format)) 1801218822Sdim format_max_len = strlen (libname_fmt[i].format); 1802218822Sdim 1803218822Sdim full_string = xmalloc (strlen (search->name) 1804218822Sdim + strlen (filename) 1805218822Sdim + format_max_len 180677298Sobrien#ifdef DLL_SUPPORT 1807218822Sdim + (pe_dll_search_prefix 1808218822Sdim ? strlen (pe_dll_search_prefix) : 0) 180977298Sobrien#endif 1810218822Sdim /* Allow for the terminating NUL and for the path 1811218822Sdim separator character that is inserted between 1812218822Sdim search->name and the start of the format string. */ 1813218822Sdim + 2); 181460484Sobrien 1815218822Sdim sprintf (full_string, "%s/", search->name); 1816218822Sdim base_string = full_string + strlen (full_string); 181777298Sobrien 1818218822Sdim for (i = 0; libname_fmt[i].format; i++) 181977298Sobrien { 1820218822Sdim#ifdef DLL_SUPPORT 1821218822Sdim if (libname_fmt[i].use_prefix) 1822218822Sdim { 1823218822Sdim if (!pe_dll_search_prefix) 1824218822Sdim continue; 1825218822Sdim sprintf (base_string, libname_fmt[i].format, pe_dll_search_prefix, filename); 1826218822Sdim } 1827218822Sdim else 1828218822Sdim#endif 1829218822Sdim sprintf (base_string, libname_fmt[i].format, filename); 183077298Sobrien 1831218822Sdim if (ldfile_try_open_bfd (full_string, entry)) 1832218822Sdim break; 183377298Sobrien } 183477298Sobrien 1835218822Sdim if (!libname_fmt[i].format) 1836218822Sdim { 1837218822Sdim free (full_string); 1838218822Sdim return FALSE; 1839218822Sdim } 184077298Sobrien 1841218822Sdim entry->filename = full_string; 1842218822Sdim 1843130561Sobrien return TRUE; 184460484Sobrien} 184560484Sobrien 184660484Sobrienstatic int 1847130561Sobriengld_${EMULATION_NAME}_find_potential_libraries 1848130561Sobrien (char *name, lang_input_statement_type *entry) 184960484Sobrien{ 185060484Sobrien return ldfile_open_file_search (name, entry, "", ".lib"); 185160484Sobrien} 185233965Sjdp 185333965Sjdpstatic char * 1854130561Sobriengld_${EMULATION_NAME}_get_script (int *isfile) 185533965SjdpEOF 185633965Sjdp# Scripts compiled in. 185733965Sjdp# sed commands to quote an ld script as a C string. 185860484Sobriensc="-f stringify.sed" 185933965Sjdp 186033965Sjdpcat >>e${EMULATION_NAME}.c <<EOF 186189857Sobrien{ 186233965Sjdp *isfile = 0; 186333965Sjdp 1864130561Sobrien if (link_info.relocatable && config.build_constructors) 186533965Sjdp return 186633965SjdpEOF 1867218822Sdimsed $sc ldscripts/${EMULATION_NAME}.xu >> e${EMULATION_NAME}.c 1868218822Sdimecho ' ; else if (link_info.relocatable) return' >> e${EMULATION_NAME}.c 1869218822Sdimsed $sc ldscripts/${EMULATION_NAME}.xr >> e${EMULATION_NAME}.c 1870218822Sdimecho ' ; else if (!config.text_read_only) return' >> e${EMULATION_NAME}.c 1871218822Sdimsed $sc ldscripts/${EMULATION_NAME}.xbn >> e${EMULATION_NAME}.c 1872218822Sdimecho ' ; else if (!config.magic_demand_paged) return' >> e${EMULATION_NAME}.c 1873218822Sdimsed $sc ldscripts/${EMULATION_NAME}.xn >> e${EMULATION_NAME}.c 1874218822Sdimecho ' ; else return' >> e${EMULATION_NAME}.c 1875218822Sdimsed $sc ldscripts/${EMULATION_NAME}.x >> e${EMULATION_NAME}.c 1876218822Sdimecho '; }' >> e${EMULATION_NAME}.c 187733965Sjdp 187833965Sjdpcat >>e${EMULATION_NAME}.c <<EOF 187933965Sjdp 188033965Sjdp 188189857Sobrienstruct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation = 188233965Sjdp{ 188333965Sjdp gld_${EMULATION_NAME}_before_parse, 188433965Sjdp syslib_default, 188533965Sjdp hll_default, 188660484Sobrien gld_${EMULATION_NAME}_after_parse, 188733965Sjdp gld_${EMULATION_NAME}_after_open, 188833965Sjdp after_allocation_default, 188933965Sjdp set_output_arch_default, 189033965Sjdp ldemul_default_target, 189133965Sjdp gld_${EMULATION_NAME}_before_allocation, 189233965Sjdp gld_${EMULATION_NAME}_get_script, 189333965Sjdp "${EMULATION_NAME}", 189433965Sjdp "${OUTPUT_FORMAT}", 1895130561Sobrien gld_${EMULATION_NAME}_finish, 1896130561Sobrien NULL, /* Create output section statements. */ 189777298Sobrien gld_${EMULATION_NAME}_open_dynamic_archive, 189860484Sobrien gld_${EMULATION_NAME}_place_orphan, 189933965Sjdp gld_${EMULATION_NAME}_set_symbols, 1900130561Sobrien NULL, /* parse_args */ 1901130561Sobrien gld${EMULATION_NAME}_add_options, 1902130561Sobrien gld${EMULATION_NAME}_handle_option, 190360484Sobrien gld_${EMULATION_NAME}_unrecognized_file, 190460484Sobrien gld_${EMULATION_NAME}_list_options, 190560484Sobrien gld_${EMULATION_NAME}_recognized_file, 1906104834Sobrien gld_${EMULATION_NAME}_find_potential_libraries, 1907130561Sobrien NULL /* new_vers_pattern. */ 190833965Sjdp}; 190933965SjdpEOF 1910