summaryrefslogtreecommitdiff
path: root/hw/xfree86/loader/elfloader.c
diff options
context:
space:
mode:
authorDaniel Stone <daniel@fooishbar.org>2006-06-01 20:18:30 +0000
committerDaniel Stone <daniel@fooishbar.org>2006-06-01 20:18:30 +0000
commitc9468177486833d521ec62c7b0266b4be8200de7 (patch)
tree5d6976c35147d5d16c22350032661a37f53d8f5f /hw/xfree86/loader/elfloader.c
parenta3a4221495dfe4cc0a3874a08dd5364ef45a7f2e (diff)
Kill a.out, COFF and ELF loaders with FIRE.
Diffstat (limited to 'hw/xfree86/loader/elfloader.c')
-rw-r--r--hw/xfree86/loader/elfloader.c3335
1 files changed, 0 insertions, 3335 deletions
diff --git a/hw/xfree86/loader/elfloader.c b/hw/xfree86/loader/elfloader.c
deleted file mode 100644
index bcc6686f4..000000000
--- a/hw/xfree86/loader/elfloader.c
+++ /dev/null
@@ -1,3335 +0,0 @@
-/* $XdotOrg: xserver/xorg/hw/xfree86/loader/elfloader.c,v 1.10.12.1 2006/02/24 05:49:34 krh Exp $ */
-/* $XFree86: xc/programs/Xserver/hw/xfree86/loader/elfloader.c,v 1.61tsi Exp $ */
-
-/*
- *
- * Copyright 1995-1998 by Metro Link, Inc.
- *
- * Permission to use, copy, modify, distribute, and sell this software and its
- * documentation for any purpose is hereby granted without fee, provided that
- * the above copyright notice appear in all copies and that both that
- * copyright notice and this permission notice appear in supporting
- * documentation, and that the name of Metro Link, Inc. not be used in
- * advertising or publicity pertaining to distribution of the software without
- * specific, written prior permission. Metro Link, Inc. makes no
- * representations about the suitability of this software for any purpose.
- * It is provided "as is" without express or implied warranty.
- *
- * METRO LINK, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
- * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
- * EVENT SHALL METRO LINK, INC. BE LIABLE FOR ANY SPECIAL, INDIRECT OR
- * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
- * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
- * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
- * PERFORMANCE OF THIS SOFTWARE.
- */
-#ifdef HAVE_XORG_CONFIG_H
-#include <xorg-config.h>
-#endif
-
-#include <sys/types.h>
-#ifndef __UNIXOS2__
-#include <sys/mman.h>
-#endif
-#include <unistd.h>
-#include <stdlib.h>
-#ifdef __QNX__
-# include <fcntl.h>
-#else
-# include <sys/fcntl.h>
-#endif
-#include <sys/stat.h>
-#if defined(linux) && defined (__ia64__)
-#include <sys/mman.h>
-#endif
-
-#ifdef DBMALLOC
-# include <debug/malloc.h>
-# define Xalloc(size) malloc(size)
-# define Xcalloc(size) calloc(1,(size))
-# define Xfree(size) free(size)
-#endif
-
-#include <X11/Xos.h>
-#include "os.h"
-#include "elf.h"
-
-#include "sym.h"
-#include "loader.h"
-
-#include "compiler.h"
-
-#ifndef LOADERDEBUG
-#define LOADERDEBUG 0
-#endif
-
-#if LOADERDEBUG
-# define ELFDEBUG ErrorF
-#endif
-
-#if defined(__ia64__)
-
-/*
- * R_IA64_LTOFF22X and R_IA64_LDXMOV are relocation optimizations for
- * IA64. Conforming implementations must recognize them and may either
- * implement the optimization or may fallback to previous
- * non-optimized behavior by treating R_IA64_LTOFF22X as a
- * R_IA64_LTOFF22 and ignoring R_IA64_LDXMOV. The
- * IA64_LDX_OPTIMIZATION conditional controls the fallback behavior,
- * if defined the optimizations are performed.
- *
- * To implement the optimization we want to change is the sequence on
- * the left to that on the right, without regard to any intervening
- * instructions:
- *
- * 1) addl t1=@ltoff(var),gp ==> addl t1=@gprel(var),gp
- * 2) ld8 t2=[t1] ==> mov t2=t1
- * 3) ld8 loc0=[t2] ==> ld8 loc0=[t2]
- *
- * The relocations that match the above instructions are:
- *
- * 1) R_IA64_LTOFF22 ==> R_IA64_LTOFF22X
- * 2) -- ==> R_IA64_LDXMOV
- * 3) -- ==> --
- *
- * First lets look at left hand column to understand the original
- * mechanism. The virtual address of a symbol is stored in the GOT,
- * when that symbol is referenced the following sequence occurs,
- * instruction 1 loads the address of the GOT entry containing the
- * virtural address of the symbol into t1. Instruction 2 loads the
- * virtual address of the symbol into t2 by dereferencing t1. Finally
- * the symbol is loaded in instruction 3 by dereferencing its virtual
- * address in t2.
- *
- * The optimization that LTOFF22X/LDXMOV introduces is based on the
- * observation we are doing an extra load (instruction 2) if we can
- * generate the virtual address for the symbol without doing a lookup in
- * the GOT. This is possible if the virtual address of the symbol can be
- * computed via GP relative addressing. In other words the virtual
- * address of the symbol is a fixed offset from the GP. This fixed offset
- * must be within the limits of the signed 22 bit immediate offset in the
- * ld8 instruction, otherwise the original indirect GOT lookup must be
- * performed (LTOFF22).
- *
- * If we can use GP relative addressing for the symbol then the
- * instruction that loaded the virtual address of the symbol into t2 must
- * also be patched, hence the introduction of the LDXMOV relocation. The
- * LDXMOV essentially turns the GOT lookup into a no-op by changing the
- * ld8 into a register move that preserves the register location of the
- * symbol's virtual address (e.g. t2).
- *
- * The important point to recognize when implementing the LTOFF22X/LDXMOV
- * optimization is that relocations are interdependent, the LDXMOV is
- * only applied if the LTOFF22X is applied. It is also worth noting that
- * there is no relationship between LDXMOV relocations and LTOFF22X in
- * the ELF relocation section other than they share the same
- * symbol+addend value.
- */
-
-#define IA64_LDX_OPTIMIZATION 1
-#endif
-
-#ifndef UseMMAP
-# if defined (__ia64__) || defined (__sparc__)
-# define MergeSectionAlloc
-# 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 (__amd64__) || !defined(__linux__)
-# 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 (__amd64__) || \
- (defined (__sparc__) && \
- (defined (__arch64__) || \
- defined (__sparcv9)))
-typedef Elf64_Ehdr Elf_Ehdr;
-typedef Elf64_Shdr Elf_Shdr;
-typedef Elf64_Sym Elf_Sym;
-typedef Elf64_Rel Elf_Rel;
-typedef Elf64_Rela Elf_Rela;
-typedef Elf64_Addr Elf_Addr;
-typedef Elf64_Half Elf_Half;
-typedef Elf64_Off Elf_Off;
-typedef Elf64_Sword Elf_Sword;
-typedef Elf64_Word Elf_Word;
-
-#define ELF_ST_BIND ELF64_ST_BIND
-#define ELF_ST_TYPE ELF64_ST_TYPE
-#define ELF_R_SYM ELF64_R_SYM
-#define ELF_R_TYPE ELF64_R_TYPE
-
-# if defined (__alpha__) || defined (__ia64__)
-/*
- * The GOT is allocated dynamically. We need to keep a list of entries that
- * have already been added to the GOT.
- *
- */
-typedef struct _elf_GOT_Entry {
- Elf_Rela *rel;
- int offset;
- struct _elf_GOT_Entry *next;
-} ELFGotEntryRec, *ELFGotEntryPtr;
-
-typedef struct _elf_GOT {
- unsigned int size;
- unsigned int nuses;
- unsigned char *freeptr;
- struct _elf_GOT *next;
- unsigned char section[1];
-} ELFGotRec, *ELFGotPtr;
-
-# ifdef MergeSectionAlloc
-static ELFGotPtr ELFSharedGOTs;
-# endif
-# endif
-
-# if defined (__ia64__)
-/*
- * The PLT is allocated dynamically. We need to keep a list of entries that
- * have already been added to the PLT.
- */
-typedef struct _elf_PLT_Entry {
- Elf_Rela *rel;
- int offset;
- int gotoffset;
- struct _elf_PLT_Entry *next;
-} ELFPltEntryRec, *ELFPltEntryPtr;
-
-/*
- * The OPD is allocated dynamically within the GOT. We need to keep a list
- * of entries that have already been added to the OPD.
- */
-typedef struct _elf_OPD {
- LOOKUP *l;
- int index;
- int offset;
- struct _elf_OPD *next;
-} ELFOpdRec, *ELFOpdPtr;
-# endif
-
-#else
-typedef Elf32_Ehdr Elf_Ehdr;
-typedef Elf32_Shdr Elf_Shdr;
-typedef Elf32_Sym Elf_Sym;
-typedef Elf32_Rel Elf_Rel;
-typedef Elf32_Rela Elf_Rela;
-typedef Elf32_Addr Elf_Addr;
-typedef Elf32_Half Elf_Half;
-typedef Elf32_Off Elf_Off;
-typedef Elf32_Sword Elf_Sword;
-typedef Elf32_Word Elf_Word;
-
-#define ELF_ST_BIND ELF32_ST_BIND
-#define ELF_ST_TYPE ELF32_ST_TYPE
-#define ELF_R_SYM ELF32_R_SYM
-#define ELF_R_TYPE ELF32_R_TYPE
-#endif
-
-#if defined(__powerpc__) || \
- defined(__mc68000__) || \
- defined(__alpha__) || \
- defined(__sparc__) || \
- defined(__ia64__) || \
- defined(__amd64__)
-typedef Elf_Rela Elf_Rel_t;
-#else
-typedef Elf_Rel Elf_Rel_t;
-#endif
-
-typedef struct {
- void *saddr;
- char *name;
- int ndx;
- int size;
- int flags;
-} LoadSection;
-
-#define RELOC_SECTION 0x1
-#define LOADED_SECTION 0x2
-
-/*
- * This structure contains all of the information about a module
- * that has been loaded.
- */
-
-typedef struct {
- int handle;
- int module;
- int fd;
- loader_funcs *funcs;
- Elf_Ehdr *header; /* file header */
- int numsh;
- Elf_Shdr *sections; /* Address of the section header table */
- int secsize; /* size of the section table */
- unsigned char **saddr; /* Start addresss of the section pointer table */
- unsigned char *shstraddr; /* Start address of the section header string table */
- int shstrndx; /* index of the section header string table */
- int shstrsize; /* size of the section header string table */
-#if defined(__alpha__) || defined(__ia64__)
- unsigned char *got; /* Start address of the .got section */
- ELFGotEntryPtr got_entries; /* List of entries in the .got section */
- int gotndx; /* index of the .got section */
- int gotsize; /* actual size of the .got section */
- ELFGotPtr shared_got; /* Pointer to ELFGotRec if shared */
-#endif /*(__alpha__) || (__ia64__) */
-#if defined(__ia64__)
- ELFOpdPtr opd_entries; /* List of entries in the .opd section */
- unsigned char *plt; /* Start address of the .plt section */
- ELFPltEntryPtr plt_entries; /* List of entries in the .plt section */
- int pltndx; /* index of the .plt section */
- int pltsize; /* size of the .plt section */
-#endif /*__ia64__*/
- Elf_Sym *symtab; /* Start address of the .symtab section */
- int symndx; /* index of the .symtab section */
- unsigned char *common; /* Start address of the SHN_COMMON space */
- int comsize; /* size of the SHN_COMMON space */
-
- unsigned char *base; /* Alloced address of section block */
- unsigned long baseptr; /* Pointer to next free space in base */
- int basesize; /* Size of that allocation */
- unsigned char *straddr; /* Start address of the string table */
- int strndx; /* index of the string table */
- int strsize; /* size of the string table */
- LoadSection *lsection;
- int lsectidx;
-} ELFModuleRec, *ELFModulePtr;
-
-/*
- * If a relocation is unable to be satisfied, then put it on a list
- * to try later after more modules have been loaded.
- */
-typedef struct _elf_reloc {
- Elf_Rel_t *rel;
- ELFModulePtr file;
- Elf_Word secn;
- struct _elf_reloc *next;
-} ELFRelocRec;
-
-/*
- * symbols with a st_shndx of COMMON need to have space allocated for them.
- *
- * Gather all of these symbols together, and allocate one chunk when we
- * are done.
- */
-typedef struct _elf_COMMON {
- Elf_Sym *sym;
- struct _elf_COMMON *next;
-} ELFCommonRec;
-
-static ELFCommonPtr listCOMMON = NULL;
-
-/* Prototypes for static functions */
-static int ELFhashCleanOut(void *, itemPtr);
-static char *ElfGetStringIndex(ELFModulePtr, int, int);
-static char *ElfGetString(ELFModulePtr, int);
-static char *ElfGetSectionName(ELFModulePtr, int);
-static ELFRelocPtr ElfDelayRelocation(ELFModulePtr, Elf_Word, Elf_Rel_t *);
-static ELFCommonPtr ElfAddCOMMON(Elf_Sym *);
-static int ElfCOMMONSize(void);
-static int ElfCreateCOMMON(ELFModulePtr, LOOKUP *);
-static char *ElfGetSymbolNameIndex(ELFModulePtr, int, int);
-static char *ElfGetSymbolName(ELFModulePtr, int);
-static Elf_Addr ElfGetSymbolValue(ELFModulePtr, int);
-static ELFRelocPtr Elf_RelocateEntry(ELFModulePtr, Elf_Word, Elf_Rel_t *,
- int);
-static ELFRelocPtr ELFCollectRelocations(ELFModulePtr, int);
-static LOOKUP *ELF_GetSymbols(ELFModulePtr, unsigned short **);
-static void ELFCollectSections(ELFModulePtr, int, int *, int *);
-
-#if defined(__alpha__) || defined(__ia64__)
-static void ElfAddGOT(ELFModulePtr, Elf_Rel_t *);
-static int ELFCreateGOT(ELFModulePtr, int);
-#endif
-#if defined(__ia64__)
-static void ElfAddOPD(ELFModulePtr, int, LOOKUP *);
-static void ELFCreateOPD(ELFModulePtr);
-static void ElfAddPLT(ELFModulePtr, Elf_Rel_t *);
-static void ELFCreatePLT(ELFModulePtr);
-enum ia64_operand {
- IA64_OPND_IMM22,
- IA64_OPND_TGT25C,
- IA64_OPND_LDXMOV
-};
-static void IA64InstallReloc(unsigned long *, int, enum ia64_operand, long);
-#endif /*__ia64__*/
-
-#ifdef MergeSectionAlloc
-static void *
-ELFLoaderSectToMem(ELFModulePtr elffile, int align, unsigned long offset,
- int size, char *label)
-{
- void *ret;
-
- elffile->baseptr = (elffile->baseptr + align - 1) & ~(align - 1);
- ret = (void *)elffile->baseptr;
- _LoaderFileRead(elffile->fd, offset, ret, size);
- elffile->baseptr += size;
- return ret;
-}
-
-static void *
-ELFLoaderSectCalloc(ELFModulePtr elffile, int align, int size)
-{
- void *ret;
-
- elffile->baseptr = (elffile->baseptr + align - 1) & ~(align - 1);
- ret = (void *)elffile->baseptr;
- elffile->baseptr += size;
-#ifndef DoMMAPedMerge
- memset(ret, 0, size); /* mmap() does this for us */
-#endif
- return ret;
-}
-#else /* MergeSectionAlloc */
-# define ELFLoaderSectToMem(elffile,align,offset,size,label) \
-_LoaderFileToMem((elffile)->fd,offset,size,label)
-# define ELFLoaderSectCalloc(elffile,align,size) xf86loadercalloc(1,size)
-#endif
-
-/*
- * Utility Functions
- */
-
-static int
-ELFhashCleanOut(void *voidptr, itemPtr item)
-{
- ELFModulePtr module = (ELFModulePtr) voidptr;
-
- return (module->handle == item->handle);
-}
-
-/*
- * Manage listResolv
- */
-static ELFRelocPtr
-ElfDelayRelocation(ELFModulePtr elffile, Elf_Word secn, Elf_Rel_t *rel)
-{
- ELFRelocPtr reloc;
-
- if ((reloc = xf86loadermalloc(sizeof(ELFRelocRec))) == NULL) {
- ErrorF("ElfDelayRelocation() Unable to allocate memory!!!!\n");
- return 0;
- }
- reloc->file = elffile;
- reloc->secn = secn;
- reloc->rel = rel;
- reloc->next = 0;
-#ifdef ELFDEBUG
- ELFDEBUG("ElfDelayRelocation %p: file %p, sec %d,"
- " r_offset 0x%lx, r_info 0x%x",
- (void *)reloc, (void *)elffile, secn,
- (unsigned long)rel->r_offset, rel->r_info);
-# if defined(__powerpc__) || \
- defined(__mc68000__) || \
- defined(__alpha__) || \
- defined(__sparc__) || \
- defined(__ia64__) || \
- defined(__amd64__)
- ELFDEBUG(", r_addend 0x%lx", rel->r_addend);
-# endif
- ELFDEBUG("\n");
-#endif
- return reloc;
-}
-
-/*
- * Manage listCOMMON
- */
-static ELFCommonPtr
-ElfAddCOMMON(Elf_Sym *sym)
-{
- ELFCommonPtr common;
-
- if ((common = xf86loadermalloc(sizeof(ELFCommonRec))) == NULL) {
- ErrorF("ElfAddCOMMON() Unable to allocate memory!!!!\n");
- return 0;
- }
- common->sym = sym;
- common->next = 0;
- return common;
-}
-
-static int
-ElfCOMMONSize(void)
-{
- int size = 0;
- ELFCommonPtr common;
-
- for (common = listCOMMON; common; common = common->next) {
- size += common->sym->st_size;
-#if defined(__alpha__) || \
- defined(__ia64__) || \
- defined(__amd64__) || \
- (defined(__sparc__) && \
- (defined(__arch64__) || \
- defined(__sparcv9)))
- size = (size + 7) & ~0x7;
-#endif
- }
- return size;
-}
-
-static int
-ElfCreateCOMMON(ELFModulePtr elffile, LOOKUP *pLookup)
-{
- int numsyms = 0, size = 0, l = 0;
- int offset = 0, firstcommon = 0;
- ELFCommonPtr common;
-
- if (listCOMMON == NULL)
- return TRUE;
-
- for (common = listCOMMON; common; common = common->next) {
- size += common->sym->st_size;
-#if defined(__alpha__) || \
- defined(__ia64__) || \
- defined(__amd64__) || \
- (defined(__sparc__) && \
- (defined(__arch64__) || \
- defined(__sparcv9)))
- size = (size + 7) & ~0x7;
-#endif
- numsyms++;
- }
-
-#ifdef ELFDEBUG
- ELFDEBUG("ElfCreateCOMMON() %d entries (%d bytes) of COMMON data\n",
- numsyms, size);
-#endif
-
- elffile->comsize = size;
- if ((elffile->common = ELFLoaderSectCalloc(elffile, 8, size)) == NULL) {
- ErrorF("ElfCreateCOMMON() Unable to allocate memory!!!!\n");
- return FALSE;
- }
-
- if (DebuggerPresent) {
- ldrCommons = xf86loadermalloc(numsyms * sizeof(LDRCommon));
- nCommons = numsyms;
- }
-
- for (l = 0; pLookup[l].symName; l++) ;
- firstcommon = l;
-
- /* Traverse the common list and create a lookup table with all the
- * common symbols. Destroy the common list in the process.
- * See also ResolveSymbols.
- */
- while (listCOMMON) {
- common = listCOMMON;
- /* this is xstrdup because is should be more efficient. it is freed
- * with xf86loaderfree
- */
- pLookup[l].symName =
- xf86loaderstrdup(ElfGetString(elffile, common->sym->st_name));
- pLookup[l].offset = (funcptr) (elffile->common + offset);
-#ifdef ELFDEBUG
- ELFDEBUG("Adding common %p %s\n",
- (void *)pLookup[l].offset, pLookup[l].symName);
-#endif
-
- /* Record the symbol address for gdb */
- if (DebuggerPresent && ldrCommons) {
- ldrCommons[l - firstcommon].addr = (void *)pLookup[l].offset;
- ldrCommons[l - firstcommon].name = pLookup[l].symName;
- ldrCommons[l - firstcommon].namelen = strlen(pLookup[l].symName);
- }
- listCOMMON = common->next;
- offset += common->sym->st_size;
-#if defined(__alpha__) || \
- defined(__ia64__) || \
- defined(__amd64__) || \
- (defined(__sparc__) && \
- (defined(__arch64__) || \
- defined(__sparcv9)))
- offset = (offset + 7) & ~0x7;
-#endif
- xf86loaderfree(common);
- l++;
- }
- /* listCOMMON == 0 */
- pLookup[l].symName = NULL; /* Terminate the list. */
- return TRUE;
-}
-
-/*
- * String Table
- */
-static char *
-ElfGetStringIndex(ELFModulePtr file, int offset, int index)
-{
- if (!offset || !index)
- return "";
-
- return (char *)(file->saddr[index] + offset);
-}
-
-static char *
-ElfGetString(ELFModulePtr file, int offset)
-{
- return ElfGetStringIndex(file, offset, file->strndx);
-}
-
-static char *
-ElfGetSectionName(ELFModulePtr file, int offset)
-{
- return (char *)(file->shstraddr + offset);
-}
-
-/*
- * Symbol Table
- */
-
-/*
- * Get symbol name
- */
-static char *
-ElfGetSymbolNameIndex(ELFModulePtr elffile, int index, int secndx)
-{
- Elf_Sym *syms;
-
-#ifdef ELFDEBUG
- ELFDEBUG("ElfGetSymbolNameIndex(%x,%x) ", index, secndx);
-#endif
-
- syms = (Elf_Sym *) elffile->saddr[secndx];
-
-#ifdef ELFDEBUG
- ELFDEBUG("%s ", ElfGetString(elffile, syms[index].st_name));
- ELFDEBUG("%x %x ", ELF_ST_BIND(syms[index].st_info),
- ELF_ST_TYPE(syms[index].st_info));
- ELFDEBUG("%lx\n", (unsigned long)syms[index].st_value);
-#endif
-
- return ElfGetString(elffile, syms[index].st_name);
-}
-
-static char *
-ElfGetSymbolName(ELFModulePtr elffile, int index)
-{
- return ElfGetSymbolNameIndex(elffile, index, elffile->symndx);
-}
-
-static Elf_Addr
-ElfGetSymbolValue(ELFModulePtr elffile, int index)
-{
- Elf_Sym *syms;
- Elf_Addr symval = 0; /* value of the indicated symbol */
- char *symname = NULL; /* name of symbol in relocation */
- itemPtr symbol = NULL; /* name/value of symbol */
-
- syms = (Elf_Sym *) elffile->saddr[elffile->symndx];
-
- switch (ELF_ST_TYPE(syms[index].st_info)) {
- case STT_NOTYPE:
- case STT_OBJECT:
- case STT_FUNC:
- switch (ELF_ST_BIND(syms[index].st_info)) {
- case STB_LOCAL:
- symval = (Elf_Addr) (elffile->saddr[syms[index].st_shndx] +
- syms[index].st_value);
-#ifdef __ia64__
- if (ELF_ST_TYPE(syms[index].st_info) == STT_FUNC) {
- ELFOpdPtr opdent;
-
- for (opdent = elffile->opd_entries; opdent;
- opdent = opdent->next)
- if (opdent->index == index)
- break;
- if (opdent) {
- ((unsigned long *)(elffile->got + opdent->offset))[0] =
- symval;
- ((unsigned long *)(elffile->got + opdent->offset))[1] =
- (long)elffile->got;
- symval = (Elf_Addr) (elffile->got + opdent->offset);
- }
- }
-#endif
- break;
- case STB_GLOBAL:
- case STB_WEAK: /* STB_WEAK seems like a hack to cover for
- * some other problem */
- symname = ElfGetString(elffile, syms[index].st_name);
- symbol = LoaderHashFind(symname);
- if (symbol == 0) {
- return 0;
- }
- symval = (Elf_Addr) symbol->address;
- break;
- default:
- symval = 0;
- ErrorF("ElfGetSymbolValue(), unhandled symbol scope %x\n",
- ELF_ST_BIND(syms[index].st_info));
- break;
- }
-#ifdef ELFDEBUG
- ELFDEBUG("%p\t", (void *)symbol);
- ELFDEBUG("%lx\t", (unsigned long)symval);
- ELFDEBUG("%s\n", symname ? symname : "NULL");
-#endif
- break;
- case STT_SECTION:
- symval = (Elf_Addr) elffile->saddr[syms[index].st_shndx];
-#ifdef ELFDEBUG
- ELFDEBUG("ST_SECTION %lx\n", (unsigned long)symval);
-#endif
- break;
- case STT_FILE:
- case STT_LOPROC:
- case STT_HIPROC:
- default:
- symval = 0;
- ErrorF("ElfGetSymbolValue(), unhandled symbol type %x\n",
- ELF_ST_TYPE(syms[index].st_info));
- break;
- }
- return symval;
-}
-
-#if defined(__powerpc__)
-/*
- * This function returns the address of a pseudo PLT routine which can
- * be used to compute a function offset. This is needed because loaded
- * modules have an offset from the .text section of greater than 24 bits.
- * The code generated makes the assumption that all function entry points
- * will be within a 24 bit offset (non-PIC code).
- */
-static Elf_Addr
-ElfGetPltAddr(ELFModulePtr elffile, int index)
-{
- Elf_Sym *syms;
- Elf_Addr symval = 0; /* value of the indicated symbol */
- char *symname = NULL; /* name of symbol in relocation */
- itemPtr symbol; /* name/value of symbol */
-
- syms = (Elf_Sym *) elffile->saddr[elffile->symndx];
-
- switch (ELF_ST_TYPE(syms[index].st_info)) {
- case STT_NOTYPE:
- case STT_OBJECT:
- case STT_FUNC:
- switch (ELF_ST_BIND(syms[index].st_info)) {
- case STB_GLOBAL:
- symname = ElfGetString(elffile, syms[index].st_name);
- symbol = LoaderHashFind(symname);
- if (symbol == 0)
- return 0;
-/*
- * Here we are building up a pseudo Plt function that can make a call to
- * a function that has an offset greater than 24 bits. The following code
- * is being used to implement this.
-
- 1 00000000 .extern realfunc
- 2 00000000 .global pltfunc
- 3 00000000 pltfunc:
- 4 00000000 3d 80 00 00 lis r12,hi16(realfunc)
- 5 00000004 61 8c 00 00 ori r12,r12,lo16(realfunc)
- 6 00000008 7d 89 03 a6 mtctr r12
- 7 0000000c 4e 80 04 20 bctr
-
- */
-
- symbol->code.plt[0] = 0x3d80; /* lis r12 */
- symbol->code.plt[1] =
- (((Elf_Addr) symbol->address) & 0xffff0000) >> 16;
- symbol->code.plt[2] = 0x618c; /* ori r12,r12 */
- symbol->code.plt[3] = (((Elf_Addr) symbol->address) & 0xffff);
- symbol->code.plt[4] = 0x7d89; /* mtcr r12 */
- symbol->code.plt[5] = 0x03a6;
- symbol->code.plt[6] = 0x4e80; /* bctr */
- symbol->code.plt[7] = 0x0420;
- symbol->address = (char *)&symbol->code.plt[0];
- symval = (Elf_Addr) symbol->address;
- ppc_flush_icache(&symbol->code.plt[0]);
- ppc_flush_icache(&symbol->code.plt[6]);
- break;
- default:
- symval = 0;
- ErrorF("ElfGetPltAddr(), unhandled symbol scope %x\n",
- ELF_ST_BIND(syms[index].st_info));
- break;
- }
-# ifdef ELFDEBUG
- ELFDEBUG("ElfGetPlt: symbol=%lx\t", symbol);
- ELFDEBUG("newval=%lx\t", symval);
- ELFDEBUG("name=\"%s\"\n", symname ? symname : "NULL");
-# endif
- break;
- case STT_SECTION:
- case STT_FILE:
- case STT_LOPROC:
- case STT_HIPROC:
- default:
- symval = 0;
- ErrorF("ElfGetPltAddr(), Unexpected symbol type %x",
- ELF_ST_TYPE(syms[index].st_info));
- ErrorF("for a Plt request\n");
- break;
- }
- return symval;
-}
-#endif /* __powerpc__ */
-
-#if defined(__alpha__) || defined(__ia64__)
-/*
- * Manage GOT Entries
- */
-static void
-ElfAddGOT(ELFModulePtr elffile, Elf_Rel_t *rel)
-{
- ELFGotEntryPtr gotent;
-
-# ifdef ELFDEBUG
- {
- Elf_Sym *sym;
-
- sym = (Elf_Sym *) & (elffile->symtab[ELF_R_SYM(rel->r_info)]);
- if (sym->st_name) {
- ELFDEBUG("ElfAddGOT: Adding GOT entry for %s\n",
- ElfGetSymbolName(elffile, ELF_R_SYM(rel->r_info)));
- } else
- ELFDEBUG("ElfAddGOT: Adding GOT entry for %s\n",
- ElfGetSectionName(elffile,
- elffile->sections[sym->st_shndx].
- sh_name));
- }
-# endif
-
- for (gotent = elffile->got_entries; gotent; gotent = gotent->next) {
- if (ELF_R_SYM(gotent->rel->r_info) == ELF_R_SYM(rel->r_info) &&
- gotent->rel->r_addend == rel->r_addend)
- break;
- }
-
- if (gotent) {
-# ifdef ELFDEBUG
- ELFDEBUG("Entry already present in GOT\n");
-# endif
- return;
- }
-
- if ((gotent = xf86loadermalloc(sizeof(ELFGotEntryRec))) == NULL) {
- ErrorF("ElfAddGOT() Unable to allocate memory!!!!\n");
- return;
- }
-# ifdef ELFDEBUG
- ELFDEBUG("Entry added with offset %x\n", elffile->gotsize);
-# endif
- gotent->rel = rel;
- gotent->offset = elffile->gotsize;
- gotent->next = elffile->got_entries;
- elffile->got_entries = gotent;
- elffile->gotsize += 8;
- return;
-}
-
-static int
-ELFCreateGOT(ELFModulePtr elffile, int maxalign)
-{
-# ifdef MergeSectionAlloc
- ELFGotPtr gots;
-# endif
- int gotsize;
-
- /*
- * XXX: Is it REALLY needed to ensure GOT's are non-null?
- */
-# ifdef ELFDEBUG
- ELFDEBUG("ELFCreateGOT: %x entries in the GOT\n", elffile->gotsize / 8);
-
- /*
- * Hmmm. Someone is getting here without any got entries, but they
- * may still have R_ALPHA_GPDISP relocations against the got.
- */
- if (elffile->gotsize == 0)
- ELFDEBUG("Module %s doesn't have any GOT entries!\n",
- _LoaderModuleToName(elffile->module));
-# endif
- if (elffile->gotsize == 0)
- elffile->gotsize = 8;
- elffile->sections[elffile->gotndx].sh_size = elffile->gotsize;
- gotsize = elffile->gotsize;
-
-# ifdef MergeSectionAlloc
-# ifdef __alpha__
-# define GOTDistance 0x100000
-# endif
-# ifdef __ia64__
-# define GOTDistance 0x200000
-# endif
- for (gots = ELFSharedGOTs; gots; gots = gots->next) {
- if (gots->freeptr + elffile->gotsize > gots->section + gots->size)
- continue;
- if (gots->section > elffile->base) {
- if (gots->section + gots->size - elffile->base >= GOTDistance)
- continue;
- } else {
- if (elffile->base + elffile->basesize - gots->section >=
- GOTDistance)
- continue;
- }
- elffile->got = gots->freeptr;
- elffile->shared_got = gots;
- gots->freeptr = gots->freeptr + elffile->gotsize;
- gots->nuses++;
-# ifdef ELFDEBUG
- ELFDEBUG("ELFCreateGOT: GOT address %lx in shared GOT, nuses %d\n",
- elffile->got, gots->nuses);
-# endif
- return TRUE;
- }
-
- gotsize += 16383 + sizeof(ELFGotRec);
-# endif /*MergeSectionAlloc */
-
- if ((elffile->got = xf86loadermalloc(gotsize)) == NULL) {
- ErrorF("ELFCreateGOT() Unable to allocate memory!!!!\n");
- return FALSE;
- }
-# ifdef MergeSectionAlloc
- if (elffile->got > elffile->base) {
- if (elffile->got + elffile->gotsize - elffile->base >= GOTDistance)
- gotsize = 0;
- } else {
- if (elffile->base + elffile->basesize - elffile->got >= GOTDistance)
- gotsize = 0;
- }
-
- 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(__OpenBSD__) || defined(sun)
- {
- unsigned long page_size = getpagesize();
- unsigned long round;
-
- round = (unsigned long)elffile->base & (page_size - 1);
- mprotect(elffile->base - round,
- (elffile->basesize + round + page_size -
- 1) & ~(page_size - 1),
- PROT_READ | PROT_WRITE | PROT_EXEC);
- }
-# 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 {
- gots = (ELFGotPtr) elffile->got;
- elffile->got = gots->section;
- gots->size = gotsize - sizeof(ELFGotRec) + 1;
- gots->nuses = 1;
- gots->freeptr = gots->section + elffile->gotsize;
- gots->next = ELFSharedGOTs;
- ELFSharedGOTs = gots;
- elffile->shared_got = gots;
-# ifdef ELFDEBUG
- ELFDEBUG("ELFCreateGOT: Created a shareable GOT with size %d\n",
- gots->size);
-# endif
- }
-# endif /*MergeSectionAlloc */
-
-# ifdef ELFDEBUG
- ELFDEBUG("ELFCreateGOT: GOT address %lx\n", elffile->got);
-# endif
-
- return TRUE;
-}
-#endif /* defined(__alpha__) || defined(__ia64__) */
-
-#if defined(__ia64__)
-/*
- * Manage OPD Entries
- */
-static void
-ElfAddOPD(ELFModulePtr elffile, int index, LOOKUP *l)
-{
- ELFOpdPtr opdent;
-
- if (index != -1) {
- for (opdent = elffile->opd_entries; opdent; opdent = opdent->next)
- if (opdent->index == index)
- return;
- }
-
- if ((opdent = xf86loadermalloc(sizeof(ELFOpdRec))) == NULL) {
- ErrorF("ElfAddOPD() Unable to allocate memory!!!!\n");
- return;
- }
-# ifdef ELFDEBUG
- ELFDEBUG("OPD Entry %d added with offset %x\n", index, elffile->gotsize);
-# endif
- opdent->l = l;
- opdent->index = index;
- opdent->offset = elffile->gotsize;
- opdent->next = elffile->opd_entries;
- elffile->opd_entries = opdent;
- elffile->gotsize += 16;
- return;
-}
-
-static void
-ELFCreateOPD(ELFModulePtr elffile)
-{
- ELFOpdPtr opdent;
-
- if (elffile->got == NULL)
- ErrorF("ELFCreateOPD() Unallocated GOT!!!!\n");
-
- for (opdent = elffile->opd_entries; opdent; opdent = opdent->next) {
- if (opdent->index != -1)
- continue;
- ((unsigned long *)(elffile->got + opdent->offset))[0] =
- (long)opdent->l->offset;
- ((unsigned long *)(elffile->got + opdent->offset))[1] =
- (long)elffile->got;
- opdent->l->offset = (funcptr) (elffile->got + opdent->offset);
- }
-}
-
-/*
- * Manage PLT Entries
- */
-static void
-ElfAddPLT(ELFModulePtr elffile, Elf_Rel_t *rel)
-{
- ELFPltEntryPtr pltent;
-
-# ifdef ELFDEBUG
- {
- Elf_Sym *sym;
-
- sym = (Elf_Sym *) & (elffile->symtab[ELF_R_SYM(rel->r_info)]);
- if (sym->st_name) {
- ELFDEBUG("ElfAddPLT: Adding PLT entry for %s\n",
- ElfGetSymbolName(elffile, ELF_R_SYM(rel->r_info)));
- } else
- ErrorF("ElfAddPLT: Add PLT entry for section??\n");
- }
-# endif
-
- if (rel->r_addend)
- ErrorF("ElfAddPLT: Add PLT entry with non-zero addend??\n");
-
- for (pltent = elffile->plt_entries; pltent; pltent = pltent->next) {
- if (ELF_R_SYM(pltent->rel->r_info) == ELF_R_SYM(rel->r_info))
- break;
- }
-
- if (pltent) {
-# ifdef ELFDEBUG
- ELFDEBUG("Entry already present in PLT\n");
-# endif
- return;
- }
-
- if ((pltent = xf86loadermalloc(sizeof(ELFPltEntryRec))) == NULL) {
- ErrorF("ElfAddPLT() Unable to allocate memory!!!!\n");
- return;
- }
-# ifdef ELFDEBUG
- ELFDEBUG("Entry added with offset %x\n", elffile->pltsize);
-# endif
- pltent->rel = rel;
- pltent->offset = elffile->pltsize;
- pltent->gotoffset = elffile->gotsize;
- pltent->next = elffile->plt_entries;
- elffile->plt_entries = pltent;
- elffile->pltsize += 32;
- elffile->gotsize += 16;
- return;
-}
-
-static void
-ELFCreatePLT(ELFModulePtr elffile)
-{
-# ifdef ELFDEBUG
- ELFDEBUG("ELFCreatePLT: %x entries in the PLT\n", elffile->pltsize / 8);
-# endif
-
- if (elffile->pltsize == 0)
- return;
-
- if ((elffile->plt =
- ELFLoaderSectCalloc(elffile, 32, elffile->pltsize)) == NULL) {
- ErrorF("ELFCreatePLT() Unable to allocate memory!!!!\n");
- return;
- }
-# if defined(linux) || defined(__OpenBSD__) || defined(sun)
- {
- unsigned long page_size = getpagesize();
- unsigned long round;
-
- round = (unsigned long)elffile->plt & (page_size - 1);
- mprotect(elffile->plt - round,
- (elffile->pltsize + round + page_size - 1) & ~(page_size - 1),
- PROT_READ | PROT_WRITE | PROT_EXEC);
- }
-# endif
-
- elffile->sections[elffile->pltndx].sh_size = elffile->pltsize;
-# ifdef ELFDEBUG
- ELFDEBUG("ELFCreatePLT: PLT address %lx\n", elffile->plt);
-# endif
-
- return;
-}
-
-static void
-IA64InstallReloc(unsigned long *data128, int slot, enum ia64_operand opnd,
- long value)
-{
- unsigned long data = 0;
-
-# ifdef ELFDEBUG
- ELFDEBUG("\nIA64InstallReloc %p %d %d %016lx\n", data128, slot, opnd,
- value);
- ELFDEBUG("Before [%016lx%016lx]\n", data128[1], data128[0]);
-# endif
- switch (slot) {
- case 0:
- data = *data128;
- break;
- case 1:
- memcpy(&data, (char *)data128 + 5, 8);
- break;
- case 2:
- memcpy(&data, (char *)data128 + 10, 6);
- break;
- default:
- FatalError("Unexpected slot in IA64InstallReloc()\n");
- }
- switch (opnd) {
- case IA64_OPND_IMM22:
- data &= ~(0x3fff9fc0000UL << slot);
- data |= (value & 0x7f) << (18 + slot); /* [13:19] + 5 + slot */
- data |= (value & 0xff80) << (25 + slot); /* [27:35] + 5 + slot */
- data |= (value & 0x1f0000) << (11 + slot); /* [22:26] + 5 + slot */
- data |= (value & 0x200000) << (20 + slot); /* [36:36] + 5 + slot */
- if (value << 42 >> 42 != value)
- ErrorF("Relocation %016lx truncated to fit into IMM22\n", value);
- break;
- case IA64_OPND_TGT25C:
- data &= ~(0x23ffffc0000UL << slot);
- data |= (value & 0xfffff0) << (14 + slot); /* [13:32] + 5 + slot */
- data |= (value & 0x1000000) << (17 + slot); /* [36:36] + 5 + slot */
- if (value << 39 >> 39 != value || (value & 0xf))
- ErrorF("Relocation %016lx truncated to fit into TGT25C\n", value);
- break;
-#ifdef IA64_LDX_OPTIMIZATION
- case IA64_OPND_LDXMOV:
- /*
- * Convert "ld8 t2=[t1]" to "mov t2=t1" which is really "add t2=0,t1"
- * Mask all but the r3,r1,qp fields,
- * then OR in the ALU opcode = 8 into the opcode field [40:37]
- *
- * Mask for the r3,r1,qp bit fields [26:20][12:6][5:0] = 0x7f01fff,
- * This mask negated only within the 41 bit wide instruction and
- * shifted left by 5 for the bundle template is 0x3FFF01FC0000
- *
- * opcode field [40:37] with a value of 8 is 0x10000000000
- * shifted left by 5 for the bundle template is 0x200000000000
- *
- */
- data &= ~(0x3FFF01FC0000 << slot);
- data |= (0x200000000000 << slot);
- break;
-#endif
- default:
- FatalError("Unhandled operand in IA64InstallReloc()\n");
- }
- switch (slot) {
- case 0:
- *data128 = data;
- break;
- case 1:
- memcpy((char *)data128 + 5, &data, 8);
- break;
- case 2:
- memcpy((char *)data128 + 10, &data, 6);
- break;
- default:
- FatalError("Unexpected slot in IA64InstallReloc()\n");
- }
- ia64_flush_cache(data128);
-# ifdef ELFDEBUG
- ELFDEBUG("After [%016lx%016lx]\n", data128[1], data128[0]);
-# endif
-}
-
-#endif /*__ia64__*/
-
-/*
- * Fix all of the relocations for the given section.
- * If the argument 'force' is non-zero, then the relocation will be
- * made even if the symbol can't be found (by substituting
- * LoaderDefaultFunc) otherwise, the relocation will be deferred.
- */
-
-static ELFRelocPtr
-Elf_RelocateEntry(ELFModulePtr elffile, Elf_Word secn, Elf_Rel_t *rel,
- int force)
-{
- unsigned char *secp = elffile->saddr[secn];
-
-#if !defined(__ia64__)
- unsigned int *dest32; /* address of the 32 bit place being modified */
-#endif
-#if defined(__powerpc__) || defined(__sparc__)
- unsigned short *dest16; /* address of the 16 bit place being modified */
-#endif
-#if defined(__sparc__)
- unsigned char *dest8; /* address of the 8 bit place being modified */
- unsigned long *dest64;
-#endif
-#if defined(__alpha__)
- unsigned int *dest32h; /* address of the high 32 bit place being modified */
- unsigned long *dest64;
- unsigned short *dest16;
-#endif
-#if defined(__amd64__)
- unsigned long *dest64;
- int *dest32s;
-#endif
-#if defined(__ia64__)
- unsigned long *dest64;
- unsigned long *dest128;
-#endif
- Elf_Addr symval = 0; /* value of the indicated symbol */
-
-#ifdef ELFDEBUG
- ELFDEBUG("%lx %d %d\n", (unsigned long)rel->r_offset,
- ELF_R_SYM(rel->r_info), ELF_R_TYPE(rel->r_info));
-# if defined(__powerpc__) || \
- defined(__mc68000__) || \
- defined(__alpha__) || \
- defined(__sparc__) || \
- defined(__ia64__) || \
- defined(__amd64__)
- ELFDEBUG("%lx", rel->r_addend);
-# endif
- ELFDEBUG("\n");
-#endif /*ELFDEBUG*/
-#if defined(__alpha__)
- if (ELF_R_SYM(rel->r_info)
- && ELF_R_TYPE(rel->r_info) != R_ALPHA_GPDISP)
-#else
- if (ELF_R_SYM(rel->r_info))
-#endif
- {
- symval = ElfGetSymbolValue(elffile, ELF_R_SYM(rel->r_info));
- if (symval == 0) {
- if (force) {
- symval = (Elf_Addr) & LoaderDefaultFunc;
- } else {
-#ifdef ELFDEBUG
- ELFDEBUG("***Unable to resolve symbol %s\n",
- ElfGetSymbolName(elffile, ELF_R_SYM(rel->r_info)));
-#endif
- return ElfDelayRelocation(elffile, secn, rel);
- }
- }
- }
-
- switch (ELF_R_TYPE(rel->r_info)) {
-#if defined(i386)
- case R_386_32:
- dest32 = (unsigned int *)(secp + rel->r_offset);
-# ifdef ELFDEBUG
- ELFDEBUG("R_386_32\t");
- ELFDEBUG("dest32=%p\t", (void *)dest32);
- ELFDEBUG("*dest32=%8.8x\t", (unsigned int)*dest32);
-# endif
- *dest32 = symval + (*dest32); /* S + A */
-# ifdef ELFDEBUG
- ELFDEBUG("*dest32=%8.8x\n", (unsigned int)*dest32);
-# endif
- break;
- case R_386_PC32:
- dest32 = (unsigned int *)(secp + rel->r_offset);
-# ifdef ELFDEBUG
- ELFDEBUG("R_386_PC32 %s\t",
- ElfGetSymbolName(elffile, ELF_R_SYM(rel->r_info)));
- ELFDEBUG("secp=%p\t", secp);
- ELFDEBUG("symval=%lx\t", (unsigned long)symval);
- ELFDEBUG("dest32=%p\t", (void *)dest32);
- ELFDEBUG("*dest32=%8.8x\t", (unsigned int)*dest32);
-# endif
-
- *dest32 = symval + (*dest32) - (Elf_Addr) dest32; /* S + A - P */
-
-# ifdef ELFDEBUG
- ELFDEBUG("*dest32=%8.8x\n", (unsigned int)*dest32);
-# endif
-
- break;
-#endif /* i386 */
-#if defined(__amd64__)
- case R_X86_64_32:
- dest32 = (unsigned int *)(secp + rel->r_offset);
-# ifdef ELFDEBUG
- ELFDEBUG("R_X86_32\t");
- ELFDEBUG("dest32=%x\t", dest32);
- ELFDEBUG("*dest32=%8.8lx\t", *dest32);
- ELFDEBUG("r_addend=%lx\t", rel->r_addend);
-# endif
- *dest32 = symval + rel->r_addend + (*dest32); /* S + A */
-# ifdef ELFDEBUG
- ELFDEBUG("*dest32=%8.8lx\n", *dest32);
-# endif
- break;
- case R_X86_64_32S:
- dest32s = (int *)(secp + rel->r_offset);
-# ifdef ELFDEBUG
- ELFDEBUG("R_X86_64_32\t");
- ELFDEBUG("dest32s=%x\t", dest32s);
- ELFDEBUG("*dest32s=%8.8lx\t", *dest32s);
- ELFDEBUG("r_addend=%lx\t", rel->r_addend);
-# endif
- *dest32s = symval + rel->r_addend + (*dest32s); /* S + A */
-# ifdef ELFDEBUG
- ELFDEBUG("*dest32s=%8.8lx\n", *dest32s);
-# endif
- break;
- case R_X86_64_PC32:
- dest32 = (unsigned int *)(secp + rel->r_offset);
-# ifdef ELFDEBUG
- ELFDEBUG("R_X86_64_PC32 %s\t",
- ElfGetSymbolName(elffile, ELF_R_SYM(rel->r_info)));
- ELFDEBUG("secp=%x\t", secp);
- ELFDEBUG("symval=%lx\t", symval);
- ELFDEBUG("dest32=%x\t", dest32);
- ELFDEBUG("*dest32=%8.8lx\t", *dest32);
- ELFDEBUG("r_addend=%lx\t", rel->r_addend);
-# endif
- *dest32 = symval + rel->r_addend + (*dest32) - (Elf_Addr) dest32; /* S + A - P */
-
-# ifdef ELFDEBUG
- ELFDEBUG("*dest32=%8.8lx\n", *dest32);
-# endif
- break;
- case R_X86_64_64:
- dest64 = (unsigned long *)(secp + rel->r_offset);
-# ifdef ELFDEBUG
- ELFDEBUG("R_AMD64_64\t");
- ELFDEBUG("dest64=%x\t", dest64);
- ELFDEBUG("*dest64=%8.8lx\t", *dest64);
- ELFDEBUG("r_addend=%lx\t", rel->r_addend);
-# endif
- *dest64 = symval + rel->r_addend + (*dest64); /* S + A */
-# ifdef ELFDEBUG
- ELFDEBUG("*dest64=%8.8lx\n", *dest64);
-# endif
- break;
-#endif /* __amd64__ */
-#if defined(__alpha__)
- case R_ALPHA_NONE:
- case R_ALPHA_LITUSE:
- break;
-
- case R_ALPHA_REFQUAD:
- dest64 = (unsigned long *)(secp + rel->r_offset);
- symval = ElfGetSymbolValue(elffile, ELF_R_SYM(rel->r_info));
-# ifdef ELFDEBUG
- ELFDEBUG("R_ALPHA_REFQUAD\t");
- ELFDEBUG("dest64=%lx\t", dest64);
- ELFDEBUG("*dest64=%8.8lx\t", *dest64);
-# endif
- *dest64 = symval + rel->r_addend + (*dest64); /* S + A + P */
-# ifdef ELFDEBUG
- ELFDEBUG("*dest64=%8.8lx\n", *dest64);
-# endif
- break;
-
- case R_ALPHA_GPREL32:
- {
- dest64 = (unsigned long *)(secp + rel->r_offset);
- dest32 = (unsigned int *)dest64;
-
-# ifdef ELFDEBUG
- ELFDEBUG("R_ALPHA_GPREL32 %s\t",
- ElfGetSymbolName(elffile, ELF_R_SYM(rel->r_info)));
- ELFDEBUG("secp=%lx\t", secp);
- ELFDEBUG("symval=%lx\t", symval);
- ELFDEBUG("dest32=%lx\t", dest32);
- ELFDEBUG("*dest32=%8.8x\t", *dest32);
-# endif
- symval += rel->r_addend;
- symval = ((unsigned char *)symval) -
- ((unsigned char *)elffile->got);
-# ifdef ELFDEBUG
- ELFDEBUG("symval=%lx\t", symval);
-# endif
- if ((symval & 0xffffffff00000000) != 0x0000000000000000 &&
- (symval & 0xffffffff00000000) != 0xffffffff00000000) {
- FatalError("R_ALPHA_GPREL32 symval-got is too large for %s\n",
- ElfGetSymbolName(elffile, ELF_R_SYM(rel->r_info)));
- }
-
- *dest32 = symval;
-# ifdef ELFDEBUG
- ELFDEBUG("*dest32=%x\n", *dest32);
-# 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;
-
- dest32 = (unsigned int *)(secp + rel->r_offset);
-# ifdef ELFDEBUG
- ELFDEBUG("R_ALPHA_LITERAL %s\t",
- ElfGetSymbolName(elffile, ELF_R_SYM(rel->r_info)));
- ELFDEBUG("secp=%lx\t", secp);
- ELFDEBUG("symval=%lx\t", symval);
- ELFDEBUG("dest32=%lx\t", dest32);
- ELFDEBUG("*dest32=%8.8x\t", *dest32);
-# endif
-
- for (gotent = elffile->got_entries; gotent; gotent = gotent->next) {
- if (ELF_R_SYM(gotent->rel->r_info) == ELF_R_SYM(rel->r_info)
- && gotent->rel->r_addend == rel->r_addend)
- break;
- }
-
- /* Set the address in the GOT */
- if (gotent) {
- *(unsigned long *)(elffile->got + gotent->offset) =
- symval + rel->r_addend;
-# ifdef ELFDEBUG
- ELFDEBUG("Setting gotent[%x]=%lx\t",
- gotent->offset, symval + rel->r_addend);
-# endif
- if ((gotent->offset & 0xffff0000) != 0)
- FatalError("\nR_ALPHA_LITERAL offset %x too large\n",
- gotent->offset);
- (*dest32) |= (gotent->offset); /* The address part is always 0 */
- } else {
- unsigned long val;
-
- /* S + A - P >> 2 */
- val = ((symval + (rel->r_addend) - (Elf_Addr) dest32));
-# ifdef ELFDEBUG
- ELFDEBUG("S+A-P=%x\t", val);
-# endif
- if ((val & 0xffff0000) != 0xffff0000 &&
- (val & 0xffff0000) != 0x00000000) {
- ErrorF("\nR_ALPHA_LITERAL offset %x too large\n", val);
- break;
- }
- val &= 0x0000ffff;
- (*dest32) |= (val); /* The address part is always 0 */
- }
-# ifdef ELFDEBUG
- ELFDEBUG("*dest32=%8.8x\n", *dest32);
-# endif
-
- break;
- }
-
- case R_ALPHA_GPDISP:
- {
- long offset;
-
- dest32h = (unsigned int *)(secp + rel->r_offset);
- dest32 = (unsigned int *)((secp + rel->r_offset) + rel->r_addend);
-
-# ifdef ELFDEBUG
- ELFDEBUG("R_ALPHA_GPDISP %s\t",
- ElfGetSymbolName(elffile, ELF_R_SYM(rel->r_info)));
- ELFDEBUG("secp=%lx\t", secp);
- ELFDEBUG("got=%lx\t", elffile->got);
- ELFDEBUG("dest32=%lx\t", dest32);
- ELFDEBUG("*dest32=%8.8x\t", *dest32);
- ELFDEBUG("dest32h=%lx\t", dest32h);
- ELFDEBUG("*dest32h=%8.8x\t", *dest32h);
-# endif
- if ((*dest32h >> 26) != 9 || (*dest32 >> 26) != 8) {
- ErrorF("***Bad instructions in relocating %s\n",
- ElfGetSymbolName(elffile, ELF_R_SYM(rel->r_info)));
- }
-
- symval = (*dest32h & 0xffff) << 16 | (*dest32 & 0xffff);
- symval = (symval ^ 0x80008000) - 0x80008000;
-
- offset = ((unsigned char *)elffile->got -
- (unsigned char *)dest32h);
-# ifdef ELFDEBUG
- ELFDEBUG("symval=%lx\t", symval);
- ELFDEBUG("got-dest32=%lx\t", offset);
-# endif
-
- if ((offset >= 0x7fff8000L) || (offset < -0x80000000L)) {
- FatalError("Offset overflow for R_ALPHA_GPDISP\n");
- }
-
- symval += (unsigned long)offset;
-# ifdef ELFDEBUG
- ELFDEBUG("symval=%lx\t", symval);
-# endif
- *dest32 = (*dest32 & 0xffff0000) | (symval & 0xffff);
- *dest32h = (*dest32h & 0xffff0000) |
- (((symval >> 16) + ((symval >> 15) & 1)) & 0xffff);
-# ifdef ELFDEBUG
- ELFDEBUG("*dest32=%8.8x\t", *dest32);
- ELFDEBUG("*dest32h=%8.8x\n", *dest32h);
-# endif
- break;
- }
-
- case R_ALPHA_HINT:
- dest32 = (unsigned int *)((secp + rel->r_offset) + rel->r_addend);
-# ifdef ELFDEBUG
- ELFDEBUG("R_ALPHA_HINT %s\t",
- ElfGetSymbolName(elffile, ELF_R_SYM(rel->r_info)));
- ELFDEBUG("secp=%lx\t", secp);
- ELFDEBUG("symval=%lx\t", symval);
- ELFDEBUG("dest32=%lx\t", dest32);
- ELFDEBUG("*dest32=%8.8x\t", *dest32);
-# endif
-
-# ifdef ELFDEBUG
- ELFDEBUG("symval=%lx\t", symval);
-# endif
- symval -= (Elf_Addr) (((unsigned char *)dest32) + 4);
- if (symval % 4) {
- ErrorF("R_ALPHA_HINT bad alignment of offset\n");
- }
- symval = symval >> 2;
-
-# ifdef ELFDEBUG
- ELFDEBUG("symval=%lx\t", symval);
-# endif
-
- if (symval & 0xffff8000) {
-# ifdef ELFDEBUG
- ELFDEBUG("R_ALPHA_HINT symval too large\n");
-# endif
- }
-
- *dest32 = (*dest32 & ~0x3fff) | (symval & 0x3fff);
-
-# ifdef ELFDEBUG
- 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;
- }
-
- case R_ALPHA_SREL32:
- {
- dest32 = (unsigned int *)(secp + rel->r_offset);
- symval += rel->r_addend;
- symval -= (unsigned long) dest32;
- if ((long)symval >= 0x80000000
- || (long)symval < -(long)0x80000000)
- FatalError("R_ALPHA_SREL32 overflow for %s: %lx\n",
- ElfGetSymbolName(elffile, ELF_R_SYM(rel->r_info)),
- symval);
- *dest32 = symval;
- break;
- }
-
- case R_ALPHA_BRSGP:
- {
- Elf_Sym *syms;
- int Delta;
-
- dest32 = (unsigned int *)((secp + rel->r_offset) + rel->r_addend);
-
-# ifdef ELFDEBUG
- ELFDEBUF("R_ALPHA_BRSGP %s\t",
- ElfGetSymbolName(elffile, ELF_R_SYM(rel->r_info)));
-
- ELFDEBUG("secp=%lx\t", secp);
- ELFDEBUG("symval=%lx\t", symval);
- ELFDEBUG("dest32=%lx\t", dest32);
- ELFDEBUG("*dest32=%8.8x\t", *dest32);
-# endif
-
-# ifdef ELFDEBUG
- ELFDEBUG("symval=%lx\t", symval);
-# endif
- syms = (Elf_Sym *) elffile->saddr[elffile->symndx];
-
- if (syms[ELF_R_SYM(rel->r_info)].st_other & 0x8)
- Delta = -4;
- else
- Delta = 4;
-
- symval -= (Elf_Addr) (((unsigned char *)dest32) + Delta);
- if (symval % 4) {
- ErrorF("R_ALPHA_BRSGP bad alignment of offset\n");
- }
- symval = symval >> 2;
-
-# ifdef ELFDEBUG
- ELFDEBUG("symval=%lx\t", symval);
-# endif
-
- if (symval & 0xffe00000) {
-# ifdef ELFDEBUG
- ELFDEBUG("R_ALPHA_BRSGP symval too large\n");
-# endif
- }
-
- *dest32 = (*dest32 & ~0x1fffff) | (symval & 0x1fffff);
-
-# ifdef ELFDEBUG
- ELFDEBUG("*dest32=%8.8x\n", *dest32);
-# endif
- break;
- }
-
-#endif /* alpha */
-#if defined(__mc68000__)
- case R_68K_32:
- dest32 = (unsigned int *)(secp + rel->r_offset);
-# ifdef ELFDEBUG
- ELFDEBUG("R_68K_32\t");
- ELFDEBUG("secp=%x\t", secp);
- ELFDEBUG("symval=%x\t", symval);
- ELFDEBUG("r_addend=%x\t", rel->r_addend);
- ELFDEBUG("dest32=%8.8x\t", dest32);
- ELFDEBUG("*dest32=%8.8x\n", *dest32);
-# endif
- {
- unsigned long val;
-
- /* S + A */
- val = symval + (rel->r_addend);
-# ifdef ELFDEBUG
- ELFDEBUG("S+A=%x\t", val);
-# endif
- *dest32 = val; /* S + A */
- }
-# ifdef ELFDEBUG
- ELFDEBUG("*dest32=%8.8x\n", *dest32);
-# endif
- break;
- case R_68K_PC32:
- dest32 = (unsigned int *)(secp + rel->r_offset);
-# ifdef ELFDEBUG
- ELFDEBUG("R_68K_PC32\t");
- ELFDEBUG("secp=%x\t", secp);
- ELFDEBUG("symval=%x\t", symval);
- ELFDEBUG("r_addend=%x\t", rel->r_addend);
- ELFDEBUG("dest32=%8.8x\t", dest32);
- ELFDEBUG("*dest32=%8.8x\n", *dest32);
-# endif
- {
- unsigned long val;
-
- /* S + A - P */
- val = symval + (rel->r_addend);
- val -= *dest32;
-# ifdef ELFDEBUG
- ELFDEBUG("S+A=%x\t", val);
- ELFDEBUG("S+A-P=%x\t", val + (*dest32) - (Elf_Addr) dest32);
-# endif
- *dest32 = val + (*dest32) - (Elf_Addr) dest32; /* S + A - P */
- }
-# ifdef ELFDEBUG
- ELFDEBUG("*dest32=%8.8x\n", *dest32);
-# endif
- break;
-#endif /* __mc68000__ */
-#if defined(__powerpc__)
-# if defined(PowerMAX_OS)
- case R_PPC_DISP24: /* 11 */
- dest32 = (unsigned long *)(secp + rel->r_offset);
-# ifdef ELFDEBUG
- ELFDEBUG("R_PPC_DISP24 %s\t",
- ElfGetSymbolName(elffile, ELF_R_SYM(rel->r_info)));
- ELFDEBUG("secp=%x\t", secp);
- ELFDEBUG("symval=%x\t", symval);
- ELFDEBUG("dest32=%x\t", dest32);
- ELFDEBUG("*dest32=%8.8x\t", *dest32);
-# endif
-
- {
- unsigned long val;
-
- /* S + A - P >> 2 */
- val = ((symval + (rel->r_addend) - (Elf_Addr) dest32));
-# ifdef ELFDEBUG
- ELFDEBUG("S+A-P=%x\t", val);
-# endif
- val = val >> 2;
- if ((val & 0x3f000000) != 0x3f000000 &&
- (val & 0x3f000000) != 0x00000000) {
-# ifdef ELFDEBUG
- ELFDEBUG("R_PPC_DISP24 offset %x too large\n", val << 2);
-# endif
- symval = ElfGetPltAddr(elffile, ELF_R_SYM(rel->r_info));
- val = ((symval + (rel->r_addend) - (Elf_Addr) dest32));
-# ifdef ELFDEBUG
- ELFDEBUG("PLT offset is %x\n", val);
-# endif
- val = val >> 2;
- if ((val & 0x3f000000) != 0x3f000000 &&
- (val & 0x3f000000) != 0x00000000)
- FatalError("R_PPC_DISP24 PLT offset %x too large\n",
- val << 2);
- }
- val &= 0x00ffffff;
- (*dest32) |= (val << 2); /* The address part is always 0 */
- ppc_flush_icache(dest32);
- }
-# ifdef ELFDEBUG
- ELFDEBUG("*dest32=%8.8x\n", *dest32);
-# endif
- break;
- case R_PPC_16HU: /* 31 */
- dest16 = (unsigned short *)(secp + rel->r_offset);
-# ifdef ELFDEBUG
- dest32 = (unsigned long *)(dest16 - 1);
-
-# endif
-# ifdef ELFDEBUG
- ELFDEBUG("R_PPC_16HU\t");
- ELFDEBUG("secp=%x\t", secp);
- ELFDEBUG("symval=%x\t", symval);
- ELFDEBUG("r_addend=%x\t", rel->r_addend);
- ELFDEBUG("dest16=%x\t", dest16);
- ELFDEBUG("*dest16=%8.8x\t", *dest16);
- ELFDEBUG("dest32=%8.8x\t", dest32);
- ELFDEBUG("*dest32=%8.8x\n", *dest32);
-# endif
- {
- unsigned short val;
-
- /* S + A */
- val = ((symval + (rel->r_addend)) & 0xffff0000) >> 16;
-# ifdef ELFDEBUG
- ELFDEBUG("uhi16(S+A)=%x\t", val);
-# endif
- *dest16 = val; /* S + A */
- ppc_flush_icache(dest16);
- }
-# ifdef ELFDEBUG
- ELFDEBUG("*dest16=%8.8x\t", *dest16);
- ELFDEBUG("*dest32=%8.8x\n", *dest32);
-# endif
- break;
- case R_PPC_32: /* 32 */
- dest32 = (unsigned long *)(secp + rel->r_offset);
-# ifdef ELFDEBUG
- ELFDEBUG("R_PPC_32\t");
- ELFDEBUG("secp=%x\t", secp);
- ELFDEBUG("symval=%x\t", symval);
- ELFDEBUG("r_addend=%x\t", rel->r_addend);
- ELFDEBUG("dest32=%8.8x\t", dest32);
- ELFDEBUG("*dest32=%8.8x\n", *dest32);
-# endif
- {
- unsigned long val;
-
- /* S + A */
- val = symval + (rel->r_addend);
-# ifdef ELFDEBUG
- ELFDEBUG("S+A=%x\t", val);
-# endif
- *dest32 = val; /* S + A */
- ppc_flush_icache(dest32);
- }
-# ifdef ELFDEBUG
- ELFDEBUG("*dest32=%8.8x\n", *dest32);
-# endif
- break;
- case R_PPC_32UA: /* 33 */
- dest32 = (unsigned long *)(secp + rel->r_offset);
-# ifdef ELFDEBUG
- ELFDEBUG("R_PPC_32UA\t");
- ELFDEBUG("secp=%x\t", secp);
- ELFDEBUG("symval=%x\t", symval);
- ELFDEBUG("r_addend=%x\t", rel->r_addend);
- ELFDEBUG("dest32=%8.8x\t", dest32);
- ELFDEBUG("*dest32=%8.8x\n", *dest32);
-# endif
- {
- unsigned long val;
- unsigned char *dest8 = (unsigned char *)dest32;
-
- /* S + A */
- val = symval + (rel->r_addend);
-# ifdef ELFDEBUG
- ELFDEBUG("S+A=%x\t", val);
-# endif
- *dest8++ = (val & 0xff000000) >> 24;
- *dest8++ = (val & 0x00ff0000) >> 16;
- *dest8++ = (val & 0x0000ff00) >> 8;
- *dest8++ = (val & 0x000000ff);
- ppc_flush_icache(dest32);
- }
-# ifdef ELFDEBUG
- ELFDEBUG("*dest32=%8.8x\n", *dest32);
-# endif
- break;
- case R_PPC_16H: /* 34 */
- dest16 = (unsigned short *)(secp + rel->r_offset);
-# ifdef ELFDEBUG
- dest32 = (unsigned long *)(dest16 - 1);
-# endif
-# ifdef ELFDEBUG
- ELFDEBUG("R_PPC_16H\t");
- ELFDEBUG("secp=%x\t", secp);
- ELFDEBUG("symbol=%s\t",
- ElfGetSymbolName(elffile, ELF_R_SYM(rel->r_info)));
- ELFDEBUG("symval=%x\t", symval);
- ELFDEBUG("r_addend=%x\t", rel->r_addend);
- ELFDEBUG("dest16=%x\t", dest16);
- ELFDEBUG("*dest16=%8.8x\t", *dest16);
- ELFDEBUG("dest32=%8.8x\t", dest32);
- ELFDEBUG("*dest32=%8.8x\n", *dest32);
-# endif
- {
- unsigned short val;
- unsigned short loval;
-
- /* S + A */
- val = ((symval + (rel->r_addend)) & 0xffff0000) >> 16;
- loval = (symval + (rel->r_addend)) & 0xffff;
- if (loval & 0x8000) {
- /*
- * This is hi16(), instead of uhi16(). Because of this,
- * if the lo16() will produce a negative offset, then
- * we have to increment this part of the address to get
- * the correct final result.
- */
- val++;
- }
-# ifdef ELFDEBUG
- ELFDEBUG("hi16(S+A)=%x\t", val);
-# endif
- *dest16 = val; /* S + A */
- ppc_flush_icache(dest16);
- }
-# ifdef ELFDEBUG
- ELFDEBUG("*dest16=%8.8x\t", *dest16);
- ELFDEBUG("*dest32=%8.8x\n", *dest32);
-# endif
- break;
- case R_PPC_16L: /* 35 */
- dest16 = (unsigned short *)(secp + rel->r_offset);
-# ifdef ELFDEBUG
- dest32 = (unsigned long *)(dest16 - 1);
-# endif
-# ifdef ELFDEBUG
- ELFDEBUG("R_PPC_16L\t");
- ELFDEBUG("secp=%x\t", secp);
- ELFDEBUG("symval=%x\t", symval);
- ELFDEBUG("r_addend=%x\t", rel->r_addend);
- ELFDEBUG("dest16=%x\t", dest16);
- ELFDEBUG("*dest16=%8.8x\t", *dest16);
- ELFDEBUG("dest32=%8.8x\t", dest32);
- ELFDEBUG("*dest32=%8.8x\n", *dest32);
-# endif
- {
- unsigned short val;
-
- /* S + A */
- val = (symval + (rel->r_addend)) & 0xffff;
-# ifdef ELFDEBUG
- ELFDEBUG("lo16(S+A)=%x\t", val);
-# endif
- *dest16 = val; /* S + A */
- ppc_flush_icache(dest16);
- }
-# ifdef ELFDEBUG
- ELFDEBUG("*dest16=%8.8x\t", *dest16);
- ELFDEBUG("*dest32=%8.8x\n", *dest32);
-# endif
- break;
-# else /* PowerMAX_OS */
- /* Linux PPC */
- case R_PPC_ADDR32: /* 1 */
- dest32 = (unsigned int *)(secp + rel->r_offset);
- symval = ElfGetSymbolValue(elffile, ELF_R_SYM(rel->r_info));
-# ifdef ELFDEBUG
- ELFDEBUG("R_PPC_ADDR32\t");
- ELFDEBUG("secp=%x\t", secp);
- ELFDEBUG("symval=%x\t", symval);
- ELFDEBUG("r_addend=%x\t", rel->r_addend);
- ELFDEBUG("dest32=%8.8x\t", dest32);
- ELFDEBUG("*dest32=%8.8x\n", *dest32);
-# endif
- {
- unsigned long val;
-
- /* S + A */
- val = symval + (rel->r_addend);
-# ifdef ELFDEBUG
- ELFDEBUG("S+A=%x\t", val);
-# endif
- *dest32 = val; /* S + A */
- ppc_flush_icache(dest32);
- }
-# ifdef ELFDEBUG
- ELFDEBUG("*dest32=%8.8x\n", *dest32);
-# endif
- break;
- case R_PPC_ADDR16_LO: /* 4 */
- dest16 = (unsigned short *)(secp + rel->r_offset);
-# ifdef ELFDEBUG
- dest32 = (unsigned long *)(dest16 - 1);
-# endif
-# ifdef ELFDEBUG
- ELFDEBUG("R_PPC_ADDR16_LO\t");
- ELFDEBUG("secp=%x\t", secp);
- ELFDEBUG("symval=%x\t", symval);
- ELFDEBUG("r_addend=%x\t", rel->r_addend);
- ELFDEBUG("dest16=%x\t", dest16);
- ELFDEBUG("*dest16=%8.8x\t", *dest16);
-# endif
- {
- unsigned short val;
-
- /* S + A */
- val = (symval + (rel->r_addend)) & 0xffff;
-# ifdef ELFDEBUG
- ELFDEBUG("lo16(S+A)=%x\t", val);
-# endif
- *dest16 = val; /* S + A */
- ppc_flush_icache(dest16);
- }
-# ifdef ELFDEBUG
- ELFDEBUG("*dest16=%8.8x\t", *dest16);
- ELFDEBUG("*dest32=%8.8x\n", *dest32);
-# endif
- break;
- case R_PPC_ADDR16_HA: /* 6 */
- dest16 = (unsigned short *)(secp + rel->r_offset);
-# ifdef ELFDEBUG
- dest32 = (unsigned long *)(dest16 - 1);
-# endif
-# ifdef ELFDEBUG
- ELFDEBUG("R_PPC_ADDR16_HA\t");
- ELFDEBUG("secp=%x\t", secp);
- ELFDEBUG("symval=%x\t", symval);
- ELFDEBUG("r_addend=%x\t", rel->r_addend);
- ELFDEBUG("dest16=%x\t", dest16);
- ELFDEBUG("*dest16=%8.8x\t", *dest16);
-# endif
- {
- unsigned short val;
- unsigned short loval;
-
- /* S + A */
- val = ((symval + (rel->r_addend)) & 0xffff0000) >> 16;
- loval = (symval + (rel->r_addend)) & 0xffff;
- if (loval & 0x8000) {
- /*
- * This is hi16(), instead of uhi16(). Because of this,
- * if the lo16() will produce a negative offset, then
- * we have to increment this part of the address to get
- * the correct final result.
- */
- val++;
- }
-# ifdef ELFDEBUG
- ELFDEBUG("hi16(S+A)=%x\t", val);
-# endif
- *dest16 = val; /* S + A */
- ppc_flush_icache(dest16);
- }
-# ifdef ELFDEBUG
- ELFDEBUG("*dest16=%8.8x\t", *dest16);
- ELFDEBUG("*dest32=%8.8x\n", *dest32);
-# endif
- break;
- case R_PPC_REL24: /* 10 */
- dest32 = (unsigned int *)(secp + rel->r_offset);
-# ifdef ELFDEBUG
- ELFDEBUG("R_PPC_REL24 %s\t",
- ElfGetSymbolName(elffile, ELF_R_SYM(rel->r_info)));
- ELFDEBUG("secp=%x\t", secp);
- ELFDEBUG("symval=%x\t", symval);
- ELFDEBUG("dest32=%x\t", dest32);
- ELFDEBUG("*dest32=%8.8x\t", *dest32);
-# endif
-
- {
- unsigned long val;
-
- /* S + A - P >> 2 */
- val = ((symval + (rel->r_addend) - (Elf_Addr) dest32));
-# ifdef ELFDEBUG
- ELFDEBUG("S+A-P=%x\t", val);
-# endif
- val = val >> 2;
- if ((val & 0x3f000000) != 0x3f000000 &&
- (val & 0x3f000000) != 0x00000000) {
-# ifdef ELFDEBUG
- ELFDEBUG("R_PPC_REL24 offset %x too large\n", val << 2);
-# endif
- symval = ElfGetPltAddr(elffile, ELF_R_SYM(rel->r_info));
- val = ((symval + (rel->r_addend) - (Elf_Addr) dest32));
-# ifdef ELFDEBUG
- ELFDEBUG("PLT offset is %x\n", val);
-# endif
- val = val >> 2;
- if ((val & 0x3f000000) != 0x3f000000 &&
- (val & 0x3f000000) != 0x00000000)
- FatalError("R_PPC_REL24 PLT offset %x too large\n",
- val << 2);
- }
- val &= 0x00ffffff;
- (*dest32) |= (val << 2); /* The address part is always 0 */
- ppc_flush_icache(dest32);
- }
-# ifdef ELFDEBUG
- ELFDEBUG("*dest32=%8.8x\n", *dest32);
-# endif
- break;
- case R_PPC_REL32: /* 26 */
- dest32 = (unsigned int *)(secp + rel->r_offset);
-# ifdef ELFDEBUG
- ELFDEBUG("R_PPC_REL32\t");
- ELFDEBUG("secp=%x\t", secp);
- ELFDEBUG("symval=%x\t", symval);
- ELFDEBUG("r_addend=%x\t", rel->r_addend);
- ELFDEBUG("dest32=%8.8x\t", dest32);
- ELFDEBUG("*dest32=%8.8x\n", *dest32);
-# endif
- {
- unsigned long val;
-
- /* S + A - P */
- val = symval + (rel->r_addend);
- val -= *dest32;
-# ifdef ELFDEBUG
- ELFDEBUG("S+A=%x\t", val);
- ELFDEBUG("S+A-P=%x\t", val + (*dest32) - (Elf_Addr) dest32);
-# endif
- *dest32 = val + (*dest32) - (Elf_Addr) dest32; /* S + A - P */
- ppc_flush_icache(dest32);
- }
-# ifdef ELFDEBUG
- ELFDEBUG("*dest32=%8.8x\n", *dest32);
-# endif
- break;
-# endif /* PowerMAX_OS */
-#endif /* __powerpc__ */
-#ifdef __sparc__
- case R_SPARC_NONE: /* 0 */
- break;
-
- case R_SPARC_8: /* 1 */
- dest8 = (unsigned char *)(secp + rel->r_offset);
- symval += rel->r_addend;
- *dest8 = symval;
- break;
-
- case R_SPARC_16: /* 2 */
- dest16 = (unsigned short *)(secp + rel->r_offset);
- symval += rel->r_addend;
- *dest16 = symval;
- break;
-
- case R_SPARC_32: /* 3 */
- case R_SPARC_UA32: /* 23 */
- dest32 = (unsigned int *)(secp + rel->r_offset);
- symval += rel->r_addend;
- ((unsigned char *)dest32)[0] = (unsigned char)(symval >> 24);
- ((unsigned char *)dest32)[1] = (unsigned char)(symval >> 16);
- ((unsigned char *)dest32)[2] = (unsigned char)(symval >> 8);
- ((unsigned char *)dest32)[3] = (unsigned char)(symval);
- break;
-
- case R_SPARC_GLOB_DAT: /* 20 */
- case R_SPARC_64: /* 32 */
- dest64 = (unsigned long *)(secp + rel->r_offset);
- symval += rel->r_addend;
- *dest64 = symval;
- break;
-
- case R_SPARC_DISP8: /* 4 */
- dest8 = (unsigned char *)(secp + rel->r_offset);
- symval += rel->r_addend;
- *dest8 = (symval - (Elf_Addr) dest8);
- break;
-
- case R_SPARC_DISP16: /* 5 */
- dest16 = (unsigned short *)(secp + rel->r_offset);
- symval += rel->r_addend;
- *dest16 = (symval - (Elf_Addr) dest16);
- break;
-
- case R_SPARC_DISP32: /* 6 */
- dest32 = (unsigned int *)(secp + rel->r_offset);
- symval += rel->r_addend;
- *dest32 = (symval - (Elf_Addr) dest32);
- break;
-
- case R_SPARC_WDISP30: /* 7 */
- dest32 = (unsigned int *)(secp + rel->r_offset);
- symval += rel->r_addend;
- *dest32 = ((*dest32 & 0xc0000000) |
- (((symval - (Elf_Addr) dest32) >> 2) & 0x3fffffff));
- break;
-
- case R_SPARC_HI22: /* 9 */
- dest32 = (unsigned int *)(secp + rel->r_offset);
- symval += rel->r_addend;
- *dest32 = (*dest32 & 0xffc00000) | (symval >> 10);
- break;
-
- case R_SPARC_LO10: /* 12 */
- dest32 = (unsigned int *)(secp + rel->r_offset);
- symval += rel->r_addend;
- *dest32 = (*dest32 & ~0x3ff) | (symval & 0x3ff);
- break;
-
- case R_SPARC_COPY: /* 19 */
- /* Fix your code... I'd rather dish out an error here
- * so people will not link together PIC and non-PIC
- * code into a final driver object file.
- */
- ErrorF("Elf_RelocateEntry():"
- " Copy relocs not supported on Sparc.\n");
- break;
-
- case R_SPARC_JMP_SLOT: /* 21 */
- dest32 = (unsigned int *)(secp + rel->r_offset);
- /* Before we change it the PLT entry looks like:
- *
- * pltent: sethi %hi(rela_plt_offset), %g1
- * b,a PLT0
- * nop
- *
- * We change it into:
- *
- * pltent: sethi %hi(rela_plt_offset), %g1
- * sethi %hi(symval), %g1
- * jmp %g1 + %lo(symval), %g0
- */
- symval += rel->r_addend;
- dest32[2] = 0x81c06000 | (symval & 0x3ff);
- __asm __volatile("flush %0 + 0x8"::"r"(dest32));
-
- dest32[1] = 0x03000000 | (symval >> 10);
- __asm __volatile("flush %0 + 0x4"::"r"(dest32));
-
- break;
-
- case R_SPARC_RELATIVE: /* 22 */
- dest64 = (unsigned long *)(secp + rel->r_offset);
- *dest64 = (unsigned long)secp + rel->r_addend;
- break;
-#endif /*__sparc__*/
-#ifdef __ia64__
- case R_IA64_NONE:
- break;
-
- case R_IA64_LTOFF_FPTR22:
- if (rel->r_addend)
- FatalError("\nAddend for R_IA64_LTOFF_FPTR22 not supported\n");
-# ifdef ELFDEBUG
- ELFDEBUG("opd=%016lx.%016lx\n",
- ((long *)symval)[0], ((long *)symval)[1]);
-# endif
- /* FALLTHROUGH */
- case R_IA64_LTOFF22:
-#ifndef IA64_LDX_OPTIMIZATION
- case R_IA64_LTOFF22X: /* If not implementing LDXMOV optimization treat LTOFF22X as LTOFF22 */
-#endif
- {
- ELFGotEntryPtr gotent;
-
- dest128 = (unsigned long *)(secp + (rel->r_offset & ~3));
-# ifdef ELFDEBUG
- ELFDEBUG("%s %s\t", ELF_R_TYPE(rel->r_info) == R_IA64_LTOFF22 ?
- "R_IA64_LTOFF22" : "R_IA64_LTOFF_FPTR22",
- ElfGetSymbolName(elffile, ELF_R_SYM(rel->r_info)));
- ELFDEBUG("secp=%lx\t", secp);
- ELFDEBUG("symval=%lx\t", symval);
- ELFDEBUG("dest128=%lx\t", dest128);
- ELFDEBUG("slot=%d\n", rel->r_offset & 3);
- ELFDEBUG("*dest128=[%016lx%016lx]\n", dest128[1], dest128[0]);
-# endif
-
- for (gotent = elffile->got_entries; gotent; gotent = gotent->next) {
- if (ELF_R_SYM(gotent->rel->r_info) == ELF_R_SYM(rel->r_info)
- && gotent->rel->r_addend == rel->r_addend)
- break;
- }
-
- /* Set the address in the GOT */
- if (gotent) {
- *(unsigned long *)(elffile->got + gotent->offset) =
- symval + rel->r_addend;
-# ifdef ELFDEBUG
- ELFDEBUG("Setting gotent[%x]=%lx\n",
- gotent->offset, symval + rel->r_addend);
-# endif
- if ((gotent->offset & 0xffe00000) != 0)
- FatalError("\nR_IA64_LTOFF22 offset %x too large\n",
- gotent->offset);
- IA64InstallReloc(dest128, rel->r_offset & 3, IA64_OPND_IMM22,
- gotent->offset);
- } else
- FatalError("\nCould not find GOT entry\n");
- }
- break;
-
- case R_IA64_PCREL21B:
- {
- ELFPltEntryPtr pltent;
-
- dest128 = (unsigned long *)(secp + (rel->r_offset & ~3));
-# ifdef ELFDEBUG
- ELFDEBUG("R_IA64_PCREL21B %s\t",
- ElfGetSymbolName(elffile, ELF_R_SYM(rel->r_info)));
- ELFDEBUG("secp=%lx\t", secp);
- ELFDEBUG("symval=%lx\t", symval);
- ELFDEBUG("opd=%lx.%lx\t", ((long *)symval)[0],
- ((long *)symval)[1]);
- ELFDEBUG("dest128=%lx\t", dest128);
- ELFDEBUG("slot=%d\n", rel->r_offset & 3);
- ELFDEBUG("*dest128=[%016lx%016lx]\n", dest128[1], dest128[0]);
-# endif
- if (rel->r_addend)
- FatalError("\nAddend for PCREL21B not supported\n");
- if (((long *)symval)[1] == (long)elffile->got
- && (((unsigned long)dest128 - ((unsigned long *)symval)[0]) +
- 0x2000000 < 0x4000000)) {
- /* We can save the travel through PLT */
- IA64InstallReloc(dest128, rel->r_offset & 3, IA64_OPND_TGT25C,
- ((unsigned long *)symval)[0] -
- (unsigned long)dest128);
- break;
- }
- for (pltent = elffile->plt_entries; pltent; pltent = pltent->next) {
- if (ELF_R_SYM(pltent->rel->r_info) == ELF_R_SYM(rel->r_info)
- && pltent->rel->r_addend == rel->r_addend)
- break;
- }
-
- /* Set the address in the PLT */
- if (pltent == NULL)
- FatalError("\nCould not find PLT entry\n");
- else {
- unsigned long *p =
- (unsigned long *)(elffile->plt + pltent->offset);
- unsigned long r =
- (unsigned long)symval - (unsigned long)elffile->got;
-
- if (r + 0x200000 >= 0x400000) {
- /* Too far from gp to use the official function descriptor,
- * so we have to make a local one.
- */
- r = pltent->gotoffset;
- memcpy(elffile->got + r, (char *)symval, 16);
- }
-
- /* [MMI] addl r15=NNN,r1;; ld8 r16=[r15],8; mov r14=r1;; */
- p[0] = 0x410024000200780bUL;
- p[1] = 0x84000801c028303cUL;
- /* [MIB] ld8 r1=[r15]; mov b6=r16; br.few b6;; */
- p[2] = 0x806010181e000811UL;
- p[3] = 0x0080006000038004UL;
- IA64InstallReloc(p, 0, IA64_OPND_IMM22, r);
- IA64InstallReloc(dest128, rel->r_offset & 3, IA64_OPND_TGT25C,
- (unsigned long)p - (unsigned long)dest128);
- }
- }
- break;
-
- case R_IA64_FPTR64LSB:
- dest64 = (unsigned long *)(secp + rel->r_offset);
-# ifdef ELFDEBUG
- ELFDEBUG("R_IA64_FPTR64LSB %s\t",
- ElfGetSymbolName(elffile, ELF_R_SYM(rel->r_info)));
- ELFDEBUG("secp=%lx\t", secp);
- ELFDEBUG("symval=%lx\t", symval);
- ELFDEBUG("dest64=%lx\t", dest64);
- ELFDEBUG("opd=%016lx.%016lx\n", ((long *)symval)[0],
- ((long *)symval)[1]);
-# endif
-
- if (rel->r_addend)
- FatalError("\nAddend not supported for R_IA64_FPTR64LSB\n");
- *dest64 = symval;
- ia64_flush_cache(dest64);
- break;
-
- case R_IA64_DIR64LSB:
- dest64 = (unsigned long *)(secp + rel->r_offset);
-# ifdef ELFDEBUG
- ELFDEBUG("R_IA64_DIR64LSB %s\t",
- ElfGetSymbolName(elffile, ELF_R_SYM(rel->r_info)));
- ELFDEBUG("secp=%lx\t", secp);
- ELFDEBUG("symval=%lx\t", symval);
- ELFDEBUG("dest64=%lx\n", dest64);
-# endif
- *dest64 = symval + rel->r_addend;
- ia64_flush_cache(dest64);
- break;
-
- case R_IA64_PCREL64LSB:
- dest64 = (unsigned long *)(secp + rel->r_offset);
-#ifdef ELFDEBUG
- ELFDEBUG("R_IA64_PCREL64LSB %s\t",
- ElfGetSymbolName(elffile, ELF_R_SYM(rel->r_info)));
- ELFDEBUG("secp=%lx\t", secp);
- ELFDEBUG("symval=%lx\t", symval);
- ELFDEBUG("dest64=%lx\n", dest64);
-#endif
- *dest64 = symval + rel->r_addend - (unsigned long)dest64;
- break;
-
- case R_IA64_GPREL22:
- dest128 = (unsigned long *)(secp + (rel->r_offset & ~3));
-# ifdef ELFDEBUG
- ELFDEBUG("R_IA64_GPREL22 %s\t",
- ElfGetSymbolName(elffile, ELF_R_SYM(rel->r_info)));
- ELFDEBUG("secp=%lx\t", secp);
- ELFDEBUG("symval=%lx\t", symval);
- ELFDEBUG("dest128=%lx\t", dest128);
- ELFDEBUG("slot=%d\n", rel->r_offset & 3);
- ELFDEBUG("*dest128=[%016lx%016lx]\n", dest128[1], dest128[0]);
-# endif
- IA64InstallReloc(dest128, rel->r_offset & 3, IA64_OPND_IMM22,
- symval + rel->r_addend - (long)elffile->got);
- break;
-
-#ifdef IA64_LDX_OPTIMIZATION
- case R_IA64_LTOFF22X:
- {
- ELFGotEntryPtr gotent;
- long gp_offset = symval + rel->r_addend - (long)elffile->got;
-
- dest128 = (unsigned long *)(secp + (rel->r_offset & ~3));
-
-# ifdef ELFDEBUG
- ELFDEBUG("R_IA64_LTOFF22X %s\t",
- ElfGetSymbolName(elffile, ELF_R_SYM(rel->r_info)));
- ELFDEBUG("secp=%lx\t", secp);
- ELFDEBUG("symval=%lx\t", symval);
- ELFDEBUG("dest128=%lx\t", dest128);
- ELFDEBUG("slot=%d\n", rel->r_offset & 3);
-# endif
-
- if (gp_offset << 42 >> 42 != gp_offset) {
- /* Offset is too large for LTOFF22X,
- * fallback to using GOT lookup, e.g. LTOFF22.
- * Note: LDXMOV will fail the same test and will be ignored. */
-
-# ifdef ELFDEBUG
- ELFDEBUG("gp_offset=%ld too large, using GOT instead (LTOFF22)\n", gp_offset);
-# endif
-
- for (gotent = elffile->got_entries; gotent;
- gotent = gotent->next) {
- if (ELF_R_SYM(gotent->rel->r_info) ==
- ELF_R_SYM(rel->r_info)
- && gotent->rel->r_addend == rel->r_addend)
- break;
- }
-
- /* Set the address in the GOT */
- if (gotent) {
- *(unsigned long *)(elffile->got + gotent->offset) =
- symval + rel->r_addend;
-# ifdef ELFDEBUG
- ELFDEBUG("Setting gotent[%x]=%lx\n", gotent->offset,
- symval + rel->r_addend);
-# endif
- if ((gotent->offset & 0xffe00000) != 0)
- FatalError("\nR_IA64_LTOFF22 offset %x too large\n",
- gotent->offset);
- } else {
- FatalError("\nCould not find GOT entry\n");
- }
- gp_offset = gotent->offset; /* Use GOT lookup */
- } else {
-# ifdef ELFDEBUG
- ELFDEBUG("using gp_offset=%ld (LTOFF22X)", gp_offset);
-# endif
- }
- IA64InstallReloc(dest128, rel->r_offset & 3, IA64_OPND_IMM22,
- gp_offset);
- }
- break;
-#endif
-
- case R_IA64_LDXMOV:
-# ifdef ELFDEBUG
- ELFDEBUG("R_IA64_LDXMOV %s\t",
- ElfGetSymbolName(elffile, ELF_R_SYM(rel->r_info)));
-# endif
-
-#ifdef IA64_LDX_OPTIMIZATION
- {
- long gp_offset = symval + rel->r_addend - (long)elffile->got;
-
- dest128 = (unsigned long *)(secp + (rel->r_offset & ~3));
-
- if (gp_offset << 42 >> 42 != gp_offset) {
- /* Offset is too large for LTOFF22X, ignore this relocation */
-# ifdef ELFDEBUG
- ELFDEBUG("offset = %ld too large, ignoring\n", gp_offset);
-# endif
- } else {
-
-# ifdef ELFDEBUG
- ELFDEBUG("secp=%lx\t", secp);
- ELFDEBUG("symval=%lx\t", symval);
- ELFDEBUG("dest128=%lx\t", dest128);
- ELFDEBUG("slot=%d\n", rel->r_offset & 3);
- ELFDEBUG("offset=%ld\n", gp_offset);
- ELFDEBUG("*dest128=[%016lx%016lx]\n", dest128[1], dest128[0]);
-# endif
-
- IA64InstallReloc(dest128, rel->r_offset & 3, IA64_OPND_LDXMOV,
- 0);
- }
- }
-#endif
- break;
-
-#endif /*__ia64__*/
-
-#if defined(__arm__)
- case R_ARM_ABS32:
- dest32 = (unsigned int *)(secp + rel->r_offset);
-# ifdef ELFDEBUG
- ELFDEBUG("R_ARM_ABS32\t");
- ELFDEBUG("dest32=%x\t", dest32);
- ELFDEBUG("*dest32=%8.8lx\t", *dest32);
-# endif
- *dest32 = symval + (*dest32); /* S + A */
-# ifdef ELFDEBUG
- ELFDEBUG("*dest32=%8.8lx\n", *dest32);
-# endif
- break;
-
- case R_ARM_REL32:
- dest32 = (unsigned int *)(secp + rel->r_offset);
-# ifdef ELFDEBUG
- {
- char *namestr;
-
- ELFDEBUG("R_ARM_REL32 %s\t",
- namestr =
- ElfGetSymbolName(elffile, ELF_R_SYM(rel->r_info)));
- xf86loaderfree(namestr);
- ELFDEBUG("secp=%x\t", secp);
- ELFDEBUG("symval=%lx\t", symval);
- ELFDEBUG("dest32=%x\t", dest32);
- ELFDEBUG("*dest32=%8.8lx\t", *dest32);
- }
-# endif
-
- *dest32 = symval + (*dest32) - (Elf_Addr) dest32; /* S + A - P */
-
-# ifdef ELFDEBUG
- ELFDEBUG("*dest32=%8.8lx\n", *dest32);
-# endif
-
- break;
-
- case R_ARM_PC24:
- {
- unsigned long val;
-
- dest32 = (unsigned int *)(secp + rel->r_offset);
- val = (*dest32 & 0x00ffffff) << 2;
- val = symval - (unsigned long)dest32 + val;
- val >>= 2;
- *dest32 = (*dest32 & 0xff000000) | (val & 0x00ffffff);
-#ifdef NOTYET
- arm_flush_cache(dest32);
-#endif
- }
- break;
-
-#endif /* (__arm__) */
-
- default:
- ErrorF("Elf_RelocateEntry() Unsupported relocation type %d\n",
- (int)ELF_R_TYPE(rel->r_info));
- break;
- }
- return 0;
-}
-
-static ELFRelocPtr
-ELFCollectRelocations(elffile, index)
- ELFModulePtr elffile;
- int index; /* The section to use as relocation data */
-{
- int i, numrel;
- Elf_Shdr *sect = &(elffile->sections[index]);
- Elf_Rel_t *rel = (Elf_Rel_t *) elffile->saddr[index];
- ELFRelocPtr reloc_head = NULL;
- ELFRelocPtr tmp;
-
- numrel = sect->sh_size / sect->sh_entsize;
-
- for (i = 0; i < numrel; i++) {
-#if defined(__alpha__)
- if (ELF_R_TYPE(rel[i].r_info) == R_ALPHA_LITERAL) {
- ElfAddGOT(elffile, &rel[i]);
- }
-#endif
-#if defined(__ia64__)
- if (ELF_R_TYPE(rel[i].r_info) == R_IA64_LTOFF22
- || ELF_R_TYPE(rel[i].r_info) == R_IA64_LTOFF22X
- || ELF_R_TYPE(rel[i].r_info) == R_IA64_LTOFF_FPTR22) {
- ElfAddGOT(elffile, &rel[i]);
- }
- if (ELF_R_TYPE(rel[i].r_info) == R_IA64_PCREL21B) {
- ElfAddPLT(elffile, &rel[i]);
- }
- if (ELF_R_TYPE(rel[i].r_info) == R_IA64_LTOFF_FPTR22
- || ELF_R_TYPE(rel[i].r_info) == R_IA64_FPTR64LSB) {
- Elf_Sym *syms = (Elf_Sym *) elffile->saddr[elffile->symndx];
-
- if (ELF_ST_BIND(syms[ELF_R_SYM(rel[i].r_info)].st_info) ==
- STB_LOCAL) {
- ElfAddOPD(elffile, ELF_R_SYM(rel[i].r_info), NULL);
- }
- }
-#endif
- tmp = ElfDelayRelocation(elffile, sect->sh_info, &(rel[i]));
- tmp->next = reloc_head;
- reloc_head = tmp;
- }
-
- return reloc_head;
-}
-
-/*
- * ELF_GetSymbols()
- *
- * add the symbols to the symbol table maintained by the loader.
- */
-
-static LOOKUP *
-ELF_GetSymbols(ELFModulePtr elffile, unsigned short **psecttable)
-{
- Elf_Sym *syms;
- Elf_Shdr *sect;
- int i, l, numsyms;
- LOOKUP *lookup, *p;
- ELFCommonPtr tmp;
- unsigned short *secttable;
-
- syms = elffile->symtab;
- sect = &(elffile->sections[elffile->symndx]);
- numsyms = sect->sh_size / sect->sh_entsize;
-
- if ((lookup = xf86loadermalloc((numsyms + 1) * sizeof(LOOKUP))) == NULL)
- return 0;
-
- if ((secttable =
- xf86loadercalloc(sizeof(unsigned short), (numsyms + 1))) == NULL) {
- xf86loaderfree(lookup);
- return 0;
- }
- *psecttable = secttable;
-
- for (i = 0, l = 0; i < numsyms; i++) {
-#ifdef ELFDEBUG
- ELFDEBUG("value=%lx\tsize=%lx\tBIND=%x\tTYPE=%x\tndx=%x\t%s\n",
- (unsigned long)syms[i].st_value,
- (unsigned long)syms[i].st_size,
- ELF_ST_BIND(syms[i].st_info), ELF_ST_TYPE(syms[i].st_info),
- syms[i].st_shndx, ElfGetString(elffile, syms[i].st_name));
-#endif
-
- if (ELF_ST_BIND(syms[i].st_info) == STB_LOCAL)
- /* Don't add static symbols to the symbol table */
- continue;
-
- switch (ELF_ST_TYPE(syms[i].st_info)) {
- case STT_OBJECT:
- case STT_FUNC:
- case STT_SECTION:
- case STT_NOTYPE:
- switch (syms[i].st_shndx) {
- case SHN_ABS:
- ErrorF("ELF_GetSymbols() Don't know how to handle SHN_ABS\n");
- break;
- case SHN_COMMON:
-#ifdef ELFDEBUG
- ELFDEBUG("Adding COMMON space for %s\n",
- ElfGetString(elffile, syms[i].st_name));
-#endif
- if (!LoaderHashFind(ElfGetString(elffile, syms[i].st_name))) {
- tmp = ElfAddCOMMON(&(syms[i]));
- if (tmp) {
- tmp->next = listCOMMON;
- listCOMMON = tmp;
- }
- }
- break;
- case SHN_UNDEF:
- /*
- * UNDEF will get resolved later, so the value
- * doesn't really matter here.
- */
- /* since we don't know the value don't advertise the symbol */
- break;
- default:
- lookup[l].symName =
- xf86loaderstrdup(ElfGetString
- (elffile, syms[i].st_name));
- lookup[l].offset = (funcptr) syms[i].st_value;
- secttable[l] = syms[i].st_shndx;
-#ifdef ELFDEBUG
- ELFDEBUG("Adding symbol %lx(%d) %s\n",
- (unsigned long)lookup[l].offset, secttable[l],
- lookup[l].symName);
-#endif
-#ifdef __ia64__
- if (ELF_ST_TYPE(syms[i].st_info) == STT_FUNC) {
- ElfAddOPD(elffile, -1, &lookup[l]);
- }
-#endif
- l++;
- break;
- }
- break;
- case STT_FILE:
- case STT_LOPROC:
- case STT_HIPROC:
- /* Skip this type */
-#ifdef ELFDEBUG
- ELFDEBUG("Skipping TYPE %d %s\n",
- ELF_ST_TYPE(syms[i].st_info),
- ElfGetString(elffile, syms[i].st_name));
-#endif
- break;
- default:
- ErrorF("ELF_GetSymbols(): Unepected symbol type %d\n",
- ELF_ST_TYPE(syms[i].st_info));
- break;
- }
- }
-
- lookup[l].symName = NULL; /* Terminate the list */
-
-/*
- * Remove the ELF symbols that will show up in every object module.
- */
- for (i = 0, p = lookup; p->symName; i++, p++) {
- while (!strcmp(lookup[i].symName, ".text")
- || !strcmp(lookup[i].symName, ".data")
- || !strcmp(lookup[i].symName, ".bss")
- || !strcmp(lookup[i].symName, ".comment")
- || !strcmp(lookup[i].symName, ".note")
- ) {
- memmove(&(lookup[i]), &(lookup[i + 1]), (l - i) * sizeof(LOOKUP));
- memmove(&(secttable[i]), &(secttable[i + 1]),
- (l-- - i) * sizeof(unsigned short));
- }
- }
- return lookup;
-}
-
-#define SecOffset(index) elffile->sections[index].sh_offset
-#define SecSize(index) elffile->sections[index].sh_size
-#define SecAlign(index) elffile->sections[index].sh_addralign
-#define SecType(index) elffile->sections[index].sh_type
-#define SecFlags(index) elffile->sections[index].sh_flags
-#define SecInfo(index) elffile->sections[index].sh_info
-
-#define AdjustSize(i) \
- if (!pass) { \
- if (SecAlign(i) > *maxalign) \
- *maxalign = SecAlign(i); \
- *totalsize += (SecAlign(i) - 1); \
- *totalsize &= ~(SecAlign(i) - 1); \
- *totalsize += SecSize(i); \
- continue; \
- } do { } while (0)
-
-/*
- * ELFCollectSections
- *
- * Do the work required to load each section into memory.
- */
-static void
-ELFCollectSections(ELFModulePtr elffile, int pass, int *totalsize,
- int *maxalign)
-{
- int i;
- int j;
-
-/*
- * Find and identify all of the Sections
- */
- j = elffile->lsectidx;
- for (i = 1; i < elffile->numsh; i++) {
- int flags = 0;
- char *name = ElfGetSectionName(elffile, elffile->sections[i].sh_name);
-
-#if defined(__alpha__) || defined(__ia64__)
- if (!strcmp(name, ".got") /*Isn't there a more generic way to do this? */
-# if defined(__ia64__)
- || !strcmp(name, ".plt") || !strcmp(name, ".IA_64.unwind_info")
-# endif
- )
- continue;
-#endif
- switch (SecType(i)) {
- case SHT_STRTAB:
- if (!strcmp(name, ".shstrtab")) /* already loaded */
- continue;
- if (!strcmp(name, ".stabstr")) /* ignore debug info */
- continue;
- if (!strcmp(name, ".stab.indexstr")) /* ignore more debug info */
- continue;
- case SHT_SYMTAB:
- if (pass)
- continue;
- flags = LOADED_SECTION;
- flags |= RELOC_SECTION;
- break;
- case SHT_REL:
- case SHT_RELA:
- if (pass)
- continue;
- if (!(SecFlags(SecInfo(i)) & SHF_ALLOC))
- continue;
-#ifdef __ia64__
- if (SecType(SecInfo(i)) == SHT_IA_64_UNWIND)
- continue;
-#endif
- flags = LOADED_SECTION;
- flags |= RELOC_SECTION;
- break;
- case SHT_PROGBITS:
- flags |= LOADED_SECTION;
- case SHT_NOBITS:
- if (!(elffile->sections[i].sh_flags & SHF_ALLOC))
- continue;
- AdjustSize(i);
- break;
- default:
-#ifdef ELFDEBUG
- if (pass)
- ELFDEBUG("ELF: Not loading %s\n", name);
-#endif
- continue;
- }
-
- elffile->lsection = xf86loaderrealloc(elffile->lsection,
- (j + 1) * sizeof(LoadSection));
- if (!(flags & RELOC_SECTION)) {
- if (flags & LOADED_SECTION) {
- elffile->lsection[j].saddr /* sect. contains data */
- = ELFLoaderSectToMem(elffile, SecAlign(i),
- SecOffset(i), SecSize(i), name);
- } else {
- if (SecSize(i))
- elffile->lsection[j].saddr
- = ELFLoaderSectCalloc(elffile, SecAlign(i),
- SecSize(i));
- else
- elffile->lsection[j].saddr = NULL;
- }
- } else {
- elffile->lsection[j].saddr =
- (Elf_Sym *) _LoaderFileToMem(elffile->fd, SecOffset(i),
- SecSize(i), name);
- }
- elffile->saddr[i] = elffile->lsection[j].saddr;
-#ifdef ELFDEBUG
- ELFDEBUG("%s starts at %p size: %lx\n",
- name, elffile->saddr[i], (unsigned long)SecSize(i));
-#endif
- elffile->lsection[j].name = name;
- elffile->lsection[j].ndx = i;
- elffile->lsection[j].size = SecSize(i);
- elffile->lsection[j].flags = flags;
- switch (SecType(i)) {
-#if defined(linux) || defined(__OpenBSD__) || defined(sun)
- case SHT_PROGBITS:
- {
- unsigned long page_size = getpagesize();
- unsigned long round;
-
- round = (unsigned long)elffile->lsection[j].saddr & (page_size -1);
- mprotect( (char *)elffile->lsection[j].saddr - round,
- SecSize(i) + round, PROT_READ | PROT_WRITE | PROT_EXEC);
- }
-#ifdef __ia64__
- {
- int k;
- for (k = 0; k < SecSize(i); k += 32)
- ia64_flush_cache(elffile->lsection[j].saddr+k);
- ia64_flush_cache(elffile->lsection[j].saddr+SecSize(i)-1);
- }
-#endif
- break;
-#endif
- case SHT_SYMTAB:
- elffile->symtab = (Elf_Sym *) elffile->saddr[i];
- elffile->symndx = i;
- break;
- case SHT_STRTAB:
- elffile->straddr = elffile->saddr[i];
- elffile->strsize = elffile->lsection[j].size;
- elffile->strndx = i;
- break;
- default:
- break;
- }
- elffile->lsectidx = ++j;
- }
-}
-
-/*
- * Public API for the ELF implementation of the loader.
- */
-void *
-ELFLoadModule(loaderPtr modrec, int elffd, LOOKUP **ppLookup, int flags)
-{
- ELFModulePtr elffile;
- Elf_Ehdr *header;
- ELFRelocPtr elf_reloc, tail;
- void *v;
- LDRModulePtr elfmod;
- int totalsize, maxalign, i;
- unsigned short *secttable;
- LOOKUP *pLookup;
-
- ldrCommons = 0;
- nCommons = 0;
-
-#ifdef ELFDEBUG
- ELFDEBUG("Loading %s %s\n", modrec->name, modrec->cname);
-#endif
- if ((elffile = xf86loadercalloc(1, sizeof(ELFModuleRec))) == NULL) {
- ErrorF("Unable to allocate ELFModuleRec\n");
- return NULL;
- }
-
- elffile->handle = modrec->handle;
- elffile->module = modrec->module;
- elffile->fd = elffd;
- v = elffile->funcs = modrec->funcs;
-
-/*
- * Get the ELF header
- */
- elffile->header =
- (Elf_Ehdr *) _LoaderFileToMem(elffd, 0, sizeof(Elf_Ehdr),
- "header");
- header = (Elf_Ehdr *) elffile->header;
-
-/*
- * Get the section table
- */
- elffile->numsh = header->e_shnum;
- elffile->secsize = (header->e_shentsize * header->e_shnum);
- elffile->sections =
- (Elf_Shdr *) _LoaderFileToMem(elffd, header->e_shoff,
- elffile->secsize, "sections");
-#if defined(__alpha__) || defined(__ia64__)
- /*
- * Need to allocate space for the .got section which will be
- * fabricated later
- */
- elffile->gotndx = header->e_shnum;
- header->e_shnum++;
-# if defined(__ia64__)
- elffile->pltndx = header->e_shnum;
- header->e_shnum++;
-# endif
- elffile->numsh = header->e_shnum;
- elffile->secsize = (header->e_shentsize * header->e_shnum);
- elffile->sections =
- xf86loaderrealloc(elffile->sections, elffile->secsize);
-#endif /*defined(__alpha__) || defined(__ia64__) */
- elffile->saddr =
- xf86loadercalloc(elffile->numsh, sizeof(unsigned char *));
-
-#if defined(__alpha__) || defined(__ia64__)
- /*
- * Manually fill in the entry for the .got section so ELFCollectSections()
- * will be able to find it.
- */
- elffile->sections[elffile->gotndx].sh_name =
- SecSize(header->e_shstrndx) + 1;
- elffile->sections[elffile->gotndx].sh_type = SHT_PROGBITS;
- elffile->sections[elffile->gotndx].sh_flags = SHF_WRITE | SHF_ALLOC;
- elffile->sections[elffile->gotndx].sh_size = 0;
- elffile->sections[elffile->gotndx].sh_addralign = 8;
- /* Add room to copy ".got", and maintain alignment */
- SecSize(header->e_shstrndx) += 8;
-#endif
-#if defined(__ia64__)
- /*
- * Manually fill in the entry for the .plt section so ELFCollectSections()
- * will be able to find it.
- */
- elffile->sections[elffile->pltndx].sh_name =
- SecSize(header->e_shstrndx) + 1;
- elffile->sections[elffile->pltndx].sh_type = SHT_PROGBITS;
- elffile->sections[elffile->pltndx].sh_flags = SHF_EXECINSTR | SHF_ALLOC;
- elffile->sections[elffile->pltndx].sh_size = 0;
- elffile->sections[elffile->pltndx].sh_addralign = 32;
- /* Add room to copy ".plt", and maintain alignment */
- SecSize(header->e_shstrndx) += 32;
-#endif
-
-/*
- * Get the section header string table
- */
- elffile->shstrsize = SecSize(header->e_shstrndx);
- elffile->shstraddr =
- _LoaderFileToMem(elffd, SecOffset(header->e_shstrndx),
- SecSize(header->e_shstrndx), ".shstrtab");
- elffile->shstrndx = header->e_shstrndx;
-#if defined(__alpha__) || defined(__ia64__)
- /*
- * Add the string for the .got section
- */
- strcpy((char *)(elffile->shstraddr +
- elffile->sections[elffile->gotndx].sh_name), ".got");
-#endif
-#if defined(__ia64__)
- /*
- * Add the string for the .plt section
- */
- strcpy((char *)(elffile->shstraddr +
- elffile->sections[elffile->pltndx].sh_name), ".plt");
-#endif
-
-/*
- * Load some desired sections, compute size of the remaining ones
- */
- totalsize = 0;
- maxalign = 0;
- ELFCollectSections(elffile, 0, &totalsize, &maxalign);
- if (elffile->straddr == NULL || elffile->strsize == 0) {
-#if 0
- ErrorF("No symbols found in this module\n");
-#endif
- ELFUnloadModule(elffile);
- return (void *)-1L;
- }
-/*
- * add symbols
- */
- *ppLookup = pLookup = ELF_GetSymbols(elffile, &secttable);
-
-/*
- * Do relocations
- */
- for (i = 0; i < elffile->lsectidx; i++) {
- switch (SecType(elffile->lsection[i].ndx)) {
- case SHT_REL:
- case SHT_RELA:
- break;
- default:
- continue;
- }
- elf_reloc = ELFCollectRelocations(elffile, elffile->lsection[i].ndx);
- if (elf_reloc) {
- for (tail = elf_reloc; tail->next; tail = tail->next) ;
- tail->next = _LoaderGetRelocations(v)->elf_reloc;
- _LoaderGetRelocations(v)->elf_reloc = elf_reloc;
- }
- }
-
-#if defined(__ia64__)
- totalsize += (elffile->sections[elffile->pltndx].sh_addralign - 1);
- totalsize &= ~(elffile->sections[elffile->pltndx].sh_addralign - 1);
- totalsize += elffile->pltsize;
- if (maxalign < elffile->sections[elffile->pltndx].sh_addralign)
- maxalign = elffile->sections[elffile->pltndx].sh_addralign;
-#endif
-
- /* Space for COMMON */
- totalsize = (totalsize + 7) & ~7;
- totalsize += ElfCOMMONSize();
-
-#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(__OpenBSD__) || defined(sun)
- {
- unsigned long page_size = getpagesize();
- unsigned long round;
-
- round = (unsigned long)elffile->base & (page_size - 1);
- mprotect(elffile->base - round,
- (elffile->basesize + round + page_size - 1) & ~(page_size -
- 1),
- PROT_READ | PROT_WRITE | PROT_EXEC);
- }
-# 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
-
-#if defined(__alpha__) || defined(__ia64__)
- if (!ELFCreateGOT(elffile, maxalign))
- return NULL;
-#endif
-#if defined(__ia64__)
- ELFCreatePLT(elffile);
-#endif
-
- ELFCollectSections(elffile, 1, NULL, NULL);
-
- for (i = 0; pLookup[i].symName; i++)
- if (secttable[i]) {
- pLookup[i].offset =
- (funcptr) ((long)pLookup[i].offset +
- (long)elffile->saddr[secttable[i]]);
-#ifdef ELFDEBUG
- ELFDEBUG("Finalizing symbol %p %s\n",
- (void *)pLookup[i].offset, pLookup[i].symName);
-#endif
- }
- xf86loaderfree(secttable);
-
-#if defined(__ia64__)
- ELFCreateOPD(elffile);
-#endif
-
- if (!ElfCreateCOMMON(elffile, *ppLookup))
- return NULL;
-
- /* Record info for gdb - if we can't allocate the loader record fail
- * silently (the user will find out soon enough that there's no VM left */
- if ((elfmod = xf86loadercalloc(1, sizeof(LDRModuleRec))) != NULL) {
- elfmod->name = strdup(modrec->name);
- elfmod->namelen = strlen(modrec->name);
- elfmod->version = 1;
- for (i = 0; i < elffile->lsectidx; i++) {
- char *name = elffile->lsection[i].name;
-
- if (!strcmp(name, ".text"))
- elfmod->text = elffile->lsection[i].saddr;
- else if (!strcmp(name, ".data"))
- elfmod->data = elffile->lsection[i].saddr;
- else if (!strcmp(name, ".rodata"))
- elfmod->rodata = elffile->lsection[i].saddr;
- else if (!strcmp(name, ".bss"))
- elfmod->bss = elffile->lsection[i].saddr;
- }
- elfmod->next = ModList;
- elfmod->commons = ldrCommons;
- elfmod->commonslen = nCommons;
-
- ModList = elfmod;
-
- /* Tell GDB something interesting happened */
- _loader_debug_state();
- }
- return (void *)elffile;
-}
-
-void
-ELFResolveSymbols(void *mod)
-{
- ELFRelocPtr newlist, p, tmp;
-
- /* Try to relocate everything. Build a new list containing entries
- * which we failed to relocate. Destroy the old list in the process.
- */
- newlist = 0;
- for (p = _LoaderGetRelocations(mod)->elf_reloc; p;) {
-#ifdef ELFDEBUG
- ELFDEBUG("ResolveSymbols: "
- "file %p, sec %d, r_offset 0x%x, r_info 0x%p\n",
- (void *)p->file, p->secn, p->rel->r_offset,
- (void *)p->rel->r_info);
-#endif
- tmp = Elf_RelocateEntry(p->file, p->secn, p->rel, FALSE);
- if (tmp) {
- /* Failed to relocate. Keep it in the list. */
- tmp->next = newlist;
- newlist = tmp;
- }
- tmp = p;
- p = p->next;
- xf86loaderfree(tmp);
- }
- _LoaderGetRelocations(mod)->elf_reloc = newlist;
-}
-
-int
-ELFCheckForUnresolved(void *mod)
-{
- ELFRelocPtr erel;
- char *name;
- int flag, fatalsym = 0;
-
- if ((erel = _LoaderGetRelocations(mod)->elf_reloc) == NULL)
- return 0;
-
- while (erel) {
- Elf_RelocateEntry(erel->file, erel->secn, erel->rel, TRUE);
- name = ElfGetSymbolName(erel->file, ELF_R_SYM(erel->rel->r_info));
- flag = _LoaderHandleUnresolved(name,
- _LoaderHandleToName(erel->file->
- handle));
- if (flag)
- fatalsym = 1;
- erel = erel->next;
- }
- return fatalsym;
-}
-
-void
-ELFUnloadModule(void *modptr)
-{
- ELFModulePtr elffile = (ELFModulePtr) modptr;
- ELFRelocPtr relptr, reltptr, *brelptr;
- int i;
-
-/*
- * Delete any unresolved relocations
- */
-
- relptr = _LoaderGetRelocations(elffile->funcs)->elf_reloc;
- brelptr = &(_LoaderGetRelocations(elffile->funcs)->elf_reloc);
-
- while (relptr) {
- if (relptr->file == elffile) {
- *brelptr = relptr->next; /* take it out of the list */
- reltptr = relptr; /* save pointer to this node */
- relptr = relptr->next; /* advance the pointer */
- xf86loaderfree(reltptr); /* free the node */
- } else {
- brelptr = &(relptr->next);
- relptr = relptr->next; /* advance the pointer */
- }
- }
-
-/*
- * Delete any symbols in the symbols table.
- */
-
- LoaderHashTraverse((void *)elffile, ELFhashCleanOut);
-
-/*
- * Free the sections that were allocated.
- */
-#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
- CheckandFree(elffile->base, elffile->basesize);
-# if defined(__alpha__) || defined(__ia64__)
- if (elffile->shared_got) {
- elffile->shared_got->nuses--;
- if (!elffile->shared_got->nuses) {
- ELFGotPtr *pgot = &ELFSharedGOTs;
-
- while (*pgot && *pgot != elffile->shared_got)
- pgot = &(*pgot)->next;
- if (*pgot)
- *pgot = elffile->shared_got->next;
- xf86loaderfree(elffile->shared_got);
- }
- }
-# endif
-#else /*MergeSectionAlloc */
- CheckandFree(elffile->common, elffile->comsize);
-# if defined(__alpha__) || defined(__ia64__)
- CheckandFree(elffile->got, elffile->gotsize);
-# endif
-# if defined(__ia64__)
- CheckandFree(elffile->plt, elffile->pltsize);
-# endif
-#endif
-#if defined(__alpha__) || defined(__ia64__)
- {
- ELFGotEntryPtr gotent;
-
- while ((gotent = elffile->got_entries)) {
- elffile->got_entries = gotent->next;
- xf86loaderfree(gotent);
- }
- }
-#endif
-#if defined(__ia64__)
- {
- ELFPltEntryPtr pltent;
-
- while ((pltent = elffile->plt_entries)) {
- elffile->plt_entries = pltent->next;
- xf86loaderfree(pltent);
- }
- }
- {
- ELFOpdPtr opdent;
-
- while ((opdent = elffile->opd_entries)) {
- elffile->opd_entries = opdent->next;
- xf86loaderfree(opdent);
- }
- }
-#endif
-
- for (i = 0; i < elffile->lsectidx; i++) {
-#ifdef MergeSectionAlloc
- if (!(elffile->lsection[i].flags & RELOC_SECTION))
- continue;
-#endif
- if (elffile->lsection[i].flags & LOADED_SECTION) {
- CheckandFreeFile(elffile->lsection[i].saddr,
- elffile->lsection[i].size);
- } else {
- CheckandFree(elffile->lsection[i].saddr,
- elffile->lsection[i].size);
- }
- }
- xf86loaderfree(elffile->lsection);
-
-/*
- * Free the section table, section pointer array, and section names
- */
- _LoaderFreeFileMem(elffile->sections, elffile->secsize);
- xf86loaderfree(elffile->saddr);
- _LoaderFreeFileMem(elffile->header, sizeof(Elf_Ehdr));
- _LoaderFreeFileMem(elffile->shstraddr, elffile->shstrsize);
-
-/*
- * Free the ELFModuleRec
- */
- xf86loaderfree(elffile);
-
- return;
-}
-
-char *
-ELFAddressToSection(void *modptr, unsigned long address)
-{
- ELFModulePtr elffile = (ELFModulePtr) modptr;
- int i;
-
- for (i = 1; i < elffile->numsh; i++) {
- if (address >= (unsigned long)elffile->saddr[i] &&
- address <= (unsigned long)elffile->saddr[i] + SecSize(i)) {
- return ElfGetSectionName(elffile, elffile->sections[i].sh_name);
- }
- }
- return NULL;
-}