diff options
author | Daniel Stone <daniel@fooishbar.org> | 2006-06-01 20:18:30 +0000 |
---|---|---|
committer | Daniel Stone <daniel@fooishbar.org> | 2006-06-01 20:18:30 +0000 |
commit | c9468177486833d521ec62c7b0266b4be8200de7 (patch) | |
tree | 5d6976c35147d5d16c22350032661a37f53d8f5f | |
parent | a3a4221495dfe4cc0a3874a08dd5364ef45a7f2e (diff) |
Kill a.out, COFF and ELF loaders with FIRE.
-rw-r--r-- | ChangeLog | 16 | ||||
-rw-r--r-- | hw/xfree86/loader/Makefile.am | 13 | ||||
-rw-r--r-- | hw/xfree86/loader/aout.h | 235 | ||||
-rw-r--r-- | hw/xfree86/loader/aoutloader.c | 866 | ||||
-rw-r--r-- | hw/xfree86/loader/aoutloader.h | 35 | ||||
-rw-r--r-- | hw/xfree86/loader/ar.h | 75 | ||||
-rw-r--r-- | hw/xfree86/loader/coff.h | 237 | ||||
-rw-r--r-- | hw/xfree86/loader/coffloader.c | 1359 | ||||
-rw-r--r-- | hw/xfree86/loader/coffloader.h | 38 | ||||
-rw-r--r-- | hw/xfree86/loader/elf.h | 712 | ||||
-rw-r--r-- | hw/xfree86/loader/elfloader.c | 3335 | ||||
-rw-r--r-- | hw/xfree86/loader/elfloader.h | 38 | ||||
-rw-r--r-- | hw/xfree86/loader/loader.c | 381 | ||||
-rw-r--r-- | hw/xfree86/loader/loader.h | 30 |
14 files changed, 18 insertions, 7352 deletions
@@ -41,6 +41,22 @@ Ignore requests to load deprecated GLcore and speedo modules (properly, this time). + * hw/xfree86/loader/Makefile.am: + * hw/xfree86/loader/loader.c: + * hw/xfree86/loader/loader.h: + * hw/xfree86/loader/ar.h: + * hw/xfree86/loader/aout.h: + * hw/xfree86/loader/aoutloader.h: + * hw/xfree86/loader/aoutloader.c: + * hw/xfree86/loader/coff.h: + * hw/xfree86/loader/coffloader.h: + * hw/xfree86/loader/coffloader.c: + * hw/xfree86/loader/elf.h: + * hw/xfree86/loader/elfloader.h: + * hw/xfree86/loader/elfloader.c: + Kill the a.out, ELF and COFF loaders with extreme prejudice. Good + riddance. There's more where this came from, too. + 2006-05-30 Matthieu Herrb <matthieu.herrb@laas.fr> * hw/xfree86/os-support/bsd/Makefile.am: diff --git a/hw/xfree86/loader/Makefile.am b/hw/xfree86/loader/Makefile.am index ad5d23c6f..684087eae 100644 --- a/hw/xfree86/loader/Makefile.am +++ b/hw/xfree86/loader/Makefile.am @@ -13,18 +13,8 @@ if XORG_LOADER_SPARC SPARC_SOURCES = SparcMulDiv.S endif -sdk_HEADERS = \ - elf.h - EXTRA_DIST = \ - aout.h \ - aoutloader.h \ - ar.h \ - coff.h \ - coffloader.h \ dlloader.h \ - elf.h \ - elfloader.h \ hash.h \ loader.h \ loaderProcs.h \ @@ -37,10 +27,7 @@ libloader_a_SOURCES = \ loadext.c \ loadmod.c \ loadfont.c \ - aoutloader.c \ dlloader.c \ - elfloader.c \ - coffloader.c \ os.c \ dixsym.c \ extsym.c \ diff --git a/hw/xfree86/loader/aout.h b/hw/xfree86/loader/aout.h deleted file mode 100644 index d092dcbda..000000000 --- a/hw/xfree86/loader/aout.h +++ /dev/null @@ -1,235 +0,0 @@ -/* $XFree86: xc/programs/Xserver/hw/xfree86/loader/aout.h,v 1.7 2002/05/31 18:46:00 dawes Exp $ */ - -/* - * Borrowed from NetBSD's exec_aout.h - * - * Copyright (c) 1993, 1994 Christopher G. Demetriou - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Christopher G. Demetriou. - * 4. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifdef HAVE_XORG_CONFIG_H -#include <xorg-config.h> -#endif - -#ifndef _AOUT_H -#define _AOUT_H - -#include <X11/Xos.h> - -/* Get prototype for ntohl, per SuSv3. */ -#include <arpa/inet.h> - -/* OS/2 EMX has ntohl in this file */ -#ifdef __UNIXOS2__ -#include <sys/param.h> -#endif - -#define __LDPGSZ 4096U -#ifndef AOUT_PAGSIZ -#define AOUT_PAGSIZ(ex) (__LDPGSZ) -#endif - -/* - * a.out header - */ -typedef struct AOUT_exec { - unsigned long a_midmag; /* htonl(flags<<26 | mid<<16 | magic) */ - unsigned long a_text; /* text segment size */ - unsigned long a_data; /* initialized data size */ - unsigned long a_bss; /* uninitialized data size */ - unsigned long a_syms; /* symbol table size */ - unsigned long a_entry; /* entry point */ - unsigned long a_trsize; /* text relocation size */ - unsigned long a_drsize; /* data relocation size */ -} AOUTHDR; - -/* a_magic */ -#define OMAGIC 0407 /* old impure format */ -#define NMAGIC 0410 /* read-only text */ -#define ZMAGIC 0413 /* demand load format */ -#define QMAGIC 0314 /* "compact" demand load format; deprecated */ - -/* - * a_mid - keep sorted in numerical order for sanity's sake - * ensure that: 0 < mid < 0x3ff - */ -#define MID_ZERO 0 /* unknown - implementation dependent */ -#define MID_SUN010 1 /* sun 68010/68020 binary */ -#define MID_SUN020 2 /* sun 68020-only binary */ -#define MID_PC386 100 /* 386 PC binary. (so quoth BFD) */ -#define MID_HP200 200 /* hp200 (68010) BSD binary */ -#define MID_I386 134 /* i386 BSD binary */ -#define MID_M68K 135 /* m68k BSD binary with 8K page sizes */ -#define MID_M68K4K 136 /* m68k BSD binary with 4K page sizes */ -#define MID_NS32532 137 /* ns32532 */ -#define MID_SPARC 138 /* sparc */ -#define MID_PMAX 139 /* pmax */ -#define MID_VAX 140 /* vax */ -#define MID_ALPHA 141 /* Alpha BSD binary */ -#define MID_MIPS 142 /* big-endian MIPS */ -#define MID_ARM6 143 /* ARM6 */ -#define MID_HP300 300 /* hp300 (68020+68881) BSD binary */ -#define MID_HPUX 0x20C /* hp200/300 HP-UX binary */ -#define MID_HPUX800 0x20B /* hp800 HP-UX binary */ - -/* - * a_flags - */ -#define EX_DYNAMIC 0x20 -#define EX_PIC 0x10 -#define EX_DPMASK 0x30 -/* - * Interpretation of the (a_flags & EX_DPMASK) bits: - * - * 00 traditional executable or object file - * 01 object file contains PIC code (set by `as -k') - * 10 dynamic executable - * 11 position independent executable image - * (eg. a shared library) - * - */ - -/* - * The a.out structure's a_midmag field is a network-byteorder encoding - * of this int - * FFFFFFmmmmmmmmmmMMMMMMMMMMMMMMMM - * Where `F' is 6 bits of flag like EX_DYNAMIC, - * `m' is 10 bits of machine-id like MID_I386, and - * `M' is 16 bits worth of magic number, ie. ZMAGIC. - * The macros below will set/get the needed fields. - */ -#define AOUT_GETMAGIC(ex) \ - ( (((ex)->a_midmag)&0xffff0000U) ? (ntohl(((ex)->a_midmag))&0xffffU) : ((ex)->a_midmag)) -#define AOUT_GETMAGIC2(ex) \ - ( (((ex)->a_midmag)&0xffff0000U) ? (ntohl(((ex)->a_midmag))&0xffffU) : \ - (((ex)->a_midmag) | 0x10000) ) -#define AOUT_GETMID(ex) \ - ( (((ex)->a_midmag)&0xffff0000U) ? ((ntohl(((ex)->a_midmag))>>16)&0x03ffU) : MID_ZERO ) -#define AOUT_GETFLAG(ex) \ - ( (((ex)->a_midmag)&0xffff0000U) ? ((ntohl(((ex)->a_midmag))>>26)&0x3fU) : 0 ) -#define AOUT_SETMAGIC(ex,mag,mid,flag) \ - ( (ex)->a_midmag = htonl( (((flag)&0x3fU)<<26) | (((mid)&0x03ffU)<<16) | \ - (((mag)&0xffffU)) ) ) - -#define AOUT_ALIGN(ex,x) \ - (AOUT_GETMAGIC(ex) == ZMAGIC || AOUT_GETMAGIC(ex) == QMAGIC ? \ - ((x) + __LDPGSZ - 1) & ~(__LDPGSZ - 1) : (x)) - -/* Valid magic number check. */ -#define AOUT_BADMAG(ex) \ - (AOUT_GETMAGIC(ex) != NMAGIC && AOUT_GETMAGIC(ex) != OMAGIC && \ - AOUT_GETMAGIC(ex) != ZMAGIC && AOUT_GETMAGIC(ex) != QMAGIC) - -/* Address of the bottom of the text segment. */ -#define AOUT_TXTADDR(ex) (AOUT_GETMAGIC2(ex) == (ZMAGIC|0x10000) ? 0 : __LDPGSZ) - -/* Address of the bottom of the data segment. */ -#define AOUT_DATADDR(ex) \ - (AOUT_GETMAGIC(ex) == OMAGIC ? AOUT_TXTADDR(ex) + (ex)->a_text : \ - (AOUT_TXTADDR(ex) + (ex)->a_text + __LDPGSZ - 1) & ~(__LDPGSZ - 1)) - -/* Address of the bottom of the bss segment. */ -#define AOUT_BSSADDR(ex) \ - (AOUT_DATADDR(ex) + (ex)->a_data) - -/* Text segment offset. */ -#define AOUT_TXTOFF(ex) \ - ( AOUT_GETMAGIC2(ex)==ZMAGIC || AOUT_GETMAGIC2(ex)==(QMAGIC|0x10000) ? \ - 0 : (AOUT_GETMAGIC2(ex)==(ZMAGIC|0x10000) ? __LDPGSZ : \ - sizeof(struct AOUT_exec)) ) - -/* Data segment offset. */ -#define AOUT_DATOFF(ex) \ - AOUT_ALIGN(ex, AOUT_TXTOFF(ex) + (ex)->a_text) - -/* Text relocation table offset. */ -#define AOUT_TRELOFF(ex) \ - (AOUT_DATOFF(ex) + (ex)->a_data) - -/* Data relocation table offset. */ -#define AOUT_DRELOFF(ex) \ - (AOUT_TRELOFF(ex) + (ex)->a_trsize) - -/* Symbol table offset. */ -#define AOUT_SYMOFF(ex) \ - (AOUT_DRELOFF(ex) + (ex)->a_drsize) - -/* String table offset. */ -#define AOUT_STROFF(ex) \ - (AOUT_SYMOFF(ex) + (ex)->a_syms) - -/* Relocation format. */ -struct relocation_info_i386 { - int r_address; /* offset in text or data segment */ - unsigned int r_symbolnum:24, /* ordinal number of add symbol */ - r_pcrel:1, /* 1 if value should be pc-relative */ - r_length:2, /* log base 2 of value's width */ - r_extern:1, /* 1 if need to add symbol to value */ - r_baserel:1, /* linkage table relative */ - r_jmptable:1, /* relocate to jump table */ - r_relative:1, /* load address relative */ - r_copy:1; /* run time copy */ -}; - -#define relocation_info relocation_info_i386 - -/* - * Symbol table entry format. The #ifdef's are so that programs including - * nlist.h can initialize nlist structures statically. - */ -typedef struct AOUT_nlist { - union { - char *n_name; /* symbol name (in memory) */ - long n_strx; /* file string table offset (on disk) */ - } n_un; - -#define AOUT_UNDF 0x00 /* undefined */ -#define AOUT_ABS 0x02 /* absolute address */ -#define AOUT_TEXT 0x04 /* text segment */ -#define AOUT_DATA 0x06 /* data segment */ -#define AOUT_BSS 0x08 /* bss segment */ -#define AOUT_INDR 0x0a /* alias definition */ -#define AOUT_SIZE 0x0c /* pseudo type, defines a symbol's size */ -#define AOUT_COMM 0x12 /* common reference */ -#define AOUT_FN 0x1e /* file name (AOUT_EXT on) */ -#define AOUT_WARN 0x1e /* warning message (AOUT_EXT off) */ - -#define AOUT_EXT 0x01 /* external (global) bit, OR'ed in */ -#define AOUT_TYPE 0x1e /* mask for all the type bits */ - unsigned char n_type; /* type defines */ - - char n_other; /* spare */ -#define n_hash n_desc /* used internally by ld(1); XXX */ - short n_desc; /* used by stab entries */ - unsigned long n_value; /* address/value of the symbol */ -} AOUT_nlist; - -#define AOUT_FORMAT "%08x" /* namelist value format; XXX */ -#define AOUT_STAB 0x0e0 /* mask for debugger symbols -- stab(5) */ - -#endif diff --git a/hw/xfree86/loader/aoutloader.c b/hw/xfree86/loader/aoutloader.c deleted file mode 100644 index 13500b93b..000000000 --- a/hw/xfree86/loader/aoutloader.c +++ /dev/null @@ -1,866 +0,0 @@ -/* $XFree86: xc/programs/Xserver/hw/xfree86/loader/aoutloader.c,v 1.19 2003/10/15 16:58:34 dawes Exp $ */ - -/* - * - * Copyright (c) 1997 Matthieu Herrb - * Copyright 1995-1998 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. - * - * Modified 21/02/97 by Sebastien Marineau to support OS/2 a.out objects - */ -#ifdef HAVE_XORG_CONFIG_H -#include <xorg-config.h> -#endif - -#include <sys/types.h> -#include <sys/stat.h> -#include <stdio.h> -#include <stdlib.h> -#ifdef __QNX__ -#include <fcntl.h> -#else -#include <sys/fcntl.h> -#endif -#include <sys/stat.h> -#include <netinet/in.h> - -#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 "aout.h" - -#include "sym.h" -#include "loader.h" -#include "aoutloader.h" - -#ifndef LOADERDEBUG -#define LOADERDEBUG 0 -#endif - -#if LOADERDEBUG -#define AOUTDEBUG ErrorF -#endif - -#ifndef MIN -#define MIN(a,b) ((a)<(b)?(a):(b)) -#endif - -/* - * 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; - AOUTHDR *header; /* file header */ - unsigned char *text; /* Start address of the text section */ - unsigned int textsize; /* Size of the text section */ - unsigned char *data; /* Start address of the data section */ - unsigned int datasize; /* Size of the data section */ - unsigned char *bss; /* Start address of the bss data */ - unsigned int bsssize; /* Size of the bss section */ - struct relocation_info *txtrel; /* Start address of the text relocation table */ - struct relocation_info *datarel; /* Start address of the data relocation table */ - AOUT_nlist *symtab; /* Start address of the symbol table */ - unsigned char *strings; /* Start address of the string table */ - unsigned long strsize; /* size of string table */ - unsigned char *common; /* Start address of the common data */ - unsigned long comsize; /* size of common data */ -} AOUTModuleRec, *AOUTModulePtr; - -/* - * If an relocation is unable to be satisfied, then put it on a list - * to try later after more modules have been loaded. - */ -typedef struct AOUT_RELOC { - AOUTModulePtr file; - struct relocation_info *rel; - int type; /* AOUT_TEXT or AOUT_DATA */ - struct AOUT_RELOC *next; -} AOUTRelocRec; - -/* - * Symbols with a section number of 0 (N_UNDF) but a value of non-zero - * need to have space allocated for them. - * - * Gather all of these symbols together, and allocate one chunk when we - * are done. - */ - -typedef struct AOUT_COMMON { - struct AOUT_nlist *sym; - int index; - struct AOUT_COMMON *next; -} AOUTCommonRec; - -static AOUTCommonPtr listCOMMON = NULL; - -/* prototypes for static functions */ -static int AOUTHashCleanOut(void *, itemPtr); -static char *AOUTGetSymbolName(AOUTModulePtr, struct AOUT_nlist *); -static void *AOUTGetSymbolValue(AOUTModulePtr, int); -static AOUTCommonPtr AOUTAddCommon(struct AOUT_nlist *, int); -static LOOKUP *AOUTCreateCommon(AOUTModulePtr); -static LOOKUP *AOUT_GetSymbols(AOUTModulePtr); -static AOUTRelocPtr AOUTDelayRelocation(AOUTModulePtr, int, - struct relocation_info_i386 *); -static AOUTRelocPtr AOUTCollectRelocations(AOUTModulePtr); -static void AOUT_Relocate(unsigned long *, unsigned long, int); -static AOUTRelocPtr AOUT_RelocateEntry(AOUTModulePtr, int, - struct relocation_info_i386 *); - -/* - * Return 1 if the symbol in item belongs to aoutfile - */ -static int -AOUTHashCleanOut(void *voidptr, itemPtr item) -{ - AOUTModulePtr aoutfile = (AOUTModulePtr) voidptr; - - return (aoutfile->handle == item->handle); -} - -/* - * Manage listResolv - */ -static AOUTRelocPtr -AOUTDelayRelocation(AOUTModulePtr aoutfile, int type, - struct relocation_info *rel) -{ - AOUTRelocPtr reloc; - - if ((reloc = xf86loadermalloc(sizeof(AOUTRelocRec))) == NULL) { - ErrorF("AOUTDelayRelocation() Unable to allocate memory\n"); - return NULL; - } - if ((unsigned long)rel < 0x200) { - ErrorF("bug"); - } - reloc->file = aoutfile; - reloc->type = type; - reloc->rel = rel; - reloc->next = 0; - return reloc; -} - -/* - * Manage listCOMMON - */ - -static AOUTCommonPtr -AOUTAddCommon(struct AOUT_nlist *sym, int index) -{ - AOUTCommonPtr common; - - if ((common = xf86loadermalloc(sizeof(AOUTCommonRec))) == NULL) { - ErrorF("AOUTAddCommon() Unable to allocate memory\n"); - return 0; - } - common->sym = sym; - common->index = index; - common->next = 0; - return common; -} - -static LOOKUP * -AOUTCreateCommon(AOUTModulePtr aoutfile) -{ - int numsyms = 0, size = 0, l = 0; - int offset = 0; - AOUTCommonPtr common; - LOOKUP *lookup; - - if (listCOMMON == NULL) - return NULL; - - common = listCOMMON; - for (common = listCOMMON; common; common = common->next) { - /* Ensure long word alignment */ - if ((common->sym->n_value & (sizeof(long) - 1)) != 0) - common->sym->n_value = (common->sym->n_value + (sizeof(long) - 1)) - & ~(sizeof(long) - 1); - - /* accumulate the sizes */ - size += common->sym->n_value; - numsyms++; - } /* while */ - -#ifdef AOUTDEBUG - AOUTDEBUG("AOUTCreateCommon() %d entries (%d bytes) of COMMON data\n", - numsyms, size); -#endif - - if ((lookup = xf86loadermalloc((numsyms + 1) * sizeof(LOOKUP))) == NULL) { - ErrorF("AOUTCreateCommon() Unable to allocate memory\n"); - return NULL; - } - - aoutfile->comsize = size; - if ((aoutfile->common = xf86loadercalloc(1, size)) == NULL) { - ErrorF("AOUTCreateCommon() Unable to allocate memory\n"); - return NULL; - } - - while (listCOMMON) { - common = listCOMMON; - lookup[l].symName = AOUTGetSymbolName(aoutfile, common->sym); - lookup[l].offset = (funcptr) (aoutfile->common + offset); -#ifdef AOUTDEBUG - AOUTDEBUG("Adding %p %s\n", (void *)lookup[l].offset, - lookup[l].symName); -#endif - listCOMMON = common->next; - offset += common->sym->n_value; - xf86loaderfree(common); - l++; - } /* while */ - /* listCOMMON == NULL */ - - lookup[l].symName = NULL; /* Terminate the list */ - return lookup; -} - -/* - * Symbol Table - */ - -static char * -AOUTGetString(AOUTModulePtr aoutfile, int index) -{ - char *symname = (char *)&(aoutfile->strings[index]); - - if (symname[0] == '_') { - symname++; - } - - return symname; -} - -/* - * Return the name of a symbol - */ -static char * -AOUTGetSymbolName(AOUTModulePtr aoutfile, struct AOUT_nlist *sym) -{ - char *symname = AOUTGetString(aoutfile, sym->n_un.n_strx); - char *name; - - name = xf86loadermalloc(strlen(symname) + 1); - if (!name) - FatalError("AOUTGetSymbolName: Out of memory\n"); - - strcpy(name, symname); - - return name; -} - -/* - * Return the value of a symbol in the loader's symbol table - */ -static void * -AOUTGetSymbolValue(AOUTModulePtr aoutfile, int index) -{ - void *symval = NULL; /* value of the indicated symbol */ - itemPtr symbol = NULL; /* name/value of symbol */ - char *name = NULL; - - name = AOUTGetSymbolName(aoutfile, aoutfile->symtab + index); - - if (name) - symbol = LoaderHashFind(name); - - if (symbol) - symval = (unsigned char *)symbol->address; - - xf86loaderfree(name); - return symval; -} - -/* - * Perform the actual relocation - */ -static void -AOUT_Relocate(unsigned long *destl, unsigned long val, int pcrel) -{ -#ifdef AOUTDEBUG - AOUTDEBUG("AOUT_Relocate %p : %08lx %s", - (void *)destl, *destl, pcrel == 1 ? "rel" : "abs"); - -#endif - if (pcrel) { - /* relative to PC */ - *destl = val - ((unsigned long)destl + sizeof(long)); - } else { - *destl += val; - } -#ifdef AOUTDEBUG - AOUTDEBUG(" -> %08lx\n", *destl); -#endif -} - -/* - * Fix the relocation for text or data section - */ -static AOUTRelocPtr -AOUT_RelocateEntry(AOUTModulePtr aoutfile, int type, - struct relocation_info *rel) -{ - AOUTHDR *header = aoutfile->header; - AOUT_nlist *symtab = aoutfile->symtab; - int symnum; - void *symval; - unsigned long *destl; /* address of the location to be modified */ - - symnum = rel->r_symbolnum; -#ifdef AOUTDEBUG - { - char *name; - - if (rel->r_extern) { - AOUTDEBUG("AOUT_RelocateEntry: extern %s\n", - name = AOUTGetSymbolName(aoutfile, symtab + symnum)); - xf86loaderfree(name); - } else { - AOUTDEBUG("AOUT_RelocateEntry: intern\n"); - } - AOUTDEBUG(" pcrel: %d", rel->r_pcrel); - AOUTDEBUG(" length: %d", rel->r_length); - AOUTDEBUG(" baserel: %d", rel->r_baserel); - AOUTDEBUG(" jmptable: %d", rel->r_jmptable); - AOUTDEBUG(" relative: %d", rel->r_relative); - AOUTDEBUG(" copy: %d\n", rel->r_copy); - } -#endif /* AOUTDEBUG */ - - if (rel->r_length != 2) { - ErrorF("AOUT_ReloateEntry: length != 2\n"); - } - /* - * First find the address to modify - */ - switch (type) { - case AOUT_TEXT: - /* Check that the relocation offset is in the text segment */ - if (rel->r_address > header->a_text) { - ErrorF("AOUT_RelocateEntry(): " - "text relocation out of text section\n"); - } - destl = (unsigned long *)(aoutfile->text + rel->r_address); - break; - case AOUT_DATA: - /* Check that the relocation offset is in the data segment */ - if (rel->r_address > header->a_data) { - ErrorF("AOUT_RelocateEntry():" - "data relocation out of data section\n"); - } - destl = (unsigned long *)(aoutfile->data + rel->r_address); - break; - default: - ErrorF("AOUT_RelocateEntry(): unknown section type %d\n", type); - return 0; - } /* switch */ - - /* - * Now handle the relocation - */ - if (rel->r_extern) { - /* Lookup the symbol in the loader's symbol table */ - symval = AOUTGetSymbolValue(aoutfile, symnum); - if (symval != 0) { - /* we've got the value */ - AOUT_Relocate(destl, (unsigned long)symval, rel->r_pcrel); - return 0; - } else { - /* The symbol should be undefined */ - switch (symtab[symnum].n_type & AOUT_TYPE) { - case AOUT_UNDF: -#ifdef AOUTDEBUG - AOUTDEBUG(" extern AOUT_UNDEF\n"); -#endif - /* Add this relocation back to the global list */ - return AOUTDelayRelocation(aoutfile, type, rel); - - default: - ErrorF("AOUT_RelocateEntry():" - " impossible intern relocation type: %d\n", - symtab[symnum].n_type); - return 0; - } /* switch */ - } - } else { - /* intern */ - switch (rel->r_symbolnum) { - case AOUT_TEXT: -#ifdef AOUTDEBUG - AOUTDEBUG(" AOUT_TEXT\n"); -#endif - /* Only absolute intern text relocations need to be handled */ - if (rel->r_pcrel == 0) - AOUT_Relocate(destl, (unsigned long)aoutfile->text, - rel->r_pcrel); - return 0; - case AOUT_DATA: -#ifdef AOUTDEBUG - AOUTDEBUG(" AOUT_DATA\n"); -#endif - if (rel->r_pcrel == 0) - AOUT_Relocate(destl, (unsigned long)aoutfile->data - - header->a_text, rel->r_pcrel); - else - ErrorF("AOUT_RelocateEntry(): " - "don't know how to handle data pc-relative reloc\n"); - - return 0; - case AOUT_BSS: -#ifdef AOUTDEBUG - AOUTDEBUG(" AOUT_BSS\n"); -#endif - if (rel->r_pcrel == 0) - AOUT_Relocate(destl, (unsigned long)aoutfile->bss - - header->a_text - header->a_data, - rel->r_pcrel); - else - ErrorF("AOUT_RelocateEntry(): " - "don't know how to handle bss pc-relative reloc\n"); - - return 0; - default: - ErrorF("AOUT_RelocateEntry():" - " unknown intern relocation type: %d\n", rel->r_symbolnum); - return 0; - } /* switch */ - } -} /* AOUT_RelocateEntry */ - -static AOUTRelocPtr -AOUTCollectRelocations(AOUTModulePtr aoutfile) -{ - AOUTHDR *header = aoutfile->header; - int i, nreloc; - struct relocation_info *rel; - AOUTRelocPtr reloc_head = NULL; - AOUTRelocPtr tmp; - - /* Text relocations */ - if (aoutfile->text != NULL && aoutfile->txtrel != NULL) { - nreloc = header->a_trsize / sizeof(struct relocation_info); - - for (i = 0; i < nreloc; i++) { - rel = aoutfile->txtrel + i; - tmp = AOUTDelayRelocation(aoutfile, AOUT_TEXT, rel); - if (tmp) { - tmp->next = reloc_head; - reloc_head = tmp; - } - } /* for */ - } - /* Data relocations */ - if (aoutfile->data != NULL && aoutfile->datarel != NULL) { - nreloc = header->a_drsize / sizeof(struct relocation_info); - - for (i = 0; i < nreloc; i++) { - rel = aoutfile->datarel + i; - tmp = AOUTDelayRelocation(aoutfile, AOUT_DATA, rel); - tmp->next = reloc_head; - reloc_head = tmp; - } /* for */ - } - return reloc_head; -} /* AOUTCollectRelocations */ - -/* - * AOUT_GetSymbols() - * - * add the symbols to the loader's symbol table - */ -static LOOKUP * -AOUT_GetSymbols(AOUTModulePtr aoutfile) -{ - int fd = aoutfile->fd; - AOUTHDR *header = aoutfile->header; - int nsyms, soff, i, l; - char *symname; - AOUT_nlist *s; - LOOKUP *lookup, *lookup_common; - AOUTCommonPtr tmp; - - aoutfile->symtab = (AOUT_nlist *) _LoaderFileToMem(fd, - AOUT_SYMOFF(header), - header->a_syms, - "symbols"); - nsyms = header->a_syms / sizeof(AOUT_nlist); - lookup = xf86loadermalloc(nsyms * sizeof(LOOKUP)); - if (lookup == NULL) { - ErrorF("AOUT_GetSymbols(): can't allocate memory\n"); - return NULL; - } - for (i = 0, l = 0; i < nsyms; i++) { - s = aoutfile->symtab + i; - soff = s->n_un.n_strx; - if (soff == 0 || (s->n_type & AOUT_STAB) != 0) - continue; - symname = AOUTGetSymbolName(aoutfile, s); -#ifdef AOUTDEBUG - AOUTDEBUG("AOUT_GetSymbols(): %s %02x %02x %08lx\n", - symname, s->n_type, s->n_other, s->n_value); -#endif - switch (s->n_type & AOUT_TYPE) { - case AOUT_UNDF: - if (s->n_value != 0) { - if (!LoaderHashFind(symname)) { -#ifdef AOUTDEBUG - AOUTDEBUG("Adding common %s\n", symname); -#endif - tmp = AOUTAddCommon(s, i); - if (tmp) { - tmp->next = listCOMMON; - listCOMMON = tmp; - } - } - } else { -#ifdef AOUTDEBUG - AOUTDEBUG("Adding undef %s\n", symname); -#endif - } - xf86loaderfree(symname); - break; - case AOUT_TEXT: - if (s->n_type & AOUT_EXT) { - lookup[l].symName = symname; - /* text symbols start at 0 */ - lookup[l].offset = (funcptr) (aoutfile->text + s->n_value); -#ifdef AOUTDEBUG - AOUTDEBUG("Adding text %s %p\n", symname, - (void *)lookup[l].offset); -#endif - l++; - } else { - xf86loaderfree(symname); - } - break; - case AOUT_DATA: - if (s->n_type & AOUT_EXT) { - lookup[l].symName = symname; - /* data symbols are following text */ - lookup[l].offset = (funcptr) (aoutfile->data + - s->n_value - header->a_text); -#ifdef AOUTDEBUG - AOUTDEBUG("Adding data %s %p\n", symname, - (void *)lookup[l].offset); -#endif - l++; - } else { - xf86loaderfree(symname); - } - break; - case AOUT_BSS: - if (s->n_type & AOUT_EXT) { - lookup[l].symName = symname; - /* bss symbols follow both text and data */ - lookup[l].offset = (funcptr) (aoutfile->bss + s->n_value - - (header->a_data - + header->a_text)); -#ifdef AOUTDEBUG - AOUTDEBUG("Adding bss %s %p\n", symname, - (void *)lookup[l].offset); -#endif - l++; - } else { - xf86loaderfree(symname); - } - break; - case AOUT_FN: -#ifdef AOUTDEBUG - if (s->n_type & AOUT_EXT) { - AOUTDEBUG("Ignoring AOUT_FN %s\n", symname); - } else { - AOUTDEBUG("Ignoring AOUT_WARN %s\n", symname); - } -#endif - xf86loaderfree(symname); - break; - default: - ErrorF("Unknown symbol type %x\n", s->n_type & AOUT_TYPE); - xf86loaderfree(symname); - } /* switch */ - } /* for */ - lookup[l].symName = NULL; - - lookup_common = AOUTCreateCommon(aoutfile); - if (lookup_common) { - LOOKUP *p; - - for (i = 0, p = lookup_common; p->symName; i++, p++) ; - memcpy(&(lookup[l]), lookup_common, i * sizeof(LOOKUP)); - - xf86loaderfree(lookup_common); - l += i; - lookup[l].symName = NULL; - } - return lookup; -} /* AOUT_GetSymbols */ - -/* - * Public API for the a.out implementation of the loader - */ -void * -AOUTLoadModule(loaderPtr modrec, int aoutfd, LOOKUP ** ppLookup, int flags) -{ - AOUTModulePtr aoutfile = NULL; - AOUTHDR *header; - AOUTRelocPtr reloc, tail; - void *v; - -#ifdef AOUTDEBUG - AOUTDEBUG("AOUTLoadModule(%s, %d, %d)\n", - modrec->name, modrec->handle, aoutfd); -#endif - if ((aoutfile = xf86loadercalloc(1, sizeof(AOUTModuleRec))) == NULL) { - ErrorF("Unable to allocate AOUTModuleRec\n"); - return NULL; - } - - aoutfile->handle = modrec->handle; - aoutfile->module = modrec->module; - aoutfile->fd = aoutfd; - v = aoutfile->funcs = modrec->funcs; - - /* - * Get the a.out header - */ - aoutfile->header = - (AOUTHDR *) _LoaderFileToMem(aoutfd, 0, sizeof(AOUTHDR), - "header"); - header = (AOUTHDR *) aoutfile->header; - - /* - * Load the 6 other sections - */ - /* text */ - if (header->a_text != 0) { - aoutfile->text = _LoaderFileToMem(aoutfile->fd, - AOUT_TXTOFF(header), - header->a_text, "text"); - aoutfile->textsize = header->a_text; - } else { - aoutfile->text = NULL; - } - /* data */ - if (header->a_data != 0) { - aoutfile->data = _LoaderFileToMem(aoutfile->fd, - AOUT_DATOFF(header), - header->a_data, "data"); - aoutfile->datasize = header->a_data; - } else { - aoutfile->data = NULL; - } - /* bss */ - if (header->a_bss != 0) { - aoutfile->bss = xf86loadercalloc(1, header->a_bss); - aoutfile->bsssize = header->a_bss; - } else { - aoutfile->bss = NULL; - } - /* Text Relocations */ - if (header->a_trsize != 0) { - aoutfile->txtrel = _LoaderFileToMem(aoutfile->fd, - AOUT_TRELOFF(header), - header->a_trsize, "txtrel"); - } else { - aoutfile->txtrel = NULL; - } - /* Data Relocations */ - if (header->a_drsize != 0) { - aoutfile->datarel = _LoaderFileToMem(aoutfile->fd, - AOUT_DRELOFF(header), - header->a_drsize, "datarel"); - } else { - aoutfile->datarel = NULL; - } - /* String table */ - _LoaderFileRead(aoutfile->fd, AOUT_STROFF(header), - &(aoutfile->strsize), sizeof(int)); - if (aoutfile->strsize != 0) { - aoutfile->strings = _LoaderFileToMem(aoutfile->fd, - AOUT_STROFF(header), - aoutfile->strsize, "strings"); - } else { - aoutfile->strings = NULL; - } - /* load symbol table */ - *ppLookup = AOUT_GetSymbols(aoutfile); - - /* Do relocations */ - reloc = AOUTCollectRelocations(aoutfile); - - if (reloc) { - for (tail = reloc; tail->next; tail = tail->next) ; - tail->next = _LoaderGetRelocations(v)->aout_reloc; - _LoaderGetRelocations(v)->aout_reloc = reloc; - } - - return (void *)aoutfile; -} - -void -AOUTResolveSymbols(void *mod) -{ - AOUTRelocPtr newlist, p, tmp; - -#ifdef AOUTDEBUG - AOUTDEBUG("AOUTResolveSymbols()\n"); -#endif - - newlist = 0; - for (p = _LoaderGetRelocations(mod)->aout_reloc; p;) { - tmp = AOUT_RelocateEntry(p->file, p->type, p->rel); - if (tmp) { - /* Failed to relocate. Keep it in the list. */ - tmp->next = newlist; - newlist = tmp; - } - tmp = p; - p = p->next; - xf86loaderfree(tmp); - } - _LoaderGetRelocations(mod)->aout_reloc = newlist; -} /* AOUTResolveSymbols */ - -int -AOUTCheckForUnresolved(void *mod) -{ - int symnum; - AOUTRelocPtr crel; - char *name; - int fatalsym = 0, flag; - -#ifdef AOUTDEBUG - AOUTDEBUG("AOUTCheckForUnResolved()\n"); -#endif - if ((crel = _LoaderGetRelocations(mod)->aout_reloc) == NULL) - return 0; - - while (crel) { - if (crel->type == AOUT_TEXT) { - /* Attempt to make unresolved text references - * point to a default function */ - AOUT_Relocate((unsigned long *)(crel->file->text - + crel->rel->r_address), - (unsigned long)LoaderDefaultFunc, - crel->rel->r_pcrel); - } - symnum = crel->rel->r_symbolnum; - name = AOUTGetSymbolName(crel->file, crel->file->symtab + symnum); - flag = _LoaderHandleUnresolved(name, - _LoaderHandleToName(crel->file-> - handle)); - xf86loaderfree(name); - if (flag) - fatalsym = 1; - crel = crel->next; - } - return fatalsym; -} - -void -AOUTUnloadModule(void *modptr) -{ - AOUTModulePtr aoutfile = (AOUTModulePtr) modptr; - AOUTRelocPtr relptr, *prevptr; - -#ifdef AOUTDEBUG - AOUTDEBUG("AOUTUnLoadModule(0x%p)\n", modptr); -#endif - -/* - * Delete any unresolved relocations - */ - - relptr = _LoaderGetRelocations(aoutfile->funcs)->aout_reloc; - prevptr = &(_LoaderGetRelocations(aoutfile->funcs)->aout_reloc); - - while (relptr) { - if (relptr->file == aoutfile) { - *prevptr = relptr->next; - xf86loaderfree(relptr); - relptr = *prevptr; - } else { - prevptr = &(relptr->next); - relptr = relptr->next; - } - } /* while */ - - /* clean the symbols table */ - LoaderHashTraverse((void *)aoutfile, AOUTHashCleanOut); - -#define CheckandFree(ptr,size) if(ptr) _LoaderFreeFileMem((ptr),(size)) - - CheckandFree(aoutfile->strings, aoutfile->strsize); - CheckandFree(aoutfile->symtab, aoutfile->header->a_syms); - CheckandFree(aoutfile->datarel, aoutfile->header->a_drsize); - CheckandFree(aoutfile->txtrel, aoutfile->header->a_trsize); - CheckandFree(aoutfile->data, aoutfile->header->a_data); - CheckandFree(aoutfile->text, aoutfile->header->a_text); - /* Free allocated sections */ - if (aoutfile->bss != NULL) { - xf86loaderfree(aoutfile->bss); - } - if (aoutfile->common != NULL) { - xf86loaderfree(aoutfile->common); - } - - /* Free header */ - _LoaderFreeFileMem(aoutfile->header, sizeof(AOUTHDR)); - - /* Free the module structure itself */ - xf86loaderfree(aoutfile); - - return; -} - -char * -AOUTAddressToSection(void *modptr, unsigned long address) -{ - AOUTModulePtr aoutfile = (AOUTModulePtr) modptr; - - if (address >= (unsigned long)aoutfile->text && - address <= (unsigned long)aoutfile->text + aoutfile->textsize) { - return "text"; - } - if (address >= (unsigned long)aoutfile->data && - address <= (unsigned long)aoutfile->data + aoutfile->datasize) { - return "data"; - } - if (address >= (unsigned long)aoutfile->bss && - address <= (unsigned long)aoutfile->bss + aoutfile->bsssize) { - return "bss"; - } - - return NULL; -} diff --git a/hw/xfree86/loader/aoutloader.h b/hw/xfree86/loader/aoutloader.h deleted file mode 100644 index 8c04a16eb..000000000 --- a/hw/xfree86/loader/aoutloader.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright 1997,1998 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. - */ - -/* $XFree86: xc/programs/Xserver/hw/xfree86/loader/aoutloader.h,v 1.3 1998/09/20 14:41:03 dawes Exp $ */ - -#ifdef HAVE_XORG_CONFIG_H -#include <xorg-config.h> -#endif - -#ifndef _AOUTLOADER_H -#define _AOUTLOADER_H -extern void *AOUTLoadModule(loaderPtr, int, LOOKUP **, int flags); -extern void AOUTResolveSymbols(void *); -extern int AOUTCheckForUnresolved(void *); -extern char *AOUTAddressToSection(void *, unsigned long); -extern void AOUTUnloadModule(void *); -#endif diff --git a/hw/xfree86/loader/ar.h b/hw/xfree86/loader/ar.h deleted file mode 100644 index c9ae558cf..000000000 --- a/hw/xfree86/loader/ar.h +++ /dev/null @@ -1,75 +0,0 @@ -/* $XFree86: xc/programs/Xserver/hw/xfree86/loader/ar.h,v 1.3 1998/07/25 16:56:12 dawes Exp $ */ - -#ifdef HAVE_XORG_CONFIG_H -#include <xorg-config.h> -#endif - -#ifndef _AR_H -#define _AR_H - -#define ARMAG "!<arch>\n" -#define SARMAG 8 -#define ARFMAG "`\n" - -#if !(defined(__powerpc__) && defined(Lynx)) -struct ar_hdr { - char ar_name[16]; - char ar_date[12]; - char ar_uid[6]; - char ar_gid[6]; - char ar_mode[8]; - char ar_size[10]; - char ar_fmag[2]; -}; - -#else - -#define AIAMAG "<aiaff>\n" -#define SAIAMAG 8 -#define AIAFMAG "`\n" - -struct fl_hdr { /* archive fixed length header - printable ascii */ - char fl_magic[SAIAMAG]; /* Archive file magic string */ - char fl_memoff[12]; /* Offset to member table */ - char fl_gstoff[12]; /* Offset to global symbol table */ - char fl_fstmoff[12]; /* Offset to first archive member */ - char fl_lstmoff[12]; /* Offset to last archive member */ - char fl_freeoff[12]; /* Offset to first mem on free list */ -}; - -#define FL_HDR struct fl_hdr -#define FL_HSZ sizeof(FL_HDR) - -struct ar_hdr { /* archive file member header - printable ascii */ - char ar_size[12]; /* file member size - decimal */ - char ar_nxtmem[12]; /* pointer to next member - decimal */ - char ar_prvmem[12]; /* pointer to previous member - decimal */ - char ar_date[12]; /* file member date - decimal */ - char ar_uid[12]; /* file member user id - decimal */ - char ar_gid[12]; /* file member group id - decimal */ - char ar_mode[12]; /* file member mode - octal */ - char ar_namlen[4]; /* file member name length - decimal */ - union { - char an_name[2]; /* variable length member name */ - char an_fmag[2]; /* AIAFMAG - string to end header */ - } _ar_name; /* and variable length name */ -}; - -#define ar_name _ar_name.an_name - -/* - * Note: 'ar_namlen' contains the length of the member name which - * may be up to 255 chars. The character string containing - * the name begins at '_ar_name.ar_name'. The terminating - * string AIAFMAG, is only cosmetic. File member contents begin - * at the first even byte boundary past 'header position + - * sizeof(struct ar_hdr) + ar_namlen', and continue for - * 'ar_size' bytes. -*/ - -#define AR_HDR struct ar_hdr -#define AR_HSZ sizeof(AR_HDR) - -#endif /* !__powerpc__ && Lynx */ - -#endif /* _AR_H */ diff --git a/hw/xfree86/loader/coff.h b/hw/xfree86/loader/coff.h deleted file mode 100644 index b3cecdfbe..000000000 --- a/hw/xfree86/loader/coff.h +++ /dev/null @@ -1,237 +0,0 @@ -/* $XFree86: xc/programs/Xserver/hw/xfree86/loader/coff.h,v 1.5 1998/07/25 16:56:12 dawes Exp $ */ - -/* This file was implemented from the information in the book - Understanding and Using COFF - Gintaras R. Gircys - O'Reilly, 1988 - and by looking at the Linux kernel code. - - It is therefore most likely free to use... - - If the file format changes in the COFF object, this file should be - subsequently updated to reflect the changes. - - The actual loader module only uses a few of the COFF structures. - Only those are included here. If you wish more information about - COFF, thein check out the book mentioned above. -*/ - -#ifdef HAVE_XORG_CONFIG_H -#include <xorg-config.h> -#endif - -#ifndef _COFF_H -#define _COFF_H - -#define E_SYMNMLEN 8 /* Number of characters in a symbol name */ -/* - * Intel 386/486 - */ - -/* - * FILE HEADER - */ - -typedef struct COFF_filehdr { - unsigned short f_magic; /* magic number */ - unsigned short f_nscns; /* number of sections */ - long f_timdat; /* time & date stamp */ - long f_symptr; /* file pointer to symtab */ - long f_nsyms; /* number of symtab entries */ - unsigned short f_opthdr; /* sizeof(optional hdr) */ - unsigned short f_flags; /* flags */ -} FILHDR; - -#define FILHSZ sizeof(FILHDR) - -/* - * SECTION HEADER - */ - -typedef struct COFF_scnhdr { - char s_name[8]; /* section name */ - long s_paddr; /* physical address */ - long s_vaddr; /* virtual address */ - long s_size; /* section size */ - long s_scnptr; /* raw data for section */ - long s_relptr; /* relocation */ - long s_lnnoptr; /* line numbers */ - unsigned short s_nreloc; /* number of relocation entries */ - unsigned short s_nlnno; /* number of line number entries */ - long s_flags; /* flags */ -} SCNHDR; - -#define COFF_SCNHDR struct COFF_scnhdr -#define COFF_SCNHSZ sizeof(COFF_SCNHDR) -#define SCNHSZ COFF_SCNHSZ - -/* - * the optional COFF header as used by Linux COFF - */ - -typedef struct { - char magic[2]; /* type of file */ - char vstamp[2]; /* version stamp */ - char tsize[4]; /* text size in bytes */ - char dsize[4]; /* initialized data */ - char bsize[4]; /* uninitialized data */ - char entry[4]; /* entry point */ - char text_start[4]; /* base of text */ - char data_start[4]; /* base of data */ -} AOUTHDR; - -/* - * SYMBOLS - */ - -typedef struct COFF_syment { - union { - char _n_name[E_SYMNMLEN]; /* Symbol name (first 8 chars) */ - struct { - long _n_zeroes; /* Leading zeros */ - long _n_offset; /* Offset for a header section */ - } _n_n; - char *_n_nptr[2]; /* allows for overlaying */ - } _n; - - long n_value; /* address of the segment */ - short n_scnum; /* Section number */ - unsigned short n_type; /* Type of section */ - char n_sclass; /* Loader class */ - char n_numaux; /* Number of aux entries following */ -} SYMENT; - -#define n_name _n._n_name -#define n_nptr _n._n_nptr[1] -#define n_zeroes _n._n_n._n_zeroes -#define n_offset _n._n_n._n_offset - -#define COFF_E_SYMNMLEN 8 /* characters in a short symbol name */ -#define COFF_E_FILNMLEN 14 /* characters in a file name */ -#define COFF_E_DIMNUM 4 /* array dimensions in aux entry */ -#define SYMNMLEN COFF_E_SYMNMLEN -#define SYMESZ 18 /* not really sizeof(SYMENT) due to padding */ - -/* Special section number found in the symbol section */ -#define N_UNDEF 0 -#define N_ABS -1 -#define N_DEBUG -2 - -/* Symbol storage class values */ -#define C_NULL 0 -#define C_EXT 2 -#define C_FILE 103 -#define C_HIDEXT 107 - -/* - * AUX Entries - */ -typedef struct COFF_auxent { - long x_scnlen; - long x_parmhash; - unsigned short x_snhash; - unsigned char x_smtyp; - unsigned char x_smclas; - long x_stab; - unsigned short x_snstab; -} AUXENT; - -/* Auxillary Symbol type values */ -#define XTY_ER 0 /* Enternal Reference */ -#define XTY_SD 1 /* csect section definition */ -#define XTY_LD 2 /* Label definition */ -#define XTY_CM 3 /* common csect definition */ - -/* Auxillary Symbol storage mapping class values */ -#define XMC_PR 0 /* Program code */ -#define XMC_RO 1 /* Read-only constant */ -#define XMC_DB 2 /* Debug dictionary */ -#define XMC_TC 3 /* TOC entry */ -#define XMC_UA 4 /* Unclassified */ -#define XMC_RW 5 /* Read/write data */ -#define XMC_GL 6 /* Global linkage */ -#define XMC_XO 7 /* Extended operation */ -#define XMC_SV 8 /* Supervisor call descriptor */ -#define XMC_BS 9 /* BSS class */ -#define XMC_DS 10 /* Function descriptor csect */ -#define XMC_UC 11 /* Unnamed FORTRAN comon */ -#define XMC_TI 12 /* Reserved */ -#define XMC_TB 13 /* Reserved */ -#define XMC_TC0 15 /* TOC anchor */ -#define XMC_TD 16 /* Scalar data entry in TOC */ - -/* - * RELOCATION DIRECTIVES - */ - -typedef struct COFF_reloc { - long r_vaddr; /* Virtual address of item */ - long r_symndx; /* Symbol index in the symtab */ -#if defined(__powerpc__) - union { - unsigned short _r_type; /* old style coff relocation type */ - struct { - char _r_rsize; /* sign and reloc bit len */ - char _r_rtype; /* toc relocation type */ - } _r_r; - } _r; -#define r_otype _r._r_type /* old style reloc - original name */ -#define r_rsize _r._r_r._r_rsize /* extract sign and bit len */ -#define r_type _r._r_r._r_rtype /* extract toc relocation type */ -#else - unsigned short r_type; /* Relocation type */ -#endif -} RELOC; - -#define COFF_RELOC struct COFF_reloc -#define COFF_RELSZ 10 -#define RELSZ COFF_RELSZ - -/* - * x86 Relocation types - */ -#define R_ABS 000 -#define R_DIR32 006 -#define R_PCRLONG 024 - -#if defined(__powerpc__) -/* - * Power PC - */ -#define R_LEN 0x1F /* extract bit-length field */ -#define R_SIGN 0x80 /* extract sign of relocation */ -#define R_FIXUP 0x40 /* extract code-fixup bit */ - -#define RELOC_RLEN(x) ((x)._r._r_r._r_rsize & R_LEN) -#define RELOC_RSIGN(x) ((x)._r._r_r._r_rsize & R_SIGN) -#define RELOC_RFIXUP(x) ((x)._r._r_r._r_rsize & R_FIXUP) -#define RELOC_RTYPE(x) ((x)._r._r_r._r_rtype) - -/* - * POWER and PowerPC - relocation types - */ -#define R_POS 0x00 /* A(sym) Positive Relocation */ -#define R_NEG 0x01 /* -A(sym) Negative Relocation */ -#define R_REL 0x02 /* A(sym-*) Relative to self */ -#define R_TOC 0x03 /* A(sym-TOC) Relative to TOC */ -#define R_TRL 0x12 /* A(sym-TOC) TOC Relative indirect load. */ - /* modifiable instruction */ -#define R_TRLA 0x13 /* A(sym-TOC) TOC Rel load address. modifiable inst */ -#define R_GL 0x05 /* A(external TOC of sym) Global Linkage */ -#define R_TCL 0x06 /* A(local TOC of sym) Local object TOC address */ -#define R_RL 0x0C /* A(sym) Pos indirect load. modifiable instruction */ -#define R_RLA 0x0D /* A(sym) Pos Load Address. modifiable instruction */ -#define R_REF 0x0F /* AL0(sym) Non relocating ref. No garbage collect */ -#define R_BA 0x08 /* A(sym) Branch absolute. Cannot modify instruction */ -#define R_RBA 0x18 /* A(sym) Branch absolute. modifiable instruction */ -#define R_RBAC 0x19 /* A(sym) Branch absolute constant. modifiable instr */ -#define R_BR 0x0A /* A(sym-*) Branch rel to self. non modifiable */ -#define R_RBR 0x1A /* A(sym-*) Branch rel to self. modifiable instr */ -#define R_RBRC 0x1B /* A(sym-*) Branch absolute const. */ - /* modifiable to R_RBR */ -#define R_RTB 0x04 /* A((sym-*)/2) RT IAR Rel Branch. non modifiable */ -#define R_RRTBI 0x14 /* A((sym-*)/2) RT IAR Rel Br. modifiable to R_RRTBA */ -#define R_RRTBA 0x15 /* A((sym-*)/2) RT absolute br. modifiable to R_RRTBI */ -#endif /* __powerpc */ - -#endif /* _COFF_H */ diff --git a/hw/xfree86/loader/coffloader.c b/hw/xfree86/loader/coffloader.c deleted file mode 100644 index d29b39a72..000000000 --- a/hw/xfree86/loader/coffloader.c +++ /dev/null @@ -1,1359 +0,0 @@ -/* $XFree86: xc/programs/Xserver/hw/xfree86/loader/coffloader.c,v 1.21tsi Exp $ */ - -/* - * - * Copyright 1995,96 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> -#include <unistd.h> -#include <stdlib.h> -#ifdef __QNX__ -#include <fcntl.h> -#else -#include <sys/fcntl.h> -#endif -#include <sys/stat.h> - -#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 "coff.h" - -#include "sym.h" -#include "loader.h" -#include "coffloader.h" - -#include "compiler.h" - -#ifndef LOADERDEBUG -#define LOADERDEBUG 0 -#endif - -#if LOADERDEBUG -#define COFFDEBUG ErrorF -#endif - -/* - * This structure contains all of the information about a module - * that has been loaded. - */ - -typedef struct { - int handle; - long module; /* Id of the module used to find inter module calls */ - int fd; - loader_funcs *funcs; - FILHDR *header; /* file header */ - AOUTHDR *optheader; /* optional file header */ - unsigned short numsh; - SCNHDR *sections; /* Start address of the section table */ - int secsize; /* size of the section table */ - unsigned char **saddr; /* Start addresss of the sections table */ - unsigned char **reladdr; /* Start addresss of the relocation table */ - unsigned char *strtab; /* Start address of the string table */ - int strsize; /* size of the string table */ - unsigned char *text; /* Start address of the .text section */ - int txtndx; /* index of the .text section */ - long txtaddr; /* offset of the .text section */ - int txtsize; /* size of the .text section */ - int txtrelsize; /* size of the .rel.text section */ - unsigned char *data; /* Start address of the .data section */ - int datndx; /* index of the .data section */ - long dataddr; /* offset of the .data section */ - int datsize; /* size of the .data section */ - int datrelsize; /* size of the .rel.data section */ - unsigned char *bss; /* Start address of the .bss section */ - int bssndx; /* index of the .bss section */ - long bssaddr; /* offset of the .bss section */ - int bsssize; /* size of the .bss section */ - SYMENT *symtab; /* Start address of the .symtab section */ - int symndx; /* index of the .symtab section */ - int symsize; /* size of the .symtab section */ - unsigned char *common; /* Start address of the .common section */ - int comsize; /* size of the .common section */ - long toc; /* Offset of the TOC csect */ - unsigned char *tocaddr; /* Address of the TOC csect */ -} COFFModuleRec, *COFFModulePtr; - -/* - * If any relocation is unable to be satisfied, then put it on a list - * to try later after more modules have been loaded. - */ -typedef struct _coff_reloc { - COFFModulePtr file; - RELOC *rel; - int secndx; - struct _coff_reloc *next; -} COFFRelocRec; - -/* - * Symbols with a section number of 0 (N_UNDEF) but a value of non-zero - * need to have space allocated for them. - * - * Gather all of these symbols together, and allocate one chunk when we - * are done. - */ - -typedef struct _coff_COMMON { - SYMENT *sym; - int index; - struct _coff_COMMON *next; -} COFFCommonRec; - -static COFFCommonPtr listCOMMON = NULL; - -/* Prototypes for static functions */ -static int COFFhashCleanOut(void *, itemPtr); -static char *COFFGetSymbolName(COFFModulePtr, int); -static COFFCommonPtr COFFAddCOMMON(SYMENT *, int); -static LOOKUP *COFFCreateCOMMON(COFFModulePtr); -static COFFRelocPtr COFFDelayRelocation(COFFModulePtr, int, RELOC *); -static SYMENT *COFFGetSymbol(COFFModulePtr, int); -#if defined(i386) || defined(__powerpc__) -static unsigned char *COFFGetSymbolValue(COFFModulePtr, int); -#endif -static COFFRelocPtr COFF_RelocateEntry(COFFModulePtr, int, RELOC *); -static LOOKUP *COFF_GetSymbols(COFFModulePtr); -static void COFFCollectSections(COFFModulePtr); -static COFFRelocPtr COFFCollectRelocations(COFFModulePtr); - -/* - * Utility Functions - */ - -static int -COFFhashCleanOut(void *voidptr, itemPtr item) -{ - COFFModulePtr module = (COFFModulePtr) voidptr; - - return (module->handle == item->handle); -} - -/* - * Manage listResolv - */ -static COFFRelocPtr -COFFDelayRelocation(COFFModulePtr cofffile, int secndx, RELOC *rel) -{ - COFFRelocPtr reloc; - - if ((reloc = xf86loadermalloc(sizeof(COFFRelocRec))) == NULL) { - ErrorF("COFFDelayRelocation() Unable to allocate memory!!!!\n"); - return 0; - } - - reloc->file = cofffile; - reloc->secndx = secndx; - reloc->rel = rel; - reloc->next = 0; - - return reloc; -} - -/* - * Manage listCOMMON - */ - -static COFFCommonPtr -COFFAddCOMMON(SYMENT *sym, int index) -{ - COFFCommonPtr common; - - if ((common = xf86loadermalloc(sizeof(COFFCommonRec))) == NULL) { - ErrorF("COFFAddCOMMON() Unable to allocate memory!!!!\n"); - return 0; - } - common->sym = sym; - common->index = index; - common->next = 0; - - return common; -} - -static LOOKUP * -COFFCreateCOMMON(COFFModulePtr cofffile) -{ - int numsyms = 0, size = 0, l = 0; - int offset = 0; - LOOKUP *lookup; - COFFCommonPtr common; - - if (listCOMMON == NULL) - return NULL; - - common = listCOMMON; - for (common = listCOMMON; common; common = common->next) { - /* Ensure long word alignment */ - if (common->sym->n_value != 2 && common->sym->n_value != 1) /* But not for short and char ;-)(mr) */ - if (common->sym->n_value % 4 != 0) - common->sym->n_value += 4 - (common->sym->n_value % 4); - - /* accumulate the sizes */ - size += common->sym->n_value; - numsyms++; - } - -#ifdef COFFDEBUG - COFFDEBUG("COFFCreateCOMMON() %d entries (%d bytes) of COMMON data\n", - numsyms, size); -#endif - - if ((lookup = xf86loadermalloc((numsyms + 1) * sizeof(LOOKUP))) == NULL) { - ErrorF("COFFCreateCOMMON() Unable to allocate memory!!!!\n"); - return NULL; - } - - cofffile->comsize = size; - if ((cofffile->common = xf86loadercalloc(1, size)) == NULL) { - ErrorF("COFFCreateCOMMON() Unable to allocate memory!!!!\n"); - return NULL; - } - - /* 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; - lookup[l].symName = COFFGetSymbolName(cofffile, common->index); - lookup[l].offset = (funcptr) (cofffile->common + offset); -#ifdef COFFDEBUG - COFFDEBUG("Adding %p %s\n", (void *)lookup[l].offset, - lookup[l].symName); -#endif - listCOMMON = common->next; - offset += common->sym->n_value; - xf86loaderfree(common); - l++; - } - /* listCOMMON == NULL */ - - lookup[l].symName = NULL; /* Terminate the list */ - return lookup; -} - -/* - * Symbol Table - */ - -/* - * Get symbol name - */ -static char * -COFFGetSymbolName(COFFModulePtr cofffile, int index) -{ - char *name; - SYMENT *sym; - - sym = (SYMENT *) (((unsigned char *)cofffile->symtab) + (index * SYMESZ)); - -#ifdef COFFDEBUG - COFFDEBUG("COFFGetSymbolName(%p,%x) %lx", (void *)cofffile, index, - sym->n_zeroes); -#endif - - name = xf86loadermalloc(sym->n_zeroes ? SYMNMLEN + 1 - : strlen((const char *)&cofffile-> - strtab[(int)sym->n_offset - 4]) + 1); - if (!name) - FatalError("COFFGetSymbolName: Out of memory\n"); - - if (sym->n_zeroes) { - strncpy(name, sym->n_name, SYMNMLEN); - name[SYMNMLEN] = '\000'; - } else { - strcpy(name, (const char *)&cofffile->strtab[(int)sym->n_offset - 4]); - } -#ifdef COFFDEBUG - COFFDEBUG(" %s\n", name); -#endif - return name; -} - -static SYMENT * -COFFGetSymbol(COFFModulePtr file, int index) -{ - return (SYMENT *) (((unsigned char *)file->symtab) + (index * SYMESZ)); -} - -#if defined(i386) || defined(__powerpc__) -static unsigned char * -COFFGetSymbolValue(COFFModulePtr cofffile, int index) -{ - unsigned char *symval = 0; /* value of the indicated symbol */ - itemPtr symbol; /* name/value of symbol */ - char *symname; - - symname = COFFGetSymbolName(cofffile, index); - -#ifdef COFFDEBUG - COFFDEBUG("COFFGetSymbolValue() for %s=", symname); -#endif - - symbol = LoaderHashFind(symname); - - if (symbol) - symval = (unsigned char *)symbol->address; - -#ifdef COFFDEBUG - COFFDEBUG("%p\n", symval); -#endif - - xf86loaderfree(symname); - return symval; -} -#endif - -#if defined(__powerpc__) -/* - * This function returns the address of the glink routine for a symbol. This - * address is used in cases where the function being called is not in the - * same module as the calling function. - */ -static unsigned char * -COFFGetSymbolGlinkValue(COFFModulePtr cofffile, int index) -{ - unsigned char *symval = 0; /* value of the indicated symbol */ - itemPtr symbol; /* name/value of symbol */ - char *name; - - name = COFFGetSymbolName(cofffile, index); - -#ifdef COFFDEBUG - COFFDEBUG("COFFGetSymbolGlinkValue() for %s=", name); -#endif - - symbol = LoaderHashFind(name + 1); /* Eat the '.' so we get the - * Function descriptor instead */ - -/* Here we are building up a glink function that will change the TOC - * pointer before calling a function that resides in a different module. - * The following code is being used to implement this. - - 1 00000000 3d80xxxx lis r12,hi16(funcdesc) - 2 00000004 618cxxxx ori r12,r12,lo16(funcdesc) - 3 00000008 90410014 st r2,20(r1) # save old TOC pointer - 4 0000000c 804c0000 l r2,0(r12) # Get address of functions - 5 00000010 7c4903a6 mtctr r2 # load destination address - 6 00000014 804c0004 l r2,4(r12) # get TOC of function - 7 00000018 4e800420 bctr # branch to it - - */ - if (symbol) { - symval = (unsigned char *)&symbol->code.glink; -#ifdef COFFDEBUG - COFFDEBUG("%x\n", symval); - COFFDEBUG("glink_%s=%x\n", name, symval); -#endif - symbol->code.glink[0] = 0x3d80; /* lis r12 */ - symbol->code.glink[1] = - ((unsigned long)symbol->address & 0xffff0000) >> 16; - symbol->code.glink[2] = 0x618c; /* ori r12 */ - symbol->code.glink[3] = ((unsigned long)symbol->address & 0x0000ffff); - symbol->code.glink[4] = 0x9041; /* st r2,20(r1) */ - symbol->code.glink[5] = 0x0014; - symbol->code.glink[6] = 0x804c; /* l r2,0(r12) */ - symbol->code.glink[7] = 0x0000; - symbol->code.glink[8] = 0x7c49; /* mtctr r2 */ - symbol->code.glink[9] = 0x03a6; - symbol->code.glink[10] = 0x804c; /* l r2,4(r12) */ - symbol->code.glink[11] = 0x0004; - symbol->code.glink[12] = 0x4e80; /* bctr */ - symbol->code.glink[13] = 0x0420; - ppc_flush_icache(&symbol->code.glink[0]); - ppc_flush_icache(&symbol->code.glink[12]); - } - - xf86loaderfree(name); - return symval; -} -#endif /* __powerpc__ */ - -/* - * Fix all of the relocation for the given section. - */ -static COFFRelocPtr -COFF_RelocateEntry(COFFModulePtr cofffile, int secndx, RELOC *rel) -{ - SYMENT *symbol; /* value of the indicated symbol */ - unsigned long *dest32; /* address of the place being modified */ - -#if defined(__powerpc__) - unsigned short *dest16; /* address of the place being modified */ - itemPtr symitem; /* symbol structure from has table */ - char *name; -#endif - unsigned char *symval; /* value of the indicated symbol */ - -/* - * Note: Section numbers are 1 biased, while the cofffile->saddr[] array - * of pointer is 0 biased, so alway have to account for the difference. - */ - -/* - * Reminder: secndx is the section to which the relocation is applied. - * symbol->n_scnum is the section in which the symbol value resides. - */ - -#ifdef COFFDEBUG - COFFDEBUG("%lx %ld %o ", (unsigned long)rel->r_vaddr, - rel->r_symndx, rel->r_type); -#if defined(__powerpc__) - COFFDEBUG("[%x %x %x] ", - RELOC_RSIGN(*rel), RELOC_RFIXUP(*rel), RELOC_RLEN(*rel)); -#endif -#endif - symbol = COFFGetSymbol(cofffile, rel->r_symndx); -#ifdef COFFDEBUG - COFFDEBUG("%d %lx %d-%d\n", symbol->n_sclass, symbol->n_value, - symbol->n_scnum, secndx); -#endif - -/* - * Check to see if the relocation offset is part of the .text segment. - * If not, we must change the offset to be relative to the .data section - * which is NOT contiguous. - */ - switch (secndx + 1) { /* change the bias */ - case N_TEXT: - if ((long)rel->r_vaddr < cofffile->txtaddr || - (long)rel->r_vaddr > - (long)(cofffile->txtaddr + cofffile->txtsize)) { - FatalError("Relocation against N_TEXT not in .text section\n"); - } - dest32 = (unsigned long *)((long)(cofffile->saddr[secndx]) + - ((unsigned char *)rel->r_vaddr - - cofffile->txtaddr)); - break; - case N_DATA: - if ((long)rel->r_vaddr < cofffile->dataddr || - (long)rel->r_vaddr > - (long)(cofffile->dataddr + cofffile->datsize)) { - FatalError("Relocation against N_DATA not in .data section\n"); - } - dest32 = (unsigned long *)((long)(cofffile->saddr[secndx]) + - ((unsigned char *)rel->r_vaddr - - cofffile->dataddr)); - break; - case N_BSS: - if ((long)rel->r_vaddr < cofffile->bssaddr || - (long)rel->r_vaddr > - (long)(cofffile->bssaddr + cofffile->bsssize)) { - FatalError("Relocation against N_TEXT not in .bss section\n"); - } - dest32 = (unsigned long *)((long)(cofffile->saddr[secndx]) + - ((unsigned char *)rel->r_vaddr - - cofffile->bssaddr)); - break; - default: - FatalError("Relocation against unknown section %d\n", secndx); - } - - if (symbol->n_sclass == 0) { - symval = (unsigned char *)(symbol->n_value + (*dest32) - - symbol->n_type); -#ifdef COFFDEBUG - COFFDEBUG("symbol->n_sclass==0\n"); - COFFDEBUG("dest32=%p\t", (void *)dest32); - COFFDEBUG("symval=%p\t", symval); - COFFDEBUG("*dest32=%8.8lx\t", *dest32); -#endif - *dest32 = (unsigned long)symval; - return 0; - } - - switch (rel->r_type) { -#if defined(i386) - case R_DIR32: - symval = COFFGetSymbolValue(cofffile, rel->r_symndx); - if (symval) { -#ifdef COFFDEBUG - char *namestr; - - COFFDEBUG("R_DIR32 %s\n", - namestr = COFFGetSymbolName(cofffile, rel->r_symndx)); - xf86loaderfree(namestr); - COFFDEBUG("txtsize=%x\t", cofffile->txtsize); - COFFDEBUG("dest32=%p\t", (void *)dest32); - COFFDEBUG("symval=%p\t", symval); - COFFDEBUG("*dest32=%8.8lx\t", *dest32); -#endif - *dest32 = (unsigned long)(symval + (*dest32) - symbol->n_value); - } else { - switch (symbol->n_scnum) { - case N_UNDEF: -#ifdef COFFDEBUG - COFFDEBUG("R_DIR32 N_UNDEF\n"); -#endif - return COFFDelayRelocation(cofffile, secndx, rel); - case N_ABS: -#ifdef COFFDEBUG - COFFDEBUG("R_DIR32 N_ABS\n"); -#endif - return 0; - case N_DEBUG: -#ifdef COFFDEBUG - COFFDEBUG("R_DIR32 N_DEBUG\n"); -#endif - return 0; - case N_COMMENT: -#ifdef COFFDEBUG - COFFDEBUG("R_DIR32 N_COMMENT\n"); -#endif - return 0; - case N_TEXT: -#ifdef COFFDEBUG - COFFDEBUG("R_DIR32 N_TEXT\n"); - COFFDEBUG("dest32=%p\t", (void *)dest32); - COFFDEBUG("symval=%p\t", symval); - COFFDEBUG("*dest32=%8.8lx\t", *dest32); -#endif - *dest32 = (unsigned long)((*dest32) + - (unsigned long)(cofffile-> - saddr[N_TEXT - 1])); - break; - case N_DATA: -#ifdef COFFDEBUG - COFFDEBUG("R_DIR32 N_DATA\n"); - COFFDEBUG("txtsize=%x\t", cofffile->txtsize); - COFFDEBUG("dest32=%p\t", (void *)dest32); - COFFDEBUG("symval=%p\t", symval); - COFFDEBUG("*dest32=%8.8lx\t", *dest32); -#endif - *dest32 = (unsigned long)((*dest32) + - ((unsigned long)(cofffile-> - saddr[N_DATA - - 1])) - - cofffile->dataddr); - break; - case N_BSS: -#ifdef COFFDEBUG - COFFDEBUG("R_DIR32 N_BSS\n"); - COFFDEBUG("dest32=%p\t", (void *)dest32); - COFFDEBUG("symval=%p\t", symval); - COFFDEBUG("*dest32=%8.8lx\t", *dest32); -#endif - *dest32 = (unsigned long)((*dest32) + - (unsigned long)(cofffile-> - saddr[N_BSS - 1]) - - (cofffile->bssaddr)); - break; - default: - ErrorF("R_DIR32 with unexpected section %d\n", - symbol->n_scnum); - } - - } -#ifdef COFFDEBUG - COFFDEBUG("*dest32=%8.8lx\n", *dest32); -#endif - break; - case R_PCRLONG: - if (symbol->n_scnum == N_TEXT) - break; - - symval = COFFGetSymbolValue(cofffile, rel->r_symndx); -#ifdef COFFDEBUG - COFFDEBUG("R_PCRLONG "); - COFFDEBUG("dest32=%p\t", (void *)dest32); - COFFDEBUG("symval=%p\t", symval); - COFFDEBUG("*dest32=%8.8lx\t", *dest32); -#endif - if (symval == 0) { -#ifdef COFFDEBUG - char *name; - - COFFDEBUG("***Unable to resolve symbol %s\n", - name = COFFGetSymbolName(cofffile, rel->r_symndx)); - xf86loaderfree(name); -#endif - return COFFDelayRelocation(cofffile, secndx, rel); - } - *dest32 = (unsigned long)(symval - ((long)dest32 + sizeof(long))); - -#ifdef COFFDEBUG - COFFDEBUG("*dest32=%8.8lx\n", *dest32); -#endif - break; - case R_ABS: - /* - * Nothing to really do here. - * Usually, a dummy relocation for .file - */ - break; -#endif /* i386 */ -#if defined(__powerpc__) - case R_POS: - /* - * Positive Relocation - */ - if (RELOC_RLEN(*rel) != 0x1f) - FatalError("R_POS with size != 32 bits"); - symval = COFFGetSymbolValue(cofffile, rel->r_symndx); - if (symval) { -#ifdef COFFDEBUG - COFFDEBUG("R_POS "); - COFFDEBUG("dest32=%x\t", dest32); - COFFDEBUG("symval=%x\t", symval); - COFFDEBUG("*dest32=%8.8x\t", *dest32); -#endif - *dest32 = (unsigned long)(symval + (*dest32) - symbol->n_value); - ppc_flush_icache(dest32); - } else { - switch (symbol->n_scnum) { - case N_UNDEF: -#ifdef COFFDEBUG - COFFDEBUG("R_POS N_UNDEF\n"); -#endif - return COFFDelayRelocation(cofffile, secndx, rel); - case N_ABS: -#ifdef COFFDEBUG - COFFDEBUG("R_POS N_ABS\n"); -#endif - return 0; - case N_DEBUG: -#ifdef COFFDEBUG - COFFDEBUG("R_POS N_DEBUG\n"); -#endif - return 0; - case N_COMMENT: -#ifdef COFFDEBUG - COFFDEBUG("R_POS N_COMMENT\n"); -#endif - return 0; - case N_TEXT: -#ifdef COFFDEBUG - COFFDEBUG("R_POS N_TEXT\n"); - COFFDEBUG("dest32=%x\t", dest32); - COFFDEBUG("symval=%x\t", symval); - COFFDEBUG("*dest32=%8.8x\t", *dest32); -#endif - *dest32 = (unsigned long)((*dest32) + - ((unsigned long)(cofffile-> - saddr[N_TEXT - - 1])) - - cofffile->txtaddr); - ppc_flush_icache(dest32); - break; - case N_DATA: -#ifdef COFFDEBUG - COFFDEBUG("R_POS N_DATA\n"); - COFFDEBUG("txtsize=%x\t", cofffile->txtsize); - COFFDEBUG("dest32=%x\t", dest32); - COFFDEBUG("symval=%x\t", symval); - COFFDEBUG("*dest32=%8.8x\t", *dest32); -#endif - *dest32 = (unsigned long)((*dest32) + - ((unsigned long)(cofffile-> - saddr[N_DATA - - 1])) - - cofffile->dataddr); - ppc_flush_icache(dest32); - break; - case N_BSS: -#ifdef COFFDEBUG - COFFDEBUG("R_POS N_BSS\n"); - COFFDEBUG("dest32=%x\t", dest32); - COFFDEBUG("symval=%x\t", symval); - COFFDEBUG("*dest32=%8.8x\t", *dest32); -#endif - *dest32 = (unsigned long)((*dest32) + - (unsigned long)(cofffile-> - saddr[N_BSS - 1]) - - (cofffile->bssaddr)); - ppc_flush_icache(dest32); - break; - default: - ErrorF("R_POS with unexpected section %d\n", symbol->n_scnum); - } - } -#ifdef COFFDEBUG - COFFDEBUG("*dest32=%8.8x\t", *dest32); - COFFDEBUG("\n"); -#endif - break; - case R_TOC: - /* - * Relative to TOC - */ - { - dest16 = (unsigned short *)dest32; - if (RELOC_RLEN(*rel) != 0x0f) - FatalError("R_TOC with size != 16 bits"); -#ifdef COFFDEBUG - COFFDEBUG("R_TOC "); - COFFDEBUG("dest16=%x\t", dest16); - COFFDEBUG("symbol=%x\t", symbol); - COFFDEBUG("symbol->n_value=%x\t", symbol->n_value); - COFFDEBUG("cofffile->toc=%x\t", cofffile->toc); - COFFDEBUG("*dest16=%8.8x\t", *dest16); -#endif - *dest16 = (unsigned long)((symbol->n_value - cofffile->toc)); - ppc_flush_icache(dest16); - } -#ifdef COFFDEBUG - COFFDEBUG("*dest16=%8.8x\t", *dest16); - COFFDEBUG("\n"); -#endif - break; - case R_BR: - /* - * Branch relative to self, non-modifiable - */ - - if (RELOC_RLEN(*rel) != 0x19) - FatalError("R_BR with size != 24 bits"); - name = COFFGetSymbolName(cofffile, rel->r_symndx); - symitem = LoaderHashFind(name); - if (symitem == 0) { - name++; - symitem = LoaderHashFind(name); - } - if (symitem && cofffile->module != symitem->module) { -#ifdef COFFDEBUG - COFFDEBUG("Symbol module %d != file module %d\n", - symitem->module, cofffile->module); -#endif - symval = COFFGetSymbolGlinkValue(cofffile, rel->r_symndx); - } else - symval = COFFGetSymbolValue(cofffile, rel->r_symndx); - if (symval == 0) { -#ifdef COFFDEBUG - char *name; - - COFFDEBUG("***Unable to resolve symbol %s\n", - name = COFFGetSymbolName(cofffile, rel->r_symndx)); - xf86loaderfree(name); -#endif - return COFFDelayRelocation(cofffile, secndx, rel); - } -#ifdef COFFDEBUG - COFFDEBUG("R_BR "); - COFFDEBUG("dest32=%x\t", dest32); - COFFDEBUG("symval=%x\t", symval); - COFFDEBUG("*dest32=%8.8x\t", *dest32); -#endif - { - unsigned long val; - - val = ((unsigned long)symval - (unsigned long)dest32); -#ifdef COFFDEBUG - COFFDEBUG("val=%8.8x\n", val); -#endif - val = val >> 2; - if ((val & 0x3f000000) != 0x3f000000 && - (val & 0x3f000000) != 0x00000000) { - FatalError("R_BR offset %x too large\n", val << 2); - break; - } - val &= 0x00ffffff; -#ifdef COFFDEBUG - COFFDEBUG("val=%8.8x\n", val); -#endif - /* - * The address part contains the offset to the beginning - * of the .text section. Disreguard this since we have - * calculated the correct offset already. - */ - (*dest32) = ((*dest32) & 0xfc000003) | (val << 2); -#ifdef COFFDEBUG - COFFDEBUG("*dest32=%8.8x\n", *dest32); -#endif - if (cofffile->module != symitem->module) { - (*++dest32) = 0x80410014; /* lwz r2,20(r1) */ - } - ppc_flush_icache(--dest32); - } - - break; -#endif /* __powerpc__ */ - default: - ErrorF("COFF_RelocateEntry() Unsupported relocation type %o\n", - rel->r_type); - break; - } - return 0; -} - -static COFFRelocPtr -COFFCollectRelocations(COFFModulePtr cofffile) -{ - unsigned short i, j; - RELOC *rel; - SCNHDR *sec; - COFFRelocPtr reloc_head = NULL; - COFFRelocPtr tmp; - - for (i = 0; i < cofffile->numsh; i++) { - if (cofffile->saddr[i] == NULL) - continue; /* Section not loaded!! */ - sec = &(cofffile->sections[i]); - for (j = 0; j < sec->s_nreloc; j++) { - rel = (RELOC *) (cofffile->reladdr[i] + (j * RELSZ)); - tmp = COFFDelayRelocation(cofffile, i, rel); - tmp->next = reloc_head; - reloc_head = tmp; - } - } - - return reloc_head; -} - -/* - * COFF_GetSymbols() - * - * add the symbols to the symbol table maintained by the loader. - */ - -static LOOKUP * -COFF_GetSymbols(COFFModulePtr cofffile) -{ - SYMENT *sym; - AUXENT *aux = NULL; - int i, l, numsyms; - LOOKUP *lookup, *lookup_common, *p; - char *symname; - -/* - * Load the symbols into memory - */ - numsyms = cofffile->header->f_nsyms; - -#ifdef COFFDEBUG - COFFDEBUG("COFF_GetSymbols(): %d symbols\n", numsyms); -#endif - - cofffile->symsize = (numsyms * SYMESZ); - cofffile->symtab = - (SYMENT *) _LoaderFileToMem(cofffile->fd, - cofffile->header->f_symptr, - (numsyms * SYMESZ), "symbols"); - - if ((lookup = xf86loadermalloc((numsyms + 1) * sizeof(LOOKUP))) == NULL) - return NULL; - - for (i = 0, l = 0; i < numsyms; i++) { - sym = (SYMENT *) (((unsigned char *)cofffile->symtab) + (i * SYMESZ)); - symname = COFFGetSymbolName(cofffile, i); - if (sym->n_numaux > 0) - aux = (AUXENT *) (((unsigned char *)cofffile->symtab) + - ((i + 1) * SYMESZ)); - else - aux = NULL; -#ifdef COFFDEBUG - COFFDEBUG("\t%d %d %lx %x %d %d %s\n", - i, sym->n_scnum, sym->n_value, sym->n_type, - sym->n_sclass, sym->n_numaux, symname); - if (aux) - COFFDEBUG("aux=\t%ld %lx %x %x %x %lx %x\n", - aux->x_scnlen, aux->x_parmhash, aux->x_snhash, - aux->x_smtyp, aux->x_smclas, aux->x_stab, - aux->x_snstab); -#endif - i += sym->n_numaux; - /* - * check for TOC csect before discarding C_HIDEXT below - */ - if (aux && aux->x_smclas == XMC_TC0) { - if (sym->n_scnum != N_DATA) - FatalError("TOC not in N_DATA section"); - cofffile->toc = sym->n_value; - cofffile->tocaddr = (cofffile->saddr[sym->n_scnum - 1] + - sym->n_value - (cofffile->dataddr)); -#ifdef COFFDEBUG - COFFDEBUG("TOC=%lx\n", cofffile->toc); - COFFDEBUG("TOCaddr=%p\n", cofffile->tocaddr); -#endif - continue; - } - if (sym->n_sclass == C_HIDEXT) { -/* - && aux && !(aux->x_smclas == XMC_DS - && aux->x_smtyp == XTY_SD) ) ) { -*/ -#ifdef COFFDEBUG - COFFDEBUG("Skipping C_HIDEXT class symbol %s\n", symname); -#endif - continue; - } - switch (sym->n_scnum) { - case N_UNDEF: - if (sym->n_value != 0) { - char *name; - COFFCommonPtr tmp; - - name = COFFGetSymbolName(cofffile, i); -#ifdef COFFDEBUG - COFFDEBUG("Adding COMMON space for %s\n", name); -#endif - if (!LoaderHashFind(name)) { - tmp = COFFAddCOMMON(sym, i); - if (tmp) { - tmp->next = listCOMMON; - listCOMMON = tmp; - } - } - xf86loaderfree(name); - } - xf86loaderfree(symname); - break; - case N_ABS: - case N_DEBUG: - case N_COMMENT: -#ifdef COFFDEBUG - COFFDEBUG("Freeing %s, section %d\n", symname, sym->n_scnum); -#endif - xf86loaderfree(symname); - break; - case N_TEXT: - if ((sym->n_sclass == C_EXT || sym->n_sclass == C_HIDEXT) - && cofffile->saddr[sym->n_scnum - 1]) { - lookup[l].symName = symname; - lookup[l].offset = (funcptr) - (cofffile->saddr[sym->n_scnum - 1] + - sym->n_value - cofffile->txtaddr); -#ifdef COFFDEBUG - COFFDEBUG("Adding %p %s\n", - (void *)lookup[l].offset, lookup[l].symName); -#endif - l++; - } else { -#ifdef COFFDEBUG - COFFDEBUG("TEXT Section not loaded %d\n", sym->n_scnum - 1); -#endif - xf86loaderfree(symname); - } - break; - case N_DATA: - /* - * Note: COFF expects .data to be contiguous with - * .data, so that offsets for .data are relative to - * .text. We need to adjust for this, and make them - * relative to .data so that the relocation can be - * properly applied. This is needed becasue we allocate - * .data seperately from .text. - */ - if ((sym->n_sclass == C_EXT || sym->n_sclass == C_HIDEXT) - && cofffile->saddr[sym->n_scnum - 1]) { - lookup[l].symName = symname; - lookup[l].offset = (funcptr) - (cofffile->saddr[sym->n_scnum - 1] + - sym->n_value - cofffile->dataddr); -#ifdef COFFDEBUG - COFFDEBUG("Adding %p %s\n", - (void *)lookup[l].offset, lookup[l].symName); -#endif - l++; - } else { -#ifdef COFFDEBUG - COFFDEBUG("DATA Section not loaded %d\n", sym->n_scnum - 1); -#endif - xf86loaderfree(symname); - } - break; - case N_BSS: - /* - * Note: COFF expects .bss to be contiguous with - * .data, so that offsets for .bss are relative to - * .text. We need to adjust for this, and make them - * relative to .bss so that the relocation can be - * properly applied. This is needed becasue we allocate - * .bss seperately from .text and .data. - */ - if ((sym->n_sclass == C_EXT || sym->n_sclass == C_HIDEXT) - && cofffile->saddr[sym->n_scnum - 1]) { - lookup[l].symName = symname; - lookup[l].offset = (funcptr) - (cofffile->saddr[sym->n_scnum - 1] + - sym->n_value - cofffile->bssaddr); -#ifdef COFFDEBUG - COFFDEBUG("Adding %p %s\n", - (void *)lookup[l].offset, lookup[l].symName); -#endif - l++; - } else { -#ifdef COFFDEBUG - COFFDEBUG("BSS Section not loaded %d\n", sym->n_scnum - 1); -#endif - xf86loaderfree(symname); - } - break; - default: - ErrorF("Unknown Section number %d\n", sym->n_scnum); - xf86loaderfree(symname); - break; - } - } - - lookup[l].symName = NULL; /* Terminate the list */ - - lookup_common = COFFCreateCOMMON(cofffile); - if (lookup_common) { - for (i = 0, p = lookup_common; p->symName; i++, p++) ; - memcpy(&(lookup[l]), lookup_common, i * sizeof(LOOKUP)); - - xf86loaderfree(lookup_common); - l += i; - lookup[l].symName = NULL; - } - -/* - * remove the COFF symbols that will show up in every module - */ - for (i = 0, p = lookup; p->symName; i++, p++) { - while (p->symName && (!strcmp(lookup[i].symName, ".text") - || !strcmp(lookup[i].symName, ".data") - || !strcmp(lookup[i].symName, ".bss") - )) { - memmove(&(lookup[i]), &(lookup[i + 1]), - (l-- - i) * sizeof(LOOKUP)); - } - } - - return lookup; -} - -#define SecOffset(index) cofffile->sections[index].s_scnptr -#define SecSize(index) cofffile->sections[index].s_size -#define SecAddr(index) cofffile->sections[index].s_paddr -#define RelOffset(index) cofffile->sections[index].s_relptr -#define RelSize(index) (cofffile->sections[index].s_nreloc*RELSZ) - -/* - * COFFCollectSections - * - * Do the work required to load each section into memory. - */ -static void -COFFCollectSections(COFFModulePtr cofffile) -{ - unsigned short i; - -/* - * Find and identify all of the Sections - */ - -#ifdef COFFDEBUG - COFFDEBUG("COFFCollectSections(): %d sections\n", cofffile->numsh); -#endif - - for (i = 0; i < cofffile->numsh; i++) { -#ifdef COFFDEBUG - COFFDEBUG("%d %s\n", i, cofffile->sections[i].s_name); -#endif - /* .text */ - if (strcmp(cofffile->sections[i].s_name, ".text") == 0) { - cofffile->text = _LoaderFileToMem(cofffile->fd, - SecOffset(i), SecSize(i), - ".text"); - cofffile->saddr[i] = cofffile->text; - cofffile->txtndx = i; - cofffile->txtaddr = SecAddr(i); - cofffile->txtsize = SecSize(i); - cofffile->txtrelsize = RelSize(i); - cofffile->reladdr[i] = _LoaderFileToMem(cofffile->fd, - RelOffset(i), RelSize(i), - ".rel.text"); -#ifdef COFFDEBUG - COFFDEBUG(".text starts at %p (%x bytes)\n", cofffile->text, - cofffile->txtsize); -#endif - continue; - } - /* .data */ - if (strcmp(cofffile->sections[i].s_name, ".data") == 0) { - cofffile->data = _LoaderFileToMem(cofffile->fd, - SecOffset(i), SecSize(i), - ".data"); - cofffile->saddr[i] = cofffile->data; - cofffile->datndx = i; - cofffile->dataddr = SecAddr(i); - cofffile->datsize = SecSize(i); - cofffile->datrelsize = RelSize(i); - cofffile->reladdr[i] = _LoaderFileToMem(cofffile->fd, - RelOffset(i), RelSize(i), - ".rel.data"); -#ifdef COFFDEBUG - COFFDEBUG(".data starts at %p (%x bytes)\n", cofffile->data, - cofffile->datsize); -#endif - continue; - } - /* .bss */ - if (strcmp(cofffile->sections[i].s_name, ".bss") == 0) { - if (SecSize(i)) - cofffile->bss = xf86loadercalloc(1, SecSize(i)); - else - cofffile->bss = NULL; - cofffile->saddr[i] = cofffile->bss; - cofffile->bssndx = i; - cofffile->bssaddr = SecAddr(i); - cofffile->bsssize = SecSize(i); -#ifdef COFFDEBUG - COFFDEBUG(".bss starts at %p (%x bytes)\n", cofffile->bss, - cofffile->bsssize); -#endif - continue; - } - /* .comment */ - if (strncmp(cofffile->sections[i].s_name, - ".comment", strlen(".comment")) == 0) { - continue; - } - /* .stab */ - if (strcmp(cofffile->sections[i].s_name, ".stab") == 0) { - continue; - } - /* .stabstr */ - if (strcmp(cofffile->sections[i].s_name, ".stabstr") == 0) { - continue; - } - /* .stab.* */ - if (strncmp(cofffile->sections[i].s_name, - ".stab.", strlen(".stab.")) == 0) { - continue; - } - ErrorF("COFF: Not loading %s\n", cofffile->sections[i].s_name); - } -} - -/* - * Public API for the COFF implementation of the loader. - */ -void * -COFFLoadModule(loaderPtr modrec, int cofffd, LOOKUP **ppLookup, int flags) -{ - COFFModulePtr cofffile; - FILHDR *header; - int stroffset; /* offset of string table */ - COFFRelocPtr coff_reloc, tail; - void *v; - -#ifdef COFFDEBUG - COFFDEBUG("COFFLoadModule(%s,%x,%x)\n", modrec->name, modrec->handle, - cofffd); -#endif - - if ((cofffile = xf86loadercalloc(1, sizeof(COFFModuleRec))) == NULL) { - ErrorF("Unable to allocate COFFModuleRec\n"); - return NULL; - } - - cofffile->handle = modrec->handle; - cofffile->module = modrec->module; - cofffile->fd = cofffd; - v = cofffile->funcs = modrec->funcs; - -/* - * Get the COFF header - */ - cofffile->header = - (FILHDR *) _LoaderFileToMem(cofffd, 0, sizeof(FILHDR), "header"); - header = (FILHDR *) cofffile->header; - - if (header->f_symptr == 0 || header->f_nsyms == 0) { - ErrorF("No symbols found in module\n"); - _LoaderFreeFileMem(header, sizeof(FILHDR)); - xf86loaderfree(cofffile); - return NULL; - } -/* - * Get the section table - */ - cofffile->numsh = header->f_nscns; - cofffile->secsize = (header->f_nscns * SCNHSZ); - cofffile->sections = - (SCNHDR *) _LoaderFileToMem(cofffd, FILHSZ + header->f_opthdr, - cofffile->secsize, "sections"); - cofffile->saddr = - xf86loadercalloc(cofffile->numsh, sizeof(unsigned char *)); - cofffile->reladdr = - xf86loadercalloc(cofffile->numsh, sizeof(unsigned char *)); - -/* - * Load the optional header if we need it ????? - */ - -/* - * Load the rest of the desired sections - */ - COFFCollectSections(cofffile); - -/* - * load the string table (must be done before we process symbols). - */ - stroffset = header->f_symptr + (header->f_nsyms * SYMESZ); - - _LoaderFileRead(cofffd, stroffset, &(cofffile->strsize), sizeof(int)); - - stroffset += 4; /* Move past the size */ - cofffile->strsize -= sizeof(int); /* size includes itself, so reduce by 4 */ - cofffile->strtab = - _LoaderFileToMem(cofffd, stroffset, cofffile->strsize, "strings"); - -/* - * add symbols - */ - *ppLookup = COFF_GetSymbols(cofffile); - -/* - * Do relocations - */ - coff_reloc = COFFCollectRelocations(cofffile); - if (coff_reloc) { - for (tail = coff_reloc; tail->next; tail = tail->next) ; - tail->next = _LoaderGetRelocations(v)->coff_reloc; - _LoaderGetRelocations(v)->coff_reloc = coff_reloc; - } - - return (void *)cofffile; -} - -void -COFFResolveSymbols(void *mod) -{ - COFFRelocPtr 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)->coff_reloc; p;) { - tmp = COFF_RelocateEntry(p->file, p->secndx, p->rel); - if (tmp) { - /* Failed to relocate. Keep it in the list. */ - tmp->next = newlist; - newlist = tmp; - } - tmp = p; - p = p->next; - xf86loaderfree(tmp); - } - _LoaderGetRelocations(mod)->coff_reloc = newlist; -} - -int -COFFCheckForUnresolved(void *mod) -{ - char *name; - COFFRelocPtr crel; - int flag, fatalsym = 0; - - if ((crel = _LoaderGetRelocations(mod)->coff_reloc) == NULL) - return 0; - - while (crel) { - name = COFFGetSymbolName(crel->file, crel->rel->r_symndx); - flag = _LoaderHandleUnresolved(name, - _LoaderHandleToName(crel->file-> - handle)); - if (flag) - fatalsym = 1; - xf86loaderfree(name); - crel = crel->next; - } - return fatalsym; -} - -void -COFFUnloadModule(void *modptr) -{ - COFFModulePtr cofffile = (COFFModulePtr) modptr; - COFFRelocPtr relptr, reltptr, *brelptr; - -/* - * Delete any unresolved relocations - */ - - relptr = _LoaderGetRelocations(cofffile->funcs)->coff_reloc; - brelptr = &(_LoaderGetRelocations(cofffile->funcs)->coff_reloc); - - while (relptr) { - if (relptr->file == cofffile) { - *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 *)cofffile, COFFhashCleanOut); - -/* - * Free the sections that were allocated. - */ -#define CheckandFree(ptr,size) if(ptr) _LoaderFreeFileMem((ptr),(size)) - - CheckandFree(cofffile->strtab, cofffile->strsize); - CheckandFree(cofffile->symtab, cofffile->symsize); - CheckandFree(cofffile->text, cofffile->txtsize); - CheckandFree(cofffile->reladdr[cofffile->txtndx], cofffile->txtrelsize); - CheckandFree(cofffile->data, cofffile->datsize); - CheckandFree(cofffile->reladdr[cofffile->datndx], cofffile->datrelsize); - CheckandFree(cofffile->bss, cofffile->bsssize); - if (cofffile->common) - xf86loaderfree(cofffile->common); -/* - * Free the section table, and section pointer array - */ - _LoaderFreeFileMem(cofffile->sections, cofffile->secsize); - xf86loaderfree(cofffile->saddr); - xf86loaderfree(cofffile->reladdr); - _LoaderFreeFileMem(cofffile->header, sizeof(FILHDR)); -/* - * Free the COFFModuleRec - */ - xf86loaderfree(cofffile); - - return; -} - -char * -COFFAddressToSection(void *modptr, unsigned long address) -{ - COFFModulePtr cofffile = (COFFModulePtr) modptr; - int i; - - for (i = 1; i < cofffile->numsh; i++) { - if (address >= (unsigned long)cofffile->saddr[i] && - address <= (unsigned long)cofffile->saddr[i] + SecSize(i)) { - return cofffile->sections[i].s_name; - } - } - return NULL; -} diff --git a/hw/xfree86/loader/coffloader.h b/hw/xfree86/loader/coffloader.h deleted file mode 100644 index 0dc4720c3..000000000 --- a/hw/xfree86/loader/coffloader.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - * - * Copyright 1997,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. - */ - -/* $XFree86: xc/programs/Xserver/hw/xfree86/loader/coffloader.h,v 1.3 1998/09/20 14:41:04 dawes Exp $ */ - -#ifdef HAVE_XORG_CONFIG_H -#include <xorg-config.h> -#endif - -#ifndef _COFFLOADER_H -#define _COFFLOADER_H -/* coffloader.c */ -extern void *COFFLoadModule(loaderPtr, int, LOOKUP **, int flags); -extern void COFFResolveSymbols(void *); -extern int COFFCheckForUnresolved(void *); -extern char *COFFAddressToSection(void *, unsigned long); -extern void COFFUnloadModule(void *); -#endif /* _COFFLOADER_H */ diff --git a/hw/xfree86/loader/elf.h b/hw/xfree86/loader/elf.h deleted file mode 100644 index c53796cb6..000000000 --- a/hw/xfree86/loader/elf.h +++ /dev/null @@ -1,712 +0,0 @@ -/* $XFree86: xc/programs/Xserver/hw/xfree86/loader/elf.h,v 1.16 2003/06/12 14:12:34 eich Exp $ */ - -typedef unsigned int Elf32_Addr; -typedef unsigned short Elf32_Half; -typedef unsigned int Elf32_Off; -typedef long Elf32_Sword; -typedef unsigned int Elf32_Word; - -typedef unsigned long Elf64_Addr; -typedef unsigned short Elf64_Half; -typedef unsigned long Elf64_Off; -typedef int Elf64_Sword; -typedef unsigned int Elf64_Word; -typedef unsigned long Elf64_Xword; -typedef long Elf64_Sxword; - -/* These constants are for the segment types stored in the image headers */ -#define PT_NULL 0 -#define PT_LOAD 1 -#define PT_DYNAMIC 2 -#define PT_INTERP 3 -#define PT_NOTE 4 -#define PT_SHLIB 5 -#define PT_PHDR 6 -#define PT_LOPROC 0x70000000 -#define PT_HIPROC 0x7fffffff - -/* These constants define the different elf file types */ -#define ET_NONE 0 -#define ET_REL 1 -#define ET_EXEC 2 -#define ET_DYN 3 -#define ET_CORE 4 -#define ET_LOPROC 5 -#define ET_HIPROC 6 - -/* These constants define the various ELF target machines */ -#define EM_NONE 0 -#define EM_M32 1 -#define EM_SPARC 2 -#define EM_386 3 -#define EM_68K 4 -#define EM_88K 5 -#define EM_486 6 /* Perhaps disused */ -#define EM_860 7 -#define EM_MIPS 8 -#define EM_MIPS_RS4_BE 10 -#define EM_PARISC 15 -#define EM_SPARC32PLUS 18 -#define EM_PPC 20 -#define EM_SPARCV9 43 -#define EM_IA_64 50 -#define EM_ALPHA 0x9026 - -/* This is the info that is needed to parse the dynamic section of the file */ -#define DT_NULL 0 -#define DT_NEEDED 1 -#define DT_PLTRELSZ 2 -#define DT_PLTGOT 3 -#define DT_HASH 4 -#define DT_STRTAB 5 -#define DT_SYMTAB 6 -#define DT_RELA 7 -#define DT_RELASZ 8 -#define DT_RELAENT 9 -#define DT_STRSZ 10 -#define DT_SYMENT 11 -#define DT_INIT 12 -#define DT_FINI 13 -#define DT_SONAME 14 -#define DT_RPATH 15 -#define DT_SYMBOLIC 16 -#define DT_REL 17 -#define DT_RELSZ 18 -#define DT_RELENT 19 -#define DT_PLTREL 20 -#define DT_DEBUG 21 -#define DT_TEXTREL 22 -#define DT_JMPREL 23 -#define DT_LOPROC 0x70000000 -#define DT_HIPROC 0x7fffffff - -/* This info is needed when parsing the symbol table */ -#define STB_LOCAL 0 -#define STB_GLOBAL 1 -#define STB_WEAK 2 - -#define STT_NOTYPE 0 -#define STT_OBJECT 1 -#define STT_FUNC 2 -#define STT_SECTION 3 -#define STT_FILE 4 -#define STT_LOPROC 13 -#define STT_HIPROC 15 - -#define ELF32_ST_BIND(x) ((x) >> 4) -#define ELF32_ST_TYPE(x) (((unsigned int) x) & 0xf) - -#define ELF64_ST_BIND(x) ELF32_ST_BIND (x) -#define ELF64_ST_TYPE(x) ELF32_ST_TYPE (x) - -typedef struct dynamic32 { - Elf32_Sword d_tag; - union { - Elf32_Sword d_val; - Elf32_Addr d_ptr; - } d_un; -} Elf32_Dyn; - -typedef struct dynamic64 { - Elf64_Sxword d_tag; - union { - Elf64_Xword d_val; - Elf64_Addr d_ptr; - } d_un; -} Elf64_Dyn; - -#ifdef HAVE_XORG_CONFIG_H -#include <xorg-config.h> -#endif - -#ifndef QNX4 -extern Elf32_Dyn _DYNAMIC[]; -#endif - -/* The following are used with relocations */ -#define ELF32_R_SYM(x) ((x) >> 8) -#define ELF32_R_TYPE(x) ((x) & 0xff) - -#define ELF64_R_SYM(x) ((x) >> 32) -#define ELF64_R_TYPE(x) ((x) & 0xffffffff) - -/* x86 Relocation Types */ -#define R_386_NONE 0 -#define R_386_32 1 -#define R_386_PC32 2 -#define R_386_GOT32 3 -#define R_386_PLT32 4 -#define R_386_COPY 5 -#define R_386_GLOB_DAT 6 -#define R_386_JMP_SLOT 7 -#define R_386_RELATIVE 8 -#define R_386_GOTOFF 9 -#define R_386_GOTPC 10 -#define R_386_NUM 11 - -/* AMD64 Relocation Types */ -#define R_X86_64_NONE 0 -#define R_X86_64_64 1 -#define R_X86_64_PC32 2 -#define R_X86_64_GOT32 3 -#define R_X86_64_PLT32 4 -#define R_X86_64_COPY 5 -#define R_X86_64_GLOB_DAT 6 -#define R_X86_64_JUMP_SLOT 7 -#define R_X86_64_RELATIVE 8 -#define R_X86_64_GOTPCREL 9 -#define R_X86_64_32 10 -#define R_X86_64_32S 11 -#define R_X86_64_16 12 -#define R_X86_64_PC16 13 -#define R_X86_64_8 14 -#define R_X86_64_PC8 15 -#define R_X86_64_GNU_VTINHERIT 250 -#define R_X86_64_GNU_VTENTRY 251 - -/* sparc Relocation Types */ -#define R_SPARC_NONE 0 -#define R_SPARC_8 1 -#define R_SPARC_16 2 -#define R_SPARC_32 3 -#define R_SPARC_DISP8 4 -#define R_SPARC_DISP16 5 -#define R_SPARC_DISP32 6 -#define R_SPARC_WDISP30 7 -#define R_SPARC_WDISP22 8 -#define R_SPARC_HI22 9 -#define R_SPARC_22 10 -#define R_SPARC_13 11 -#define R_SPARC_LO10 12 -#define R_SPARC_GOT10 13 -#define R_SPARC_GOT13 14 -#define R_SPARC_GOT22 15 -#define R_SPARC_PC10 16 -#define R_SPARC_PC22 17 -#define R_SPARC_WPLT30 18 -#define R_SPARC_COPY 19 -#define R_SPARC_GLOB_DAT 20 -#define R_SPARC_JMP_SLOT 21 -#define R_SPARC_RELATIVE 22 -#define R_SPARC_UA32 23 -#define R_SPARC_PLT32 24 -#define R_SPARC_HIPLT22 25 -#define R_SPARC_LOPLT10 26 -#define R_SPARC_PCPLT32 27 -#define R_SPARC_PCPLT22 28 -#define R_SPARC_PCPLT10 29 -#define R_SPARC_10 30 -#define R_SPARC_11 31 -#define R_SPARC_64 32 -#define R_SPARC_OLO10 33 -#define R_SPARC_HH22 34 -#define R_SPARC_HM10 35 -#define R_SPARC_LM22 36 -#define R_SPARC_PC_HH22 37 -#define R_SPARC_PC_HM10 38 -#define R_SPARC_PC_LM22 39 -#define R_SPARC_WDISP16 40 -#define R_SPARC_WDISP19 41 -#define R_SPARC_GLOB_JMP 42 -#define R_SPARC_7 43 -#define R_SPARC_5 44 -#define R_SPARC_6 45 -#define R_SPARC_DISP64 46 -#define R_SPARC_PLT64 47 -#define R_SPARC_HIX22 48 -#define R_SPARC_LOX10 49 -#define R_SPARC_H44 50 -#define R_SPARC_M44 51 -#define R_SPARC_L44 52 -#define R_SPARC_REGISTER 53 -#define R_SPARC_UA64 54 -#define R_SPARC_UA16 55 -#define R_SPARC_NUM 56 - -/* m68k Relocation Types */ -#define R_68K_NONE 0 /* No reloc */ -#define R_68K_32 1 /* Direct 32 bit */ -#define R_68K_16 2 /* Direct 16 bit */ -#define R_68K_8 3 /* Direct 8 bit */ -#define R_68K_PC32 4 /* PC relative 32 bit */ -#define R_68K_PC16 5 /* PC relative 16 bit */ -#define R_68K_PC8 6 /* PC relative 8 bit */ -#define R_68K_GOT32 7 /* 32 bit PC relative GOT entry */ -#define R_68K_GOT16 8 /* 16 bit PC relative GOT entry */ -#define R_68K_GOT8 9 /* 8 bit PC relative GOT entry */ -#define R_68K_GOT32O 10 /* 32 bit GOT offset */ -#define R_68K_GOT16O 11 /* 16 bit GOT offset */ -#define R_68K_GOT8O 12 /* 8 bit GOT offset */ -#define R_68K_PLT32 13 /* 32 bit PC relative PLT address */ -#define R_68K_PLT16 14 /* 16 bit PC relative PLT address */ -#define R_68K_PLT8 15 /* 8 bit PC relative PLT address */ -#define R_68K_PLT32O 16 /* 32 bit PLT offset */ -#define R_68K_PLT16O 17 /* 16 bit PLT offset */ -#define R_68K_PLT8O 18 /* 8 bit PLT offset */ -#define R_68K_COPY 19 /* Copy symbol at runtime */ -#define R_68K_GLOB_DAT 20 /* Create GOT entry */ -#define R_68K_JMP_SLOT 21 /* Create PLT entry */ -#define R_68K_RELATIVE 22 /* Adjust by program base */ - -/* Alpha Relocation Types */ -#define R_ALPHA_NONE 0 /* No reloc */ -#define R_ALPHA_REFLONG 1 /* Direct 32 bit */ -#define R_ALPHA_REFQUAD 2 /* Direct 64 bit */ -#define R_ALPHA_GPREL32 3 /* GP relative 32 bit */ -#define R_ALPHA_LITERAL 4 /* GP relative 16 bit w/optimization */ -#define R_ALPHA_LITUSE 5 /* Optimization hint for LITERAL */ -#define R_ALPHA_GPDISP 6 /* Add displacement to GP */ -#define R_ALPHA_BRADDR 7 /* PC+4 relative 23 bit shifted */ -#define R_ALPHA_HINT 8 /* PC+4 relative 16 bit shifted */ -#define R_ALPHA_SREL16 9 /* PC relative 16 bit */ -#define R_ALPHA_SREL32 10 /* PC relative 32 bit */ -#define R_ALPHA_SREL64 11 /* PC relative 64 bit */ -#define R_ALPHA_OP_PUSH 12 /* OP stack push */ -#define R_ALPHA_OP_STORE 13 /* OP stack pop and store */ -#define R_ALPHA_OP_PSUB 14 /* OP stack subtract */ -#define R_ALPHA_OP_PRSHIFT 15 /* OP stack right shift */ -#define R_ALPHA_GPVALUE 16 -#define R_ALPHA_GPRELHIGH 17 -#define R_ALPHA_GPRELLOW 18 -#define R_ALPHA_GPREL16 19 -#define R_ALPHA_IMMED_GP_HI32 20 -#define R_ALPHA_IMMED_SCN_HI32 21 -#define R_ALPHA_IMMED_BR_HI32 22 -#define R_ALPHA_IMMED_LO32 23 -#define R_ALPHA_COPY 24 /* Copy symbol at runtime */ -#define R_ALPHA_GLOB_DAT 25 /* Create GOT entry */ -#define R_ALPHA_JMP_SLOT 26 /* Create PLT entry */ -#define R_ALPHA_RELATIVE 27 /* Adjust by program base */ -#define R_ALPHA_BRSGP 28 /* Calc displacement for BRS */ - -/* IA-64 relocations. */ -#define R_IA64_NONE 0x00 /* none */ -#define R_IA64_IMM14 0x21 /* symbol + addend, add imm14 */ -#define R_IA64_IMM22 0x22 /* symbol + addend, add imm22 */ -#define R_IA64_IMM64 0x23 /* symbol + addend, mov imm64 */ -#define R_IA64_DIR32MSB 0x24 /* symbol + addend, data4 MSB */ -#define R_IA64_DIR32LSB 0x25 /* symbol + addend, data4 LSB */ -#define R_IA64_DIR64MSB 0x26 /* symbol + addend, data8 MSB */ -#define R_IA64_DIR64LSB 0x27 /* symbol + addend, data8 LSB */ -#define R_IA64_GPREL22 0x2a /* @gprel(sym + add), add imm22 */ -#define R_IA64_GPREL64I 0x2b /* @gprel(sym + add), mov imm64 */ -#define R_IA64_GPREL64MSB 0x2e /* @gprel(sym + add), data8 MSB */ -#define R_IA64_GPREL64LSB 0x2f /* @gprel(sym + add), data8 LSB */ -#define R_IA64_LTOFF22 0x32 /* @ltoff(sym + add), add imm22 */ -#define R_IA64_LTOFF64I 0x33 /* @ltoff(sym + add), mov imm64 */ -#define R_IA64_PLTOFF22 0x3a /* @pltoff(sym + add), add imm22 */ -#define R_IA64_PLTOFF64I 0x3b /* @pltoff(sym + add), mov imm64 */ -#define R_IA64_PLTOFF64MSB 0x3e /* @pltoff(sym + add), data8 MSB */ -#define R_IA64_PLTOFF64LSB 0x3f /* @pltoff(sym + add), data8 LSB */ -#define R_IA64_FPTR64I 0x43 /* @fptr(sym + add), mov imm64 */ -#define R_IA64_FPTR32MSB 0x44 /* @fptr(sym + add), data4 MSB */ -#define R_IA64_FPTR32LSB 0x45 /* @fptr(sym + add), data4 LSB */ -#define R_IA64_FPTR64MSB 0x46 /* @fptr(sym + add), data8 MSB */ -#define R_IA64_FPTR64LSB 0x47 /* @fptr(sym + add), data8 LSB */ -#define R_IA64_PCREL21B 0x49 /* @pcrel(sym + add), ptb, call */ -#define R_IA64_PCREL21M 0x4a /* @pcrel(sym + add), chk.s */ -#define R_IA64_PCREL21F 0x4b /* @pcrel(sym + add), fchkf */ -#define R_IA64_PCREL32MSB 0x4c /* @pcrel(sym + add), data4 MSB */ -#define R_IA64_PCREL32LSB 0x4d /* @pcrel(sym + add), data4 LSB */ -#define R_IA64_PCREL64MSB 0x4e /* @pcrel(sym + add), data8 MSB */ -#define R_IA64_PCREL64LSB 0x4f /* @pcrel(sym + add), data8 LSB */ -#define R_IA64_LTOFF_FPTR22 0x52 /* @ltoff(@fptr(s+a)), imm22 */ -#define R_IA64_LTOFF_FPTR64I 0x53 /* @ltoff(@fptr(s+a)), imm64 */ -#define R_IA64_SEGREL32MSB 0x5c /* @segrel(sym + add), data4 MSB */ -#define R_IA64_SEGREL32LSB 0x5d /* @segrel(sym + add), data4 LSB */ -#define R_IA64_SEGREL64MSB 0x5e /* @segrel(sym + add), data8 MSB */ -#define R_IA64_SEGREL64LSB 0x5f /* @segrel(sym + add), data8 LSB */ -#define R_IA64_SECREL32MSB 0x64 /* @secrel(sym + add), data4 MSB */ -#define R_IA64_SECREL32LSB 0x65 /* @secrel(sym + add), data4 LSB */ -#define R_IA64_SECREL64MSB 0x66 /* @secrel(sym + add), data8 MSB */ -#define R_IA64_SECREL64LSB 0x67 /* @secrel(sym + add), data8 LSB */ -#define R_IA64_REL32MSB 0x6c /* data 4 + REL */ -#define R_IA64_REL32LSB 0x6d /* data 4 + REL */ -#define R_IA64_REL64MSB 0x6e /* data 8 + REL */ -#define R_IA64_REL64LSB 0x6f /* data 8 + REL */ -#define R_IA64_LTV32MSB 0x70 /* symbol + addend, data4 MSB */ -#define R_IA64_LTV32LSB 0x71 /* symbol + addend, data4 LSB */ -#define R_IA64_LTV64MSB 0x72 /* symbol + addend, data8 MSB */ -#define R_IA64_LTV64LSB 0x73 /* symbol + addend, data8 LSB */ -#define R_IA64_IPLTMSB 0x80 /* dynamic reloc, imported PLT, MSB */ -#define R_IA64_IPLTLSB 0x81 /* dynamic reloc, imported PLT, LSB */ -#define R_IA64_LTOFF22X 0x86 /* LTOFF22, relaxable. */ -#define R_IA64_LDXMOV 0x87 /* Use of LTOFF22X. */ - -#define R_IA64_TYPE(R) ((R) & -8) -#define R_IA64_FORMAT(R) ((R) & 7) - -/* - * Apparantly, Linux and PowerMAXOS use different version of ELF as the - * Relocation types are very different. - */ -#if defined(PowerMAX_OS) -/* PPC Relocation Types */ -#define R_PPC_NONE 0 -#define R_PPC_COPY 1 -#define R_PPC_GOTP_ENT 2 -#define R_PPC_8 4 -#define R_PPC_8S 5 -#define R_PPC_16S 7 -#define R_PPC_14 8 -#define R_PPC_DISP14 9 -#define R_PPC_24 10 -#define R_PPC_DISP24 11 -#define R_PPC_PLT_DISP24 14 -#define R_PPC_BBASED_16HU 15 -#define R_PPC_BBASED_32 16 -#define R_PPC_BBASED_32UA 17 -#define R_PPC_BBASED_16H 18 -#define R_PPC_BBASED_16L 19 -#define R_PPC_ABDIFF_16HU 23 -#define R_PPC_ABDIFF_32 24 -#define R_PPC_ABDIFF_32UA 25 -#define R_PPC_ABDIFF_16H 26 -#define R_PPC_ABDIFF_16L 27 -#define R_PPC_ABDIFF_16 28 -#define R_PPC_16HU 31 -#define R_PPC_32 32 -#define R_PPC_32UA 33 -#define R_PPC_16H 34 -#define R_PPC_16L 35 -#define R_PPC_16 36 -#define R_PPC_GOT_16HU 39 -#define R_PPC_GOT_32 40 -#define R_PPC_GOT_32UA 41 -#define R_PPC_GOT_16H 42 -#define R_PPC_GOT_16L 43 -#define R_PPC_GOT_16 44 -#define R_PPC_GOTP_16HU 47 -#define R_PPC_GOTP_32 48 -#define R_PPC_GOTP_32UA 49 -#define R_PPC_GOTP_16H 50 -#define R_PPC_GOTP_16L 51 -#define R_PPC_GOTP_16 52 -#define R_PPC_PLT_16HU 55 -#define R_PPC_PLT_32 56 -#define R_PPC_PLT_32UA 57 -#define R_PPC_PLT_16H 58 -#define R_PPC_PLT_16L 59 -#define R_PPC_PLT_16 60 -#define R_PPC_ABREL_16HU 63 -#define R_PPC_ABREL_32 64 -#define R_PPC_ABREL_32UA 65 -#define R_PPC_ABREL_16H 66 -#define R_PPC_ABREL_16L 67 -#define R_PPC_ABREL_16 68 -#define R_PPC_GOT_ABREL_16HU 71 -#define R_PPC_GOT_ABREL_32 72 -#define R_PPC_GOT_ABREL_32UA 73 -#define R_PPC_GOT_ABREL_16H 74 -#define R_PPC_GOT_ABREL_16L 75 -#define R_PPC_GOT_ABREL_16 76 -#define R_PPC_GOTP_ABREL_16HU 79 -#define R_PPC_GOTP_ABREL_32 80 -#define R_PPC_GOTP_ABREL_32UA 81 -#define R_PPC_GOTP_ABREL_16H 82 -#define R_PPC_GOTP_ABREL_16L 83 -#define R_PPC_GOTP_ABREL_16 84 -#define R_PPC_PLT_ABREL_16HU 87 -#define R_PPC_PLT_ABREL_32 88 -#define R_PPC_PLT_ABREL_32UA 89 -#define R_PPC_PLT_ABREL_16H 90 -#define R_PPC_PLT_ABREL_16L 91 -#define R_PPC_PLT_ABREL_16 92 -#define R_PPC_SREL_16HU 95 -#define R_PPC_SREL_32 96 -#define R_PPC_SREL_32UA 97 -#define R_PPC_SREL_16H 98 -#define R_PPC_SREL_16L 99 -#else -/* - * The Linux version - */ -#define R_PPC_NONE 0 -#define R_PPC_ADDR32 1 -#define R_PPC_ADDR24 2 -#define R_PPC_ADDR16 3 -#define R_PPC_ADDR16_LO 4 -#define R_PPC_ADDR16_HI 5 -#define R_PPC_ADDR16_HA 6 -#define R_PPC_ADDR14 7 -#define R_PPC_ADDR14_BRTAKEN 8 -#define R_PPC_ADDR14_BRNTAKEN 9 -#define R_PPC_REL24 10 -#define R_PPC_REL14 11 -#define R_PPC_REL14_BRTAKEN 12 -#define R_PPC_REL14_BRNTAKEN 13 -#define R_PPC_GOT16 14 -#define R_PPC_GOT16_LO 15 -#define R_PPC_GOT16_HI 16 -#define R_PPC_GOT16_HA 17 -#define R_PPC_PLTREL24 18 -#define R_PPC_COPY 19 -#define R_PPC_GLOB_DAT 20 -#define R_PPC_JMP_SLOT 21 -#define R_PPC_RELATIVE 22 -#define R_PPC_LOCAL24PC 23 -#define R_PPC_UADDR32 24 -#define R_PPC_UADDR16 25 -#define R_PPC_REL32 26 -#define R_PPC_PLT32 27 -#define R_PPC_PLTREL32 28 -#define R_PPC_PLT16_LO 29 -#define R_PPC_PLT16_HI 30 -#define R_PPC_PLT16_HA 31 -#define R_PPC_SDAREL16 32 -#define R_PPC_SECTOFF 33 -#define R_PPC_SECTOFF_LO 34 -#define R_PPC_SECTOFF_HI 35 -#define R_PPC_SECTOFF_HA 36 -#endif - -/* ARM relocs. */ -#define R_ARM_NONE 0 /* No reloc */ -#define R_ARM_PC24 1 /* PC relative 26 bit branch */ -#define R_ARM_ABS32 2 /* Direct 32 bit */ -#define R_ARM_REL32 3 /* PC relative 32 bit */ -#define R_ARM_PC13 4 -#define R_ARM_ABS16 5 /* Direct 16 bit */ -#define R_ARM_ABS12 6 /* Direct 12 bit */ -#define R_ARM_THM_ABS5 7 -#define R_ARM_ABS8 8 /* Direct 8 bit */ -#define R_ARM_SBREL32 9 -#define R_ARM_THM_PC22 10 -#define R_ARM_THM_PC8 11 -#define R_ARM_AMP_VCALL9 12 -#define R_ARM_SWI24 13 -#define R_ARM_THM_SWI8 14 -#define R_ARM_XPC25 15 -#define R_ARM_THM_XPC22 16 -#define R_ARM_COPY 20 /* Copy symbol at runtime */ -#define R_ARM_GLOB_DAT 21 /* Create GOT entry */ -#define R_ARM_JUMP_SLOT 22 /* Create PLT entry */ -#define R_ARM_RELATIVE 23 /* Adjust by program base */ -#define R_ARM_GOTOFF 24 /* 32 bit offset to GOT */ -#define R_ARM_GOTPC 25 /* 32 bit PC relative offset to GOT */ -#define R_ARM_GOT32 26 /* 32 bit GOT entry */ -#define R_ARM_PLT32 27 /* 32 bit PLT address */ -#define R_ARM_GNU_VTENTRY 100 -#define R_ARM_GNU_VTINHERIT 101 -#define R_ARM_THM_PC11 102 /* thumb unconditional branch */ -#define R_ARM_THM_PC9 103 /* thumb conditional branch */ -#define R_ARM_RXPC25 249 -#define R_ARM_RSBREL32 250 -#define R_ARM_THM_RPC22 251 -#define R_ARM_RREL32 252 -#define R_ARM_RABS22 253 -#define R_ARM_RPC24 254 -#define R_ARM_RBASE 255 - -typedef struct elf32_rel { - Elf32_Addr r_offset; - Elf32_Word r_info; -} Elf32_Rel; - -typedef struct elf64_rel { - Elf64_Addr r_offset; - Elf64_Xword r_info; -} Elf64_Rel; - -typedef struct elf32_rela { - Elf32_Addr r_offset; - Elf32_Word r_info; - Elf32_Sword r_addend; -} Elf32_Rela; - -typedef struct elf64_rela { - Elf64_Addr r_offset; - Elf64_Xword r_info; - Elf64_Sxword r_addend; -} Elf64_Rela; - -typedef struct elf32_sym { - Elf32_Word st_name; - Elf32_Addr st_value; - Elf32_Word st_size; - unsigned char st_info; - unsigned char st_other; - Elf32_Half st_shndx; -} Elf32_Sym; - -typedef struct elf64_sym { - Elf64_Word st_name; - unsigned char st_info; - unsigned char st_other; - Elf64_Half st_shndx; - Elf64_Addr st_value; - Elf64_Xword st_size; -} Elf64_Sym; - -#define EI_NIDENT 16 - -typedef struct elf32hdr { - unsigned char e_ident[EI_NIDENT]; - Elf32_Half e_type; - Elf32_Half e_machine; - Elf32_Word e_version; - Elf32_Addr e_entry; /* Entry point */ - Elf32_Off e_phoff; - Elf32_Off e_shoff; - Elf32_Word e_flags; - Elf32_Half e_ehsize; - Elf32_Half e_phentsize; - Elf32_Half e_phnum; - Elf32_Half e_shentsize; - Elf32_Half e_shnum; - Elf32_Half e_shstrndx; -} Elf32_Ehdr; - -typedef struct elf64hdr { - unsigned char e_ident[EI_NIDENT]; - Elf64_Half e_type; - Elf64_Half e_machine; - Elf64_Word e_version; - Elf64_Addr e_entry; - Elf64_Off e_phoff; - Elf64_Off e_shoff; - Elf64_Word e_flags; - Elf64_Half e_ehsize; - Elf64_Half e_phentsize; - Elf64_Half e_phnum; - Elf64_Half e_shentsize; - Elf64_Half e_shnum; - Elf64_Half e_shstrndx; -} Elf64_Ehdr; - -/* These constants define the permissions on sections in the program - header, p_flags. */ -#define PF_R 0x4 -#define PF_W 0x2 -#define PF_X 0x1 - -typedef struct elf_phdr { - Elf32_Word p_type; - Elf32_Off p_offset; - Elf32_Addr p_vaddr; - Elf32_Addr p_paddr; - Elf32_Word p_filesz; - Elf32_Word p_memsz; - Elf32_Word p_flags; - Elf32_Word p_align; -} Elf32_Phdr; - -typedef struct { - Elf64_Word p_type; - Elf64_Word p_flags; - Elf64_Off p_offset; - Elf64_Addr p_vaddr; - Elf64_Addr p_paddr; - Elf64_Xword p_filesz; - Elf64_Xword p_memsz; - Elf64_Xword p_align; -} Elf64_Phdr; - -/* sh_type */ -#define SHT_NULL 0 -#define SHT_PROGBITS 1 -#define SHT_SYMTAB 2 -#define SHT_STRTAB 3 -#define SHT_RELA 4 -#define SHT_HASH 5 -#define SHT_DYNAMIC 6 -#define SHT_NOTE 7 -#define SHT_NOBITS 8 -#define SHT_REL 9 -#define SHT_SHLIB 10 -#define SHT_DYNSYM 11 -#define SHT_NUM 12 -#define SHT_LOPROC 0x70000000 -#define SHT_HIPROC 0x7fffffff -#define SHT_LOUSER 0x80000000 -#define SHT_HIUSER 0xffffffff - -#define SHT_IA_64_UNWIND (SHT_LOPROC + 1) /* unwind bits */ - -/* sh_flags */ -#define SHF_WRITE 0x1 -#define SHF_ALLOC 0x2 -#define SHF_EXECINSTR 0x4 -#define SHF_MASKPROC 0xf0000000 - -/* special section indexes */ -#define SHN_UNDEF 0 -#define SHN_LORESERVE 0xff00 -#define SHN_LOPROC 0xff00 -#define SHN_HIPROC 0xff1f -#define SHN_ABS 0xfff1 -#define SHN_COMMON 0xfff2 -#define SHN_HIRESERVE 0xffff - -typedef struct { - Elf32_Word sh_name; - Elf32_Word sh_type; - Elf32_Word sh_flags; - Elf32_Addr sh_addr; - Elf32_Off sh_offset; - Elf32_Word sh_size; - Elf32_Word sh_link; - Elf32_Word sh_info; - Elf32_Word sh_addralign; - Elf32_Word sh_entsize; -} Elf32_Shdr; - -typedef struct { - Elf64_Word sh_name; - Elf64_Word sh_type; - Elf64_Xword sh_flags; - Elf64_Addr sh_addr; - Elf64_Off sh_offset; - Elf64_Xword sh_size; - Elf64_Word sh_link; - Elf64_Word sh_info; - Elf64_Xword sh_addralign; - Elf64_Xword sh_entsize; -} Elf64_Shdr; - -#define EI_MAG0 0 /* e_ident[] indexes */ -#define EI_MAG1 1 -#define EI_MAG2 2 -#define EI_MAG3 3 -#define EI_CLASS 4 -#define EI_DATA 5 -#define EI_VERSION 6 -#define EI_PAD 7 - -#define ELFMAG0 0x7f /* EI_MAG */ -#define ELFMAG1 'E' -#define ELFMAG2 'L' -#define ELFMAG3 'F' -#define ELFMAG "\177ELF" -#define SELFMAG 4 - -#define ELFDLMAG 3 -#define ELFDLOFF 16 - -#define ELFCLASSNONE 0 /* EI_CLASS */ -#define ELFCLASS32 1 -#define ELFCLASS64 2 -#define ELFCLASSNUM 3 - -#define ELFDATANONE 0 /* e_ident[EI_DATA] */ -#define ELFDATA2LSB 1 -#define ELFDATA2MSB 2 - -#define EV_NONE 0 /* e_version, EI_VERSION */ -#define EV_CURRENT 1 -#define EV_NUM 2 - -/* Notes used in ET_CORE */ -#define NT_PRSTATUS 1 -#define NT_PRFPREG 2 -#define NT_PRPSINFO 3 -#define NT_TASKSTRUCT 4 - -/* Note header in a PT_NOTE section */ -typedef struct elf_note { - Elf32_Word n_namesz; /* Name size */ - Elf32_Word n_descsz; /* Content size */ - Elf32_Word n_type; /* Content type */ -} Elf32_Nhdr; - -#define ELF_START_MMAP 0x80000000 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, §table); - -/* - * 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; -} diff --git a/hw/xfree86/loader/elfloader.h b/hw/xfree86/loader/elfloader.h deleted file mode 100644 index 8cb09eeba..000000000 --- a/hw/xfree86/loader/elfloader.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - * - * Copyright 1997,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. - */ - -/* $XFree86: xc/programs/Xserver/hw/xfree86/loader/elfloader.h,v 1.3 1998/09/20 14:41:05 dawes Exp $ */ - -#ifdef HAVE_XORG_CONFIG_H -#include <xorg-config.h> -#endif - -#ifndef _ELFLOADER_H -#define _ELFLOADER_H -/* elfloader.c */ -extern void *ELFLoadModule(loaderPtr, int, LOOKUP **, int flags); -extern void ELFResolveSymbols(void *); -extern int ELFCheckForUnresolved(void *); -extern char *ELFAddressToSection(void *, unsigned long); -extern void ELFUnloadModule(void *); -#endif /* _ELFLOADER_h */ diff --git a/hw/xfree86/loader/loader.c b/hw/xfree86/loader/loader.c index 4c904128e..f59e1ec4b 100644 --- a/hw/xfree86/loader/loader.c +++ b/hw/xfree86/loader/loader.c @@ -69,9 +69,6 @@ #include <malloc.h> #endif #include <stdarg.h> -#include "ar.h" -#include "elf.h" -#include "coff.h" #include "os.h" #include "sym.h" @@ -259,88 +256,23 @@ static int fatalReqSym = 0; static int _GetModuleType(int, long); static loaderPtr _LoaderListPush(void); static loaderPtr _LoaderListPop(int); - /*ARGSUSED*/ static void -ARCHIVEResolveSymbols(void *unused) -{ -} - /*ARGSUSED*/ static int -ARCHIVECheckForUnresolved(void *v) -{ - return 0; -} /*ARGSUSED*/ static char * ARCHIVEAddressToSection(void *modptr, unsigned long address) { return NULL; } - /*ARGSUSED*/ static void -ARCHIVEUnload(void *unused2) -{ -} /* * Array containing entry points for different formats. */ static loader_funcs funcs[] = { - /* LD_ARCHIVE */ - {ARCHIVELoadModule, - ARCHIVEResolveSymbols, - ARCHIVECheckForUnresolved, - ARCHIVEAddressToSection, - ARCHIVEUnload, {0, 0, 0, 0, 0}}, - /* LD_ELFOBJECT */ - {ELFLoadModule, - ELFResolveSymbols, - ELFCheckForUnresolved, - ELFAddressToSection, - ELFUnloadModule, {0, 0, 0, 0, 0}}, - /* LD_COFFOBJECT */ - {COFFLoadModule, - COFFResolveSymbols, - COFFCheckForUnresolved, - COFFAddressToSection, - COFFUnloadModule, {0, 0, 0, 0, 0}}, - /* LD_XCOFFOBJECT */ - {COFFLoadModule, - COFFResolveSymbols, - COFFCheckForUnresolved, - COFFAddressToSection, - COFFUnloadModule, {0, 0, 0, 0, 0}}, - /* LD_AOUTOBJECT */ - {AOUTLoadModule, - AOUTResolveSymbols, - AOUTCheckForUnresolved, - AOUTAddressToSection, - AOUTUnloadModule, {0, 0, 0, 0, 0}}, - /* LD_AOUTDLOBJECT */ -#ifdef DLOPEN_SUPPORT - {DLLoadModule, - DLResolveSymbols, - DLCheckForUnresolved, - ARCHIVEAddressToSection, - DLUnloadModule, {0, 0, 0, 0, 0}}, -#else - {AOUTLoadModule, - AOUTResolveSymbols, - AOUTCheckForUnresolved, - AOUTAddressToSection, - AOUTUnloadModule, {0, 0, 0, 0, 0}}, -#endif /* LD_ELFDLOBJECT */ -#ifdef DLOPEN_SUPPORT {DLLoadModule, DLResolveSymbols, DLCheckForUnresolved, ARCHIVEAddressToSection, DLUnloadModule, {0, 0, 0, 0, 0}}, -#else - {ELFLoadModule, - ELFResolveSymbols, - ELFCheckForUnresolved, - ELFAddressToSection, - ELFUnloadModule, {0, 0, 0, 0, 0}}, -#endif }; int numloaders = sizeof(funcs) / sizeof(loader_funcs); @@ -434,69 +366,7 @@ LoaderInit(void) static int _GetModuleType(int fd, long offset) { - unsigned char buf[256]; /* long enough for the largest magic type */ - - if (read(fd, buf, sizeof(buf)) < 0) { - return -1; - } -#ifdef DEBUG - ErrorF("Checking module type %10s\n", buf); - ErrorF("Checking module type %x %x %x %x\n", buf[0], buf[1], buf[2], - buf[3]); -#endif - - lseek(fd, offset, SEEK_SET); - - if (strncmp((char *)buf, ARMAG, SARMAG) == 0) { - return LD_ARCHIVE; - } -#if defined(AIAMAG) - /* LynxOS PPC style archives */ - if (strncmp((char *)buf, AIAMAG, SAIAMAG) == 0) { - return LD_ARCHIVE; - } -#endif - - if (strncmp((char *)buf, ELFMAG, SELFMAG) == 0) { - if (*((Elf32_Half *) (buf + ELFDLOFF)) == ELFDLMAG) { - return LD_ELFDLOBJECT; - } else { - return LD_ELFOBJECT; - } - } - - if (buf[0] == 0x4c && buf[1] == 0x01) { - /* I386MAGIC */ - return LD_COFFOBJECT; - } - if (buf[0] == 0x01 && buf[1] == 0xdf) { - /* XCOFFMAGIC */ - return LD_COFFOBJECT; - } - if (buf[0] == 0x0d && buf[1] == 0x01) { - /* ZCOFFMAGIC (LynxOS) */ - return LD_COFFOBJECT; - } - if (buf[0] == 0x00 && buf[1] == 0x86 && buf[2] == 0x01 && buf[3] == 0x07) { - /* AOUTMAGIC */ - return LD_AOUTOBJECT; - } - if (buf[0] == 0x07 && buf[1] == 0x01 - && (buf[2] == 0x64 || buf[2] == 0x86)) { - /* AOUTMAGIC, (Linux OMAGIC, old impure format, also used by OS/2 */ - return LD_AOUTOBJECT; - } - if (buf[0] == 0x07 && buf[1] == 0x01 && buf[2] == 0x00 && buf[3] == 0x00) { - /* AOUTMAGIC, BSDI */ - return LD_AOUTOBJECT; - } - if ((buf[0] == 0xc0 && buf[1] == 0x86) || /* big endian form */ - (buf[3] == 0xc0 && buf[2] == 0x86)) { /* little endian form */ - /* i386 shared object */ - return LD_AOUTDLOBJECT; - } - - return LD_UNKNOWN; + return LD_ELFDLOBJECT; } static int offsetbias = 0; /* offset into archive */ @@ -972,255 +842,6 @@ _LoaderHandleUnresolved(char *symbol, char *module) } /* - * Handle an archive. - */ -void * -ARCHIVELoadModule(loaderPtr modrec, int arfd, LOOKUP ** ppLookup, int flags) -{ - loaderPtr tmp = NULL; - void *ret = NULL; - unsigned char magic[SARMAG]; - struct ar_hdr hdr; - -#if defined(__powerpc__) && defined(Lynx) - struct fl_hdr fhdr; - char name[255]; - int namlen; -#endif - unsigned int size; - unsigned int offset; - int arnamesize, modnamesize; - char *slash, *longname; - char *nametable = NULL; - int nametablelen = 0; - LOOKUP *lookup_ret, *p; - LOOKUP *myLookup = NULL; /* Does realloc behave if ptr == 0? */ - int modtype; - int i; - int numsyms = 0; - - /* lookup_ret = xf86loadermalloc(sizeof (LOOKUP *)); */ - - arnamesize = strlen(modrec->name); - -#if !(defined(__powerpc__) && defined(Lynx)) - read(arfd, magic, SARMAG); - - if (strncmp((const char *)magic, ARMAG, SARMAG) != 0) { - ErrorF("ARCHIVELoadModule: wrong magic!!\n"); - return NULL; - } -#else - read(arfd, &fhdr, FL_HSZ); - - if (strncmp(fhdr.fl_magic, AIAMAG, SAIAMAG) != 0) { - ErrorF("ARCHIVELoadModule: wrong magic!!\n"); - return NULL; - } -#endif /* __powerpc__ && Lynx */ - -#ifdef DEBUGAR - ErrorF("Looking for archive members starting at offset %o\n", offset); -#endif - - while (read(arfd, &hdr, sizeof(struct ar_hdr))) { - - longname = NULL; - sscanf(hdr.ar_size, "%u", &size); -#if defined(__powerpc__) && defined(Lynx) - sscanf(hdr.ar_namlen, "%d", &namlen); - name[0] = hdr.ar_name[0]; - name[1] = hdr.ar_name[1]; - read(arfd, &name[2], namlen); - name[namlen] = '\0'; - offset = lseek(arfd, 0, SEEK_CUR); - if (offset & 0x1) /* odd value */ - offset = lseek(arfd, 1, SEEK_CUR); /* make it an even boundary */ -#endif - offset = lseek(arfd, 0, SEEK_CUR); - - /* Check for a Symbol Table */ - if ((hdr.ar_name[0] == '/' && hdr.ar_name[1] == ' ') || -#if defined(__powerpc__) && defined(Lynx) - namlen == 0 || -#endif - strncmp(hdr.ar_name, "__.SYMDEF", 9) == 0) { - /* If the file name is NULL, then it is a symbol table */ -#ifdef DEBUGAR - ErrorF("Symbol Table Member '%16.16s', size %d, offset %d\n", - hdr.ar_name, size, offset); - ErrorF("Symbol table size %d\n", size); -#endif - offset = lseek(arfd, offset + size, SEEK_SET); - if (offset & 0x1) /* odd value */ - offset = lseek(arfd, 1, SEEK_CUR); /* make it an even boundary */ - continue; - } - - /* Check for a String Table */ - if (hdr.ar_name[0] == '/' && hdr.ar_name[1] == '/') { - /* If the file name is '/', then it is a string table */ -#ifdef DEBUGAR - ErrorF("String Table Member '%16.16s', size %d, offset %d\n", - hdr.ar_name, size, offset); - ErrorF("String table size %d\n", size); -#endif - nametablelen = size; - nametable = (char *)xf86loadermalloc(nametablelen); - read(arfd, nametable, size); - offset = lseek(arfd, 0, SEEK_CUR); - /* offset=lseek(arfd,offset+size,SEEK_SET); */ - if (offset & 0x1) /* odd value */ - offset = lseek(arfd, 1, SEEK_CUR); /* make it an even boundary */ - continue; - } - - if (hdr.ar_name[0] == '/') { - /* SYS V r4 style long member name */ - int nameoffset = atol(&hdr.ar_name[1]); - char *membername; - - if (!nametable) { - ErrorF("Missing string table whilst processing %s\n", - modrec->name); - offsetbias = 0; - return NULL; - } - if (nameoffset > nametablelen) { - ErrorF("Invalid string table offset (%s) whilst processing %s\n", hdr.ar_name, modrec->name); - offsetbias = 0; - xf86loaderfree(nametable); - return NULL; - } - membername = nametable + nameoffset; - slash = strchr(membername, '/'); - if (slash) - *slash = '\0'; - longname = xf86loadermalloc(arnamesize + strlen(membername) + 2); - strcpy(longname, modrec->name); - strcat(longname, ":"); - strcat(longname, membername); - } else if (hdr.ar_name[0] == '#' && hdr.ar_name[1] == '1' && - hdr.ar_name[2] == '/') { - /* BSD 4.4 style long member name */ - if (sscanf(hdr.ar_name + 3, "%d", &modnamesize) != 1) { - ErrorF("Bad archive member %s\n", hdr.ar_name); - offsetbias = 0; - return NULL; - } - /* allocate space for fully qualified name */ - longname = xf86loadermalloc(arnamesize + modnamesize + 2); - strcpy(longname, modrec->name); - strcat(longname, ":"); - i = read(arfd, longname + modnamesize + 1, modnamesize); - if (i != modnamesize) { - ErrorF("Bad archive member %s\n", hdr.ar_name); - xf86loaderfree(longname); - offsetbias = 0; - return NULL; - } - longname[i] = '\0'; - offset += i; - size -= i; - } else { - /* Regular archive member */ -#ifdef DEBUGAR - ErrorF("Member '%16.16s', size %d, offset %x\n", -#if !(defined(__powerpc__) && defined(Lynx)) - hdr.ar_name, -#else - name, -#endif - size, offset); -#endif - - slash = strchr(hdr.ar_name, '/'); - if (slash == NULL) { - /* BSD format without trailing slash */ - slash = strchr(hdr.ar_name, ' '); - } - /* SM: Make sure we do not overwrite other parts of struct */ - - if ((slash - hdr.ar_name) > sizeof(hdr.ar_name)) - slash = hdr.ar_name + sizeof(hdr.ar_name) - 1; - *slash = '\000'; - } - if ((modtype = _GetModuleType(arfd, offset)) < 0) { - ErrorF("%s is an unrecognized module type\n", hdr.ar_name); - offsetbias = 0; - if (nametable) - xf86loaderfree(nametable); - return NULL; - } - - tmp = _LoaderListPush(); - - tmp->handle = modrec->handle; - tmp->module = moduleseq++; - tmp->cname = xf86loadermalloc(strlen(modrec->cname) + 1); - strcpy(tmp->cname, modrec->cname); - tmp->funcs = &funcs[modtype]; - if (longname == NULL) { - modnamesize = strlen(hdr.ar_name); - tmp->name = - (char *)xf86loadermalloc(arnamesize + modnamesize + 2); - strcpy(tmp->name, modrec->name); - strcat(tmp->name, ":"); - strcat(tmp->name, hdr.ar_name); - - } else { - tmp->name = longname; - } - offsetbias = offset; - - if ((tmp->private = funcs[modtype].LoadModule(tmp, arfd, &lookup_ret, LD_FLAG_GLOBAL)) - == NULL) { - ErrorF("Failed to load %s\n", hdr.ar_name); - offsetbias = 0; - if (nametable) - xf86loaderfree(nametable); - return NULL; - } - - offset = lseek(arfd, offset + size, SEEK_SET); - if (offset & 0x1) /* odd value */ - lseek(arfd, 1, SEEK_CUR); /* make it an even boundary */ - - if (tmp->private == (void *)-1L) { - xf86Msg(X_INFO, "Skipping \"%s\": " - "object file contains no symbols\n", - tmp->name); - continue; - } else - ret = tmp->private; - - /* Add the lookup table returned from funcs.LoadModule to the - * one we're going to return. - */ - for (i = 0, p = lookup_ret; p && p->symName; i++, p++) ; - if (i) { - myLookup = xf86loaderrealloc(myLookup, (numsyms + i + 1) - * sizeof(LOOKUP)); - if (!myLookup) - continue; /* Oh well! */ - - memcpy(&(myLookup[numsyms]), lookup_ret, i * sizeof(LOOKUP)); - numsyms += i; - myLookup[numsyms].symName = 0; - } - xf86loaderfree(lookup_ret); - } - /* xf86loaderfree(lookup_ret); */ - offsetbias = 0; - - *ppLookup = myLookup; - if (nametable) - xf86loaderfree(nametable); - - return ret; -} - -/* * Relocation list manipulation routines */ diff --git a/hw/xfree86/loader/loader.h b/hw/xfree86/loader/loader.h index cc8b8f381..da4663995 100644 --- a/hw/xfree86/loader/loader.h +++ b/hw/xfree86/loader/loader.h @@ -70,13 +70,7 @@ /* For LOOKUP definition */ #include "sym.h" #define LD_UNKNOWN -1 -#define LD_ARCHIVE 0 -#define LD_ELFOBJECT 1 -#define LD_COFFOBJECT 2 -#define LD_XCOFFOBJECT 3 -#define LD_AOUTOBJECT 4 -#define LD_AOUTDLOBJECT 5 -#define LD_ELFDLOBJECT 6 +#define LD_ELFDLOBJECT 0 #define LD_PROCESSED_ARCHIVE -1 /* #define UNINIT_SECTION */ #define HANDLE_IN_HASH_ENTRY @@ -85,29 +79,13 @@ * namespace, default is to keep symbols local to module. */ #define LD_FLAG_GLOBAL 1 -/* - * COFF Section nmumbers - */ -#define N_TEXT 1 -#define N_DATA 2 -#define N_BSS 3 -#define N_COMMENT 4 #define TestFree(a) if (a) { xfree (a); a = NULL; } #define HASHDIV 10 #define HASHSIZE (1<<HASHDIV) -typedef struct _elf_reloc *ELFRelocPtr; -typedef struct _elf_COMMON *ELFCommonPtr; -typedef struct _coff_reloc *COFFRelocPtr; -typedef struct _coff_COMMON *COFFCommonPtr; -typedef struct AOUT_RELOC *AOUTRelocPtr; -typedef struct AOUT_COMMON *AOUTCommonPtr; typedef struct _LoaderReloc { int modtype; struct _LoaderReloc *next; - COFFRelocPtr coff_reloc; - ELFRelocPtr elf_reloc; - AOUTRelocPtr aout_reloc; } LoaderRelocRec, *LoaderRelocPtr; typedef struct _loader_item *itemPtr; @@ -126,7 +104,6 @@ typedef struct _loader_item { */ union { unsigned short plt[8]; /* ELF */ - unsigned short glink[14]; /* XCOFF */ } code; #endif } itemRec; @@ -285,12 +262,7 @@ char *_LoaderHandleToCanonicalName(int handle); /* * Entry points for the different loader types */ -#include "aoutloader.h" -#include "coffloader.h" -#include "elfloader.h" #include "dlloader.h" -/* LD_ARCHIVE */ -void *ARCHIVELoadModule(loaderPtr, int, LOOKUP **, int flags); extern void _loader_debug_state(void); |