summaryrefslogtreecommitdiff
path: root/hw/xfree86/loader/aoutloader.c
diff options
context:
space:
mode:
Diffstat (limited to 'hw/xfree86/loader/aoutloader.c')
-rw-r--r--hw/xfree86/loader/aoutloader.c858
1 files changed, 858 insertions, 0 deletions
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;
+}
+