Ticket #2972: 0001-Fix-GHCi-segfault-during-startup-on-PowerPC-2972.patch

File 0001-Fix-GHCi-segfault-during-startup-on-PowerPC-2972.patch, 3.7 KB (added by erikd, 3 years ago)

Patch that fixes ghci segfault on start up on linux-ppc

  • rts/Linker.c

    From 423e644abefcff446fdedbf1c273a8e4e046eb43 Mon Sep 17 00:00:00 2001
    From: Erik de Castro Lopo <[email protected]>
    Date: Fri, 13 Jul 2012 19:44:45 +1000
    Subject: [PATCH] Fix GHCi segfault during startup on 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.
    ---
     rts/Linker.c |   39 +++++++++++++++++++++++++++------------
     1 file changed, 27 insertions(+), 12 deletions(-)
    
    diff --git a/rts/Linker.c b/rts/Linker.c
    index 703bc5f..1ccc7e5 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) || \ 
    75         defined(dragonfly_HOST_OS) || defined(netbsd_HOST_OS ) || \ 
    76         defined(openbsd_HOST_OS  ) || defined(darwin_HOST_OS ) || \ 
    77         defined(kfreebsdgnu_HOST_OS) || defined(gnu_HOST_OS)) 
    78 /* Don't use mmap on powerpc_HOST_ARCH as mmap doesn't support 
    79  * reallocating but we need to allocate jump islands just after each 
    80  * object images. Otherwise relative branches to jump islands can fail 
    81  * due to 24-bits displacement overflow. 
     73#if defined(powerpc_HOST_ARCH) 
     74/* PowerPC has relative branch instructions with only 24 bit displacements 
     75 * and therefore needs jump islands contiguous with each object code module. 
    8276 */ 
     77#define USE_CONTIGUOUS_MMAP 1 
     78#else 
     79#define USE_CONTIGUOUS_MMAP 0 
     80#endif 
     81 
    8382#define USE_MMAP 
    8483#include <fcntl.h> 
    8584#include <sys/mman.h> 
     
    8887#include <unistd.h> 
    8988#endif 
    9089 
    91 #endif 
    92  
    9390#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) 
    9491#  define OBJFORMAT_ELF 
    9592#  include <regex.h>    // regex is already used by dlopen() so this is OK 
    static int ocAllocateSymbolExtras( ObjectCode* oc, int count, int first ) 
    27972794     */ 
    27982795    if( m > n ) // we need to allocate more pages 
    27992796    { 
    2800         oc->symbol_extras = mmapForLinker(sizeof(SymbolExtra) * count, 
     2797        if (USE_CONTIGUOUS_MMAP) 
     2798        { 
     2799            /* Keep image and symbol_extras contiguous */ 
     2800            void *new = mmapForLinker(n + (sizeof(SymbolExtra) * count), 
     2801                                  MAP_ANONYMOUS, -1); 
     2802            if (new) 
     2803            { 
     2804                memcpy(new, oc->image, oc->fileSize); 
     2805                munmap(oc->image, n); 
     2806                oc->image = new; 
     2807                oc->symbol_extras = (SymbolExtra *) (oc->image + n); 
     2808            } 
     2809            else 
     2810                oc->symbol_extras = NULL; 
     2811        } 
     2812        else 
     2813        { 
     2814            oc->symbol_extras = mmapForLinker(sizeof(SymbolExtra) * count, 
    28012815                                          MAP_ANONYMOUS, -1); 
     2816        } 
    28022817    } 
    28032818    else 
    28042819    {