diff --ru --new-file a/ld/ldfile.c b/ld/ldfile.c --- a/ld/ldfile.c 2014-07-03 01:37:48.000000000 -0400 +++ b/ld/ldfile.c 2019-08-17 11:38:31.062209027 -0400 @@ -122,6 +122,16 @@ bfd_boolean ldfile_try_open_bfd (const char *attempt, lang_input_statement_type *entry) { + +#ifdef PE_TARGET_MDSO + if (!entry->flags.dynamic) { + (void)0; + } else if (!(attempt = pe_mdso_input_name(attempt))) { + fprintf(stderr,"%s: pe_mdso_input_name() returned an error.\n",program_name); + xexit(EXIT_FAILURE); + } +#endif + entry->the_bfd = bfd_openr (attempt, entry->target); if (verbose) diff -ru --new-file a/ld/configure b/ld/configure --- a/ld/configure 2014-07-03 01:37:48.000000000 -0400 +++ b/ld/configure 2015-03-11 20:01:08.888756786 -0400 @@ -19773,3 +19773,31 @@ $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} fi +sed -i -e 's/@pe_executable_name@/'"$PE_EXECUTABLE_NAME"'/g' Makefile +sed -i -e 's/@pe_framework_libs@/'"$PE_FRAMEWORK_LIBS"'/g' Makefile +sed -i -e 's/@pe_crt_section@/'"$PE_CRT_SECTION"'/g' Makefile +sed -i -e 's/@pe_cygwin_fork_support@/'"$PE_CYGWIN_FORK_SUPPORT"'/g' Makefile + +#PE custom import library support +if [ -f peimplib.h ]; then + echo 'build directory is not clean (peimplib.h already exists)' + exit 2 +fi + +touch peimplib.h || exit 2 + +case $target_os in + *midipix*) + cat >> peimplib.h << EOF +/* PE target-specific bits, generated by ld/configure */ +#ifndef PE_TARGET_MIDIPIX +#define PE_TARGET_MIDIPIX +#endif + +#ifndef PE_TARGET_MDSO +#define PE_TARGET_MDSO 1 +#endif + +#include "pe-mdso.h" +EOF +esac diff --ru --new-file a/ld/sysdep.h b/ld/sysdep.h --- a/ld/sysdep.h 2014-07-03 01:37:48.000000000 -0400 +++ b/ld/sysdep.h 2019-08-16 03:08:47.771929753 -0400 @@ -26,6 +26,7 @@ #endif #include "config.h" +#include "peimplib.h" #include #include diff -ru --new-file a/ld/emultempl/pe.em b/ld/emultempl/pe.em --- a/ld/emultempl/pe.em 2014-07-03 01:37:48.000000000 -0400 +++ b/ld/emultempl/pe.em 2019-08-17 11:38:31.062209027 -0400 @@ -69,6 +69,14 @@ fragment < When linking dynamically to a dll without\n\ - an importlib, use .dll\n\ - in preference to lib.dll \n")); + an importlib, use "PE_DSO_SUFFIX"\n\ + in preference to lib"PE_DSO_SUFFIX" \n")); fprintf (file, _(" --enable-auto-import Do sophisticated linking of _sym to\n\ __imp_sym for DATA references\n")); fprintf (file, _(" --disable-auto-import Do not auto-import DATA items from DLLs\n")); @@ -808,6 +822,12 @@ gld${EMULATION_NAME}_handle_option (int optc) case OPTION_IMPLIB_FILENAME: pe_implib_filename = xstrdup (optarg); break; + case OPTION_DSOLIB_FILENAME: + pe_dsolib_filename = xstrdup (optarg); + break; + case OPTION_DSOLIB_LOADER_PATH: + pe_dsolib_loader_path = xstrdup (optarg); + break; case OPTION_WARN_DUPLICATE_EXPORTS: pe_dll_warn_dup_exports = 1; break; @@ -1698,7 +1718,7 @@ gld_${EMULATION_NAME}_after_open (void) extension, and use that for the remainder of the comparisons. */ pnt = strrchr (is3->the_bfd->filename, '.'); - if (pnt != NULL && filename_cmp (pnt, ".dll") == 0) + if (pnt != NULL && filename_cmp (pnt, PE_DSO_SUFFIX) == 0) break; } @@ -1733,7 +1753,7 @@ gld_${EMULATION_NAME}_after_open (void) then leave the filename alone. */ pnt = strrchr (is->the_bfd->filename, '.'); - if (is_ms_arch && (filename_cmp (pnt, ".dll") == 0)) + if (is_ms_arch && (filename_cmp (pnt, PE_DSO_SUFFIX) == 0)) { int idata2 = 0, reloc_count=0; asection *sec; @@ -2063,8 +2083,14 @@ gld_${EMULATION_NAME}_finish (void) ) { pe_dll_fill_sections (link_info.output_bfd, &link_info); + + /* generate legacy implib? */ if (pe_implib_filename) pe_dll_generate_implib (pe_def_file, pe_implib_filename, &link_info); + + /* generate mdso implib? */ + if (pe_dsolib_filename) + pe_dll_generate_dsolib (pe_def_file, 0, pe_dsolib_filename, pe_dsolib_loader_path, 32); } #if defined(TARGET_IS_shpe) /* ARM doesn't need relocs. */ @@ -2298,16 +2324,25 @@ gld_${EMULATION_NAME}_open_dynamic_archive } libname_fmt [] = { + /* optionally support ldso-specific import libraries */ + #ifdef PE_TARGET_MDSO + { "lib%s"PE_DSOLIB_SUFFIX, FALSE }, + #endif /* Preferred explicit import library for dll's. */ - { "lib%s.dll.a", FALSE }, + { "lib%s"PE_IMPLIB_SUFFIX, FALSE }, /* Alternate explicit import library for dll's. */ - { "%s.dll.a", FALSE }, + { "%s"PE_IMPLIB_SUFFIX, FALSE }, +#ifdef PE_TARGET_MDSO + /* libfoo.so precedes libfoo.a, generate mdso implib as needed */ + { "lib%s"PE_DSO_SUFFIX, FALSE }, +#endif /* "libfoo.a" could be either an import lib or a static lib. For backwards compatibility, libfoo.a needs to precede libfoo.dll and foo.dll in the search. */ { "lib%s.a", FALSE }, /* The 'native' spelling of an import lib name is "foo.lib". */ { "%s.lib", FALSE }, +#ifndef PE_TARGET_MDSO #ifdef DLL_SUPPORT /* Try "foo.dll" (preferred dll name, if specified). */ { "%s%s.dll", TRUE }, @@ -2316,6 +2351,7 @@ gld_${EMULATION_NAME}_open_dynamic_archive { "lib%s.dll", FALSE }, /* Finally try 'native' dll name "foo.dll". */ { "%s.dll", FALSE }, +#endif /* Note: If adding more formats to this table, make sure to check to see if their length is longer than libname_fmt[0].format, and if so, update the call to xmalloc() below. */ diff -ru --new-file a/ld/emultempl/pep.em b/ld/emultempl/pep.em --- a/ld/emultempl/pep.em 2014-07-03 01:37:48.000000000 -0400 +++ b/ld/emultempl/pep.em 2019-08-17 11:38:31.062209027 -0400 @@ -67,6 +67,14 @@ fragment < When linking dynamically to a dll without\n\ - an importlib, use .dll\n\ - in preference to lib.dll \n")); + an importlib, use "PE_DSO_SUFFIX"\n\ + in preference to lib"PE_DSO_SUFFIX" \n")); fprintf (file, _(" --enable-auto-import Do sophisticated linking of _sym to\n\ __imp_sym for DATA references\n")); fprintf (file, _(" --disable-auto-import Do not auto-import DATA items from DLLs\n")); @@ -760,6 +774,12 @@ gld${EMULATION_NAME}_handle_option (int optc) case OPTION_IMPLIB_FILENAME: pep_implib_filename = xstrdup (optarg); break; + case OPTION_DSOLIB_FILENAME: + pep_dsolib_filename = xstrdup (optarg); + break; + case OPTION_DSOLIB_LOADER_PATH: + pep_dsolib_loader_path = xstrdup (optarg); + break; case OPTION_WARN_DUPLICATE_EXPORTS: pep_dll_warn_dup_exports = 1; break; @@ -1635,7 +1655,7 @@ gld_${EMULATION_NAME}_after_open (void) extension, and use that for the remainder of the comparisons. */ pnt = strrchr (is3->the_bfd->filename, '.'); - if (pnt != NULL && filename_cmp (pnt, ".dll") == 0) + if (pnt != NULL && filename_cmp (pnt, PE_DSO_SUFFIX) == 0) break; } @@ -1670,7 +1690,7 @@ gld_${EMULATION_NAME}_after_open (void) then leave the filename alone. */ pnt = strrchr (is->the_bfd->filename, '.'); - if (is_ms_arch && (filename_cmp (pnt, ".dll") == 0)) + if (is_ms_arch && (filename_cmp (pnt, PE_DSO_SUFFIX) == 0)) { int idata2 = 0, reloc_count=0; asection *sec; @@ -1834,8 +1854,14 @@ gld_${EMULATION_NAME}_finish (void) || (!link_info.relocatable && pep_def_file->num_exports != 0)) { pep_dll_fill_sections (link_info.output_bfd, &link_info); + + /* generate legacy implib? */ if (pep_implib_filename) pep_dll_generate_implib (pep_def_file, pep_implib_filename, &link_info); + + /* generate mdso implib? */ + if (pep_dsolib_filename) + pep_dll_generate_dsolib (pep_def_file, 0, pep_dsolib_filename, pep_dsolib_loader_path, 64); } if (pep_out_def_filename) @@ -2062,16 +2088,25 @@ gld_${EMULATION_NAME}_open_dynamic_archive } libname_fmt [] = { + /* optionally support ldso-specific import libraries */ +#ifdef PE_TARGET_MDSO + { "lib%s"PE_DSOLIB_SUFFIX, FALSE }, +#endif /* Preferred explicit import library for dll's. */ - { "lib%s.dll.a", FALSE }, + { "lib%s"PE_IMPLIB_SUFFIX, FALSE }, /* Alternate explicit import library for dll's. */ - { "%s.dll.a", FALSE }, + { "%s"PE_IMPLIB_SUFFIX, FALSE }, +#ifdef PE_TARGET_MDSO + /* libfoo.so precedes libfoo.a, generate mdso implib as needed */ + { "lib%s"PE_DSO_SUFFIX, FALSE }, +#endif /* "libfoo.a" could be either an import lib or a static lib. For backwards compatibility, libfoo.a needs to precede libfoo.dll and foo.dll in the search. */ { "lib%s.a", FALSE }, /* The 'native' spelling of an import lib name is "foo.lib". */ { "%s.lib", FALSE }, +#ifndef PE_TARGET_MDSO #ifdef DLL_SUPPORT /* Try "foo.dll" (preferred dll name, if specified). */ { "%s%s.dll", TRUE }, @@ -2080,6 +2115,7 @@ gld_${EMULATION_NAME}_open_dynamic_archive { "lib%s.dll", FALSE }, /* Finally try 'native' dll name "foo.dll". */ { "%s.dll", FALSE }, +#endif /* Note: If adding more formats to this table, make sure to check to see if their length is longer than libname_fmt[0].format, and if so, update the call to xmalloc() below. */ diff -ru --new-file a/ld/configure.tgt b/ld/configure.tgt --- a/ld/configure.tgt 2014-07-03 01:37:48.000000000 -0400 +++ b/ld/configure.tgt 2019-08-15 06:52:04.192983142 -0400 @@ -319,6 +319,12 @@ test "$targ" != "$host" && LIB_PATH='${tooldir}/lib/w32api' ;; i[3-7]86-*-mingw32*) targ_emul=i386pe ; targ_extra_ofiles="deffilep.o pe-dll.o" ;; +i[3-7]86-*-midipix*) targ_emul=i386pe ; + targ_extra_ofiles="deffilep.o pe-dll.o pe-mdso.o" ; + PE_FRAMEWORK_LIBS="-lperk -lmdso" ; + PE_EXECUTABLE_NAME=a.out ; + PE_CRT_SECTION=no ; + PE_CYGWIN_FORK_SUPPORT=no ;; x86_64-*-pe | x86_64-*-pep) targ_emul=i386pep ; targ_extra_emuls=i386pe ; targ_extra_ofiles="deffilep.o pep-dll.o pe-dll.o" ;; @@ -329,7 +335,14 @@ x86_64-*-mingw*) targ_emul=i386pep ; targ_extra_emuls=i386pe targ_extra_ofiles="deffilep.o pep-dll.o pe-dll.o" ;; -i[3-7]86-*-interix*) targ_emul=i386pe_posix; +x86_64-*-midipix*) targ_emul=i386pep ; + targ_extra_emuls=i386pe ; + targ_extra_ofiles="deffilep.o pep-dll.o pe-dll.o pe-mdso.o" ; + PE_FRAMEWORK_LIBS="-lperk -lmdso" ; + PE_EXECUTABLE_NAME=a.out ; + PE_CRT_SECTION=no ; + PE_CYGWIN_FORK_SUPPORT=no ;; +i[3-7]86-*-interix*) targ_emul=i386pe_posix ; targ_extra_ofiles="deffilep.o pe-dll.o" ;; i[3-7]86-*-beospe*) targ_emul=i386beos ;; i[3-7]86-*-beos*) targ_emul=elf_i386_be ;; @@ -825,6 +838,10 @@ *-*-linux*) ;; +*-*-midipix*) + NATIVE_LIB_DIRS= + ;; + *-*-netbsd*) ;; diff -ru --new-file a/ld/Makefile.in b/ld/Makefile.in --- a/ld/Makefile.in 2014-07-03 01:37:48.000000000 -0400 +++ b/ld/Makefile.in 2019-08-15 05:53:23.807970635 -0400 @@ -54,6 +54,10 @@ host_triplet = @host@ target_triplet = @target@ bin_PROGRAMS = ld-new$(EXEEXT) +PE_EXECUTABLE_NAME = @pe_executable_name@ +PE_FRAMEWORK_LIBS = @pe_framework_libs@ +PE_CRT_SECTION = @pe_crt_section@ +PE_CYGWIN_FORK_SUPPORT = @pe_cygwin_fork_support@ # Automake 1.9 will only build info files in the objdir if they are # mentioned in DISTCLEANFILES. It doesn't have to be unconditional, @@ -831,7 +835,7 @@ POTFILES = $(CFILES) $(HFILES) $(EMULATION_FILES) # These all start with e so 'make clean' can find them. -GENSCRIPTS = LIB_PATH='${LIB_PATH}' $(SHELL) $(srcdir)/genscripts.sh "${srcdir}" "${libdir}" "${prefix}" "${exec_prefix}" @host@ @target@ @target_alias@ "@EMULATION_LIBPATH@" "@NATIVE_LIB_DIRS@" @use_sysroot@ @enable_initfini_array@ +GENSCRIPTS = EXECUTABLE_NAME='${PE_EXECUTABLE_NAME}' PE_FRAMEWORK_LIBS='${PE_FRAMEWORK_LIBS}' PE_CRT_SECTION='${PE_CRT_SECTION}' PE_CYGWIN_FORK_SUPPORT='${PE_CYGWIN_FORK_SUPPORT}' LIB_PATH='${LIB_PATH}' $(SHELL) $(srcdir)/genscripts.sh "${srcdir}" "${libdir}" "${prefix}" "${exec_prefix}" @host@ @target@ @target_alias@ "@EMULATION_LIBPATH@" "@NATIVE_LIB_DIRS@" @use_sysroot@ @enable_initfini_array@ GEN_DEPENDS = $(srcdir)/genscripts.sh stringify.sed ELF_DEPS = $(srcdir)/emultempl/elf32.em $(srcdir)/emultempl/elf-generic.em $(srcdir)/scripttempl/DWARF.sc ELF_GEN_DEPS = $(srcdir)/emultempl/generic.em $(srcdir)/emultempl/elf-generic.em $(srcdir)/emultempl/genelf.em $(srcdir)/scripttempl/DWARF.sc @@ -1032,7 +1036,7 @@ else :; fi ld-new$(EXEEXT): $(ld_new_OBJECTS) $(ld_new_DEPENDENCIES) @rm -f ld-new$(EXEEXT) - $(LINK) $(ld_new_OBJECTS) $(ld_new_LDADD) $(LIBS) + $(LINK) $(ld_new_OBJECTS) $(ld_new_LDADD) $(LIBS) $(PE_FRAMEWORK_LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) @@ -3411,16 +3415,16 @@ ld-partial.@OBJEXT@: ld-new$(EXEEXT) ./ld-new$(EXEEXT) $(HOSTING_EMU) -o ld-partial.@OBJEXT@ -r $(OFILES) ld1$(EXEEXT): ld-partial.@OBJEXT@ - ./ld-new$(EXEEXT) $(HOSTING_EMU) -o ld1$(EXEEXT) $(HOSTING_CRT0) ld-partial.@OBJEXT@ $(TESTBFDLIB) $(LIBIBERTY) $(HOSTING_LIBS) $(LIBS) + ./ld-new$(EXEEXT) $(HOSTING_EMU) -o ld1$(EXEEXT) $(HOSTING_CRT0) ld-partial.@OBJEXT@ $(TESTBFDLIB) $(LIBIBERTY) $(HOSTING_LIBS) $(LIBS) $(PE_FRAMEWORK_LIBS) ld1-full$(EXEEXT): ld-new - ./ld-new$(EXEEXT) $(HOSTING_EMU) -o ld1-full$(EXEEXT) $(HOSTING_CRT0) $(OFILES) $(TESTBFDLIB) $(LIBIBERTY) $(HOSTING_LIBS) $(LIBS) + ./ld-new$(EXEEXT) $(HOSTING_EMU) -o ld1-full$(EXEEXT) $(HOSTING_CRT0) $(OFILES) $(TESTBFDLIB) $(LIBIBERTY) $(HOSTING_LIBS) $(LIBS) $(PE_FRAMEWORK_LIBS) ld2$(EXEEXT): ld1$(EXEEXT) - ./ld1$(EXEEXT) $(HOSTING_EMU) -o ld2$(EXEEXT) $(HOSTING_CRT0) $(OFILES) $(TESTBFDLIB) $(LIBIBERTY) $(HOSTING_LIBS) $(LIBS) + ./ld1$(EXEEXT) $(HOSTING_EMU) -o ld2$(EXEEXT) $(HOSTING_CRT0) $(OFILES) $(TESTBFDLIB) $(LIBIBERTY) $(HOSTING_LIBS) $(LIBS) $(PE_FRAMEWORK_LIBS) ld3$(EXEEXT): ld2$(EXEEXT) - ./ld2$(EXEEXT) $(HOSTING_EMU) -o ld3$(EXEEXT) $(HOSTING_CRT0) $(OFILES) $(TESTBFDLIB) $(LIBIBERTY) $(HOSTING_LIBS) $(LIBS) + ./ld2$(EXEEXT) $(HOSTING_EMU) -o ld3$(EXEEXT) $(HOSTING_CRT0) $(OFILES) $(TESTBFDLIB) $(LIBIBERTY) $(HOSTING_LIBS) $(LIBS) $(PE_FRAMEWORK_LIBS) bootstrap: ld3$(EXEEXT) cmp ld2$(EXEEXT) ld3$(EXEEXT) diff -ru --new-file a/ld/scripttempl/pep.sc b/ld/scripttempl/pep.sc --- a/ld/scripttempl/pep.sc 2014-07-03 01:37:48.000000000 -0400 +++ b/ld/scripttempl/pep.sc 2015-03-11 20:10:05.324773952 -0400 @@ -92,12 +92,17 @@ ${RELOCATING+ *(.gcc_except_table)} } +EOF +if [ x"$PE_CYGWIN_FORK_SUPPORT" != xno ]; then cat << EOF /* The Cygwin32 library uses a section to avoid copying certain data on fork. This used to be named ".data$nocopy". The linker used to include this between __data_start__ and __data_end__, but that breaks building the cygwin32 dll. Instead, we name the section ".data_cygwin_nocopy" and explicitly include it after __data_end__. */ +EOF +fi +cat << EOF .data ${RELOCATING+BLOCK(__section_alignment__)} : { ${RELOCATING+__data_start__ = . ;} @@ -106,7 +111,12 @@ ${R_DATA} *(.jcr) ${RELOCATING+__data_end__ = . ;} +EOF +if [ x"$PE_CYGWIN_FORK_SUPPORT" != xno ]; then cat << EOF ${RELOCATING+*(.data_cygwin_nocopy)} +EOF +fi +cat << EOF } .rdata ${RELOCATING+BLOCK(__section_alignment__)} : @@ -170,6 +180,8 @@ ${RELOCATING+__IAT_end__ = .;} ${R_IDATA67} } +EOF +if [ x"$PE_CRT_SECTION" != xno ]; then cat << EOF .CRT ${RELOCATING+BLOCK(__section_alignment__)} : { ${RELOCATING+___crt_xc_start__ = . ;} @@ -188,6 +200,9 @@ ${R_CRT_XT} ${RELOCATING+___crt_xt_end__ = . ;} } +EOF +fi +cat << EOF /* Windows TLS expects .tls\$AAA to be at the start and .tls\$ZZZ to be at the end of the .tls section. This is important because _tls_start MUST diff -ru --new-file a/ld/scripttempl/pe.sc b/ld/scripttempl/pe.sc --- a/ld/scripttempl/pe.sc 2014-07-03 01:37:48.000000000 -0400 +++ b/ld/scripttempl/pe.sc 2015-03-11 20:10:10.036774102 -0400 @@ -92,12 +92,17 @@ ${RELOCATING+ *(.gcc_except_table)} } +EOF +if [ x"$PE_CYGWIN_FORK_SUPPORT" != xno ]; then cat << EOF /* The Cygwin32 library uses a section to avoid copying certain data on fork. This used to be named ".data$nocopy". The linker used to include this between __data_start__ and __data_end__, but that breaks building the cygwin32 dll. Instead, we name the section ".data_cygwin_nocopy" and explicitly include it after __data_end__. */ +EOF +fi +cat << EOF .data ${RELOCATING+BLOCK(__section_alignment__)} : { ${RELOCATING+__data_start__ = . ;} @@ -106,7 +111,12 @@ ${R_DATA} *(.jcr) ${RELOCATING+__data_end__ = . ;} +EOF +if [ x"$PE_CYGWIN_FORK_SUPPORT" != xno ]; then cat << EOF ${RELOCATING+*(.data_cygwin_nocopy)} +EOF +fi +cat << EOF } .rdata ${RELOCATING+BLOCK(__section_alignment__)} : @@ -165,6 +175,8 @@ ${RELOCATING+__IAT_end__ = .;} ${R_IDATA67} } +EOF +if [ x"$PE_CRT_SECTION" != xno ]; then cat << EOF .CRT ${RELOCATING+BLOCK(__section_alignment__)} : { ${RELOCATING+___crt_xc_start__ = . ;} @@ -183,6 +195,9 @@ ${R_CRT_XT} ${RELOCATING+___crt_xt_end__ = . ;} } +EOF +fi +cat << EOF /* Windows TLS expects .tls\$AAA to be at the start and .tls\$ZZZ to be at the end of section. This is important because _tls_start MUST diff -ru --new-file a/binutils/winduni.c b/binutils/winduni.c --- a/binutils/winduni.c 2014-07-03 01:37:23.000000000 -0400 +++ b/binutils/winduni.c 2015-02-14 11:18:32.987163288 -0500 @@ -57,7 +57,7 @@ /* Codepages mapped. */ static local_iconv_map codepages[] = { - { 0, "MS-ANSI" }, + { 0, "cp1252" }, { 1, "WINDOWS-1252" }, { 437, "MS-ANSI" }, { 737, "MS-GREEK" }, diff -ru a/ld/pe-dll.c b/ld/pe-dll.c --- a/ld/pe-dll.c 2014-07-03 01:37:48.000000000 -0400 +++ b/ld/pe-dll.c 2019-06-30 22:22:22.643202346 -0400 @@ -27,6 +27,7 @@ #include "safe-ctype.h" #include +#include #include "ld.h" #include "ldexp.h" @@ -40,6 +41,7 @@ #include "coff/internal.h" #include "../bfd/libcoff.h" #include "deffile.h" +#include "peimplib.h" #ifdef pe_use_x86_64 @@ -234,7 +236,11 @@ { STRING_COMMA_LEN ("impure_ptr") }, { STRING_COMMA_LEN ("_impure_ptr") }, { STRING_COMMA_LEN ("_fmode") }, + #ifdef PE_TARGET_MIDIPIX + /* (default) excluded symbols are defined by the caller (specs, etc.) */ + #else { STRING_COMMA_LEN ("environ") }, + #endif { NULL, 0 } }; @@ -644,10 +650,13 @@ { int i, j; struct bfd_link_hash_entry *blhe; + struct bfd_link_hash_entry *blhew; bfd *b; struct bfd_section *s; def_file_export *e = 0; bfd_boolean resort_needed; + char *weaksym; + char *objsym; if (!pe_def_file) pe_def_file = def_file_empty (); @@ -737,6 +746,16 @@ if (is_import (sn)) continue; + if (!strncmp (sn, ".weak.", 6) && strchr (sn + 6, '.')) + { + objsym = strdup (sn); + weaksym = strdup (sn + 6); + *(strchr (weaksym, '.')) = '\0'; + sn = weaksym; + } + else + weaksym = 0; + name = xmalloc (strlen ("__imp_") + strlen (sn) + 1); sprintf (name, "%s%s", "__imp_", sn); @@ -745,7 +764,9 @@ free (name); if (blhe && blhe->type == bfd_link_hash_defined) - continue; + if (strncmp (blhe->u.def.section->name, ".got$", 5)) + if (strncmp (blhe->u.def.section->name, ".dsosyms$", 9)) + continue; } if (pe_details->underscored && *sn == '_') @@ -756,12 +777,30 @@ int is_dup = 0; def_file_export *p; - p = def_file_add_export (pe_def_file, sn, 0, -1, - NULL, &is_dup); - /* Fill data flag properly, from dlltool.c. */ - if (!is_dup) - p->flag_data = !(symbols[j]->flags & BSF_FUNCTION); - } + if (weaksym) { + blhew = bfd_link_hash_lookup (info->hash, weaksym, + FALSE, FALSE, FALSE); + } + + if (!weaksym || blhew) { + p = def_file_add_export (pe_def_file, sn, 0, -1, + NULL, &is_dup); + + /* Fill data flag properly, from dlltool.c. */ + if (!is_dup) + p->flag_data = !(symbols[j]->flags & BSF_FUNCTION); + + if (weaksym) { + if (blhew->type != bfd_link_hash_defined) { + free (p->internal_name); + p->internal_name = objsym; + } + } + + if (weaksym) + free (weaksym); + } + } } } } @@ -910,6 +949,7 @@ if (blhe && (blhe->type == bfd_link_hash_defined + || (blhe->type == bfd_link_hash_defweak) || (blhe->type == bfd_link_hash_common))) { count_exported++; @@ -919,7 +959,7 @@ /* Only fill in the sections. The actual offsets are computed in fill_exported_offsets() after common symbols are laid out. */ - if (blhe->type == bfd_link_hash_defined) + if ((blhe->type == bfd_link_hash_defined) || (blhe->type == bfd_link_hash_defweak)) exported_symbol_sections[i] = blhe->u.def.section; else exported_symbol_sections[i] = blhe->u.c.p->section; @@ -2688,6 +2728,160 @@ } + + +void +pe_dll_generate_dsolib( + def_file * def, + const char ** expsyms, + const char * dsolib_file_name, + const char * loader_path, + unsigned char bits) +{ + char * mdso_exe_path; + char * slash; + char * mark; + FILE * fout; + char * argv[10]; + int fd[2]; + int pid; + int rpid; + int ecode; + int i; + + /* sigh; even though pe_dll_generate_implib() might fail, */ + /* ld's _finish() code path assumes no errors could occur */ + /* and accordingly does not perform any checks upon return. */ + /* handle errors here and invoke xexit() as needed. */ + + /* bits */ + if ((bits != 32) && (bits != 64)) { + fprintf(stderr,"%s: internal error (bits == %d.\n",program_name,bits); + xexit(EXIT_FAILURE); + } + + /* mdso_exe_path buffer alloc */ + if (!(mdso_exe_path = calloc(1,strlen(program_name) + strlen("mdso") + 1))) { + fprintf(stderr,"%s: cannot allocate mdso_exe_path buffer.\n",program_name); + xexit(EXIT_FAILURE); + } + + /* mdso_exe_path init */ + strcpy(mdso_exe_path,program_name); + + if ((slash = strrchr(mdso_exe_path,'/'))) + slash++; + else + slash = mdso_exe_path; + + if ((mark = strrchr(slash,'-'))) + mark++; + else + mark = slash; + + sprintf(mark,"%s","mdso"); + + /* pipe */ + if (pipe(fd)) { + fprintf(stderr,"%s: cannot create a pipe.\n",program_name); + xexit(EXIT_FAILURE); + } + + /* fout init */ + if (!(fout = fdopen(fd[1],"a"))) { + fprintf(stderr,"%s: pipe fdopen failed.\n",program_name); + xexit(EXIT_FAILURE); + } + + /* fork */ + if ((pid = fork()) < 0) { + fprintf(stderr,"%s: fork failed.\n",program_name); + xexit(EXIT_FAILURE); + } + + /* child: execvp */ + if (pid == 0) { + argv[0] = mdso_exe_path; + argv[1] = (bits == 64) ? "-m64" : "-m32"; + argv[2] = "--implib"; + argv[3] = (char *)dsolib_file_name; + argv[4] = "--libname"; + argv[5] = (def->name) ? def->name : (char *)dll_name; + + if (loader_path) { + argv[6] = "--libpath"; + argv[7] = (char *)loader_path; + argv[8] = "-"; + argv[9] = 0; + } else { + argv[6] = "-"; + argv[7] = 0; + } + + fclose(fout); + close(fd[1]); + close(0); + + if (dup(fd[0]) == 0) + execvp(mdso_exe_path,argv); + + exit(EXIT_FAILURE); + } + + /* be good */ + free(mdso_exe_path); + + /* parent: expsyms --> pipe */ + if (expsyms) { + for (; *expsyms; ) { + if (fprintf(fout,"%s\n",*expsyms++) < 0) { + fprintf(stderr,"%s: pipe write operation failed.\n",program_name); + xexit(EXIT_FAILURE); + } + } + } else { + for (i=0; i < def->num_exports; i++) { + if (!(pe_def_file->exports[i].flag_private)) { + if (fprintf(fout,"%s\n",def->exports[i].name) < 0) { + fprintf(stderr,"%s: pipe write operation failed.\n",program_name); + xexit(EXIT_FAILURE); + } + } + } + } + + if (fflush(fout) < 0) { + fprintf(stderr,"%s: pipe fflush operation failed.\n",program_name); + xexit(EXIT_FAILURE); + } + + fclose(fout); + close(fd[0]); + + /* obtain child exit status */ + if ((rpid = waitpid(pid,&ecode,0)) < 0) { + fprintf(stderr,"%s: waitpid operation failed.\n",program_name); + xexit(EXIT_FAILURE); + } + + if (rpid != pid) { + fprintf(stderr,"%s: waitpid returned an unexpected pid.\n",program_name); + xexit(EXIT_FAILURE); + } + + if (!(WIFEXITED(ecode))) { + fprintf(stderr,"%s: waitpid reported abnormal child process termination.\n",program_name); + xexit(EXIT_FAILURE); + } + + if (WEXITSTATUS(ecode)) { + fprintf(stderr,"%s: the child process returned an error.\n",program_name); + xexit(EXIT_FAILURE); + } +} + + + void pe_dll_generate_implib (def_file *def, const char *impfilename, struct bfd_link_info *info) { diff -ru a/ld/pe-dll.h b/ld/pe-dll.h --- a/ld/pe-dll.h 2014-07-03 01:37:48.000000000 -0400 +++ b/ld/pe-dll.h 2017-10-14 20:01:45.817295022 -0400 @@ -49,6 +49,8 @@ (const char *); extern void pe_dll_generate_implib (def_file *, const char *, struct bfd_link_info *); +extern void pe_dll_generate_dsolib + (def_file *, const char **, const char *, const char *, unsigned char); extern void pe_process_import_defs (bfd *, struct bfd_link_info *); extern bfd_boolean pe_implied_import_dll diff -ru a/ld/pep-dll.c b/ld/pep-dll.c --- a/ld/pep-dll.c 2014-07-03 01:37:48.000000000 -0400 +++ b/ld/pep-dll.c 2017-10-14 10:14:35.490521636 -0400 @@ -54,6 +54,7 @@ #define pe_dll_fill_sections pep_dll_fill_sections #define pe_exe_fill_sections pep_exe_fill_sections #define pe_dll_generate_implib pep_dll_generate_implib +#define pe_dll_generate_dsolib pep_dll_generate_dsolib #define pe_dll_add_excludes pep_dll_add_excludes #define pe_walk_relocs_of_symbol pep_walk_relocs_of_symbol #define pe_bfd_is_dll pep_bfd_is_dll diff -ru a/ld/pep-dll.h b/ld/pep-dll.h --- a/ld/pep-dll.h 2014-07-03 01:37:48.000000000 -0400 +++ b/ld/pep-dll.h 2017-10-14 19:17:26.885792850 -0400 @@ -46,6 +46,7 @@ extern void pep_dll_add_excludes (const char *, const exclude_type); extern void pep_dll_generate_def_file (const char *); extern void pep_dll_generate_implib (def_file *, const char *, struct bfd_link_info *); +extern void pep_dll_generate_dsolib (def_file *, const char **, const char *, const char *, unsigned char); extern void pep_process_import_defs (bfd *, struct bfd_link_info *); extern bfd_boolean pep_implied_import_dll (const char *); extern void pep_dll_build_sections (bfd *, struct bfd_link_info *); diff -ru --new-file a/bfd/config.bfd b/bfd/config.bfd --- a/bfd/config.bfd 2014-07-03 01:37:20.000000000 -0400 +++ b/bfd/config.bfd 2015-02-14 11:27:08.199179775 -0500 @@ -679,7 +679,7 @@ targ_archs="$targ_archs bfd_arm_arch" want64=true ;; - x86_64-*-mingw* | x86_64-*-pe | x86_64-*-pep | x86_64-*-cygwin) + x86_64-*-mingw* | x86_64-*-pe | x86_64-*-pep | x86_64-*-cygwin | x86_64-*-midipix*) targ_defvec=x86_64_pe_vec targ_selvecs="x86_64_pe_vec x86_64_pei_vec x86_64_pe_be_vec x86_64_elf64_vec l1om_elf64_vec k1om_elf64_vec i386_pe_vec i386_pei_vec i386_elf32_vec" want64=true @@ -731,7 +731,7 @@ targ_defvec=i386_elf32_vec targ_selvecs=i386_coff_vec ;; - i[3-7]86-*-mingw32* | i[3-7]86-*-cygwin* | i[3-7]86-*-winnt | i[3-7]86-*-pe) + i[3-7]86-*-mingw32* | i[3-7]86-*-cygwin* | i[3-7]86-*-winnt | i[3-7]86-*-pe | i[3-7]86-*-midipix*) targ_defvec=i386_pe_vec targ_selvecs="i386_pe_vec i386_pei_vec i386_elf32_vec" targ_underscore=yes diff -ru --new-file a/binutils/configure b/binutils/configure --- a/binutils/configure 2014-07-03 01:37:22.000000000 -0400 +++ b/binutils/configure 2015-09-13 21:35:09.738957435 -0400 @@ -14015,7 +14015,7 @@ BUILD_WINDRES='$(WINDRES_PROG)$(EXEEXT)' BUILD_WINDMC='$(WINDMC_PROG)$(EXEEXT)' ;; - x86_64-*-mingw* | x86_64-*-cygwin*) + x86_64-*-mingw* | x86_64-*-midipix* | x86_64-*-cygwin*) BUILD_DLLTOOL='$(DLLTOOL_PROG)$(EXEEXT)' if test -z "$DLLTOOL_DEFAULT"; then DLLTOOL_DEFAULT="-DDLLTOOL_DEFAULT_MX86_64" @@ -14025,7 +14025,7 @@ BUILD_WINDMC='$(WINDMC_PROG)$(EXEEXT)' BUILD_DLLWRAP='$(DLLWRAP_PROG)$(EXEEXT)' ;; - i[3-7]86-*-pe* | i[3-7]86-*-cygwin* | i[3-7]86-*-mingw32** | i[3-7]86-*-netbsdpe*) + i[3-7]86-*-pe* | i[3-7]86-*-cygwin* | i[3-7]86-*-midipix* | i[3-7]86-*-mingw32** | i[3-7]86-*-netbsdpe*) BUILD_DLLTOOL='$(DLLTOOL_PROG)$(EXEEXT)' if test -z "$DLLTOOL_DEFAULT"; then DLLTOOL_DEFAULT="-DDLLTOOL_DEFAULT_I386" diff -ru --new-file a/configure b/configure --- a/configure 2014-07-03 01:37:23.000000000 -0400 +++ b/configure 2015-03-11 17:07:15.820422926 -0400 @@ -3428,6 +3428,9 @@ x86_64-*-mingw*) noconfigdirs="$noconfigdirs ${libgcj}" ;; + *-midipix*) + noconfigdirs="$noconfigdirs ${libgcj}" + ;; mmix-*-*) noconfigdirs="$noconfigdirs target-libffi target-boehm-gc" ;; @@ -3549,6 +3552,9 @@ *-*-mingw*) noconfigdirs="$noconfigdirs target-newlib target-libgloss" ;; + *-*-midipix*) + noconfigdirs="$noconfigdirs target-newlib target-libgloss" + ;; *-*-netbsd*) noconfigdirs="$noconfigdirs target-newlib target-libgloss" ;; @@ -6257,7 +6263,7 @@ target_elf=no case $target in - *-darwin* | *-aix* | *-cygwin* | *-mingw* | *-aout* | *-*coff* | \ + *-darwin* | *-aix* | *-cygwin* | *-mingw* | *-midipix* | *-aout* | *-*coff* | \ *-msdosdjgpp* | *-vms* | *-wince* | *-*-pe* | \ alpha*-dec-osf* | *-interix* | hppa[12]*-*-hpux*) target_elf=no diff -ru --new-file a/gas/configure.tgt b/gas/configure.tgt --- a/gas/configure.tgt 2014-07-03 01:37:25.000000000 -0400 +++ b/gas/configure.tgt 2015-02-14 11:27:08.223179776 -0500 @@ -262,7 +262,7 @@ i*) fmt=coff em=pe ;; esac ;; i386-*-interix*) fmt=coff em=interix ;; - i386-*-mingw*) + i386-*-mingw* | i386-*-midipix*) case ${cpu} in x86_64*) fmt=coff em=pep ;; i*) fmt=coff em=pe ;; diff -ru a/bfd/cofflink.c b/bfd/cofflink.c --- a/bfd/cofflink.c 2014-07-03 01:37:20.000000000 -0400 +++ b/bfd/cofflink.c 2015-06-13 20:22:46.000389638 -0400 @@ -202,6 +202,7 @@ bfd_size_type symesz; bfd_byte *esym; bfd_byte *esym_end; + char *weaksym; *pneeded = FALSE; @@ -236,6 +237,16 @@ && CONST_STRNEQ (name, "__imp_")) h = bfd_link_hash_lookup (info->hash, name + 6, FALSE, FALSE, TRUE); + if (!h && !strncmp (name, ".weak.", 6) && strchr (name + 6, '.')) + { + weaksym = strdup (name + 6); + *(strchr (weaksym, '.')) = '\0'; + h = bfd_link_hash_lookup (info->hash, weaksym, FALSE, FALSE, TRUE); + name = weaksym; + } + else + weaksym = 0; + /* We are only interested in symbols that are currently undefined. If a symbol is currently known to be common, COFF linkers do not bring in an object file which defines @@ -249,6 +260,9 @@ *pneeded = TRUE; return TRUE; } + + if (weaksym) + free (weaksym); } esym += (sym.n_numaux + 1) * symesz; @@ -320,6 +334,7 @@ bfd_byte *esym; bfd_byte *esym_end; bfd_size_type amt; + char *weaksym; symcount = obj_raw_syment_count (abfd); @@ -476,6 +491,20 @@ addit = FALSE; } + if (!strncmp (name, ".weak.", 6) && strchr (name + 6, '.')) + { + if (! (bfd_coff_link_add_one_symbol + (info, abfd, name, flags, section, value, + (const char *) NULL, copy, FALSE, + (struct bfd_link_hash_entry **) sym_hash))) + goto error_return; + + weaksym = strdup (name + 6); + *(strchr(weaksym, '.')) = 0; + name = weaksym; + flags |= BSF_WEAK; + } + if (addit) { if (! (bfd_coff_link_add_one_symbol diff -ru a/bfd/linker.c b/bfd/linker.c --- a/bfd/linker.c 2014-07-03 01:37:21.000000000 -0400 +++ b/bfd/linker.c 2015-06-06 17:51:24.148275212 -0400 @@ -1050,6 +1050,7 @@ struct archive_hash_table arsym_hash; unsigned int indx; struct bfd_link_hash_entry **pundef; + char *weaksym; if (! bfd_has_map (abfd)) { @@ -1073,6 +1074,13 @@ struct archive_hash_entry *arh; struct archive_list *l, **pp; + if (!strncmp (arsym->name, ".weak.", 6) && strchr (arsym->name + 6, '.')) + { + weaksym = strdup (arsym->name + 6); + *(strchr (weaksym, '.')) = '\0'; + arsym->name = weaksym; + } + arh = archive_hash_lookup (&arsym_hash, arsym->name, TRUE, FALSE); if (arh == NULL) goto error_return; diff -ru a/gas/config/tc-i386.c b/gas/config/tc-i386.c --- a/gas/config/tc-i386.c 2014-07-03 01:37:25.000000000 -0400 +++ b/gas/config/tc-i386.c 2015-06-12 22:40:37.100250091 -0400 @@ -9148,25 +9148,6 @@ value += md_pcrel_from (fixP); #endif } -#if defined (OBJ_COFF) && defined (TE_PE) - if (fixP->fx_addsy != NULL - && S_IS_WEAK (fixP->fx_addsy) - /* PR 16858: Do not modify weak function references. */ - && ! fixP->fx_pcrel) - { -#if !defined (TE_PEP) - /* For x86 PE weak function symbols are neither PC-relative - nor do they set S_IS_FUNCTION. So the only reliable way - to detect them is to check the flags of their containing - section. */ - if (S_GET_SEGMENT (fixP->fx_addsy) != NULL - && S_GET_SEGMENT (fixP->fx_addsy)->flags & SEC_CODE) - ; - else -#endif - value -= S_GET_VALUE (fixP->fx_addsy); - } -#endif /* Fix a few things - the dynamic linker expects certain values here, and we must not disappoint it. */ @@ -9237,8 +9218,11 @@ fixP->fx_done = 0; /* Remember value for tc_gen_reloc. */ fixP->fx_addnumber = value; - /* Clear out the frag for now. */ - value = 0; + /* for data symbols, cancel the effect of the relocation */ + if (!((S_GET_SEGMENT (fixP->fx_addsy)->flags) & SEC_CODE)) + value = -S_GET_VALUE (fixP->fx_addsy); + else + value = 0; } #endif else if (use_rela_relocations) --- a/binutils/rename.c 2014-07-03 01:37:22.000000000 -0400 +++ b/binutils/rename.c 2015-11-25 23:13:38.086948592 -0500 @@ -167,7 +167,10 @@ && s.st_nlink == 1) ) { - ret = rename (from, to); + if ((ret = rename (from, to))) + if (!(ret = simple_copy (from, to))) + unlink (from); + if (ret == 0) { if (exists)