Repository : ssh://darcs.haskell.org//srv/darcs/ghc On branch : master
http://hackage.haskell.org/trac/ghc/changeset/3e6c9308777caf83122baef504028d619d3dd588 >--------------------------------------------------------------- commit 3e6c9308777caf83122baef504028d619d3dd588 Author: Erik de Castro Lopo <[email protected]> Date: Tue Jul 31 05:53:49 2012 +1000 Fix GHCi segfault during startup on linux-powerpc (#2972). Slightly modified version of a patch from Ben Collins <[email protected]> who did the final debugging that showed the segfault was being caused the memory protection mechanism. Due to the requirement of "jump islands" to handle 24 bit relative jump offsets, GHCi on PowerPC did not use mmap to load object files like the other architectures. Instead, it allocated memory using malloc and fread to load the object code. However there is a quirk in the GNU libc malloc implementation. For memory regions over certain size (dynamic and configurable), malloc will use mmap to obtain the required memory instead of sbrk and malloc's call to mmap sets the memory readable and writable, but not executable. That means when GHCi loads code into a memory region that was mmapped instead of malloc-ed and tries to execute it we get a segfault. This solution drops the malloc/fread object loading in favour of using mmap and then puts the jump island for each object code module at the end of the mmaped region for that object. This patch may also be a solution on other ELF based powerpc systems but does not work on darwin-powerpc. >--------------------------------------------------------------- rts/Linker.c | 37 +++++++++++++++++++++++++++++++++---- 1 files changed, 33 insertions(+), 4 deletions(-) diff --git a/rts/Linker.c b/rts/Linker.c index fd5550e..6beb534 100644 --- a/rts/Linker.c +++ b/rts/Linker.c @@ -70,11 +70,12 @@ #include <sys/wait.h> #endif -#if !defined(powerpc_HOST_ARCH) && \ - ( defined(linux_HOST_OS ) || defined(freebsd_HOST_OS) || \ +#if (defined(powerpc_HOST_ARCH) && defined(linux_HOST_OS)) \ + || (!defined(powerpc_HOST_ARCH) && \ + ( defined(linux_HOST_OS) || defined(freebsd_HOST_OS) || \ defined(dragonfly_HOST_OS) || defined(netbsd_HOST_OS ) || \ defined(openbsd_HOST_OS ) || defined(darwin_HOST_OS ) || \ - defined(kfreebsdgnu_HOST_OS) || defined(gnu_HOST_OS)) + defined(kfreebsdgnu_HOST_OS) || defined(gnu_HOST_OS))) /* Don't use mmap on powerpc_HOST_ARCH as mmap doesn't support * reallocating but we need to allocate jump islands just after each * object images. Otherwise relative branches to jump islands can fail @@ -90,6 +91,16 @@ #endif + +/* PowerPC has relative branch instructions with only 24 bit displacements + * and therefore needs jump islands contiguous with each object code module. + */ +#if (defined(USE_MMAP) && defined(powerpc_HOST_ARCH) && defined(linux_HOST_OS)) +#define USE_CONTIGUOUS_MMAP 1 +#else +#define USE_CONTIGUOUS_MMAP 0 +#endif + #if defined(linux_HOST_OS) || defined(solaris2_HOST_OS) || defined(freebsd_HOST_OS) || defined(kfreebsdgnu_HOST_OS) || defined(dragonfly_HOST_OS) || defined(netbsd_HOST_OS) || defined(openbsd_HOST_OS) || defined(gnu_HOST_OS) # define OBJFORMAT_ELF # include <regex.h> // regex is already used by dlopen() so this is OK @@ -2797,8 +2808,26 @@ static int ocAllocateSymbolExtras( ObjectCode* oc, int count, int first ) */ if( m > n ) // we need to allocate more pages { - oc->symbol_extras = mmapForLinker(sizeof(SymbolExtra) * count, + if (USE_CONTIGUOUS_MMAP) + { + /* Keep image and symbol_extras contiguous */ + void *new = mmapForLinker(n + (sizeof(SymbolExtra) * count), + MAP_ANONYMOUS, -1); + if (new) + { + memcpy(new, oc->image, oc->fileSize); + munmap(oc->image, n); + oc->image = new; + oc->symbol_extras = (SymbolExtra *) (oc->image + n); + } + else + oc->symbol_extras = NULL; + } + else + { + oc->symbol_extras = mmapForLinker(sizeof(SymbolExtra) * count, MAP_ANONYMOUS, -1); + } } else { _______________________________________________ Cvs-ghc mailing list [email protected] http://www.haskell.org/mailman/listinfo/cvs-ghc
