diff options
Diffstat (limited to 'xc/programs/Xserver/hw/xfree86/loader/elfloader.c')
-rw-r--r-- | xc/programs/Xserver/hw/xfree86/loader/elfloader.c | 131 |
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 |