summaryrefslogtreecommitdiff
path: root/xc/programs/Xserver/hw/xfree86/loader/elfloader.c
diff options
context:
space:
mode:
Diffstat (limited to 'xc/programs/Xserver/hw/xfree86/loader/elfloader.c')
-rw-r--r--xc/programs/Xserver/hw/xfree86/loader/elfloader.c131
1 files changed, 121 insertions, 10 deletions
diff --git a/xc/programs/Xserver/hw/xfree86/loader/elfloader.c b/xc/programs/Xserver/hw/xfree86/loader/elfloader.c
index d57e7103b..822a50efa 100644
--- a/xc/programs/Xserver/hw/xfree86/loader/elfloader.c
+++ b/xc/programs/Xserver/hw/xfree86/loader/elfloader.c
@@ -1,4 +1,4 @@
-/* $XFree86: xc/programs/Xserver/hw/xfree86/loader/elfloader.c,v 1.44 2002/09/19 13:22:02 tsi Exp $ */
+/* $XFree86: xc/programs/Xserver/hw/xfree86/loader/elfloader.c,v 1.49 2003/01/24 17:26:35 tsi Exp $ */
/*
*
@@ -23,6 +23,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
#include <sys/types.h>
+#include <sys/mman.h>
#include <unistd.h>
#include <stdlib.h>
#ifdef __QNX__
@@ -65,6 +66,29 @@
# endif
#endif
+#if defined (DoMMAPedMerge)
+# include <sys/mman.h>
+# define MergeSectionAlloc
+# define MMAP_PROT (PROT_READ | PROT_WRITE | PROT_EXEC)
+# if !defined(linux)
+# error No MAP_ANON?
+# endif
+# if !defined (__x86_64__)
+# define MMAP_FLAGS (MAP_PRIVATE | MAP_ANON)
+# else
+# define MMAP_FLAGS (MAP_PRIVATE | MAP_ANON | MAP_32BIT)
+# endif
+# if defined (MmapPageAlign)
+# define MMAP_ALIGN(size) do { \
+ int pagesize = getpagesize(); \
+ size = ( size + pagesize - 1) / pagesize; \
+ size *= pagesize; \
+ } while (0);
+# else
+# define MMAP_ALIGN(size)
+# endif
+#endif
+
#if defined (__alpha__) || \
defined (__ia64__) || \
defined (__x86_64__) || \
@@ -304,7 +328,9 @@ int size;
elffile->baseptr = (elffile->baseptr + align - 1) & ~(align - 1);
ret = (void *)elffile->baseptr;
elffile->baseptr += size;
- memset(ret, 0, size);
+#ifndef DoMMAPedMerge
+ memset(ret, 0, size); /* mmap() does this for us */
+#endif
return ret;
}
#else /* MergeSectionAlloc */
@@ -860,13 +886,14 @@ int maxalign;
if (!gotsize) {
xf86loaderfree(elffile->got);
+# if !defined(DoMMAPedMerge)
elffile->basesize += 8 + elffile->gotsize;
elffile->base = xf86loaderrealloc(elffile->base, elffile->basesize);
if (elffile->base == NULL) {
ErrorF( "ELFCreateGOT() Unable to reallocate memory!!!!\n" );
return FALSE;
}
-#if defined(linux) && defined(__ia64__)
+# if defined(linux) && defined(__ia64__) || defined(__OpenBSD__)
{
unsigned long page_size = getpagesize();
unsigned long round;
@@ -875,7 +902,21 @@ int maxalign;
mprotect(elffile->base - round, (elffile->basesize+round+page_size-1) & ~(page_size-1),
PROT_READ|PROT_WRITE|PROT_EXEC);
}
-#endif
+# endif
+# else
+ {
+ int oldbasesize = elffile->basesize;
+ elffile->basesize += 8 + elffile->gotsize;
+ MMAP_ALIGN(elffile->basesize);
+ elffile->base = mremap(elffile->base,oldbasesize,
+ elffile->basesize,MREMAP_MAYMOVE);
+ if (elffile->base == NULL) {
+ ErrorF( "ELFCreateGOT() Unable to remap memory!!!!\n" );
+ return FALSE;
+ }
+ }
+# endif
+
elffile->baseptr = ((long)elffile->base + (maxalign - 1)) & ~(maxalign - 1);
elffile->got = (unsigned char *)((long)(elffile->base + elffile->basesize - elffile->gotsize) & ~7);
} else {
@@ -1113,6 +1154,7 @@ int force;
#if defined(__alpha__)
unsigned int *dest32h; /* address of the high 32 bit place being modified */
unsigned long *dest64;
+ unsigned short *dest16;
#endif
#if defined(__x86_64__)
unsigned long *dest64;
@@ -1299,6 +1341,36 @@ int force;
# endif
break;
}
+
+ case R_ALPHA_GPRELLOW:
+ {
+ dest64=(unsigned long *)(secp+rel->r_offset);
+ dest16=(unsigned short *)dest64;
+
+ symval += rel->r_addend;
+ symval = ((unsigned char *)symval)-((unsigned char *)elffile->got);
+
+ *dest16=symval;
+ break;
+ }
+
+ case R_ALPHA_GPRELHIGH:
+ {
+ dest64=(unsigned long *)(secp+rel->r_offset);
+ dest16=(unsigned short *)dest64;
+
+ symval += rel->r_addend;
+ symval = ((unsigned char *)symval)-((unsigned char *)elffile->got);
+ symval = ((long)symval >> 16) + ((symval >> 15) & 1);
+ if( (long)symval > 0x7fff || (long)symval < -(long)0x8000 ) {
+ FatalError("R_ALPHA_GPRELHIGH symval-got is too large for %s:%lx\n",
+ ElfGetSymbolName(elffile,ELF_R_SYM(rel->r_info)),symval);
+ }
+
+ *dest16=symval;
+ break;
+ }
+
case R_ALPHA_LITERAL:
{
ELFGotEntryPtr gotent;
@@ -1439,6 +1511,23 @@ int force;
ELFDEBUG( "*dest32=%8.8x\n", *dest32 );
# endif
break;
+
+ case R_ALPHA_GPREL16:
+ {
+ dest64=(unsigned long *)(secp+rel->r_offset);
+ dest16=(unsigned short *)dest64;
+
+ symval += rel->r_addend;
+ symval = ((unsigned char *)symval)-((unsigned char *)elffile->got);
+ if( (long)symval > 0x7fff ||
+ (long)symval < -(long)0x8000 ) {
+ FatalError("R_ALPHA_GPREL16 symval-got is too large for %s:%lx\n",
+ ElfGetSymbolName(elffile,ELF_R_SYM(rel->r_info)),symval);
+ }
+
+ *dest16=symval;
+ break;
+ }
#endif /* alpha */
#if defined(__mc68000__)
@@ -2376,7 +2465,6 @@ unsigned short **psecttable;
*
* Do the work required to load each section into memory.
*/
-
static void
ELFCollectSections(elffile,pass,totalsize,maxalign)
ELFModulePtr elffile;
@@ -2405,6 +2493,8 @@ int *maxalign;
case SHT_STRTAB:
if (!strcmp(name,".shstrtab")) /* already loaded */
continue;
+ if (!strcmp(name,".stabstr")) /* ignore debug info */
+ continue;
case SHT_SYMTAB:
if (pass) continue;
flags = LOADED_SECTION;
@@ -2446,10 +2536,10 @@ int *maxalign;
SecSize(i), name);
} else {
if( SecSize(i) )
- elffile->lsection[j].saddr
+ elffile->lsection[j].saddr
= ELFLoaderSectCalloc(elffile,SecAlign(i),
SecSize(i));
- else
+ else
elffile->lsection[j].saddr = NULL;
}
} else {
@@ -2467,6 +2557,12 @@ int *maxalign;
elffile->lsection[j].size=SecSize(i);
elffile->lsection[j].flags=flags;
switch (SecType(i)) {
+#ifdef __OpenBSD__
+ case SHT_PROGBITS:
+ mprotect(elffile->lsection[j].saddr, SecSize(i),
+ PROT_READ|PROT_WRITE|PROT_EXEC);
+ break;
+#endif
case SHT_SYMTAB:
elffile->symtab = (Elf_Sym *)elffile->saddr[i];
elffile->symndx = i;
@@ -2651,12 +2747,14 @@ LOOKUP **ppLookup;
#ifdef MergeSectionAlloc
elffile->basesize = totalsize + maxalign;
+
+# if !defined(DoMMAPedMerge)
elffile->base = xf86loadermalloc(elffile->basesize);
if (elffile->base == NULL) {
ErrorF( "Unable to allocate ELF sections\n" );
return NULL;
}
-#if defined(linux) && defined(__ia64__)
+# if defined(linux) && defined(__ia64__) || defined(__OpenBSD__)
{
unsigned long page_size = getpagesize();
unsigned long round;
@@ -2665,7 +2763,16 @@ LOOKUP **ppLookup;
mprotect(elffile->base - round, (elffile->basesize+round+page_size-1) & ~(page_size-1),
PROT_READ|PROT_WRITE|PROT_EXEC);
}
-#endif
+# endif
+# else
+ MMAP_ALIGN(elffile->basesize);
+ elffile->base = mmap( 0,elffile->basesize,MMAP_PROT,MMAP_FLAGS,-1,
+ (off_t)0);
+ if (elffile->base == NULL) {
+ ErrorF( "Unable to mmap ELF sections\n" );
+ return NULL;
+ }
+# endif
elffile->baseptr = ((long)elffile->base + (maxalign - 1)) & ~(maxalign - 1);
#endif
@@ -2812,7 +2919,11 @@ void *modptr;
/*
* Free the sections that were allocated.
*/
-#define CheckandFree(ptr,size) if(ptr) xf86loaderfree(ptr)
+#if !defined (DoMMAPedMerge)
+# define CheckandFree(ptr,size) if(ptr) xf86loaderfree(ptr)
+#else
+# define CheckandFree(ptr,size) if (ptr) munmap(ptr,size)
+#endif
#define CheckandFreeFile(ptr,size) if(ptr) _LoaderFreeFileMem((ptr),(size))
#ifdef MergeSectionAlloc