From bf7e78fa99b8e73b33aeecc8e86776f42cff33d4 Mon Sep 17 00:00:00 2001 From: Simon Marlow Date: Mon, 15 Sep 2008 14:59:24 +0000 Subject: [PATCH] Stop using mremap() to allocate space for trampolines This was causing problems because sometimes mremap() moved the memory we had allocated from the low 2Gb to above the 2Gb boundary, causing some linkages to fail. There's no MAP_32BIT flag to mremap(). So now we just use mmap(MAP_ANON|MAP_32BIT) to allocated space for the trampolines. People without MAP_32BIT (eg. *BSD) will still have to do something else here, such as allocating memory from a fixed address; so I've made it slightly easier for those guys, but there's still work to do (#2063). One solution (that Simon PJ is advocating) is to turn on -fPIC by default on x86-64. This is a good solution as it removes the need for MAP_32BIT, but doesn't work with -fvia-C, so probably this is for later. --- rts/Linker.c | 60 ++++++++++++++++++++++++---------------------------------- 1 file changed, 25 insertions(+), 35 deletions(-) diff --git a/rts/Linker.c b/rts/Linker.c index 3735a2e..e5a5ae6 100644 --- a/rts/Linker.c +++ b/rts/Linker.c @@ -1613,47 +1613,36 @@ static int ocAllocateSymbolExtras( ObjectCode* oc, int count, int first ) aligned = (oc->fileSize + 3) & ~3; #ifdef USE_MMAP - #ifndef linux_HOST_OS /* mremap is a linux extension */ - #error ocAllocateSymbolExtras doesnt want USE_MMAP to be defined - #endif - pagesize = getpagesize(); n = ROUND_UP( oc->fileSize, pagesize ); m = ROUND_UP( aligned + sizeof (SymbolExtra) * count, pagesize ); - /* If we have a half-page-size file and map one page of it then - * the part of the page after the size of the file remains accessible. - * If, however, we map in 2 pages, the 2nd page is not accessible - * and will give a "Bus Error" on access. To get around this, we check - * if we need any extra pages for the jump islands and map them in - * anonymously. We must check that we actually require extra pages - * otherwise the attempt to mmap 0 pages of anonymous memory will - * fail -EINVAL. + /* we try to use spare space at the end of the last page of the + * image for the jump islands, but if there isn't enough space + * then we have to map some (anonymously, remembering MAP_32BIT). */ - - if( m > n ) + if( m > n ) // we need to allocate more pages { - /* The effect of this mremap() call is only the ensure that we have - * a sufficient number of virtually contiguous pages. As returned from - * mremap, the pages past the end of the file are not backed. We give - * them a backing by using MAP_FIXED to map in anonymous pages. - */ - oc->image = mremap( oc->image, n, m, MREMAP_MAYMOVE ); - - if( oc->image == MAP_FAILED ) - { - errorBelch( "Unable to mremap for Jump Islands\n" ); - return 0; - } - - if( mmap( oc->image + n, m - n, PROT_READ | PROT_WRITE | PROT_EXEC, - MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, 0, 0 ) == MAP_FAILED ) - { - errorBelch( "Unable to mmap( MAP_FIXED ) for Jump Islands\n" ); - return 0; - } + oc->symbol_extras = mmap (NULL, sizeof(SymbolExtra) * count, + PROT_EXEC|PROT_READ|PROT_WRITE, + MAP_PRIVATE|MAP_ANONYMOUS|EXTRA_MAP_FLAGS, + 0, 0); + if (oc->symbol_extras == MAP_FAILED) + { + errorBelch( "Unable to mmap() for jump islands\n" ); + return 0; + } +#ifdef x86_64_HOST_ARCH + if (oc->symbol_extras > 0x80000000) + { + barf("mmap() returned memory outside 2Gb"); + } +#endif + } + else + { + oc->symbol_extras = (SymbolExtra *) (oc->image + aligned); } - #else oc->image -= misalignment; oc->image = stgReallocBytes( oc->image, @@ -1661,9 +1650,10 @@ static int ocAllocateSymbolExtras( ObjectCode* oc, int count, int first ) aligned + sizeof (SymbolExtra) * count, "ocAllocateSymbolExtras" ); oc->image += misalignment; -#endif /* USE_MMAP */ oc->symbol_extras = (SymbolExtra *) (oc->image + aligned); +#endif /* USE_MMAP */ + memset( oc->symbol_extras, 0, sizeof (SymbolExtra) * count ); } else -- 1.7.10.4