Ticket #2972: 0002-Fix-GHCi-segfault-during-startup-on-linux-powerpc-29.patch

File 0002-Fix-GHCi-segfault-during-startup-on-linux-powerpc-29.patch, 4.0 KB (added by erikd, 3 years ago)

Updated version of the patch.

  • rts/Linker.c

    From 94ab3cc273e0f5ceeefe5c63d9f51c664a1dee5e Mon Sep 17 00:00:00 2001
    From: Erik de Castro Lopo <[email protected]>
    Date: Tue, 31 Jul 2012 05:53:49 +1000
    Subject: [PATCH 2/2] 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 file changed, 33 insertions(+), 4 deletions(-)
    
    diff --git a/rts/Linker.c b/rts/Linker.c
    index fd5550e..6beb534 100644
    a b  
    7070#include <sys/wait.h> 
    7171#endif 
    7272 
    73 #if !defined(powerpc_HOST_ARCH) && \ 
    74     (   defined(linux_HOST_OS    ) || defined(freebsd_HOST_OS) || \ 
     73#if (defined(powerpc_HOST_ARCH) && defined(linux_HOST_OS)) \ 
     74 || (!defined(powerpc_HOST_ARCH) && \ 
     75    (   defined(linux_HOST_OS)     || defined(freebsd_HOST_OS) || \ 
    7576        defined(dragonfly_HOST_OS) || defined(netbsd_HOST_OS ) || \ 
    7677        defined(openbsd_HOST_OS  ) || defined(darwin_HOST_OS ) || \ 
    77         defined(kfreebsdgnu_HOST_OS) || defined(gnu_HOST_OS)) 
     78        defined(kfreebsdgnu_HOST_OS) || defined(gnu_HOST_OS))) 
    7879/* Don't use mmap on powerpc_HOST_ARCH as mmap doesn't support 
    7980 * reallocating but we need to allocate jump islands just after each 
    8081 * object images. Otherwise relative branches to jump islands can fail 
     
    9091 
    9192#endif 
    9293 
     94 
     95/* PowerPC has relative branch instructions with only 24 bit displacements 
     96 * and therefore needs jump islands contiguous with each object code module. 
     97 */ 
     98#if (defined(USE_MMAP) && defined(powerpc_HOST_ARCH) && defined(linux_HOST_OS)) 
     99#define USE_CONTIGUOUS_MMAP 1 
     100#else 
     101#define USE_CONTIGUOUS_MMAP 0 
     102#endif 
     103 
    93104#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) 
    94105#  define OBJFORMAT_ELF 
    95106#  include <regex.h>    // regex is already used by dlopen() so this is OK 
    static int ocAllocateSymbolExtras( ObjectCode* oc, int count, int first ) 
    27972808     */ 
    27982809    if( m > n ) // we need to allocate more pages 
    27992810    { 
    2800         oc->symbol_extras = mmapForLinker(sizeof(SymbolExtra) * count, 
     2811        if (USE_CONTIGUOUS_MMAP) 
     2812        { 
     2813            /* Keep image and symbol_extras contiguous */ 
     2814            void *new = mmapForLinker(n + (sizeof(SymbolExtra) * count), 
     2815                                  MAP_ANONYMOUS, -1); 
     2816            if (new) 
     2817            { 
     2818                memcpy(new, oc->image, oc->fileSize); 
     2819                munmap(oc->image, n); 
     2820                oc->image = new; 
     2821                oc->symbol_extras = (SymbolExtra *) (oc->image + n); 
     2822            } 
     2823            else 
     2824                oc->symbol_extras = NULL; 
     2825        } 
     2826        else 
     2827        { 
     2828            oc->symbol_extras = mmapForLinker(sizeof(SymbolExtra) * count, 
    28012829                                          MAP_ANONYMOUS, -1); 
     2830        } 
    28022831    } 
    28032832    else 
    28042833    {