diff options
Diffstat (limited to 'hw/xfree86/loader')
28 files changed, 12790 insertions, 0 deletions
diff --git a/hw/xfree86/loader/SparcMulDiv.S b/hw/xfree86/loader/SparcMulDiv.S new file mode 100644 index 000000000..e7281593c --- /dev/null +++ b/hw/xfree86/loader/SparcMulDiv.S @@ -0,0 +1,87 @@ +/* + * Hardware integer division and multiplication routines for SPARC v8 and higher. + * + * Copyright (C) 1996 David S. Miller (davem@redhat.com) + * Copyright (C) 1999 Jakub Jelinek (jj@ultra.linux.cz) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * JAKUB JELINEK OR DAVID MILLER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/loader/SparcMulDiv.S,v 1.1 2000/11/02 19:10:54 dawes Exp $ */ + + .globl urem_sparcv89, umul_sparcv89, udiv_sparcv89 + .globl rem_sparcv89, mul_sparcv89, div_sparcv89 + + .align 32 +urem_sparcv89: + wr %g0, 0x0, %y + nop + nop + nop + udiv %o0, %o1, %o2 + umul %o2, %o1, %o2 + retl + sub %o0, %o2, %o0 + + .align 32 +umul_sparcv89: + umul %o0, %o1, %o0 + retl + rd %y, %o1 + + .align 32 +udiv_sparcv89: + wr %g0, 0x0, %y + nop + nop + retl + udiv %o0, %o1, %o0 + + .align 32 +rem_sparcv89: + sra %o0, 0x1f, %o4 + wr %o4, 0x0, %y + nop + nop + nop + sdivcc %o0, %o1, %o2 + bvs,a 1f + xnor %o2, %g0, %o2 +1: smul %o2, %o1, %o2 + retl + sub %o0, %o2, %o0 + + .align 32 +mul_sparcv89: + smul %o0, %o1, %o0 + retl + rd %y, %o1 + nop + + .align 32 +div_sparcv89: + sra %o0, 0x1f, %o2 + wr %o2, 0x0, %y + nop + nop + nop + sdivcc %o0, %o1, %o0 + bvs,a 1f + xnor %o0, %g0, %o0 +1: retl + nop diff --git a/hw/xfree86/loader/aout.h b/hw/xfree86/loader/aout.h new file mode 100644 index 000000000..2e58f2cab --- /dev/null +++ b/hw/xfree86/loader/aout.h @@ -0,0 +1,232 @@ +/* $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. + */ + +#ifndef _AOUT_H +#define _AOUT_H + +#include "Xos.h" + +/* Get prototype for ntohl. */ +#include <ctype.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 new file mode 100644 index 000000000..98e657dca --- /dev/null +++ b/hw/xfree86/loader/aoutloader.c @@ -0,0 +1,858 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/loader/aoutloader.c,v 1.17 2001/11/16 16:47:55 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 + */ +#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 "Xos.h" +#include "os.h" +#include "aout.h" + +#include "sym.h" +#include "loader.h" +#include "aoutloader.h" + +/* +#define AOUTDEBUG ErrorF +*/ + + +#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 %x %s\n", 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 : %08x %s", + 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(" -> %08x\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 %08x\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 %08x\n", symname, 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 %08x\n", symname, 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 %08x\n", symname, lookup[l].offset); +#endif + l++; + } else { + xf86loaderfree(symname); + } + break; + case AOUT_FN: +#ifdef AOUTDEBUG + if (n->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) +{ + 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(mod) +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(mod) +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 new file mode 100644 index 000000000..2714b140f --- /dev/null +++ b/hw/xfree86/loader/aoutloader.h @@ -0,0 +1,31 @@ +/* + * 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 $ */ + +#ifndef _AOUTLOADER_H +#define _AOUTLOADER_H +extern void *AOUTLoadModule(loaderPtr, int, LOOKUP **); +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 new file mode 100644 index 000000000..4dbc97901 --- /dev/null +++ b/hw/xfree86/loader/ar.h @@ -0,0 +1,77 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/loader/ar.h,v 1.3 1998/07/25 16:56:12 dawes Exp $ */ + + +#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], + ar_date[12], + ar_uid[6], + ar_gid[6], + ar_mode[8], + ar_size[10], + 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 new file mode 100644 index 000000000..cebf5e179 --- /dev/null +++ b/hw/xfree86/loader/coff.h @@ -0,0 +1,244 @@ +/* $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. +*/ + +#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 new file mode 100644 index 000000000..7a1ef28ad --- /dev/null +++ b/hw/xfree86/loader/coffloader.c @@ -0,0 +1,1358 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/loader/coffloader.c,v 1.18 2002/09/16 18:06:10 eich 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. + */ +#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 "Xos.h" +#include "os.h" +#include "coff.h" + +#include "sym.h" +#include "loader.h" +#include "coffloader.h" + +#include "compiler.h" +/* +#ifndef LDTEST +#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); +static unsigned char *COFFGetSymbolValue(COFFModulePtr, int); +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(voidptr, item) +void *voidptr; +itemPtr item ; +{ + COFFModulePtr module = (COFFModulePtr) voidptr; + return ( module->handle == item->handle ) ; +} + + +/* + * Manage listResolv + */ +static COFFRelocPtr +COFFDelayRelocation(cofffile,secndx,rel) +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(sym,index) +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(cofffile) +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 %x %s\n", 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(cofffile, index) +COFFModulePtr cofffile; +int index; +{ + char *name; + SYMENT *sym; + + sym=(SYMENT *)(((unsigned char *)cofffile->symtab)+(index*SYMESZ)); + +#ifdef COFFDEBUG + COFFDEBUG("COFFGetSymbolName(%x,%x) %x",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(file, index) +COFFModulePtr file; +int index; +{ + return (SYMENT *)(((unsigned char *)file->symtab)+(index*SYMESZ)); +} + +static unsigned char * +COFFGetSymbolValue(cofffile, index) +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("%x\n", symval ); +#endif + + xf86loaderfree(symname); + return symval; +} + +#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(cofffile, index) +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(cofffile, secndx, rel) +COFFModulePtr cofffile; +int secndx; /* index of the target section */ +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("%x %d %o ", + 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 %x %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=%x\t", dest32 ); + COFFDEBUG( "symval=%x\t", symval ); + COFFDEBUG( "*dest32=%8.8x\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=%x\t", dest32 ); + COFFDEBUG( "symval=%x\t", symval ); + COFFDEBUG( "*dest32=%8.8x\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=%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])); + break; + case N_DATA: +#ifdef COFFDEBUG + COFFDEBUG( "R_DIR32 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); + break; + case N_BSS: +#ifdef COFFDEBUG + COFFDEBUG( "R_DIR32 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)); + break; + default: + ErrorF("R_DIR32 with unexpected section %d\n", + symbol->n_scnum ); + } + + } +#ifdef COFFDEBUG + COFFDEBUG( "*dest32=%8.8x\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=%x\t", dest32 ); + COFFDEBUG( "symval=%x\t", symval ); + COFFDEBUG( "*dest32=%8.8x\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.8x\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(cofffile) +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(cofffile) +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 %x %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%d %x %x %x %x %x %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=%x\n", cofffile->toc ); + COFFDEBUG("TOCaddr=%x\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 %x %s\n", + 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 %x %s\n", + 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 %x %s\n", + 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(cofffile) +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 %x (%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 %x (%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 %x (%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(modrec, cofffd, ppLookup) +loaderPtr modrec; +int cofffd; +LOOKUP **ppLookup; +{ + 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(mod) +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( mod) +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(modptr) +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 new file mode 100644 index 000000000..35ce4b2c5 --- /dev/null +++ b/hw/xfree86/loader/coffloader.h @@ -0,0 +1,34 @@ +/* + * + * 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 $ */ + +#ifndef _COFFLOADER_H +#define _COFFLOADER_H +/* coffloader.c */ +extern void *COFFLoadModule(loaderPtr, int, LOOKUP **); +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/dixsym.c b/hw/xfree86/loader/dixsym.c new file mode 100644 index 000000000..3c1d5b883 --- /dev/null +++ b/hw/xfree86/loader/dixsym.c @@ -0,0 +1,367 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/loader/dixsym.c,v 1.53 2003/01/26 16:40:42 eich 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. + */ + +#undef DBMALLOC +#include "sym.h" +#include "colormap.h" +#include "cursor.h" +#include "dix.h" +#include "dixevents.h" +#include "dixfont.h" +#include "dixstruct.h" +#include "misc.h" +#include "globals.h" +#include "os.h" +#include "osdep.h" +#include "resource.h" +#include "servermd.h" +#include "scrnintstr.h" +#include "windowstr.h" +#include "extension.h" +#define EXTENSION_PROC_ARGS void * +#include "extnsionst.h" +#include "swaprep.h" +#include "swapreq.h" +#include "inputstr.h" +#include "XIproto.h" +#include "exevents.h" +#include "extinit.h" +#ifdef XV +#include "xvmodproc.h" +#endif +#include "dgaproc.h" +#ifdef RENDER +#include "mipict.h" +#endif +#include "selection.h" +#ifdef XKB +#include <X11/extensions/XKBsrv.h> +#endif + +extern Selection *CurrentSelections; +extern int NumCurrentSelections; + +/* DIX things */ + +LOOKUP dixLookupTab[] = { + + /* dix */ + /* atom.c */ + SYMFUNC(MakeAtom) + SYMFUNC(ValidAtom) + /* colormap.c */ + SYMFUNC(AllocColor) + SYMFUNC(CreateColormap) + SYMFUNC(FakeAllocColor) + SYMFUNC(FakeFreeColor) + SYMFUNC(FreeColors) + SYMFUNC(StoreColors) + SYMFUNC(TellLostMap) + SYMFUNC(TellGainedMap) + SYMFUNC(QueryColors) + /* cursor.c */ + SYMFUNC(FreeCursor) + /* devices.c */ + SYMFUNC(Ones) + SYMFUNC(InitButtonClassDeviceStruct) + SYMFUNC(InitFocusClassDeviceStruct) + SYMFUNC(InitLedFeedbackClassDeviceStruct) + SYMFUNC(InitPtrFeedbackClassDeviceStruct) + SYMFUNC(InitValuatorClassDeviceStruct) + SYMFUNC(InitKeyClassDeviceStruct) + SYMFUNC(InitKeyboardDeviceStruct) + SYMFUNC(SendMappingNotify) + /* dispatch.c */ + SYMFUNC(SetInputCheck) + SYMFUNC(SendErrorToClient) + SYMFUNC(UpdateCurrentTime) + SYMFUNC(UpdateCurrentTimeIf) + SYMFUNC(ProcBadRequest) + SYMVAR(dispatchException) + SYMVAR(isItTimeToYield) + SYMVAR(ClientStateCallback) + SYMVAR(ServerGrabCallback) + SYMVAR(CurrentSelections) + SYMVAR(NumCurrentSelections) + /* dixfonts.c */ + SYMFUNC(CloseFont) + SYMFUNC(FontToXError) + SYMFUNC(LoadGlyphs) + SYMVAR(fpe_functions) + /* dixutils.c */ + SYMFUNC(AddCallback) + SYMFUNC(ClientSleep) + SYMFUNC(ClientTimeToServerTime) + SYMFUNC(ClientWakeup) + SYMFUNC(CompareTimeStamps) + SYMFUNC(CopyISOLatin1Lowered) + SYMFUNC(DeleteCallback) + SYMFUNC(LookupClient) + SYMFUNC(LookupDrawable) + SYMFUNC(LookupWindow) + SYMFUNC(NoopDDA) + SYMFUNC(QueueWorkProc) + SYMFUNC(RegisterBlockAndWakeupHandlers) + SYMFUNC(RemoveBlockAndWakeupHandlers) +#ifdef XCSECURITY + SYMFUNC(SecurityLookupDrawable) + SYMFUNC(SecurityLookupWindow) +#endif + /* events.c */ + SYMFUNC(CheckCursorConfinement) + SYMFUNC(DeliverEvents) + SYMFUNC(NewCurrentScreen) + SYMFUNC(PointerConfinedToScreen) + SYMFUNC(TryClientEvents) + SYMFUNC(WriteEventsToClient) + SYMVAR(DeviceEventCallback) + SYMVAR(EventCallback) + SYMVAR(inputInfo) + SYMVAR(SetCriticalEvent) +#ifdef PANORAMIX + SYMVAR(XineramaGetCursorScreen) +#endif + /* property.c */ + SYMFUNC(ChangeWindowProperty) + /* extension.c */ + SYMFUNC(AddExtension) + SYMFUNC(AddExtensionAlias) + SYMFUNC(CheckExtension) + SYMFUNC(DeclareExtensionSecurity) + SYMFUNC(MinorOpcodeOfRequest) + SYMFUNC(StandardMinorOpcode) + /* gc.c */ + SYMFUNC(CopyGC) + SYMFUNC(CreateGC) + SYMFUNC(CreateScratchGC) + SYMFUNC(ChangeGC) + SYMFUNC(dixChangeGC) + SYMFUNC(DoChangeGC) + SYMFUNC(FreeGC) + SYMFUNC(FreeScratchGC) + SYMFUNC(GetScratchGC) + SYMFUNC(SetClipRects) + SYMFUNC(ValidateGC) + SYMFUNC(VerifyRectOrder) + SYMFUNC(SetDashes) + /* globals.c */ + SYMVAR(DPMSEnabled) + SYMVAR(DPMSCapableFlag) + SYMVAR(DPMSOffTime) + SYMVAR(DPMSPowerLevel) + SYMVAR(DPMSStandbyTime) + SYMVAR(DPMSSuspendTime) + SYMVAR(DPMSEnabledSwitch) + SYMVAR(DPMSDisabledSwitch) + SYMVAR(defaultDPMSEnabled) +#ifdef XV + /* XXX These are exported from the DDX, not DIX. */ + SYMVAR(XvScreenInitProc) + SYMVAR(XvGetScreenIndexProc) + SYMVAR(XvGetRTPortProc) + SYMVAR(XvMCScreenInitProc) +#endif + SYMVAR(ScreenSaverBlanking) + SYMVAR(WindowTable) + SYMVAR(clients) + SYMVAR(currentMaxClients) + SYMVAR(currentTime) + SYMVAR(defaultColorVisualClass) + SYMVAR(globalSerialNumber) + SYMVAR(lastDeviceEventTime) + SYMVAR(monitorResolution) + SYMVAR(permitOldBugs) + SYMVAR(screenInfo) + SYMVAR(serverClient) + SYMVAR(serverGeneration) + /* main.c */ + SYMFUNC(NotImplemented) + /* pixmap.c */ + SYMFUNC(AllocatePixmap) + SYMFUNC(GetScratchPixmapHeader) + SYMFUNC(FreeScratchPixmapHeader) + SYMVAR(PixmapWidthPaddingInfo) + /* privates.c */ + SYMFUNC(AllocateClientPrivate) + SYMFUNC(AllocateClientPrivateIndex) + SYMFUNC(AllocateGCPrivate) + SYMFUNC(AllocateGCPrivateIndex) + SYMFUNC(AllocateWindowPrivate) + SYMFUNC(AllocateWindowPrivateIndex) + SYMFUNC(AllocateScreenPrivateIndex) + SYMFUNC(AllocateColormapPrivateIndex) + /* resource.c */ + SYMFUNC(AddResource) + SYMFUNC(ChangeResourceValue) + SYMFUNC(CreateNewResourceClass) + SYMFUNC(CreateNewResourceType) + SYMFUNC(FakeClientID) + SYMFUNC(FreeResource) + SYMFUNC(FreeResourceByType) + SYMFUNC(GetXIDList) + SYMFUNC(GetXIDRange) + SYMFUNC(LookupIDByType) + SYMFUNC(LookupIDByClass) + SYMFUNC(LegalNewID) +#ifdef XCSECURITY + SYMFUNC(SecurityLookupIDByClass) + SYMFUNC(SecurityLookupIDByType) +#endif + SYMFUNC(FindClientResourcesByType) + SYMFUNC(FindAllClientResources) + SYMVAR(lastResourceType) + SYMVAR(TypeMask) +#ifdef RES + SYMFUNC(RegisterResourceName) + SYMVAR(ResourceNames) +#endif + /* swaprep.c */ + SYMFUNC(CopySwap32Write) + SYMFUNC(Swap32Write) + SYMFUNC(SwapConnSetupInfo) + SYMFUNC(SwapConnSetupPrefix) + SYMFUNC(SwapShorts) + SYMFUNC(SwapLongs) + /* swapreq.c */ + SYMFUNC(SwapColorItem) + /* tables.c */ + SYMVAR(EventSwapVector) + SYMVAR(ReplySwapVector) + SYMVAR(ProcVector) + /* window.c */ + SYMFUNC(ChangeWindowAttributes) + SYMFUNC(CheckWindowOptionalNeed) + SYMFUNC(CreateUnclippedWinSize) + SYMFUNC(CreateWindow) + SYMFUNC(FindWindowWithOptional) + SYMFUNC(GravityTranslate) + SYMFUNC(MakeWindowOptional) + SYMFUNC(MapWindow) + SYMFUNC(MoveWindowInStack) + SYMFUNC(NotClippedByChildren) + SYMFUNC(ResizeChildrenWinSize) + SYMFUNC(SaveScreens) + SYMFUNC(SendVisibilityNotify) + SYMFUNC(SetWinSize) + SYMFUNC(SetBorderSize) + SYMFUNC(TraverseTree) + SYMFUNC(UnmapWindow) + SYMFUNC(WalkTree) + SYMFUNC(WindowsRestructured) + SYMVAR(deltaSaveUndersViewable) + SYMVAR(numSaveUndersViewable) + SYMVAR(savedScreenInfo) + SYMVAR(screenIsSaved) + + /*os/ */ + /* access.c */ + SYMFUNC(LocalClient) + /* util.c */ + SYMFUNC(Error) + SYMFUNC(VErrorF) + SYMFUNC(ErrorF) + SYMFUNC(FatalError) + SYMFUNC(Xstrdup) + SYMFUNC(XNFstrdup) + SYMVAR(Must_have_memory) + /* xalloc.c */ + SYMFUNC(XNFalloc) + SYMFUNC(XNFcalloc) + SYMFUNC(XNFrealloc) + SYMFUNC(Xalloc) + SYMFUNC(Xcalloc) + SYMFUNC(Xfree) + SYMFUNC(Xrealloc) + /* WaitFor.c */ + SYMFUNC(ScreenSaverTime) + SYMFUNC(TimerFree) + SYMFUNC(TimerSet) + SYMFUNC(TimerCancel) + /* io.c */ + SYMFUNC(WriteToClient) + SYMFUNC(SetCriticalOutputPending) + SYMVAR(FlushCallback) + SYMVAR(ReplyCallback) + SYMVAR(SkippedRequestsCallback) + SYMFUNC(ResetCurrentRequest) + /* connection.c */ + SYMFUNC(IgnoreClient) + SYMFUNC(AttendClient) + SYMFUNC(AddEnabledDevice) + SYMFUNC(RemoveEnabledDevice) + SYMFUNC(MakeClientGrabPervious) + SYMFUNC(MakeClientGrabImpervious) + SYMVAR(GrabInProgress) + /* utils.c */ + SYMFUNC(AdjustWaitForDelay) + SYMVAR(noTestExtensions) + + /* devices.c */ + SYMFUNC(InitPointerDeviceStruct) + SYMFUNC(LookupKeyboardDevice) + SYMFUNC(LookupPointerDevice) + +#ifdef XKB + /* xkb/xkbInit.c */ + SYMFUNC(XkbInitKeyboardDeviceStruct) + SYMFUNC(XkbSetRulesDflts) + SYMVAR(noXkbExtension) +#endif + +#ifdef XINPUT + /* Xi */ + /* exevents.c */ + SYMFUNC(InitValuatorAxisStruct) + SYMFUNC(InitProximityClassDeviceStruct) + /* extinit.c */ + SYMFUNC(AssignTypeAndName) +#endif + + /* xf86DGA.c */ + /* XXX This is exported from the DDX, not DIX. */ + SYMVAR(XDGAEventBase) + + /* librender.a */ +#ifdef RENDER + SYMFUNC(PictureInit) + SYMFUNC(miPictureInit) + SYMFUNC(miComputeCompositeRegion) + SYMFUNC(miGlyphs) + SYMFUNC(miCompositeRects) + SYMVAR(PictureScreenPrivateIndex) + SYMFUNC(PictureTransformPoint) + SYMFUNC(PictureAddFilter) + SYMFUNC(PictureSetFilterAlias) + SYMFUNC(PictureGetSubpixelOrder) + SYMFUNC(PictureSetSubpixelOrder) +#endif + + /* os/utils.c */ + SYMFUNC(GiveUp) + + { 0, 0 }, + +}; diff --git a/hw/xfree86/loader/dlloader.c b/hw/xfree86/loader/dlloader.c new file mode 100644 index 000000000..bf4c8c078 --- /dev/null +++ b/hw/xfree86/loader/dlloader.c @@ -0,0 +1,191 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/loader/dlloader.c,v 1.11 2000/08/23 22:10:14 tsi Exp $ */ + + +/* + * + * Copyright (c) 1997 The XFree86 Project, 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 the + * XFree86 Project, Inc. not be used in advertising or publicity + * pertaining to distribution of the software without specific, + * written prior permission. The Xfree86 Project, Inc. makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied + * warranty. + * + * THE XFREE86 PROJECT, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL THE XFREE86 PROJECT, 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. */ + +#include <stdio.h> +#include <stdlib.h> +#include <dlfcn.h> + +#include "Xos.h" +#include "os.h" + +#include "sym.h" +#include "loader.h" +#include "dlloader.h" + +#ifdef DL_LAZY +#define DLOPEN_LAZY DL_LAZY +#else +#ifdef RTLD_LAZY +#define DLOPEN_LAZY RTLD_LAZY +#else +#ifdef __FreeBSD__ +#define DLOPEN_LAZY 1 +#else +#define DLOPEN_LAZY 0 +#endif +#endif +#endif +#ifdef LD_GLOBAL +#define DLOPEN_GLOBAL LD_GLOBAL +#else +#ifdef RTLD_GLOBAL +#define DLOPEN_GLOBAL RTLD_GLOBAL +#else +#define DLOPEN_GLOBAL 0 +#endif +#endif + +#define DLOPEN_FLAGS ( DLOPEN_LAZY | DLOPEN_GLOBAL ) + +#if defined(CSRG_BASED) && !defined(__ELF__) +#define NEED_UNDERSCORE_FOR_DLLSYM +#endif + +/* + * This structure contains all of the information about a module + * that has been loaded. + */ +typedef struct { + int handle; + void *dlhandle; +} DLModuleRec, *DLModulePtr; + +/* + * a list of loaded modules XXX can be improved + */ +typedef struct DLModuleList { + DLModulePtr module; + struct DLModuleList *next; +} DLModuleList; + +DLModuleList *dlModuleList = NULL; + +/* + * Search a symbol in the module list + */ +void * +DLFindSymbol(const char *name) +{ + DLModuleList *l; + void *p; + +#ifdef NEED_UNDERSCORE_FOR_DLLSYM + char *n; + + n = xf86loadermalloc(strlen(name) + 2); + sprintf(n, "_%s", name); +#endif + + (void)dlerror(); /* Clear out any previous error */ + for (l = dlModuleList; l != NULL; l = l->next) { +#ifdef NEED_UNDERSCORE_FOR_DLLSYM + p = dlsym(l->module->dlhandle, n); +#else + p = dlsym(l->module->dlhandle, name); +#endif + if (dlerror() == NULL) { +#ifdef NEED_UNDERSCORE_FOR_DLLSYM + xf86loaderfree(n); +#endif + return p; + } + } +#ifdef NEED_UNDERSCORE_FOR_DLLSYM + xf86loaderfree(n); +#endif + + return NULL; +} + +/* + * public interface + */ +void * +DLLoadModule(loaderPtr modrec, int fd, LOOKUP **ppLookup) +{ + DLModulePtr dlfile; + DLModuleList *l; + + if ((dlfile=xf86loadercalloc(1,sizeof(DLModuleRec)))==NULL) { + ErrorF("Unable to allocate DLModuleRec\n"); + return NULL; + } + dlfile->handle = modrec->handle; + dlfile->dlhandle = dlopen(modrec->name, DLOPEN_FLAGS); + if (dlfile->dlhandle == NULL) { + ErrorF("dlopen: %s\n", dlerror()); + xf86loaderfree(dlfile); + return NULL; + } + /* Add it to the module list */ + l = xf86loadermalloc(sizeof(DLModuleList)); + l->module = dlfile; + l->next = dlModuleList; + dlModuleList = l; + *ppLookup = NULL; + + return (void *)dlfile; +} + +void +DLResolveSymbols(void *mod) +{ + return; +} + +int +DLCheckForUnresolved(void *mod) +{ + return 0; +} + +void +DLUnloadModule(void *modptr) +{ + DLModulePtr dlfile = (DLModulePtr)modptr; + DLModuleList *l, *p; + + /* remove it from dlModuleList */ + if (dlModuleList->module == modptr) { + l = dlModuleList; + dlModuleList = l->next; + xf86loaderfree(l); + } else { + p = dlModuleList; + for (l = dlModuleList->next; l != NULL; l = l->next) { + if (l->module == modptr) { + p->next = l->next; + xf86loaderfree(l); + break; + } + p = l; + } + } + dlclose(dlfile->dlhandle); + xf86loaderfree(modptr); +} diff --git a/hw/xfree86/loader/dlloader.h b/hw/xfree86/loader/dlloader.h new file mode 100644 index 000000000..e9468e97b --- /dev/null +++ b/hw/xfree86/loader/dlloader.h @@ -0,0 +1,32 @@ +/* + * Copyright 1997 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/dlloader.h,v 1.3 1998/09/20 14:41:04 dawes Exp $ */ + +#ifndef _DLLOADER_H +#define _DLLOADER_H +extern void *DLLoadModule(loaderPtr, int, LOOKUP **); +extern void DLResolveSymbols(void *); +extern int DLCheckForUnresolved(void *); +extern void DLUnloadModule(void *); +extern void *DLFindSymbol(const char *name); + +#endif diff --git a/hw/xfree86/loader/elf.h b/hw/xfree86/loader/elf.h new file mode 100644 index 000000000..ad072c199 --- /dev/null +++ b/hw/xfree86/loader/elf.h @@ -0,0 +1,710 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/loader/elf.h,v 1.15 2002/10/30 17:50:19 alanh 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; + +#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 + +/* x86_64 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 */ + +/* 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 new file mode 100644 index 000000000..822a50efa --- /dev/null +++ b/hw/xfree86/loader/elfloader.c @@ -0,0 +1,3024 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/loader/elfloader.c,v 1.49 2003/01/24 17:26:35 tsi 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. + */ +#include <sys/types.h> +#include <sys/mman.h> +#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 "Xos.h" +#include "os.h" +#include "elf.h" + +#include "sym.h" +#include "loader.h" + +#include "compiler.h" + +#undef LDTEST + +/* +#ifndef LDTEST +# define ELFDEBUG ErrorF +#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 (__x86_64__) +# define MMAP_FLAGS (MAP_PRIVATE | MAP_ANON) +# else +# define MMAP_FLAGS (MAP_PRIVATE | MAP_ANON | MAP_32BIT) +# endif +# if defined (MmapPageAlign) +# define MMAP_ALIGN(size) do { \ + int pagesize = getpagesize(); \ + size = ( size + pagesize - 1) / pagesize; \ + size *= pagesize; \ + } while (0); +# else +# define MMAP_ALIGN(size) +# endif +#endif + +#if defined (__alpha__) || \ + defined (__ia64__) || \ + defined (__x86_64__) || \ + (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(__x86_64__) +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 +}; +static void IA64InstallReloc(unsigned long *, int, enum ia64_operand, long); +#endif /*__ia64__*/ + +#ifdef MergeSectionAlloc +static void * +ELFLoaderSectToMem(elffile, align, offset, size, label) +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(elffile, align, size) +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(voidptr, item) +void *voidptr; +itemPtr item ; +{ + ELFModulePtr module = (ELFModulePtr) voidptr; + return (module->handle == item->handle); +} + +/* + * Manage listResolv + */ +static ELFRelocPtr +ElfDelayRelocation(elffile, secn, rel) +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 %lx: file %lx, sec %d," + " r_offset 0x%lx, r_info 0x%x", + reloc, elffile, secn, rel->r_offset, rel->r_info); +# if defined(__powerpc__) || \ + defined(__mc68000__) || \ + defined(__alpha__) || \ + defined(__sparc__) || \ + defined(__ia64__) || \ + defined(__x86_64__) + ELFDEBUG(", r_addend 0x%lx", rel->r_addend); +# endif + ELFDEBUG("\n"); +#endif + return reloc; +} + +/* + * Manage listCOMMON + */ +static ELFCommonPtr +ElfAddCOMMON(sym) +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(__x86_64__) || \ + (defined(__sparc__) && \ + (defined(__arch64__) || \ + defined(__sparcv9))) + size = (size+7)&~0x7; +#endif + } + return size; +} + +static int +ElfCreateCOMMON(elffile,pLookup) +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(__x86_64__) || \ + (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 %lx %s\n", + 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(__x86_64__) || \ + (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(file, offset, index) +ELFModulePtr file; +int offset; +int index; +{ + if( !offset || !index ) + return ""; + + return (char *)(file->saddr[index]+offset); +} + +static char * +ElfGetString(file, offset) +ELFModulePtr file; +int offset; +{ + return ElfGetStringIndex( file, offset, file->strndx ); +} + +static char * +ElfGetSectionName(file, offset) +ELFModulePtr file; +int offset; +{ + return (char *)(file->shstraddr+offset); +} + + + +/* + * Symbol Table + */ + +/* + * Get symbol name + */ +static char * +ElfGetSymbolNameIndex(elffile, index, secndx) +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",syms[index].st_value); +#endif + + return ElfGetString(elffile,syms[index].st_name ); +} + +static char * +ElfGetSymbolName(elffile, index) +ELFModulePtr elffile; +int index; +{ + return ElfGetSymbolNameIndex(elffile, index, elffile->symndx); +} + +static Elf_Addr +ElfGetSymbolValue(elffile, index) +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( "%lx\t", symbol ); + ELFDEBUG( "%lx\t", 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", 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(elffile, index) +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(elffile,rel) +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(elffile, maxalign) +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(__ia64__) || defined(__OpenBSD__) + { + 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(elffile,index,l) +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(elffile) +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(elffile,rel) +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(elffile) +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; + } + elffile->sections[elffile->pltndx].sh_size=elffile->pltsize; +# ifdef ELFDEBUG + ELFDEBUG( "ELFCreatePLT: PLT address %lx\n", elffile->plt ); +# endif + + return; +} + +static void +IA64InstallReloc(data128, slot, opnd, value) +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; + 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(elffile, secn, rel, force) +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 */ +#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(__x86_64__) + 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", 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(__x86_64__) + 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=%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_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=%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; +#endif /* i386 */ +#if defined(__x86_64__) + 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_x86_64_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 /* __x86_64__ */ +#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; + } + +#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_GLOB_DAT: /* 20 */ + 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_DISP8: /* 4 */ + dest8 = (unsigned char *)(secp + rel->r_offset); + symval += rel->r_addend; + *dest8 = (symval - (Elf32_Addr) dest8); + break; + + case R_SPARC_DISP16: /* 5 */ + dest16 = (unsigned short *)(secp + rel->r_offset); + symval += rel->r_addend; + *dest16 = (symval - (Elf32_Addr) dest16); + break; + + case R_SPARC_DISP32: /* 6 */ + dest32 = (unsigned int *)(secp + rel->r_offset); + symval += rel->r_addend; + *dest32 = (symval - (Elf32_Addr) dest32); + break; + + case R_SPARC_WDISP30: /* 7 */ + dest32 = (unsigned int *)(secp + rel->r_offset); + symval += rel->r_addend; + *dest32 = ((*dest32 & 0xc0000000) | + ((symval - (Elf32_Addr) dest32) >> 2)); + 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 */ + dest32 = (unsigned int *)(secp + rel->r_offset); + *dest32 += (unsigned int)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: + { + 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; + +#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", + 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]; + Elf_Sym *syms; + ELFRelocPtr reloc_head = NULL; + ELFRelocPtr tmp; + + syms = (Elf_Sym *) elffile->saddr[elffile->symndx]; + + 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_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) { + 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(elffile, psecttable) +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", + syms[i].st_value,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", + 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)); + } + } + 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(elffile,pass,totalsize,maxalign) +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; + 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 %lx size: %lx\n", + name, elffile->saddr[i], 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)) { +#ifdef __OpenBSD__ + case SHT_PROGBITS: + mprotect(elffile->lsection[j].saddr, SecSize(i), + PROT_READ|PROT_WRITE|PROT_EXEC); + break; +#endif + case SHT_SYMTAB: + elffile->symtab = (Elf_Sym *)elffile->saddr[i]; + elffile->symndx = i; + 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(modrec, elffd, ppLookup) +loaderPtr modrec; +int elffd; +LOOKUP **ppLookup; +{ + 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(__ia64__) || defined(__OpenBSD__) + { + 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 %lx %s\n", + 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(mod) +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 + ErrorF("ResolveSymbols: file %lx, sec %d, r_offset 0x%x, r_info 0x%lx\n", + p->file, p->secn, p->rel->r_offset, 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(mod) +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(modptr) +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 new file mode 100644 index 000000000..cbd5f118a --- /dev/null +++ b/hw/xfree86/loader/elfloader.h @@ -0,0 +1,34 @@ +/* + * + * 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 $ */ + +#ifndef _ELFLOADER_H +#define _ELFLOADER_H +/* elfloader.c */ +extern void *ELFLoadModule(loaderPtr, int, LOOKUP **); +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/extsym.c b/hw/xfree86/loader/extsym.c new file mode 100644 index 000000000..62a5ea98a --- /dev/null +++ b/hw/xfree86/loader/extsym.c @@ -0,0 +1,79 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/loader/extsym.c,v 1.6 2001/11/17 16:05:59 dawes Exp $ */ + +/* + * + * Copyright 1999 by The XFree86 Project, 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 The XFree86 Project, Inc. not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. The XFree86 Project, Inc. makes no + * representations about the suitability of this software for any purpose. + * It is provided "as is" without express or implied warranty. + * + * THE XFREE86 PROJECT, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL THE XFREE86 PROJECT, 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. + */ + +#include "resource.h" +#include "sym.h" +#include "misc.h" +#ifdef PANORAMIX +#include "panoramiX.h" +#endif +#include "sleepuntil.h" + +#ifdef HAS_SHM +extern int ShmCompletionCode; +extern int BadShmSegCode; +extern RESTYPE ShmSegType, ShmPixType; +#endif + +#ifdef PANORAMIX +extern Bool noPanoramiXExtension; +extern int PanoramiXNumScreens; +extern PanoramiXData *panoramiXdataPtr; +extern unsigned long XRT_WINDOW; +extern unsigned long XRT_PIXMAP; +extern unsigned long XRT_GC; +extern unsigned long XRT_COLORMAP; +extern unsigned long XRC_DRAWABLE; +extern Bool XineramaRegisterConnectionBlockCallback(void (*func)(void)); +extern int XineramaDeleteResource(pointer, XID); +#endif + +LOOKUP extLookupTab[] = { + + SYMFUNC(ClientSleepUntil) + +#ifdef HAS_SHM + SYMVAR(ShmCompletionCode) + SYMVAR(BadShmSegCode) + SYMVAR(ShmSegType) +#endif + +#ifdef PANORAMIX + SYMFUNC(XineramaRegisterConnectionBlockCallback) + SYMFUNC(XineramaDeleteResource) + SYMVAR(noPanoramiXExtension) + SYMVAR(PanoramiXNumScreens) + SYMVAR(panoramiXdataPtr) + SYMVAR(XRT_WINDOW) + SYMVAR(XRT_PIXMAP) + SYMVAR(XRT_GC) + SYMVAR(XRT_COLORMAP) + SYMVAR(XRC_DRAWABLE) +#endif + + { 0, 0 }, + +}; diff --git a/hw/xfree86/loader/fontsym.c b/hw/xfree86/loader/fontsym.c new file mode 100644 index 000000000..50def63ea --- /dev/null +++ b/hw/xfree86/loader/fontsym.c @@ -0,0 +1,79 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/loader/fontsym.c,v 1.11 2002/12/09 17:30:12 dawes Exp $ */ + +#include "font.h" +#include "sym.h" +#include "fntfilst.h" +#include "fontenc.h" +#ifdef FONTENC_COMPATIBILITY +#include "fontencc.h" +#endif +#include "fntfilio.h" +#include "fntfil.h" +#include "fontutil.h" +#include "fontxlfd.h" +#define _FONTCACHE_SERVER_ +#include "fontcache.h" + +LOOKUP fontLookupTab[] = { + + SYMFUNC(TwoByteSwap) + SYMFUNC(FourByteSwap) + SYMFUNC(FontCouldBeTerminal) + SYMFUNC(BufFileRead) + SYMFUNC(BufFileWrite) + SYMFUNC(CheckFSFormat) + SYMFUNC(FontFileOpen) + SYMFUNC(FontFilePriorityRegisterRenderer) + SYMFUNC(FontFileRegisterRenderer) + SYMFUNC(FontParseXLFDName) + SYMFUNC(FontFileCloseFont) + SYMFUNC(FontFileOpenBitmap) + SYMFUNC(FontFileCompleteXLFD) + SYMFUNC(FontFileCountDashes) + SYMFUNC(FontFileFindNameInDir) + SYMFUNC(FontFileClose) + SYMFUNC(FontComputeInfoAccelerators) + SYMFUNC(FontDefaultFormat) + SYMFUNC(NameForAtom) + SYMFUNC(BitOrderInvert) + SYMFUNC(FontFileMatchRenderer) + SYMFUNC(RepadBitmap) + SYMFUNC(FontEncName) + SYMFUNC(FontEncRecode) + SYMFUNC(FontEncFind) + SYMFUNC(FontMapFind) + SYMFUNC(FontEncMapFind) + SYMFUNC(FontEncFromXLFD) + SYMFUNC(FontEncDirectory) + SYMFUNC(FontMapReverse) + SYMFUNC(FontMapReverseFree) + SYMFUNC(CreateFontRec) + SYMFUNC(DestroyFontRec) + SYMFUNC(GetGlyphs) + SYMFUNC(QueryGlyphExtents) + + SYMVAR(FontFileBitmapSources) + +#ifdef FONTENC_COMPATIBILITY + /* Obsolete backwards compatibility symbols -- fontencc.c */ + SYMFUNC(font_encoding_from_xlfd) + SYMFUNC(font_encoding_find) + SYMFUNC(font_encoding_recode) + SYMFUNC(font_encoding_name) + SYMFUNC(identifyEncodingFile) +#endif + + /* fontcache.c */ + SYMFUNC(FontCacheGetSettings) + SYMFUNC(FontCacheGetStatistics) + SYMFUNC(FontCacheChangeSettings) + SYMFUNC(FontCacheOpenCache) + SYMFUNC(FontCacheCloseCache) + SYMFUNC(FontCacheSearchEntry) + SYMFUNC(FontCacheGetEntry) + SYMFUNC(FontCacheInsertEntry) + SYMFUNC(FontCacheGetBitmap) + + { 0, 0 }, + +}; diff --git a/hw/xfree86/loader/hash.c b/hw/xfree86/loader/hash.c new file mode 100644 index 000000000..22996f217 --- /dev/null +++ b/hw/xfree86/loader/hash.c @@ -0,0 +1,364 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/loader/hash.c,v 1.19 2001/07/25 15:05:07 dawes 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. + */ + +#include "os.h" +#include "Xos.h" +#undef abs +#include <stdlib.h> +#include "sym.h" +#include "loader.h" +#include "hash.h" + +#if defined(Lynx) +#define MAXINT 32000 +#else +#include <limits.h> +#undef MAXINT +#define MAXINT INT_MAX +#endif + +/* Prototypes for static functions. */ +static unsigned int hashFunc(const char *); +static itemPtr LoaderHashFindNearest( +#if NeedFunctionPrototypes +unsigned long +#endif +); + +static itemPtr LoaderhashTable[ HASHSIZE ] ; + +#ifdef DEBUG +static int hashhits[ HASHSIZE ] ; + +void +DumpHashHits(void) +{ + int i; + int depth=0; + int dev=0; + + for(i=0;i<HASHSIZE;i++) { + ErrorF("hashhits[%d]=%d\n", i, hashhits[i] ); + depth += hashhits[i]; + } + + depth /= HASHSIZE; + ErrorF("Average hash depth=%d\n", depth ); + + for(i=0;i<HASHSIZE;i++) { + if( hashhits[i] < depth ) + dev += depth-hashhits[i]; + else + dev += hashhits[i]-depth; + } + + dev /=HASHSIZE; + ErrorF("Average hash deviation=%d\n", dev ); +} +#endif + + +static unsigned int +hashFunc(string) +const char *string; +{ + int i=0; + + while ( i < 10 && string[i] ) + i ++ ; + + if ( i < 5 ) { +#ifdef DEBUG + hashhits[i]++; +#endif + return i ; + } + +/* + * Original has function +#define HASH ((string[ i-4 ] * string[i-3] + string[i-2] ) & (HASHSIZE-1)) + */ + +#define HASH ((string[i-5] * string[ i-4 ] + string[i-3] * string[i-2] ) & (HASHSIZE-1)) + +#ifdef DEBUG + hashhits[HASH]++; +#endif + + return HASH; +} + +void +LoaderHashAdd( entry ) + itemPtr entry ; +{ + int bucket = hashFunc( entry->name ) ; + itemPtr oentry; + + if ((oentry = LoaderHashFind(entry->name)) != NULL) + LoaderDuplicateSymbol(entry->name, oentry->handle); + + entry->next = LoaderhashTable[ bucket ] ; + LoaderhashTable[ bucket ] = entry ; + return; +} + +void +LoaderAddSymbols(handle, module, list) +int handle; +int module; +LOOKUP *list ; +{ + LOOKUP *l = list, *exports = NULL; + itemPtr i, exportsItem = NULL; + char *modname; + + if (!list) + return; + + /* + * First look for a symbol called <name>ExportedSymbols. If it exists, + * only export the symbols that are listed in that array. Otherwise + * export all of the external symbols. + */ + modname = _LoaderHandleToCanonicalName(handle); + if (modname) { + char *exportname; + + exportname = xf86loadermalloc(strlen("ExportedSymbols") + + strlen(modname) + 1); + if (exportname) { + sprintf(exportname, "%sExportedSymbols", modname); + while (l->symName) { + if (strcmp(l->symName, exportname) == 0) { + exports = l; + ErrorF("LoaderAddSymbols: %s: %s found\n", modname, + exportname); + break; + } + l++; + } + } + } + + /* + * Allocate the exports list item first. + */ + if (exports) { + exportsItem = xf86loadermalloc( sizeof( itemRec )) ; + exportsItem->name = exports->symName ; + exportsItem->address = (char *) exports->offset ; + exportsItem->handle = handle ; + exportsItem->module = module ; + exportsItem->exports = NULL; + LoaderHashAdd( exportsItem ); + } + + /* + * Visit every symbol in the lookup table, tagging it with the + * reference to the export list, if present. + */ + l = list; + while ( l->symName ) { + if (l != exports) { + i = xf86loadermalloc( sizeof( itemRec )) ; + i->name = l->symName ; + i->address = (char *) l->offset ; + i->handle = handle ; + i->module = module ; + i->exports = exportsItem; + LoaderHashAdd( i ); + } + l ++ ; + } +} + +itemPtr +LoaderHashDelete(string) +const char *string; +{ + int bucket = hashFunc( string ) ; + itemPtr entry; + itemPtr *entry2; + + entry = LoaderhashTable[ bucket ] ; + entry2= &(LoaderhashTable[ bucket ]); + while ( entry ) { + if (! strcmp( entry->name, string )) { + *entry2=entry->next; + xf86loaderfree(entry->name); + xf86loaderfree( entry ) ; + return 0 ; + } + entry2 = &(entry->next) ; + entry = entry->next ; + } + return 0 ; +} + +itemPtr +LoaderHashFind(string) +const char *string; +{ + int bucket = hashFunc( string ) ; + itemPtr entry ; + entry = LoaderhashTable[ bucket ] ; + while ( entry ) { + if (!strcmp(entry->name, string)) { + return entry; + } + entry = entry->next; + } + return 0; +} + +static itemPtr +LoaderHashFindNearest(address) +unsigned long address; +{ + int i ; + itemPtr entry, best_entry = 0 ; + long best_difference = MAXINT; + + for ( i = 0 ; i < HASHSIZE ; i ++ ) { + entry = LoaderhashTable[ i ] ; + while ( entry ) { + long difference = (long) address - (long) entry->address ; + if ( difference >= 0 ) { + if ( best_entry ) { + if ( difference < best_difference ) { + best_entry = entry ; + best_difference = difference ; + } + } + else { + best_entry = entry ; + best_difference = difference ; + } + } + entry = entry->next ; + } + } + return best_entry ; +} + +void +LoaderPrintSymbol(address) +unsigned long address; +{ + itemPtr entry; + entry=LoaderHashFindNearest(address); + if (entry) { + const char *module, *section; +#if defined(__alpha__) || defined(__ia64__) + ErrorF("0x%016lx %s+%lx\n", entry->address, entry->name, + address - (unsigned long) entry->address); +#else + ErrorF("0x%x %s+%x\n", entry->address, entry->name, + address - (unsigned long) entry->address); +#endif + + if ( _LoaderAddressToSection(address, &module, §ion) ) + ErrorF("\tModule \"%s\"\n\tSection \"%s\"\n",module, section ); + } else { + ErrorF("(null)\n"); + } +} + +void +LoaderPrintItem(itemPtr pItem) +{ + if (pItem) { + const char *module, *section; +#if defined(__alpha__) || defined(__ia64__) + ErrorF("0x%016lx %s\n", pItem->address, pItem->name); +#else + ErrorF("0x%lx %s\n", pItem->address, pItem->name); +#endif + if ( _LoaderAddressToSection((unsigned long)pItem->address, + &module, §ion) ) + ErrorF("\tModule \"%s\"\n\tSection \"%s\"\n",module, section ); + } else + ErrorF("(null)\n"); +} + +void +LoaderPrintAddress(symbol) +const char *symbol; +{ + itemPtr entry; + entry = LoaderHashFind(symbol); + LoaderPrintItem(entry); +} + +void +LoaderHashTraverse(card, fnp) + void *card; + int (*fnp)(void *, itemPtr); +{ + int i ; + itemPtr entry, last_entry = 0 ; + + for ( i = 0 ; i < HASHSIZE ; i ++ ) { + last_entry = 0 ; + entry = LoaderhashTable[ i ] ; + while ( entry ) { + if (( * fnp )( card, entry )) { + if ( last_entry ) { + last_entry->next = entry->next ; + xf86loaderfree( entry->name ) ; + xf86loaderfree( entry ) ; + entry = last_entry->next ; + } + else { + LoaderhashTable[ i ] = entry->next ; + xf86loaderfree( entry->name ) ; + xf86loaderfree( entry ) ; + entry = LoaderhashTable[ i ] ; + } + } + else { + last_entry = entry ; + entry = entry->next ; + } + } + } +} + +void +LoaderDumpSymbols() +{ + itemPtr entry; + int j; + + for (j=0; j<HASHSIZE; j++) { + entry = LoaderhashTable[j]; + while (entry) { + LoaderPrintItem(entry); + entry = entry->next; + } + } + +} diff --git a/hw/xfree86/loader/hash.h b/hw/xfree86/loader/hash.h new file mode 100644 index 000000000..96cd41c02 --- /dev/null +++ b/hw/xfree86/loader/hash.h @@ -0,0 +1,36 @@ +/* + * + * 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. + */ + +/* $XFree86: xc/programs/Xserver/hw/xfree86/loader/hash.h,v 1.3 1998/07/25 16:56:16 dawes Exp $ */ + +#ifndef _HASH_H +#define _HASH_H + +#include "loader.h" + +typedef struct _HashIterator { + itemPtr pItem; + int bucket; +} HashIteratorRec, *HashIteratorPtr; + +#endif /* _HASH_H */ diff --git a/hw/xfree86/loader/loader.c b/hw/xfree86/loader/loader.c new file mode 100644 index 000000000..e09fa50b0 --- /dev/null +++ b/hw/xfree86/loader/loader.c @@ -0,0 +1,1412 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/loader/loader.c,v 1.63 2002/11/25 14:05:03 eich 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. + */ +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <sys/types.h> +#if defined(UseMMAP) || (defined(linux) && defined(__ia64__)) +#include <sys/mman.h> +#endif +#include <unistd.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <string.h> +#if defined(linux) && \ + (defined(__alpha__) || defined(__powerpc__) || defined(__ia64__) \ + || defined(__x86_64__)) +#include <malloc.h> +#endif +#include <stdarg.h> +#include "ar.h" +#include "elf.h" +#include "coff.h" + +#include "os.h" +#include "sym.h" +#include "loader.h" +#include "loaderProcs.h" +#include "xf86.h" +#include "xf86Priv.h" + +#include "compiler.h" + +extern LOOKUP miLookupTab[]; +extern LOOKUP xfree86LookupTab[]; +extern LOOKUP dixLookupTab[]; +extern LOOKUP fontLookupTab[]; +extern LOOKUP extLookupTab[]; + +/* +#define DEBUG +#define DEBUGAR +#define DEBUGLIST +#define DEBUGMEM +*/ + +int check_unresolved_sema = 0; + +#if defined(Lynx) && defined(sun) +/* Cross build machine doesn;t have strerror() */ +#define strerror(err) "strerror unsupported" +#endif + +#ifdef __UNIXOS2__ +void * os2ldcalloc(size_t,size_t); +#endif + +#ifdef HANDLE_IN_HASH_ENTRY +/* + * handles are used to identify files that are loaded. Even archives + * are counted as a single file. + */ +#define MAX_HANDLE 256 +#define HANDLE_FREE 0 +#define HANDLE_USED 1 +static char freeHandles[MAX_HANDLE] ; +static int refCount[MAX_HANDLE] ; +#endif + +#if defined(__sparc__) && defined(__GNUC__) +# define SYMFUNCDOT(func) { "." #func, (funcptr)&__sparc_dot_ ## func }, +# if !defined(__OpenBSD__) +# define SYMFUNCDOT89(func) { "." #func, (funcptr)&func ## _sparcv89 }, +# define DEFFUNCDOT(func) \ +extern void __sparc_dot_ ## func (void) __asm__ ("." #func); \ +extern void func ## _sparcv89 (void); +# else +# define SYMFUNCDOT(func) { "." #func, (funcptr)&__sparc_dot_ ## func }, +# define DEFFUNCDOT(func) \ +extern void __sparc_dot_ ## func (void) __asm__ ("." #func); +#endif +DEFFUNCDOT(rem) +DEFFUNCDOT(urem) +DEFFUNCDOT(mul) +DEFFUNCDOT(umul) +DEFFUNCDOT(div) +DEFFUNCDOT(udiv) +#ifdef linux +static LOOKUP SparcV89LookupTab[] = { + SYMFUNCDOT89(rem) + SYMFUNCDOT89(urem) + SYMFUNCDOT89(mul) + SYMFUNCDOT89(umul) + SYMFUNCDOT89(div) + SYMFUNCDOT89(udiv) + { 0, 0 } +}; +#endif +static LOOKUP SparcLookupTab[] = { + SYMFUNCDOT(rem) + SYMFUNCDOT(urem) + SYMFUNCDOT(mul) + SYMFUNCDOT(umul) + SYMFUNCDOT(div) + SYMFUNCDOT(udiv) + { 0, 0 } +}; +#ifdef linux +#if defined(__GNUC__) && defined(__GLIBC__) +#define HWCAP_SPARC_MULDIV 8 +extern unsigned long int _dl_hwcap; +#endif + +static int +sparcUseHWMulDiv(void) +{ + FILE *f; + char buffer[1024]; + char *p; +#if defined(__GNUC__) && defined(__GLIBC__) + unsigned long *hwcap; + __asm(".weak _dl_hwcap"); + + hwcap = &_dl_hwcap; + __asm("" : "=r" (hwcap) : "0" (hwcap)); + if (hwcap) { + if (*hwcap & HWCAP_SPARC_MULDIV) + return 1; + else + return 0; + } +#endif + f = fopen("/proc/cpuinfo","r"); + if (!f) return 0; + while (fgets(buffer, 1024, f) != NULL) { + if (!strncmp (buffer, "type", 4)) { + p = strstr (buffer, "sun4"); + if (p && (p[4] == 'u' || p[4] == 'd' || p[4] == 'm')) { + fclose(f); + return 1; + } + } + } + fclose(f); + return 0; +} +#endif +#endif + +/* + * modules are used to identify compilation units (ie object modules). + * Archives contain multiple modules, each of which is treated seperately. + */ +static int moduleseq = 0; + +/* + * GDB Interface + * ============= + * + * Linked list of loaded modules - gdb will traverse this to determine + * whether it needs to add the symbols for the loaded module. + */ +LDRModulePtr ModList = 0; + +/* Flag which gdb sets to let us know we're being debugged */ +char DebuggerPresent = 0; + +/* List of common symbols */ +LDRCommonPtr ldrCommons; +int nCommons; + +typedef struct { + int num; + const char ** list; +} symlist; + +/* + * List of symbols that may be referenced, and which are allowed to be + * unresolved providing that they don't appear on the "reqired" list. + */ +static symlist refList = { 0, NULL }; + +/* List of symbols that must not be unresolved */ +static symlist reqList = { 0, NULL }; + +static int fatalReqSym = 0; + +/* Prototypes for static functions. */ +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); + + +void +LoaderInit(void) +{ + const char *osname = NULL; + + LoaderAddSymbols(-1, -1, miLookupTab ) ; + LoaderAddSymbols(-1, -1, xfree86LookupTab ) ; + LoaderAddSymbols(-1, -1, dixLookupTab ) ; + LoaderAddSymbols(-1, -1, fontLookupTab ) ; + LoaderAddSymbols(-1, -1, extLookupTab ); +#ifdef __sparc__ +#ifdef linux + if (sparcUseHWMulDiv()) + LoaderAddSymbols(-1, -1, SparcV89LookupTab ) ; + else +#endif + LoaderAddSymbols(-1, -1, SparcLookupTab ) ; +#endif + + xf86MsgVerb(X_INFO, 2, "Module ABI versions:\n"); + xf86ErrorFVerb(2, "\t%s: %d.%d\n", ABI_CLASS_ANSIC, + GET_ABI_MAJOR(LoaderVersionInfo.ansicVersion), + GET_ABI_MINOR(LoaderVersionInfo.ansicVersion)); + xf86ErrorFVerb(2, "\t%s: %d.%d\n", ABI_CLASS_VIDEODRV, + GET_ABI_MAJOR(LoaderVersionInfo.videodrvVersion), + GET_ABI_MINOR(LoaderVersionInfo.videodrvVersion)); + xf86ErrorFVerb(2, "\t%s : %d.%d\n", ABI_CLASS_XINPUT, + GET_ABI_MAJOR(LoaderVersionInfo.xinputVersion), + GET_ABI_MINOR(LoaderVersionInfo.xinputVersion)); + xf86ErrorFVerb(2, "\t%s : %d.%d\n", ABI_CLASS_EXTENSION, + GET_ABI_MAJOR(LoaderVersionInfo.extensionVersion), + GET_ABI_MINOR(LoaderVersionInfo.extensionVersion)); + xf86ErrorFVerb(2, "\t%s : %d.%d\n", ABI_CLASS_FONT, + GET_ABI_MAJOR(LoaderVersionInfo.fontVersion), + GET_ABI_MINOR(LoaderVersionInfo.fontVersion)); + + LoaderGetOS(&osname, NULL, NULL, NULL); + if (osname) + xf86MsgVerb(X_INFO, 2, "Loader running on %s\n", osname); + +#if defined(linux) && \ + (defined(__alpha__) || defined(__powerpc__) || defined(__ia64__) \ + || ( defined __x86_64__ && ! defined UseMMAP && ! defined DoMMAPedMerge)) + /* + * The glibc malloc uses mmap for large allocations anyway. This breaks + * some relocation types because the offset overflow. See loader.h for more + * details. We need to turn off this behavior here. + */ + mallopt(M_MMAP_MAX,0); +#endif +} + +/* + * Determine what type of object is being loaded. + * This function is responsible for restoring the offset. + * The fd and offset are used here so that when Archive processing + * is enabled, individual elements of an archive can be evaluated + * so the correct loader_funcs can be determined. + */ +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; +} + + +static int offsetbias=0; /* offset into archive */ +/* + * _LoaderFileToMem() loads the contents of a file into memory using + * the most efficient method for a platform. + */ +void * +_LoaderFileToMem(int fd, unsigned long offset,int size, char *label) +{ +#ifdef UseMMAP + unsigned long ret; +# ifdef MmapPageAlign + unsigned long pagesize; + unsigned long new_size; + unsigned long new_off; + unsigned long new_off_bias; +# endif +# define MMAP_PROT (PROT_READ|PROT_WRITE|PROT_EXEC) + +# ifdef DEBUGMEM + ErrorF("_LoaderFileToMem(%d,%u(%u),%d,%s)",fd,offset,offsetbias,size,label); +# endif +# ifdef MmapPageAlign + pagesize = getpagesize(); + new_size = (size + pagesize - 1) / pagesize; + new_size *= pagesize; + new_off = (offset + offsetbias) / pagesize; + new_off *= pagesize; + new_off_bias = (offset + offsetbias) - new_off; + if ((new_off_bias + size) > new_size) new_size += pagesize; + ret = (unsigned long) mmap(0,new_size,MMAP_PROT,MAP_PRIVATE +# ifdef __x86_64__ + | MAP_32BIT +# endif + , + fd,new_off); + if(ret == -1) + FatalError("mmap() failed: %s\n", strerror(errno) ); + return (void *)(ret + new_off_bias); +# else + ret = (unsigned long) mmap(0,size,MMAP_PROT,MAP_PRIVATE +# ifdef __x86_64__ + | MAP_32BIT +# endif + , + fd,offset + offsetbias); + if(ret == -1) + FatalError("mmap() failed: %s\n", strerror(errno) ); + return (void *)ret; +# endif +#else + char *ptr; + +# ifdef DEBUGMEM + ErrorF("_LoaderFileToMem(%d,%u(%u),%d,%s)",fd,offset,offsetbias,size,label); +# endif + + if(size == 0){ +# ifdef DEBUGMEM + ErrorF("=NULL\n",ptr); +# endif + return NULL; + } + +# ifndef __UNIXOS2__ + if( (ptr=xf86loadercalloc(size,1)) == NULL ) + FatalError("_LoaderFileToMem() malloc failed\n" ); +# else + if( (ptr=os2ldcalloc(size,1)) == NULL ) + FatalError("_LoaderFileToMem() malloc failed\n" ); +# endif +# if defined(linux) && defined(__ia64__) + { + unsigned long page_size = getpagesize(); + unsigned long round; + + round = (unsigned long)ptr & (page_size-1); + mprotect(ptr - round, (size+round+page_size-1) & ~(page_size-1), + PROT_READ|PROT_WRITE|PROT_EXEC); + } +# endif + + if(lseek(fd,offset+offsetbias,SEEK_SET)<0) + FatalError("\n_LoaderFileToMem() lseek() failed: %s\n",strerror(errno)); + + if(read(fd,ptr,size)!=size) + FatalError("\n_LoaderFileToMem() read() failed: %s\n",strerror(errno)); + +# if (defined(linux) || defined(__NetBSD__) || defined(__OpenBSD__)) \ + && defined(__powerpc__) + /* + * Keep the instruction cache in sync with changes in the + * main memory. + */ + { + int i; + for (i = 0; i < size; i += 16) + ppc_flush_icache(ptr+i); + ppc_flush_icache(ptr+size-1); + } +# endif + +# ifdef DEBUGMEM + ErrorF("=%lx\n",ptr); +# endif + + return (void *)ptr; +#endif +} + +/* + * _LoaderFreeFileMem() free the memory in which a file was loaded. + */ +void +_LoaderFreeFileMem(void *addr, int size) +{ +#if defined (UseMMAP) && defined (MmapPageAlign) + unsigned long pagesize = getpagesize(); + memType i_addr = (memType)addr; + unsigned long new_size; +#endif +#ifdef DEBUGMEM + ErrorF("_LoaderFreeFileMem(%x,%d)\n",addr,size); +#endif +#ifdef UseMMAP +# if defined (MmapPageAlign) + i_addr /= pagesize; + i_addr *= pagesize; + new_size = (size + pagesize - 1) / pagesize; + new_size *= pagesize; + if (((memType)addr - i_addr + size) > new_size) new_size += pagesize; + munmap((void *)i_addr,new_size); +# else + munmap((void *)addr,size); +# endif +#else + if(size == 0) + return; + + xf86loaderfree(addr); +#endif + + return; +} + +int +_LoaderFileRead(int fd, unsigned int offset, void *buf, int size) +{ + if(lseek(fd,offset+offsetbias,SEEK_SET)<0) + FatalError("_LoaderFileRead() lseek() failed: %s\n", strerror(errno) ); + + if(read(fd,buf,size)!=size) + FatalError("_LoaderFileRead() read() failed: %s\n", strerror(errno) ); + + return size; +} + +static loaderPtr listHead = (loaderPtr) 0 ; + +static loaderPtr +_LoaderListPush() +{ + loaderPtr item = xf86loadercalloc(1, sizeof (struct _loader)); + item->next = listHead ; + listHead = item; + + return item; +} + +static loaderPtr +_LoaderListPop(int handle) +{ + loaderPtr item=listHead; + loaderPtr *bptr=&listHead; /* pointer to previous node */ + + while(item) { + if( item->handle == handle ) { + *bptr=item->next; /* remove this from the list */ + return item; + } + bptr=&(item->next); + item=item->next; + } + + return 0; +} + +/* + * _LoaderHandleToName() will return the name of the first module with a + * given handle. This requires getting the last module on the LIFO with + * the given handle. + */ +char * +_LoaderHandleToName(int handle) +{ + loaderPtr item=listHead; + loaderPtr aritem=NULL; + loaderPtr lastitem=NULL; + + if ( handle < 0 ) { + return "(built-in)"; + } + while(item) { + if( item->handle == handle ) { + if( strchr(item->name,':') == NULL ) + aritem=item; + else + lastitem=item; + } + item=item->next; + } + + if( aritem ) + return aritem->name; + + if( lastitem ) + return lastitem->name; + + return 0; +} + +/* + * _LoaderHandleToCanonicalName() will return the cname of the first module + * with a given handle. This requires getting the last module on the LIFO with + * the given handle. + */ +char * +_LoaderHandleToCanonicalName(int handle) +{ + loaderPtr item=listHead; + loaderPtr lastitem=NULL; + + if ( handle < 0 ) { + return "(built-in)"; + } + while(item) { + if( item->handle == handle ) { + lastitem=item; + } + item=item->next; + } + + if( lastitem ) + return lastitem->cname; + + return NULL; +} + +/* + * _LoaderModuleToName() will return the name of the first module with a + * given handle. This requires getting the last module on the LIFO with + * the given handle. + */ +char * +_LoaderModuleToName(int module) +{ + loaderPtr item=listHead; + loaderPtr aritem=NULL; + loaderPtr lastitem=NULL; + + if ( module < 0 ) { + return "(built-in)"; + } + while(item) { + if( item->module == module ) { + if( strchr(item->name,':') == NULL ) + aritem=item; + else + lastitem=item; + } + item=item->next; + } + + if( aritem ) + return aritem->name; + + if( lastitem ) + return lastitem->name; + + return 0; +} + +/* + * _LoaderAddressToSection() will return the name of the file & section + * that contains the given address. + */ +int +_LoaderAddressToSection(const unsigned long address, const char **module, + const char ** section) +{ + loaderPtr item=listHead; + + while(item) { + if( (*section=item->funcs->AddressToSection(item->private, address)) != NULL ) { + *module=_LoaderModuleToName(item->module); + return 1; + } + item=item->next; + } + + return 0; +} + + +/* + * Add a list of symbols to the referenced list. + */ + +static void +AppendSymbol(symlist *list, const char *sym) +{ + list->list = xnfrealloc(list->list, (list->num + 1) * sizeof(char **)); + list->list[list->num] = sym; + list->num++; +} + +static void +AppendSymList(symlist *list, const char **syms) +{ + while (*syms) { + AppendSymbol(list, *syms); + syms++; + } +} + +static int +SymInList(symlist *list, char *sym) +{ + int i; + + for (i = 0; i < list->num; i++) + if (strcmp(list->list[i], sym) == 0) + return 1; + + return 0; +} + +void +LoaderVRefSymbols(const char *sym0, va_list args) +{ + const char *s; + + if (sym0 == NULL) + return; + + s = sym0; + do { + AppendSymbol(&refList, s); + s = va_arg(args, const char *); + } while (s != NULL); +} + +void +LoaderRefSymbols(const char *sym0, ...) +{ + va_list ap; + + va_start(ap, sym0); + LoaderVRefSymbols(sym0, ap); + va_end(ap); +} + +void +LoaderVRefSymLists(const char **list0, va_list args) +{ + const char **l; + + if (list0 == NULL) + return; + + l = list0; + do { + AppendSymList(&refList, l); + l = va_arg(args, const char **); + } while (l != NULL); +} + +void +LoaderRefSymLists(const char **list0, ...) +{ + va_list ap; + + va_start(ap, list0); + LoaderVRefSymLists(list0, ap); + va_end(ap); +} + +void +LoaderVReqSymLists(const char **list0, va_list args) +{ + const char **l; + + if (list0 == NULL) + return; + + l = list0; + do { + AppendSymList(&reqList, l); + l = va_arg(args, const char **); + } while (l != NULL); +} + +void +LoaderReqSymLists(const char **list0, ...) +{ + va_list ap; + + va_start(ap, list0); + LoaderVReqSymLists(list0, ap); + va_end(ap); +} + +void +LoaderVReqSymbols(const char *sym0, va_list args) +{ + const char *s; + + if (sym0 == NULL) + return; + + s = sym0; + do { + AppendSymbol(&reqList, s); + s = va_arg(args, const char *); + } while (s != NULL); +} + +void +LoaderReqSymbols(const char *sym0, ...) +{ + va_list ap; + + va_start(ap, sym0); + LoaderVReqSymbols(sym0, ap); + va_end(ap); +} + +/* + * _LoaderHandleUnresolved() decides what to do with an unresolved + * symbol. Symbols that are not on the "referenced" or "required" lists + * get a warning if they are unresolved. Symbols that are on the "required" + * list generate a fatal error if they are unresolved. + */ + +int +_LoaderHandleUnresolved(char *symbol, char *module) +{ + int fatalsym = 0; + + if (xf86ShowUnresolved && !fatalsym) { + if (SymInList(&reqList, symbol)) { + fatalReqSym = 1; + ErrorF("Required symbol %s from module %s is unresolved!\n", + symbol, module); + } + if (!SymInList(&refList, symbol)) { + ErrorF("Symbol %s from module %s is unresolved!\n", + symbol, module); + } + } + return(fatalsym); +} + +/* + * Handle an archive. + */ +void * +ARCHIVELoadModule(loaderPtr modrec, int arfd, LOOKUP **ppLookup) +{ + 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; + int resetoff; + + /* 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; + } + resetoff=SARMAG; +#else + read(arfd,&fhdr,FL_HSZ); + + if(strncmp(fhdr.fl_magic,AIAMAG,SAIAMAG) != 0 ) { + ErrorF("ARCHIVELoadModule: wrong magic!!\n" ); + return NULL; + } + resetoff=FL_HSZ; +#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,"%d",&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 %d\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)) + == 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) { + ErrorF("Skipping \"%s\": No symbols found\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 + */ + +/* + * _LoaderGetRelocations() Return the list of outstanding relocations + */ +LoaderRelocPtr +_LoaderGetRelocations(void *mod) +{ + loader_funcs *formatrec = (loader_funcs *)mod; + + return &(formatrec->pRelocs); +} + +/* + * Public Interface to the loader. + */ + +int +LoaderOpen(const char *module, const char *cname, int handle, + int *errmaj, int *errmin, int *wasLoaded) +{ + loaderPtr tmp ; + int new_handle, modtype ; + int fd; + LOOKUP *pLookup; + +#if defined(DEBUG) + ErrorF("LoaderOpen(%s)\n", module ); +#endif + + /* + * Check to see if the module is already loaded. + * Only if we are loading it into an existing namespace. + * If it is to be loaded into a new namespace, don't check. + * Note: We only have one namespace. + */ + if (handle >= 0) { + tmp = listHead; + while ( tmp ) { +#ifdef DEBUGLIST + ErrorF("strcmp(%x(%s),{%x} %x(%s))\n", module,module,&(tmp->name), + tmp->name,tmp->name ); +#endif + if ( ! strcmp( module, tmp->name )) { + refCount[tmp->handle]++; + if (wasLoaded) + *wasLoaded = 1; + xf86MsgVerb(X_INFO, 2, "Reloading %s\n", module); + return tmp->handle; + } + tmp = tmp->next ; + } + } + + /* + * OK, it's a new one. Add it. + */ + xf86Msg(X_INFO, "Loading %s\n", module ) ; + if (wasLoaded) + *wasLoaded = 0; + + /* + * Find a free handle. + */ + new_handle = 1; + while ( freeHandles[new_handle] && new_handle < MAX_HANDLE ) + new_handle ++ ; + + if ( new_handle == MAX_HANDLE ) { + xf86Msg(X_ERROR, "Out of loader space\n" ) ; /* XXX */ + if(errmaj) *errmaj = LDR_NOSPACE; + if(errmin) *errmin = LDR_NOSPACE; + return -1 ; + } + + freeHandles[new_handle] = HANDLE_USED ; + refCount[new_handle] = 1; + + if( (fd=open(module, O_RDONLY)) < 0 ) { + xf86Msg(X_ERROR, "Unable to open %s\n", module ); + freeHandles[new_handle] = HANDLE_FREE ; + if(errmaj) *errmaj = LDR_NOMODOPEN; + if(errmin) *errmin = errno; + return -1 ; + } + + if( (modtype=_GetModuleType(fd,0)) < 0 ) { + xf86Msg(X_ERROR, "%s is an unrecognized module type\n", module ) ; + freeHandles[new_handle] = HANDLE_FREE ; + if(errmaj) *errmaj = LDR_UNKTYPE; + if(errmin) *errmin = LDR_UNKTYPE; + return -1; + } + + tmp=_LoaderListPush(); + tmp->name = xf86loadermalloc(strlen(module) + 1); + strcpy(tmp->name, module); + tmp->cname = xf86loadermalloc(strlen(cname) + 1); + strcpy(tmp->cname, cname); + tmp->handle = new_handle; + tmp->module = moduleseq++; + tmp->funcs=&funcs[modtype]; + + if((tmp->private = funcs[modtype].LoadModule(tmp,fd, &pLookup)) == NULL) { + xf86Msg(X_ERROR, "Failed to load %s\n", module ) ; + _LoaderListPop(new_handle); + freeHandles[new_handle] = HANDLE_FREE ; + if(errmaj) *errmaj = LDR_NOLOAD; + if(errmin) *errmin = LDR_NOLOAD; + return -1; + } + + if (tmp->private != (void *) -1L) { + LoaderAddSymbols(new_handle, tmp->module, pLookup); + xf86loaderfree(pLookup); + } + + close(fd); + + return new_handle; +} + +int +LoaderHandleOpen(int handle) +{ + if (handle < 0 || handle >= MAX_HANDLE) + return -1; + + if (freeHandles[handle] != HANDLE_USED) + return -1; + + refCount[handle]++; + return handle; +} + +void * +LoaderSymbol(const char *sym) +{ + int i; + itemPtr item = NULL; + for (i = 0; i < numloaders; i++) + funcs[i].ResolveSymbols(&funcs[i]); + + item = (itemPtr) LoaderHashFind(sym); + + if ( item ) + return item->address ; + else +#ifdef DLOPEN_SUPPORT + return(DLFindSymbol(sym)); +#else + return NULL; +#endif +} + +int +LoaderResolveSymbols(void) +{ + int i; + for(i=0;i<numloaders;i++) + funcs[i].ResolveSymbols(&funcs[i]); + return 0; +} + +int +LoaderCheckUnresolved(int delay_flag ) +{ + int i,ret=0; + LoaderResolveOptions delayFlag = delay_flag; + + LoaderResolveSymbols(); + + if (delayFlag == LD_RESOLV_NOW) { + if (check_unresolved_sema > 0) + check_unresolved_sema--; + else + xf86Msg(X_WARNING, "LoaderCheckUnresolved: not enough " + "MAGIC_DONT_CHECK_UNRESOLVED\n"); + } + + if (!check_unresolved_sema || delayFlag == LD_RESOLV_FORCE) + for(i=0;i<numloaders;i++) + if (funcs[i].CheckForUnresolved(&funcs[i])) + ret=1; + + if (fatalReqSym) + FatalError("Some required symbols were unresolved\n"); + + return ret; +} + +void xf86LoaderTrap(void); + +void +xf86LoaderTrap(void) +{ +} + +void +LoaderDefaultFunc(void) +{ + ErrorF("\n\n\tThis should not happen!\n" + "\tAn unresolved function was called!\n"); + + xf86LoaderTrap(); + + FatalError("\n"); +} + +int +LoaderUnload(int handle) +{ + loaderRec fakeHead ; + loaderPtr tmp = & fakeHead ; + + if ( handle < 0 || handle > MAX_HANDLE ) + return -1; + + /* + * check the reference count, only free it if it goes to zero + */ + if (--refCount[handle]) + return 0; + /* + * find the loaderRecs associated with this handle. + */ + + while( (tmp=_LoaderListPop(handle)) != NULL ) { + if( strchr(tmp->name,':') == NULL ) { + /* It is not a member of an archive */ + xf86Msg(X_INFO, "Unloading %s\n", tmp->name ) ; + } + tmp->funcs->LoaderUnload(tmp->private); + xf86loaderfree(tmp->name); + xf86loaderfree(tmp->cname); + xf86loaderfree(tmp); + } + + freeHandles[handle] = HANDLE_FREE ; + +return 0; +} + +void +LoaderDuplicateSymbol(const char *symbol, const int handle) +{ + ErrorF("Duplicate symbol %s in %s\n", symbol, + listHead ? listHead->name : "(built-in)"); + ErrorF("Also defined in %s\n", _LoaderHandleToName(handle)); + FatalError("Module load failure\n"); +} + +/* GDB Sync function */ +void _loader_debug_state() +{ +} + +unsigned long LoaderOptions = 0; + +void +LoaderResetOptions(void) +{ + LoaderOptions = 0; +} + +void +LoaderSetOptions(unsigned long opts) +{ + LoaderOptions |= opts; +} + +void +LoaderClearOptions(unsigned long opts) +{ + LoaderOptions &= ~opts; +} + diff --git a/hw/xfree86/loader/loader.h b/hw/xfree86/loader/loader.h new file mode 100644 index 000000000..a814544b8 --- /dev/null +++ b/hw/xfree86/loader/loader.h @@ -0,0 +1,269 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/loader/loader.h,v 1.25 2001/02/22 23:17:09 dawes 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. + */ +#ifndef _LOADER_H +#define _LOADER_H + +#include "sym.h" + +#if defined(Lynx) && defined(sun) +#define const /**/ +#endif + +#if (defined(__i386__) || defined(__ix86)) && !defined(i386) +#define i386 +#endif + +#include <X11/Xosdefs.h> +#include <X11/Xfuncproto.h> +#include <X11/Xmd.h> + +/* 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_PROCESSED_ARCHIVE -1 + +/* #define UNINIT_SECTION */ +#define HANDLE_IN_HASH_ENTRY + +/* + * 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; +typedef struct _loader_item { + char *name ; + void *address ; + itemPtr next ; + int handle ; + int module ; + itemPtr exports; +#if defined(__powerpc__) + /* + * PowerPC file formats require special routines in some circumstances + * to assist in the linking process. See the specific loader for + * more details. + */ + union { + unsigned short plt[8]; /* ELF */ + unsigned short glink[14]; /* XCOFF */ + } code ; +#endif + } itemRec ; + +/* The following structures provide an interface to GDB (note that GDB + has copies of the definitions - if you change anything here make + sure that the changes are also made to GDB */ + +typedef struct { + char *name; /* Name of this symbol */ + unsigned int namelen; /* Name of this module */ + void *addr; /* Start address of the .text section */ +} LDRCommon, *LDRCommonPtr; + +typedef struct x_LDRModuleRec{ + unsigned int version; /* Version of this struct */ + char *name; /* Name of this module */ + unsigned int namelen; /* Length of name */ + void *text; /* Start address of the .text section */ + void *data; /* Start address of the .data section */ + void *rodata; /* Start address of the .rodata section */ + void *bss; /* Start address of the .bss section */ + LDRCommonPtr commons; /* List of commmon symbols */ + int commonslen; /* Number of common symbols */ + struct x_LDRModuleRec *next; /* Next module record in chain */ +} LDRModuleRec, *LDRModulePtr; + +extern char DebuggerPresent; +extern LDRModulePtr ModList; +extern LDRCommonPtr ldrCommons; +extern int nCommons; + +/* + * The loader uses loader specific alloc/calloc/free functions that + * are mapped to either to the regular Xserver functions, or in a couple + * of special cases, mapped to the C library functions. + */ +#if !defined(PowerMAX_OS) && !(defined(linux) && (defined(__alpha__) || defined(__powerpc__) || defined(__ia64__))) && 0 +#define xf86loadermalloc(size) xalloc(size) +#define xf86loaderrealloc(ptr,size) xrealloc(ptr,size) +#define xf86loadercalloc(num,size) xcalloc(num,size) +#define xf86loaderfree(ptr) xfree(ptr) +#define xf86loaderstrdup(ptr) xstrdup(ptr) +#else +/* + * On Some OSes, xalloc() et al uses mmap to allocate space for large + * allocation. This has the effect of placing the text section of some + * modules very far away from the rest which are placed on the heap. + * Certain relocations are limited in the size of the offsets that can be + * handled, and this seperation causes these relocation to overflow. This + * is fixed by just using the C library allocation functions for the loader + * to ensure that all text sections are located on the heap. OSes that have + * this problem are: + * PowerMAX_OS/PPC + * Linux/Alpha + * Linux/PPC + * Linux/IA-64 + */ +#define xf86loadermalloc(size) malloc(size) +#define xf86loaderrealloc(ptr,size) realloc(ptr,size) +#define xf86loadercalloc(num,size) calloc(num,size) +#define xf86loaderfree(ptr) free(ptr) +#define xf86loaderstrdup(ptr) strdup(ptr) +#endif + +typedef struct _loader *loaderPtr; + +/* + * _loader_funcs hold the entry points for a module format. + */ + +typedef void * (*LoadModuleProcPtr)(loaderPtr modrec, int fd, LOOKUP **); +typedef void (*ResolveSymbolsProcPtr)(void *); +typedef int (*CheckForUnresolvedProcPtr)(void *); +typedef char * (*AddressToSectionProcPtr)(void *, unsigned long); +typedef void (*LoaderUnloadProcPtr)(void *); + +typedef struct _loader_funcs { + LoadModuleProcPtr LoadModule; + ResolveSymbolsProcPtr ResolveSymbols; + CheckForUnresolvedProcPtr CheckForUnresolved; + AddressToSectionProcPtr AddressToSection; + LoaderUnloadProcPtr LoaderUnload; + LoaderRelocRec pRelocs; /* type specific relocations */ +} loader_funcs; + +/* Each module loaded has a loaderRec */ +typedef struct _loader { + int handle; /* Unique id used to remove symbols from + this module when it is unloaded */ + int module; /* Unique id to identify compilation units */ + char *name; + char *cname; + void *private; /* format specific data */ + loader_funcs *funcs; /* funcs for operating on this module */ + loaderPtr next; +} loaderRec; + +/* Compiled-in version information */ +typedef struct { + INT32 xf86Version; + INT32 ansicVersion; + INT32 videodrvVersion; + INT32 xinputVersion; + INT32 extensionVersion; + INT32 fontVersion; +} ModuleVersions; +extern ModuleVersions LoaderVersionInfo; + +extern unsigned long LoaderOptions; + +/* Internal Functions */ + +void LoaderAddSymbols(int, int, LOOKUP *); +void LoaderDefaultFunc(void); +void LoaderDuplicateSymbol(const char *, const int); +#if 0 +void LoaderFixups(void); +#endif +void LoaderResolve(void); +int LoaderResolveSymbols(void); +int _LoaderHandleUnresolved(char *, char *); +void LoaderHashAdd(itemPtr); +itemPtr LoaderHashDelete(const char *); +itemPtr LoaderHashFind(const char *); +void LoaderHashTraverse(void *, int (*)(void *, itemPtr)); +void LoaderPrintAddress(const char *); +void LoaderPrintItem(itemPtr); +void LoaderPrintSymbol(unsigned long); +void LoaderDumpSymbols(void); +char *_LoaderModuleToName(int); +int _LoaderAddressToSection(const unsigned long, const char **, const char **); +int LoaderOpen(const char *, const char *, int, int *, int *, int *); +int LoaderHandleOpen(int); + +/* + * File interface functions + */ +void *_LoaderFileToMem(int fd, unsigned long offset, int size, char *label); +void _LoaderFreeFileMem(void *addr, int size); +int _LoaderFileRead(int fd, unsigned int offset, void *addr, int size); + +/* + * Relocation list manipulation routines + */ +LoaderRelocPtr _LoaderGetRelocations(void *); + +/* + * object to name lookup routines + */ +char * _LoaderHandleToName(int handle); +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 **); + +extern void _loader_debug_state(void); + +#endif /* _LOADER_H */ diff --git a/hw/xfree86/loader/loaderProcs.h b/hw/xfree86/loader/loaderProcs.h new file mode 100644 index 000000000..ff6c64b07 --- /dev/null +++ b/hw/xfree86/loader/loaderProcs.h @@ -0,0 +1,96 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/loader/loaderProcs.h,v 1.19 2002/07/30 18:36:18 dawes 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. + */ + +#ifndef _LOADERPROCS_H +#define _LOADERPROCS_H + +#define IN_LOADER +#include "xf86Module.h" +#include "fontmod.h" + +typedef struct module_desc { + struct module_desc *child; + struct module_desc *sib; + struct module_desc *parent; + struct module_desc *demand_next; + char *name; + char *filename; + char *identifier; + XID client_id; + int in_use; + int handle; + ModuleSetupProc SetupProc; + ModuleTearDownProc TearDownProc; + void *TearDownData; /* returned from SetupProc */ + const char *path; + const XF86ModuleVersionInfo *VersionInfo; +} ModuleDesc, *ModuleDescPtr; + + +/* + * Extenal API for the loader + */ + +void LoaderInit(void); + +ModuleDescPtr LoadDriver(const char *, const char *, int, pointer, int *, + int *); +ModuleDescPtr LoadModule(const char *, const char *, const char **, + const char **, pointer, const XF86ModReqInfo *, + int *, int *); +ModuleDescPtr LoadSubModule(ModuleDescPtr, const char *, + const char **, const char **, pointer, + const XF86ModReqInfo *, int *, int *); +ModuleDescPtr DuplicateModule(ModuleDescPtr mod, ModuleDescPtr parent); +void LoadFont (FontModule *); +void UnloadModule (ModuleDescPtr); +void UnloadSubModule (ModuleDescPtr); +void UnloadDriver (ModuleDescPtr); +void FreeModuleDesc (ModuleDescPtr mod); +ModuleDescPtr NewModuleDesc (const char *); +ModuleDescPtr AddSibling (ModuleDescPtr head, ModuleDescPtr new); +void LoaderSetPath(const char *path); +void LoaderSortExtensions(void); + + +void LoaderVReqSymLists(const char **, va_list args); +void LoaderVReqSymbols(const char *, va_list args); +void LoaderVRefSymLists(const char **, va_list args); +void LoaderVRefSymbols(const char *, va_list args); + +void LoaderShowStack(void); +void *LoaderSymbolHandle(const char *, int); +int LoaderUnload(int); +unsigned long LoaderGetModuleVersion(ModuleDescPtr mod); + +void LoaderResetOptions(void); +void LoaderSetOptions(unsigned long); +void LoaderClearOptions(unsigned long); + +/* Options for LoaderSetOptions */ +#define LDR_OPT_ABI_MISMATCH_NONFATAL 0x0001 + + +#endif /* _LOADERPROCS_H */ diff --git a/hw/xfree86/loader/loadext.c b/hw/xfree86/loader/loadext.c new file mode 100644 index 000000000..206c8296a --- /dev/null +++ b/hw/xfree86/loader/loadext.c @@ -0,0 +1,419 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/loader/loadext.c,v 1.6 2000/02/08 17:19:19 dawes Exp $ */ + +/* Copyright 2000 by The XFree86 Project, Inc */ + +/* Maybe this file belongs elsewhere? */ + +#define LOADERDECLARATIONS +#include "loaderProcs.h" +#include "misc.h" +#include "xf86.h" + +ExtensionModule *ExtensionModuleList = NULL; +static int numExtensionModules = 0; + + +static ExtensionModule * +NewExtensionModule(void) +{ + ExtensionModule *save = ExtensionModuleList; + int n; + + /* Sanity check */ + if (!ExtensionModuleList) + numExtensionModules = 0; + + n = numExtensionModules + 1; + ExtensionModuleList = xrealloc(ExtensionModuleList, + (n + 1) * sizeof(ExtensionModule)); + if (ExtensionModuleList == NULL) { + ExtensionModuleList = save; + return NULL; + } else { + numExtensionModules++; + ExtensionModuleList[numExtensionModules].name = NULL; + return ExtensionModuleList + (numExtensionModules - 1); + } +} + +void +LoadExtension(ExtensionModule *e, Bool builtin) +{ + ExtensionModule *newext; + + if (e == NULL || e->name == NULL) + return; + + if (!(newext = NewExtensionModule())) + return; + + if (builtin) + xf86MsgVerb(X_INFO, 2, "Initializing built-in extension %s\n", + e->name); + else + xf86MsgVerb(X_INFO, 2, "Loading extension %s\n", e->name); + + newext->name = e->name; + newext->initFunc = e->initFunc; + newext->disablePtr = e->disablePtr; + newext->setupFunc = e->setupFunc; + newext->initDependencies = e->initDependencies; + + if (e->setupFunc != NULL) + e->setupFunc(); +} + + +/* + * Sort ExtensionModuleList according to the initialisation order + * dependencies. The code for this is taken from BSD's tsort, + * and carries the following copyright/license: + * + * + * Copyright (c) 1989, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Michael Rendell of Memorial University of Newfoundland. + * + * 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 the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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. + */ + + +#define NF_MARK 0x1 /* marker for cycle detection */ +#define NF_ACYCLIC 0x2 /* this node is cycle free */ +#define NF_NODEST 0x4 /* Unreachable */ + +typedef struct node_str NODE; +struct node_str { + NODE **n_prevp; /* pointer to previous node's n_next */ + NODE *n_next; /* next node in graph */ + NODE **n_arcs; /* array of arcs to other nodes */ + int n_narcs; /* number of arcs in n_arcs[] */ + int n_arcsize; /* size of n_arcs[] array */ + int n_refcnt; /* # of arcs pointing to this node */ + int n_flags; /* NF_* */ + const char *n_name; /* name of this node */ +}; + +static NODE *graph = NULL, **cycle_buf = NULL, **longest_cycle = NULL; +static int longest = 0; +static NODE *sorted = NULL, *last = NULL; + +/* Find a node in the graph (insert if not found) and return a pointer to it. */ +static NODE * +get_node(const char *name) +{ + NODE *n; + + for (n = graph; n && n->n_name && strcmp(n->n_name, name); n = n->n_next) + ; + if (n) + return (n); + + n = xnfalloc(sizeof(NODE)); + + n->n_narcs = 0; + n->n_arcsize = 0; + n->n_arcs = NULL; + n->n_refcnt = 0; + n->n_flags = 0; + n->n_name = name; + + /* Add to linked list. */ + if ((n->n_next = graph) != NULL) + graph->n_prevp = &n->n_next; + n->n_prevp = &graph; + graph = n; + + return (n); +} + + +/* + * add an arc from node s1 to node s2 in the graph. If s1 or s2 are not in + * the graph, then add them. + */ +static void +add_arc(const char *s1, const char *s2) +{ + NODE *n1; + NODE *n2; + int bsize, i; + + n1 = get_node(s1); + + if (!strcmp(s1, s2)) + return; + + n2 = get_node(s2); + + /* + * Check if this arc is already here. + */ + for (i = 0; i < n1->n_narcs; i++) + if (n1->n_arcs[i] == n2) + return; + /* + * Add it. + */ + if (n1->n_narcs == n1->n_arcsize) { + if (!n1->n_arcsize) + n1->n_arcsize = 10; + bsize = n1->n_arcsize * sizeof(*n1->n_arcs) * 2; + n1->n_arcs = xnfrealloc(n1->n_arcs, bsize); + n1->n_arcsize = bsize / sizeof(*n1->n_arcs); + } + n1->n_arcs[n1->n_narcs++] = n2; + ++n2->n_refcnt; +} + +/* + * Clear the NODEST flag from all nodes. + */ +static void +clear_cycle(void) +{ + NODE *n; + + for (n = graph; n != NULL; n = n->n_next) + n->n_flags &= ~NF_NODEST; +} + +/* print node and remove from graph (does not actually free node) */ +static void +remove_node(NODE *n) +{ + NODE **np; + NODE *newnode; + int i; + +#ifdef DEBUG + ErrorF("%s\n", n->n_name); +#endif + newnode = xnfalloc(sizeof(NODE)); + memcpy(newnode, n, sizeof(NODE)); + if (last) + last->n_next = newnode; + else + sorted = newnode; + last = newnode; + newnode->n_next = NULL; + + for (np = n->n_arcs, i = n->n_narcs; --i >= 0; np++) + --(*np)->n_refcnt; + n->n_narcs = 0; + *n->n_prevp = n->n_next; + if (n->n_next) + n->n_next->n_prevp = n->n_prevp; +} + + +static void +free_nodes(NODE *nodelist) +{ + NODE *n, *nextnode; + + for (n = nodelist; n;) { + nextnode = n->n_next; + xfree(n); + n = nextnode; + } +} + + +/* look for the longest? cycle from node from to node to. */ +static int +find_cycle(NODE *from, NODE *to, int longest_len, int depth) +{ + NODE **np; + int i, len; + + /* + * avoid infinite loops and ignore portions of the graph known + * to be acyclic + */ + if (from->n_flags & (NF_NODEST|NF_MARK|NF_ACYCLIC)) + return (0); + from->n_flags |= NF_MARK; + + for (np = from->n_arcs, i = from->n_narcs; --i >= 0; np++) { + cycle_buf[depth] = *np; + if (*np == to) { + if (depth + 1 > longest_len) { + longest_len = depth + 1; + memcpy((char *)longest_cycle, + (char *)cycle_buf, + longest_len * sizeof(NODE *)); + } + } else { + if ((*np)->n_flags & (NF_MARK|NF_ACYCLIC|NF_NODEST)) + continue; + len = find_cycle(*np, to, longest_len, depth + 1); + +#ifdef DEBUG + ErrorF("%*s %s->%s %d\n", depth, "", + from->n_name, to->n_name, len); +#endif + + if (len == 0) + (*np)->n_flags |= NF_NODEST; + + if (len > longest_len) + longest_len = len; + + if (len > 0 && !longest) + break; + } + } + from->n_flags &= ~NF_MARK; + return (longest_len); +} + + +/* do topological sort on graph */ +static void +tsort(void) +{ + NODE *n, *next; + int cnt, i; + + while (graph != NULL) { + /* + * Keep getting rid of simple cases until there are none left, + * if there are any nodes still in the graph, then there is + * a cycle in it. + */ + do { + for (cnt = 0, n = graph; n != NULL; n = next) { + next = n->n_next; + if (n->n_refcnt == 0) { + remove_node(n); + ++cnt; + } + } + } while (graph != NULL && cnt); + + if (graph == NULL) + break; + + if (!cycle_buf) { + /* + * Allocate space for two cycle logs - one to be used + * as scratch space, the other to save the longest + * cycle. + */ + for (cnt = 0, n = graph; n != NULL; n = n->n_next) + ++cnt; + cycle_buf = xnfalloc(sizeof(NODE *) * cnt); + longest_cycle = xnfalloc(sizeof(NODE *) * cnt); + if (cycle_buf == NULL || longest_cycle == NULL) + return; + } + for (n = graph; n != NULL; n = n->n_next) + if (!(n->n_flags & NF_ACYCLIC)) { + if ((cnt = find_cycle(n, n, 0, 0))) { + ErrorF("tsort: cycle in data"); + for (i = 0; i < cnt; i++) + ErrorF("%s", + longest_cycle[i]->n_name); + remove_node(n); + clear_cycle(); + break; + } else { + /* to avoid further checks */ + n->n_flags |= NF_ACYCLIC; + clear_cycle(); + } + } + + if (n == NULL) + ErrorF("tsort: internal error -- could not find cycle"); + } + if (cycle_buf) + xfree(cycle_buf); + if (longest_cycle) + xfree(longest_cycle); + if (graph) + free_nodes(graph); +} + +void +LoaderSortExtensions() +{ + int i, j; + ExtensionModule *ext, *newList; + NODE *node; + + graph = NULL; + longest = 0; + sorted = NULL; + last = NULL; + cycle_buf = NULL; + longest_cycle = NULL; + + /* + * Parse list and build the graph. Enter them in reverse order + * because tsort() will reverse those that have no depedencies. + */ + for (i = numExtensionModules - 1; i >= 0; i--) { + ext = &ExtensionModuleList[i]; + add_arc(ext->name, ext->name); +#ifdef DEBUG + ErrorF("Extension %s:\n", ext->name); +#endif + if (ext->initDependencies) + for (j = 0; ext->initDependencies[j]; j++) { + add_arc(ext->initDependencies[j], ext->name); +#ifdef DEBUG + ErrorF("\t%s\n", ext->initDependencies[j]); +#endif + } + } + tsort(); + newList = xnfalloc((numExtensionModules + 1) * sizeof(ExtensionModule)); + i = 0; + for (node = sorted; node; node = node->n_next) { + for (j = 0; j < numExtensionModules; j++) + if (!strcmp(node->n_name, ExtensionModuleList[j].name)) + break; + if (j != numExtensionModules) + newList[i++] = ExtensionModuleList[j]; + } + if (sorted) + free_nodes(sorted); + newList[i].name = NULL; + xfree(ExtensionModuleList); + ExtensionModuleList = newList; +#ifdef DEBUG + for (i = 0; ExtensionModuleList[i].name; i++) + ErrorF("Extension %s\n", ExtensionModuleList[i].name); +#endif +} + diff --git a/hw/xfree86/loader/loadfont.c b/hw/xfree86/loader/loadfont.c new file mode 100644 index 000000000..8ab5d0d6e --- /dev/null +++ b/hw/xfree86/loader/loadfont.c @@ -0,0 +1,53 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/loader/loadfont.c,v 1.2 1998/12/13 12:42:41 dawes Exp $ */ + +/* Maybe this file belongs in lib/font/fontfile/module/ ? */ + +#define LOADERDECLARATIONS +#include "loaderProcs.h" +#include "misc.h" +#include "xf86.h" + +FontModule *FontModuleList = NULL; +static int numFontModules = 0; + + +static FontModule * +NewFontModule(void) +{ + FontModule *save = FontModuleList; + int n; + + /* Sanity check */ + if (!FontModuleList) + numFontModules = 0; + + n = numFontModules + 1; + FontModuleList = xrealloc(FontModuleList, (n + 1) * sizeof(FontModule)); + if (FontModuleList == NULL) { + FontModuleList = save; + return NULL; + } else { + numFontModules++; + FontModuleList[numFontModules].name = NULL; + return FontModuleList + (numFontModules - 1); + } +} + +void +LoadFont(FontModule *f) +{ + FontModule *newfont; + + if (f == NULL) + return; + + if (!(newfont = NewFontModule())) + return; + + xf86MsgVerb(X_INFO, 2, "Loading font %s\n", f->name); + + newfont->name = f->name; + newfont->initFunc = f->initFunc; + newfont->module = f->module; +} + diff --git a/hw/xfree86/loader/loadmod.c b/hw/xfree86/loader/loadmod.c new file mode 100644 index 000000000..deba80643 --- /dev/null +++ b/hw/xfree86/loader/loadmod.c @@ -0,0 +1,1296 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/loader/loadmod.c,v 1.68 2002/07/30 18:36:18 dawes 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. + */ + +/* This file is best viewed with tab stops set to 4 spaces */ + +#include "os.h" +/* For stat() and related stuff */ +#define NO_OSLIB_PROTOTYPES +#include "xf86_OSlib.h" +#define LOADERDECLARATIONS +#include "loaderProcs.h" +#include "misc.h" +#include "xf86.h" +#include "xf86Priv.h" +#ifdef XINPUT +#include "xf86Xinput.h" +#endif +#include "loader.h" +#include "xf86Optrec.h" + +#include <sys/types.h> +#include <regex.h> +#include <dirent.h> +#include <limits.h> + +extern int check_unresolved_sema; + +typedef struct _pattern { + const char * pattern; + regex_t rex; +} PatternRec, *PatternPtr; + +/* Prototypes for static functions */ +static char *FindModule (const char *, const char *, const char **, PatternPtr); +static Bool CheckVersion (const char *, XF86ModuleVersionInfo *, + const XF86ModReqInfo *); +static void UnloadModuleOrDriver (ModuleDescPtr mod); +static char *LoaderGetCanonicalName(const char *, PatternPtr); +static void RemoveChild(ModuleDescPtr); + +ModuleVersions LoaderVersionInfo = { + XF86_VERSION_CURRENT, + ABI_ANSIC_VERSION, + ABI_VIDEODRV_VERSION, + ABI_XINPUT_VERSION, + ABI_EXTENSION_VERSION, + ABI_FONT_VERSION +}; + +#if 0 +void +LoaderFixups (void) +{ + /* Need to call LRS here because the frame buffers get loaded last, + * and the drivers depend on them. */ + + LoaderResolveSymbols (); +} +#endif + +static void +FreeStringList(char **paths) +{ + char **p; + + if (!paths) + return; + + for (p = paths; *p; p++) + xfree(*p); + + xfree(paths); +} + +static char **defaultPathList = NULL; + +/* + * Convert a comma-separated path into a NULL-terminated array of path + * elements, rejecting any that are not full absolute paths, and appending + * a '/' when it isn't already present. + */ +static char ** +InitPathList(const char *path) +{ + char *fullpath = NULL; + char *elem = NULL; + char **list = NULL, **save = NULL; + int len; + int addslash; + int n = 0; + + if (!path) + return defaultPathList; + + fullpath = xstrdup(path); + if (!fullpath) + return NULL; + elem = strtok(fullpath, ","); + while (elem) { + /* Only allow fully specified paths */ +#ifndef __UNIXOS2__ + if (*elem == '/') +#else + if (*elem == '/' || (strlen(elem) > 2 && isalpha(elem[0]) && + elem[1] == ':' && elem[2] == '/')) +#endif + { + len = strlen(elem); + addslash = (elem[len - 1] != '/'); + if (addslash) + len++; + save = list; + list = xrealloc(list, (n + 2) * sizeof(char *)); + if (!list) { + if (save) { + save[n] = NULL; + FreeStringList(save); + } + xfree(fullpath); + return NULL; + } + list[n] = xalloc(len + 1); + if (!list[n]) { + FreeStringList(list); + xfree(fullpath); + return NULL; + } + strcpy(list[n], elem); + if (addslash) { + list[n][len - 1] = '/'; + list[n][len] = '\0'; + } + n++; + } + elem = strtok(NULL, ","); + } + if (list) + list[n] = NULL; + return list; +} + +static void +FreePathList(char **pathlist) +{ + if (pathlist && pathlist != defaultPathList) + FreeStringList(pathlist); +} + +void +LoaderSetPath(const char *path) +{ + if (!path) + return; + + defaultPathList = InitPathList(path); +} + +/* Standard set of module subdirectories to search, in order of preference */ +static const char *stdSubdirs[] = +{ + "drivers/", + "input/", + "multimedia/", + "extensions/", + "fonts/", + "internal/", + "", + NULL +}; + +/* + * Standard set of module name patterns to check, in order of preference + * These are regular expressions (suitable for use with POSIX regex(3)). + */ +static PatternRec stdPatterns[] = { + { "^lib(.*)\\.so$", }, + { "^lib(.*)\\.a$", }, + { "(.*)_drv\\.so$", }, + { "(.*)_drv\\.o$", }, + { "(.*)\\.so$", }, + { "(.*)\\.a$", }, + { "(.*)\\.o$", }, + { NULL, } +}; + +static PatternPtr +InitPatterns(const char **patternlist) +{ + char errmsg[80]; + int i, e; + PatternPtr patterns = NULL; + PatternPtr p = NULL; + static int firstTime = 1; + const char **s; + + if (firstTime) { + /* precompile stdPatterns */ + firstTime = 0; + for (p = stdPatterns; p->pattern; p++) + if ((e = regcomp(&p->rex, p->pattern, REG_EXTENDED)) != 0) { + regerror(e, &p->rex, errmsg, sizeof(errmsg)); + FatalError("InitPatterns: regcomp error for `%s': %s\n", + p->pattern, errmsg); + } + } + + if (patternlist) { + for (i = 0, s = patternlist; *s; i++, s++) + if (*s == DEFAULT_LIST) + i += sizeof(stdPatterns) / sizeof(stdPatterns[0]) - 1 - 1; + patterns = xalloc((i + 1) * sizeof(PatternRec)); + if (!patterns) { + return NULL; + } + for (i = 0, s = patternlist; *s; i++, s++) + if (*s != DEFAULT_LIST) { + p = patterns + i; + p->pattern = *s; + if ((e = regcomp(&p->rex, p->pattern, REG_EXTENDED)) != 0) { + regerror(e, &p->rex, errmsg, sizeof(errmsg)); + ErrorF("InitPatterns: regcomp error for `%s': %s\n", + p->pattern, errmsg); + i--; + } + } else { + for (p = stdPatterns; p->pattern; p++, i++) + patterns[i] = *p; + if (p != stdPatterns) + i--; + } + patterns[i].pattern = NULL; + } else + patterns = stdPatterns; + return patterns; +} + +static void +FreePatterns(PatternPtr patterns) +{ + if (patterns && patterns != stdPatterns) + xfree(patterns); +} + +static const char ** +InitSubdirs(const char **subdirlist) +{ + int i; + char **subdirs = NULL; + const char **s, **stmp = NULL; + const char *osname; + const char *slash; + int oslen = 0, len; + Bool indefault; + + if (subdirlist == NULL) { + subdirlist = xalloc(2 * sizeof(char *)); + if (subdirlist == NULL) + return NULL; + subdirlist[0] = DEFAULT_LIST; + subdirlist[1] = NULL; + } + + LoaderGetOS(&osname, NULL, NULL, NULL); + oslen = strlen(osname); + + { + /* Count number of entries and check for invalid paths */ + for (i = 0, s = subdirlist; *s; i++, s++) { + if (*s == DEFAULT_LIST) { + i += sizeof(stdSubdirs) / sizeof(stdSubdirs[0]) - 1 - 1; + } else { + /* + * Path validity check. Don't allow absolute paths, or + * paths containing "..". To catch absolute paths on + * platforms that use driver letters, don't allow the ':' + * character to appear at all. + */ + if (**s == '/' || **s == '\\' || strchr(*s, ':') || + strstr(*s, "..")) { + xf86Msg(X_ERROR, "InitSubdirs: Bad subdir: \"%s\"\n", *s); + return NULL; + } + } + } + subdirs = xalloc((i * 2 + 1) * sizeof(char *)); + if (!subdirs) + return NULL; + i = 0; + s = subdirlist; + indefault = FALSE; + while (*s) { + if (*s == DEFAULT_LIST) { + /* Divert to the default list */ + indefault = TRUE; + stmp = ++s; + s = stdSubdirs; + } + len = strlen(*s); + if (**s && (*s)[len - 1] != '/') { + slash = "/"; + len++; + } else + slash = ""; + len += oslen + 2; + if (!(subdirs[i] = xalloc(len))) + return NULL; + /* tack on the OS name */ + sprintf(subdirs[i], "%s%s%s/", *s, slash, osname); + i++; + /* path as given */ + subdirs[i] = xstrdup(*s); + i++; + s++; + if (indefault && !s) { + /* revert back to the main list */ + indefault = FALSE; + s = stmp; + } + } + subdirs[i] = NULL; + } + return (const char **)subdirs; +} + +static void +FreeSubdirs(const char **subdirs) +{ + const char **s; + + if (subdirs) { + for (s = subdirs; *s; s++) + xfree(*s); + xfree(subdirs); + } +} + +static char * +FindModule (const char *module, const char *dir, const char **subdirlist, + PatternPtr patterns) +{ + char buf[PATH_MAX + 1]; + char *dirpath = NULL; + char *name = NULL; + struct stat stat_buf; + int len, dirlen; + char *fp; + DIR *d; + const char **subdirs = NULL; + PatternPtr p = NULL; + const char **s; + struct dirent *dp; + regmatch_t match[2]; + + subdirs = InitSubdirs(subdirlist); + if (!subdirs) + return NULL; + +#ifndef __EMX__ + dirpath = (char *)dir; +#else + dirpath = xalloc(strlen(dir) + 10); + strcpy(dirpath, (char *) __XOS2RedirRoot (dir)); +#endif + if (strlen(dirpath) > PATH_MAX) + return NULL; + /*xf86Msg(X_INFO,"OS2DIAG: FindModule: dirpath=%s\n",dirpath);*/ + + for (s = subdirs; *s; s++) { + if ((dirlen = strlen(dirpath) + strlen(*s)) > PATH_MAX) + continue; + strcpy(buf, dirpath); + strcat(buf, *s); + /*xf86Msg(X_INFO,"OS2DIAG: FindModule: buf=%s\n",buf);*/ + fp = buf + dirlen; + if (stat(buf, &stat_buf) == 0 && S_ISDIR(stat_buf.st_mode) && + (d = opendir(buf))) { + if (buf[dirlen - 1] != '/') { + buf[dirlen++] = '/'; + fp++; + } + while ((dp = readdir(d))) { + if (dirlen + strlen(dp->d_name) + 1 > PATH_MAX) + continue; + strcpy(fp, dp->d_name); + if (!(stat(buf, &stat_buf) == 0 && S_ISREG(stat_buf.st_mode))) + continue; + for (p = patterns; p->pattern; p++) { + if (regexec(&p->rex, dp->d_name, 2, match, 0) == 0 && + match[1].rm_so != -1) { + len = match[1].rm_eo - match[1].rm_so; + if (len == strlen(module) && + strncmp(module, dp->d_name + match[1].rm_so, len) == 0) { + /*xf86Msg(X_INFO,"OS2DIAG: matching %s\n",buf);*/ + name = buf; + break; + } + } + } + if (name) + break; + } + closedir(d); + if (name) + break; + } + } + FreeSubdirs(subdirs); + if (dirpath != dir) + xfree(dirpath); + + if (name) { + return xstrdup(name); + } + return NULL; +} + +char ** +LoaderListDirs(const char **subdirlist, const char **patternlist) +{ + char buf[PATH_MAX + 1]; + char **pathlist; + char **elem; + const char **subdirs; + const char **s; + PatternPtr patterns; + PatternPtr p; + DIR *d; + struct dirent *dp; + regmatch_t match[2]; + struct stat stat_buf; + int len, dirlen; + char *fp; + char **listing = NULL; + char **save; + int n = 0; + + if (!(pathlist = InitPathList(NULL))) + return NULL; + if (!(subdirs = InitSubdirs(subdirlist))) { + FreePathList(pathlist); + return NULL; + } + if (!(patterns = InitPatterns(patternlist))) { + FreePathList(pathlist); + FreeSubdirs(subdirs); + return NULL; + } + + for (elem = pathlist; *elem; elem++) { + for (s = subdirs; *s; s++) { + if ((dirlen = strlen(*elem) + strlen(*s)) > PATH_MAX) + continue; + strcpy(buf, *elem); + strcat(buf, *s); + fp = buf + dirlen; + if (stat(buf, &stat_buf) == 0 && S_ISDIR(stat_buf.st_mode) && + (d = opendir(buf))) { + if (buf[dirlen - 1] != '/') { + buf[dirlen++] = '/'; + fp++; + } + while ((dp = readdir(d))) { + if (dirlen + strlen(dp->d_name) > PATH_MAX) + continue; + strcpy(fp, dp->d_name); + if (!(stat(buf, &stat_buf) == 0 && + S_ISREG(stat_buf.st_mode))) + continue; + for (p = patterns; p->pattern; p++) { + if (regexec(&p->rex, dp->d_name, 2, match, 0) == 0 && + match[1].rm_so != -1) { + len = match[1].rm_eo - match[1].rm_so; + save = listing; + listing = xrealloc(listing, + (n + 2) * sizeof(char *)); + if (!listing) { + if (save) { + save[n] = NULL; + FreeStringList(save); + } + FreePathList(pathlist); + FreeSubdirs(subdirs); + FreePatterns(patterns); + return NULL; + } + listing[n] = xalloc(len + 1); + if (!listing[n]) { + FreeStringList(listing); + FreePathList(pathlist); + FreeSubdirs(subdirs); + FreePatterns(patterns); + return NULL; + } + strncpy(listing[n], dp->d_name + match[1].rm_so, + len); + listing[n][len] = '\0'; + n++; + break; + } + } + } + closedir(d); + } + } + } + if (listing) + listing[n] = NULL; + return listing; +} + +void +LoaderFreeDirList(char **list) +{ + FreeStringList(list); +} + + +static Bool +CheckVersion (const char *module, XF86ModuleVersionInfo *data, + const XF86ModReqInfo *req) +{ + int vercode[4]; + char verstr[4]; + long ver = data->xf86version; + int errtype = 0; + + xf86Msg (X_INFO, "Module %s: vendor=\"%s\"\n", + data->modname ? data->modname : "UNKNOWN!", + data->vendor ? data->vendor : "UNKNOWN!"); + + if (ver > (4 << 24)) { + /* 4.0.x and earlier */ + verstr[1] = verstr[3] = 0; + verstr[2] = (ver & 0x1f) ? (ver & 0x1f) + 'a' - 1 : 0; + ver >>= 5; + verstr[0] = (ver & 0x1f) ? (ver & 0x1f) + 'A' - 1 : 0; + ver >>= 5; + vercode[2] = ver & 0x7f; + ver >>= 7; + vercode[1] = ver & 0x7f; + ver >>= 7; + vercode[0] = ver; + xf86ErrorF("\tcompiled for %d.%d", vercode[0], vercode[1]); + if (vercode[2] != 0) + xf86ErrorF(".%d", vercode[2]); + xf86ErrorF("%s%s, module version = %d.%d.%d\n", verstr, verstr + 2, + data->majorversion, data->minorversion, data->patchlevel); + } else { + vercode[0] = ver / 10000000; + vercode[1] = (ver / 100000) % 100; + vercode[2] = (ver / 1000) % 100; + vercode[3] = ver % 1000; + xf86ErrorF("\tcompiled for %d.%d.%d", vercode[0], vercode[1], + vercode[2]); + if (vercode[3] != 0) + xf86ErrorF(".%d", vercode[3]); + xf86ErrorF(", module version = %d.%d.%d\n", data->majorversion, + data->minorversion, data->patchlevel); + } + + if (data->moduleclass) + xf86ErrorFVerb(2, "\tModule class: %s\n", data->moduleclass); + + ver = -1; + if (data->abiclass) { + int abimaj, abimin; + int vermaj, vermin; + + if (!strcmp(data->abiclass, ABI_CLASS_ANSIC)) + ver = LoaderVersionInfo.ansicVersion; + else if (!strcmp(data->abiclass, ABI_CLASS_VIDEODRV)) + ver = LoaderVersionInfo.videodrvVersion; + else if (!strcmp(data->abiclass, ABI_CLASS_XINPUT)) + ver = LoaderVersionInfo.xinputVersion; + else if (!strcmp(data->abiclass, ABI_CLASS_EXTENSION)) + ver = LoaderVersionInfo.extensionVersion; + else if (!strcmp(data->abiclass, ABI_CLASS_FONT)) + ver = LoaderVersionInfo.fontVersion; + + abimaj = GET_ABI_MAJOR(data->abiversion); + abimin = GET_ABI_MINOR(data->abiversion); + xf86ErrorFVerb(2, "\tABI class: %s, version %d.%d\n", + data->abiclass, abimaj, abimin); + if (ver != -1) { + vermaj = GET_ABI_MAJOR(ver); + vermin = GET_ABI_MINOR(ver); + if (abimaj != vermaj) { + if (LoaderOptions & LDR_OPT_ABI_MISMATCH_NONFATAL) + errtype = X_WARNING; + else + errtype = X_ERROR; + xf86MsgVerb(errtype, 0, + "module ABI major version (%d) doesn't" + " match the server's version (%d)\n", + abimaj, vermaj); + if (!(LoaderOptions & LDR_OPT_ABI_MISMATCH_NONFATAL)) + return FALSE; + } else if (abimin > vermin) { + if (LoaderOptions & LDR_OPT_ABI_MISMATCH_NONFATAL) + errtype = X_WARNING; + else + errtype = X_ERROR; + xf86MsgVerb(errtype, 0, + "module ABI minor version (%d) is " + "newer than the server's version " + "(%d)\n", abimin, vermin); + if (!(LoaderOptions & LDR_OPT_ABI_MISMATCH_NONFATAL)) + return FALSE; + } + } + } + + /* Check against requirements that the caller has specified */ + if (req) { + if (req->majorversion != MAJOR_UNSPEC) { + if (data->majorversion != req->majorversion) { + xf86MsgVerb(X_WARNING, 2, "module major version (%d) " + "doesn't match required major version (%d)\n", + data->majorversion, req->majorversion); + return FALSE; + } else if (req->minorversion != MINOR_UNSPEC) { + if (data->minorversion < req->minorversion) { + xf86MsgVerb(X_WARNING, 2, "module minor version (%d) " + "is less than the required minor version (%d)\n", + data->minorversion, req->minorversion); + return FALSE; + } else if (data->minorversion == req->minorversion && + req->patchlevel != PATCH_UNSPEC) { + if (data->patchlevel < req->patchlevel) { + xf86MsgVerb(X_WARNING, 2, "module patch level (%d) " + "is less than the required patch level (%d)\n", + data->patchlevel, req->patchlevel); + return FALSE; + } + } + } + } + if (req->moduleclass) { + if (!data->moduleclass || + strcmp(req->moduleclass, data->moduleclass)) { + xf86MsgVerb(X_WARNING, 2, "Module class (%s) doesn't match " + "the required class (%s)\n", + data->moduleclass ? data->moduleclass : "<NONE>", + req->moduleclass); + return FALSE; + } + } else if (req->abiclass != ABI_CLASS_NONE) { + if (!data->abiclass || strcmp(req->abiclass, data->moduleclass)) { + xf86MsgVerb(X_WARNING, 2, "ABI class (%s) doesn't match the " + "required ABI class (%s)\n", + data->abiclass ? data->abiclass : "<NONE>", + req->abiclass); + return FALSE; + } + } + if ((req->abiclass != ABI_CLASS_NONE) && + req->abiversion != ABI_VERS_UNSPEC) { + int reqmaj, reqmin, maj, min; + reqmaj = GET_ABI_MAJOR(req->abiversion); + reqmin = GET_ABI_MINOR(req->abiversion); + maj = GET_ABI_MAJOR(data->abiversion); + min = GET_ABI_MINOR(data->abiversion); + if (maj != reqmaj) { + xf86MsgVerb(X_WARNING, 2, "ABI major version (%d) doesn't " + "match the required ABI major version (%d)\n", + maj, reqmaj); + return FALSE; + } + /* XXX Maybe this should be the other way around? */ + if (min > reqmin) { + xf86MsgVerb(X_WARNING, 2, "module ABI minor version (%d) " + "is new than that available (%d)\n", + min, reqmin); + return FALSE; + } + } + } + +#ifdef NOTYET + if (data->checksum) + { + /* verify the checksum field */ + /* TO BE DONE */ + } + else + { + ErrorF ("\t*** Checksum field is 0 - this module is untrusted!\n"); + } +#endif + return TRUE; +} + +ModuleDescPtr +LoadSubModule(ModuleDescPtr parent, const char *module, + const char **subdirlist, const char **patternlist, + pointer options, const XF86ModReqInfo *modreq, + int *errmaj, int *errmin) +{ + ModuleDescPtr submod; + + xf86MsgVerb(X_INFO, 3, "Loading sub module \"%s\"\n", module); + + /* Absolute module paths are not allowed here */ +#ifndef __UNIXOS2__ + if (module[0] == '/') +#else + if (isalpha (module[0]) && module[1] == ':' && module[2] == '/') +#endif + { + xf86Msg(X_ERROR, + "LoadSubModule: Absolute module path not permitted: \"%s\"\n", + module); + if (errmaj) + *errmaj = LDR_BADUSAGE; + if (errmin) + *errmin = 0; + return NULL; + } + + submod = LoadModule (module, NULL, subdirlist, patternlist, options, + modreq, errmaj, errmin); + if (submod) { + parent->child = AddSibling (parent->child, submod); + submod->parent = parent; + } + return submod; +} + +ModuleDescPtr +DuplicateModule(ModuleDescPtr mod, ModuleDescPtr parent) +{ + ModuleDescPtr ret; + + if (!mod) + return NULL; + + ret = NewModuleDesc(mod->name); + if (ret == NULL) + return NULL; + + if (LoaderHandleOpen(mod->handle) == -1) + return NULL; + + ret->filename = xstrdup(mod->filename); + ret->identifier = mod->identifier; + ret->client_id = mod->client_id; + ret->in_use = mod->in_use; + ret->handle = mod->handle; + ret->SetupProc = mod->SetupProc; + ret->TearDownProc = mod->TearDownProc; + ret->TearDownData = NULL; + ret->path = mod->path; + ret->child = DuplicateModule(mod->child, ret); + ret->sib = DuplicateModule(mod->sib, parent); + ret->parent = parent; + ret->VersionInfo = mod->VersionInfo; + + return ret; +} + +/* + * LoadModule: load a module + * + * module The module name. Normally this is not a filename but the + * module's "canonical name. A full pathname is, however, + * also accepted. + * path A comma separated list of module directories. + * subdirlist A NULL terminated list of subdirectories to search. When + * NULL, the default "stdSubdirs" list is used. The default + * list is also substituted for entries with value DEFAULT_LIST. + * patternlist A NULL terminated list of regular expressions used to find + * module filenames. Each regex should contain exactly one + * subexpression that corresponds to the canonical module name. + * When NULL, the default "stdPatterns" list is used. The + * default list is also substituted for entries with value + * DEFAULT_LIST. + * options A NULL terminated list of Options that are passed to the + * module's SetupProc function. + * modreq An optional XF86ModReqInfo* containing + * version/ABI/vendor-ABI requirements to check for when + * loading the module. The following fields of the + * XF86ModReqInfo struct are checked: + * majorversion - must match the module's majorversion exactly + * minorversion - the module's minorversion must be >= this + * patchlevel - the module's minorversion.patchlevel must be + * >= this. Patchlevel is ignored when + * minorversion is not set. + * abiclass - (string) must match the module's abiclass + * abiversion - must be consistent with the module's + * abiversion (major equal, minor no older) + * moduleclass - string must match the module's moduleclass + * string + * "don't care" values are ~0 for numbers, and NULL for strings + * errmaj Major error return. + * errmin Minor error return. + * + */ + +ModuleDescPtr +LoadModule (const char *module, const char *path, const char **subdirlist, + const char **patternlist, pointer options, + const XF86ModReqInfo * modreq, + int *errmaj, int *errmin) +{ + XF86ModuleData *initdata = NULL; + char **pathlist = NULL; + char *found = NULL; + char *name = NULL; + char **path_elem = NULL; + char *p = NULL; + ModuleDescPtr ret = NULL; + int wasLoaded = 0; + PatternPtr patterns = NULL; + int noncanonical = 0; + char *m = NULL; + + /*xf86Msg(X_INFO,"OS2DIAG: LoadModule: %s\n",module);*/ + xf86MsgVerb(X_INFO, 3, "LoadModule: \"%s\"", module); + + patterns = InitPatterns(patternlist); + name = LoaderGetCanonicalName(module, patterns); + noncanonical = (name && strcmp(module, name) != 0); + if (noncanonical) + { + xf86ErrorFVerb(3, " (%s)\n", name); + xf86MsgVerb(X_WARNING, 1, + "LoadModule: given non-canonical module name \"%s\"\n", + module); + m = name; + } + else + { + xf86ErrorFVerb(3, "\n"); + m = (char *)module; + } + if (!name) { + if (errmaj) + *errmaj = LDR_BADUSAGE; + if (errmin) + *errmin = 0; + goto LoadModule_fail; + } + ret = NewModuleDesc (name); + if (!ret) { + if (errmaj) + *errmaj = LDR_NOMEM; + if (errmin) + *errmin = 0; + goto LoadModule_fail; + } + + pathlist = InitPathList(path); + if (!pathlist) { + /* This could be a malloc failure too */ + if (errmaj) + *errmaj = LDR_BADUSAGE; + if (errmin) + *errmin = 1; + goto LoadModule_fail; + } + + /* + * if the module name is not a full pathname, we need to + * check the elements in the path + */ +#ifndef __UNIXOS2__ + if (module[0] == '/') + found = xstrdup(module); +#else + /* accept a drive name here */ + if (isalpha (module[0]) && module[1] == ':' && module[2] == '/') + found = xstrdup(module); +#endif + path_elem = pathlist; + while (!found && *path_elem != NULL) + { + found = FindModule (m, *path_elem, subdirlist, patterns); + path_elem++; + /* + * When the module name isn't the canonical name, search for the + * former if no match was found for the latter. + */ + if (!*path_elem && m == name) + { + path_elem = pathlist; + m = (char *)module; + } + } + + /* + * did we find the module? + */ + if (!found) + { + xf86Msg (X_WARNING, "Warning, couldn't open module %s\n", + module); + if (errmaj) + *errmaj = LDR_NOENT; + if (errmin) + *errmin = 0; + goto LoadModule_fail; + } + ret->handle = LoaderOpen (found, name, 0, errmaj, errmin, &wasLoaded); + if (ret->handle < 0) + goto LoadModule_fail; + + ret->filename = xstrdup(found); + + /* + * now check if the special data object <modulename>ModuleData is + * present. + */ + p = xalloc (strlen (name) + strlen ("ModuleData") + 1); + if (!p) { + if (errmaj) + *errmaj = LDR_NOMEM; + if (errmin) + *errmin = 0; + goto LoadModule_fail; + } + strcpy (p, name); + strcat (p, "ModuleData"); + initdata = LoaderSymbol (p); + if (initdata) + { + ModuleSetupProc setup; + ModuleTearDownProc teardown; + XF86ModuleVersionInfo *vers; + + vers = initdata->vers; + setup = initdata->setup; + teardown = initdata->teardown; + + if (!wasLoaded) { + if (vers) { + if (!CheckVersion (module, vers, modreq)) { + if (errmaj) + *errmaj = LDR_MISMATCH; + if (errmin) + *errmin = 0; + goto LoadModule_fail; + } + } else { + xf86Msg(X_ERROR, + "LoadModule: Module %s does not supply" + " version information\n", module); + if (errmaj) + *errmaj = LDR_INVALID; + if (errmin) + *errmin = 0; + goto LoadModule_fail; + } + } + if (setup) + ret->SetupProc = setup; + if (teardown) + ret->TearDownProc = teardown; + ret->path = path; + ret->VersionInfo = vers; + } + else + { + /* No initdata is OK for external modules */ + if (options == EXTERN_MODULE) + goto LoadModule_exit; + + /* no initdata, fail the load */ + xf86Msg (X_ERROR, "LoadModule: Module %s does not have a %s " + "data object.\n", module, p); + if (errmaj) + *errmaj = LDR_INVALID; + if (errmin) + *errmin = 0; + goto LoadModule_fail; + } + if (ret->SetupProc) + { + ret->TearDownData = ret->SetupProc (ret, options, errmaj, errmin); + if (!ret->TearDownData) + { + goto LoadModule_fail; + } + } + else if (options) + { + xf86Msg (X_WARNING, "Module Options present, but no SetupProc " + "available for %s\n", module); + } + goto LoadModule_exit; + + LoadModule_fail: + UnloadModule (ret); + ret = NULL; + + LoadModule_exit: + FreePathList(pathlist); + FreePatterns(patterns); + TestFree (found); + TestFree (name); + TestFree (p); + + /* + * If you need to do something to keep the + * instruction cache in sync with the main + * memory before jumping to that code, you may + * do it here. + */ +#ifdef __alpha__ + istream_mem_barrier(); +#endif + return ret; +} + +ModuleDescPtr +LoadDriver (const char *module, const char *path, int handle, pointer options, + int *errmaj, int *errmin) +{ +return LoadModule (module, path, NULL, NULL, options, NULL, errmaj, errmin); +} + +void +UnloadModule (ModuleDescPtr mod) +{ + UnloadModuleOrDriver (mod); +} + +void +UnloadDriver (ModuleDescPtr mod) +{ + UnloadModuleOrDriver (mod); +} + +static void +UnloadModuleOrDriver (ModuleDescPtr mod) +{ + if (mod == NULL || mod->name == NULL) + return; + + xf86MsgVerb(X_INFO, 3, "UnloadModule: \"%s\"\n", mod->name); + + if ((mod->TearDownProc) && (mod->TearDownData)) + mod->TearDownProc (mod->TearDownData); + LoaderUnload (mod->handle); + + if (mod->child) + UnloadModuleOrDriver (mod->child); + if (mod->sib) + UnloadModuleOrDriver (mod->sib); + TestFree (mod->name); + TestFree (mod->filename); + xfree (mod); +#ifdef __alpha__ + istream_mem_barrier(); +#endif +} + +void +UnloadSubModule(ModuleDescPtr mod) +{ + if (mod == NULL || mod->name == NULL) + return; + + xf86MsgVerb(X_INFO, 3, "UnloadSubModule: \"%s\"\n", mod->name); + + if ((mod->TearDownProc) && (mod->TearDownData)) + mod->TearDownProc (mod->TearDownData); + LoaderUnload (mod->handle); + + RemoveChild(mod); + + if (mod->child) + UnloadModuleOrDriver (mod->child); + + TestFree (mod->name); + TestFree (mod->filename); + xfree (mod); +} + +void +FreeModuleDesc (ModuleDescPtr head) +{ + ModuleDescPtr sibs, prev; + + /* + * only free it if it's not marked as in use. In use means that it may + * be unloaded someday, and UnloadModule or UnloadDriver will free it + */ + if (head->in_use) + return; + if (head->child) + FreeModuleDesc (head->child); + sibs = head; + while (sibs) + { + prev = sibs; + sibs = sibs->sib; + TestFree (prev->name); + xfree (prev); + } +} + +ModuleDescPtr +NewModuleDesc (const char *name) +{ + ModuleDescPtr mdp = xalloc (sizeof (ModuleDesc)); + + if (mdp) + { + mdp->child = NULL; + mdp->sib = NULL; + mdp->parent = NULL; + mdp->demand_next = NULL; + mdp->name = xstrdup (name); + mdp->filename = NULL; + mdp->identifier = NULL; + mdp->client_id = 0; + mdp->in_use = 0; + mdp->handle = -1; + mdp->SetupProc = NULL; + mdp->TearDownProc = NULL; + mdp->TearDownData = NULL; + } + + return (mdp); +} + +ModuleDescPtr +AddSibling (ModuleDescPtr head, ModuleDescPtr new) +{ + new->sib = head; + return (new); + +} + +static void +RemoveChild (ModuleDescPtr child) +{ + ModuleDescPtr mdp; + ModuleDescPtr prevsib; + ModuleDescPtr parent; + + if (!child->parent) + return; + + parent = child->parent; + if (parent->child == child) { + parent->child = child->sib; + return; + } + + prevsib = parent->child; + mdp = prevsib->sib; + while (mdp && mdp != child) { + prevsib = mdp; + mdp = mdp->sib; + } + if (mdp == child) + prevsib->sib = child->sib; + return; +} + +void +LoaderErrorMsg(const char *name, const char *modname, int errmaj, int errmin) +{ + const char *msg; + + switch (errmaj) { + case LDR_NOERROR: + msg = "no error"; + break; + case LDR_NOMEM: + msg = "out of memory"; + break; + case LDR_NOENT: + msg = "module does not exist"; + break; + case LDR_NOSUBENT: + msg = "a required submodule could not be loaded"; + break; + case LDR_NOSPACE: + msg = "too many modules"; + break; + case LDR_NOMODOPEN: + msg = "open failed"; + break; + case LDR_UNKTYPE: + msg = "unknown module type"; + break; + case LDR_NOLOAD: + msg = "loader failed"; + break; + case LDR_ONCEONLY: + msg = "once-only module"; + break; + case LDR_NOPORTOPEN: + msg = "port open failed"; + break; + case LDR_NOHARDWARE: + msg = "no hardware found"; + break; + case LDR_MISMATCH: + msg = "module requirement mismatch"; + break; + case LDR_BADUSAGE: + msg = "invalid argument(s) to LoadModule()"; + break; + case LDR_INVALID: + msg = "invalid module"; + break; + case LDR_BADOS: + msg = "module doesn't support this OS"; + break; + case LDR_MODSPECIFIC: + msg = "module-specific error"; + break; + default: + msg = "uknown error"; + } + if (name) + xf86Msg(X_ERROR, "%s: Failed to load module \"%s\" (%s, %d)\n", + name, modname, msg, errmin); + else + xf86Msg(X_ERROR, "Failed to load module \"%s\" (%s, %d)\n", + modname, msg, errmin); +} + + +/* Given a module path or file name, return the module's canonical name */ +static char * +LoaderGetCanonicalName(const char *modname, PatternPtr patterns) +{ + char *str; + const char *s; + int len; + PatternPtr p; + regmatch_t match[2]; + + /* Strip off any leading path */ + s = strrchr(modname, '/'); + if (s == NULL) + s = modname; + else + s++; + + /* Find the first regex that is matched */ + for (p = patterns; p->pattern; p++) + if (regexec(&p->rex, s, 2, match, 0) == 0 && + match[1].rm_so != -1) { + len = match[1].rm_eo - match[1].rm_so; + str = xalloc(len + 1); + if (!str) + return NULL; + strncpy(str, s + match[1].rm_so, len); + str[len] = '\0'; + return str; + } + + /* If there is no match, return the whole name minus the leading path */ + return xstrdup(s); +} + +/* + * Return the module version information. + */ +unsigned long +LoaderGetModuleVersion (ModuleDescPtr mod) +{ + if (!mod || !mod->VersionInfo) + return 0; + + return MODULE_VERSION_NUMERIC(mod->VersionInfo->majorversion, + mod->VersionInfo->minorversion, + mod->VersionInfo->patchlevel); +} diff --git a/hw/xfree86/loader/misym.c b/hw/xfree86/loader/misym.c new file mode 100644 index 000000000..989978330 --- /dev/null +++ b/hw/xfree86/loader/misym.c @@ -0,0 +1,180 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/loader/misym.c,v 1.35 2002/09/16 18:06:11 eich 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. + */ +#include "sym.h" +#include "misc.h" +#include "mi.h" +#include "mibank.h" +#include "miwideline.h" +#include "mibstore.h" +#include "cursor.h" +#include "mipointer.h" +#include "migc.h" +#include "miline.h" +#include "mizerarc.h" +#include "mifillarc.h" +#include "micmap.h" +#include "mioverlay.h" +#ifdef PANORAMIX +#include "resource.h" +#include "panoramiX.h" +#endif +#ifdef RENDER +#include "mipict.h" +#endif + +/* mi things */ + +extern miPointerSpriteFuncRec miSpritePointerFuncs; + +LOOKUP miLookupTab[] = { + SYMFUNC(miClearToBackground) + SYMFUNC(miSendGraphicsExpose) + SYMFUNC(miModifyPixmapHeader) + SYMFUNC(miHandleValidateExposures) + SYMFUNC(miSetShape) + SYMFUNC(miChangeBorderWidth) + SYMFUNC(miShapedWindowIn) + SYMFUNC(miRectIn) + SYMFUNC(miZeroClipLine) + SYMFUNC(miZeroDashLine) + SYMFUNC(miClearDrawable) + SYMFUNC(miPolyPoint) + SYMFUNC(miStepDash) + SYMFUNC(miEmptyBox) + SYMFUNC(miEmptyData) + SYMFUNC(miIntersect) + SYMFUNC(miRegionAppend) + SYMFUNC(miRegionCopy) + SYMFUNC(miRegionDestroy) + SYMFUNC(miRegionEmpty) + SYMFUNC(miRegionExtents) + SYMFUNC(miRegionInit) + SYMFUNC(miRegionNotEmpty) + SYMFUNC(miRegionReset) + SYMFUNC(miRegionUninit) + SYMFUNC(miRegionValidate) + SYMFUNC(miTranslateRegion) + SYMFUNC(miHandleExposures) + SYMFUNC(miPolyFillRect) + SYMFUNC(miPolyFillArc) + SYMFUNC(miImageGlyphBlt) + SYMFUNC(miPolyGlyphBlt) + SYMFUNC(miFillPolygon) + SYMFUNC(miFillConvexPoly) + SYMFUNC(miPolySegment) + SYMFUNC(miZeroLine) + SYMFUNC(miWideLine) + SYMFUNC(miWideDash) + SYMFUNC(miZeroPolyArc) + SYMFUNC(miPolyArc) + SYMFUNC(miCreateGCOps) + SYMFUNC(miDestroyGCOps) + SYMFUNC(miComputeCompositeClip) + SYMFUNC(miChangeGC) + SYMFUNC(miCopyGC) + SYMFUNC(miDestroyGC) + SYMFUNC(miChangeClip) + SYMFUNC(miDestroyClip) + SYMFUNC(miCopyClip) + SYMFUNC(miPolyRectangle) + SYMFUNC(miPolyText8) + SYMFUNC(miPolyText16) + SYMFUNC(miImageText8) + SYMFUNC(miImageText16) + SYMFUNC(miRegionCreate) + SYMFUNC(miPaintWindow) + SYMFUNC(miZeroArcSetup) + SYMFUNC(miFillArcSetup) + SYMFUNC(miFillArcSliceSetup) + SYMFUNC(miFindMaxBand) + SYMFUNC(miClipSpans) + SYMFUNC(miAllocateGCPrivateIndex) + SYMFUNC(miScreenInit) + SYMFUNC(miGetScreenPixmap) + SYMFUNC(miSetScreenPixmap) + SYMFUNC(miPointerCurrentScreen) + SYMFUNC(miRectAlloc) + SYMFUNC(miInitializeBackingStore) + SYMFUNC(miInitializeBanking) + SYMFUNC(miModifyBanking) + SYMFUNC(miCopyPlane) + SYMFUNC(miCopyArea) + SYMFUNC(miCreateScreenResources) + SYMFUNC(miGetImage) + SYMFUNC(miPutImage) + SYMFUNC(miPushPixels) + SYMFUNC(miPointerInitialize) + SYMFUNC(miPointerPosition) + SYMFUNC(miRecolorCursor) + SYMFUNC(miPointerWarpCursor) + SYMFUNC(miDCInitialize) + SYMFUNC(miRectsToRegion) + SYMFUNC(miPointInRegion) + SYMFUNC(miInverse) + SYMFUNC(miSubtract) + SYMFUNC(miUnion) + SYMFUNC(miPolyBuildEdge) + SYMFUNC(miPolyBuildPoly) + SYMFUNC(miRoundJoinClip) + SYMFUNC(miRoundCapClip) + SYMFUNC(miSetZeroLineBias) + SYMFUNC(miResolveColor) + SYMFUNC(miInitializeColormap) + SYMFUNC(miInstallColormap) + SYMFUNC(miUninstallColormap) + SYMFUNC(miListInstalledColormaps) + SYMFUNC(miExpandDirectColors) + SYMFUNC(miCreateDefColormap) + SYMFUNC(miClearVisualTypes) + SYMFUNC(miSetVisualTypes) + SYMFUNC(miSetVisualTypesAndMasks) + SYMFUNC(miGetDefaultVisualMask) + SYMFUNC(miSetPixmapDepths) + SYMFUNC(miInitVisuals) + SYMFUNC(miWindowExposures) + SYMFUNC(miSegregateChildren) + SYMFUNC(miClipNotify) + SYMFUNC(miHookInitVisuals) + SYMFUNC(miPointerAbsoluteCursor) + SYMFUNC(miPointerGetMotionEvents) + SYMFUNC(miPointerGetMotionBufferSize) + SYMFUNC(miOverlayCopyUnderlay) + SYMFUNC(miOverlaySetTransFunction) + SYMFUNC(miOverlayCollectUnderlayRegions) + SYMFUNC(miInitOverlay) + SYMFUNC(miOverlayComputeCompositeClip) + SYMFUNC(miOverlayGetPrivateClips) + SYMFUNC(miOverlaySetRootClip) + SYMVAR(miZeroLineScreenIndex) + SYMVAR(miSpritePointerFuncs) + SYMVAR(miPointerScreenIndex) + SYMVAR(miInstalledMaps) + SYMVAR(miInitVisualsProc) +#ifdef RENDER + SYMVAR(miGlyphExtents) +#endif + { 0, 0 }, + +}; diff --git a/hw/xfree86/loader/os.c b/hw/xfree86/loader/os.c new file mode 100644 index 000000000..e2e710077 --- /dev/null +++ b/hw/xfree86/loader/os.c @@ -0,0 +1,49 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/loader/os.c,v 1.2 2002/05/31 18:46:00 dawes Exp $ */ + +#include "loaderProcs.h" + +/* + * OSNAME is a standard form of the OS name that may be used by the + * loader and by OS-specific modules. + */ + +#if defined(__linux__) +#define OSNAME "linux" +#elif defined(__FreeBSD__) +#define OSNAME "freebsd" +#elif defined(__NetBSD__) +#define OSNAME "netbsd" +#elif defined(__OpenBSD__) +#define OSNAME "openbsd" +#elif defined(Lynx) +#define OSNAME "lynxos" +#elif defined(__GNU__) +#define OSNAME "hurd" +#elif defined(SCO) +#define OSNAME "sco" +#elif defined(DGUX) +#define OSNAME "dgux" +#elif defined(ISC) +#define OSNAME "isc" +#elif defined(SVR4) && defined(sun) +#define OSNAME "solaris" +#elif defined(SVR4) +#define OSNAME "svr4" +#elif defined(__UNIXOS2__) +#define OSNAME "os2" +#else +#define OSNAME "unknown" +#endif + + +/* Return the OS name, and run-time OS version */ + +void +LoaderGetOS(const char **name, int *major, int *minor, int *teeny) +{ + if (name) + *name = OSNAME; + + /* reporting runtime versions isn't supported yet */ +} + diff --git a/hw/xfree86/loader/sym.h b/hw/xfree86/loader/sym.h new file mode 100644 index 000000000..6ad38aa49 --- /dev/null +++ b/hw/xfree86/loader/sym.h @@ -0,0 +1,46 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/loader/sym.h,v 1.6 2000/10/24 00:06:55 anderson 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. + */ + +#ifndef _SYM_H +#define _SYM_H + +/* + * This structure is used to pass in symbol information that is being + * added to the symbol table. + */ + +typedef void (*funcptr)(void); + +typedef struct { + char *symName; + funcptr offset; +} LOOKUP; + +#define SYMFUNC( func ) { #func, (funcptr)&func }, +#define SYMFUNCALIAS( name, func ) { name, (funcptr)&func }, +#define SYMVAR( var ) { #var, (funcptr)&var }, +#define SYMVARALIAS( name, var ) { name, (funcptr)&var }, + +#endif /* _SYM_H */ diff --git a/hw/xfree86/loader/xf86sym.c b/hw/xfree86/loader/xf86sym.c new file mode 100644 index 000000000..8e8bdadfc --- /dev/null +++ b/hw/xfree86/loader/xf86sym.c @@ -0,0 +1,1133 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/loader/xf86sym.c,v 1.227.2.1 2003/03/13 04:10:47 tsi 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. + */ + +#define INCLUDE_DEPRECATED 1 + +#include <fcntl.h> +#include <setjmp.h> +#include "sym.h" +#include "misc.h" +#include "mi.h" +#include "cursor.h" +#include "mipointer.h" +#include "loaderProcs.h" +#include "xf86Pci.h" +#include "xf86.h" +#include "xf86Resources.h" +#include "xf86_OSproc.h" +#include "xf86Parser.h" +#include "xf86Config.h" +#ifdef XINPUT +# include "xf86Xinput.h" +#endif +#include "xf86OSmouse.h" +#include "xf86OSKbd.h" +#include "xf86xv.h" +#include "xf86xvmc.h" +#include "xf86cmap.h" +#include "xf86fbman.h" +#include "dgaproc.h" +#include "dpmsproc.h" +#include "vidmodeproc.h" +#include "xf86miscproc.h" +#include "loader.h" +#define DONT_DEFINE_WRAPPERS +#include "xf86_ansic.h" +#include "xisb.h" +#include "vbe.h" +#ifndef __OpenBSD__ +#include "xf86sbusBus.h" +#endif +#include "compiler.h" + +#ifndef HAS_GLIBC_SIGSETJMP +#if defined(setjmp) && defined(__GNU_LIBRARY__) && \ + (!defined(__GLIBC__) || (__GLIBC__ < 2) || \ + ((__GLIBC__ == 2) && (__GLIBC_MINOR__ < 3))) +#define HAS_GLIBC_SIGSETJMP 1 +#endif +#endif + +#ifdef __FreeBSD__ +/* XXX used in drmOpen(). This should change to use a less os-specific + * method. */ +int sysctlbyname(const char*, void *, size_t *, void *, size_t); +#endif + +#if defined(__alpha__) +# ifdef linux +extern unsigned long _bus_base(void); +extern void _outb(char val, unsigned short port); +extern void _outw(short val, unsigned short port); +extern void _outl(int val, unsigned short port); +extern unsigned int _inb(unsigned short port); +extern unsigned int _inw(unsigned short port); +extern unsigned int _inl(unsigned short port); +# endif + +# ifdef __FreeBSD__ +# include <sys/types.h> +extern void outb(u_int32_t port, u_int8_t val); +extern void outw(u_int32_t port, u_int16_t val); +extern void outl(u_int32_t port, u_int32_t val); +extern u_int8_t inb(u_int32_t port); +extern u_int16_t inw(u_int32_t port); +extern u_int32_t inl(u_int32_t port); +# endif + +extern void* __divl(long, long); +extern void* __reml(long, long); +extern void* __divlu(long, long); +extern void* __remlu(long, long); +extern void* __divq(long, long); +extern void* __divqu(long, long); +extern void* __remq(long, long); +extern void* __remqu(long, long); +#endif + +#if defined(__GNUC__) +extern long __div64(long, long); +extern long __divdf3(long, long); +extern long __divdi3(long, long); +extern long __divsf3(long, long); +extern long __divsi3(long, long); +extern long __moddi3(long, long); +extern long __modsi3(long, long); +extern long __mul64(long, long); +extern long __muldf3(long, long); +extern long __muldi3(long, long); +extern long __mulsf3(long, long); +extern long __mulsi3(long, long); +extern long __udivdi3(long, long); +extern long __udivsi3(long, long); +extern long __umoddi3(long, long); +extern long __umodsi3(long, long); +#pragma weak __div64 +#pragma weak __divdf3 +#pragma weak __divdi3 +#pragma weak __divsf3 +#pragma weak __divsi3 +#pragma weak __moddi3 +#pragma weak __modsi3 +#pragma weak __mul64 +#pragma weak __muldf3 +#pragma weak __muldi3 +#pragma weak __mulsf3 +#pragma weak __mulsi3 +#pragma weak __udivdi3 +#pragma weak __udivsi3 +#pragma weak __umoddi3 +#pragma weak __umodsi3 +#endif + +#if defined(__arm__) && defined(__linux__) +#include <sys/io.h> +#endif + +#if defined(__powerpc__) && (defined(Lynx) || defined(linux)) +void _restf14(); +void _restf17(); +void _restf18(); +void _restf19(); +void _restf20(); +void _restf22(); +void _restf23(); +void _restf24(); +void _restf25(); +void _restf26(); +void _restf27(); +void _restf28(); +void _restf29(); +void _savef14(); +void _savef17(); +void _savef18(); +void _savef19(); +void _savef20(); +void _savef22(); +void _savef23(); +void _savef24(); +void _savef25(); +void _savef26(); +void _savef27(); +void _savef28(); +void _savef29(); + +/* even if we compile without -DNO_INLINE we still provide + * the usual port i/o functions for module use + */ + +extern volatile unsigned char *ioBase; + +/* XXX Should get all of these from elsewhere */ +#ifndef linux +extern void outb(IOADDRESS, unsigned char); +extern void outw(IOADDRESS, unsigned short); +extern void outl(IOADDRESS, unsigned int); +extern unsigned int inb(IOADDRESS); +extern unsigned int inw(IOADDRESS); +extern unsigned int inl(IOADDRESS); +#endif +extern void stl_brx(unsigned long, volatile unsigned char *, int); +extern void stw_brx(unsigned short, volatile unsigned char *, int); +extern unsigned long ldl_brx(volatile unsigned char *, int); +extern unsigned short ldw_brx(volatile unsigned char *, int); +#endif + +/* XFree86 things */ + +LOOKUP xfree86LookupTab[] = { + + /* Public OSlib functions */ + SYMFUNC(xf86ReadBIOS) + SYMFUNC(xf86EnableIO) + SYMFUNC(xf86DisableIO) + SYMFUNC(xf86DisableInterrupts) + SYMFUNC(xf86EnableInterrupts) + SYMFUNC(xf86LinearVidMem) + SYMFUNC(xf86CheckMTRR) + SYMFUNC(xf86MapVidMem) + SYMFUNC(xf86UnMapVidMem) + SYMFUNC(xf86MapReadSideEffects) + SYMFUNC(xf86GetPciDomain) + SYMFUNC(xf86MapDomainMemory) + SYMFUNC(xf86MapDomainIO) + SYMFUNC(xf86ReadDomainMemory) + SYMFUNC(xf86UDelay) + SYMFUNC(xf86IODelay) + SYMFUNC(xf86SlowBcopy) +#ifdef __alpha__ + SYMFUNC(xf86SlowBCopyToBus) + SYMFUNC(xf86SlowBCopyFromBus) +#endif + SYMFUNC(xf86BusToMem) + SYMFUNC(xf86MemToBus) + SYMFUNC(xf86OpenSerial) + SYMFUNC(xf86SetSerial) + SYMFUNC(xf86SetSerialSpeed) + SYMFUNC(xf86ReadSerial) + SYMFUNC(xf86WriteSerial) + SYMFUNC(xf86CloseSerial) + SYMFUNC(xf86GetErrno) + SYMFUNC(xf86WaitForInput) + SYMFUNC(xf86SerialSendBreak) + SYMFUNC(xf86FlushInput) + SYMFUNC(xf86SetSerialModemState) + SYMFUNC(xf86GetSerialModemState) + SYMFUNC(xf86SerialModemSetBits) + SYMFUNC(xf86SerialModemClearBits) + SYMFUNC(xf86LoadKernelModule) + SYMFUNC(xf86OSMouseInit) + SYMFUNC(xf86OSKbdPreInit) + SYMFUNC(xf86AgpGARTSupported) + SYMFUNC(xf86GetAGPInfo) + SYMFUNC(xf86AcquireGART) + SYMFUNC(xf86ReleaseGART) + SYMFUNC(xf86AllocateGARTMemory) + SYMFUNC(xf86BindGARTMemory) + SYMFUNC(xf86UnbindGARTMemory) + SYMFUNC(xf86EnableAGP) + SYMFUNC(xf86SoundKbdBell) + SYMFUNC(xf86GARTCloseScreen) +#ifdef XINPUT +/* XISB routines (Merged from Metrolink tree) */ + SYMFUNC(XisbNew) + SYMFUNC(XisbFree) + SYMFUNC(XisbRead) + SYMFUNC(XisbWrite) + SYMFUNC(XisbTrace) + SYMFUNC(XisbBlockDuration) +#endif + + /* xf86Bus.c */ + SYMFUNC(xf86CheckPciSlot) + SYMFUNC(xf86ClaimPciSlot) + SYMFUNC(xf86GetPciVideoInfo) + SYMFUNC(xf86GetPciEntity) + SYMFUNC(xf86GetPciConfigInfo) + SYMFUNC(xf86SetPciVideo) + SYMFUNC(xf86ClaimIsaSlot) + SYMFUNC(xf86ClaimFbSlot) + SYMFUNC(xf86ClaimNoSlot) + SYMFUNC(xf86ParsePciBusString) + SYMFUNC(xf86ComparePciBusString) + SYMFUNC(xf86FormatPciBusNumber) + SYMFUNC(xf86ParseIsaBusString) + SYMFUNC(xf86EnableAccess) + SYMFUNC(xf86SetCurrentAccess) + SYMFUNC(xf86IsPrimaryPci) + SYMFUNC(xf86IsPrimaryIsa) + SYMFUNC(xf86CheckPciGAType) + SYMFUNC(xf86PrintResList) + SYMFUNC(xf86AddResToList) + SYMFUNC(xf86JoinResLists) + SYMFUNC(xf86DupResList) + SYMFUNC(xf86FreeResList) + SYMFUNC(xf86ClaimFixedResources) + SYMFUNC(xf86AddEntityToScreen) + SYMFUNC(xf86SetEntityInstanceForScreen) + SYMFUNC(xf86RemoveEntityFromScreen) + SYMFUNC(xf86GetEntityInfo) + SYMFUNC(xf86GetNumEntityInstances) + SYMFUNC(xf86GetDevFromEntity) + SYMFUNC(xf86GetPciInfoForEntity) + SYMFUNC(xf86SetEntityFuncs) + SYMFUNC(xf86DeallocateResourcesForEntity) + SYMFUNC(xf86RegisterResources) + SYMFUNC(xf86CheckPciMemBase) + SYMFUNC(xf86SetAccessFuncs) + SYMFUNC(xf86IsEntityPrimary) + SYMFUNC(xf86FixPciResource) + SYMFUNC(xf86SetOperatingState) + SYMFUNC(xf86EnterServerState) + SYMFUNC(xf86GetBlock) + SYMFUNC(xf86GetSparse) + SYMFUNC(xf86ReallocatePciResources) + SYMFUNC(xf86ChkConflict) + SYMFUNC(xf86IsPciDevPresent) + SYMFUNC(xf86FindScreenForEntity) + SYMFUNC(xf86FindPciDeviceVendor) + SYMFUNC(xf86FindPciClass) +#ifdef INCLUDE_DEPRECATED + SYMFUNC(xf86EnablePciBusMaster) +#endif + SYMFUNC(xf86RegisterStateChangeNotificationCallback) + SYMFUNC(xf86DeregisterStateChangeNotificationCallback) + SYMFUNC(xf86NoSharedResources) +#ifdef async + SYMFUNC(xf86QueueAsyncEvent) +#endif + /* Shared Accel Accessor Functions */ + SYMFUNC(xf86GetLastScrnFlag) + SYMFUNC(xf86SetLastScrnFlag) + SYMFUNC(xf86IsEntityShared) + SYMFUNC(xf86SetEntityShared) + SYMFUNC(xf86IsEntitySharable) + SYMFUNC(xf86SetEntitySharable) + SYMFUNC(xf86IsPrimInitDone) + SYMFUNC(xf86SetPrimInitDone) + SYMFUNC(xf86ClearPrimInitDone) + SYMFUNC(xf86AllocateEntityPrivateIndex) + SYMFUNC(xf86GetEntityPrivate) + + /* xf86Configure.c */ + SYMFUNC(xf86AddDeviceToConfigure) + + /* xf86Cursor.c */ + SYMFUNC(xf86GetPointerScreenFuncs) + + /* xf86DGA.c */ + /* For drivers */ + SYMFUNC(DGAInit) + /* For extmod */ + SYMFUNC(DGAAvailable) + SYMFUNC(DGAActive) + SYMFUNC(DGASetMode) + SYMFUNC(DGASetInputMode) + SYMFUNC(DGASelectInput) + SYMFUNC(DGAGetViewportStatus) + SYMFUNC(DGASetViewport) + SYMFUNC(DGAInstallCmap) + SYMFUNC(DGASync) + SYMFUNC(DGAFillRect) + SYMFUNC(DGABlitRect) + SYMFUNC(DGABlitTransRect) + SYMFUNC(DGAGetModes) + SYMFUNC(DGAGetOldDGAMode) + SYMFUNC(DGAGetModeInfo) + SYMFUNC(DGAChangePixmapMode) + SYMFUNC(DGACreateColormap) + SYMFUNC(DGAOpenFramebuffer) + SYMFUNC(DGACloseFramebuffer) + + /* xf86DPMS.c */ + SYMFUNC(xf86DPMSInit) + + /* xf86Events.c */ + SYMFUNC(SetTimeSinceLastInputEvent) + SYMFUNC(xf86AddInputHandler) + SYMFUNC(xf86RemoveInputHandler) + SYMFUNC(xf86DisableInputHandler) + SYMFUNC(xf86EnableInputHandler) + SYMFUNC(xf86AddEnabledDevice) + SYMFUNC(xf86RemoveEnabledDevice) + SYMFUNC(xf86InterceptSignals) + SYMFUNC(xf86EnableVTSwitch) + + /* xf86Helper.c */ + SYMFUNC(xf86AddDriver) + SYMFUNC(xf86AddInputDriver) + SYMFUNC(xf86DeleteDriver) + SYMFUNC(xf86DeleteInput) + SYMFUNC(xf86AllocateInput) + SYMFUNC(xf86AllocateScreen) + SYMFUNC(xf86DeleteScreen) + SYMFUNC(xf86AllocateScrnInfoPrivateIndex) + SYMFUNC(xf86AddPixFormat) + SYMFUNC(xf86SetDepthBpp) + SYMFUNC(xf86PrintDepthBpp) + SYMFUNC(xf86SetWeight) + SYMFUNC(xf86SetDefaultVisual) + SYMFUNC(xf86SetGamma) + SYMFUNC(xf86SetDpi) + SYMFUNC(xf86SetBlackWhitePixels) + SYMFUNC(xf86EnableDisableFBAccess) + SYMFUNC(xf86VDrvMsgVerb) + SYMFUNC(xf86DrvMsgVerb) + SYMFUNC(xf86DrvMsg) + SYMFUNC(xf86MsgVerb) + SYMFUNC(xf86Msg) + SYMFUNC(xf86ErrorFVerb) + SYMFUNC(xf86ErrorF) + SYMFUNC(xf86TokenToString) + SYMFUNC(xf86StringToToken) + SYMFUNC(xf86ShowClocks) + SYMFUNC(xf86PrintChipsets) + SYMFUNC(xf86MatchDevice) + SYMFUNC(xf86MatchPciInstances) + SYMFUNC(xf86MatchIsaInstances) + SYMFUNC(xf86GetVerbosity) + SYMFUNC(xf86GetVisualName) + SYMFUNC(xf86GetPix24) + SYMFUNC(xf86GetDepth) + SYMFUNC(xf86GetWeight) + SYMFUNC(xf86GetGamma) + SYMFUNC(xf86GetFlipPixels) + SYMFUNC(xf86GetServerName) + SYMFUNC(xf86ServerIsExiting) + SYMFUNC(xf86ServerIsOnlyDetecting) + SYMFUNC(xf86ServerIsOnlyProbing) + SYMFUNC(xf86ServerIsResetting) + SYMFUNC(xf86CaughtSignal) + SYMFUNC(xf86GetVidModeAllowNonLocal) + SYMFUNC(xf86GetVidModeEnabled) + SYMFUNC(xf86GetModInDevAllowNonLocal) + SYMFUNC(xf86GetModInDevEnabled) + SYMFUNC(xf86GetAllowMouseOpenFail) + SYMFUNC(xf86CommonSpecialKey) + SYMFUNC(xf86IsPc98) + SYMFUNC(xf86DisableRandR) + SYMFUNC(xf86GetVersion) + SYMFUNC(xf86GetModuleVersion) + SYMFUNC(xf86GetClocks) + SYMFUNC(xf86SetPriority) + SYMFUNC(xf86LoadDrvSubModule) + SYMFUNC(xf86LoadSubModule) + SYMFUNC(xf86LoadOneModule) + SYMFUNC(xf86UnloadSubModule) + SYMFUNC(xf86LoaderCheckSymbol) + SYMFUNC(xf86LoaderRefSymLists) + SYMFUNC(xf86LoaderRefSymbols) + SYMFUNC(xf86LoaderReqSymLists) + SYMFUNC(xf86LoaderReqSymbols) + SYMFUNC(xf86SetBackingStore) + SYMFUNC(xf86SetSilkenMouse) + /* SYMFUNC(xf86NewSerialNumber) */ + SYMFUNC(xf86FindXvOptions) + SYMFUNC(xf86GetOS) + SYMFUNC(xf86ConfigPciEntity) + SYMFUNC(xf86ConfigIsaEntity) + SYMFUNC(xf86ConfigFbEntity) + SYMFUNC(xf86ConfigActivePciEntity) + SYMFUNC(xf86ConfigActiveIsaEntity) + SYMFUNC(xf86ConfigPciEntityInactive) + SYMFUNC(xf86ConfigIsaEntityInactive) + SYMFUNC(xf86IsScreenPrimary) + SYMFUNC(xf86RegisterRootWindowProperty) + SYMFUNC(xf86IsUnblank) + SYMFUNC(xf86AddModuleInfo) + SYMFUNC(xf86DeleteModuleInfo) + +#if defined(__sparc__) && !defined(__OpenBSD__) + /* xf86sbusBus.c */ + SYMFUNC(xf86MatchSbusInstances) + SYMFUNC(xf86GetSbusInfoForEntity) + SYMFUNC(xf86GetEntityForSbusInfo) + SYMFUNC(xf86SbusUseBuiltinMode) + SYMFUNC(xf86MapSbusMem) + SYMFUNC(xf86UnmapSbusMem) + SYMFUNC(xf86SbusHideOsHwCursor) + SYMFUNC(xf86SbusSetOsHwCursorCmap) + SYMFUNC(xf86SbusHandleColormaps) + SYMFUNC(sparcPromInit) + SYMFUNC(sparcPromClose) + SYMFUNC(sparcPromGetProperty) + SYMFUNC(sparcPromGetBool) +#endif + + /* xf86Init.c */ + SYMFUNC(xf86GetPixFormat) + SYMFUNC(xf86GetBppFromDepth) + + /* xf86Mode.c */ + SYMFUNC(xf86GetNearestClock) + SYMFUNC(xf86ModeStatusToString) + SYMFUNC(xf86LookupMode) + SYMFUNC(xf86CheckModeForMonitor) + SYMFUNC(xf86InitialCheckModeForDriver) + SYMFUNC(xf86CheckModeForDriver) + SYMFUNC(xf86ValidateModes) + SYMFUNC(xf86DeleteMode) + SYMFUNC(xf86PruneDriverModes) + SYMFUNC(xf86SetCrtcForModes) + SYMFUNC(xf86PrintModes) + SYMFUNC(xf86ShowClockRanges) + + /* xf86Option.c */ + SYMFUNC(xf86CollectOptions) + SYMFUNC(xf86CollectInputOptions) + /* Merging of XInput stuff */ + SYMFUNC(xf86AddNewOption) + SYMFUNC(xf86SetBoolOption) + SYMFUNC(xf86NewOption) + SYMFUNC(xf86NextOption) + SYMFUNC(xf86OptionListCreate) + SYMFUNC(xf86OptionListMerge) + SYMFUNC(xf86OptionListFree) + SYMFUNC(xf86OptionName) + SYMFUNC(xf86OptionValue) + SYMFUNC(xf86OptionListReport) + SYMFUNC(xf86SetIntOption) + SYMFUNC(xf86SetRealOption) + SYMFUNC(xf86SetStrOption) + SYMFUNC(xf86ReplaceIntOption) + SYMFUNC(xf86ReplaceStrOption) + SYMFUNC(xf86ReplaceBoolOption) + SYMFUNC(xf86FindOption) + SYMFUNC(xf86FindOptionValue) + SYMFUNC(xf86MarkOptionUsed) + SYMFUNC(xf86MarkOptionUsedByName) + SYMFUNC(xf86CheckIfOptionUsed) + SYMFUNC(xf86CheckIfOptionUsedByName) + SYMFUNC(xf86ShowUnusedOptions) + SYMFUNC(xf86ProcessOptions) + SYMFUNC(xf86TokenToOptinfo) + SYMFUNC(xf86TokenToOptName) + SYMFUNC(xf86IsOptionSet) + SYMFUNC(xf86GetOptValString) + SYMFUNC(xf86GetOptValInteger) + SYMFUNC(xf86GetOptValULong) + SYMFUNC(xf86GetOptValReal) + SYMFUNC(xf86GetOptValFreq) + SYMFUNC(xf86GetOptValBool) + SYMFUNC(xf86ReturnOptValBool) + SYMFUNC(xf86NameCmp) + SYMFUNC(xf86InitValuatorAxisStruct) + SYMFUNC(xf86InitValuatorDefaults) + + + /* xf86fbman.c */ + SYMFUNC(xf86InitFBManager) + SYMFUNC(xf86InitFBManagerArea) + SYMFUNC(xf86InitFBManagerRegion) + SYMFUNC(xf86RegisterFreeBoxCallback) + SYMFUNC(xf86FreeOffscreenArea) + SYMFUNC(xf86AllocateOffscreenArea) + SYMFUNC(xf86AllocateLinearOffscreenArea) + SYMFUNC(xf86ResizeOffscreenArea) + SYMFUNC(xf86FBManagerRunning) + SYMFUNC(xf86QueryLargestOffscreenArea) + SYMFUNC(xf86PurgeUnlockedOffscreenAreas) + SYMFUNC(xf86RegisterOffscreenManager) + SYMFUNC(xf86AllocateOffscreenLinear) + SYMFUNC(xf86ResizeOffscreenLinear) + SYMFUNC(xf86QueryLargestOffscreenLinear) + SYMFUNC(xf86FreeOffscreenLinear) + + + /* xf86cmap.c */ + SYMFUNC(xf86HandleColormaps) + + /* xf86xv.c */ + SYMFUNC(xf86XVScreenInit) + SYMFUNC(xf86XVRegisterGenericAdaptorDriver) + SYMFUNC(xf86XVListGenericAdaptors) + SYMFUNC(xf86XVRegisterOffscreenImages) + SYMFUNC(xf86XVQueryOffscreenImages) + SYMFUNC(xf86XVAllocateVideoAdaptorRec) + SYMFUNC(xf86XVFreeVideoAdaptorRec) + SYMFUNC(xf86XVFillKeyHelper) + SYMFUNC(xf86XVClipVideoHelper) + + /* xf86xvmc.c */ + SYMFUNC(xf86XvMCScreenInit) + + /* xf86VidMode.c */ + SYMFUNC(VidModeExtensionInit) +#ifdef XF86VIDMODE + SYMFUNC(VidModeGetCurrentModeline) + SYMFUNC(VidModeGetFirstModeline) + SYMFUNC(VidModeGetNextModeline) + SYMFUNC(VidModeDeleteModeline) + SYMFUNC(VidModeZoomViewport) + SYMFUNC(VidModeGetViewPort) + SYMFUNC(VidModeSetViewPort) + SYMFUNC(VidModeSwitchMode) + SYMFUNC(VidModeLockZoom) + SYMFUNC(VidModeGetMonitor) + SYMFUNC(VidModeGetNumOfClocks) + SYMFUNC(VidModeGetClocks) + SYMFUNC(VidModeCheckModeForMonitor) + SYMFUNC(VidModeCheckModeForDriver) + SYMFUNC(VidModeSetCrtcForMode) + SYMFUNC(VidModeAddModeline) + SYMFUNC(VidModeGetDotClock) + SYMFUNC(VidModeGetNumOfModes) + SYMFUNC(VidModeSetGamma) + SYMFUNC(VidModeGetGamma) + SYMFUNC(VidModeCreateMode) + SYMFUNC(VidModeCopyMode) + SYMFUNC(VidModeGetModeValue) + SYMFUNC(VidModeSetModeValue) + SYMFUNC(VidModeGetMonitorValue) + SYMFUNC(VidModeSetGammaRamp) + SYMFUNC(VidModeGetGammaRamp) + SYMFUNC(VidModeGetGammaRampSize) +#endif + + /* xf86MiscExt.c */ +#ifdef XF86MISC + SYMFUNC(MiscExtGetMouseSettings) + SYMFUNC(MiscExtGetMouseValue) + SYMFUNC(MiscExtSetMouseValue) + SYMFUNC(MiscExtSetMouseDevice) + SYMFUNC(MiscExtGetKbdSettings) + SYMFUNC(MiscExtGetKbdValue) + SYMFUNC(MiscExtSetKbdValue) + SYMFUNC(MiscExtSetGrabKeysState) + SYMFUNC(MiscExtCreateStruct) + SYMFUNC(MiscExtDestroyStruct) + SYMFUNC(MiscExtApply) + SYMFUNC(MiscExtGetFilePaths) +#endif + + /* Misc */ + SYMFUNC(GetTimeInMillis) + + /* xf86Xinput.c */ +#ifdef XINPUT + SYMFUNC(xf86ProcessCommonOptions) + SYMFUNC(xf86IsCorePointer) + SYMFUNC(xf86PostMotionEvent) + SYMFUNC(xf86PostProximityEvent) + SYMFUNC(xf86PostButtonEvent) + SYMFUNC(xf86PostKeyEvent) + SYMFUNC(xf86PostKeyboardEvent) + SYMFUNC(xf86GetMotionEvents) + SYMFUNC(xf86MotionHistoryAllocate) + SYMFUNC(xf86FirstLocalDevice) + SYMFUNC(xf86eqEnqueue) +/* The following segment merged from Metrolink tree */ + SYMFUNC(xf86XInputSetScreen) + SYMFUNC(xf86ScaleAxis) + SYMFUNC(xf86XInputSetSendCoreEvents) +/* End merged segment */ +#endif + SYMFUNC(DPMSGet) + SYMFUNC(DPMSSet) + SYMFUNC(DPMSSupported) +/* xf86Debug.c */ +#ifdef BUILDDEBUG + SYMFUNC(xf86Break1) + SYMFUNC(xf86Break2) + SYMFUNC(xf86Break3) + SYMFUNC(xf86SPTimestamp) + SYMFUNC(xf86STimestamp) +#endif + +#if 0 /* we want to move the hw stuff in a module */ + SYMFUNC(xf86dactopel) + SYMFUNC(xf86dactocomm) + SYMFUNC(xf86getdaccomm) + SYMFUNC(xf86setdaccomm) + SYMFUNC(xf86setdaccommbit) + SYMFUNC(xf86clrdaccommbit) + SYMFUNC(s3IBMRGB_Probe) + SYMFUNC(s3IBMRGB_Init) + SYMFUNC(s3InIBMRGBIndReg) + SYMFUNC(Ti3025SetClock) + SYMFUNC(Ti3026SetClock) + SYMFUNC(Ti3030SetClock) + SYMFUNC(AltICD2061SetClock) + SYMFUNC(SC11412SetClock) + SYMFUNC(ICS2595SetClock) + SYMFUNC(Att409SetClock) + SYMFUNC(Chrontel8391SetClock) + SYMFUNC(IBMRGBSetClock) + SYMFUNC(ICS5342SetClock) + SYMFUNC(S3TrioSetClock) + SYMFUNC(S3Trio64V2SetClock) + SYMFUNC(S3gendacSetClock) + SYMFUNC(STG1703SetClock) + SYMFUNC(ET6000SetClock) + SYMFUNC(S3AuroraSetClock) + SYMFUNC(commonCalcClock) + SYMFUNC(xf86writepci) + SYMFUNC(dacOutTi3026IndReg) + SYMFUNC(dacInTi3026IndReg) + SYMFUNC(s3OutIBMRGBIndReg) + SYMFUNC(CirrusFindClock) + SYMFUNC(CirrusSetClock) + SYMFUNC(STG1703getIndex) + SYMFUNC(STG1703setIndex) + SYMFUNC(STG1703magic) + SYMFUNC(gendacMNToClock) + SYMFUNC(Et4000AltICD2061SetClock) + SYMFUNC(ET4000stg1703SetClock) + SYMFUNC(ET4000gendacSetClock) + +#endif + + SYMFUNC(pciFindFirst) + SYMFUNC(pciFindNext) + SYMFUNC(pciWriteByte) + SYMFUNC(pciWriteWord) + SYMFUNC(pciWriteLong) + SYMFUNC(pciReadByte) + SYMFUNC(pciReadWord) + SYMFUNC(pciReadLong) + SYMFUNC(pciSetBitsLong) + SYMFUNC(pciTag) + SYMFUNC(pciBusAddrToHostAddr) + SYMFUNC(pciHostAddrToBusAddr) + SYMFUNC(xf86MapPciMem) + SYMFUNC(xf86scanpci) + SYMFUNC(xf86ReadPciBIOS) + SYMFUNC(AllocatePixmapPrivateIndex) + SYMFUNC(AllocatePixmapPrivate) + + /* Loader functions */ + SYMFUNC(LoaderDefaultFunc) + SYMFUNC(LoadSubModule) + SYMFUNC(DuplicateModule) + SYMFUNC(LoaderErrorMsg) + SYMFUNC(LoaderCheckUnresolved) + SYMFUNC(LoadExtension) + SYMFUNC(LoadFont) + SYMFUNC(LoaderReqSymbols) + SYMFUNC(LoaderReqSymLists) + SYMFUNC(LoaderRefSymbols) + SYMFUNC(LoaderRefSymLists) + SYMFUNC(UnloadSubModule) + SYMFUNC(LoaderSymbol) + SYMFUNC(LoaderListDirs) + SYMFUNC(LoaderFreeDirList) + SYMFUNC(LoaderGetOS) + + /* + * these here are our own interfaces to libc functions + */ + SYMFUNC(xf86abort) + SYMFUNC(xf86abs) + SYMFUNC(xf86acos) + SYMFUNC(xf86asin) + SYMFUNC(xf86atan) + SYMFUNC(xf86atan2) + SYMFUNC(xf86atof) + SYMFUNC(xf86atoi) + SYMFUNC(xf86atol) + SYMFUNC(xf86bsearch) + SYMFUNC(xf86ceil) + SYMFUNC(xf86calloc) + SYMFUNC(xf86clearerr) + SYMFUNC(xf86close) + SYMFUNC(xf86cos) + SYMFUNC(xf86exit) + SYMFUNC(xf86exp) + SYMFUNC(xf86fabs) + SYMFUNC(xf86fclose) + SYMFUNC(xf86feof) + SYMFUNC(xf86ferror) + SYMFUNC(xf86fflush) + SYMFUNC(xf86fgetc) + SYMFUNC(xf86fgetpos) + SYMFUNC(xf86fgets) + SYMFUNC(xf86finite) + SYMFUNC(xf86floor) + SYMFUNC(xf86fmod) + SYMFUNC(xf86fopen) + SYMFUNC(xf86fprintf) + SYMFUNC(xf86fputc) + SYMFUNC(xf86fputs) + SYMFUNC(xf86fread) + SYMFUNC(xf86free) + SYMFUNC(xf86freopen) + SYMFUNC(xf86frexp) + SYMFUNC(xf86fscanf) + SYMFUNC(xf86fseek) + SYMFUNC(xf86fsetpos) + SYMFUNC(xf86ftell) + SYMFUNC(xf86fwrite) + SYMFUNC(xf86getc) + SYMFUNC(xf86getenv) + SYMFUNC(xf86getpagesize) + SYMFUNC(xf86hypot) + SYMFUNC(xf86ioctl) + SYMFUNC(xf86isalnum) + SYMFUNC(xf86isalpha) + SYMFUNC(xf86iscntrl) + SYMFUNC(xf86isdigit) + SYMFUNC(xf86isgraph) + SYMFUNC(xf86islower) + SYMFUNC(xf86isprint) + SYMFUNC(xf86ispunct) + SYMFUNC(xf86isspace) + SYMFUNC(xf86isupper) + SYMFUNC(xf86isxdigit) + SYMFUNC(xf86labs) + SYMFUNC(xf86ldexp) + SYMFUNC(xf86log) + SYMFUNC(xf86log10) + SYMFUNC(xf86lseek) + SYMFUNC(xf86malloc) + SYMFUNC(xf86memchr) + SYMFUNC(xf86memcmp) + SYMFUNC(xf86memcpy) + /* + * Some compilers generate calls to memcpy to handle structure copies + * or run-time initializations. + */ + SYMFUNCALIAS("memcpy",xf86memcpy) + SYMFUNC(xf86memset) + /* + * Some compilers generate calls to memset to handle aggregate + * initializations. + */ + SYMFUNCALIAS("memset",xf86memset) + SYMFUNC(xf86memmove) + SYMFUNC(xf86mmap) + SYMFUNC(xf86modf) + SYMFUNC(xf86munmap) + SYMFUNC(xf86open) + SYMFUNC(xf86perror) + SYMFUNC(xf86pow) + SYMFUNC(xf86printf) + SYMFUNC(xf86qsort) + SYMFUNC(xf86read) + SYMFUNC(xf86realloc) + SYMFUNC(xf86remove) + SYMFUNC(xf86rename) + SYMFUNC(xf86rewind) + SYMFUNC(xf86setbuf) + SYMFUNC(xf86setvbuf) + SYMFUNC(xf86sin) + SYMFUNC(xf86snprintf) + SYMFUNC(xf86sprintf) + SYMFUNC(xf86sqrt) + SYMFUNC(xf86sscanf) + SYMFUNC(xf86strcat) + SYMFUNC(xf86strcmp) + SYMFUNC(xf86strcasecmp) + SYMFUNC(xf86strcpy) + SYMFUNC(xf86strcspn) + SYMFUNC(xf86strerror) + SYMFUNC(xf86strlen) + SYMFUNC(xf86strncasecmp) + SYMFUNC(xf86strncat) + SYMFUNC(xf86strncmp) + SYMFUNC(xf86strncpy) + SYMFUNC(xf86strpbrk) + SYMFUNC(xf86strchr) + SYMFUNC(xf86strrchr) + SYMFUNC(xf86strspn) + SYMFUNC(xf86strstr) + SYMFUNC(xf86strtod) + SYMFUNC(xf86strtok) + SYMFUNC(xf86strtol) + SYMFUNC(xf86strtoul) + SYMFUNC(xf86tan) + SYMFUNC(xf86tmpfile) + SYMFUNC(xf86tolower) + SYMFUNC(xf86toupper) + SYMFUNC(xf86ungetc) + SYMFUNC(xf86vfprintf) + SYMFUNC(xf86vsnprintf) + SYMFUNC(xf86vsprintf) + SYMFUNC(xf86write) + +/* non-ANSI C functions */ + SYMFUNC(xf86opendir) + SYMFUNC(xf86closedir) + SYMFUNC(xf86readdir) + SYMFUNC(xf86rewinddir) + SYMFUNC(xf86ffs) + SYMFUNC(xf86strdup) + SYMFUNC(xf86bzero) + SYMFUNC(xf86usleep) + SYMFUNC(xf86execl) + + SYMFUNC(xf86getsecs) + SYMFUNC(xf86fpossize) /* for returning sizeof(fpos_t) */ + + /* These provide for DRI support. */ + SYMFUNC(xf86stat) + SYMFUNC(xf86fstat) + SYMFUNC(xf86access) + SYMFUNC(xf86geteuid) + SYMFUNC(xf86getegid) + SYMFUNC(xf86getpid) + SYMFUNC(xf86mknod) + SYMFUNC(xf86chmod) + SYMFUNC(xf86chown) + SYMFUNC(xf86sleep) + SYMFUNC(xf86mkdir) + SYMFUNC(xf86shmget) + SYMFUNC(xf86shmat) + SYMFUNC(xf86shmdt) + SYMFUNC(xf86shmctl) +#ifdef HAS_GLIBC_SIGSETJMP + SYMFUNC(xf86setjmp) + SYMFUNC(xf86setjmp0) +#if defined(__GLIBC__) && (__GLIBC__ >= 2) + SYMFUNCALIAS("xf86setjmp1",__sigsetjmp) +#else + SYMFUNC(xf86setjmp1) /* For libc5 */ +#endif +#else + SYMFUNCALIAS("xf86setjmp",setjmp) + SYMFUNCALIAS("xf86setjmp0",setjmp) + SYMFUNC(xf86setjmp1) +#endif + SYMFUNCALIAS("xf86longjmp",longjmp) + SYMFUNC(xf86getjmptype) + SYMFUNC(xf86setjmp1_arg2) + SYMFUNC(xf86setjmperror) +#ifdef XF86DRI + /* These may have more general uses, but + for now, they are only used by the DRI. + Loading them only when the DRI is built + may make porting (the non-DRI portions + of the X server) easier. */ + SYMFUNC(xf86InstallSIGIOHandler) + SYMFUNC(xf86RemoveSIGIOHandler) +# if defined(__alpha__) && defined(linux) + SYMFUNC(_bus_base) +# endif +#endif + SYMFUNC(xf86BlockSIGIO) + SYMFUNC(xf86UnblockSIGIO) + +#if defined(__alpha__) + SYMFUNC(__divl) + SYMFUNC(__reml) + SYMFUNC(__divlu) + SYMFUNC(__remlu) + SYMFUNC(__divq) + SYMFUNC(__divqu) + SYMFUNC(__remq) + SYMFUNC(__remqu) + +# ifdef linux + SYMFUNC(_outw) + SYMFUNC(_outb) + SYMFUNC(_outl) + SYMFUNC(_inb) + SYMFUNC(_inw) + SYMFUNC(_inl) + SYMFUNC(_alpha_outw) + SYMFUNC(_alpha_outb) + SYMFUNC(_alpha_outl) + SYMFUNC(_alpha_inb) + SYMFUNC(_alpha_inw) + SYMFUNC(_alpha_inl) +# else + SYMFUNC(outw) + SYMFUNC(outb) + SYMFUNC(outl) + SYMFUNC(inb) + SYMFUNC(inw) + SYMFUNC(inl) +# endif + SYMFUNC(xf86ReadMmio32) + SYMFUNC(xf86ReadMmio16) + SYMFUNC(xf86ReadMmio8) + SYMFUNC(xf86WriteMmio32) + SYMFUNC(xf86WriteMmio16) + SYMFUNC(xf86WriteMmio8) + SYMFUNC(xf86WriteMmioNB32) + SYMFUNC(xf86WriteMmioNB16) + SYMFUNC(xf86WriteMmioNB8) +#endif +#if defined(sun) && defined(SVR4) + SYMFUNC(inb) + SYMFUNC(inw) + SYMFUNC(inl) + SYMFUNC(outb) + SYMFUNC(outw) + SYMFUNC(outl) +#endif +#if defined(__powerpc__) && !defined(__OpenBSD__) + SYMFUNC(inb) + SYMFUNC(inw) + SYMFUNC(inl) + SYMFUNC(outb) + SYMFUNC(outw) + SYMFUNC(outl) +# if defined(NO_INLINE) || defined(Lynx) + SYMFUNC(mem_barrier) + SYMFUNC(ldl_u) + SYMFUNC(eieio) + SYMFUNC(ldl_brx) + SYMFUNC(ldw_brx) + SYMFUNC(stl_brx) + SYMFUNC(stw_brx) + SYMFUNC(ldq_u) + SYMFUNC(ldw_u) + SYMFUNC(stl_u) + SYMFUNC(stq_u) + SYMFUNC(stw_u) + SYMFUNC(write_mem_barrier) +# endif +# if defined(Lynx) + SYMFUNC(_restf14) + SYMFUNC(_restf17) + SYMFUNC(_restf18) + SYMFUNC(_restf19) + SYMFUNC(_restf20) + SYMFUNC(_restf22) + SYMFUNC(_restf23) + SYMFUNC(_restf24) + SYMFUNC(_restf25) + SYMFUNC(_restf26) + SYMFUNC(_restf27) + SYMFUNC(_restf28) + SYMFUNC(_restf29) + SYMFUNC(_savef14) + SYMFUNC(_savef17) + SYMFUNC(_savef18) + SYMFUNC(_savef19) + SYMFUNC(_savef20) + SYMFUNC(_savef22) + SYMFUNC(_savef23) + SYMFUNC(_savef24) + SYMFUNC(_savef25) + SYMFUNC(_savef26) + SYMFUNC(_savef27) + SYMFUNC(_savef28) + SYMFUNC(_savef29) +# endif +# if PPCIO_DEBUG + SYMFUNC(debug_inb) + SYMFUNC(debug_inw) + SYMFUNC(debug_inl) + SYMFUNC(debug_outb) + SYMFUNC(debug_outw) + SYMFUNC(debug_outl) +# endif +#endif +#if defined(__GNUC__) + SYMFUNC(__div64) + SYMFUNC(__divdf3) + SYMFUNC(__divdi3) + SYMFUNC(__divsf3) + SYMFUNC(__divsi3) + SYMFUNC(__moddi3) + SYMFUNC(__modsi3) + SYMFUNC(__mul64) + SYMFUNC(__muldf3) + SYMFUNC(__muldi3) + SYMFUNC(__mulsf3) + SYMFUNC(__mulsi3) + SYMFUNC(__udivdi3) + SYMFUNC(__udivsi3) + SYMFUNC(__umoddi3) + SYMFUNC(__umodsi3) +#endif +#if defined(__ia64__) + SYMFUNC(_outw) + SYMFUNC(_outb) + SYMFUNC(_outl) + SYMFUNC(_inb) + SYMFUNC(_inw) + SYMFUNC(_inl) +#endif +#if defined(__arm__) + SYMFUNC(outw) + SYMFUNC(outb) + SYMFUNC(outl) + SYMFUNC(inb) + SYMFUNC(inw) + SYMFUNC(inl) +#endif + +#ifdef __FreeBSD__ + SYMFUNC(sysctlbyname) +#endif + +/* + * and now some variables + */ + + SYMVAR(xf86stdin) + SYMVAR(xf86stdout) + SYMVAR(xf86stderr) + SYMVAR(xf86errno) + SYMVAR(xf86HUGE_VAL) + + /* General variables (from xf86.h) */ + SYMVAR(xf86ScreenIndex) + SYMVAR(xf86PixmapIndex) + SYMVAR(xf86Screens) + SYMVAR(byte_reversed) + SYMVAR(xf86inSuspend) + /* debugging variables */ +#ifdef BUILDDEBUG + SYMVAR(xf86p8bit) + SYMVAR(xf86DummyVar1) + SYMVAR(xf86DummyVar2) + SYMVAR(xf86DummyVar3) +#endif + +#ifdef async + SYMVAR(xf86CurrentScreen) +#endif + /* predefined resource lists from xf86Bus.h */ + SYMVAR(resVgaExclusive) + SYMVAR(resVgaShared) + SYMVAR(resVgaMemShared) + SYMVAR(resVgaIoShared) + SYMVAR(resVgaUnusedExclusive) + SYMVAR(resVgaUnusedShared) + SYMVAR(resVgaSparseExclusive) + SYMVAR(resVgaSparseShared) + SYMVAR(res8514Exclusive) + SYMVAR(res8514Shared) + SYMVAR(PciAvoid) + +#if defined(__powerpc__) && (!defined(NO_INLINE) || defined(Lynx)) + SYMVAR(ioBase) +#endif + + /* Globals from xf86Globals.c and xf86Priv.h */ + SYMVAR(xf86ConfigDRI) + + /* Globals from xf86Configure.c */ + SYMVAR(ConfiguredMonitor) + + /* Pci.c */ + SYMVAR(pciNumBuses) + + { 0, 0 }, + +}; |