diff options
author | Tamar Christina <tamar@zhox.com> | 2019-09-08 23:11:19 +0100 |
---|---|---|
committer | Tamar Christina <tamar@zhox.com> | 2019-10-20 16:21:10 +0100 |
commit | 4b431f334018eaef2cf36de3316025c68c922915 (patch) | |
tree | 7f85d5a1a6bc6d39e9a8c51fe33904ff61461a7e | |
parent | c4c9904b324736dc5d190a91418e8d8f564d4104 (diff) | |
download | haskell-4b431f334018eaef2cf36de3316025c68c922915.tar.gz |
Windows: Update tarballs to GCC 9.2 and remove MAX_PATH limit.
-rw-r--r-- | compiler/cbits/genSym.c | 2 | ||||
-rw-r--r-- | configure.ac | 2 | ||||
-rw-r--r-- | docs/users_guide/8.10.1-notes.rst | 4 | ||||
-rw-r--r-- | includes/Rts.h | 6 | ||||
-rw-r--r-- | includes/stg/Types.h | 9 | ||||
-rw-r--r-- | libraries/base/cbits/inputReady.c | 2 | ||||
-rwxr-xr-x | mk/get-win32-tarballs.sh | 124 | ||||
-rw-r--r-- | mk/win32-tarballs.md5sum | 63 | ||||
-rw-r--r-- | rts/RtsSymbols.c | 44 | ||||
-rw-r--r-- | rts/RtsSymbols.h | 5 | ||||
-rw-r--r-- | rts/linker/PEi386.c | 10 | ||||
-rw-r--r-- | rts/linker/PEi386.h | 1 | ||||
-rw-r--r-- | rts/linker/elf_plt.h | 4 | ||||
-rw-r--r-- | rts/linker/elf_reloc_aarch64.c | 8 | ||||
-rw-r--r-- | rts/linker/elf_reloc_aarch64.h | 4 | ||||
-rw-r--r-- | rts/win32/OSMem.c | 8 | ||||
-rw-r--r-- | rts/win32/OSThreads.c | 22 | ||||
-rw-r--r-- | testsuite/tests/ffi/should_run/T5594_c.c | 4 | ||||
-rw-r--r-- | testsuite/tests/ffi/should_run/ffi002_c.c | 4 | ||||
-rw-r--r-- | testsuite/tests/ffi/should_run/fptr01_c.c | 5 | ||||
-rw-r--r-- | testsuite/tests/ffi/should_run/fptrfail01_c.c | 5 | ||||
-rw-r--r-- | testsuite/tests/rts/linker/linker_error.c | 2 | ||||
-rw-r--r-- | testsuite/tests/rts/linker/linker_unload.c | 2 | ||||
-rw-r--r-- | utils/fs/fs.c | 299 | ||||
-rw-r--r-- | utils/fs/fs.h | 11 | ||||
-rw-r--r-- | utils/ghc-cabal/Main.hs | 21 |
26 files changed, 530 insertions, 141 deletions
diff --git a/compiler/cbits/genSym.c b/compiler/cbits/genSym.c index 769c09358c..ecb318d5a8 100644 --- a/compiler/cbits/genSym.c +++ b/compiler/cbits/genSym.c @@ -1,5 +1,5 @@ -#include <assert.h> #include <Rts.h> +#include <assert.h> #include "Unique.h" static HsInt GenSymCounter = 0; diff --git a/configure.ac b/configure.ac index 6fddd04bb0..f1c926903c 100644 --- a/configure.ac +++ b/configure.ac @@ -329,7 +329,7 @@ then if test "$HostArch" = "i386" then mingw_arch="i686" - tarball_dest_dir="mingw-w64/x86" + tarball_dest_dir="mingw-w64/i686" tarball_mingw_dir="mingw32" else mingw_arch="x86_64" diff --git a/docs/users_guide/8.10.1-notes.rst b/docs/users_guide/8.10.1-notes.rst index 0d7be2e6d8..eb06b02ac8 100644 --- a/docs/users_guide/8.10.1-notes.rst +++ b/docs/users_guide/8.10.1-notes.rst @@ -173,6 +173,10 @@ Compiler implemented correctly, and appears to be largely unused. This flag will be removed in a later version of GHC. +- Windows bindist has been updated to GCC 9.2 and binutils 2.32. These binaries have + been patched to no longer have have the MAX_PATH limit. Windows users should no longer + have any issues with long path names. + GHCi ~~~~ diff --git a/includes/Rts.h b/includes/Rts.h index dd60726c39..256a3e586c 100644 --- a/includes/Rts.h +++ b/includes/Rts.h @@ -16,6 +16,12 @@ extern "C" { #endif +/* get types from GHC's runtime system */ +#include "ghcconfig.h" +/* We have to include Types.h before everything else as this defines some + macros that will change the behaviour of system headers. */ +#include "stg/Types.h" + /* We include windows.h very early, as on Win64 the CONTEXT type has fields "R8", "R9" and "R10", which goes bad if we've already #define'd those names for our own purposes (in stg/Regs.h) */ diff --git a/includes/stg/Types.h b/includes/stg/Types.h index f270686ebc..08ba58c799 100644 --- a/includes/stg/Types.h +++ b/includes/stg/Types.h @@ -21,8 +21,15 @@ #pragma once #if defined(mingw32_HOST_OS) +# if defined(__USE_MINGW_ANSI_STDIO) +# if __USE_MINGW_ANSI_STDIO != 1 +# warning "Mismatch between __USE_MINGW_ANSI_STDIO definitions. \ +If using Rts.h make sure it is the first header included." +# endif +# else /* Inform mingw we want the ISO rather than Windows printf format specifiers. */ -#define __USE_MINGW_ANSI_STDIO 1 +# define __USE_MINGW_ANSI_STDIO 1 +#endif #endif /* ISO C 99 says: diff --git a/libraries/base/cbits/inputReady.c b/libraries/base/cbits/inputReady.c index 8d100e8fbe..7a281d6d90 100644 --- a/libraries/base/cbits/inputReady.c +++ b/libraries/base/cbits/inputReady.c @@ -22,10 +22,10 @@ /* select and supporting types is not Posix */ /* #include "PosixSource.h" */ +#include "Rts.h" #include <limits.h> #include <stdbool.h> #include "HsBase.h" -#include "Rts.h" #if !defined(_WIN32) #include <poll.h> #endif diff --git a/mk/get-win32-tarballs.sh b/mk/get-win32-tarballs.sh index fd47232b91..4732ede52d 100755 --- a/mk/get-win32-tarballs.sh +++ b/mk/get-win32-tarballs.sh @@ -2,6 +2,7 @@ tarball_dir='ghc-tarballs' missing_files=0 +pkg_variant="phyx" # see #12502 if test -z "$FIND"; then FIND="find"; fi @@ -37,7 +38,7 @@ download_file() { return else echo "Downloading ${description} to ${dest_dir}..." - $curl_cmd || echo "Checking repo.msys2.org instead of Haskell.org..." && $curl_cmd_bnk || { + $curl_cmd || (echo "Checking repo.msys2.org instead of Haskell.org..." && $curl_cmd_bnk) || { rm -f "${dest_file}" fail "ERROR: Download failed." exit 1 @@ -51,11 +52,11 @@ download_file() { echo "Downloading ${description} (signature) to ${dest_dir}..." local curl_cmd="curl -f -L ${file_url}.sig -o ${sig_file} --create-dirs -# ${extra_curl_opts}" if test -n "${backup_url}"; then - local curl_cmd_bnk="curl -f -L ${backup_url} -o ${sig_file} --create-dirs -# ${extra_curl_opts}" + local curl_cmd_bnk="curl -f -L "${backup_url}.sig" -o ${sig_file} --create-dirs -# ${extra_curl_opts}" else local curl_cmd_bnk="true" fi - $curl_cmd || echo "Checking repo.msys2.org instead of Haskell.org..." && $curl_cmd_bnk || { + $curl_cmd || (echo "Checking repo.msys2.org instead of Haskell.org..." && $curl_cmd_bnk) || { rm -f "${dest_file}.sig" fail "ERROR: Download failed." exit 1 @@ -101,26 +102,23 @@ download_tarballs() { local package_prefix="mingw-w64" local format_url="/${mingw_arch}/${package_prefix}-${mingw_arch}" - download_mingw "${format_url}-crt-git-5.0.0.4795.e3d96cb1-1-any.pkg.tar.xz" - download_mingw "${format_url}-winpthreads-git-5.0.0.4850.d1662dc7-1-any.pkg.tar.xz" - download_mingw "${format_url}-headers-git-5.0.0.4966.1eee2140-1-any.pkg.tar.xz" - download_mingw "${format_url}-libwinpthread-git-5.0.0.4850.d1662dc7-1-any.pkg.tar.xz" + download_mingw "${format_url}-crt-git-7.0.0.5491.fe45801e-1-any.pkg.tar.xz" + download_mingw "${format_url}-winpthreads-git-7.0.0.5480.e14d23be-1-any.pkg.tar.xz" + download_mingw "${format_url}-headers-git-7.0.0.5490.9ec54ed1-1-any.pkg.tar.xz" + download_mingw "${format_url}-libwinpthread-git-7.0.0.5480.e14d23be-1-any.pkg.tar.xz" download_mingw "${format_url}-zlib-1.2.8-9-any.pkg.tar.xz" - download_mingw "${format_url}-isl-0.18-1-any.pkg.tar.xz" - download_mingw "${format_url}-mpfr-3.1.6-1-any.pkg.tar.xz" + download_mingw "${format_url}-isl-0.21-1-any.pkg.tar.xz" + download_mingw "${format_url}-mpfr-4.0.2-2-any.pkg.tar.xz" download_mingw "${format_url}-gmp-6.1.2-1-any.pkg.tar.xz" - download_mingw "${format_url}-binutils-2.29.1-1-any.pkg.tar.xz" - download_mingw "${format_url}-libidn2-2.0.4-1-any.pkg.tar.xz" - download_mingw "${format_url}-gcc-7.2.0-1-any.pkg.tar.xz" + download_mingw "${format_url}-binutils-2.32-3-$pkg_variant.pkg.tar.xz" + download_mingw "${format_url}-libidn2-2.2.0-1-any.pkg.tar.xz" + download_mingw "${format_url}-gcc-9.2.0-1-$pkg_variant.pkg.tar.xz" + download_mingw "${format_url}-mpc-1.1.0-1-any.pkg.tar.xz" + download_mingw "${format_url}-windows-default-manifest-6.4-3-any.pkg.tar.xz" # Upstream is unfortunately quite inconsistent in naming if test "$mingw_arch" != "sources"; then - download_mingw "${format_url}-mpc-1.0.3-2-any.pkg.tar.xz" - download_mingw "${format_url}-gcc-libs-7.2.0-1-any.pkg.tar.xz" - else - local format_url="${mingw_base_url}/${mingw_arch}/${package_prefix}" - download_mingw "${format_url}-i686-mpc-1.0.3-2.src.tar.gz" - download_mingw "${format_url}-x86_64-mpc-1.0.3-2.src.tar.gz" + download_mingw "${format_url}-gcc-libs-9.2.0-1-$pkg_variant.pkg.tar.xz" fi if ! test "$missing_files" = "0" @@ -131,7 +129,7 @@ download_tarballs() { download_i386() { mingw_arch="i686" - tarball_dest_dir="mingw-w64/x86" + tarball_dest_dir="mingw-w64/i686" download_tarballs } @@ -171,6 +169,54 @@ sync_binaries_and_sources() { done } +patch_single_file () { + local patcher_base="$1" + local filename=$(readlink -f "$2") + local filepath=$(dirname "$filename") + local patcher="$patcher_base/iat-patcher.exe" + $patcher install "$filename" > /dev/null + rm -f "$filename.bak" + for file in $patcher_base/*.dll; do cp -f "$file" "${filepath}"; done + echo "Patched '$filename'" +} + +patch_tarball () { + local tarball_name="$1" + local filename=$(basename "$tarball_name") + local filepath=$(dirname "$tarball_name") + local newfile=`echo "$filepath/$filename" | sed -e 's/-any/-phyx/'` + local arch="" + + echo "=> ${filename}" + + case $1 in + *x86_64*) + arch="x86_64" + ;; + *i686*) + arch="i686" + ;; + *) + echo "unknown architecture detected. Stopping." + exit 1 + ;; + esac + + local base="$(pwd)" + local patcher_base="$(pwd)/ghc-tarballs/ghc-jailbreak/$arch" + local tmpdir="ghc-tarballs/tmpdir" + mkdir -p $tmpdir + cd $tmpdir + tar xJf "$base/$tarball_name" + find . -iname "*.exe" -exec bash -c \ + 'patch_single_file "'"${patcher_base}"'" "$0"' {} \; + tar cJf "$base/$newfile" . + cd "$base" + rm -rf $tmpdir + gpg --output "$base/${newfile}.sig" --detach-sig "$base/$newfile" + rm -f "$base/$tarball_name" +} + show_hashes_for_binaries() { $FIND ghc-tarballs/ -iname "*.*" | xargs md5sum | grep -v "\.sig" | sed -s "s/\*//" } @@ -182,11 +228,13 @@ usage() { echo echo "Where <action> is one of," echo "" - echo " download download the necessary tarballs for the given architecture" - echo " fetch download the necessary tarballs for the given architecture but doesn't verify their md5." - echo " verify verify the existence and correctness of the necessary tarballs" - echo " hash generate md5 hashes for inclusion in win32-tarballs.md5sum" - echo " sync upload packages downloaded with 'fetch mirror' to haskell.org" + echo " download download the necessary tarballs for the given architecture" + echo " fetch download the necessary tarballs for the given architecture but doesn't verify their md5." + echo " grab download the necessary tarballs using patched toolchains for the given architecture but doesn't verify their md5." + echo " verify verify the existence and correctness of the necessary tarballs" + echo " patch jailbreak the binaries in the tarballs and remove MAX_PATH limitations." + echo " hash generate md5 hashes for inclusion in win32-tarballs.md5sum" + echo " sync upload packages downloaded with 'fetch mirror' to haskell.org" echo "" echo "and <arch> is one of i386, x86_64,all or mirror (which includes sources)" } @@ -199,7 +247,12 @@ case $1 in ;; fetch) download=1 + verify= + ;; + grab) + download=1 verify=0 + pkg_variant="any" ;; verify) download=0 @@ -214,6 +267,28 @@ case $1 in show_hashes_for_binaries exit 1 ;; + # This routine will download the latest ghc-jailbreak and unpack binutils and + # the ghc tarballs and patches every .exe in each. Along with this is copies + # two dlls in every folder that it patches a .exe in. Afterwards it re-creates + # the tarballs and generates a new signature file. + patch) + export -f patch_tarball + export -f patch_single_file + + echo "Downloading ghc-jailbreak..." + curl -f -L https://mistuke.blob.core.windows.net/binaries/ghc-jailbreak-0.3.tar.gz \ + -o ghc-tarballs/ghc-jailbreak/ghc-jailbreak.tar.gz --create-dirs -# + tar -C ghc-tarballs/ghc-jailbreak/ -xf ghc-tarballs/ghc-jailbreak/ghc-jailbreak.tar.gz + + find ghc-tarballs/mingw-w64/ \( -iname "*binutils*.tar.xz" \ + -o -iname "*gcc*.tar.xz" \) \ + -exec bash -c 'patch_tarball "$0"' {} \; + + rm -rf ghc-tarballs/ghc-jailbreak + + echo "Finished tarball generation, toolchain has been pre-patched." + exit 0 + ;; *) usage exit 1 @@ -236,6 +311,7 @@ case $2 in download_i386 download_x86_64 verify=0 + sigs=0 download_sources show_hashes_for_binaries ;; diff --git a/mk/win32-tarballs.md5sum b/mk/win32-tarballs.md5sum index 2c2d3df93a..5d23609de5 100644 --- a/mk/win32-tarballs.md5sum +++ b/mk/win32-tarballs.md5sum @@ -1,39 +1,28 @@ -d0b3537c3f56b6f396b3dc23a905d186 ghc-tarballs/mingw-w64/sources/mingw-w64-crt-git-5.0.0.4795.e3d96cb1-1.src.tar.gz -51d1006727d50a599bf30c34537bb6a9 ghc-tarballs/mingw-w64/sources/mingw-w64-binutils-2.29.1-1.src.tar.gz -4578c232f7ed327bd6a364737cb018f5 ghc-tarballs/mingw-w64/sources/mingw-w64-gcc-7.2.0-1.src.tar.gz -b605210c3d1b03092e3b223d1ccf4001 ghc-tarballs/mingw-w64/sources/mingw-w64-gmp-6.1.2-1.src.tar.gz -1ad83604bb58ecf43f26843975046c1c ghc-tarballs/mingw-w64/sources/mingw-w64-headers-git-5.0.0.4966.1eee2140-1.src.tar.gz -5c24d319656ed61e517dfa0fee7e475c ghc-tarballs/mingw-w64/sources/mingw-w64-i686-mpc-1.0.3-2.src.tar.gz -214032557d2474f10c23c33bdaced8e5 ghc-tarballs/mingw-w64/sources/mingw-w64-isl-0.18-1.src.tar.gz -8c7efe60059c4c80d0d1966c943b5aaa ghc-tarballs/mingw-w64/sources/mingw-w64-libidn2-2.0.4-1.src.tar.gz -18e9d17e968773c0691c50d9ceeede34 ghc-tarballs/mingw-w64/sources/mingw-w64-mpfr-3.1.6-1.src.tar.gz -0462bc73a8b15a68dece429f6f33ca81 ghc-tarballs/mingw-w64/sources/mingw-w64-winpthreads-git-5.0.0.4850.d1662dc7-1.src.tar.gz -d4261042f502998006c57f0e6517998e ghc-tarballs/mingw-w64/sources/mingw-w64-x86_64-mpc-1.0.3-2.src.tar.gz -534bb4756482f3271308576cdadfe5dc ghc-tarballs/mingw-w64/x86/mingw-w64-i686-crt-git-5.0.0.4795.e3d96cb1-1-any.pkg.tar.xz -32078e2a67e34ff6c0b1795fe6ed9d36 ghc-tarballs/mingw-w64/sources/mingw-w64-zlib-1.2.8-9.src.tar.gz -66e4fc3e62c0fa6723c0d27bdb832962 ghc-tarballs/mingw-w64/x86/mingw-w64-i686-binutils-2.29.1-1-any.pkg.tar.xz -634ad635913713abc0dbcb0ebef8c85b ghc-tarballs/mingw-w64/x86/mingw-w64-i686-gcc-7.2.0-1-any.pkg.tar.xz -5343540bc6caa7ada564483f3a1fdff7 ghc-tarballs/mingw-w64/x86/mingw-w64-i686-gcc-libs-7.2.0-1-any.pkg.tar.xz -2f97e71e4ec122151c20350433268d8b ghc-tarballs/mingw-w64/x86/mingw-w64-i686-gmp-6.1.2-1-any.pkg.tar.xz -07f374e6eb4846169921551ee73103e6 ghc-tarballs/mingw-w64/x86/mingw-w64-i686-headers-git-5.0.0.4966.1eee2140-1-any.pkg.tar.xz -ac7017bd5d69030cfe76e475e213b43a ghc-tarballs/mingw-w64/x86/mingw-w64-i686-isl-0.18-1-any.pkg.tar.xz -f758e0d121619b166dbe36060c641767 ghc-tarballs/mingw-w64/x86/mingw-w64-i686-libidn2-2.0.4-1-any.pkg.tar.xz -3c718f86311bdd8c4438513a0f417391 ghc-tarballs/mingw-w64/x86/mingw-w64-i686-libwinpthread-git-5.0.0.4850.d1662dc7-1-any.pkg.tar.xz -719e76fa7a54a8676d2e60af3bb13c45 ghc-tarballs/mingw-w64/x86/mingw-w64-i686-mpc-1.0.3-2-any.pkg.tar.xz -3780a25a6f20eef9b143f47f4b615e39 ghc-tarballs/mingw-w64/x86_64/mingw-w64-x86_64-crt-git-5.0.0.4795.e3d96cb1-1-any.pkg.tar.xz -9d71b5b4698310a6b961a7d9e273a204 ghc-tarballs/mingw-w64/x86/mingw-w64-i686-mpfr-3.1.6-1-any.pkg.tar.xz -8912539507692ecf3cebcd5405e1a526 ghc-tarballs/mingw-w64/x86/mingw-w64-i686-winpthreads-git-5.0.0.4850.d1662dc7-1-any.pkg.tar.xz -87c65e9b2930436a75dfd7d459ae98cb ghc-tarballs/mingw-w64/x86/mingw-w64-i686-zlib-1.2.8-9-any.pkg.tar.xz -a7e26551a47ce247e432d3f3db416f2b ghc-tarballs/mingw-w64/x86_64/mingw-w64-x86_64-binutils-2.29.1-1-any.pkg.tar.xz -c4ce9e9a696a76a350d6ed4222fe205e ghc-tarballs/mingw-w64/x86_64/mingw-w64-x86_64-gcc-7.2.0-1-any.pkg.tar.xz -872a54d953e7d9e6f375e3712d540701 ghc-tarballs/mingw-w64/x86_64/mingw-w64-x86_64-gcc-libs-7.2.0-1-any.pkg.tar.xz +8af4600c30671775a1dde3b60fe75854 ghc-tarballs/mingw-w64/i686/mingw-w64-i686-binutils-2.32-3-phyx.pkg.tar.xz +c442f8999c10a24059a79a0a8974bc46 ghc-tarballs/mingw-w64/i686/mingw-w64-i686-crt-git-7.0.0.5491.fe45801e-1-any.pkg.tar.xz +dddc20e7431ab369f6e2726feb4f65d1 ghc-tarballs/mingw-w64/i686/mingw-w64-i686-gcc-9.2.0-1-phyx.pkg.tar.xz +64130e9d870de2292d4627a67fabee51 ghc-tarballs/mingw-w64/i686/mingw-w64-i686-gcc-libs-9.2.0-1-phyx.pkg.tar.xz +2f97e71e4ec122151c20350433268d8b ghc-tarballs/mingw-w64/i686/mingw-w64-i686-gmp-6.1.2-1-any.pkg.tar.xz +192a25fe284cf8a78851a673d6ef672a ghc-tarballs/mingw-w64/i686/mingw-w64-i686-headers-git-7.0.0.5490.9ec54ed1-1-any.pkg.tar.xz +a18983513ec46ff0716dc5742604a78b ghc-tarballs/mingw-w64/i686/mingw-w64-i686-isl-0.21-1-any.pkg.tar.xz +c8dabb32fabe2492878e070ffad473f0 ghc-tarballs/mingw-w64/i686/mingw-w64-i686-libidn2-2.2.0-1-any.pkg.tar.xz +d05ca6e90126c17db19a8cd32e7347e8 ghc-tarballs/mingw-w64/i686/mingw-w64-i686-libwinpthread-git-7.0.0.5480.e14d23be-1-any.pkg.tar.xz +cae596bd144ad70875ef8f21e5bdb77d ghc-tarballs/mingw-w64/i686/mingw-w64-i686-mpc-1.1.0-1-any.pkg.tar.xz +317a7a490da5c88f63638fbc5461b51e ghc-tarballs/mingw-w64/i686/mingw-w64-i686-mpfr-4.0.2-2-any.pkg.tar.xz +15a5557d7b321bb26436dcf7adced5b7 ghc-tarballs/mingw-w64/i686/mingw-w64-i686-windows-default-manifest-6.4-3-any.pkg.tar.xz +beb76cd6141d11c000a1f5ff2ad34971 ghc-tarballs/mingw-w64/i686/mingw-w64-i686-winpthreads-git-7.0.0.5480.e14d23be-1-any.pkg.tar.xz +87c65e9b2930436a75dfd7d459ae98cb ghc-tarballs/mingw-w64/i686/mingw-w64-i686-zlib-1.2.8-9-any.pkg.tar.xz +4dca7def5591b8f999e5fa20084cc7a9 ghc-tarballs/mingw-w64/x86_64/mingw-w64-x86_64-binutils-2.32-3-phyx.pkg.tar.xz +d4336ca77b5edf3126a6c1358952567a ghc-tarballs/mingw-w64/x86_64/mingw-w64-x86_64-crt-git-7.0.0.5491.fe45801e-1-any.pkg.tar.xz +e84e0426204b73af13752b65a035dfc2 ghc-tarballs/mingw-w64/x86_64/mingw-w64-x86_64-gcc-9.2.0-1-phyx.pkg.tar.xz +b6200865004cb558c8f5cd7526975602 ghc-tarballs/mingw-w64/x86_64/mingw-w64-x86_64-gcc-libs-9.2.0-1-phyx.pkg.tar.xz 1e1f79abc9fc0534d360c2889b10a9f5 ghc-tarballs/mingw-w64/x86_64/mingw-w64-x86_64-gmp-6.1.2-1-any.pkg.tar.xz -8cce0779e70d5c3ef3564a11fb3bd931 ghc-tarballs/mingw-w64/x86_64/mingw-w64-x86_64-headers-git-5.0.0.4966.1eee2140-1-any.pkg.tar.xz -e1c25a67656e3667847be1f5eba73862 ghc-tarballs/mingw-w64/x86_64/mingw-w64-x86_64-isl-0.18-1-any.pkg.tar.xz -6faaa722dce8af954b30e39c4213d657 ghc-tarballs/mingw-w64/x86_64/mingw-w64-x86_64-libidn2-2.0.4-1-any.pkg.tar.xz -df50f51f32efe8bff7a87f26c6832045 ghc-tarballs/mingw-w64/x86_64/mingw-w64-x86_64-libwinpthread-git-5.0.0.4850.d1662dc7-1-any.pkg.tar.xz -df1a7d4050568d83c265ae78c32ef30b ghc-tarballs/mingw-w64/x86_64/mingw-w64-x86_64-mpc-1.0.3-2-any.pkg.tar.xz -d15495e807e2a87b917febedbfb3f5b3 ghc-tarballs/mingw-w64/x86_64/mingw-w64-x86_64-mpfr-3.1.6-1-any.pkg.tar.xz -c5ffd1a27eb459242b46d76b066e557e ghc-tarballs/mingw-w64/x86_64/mingw-w64-x86_64-winpthreads-git-5.0.0.4850.d1662dc7-1-any.pkg.tar.xz +ef6ad2b29b92264c78d7ba6f0a875838 ghc-tarballs/mingw-w64/x86_64/mingw-w64-x86_64-headers-git-7.0.0.5490.9ec54ed1-1-any.pkg.tar.xz +623c059a9691ee7fc74b9e3f89b35782 ghc-tarballs/mingw-w64/x86_64/mingw-w64-x86_64-isl-0.21-1-any.pkg.tar.xz +29a39230c6208366b9d046fbe5bdde6f ghc-tarballs/mingw-w64/x86_64/mingw-w64-x86_64-libidn2-2.2.0-1-any.pkg.tar.xz +9953a82fd713f0c7ece69d9228238f4d ghc-tarballs/mingw-w64/x86_64/mingw-w64-x86_64-libwinpthread-git-7.0.0.5480.e14d23be-1-any.pkg.tar.xz +c3aa7f45926edaaafe3bba988e327271 ghc-tarballs/mingw-w64/x86_64/mingw-w64-x86_64-mpc-1.1.0-1-any.pkg.tar.xz +951d8046e65768e00b6dfe1bb6e23016 ghc-tarballs/mingw-w64/x86_64/mingw-w64-x86_64-mpfr-4.0.2-2-any.pkg.tar.xz +8360a1dd2f6f4fd518907530f0839a48 ghc-tarballs/mingw-w64/x86_64/mingw-w64-x86_64-windows-default-manifest-6.4-3-any.pkg.tar.xz +e7cf8d4ac9e9b3f79c16a09413dd1322 ghc-tarballs/mingw-w64/x86_64/mingw-w64-x86_64-winpthreads-git-7.0.0.5480.e14d23be-1-any.pkg.tar.xz 60c3a388478f411b7a0908441ebeb537 ghc-tarballs/mingw-w64/x86_64/mingw-w64-x86_64-zlib-1.2.8-9-any.pkg.tar.xz -b21d1681b61cf7a024e854096285b02e ghc-tarballs/perl/ghc-perl-1.tar.gz diff --git a/rts/RtsSymbols.c b/rts/RtsSymbols.c index e34fcf03f5..4da4258e95 100644 --- a/rts/RtsSymbols.c +++ b/rts/RtsSymbols.c @@ -97,6 +97,35 @@ * https://sourceforge.net/p/mingw-w64/wiki2/gnu%20printf/ * https://sourceforge.net/p/mingw-w64/discussion/723797/thread/55520785/ */ +/* Note [_iob_func symbol] + * ~~~~~~~~~~~~~~~~~~~~~~~ + * + * Microsoft in VS2013 to VS2015 transition made a backwards incompatible change + * to the stdio function __iob_func. + * + * They used to be defined as: + * + * #define stdin (&__iob_func()[0]) + * #define stdout (&__iob_func()[1]) + * #define stderr (&__iob_func()[2]) + * + * whereas now they're defined as: + * + * #define stdin (__acrt_iob_func(0)) + * #define stdout (__acrt_iob_func(1)) + * #define stderr (__acrt_iob_func(2)) + * + * Mingw-w64 followed along with the madness and so we have to deal with both + * version of these symbols. + * + * As such when you mix new and old libraries you get a missing symbols error + * for __acrt_iob_func. It then links against the PLT for the function but that + * no longer exists. Instead we forward the request for the PLT symbol to the + * symbol directly which is defined inline since we're using a newer compiler. + * + * See also: + * https://docs.microsoft.com/en-us/cpp/porting/visual-cpp-change-history-2003-2015?view=vs-2017#stdioh-and-conioh + */ #define RTS_MINGW_ONLY_SYMBOLS \ SymI_HasProto(stg_asyncReadzh) \ SymI_HasProto(stg_asyncWritezh) \ @@ -112,7 +141,12 @@ RTS_WIN64_ONLY(SymI_HasProto(__iob_func)) \ /* see Note [Symbols for MinGW's printf] */ \ SymI_HasProto(_lock_file) \ - SymI_HasProto(_unlock_file) + SymI_HasProto(_unlock_file) \ + /* See Note [_iob_func symbol] */ \ + RTS_WIN64_ONLY(SymI_HasProto_redirect( \ + __imp___acrt_iob_func, __rts_iob_func, true)) \ + RTS_WIN32_ONLY(SymI_HasProto_redirect( \ + __imp____acrt_iob_func, __rts_iob_func, true)) #define RTS_MINGW_COMPAT_SYMBOLS \ SymI_HasProto_deprecated(access) \ @@ -977,7 +1011,7 @@ #define SymE_HasProto(vvv) SymI_HasProto(vvv) #endif #define SymI_HasProto(vvv) /**/ -#define SymI_HasProto_redirect(vvv,xxx) /**/ +#define SymI_HasProto_redirect(vvv,xxx,weak) /**/ #define SymI_HasProto_deprecated(vvv) /**/ RTS_SYMBOLS RTS_RET_SYMBOLS @@ -1013,9 +1047,9 @@ RTS_LIBFFI_SYMBOLS // SymI_HasProto_redirect allows us to redirect references to one symbol to // another symbol. See newCAF/newRetainedCAF/newGCdCAF for an example. -#define SymI_HasProto_redirect(vvv,xxx) \ - { MAYBE_LEADING_UNDERSCORE_STR(#vvv), \ - (void*)(&(xxx)), false }, +#define SymI_HasProto_redirect(vvv,xxx,weak) \ + { MAYBE_LEADING_UNDERSCORE_STR(#vvv), \ + (void*)(&(xxx)), weak }, // SymI_HasProto_deprecated allows us to redirect references from their deprecated // names to the undeprecated ones. e.g. access -> _access. diff --git a/rts/RtsSymbols.h b/rts/RtsSymbols.h index 650b1f5fed..b17c56e0dd 100644 --- a/rts/RtsSymbols.h +++ b/rts/RtsSymbols.h @@ -25,3 +25,8 @@ typedef struct _RtsSymbolVal { } RtsSymbolVal; extern RtsSymbolVal rtsSyms[]; + +/* See Note [_iob_func symbol]. */ +#if defined(mingw32_HOST_OS) +extern const void* __rts_iob_func; +#endif diff --git a/rts/linker/PEi386.c b/rts/linker/PEi386.c index f2c49f6513..788b239d9f 100644 --- a/rts/linker/PEi386.c +++ b/rts/linker/PEi386.c @@ -275,6 +275,12 @@ const int default_alignment = 8; const int initHeapSizeMB = 15; static HANDLE code_heap = NULL; +/* See Note [_iob_func symbol] + In order to emulate __iob_func the memory location needs to point the + location of the I/O structures in memory. As such we need RODATA to contain + the pointer as a redirect. Essentially it's a DATA DLL reference. */ +const void* __rts_iob_func = (void*)&__acrt_iob_func; + /* Low Fragmentation Heap, try to prevent heap from increasing in size when space can simply be reclaimed. These are enums missing from mingw-w64's headers. */ @@ -758,7 +764,7 @@ pathchar* findSystemLibrary_PEi386( pathchar* dll_name ) HsPtr addLibrarySearchPath_PEi386(pathchar* dll_path) { HINSTANCE hDLL = LoadLibraryW(L"Kernel32.DLL"); - LPAddDLLDirectory AddDllDirectory = (LPAddDLLDirectory)GetProcAddress((HMODULE)hDLL, "AddDllDirectory"); + LPAddDLLDirectory AddDllDirectory = (LPAddDLLDirectory)(void*)GetProcAddress((HMODULE)hDLL, "AddDllDirectory"); HsPtr result = NULL; @@ -828,7 +834,7 @@ bool removeLibrarySearchPath_PEi386(HsPtr dll_path_index) if (dll_path_index != NULL) { HINSTANCE hDLL = LoadLibraryW(L"Kernel32.DLL"); - LPRemoveDLLDirectory RemoveDllDirectory = (LPRemoveDLLDirectory)GetProcAddress((HMODULE)hDLL, "RemoveDllDirectory"); + LPRemoveDLLDirectory RemoveDllDirectory = (LPRemoveDLLDirectory)(void*)GetProcAddress((HMODULE)hDLL, "RemoveDllDirectory"); if (RemoveDllDirectory) { result = RemoveDllDirectory(dll_path_index); diff --git a/rts/linker/PEi386.h b/rts/linker/PEi386.h index 538f132ab5..4c33dfd4d9 100644 --- a/rts/linker/PEi386.h +++ b/rts/linker/PEi386.h @@ -172,5 +172,4 @@ because we have no stdcall convention on 64 bits. See #9218 */ - #include "EndPrivate.h" diff --git a/rts/linker/elf_plt.h b/rts/linker/elf_plt.h index 1995d51207..0d99c7e462 100644 --- a/rts/linker/elf_plt.h +++ b/rts/linker/elf_plt.h @@ -1,10 +1,10 @@ #pragma once +#if defined(arm_HOST_ARCH) || defined(aarch64_HOST_ARCH) + #include "ghcplatform.h" #include <LinkerInternals.h> -#if defined(arm_HOST_ARCH) || defined(aarch64_HOST_ARCH) - #include "elf_plt_arm.h" #include "elf_plt_aarch64.h" diff --git a/rts/linker/elf_reloc_aarch64.c b/rts/linker/elf_reloc_aarch64.c index bb15576d06..35cc70b5bc 100644 --- a/rts/linker/elf_reloc_aarch64.c +++ b/rts/linker/elf_reloc_aarch64.c @@ -1,3 +1,7 @@ +#if defined(aarch64_HOST_ARCH) + +#if defined(OBJFORMAT_ELF) + #include <stdlib.h> #include <assert.h> #include "elf_compat.h" @@ -6,10 +10,6 @@ #include "elf_util.h" #include "elf_plt.h" -#if defined(aarch64_HOST_ARCH) - -#if defined(OBJFORMAT_ELF) - #define Page(x) ((x) & ~0xFFF) typedef uint64_t addr_t; diff --git a/rts/linker/elf_reloc_aarch64.h b/rts/linker/elf_reloc_aarch64.h index ac7a90ea16..06b41eff0e 100644 --- a/rts/linker/elf_reloc_aarch64.h +++ b/rts/linker/elf_reloc_aarch64.h @@ -1,9 +1,9 @@ #pragma once -#include "LinkerInternals.h" - #if defined(OBJFORMAT_ELF) +#include "LinkerInternals.h" + bool relocateObjectCodeAarch64(ObjectCode * oc); diff --git a/rts/win32/OSMem.c b/rts/win32/OSMem.c index 57997b1ac5..35fe72fd58 100644 --- a/rts/win32/OSMem.c +++ b/rts/win32/OSMem.c @@ -41,7 +41,7 @@ static block_rec* free_blocks = NULL; typedef LPVOID(WINAPI *VirtualAllocExNumaProc)(HANDLE, LPVOID, SIZE_T, DWORD, DWORD, DWORD); /* Cache NUMA API call. */ -VirtualAllocExNumaProc VirtualAllocExNuma; +VirtualAllocExNumaProc _VirtualAllocExNuma; void osMemInit(void) @@ -52,8 +52,8 @@ osMemInit(void) /* Resolve and cache VirtualAllocExNuma. */ if (osNumaAvailable() && RtsFlags.GcFlags.numa) { - VirtualAllocExNuma = (VirtualAllocExNumaProc)GetProcAddress(GetModuleHandleW(L"kernel32"), "VirtualAllocExNuma"); - if (!VirtualAllocExNuma) + _VirtualAllocExNuma = (VirtualAllocExNumaProc)(void*)GetProcAddress(GetModuleHandleW(L"kernel32"), "VirtualAllocExNuma"); + if (!_VirtualAllocExNuma) { sysErrorBelch( "osBindMBlocksToNode: VirtualAllocExNuma does not exist. How did you get this far?"); @@ -569,7 +569,7 @@ void osBindMBlocksToNode( On windows also -xb is broken, it does nothing so that can't be used to tweak it (see #12577). So for now, just let the OS decide. */ - temp = VirtualAllocExNuma( + temp = _VirtualAllocExNuma( GetCurrentProcess(), NULL, // addr? See base memory size, diff --git a/rts/win32/OSThreads.c b/rts/win32/OSThreads.c index c67d621bc2..0942382da2 100644 --- a/rts/win32/OSThreads.c +++ b/rts/win32/OSThreads.c @@ -111,7 +111,7 @@ createOSThread (OSThreadId* pId, char *name STG_UNUSED, HANDLE h; h = CreateThread ( NULL, /* default security attributes */ 0, - (LPTHREAD_START_ROUTINE)startProc, + (LPTHREAD_START_ROUTINE)(void*)startProc, param, 0, pId); @@ -314,7 +314,9 @@ getNumberOfProcessorsGroups (void) on the API being available. So we'll have to resolve manually. */ HMODULE kernel = GetModuleHandleW(L"kernel32"); - GetGroupCountProc GetActiveProcessorGroupCount = (GetGroupCountProc)GetProcAddress(kernel, "GetActiveProcessorGroupCount"); + GetGroupCountProc GetActiveProcessorGroupCount + = (GetGroupCountProc)(void*) + GetProcAddress(kernel, "GetActiveProcessorGroupCount"); n_groups = GetActiveProcessorGroupCount(); IF_DEBUG(scheduler, debugBelch("[*] Number of processor groups detected: %u\n", n_groups)); @@ -348,7 +350,9 @@ getProcessorsDistribution (void) on the API being available. So we'll have to resolve manually. */ HMODULE kernel = GetModuleHandleW(L"kernel32"); - GetItemCountProc GetActiveProcessorCount = (GetItemCountProc)GetProcAddress(kernel, "GetActiveProcessorCount"); + GetItemCountProc GetActiveProcessorCount + = (GetItemCountProc)(void*) + GetProcAddress(kernel, "GetActiveProcessorCount"); if (GetActiveProcessorCount) { @@ -449,7 +453,9 @@ getNumberOfProcessors (void) on the API being available. So we'll have to resolve manually. */ HMODULE kernel = GetModuleHandleW(L"kernel32"); - GetItemCountProc GetActiveProcessorCount = (GetItemCountProc)GetProcAddress(kernel, "GetActiveProcessorCount"); + GetItemCountProc GetActiveProcessorCount + = (GetItemCountProc)(void*) + GetProcAddress(kernel, "GetActiveProcessorCount"); if (GetActiveProcessorCount && !nproc) { nproc = GetActiveProcessorCount(ALL_PROCESSOR_GROUPS); @@ -516,7 +522,9 @@ setThreadAffinity (uint32_t n, uint32_t m) // cap N of M on the API being available. So we'll have to resolve manually. */ HMODULE kernel = GetModuleHandleW(L"kernel32"); - SetThreadGroupAffinityProc SetThreadGroupAffinity = (SetThreadGroupAffinityProc)GetProcAddress(kernel, "SetThreadGroupAffinity"); + SetThreadGroupAffinityProc SetThreadGroupAffinity + = (SetThreadGroupAffinityProc)(void*) + GetProcAddress(kernel, "SetThreadGroupAffinity"); #endif for (i = 0; i < n_groups; i++) @@ -564,8 +572,8 @@ interruptOSThread (OSThreadId id) sysErrorBelch("interruptOSThread: OpenThread"); stg_exit(EXIT_FAILURE); } - pCSIO = (PCSIO) GetProcAddress(GetModuleHandle(TEXT("Kernel32.dll")), - "CancelSynchronousIo"); + pCSIO = (PCSIO)(void*)GetProcAddress(GetModuleHandle(TEXT("Kernel32.dll")), + "CancelSynchronousIo"); if ( NULL != pCSIO ) { pCSIO(hdl); } else { diff --git a/testsuite/tests/ffi/should_run/T5594_c.c b/testsuite/tests/ffi/should_run/T5594_c.c index 9ef22e8efd..bcdb2262f3 100644 --- a/testsuite/tests/ffi/should_run/T5594_c.c +++ b/testsuite/tests/ffi/should_run/T5594_c.c @@ -1,8 +1,8 @@ -#include <stdio.h> #include "T5594_stub.h" - #include "HsFFI.h" +#include <stdio.h> + int main(int argc, char *argv[]) { hs_init(&argc, &argv); diff --git a/testsuite/tests/ffi/should_run/ffi002_c.c b/testsuite/tests/ffi/should_run/ffi002_c.c index ccf9ac99cf..5783fba051 100644 --- a/testsuite/tests/ffi/should_run/ffi002_c.c +++ b/testsuite/tests/ffi/should_run/ffi002_c.c @@ -1,8 +1,8 @@ -#include <stdio.h> #include "ffi002_stub.h" - #include "HsFFI.h" +#include <stdio.h> + int main(int argc, char *argv[]) { int i; diff --git a/testsuite/tests/ffi/should_run/fptr01_c.c b/testsuite/tests/ffi/should_run/fptr01_c.c index 0a0e1efe1c..07197c4172 100644 --- a/testsuite/tests/ffi/should_run/fptr01_c.c +++ b/testsuite/tests/ffi/should_run/fptr01_c.c @@ -1,9 +1,8 @@ -#include <stdio.h> - #include "HsFFI.h" - #include "fptr01.h" +#include <stdio.h> + void f( HsInt *i ) { printf( "f%d\n", (int)*i ); diff --git a/testsuite/tests/ffi/should_run/fptrfail01_c.c b/testsuite/tests/ffi/should_run/fptrfail01_c.c index 070a786e57..c620e7535c 100644 --- a/testsuite/tests/ffi/should_run/fptrfail01_c.c +++ b/testsuite/tests/ffi/should_run/fptrfail01_c.c @@ -1,9 +1,8 @@ -#include <stdio.h> - #include "HsFFI.h" - #include "fptrfail01.h" +#include <stdio.h> + void f( HsInt *i ) { printf( "f%d\n", (int)*i ); diff --git a/testsuite/tests/rts/linker/linker_error.c b/testsuite/tests/rts/linker/linker_error.c index 264c95d710..aad83686b0 100644 --- a/testsuite/tests/rts/linker/linker_error.c +++ b/testsuite/tests/rts/linker/linker_error.c @@ -1,7 +1,7 @@ #include "ghcconfig.h" +#include "Rts.h" #include <stdio.h> #include <stdlib.h> -#include "Rts.h" #if defined(mingw32_HOST_OS) #include <malloc.h> #endif diff --git a/testsuite/tests/rts/linker/linker_unload.c b/testsuite/tests/rts/linker/linker_unload.c index acf41cb86c..159570314a 100644 --- a/testsuite/tests/rts/linker/linker_unload.c +++ b/testsuite/tests/rts/linker/linker_unload.c @@ -1,7 +1,7 @@ #include "ghcconfig.h" +#include "Rts.h" #include <stdio.h> #include <stdlib.h> -#include "Rts.h" #include <string.h> #define ITERATIONS 1000 diff --git a/utils/fs/fs.c b/utils/fs/fs.c index 6644705ffe..4a761e5f9e 100644 --- a/utils/fs/fs.c +++ b/utils/fs/fs.c @@ -1,6 +1,6 @@ /* ----------------------------------------------------------------------------- * - * (c) Tamar Christina 2018 + * (c) Tamar Christina 2018-2019 * * Windows I/O routines for file opening. * @@ -24,16 +24,20 @@ #include <sys/stat.h> #include <sys/types.h> #include <share.h> +#include <errno.h> /* This function converts Windows paths between namespaces. More specifically It converts an explorer style path into a NT or Win32 namespace. - This has several caveats but they are caviats that are native to Windows and + This has several caveats but they are caveats that are native to Windows and not POSIX. See https://msdn.microsoft.com/en-us/library/windows/desktop/aa365247.aspx. Anything else such as raw device paths we leave untouched. The main benefit of doing any of this is that we can break the MAX_PATH restriction and also - access raw handles that we couldn't before. */ -static wchar_t* __hs_create_device_name (const wchar_t* filename) { + access raw handles that we couldn't before. + + The resulting string is dynamically allocated and so callers are expected to + free this string. */ +wchar_t* FS(create_device_name) (const wchar_t* filename) { const wchar_t* win32_dev_namespace = L"\\\\.\\"; const wchar_t* win32_file_namespace = L"\\\\?\\"; const wchar_t* nt_device_namespace = L"\\Device\\"; @@ -57,13 +61,31 @@ static wchar_t* __hs_create_device_name (const wchar_t* filename) { result[i] = L'\\'; } + /* We need to expand dos short paths as well. */ + DWORD nResult = GetLongPathNameW (result, NULL, 0) + 1; + wchar_t* temp = NULL; + if (nResult > 1) + { + temp = _wcsdup (result); + free (result); + result = malloc (nResult * sizeof (wchar_t)); + if (GetLongPathNameW (temp, result, nResult) == 0) + { + result = memcpy (result, temp, wcslen (temp)); + goto cleanup; + } + free (temp); + } + /* Now resolve any . and .. in the path or subsequent API calls may fail since Win32 will no longer resolve them. */ - DWORD nResult = GetFullPathNameW (result, 0, NULL, NULL) + 1; - wchar_t *temp = _wcsdup (result); + nResult = GetFullPathNameW (result, 0, NULL, NULL) + 1; + temp = _wcsdup (result); + free (result); result = malloc (nResult * sizeof (wchar_t)); if (GetFullPathNameW (temp, nResult, result, NULL) == 0) { + result = memcpy (result, temp, wcslen (temp)); goto cleanup; } @@ -84,6 +106,7 @@ static wchar_t* __hs_create_device_name (const wchar_t* filename) { /* Create new string. */ int bLen = wcslen (result) + wcslen (ns) + 1; temp = _wcsdup (result); + free (result); result = malloc (bLen * sizeof (wchar_t)); if (swprintf (result, bLen, L"%ls%ls", ns, temp) <= 0) { @@ -100,23 +123,64 @@ cleanup: return NULL; } -#define HAS_FLAG(a,b) ((a & b) == b) +static int setErrNoFromWin32Error (void); +/* Sets errno to the right error value and returns -1 to indicate the failure. + This function should only be called when the creation of the fd actually + failed and you want to return -1 for the fd. */ +static +int setErrNoFromWin32Error () { + switch (GetLastError()) { + case ERROR_SUCCESS: + errno = 0; + break; + case ERROR_ACCESS_DENIED: + case ERROR_FILE_READ_ONLY: + errno = EACCES; + break; + case ERROR_FILE_NOT_FOUND: + case ERROR_PATH_NOT_FOUND: + errno = ENOENT; + break; + case ERROR_FILE_EXISTS: + errno = EEXIST; + break; + case ERROR_NOT_ENOUGH_MEMORY: + case ERROR_OUTOFMEMORY: + errno = ENOMEM; + break; + case ERROR_INVALID_HANDLE: + errno = EBADF; + break; + case ERROR_INVALID_FUNCTION: + errno = EFAULT; + break; + default: + errno = EINVAL; + break; + } + return -1; +} + + +#define HAS_FLAG(a,b) (((a) & (b)) == (b)) int FS(swopen) (const wchar_t* filename, int oflag, int shflag, int pmode) { /* Construct access mode. */ + /* https://docs.microsoft.com/en-us/windows/win32/fileio/file-access-rights-constants */ DWORD dwDesiredAccess = 0; if (HAS_FLAG (oflag, _O_RDONLY)) - dwDesiredAccess |= GENERIC_READ | FILE_READ_DATA | FILE_READ_ATTRIBUTES; + dwDesiredAccess |= GENERIC_READ; if (HAS_FLAG (oflag, _O_RDWR)) - dwDesiredAccess |= GENERIC_WRITE | GENERIC_READ | FILE_READ_DATA | - FILE_WRITE_DATA | FILE_READ_ATTRIBUTES | - FILE_WRITE_ATTRIBUTES; - if (HAS_FLAG (oflag, _O_WRONLY)) - dwDesiredAccess|= GENERIC_WRITE | FILE_WRITE_DATA | FILE_WRITE_ATTRIBUTES; + dwDesiredAccess |= GENERIC_WRITE | GENERIC_READ; + if (HAS_FLAG (oflag, _O_WRONLY)) + dwDesiredAccess |= GENERIC_WRITE; + if (HAS_FLAG (oflag, _O_APPEND)) + dwDesiredAccess |= FILE_APPEND_DATA; /* Construct shared mode. */ - DWORD dwShareMode = FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE; + /* https://docs.microsoft.com/en-us/windows/win32/fileio/file-attribute-constants */ + DWORD dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE; if (HAS_FLAG (shflag, _SH_DENYRW)) dwShareMode &= ~(FILE_SHARE_READ | FILE_SHARE_WRITE); if (HAS_FLAG (shflag, _SH_DENYWR)) @@ -138,21 +202,33 @@ int FS(swopen) (const wchar_t* filename, int oflag, int shflag, int pmode) } /* Create file disposition. */ - DWORD dwCreationDisposition = OPEN_EXISTING; - if (HAS_FLAG (oflag, _O_CREAT)) - dwCreationDisposition = OPEN_ALWAYS; + /* https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfilea */ + DWORD dwCreationDisposition = 0; if (HAS_FLAG (oflag, (_O_CREAT | _O_EXCL))) - dwCreationDisposition = CREATE_NEW; - if (HAS_FLAG (oflag, _O_TRUNC) && !HAS_FLAG (oflag, _O_CREAT)) - dwCreationDisposition = TRUNCATE_EXISTING; + dwCreationDisposition |= CREATE_NEW; + else if (HAS_FLAG (oflag, _O_TRUNC | _O_CREAT)) + dwCreationDisposition |= CREATE_ALWAYS; + else if (HAS_FLAG (oflag, _O_TRUNC) && !HAS_FLAG (oflag, O_RDONLY)) + dwCreationDisposition |= TRUNCATE_EXISTING; + else if (HAS_FLAG (oflag, _O_APPEND | _O_CREAT)) + dwCreationDisposition |= OPEN_ALWAYS; + else if (HAS_FLAG (oflag, _O_APPEND)) + dwCreationDisposition |= OPEN_EXISTING; + else if (HAS_FLAG (oflag, _O_CREAT)) + dwCreationDisposition |= OPEN_ALWAYS; + else + dwCreationDisposition |= OPEN_EXISTING; /* Set file access attributes. */ DWORD dwFlagsAndAttributes = FILE_ATTRIBUTE_NORMAL; if (HAS_FLAG (oflag, _O_RDONLY)) dwFlagsAndAttributes |= 0; /* No special attribute. */ - if (HAS_FLAG (oflag, (_O_CREAT | _O_TEMPORARY))) - dwFlagsAndAttributes |= FILE_FLAG_DELETE_ON_CLOSE; - if (HAS_FLAG (oflag, (_O_CREAT | _O_SHORT_LIVED))) + if (HAS_FLAG (oflag, _O_TEMPORARY)) + { + dwFlagsAndAttributes |= FILE_FLAG_DELETE_ON_CLOSE; + dwShareMode |= FILE_SHARE_DELETE; + } + if (HAS_FLAG (oflag, _O_SHORT_LIVED)) dwFlagsAndAttributes |= FILE_ATTRIBUTE_TEMPORARY; if (HAS_FLAG (oflag, _O_RANDOM)) dwFlagsAndAttributes |= FILE_FLAG_RANDOM_ACCESS; @@ -162,6 +238,11 @@ int FS(swopen) (const wchar_t* filename, int oflag, int shflag, int pmode) if (dwFlagsAndAttributes != FILE_ATTRIBUTE_NORMAL) dwFlagsAndAttributes &= ~FILE_ATTRIBUTE_NORMAL; + /* Ensure we have shared read for files which are opened read-only. */ + if (HAS_FLAG (dwCreationDisposition, OPEN_EXISTING) + && ((dwDesiredAccess & (GENERIC_WRITE|GENERIC_READ)) == GENERIC_READ)) + dwShareMode |= FILE_SHARE_READ; + /* Set security attributes. */ SECURITY_ATTRIBUTES securityAttributes; ZeroMemory (&securityAttributes, sizeof(SECURITY_ATTRIBUTES)); @@ -169,41 +250,39 @@ int FS(swopen) (const wchar_t* filename, int oflag, int shflag, int pmode) securityAttributes.lpSecurityDescriptor = NULL; securityAttributes.nLength = sizeof(SECURITY_ATTRIBUTES); - wchar_t* _filename = __hs_create_device_name (filename); + wchar_t* _filename = FS(create_device_name) (filename); if (!_filename) return -1; HANDLE hResult = CreateFileW (_filename, dwDesiredAccess, dwShareMode, &securityAttributes, dwCreationDisposition, dwFlagsAndAttributes, NULL); + free (_filename); if (INVALID_HANDLE_VALUE == hResult) - return -1; + return setErrNoFromWin32Error (); /* Now we have a Windows handle, we have to convert it to an FD and apply the remaining flags. */ const int flag_mask = _O_APPEND | _O_RDONLY | _O_TEXT | _O_WTEXT; int fd = _open_osfhandle ((intptr_t)hResult, oflag & flag_mask); if (-1 == fd) - return -1; + return setErrNoFromWin32Error (); /* Finally we can change the mode to the requested one. */ const int mode_mask = _O_TEXT | _O_BINARY | _O_U16TEXT | _O_U8TEXT | _O_WTEXT; if ((oflag & mode_mask) && (-1 == _setmode (fd, oflag & mode_mask))) - return -1; + return setErrNoFromWin32Error (); return fd; } -FILE *FS(fwopen) (const wchar_t* filename, const wchar_t* mode) +int FS(translate_mode) (const wchar_t* mode) { - int shflag = 0; - int pmode = 0; - int oflag = 0; - + int oflag = 0; int len = wcslen (mode); int i; - #define IS_EXT(X) ((i < (len - 1)) && mode[i] == X) + #define IS_EXT(X) ((i < (len - 1)) && mode[i+1] == X) for (i = 0; i < len; i++) { @@ -261,7 +340,19 @@ FILE *FS(fwopen) (const wchar_t* filename, const wchar_t* mode) } #undef IS_EXT + return oflag; +} + +FILE *FS(fwopen) (const wchar_t* filename, const wchar_t* mode) +{ + int shflag = 0; + int pmode = 0; + int oflag = FS(translate_mode) (mode); + int fd = FS(swopen) (filename, oflag, shflag, pmode); + if (fd < 0) + return NULL; + FILE* file = _wfdopen (fd, mode); return file; } @@ -281,8 +372,150 @@ FILE *FS(fopen) (const char* filename, const char* mode) FILE *result = FS(fwopen) (w_filename, w_mode); free (w_filename); free (w_mode); + + return result; +} + +int FS(sopen) (const char* filename, int oflag, int shflag, int pmode) +{ + size_t len = mbstowcs (NULL, filename, 0); + wchar_t *w_filename = malloc (sizeof (wchar_t) * (len + 1)); + mbstowcs (w_filename, filename, len); + w_filename[len] = L'\0'; + + int result = FS(swopen) (w_filename, oflag, shflag, pmode); + free (w_filename); + + return result; +} + +int FS(_stat) (const char *path, struct _stat *buffer) +{ + size_t len = mbstowcs (NULL, path, 0); + wchar_t *w_path = malloc (sizeof (wchar_t) * (len + 1)); + mbstowcs (w_path, path, len); + w_path[len] = L'\0'; + + int result = FS(_wstat) (w_path, buffer); + free (w_path); + return result; } + +int FS(_stat64) (const char *path, struct __stat64 *buffer) +{ + size_t len = mbstowcs (NULL, path, 0); + wchar_t *w_path = malloc (sizeof (wchar_t) * (len + 1)); + mbstowcs (w_path, path, len); + w_path[len] = L'\0'; + + int result = FS(_wstat64) (w_path, buffer); + free (w_path); + + return result; +} + +static __time64_t ftToPosix(FILETIME ft) +{ + /* takes the last modified date. */ + LARGE_INTEGER date, adjust; + date.HighPart = ft.dwHighDateTime; + date.LowPart = ft.dwLowDateTime; + + /* 100-nanoseconds = milliseconds * 10000. */ + /* A UNIX timestamp contains the number of seconds from Jan 1, 1970, while the + FILETIME documentation says: Contains a 64-bit value representing the + number of 100-nanosecond intervals since January 1, 1601 (UTC). + + Between Jan 1, 1601 and Jan 1, 1970 there are 11644473600 seconds */ + adjust.QuadPart = 11644473600000 * 10000; + + /* removes the diff between 1970 and 1601. */ + date.QuadPart -= adjust.QuadPart; + + /* converts back from 100-nanoseconds to seconds. */ + return (__time64_t)date.QuadPart / 10000000; +} + +int FS(_wstat) (const wchar_t *path, struct _stat *buffer) +{ + ZeroMemory (buffer, sizeof (struct _stat)); + wchar_t* _path = FS(create_device_name) (path); + if (!_path) + return -1; + + /* Construct shared mode. */ + DWORD dwShareMode = FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE; + DWORD dwDesiredAccess = FILE_READ_ATTRIBUTES; + DWORD dwFlagsAndAttributes = FILE_FLAG_BACKUP_SEMANTICS; + DWORD dwCreationDisposition = OPEN_EXISTING; + + SECURITY_ATTRIBUTES securityAttributes; + ZeroMemory (&securityAttributes, sizeof(SECURITY_ATTRIBUTES)); + securityAttributes.bInheritHandle = false; + securityAttributes.lpSecurityDescriptor = NULL; + securityAttributes.nLength = sizeof(SECURITY_ATTRIBUTES); + + HANDLE hResult + = CreateFileW (_path, dwDesiredAccess, dwShareMode, &securityAttributes, + dwCreationDisposition, dwFlagsAndAttributes, NULL); + + if (INVALID_HANDLE_VALUE == hResult) + { + free (_path); + return setErrNoFromWin32Error (); + } + + WIN32_FILE_ATTRIBUTE_DATA finfo; + ZeroMemory (&finfo, sizeof (WIN32_FILE_ATTRIBUTE_DATA)); + if(!GetFileAttributesExW (_path, GetFileExInfoStandard, &finfo)) + { + free (_path); + CloseHandle (hResult); + return setErrNoFromWin32Error (); + } + + unsigned short mode = _S_IREAD; + + if (finfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) + mode |= (_S_IFDIR | _S_IEXEC); + else + { + mode |= _S_IFREG; + DWORD type; + if (GetBinaryTypeW (_path, &type)) + mode |= _S_IEXEC; + } + + if (!(finfo.dwFileAttributes & FILE_ATTRIBUTE_READONLY)) + mode |= _S_IWRITE; + + buffer->st_mode = mode; + buffer->st_nlink = 1; + buffer->st_size = ((uint64_t)finfo.nFileSizeHigh << 32) + finfo.nFileSizeLow; + buffer->st_atime = ftToPosix (finfo.ftLastAccessTime); + buffer->st_mtime = buffer->st_ctime = ftToPosix (finfo.ftLastWriteTime); + free (_path); + CloseHandle (hResult); + return 0; +} + +int FS(_wstat64) (const wchar_t *path, struct __stat64 *buffer) +{ + struct _stat buf; + ZeroMemory (buffer, sizeof (struct __stat64)); + + int result = FS(_wstat) (path, &buf); + + buffer->st_mode = buf.st_mode; + buffer->st_nlink = 1; + buffer->st_size = buf.st_size; + buffer->st_atime = buf.st_atime; + buffer->st_mtime = buf.st_mtime; + + return result; +} + #else FILE *FS(fopen) (const char* filename, const char* mode) { diff --git a/utils/fs/fs.h b/utils/fs/fs.h index ab2eded2a1..3931e6e03e 100644 --- a/utils/fs/fs.h +++ b/utils/fs/fs.h @@ -1,6 +1,6 @@ /* ----------------------------------------------------------------------------- * - * (c) Tamar Christina 2018 + * (c) Tamar Christina 2018-2019 * * Windows I/O routines for file opening. * @@ -25,11 +25,18 @@ #if defined(_WIN32) #include <wchar.h> - +wchar_t* FS(create_device_name) (const wchar_t*); +int FS(translate_mode) (const wchar_t*); int FS(swopen) (const wchar_t* filename, int oflag, int shflag, int pmode); +int FS(sopen) (const char* filename, int oflag, + int shflag, int pmode); FILE *FS(fwopen) (const wchar_t* filename, const wchar_t* mode); FILE *FS(fopen) (const char* filename, const char* mode); +int FS(_stat) (const char *path, struct _stat *buffer); +int FS(_stat64) (const char *path, struct __stat64 *buffer); +int FS(_wstat) (const wchar_t *path, struct _stat *buffer); +int FS(_wstat64) (const wchar_t *path, struct __stat64 *buffer); #else FILE *FS(fopen) (const char* filename, const char* mode); diff --git a/utils/ghc-cabal/Main.hs b/utils/ghc-cabal/Main.hs index 5827331c9c..0962f9ccde 100644 --- a/utils/ghc-cabal/Main.hs +++ b/utils/ghc-cabal/Main.hs @@ -385,7 +385,23 @@ generate directory distdir config_args fixupRtsLibName x = x transitiveDepNames = map (display . packageName) transitive_dep_ids - libraryDirs = forDeps Installed.libraryDirs + -- Note [Msys2 path translation bug]. + -- Msys2 has an annoying bug in their path conversion code. + -- Officially anything starting with a drive letter should not be + -- subjected to path translations, however it seems to only consider + -- E:\\ and E:// to be Windows paths. Mixed mode paths such as E:/ + -- that are produced here get corrupted. + -- + -- Tamar@Rage /t/translate> ./a.exe -optc-I"E://ghc-dev/msys64/" + -- path: -optc-IE://ghc-dev/msys64/ + -- Tamar@Rage /t/translate> ./a.exe -optc-I"E:ghc-dev/msys64/" + -- path: -optc-IE:ghc-dev/msys64/ + -- Tamar@Rage /t/translate> ./a.exe -optc-I"E:\ghc-dev/msys64/" + -- path: -optc-IE:\ghc-dev/msys64/ + -- + -- As such, let's just normalize the filepaths which is a good thing + -- to do anyway. + libraryDirs = map normalise $ forDeps Installed.libraryDirs -- The mkLibraryRelDir function is a bit of a hack. -- Ideally it should be handled in the makefiles instead. mkLibraryRelDir "rts" = "rts/dist/build" @@ -402,7 +418,8 @@ generate directory distdir config_args injectDistInstall x | takeBaseName x == "include" = [x, takeDirectory x ++ "/dist-install/build/" ++ takeBaseName x] injectDistInstall x = [x] - wrappedIncludeDirs <- wrap $ concatMap injectDistInstall $ forDeps Installed.includeDirs + -- See Note [Msys2 path translation bug]. + wrappedIncludeDirs <- wrap $ map normalise $ concatMap injectDistInstall $ forDeps Installed.includeDirs let variablePrefix = directory ++ '_':distdir mods = map display modules |