pe.em revision 107492
133965Sjdp# This shell script emits a C file. -*- C -*- 233965Sjdp# It does some substitutions. 389857Sobrienif [ -z "$MACHINE" ]; then 489857Sobrien OUTPUT_ARCH=${ARCH} 589857Sobrienelse 689857Sobrien OUTPUT_ARCH=${ARCH}:${MACHINE} 789857Sobrienfi 860484Sobrienrm -f e${EMULATION_NAME}.c 960484Sobrien(echo;echo;echo;echo;echo)>e${EMULATION_NAME}.c # there, now line numbers match ;-) 1060484Sobriencat >>e${EMULATION_NAME}.c <<EOF 1133965Sjdp/* This file is part of GLD, the Gnu Linker. 12104834Sobrien Copyright 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002 1378828Sobrien Free Software Foundation, Inc. 1433965Sjdp 1533965SjdpThis program is free software; you can redistribute it and/or modify 1633965Sjdpit under the terms of the GNU General Public License as published by 1733965Sjdpthe Free Software Foundation; either version 2 of the License, or 1833965Sjdp(at your option) any later version. 1933965Sjdp 2033965SjdpThis program is distributed in the hope that it will be useful, 2133965Sjdpbut WITHOUT ANY WARRANTY; without even the implied warranty of 2233965SjdpMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 2333965SjdpGNU General Public License for more details. 2433965Sjdp 2533965SjdpYou should have received a copy of the GNU General Public License 2633965Sjdpalong with this program; if not, write to the Free Software 2733965SjdpFoundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ 2833965Sjdp 2933965Sjdp/* For WINDOWS_NT */ 3033965Sjdp/* The original file generated returned different default scripts depending 3133965Sjdp on whether certain switches were set, but these switches pertain to the 3233965Sjdp Linux system and that particular version of coff. In the NT case, we 3333965Sjdp only determine if the subsystem is console or windows in order to select 3489857Sobrien the correct entry point by default. */ 3589857Sobrien 3689857Sobrien#define TARGET_IS_${EMULATION_NAME} 3789857Sobrien 3889857Sobrien/* Do this before including bfd.h, so we prototype the right functions. */ 3989857Sobrien#ifdef TARGET_IS_arm_epoc_pe 4089857Sobrien#define bfd_arm_pe_allocate_interworking_sections \ 4189857Sobrien bfd_arm_epoc_pe_allocate_interworking_sections 4289857Sobrien#define bfd_arm_pe_get_bfd_for_interworking \ 4389857Sobrien bfd_arm_epoc_pe_get_bfd_for_interworking 4489857Sobrien#define bfd_arm_pe_process_before_allocation \ 4589857Sobrien bfd_arm_epoc_pe_process_before_allocation 4689857Sobrien#endif 4789857Sobrien 4833965Sjdp#include "bfd.h" 4933965Sjdp#include "sysdep.h" 5033965Sjdp#include "bfdlink.h" 5133965Sjdp#include "getopt.h" 5233965Sjdp#include "libiberty.h" 5333965Sjdp#include "ld.h" 5433965Sjdp#include "ldmain.h" 5533965Sjdp#include "ldexp.h" 5633965Sjdp#include "ldlang.h" 5777298Sobrien#include "ldfile.h" 5833965Sjdp#include "ldemul.h" 59107492Sobrien#include <ldgram.h> 6033965Sjdp#include "ldlex.h" 6133965Sjdp#include "ldmisc.h" 6233965Sjdp#include "ldctor.h" 6333965Sjdp#include "coff/internal.h" 6460484Sobrien 6560484Sobrien/* FIXME: This is a BFD internal header file, and we should not be 6660484Sobrien using it here. */ 6733965Sjdp#include "../bfd/libcoff.h" 6833965Sjdp 6960484Sobrien#include "deffile.h" 7060484Sobrien#include "pe-dll.h" 7160484Sobrien 7289857Sobrien#include <ctype.h> 7333965Sjdp 7460484Sobrien/* Permit the emulation parameters to override the default section 7560484Sobrien alignment by setting OVERRIDE_SECTION_ALIGNMENT. FIXME: This makes 7660484Sobrien it seem that include/coff/internal.h should not define 7760484Sobrien PE_DEF_SECTION_ALIGNMENT. */ 7860484Sobrien#if PE_DEF_SECTION_ALIGNMENT != ${OVERRIDE_SECTION_ALIGNMENT:-PE_DEF_SECTION_ALIGNMENT} 7960484Sobrien#undef PE_DEF_SECTION_ALIGNMENT 8060484Sobrien#define PE_DEF_SECTION_ALIGNMENT ${OVERRIDE_SECTION_ALIGNMENT} 8160484Sobrien#endif 8260484Sobrien 8360484Sobrien#if defined(TARGET_IS_i386pe) 8460484Sobrien#define DLL_SUPPORT 8560484Sobrien#endif 8660484Sobrien#if defined(TARGET_IS_shpe) || defined(TARGET_IS_mipspe) || defined(TARGET_IS_armpe) 8760484Sobrien#define DLL_SUPPORT 8860484Sobrien#endif 8960484Sobrien 9060484Sobrien#if defined(TARGET_IS_i386pe) || ! defined(DLL_SUPPORT) 9160484Sobrien#define PE_DEF_SUBSYSTEM 3 9260484Sobrien#else 9360484Sobrien#undef NT_EXE_IMAGE_BASE 9460484Sobrien#undef PE_DEF_SECTION_ALIGNMENT 9560484Sobrien#undef PE_DEF_FILE_ALIGNMENT 9660484Sobrien#define NT_EXE_IMAGE_BASE 0x00010000 9760484Sobrien#ifdef TARGET_IS_armpe 9860484Sobrien#define PE_DEF_SECTION_ALIGNMENT 0x00001000 9960484Sobrien#define PE_DEF_SUBSYSTEM 9 10060484Sobrien#else 10160484Sobrien#define PE_DEF_SECTION_ALIGNMENT 0x00000400 10260484Sobrien#define PE_DEF_SUBSYSTEM 2 10360484Sobrien#endif 10460484Sobrien#define PE_DEF_FILE_ALIGNMENT 0x00000200 10560484Sobrien#endif 10660484Sobrien 10733965Sjdpstatic void gld_${EMULATION_NAME}_set_symbols PARAMS ((void)); 10833965Sjdpstatic void gld_${EMULATION_NAME}_after_open PARAMS ((void)); 10933965Sjdpstatic void gld_${EMULATION_NAME}_before_parse PARAMS ((void)); 11060484Sobrienstatic void gld_${EMULATION_NAME}_after_parse PARAMS ((void)); 11133965Sjdpstatic void gld_${EMULATION_NAME}_before_allocation PARAMS ((void)); 11289857Sobrienstatic asection *output_prev_sec_find 11389857Sobrien PARAMS ((lang_output_section_statement_type *)); 11460484Sobrienstatic boolean gld_${EMULATION_NAME}_place_orphan 11533965Sjdp PARAMS ((lang_input_statement_type *, asection *)); 11633965Sjdpstatic char *gld_${EMULATION_NAME}_get_script PARAMS ((int *)); 11733965Sjdpstatic int gld_${EMULATION_NAME}_parse_args PARAMS ((int, char **)); 11860484Sobrienstatic void gld_${EMULATION_NAME}_finish PARAMS ((void)); 11989857Sobrienstatic boolean gld_${EMULATION_NAME}_open_dynamic_archive 12077298Sobrien PARAMS ((const char *, search_dirs_type *, lang_input_statement_type *)); 12189857Sobrienstatic void gld_${EMULATION_NAME}_list_options PARAMS ((FILE *)); 12289857Sobrienstatic void set_pe_name PARAMS ((char *, long)); 12389857Sobrienstatic void set_pe_subsystem PARAMS ((void)); 12489857Sobrienstatic void set_pe_value PARAMS ((char *)); 12589857Sobrienstatic void set_pe_stack_heap PARAMS ((char *, char *)); 12633965Sjdp 12789857Sobrien#ifdef DLL_SUPPORT 12889857Sobrienstatic boolean pe_undef_cdecl_match 12989857Sobrien PARAMS ((struct bfd_link_hash_entry *, PTR)); 13089857Sobrienstatic void pe_fixup_stdcalls PARAMS ((void)); 13189857Sobrienstatic int make_import_fixup PARAMS ((arelent *, asection *)); 13289857Sobrienstatic void pe_find_data_imports PARAMS ((void)); 13389857Sobrien#endif 13489857Sobrien 13589857Sobrienstatic boolean pr_sym PARAMS ((struct bfd_hash_entry *, PTR string)); 13689857Sobrienstatic boolean gld_${EMULATION_NAME}_unrecognized_file 13789857Sobrien PARAMS ((lang_input_statement_type *)); 13889857Sobrienstatic boolean gld_${EMULATION_NAME}_recognized_file 13989857Sobrien PARAMS ((lang_input_statement_type *)); 14089857Sobrienstatic int gld_${EMULATION_NAME}_find_potential_libraries 14189857Sobrien PARAMS ((char *, lang_input_statement_type *)); 14289857Sobrien 14389857Sobrien 14433965Sjdpstatic struct internal_extra_pe_aouthdr pe; 14533965Sjdpstatic int dll; 14660484Sobrienstatic int support_old_code = 0; 14760484Sobrienstatic char * thumb_entry_symbol = NULL; 14860484Sobrienstatic lang_assignment_statement_type *image_base_statement = 0; 14933965Sjdp 15077298Sobrien#ifdef DLL_SUPPORT 15160484Sobrienstatic int pe_enable_stdcall_fixup = -1; /* 0=disable 1=enable */ 15277298Sobrienstatic char *pe_out_def_filename = NULL; 15377298Sobrienstatic char *pe_implib_filename = NULL; 15477298Sobrienstatic int pe_enable_auto_image_base = 0; 15577298Sobrienstatic char *pe_dll_search_prefix = NULL; 15660484Sobrien#endif 15760484Sobrien 15833965Sjdpextern const char *output_filename; 15933965Sjdp 16033965Sjdpstatic void 16133965Sjdpgld_${EMULATION_NAME}_before_parse() 16233965Sjdp{ 16389857Sobrien const bfd_arch_info_type *arch = bfd_scan_arch ("${OUTPUT_ARCH}"); 16489857Sobrien if (arch) 16589857Sobrien { 16689857Sobrien ldfile_output_architecture = arch->arch; 16789857Sobrien ldfile_output_machine = arch->mach; 16889857Sobrien ldfile_output_machine_name = arch->printable_name; 16989857Sobrien } 17089857Sobrien else 17189857Sobrien ldfile_output_architecture = bfd_arch_${ARCH}; 17260484Sobrien output_filename = "${EXECUTABLE_NAME:-a.exe}"; 17360484Sobrien#ifdef DLL_SUPPORT 17489857Sobrien config.dynamic_link = true; 17560484Sobrien config.has_shared = 1; 176104834Sobrien link_info.pei386_auto_import = -1; 17760484Sobrien 17860484Sobrien#if (PE_DEF_SUBSYSTEM == 9) || (PE_DEF_SUBSYSTEM == 2) 17960484Sobrien#if defined TARGET_IS_mipspe || defined TARGET_IS_armpe 18060484Sobrien lang_add_entry ("WinMainCRTStartup", 1); 18160484Sobrien#else 18260484Sobrien lang_add_entry ("_WinMainCRTStartup", 1); 18360484Sobrien#endif 18460484Sobrien#endif 18560484Sobrien#endif 18633965Sjdp} 18733965Sjdp 18833965Sjdp/* PE format extra command line options. */ 18933965Sjdp 19033965Sjdp/* Used for setting flags in the PE header. */ 19133965Sjdp#define OPTION_BASE_FILE (300 + 1) 19233965Sjdp#define OPTION_DLL (OPTION_BASE_FILE + 1) 19333965Sjdp#define OPTION_FILE_ALIGNMENT (OPTION_DLL + 1) 19433965Sjdp#define OPTION_IMAGE_BASE (OPTION_FILE_ALIGNMENT + 1) 19533965Sjdp#define OPTION_MAJOR_IMAGE_VERSION (OPTION_IMAGE_BASE + 1) 19633965Sjdp#define OPTION_MAJOR_OS_VERSION (OPTION_MAJOR_IMAGE_VERSION + 1) 19733965Sjdp#define OPTION_MAJOR_SUBSYSTEM_VERSION (OPTION_MAJOR_OS_VERSION + 1) 19833965Sjdp#define OPTION_MINOR_IMAGE_VERSION (OPTION_MAJOR_SUBSYSTEM_VERSION + 1) 19933965Sjdp#define OPTION_MINOR_OS_VERSION (OPTION_MINOR_IMAGE_VERSION + 1) 20033965Sjdp#define OPTION_MINOR_SUBSYSTEM_VERSION (OPTION_MINOR_OS_VERSION + 1) 20133965Sjdp#define OPTION_SECTION_ALIGNMENT (OPTION_MINOR_SUBSYSTEM_VERSION + 1) 20233965Sjdp#define OPTION_STACK (OPTION_SECTION_ALIGNMENT + 1) 20333965Sjdp#define OPTION_SUBSYSTEM (OPTION_STACK + 1) 20433965Sjdp#define OPTION_HEAP (OPTION_SUBSYSTEM + 1) 20560484Sobrien#define OPTION_SUPPORT_OLD_CODE (OPTION_HEAP + 1) 20660484Sobrien#define OPTION_OUT_DEF (OPTION_SUPPORT_OLD_CODE + 1) 20760484Sobrien#define OPTION_EXPORT_ALL (OPTION_OUT_DEF + 1) 20860484Sobrien#define OPTION_EXCLUDE_SYMBOLS (OPTION_EXPORT_ALL + 1) 20960484Sobrien#define OPTION_KILL_ATS (OPTION_EXCLUDE_SYMBOLS + 1) 21060484Sobrien#define OPTION_STDCALL_ALIASES (OPTION_KILL_ATS + 1) 21160484Sobrien#define OPTION_ENABLE_STDCALL_FIXUP (OPTION_STDCALL_ALIASES + 1) 21260484Sobrien#define OPTION_DISABLE_STDCALL_FIXUP (OPTION_ENABLE_STDCALL_FIXUP + 1) 21360484Sobrien#define OPTION_IMPLIB_FILENAME (OPTION_DISABLE_STDCALL_FIXUP + 1) 21460484Sobrien#define OPTION_THUMB_ENTRY (OPTION_IMPLIB_FILENAME + 1) 21560484Sobrien#define OPTION_WARN_DUPLICATE_EXPORTS (OPTION_THUMB_ENTRY + 1) 21660484Sobrien#define OPTION_IMP_COMPAT (OPTION_WARN_DUPLICATE_EXPORTS + 1) 21777298Sobrien#define OPTION_ENABLE_AUTO_IMAGE_BASE (OPTION_IMP_COMPAT + 1) 21877298Sobrien#define OPTION_DISABLE_AUTO_IMAGE_BASE (OPTION_ENABLE_AUTO_IMAGE_BASE + 1) 21977298Sobrien#define OPTION_DLL_SEARCH_PREFIX (OPTION_DISABLE_AUTO_IMAGE_BASE + 1) 22077298Sobrien#define OPTION_NO_DEFAULT_EXCLUDES (OPTION_DLL_SEARCH_PREFIX + 1) 22189857Sobrien#define OPTION_DLL_ENABLE_AUTO_IMPORT (OPTION_NO_DEFAULT_EXCLUDES + 1) 22289857Sobrien#define OPTION_DLL_DISABLE_AUTO_IMPORT (OPTION_DLL_ENABLE_AUTO_IMPORT + 1) 22389857Sobrien#define OPTION_ENABLE_EXTRA_PE_DEBUG (OPTION_DLL_DISABLE_AUTO_IMPORT + 1) 224104834Sobrien#define OPTION_EXCLUDE_LIBS (OPTION_ENABLE_EXTRA_PE_DEBUG + 1) 22533965Sjdp 22677298Sobrienstatic struct option longopts[] = { 22733965Sjdp /* PE options */ 22860484Sobrien {"base-file", required_argument, NULL, OPTION_BASE_FILE}, 22960484Sobrien {"dll", no_argument, NULL, OPTION_DLL}, 23060484Sobrien {"file-alignment", required_argument, NULL, OPTION_FILE_ALIGNMENT}, 23189857Sobrien {"heap", required_argument, NULL, OPTION_HEAP}, 23260484Sobrien {"image-base", required_argument, NULL, OPTION_IMAGE_BASE}, 23360484Sobrien {"major-image-version", required_argument, NULL, OPTION_MAJOR_IMAGE_VERSION}, 23460484Sobrien {"major-os-version", required_argument, NULL, OPTION_MAJOR_OS_VERSION}, 23560484Sobrien {"major-subsystem-version", required_argument, NULL, OPTION_MAJOR_SUBSYSTEM_VERSION}, 23660484Sobrien {"minor-image-version", required_argument, NULL, OPTION_MINOR_IMAGE_VERSION}, 23760484Sobrien {"minor-os-version", required_argument, NULL, OPTION_MINOR_OS_VERSION}, 23860484Sobrien {"minor-subsystem-version", required_argument, NULL, OPTION_MINOR_SUBSYSTEM_VERSION}, 23960484Sobrien {"section-alignment", required_argument, NULL, OPTION_SECTION_ALIGNMENT}, 24060484Sobrien {"stack", required_argument, NULL, OPTION_STACK}, 24160484Sobrien {"subsystem", required_argument, NULL, OPTION_SUBSYSTEM}, 24260484Sobrien {"support-old-code", no_argument, NULL, OPTION_SUPPORT_OLD_CODE}, 24360484Sobrien {"thumb-entry", required_argument, NULL, OPTION_THUMB_ENTRY}, 24460484Sobrien#ifdef DLL_SUPPORT 24560484Sobrien /* getopt allows abbreviations, so we do this to stop it from treating -o 24660484Sobrien as an abbreviation for this option */ 24760484Sobrien {"output-def", required_argument, NULL, OPTION_OUT_DEF}, 24860484Sobrien {"output-def", required_argument, NULL, OPTION_OUT_DEF}, 24960484Sobrien {"export-all-symbols", no_argument, NULL, OPTION_EXPORT_ALL}, 25060484Sobrien {"exclude-symbols", required_argument, NULL, OPTION_EXCLUDE_SYMBOLS}, 251104834Sobrien {"exclude-libs", required_argument, NULL, OPTION_EXCLUDE_LIBS}, 25260484Sobrien {"kill-at", no_argument, NULL, OPTION_KILL_ATS}, 25360484Sobrien {"add-stdcall-alias", no_argument, NULL, OPTION_STDCALL_ALIASES}, 25460484Sobrien {"enable-stdcall-fixup", no_argument, NULL, OPTION_ENABLE_STDCALL_FIXUP}, 25560484Sobrien {"disable-stdcall-fixup", no_argument, NULL, OPTION_DISABLE_STDCALL_FIXUP}, 25660484Sobrien {"out-implib", required_argument, NULL, OPTION_IMPLIB_FILENAME}, 25760484Sobrien {"warn-duplicate-exports", no_argument, NULL, OPTION_WARN_DUPLICATE_EXPORTS}, 25860484Sobrien {"compat-implib", no_argument, NULL, OPTION_IMP_COMPAT}, 25977298Sobrien {"enable-auto-image-base", no_argument, NULL, OPTION_ENABLE_AUTO_IMAGE_BASE}, 26077298Sobrien {"disable-auto-image-base", no_argument, NULL, OPTION_DISABLE_AUTO_IMAGE_BASE}, 26177298Sobrien {"dll-search-prefix", required_argument, NULL, OPTION_DLL_SEARCH_PREFIX}, 26277298Sobrien {"no-default-excludes", no_argument, NULL, OPTION_NO_DEFAULT_EXCLUDES}, 26389857Sobrien {"enable-auto-import", no_argument, NULL, OPTION_DLL_ENABLE_AUTO_IMPORT}, 26489857Sobrien {"disable-auto-import", no_argument, NULL, OPTION_DLL_DISABLE_AUTO_IMPORT}, 26589857Sobrien {"enable-extra-pe-debug", no_argument, NULL, OPTION_ENABLE_EXTRA_PE_DEBUG}, 26660484Sobrien#endif 26760484Sobrien {NULL, no_argument, NULL, 0} 26860484Sobrien}; 26933965Sjdp 27033965Sjdp 27133965Sjdp/* PE/WIN32; added routines to get the subsystem type, heap and/or stack 27233965Sjdp parameters which may be input from the command line */ 27333965Sjdp 27460484Sobrientypedef struct 27560484Sobrien{ 27633965Sjdp void *ptr; 27733965Sjdp int size; 27833965Sjdp int value; 27933965Sjdp char *symbol; 28033965Sjdp int inited; 28133965Sjdp} definfo; 28233965Sjdp 28333965Sjdp#define D(field,symbol,def) {&pe.field,sizeof(pe.field), def, symbol,0} 28433965Sjdp 28533965Sjdpstatic definfo init[] = 28633965Sjdp{ 28733965Sjdp /* imagebase must be first */ 28833965Sjdp#define IMAGEBASEOFF 0 28933965Sjdp D(ImageBase,"__image_base__", NT_EXE_IMAGE_BASE), 29033965Sjdp#define DLLOFF 1 29160484Sobrien {&dll, sizeof(dll), 0, "__dll__", 0}, 29233965Sjdp D(SectionAlignment,"__section_alignment__", PE_DEF_SECTION_ALIGNMENT), 29333965Sjdp D(FileAlignment,"__file_alignment__", PE_DEF_FILE_ALIGNMENT), 29433965Sjdp D(MajorOperatingSystemVersion,"__major_os_version__", 4), 29533965Sjdp D(MinorOperatingSystemVersion,"__minor_os_version__", 0), 29633965Sjdp D(MajorImageVersion,"__major_image_version__", 1), 29733965Sjdp D(MinorImageVersion,"__minor_image_version__", 0), 29860484Sobrien#ifdef TARGET_IS_armpe 29960484Sobrien D(MajorSubsystemVersion,"__major_subsystem_version__", 2), 30060484Sobrien#else 30133965Sjdp D(MajorSubsystemVersion,"__major_subsystem_version__", 4), 30260484Sobrien#endif 30333965Sjdp D(MinorSubsystemVersion,"__minor_subsystem_version__", 0), 30460484Sobrien D(Subsystem,"__subsystem__", ${SUBSYSTEM}), 30578828Sobrien D(SizeOfStackReserve,"__size_of_stack_reserve__", 0x200000), 30633965Sjdp D(SizeOfStackCommit,"__size_of_stack_commit__", 0x1000), 30733965Sjdp D(SizeOfHeapReserve,"__size_of_heap_reserve__", 0x100000), 30833965Sjdp D(SizeOfHeapCommit,"__size_of_heap_commit__", 0x1000), 30933965Sjdp D(LoaderFlags,"__loader_flags__", 0x0), 31033965Sjdp { NULL, 0, 0, NULL, 0 } 31133965Sjdp}; 31233965Sjdp 31360484Sobrienstatic void 31460484Sobriengld_${EMULATION_NAME}_list_options (file) 31560484Sobrien FILE * file; 31660484Sobrien{ 31760484Sobrien fprintf (file, _(" --base_file <basefile> Generate a base file for relocatable DLLs\n")); 31860484Sobrien fprintf (file, _(" --dll Set image base to the default for DLLs\n")); 31960484Sobrien fprintf (file, _(" --file-alignment <size> Set file alignment\n")); 32060484Sobrien fprintf (file, _(" --heap <size> Set initial size of the heap\n")); 32160484Sobrien fprintf (file, _(" --image-base <address> Set start address of the executable\n")); 32260484Sobrien fprintf (file, _(" --major-image-version <number> Set version number of the executable\n")); 32360484Sobrien fprintf (file, _(" --major-os-version <number> Set minimum required OS version\n")); 32460484Sobrien fprintf (file, _(" --major-subsystem-version <number> Set minimum required OS subsystem version\n")); 32560484Sobrien fprintf (file, _(" --minor-image-version <number> Set revision number of the executable\n")); 32660484Sobrien fprintf (file, _(" --minor-os-version <number> Set minimum required OS revision\n")); 32760484Sobrien fprintf (file, _(" --minor-subsystem-version <number> Set minimum required OS subsystem revision\n")); 32860484Sobrien fprintf (file, _(" --section-alignment <size> Set section alignment\n")); 32960484Sobrien fprintf (file, _(" --stack <size> Set size of the initial stack\n")); 33060484Sobrien fprintf (file, _(" --subsystem <name>[:<version>] Set required OS subsystem [& version]\n")); 33160484Sobrien fprintf (file, _(" --support-old-code Support interworking with old code\n")); 33260484Sobrien fprintf (file, _(" --thumb-entry=<symbol> Set the entry point to be Thumb <symbol>\n")); 33360484Sobrien#ifdef DLL_SUPPORT 33460484Sobrien fprintf (file, _(" --add-stdcall-alias Export symbols with and without @nn\n")); 33560484Sobrien fprintf (file, _(" --disable-stdcall-fixup Don't link _sym to _sym@nn\n")); 33660484Sobrien fprintf (file, _(" --enable-stdcall-fixup Link _sym to _sym@nn without warnings\n")); 33760484Sobrien fprintf (file, _(" --exclude-symbols sym,sym,... Exclude symbols from automatic export\n")); 338104834Sobrien fprintf (file, _(" --exclude-libs lib,lib,... Exclude libraries from automatic export\n")); 33960484Sobrien fprintf (file, _(" --export-all-symbols Automatically export all globals to DLL\n")); 34060484Sobrien fprintf (file, _(" --kill-at Remove @nn from exported symbols\n")); 34160484Sobrien fprintf (file, _(" --out-implib <file> Generate import library\n")); 34260484Sobrien fprintf (file, _(" --output-def <file> Generate a .DEF file for the built DLL\n")); 34360484Sobrien fprintf (file, _(" --warn-duplicate-exports Warn about duplicate exports.\n")); 34489857Sobrien fprintf (file, _(" --compat-implib Create backward compatible import libs;\n\ 34589857Sobrien create __imp_<SYMBOL> as well.\n")); 34689857Sobrien fprintf (file, _(" --enable-auto-image-base Automatically choose image base for DLLs\n\ 34789857Sobrien unless user specifies one\n")); 34877298Sobrien fprintf (file, _(" --disable-auto-image-base Do not auto-choose image base. (default)\n")); 34989857Sobrien fprintf (file, _(" --dll-search-prefix=<string> When linking dynamically to a dll without an\n\ 35089857Sobrien importlib, use <string><basename>.dll \n\ 35189857Sobrien in preference to lib<basename>.dll \n")); 35289857Sobrien fprintf (file, _(" --enable-auto-import Do sophistcated linking of _sym to \n\ 35389857Sobrien __imp_sym for DATA references\n")); 35489857Sobrien fprintf (file, _(" --disable-auto-import Do not auto-import DATA items from DLLs\n")); 35589857Sobrien fprintf (file, _(" --enable-extra-pe-debug Enable verbose debug output when building\n\ 35689857Sobrien or linking to DLLs (esp. auto-import)\n")); 35760484Sobrien#endif 35860484Sobrien} 35933965Sjdp 36033965Sjdpstatic void 36133965Sjdpset_pe_name (name, val) 36233965Sjdp char *name; 36333965Sjdp long val; 36433965Sjdp{ 36533965Sjdp int i; 36633965Sjdp /* Find the name and set it. */ 36733965Sjdp for (i = 0; init[i].ptr; i++) 36833965Sjdp { 36933965Sjdp if (strcmp (name, init[i].symbol) == 0) 37033965Sjdp { 37133965Sjdp init[i].value = val; 37233965Sjdp init[i].inited = 1; 37333965Sjdp return; 37433965Sjdp } 37533965Sjdp } 37633965Sjdp abort(); 37733965Sjdp} 37833965Sjdp 37933965Sjdp 38033965Sjdpstatic void 38133965Sjdpset_pe_subsystem () 38233965Sjdp{ 38333965Sjdp const char *sver; 38433965Sjdp int len; 38533965Sjdp int i; 38689857Sobrien static const struct 38733965Sjdp { 38833965Sjdp const char *name; 38933965Sjdp const int value; 39033965Sjdp const char *entry; 39133965Sjdp } 39233965Sjdp v[] = 39333965Sjdp { 39460484Sobrien { "native", 1, "NtProcessStartup" }, 39560484Sobrien#if defined TARGET_IS_mipspe || defined TARGET_IS_armpe 39660484Sobrien { "windows", 2, "WinMainCRTStartup" }, 39760484Sobrien#else 39860484Sobrien { "windows", 2, "WinMainCRTStartup" }, 39960484Sobrien#endif 40060484Sobrien { "console", 3, "mainCRTStartup" }, 40133965Sjdp#if 0 40233965Sjdp /* The Microsoft linker does not recognize this. */ 40333965Sjdp { "os2", 5, "" }, 40433965Sjdp#endif 40560484Sobrien { "posix", 7, "__PosixProcessStartup"}, 40660484Sobrien { "wince", 9, "_WinMainCRTStartup" }, 40733965Sjdp { 0, 0, 0 } 40833965Sjdp }; 40933965Sjdp 41033965Sjdp sver = strchr (optarg, ':'); 41133965Sjdp if (sver == NULL) 41233965Sjdp len = strlen (optarg); 41333965Sjdp else 41433965Sjdp { 41533965Sjdp char *end; 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 42733965Sjdp for (i = 0; v[i].name; i++) 42833965Sjdp { 42933965Sjdp if (strncmp (optarg, v[i].name, len) == 0 43033965Sjdp && v[i].name[len] == '\0') 43133965Sjdp { 43260484Sobrien const char *initial_symbol_char; 43360484Sobrien const char *entry; 43460484Sobrien 43533965Sjdp set_pe_name ("__subsystem__", v[i].value); 43633965Sjdp 43760484Sobrien initial_symbol_char = ${INITIAL_SYMBOL_CHAR}; 43860484Sobrien if (*initial_symbol_char == '\0') 43960484Sobrien entry = v[i].entry; 44060484Sobrien else 44160484Sobrien { 44260484Sobrien char *alc_entry; 44333965Sjdp 44460484Sobrien /* lang_add_entry expects its argument to be permanently 44560484Sobrien allocated, so we don't free this string. */ 44660484Sobrien alc_entry = xmalloc (strlen (initial_symbol_char) 44760484Sobrien + strlen (v[i].entry) 44860484Sobrien + 1); 44960484Sobrien strcpy (alc_entry, initial_symbol_char); 45060484Sobrien strcat (alc_entry, v[i].entry); 45160484Sobrien entry = alc_entry; 45260484Sobrien } 45360484Sobrien 454104834Sobrien lang_add_entry (entry, 0); 45560484Sobrien 45633965Sjdp return; 45733965Sjdp } 45833965Sjdp } 45989857Sobrien 46060484Sobrien einfo (_("%P%F: invalid subsystem type %s\n"), optarg); 46133965Sjdp} 46233965Sjdp 46333965Sjdp 46433965Sjdp 46533965Sjdpstatic void 46633965Sjdpset_pe_value (name) 46733965Sjdp char *name; 46889857Sobrien 46933965Sjdp{ 47033965Sjdp char *end; 47189857Sobrien 47233965Sjdp set_pe_name (name, strtoul (optarg, &end, 0)); 47389857Sobrien 47433965Sjdp if (end == optarg) 47560484Sobrien einfo (_("%P%F: invalid hex number for PE parameter '%s'\n"), optarg); 47633965Sjdp 47733965Sjdp optarg = end; 47833965Sjdp} 47933965Sjdp 48033965Sjdpstatic void 48133965Sjdpset_pe_stack_heap (resname, comname) 48233965Sjdp char *resname; 48333965Sjdp char *comname; 48433965Sjdp{ 48533965Sjdp set_pe_value (resname); 48689857Sobrien 48733965Sjdp if (*optarg == ',') 48833965Sjdp { 48933965Sjdp optarg++; 49033965Sjdp set_pe_value (comname); 49133965Sjdp } 49233965Sjdp else if (*optarg) 49360484Sobrien einfo (_("%P%F: strange hex info for PE parameter '%s'\n"), optarg); 49433965Sjdp} 49533965Sjdp 49633965Sjdp 49733965Sjdp 49833965Sjdpstatic int 49933965Sjdpgld_${EMULATION_NAME}_parse_args(argc, argv) 50033965Sjdp int argc; 50133965Sjdp char **argv; 50233965Sjdp{ 50333965Sjdp int longind; 50433965Sjdp int optc; 50533965Sjdp int prevoptind = optind; 50633965Sjdp int prevopterr = opterr; 50733965Sjdp int wanterror; 50833965Sjdp static int lastoptind = -1; 50933965Sjdp 51033965Sjdp if (lastoptind != optind) 51133965Sjdp opterr = 0; 51233965Sjdp wanterror = opterr; 51333965Sjdp 51433965Sjdp lastoptind = optind; 51533965Sjdp 51633965Sjdp optc = getopt_long_only (argc, argv, "-", longopts, &longind); 51733965Sjdp opterr = prevopterr; 51833965Sjdp 51933965Sjdp switch (optc) 52033965Sjdp { 52133965Sjdp default: 52233965Sjdp if (wanterror) 52333965Sjdp xexit (1); 52433965Sjdp optind = prevoptind; 52533965Sjdp return 0; 52633965Sjdp 52733965Sjdp case OPTION_BASE_FILE: 52833965Sjdp link_info.base_file = (PTR) fopen (optarg, FOPEN_WB); 52933965Sjdp if (link_info.base_file == NULL) 53033965Sjdp { 53160484Sobrien /* xgettext:c-format */ 53260484Sobrien fprintf (stderr, _("%s: Can't open base file %s\n"), 53333965Sjdp program_name, optarg); 53433965Sjdp xexit (1); 53533965Sjdp } 53633965Sjdp break; 53733965Sjdp 53833965Sjdp /* PE options */ 53989857Sobrien case OPTION_HEAP: 54033965Sjdp set_pe_stack_heap ("__size_of_heap_reserve__", "__size_of_heap_commit__"); 54133965Sjdp break; 54289857Sobrien case OPTION_STACK: 54333965Sjdp set_pe_stack_heap ("__size_of_stack_reserve__", "__size_of_stack_commit__"); 54433965Sjdp break; 54533965Sjdp case OPTION_SUBSYSTEM: 54633965Sjdp set_pe_subsystem (); 54733965Sjdp break; 54833965Sjdp case OPTION_MAJOR_OS_VERSION: 54933965Sjdp set_pe_value ("__major_os_version__"); 55033965Sjdp break; 55133965Sjdp case OPTION_MINOR_OS_VERSION: 55233965Sjdp set_pe_value ("__minor_os_version__"); 55333965Sjdp break; 55433965Sjdp case OPTION_MAJOR_SUBSYSTEM_VERSION: 55533965Sjdp set_pe_value ("__major_subsystem_version__"); 55633965Sjdp break; 55733965Sjdp case OPTION_MINOR_SUBSYSTEM_VERSION: 55833965Sjdp set_pe_value ("__minor_subsystem_version__"); 55933965Sjdp break; 56033965Sjdp case OPTION_MAJOR_IMAGE_VERSION: 56133965Sjdp set_pe_value ("__major_image_version__"); 56233965Sjdp break; 56333965Sjdp case OPTION_MINOR_IMAGE_VERSION: 56433965Sjdp set_pe_value ("__minor_image_version__"); 56533965Sjdp break; 56633965Sjdp case OPTION_FILE_ALIGNMENT: 56733965Sjdp set_pe_value ("__file_alignment__"); 56833965Sjdp break; 56933965Sjdp case OPTION_SECTION_ALIGNMENT: 57033965Sjdp set_pe_value ("__section_alignment__"); 57133965Sjdp break; 57233965Sjdp case OPTION_DLL: 57333965Sjdp set_pe_name ("__dll__", 1); 57433965Sjdp break; 57533965Sjdp case OPTION_IMAGE_BASE: 57633965Sjdp set_pe_value ("__image_base__"); 57733965Sjdp break; 57860484Sobrien case OPTION_SUPPORT_OLD_CODE: 57960484Sobrien support_old_code = 1; 58060484Sobrien break; 58160484Sobrien case OPTION_THUMB_ENTRY: 58260484Sobrien thumb_entry_symbol = optarg; 58360484Sobrien break; 58460484Sobrien#ifdef DLL_SUPPORT 58560484Sobrien case OPTION_OUT_DEF: 58660484Sobrien pe_out_def_filename = xstrdup (optarg); 58760484Sobrien break; 58860484Sobrien case OPTION_EXPORT_ALL: 58960484Sobrien pe_dll_export_everything = 1; 59060484Sobrien break; 59160484Sobrien case OPTION_EXCLUDE_SYMBOLS: 592104834Sobrien pe_dll_add_excludes (optarg, 0); 59360484Sobrien break; 594104834Sobrien case OPTION_EXCLUDE_LIBS: 595104834Sobrien pe_dll_add_excludes (optarg, 1); 596104834Sobrien break; 59760484Sobrien case OPTION_KILL_ATS: 59860484Sobrien pe_dll_kill_ats = 1; 59960484Sobrien break; 60060484Sobrien case OPTION_STDCALL_ALIASES: 60160484Sobrien pe_dll_stdcall_aliases = 1; 60260484Sobrien break; 60360484Sobrien case OPTION_ENABLE_STDCALL_FIXUP: 60460484Sobrien pe_enable_stdcall_fixup = 1; 60560484Sobrien break; 60660484Sobrien case OPTION_DISABLE_STDCALL_FIXUP: 60760484Sobrien pe_enable_stdcall_fixup = 0; 60860484Sobrien break; 60960484Sobrien case OPTION_IMPLIB_FILENAME: 61060484Sobrien pe_implib_filename = xstrdup (optarg); 61160484Sobrien break; 61260484Sobrien case OPTION_WARN_DUPLICATE_EXPORTS: 61360484Sobrien pe_dll_warn_dup_exports = 1; 61460484Sobrien break; 61560484Sobrien case OPTION_IMP_COMPAT: 61660484Sobrien pe_dll_compat_implib = 1; 61760484Sobrien break; 61877298Sobrien case OPTION_ENABLE_AUTO_IMAGE_BASE: 61977298Sobrien pe_enable_auto_image_base = 1; 62077298Sobrien break; 62177298Sobrien case OPTION_DISABLE_AUTO_IMAGE_BASE: 62277298Sobrien pe_enable_auto_image_base = 0; 62377298Sobrien break; 62477298Sobrien case OPTION_DLL_SEARCH_PREFIX: 62577298Sobrien pe_dll_search_prefix = xstrdup( optarg ); 62677298Sobrien break; 62777298Sobrien case OPTION_NO_DEFAULT_EXCLUDES: 62877298Sobrien pe_dll_do_default_excludes = 0; 62977298Sobrien break; 63089857Sobrien case OPTION_DLL_ENABLE_AUTO_IMPORT: 631104834Sobrien link_info.pei386_auto_import = 1; 63289857Sobrien break; 63389857Sobrien case OPTION_DLL_DISABLE_AUTO_IMPORT: 634104834Sobrien link_info.pei386_auto_import = 0; 63589857Sobrien break; 63689857Sobrien case OPTION_ENABLE_EXTRA_PE_DEBUG: 63789857Sobrien pe_dll_extra_pe_debug = 1; 63889857Sobrien break; 63960484Sobrien#endif 64033965Sjdp } 64133965Sjdp return 1; 64233965Sjdp} 64333965Sjdp 64477298Sobrien 64577298Sobrien#ifdef DLL_SUPPORT 64689857Sobrienstatic unsigned long 64777298Sobrienstrhash (const char *str) 64877298Sobrien{ 64977298Sobrien const unsigned char *s; 65077298Sobrien unsigned long hash; 65177298Sobrien unsigned int c; 65277298Sobrien unsigned int len; 65377298Sobrien 65477298Sobrien hash = 0; 65577298Sobrien len = 0; 65677298Sobrien s = (const unsigned char *) str; 65777298Sobrien while ((c = *s++) != '\0') 65877298Sobrien { 65977298Sobrien hash += c + (c << 17); 66077298Sobrien hash ^= hash >> 2; 66177298Sobrien ++len; 66277298Sobrien } 66377298Sobrien hash += len + (len << 17); 66477298Sobrien hash ^= hash >> 2; 66577298Sobrien 66677298Sobrien return hash; 66777298Sobrien} 66877298Sobrien 66977298Sobrien/* Use the output file to create a image base for relocatable DLLs. */ 67077298Sobrienstatic unsigned long 67177298Sobriencompute_dll_image_base (const char *ofile) 67277298Sobrien{ 67377298Sobrien unsigned long hash = strhash (ofile); 67477298Sobrien return 0x60000000 | ((hash << 16) & 0x0FFC0000); 67577298Sobrien} 67677298Sobrien#endif 67777298Sobrien 67838889Sjdp/* Assign values to the special symbols before the linker script is 67938889Sjdp read. */ 68038889Sjdp 68133965Sjdpstatic void 68260484Sobriengld_${EMULATION_NAME}_set_symbols () 68333965Sjdp{ 68433965Sjdp /* Run through and invent symbols for all the 68533965Sjdp names and insert the defaults. */ 68633965Sjdp int j; 68733965Sjdp lang_statement_list_type *save; 68833965Sjdp 68933965Sjdp if (!init[IMAGEBASEOFF].inited) 69038889Sjdp { 69138889Sjdp if (link_info.relocateable) 69238889Sjdp init[IMAGEBASEOFF].value = 0; 69360484Sobrien else if (init[DLLOFF].value || link_info.shared) 69477298Sobrien#ifdef DLL_SUPPORT 69577298Sobrien init[IMAGEBASEOFF].value = (pe_enable_auto_image_base) ? 69677298Sobrien compute_dll_image_base (output_filename) : NT_DLL_IMAGE_BASE; 69777298Sobrien#else 69838889Sjdp init[IMAGEBASEOFF].value = NT_DLL_IMAGE_BASE; 69977298Sobrien#endif 70038889Sjdp else 70138889Sjdp init[IMAGEBASEOFF].value = NT_EXE_IMAGE_BASE; 70238889Sjdp } 70333965Sjdp 70438889Sjdp /* Don't do any symbol assignments if this is a relocateable link. */ 70538889Sjdp if (link_info.relocateable) 70638889Sjdp return; 70738889Sjdp 70833965Sjdp /* Glue the assignments into the abs section */ 70933965Sjdp save = stat_ptr; 71033965Sjdp 71133965Sjdp stat_ptr = &(abs_output_section->children); 71233965Sjdp 71333965Sjdp for (j = 0; init[j].ptr; j++) 71433965Sjdp { 71533965Sjdp long val = init[j].value; 71660484Sobrien lang_assignment_statement_type *rv; 717104834Sobrien rv = lang_add_assignment (exp_assop ('=', init[j].symbol, 718104834Sobrien exp_intop (val))); 71933965Sjdp if (init[j].size == sizeof(short)) 72033965Sjdp *(short *)init[j].ptr = val; 72133965Sjdp else if (init[j].size == sizeof(int)) 72233965Sjdp *(int *)init[j].ptr = val; 72333965Sjdp else if (init[j].size == sizeof(long)) 72433965Sjdp *(long *)init[j].ptr = val; 72533965Sjdp /* This might be a long long or other special type. */ 72633965Sjdp else if (init[j].size == sizeof(bfd_vma)) 72733965Sjdp *(bfd_vma *)init[j].ptr = val; 72833965Sjdp else abort(); 72960484Sobrien if (j == IMAGEBASEOFF) 73060484Sobrien image_base_statement = rv; 73133965Sjdp } 73233965Sjdp /* Restore the pointer. */ 73333965Sjdp stat_ptr = save; 73489857Sobrien 73533965Sjdp if (pe.FileAlignment > 73633965Sjdp pe.SectionAlignment) 73733965Sjdp { 73860484Sobrien einfo (_("%P: warning, file alignment > section alignment.\n")); 73933965Sjdp } 74033965Sjdp} 74133965Sjdp 74260484Sobrien/* This is called after the linker script and the command line options 74360484Sobrien have been read. */ 74460484Sobrien 74533965Sjdpstatic void 74660484Sobriengld_${EMULATION_NAME}_after_parse () 74733965Sjdp{ 74860484Sobrien /* The Windows libraries are designed for the linker to treat the 74960484Sobrien entry point as an undefined symbol. Otherwise, the .obj that 75060484Sobrien defines mainCRTStartup is brought in because it is the first 75160484Sobrien encountered in libc.lib and it has other symbols in it which will 75260484Sobrien be pulled in by the link process. To avoid this, we act as 75360484Sobrien though the user specified -u with the entry point symbol. 75433965Sjdp 75560484Sobrien This function is called after the linker script and command line 75660484Sobrien options have been read, so at this point we know the right entry 75760484Sobrien point. This function is called before the input files are 75860484Sobrien opened, so registering the symbol as undefined will make a 75960484Sobrien difference. */ 76033965Sjdp 761104834Sobrien if (! link_info.relocateable && entry_symbol.name != NULL) 762104834Sobrien ldlang_add_undef (entry_symbol.name); 76333965Sjdp} 76433965Sjdp 76589857Sobrien/* pe-dll.c directly accesses pe_data_import_dll, 76689857Sobrien so it must be defined outside of #ifdef DLL_SUPPORT. 76789857Sobrien Note - this variable is deliberately not initialised. 76889857Sobrien This allows it to be treated as a common varaible, and only 76989857Sobrien exist in one incarnation in a multiple target enabled linker. */ 77089857Sobrienchar * pe_data_import_dll; 77189857Sobrien 77277298Sobrien#ifdef DLL_SUPPORT 77360484Sobrienstatic struct bfd_link_hash_entry *pe_undef_found_sym; 77460484Sobrien 77560484Sobrienstatic boolean 77660484Sobrienpe_undef_cdecl_match (h, string) 77760484Sobrien struct bfd_link_hash_entry *h; 77860484Sobrien PTR string; 77933965Sjdp{ 78089857Sobrien int sl; 78189857Sobrien sl = strlen (string); /* silence compiler warning */ 78260484Sobrien if (h->type == bfd_link_hash_defined 78360484Sobrien && strncmp (h->root.string, string, sl) == 0 78460484Sobrien && h->root.string[sl] == '@') 78589857Sobrien { 78689857Sobrien pe_undef_found_sym = h; 78789857Sobrien return false; 78889857Sobrien } 78960484Sobrien return true; 79033965Sjdp} 79133965Sjdp 79260484Sobrienstatic void 79360484Sobrienpe_fixup_stdcalls () 79433965Sjdp{ 79560484Sobrien static int gave_warning_message = 0; 79660484Sobrien struct bfd_link_hash_entry *undef, *sym; 79760484Sobrien char *at; 79889857Sobrien if (pe_dll_extra_pe_debug) 79989857Sobrien { 80089857Sobrien printf ("%s\n", __FUNCTION__); 80189857Sobrien } 80289857Sobrien 80360484Sobrien for (undef = link_info.hash->undefs; undef; undef=undef->next) 80460484Sobrien if (undef->type == bfd_link_hash_undefined) 80560484Sobrien { 80660484Sobrien at = strchr (undef->root.string, '@'); 80760484Sobrien if (at) 80860484Sobrien { 80960484Sobrien /* The symbol is a stdcall symbol, so let's look for a cdecl 81060484Sobrien symbol with the same name and resolve to that */ 81160484Sobrien char *cname = xstrdup (undef->root.string); 81260484Sobrien at = strchr (cname, '@'); 81360484Sobrien *at = 0; 81460484Sobrien sym = bfd_link_hash_lookup (link_info.hash, cname, 0, 0, 1); 81560484Sobrien if (sym && sym->type == bfd_link_hash_defined) 81660484Sobrien { 81760484Sobrien undef->type = bfd_link_hash_defined; 81860484Sobrien undef->u.def.value = sym->u.def.value; 81960484Sobrien undef->u.def.section = sym->u.def.section; 82060484Sobrien if (pe_enable_stdcall_fixup == -1) 82160484Sobrien { 82260484Sobrien einfo (_("Warning: resolving %s by linking to %s\n"), 82360484Sobrien undef->root.string, cname); 82460484Sobrien if (! gave_warning_message) 82560484Sobrien { 82660484Sobrien gave_warning_message = 1; 82760484Sobrien einfo(_("Use --enable-stdcall-fixup to disable these warnings\n")); 82860484Sobrien einfo(_("Use --disable-stdcall-fixup to disable these fixups\n")); 82960484Sobrien } 83060484Sobrien } 83160484Sobrien } 83260484Sobrien } 83360484Sobrien else 83460484Sobrien { 83560484Sobrien /* The symbol is a cdecl symbol, so we look for stdcall 83660484Sobrien symbols - which means scanning the whole symbol table */ 83760484Sobrien pe_undef_found_sym = 0; 83860484Sobrien bfd_link_hash_traverse (link_info.hash, pe_undef_cdecl_match, 83960484Sobrien (PTR) undef->root.string); 84060484Sobrien sym = pe_undef_found_sym; 84160484Sobrien if (sym) 84260484Sobrien { 84360484Sobrien undef->type = bfd_link_hash_defined; 84460484Sobrien undef->u.def.value = sym->u.def.value; 84560484Sobrien undef->u.def.section = sym->u.def.section; 84660484Sobrien if (pe_enable_stdcall_fixup == -1) 84760484Sobrien { 84860484Sobrien einfo (_("Warning: resolving %s by linking to %s\n"), 84960484Sobrien undef->root.string, sym->root.string); 85060484Sobrien if (! gave_warning_message) 85160484Sobrien { 85260484Sobrien gave_warning_message = 1; 85360484Sobrien einfo(_("Use --enable-stdcall-fixup to disable these warnings\n")); 85460484Sobrien einfo(_("Use --disable-stdcall-fixup to disable these fixups\n")); 85560484Sobrien } 85660484Sobrien } 85760484Sobrien } 85860484Sobrien } 85960484Sobrien } 86033965Sjdp} 86189857Sobrien 86289857Sobrienstatic int 86389857Sobrienmake_import_fixup (rel, s) 86489857Sobrien arelent *rel; 86589857Sobrien asection *s; 86689857Sobrien{ 86789857Sobrien struct symbol_cache_entry *sym = *rel->sym_ptr_ptr; 86889857Sobrien 86989857Sobrien if (pe_dll_extra_pe_debug) 87089857Sobrien { 87189857Sobrien printf ("arelent: %s@%#lx: add=%li\n", sym->name, 87289857Sobrien (long) rel->address, (long) rel->addend); 87389857Sobrien } 87489857Sobrien 87589857Sobrien { 87689857Sobrien int addend = 0; 87789857Sobrien if (!bfd_get_section_contents(s->owner, s, &addend, rel->address, sizeof(addend))) 87889857Sobrien { 87989857Sobrien einfo (_("%C: Cannot get section contents - auto-import exception\n"), 88089857Sobrien s->owner, s, rel->address); 88189857Sobrien } 88289857Sobrien 88389857Sobrien if (addend == 0) 88489857Sobrien pe_create_import_fixup (rel); 88589857Sobrien else 88689857Sobrien { 88789857Sobrien einfo (_("%C: variable '%T' can't be auto-imported. Please read the documentation for ld's --enable-auto-import for details.\n"), 88889857Sobrien s->owner, s, rel->address, sym->name); 88989857Sobrien einfo ("%X"); 89089857Sobrien } 89189857Sobrien } 89289857Sobrien 89389857Sobrien return 1; 89489857Sobrien} 89589857Sobrien 89689857Sobrienstatic void 89789857Sobrienpe_find_data_imports () 89889857Sobrien{ 89989857Sobrien struct bfd_link_hash_entry *undef, *sym; 90089857Sobrien for (undef = link_info.hash->undefs; undef; undef=undef->next) 90189857Sobrien { 90289857Sobrien if (undef->type == bfd_link_hash_undefined) 90389857Sobrien { 90489857Sobrien /* C++ symbols are *long* */ 90589857Sobrien char buf[4096]; 90689857Sobrien if (pe_dll_extra_pe_debug) 90789857Sobrien { 90889857Sobrien printf ("%s:%s\n", __FUNCTION__, undef->root.string); 90989857Sobrien } 91089857Sobrien sprintf (buf, "__imp_%s", undef->root.string); 91189857Sobrien 91289857Sobrien sym = bfd_link_hash_lookup (link_info.hash, buf, 0, 0, 1); 91389857Sobrien if (sym && sym->type == bfd_link_hash_defined) 91489857Sobrien { 915104834Sobrien if (link_info.pei386_auto_import == -1) 916104834Sobrien info_msg (_("Info: resolving %s by linking to %s (auto-import)\n"), 917104834Sobrien undef->root.string, buf); 91889857Sobrien { 91989857Sobrien bfd *b = sym->u.def.section->owner; 92089857Sobrien asymbol **symbols; 92189857Sobrien int nsyms, symsize, i; 92289857Sobrien 92389857Sobrien symsize = bfd_get_symtab_upper_bound (b); 92489857Sobrien symbols = (asymbol **) xmalloc (symsize); 92589857Sobrien nsyms = bfd_canonicalize_symtab (b, symbols); 92689857Sobrien 92789857Sobrien for (i = 0; i < nsyms; i++) 92889857Sobrien { 92989857Sobrien if (memcmp(symbols[i]->name, "__head_", 93089857Sobrien sizeof ("__head_") - 1)) 93189857Sobrien continue; 93289857Sobrien if (pe_dll_extra_pe_debug) 93389857Sobrien { 93489857Sobrien printf ("->%s\n", symbols[i]->name); 93589857Sobrien } 93689857Sobrien pe_data_import_dll = (char*) (symbols[i]->name + 93789857Sobrien sizeof ("__head_") - 1); 93889857Sobrien break; 93989857Sobrien } 94089857Sobrien } 94189857Sobrien 94289857Sobrien pe_walk_relocs_of_symbol (&link_info, undef->root.string, 94389857Sobrien make_import_fixup); 94489857Sobrien 94589857Sobrien /* let's differentiate it somehow from defined */ 94689857Sobrien undef->type = bfd_link_hash_defweak; 94789857Sobrien /* we replace original name with __imp_ prefixed, this 94889857Sobrien 1) may trash memory 2) leads to duplicate symbol generation. 94989857Sobrien Still, IMHO it's better than having name poluted. */ 95089857Sobrien undef->root.string = sym->root.string; 95189857Sobrien undef->u.def.value = sym->u.def.value; 95289857Sobrien undef->u.def.section = sym->u.def.section; 95389857Sobrien } 95489857Sobrien } 95589857Sobrien } 95689857Sobrien} 95760484Sobrien#endif /* DLL_SUPPORT */ 95833965Sjdp 95989857Sobrienstatic boolean 96089857Sobrienpr_sym (h, string) 96189857Sobrien struct bfd_hash_entry *h; 96289857Sobrien PTR string ATTRIBUTE_UNUSED; 96389857Sobrien{ 96489857Sobrien if (pe_dll_extra_pe_debug) 96589857Sobrien { 96689857Sobrien printf("+%s\n",h->string); 96789857Sobrien } 96889857Sobrien return true; 96989857Sobrien} 97089857Sobrien 97189857Sobrien 97260484Sobrienstatic void 97360484Sobriengld_${EMULATION_NAME}_after_open () 97433965Sjdp{ 97589857Sobrien 97689857Sobrien if (pe_dll_extra_pe_debug) 97789857Sobrien { 97889857Sobrien bfd *a; 97989857Sobrien struct bfd_link_hash_entry *sym; 98089857Sobrien printf ("%s()\n", __FUNCTION__); 98189857Sobrien 98289857Sobrien for (sym = link_info.hash->undefs; sym; sym=sym->next) 98389857Sobrien printf ("-%s\n", sym->root.string); 98489857Sobrien bfd_hash_traverse (&link_info.hash->table, pr_sym,NULL); 98589857Sobrien 98689857Sobrien for (a = link_info.input_bfds; a; a = a->link_next) 98789857Sobrien { 98889857Sobrien printf("*%s\n",a->filename); 98989857Sobrien } 99089857Sobrien } 99189857Sobrien 99260484Sobrien /* Pass the wacky PE command line options into the output bfd. 99360484Sobrien FIXME: This should be done via a function, rather than by 99460484Sobrien including an internal BFD header. */ 99589857Sobrien 99689857Sobrien if (coff_data (output_bfd) == NULL || coff_data (output_bfd)->pe == 0) 99760484Sobrien einfo (_("%F%P: PE operations on non PE file.\n")); 99833965Sjdp 99960484Sobrien pe_data (output_bfd)->pe_opthdr = pe; 100060484Sobrien pe_data (output_bfd)->dll = init[DLLOFF].value; 100133965Sjdp 100260484Sobrien#ifdef DLL_SUPPORT 100360484Sobrien if (pe_enable_stdcall_fixup) /* -1=warn or 1=disable */ 100460484Sobrien pe_fixup_stdcalls (); 100533965Sjdp 100689857Sobrien pe_find_data_imports (); 100789857Sobrien 100860484Sobrien pe_process_import_defs(output_bfd, &link_info); 100960484Sobrien if (link_info.shared) 101060484Sobrien pe_dll_build_sections (output_bfd, &link_info); 101133965Sjdp 101260484Sobrien#ifndef TARGET_IS_i386pe 101360484Sobrien#ifndef TARGET_IS_armpe 101460484Sobrien else 101560484Sobrien pe_exe_build_sections (output_bfd, &link_info); 101660484Sobrien#endif 101760484Sobrien#endif 101860484Sobrien#endif 101933965Sjdp 102060484Sobrien#if defined(TARGET_IS_armpe) || defined(TARGET_IS_arm_epoc_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 { 103460484Sobrien if (bfd_arm_pe_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 104977298Sobrien 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; 106377298Sobrien if (strncmp (sec->name, ".idata\$", 7) == 0) 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, 109877298Sobrien 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 { 110877298Sobrien struct symbol_cache_entry *s; 110977298Sobrien struct bfd_link_hash_entry * blhe; 111077298Sobrien bfd *other_bfd; 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, 112177298Sobrien false, false, true); 112289857Sobrien 112377298Sobrien if (blhe == NULL 112477298Sobrien || blhe->type != bfd_link_hash_defined) 112577298Sobrien continue; 112689857Sobrien 112777298Sobrien other_bfd = blhe->u.def.section->owner; 112889857Sobrien 112977298Sobrien if (strcmp (is->the_bfd->my_archive->filename, 113077298Sobrien other_bfd->my_archive->filename) == 0) 113177298Sobrien continue; 113289857Sobrien 113377298Sobrien /* Rename this implib to match the other. */ 113477298Sobrien n = (char *) xmalloc (strlen (other_bfd->my_archive->filename) + 1); 113589857Sobrien 113677298Sobrien strcpy (n, other_bfd->my_archive->filename); 113789857Sobrien 113877298Sobrien is->the_bfd->my_archive->filename = n; 113977298Sobrien } 114077298Sobrien 114177298Sobrien free (relocs); 114277298Sobrien /* Note - we do not free the symbols, 114377298Sobrien they are now cached in the BFD. */ 114477298Sobrien } 114577298Sobrien } 114677298Sobrien } 114777298Sobrien } 114877298Sobrien } 114977298Sobrien 115077298Sobrien { 115160484Sobrien int is_ms_arch = 0; 115260484Sobrien bfd *cur_arch = 0; 115360484Sobrien lang_input_statement_type *is2; 115433965Sjdp 115560484Sobrien /* Careful - this is a shell script. Watch those dollar signs! */ 115660484Sobrien /* Microsoft import libraries have every member named the same, 115760484Sobrien and not in the right order for us to link them correctly. We 115860484Sobrien must detect these and rename the members so that they'll link 115960484Sobrien correctly. There are three types of objects: the head, the 116060484Sobrien thunks, and the sentinel(s). The head is easy; it's the one 116160484Sobrien with idata2. We assume that the sentinels won't have relocs, 116260484Sobrien and the thunks will. It's easier than checking the symbol 116360484Sobrien table for external references. */ 116460484Sobrien LANG_FOR_EACH_INPUT_STATEMENT (is) 116533965Sjdp { 116660484Sobrien if (is->the_bfd->my_archive) 116760484Sobrien { 116860484Sobrien bfd *arch = is->the_bfd->my_archive; 116960484Sobrien if (cur_arch != arch) 117060484Sobrien { 117160484Sobrien cur_arch = arch; 117260484Sobrien is_ms_arch = 1; 117360484Sobrien for (is2 = is; 117460484Sobrien is2 && is2->the_bfd->my_archive == arch; 117560484Sobrien is2 = (lang_input_statement_type *)is2->next) 117660484Sobrien { 117760484Sobrien if (strcmp (is->the_bfd->filename, is2->the_bfd->filename)) 117860484Sobrien is_ms_arch = 0; 117960484Sobrien } 118060484Sobrien } 118133965Sjdp 118260484Sobrien if (is_ms_arch) 118360484Sobrien { 118460484Sobrien int idata2 = 0, reloc_count=0; 118560484Sobrien asection *sec; 118660484Sobrien char *new_name, seq; 118733965Sjdp 118860484Sobrien for (sec = is->the_bfd->sections; sec; sec = sec->next) 118960484Sobrien { 119060484Sobrien if (strcmp (sec->name, ".idata\$2") == 0) 119160484Sobrien idata2 = 1; 119260484Sobrien reloc_count += sec->reloc_count; 119360484Sobrien } 119433965Sjdp 119560484Sobrien if (idata2) /* .idata2 is the TOC */ 119660484Sobrien seq = 'a'; 119760484Sobrien else if (reloc_count > 0) /* thunks */ 119860484Sobrien seq = 'b'; 119960484Sobrien else /* sentinel */ 120060484Sobrien seq = 'c'; 120133965Sjdp 120260484Sobrien new_name = xmalloc (strlen (is->the_bfd->filename) + 3); 120360484Sobrien sprintf (new_name, "%s.%c", is->the_bfd->filename, seq); 120460484Sobrien is->the_bfd->filename = new_name; 120533965Sjdp 120677298Sobrien new_name = xmalloc (strlen (is->filename) + 3); 120760484Sobrien sprintf (new_name, "%s.%c", is->filename, seq); 120860484Sobrien is->filename = new_name; 120960484Sobrien } 121060484Sobrien } 121133965Sjdp } 121260484Sobrien } 121333965Sjdp} 121460484Sobrien 121589857Sobrienstatic void 121633965Sjdpgld_${EMULATION_NAME}_before_allocation() 121733965Sjdp{ 121833965Sjdp#ifdef TARGET_IS_ppcpe 121933965Sjdp /* Here we rummage through the found bfds to collect toc information */ 122033965Sjdp { 122133965Sjdp LANG_FOR_EACH_INPUT_STATEMENT (is) 122233965Sjdp { 122360484Sobrien if (!ppc_process_before_allocation (is->the_bfd, &link_info)) 122433965Sjdp { 122560484Sobrien /* xgettext:c-format */ 122660484Sobrien einfo (_("Errors encountered processing file %s\n"), is->filename); 122733965Sjdp } 122833965Sjdp } 122933965Sjdp } 123033965Sjdp 123133965Sjdp /* We have seen it all. Allocate it, and carry on */ 123233965Sjdp ppc_allocate_toc_section (&link_info); 123360484Sobrien#endif /* TARGET_IS_ppcpe */ 123460484Sobrien 123560484Sobrien#if defined(TARGET_IS_armpe) || defined(TARGET_IS_arm_epoc_pe) 123638889Sjdp /* FIXME: we should be able to set the size of the interworking stub 123738889Sjdp section. 123833965Sjdp 123938889Sjdp Here we rummage through the found bfds to collect glue 124038889Sjdp information. FIXME: should this be based on a command line 124138889Sjdp option? krk@cygnus.com */ 124238889Sjdp { 124338889Sjdp LANG_FOR_EACH_INPUT_STATEMENT (is) 124438889Sjdp { 124560484Sobrien if (! bfd_arm_pe_process_before_allocation 124660484Sobrien (is->the_bfd, & link_info, support_old_code)) 124738889Sjdp { 124860484Sobrien /* xgettext:c-format */ 124960484Sobrien einfo (_("Errors encountered processing file %s for interworking"), 125060484Sobrien is->filename); 125138889Sjdp } 125238889Sjdp } 125338889Sjdp } 125438889Sjdp 125538889Sjdp /* We have seen it all. Allocate it, and carry on */ 125660484Sobrien bfd_arm_pe_allocate_interworking_sections (& link_info); 125738889Sjdp#endif /* TARGET_IS_armpe */ 125860484Sobrien} 125960484Sobrien 126077298Sobrien#ifdef DLL_SUPPORT 126160484Sobrien/* This is called when an input file isn't recognized as a BFD. We 126260484Sobrien check here for .DEF files and pull them in automatically. */ 126377298Sobrien 126460484Sobrienstatic int 126560484Sobriensaw_option(char *option) 126660484Sobrien{ 126760484Sobrien int i; 126860484Sobrien for (i=0; init[i].ptr; i++) 126960484Sobrien if (strcmp (init[i].symbol, option) == 0) 127060484Sobrien return init[i].inited; 127160484Sobrien return 0; 127233965Sjdp} 127377298Sobrien#endif /* DLL_SUPPORT */ 127460484Sobrien 127560484Sobrienstatic boolean 127660484Sobriengld_${EMULATION_NAME}_unrecognized_file(entry) 127760484Sobrien lang_input_statement_type *entry ATTRIBUTE_UNUSED; 127860484Sobrien{ 127960484Sobrien#ifdef DLL_SUPPORT 128060484Sobrien const char *ext = entry->filename + strlen (entry->filename) - 4; 128160484Sobrien 128260484Sobrien if (strcmp (ext, ".def") == 0 || strcmp (ext, ".DEF") == 0) 128360484Sobrien { 128460484Sobrien if (pe_def_file == 0) 128560484Sobrien pe_def_file = def_file_empty (); 128660484Sobrien def_file_parse (entry->filename, pe_def_file); 128760484Sobrien if (pe_def_file) 128860484Sobrien { 128960484Sobrien int i, buflen=0, len; 129060484Sobrien char *buf; 129160484Sobrien for (i=0; i<pe_def_file->num_exports; i++) 129260484Sobrien { 129360484Sobrien len = strlen(pe_def_file->exports[i].internal_name); 129460484Sobrien if (buflen < len+2) 129560484Sobrien buflen = len+2; 129660484Sobrien } 129760484Sobrien buf = (char *) xmalloc (buflen); 129860484Sobrien for (i=0; i<pe_def_file->num_exports; i++) 129960484Sobrien { 130060484Sobrien struct bfd_link_hash_entry *h; 130160484Sobrien sprintf(buf, "_%s", pe_def_file->exports[i].internal_name); 130260484Sobrien 130360484Sobrien h = bfd_link_hash_lookup (link_info.hash, buf, true, true, true); 130460484Sobrien if (h == (struct bfd_link_hash_entry *) NULL) 130560484Sobrien einfo (_("%P%F: bfd_link_hash_lookup failed: %E\n")); 130660484Sobrien if (h->type == bfd_link_hash_new) 130760484Sobrien { 130860484Sobrien h->type = bfd_link_hash_undefined; 130960484Sobrien h->u.undef.abfd = NULL; 131060484Sobrien bfd_link_add_undef (link_info.hash, h); 131160484Sobrien } 131260484Sobrien } 131360484Sobrien free (buf); 131460484Sobrien 131560484Sobrien /* def_file_print (stdout, pe_def_file); */ 131660484Sobrien if (pe_def_file->is_dll == 1) 131760484Sobrien link_info.shared = 1; 131860484Sobrien 131960484Sobrien if (pe_def_file->base_address != (bfd_vma)(-1)) 132060484Sobrien { 132160484Sobrien pe.ImageBase = 132260484Sobrien pe_data (output_bfd)->pe_opthdr.ImageBase = 132360484Sobrien init[IMAGEBASEOFF].value = pe_def_file->base_address; 132460484Sobrien init[IMAGEBASEOFF].inited = 1; 132560484Sobrien if (image_base_statement) 132660484Sobrien image_base_statement->exp = 132760484Sobrien exp_assop ('=', "__image_base__", exp_intop (pe.ImageBase)); 132860484Sobrien } 132960484Sobrien 133060484Sobrien#if 0 133160484Sobrien /* Not sure if these *should* be set */ 133260484Sobrien if (pe_def_file->version_major != -1) 133360484Sobrien { 133460484Sobrien pe.MajorImageVersion = pe_def_file->version_major; 133560484Sobrien pe.MinorImageVersion = pe_def_file->version_minor; 133660484Sobrien } 133760484Sobrien#endif 133860484Sobrien if (pe_def_file->stack_reserve != -1 133960484Sobrien && ! saw_option ("__size_of_stack_reserve__")) 134060484Sobrien { 134160484Sobrien pe.SizeOfStackReserve = pe_def_file->stack_reserve; 134260484Sobrien if (pe_def_file->stack_commit != -1) 134360484Sobrien pe.SizeOfStackCommit = pe_def_file->stack_commit; 134460484Sobrien } 134560484Sobrien if (pe_def_file->heap_reserve != -1 134660484Sobrien && ! saw_option ("__size_of_heap_reserve__")) 134760484Sobrien { 134860484Sobrien pe.SizeOfHeapReserve = pe_def_file->heap_reserve; 134960484Sobrien if (pe_def_file->heap_commit != -1) 135060484Sobrien pe.SizeOfHeapCommit = pe_def_file->heap_commit; 135160484Sobrien } 135260484Sobrien return true; 135360484Sobrien } 135460484Sobrien } 135560484Sobrien#endif 135660484Sobrien return false; 135789857Sobrien 135860484Sobrien} 135960484Sobrien 136060484Sobrienstatic boolean 136160484Sobriengld_${EMULATION_NAME}_recognized_file(entry) 136260484Sobrien lang_input_statement_type *entry ATTRIBUTE_UNUSED; 136360484Sobrien{ 136460484Sobrien#ifdef DLL_SUPPORT 136560484Sobrien#ifdef TARGET_IS_i386pe 136660484Sobrien pe_dll_id_target ("pei-i386"); 136760484Sobrien#endif 136860484Sobrien#ifdef TARGET_IS_shpe 136960484Sobrien pe_dll_id_target ("pei-shl"); 137060484Sobrien#endif 137160484Sobrien#ifdef TARGET_IS_mipspe 137260484Sobrien pe_dll_id_target ("pei-mips"); 137360484Sobrien#endif 137460484Sobrien#ifdef TARGET_IS_armpe 137560484Sobrien pe_dll_id_target ("pei-arm-little"); 137660484Sobrien#endif 137760484Sobrien if (bfd_get_format (entry->the_bfd) == bfd_object) 137860484Sobrien { 137960484Sobrien const char *ext = entry->filename + strlen (entry->filename) - 4; 138060484Sobrien if (strcmp (ext, ".dll") == 0 || strcmp (ext, ".DLL") == 0) 138160484Sobrien return pe_implied_import_dll (entry->filename); 138260484Sobrien } 138360484Sobrien#endif 138460484Sobrien return false; 138560484Sobrien} 138660484Sobrien 138760484Sobrienstatic void 138860484Sobriengld_${EMULATION_NAME}_finish () 138960484Sobrien{ 139060484Sobrien#if defined(TARGET_IS_armpe) || defined(TARGET_IS_arm_epoc_pe) 139160484Sobrien struct bfd_link_hash_entry * h; 139260484Sobrien 139360484Sobrien if (thumb_entry_symbol != NULL) 139460484Sobrien { 139560484Sobrien h = bfd_link_hash_lookup (link_info.hash, thumb_entry_symbol, false, false, true); 139689857Sobrien 139760484Sobrien if (h != (struct bfd_link_hash_entry *) NULL 139860484Sobrien && (h->type == bfd_link_hash_defined 139960484Sobrien || h->type == bfd_link_hash_defweak) 140060484Sobrien && h->u.def.section->output_section != NULL) 140160484Sobrien { 140260484Sobrien static char buffer[32]; 140360484Sobrien bfd_vma val; 140489857Sobrien 140560484Sobrien /* Special procesing is required for a Thumb entry symbol. The 140660484Sobrien bottom bit of its address must be set. */ 140760484Sobrien val = (h->u.def.value 140860484Sobrien + bfd_get_section_vma (output_bfd, 140960484Sobrien h->u.def.section->output_section) 141060484Sobrien + h->u.def.section->output_offset); 141189857Sobrien 141260484Sobrien val |= 1; 141389857Sobrien 141460484Sobrien /* Now convert this value into a string and store it in entry_symbol 141560484Sobrien where the lang_finish() function will pick it up. */ 141660484Sobrien buffer[0] = '0'; 141760484Sobrien buffer[1] = 'x'; 141889857Sobrien 141960484Sobrien sprintf_vma (buffer + 2, val); 142089857Sobrien 1421104834Sobrien if (entry_symbol.name != NULL && entry_from_cmdline) 142260484Sobrien einfo (_("%P: warning: '--thumb-entry %s' is overriding '-e %s'\n"), 1423104834Sobrien thumb_entry_symbol, entry_symbol.name); 1424104834Sobrien entry_symbol.name = buffer; 142560484Sobrien } 142660484Sobrien else 142760484Sobrien einfo (_("%P: warning: connot find thumb start symbol %s\n"), thumb_entry_symbol); 142860484Sobrien } 142960484Sobrien#endif /* defined(TARGET_IS_armpe) || defined(TARGET_IS_arm_epoc_pe) */ 143060484Sobrien 143160484Sobrien#ifdef DLL_SUPPORT 143260484Sobrien if (link_info.shared) 143360484Sobrien { 143460484Sobrien pe_dll_fill_sections (output_bfd, &link_info); 143560484Sobrien if (pe_implib_filename) 143660484Sobrien pe_dll_generate_implib (pe_def_file, pe_implib_filename); 143760484Sobrien } 143860484Sobrien#if defined(TARGET_IS_shpe) || defined(TARGET_IS_mipspe) 143977298Sobrien /* ARM doesn't need relocs. */ 144060484Sobrien else 144160484Sobrien { 144260484Sobrien pe_exe_fill_sections (output_bfd, &link_info); 144360484Sobrien } 144460484Sobrien#endif 144589857Sobrien 144660484Sobrien if (pe_out_def_filename) 144760484Sobrien pe_dll_generate_def_file (pe_out_def_filename); 144877298Sobrien#endif /* DLL_SUPPORT */ 144989857Sobrien 145089857Sobrien /* I don't know where .idata gets set as code, but it shouldn't be */ 145189857Sobrien { 145289857Sobrien asection *asec = bfd_get_section_by_name (output_bfd, ".idata"); 145389857Sobrien if (asec) 145489857Sobrien { 145589857Sobrien asec->flags &= ~SEC_CODE; 145689857Sobrien asec->flags |= SEC_DATA; 145789857Sobrien } 145889857Sobrien } 145960484Sobrien} 146060484Sobrien 146133965Sjdp 146289857Sobrien/* Find the last output section before given output statement. 146389857Sobrien Used by place_orphan. */ 146489857Sobrien 146589857Sobrienstatic asection * 146689857Sobrienoutput_prev_sec_find (os) 146789857Sobrien lang_output_section_statement_type *os; 146889857Sobrien{ 146989857Sobrien asection *s = (asection *) NULL; 147089857Sobrien lang_statement_union_type *u; 147189857Sobrien lang_output_section_statement_type *lookup; 147289857Sobrien 147389857Sobrien for (u = lang_output_section_statement.head; 147489857Sobrien u != (lang_statement_union_type *) NULL; 147589857Sobrien u = lookup->next) 147689857Sobrien { 147789857Sobrien lookup = &u->output_section_statement; 147889857Sobrien if (lookup == os) 147989857Sobrien return s; 148089857Sobrien 148189857Sobrien if (lookup->bfd_section != NULL && lookup->bfd_section->owner != NULL) 148289857Sobrien s = lookup->bfd_section; 148389857Sobrien } 148489857Sobrien 148589857Sobrien return NULL; 148689857Sobrien} 148789857Sobrien 148860484Sobrien/* Place an orphan section. 148933965Sjdp 149060484Sobrien We use this to put sections in a reasonable place in the file, and 149160484Sobrien to ensure that they are aligned as required. 149238889Sjdp 149360484Sobrien We handle grouped sections here as well. A section named .foo$nn 149460484Sobrien goes into the output section .foo. All grouped sections are sorted 149560484Sobrien by name. 149660484Sobrien 149760484Sobrien Grouped sections for the default sections are handled by the 149860484Sobrien default linker script using wildcards, and are sorted by 149960484Sobrien sort_sections. */ 150060484Sobrien 150177298Sobrienstruct orphan_save 150277298Sobrien{ 150377298Sobrien lang_output_section_statement_type *os; 150477298Sobrien asection **section; 150577298Sobrien lang_statement_union_type **stmt; 150677298Sobrien}; 150760484Sobrien 150833965Sjdp/*ARGSUSED*/ 150933965Sjdpstatic boolean 151060484Sobriengld_${EMULATION_NAME}_place_orphan (file, s) 151133965Sjdp lang_input_statement_type *file; 151233965Sjdp asection *s; 151333965Sjdp{ 151433965Sjdp const char *secname; 151577298Sobrien char *hold_section_name; 151660484Sobrien char *dollar = NULL; 151777298Sobrien const char *ps = NULL; 151877298Sobrien lang_output_section_statement_type *os; 151977298Sobrien lang_statement_list_type add_child; 152033965Sjdp 152133965Sjdp secname = bfd_get_section_name (s->owner, s); 152233965Sjdp 152360484Sobrien /* Look through the script to see where to place this section. */ 152433965Sjdp 152560484Sobrien hold_section_name = xstrdup (secname); 152660484Sobrien if (!link_info.relocateable) 152760484Sobrien { 152860484Sobrien dollar = strchr (hold_section_name, '$'); 152960484Sobrien if (dollar != NULL) 153060484Sobrien *dollar = '\0'; 153160484Sobrien } 153233965Sjdp 153377298Sobrien os = lang_output_section_find (hold_section_name); 153460484Sobrien 153577298Sobrien lang_list_init (&add_child); 153677298Sobrien 153777298Sobrien if (os != NULL 153889857Sobrien && (os->bfd_section == NULL 153989857Sobrien || ((s->flags ^ os->bfd_section->flags) 154089857Sobrien & (SEC_LOAD | SEC_ALLOC)) == 0)) 154133965Sjdp { 154289857Sobrien /* We already have an output section statement with this 154389857Sobrien name, and its bfd section, if any, has compatible flags. */ 154489857Sobrien lang_add_section (&add_child, s, os, file); 154577298Sobrien } 154677298Sobrien else 154777298Sobrien { 154877298Sobrien struct orphan_save *place; 154977298Sobrien static struct orphan_save hold_text; 155077298Sobrien static struct orphan_save hold_rdata; 155177298Sobrien static struct orphan_save hold_data; 155277298Sobrien static struct orphan_save hold_bss; 155360484Sobrien char *outsecname; 155460484Sobrien lang_statement_list_type *old; 155560484Sobrien lang_statement_list_type add; 155660484Sobrien etree_type *address; 155760484Sobrien 155860484Sobrien /* Try to put the new output section in a reasonable place based 155960484Sobrien on the section name and section flags. */ 156077298Sobrien#define HAVE_SECTION(hold, name) \ 156177298Sobrien(hold.os != NULL || (hold.os = lang_output_section_find (name)) != NULL) 156277298Sobrien 156360484Sobrien place = NULL; 156477298Sobrien if ((s->flags & SEC_ALLOC) == 0) 156577298Sobrien ; 156677298Sobrien else if ((s->flags & SEC_HAS_CONTENTS) == 0 156777298Sobrien && HAVE_SECTION (hold_bss, ".bss")) 156877298Sobrien place = &hold_bss; 156960484Sobrien else if ((s->flags & SEC_READONLY) == 0 157077298Sobrien && HAVE_SECTION (hold_data, ".data")) 157177298Sobrien place = &hold_data; 157260484Sobrien else if ((s->flags & SEC_CODE) == 0 157360484Sobrien && (s->flags & SEC_READONLY) != 0 157477298Sobrien && HAVE_SECTION (hold_rdata, ".rdata")) 157577298Sobrien place = &hold_rdata; 157660484Sobrien else if ((s->flags & SEC_READONLY) != 0 157777298Sobrien && HAVE_SECTION (hold_text, ".text")) 157877298Sobrien place = &hold_text; 157960484Sobrien 158077298Sobrien#undef HAVE_SECTION 158177298Sobrien 158260484Sobrien /* Choose a unique name for the section. This will be needed if 158360484Sobrien the same section name appears in the input file with 158489857Sobrien different loadable or allocatable characteristics. */ 158560484Sobrien outsecname = xstrdup (hold_section_name); 158660484Sobrien if (bfd_get_section_by_name (output_bfd, outsecname) != NULL) 158760484Sobrien { 158860484Sobrien unsigned int len; 158960484Sobrien char *newname; 159060484Sobrien unsigned int i; 159160484Sobrien 159260484Sobrien len = strlen (outsecname); 159360484Sobrien newname = xmalloc (len + 5); 159460484Sobrien strcpy (newname, outsecname); 159560484Sobrien i = 0; 159660484Sobrien do 159760484Sobrien { 159860484Sobrien sprintf (newname + len, "%d", i); 159960484Sobrien ++i; 160060484Sobrien } 160160484Sobrien while (bfd_get_section_by_name (output_bfd, newname) != NULL); 160260484Sobrien 160360484Sobrien free (outsecname); 160460484Sobrien outsecname = newname; 160560484Sobrien } 160660484Sobrien 160760484Sobrien /* Start building a list of statements for this section. */ 160860484Sobrien old = stat_ptr; 160960484Sobrien stat_ptr = &add; 161060484Sobrien lang_list_init (stat_ptr); 161160484Sobrien 161277298Sobrien if (config.build_constructors) 161377298Sobrien { 161477298Sobrien /* If the name of the section is representable in C, then create 161577298Sobrien symbols to mark the start and the end of the section. */ 161677298Sobrien for (ps = outsecname; *ps != '\0'; ps++) 161777298Sobrien if (! isalnum ((unsigned char) *ps) && *ps != '_') 161877298Sobrien break; 161977298Sobrien if (*ps == '\0') 162077298Sobrien { 162177298Sobrien char *symname; 162277298Sobrien etree_type *e_align; 162389857Sobrien 162477298Sobrien symname = (char *) xmalloc (ps - outsecname + sizeof "___start_"); 162577298Sobrien sprintf (symname, "___start_%s", outsecname); 162677298Sobrien e_align = exp_unop (ALIGN_K, 162777298Sobrien exp_intop ((bfd_vma) 1 << s->alignment_power)); 162877298Sobrien lang_add_assignment (exp_assop ('=', symname, e_align)); 162977298Sobrien } 163077298Sobrien } 163189857Sobrien 163277298Sobrien if (link_info.relocateable || (s->flags & (SEC_LOAD | SEC_ALLOC)) == 0) 163377298Sobrien address = exp_intop ((bfd_vma) 0); 163460484Sobrien else 163560484Sobrien { 163660484Sobrien /* All sections in an executable must be aligned to a page 163760484Sobrien boundary. */ 163860484Sobrien address = exp_unop (ALIGN_K, 163960484Sobrien exp_nameop (NAME, "__section_alignment__")); 164060484Sobrien } 164160484Sobrien 164277298Sobrien os = lang_enter_output_section_statement (outsecname, address, 0, 164377298Sobrien (bfd_vma) 0, 164477298Sobrien (etree_type *) NULL, 164577298Sobrien (etree_type *) NULL, 164677298Sobrien (etree_type *) NULL); 164760484Sobrien 164889857Sobrien lang_add_section (&add_child, s, os, file); 164960484Sobrien 165060484Sobrien lang_leave_output_section_statement 165160484Sobrien ((bfd_vma) 0, "*default*", 1652104834Sobrien (struct lang_output_section_phdr_list *) NULL, NULL); 165360484Sobrien 165477298Sobrien if (config.build_constructors && *ps == '\0') 165577298Sobrien { 165677298Sobrien char *symname; 165777298Sobrien 165877298Sobrien /* lang_leave_ouput_section_statement resets stat_ptr. Put 165977298Sobrien stat_ptr back where we want it. */ 166077298Sobrien if (place != NULL) 166177298Sobrien stat_ptr = &add; 166289857Sobrien 166377298Sobrien symname = (char *) xmalloc (ps - outsecname + sizeof "___stop_"); 166477298Sobrien sprintf (symname, "___stop_%s", outsecname); 166577298Sobrien lang_add_assignment (exp_assop ('=', symname, 166677298Sobrien exp_nameop (NAME, "."))); 166760484Sobrien } 166860484Sobrien 166960484Sobrien stat_ptr = old; 167060484Sobrien 1671104834Sobrien if (place != NULL && os->bfd_section != NULL) 167277298Sobrien { 167377298Sobrien asection *snew, **pps; 167460484Sobrien 167577298Sobrien snew = os->bfd_section; 167689857Sobrien 167789857Sobrien /* Shuffle the bfd section list to make the output file look 167889857Sobrien neater. This is really only cosmetic. */ 167989857Sobrien if (place->section == NULL) 168077298Sobrien { 168189857Sobrien asection *bfd_section = place->os->bfd_section; 168260484Sobrien 168389857Sobrien /* If the output statement hasn't been used to place 168489857Sobrien any input sections (and thus doesn't have an output 168589857Sobrien bfd_section), look for the closest prior output statement 168689857Sobrien having an output section. */ 168789857Sobrien if (bfd_section == NULL) 168889857Sobrien bfd_section = output_prev_sec_find (place->os); 168989857Sobrien 169089857Sobrien if (bfd_section != NULL && bfd_section != snew) 169189857Sobrien place->section = &bfd_section->next; 169289857Sobrien } 169389857Sobrien 169489857Sobrien if (place->section != NULL) 169589857Sobrien { 169689857Sobrien /* Unlink the section. */ 169789857Sobrien for (pps = &output_bfd->sections; 169889857Sobrien *pps != snew; 169989857Sobrien pps = &(*pps)->next) 170077298Sobrien ; 170189857Sobrien bfd_section_list_remove (output_bfd, pps); 170260484Sobrien 170377298Sobrien /* Now tack it on to the "place->os" section list. */ 170489857Sobrien bfd_section_list_insert (output_bfd, place->section, snew); 170577298Sobrien } 170660484Sobrien 170789857Sobrien /* Save the end of this list. Further ophans of this type will 170889857Sobrien follow the one we've just added. */ 170989857Sobrien place->section = &snew->next; 171089857Sobrien 171189857Sobrien /* The following is non-cosmetic. We try to put the output 171289857Sobrien statements in some sort of reasonable order here, because 171389857Sobrien they determine the final load addresses of the orphan 171489857Sobrien sections. In addition, placing output statements in the 171589857Sobrien wrong order may require extra segments. For instance, 171689857Sobrien given a typical situation of all read-only sections placed 171789857Sobrien in one segment and following that a segment containing all 171889857Sobrien the read-write sections, we wouldn't want to place an orphan 171989857Sobrien read/write section before or amongst the read-only ones. */ 172089857Sobrien if (add.head != NULL) 172160484Sobrien { 172289857Sobrien if (place->stmt == NULL) 172389857Sobrien { 172489857Sobrien /* Put the new statement list right at the head. */ 172589857Sobrien *add.tail = place->os->header.next; 172689857Sobrien place->os->header.next = add.head; 172789857Sobrien } 172889857Sobrien else 172989857Sobrien { 173089857Sobrien /* Put it after the last orphan statement we added. */ 173189857Sobrien *add.tail = *place->stmt; 173289857Sobrien *place->stmt = add.head; 173389857Sobrien } 173489857Sobrien 173589857Sobrien /* Fix the global list pointer if we happened to tack our 173689857Sobrien new list at the tail. */ 173789857Sobrien if (*old->tail == add.head) 173889857Sobrien old->tail = add.tail; 173989857Sobrien 174089857Sobrien /* Save the end of this list. */ 174189857Sobrien place->stmt = add.tail; 174260484Sobrien } 174360484Sobrien } 174433965Sjdp } 174533965Sjdp 174677298Sobrien { 174777298Sobrien lang_statement_union_type **pl = &os->children.head; 174877298Sobrien 174977298Sobrien if (dollar != NULL) 175077298Sobrien { 175177298Sobrien boolean found_dollar; 175277298Sobrien 175377298Sobrien /* The section name has a '$'. Sort it with the other '$' 175477298Sobrien sections. */ 175577298Sobrien 175677298Sobrien found_dollar = false; 175789857Sobrien for ( ; *pl != NULL; pl = &(*pl)->header.next) 175877298Sobrien { 175977298Sobrien lang_input_section_type *ls; 176077298Sobrien const char *lname; 176177298Sobrien 176277298Sobrien if ((*pl)->header.type != lang_input_section_enum) 176377298Sobrien continue; 176477298Sobrien 176577298Sobrien ls = &(*pl)->input_section; 176677298Sobrien 176777298Sobrien lname = bfd_get_section_name (ls->ifile->the_bfd, ls->section); 176877298Sobrien if (strchr (lname, '$') == NULL) 176977298Sobrien { 177077298Sobrien if (found_dollar) 177177298Sobrien break; 177277298Sobrien } 177377298Sobrien else 177477298Sobrien { 177577298Sobrien found_dollar = true; 177677298Sobrien if (strcmp (secname, lname) < 0) 177777298Sobrien break; 177877298Sobrien } 177977298Sobrien } 178077298Sobrien } 178177298Sobrien 178277298Sobrien if (add_child.head != NULL) 178377298Sobrien { 178489857Sobrien add_child.head->header.next = *pl; 178577298Sobrien *pl = add_child.head; 178677298Sobrien } 178777298Sobrien } 178877298Sobrien 178960484Sobrien free (hold_section_name); 179033965Sjdp 179133965Sjdp return true; 179233965Sjdp} 179360484Sobrien 179477298Sobrienstatic boolean 179577298Sobriengld_${EMULATION_NAME}_open_dynamic_archive (arch, search, entry) 179677298Sobrien const char * arch ATTRIBUTE_UNUSED; 179777298Sobrien search_dirs_type * search; 179877298Sobrien lang_input_statement_type * entry; 179960484Sobrien{ 180077298Sobrien const char * filename; 180177298Sobrien char * string; 180260484Sobrien 180377298Sobrien if (! entry->is_archive) 180477298Sobrien return false; 180560484Sobrien 180677298Sobrien filename = entry->filename; 180760484Sobrien 180877298Sobrien string = (char *) xmalloc (strlen (search->name) 180989857Sobrien + strlen (filename) 181077298Sobrien + sizeof "/lib.a.dll" 181177298Sobrien#ifdef DLL_SUPPORT 181277298Sobrien + (pe_dll_search_prefix ? strlen (pe_dll_search_prefix) : 0) 181377298Sobrien#endif 181477298Sobrien + 1); 181560484Sobrien 181677298Sobrien /* Try "libfoo.dll.a" first (preferred explicit import library for dll's */ 181777298Sobrien sprintf (string, "%s/lib%s.dll.a", search->name, filename); 181877298Sobrien 181977298Sobrien if (! ldfile_try_open_bfd (string, entry)) 182077298Sobrien { 182177298Sobrien /* Try "foo.dll.a" next (alternate explicit import library for dll's */ 182277298Sobrien sprintf (string, "%s/%s.dll.a", search->name, filename); 182377298Sobrien if (! ldfile_try_open_bfd (string, entry)) 182477298Sobrien { 182577298Sobrien/* 182677298Sobrien Try libfoo.a next. Normally, this would be interpreted as a static 182777298Sobrien library, but it *could* be an import library. For backwards compatibility, 182877298Sobrien libfoo.a needs to ==precede== libfoo.dll and foo.dll in the search, 182977298Sobrien or sometimes errors occur when building legacy packages. 183077298Sobrien 183177298Sobrien Putting libfoo.a here means that in a failure case (i.e. the library 183277298Sobrien -lfoo is not found) we will search for libfoo.a twice before 183377298Sobrien giving up -- once here, and once when searching for a "static" lib. 183477298Sobrien for a "static" lib. 183577298Sobrien*/ 183677298Sobrien /* Try "libfoo.a" (import lib, or static lib, but must 183777298Sobrien take precedence over dll's) */ 183877298Sobrien sprintf (string, "%s/lib%s.a", search->name, filename); 183977298Sobrien if (! ldfile_try_open_bfd (string, entry)) 184077298Sobrien { 184177298Sobrien#ifdef DLL_SUPPORT 184277298Sobrien if (pe_dll_search_prefix) 184389857Sobrien { 184477298Sobrien /* Try "<prefix>foo.dll" (preferred dll name, if specified) */ 184577298Sobrien sprintf (string, "%s/%s%s.dll", search->name, pe_dll_search_prefix, filename); 184677298Sobrien if (! ldfile_try_open_bfd (string, entry)) 184777298Sobrien { 184877298Sobrien /* Try "libfoo.dll" (default preferred dll name) */ 184977298Sobrien sprintf (string, "%s/lib%s.dll", search->name, filename); 185077298Sobrien if (! ldfile_try_open_bfd (string, entry)) 185177298Sobrien { 185277298Sobrien /* Finally, try "foo.dll" (alternate dll name) */ 185377298Sobrien sprintf (string, "%s/%s.dll", search->name, filename); 185477298Sobrien if (! ldfile_try_open_bfd (string, entry)) 185577298Sobrien { 185677298Sobrien free (string); 185777298Sobrien return false; 185877298Sobrien } 185977298Sobrien } 186077298Sobrien } 186177298Sobrien } 186277298Sobrien else /* pe_dll_search_prefix not specified */ 186389857Sobrien#endif 186477298Sobrien { 186577298Sobrien /* Try "libfoo.dll" (preferred dll name) */ 186677298Sobrien sprintf (string, "%s/lib%s.dll", search->name, filename); 186777298Sobrien if (! ldfile_try_open_bfd (string, entry)) 186877298Sobrien { 186977298Sobrien /* Finally, try "foo.dll" (alternate dll name) */ 187077298Sobrien sprintf (string, "%s/%s.dll", search->name, filename); 187177298Sobrien if (! ldfile_try_open_bfd (string, entry)) 187277298Sobrien { 187377298Sobrien free (string); 187477298Sobrien return false; 187577298Sobrien } 187677298Sobrien } 187777298Sobrien } 187877298Sobrien } 187977298Sobrien } 188077298Sobrien } 188177298Sobrien 188277298Sobrien entry->filename = string; 188377298Sobrien 188477298Sobrien return true; 188560484Sobrien} 188660484Sobrien 188760484Sobrienstatic int 188860484Sobriengld_${EMULATION_NAME}_find_potential_libraries (name, entry) 188960484Sobrien char * name; 189060484Sobrien lang_input_statement_type * entry; 189160484Sobrien{ 189260484Sobrien return ldfile_open_file_search (name, entry, "", ".lib"); 189360484Sobrien} 189433965Sjdp 189533965Sjdpstatic char * 189633965Sjdpgld_${EMULATION_NAME}_get_script(isfile) 189733965Sjdp int *isfile; 189833965SjdpEOF 189933965Sjdp# Scripts compiled in. 190033965Sjdp# sed commands to quote an ld script as a C string. 190160484Sobriensc="-f stringify.sed" 190233965Sjdp 190333965Sjdpcat >>e${EMULATION_NAME}.c <<EOF 190489857Sobrien{ 190533965Sjdp *isfile = 0; 190633965Sjdp 190733965Sjdp if (link_info.relocateable == true && config.build_constructors == true) 190833965Sjdp return 190933965SjdpEOF 191033965Sjdpsed $sc ldscripts/${EMULATION_NAME}.xu >> e${EMULATION_NAME}.c 191133965Sjdpecho ' ; else if (link_info.relocateable == true) return' >> e${EMULATION_NAME}.c 191233965Sjdpsed $sc ldscripts/${EMULATION_NAME}.xr >> e${EMULATION_NAME}.c 191333965Sjdpecho ' ; else if (!config.text_read_only) return' >> e${EMULATION_NAME}.c 191433965Sjdpsed $sc ldscripts/${EMULATION_NAME}.xbn >> e${EMULATION_NAME}.c 191533965Sjdpecho ' ; else if (!config.magic_demand_paged) return' >> e${EMULATION_NAME}.c 191633965Sjdpsed $sc ldscripts/${EMULATION_NAME}.xn >> e${EMULATION_NAME}.c 191733965Sjdpecho ' ; else return' >> e${EMULATION_NAME}.c 191833965Sjdpsed $sc ldscripts/${EMULATION_NAME}.x >> e${EMULATION_NAME}.c 191933965Sjdpecho '; }' >> e${EMULATION_NAME}.c 192033965Sjdp 192133965Sjdpcat >>e${EMULATION_NAME}.c <<EOF 192233965Sjdp 192333965Sjdp 192489857Sobrienstruct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation = 192533965Sjdp{ 192633965Sjdp gld_${EMULATION_NAME}_before_parse, 192733965Sjdp syslib_default, 192833965Sjdp hll_default, 192960484Sobrien gld_${EMULATION_NAME}_after_parse, 193033965Sjdp gld_${EMULATION_NAME}_after_open, 193133965Sjdp after_allocation_default, 193233965Sjdp set_output_arch_default, 193333965Sjdp ldemul_default_target, 193433965Sjdp gld_${EMULATION_NAME}_before_allocation, 193533965Sjdp gld_${EMULATION_NAME}_get_script, 193633965Sjdp "${EMULATION_NAME}", 193733965Sjdp "${OUTPUT_FORMAT}", 193860484Sobrien gld_${EMULATION_NAME}_finish, /* finish */ 193933965Sjdp NULL, /* create output section statements */ 194077298Sobrien gld_${EMULATION_NAME}_open_dynamic_archive, 194160484Sobrien gld_${EMULATION_NAME}_place_orphan, 194233965Sjdp gld_${EMULATION_NAME}_set_symbols, 194360484Sobrien gld_${EMULATION_NAME}_parse_args, 194460484Sobrien gld_${EMULATION_NAME}_unrecognized_file, 194560484Sobrien gld_${EMULATION_NAME}_list_options, 194660484Sobrien gld_${EMULATION_NAME}_recognized_file, 1947104834Sobrien gld_${EMULATION_NAME}_find_potential_libraries, 1948104834Sobrien NULL /* new_vers_pattern */ 194933965Sjdp}; 195033965SjdpEOF 1951