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    {