diff --git a/lang/ghc810/Makefile b/lang/ghc810/Makefile index 0105166c8178..f6daff8f66f6 100644 --- a/lang/ghc810/Makefile +++ b/lang/ghc810/Makefile @@ -1,30 +1,31 @@ +PORTREVISION= 1 PKGNAMESUFFIX= 810 LIB_DEPENDS= ${GMP_LIB_DEPENDS} CONFIGURE_ARGS= ${GMP_CONFIGURE_WITH:C/^/--with-/} OPTIONS_DEFINE= DYNAMIC PROFILE SLAVE_BUILD_MK= BUILD_SPHINX_HTML=NO GHC_VERSION= 8.10.7 LLVM_VERSION= 10 BASE_PACKAGES= Cabal-3.2.1.0 array-0.5.4.0 base-4.14.3.0 binary-0.8.8.0 \ bytestring-0.10.12.0 containers-0.6.5.1 deepseq-1.4.4.0 \ directory-1.3.6.0 exceptions-0.10.4 filepath-1.4.2.1 \ ghc-${GHC_VERSION} ghc-compact-0.1.0.0 \ ghc-prim-0.6.1 haskeline-0.8.2 hpc-0.6.1.0 \ integer-gmp-1.0.3.0 mtl-2.2.2 parsec-3.1.14.0 pretty-1.1.3.6 \ process-1.6.13.2 stm-2.5.0.1 template-haskell-2.16.0.0 \ terminfo-0.4.1.4 text-1.2.4.1 time-1.9.3 \ transformers-0.5.6.2 unix-2.7.2.2 xhtml-3000.2.2.1 EXTRA_PATCHES= ${MASTERDIR}/files/extra-utils_llvm-targets_gen-data-layout.sh \ ${MASTERDIR}/files/patch-llvm-targets MASTERDIR= ${.CURDIR}/../ghc PATCHDIR= ${.CURDIR}/files PLIST= ${.CURDIR}/pkg-plist .include "${MASTERDIR}/Makefile" diff --git a/lang/ghc810/files/patch-linker-iconv.diff b/lang/ghc810/files/patch-linker-iconv.diff new file mode 100644 index 000000000000..a3f7a70fb528 --- /dev/null +++ b/lang/ghc810/files/patch-linker-iconv.diff @@ -0,0 +1,89 @@ +https://gitlab.haskell.org/ghc/ghc/-/commit/66d2e927842653fbc1cf2e6f997f443c78c2203b + +diff --git a/rts/Linker.c b/rts/Linker.c +index 1faff3b3716dd6de440071c89d0dafa471657962..12d5418d02a95893b14a619be10b5cd49a054f1a 100644 +--- rts/Linker.c ++++ rts/Linker.c +@@ -80,6 +80,33 @@ + #if defined(dragonfly_HOST_OS) + #include + #endif ++ ++/* ++ * Note [iconv and FreeBSD] ++ * ~~~~~~~~~~~~~~~~~~~~~~~~ ++ * ++ * On FreeBSD libc.so provides an implementation of the iconv_* family of ++ * functions. However, due to their implementation, these symbols cannot be ++ * resolved via dlsym(); rather, they can only be resolved using the ++ * explicitly-versioned dlvsym(). ++ * ++ * This is problematic for the RTS linker since we may be asked to load ++ * an object that depends upon iconv. To handle this we include a set of ++ * fallback cases for these functions, allowing us to resolve them to the ++ * symbols provided by the libc against which the RTS is linked. ++ * ++ * See #20354. ++ */ ++ ++#if defined(freebsd_HOST_OS) ++extern void iconvctl(); ++extern void iconv_open_into(); ++extern void iconv_open(); ++extern void iconv_close(); ++extern void iconv_canonicalize(); ++extern void iconv(); ++#endif ++ + /* + Note [runtime-linker-support] + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +@@ -637,6 +664,10 @@ internal_dlsym(const char *symbol) { + } + RELEASE_LOCK(&dl_mutex); + ++ IF_DEBUG(linker, debugBelch("internal_dlsym: looking for symbol '%s' in special cases\n", symbol)); ++# define SPECIAL_SYMBOL(sym) \ ++ if (strcmp(symbol, #sym) == 0) return (void*)&sym; ++ + # if defined(HAVE_SYS_STAT_H) && defined(linux_HOST_OS) && defined(__GLIBC__) + // HACK: GLIBC implements these functions with a great deal of trickery where + // they are either inlined at compile time to their corresponding +@@ -646,18 +677,28 @@ internal_dlsym(const char *symbol) { + // We borrow the approach that the LLVM JIT uses to resolve these + // symbols. See http://llvm.org/PR274 and #7072 for more info. + +- IF_DEBUG(linker, debugBelch("internal_dlsym: looking for symbol '%s' in GLIBC special cases\n", symbol)); ++ SPECIAL_SYMBOL(stat); ++ SPECIAL_SYMBOL(fstat); ++ SPECIAL_SYMBOL(lstat); ++ SPECIAL_SYMBOL(stat64); ++ SPECIAL_SYMBOL(fstat64); ++ SPECIAL_SYMBOL(lstat64); ++ SPECIAL_SYMBOL(atexit); ++ SPECIAL_SYMBOL(mknod); ++# endif + +- if (strcmp(symbol, "stat") == 0) return (void*)&stat; +- if (strcmp(symbol, "fstat") == 0) return (void*)&fstat; +- if (strcmp(symbol, "lstat") == 0) return (void*)&lstat; +- if (strcmp(symbol, "stat64") == 0) return (void*)&stat64; +- if (strcmp(symbol, "fstat64") == 0) return (void*)&fstat64; +- if (strcmp(symbol, "lstat64") == 0) return (void*)&lstat64; +- if (strcmp(symbol, "atexit") == 0) return (void*)&atexit; +- if (strcmp(symbol, "mknod") == 0) return (void*)&mknod; ++ // See Note [iconv and FreeBSD] ++# if defined(freebsd_HOST_OS) ++ SPECIAL_SYMBOL(iconvctl); ++ SPECIAL_SYMBOL(iconv_open_into); ++ SPECIAL_SYMBOL(iconv_open); ++ SPECIAL_SYMBOL(iconv_close); ++ SPECIAL_SYMBOL(iconv_canonicalize); ++ SPECIAL_SYMBOL(iconv); + # endif + ++#undef SPECIAL_SYMBOL ++ + // we failed to find the symbol + return NULL; + }