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    {