#include "PosixSource.h"
#endif
-// Linux needs _GNU_SOURCE to get RTLD_DEFAULT from <dlfcn.h>.
+/* Linux needs _GNU_SOURCE to get RTLD_DEFAULT from <dlfcn.h> and
+ MREMAP_MAYMOVE from <sys/mman.h>.
+ */
#ifdef __linux__
#define _GNU_SOURCE
#endif
static int ocAllocateJumpIslands( ObjectCode* oc, int count, int first )
{
+#ifdef USE_MMAP
+ int pagesize, n, m;
+#endif
int aligned;
if( count > 0 )
{
-#ifdef USE_MMAP
- #error ocAllocateJumpIslands doesnt want USE_MMAP to be defined
-#endif
// round up to the nearest 4
aligned = (oc->fileSize + 3) & ~3;
+#ifdef USE_MMAP
+ #ifndef linux_HOST_OS /* mremap is a linux extension */
+ #error ocAllocateJumpIslands doesnt want USE_MMAP to be defined
+ #endif
+
+ pagesize = getpagesize();
+ n = ROUND_UP( oc->fileSize, pagesize );
+ m = ROUND_UP( aligned + sizeof (ppcJumpIsland) * count, pagesize );
+
+ /* 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.
+ */
+ if( (oc->image = mremap( oc->image, n, m, MREMAP_MAYMOVE )) == 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;
+ }
+
+#else
oc->image = stgReallocBytes( oc->image,
- aligned + sizeof( ppcJumpIsland ) * count,
+ aligned + sizeof (ppcJumpIsland) * count,
"ocAllocateJumpIslands" );
- oc->jump_islands = (ppcJumpIsland *) (((char *) oc->image) + aligned);
- memset( oc->jump_islands, 0, sizeof( ppcJumpIsland ) * count );
+#endif /* USE_MMAP */
+
+ oc->jump_islands = (ppcJumpIsland *) (oc->image + aligned);
+ memset( oc->jump_islands, 0, sizeof (ppcJumpIsland) * count );
}
else
oc->jump_islands = NULL;
return ptr;
}
+static int
+findElfSectionIndexByName( ObjectCode *oc, const char *sh_name,
+ Elf_Word expected_type, Elf_Word expected_entsize )
+{
+ Elf_Ehdr *ehdr = (Elf_Ehdr *) oc->image;
+ Elf_Shdr *shdr = (Elf_Shdr *) (oc->image + ehdr->e_shoff);
+ char *sectnames = oc->image + shdr[ehdr->e_shstrndx].sh_offset;
+ int i;
+
+ for( i = 0; i < ehdr->e_shnum; i++ )
+ if( !strcmp( sectnames + shdr[i].sh_name, sh_name ) )
+ {
+ if( shdr[i].sh_type != expected_type )
+ {
+ errorBelch( "The entry type (%d) of the '%s' section isn't %d\n",
+ shdr[i].sh_type, sh_name, expected_type );
+ return -1;
+ }
+
+ if( shdr[i].sh_entsize != expected_entsize )
+ {
+ errorBelch( "The entry size (%d) of the '%s' section isn't %d\n",
+ shdr[i].sh_entsize, sh_name, expected_entsize );
+
+ return -1;
+ }
+
+ return i;
+ }
+
+ errorBelch( "This ELF file contains no '%s' section", sh_name );
+ return -1;
+}
+
+static char *
+findElfSectionByName( ObjectCode *oc, const char *sh_name,
+ Elf_Word expected_type, int expected_entsize,
+ int *num_entries )
+{
+ Elf_Ehdr *ehdr = (Elf_Ehdr *) oc->image;
+ Elf_Shdr *shdr = (Elf_Shdr *) (oc->image + ehdr->e_shoff);
+ int section;
+
+ section = findElfSectionIndexByName( oc, sh_name, expected_type,
+ expected_entsize );
+
+ if( section < 0 )
+ return NULL;
+
+ /* allow for meaningful results in num_entries even when entsize is 0 */
+ if( expected_entsize == 0 )
+ expected_entsize = 1;
+
+ if( num_entries )
+ *num_entries = shdr[section].sh_size / expected_entsize;
+
+ return oc->image + shdr[section].sh_offset;
+}
+
#if defined(ia64_HOST_ARCH)
static Elf_Addr
findElfSegment ( void* objImage, Elf_Addr vaddr )