On Mon, 01 Oct 2012, Matthias Kilian wrote: > Hi, > > On Mon, Oct 01, 2012 at 04:32:51PM +0200, David Coppa wrote: > > > >> Loading package integer-gmp ... linking ... ghc: > > > >> /usr/local/lib/libgmp.a: unknown symbol `__guard_local' > [...] > > > I applied the patches to both amd64 and i386, the two failing ports > > > hs-vector and hs-type-level built on i386, not on amd64. > [...] > > The diff below, replacing SymE_NeedsProto with SymI_NeedsProto, > > makes things work for me on amd64 (tested with hs-vector and > > hs-type-level)... > > For me, both versions (using either SymI_NeedsProto or SymE_NeedsProto) > *appear* to work (on amd64). I don't understand why the SymE_NeedsProto > did fail for Nigel on amd64. > > Note: if you don't want to read all the details, just skip forward > to "What can we do?" ;-) > > Anyway, that's not important, because both "fixes" are wrong, because > they fix the linker error (unknown symbol `__guard_local') but cause > random crashes at runtime if there's heavy enough use of libgmp.a (that > just tries to calculate the 400th fibonacci number): > > $ cd $(make show=WRKBUILD) > $ echo 'let f = 1 : 1 : zipWith (+) f (tail f) in f !! 400' | > ./inplace/bin/ghc-stage2 --interactive > GHCi, version 7.4.2: http://www.haskell.org/ghc/ :? for help > Loading package ghc-prim ... linking ... done. > Loading package integer-gmp ... linking ... done. > Loading package base ... linking ... done. > Prelude> > 284812298108489611757988937681460995615380088782304890986477195645969271404032323901 > Prelude> Leaving GHCi. > $ echo 'let f = 1 : 1 : zipWith (+) f (tail f) in f !! 400' | > ./inplace/bin/ghc-stage2 --interactive > GHCi, version 7.4.2: http://www.haskell.org/ghc/ :? for help > Loading package ghc-prim ... linking ... done. > Loading package integer-gmp ... linking ... done. > Loading package base ... linking ... done. > Prelude> Segmentation fault (core dumped)
Hi again, After three days of puking blood while wandering inside the GHC build system, I think I've found a possible solution to this messy problem... First, the "unknown symbol `__guard_local'" error is an entirely different beast than the random crashes at runtime with libgmp.a. Good news is kili's "SymE_NeedsProto" workaround effectively fixes it. On the other hand, the root cause of segmentation faults at runtime is that ghc requires a patched gmp library with customized memory allocation functions. Quoting from http://hackage.haskell.org/trac/ghc/wiki/ReplacingGMPNotes/TheCurrentGMPImplementation: ---8<--- The most insidious and unique feature of the GHC implementation with GMP is memory management. GHC uses the special memory functions in GMP ( mp_set_memory_functions( (*alloc)(), (*realloc)(), (*dealloc)() ) to let GMP use GHC's own garbage collector. The memory functions are implemented in rts/sm/Storage.c as: static void* stgAllocForGMP (size_t size_in_bytes); static void stgDeallocForGMP (void *ptr STG_UNUSED, size_t size STG_UNUSED); static void* stgReallocForGMP (void *ptr, size_t old_size, size_t new_size); These special allocation functions bring most GMP memory usage into the GHC heap but do not seem that efficient otherwise. (I could be wrong --PDT.) Allocation uses the internal allocate() interface, so no garbage collection is performed during a GMP operation. Note that GMP operations may use these functions to allocate more memory themselves, after being called from Haskell code. The memory allocated is a simple array of words (W_), rounded up to a whole number. ---8<--- And indeed: $ nm /usr/ports/pobj/ghc-7.4.2-no_doc/ghc-7.4.2/libraries/integer-gmp/gmp/libgmp.a | grep stg U stgAllocForGMP U stgDeallocForGMP U stgReallocForGMP But since /usr/local/lib/libgmp.a comes from a vanilla gmp-5.0.2, we're totally belly-up! As a proof, try this: $ cd /usr/ports/devel/gmp $ make clean patch $ cd /usr/ports/pobj/gmp-5.0.2/gmp-5.0.2/ $ patch -NEp1 -i /usr/ports/pobj/ghc-7.4.2-no_doc/ghc-7.4.2/libraries/integer-gmp/gmp/tarball/patch $ cd - $ make fake $ sudo cp /usr/ports/pobj/gmp-5.0.2/fake-amd64/usr/local/lib/libgmp.a /usr/local/lib/libgmp.a and then repeat the fibonacci test: $ ghci GHCi, version 7.4.2: http://www.haskell.org/ghc/ :? for help Loading package ghc-prim ... linking ... done. Loading package integer-gmp ... linking ... done. Loading package base ... linking ... done. Prelude> let fibs = 0 : 1 : zipWith (+) fibs (tail fibs) Prelude> let fib n = fibs!!n Prelude> fib 10000 33644764876431783266621612005107543310302148460680063906564769974680081442166662368155595513633734025582065332680836159373734790483865268263040892463056431887354544369559827491606602099884183933864652731300088830269235673613135117579297437854413752130520504347701602264758318906527890855154366159582987279682987510631200575428783453215515103870818298969791613127856265033195487140214287532698187962046936097879900350962302291026368131493195275630227837628441540360584402572114334961180023091208287046088923962328835461505776583271252546093591128203925285393434620904245248929403901706233888991085841065183173360437470737908552631764325733993712871937587746897479926305837065742830161637408969178426378624212835258112820516370298089332099905707920064367426202389783111470054074998459250360633560933883831923386783056136435351892133279732908133732642652633989763922723407882928177953580570993691049175470808931841056146322338217465637321248226383092103297701648054726243842374862411453093812206564914032751086643394517512161526545361333111314042436854805106765843493523836959653428071768775328348234345557366719731392746273629108210679280784718035329131176778924659089938635459327894523777674406192240337638674004021330343297496902028328145933418826817683893072003634795623117103101291953169794607632737589253530772552375943788434504067715555779056450443016640119462580972216729758615026968443146952034614932291105970676243268515992834709891284706740862008587135016260312071903172086094081298321581077282076353186624611278245537208532365305775956430072517744315051539600905168603220349163222640885248852433158051534849622434848299380905070483482449327453732624567755879089187190803662058009594743150052402532709746995318770724376825907419939632265984147498193609285223945039707165443156421328157688908058783183404917434556270520223564846495196112460268313970975069382648706613264507665074611512677522748621598642530711298441182622661057163515069260029861704945425047491378115154139941550671256271197133252763631939606902895650288268608362241082050562430701794976171121233066073310059947366875 Prelude> Leaving GHCi. $ How to properly fix this problem (ports-wise speaking)? A working solution is to use the gmp library that comes bundled with GHC. While doing a build with my diff, for mysterious causes I caught another error: ---8<--- "inplace/bin/ghc-stage1" -o utils/hsc2hs/dist-install/build/tmp/hsc2hs -H32m -O -hide-all-packages -i -iutils/hsc2hs/. -iutils/hsc2hs/dist-install/build -iutils/hsc2hs/dist-install/build/autogen -Iutils/hsc2hs/dist-install/build -Iutils/hsc2hs/dist-install/build/autogen -optP-include -optPutils/hsc2hs/dist-install/build/autogen/cabal_macros.h -package base-4.5.1.0 -package containers-0.4.2.1 -package directory-1.1.0.2 -package process-1.1.0.1 -XHaskell98 -XCPP -XForeignFunctionInterface -no-user-package-conf -rtsopts -odir utils/hsc2hs/dist-install/build -hidir utils/hsc2hs/dist-install/build -stubdir utils/hsc2hs/dist-install/build -hisuf hi -osuf o -hcsuf hc utils/hsc2hs/dist-install/build/Main.o utils/hsc2hs/dist-install/build/HSCParser.o utils/hsc2hs/dist-install/build/DirectCodegen.o utils/hsc2hs/dist-install/build/CrossCodegen.o utils/hsc2hs/dist-install/build/UtilsCodegen.o utils/hsc2hs/dist-install/build/Common.o utils/hsc2hs/dist-install/build/C.o utils/hsc2hs/dist-install/build/Flags.o utils/hsc2hs/dist-install/build/Paths_hsc2hs.o /usr/ports/pobj/ghc-7.4.2-no_doc/ghc-7.4.2/rts/dist/build/libHSrts.a(RtsFlags.o): In function `copyArg': RtsFlags.c:(.text+0x2bd): warning: warning: strcpy() is almost always misused, please use strlcpy() /usr/ports/pobj/ghc-7.4.2-no_doc/ghc-7.4.2/rts/dist/build/libHSrts.a(RtsUtils.o): In function `showStgWord64': RtsUtils.c:(.text+0x329): warning: warning: sprintf() is often misused, please use snprintf() /usr/ports/pobj/ghc-7.4.2-no_doc/ghc-7.4.2/rts/dist/build/libHSrts.a(ffi64.o): In function `ffi_call': ../src/x86/ffi64.c:486:0: undefined reference to `ffi_call_unix64' /usr/ports/pobj/ghc-7.4.2-no_doc/ghc-7.4.2/rts/dist/build/libHSrts.a(ffi64.o): In function `ffi_prep_closure_loc': ../src/x86/ffi64.c:512:0: undefined reference to `ffi_closure_unix64' ---8<--- So I fixed this too... Here's the diff, comments are highly appreciated. Ciao, David Index: Makefile =================================================================== RCS file: /cvs/ports/lang/ghc/Makefile,v retrieving revision 1.82 diff -u -p -r1.82 Makefile --- Makefile 5 Oct 2012 19:28:12 -0000 1.82 +++ Makefile 10 Oct 2012 12:11:02 -0000 @@ -11,7 +11,7 @@ COMMENT-doc = documentation for GHC DISTNAME = ghc-${MODGHC_VER} PKGNAME-main = ghc-${MODGHC_VER} -REVISION-main = 0 +REVISION-main = 1 PKGNAME-doc = ghc-doc-${MODGHC_VER} CATEGORIES = lang devel HOMEPAGE = http://www.haskell.org/ghc/ @@ -44,11 +44,11 @@ PKG_ARCH-doc = * BUILD_DEPENDS = archivers/gtar \ textproc/docbook-xsl LIB_DEPENDS-doc = -LIB_DEPENDS-main = ${LIB_DEPENDS} devel/gmp +LIB_DEPENDS-main = ${LIB_DEPENDS} RUN_DEPENDS-doc = RUN_DEPENDS-main = -WANTLIB-main = ${WANTLIB} c gmp m ncursesw pthread util +WANTLIB-main = ${WANTLIB} c m ncursesw pthread util WANTLIB-doc = @@ -78,9 +78,7 @@ USE_GMAKE = Yes USE_GROFF = Yes CONFIGURE_STYLE = gnu -CONFIGURE_ARGS += --with-gmp-includes=${LOCALBASE}/include \ - --with-gmp-libraries=${LOCALBASE}/lib \ - --with-iconv-includes=${LOCALBASE}/include \ +CONFIGURE_ARGS += --with-iconv-includes=${LOCALBASE}/include \ --with-iconv-libraries=${LOCALBASE}/lib CONFIGURE_ENV = CONF_CC_OPTS_STAGE0="-fno-pie -nopie" \ CONF_CC_OPTS_STAGE1="-fno-pie -nopie" \ Index: patches/patch-libffi_ghc_mk =================================================================== RCS file: patches/patch-libffi_ghc_mk diff -N patches/patch-libffi_ghc_mk --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ patches/patch-libffi_ghc_mk 10 Oct 2012 12:11:02 -0000 @@ -0,0 +1,15 @@ +$OpenBSD$ + +Unbreak the build on OpenBSD/amd64: gcc supports @unwind sections +while GHC's linker does not + +--- libffi/ghc.mk.orig Wed Jun 6 19:10:25 2012 ++++ libffi/ghc.mk Wed Oct 10 11:25:30 2012 +@@ -78,6 +78,7 @@ $(libffi_STAMP_CONFIGURE): $(TOUCH_DEP) + NM=$(NM) \ + CFLAGS="$(SRC_CC_OPTS) $(CONF_CC_OPTS_STAGE1) -w" \ + LDFLAGS="$(SRC_LD_OPTS) $(CONF_GCC_LINKER_OPTS_STAGE1) -w" \ ++ libffi_cv_as_x86_64_unwind_section_type=no \ + "$(SHELL)" configure \ + --prefix=$(TOP)/libffi/build/inst \ + --enable-static=yes \ Index: patches/patch-libraries_integer-gmp_configure =================================================================== RCS file: patches/patch-libraries_integer-gmp_configure diff -N patches/patch-libraries_integer-gmp_configure --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ patches/patch-libraries_integer-gmp_configure 10 Oct 2012 12:11:02 -0000 @@ -0,0 +1,100 @@ +$OpenBSD$ + +Coerce GHC to use the bundled gmp library + +--- libraries/integer-gmp/configure.orig Tue Oct 9 22:08:06 2012 ++++ libraries/integer-gmp/configure Tue Oct 9 22:11:52 2012 +@@ -2982,92 +2982,7 @@ fi + + + +-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for __gmpz_fdiv_qr in -lgmp" >&5 +-$as_echo_n "checking for __gmpz_fdiv_qr in -lgmp... " >&6; } +-if test "${ac_cv_lib_gmp___gmpz_fdiv_qr+set}" = set; then : +- $as_echo_n "(cached) " >&6 +-else +- ac_check_lib_save_LIBS=$LIBS +-LIBS="-lgmp $LIBS" +-cat confdefs.h - <<_ACEOF >conftest.$ac_ext +-/* end confdefs.h. */ +- +-/* Override any GCC internal prototype to avoid an error. +- Use char because int might match the return type of a GCC +- builtin and then its argument prototype would still apply. */ +-#ifdef __cplusplus +-extern "C" +-#endif +-char __gmpz_fdiv_qr (); +-int +-main () +-{ +-return __gmpz_fdiv_qr (); +- ; +- return 0; +-} +-_ACEOF +-if ac_fn_c_try_link "$LINENO"; then : +- ac_cv_lib_gmp___gmpz_fdiv_qr=yes +-else +- ac_cv_lib_gmp___gmpz_fdiv_qr=no +-fi +-rm -f core conftest.err conftest.$ac_objext \ +- conftest$ac_exeext conftest.$ac_ext +-LIBS=$ac_check_lib_save_LIBS +-fi +-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_gmp___gmpz_fdiv_qr" >&5 +-$as_echo "$ac_cv_lib_gmp___gmpz_fdiv_qr" >&6; } +-if test "x$ac_cv_lib_gmp___gmpz_fdiv_qr" = x""yes; then : +- HaveLibGmp=YES; GMP_LIBS=gmp +-else +- HaveLibGmp=NO; GMP_LIBS= +-fi +- +-if test "$HaveLibGmp" = "NO"; then +-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for __gmpz_fdiv_qr in -lgmp3" >&5 +-$as_echo_n "checking for __gmpz_fdiv_qr in -lgmp3... " >&6; } +-if test "${ac_cv_lib_gmp3___gmpz_fdiv_qr+set}" = set; then : +- $as_echo_n "(cached) " >&6 +-else +- ac_check_lib_save_LIBS=$LIBS +-LIBS="-lgmp3 $LIBS" +-cat confdefs.h - <<_ACEOF >conftest.$ac_ext +-/* end confdefs.h. */ +- +-/* Override any GCC internal prototype to avoid an error. +- Use char because int might match the return type of a GCC +- builtin and then its argument prototype would still apply. */ +-#ifdef __cplusplus +-extern "C" +-#endif +-char __gmpz_fdiv_qr (); +-int +-main () +-{ +-return __gmpz_fdiv_qr (); +- ; +- return 0; +-} +-_ACEOF +-if ac_fn_c_try_link "$LINENO"; then : +- ac_cv_lib_gmp3___gmpz_fdiv_qr=yes +-else +- ac_cv_lib_gmp3___gmpz_fdiv_qr=no +-fi +-rm -f core conftest.err conftest.$ac_objext \ +- conftest$ac_exeext conftest.$ac_ext +-LIBS=$ac_check_lib_save_LIBS +-fi +-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_gmp3___gmpz_fdiv_qr" >&5 +-$as_echo "$ac_cv_lib_gmp3___gmpz_fdiv_qr" >&6; } +-if test "x$ac_cv_lib_gmp3___gmpz_fdiv_qr" = x""yes; then : +- HaveLibGmp=YES; GMP_LIBS=gmp3 +-else +- HaveLibGmp=NO; GMP_LIBS= +-fi +- +-fi ++HaveLibGmp=NO; GMP_LIBS= + + + case $target_os in Index: patches/patch-rts_Linker_c =================================================================== RCS file: patches/patch-rts_Linker_c diff -N patches/patch-rts_Linker_c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ patches/patch-rts_Linker_c 10 Oct 2012 12:11:02 -0000 @@ -0,0 +1,37 @@ +$OpenBSD$ + +Workaround error: unknown symbol '__guard_local' + +--- rts/Linker.c.orig Tue Oct 9 21:15:55 2012 ++++ rts/Linker.c Tue Oct 9 21:29:11 2012 +@@ -563,6 +563,14 @@ typedef struct _RtsSymbolVal { + #define RTS_DARWIN_ONLY_SYMBOLS + #endif + ++#if defined(openbsd_HOST_OS) ++#define RTS_OPENBSD_ONLY_SYMBOLS \ ++ SymE_NeedsProto(__guard_local) \ ++ SymE_NeedsProto(__stack_smash_handler) ++#else ++#define RTS_OPENBSD_ONLY_SYMBOLS ++#endif ++ + #ifndef SMP + # define MAIN_CAP_SYM SymI_HasProto(MainCapability) + #else +@@ -1084,6 +1092,7 @@ RTS_POSIX_ONLY_SYMBOLS + RTS_MINGW_ONLY_SYMBOLS + RTS_CYGWIN_ONLY_SYMBOLS + RTS_DARWIN_ONLY_SYMBOLS ++RTS_OPENBSD_ONLY_SYMBOLS + RTS_LIBGCC_SYMBOLS + RTS_LIBFFI_SYMBOLS + #undef SymI_NeedsProto +@@ -1119,6 +1128,7 @@ static RtsSymbolVal rtsSyms[] = { + RTS_MINGW_ONLY_SYMBOLS + RTS_CYGWIN_ONLY_SYMBOLS + RTS_DARWIN_ONLY_SYMBOLS ++ RTS_OPENBSD_ONLY_SYMBOLS + RTS_LIBGCC_SYMBOLS + RTS_LIBFFI_SYMBOLS + #if defined(darwin_HOST_OS) && defined(i386_HOST_ARCH)
