1214571Sdim# This shell script emits a C file. -*- C -*- 2214571Sdim# It does some substitutions. 3214571Sdimtest -z "${ENTRY}" && ENTRY="_mainCRTStartup" 4214571Sdimif [ -z "$MACHINE" ]; then 5214571Sdim OUTPUT_ARCH=${ARCH} 6214571Sdimelse 7214571Sdim OUTPUT_ARCH=${ARCH}:${MACHINE} 8214571Sdimfi 9214571Sdimrm -f e${EMULATION_NAME}.c 10214571Sdim(echo;echo;echo;echo;echo)>e${EMULATION_NAME}.c # there, now line numbers match ;-) 11214571Sdimcat >>e${EMULATION_NAME}.c <<EOF 12214571Sdim/* This file is part of GLD, the Gnu Linker. 13214571Sdim Copyright 2006, 2007 Free Software Foundation, Inc. 14214571Sdim 15214571Sdim This program is free software; you can redistribute it and/or modify 16214571Sdim it under the terms of the GNU General Public License as published by 17214571Sdim the Free Software Foundation; either version 2 of the License, or 18214571Sdim (at your option) any later version. 19214571Sdim 20214571Sdim This program is distributed in the hope that it will be useful, 21214571Sdim but WITHOUT ANY WARRANTY; without even the implied warranty of 22214571Sdim MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 23214571Sdim GNU General Public License for more details. 24214571Sdim 25214571Sdim You should have received a copy of the GNU General Public License 26214571Sdim along with this program; if not, write to the Free Software 27214571Sdim Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. 28214571Sdim 29214571Sdim Written by Kai Tietz, OneVision Software GmbH&CoKg. */ 30214571Sdim 31214571Sdim/* For WINDOWS_XP64 and higher */ 32214571Sdim/* Based on pe.em, but modified for 64 bit support. */ 33214571Sdim 34214571Sdim#define TARGET_IS_${EMULATION_NAME} 35214571Sdim 36214571Sdim#define COFF_IMAGE_WITH_PE 37214571Sdim#define COFF_WITH_PE 38214571Sdim#define COFF_WITH_pex64 39214571Sdim 40214571Sdim#include "sysdep.h" 41214571Sdim#include "bfd.h" 42214571Sdim#include "bfdlink.h" 43214571Sdim#include "getopt.h" 44214571Sdim#include "libiberty.h" 45214571Sdim#include "ld.h" 46214571Sdim#include "ldmain.h" 47214571Sdim#include "ldexp.h" 48214571Sdim#include "ldlang.h" 49214571Sdim#include "ldfile.h" 50214571Sdim#include "ldemul.h" 51214571Sdim#include <ldgram.h> 52214571Sdim#include "ldlex.h" 53214571Sdim#include "ldmisc.h" 54214571Sdim#include "ldctor.h" 55214571Sdim#include "coff/internal.h" 56214571Sdim 57214571Sdim/* FIXME: See bfd/peXXigen.c for why we include an architecture specific 58214571Sdim header in generic PE code. */ 59214571Sdim#include "coff/x86_64.h" 60214571Sdim#include "coff/pe.h" 61214571Sdim 62214571Sdim/* FIXME: This is a BFD internal header file, and we should not be 63214571Sdim using it here. */ 64214571Sdim#include "../bfd/libcoff.h" 65214571Sdim 66214571Sdim#undef AOUTSZ 67214571Sdim#define AOUTSZ PEPAOUTSZ 68214571Sdim#define PEAOUTHDR PEPAOUTHDR 69214571Sdim 70214571Sdim#include "deffile.h" 71214571Sdim#include "pep-dll.h" 72214571Sdim#include "safe-ctype.h" 73214571Sdim 74214571Sdim/* Permit the emulation parameters to override the default section 75214571Sdim alignment by setting OVERRIDE_SECTION_ALIGNMENT. FIXME: This makes 76214571Sdim it seem that include/coff/internal.h should not define 77214571Sdim PE_DEF_SECTION_ALIGNMENT. */ 78214571Sdim#if PE_DEF_SECTION_ALIGNMENT != ${OVERRIDE_SECTION_ALIGNMENT:-PE_DEF_SECTION_ALIGNMENT} 79214571Sdim#undef PE_DEF_SECTION_ALIGNMENT 80214571Sdim#define PE_DEF_SECTION_ALIGNMENT ${OVERRIDE_SECTION_ALIGNMENT} 81214571Sdim#endif 82214571Sdim 83214571Sdim#ifdef TARGET_IS_i386pep 84214571Sdim#define DLL_SUPPORT 85214571Sdim#endif 86214571Sdim 87214571Sdim#if defined(TARGET_IS_i386pep) || ! defined(DLL_SUPPORT) 88214571Sdim#define PE_DEF_SUBSYSTEM 3 89214571Sdim#else 90214571Sdim#undef NT_EXE_IMAGE_BASE 91214571Sdim#define NT_EXE_IMAGE_BASE 0x00010000 92214571Sdim#undef PE_DEF_SECTION_ALIGNMENT 93214571Sdim#define PE_DEF_SUBSYSTEM 2 94214571Sdim#undef PE_DEF_FILE_ALIGNMENT 95214571Sdim#define PE_DEF_FILE_ALIGNMENT 0x00000200 96214571Sdim#define PE_DEF_SECTION_ALIGNMENT 0x00000400 97214571Sdim#endif 98214571Sdim 99214571Sdim 100214571Sdimstatic struct internal_extra_pe_aouthdr pep; 101214571Sdimstatic int dll; 102214571Sdimstatic flagword real_flags = IMAGE_FILE_LARGE_ADDRESS_AWARE; 103214571Sdimstatic int support_old_code = 0; 104214571Sdimstatic lang_assignment_statement_type *image_base_statement = 0; 105214571Sdim 106214571Sdim#ifdef DLL_SUPPORT 107214571Sdimstatic int pep_enable_stdcall_fixup = -1; /* 0=disable 1=enable. */ 108214571Sdimstatic char * pep_out_def_filename = NULL; 109214571Sdimstatic char * pep_implib_filename = NULL; 110214571Sdimstatic int pep_enable_auto_image_base = 0; 111214571Sdimstatic char * pep_dll_search_prefix = NULL; 112214571Sdim#endif 113214571Sdim 114214571Sdimextern const char *output_filename; 115214571Sdim 116214571Sdimstatic void 117214571Sdimgld_${EMULATION_NAME}_before_parse (void) 118214571Sdim{ 119214571Sdim ldfile_set_output_arch ("${OUTPUT_ARCH}", bfd_arch_`echo ${ARCH} | sed -e 's/:.*//'`); 120214571Sdim output_filename = "${EXECUTABLE_NAME:-a.exe}"; 121214571Sdim#ifdef DLL_SUPPORT 122214571Sdim config.dynamic_link = TRUE; 123214571Sdim config.has_shared = 1; 124214571Sdim link_info.pei386_auto_import = -1; 125214571Sdim link_info.pei386_runtime_pseudo_reloc = -1; 126214571Sdim 127214571Sdim#if (PE_DEF_SUBSYSTEM == 9) || (PE_DEF_SUBSYSTEM == 2) 128214571Sdim lang_default_entry ("_WinMainCRTStartup"); 129214571Sdim#else 130214571Sdim lang_default_entry ("${ENTRY}"); 131214571Sdim#endif 132214571Sdim#endif 133214571Sdim} 134214571Sdim 135214571Sdim/* PE format extra command line options. */ 136214571Sdim 137214571Sdim/* Used for setting flags in the PE header. */ 138214571Sdimenum options 139214571Sdim{ 140214571Sdim OPTION_BASE_FILE = 300 + 1, 141214571Sdim OPTION_DLL, 142214571Sdim OPTION_FILE_ALIGNMENT, 143214571Sdim OPTION_IMAGE_BASE, 144214571Sdim OPTION_MAJOR_IMAGE_VERSION, 145214571Sdim OPTION_MAJOR_OS_VERSION, 146214571Sdim OPTION_MAJOR_SUBSYSTEM_VERSION, 147214571Sdim OPTION_MINOR_IMAGE_VERSION, 148214571Sdim OPTION_MINOR_OS_VERSION, 149214571Sdim OPTION_MINOR_SUBSYSTEM_VERSION, 150214571Sdim OPTION_SECTION_ALIGNMENT, 151214571Sdim OPTION_STACK, 152214571Sdim OPTION_SUBSYSTEM, 153214571Sdim OPTION_HEAP, 154214571Sdim OPTION_SUPPORT_OLD_CODE, 155214571Sdim OPTION_OUT_DEF, 156214571Sdim OPTION_EXPORT_ALL, 157214571Sdim OPTION_EXCLUDE_SYMBOLS, 158214571Sdim OPTION_KILL_ATS, 159214571Sdim OPTION_STDCALL_ALIASES, 160214571Sdim OPTION_ENABLE_STDCALL_FIXUP, 161214571Sdim OPTION_DISABLE_STDCALL_FIXUP, 162214571Sdim OPTION_IMPLIB_FILENAME, 163214571Sdim OPTION_WARN_DUPLICATE_EXPORTS, 164214571Sdim OPTION_IMP_COMPAT, 165214571Sdim OPTION_ENABLE_AUTO_IMAGE_BASE, 166214571Sdim OPTION_DISABLE_AUTO_IMAGE_BASE, 167214571Sdim OPTION_DLL_SEARCH_PREFIX, 168214571Sdim OPTION_NO_DEFAULT_EXCLUDES, 169214571Sdim OPTION_DLL_ENABLE_AUTO_IMPORT, 170214571Sdim OPTION_DLL_DISABLE_AUTO_IMPORT, 171214571Sdim OPTION_ENABLE_EXTRA_PE_DEBUG, 172214571Sdim OPTION_EXCLUDE_LIBS, 173214571Sdim OPTION_DLL_ENABLE_RUNTIME_PSEUDO_RELOC, 174214571Sdim OPTION_DLL_DISABLE_RUNTIME_PSEUDO_RELOC 175214571Sdim}; 176214571Sdim 177214571Sdimstatic void 178214571Sdimgld${EMULATION_NAME}_add_options 179214571Sdim (int ns ATTRIBUTE_UNUSED, 180214571Sdim char **shortopts ATTRIBUTE_UNUSED, 181214571Sdim int nl, 182214571Sdim struct option **longopts, 183214571Sdim int nrl ATTRIBUTE_UNUSED, 184214571Sdim struct option **really_longopts ATTRIBUTE_UNUSED) 185214571Sdim{ 186214571Sdim static const struct option xtra_long[] = 187214571Sdim { 188214571Sdim /* PE options */ 189214571Sdim {"base-file", required_argument, NULL, OPTION_BASE_FILE}, 190214571Sdim {"dll", no_argument, NULL, OPTION_DLL}, 191214571Sdim {"file-alignment", required_argument, NULL, OPTION_FILE_ALIGNMENT}, 192214571Sdim {"heap", required_argument, NULL, OPTION_HEAP}, 193214571Sdim {"image-base", required_argument, NULL, OPTION_IMAGE_BASE}, 194214571Sdim {"major-image-version", required_argument, NULL, OPTION_MAJOR_IMAGE_VERSION}, 195214571Sdim {"major-os-version", required_argument, NULL, OPTION_MAJOR_OS_VERSION}, 196214571Sdim {"major-subsystem-version", required_argument, NULL, OPTION_MAJOR_SUBSYSTEM_VERSION}, 197214571Sdim {"minor-image-version", required_argument, NULL, OPTION_MINOR_IMAGE_VERSION}, 198214571Sdim {"minor-os-version", required_argument, NULL, OPTION_MINOR_OS_VERSION}, 199214571Sdim {"minor-subsystem-version", required_argument, NULL, OPTION_MINOR_SUBSYSTEM_VERSION}, 200214571Sdim {"section-alignment", required_argument, NULL, OPTION_SECTION_ALIGNMENT}, 201214571Sdim {"stack", required_argument, NULL, OPTION_STACK}, 202214571Sdim {"subsystem", required_argument, NULL, OPTION_SUBSYSTEM}, 203214571Sdim {"support-old-code", no_argument, NULL, OPTION_SUPPORT_OLD_CODE}, 204214571Sdim#ifdef DLL_SUPPORT 205214571Sdim /* getopt allows abbreviations, so we do this to stop it 206214571Sdim from treating -o as an abbreviation for this option. */ 207214571Sdim {"output-def", required_argument, NULL, OPTION_OUT_DEF}, 208214571Sdim {"output-def", required_argument, NULL, OPTION_OUT_DEF}, 209214571Sdim {"export-all-symbols", no_argument, NULL, OPTION_EXPORT_ALL}, 210214571Sdim {"exclude-symbols", required_argument, NULL, OPTION_EXCLUDE_SYMBOLS}, 211214571Sdim {"exclude-libs", required_argument, NULL, OPTION_EXCLUDE_LIBS}, 212214571Sdim {"kill-at", no_argument, NULL, OPTION_KILL_ATS}, 213214571Sdim {"add-stdcall-alias", no_argument, NULL, OPTION_STDCALL_ALIASES}, 214214571Sdim {"enable-stdcall-fixup", no_argument, NULL, OPTION_ENABLE_STDCALL_FIXUP}, 215214571Sdim {"disable-stdcall-fixup", no_argument, NULL, OPTION_DISABLE_STDCALL_FIXUP}, 216214571Sdim {"out-implib", required_argument, NULL, OPTION_IMPLIB_FILENAME}, 217214571Sdim {"warn-duplicate-exports", no_argument, NULL, OPTION_WARN_DUPLICATE_EXPORTS}, 218214571Sdim /* getopt() allows abbreviations, so we do this to stop it from 219214571Sdim treating -c as an abbreviation for these --compat-implib. */ 220214571Sdim {"compat-implib", no_argument, NULL, OPTION_IMP_COMPAT}, 221214571Sdim {"compat-implib", no_argument, NULL, OPTION_IMP_COMPAT}, 222214571Sdim {"enable-auto-image-base", no_argument, NULL, OPTION_ENABLE_AUTO_IMAGE_BASE}, 223214571Sdim {"disable-auto-image-base", no_argument, NULL, OPTION_DISABLE_AUTO_IMAGE_BASE}, 224214571Sdim {"dll-search-prefix", required_argument, NULL, OPTION_DLL_SEARCH_PREFIX}, 225214571Sdim {"no-default-excludes", no_argument, NULL, OPTION_NO_DEFAULT_EXCLUDES}, 226214571Sdim {"enable-auto-import", no_argument, NULL, OPTION_DLL_ENABLE_AUTO_IMPORT}, 227214571Sdim {"disable-auto-import", no_argument, NULL, OPTION_DLL_DISABLE_AUTO_IMPORT}, 228214571Sdim {"enable-extra-pep-debug", no_argument, NULL, OPTION_ENABLE_EXTRA_PE_DEBUG}, 229214571Sdim {"enable-runtime-pseudo-reloc", no_argument, NULL, OPTION_DLL_ENABLE_RUNTIME_PSEUDO_RELOC}, 230214571Sdim {"disable-runtime-pseudo-reloc", no_argument, NULL, OPTION_DLL_DISABLE_RUNTIME_PSEUDO_RELOC}, 231214571Sdim#endif 232214571Sdim {NULL, no_argument, NULL, 0} 233214571Sdim }; 234214571Sdim 235214571Sdim *longopts = xrealloc (*longopts, nl * sizeof (struct option) + sizeof (xtra_long)); 236214571Sdim memcpy (*longopts + nl, &xtra_long, sizeof (xtra_long)); 237214571Sdim} 238214571Sdim 239214571Sdim/* PE/WIN32; added routines to get the subsystem type, heap and/or stack 240214571Sdim parameters which may be input from the command line. */ 241214571Sdim 242214571Sdimtypedef struct 243214571Sdim{ 244214571Sdim void *ptr; 245214571Sdim int size; 246214571Sdim int value; 247214571Sdim char *symbol; 248214571Sdim int inited; 249214571Sdim} definfo; 250214571Sdim 251214571Sdim#define D(field,symbol,def) {&pep.field,sizeof(pep.field), def, symbol,0} 252214571Sdim 253214571Sdimstatic definfo init[] = 254214571Sdim{ 255214571Sdim /* imagebase must be first */ 256214571Sdim#define IMAGEBASEOFF 0 257214571Sdim D(ImageBase,"__image_base__", NT_EXE_IMAGE_BASE), 258214571Sdim#define DLLOFF 1 259214571Sdim {&dll, sizeof(dll), 0, "__dll__", 0}, 260214571Sdim#define MSIMAGEBASEOFF 2 261214571Sdim D(ImageBase,"__ImageBase", NT_EXE_IMAGE_BASE), 262214571Sdim D(SectionAlignment,"__section_alignment__", PE_DEF_SECTION_ALIGNMENT), 263214571Sdim D(FileAlignment,"__file_alignment__", PE_DEF_FILE_ALIGNMENT), 264214571Sdim D(MajorOperatingSystemVersion,"__major_os_version__", 4), 265214571Sdim D(MinorOperatingSystemVersion,"__minor_os_version__", 0), 266214571Sdim D(MajorImageVersion,"__major_image_version__", 0), 267214571Sdim D(MinorImageVersion,"__minor_image_version__", 0), 268214571Sdim D(MajorSubsystemVersion,"__major_subsystem_version__", 5), 269214571Sdim D(MinorSubsystemVersion,"__minor_subsystem_version__", 2), 270214571Sdim D(Subsystem,"__subsystem__", ${SUBSYSTEM}), 271214571Sdim D(SizeOfStackReserve,"__size_of_stack_reserve__", 0x200000), 272214571Sdim D(SizeOfStackCommit,"__size_of_stack_commit__", 0x1000), 273214571Sdim D(SizeOfHeapReserve,"__size_of_heap_reserve__", 0x100000), 274214571Sdim D(SizeOfHeapCommit,"__size_of_heap_commit__", 0x1000), 275214571Sdim D(LoaderFlags,"__loader_flags__", 0x0), 276214571Sdim { NULL, 0, 0, NULL, 0 } 277214571Sdim}; 278214571Sdim 279214571Sdim 280214571Sdimstatic void 281214571Sdimgld_${EMULATION_NAME}_list_options (FILE *file) 282214571Sdim{ 283214571Sdim fprintf (file, _(" --base_file <basefile> Generate a base file for relocatable DLLs\n")); 284214571Sdim fprintf (file, _(" --dll Set image base to the default for DLLs\n")); 285214571Sdim fprintf (file, _(" --file-alignment <size> Set file alignment\n")); 286214571Sdim fprintf (file, _(" --heap <size> Set initial size of the heap\n")); 287214571Sdim fprintf (file, _(" --image-base <address> Set start address of the executable\n")); 288214571Sdim fprintf (file, _(" --major-image-version <number> Set version number of the executable\n")); 289214571Sdim fprintf (file, _(" --major-os-version <number> Set minimum required OS version\n")); 290214571Sdim fprintf (file, _(" --major-subsystem-version <number> Set minimum required OS subsystem version\n")); 291214571Sdim fprintf (file, _(" --minor-image-version <number> Set revision number of the executable\n")); 292214571Sdim fprintf (file, _(" --minor-os-version <number> Set minimum required OS revision\n")); 293214571Sdim fprintf (file, _(" --minor-subsystem-version <number> Set minimum required OS subsystem revision\n")); 294214571Sdim fprintf (file, _(" --section-alignment <size> Set section alignment\n")); 295214571Sdim fprintf (file, _(" --stack <size> Set size of the initial stack\n")); 296214571Sdim fprintf (file, _(" --subsystem <name>[:<version>] Set required OS subsystem [& version]\n")); 297214571Sdim fprintf (file, _(" --support-old-code Support interworking with old code\n")); 298214571Sdim#ifdef DLL_SUPPORT 299214571Sdim fprintf (file, _(" --add-stdcall-alias Export symbols with and without @nn\n")); 300214571Sdim fprintf (file, _(" --disable-stdcall-fixup Don't link _sym to _sym@nn\n")); 301214571Sdim fprintf (file, _(" --enable-stdcall-fixup Link _sym to _sym@nn without warnings\n")); 302214571Sdim fprintf (file, _(" --exclude-symbols sym,sym,... Exclude symbols from automatic export\n")); 303214571Sdim fprintf (file, _(" --exclude-libs lib,lib,... Exclude libraries from automatic export\n")); 304214571Sdim fprintf (file, _(" --export-all-symbols Automatically export all globals to DLL\n")); 305214571Sdim fprintf (file, _(" --kill-at Remove @nn from exported symbols\n")); 306214571Sdim fprintf (file, _(" --out-implib <file> Generate import library\n")); 307214571Sdim fprintf (file, _(" --output-def <file> Generate a .DEF file for the built DLL\n")); 308214571Sdim fprintf (file, _(" --warn-duplicate-exports Warn about duplicate exports.\n")); 309214571Sdim fprintf (file, _(" --compat-implib Create backward compatible import libs;\n\ 310214571Sdim create __imp_<SYMBOL> as well.\n")); 311214571Sdim fprintf (file, _(" --enable-auto-image-base Automatically choose image base for DLLs\n\ 312214571Sdim unless user specifies one\n")); 313214571Sdim fprintf (file, _(" --disable-auto-image-base Do not auto-choose image base. (default)\n")); 314214571Sdim fprintf (file, _(" --dll-search-prefix=<string> When linking dynamically to a dll without\n\ 315214571Sdim an importlib, use <string><basename>.dll\n\ 316214571Sdim in preference to lib<basename>.dll \n")); 317214571Sdim fprintf (file, _(" --enable-auto-import Do sophistcated linking of _sym to\n\ 318214571Sdim __imp_sym for DATA references\n")); 319214571Sdim fprintf (file, _(" --disable-auto-import Do not auto-import DATA items from DLLs\n")); 320214571Sdim fprintf (file, _(" --enable-runtime-pseudo-reloc Work around auto-import limitations by\n\ 321214571Sdim adding pseudo-relocations resolved at\n\ 322214571Sdim runtime.\n")); 323214571Sdim fprintf (file, _(" --disable-runtime-pseudo-reloc Do not add runtime pseudo-relocations for\n\ 324214571Sdim auto-imported DATA.\n")); 325214571Sdim fprintf (file, _(" --enable-extra-pep-debug Enable verbose debug output when building\n\ 326214571Sdim or linking to DLLs (esp. auto-import)\n")); 327214571Sdim#endif 328214571Sdim} 329214571Sdim 330214571Sdim 331214571Sdimstatic void 332214571Sdimset_pep_name (char *name, long val) 333214571Sdim{ 334214571Sdim int i; 335214571Sdim 336214571Sdim /* Find the name and set it. */ 337214571Sdim for (i = 0; init[i].ptr; i++) 338214571Sdim { 339214571Sdim if (strcmp (name, init[i].symbol) == 0) 340214571Sdim { 341214571Sdim init[i].value = val; 342214571Sdim init[i].inited = 1; 343214571Sdim if (strcmp (name,"__image_base__") == 0) 344214571Sdim set_pep_name ("__ImageBase", val); 345214571Sdim return; 346214571Sdim } 347214571Sdim } 348214571Sdim abort (); 349214571Sdim} 350214571Sdim 351214571Sdim 352214571Sdimstatic void 353214571Sdimset_pep_subsystem (void) 354214571Sdim{ 355214571Sdim const char *sver; 356214571Sdim const char *entry; 357214571Sdim const char *initial_symbol_char; 358214571Sdim char *end; 359214571Sdim int len; 360214571Sdim int i; 361214571Sdim int subsystem; 362214571Sdim unsigned long temp_subsystem; 363214571Sdim static const struct 364214571Sdim { 365214571Sdim const char *name; 366214571Sdim const int value; 367214571Sdim const char *entry; 368214571Sdim } 369214571Sdim v[] = 370214571Sdim { 371214571Sdim { "native", 1, "NtProcessStartup" }, 372214571Sdim { "windows", 2, "WinMainCRTStartup" }, 373214571Sdim { "console", 3, "mainCRTStartup" }, 374214571Sdim { "posix", 7, "__PosixProcessStartup"}, 375214571Sdim { "wince", 9, "_WinMainCRTStartup" }, 376214571Sdim { "xbox", 14, "mainCRTStartup" }, 377214571Sdim { NULL, 0, NULL } 378214571Sdim }; 379214571Sdim /* Entry point name for arbitrary subsystem numbers. */ 380214571Sdim static const char default_entry[] = "mainCRTStartup"; 381214571Sdim 382214571Sdim /* Check for the presence of a version number. */ 383214571Sdim sver = strchr (optarg, ':'); 384214571Sdim if (sver == NULL) 385214571Sdim len = strlen (optarg); 386214571Sdim else 387214571Sdim { 388214571Sdim len = sver - optarg; 389214571Sdim set_pep_name ("__major_subsystem_version__", 390214571Sdim strtoul (sver + 1, &end, 0)); 391214571Sdim if (*end == '.') 392214571Sdim set_pep_name ("__minor_subsystem_version__", 393214571Sdim strtoul (end + 1, &end, 0)); 394214571Sdim if (*end != '\0') 395214571Sdim einfo (_("%P: warning: bad version number in -subsystem option\n")); 396214571Sdim } 397214571Sdim 398214571Sdim /* Check for numeric subsystem. */ 399214571Sdim temp_subsystem = strtoul (optarg, & end, 0); 400214571Sdim if ((*end == ':' || *end == '\0') && (temp_subsystem < 65536)) 401214571Sdim { 402214571Sdim /* Search list for a numeric match to use its entry point. */ 403214571Sdim for (i = 0; v[i].name; i++) 404214571Sdim if (v[i].value == (int) temp_subsystem) 405214571Sdim break; 406214571Sdim 407214571Sdim /* If no match, use the default. */ 408214571Sdim if (v[i].name != NULL) 409214571Sdim entry = v[i].entry; 410214571Sdim else 411214571Sdim entry = default_entry; 412214571Sdim 413214571Sdim /* Use this subsystem. */ 414214571Sdim subsystem = (int) temp_subsystem; 415214571Sdim } 416214571Sdim else 417214571Sdim { 418214571Sdim /* Search for subsystem by name. */ 419214571Sdim for (i = 0; v[i].name; i++) 420214571Sdim if (strncmp (optarg, v[i].name, len) == 0 421214571Sdim && v[i].name[len] == '\0') 422214571Sdim break; 423214571Sdim 424214571Sdim if (v[i].name == NULL) 425214571Sdim { 426214571Sdim einfo (_("%P%F: invalid subsystem type %s\n"), optarg); 427214571Sdim return; 428214571Sdim } 429214571Sdim 430214571Sdim entry = v[i].entry; 431214571Sdim subsystem = v[i].value; 432214571Sdim } 433214571Sdim 434214571Sdim set_pep_name ("__subsystem__", subsystem); 435214571Sdim 436214571Sdim initial_symbol_char = ${INITIAL_SYMBOL_CHAR}; 437214571Sdim if (*initial_symbol_char != '\0') 438214571Sdim { 439214571Sdim char *alc_entry; 440214571Sdim 441214571Sdim /* lang_default_entry expects its argument to be permanently 442214571Sdim allocated, so we don't free this string. */ 443214571Sdim alc_entry = xmalloc (strlen (initial_symbol_char) 444214571Sdim + strlen (entry) 445214571Sdim + 1); 446214571Sdim strcpy (alc_entry, initial_symbol_char); 447214571Sdim strcat (alc_entry, entry); 448214571Sdim entry = alc_entry; 449214571Sdim } 450214571Sdim 451214571Sdim lang_default_entry (entry); 452214571Sdim 453214571Sdim return; 454214571Sdim} 455214571Sdim 456214571Sdim 457214571Sdimstatic void 458214571Sdimset_pep_value (char *name) 459214571Sdim{ 460214571Sdim char *end; 461214571Sdim 462214571Sdim set_pep_name (name, strtoul (optarg, &end, 0)); 463214571Sdim 464214571Sdim if (end == optarg) 465214571Sdim einfo (_("%P%F: invalid hex number for PE parameter '%s'\n"), optarg); 466214571Sdim 467214571Sdim optarg = end; 468214571Sdim} 469214571Sdim 470214571Sdim 471214571Sdimstatic void 472214571Sdimset_pep_stack_heap (char *resname, char *comname) 473214571Sdim{ 474214571Sdim set_pep_value (resname); 475214571Sdim 476214571Sdim if (*optarg == ',') 477214571Sdim { 478214571Sdim optarg++; 479214571Sdim set_pep_value (comname); 480214571Sdim } 481214571Sdim else if (*optarg) 482214571Sdim einfo (_("%P%F: strange hex info for PE parameter '%s'\n"), optarg); 483214571Sdim} 484214571Sdim 485214571Sdim 486214571Sdimstatic bfd_boolean 487214571Sdimgld${EMULATION_NAME}_handle_option (int optc) 488214571Sdim{ 489214571Sdim switch (optc) 490214571Sdim { 491214571Sdim default: 492214571Sdim return FALSE; 493214571Sdim 494214571Sdim case OPTION_BASE_FILE: 495214571Sdim link_info.base_file = fopen (optarg, FOPEN_WB); 496214571Sdim if (link_info.base_file == NULL) 497214571Sdim { 498214571Sdim /* xgettext:c-format */ 499214571Sdim fprintf (stderr, _("%s: Can't open base file %s\n"), 500214571Sdim program_name, optarg); 501214571Sdim xexit (1); 502214571Sdim } 503214571Sdim break; 504214571Sdim 505214571Sdim /* PE options. */ 506214571Sdim case OPTION_HEAP: 507214571Sdim set_pep_stack_heap ("__size_of_heap_reserve__", "__size_of_heap_commit__"); 508214571Sdim break; 509214571Sdim case OPTION_STACK: 510214571Sdim set_pep_stack_heap ("__size_of_stack_reserve__", "__size_of_stack_commit__"); 511214571Sdim break; 512214571Sdim case OPTION_SUBSYSTEM: 513214571Sdim set_pep_subsystem (); 514214571Sdim break; 515214571Sdim case OPTION_MAJOR_OS_VERSION: 516214571Sdim set_pep_value ("__major_os_version__"); 517214571Sdim break; 518214571Sdim case OPTION_MINOR_OS_VERSION: 519214571Sdim set_pep_value ("__minor_os_version__"); 520214571Sdim break; 521214571Sdim case OPTION_MAJOR_SUBSYSTEM_VERSION: 522214571Sdim set_pep_value ("__major_subsystem_version__"); 523214571Sdim break; 524214571Sdim case OPTION_MINOR_SUBSYSTEM_VERSION: 525214571Sdim set_pep_value ("__minor_subsystem_version__"); 526214571Sdim break; 527214571Sdim case OPTION_MAJOR_IMAGE_VERSION: 528214571Sdim set_pep_value ("__major_image_version__"); 529214571Sdim break; 530214571Sdim case OPTION_MINOR_IMAGE_VERSION: 531214571Sdim set_pep_value ("__minor_image_version__"); 532214571Sdim break; 533214571Sdim case OPTION_FILE_ALIGNMENT: 534214571Sdim set_pep_value ("__file_alignment__"); 535214571Sdim break; 536214571Sdim case OPTION_SECTION_ALIGNMENT: 537214571Sdim set_pep_value ("__section_alignment__"); 538214571Sdim break; 539214571Sdim case OPTION_DLL: 540214571Sdim set_pep_name ("__dll__", 1); 541214571Sdim break; 542214571Sdim case OPTION_IMAGE_BASE: 543214571Sdim set_pep_value ("__image_base__"); 544214571Sdim break; 545214571Sdim case OPTION_SUPPORT_OLD_CODE: 546214571Sdim support_old_code = 1; 547214571Sdim break; 548214571Sdim#ifdef DLL_SUPPORT 549214571Sdim case OPTION_OUT_DEF: 550214571Sdim pep_out_def_filename = xstrdup (optarg); 551214571Sdim break; 552214571Sdim case OPTION_EXPORT_ALL: 553214571Sdim pep_dll_export_everything = 1; 554214571Sdim break; 555214571Sdim case OPTION_EXCLUDE_SYMBOLS: 556214571Sdim pep_dll_add_excludes (optarg, 0); 557214571Sdim break; 558214571Sdim case OPTION_EXCLUDE_LIBS: 559214571Sdim pep_dll_add_excludes (optarg, 1); 560214571Sdim break; 561214571Sdim case OPTION_KILL_ATS: 562214571Sdim pep_dll_kill_ats = 1; 563214571Sdim break; 564214571Sdim case OPTION_STDCALL_ALIASES: 565214571Sdim pep_dll_stdcall_aliases = 1; 566214571Sdim break; 567214571Sdim case OPTION_ENABLE_STDCALL_FIXUP: 568214571Sdim pep_enable_stdcall_fixup = 1; 569214571Sdim break; 570214571Sdim case OPTION_DISABLE_STDCALL_FIXUP: 571214571Sdim pep_enable_stdcall_fixup = 0; 572214571Sdim break; 573214571Sdim case OPTION_IMPLIB_FILENAME: 574214571Sdim pep_implib_filename = xstrdup (optarg); 575214571Sdim break; 576214571Sdim case OPTION_WARN_DUPLICATE_EXPORTS: 577214571Sdim pep_dll_warn_dup_exports = 1; 578214571Sdim break; 579214571Sdim case OPTION_IMP_COMPAT: 580214571Sdim pep_dll_compat_implib = 1; 581214571Sdim break; 582214571Sdim case OPTION_ENABLE_AUTO_IMAGE_BASE: 583214571Sdim pep_enable_auto_image_base = 1; 584214571Sdim break; 585214571Sdim case OPTION_DISABLE_AUTO_IMAGE_BASE: 586214571Sdim pep_enable_auto_image_base = 0; 587214571Sdim break; 588214571Sdim case OPTION_DLL_SEARCH_PREFIX: 589214571Sdim pep_dll_search_prefix = xstrdup (optarg); 590214571Sdim break; 591214571Sdim case OPTION_NO_DEFAULT_EXCLUDES: 592214571Sdim pep_dll_do_default_excludes = 0; 593214571Sdim break; 594214571Sdim case OPTION_DLL_ENABLE_AUTO_IMPORT: 595214571Sdim link_info.pei386_auto_import = 1; 596214571Sdim break; 597214571Sdim case OPTION_DLL_DISABLE_AUTO_IMPORT: 598214571Sdim link_info.pei386_auto_import = 0; 599214571Sdim break; 600214571Sdim case OPTION_DLL_ENABLE_RUNTIME_PSEUDO_RELOC: 601214571Sdim link_info.pei386_runtime_pseudo_reloc = 1; 602214571Sdim break; 603214571Sdim case OPTION_DLL_DISABLE_RUNTIME_PSEUDO_RELOC: 604214571Sdim link_info.pei386_runtime_pseudo_reloc = 0; 605214571Sdim break; 606214571Sdim case OPTION_ENABLE_EXTRA_PE_DEBUG: 607214571Sdim pep_dll_extra_pe_debug = 1; 608214571Sdim break; 609214571Sdim#endif 610214571Sdim } 611214571Sdim return TRUE; 612214571Sdim} 613214571Sdim 614214571Sdim 615214571Sdim#ifdef DLL_SUPPORT 616214571Sdimstatic unsigned long 617214571Sdimstrhash (const char *str) 618214571Sdim{ 619214571Sdim const unsigned char *s; 620214571Sdim unsigned long hash; 621214571Sdim unsigned int c; 622214571Sdim unsigned int len; 623214571Sdim 624214571Sdim hash = 0; 625214571Sdim len = 0; 626214571Sdim s = (const unsigned char *) str; 627214571Sdim while ((c = *s++) != '\0') 628214571Sdim { 629214571Sdim hash += c + (c << 17); 630214571Sdim hash ^= hash >> 2; 631214571Sdim ++len; 632214571Sdim } 633214571Sdim hash += len + (len << 17); 634214571Sdim hash ^= hash >> 2; 635214571Sdim 636214571Sdim return hash; 637214571Sdim} 638214571Sdim 639214571Sdim/* Use the output file to create a image base for relocatable DLLs. */ 640214571Sdim 641214571Sdimstatic unsigned long 642214571Sdimcompute_dll_image_base (const char *ofile) 643214571Sdim{ 644214571Sdim unsigned long hash = strhash (ofile); 645214571Sdim return 0x61300000 + ((hash << 16) & 0x0FFC0000); 646214571Sdim} 647214571Sdim#endif 648214571Sdim 649214571Sdim/* Assign values to the special symbols before the linker script is 650214571Sdim read. */ 651214571Sdim 652214571Sdimstatic void 653214571Sdimgld_${EMULATION_NAME}_set_symbols (void) 654214571Sdim{ 655214571Sdim /* Run through and invent symbols for all the 656214571Sdim names and insert the defaults. */ 657214571Sdim int j; 658214571Sdim lang_statement_list_type *save; 659214571Sdim 660214571Sdim if (!init[IMAGEBASEOFF].inited) 661214571Sdim { 662214571Sdim if (link_info.relocatable) 663214571Sdim init[IMAGEBASEOFF].value = 0; 664214571Sdim else if (init[DLLOFF].value || (link_info.shared && !link_info.pie)) 665214571Sdim#ifdef DLL_SUPPORT 666214571Sdim init[IMAGEBASEOFF].value = (pep_enable_auto_image_base) ? 667214571Sdim compute_dll_image_base (output_filename) : NT_DLL_IMAGE_BASE; 668214571Sdim#else 669214571Sdim init[IMAGEBASEOFF].value = NT_DLL_IMAGE_BASE; 670214571Sdim#endif 671214571Sdim else 672214571Sdim init[IMAGEBASEOFF].value = NT_EXE_IMAGE_BASE; 673214571Sdim init[MSIMAGEBASEOFF].value = init[IMAGEBASEOFF].value; 674214571Sdim } 675214571Sdim 676214571Sdim /* Don't do any symbol assignments if this is a relocatable link. */ 677214571Sdim if (link_info.relocatable) 678214571Sdim return; 679214571Sdim 680214571Sdim /* Glue the assignments into the abs section. */ 681214571Sdim save = stat_ptr; 682214571Sdim 683214571Sdim stat_ptr = &(abs_output_section->children); 684214571Sdim 685214571Sdim for (j = 0; init[j].ptr; j++) 686214571Sdim { 687214571Sdim long val = init[j].value; 688214571Sdim lang_assignment_statement_type *rv; 689214571Sdim rv = lang_add_assignment (exp_assop ('=', init[j].symbol, 690214571Sdim exp_intop (val))); 691214571Sdim if (init[j].size == sizeof (short)) 692214571Sdim *(short *) init[j].ptr = val; 693214571Sdim else if (init[j].size == sizeof (int)) 694214571Sdim *(int *) init[j].ptr = val; 695214571Sdim else if (init[j].size == sizeof (long)) 696214571Sdim *(long *) init[j].ptr = val; 697214571Sdim /* This might be a long long or other special type. */ 698214571Sdim else if (init[j].size == sizeof (bfd_vma)) 699214571Sdim *(bfd_vma *) init[j].ptr = val; 700214571Sdim else abort (); 701214571Sdim if (j == IMAGEBASEOFF) 702214571Sdim image_base_statement = rv; 703214571Sdim } 704214571Sdim /* Restore the pointer. */ 705214571Sdim stat_ptr = save; 706214571Sdim 707214571Sdim if (pep.FileAlignment > pep.SectionAlignment) 708214571Sdim { 709214571Sdim einfo (_("%P: warning, file alignment > section alignment.\n")); 710214571Sdim } 711214571Sdim} 712214571Sdim 713214571Sdim/* This is called after the linker script and the command line options 714214571Sdim have been read. */ 715214571Sdim 716214571Sdimstatic void 717214571Sdimgld_${EMULATION_NAME}_after_parse (void) 718214571Sdim{ 719214571Sdim /* The Windows libraries are designed for the linker to treat the 720214571Sdim entry point as an undefined symbol. Otherwise, the .obj that 721214571Sdim defines mainCRTStartup is brought in because it is the first 722214571Sdim encountered in libc.lib and it has other symbols in it which will 723214571Sdim be pulled in by the link process. To avoid this, we act as 724214571Sdim though the user specified -u with the entry point symbol. 725214571Sdim 726214571Sdim This function is called after the linker script and command line 727214571Sdim options have been read, so at this point we know the right entry 728214571Sdim point. This function is called before the input files are 729214571Sdim opened, so registering the symbol as undefined will make a 730214571Sdim difference. */ 731214571Sdim 732214571Sdim if (! link_info.relocatable && entry_symbol.name != NULL) 733214571Sdim ldlang_add_undef (entry_symbol.name); 734214571Sdim} 735214571Sdim 736214571Sdim/* pep-dll.c directly accesses pep_data_import_dll, 737214571Sdim so it must be defined outside of #ifdef DLL_SUPPORT. 738214571Sdim Note - this variable is deliberately not initialised. 739214571Sdim This allows it to be treated as a common varaible, and only 740214571Sdim exist in one incarnation in a multiple target enabled linker. */ 741214571Sdimchar * pep_data_import_dll; 742214571Sdim 743214571Sdim#ifdef DLL_SUPPORT 744214571Sdimstatic struct bfd_link_hash_entry *pep_undef_found_sym; 745214571Sdim 746214571Sdimstatic bfd_boolean 747214571Sdimpep_undef_cdecl_match (struct bfd_link_hash_entry *h, void *inf) 748214571Sdim{ 749214571Sdim int sl; 750214571Sdim char *string = inf; 751214571Sdim 752214571Sdim sl = strlen (string); 753214571Sdim if (h->type == bfd_link_hash_defined 754214571Sdim && strncmp (h->root.string, string, sl) == 0 755214571Sdim && h->root.string[sl] == '@') 756214571Sdim { 757214571Sdim pep_undef_found_sym = h; 758214571Sdim return FALSE; 759214571Sdim } 760214571Sdim return TRUE; 761214571Sdim} 762214571Sdim 763214571Sdimstatic void 764214571Sdimpep_fixup_stdcalls (void) 765214571Sdim{ 766214571Sdim static int gave_warning_message = 0; 767214571Sdim struct bfd_link_hash_entry *undef, *sym; 768214571Sdim 769214571Sdim if (pep_dll_extra_pe_debug) 770214571Sdim printf ("%s\n", __FUNCTION__); 771214571Sdim 772214571Sdim for (undef = link_info.hash->undefs; undef; undef=undef->u.undef.next) 773214571Sdim if (undef->type == bfd_link_hash_undefined) 774214571Sdim { 775214571Sdim char* at = strchr (undef->root.string, '@'); 776214571Sdim int lead_at = (*undef->root.string == '@'); 777214571Sdim /* For now, don't try to fixup fastcall symbols. */ 778214571Sdim 779214571Sdim if (at && !lead_at) 780214571Sdim { 781214571Sdim /* The symbol is a stdcall symbol, so let's look for a 782214571Sdim cdecl symbol with the same name and resolve to that. */ 783214571Sdim char *cname = xstrdup (undef->root.string /* + lead_at */); 784214571Sdim at = strchr (cname, '@'); 785214571Sdim *at = 0; 786214571Sdim sym = bfd_link_hash_lookup (link_info.hash, cname, 0, 0, 1); 787214571Sdim 788214571Sdim if (sym && sym->type == bfd_link_hash_defined) 789214571Sdim { 790214571Sdim undef->type = bfd_link_hash_defined; 791214571Sdim undef->u.def.value = sym->u.def.value; 792214571Sdim undef->u.def.section = sym->u.def.section; 793214571Sdim 794214571Sdim if (pep_enable_stdcall_fixup == -1) 795214571Sdim { 796214571Sdim einfo (_("Warning: resolving %s by linking to %s\n"), 797214571Sdim undef->root.string, cname); 798214571Sdim if (! gave_warning_message) 799214571Sdim { 800214571Sdim gave_warning_message = 1; 801214571Sdim einfo (_("Use --enable-stdcall-fixup to disable these warnings\n")); 802214571Sdim einfo (_("Use --disable-stdcall-fixup to disable these fixups\n")); 803214571Sdim } 804214571Sdim } 805214571Sdim } 806214571Sdim } 807214571Sdim else 808214571Sdim { 809214571Sdim /* The symbol is a cdecl symbol, so we look for stdcall 810214571Sdim symbols - which means scanning the whole symbol table. */ 811214571Sdim pep_undef_found_sym = 0; 812214571Sdim bfd_link_hash_traverse (link_info.hash, pep_undef_cdecl_match, 813214571Sdim (char *) undef->root.string); 814214571Sdim sym = pep_undef_found_sym; 815214571Sdim if (sym) 816214571Sdim { 817214571Sdim undef->type = bfd_link_hash_defined; 818214571Sdim undef->u.def.value = sym->u.def.value; 819214571Sdim undef->u.def.section = sym->u.def.section; 820214571Sdim 821214571Sdim if (pep_enable_stdcall_fixup == -1) 822214571Sdim { 823214571Sdim einfo (_("Warning: resolving %s by linking to %s\n"), 824214571Sdim undef->root.string, sym->root.string); 825214571Sdim if (! gave_warning_message) 826214571Sdim { 827214571Sdim gave_warning_message = 1; 828214571Sdim einfo (_("Use --enable-stdcall-fixup to disable these warnings\n")); 829214571Sdim einfo (_("Use --disable-stdcall-fixup to disable these fixups\n")); 830214571Sdim } 831214571Sdim } 832214571Sdim } 833214571Sdim } 834214571Sdim } 835214571Sdim} 836214571Sdim 837214571Sdimstatic int 838214571Sdimmake_import_fixup (arelent *rel, asection *s) 839214571Sdim{ 840214571Sdim struct bfd_symbol *sym = *rel->sym_ptr_ptr; 841214571Sdim char addend[4]; 842214571Sdim 843214571Sdim if (pep_dll_extra_pe_debug) 844214571Sdim printf ("arelent: %s@%#lx: add=%li\n", sym->name, 845214571Sdim (long) rel->address, (long) rel->addend); 846214571Sdim 847214571Sdim if (! bfd_get_section_contents (s->owner, s, addend, rel->address, sizeof (addend))) 848214571Sdim einfo (_("%C: Cannot get section contents - auto-import exception\n"), 849214571Sdim s->owner, s, rel->address); 850214571Sdim 851214571Sdim pep_create_import_fixup (rel, s, bfd_get_32 (s->owner, addend)); 852214571Sdim 853214571Sdim return 1; 854214571Sdim} 855214571Sdim 856214571Sdimstatic void 857214571Sdimpep_find_data_imports (void) 858214571Sdim{ 859214571Sdim struct bfd_link_hash_entry *undef, *sym; 860214571Sdim 861214571Sdim if (link_info.pei386_auto_import == 0) 862214571Sdim return; 863214571Sdim 864214571Sdim for (undef = link_info.hash->undefs; undef; undef=undef->u.undef.next) 865214571Sdim { 866214571Sdim if (undef->type == bfd_link_hash_undefined) 867214571Sdim { 868214571Sdim /* C++ symbols are *long*. */ 869214571Sdim char buf[4096]; 870214571Sdim 871214571Sdim if (pep_dll_extra_pe_debug) 872214571Sdim printf ("%s:%s\n", __FUNCTION__, undef->root.string); 873214571Sdim 874214571Sdim sprintf (buf, "__imp_%s", undef->root.string); 875214571Sdim 876214571Sdim sym = bfd_link_hash_lookup (link_info.hash, buf, 0, 0, 1); 877214571Sdim 878214571Sdim if (sym && sym->type == bfd_link_hash_defined) 879214571Sdim { 880214571Sdim bfd *b = sym->u.def.section->owner; 881214571Sdim asymbol **symbols; 882214571Sdim int nsyms, symsize, i; 883214571Sdim 884214571Sdim if (link_info.pei386_auto_import == -1) 885214571Sdim info_msg (_("Info: resolving %s by linking to %s (auto-import)\n"), 886214571Sdim undef->root.string, buf); 887214571Sdim 888214571Sdim symsize = bfd_get_symtab_upper_bound (b); 889214571Sdim symbols = xmalloc (symsize); 890214571Sdim nsyms = bfd_canonicalize_symtab (b, symbols); 891214571Sdim 892214571Sdim for (i = 0; i < nsyms; i++) 893214571Sdim { 894214571Sdim if (! CONST_STRNEQ (symbols[i]->name, "__head_")) 895214571Sdim continue; 896214571Sdim 897214571Sdim if (pep_dll_extra_pe_debug) 898214571Sdim printf ("->%s\n", symbols[i]->name); 899214571Sdim 900214571Sdim pep_data_import_dll = (char*) (symbols[i]->name + 901214571Sdim sizeof ("__head_") - 1); 902214571Sdim break; 903214571Sdim } 904214571Sdim 905214571Sdim pep_walk_relocs_of_symbol (&link_info, undef->root.string, 906214571Sdim make_import_fixup); 907214571Sdim 908214571Sdim /* Let's differentiate it somehow from defined. */ 909214571Sdim undef->type = bfd_link_hash_defweak; 910214571Sdim /* We replace original name with __imp_ prefixed, this 911214571Sdim 1) may trash memory 2) leads to duplicate symbol generation. 912214571Sdim Still, IMHO it's better than having name poluted. */ 913214571Sdim undef->root.string = sym->root.string; 914214571Sdim undef->u.def.value = sym->u.def.value; 915214571Sdim undef->u.def.section = sym->u.def.section; 916214571Sdim } 917214571Sdim } 918214571Sdim } 919214571Sdim} 920214571Sdim 921214571Sdimstatic bfd_boolean 922214571Sdimpr_sym (struct bfd_hash_entry *h, void *inf ATTRIBUTE_UNUSED) 923214571Sdim{ 924214571Sdim if (pep_dll_extra_pe_debug) 925214571Sdim printf ("+%s\n", h->string); 926214571Sdim 927214571Sdim return TRUE; 928214571Sdim} 929214571Sdim#endif /* DLL_SUPPORT */ 930214571Sdim 931214571Sdim 932214571Sdimstatic void 933214571Sdimgld_${EMULATION_NAME}_after_open (void) 934214571Sdim{ 935214571Sdim#ifdef DLL_SUPPORT 936214571Sdim if (pep_dll_extra_pe_debug) 937214571Sdim { 938214571Sdim bfd *a; 939214571Sdim struct bfd_link_hash_entry *sym; 940214571Sdim 941214571Sdim printf ("%s()\n", __FUNCTION__); 942214571Sdim 943214571Sdim for (sym = link_info.hash->undefs; sym; sym=sym->u.undef.next) 944214571Sdim printf ("-%s\n", sym->root.string); 945214571Sdim bfd_hash_traverse (&link_info.hash->table, pr_sym, NULL); 946214571Sdim 947214571Sdim for (a = link_info.input_bfds; a; a = a->link_next) 948214571Sdim printf ("*%s\n",a->filename); 949214571Sdim } 950214571Sdim#endif 951214571Sdim 952214571Sdim /* Pass the wacky PE command line options into the output bfd. 953214571Sdim FIXME: This should be done via a function, rather than by 954214571Sdim including an internal BFD header. */ 955214571Sdim 956214571Sdim if (coff_data (output_bfd) == NULL || coff_data (output_bfd)->pe == 0) 957214571Sdim einfo (_("%F%P: cannot perform PE operations on non PE output file '%B'.\n"), output_bfd); 958214571Sdim 959214571Sdim pe_data (output_bfd)->pe_opthdr = pep; 960214571Sdim pe_data (output_bfd)->dll = init[DLLOFF].value; 961214571Sdim pe_data (output_bfd)->real_flags |= real_flags; 962214571Sdim 963214571Sdim#ifdef DLL_SUPPORT 964214571Sdim if (pep_enable_stdcall_fixup) /* -1=warn or 1=disable */ 965214571Sdim pep_fixup_stdcalls (); 966214571Sdim 967214571Sdim pep_process_import_defs (output_bfd, & link_info); 968214571Sdim 969214571Sdim pep_find_data_imports (); 970214571Sdim 971214571Sdim#ifndef TARGET_IS_i386pep 972214571Sdim if (link_info.shared) 973214571Sdim#else 974214571Sdim if (!link_info.relocatable) 975214571Sdim#endif 976214571Sdim pep_dll_build_sections (output_bfd, &link_info); 977214571Sdim 978214571Sdim#ifndef TARGET_IS_i386pep 979214571Sdim else 980214571Sdim pep_exe_build_sections (output_bfd, &link_info); 981214571Sdim#endif 982214571Sdim#endif /* DLL_SUPPORT */ 983214571Sdim 984214571Sdim { 985214571Sdim /* This next chunk of code tries to detect the case where you have 986214571Sdim two import libraries for the same DLL (specifically, 987214571Sdim symbolically linking libm.a and libc.a in cygwin to 988214571Sdim libcygwin.a). In those cases, it's possible for function 989214571Sdim thunks from the second implib to be used but without the 990214571Sdim head/tail objects, causing an improper import table. We detect 991214571Sdim those cases and rename the "other" import libraries to match 992214571Sdim the one the head/tail come from, so that the linker will sort 993214571Sdim things nicely and produce a valid import table. */ 994214571Sdim 995214571Sdim LANG_FOR_EACH_INPUT_STATEMENT (is) 996214571Sdim { 997214571Sdim if (is->the_bfd->my_archive) 998214571Sdim { 999214571Sdim int idata2 = 0, reloc_count=0, is_imp = 0; 1000214571Sdim asection *sec; 1001214571Sdim 1002214571Sdim /* See if this is an import library thunk. */ 1003214571Sdim for (sec = is->the_bfd->sections; sec; sec = sec->next) 1004214571Sdim { 1005214571Sdim if (strcmp (sec->name, ".idata\$2") == 0) 1006214571Sdim idata2 = 1; 1007214571Sdim if (CONST_STRNEQ (sec->name, ".idata\$")) 1008214571Sdim is_imp = 1; 1009214571Sdim reloc_count += sec->reloc_count; 1010214571Sdim } 1011214571Sdim 1012214571Sdim if (is_imp && !idata2 && reloc_count) 1013214571Sdim { 1014214571Sdim /* It is, look for the reference to head and see if it's 1015214571Sdim from our own library. */ 1016214571Sdim for (sec = is->the_bfd->sections; sec; sec = sec->next) 1017214571Sdim { 1018214571Sdim int i; 1019214571Sdim long symsize; 1020214571Sdim long relsize; 1021214571Sdim asymbol **symbols; 1022214571Sdim arelent **relocs; 1023214571Sdim int nrelocs; 1024214571Sdim 1025214571Sdim symsize = bfd_get_symtab_upper_bound (is->the_bfd); 1026214571Sdim if (symsize < 1) 1027214571Sdim break; 1028214571Sdim relsize = bfd_get_reloc_upper_bound (is->the_bfd, sec); 1029214571Sdim if (relsize < 1) 1030214571Sdim break; 1031214571Sdim 1032214571Sdim symbols = xmalloc (symsize); 1033214571Sdim symsize = bfd_canonicalize_symtab (is->the_bfd, symbols); 1034214571Sdim if (symsize < 0) 1035214571Sdim { 1036214571Sdim einfo ("%X%P: unable to process symbols: %E"); 1037214571Sdim return; 1038214571Sdim } 1039214571Sdim 1040214571Sdim relocs = xmalloc ((size_t) relsize); 1041214571Sdim nrelocs = bfd_canonicalize_reloc (is->the_bfd, sec, 1042214571Sdim relocs, symbols); 1043214571Sdim if (nrelocs < 0) 1044214571Sdim { 1045214571Sdim free (relocs); 1046214571Sdim einfo ("%X%P: unable to process relocs: %E"); 1047214571Sdim return; 1048214571Sdim } 1049214571Sdim 1050214571Sdim for (i = 0; i < nrelocs; i++) 1051214571Sdim { 1052214571Sdim struct bfd_symbol *s; 1053214571Sdim struct bfd_link_hash_entry * blhe; 1054214571Sdim char *other_bfd_filename; 1055214571Sdim char *n; 1056214571Sdim 1057214571Sdim s = (relocs[i]->sym_ptr_ptr)[0]; 1058214571Sdim 1059214571Sdim if (s->flags & BSF_LOCAL) 1060214571Sdim continue; 1061214571Sdim 1062214571Sdim /* Thunk section with reloc to another bfd. */ 1063214571Sdim blhe = bfd_link_hash_lookup (link_info.hash, 1064214571Sdim s->name, 1065214571Sdim FALSE, FALSE, TRUE); 1066214571Sdim 1067214571Sdim if (blhe == NULL 1068214571Sdim || blhe->type != bfd_link_hash_defined) 1069214571Sdim continue; 1070214571Sdim 1071214571Sdim other_bfd_filename 1072214571Sdim = blhe->u.def.section->owner->my_archive 1073214571Sdim ? bfd_get_filename (blhe->u.def.section->owner->my_archive) 1074214571Sdim : bfd_get_filename (blhe->u.def.section->owner); 1075214571Sdim 1076214571Sdim if (strcmp (bfd_get_filename (is->the_bfd->my_archive), 1077214571Sdim other_bfd_filename) == 0) 1078214571Sdim continue; 1079214571Sdim 1080214571Sdim /* Rename this implib to match the other one. */ 1081214571Sdim n = xmalloc (strlen (other_bfd_filename) + 1); 1082214571Sdim strcpy (n, other_bfd_filename); 1083214571Sdim is->the_bfd->my_archive->filename = n; 1084214571Sdim } 1085214571Sdim 1086214571Sdim free (relocs); 1087214571Sdim /* Note - we do not free the symbols, 1088214571Sdim they are now cached in the BFD. */ 1089214571Sdim } 1090214571Sdim } 1091214571Sdim } 1092214571Sdim } 1093214571Sdim } 1094214571Sdim 1095214571Sdim { 1096214571Sdim int is_ms_arch = 0; 1097214571Sdim bfd *cur_arch = 0; 1098214571Sdim lang_input_statement_type *is2; 1099214571Sdim lang_input_statement_type *is3; 1100214571Sdim 1101214571Sdim /* Careful - this is a shell script. Watch those dollar signs! */ 1102214571Sdim /* Microsoft import libraries have every member named the same, 1103214571Sdim and not in the right order for us to link them correctly. We 1104214571Sdim must detect these and rename the members so that they'll link 1105214571Sdim correctly. There are three types of objects: the head, the 1106214571Sdim thunks, and the sentinel(s). The head is easy; it's the one 1107214571Sdim with idata2. We assume that the sentinels won't have relocs, 1108214571Sdim and the thunks will. It's easier than checking the symbol 1109214571Sdim table for external references. */ 1110214571Sdim LANG_FOR_EACH_INPUT_STATEMENT (is) 1111214571Sdim { 1112214571Sdim if (is->the_bfd->my_archive) 1113214571Sdim { 1114214571Sdim char *pnt; 1115214571Sdim bfd *arch = is->the_bfd->my_archive; 1116214571Sdim 1117214571Sdim if (cur_arch != arch) 1118214571Sdim { 1119214571Sdim cur_arch = arch; 1120214571Sdim is_ms_arch = 1; 1121214571Sdim 1122214571Sdim for (is3 = is; 1123214571Sdim is3 && is3->the_bfd->my_archive == arch; 1124214571Sdim is3 = (lang_input_statement_type *) is3->next) 1125214571Sdim { 1126214571Sdim /* A MS dynamic import library can also contain static 1127214571Sdim members, so look for the first element with a .dll 1128214571Sdim extension, and use that for the remainder of the 1129214571Sdim comparisons. */ 1130214571Sdim pnt = strrchr (is3->the_bfd->filename, '.'); 1131214571Sdim if (pnt != NULL && strcmp (pnt, ".dll") == 0) 1132214571Sdim break; 1133214571Sdim } 1134214571Sdim 1135214571Sdim if (is3 == NULL) 1136214571Sdim is_ms_arch = 0; 1137214571Sdim else 1138214571Sdim { 1139214571Sdim /* OK, found one. Now look to see if the remaining 1140214571Sdim (dynamic import) members use the same name. */ 1141214571Sdim for (is2 = is; 1142214571Sdim is2 && is2->the_bfd->my_archive == arch; 1143214571Sdim is2 = (lang_input_statement_type *) is2->next) 1144214571Sdim { 1145214571Sdim /* Skip static members, ie anything with a .obj 1146214571Sdim extension. */ 1147214571Sdim pnt = strrchr (is2->the_bfd->filename, '.'); 1148214571Sdim if (pnt != NULL && strcmp (pnt, ".obj") == 0) 1149214571Sdim continue; 1150214571Sdim 1151214571Sdim if (strcmp (is3->the_bfd->filename, 1152214571Sdim is2->the_bfd->filename)) 1153214571Sdim { 1154214571Sdim is_ms_arch = 0; 1155214571Sdim break; 1156214571Sdim } 1157214571Sdim } 1158214571Sdim } 1159214571Sdim } 1160214571Sdim 1161214571Sdim /* This fragment might have come from an .obj file in a Microsoft 1162214571Sdim import, and not an actual import record. If this is the case, 1163214571Sdim then leave the filename alone. */ 1164214571Sdim pnt = strrchr (is->the_bfd->filename, '.'); 1165214571Sdim 1166214571Sdim if (is_ms_arch && (strcmp (pnt, ".dll") == 0)) 1167214571Sdim { 1168214571Sdim int idata2 = 0, reloc_count=0; 1169214571Sdim asection *sec; 1170214571Sdim char *new_name, seq; 1171214571Sdim 1172214571Sdim for (sec = is->the_bfd->sections; sec; sec = sec->next) 1173214571Sdim { 1174214571Sdim if (strcmp (sec->name, ".idata\$2") == 0) 1175214571Sdim idata2 = 1; 1176214571Sdim reloc_count += sec->reloc_count; 1177214571Sdim } 1178214571Sdim 1179214571Sdim if (idata2) /* .idata2 is the TOC */ 1180214571Sdim seq = 'a'; 1181214571Sdim else if (reloc_count > 0) /* thunks */ 1182214571Sdim seq = 'b'; 1183214571Sdim else /* sentinel */ 1184214571Sdim seq = 'c'; 1185214571Sdim 1186214571Sdim new_name = xmalloc (strlen (is->the_bfd->filename) + 3); 1187214571Sdim sprintf (new_name, "%s.%c", is->the_bfd->filename, seq); 1188214571Sdim is->the_bfd->filename = new_name; 1189214571Sdim 1190214571Sdim new_name = xmalloc (strlen (is->filename) + 3); 1191214571Sdim sprintf (new_name, "%s.%c", is->filename, seq); 1192214571Sdim is->filename = new_name; 1193214571Sdim } 1194214571Sdim } 1195214571Sdim } 1196214571Sdim } 1197214571Sdim} 1198214571Sdim 1199214571Sdimstatic void 1200214571Sdimgld_${EMULATION_NAME}_before_allocation (void) 1201214571Sdim{ 1202214571Sdim before_allocation_default (); 1203214571Sdim} 1204214571Sdim 1205214571Sdim#ifdef DLL_SUPPORT 1206214571Sdim/* This is called when an input file isn't recognized as a BFD. We 1207214571Sdim check here for .DEF files and pull them in automatically. */ 1208214571Sdim 1209214571Sdimstatic int 1210214571Sdimsaw_option (char *option) 1211214571Sdim{ 1212214571Sdim int i; 1213214571Sdim 1214214571Sdim for (i = 0; init[i].ptr; i++) 1215214571Sdim if (strcmp (init[i].symbol, option) == 0) 1216214571Sdim return init[i].inited; 1217214571Sdim return 0; 1218214571Sdim} 1219214571Sdim#endif /* DLL_SUPPORT */ 1220214571Sdim 1221214571Sdimstatic bfd_boolean 1222214571Sdimgld_${EMULATION_NAME}_unrecognized_file (lang_input_statement_type *entry ATTRIBUTE_UNUSED) 1223214571Sdim{ 1224214571Sdim#ifdef DLL_SUPPORT 1225214571Sdim const char *ext = entry->filename + strlen (entry->filename) - 4; 1226214571Sdim 1227214571Sdim if (strcmp (ext, ".def") == 0 || strcmp (ext, ".DEF") == 0) 1228214571Sdim { 1229214571Sdim pep_def_file = def_file_parse (entry->filename, pep_def_file); 1230214571Sdim 1231214571Sdim if (pep_def_file) 1232214571Sdim { 1233214571Sdim int i, buflen=0, len; 1234214571Sdim char *buf; 1235214571Sdim 1236214571Sdim for (i = 0; i < pep_def_file->num_exports; i++) 1237214571Sdim { 1238214571Sdim len = strlen (pep_def_file->exports[i].internal_name); 1239214571Sdim if (buflen < len + 2) 1240214571Sdim buflen = len + 2; 1241214571Sdim } 1242214571Sdim 1243214571Sdim buf = xmalloc (buflen); 1244214571Sdim 1245214571Sdim for (i = 0; i < pep_def_file->num_exports; i++) 1246214571Sdim { 1247214571Sdim struct bfd_link_hash_entry *h; 1248214571Sdim 1249214571Sdim sprintf (buf, "_%s", pep_def_file->exports[i].internal_name); 1250214571Sdim 1251214571Sdim h = bfd_link_hash_lookup (link_info.hash, buf, TRUE, TRUE, TRUE); 1252214571Sdim if (h == (struct bfd_link_hash_entry *) NULL) 1253214571Sdim einfo (_("%P%F: bfd_link_hash_lookup failed: %E\n")); 1254214571Sdim if (h->type == bfd_link_hash_new) 1255214571Sdim { 1256214571Sdim h->type = bfd_link_hash_undefined; 1257214571Sdim h->u.undef.abfd = NULL; 1258214571Sdim bfd_link_add_undef (link_info.hash, h); 1259214571Sdim } 1260214571Sdim } 1261214571Sdim free (buf); 1262214571Sdim 1263214571Sdim /* def_file_print (stdout, pep_def_file); */ 1264214571Sdim if (pep_def_file->is_dll == 1) 1265214571Sdim link_info.shared = 1; 1266214571Sdim 1267214571Sdim if (pep_def_file->base_address != (bfd_vma)(-1)) 1268214571Sdim { 1269214571Sdim pep.ImageBase = 1270214571Sdim pe_data (output_bfd)->pe_opthdr.ImageBase = 1271214571Sdim init[IMAGEBASEOFF].value = pep_def_file->base_address; 1272214571Sdim init[IMAGEBASEOFF].inited = 1; 1273214571Sdim if (image_base_statement) 1274214571Sdim image_base_statement->exp = 1275214571Sdim exp_assop ('=', "__image_base__", exp_intop (pep.ImageBase)); 1276214571Sdim } 1277214571Sdim 1278214571Sdim if (pep_def_file->stack_reserve != -1 1279214571Sdim && ! saw_option ("__size_of_stack_reserve__")) 1280214571Sdim { 1281214571Sdim pep.SizeOfStackReserve = pep_def_file->stack_reserve; 1282214571Sdim if (pep_def_file->stack_commit != -1) 1283214571Sdim pep.SizeOfStackCommit = pep_def_file->stack_commit; 1284214571Sdim } 1285214571Sdim if (pep_def_file->heap_reserve != -1 1286214571Sdim && ! saw_option ("__size_of_heap_reserve__")) 1287214571Sdim { 1288214571Sdim pep.SizeOfHeapReserve = pep_def_file->heap_reserve; 1289214571Sdim if (pep_def_file->heap_commit != -1) 1290214571Sdim pep.SizeOfHeapCommit = pep_def_file->heap_commit; 1291214571Sdim } 1292214571Sdim return TRUE; 1293214571Sdim } 1294214571Sdim } 1295214571Sdim#endif 1296214571Sdim return FALSE; 1297214571Sdim} 1298214571Sdim 1299214571Sdimstatic bfd_boolean 1300214571Sdimgld_${EMULATION_NAME}_recognized_file (lang_input_statement_type *entry ATTRIBUTE_UNUSED) 1301214571Sdim{ 1302214571Sdim#ifdef DLL_SUPPORT 1303214571Sdim#ifdef TARGET_IS_i386pep 1304214571Sdim pep_dll_id_target ("pei-x86-64"); 1305214571Sdim#endif 1306214571Sdim if (bfd_get_format (entry->the_bfd) == bfd_object) 1307214571Sdim { 1308214571Sdim char fbuf[LD_PATHMAX + 1]; 1309214571Sdim const char *ext; 1310214571Sdim 1311214571Sdim if (REALPATH (entry->filename, fbuf) == NULL) 1312214571Sdim strncpy (fbuf, entry->filename, sizeof (fbuf)); 1313214571Sdim 1314214571Sdim ext = fbuf + strlen (fbuf) - 4; 1315214571Sdim 1316214571Sdim if (strcmp (ext, ".dll") == 0 || strcmp (ext, ".DLL") == 0) 1317214571Sdim return pep_implied_import_dll (fbuf); 1318214571Sdim } 1319214571Sdim#endif 1320214571Sdim return FALSE; 1321214571Sdim} 1322214571Sdim 1323214571Sdimstatic void 1324214571Sdimgld_${EMULATION_NAME}_finish (void) 1325214571Sdim{ 1326214571Sdim finish_default (); 1327214571Sdim 1328214571Sdim#ifdef DLL_SUPPORT 1329214571Sdim if (link_info.shared 1330214571Sdim || (!link_info.relocatable && pep_def_file->num_exports != 0)) 1331214571Sdim { 1332214571Sdim pep_dll_fill_sections (output_bfd, &link_info); 1333214571Sdim if (pep_implib_filename) 1334214571Sdim pep_dll_generate_implib (pep_def_file, pep_implib_filename); 1335214571Sdim } 1336214571Sdim 1337214571Sdim if (pep_out_def_filename) 1338214571Sdim pep_dll_generate_def_file (pep_out_def_filename); 1339214571Sdim#endif /* DLL_SUPPORT */ 1340214571Sdim 1341214571Sdim /* I don't know where .idata gets set as code, but it shouldn't be. */ 1342214571Sdim { 1343214571Sdim asection *asec = bfd_get_section_by_name (output_bfd, ".idata"); 1344214571Sdim 1345214571Sdim if (asec) 1346214571Sdim { 1347214571Sdim asec->flags &= ~SEC_CODE; 1348214571Sdim asec->flags |= SEC_DATA; 1349214571Sdim } 1350214571Sdim } 1351214571Sdim} 1352214571Sdim 1353214571Sdim 1354214571Sdim/* Place an orphan section. 1355214571Sdim 1356214571Sdim We use this to put sections in a reasonable place in the file, and 1357214571Sdim to ensure that they are aligned as required. 1358214571Sdim 1359214571Sdim We handle grouped sections here as well. A section named .foo$nn 1360214571Sdim goes into the output section .foo. All grouped sections are sorted 1361214571Sdim by name. 1362214571Sdim 1363214571Sdim Grouped sections for the default sections are handled by the 1364214571Sdim default linker script using wildcards, and are sorted by 1365214571Sdim sort_sections. */ 1366214571Sdim 1367214571Sdimstatic bfd_boolean 1368214571Sdimgld_${EMULATION_NAME}_place_orphan (asection *s) 1369214571Sdim{ 1370214571Sdim const char *secname; 1371214571Sdim const char *orig_secname; 1372214571Sdim char *dollar = NULL; 1373214571Sdim lang_output_section_statement_type *os; 1374214571Sdim lang_statement_list_type add_child; 1375214571Sdim 1376214571Sdim secname = bfd_get_section_name (s->owner, s); 1377214571Sdim 1378214571Sdim /* Look through the script to see where to place this section. */ 1379214571Sdim orig_secname = secname; 1380214571Sdim if (!link_info.relocatable 1381214571Sdim && (dollar = strchr (secname, '$')) != NULL) 1382214571Sdim { 1383214571Sdim size_t len = dollar - orig_secname; 1384214571Sdim char *newname = xmalloc (len + 1); 1385214571Sdim memcpy (newname, orig_secname, len); 1386214571Sdim newname[len] = '\0'; 1387214571Sdim secname = newname; 1388214571Sdim } 1389214571Sdim 1390214571Sdim os = lang_output_section_find (secname); 1391214571Sdim 1392214571Sdim lang_list_init (&add_child); 1393214571Sdim 1394214571Sdim if (os != NULL 1395214571Sdim && (os->bfd_section == NULL 1396214571Sdim || os->bfd_section->flags == 0 1397214571Sdim || ((s->flags ^ os->bfd_section->flags) 1398214571Sdim & (SEC_LOAD | SEC_ALLOC)) == 0)) 1399214571Sdim { 1400214571Sdim /* We already have an output section statement with this 1401214571Sdim name, and its bfd section, if any, has compatible flags. 1402214571Sdim If the section already exists but does not have any flags set, 1403214571Sdim then it has been created by the linker, probably as a result of 1404214571Sdim a --section-start command line switch. */ 1405214571Sdim lang_add_section (&add_child, s, os); 1406214571Sdim } 1407214571Sdim else 1408214571Sdim { 1409214571Sdim static struct orphan_save hold[] = 1410214571Sdim { 1411214571Sdim { ".text", 1412214571Sdim SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_CODE, 1413214571Sdim 0, 0, 0, 0 }, 1414214571Sdim { ".rdata", 1415214571Sdim SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_DATA, 1416214571Sdim 0, 0, 0, 0 }, 1417214571Sdim { ".data", 1418214571Sdim SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_DATA, 1419214571Sdim 0, 0, 0, 0 }, 1420214571Sdim { ".bss", 1421214571Sdim SEC_ALLOC, 1422214571Sdim 0, 0, 0, 0 } 1423214571Sdim }; 1424214571Sdim enum orphan_save_index 1425214571Sdim { 1426214571Sdim orphan_text = 0, 1427214571Sdim orphan_rodata, 1428214571Sdim orphan_data, 1429214571Sdim orphan_bss 1430214571Sdim }; 1431214571Sdim static int orphan_init_done = 0; 1432214571Sdim struct orphan_save *place; 1433214571Sdim lang_output_section_statement_type *after; 1434214571Sdim etree_type *address; 1435214571Sdim 1436214571Sdim if (!orphan_init_done) 1437214571Sdim { 1438214571Sdim struct orphan_save *ho; 1439214571Sdim for (ho = hold; ho < hold + sizeof (hold) / sizeof (hold[0]); ++ho) 1440214571Sdim if (ho->name != NULL) 1441214571Sdim { 1442214571Sdim ho->os = lang_output_section_find (ho->name); 1443214571Sdim if (ho->os != NULL && ho->os->flags == 0) 1444214571Sdim ho->os->flags = ho->flags; 1445214571Sdim } 1446214571Sdim orphan_init_done = 1; 1447214571Sdim } 1448214571Sdim 1449214571Sdim /* Try to put the new output section in a reasonable place based 1450214571Sdim on the section name and section flags. */ 1451214571Sdim 1452214571Sdim place = NULL; 1453214571Sdim if ((s->flags & SEC_ALLOC) == 0) 1454214571Sdim ; 1455214571Sdim else if ((s->flags & (SEC_LOAD | SEC_HAS_CONTENTS)) == 0) 1456214571Sdim place = &hold[orphan_bss]; 1457214571Sdim else if ((s->flags & SEC_READONLY) == 0) 1458214571Sdim place = &hold[orphan_data]; 1459214571Sdim else if ((s->flags & SEC_CODE) == 0) 1460214571Sdim place = &hold[orphan_rodata]; 1461214571Sdim else 1462214571Sdim place = &hold[orphan_text]; 1463214571Sdim 1464214571Sdim after = NULL; 1465214571Sdim if (place != NULL) 1466214571Sdim { 1467214571Sdim if (place->os == NULL) 1468214571Sdim place->os = lang_output_section_find (place->name); 1469214571Sdim after = place->os; 1470214571Sdim if (after == NULL) 1471214571Sdim after = lang_output_section_find_by_flags (s, &place->os, NULL); 1472214571Sdim if (after == NULL) 1473214571Sdim /* *ABS* is always the first output section statement. */ 1474214571Sdim after = (&lang_output_section_statement.head 1475214571Sdim ->output_section_statement); 1476214571Sdim } 1477214571Sdim 1478214571Sdim /* Choose a unique name for the section. This will be needed if the 1479214571Sdim same section name appears in the input file with different 1480214571Sdim loadable or allocatable characteristics. */ 1481214571Sdim if (bfd_get_section_by_name (output_bfd, secname) != NULL) 1482214571Sdim { 1483214571Sdim static int count = 1; 1484214571Sdim secname = bfd_get_unique_section_name (output_bfd, secname, &count); 1485214571Sdim if (secname == NULL) 1486214571Sdim einfo ("%F%P: place_orphan failed: %E\n"); 1487214571Sdim } 1488214571Sdim 1489214571Sdim /* All sections in an executable must be aligned to a page boundary. */ 1490214571Sdim address = exp_unop (ALIGN_K, exp_nameop (NAME, "__section_alignment__")); 1491214571Sdim os = lang_insert_orphan (s, secname, after, place, address, &add_child); 1492214571Sdim } 1493214571Sdim 1494214571Sdim { 1495214571Sdim lang_statement_union_type **pl = &os->children.head; 1496214571Sdim 1497214571Sdim if (dollar != NULL) 1498214571Sdim { 1499214571Sdim bfd_boolean found_dollar; 1500214571Sdim 1501214571Sdim /* The section name has a '$'. Sort it with the other '$' 1502214571Sdim sections. */ 1503214571Sdim found_dollar = FALSE; 1504214571Sdim for ( ; *pl != NULL; pl = &(*pl)->header.next) 1505214571Sdim { 1506214571Sdim lang_input_section_type *ls; 1507214571Sdim const char *lname; 1508214571Sdim 1509214571Sdim if ((*pl)->header.type != lang_input_section_enum) 1510214571Sdim continue; 1511214571Sdim 1512214571Sdim ls = &(*pl)->input_section; 1513214571Sdim 1514214571Sdim lname = bfd_get_section_name (ls->section->owner, ls->section); 1515214571Sdim if (strchr (lname, '$') == NULL) 1516214571Sdim { 1517214571Sdim if (found_dollar) 1518214571Sdim break; 1519214571Sdim } 1520214571Sdim else 1521214571Sdim { 1522214571Sdim found_dollar = TRUE; 1523214571Sdim if (strcmp (orig_secname, lname) < 0) 1524214571Sdim break; 1525214571Sdim } 1526214571Sdim } 1527214571Sdim } 1528214571Sdim 1529214571Sdim if (add_child.head != NULL) 1530214571Sdim { 1531214571Sdim add_child.head->header.next = *pl; 1532214571Sdim *pl = add_child.head; 1533214571Sdim } 1534214571Sdim } 1535214571Sdim 1536214571Sdim return TRUE; 1537214571Sdim} 1538214571Sdim 1539214571Sdimstatic bfd_boolean 1540214571Sdimgld_${EMULATION_NAME}_open_dynamic_archive 1541214571Sdim (const char *arch ATTRIBUTE_UNUSED, 1542214571Sdim search_dirs_type *search, 1543214571Sdim lang_input_statement_type *entry) 1544214571Sdim{ 1545214571Sdim static const struct 1546214571Sdim { 1547214571Sdim const char * format; 1548214571Sdim bfd_boolean use_prefix; 1549214571Sdim } 1550214571Sdim libname_fmt [] = 1551214571Sdim { 1552214571Sdim /* Preferred explicit import library for dll's. */ 1553214571Sdim { "lib%s.dll.a", FALSE }, 1554214571Sdim /* Alternate explicit import library for dll's. */ 1555214571Sdim { "%s.dll.a", FALSE }, 1556214571Sdim /* "libfoo.a" could be either an import lib or a static lib. 1557214571Sdim For backwards compatibility, libfoo.a needs to precede 1558214571Sdim libfoo.dll and foo.dll in the search. */ 1559214571Sdim { "lib%s.a", FALSE }, 1560214571Sdim /* The 'native' spelling of an import lib name is "foo.lib". */ 1561214571Sdim { "%s.lib", FALSE }, 1562214571Sdim#ifdef DLL_SUPPORT 1563214571Sdim /* Try "<prefix>foo.dll" (preferred dll name, if specified). */ 1564214571Sdim { "%s%s.dll", TRUE }, 1565214571Sdim#endif 1566214571Sdim /* Try "libfoo.dll" (default preferred dll name). */ 1567214571Sdim { "lib%s.dll", FALSE }, 1568214571Sdim /* Finally try 'native' dll name "foo.dll". */ 1569214571Sdim { "%s.dll", FALSE }, 1570214571Sdim /* Note: If adding more formats to this table, make sure to check to 1571214571Sdim see if their length is longer than libname_fmt[0].format, and if 1572214571Sdim so, update the call to xmalloc() below. */ 1573214571Sdim { NULL, FALSE } 1574214571Sdim }; 1575214571Sdim static unsigned int format_max_len = 0; 1576214571Sdim const char * filename; 1577214571Sdim char * full_string; 1578214571Sdim char * base_string; 1579214571Sdim unsigned int i; 1580214571Sdim 1581214571Sdim 1582214571Sdim if (! entry->is_archive) 1583214571Sdim return FALSE; 1584214571Sdim 1585214571Sdim filename = entry->filename; 1586214571Sdim 1587214571Sdim if (format_max_len == 0) 1588214571Sdim /* We need to allow space in the memory that we are going to allocate 1589214571Sdim for the characters in the format string. Since the format array is 1590214571Sdim static we only need to calculate this information once. In theory 1591214571Sdim this value could also be computed statically, but this introduces 1592214571Sdim the possibility for a discrepancy and hence a possible memory 1593214571Sdim corruption. The lengths we compute here will be too long because 1594214571Sdim they will include any formating characters (%s) in the strings, but 1595214571Sdim this will not matter. */ 1596214571Sdim for (i = 0; libname_fmt[i].format; i++) 1597214571Sdim if (format_max_len < strlen (libname_fmt[i].format)) 1598214571Sdim format_max_len = strlen (libname_fmt[i].format); 1599214571Sdim 1600214571Sdim full_string = xmalloc (strlen (search->name) 1601214571Sdim + strlen (filename) 1602214571Sdim + format_max_len 1603214571Sdim#ifdef DLL_SUPPORT 1604214571Sdim + (pep_dll_search_prefix 1605214571Sdim ? strlen (pep_dll_search_prefix) : 0) 1606214571Sdim#endif 1607214571Sdim /* Allow for the terminating NUL and for the path 1608214571Sdim separator character that is inserted between 1609214571Sdim search->name and the start of the format string. */ 1610214571Sdim + 2); 1611214571Sdim 1612214571Sdim sprintf (full_string, "%s/", search->name); 1613214571Sdim base_string = full_string + strlen (full_string); 1614214571Sdim 1615214571Sdim for (i = 0; libname_fmt[i].format; i++) 1616214571Sdim { 1617214571Sdim#ifdef DLL_SUPPORT 1618214571Sdim if (libname_fmt[i].use_prefix) 1619214571Sdim { 1620214571Sdim if (!pep_dll_search_prefix) 1621214571Sdim continue; 1622214571Sdim sprintf (base_string, libname_fmt[i].format, pep_dll_search_prefix, filename); 1623214571Sdim } 1624214571Sdim else 1625214571Sdim#endif 1626214571Sdim sprintf (base_string, libname_fmt[i].format, filename); 1627214571Sdim 1628214571Sdim if (ldfile_try_open_bfd (full_string, entry)) 1629214571Sdim break; 1630214571Sdim } 1631214571Sdim 1632214571Sdim if (!libname_fmt[i].format) 1633214571Sdim { 1634214571Sdim free (full_string); 1635214571Sdim return FALSE; 1636214571Sdim } 1637214571Sdim 1638214571Sdim entry->filename = full_string; 1639214571Sdim 1640214571Sdim return TRUE; 1641214571Sdim} 1642214571Sdim 1643214571Sdimstatic int 1644214571Sdimgld_${EMULATION_NAME}_find_potential_libraries 1645214571Sdim (char *name, lang_input_statement_type *entry) 1646214571Sdim{ 1647214571Sdim return ldfile_open_file_search (name, entry, "", ".lib"); 1648214571Sdim} 1649214571Sdim 1650214571Sdimstatic char * 1651214571Sdimgld_${EMULATION_NAME}_get_script (int *isfile) 1652214571SdimEOF 1653214571Sdim# Scripts compiled in. 1654214571Sdim# sed commands to quote an ld script as a C string. 1655214571Sdimsc="-f stringify.sed" 1656214571Sdim 1657214571Sdimcat >>e${EMULATION_NAME}.c <<EOF 1658214571Sdim{ 1659214571Sdim *isfile = 0; 1660214571Sdim 1661214571Sdim if (link_info.relocatable && config.build_constructors) 1662214571Sdim return 1663214571SdimEOF 1664214571Sdimsed $sc ldscripts/${EMULATION_NAME}.xu >> e${EMULATION_NAME}.c 1665214571Sdimecho ' ; else if (link_info.relocatable) return' >> e${EMULATION_NAME}.c 1666214571Sdimsed $sc ldscripts/${EMULATION_NAME}.xr >> e${EMULATION_NAME}.c 1667214571Sdimecho ' ; else if (!config.text_read_only) return' >> e${EMULATION_NAME}.c 1668214571Sdimsed $sc ldscripts/${EMULATION_NAME}.xbn >> e${EMULATION_NAME}.c 1669214571Sdimecho ' ; else if (!config.magic_demand_paged) return' >> e${EMULATION_NAME}.c 1670214571Sdimsed $sc ldscripts/${EMULATION_NAME}.xn >> e${EMULATION_NAME}.c 1671214571Sdimecho ' ; else return' >> e${EMULATION_NAME}.c 1672214571Sdimsed $sc ldscripts/${EMULATION_NAME}.x >> e${EMULATION_NAME}.c 1673214571Sdimecho '; }' >> e${EMULATION_NAME}.c 1674214571Sdim 1675214571Sdimcat >>e${EMULATION_NAME}.c <<EOF 1676214571Sdim 1677214571Sdim 1678214571Sdimstruct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation = 1679214571Sdim{ 1680214571Sdim gld_${EMULATION_NAME}_before_parse, 1681214571Sdim syslib_default, 1682214571Sdim hll_default, 1683214571Sdim gld_${EMULATION_NAME}_after_parse, 1684214571Sdim gld_${EMULATION_NAME}_after_open, 1685214571Sdim after_allocation_default, 1686214571Sdim set_output_arch_default, 1687214571Sdim ldemul_default_target, 1688214571Sdim gld_${EMULATION_NAME}_before_allocation, 1689214571Sdim gld_${EMULATION_NAME}_get_script, 1690214571Sdim "${EMULATION_NAME}", 1691214571Sdim "${OUTPUT_FORMAT}", 1692214571Sdim gld_${EMULATION_NAME}_finish, 1693214571Sdim NULL, /* Create output section statements. */ 1694214571Sdim gld_${EMULATION_NAME}_open_dynamic_archive, 1695214571Sdim gld_${EMULATION_NAME}_place_orphan, 1696214571Sdim gld_${EMULATION_NAME}_set_symbols, 1697214571Sdim NULL, /* parse_args */ 1698214571Sdim gld${EMULATION_NAME}_add_options, 1699214571Sdim gld${EMULATION_NAME}_handle_option, 1700214571Sdim gld_${EMULATION_NAME}_unrecognized_file, 1701214571Sdim gld_${EMULATION_NAME}_list_options, 1702214571Sdim gld_${EMULATION_NAME}_recognized_file, 1703214571Sdim gld_${EMULATION_NAME}_find_potential_libraries, 1704214571Sdim NULL /* new_vers_pattern. */ 1705214571Sdim}; 1706214571SdimEOF 1707