summaryrefslogtreecommitdiff
path: root/hw/xfree86/loader
diff options
context:
space:
mode:
Diffstat (limited to 'hw/xfree86/loader')
-rw-r--r--hw/xfree86/loader/SparcMulDiv.S87
-rw-r--r--hw/xfree86/loader/aout.h232
-rw-r--r--hw/xfree86/loader/aoutloader.c858
-rw-r--r--hw/xfree86/loader/aoutloader.h31
-rw-r--r--hw/xfree86/loader/ar.h77
-rw-r--r--hw/xfree86/loader/coff.h244
-rw-r--r--hw/xfree86/loader/coffloader.c1358
-rw-r--r--hw/xfree86/loader/coffloader.h34
-rw-r--r--hw/xfree86/loader/dixsym.c367
-rw-r--r--hw/xfree86/loader/dlloader.c191
-rw-r--r--hw/xfree86/loader/dlloader.h32
-rw-r--r--hw/xfree86/loader/elf.h710
-rw-r--r--hw/xfree86/loader/elfloader.c3024
-rw-r--r--hw/xfree86/loader/elfloader.h34
-rw-r--r--hw/xfree86/loader/extsym.c79
-rw-r--r--hw/xfree86/loader/fontsym.c79
-rw-r--r--hw/xfree86/loader/hash.c364
-rw-r--r--hw/xfree86/loader/hash.h36
-rw-r--r--hw/xfree86/loader/loader.c1412
-rw-r--r--hw/xfree86/loader/loader.h269
-rw-r--r--hw/xfree86/loader/loaderProcs.h96
-rw-r--r--hw/xfree86/loader/loadext.c419
-rw-r--r--hw/xfree86/loader/loadfont.c53
-rw-r--r--hw/xfree86/loader/loadmod.c1296
-rw-r--r--hw/xfree86/loader/misym.c180
-rw-r--r--hw/xfree86/loader/os.c49
-rw-r--r--hw/xfree86/loader/sym.h46
-rw-r--r--hw/xfree86/loader/xf86sym.c1133
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, &secttable);
+
+/*
+ * Do relocations
+ */
+ for (i = 0; i < elffile->lsectidx; i++) {
+ switch (SecType(elffile->lsection[i].ndx)) {
+ case SHT_REL:
+ case SHT_RELA:
+ break;
+ default:
+ continue;
+ }
+ elf_reloc = ELFCollectRelocations(elffile,elffile->lsection[i].ndx);
+ if (elf_reloc) {
+ for (tail = elf_reloc; tail->next; tail = tail->next)
+ ;
+ tail->next = _LoaderGetRelocations(v)->elf_reloc;
+ _LoaderGetRelocations(v)->elf_reloc = elf_reloc;
+ }
+ }
+
+#if defined(__ia64__)
+ totalsize += (elffile->sections[elffile->pltndx].sh_addralign - 1);
+ totalsize &= ~(elffile->sections[elffile->pltndx].sh_addralign - 1);
+ totalsize += elffile->pltsize;
+ if (maxalign < elffile->sections[elffile->pltndx].sh_addralign)
+ maxalign = elffile->sections[elffile->pltndx].sh_addralign;
+#endif
+
+ /* Space for COMMON */
+ totalsize = (totalsize + 7) & ~7;
+ totalsize += ElfCOMMONSize();
+
+#ifdef MergeSectionAlloc
+ elffile->basesize = totalsize + maxalign;
+
+# if !defined(DoMMAPedMerge)
+ elffile->base = xf86loadermalloc(elffile->basesize);
+ if (elffile->base == NULL) {
+ ErrorF( "Unable to allocate ELF sections\n" );
+ return NULL;
+ }
+# if defined(linux) && defined(__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, &section) )
+ 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, &section) )
+ 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 },
+
+};