v18i018: cdl - COFF Dynamic Loader, Part02/02
Mauro DePalma
mauro at netcom.COM
Sun Apr 14 07:26:20 AEST 1991
Submitted-by: Mauro DePalma <mauro at netcom.COM>
Posting-number: Volume 18, Issue 18
Archive-name: cdl/part02
#!/bin/sh
# This is part 02 of CDL-1.2
if touch 2>&1 | fgrep '[-amc]' > /dev/null
then TOUCH=touch
else TOUCH=true
fi
# ============= loader.c ==============
echo "x - extracting loader.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > loader.c &&
X
X#ifndef lint
Xstatic char sccsid[] = "@(#) loader.c 1.5 1/18/91 by DePalma SoftCraft";
X#endif
X
X/* UNIX System V/386 COFF Dynamic Loader (CDL).
X*/
X#ifndef PORTAR
X# define PORTAR yes
X#endif
X
X#include <errno.h>
X#include <stdio.h>
X#include <sys/stat.h>
X#include <sys/fcntl.h>
X#include <a.out.h>
X#include <ldfcn.h>
X
X#include "craft.h"
X#include "loader.h"
X
X
X/*
X NAME
X assort(CDL) -- adjust and sort out symbols.
X
X SYNOPSIS
X*/
X int assort(source, seed, name, symndx, dynamic)
X buffer_t source;
X caddr_t * seed;
X char * name;
X int symndx;
X loader_t dynamic;
X/*
X DESCRIPTION
X The goal here is to provide correct values for symbols and
X and place those which are defined in the 'seed' structure.
X*/
X{
X SYMENT * symbol = (SYMENT *) (dynamic->table + symndx * SYMESZ);
X caddr_t item;
X
X/* object archive support
X*/
X if (AVLsearch(*seed, (caddr_t) name, &item, strcmp) == SUCCESS)
X {
X collect_t parcel = (collect_t) item;
X
X if (symbol->n_scnum || (symbol->n_scnum == N_UNDEF && symbol->n_value))
X {
X if (symbol->n_scnum == N_UNDEF && symbol->n_value)
X {
X if (symbol->n_value = (long) allocate(NIL, symbol->n_value))
X symbol->n_sclass = (char) 0;
X else
X return ELDNOMEM;
X }
X
X parcel->sector = sectarian(symbol->n_scnum);
X parcel->segment = source->base;
X parcel->site = symbol->n_value;
X }
X
X return SUCCESS;
X }
X
X/* see if it's a global symbol
X*/
X if (AVLsearch(Global, (caddr_t) name, &item, strcmp) == SUCCESS)
X if (symbol->n_scnum == N_UNDEF)
X {
X collect_t parcel = (collect_t) item;
X
X symbol->n_value = parcel->site;
X
X if (parcel->sector == N_DATA || parcel->sector == N_BSS)
X symbol->n_sclass = (char) 0;
X
X return SUCCESS;
X }
X
X/* see if it's uninitialized data
X*/
X if (symbol->n_scnum == N_UNDEF && symbol->n_value)
X {
X if (symbol->n_value = (long) allocate(NIL, symbol->n_value))
X symbol->n_sclass = (char) 0;
X else
X return ELDNOMEM;
X }
X
X return collect(source, seed, name, symbol, dynamic);
X} /* assort */
X
X
X
X/*
X NAME
X collect(CDL) -- collect symbols.
X
X SYNOPSIS
X*/
X static int collect(source, seed, name, symbol, dynamic)
X buffer_t source;
X caddr_t * seed;
X char * name;
X SYMENT * symbol;
X loader_t dynamic;
X/*
X DESCRIPTION
X*/
X{
X collect_t parcel = (collect_t) 0;
X int status;
X
X if (! (parcel = (collect_t) allocate(NIL, sizeof(struct _collect))))
X return ELDNOMEM;
X
X if (symbol)
X {
X parcel->sector = sectarian(symbol->n_scnum);
X parcel->segment = source->base;
X parcel->site = symbol->n_value;
X }
X else
X {
X parcel->sector = N_FILE;
X parcel->segment = (dynamic) ? dynamic->segment : (char *) 0;
X parcel->site = source->mark;
X }
X
X status = AVLinsert(seed, (caddr_t) name, (caddr_t) parcel, strcmp);
X
X if (status != SUCCESS)
X {
X deallocate((caddr_t) parcel);
X status = DUBIOUS(status);
X }
X
X return status;
X} /* collect */
X
X
X
X/*
X NAME
X destruct(CDL) -- dispose of a single stored symbol.
X
X SYNOPSIS
X*/
X static int destruct(key, item)
X caddr_t key;
X caddr_t item;
X/*
X DESCRIPTION
X*/
X{
X deallocate(item);
X deallocate(key);
X
X return SUCCESS;
X} /* destruct */
X
X
X
X/*
X NAME
X initialize(CDL) -- dynamic loader initialization.
X
X SYNOPSIS
X*/
X static int initialize(pid)
X int pid;
X/*
X DESCRIPTION
X Initialization consists on a "ps -fp `echo $$`" using the 8th
X field of the last line of output from that command.
X*/
X{
X if (Global == (caddr_t) 0) /* initialization required */
X {
X FILE * stream;
X LDFILE * ldptr;
X char line[BUFSIZ];
X char * image;
X int status;
X short scan;
X
X (void) sprintf(line, "ps -fp %d", pid);
X
X if (stream = popen(line, "r"))
X while (fgets(line, BUFSIZ, stream))
X ;
X
X for (scan = 0; scan < 8; scan++) /* 'image' is the 8th field */
X image = strtok((scan) ? NULL : line, " ");
X
X ldptr = ldopen(image = which(image), NULL);
X status = (ldptr) ? SUCCESS : ERROR(sys_errlist, errno);
X
X if (status == SUCCESS)
X {
X struct _buffer record;
X struct _buffer * source = &record;
X
X if ((status = quantum(ldptr, source, image)) == SUCCESS)
X status = prospect(ldptr, source, &Global, NIL);
X
X (void) ldclose(ldptr);
X }
X
X return status;
X }
X
X return SUCCESS;
X} /* initialize */
X
X
X
X/*
X NAME
X process(CDL) -- driver for loading a module.
X
X SYNOPSIS
X*/
X static int process(ldptr, source, seed, card)
X LDFILE * ldptr;
X buffer_t source;
X caddr_t * seed;
X caddr_t * card;
X/*
X DESCRIPTION
X*/
X{
X int status;
X loader_t dynamic;
X
X if (! (dynamic = (loader_t) allocate(NIL, sizeof(struct _loader))))
X return ELDNOMEM;
X
X if ((status = profile(ldptr, dynamic)) == SUCCESS)
X if ((status = prospect(ldptr, source, seed, dynamic)) == SUCCESS)
X if (Stack(card, (caddr_t) dynamic) == (caddr_t) 0)
X status = ELDNOMEM;
X
X if (status != SUCCESS)
X {
X deallocate((caddr_t) dynamic->reloc.base);
X deallocate((caddr_t) dynamic->segment);
X deallocate((caddr_t) dynamic->table);
X deallocate((caddr_t) dynamic);
X }
X
X return status;
X} /* process */
X
X
X
X/*
X NAME
X profile(CDL) -- read relevant information.
X
X SYNOPSIS
X*/
X static int profile(ldptr, dynamic)
X LDFILE * ldptr;
X loader_t dynamic;
X/*
X DESCRIPTION
X Sufficient memory is allocated for combined section data,
X relocation information, and symbol table; each of these parts
X are read from the LDFILE* 'ldptr' into their respective
X loader_t (see, loader.h) 'dynamic' component.
X*/
X{
X FILHDR * header = &HEADER(ldptr);
X SCNHDR scnhdr;
X SCNHDR * section = &scnhdr;
X long region = (long) 0;
X ushort nreloc = (ushort) 0;
X ushort scnum;
X
X if (! ISCOFF(header->f_magic))
X return ELDBADHDR;
X
X/* read section headers and track size of combined section data
X along with the number of relocation entries
X*/
X for (scnum = 1; scnum <= header->f_nscns; scnum++)
X {
X if (ldshread(ldptr, scnum, section) == FAILURE)
X return ELDSCNHDR;
X
X nreloc += section->s_nreloc;
X region += section->s_size;
X }
X
X/* allocate and read combined section data
X*/
X if (! (dynamic->segment = (char *) allocate(NIL, region)))
X return ELDNOMEM;
X
X if (ldsseek(ldptr, N_TEXT) == FAILURE && errno > 0)
X return ERROR(sys_errlist, errno);
X
X if (FREAD(dynamic->segment, sizeof(char), region, ldptr) != region)
X return ELDSECTION;
X
X/* allocate and read combined relocation entries
X*/
X region = (long) nreloc * RELSZ;
X
X if (! (dynamic->reloc.base = (char *) allocate(NIL, region)))
X return ELDNOMEM;
X
X dynamic->reloc.mark = (long) nreloc;
X
X if (FREAD(dynamic->reloc.base, sizeof(char), region, ldptr) != region)
X return ELDRELOC;
X
X/* allocate and read the symbol table (assume: AUXESZ == SYMESZ)
X*/
X region = header->f_nsyms * SYMESZ;
X
X if (! (dynamic->table = (char *) allocate(NIL, region)))
X return ELDNOMEM;
X
X if (ldtbseek(ldptr) == FAILURE)
X return ERROR(sys_errlist, errno);
X
X if (FREAD(dynamic->table, sizeof(char), region, ldptr) != region)
X return ELDSYMBOL;
X
X return SUCCESS;
X} /* profile */
X
X
X
X/*
X NAME
X prospect(CDL) -- store global symbols.
X
X SYNOPSIS
X*/
X static int prospect(ldptr, source, seed, dynamic)
X LDFILE * ldptr;
X buffer_t source;
X caddr_t * seed;
X loader_t dynamic;
X/*
X DESCRIPTION
X*/
X{
X SYMENT syment;
X SYMENT * symbol = &syment;
X int status = SUCCESS;
X ushort symndx;
X ushort nsyms;
X
X for (nsyms = HEADER(ldptr).f_nsyms, symndx = 0; symndx < nsyms; )
X {
X if (ldtbread(ldptr, symndx, symbol) == FAILURE)
X break;
X
X if (symbol->n_sclass == C_EXT && symbol->n_scnum >= 0)
X {
X char * name = strdup(ldgetname(ldptr, symbol));
X
X if (dynamic)
X status = assort(source, seed, name, symndx, dynamic);
X else
X status = collect(source, seed, name, symbol, dynamic);
X
X if (status != SUCCESS)
X break;
X }
X
X symndx += symbol->n_numaux + 1;
X }
X
X if (status == SUCCESS)
X status = collect(source, seed, source->base, NULL, dynamic);
X
X return status;
X} /* prospect */
X
X
X
X/*
X NAME
X quantum(CDL) -- identify module.
X
X SYNOPSIS
X*/
X static int quantum(ldptr, source, module)
X LDFILE * ldptr;
X buffer_t source;
X char * module;
X/*
X DESCRIPTION
X Here we determine whether what is being processed is an object
X file or an archive. The buffer_t (see, craft.h) 'source' fields
X in either case are set to the module name and its modification
X date/time.
X
X BUGS
X Although, there may be other reasons, ldahread(3X) failure is
X taken as proof that we're dealing with and object file.
X*/
X{
X ARCHDR archdr;
X char buffer[BLOCK];
X
X if (ldahread(ldptr, &archdr) == SUCCESS)
X {
X (void) sprintf(buffer, "%s[%s]", module, archdr.ar_name);
X
X source->base = strdup(buffer);
X source->mark = archdr.ar_date;
X }
X else
X {
X struct stat info;
X
X if (stat(module, &info) == -1)
X return ERROR(sys_errlist, errno);
X
X source->base = strdup(module);
X source->mark = info.st_mtime;
X }
X
X return SUCCESS;
X} /* quantum */
X
X
X
X/*
X NAME
X realize(CDL) -- realize a newly loaded file.
X
X SYNOPSIS
X*/
X static int realize(symtab, card)
X caddr_t symtab;
X caddr_t * card;
X/*
X DESCRIPTION
X*/
X{
X int status = SUCCESS;
X loader_t dynamic;
X
X AVLwalk(symtab, shepherd, (caddr_t) &status);
X
X if (status == SUCCESS)
X {
X AVLwalk(symtab, sloven, (caddr_t) &status);
X
X while (status == SUCCESS && (dynamic = (loader_t) Stack(card, NIL)))
X {
X status = resolve(dynamic);
X
X if (status == SUCCESS)
X {
X struct _assoc vehicle;
X struct _assoc * shuttle = &vehicle;
X
X shuttle->key = (caddr_t) dynamic->segment;
X shuttle->item = (caddr_t) &status;
X
X AVLwalk(symtab, solder, (caddr_t) shuttle);
X }
X
X if (status != SUCCESS)
X deallocate((caddr_t) dynamic->segment);
X
X deallocate((caddr_t) dynamic->reloc.base);
X deallocate((caddr_t) dynamic->table);
X deallocate((caddr_t) dynamic);
X }
X }
X
X/* always: completely discard 'card' stack and contents
X*/
X while (dynamic = (loader_t) Stack(card, NIL))
X {
X deallocate((caddr_t) dynamic->reloc.base);
X deallocate((caddr_t) dynamic->segment);
X deallocate((caddr_t) dynamic->table);
X deallocate((caddr_t) dynamic);
X }
X
X return status;
X} /* realize */
X
X
X
X/*
X NAME
X resolve(CDL) -- resolve relocation entries.
X
X SYNOPSIS
X*/
X static int resolve(dynamic)
X loader_t dynamic;
X/*
X DESCRIPTION
X*/
X{
X SYMENT * symbol;
X RELOC * reloc;
X char * address;
X long datum;
X ushort nreloc;
X ushort count;
X
X for (count = 0, nreloc = dynamic->reloc.mark; count < nreloc; count++)
X {
X reloc = (RELOC *) (dynamic->reloc.base + count * RELSZ);
X
X if (reloc->r_type == R_ABS) /* absolute: no relocation necessary */
X continue;
X
X address = (char *) (reloc->r_vaddr + (long) dynamic->segment);
X symbol = (SYMENT *) (dynamic->table + reloc->r_symndx * SYMESZ);
X
X if (symbol->n_scnum == N_UNDEF || symbol->n_scnum == N_TEXT)
X datum = symbol->n_value;
X else
X datum = (long) 0;
X
X if (symbol->n_sclass) /* see, assort(CDL) for details */
X switch (reloc->r_type)
X {
X case R_DIR16:
X (void) puts(DANGER("relocation type R_DIR16 untested"));
X datum += *(short *) address + (long) dynamic->segment;
X break;
X
X case R_REL16:
X (void) puts(DANGER("relocation type R_REL16 untested"));
X if (datum)
X datum -= (long) address + sizeof(short);
X break;
X
X case R_DIR32:
X datum += *(long *) address + (long) dynamic->segment;
X break;
X
X case R_PCRLONG:
X if (datum)
X datum -= (long) address + sizeof(long);
X break;
X
X default:
X return ELDRESOLVE;
X }
X
X switch (reloc->r_type)
X {
X case R_DIR16: /* direct, 16-bit reference */
X case R_REL16: /* PC relative, 16-bit reference */
X if (datum < -32768 || datum > 32767)
X return ELDRESOLVE;
X
X *(short *) address = datum;
X break;
X
X case R_DIR32: /* direct, 32-bit reference */
X case R_PCRLONG: /* PC relative, 32-bit reference */
X if (datum)
X *(long *) address = datum;
X break;
X
X default:
X return ELDRESOLVE;
X }
X }
X
X return SUCCESS;
X} /* resolve */
X
X
X
X/*
X NAME
X selector(CDL) -- select a global symbol.
X
X SYNOPSIS
X*/
X static int selector(key, item, ark)
X caddr_t key;
X caddr_t item;
X caddr_t ark;
X/*
X DESCRIPTION
X Selector inserts a global symbol in a 'list' when
X the symbol belongs to the 'module' given.
X
X ark -> +--------+
X | module |
X |--------|
X | list |
X +--------+
X*/
X{
X assoc_t shuttle = (assoc_t) ark;
X collect_t parcel = (collect_t) item;
X int status = SUCCESS;
X
X if (parcel->sector != N_FILE)
X if (strcmp(parcel->segment, (char *) shuttle->key) == 0)
X status = LLinsert(&(shuttle->item), key, item);
X
X return status;
X} /* selector */
X
X
X
X/*
X NAME
X shepherd(CDL) -- govern a local symbol tree.
X
X SYNOPSIS
X*/
X static int shepherd(key, item, ark)
X caddr_t key;
X caddr_t item;
X caddr_t ark;
X/*
X DESCRIPTION
X Shepherd flags multiply defined symbols and corrects the
X address for those which exist.
X*/
X{
X caddr_t store = (caddr_t) 0;
X
X if (AVLsearch(Global, key, &store, strcmp) == SUCCESS)
X {
X collect_t packet = (collect_t) item;
X collect_t parcel = (collect_t) store;
X int * state = (int *) ark;
X
X if (*state == SUCCESS)
X {
X *state = FAILURE;
X error(ELDMULDEF);
X }
X
X error(ERRMSG, "%s : '%s' already defined in '%s'",
X packet->segment, key, parcel->segment);
X }
X
X return SUCCESS;
X} /* shepherd */
X
X
X
X/*
X NAME
X sloven(CDL) -- flag undefined symbols.
X
X SYNOPSIS
X*/
X static int sloven(key, item, ark)
X caddr_t key;
X caddr_t item;
X caddr_t ark;
X/*
X DESCRIPTION
X*/
X{
X collect_t parcel = (collect_t) item;
X
X if (parcel->sector == N_UNDEF && parcel->site == (long) 0)
X {
X int * state = (int *) ark;
X
X if (*state == SUCCESS)
X {
X *state = FAILURE;
X error(ELDUNDEF);
X }
X
X error(ERRMSG, "'%s' referenced in '%s'", key, parcel->segment);
X }
X
X return SUCCESS;
X} /* sloven */
X
X
X
X/*
X NAME
X solder(CDL) -- add new symbols to global structure.
X
X SYNOPSIS
X*/
X static int solder(key, item, ark)
X caddr_t key;
X caddr_t item;
X caddr_t ark;
X/*
X DESCRIPTION
X Solder is an action routine which serves to copy a symbol
X from a working structure to the global symbols structure.
X
X ark -> +--------------------------------+
X | loader_t record |
X |--------------------------------|
X | start of combined section data |
X +--------------------------------+
X*/
X{
X assoc_t shuttle = (assoc_t) ark;
X collect_t parcel = (collect_t) item;
X int * state = (int *) shuttle->item;
X
X if (*state == SUCCESS)
X {
X collect_t store;
X
X if (store = (collect_t) allocate(NIL, sizeof(struct _collect)))
X {
X store->sector = parcel->sector;
X store->segment = parcel->segment;
X store->site = parcel->site;
X
X if (store->sector != N_FILE)
X store->site += (long) shuttle->key;
X
X *state = AVLinsert(&Global, (caddr_t) key, (caddr_t) store, strcmp);
X }
X else
X {
X *state = ELDNOMEM;
X }
X }
X
X return SUCCESS;
X} /* solder */
X
X
X
X/*
X NAME
X solvent(CDL) -- remove a global symbol.
X
X SYNOPSIS
X*/
X static int solvent(key, item)
X caddr_t key;
X caddr_t item;
X/*
X DESCRIPTION
X*/
X{
X return AVLremove(&Global, key, strcmp, destruct);
X} /* solvent */
X
X
X
X/*
X NAME
X load(3L) -- load a common object file.
X
X SYNOPSIS
X*/
X int load(module)
X char * module;
X/*
X DESCRIPTION
X If the given 'module' has been loaded already its modification
X date is compared with the dynamic loading date; when the two dates
X differ an unload(3L) is performed on the one in memory and dynamic
X loading is then attempted with the 'module' given.
X
X SEE ALSO
X error(3L), symbol(3L), unload(3L).
X
X DIAGNOSTICS
X Upon successful completion SUCCESS is returned. Otherwise the
X value of the return status indicates what error was encountered.
X*/
X{
X LDFILE * ldptr = (LDFILE *) 0;
X caddr_t item;
X caddr_t symtab = (caddr_t) 0;
X caddr_t vitals = (caddr_t) 0;
X int status;
X long stamp;
X struct _buffer record;
X struct _buffer * source = &record;
X
X if ((status = initialize(getpid())) == SUCCESS)
X {
X do
X {
X if (ldptr = ldopen(module, ldptr))
X {
X if ((status = quantum(ldptr, source, module)) != SUCCESS)
X break;
X
X if (stamp = (long) symbol(source->base))
X {
X if (stamp == source->mark)
X continue;
X
X if ((status = unload(source->base)) != SUCCESS)
X break;
X }
X
X status = process(ldptr, source, &symtab, &vitals);
X }
X } while (ldclose(ldptr) == FAILURE && status == SUCCESS);
X
X if (symtab)
X {
X if (status == SUCCESS) /* augment global structure */
X status = realize(symtab, &vitals);
X
X AVLdispose(symtab, (agent_t)((status == SUCCESS) ? 0 : destruct));
X }
X else
X {
X if (errno)
X status = ERROR(sys_errlist, errno);
X }
X }
X
X return status;
X} /* load */
X
X
X
X/*
X NAME
X symbol(3L) -- symbol look up.
X
X SYNOPSIS
X*/
X void * symbol(name)
X char * name;
X/*
X DESCRIPTION
X The specified 'name' is looked up and if found its value returned.
X A value of NIL indicates look up failure.
X*/
X{
X caddr_t item;
X void * entry = NIL;
X
X if (AVLsearch(Global, (caddr_t) name, &item, strcmp) == SUCCESS)
X {
X collect_t parcel = (collect_t) item;
X
X entry = (void *) parcel->site;
X }
X
X return entry;
X} /* symbol */
X
X
X
X/*
X NAME
X unload(3L) -- unload all symbols associated with a module.
X
X SYNOPSIS
X*/
X int unload(module)
X char * module;
X/*
X DESCRIPTION
X All symbols associated with the given module are indiscriminately
X removed and any memory allocated is freed.
X*/
X{
X caddr_t item;
X collect_t parcel;
X struct _assoc vehicle;
X struct _assoc * shuttle = &vehicle;
X
X if (AVLsearch(Global, (caddr_t) module, &item, strcmp) != SUCCESS)
X return ELDNOFILE;
X
X shuttle->key = (caddr_t) module;
X shuttle->item = (caddr_t) 0;
X
X/* we cannot directly remove symbols
X*/
X AVLwalk(Global, selector, (caddr_t) shuttle);
X
X LLwalk(shuttle->item, solvent, NIL);
X LLdispose(shuttle->item, destruct);
X
X/* free what we allocated for combined section data
X*/
X parcel = (collect_t) item;
X
X if (parcel->segment)
X deallocate(parcel->segment);
X
X return DUBIOUS(AVLremove(&Global, (caddr_t) module, strcmp, destruct));
X} /* unload */
X
X
X
X#ifdef DEBUG
X/*
X NAME
X display -- display routine for symbols.
X
X SYNOPSIS
X*/
X static int display(key, item, nest, ark)
X caddr_t key;
X caddr_t item;
X int nest;
X caddr_t ark;
X/*
X DESCRIPTION
X*/
X{
X collect_t parcel = (collect_t) item;
X int status;
X
X if (parcel->sector == N_FILE)
X status = printf("%19s(%d) : 0x%8.8x\n", (char*) key,
X parcel->site, (long) parcel->segment);
X else
X status = printf("%19s(%s) : 0x%8.8x\n", (char*) key,
X parcel->segment, parcel->site);
X
X return status;
X} /* display */
X
X
X
X/*
X NAME
X dump -- dump symbol table.
X
X SYNOPSIS
X*/
X void dump(symtab)
X caddr_t symtab;
X/*
X DESCRIPTION
X*/
X{
X
X AVLdump(symtab, display, NIL);
X} /* dump */
X#endif /* DEBUG */
SHAR_EOF
$TOUCH -am 0118122491 loader.c &&
chmod 0444 loader.c ||
echo "restore of loader.c failed"
set `wc -c loader.c`;Wc_c=$1
if test "$Wc_c" != "21155"; then
echo original size 21155, current size $Wc_c
fi
# ============= loader.h ==============
echo "x - extracting loader.h (Text)"
sed 's/^X//' << 'SHAR_EOF' > loader.h &&
X
X/* UNIX System V/386 COFF Dynamic Loader (CDL) header file.
X
X loader.h 1.5 1/18/91 by DePalma SoftCraft
X*/
X
X#ifndef __LOADER_H__ /* guard against multiple includes */
X#define __LOADER_H__
X
X/* mauro at olympus (19910104.1808)
X
X The, UNIX System V/386 Programmer's Guide warns that it is a mistake
X to assume the characteristics of sections in general of a COFF file.
X
X Here however the assumption is made that the sections named '.text',
X '.data', '.bss' appear as the first three sections in a COFF file.
X*/
X#define sectarian(x) (x) /* .. only if assumption hold true */
X
X#define N_TEXT 1 /* mnemonic for '.text' section */
X#define N_DATA 2 /* mnemonic for '.data' section */
X#define N_BSS 3 /* mnemonic for '.bss' section */
X
X#define N_FILE 0x1f /* special: file name symbol */
X
X
Xtypedef union /* either symbol or auxiliary entry */
X {
X AUXENT auxent; /* .. auxiliary entry */
X SYMENT syment; /* .. symbol entry */
X } SYMBOL;
X
X
Xtypedef struct _collect /* Dynamic Loader symbol data */
X {
X char sector; /* .. section mnemonic or N_FILE */
X char * segment; /* .. combined section data or file */
X long site; /* .. offset in memory or date/time */
X } *collect_t;
X
X
Xtypedef struct _loader /* Dynamic Loader data structure */
X {
X struct _buffer reloc; /* .. relocation entries */
X char * segment; /* .. start of combined section data */
X char * table; /* .. symbol table and auxiliary */
X } *loader_t;
X
X
X/* Dynamic Loader Specific Errors (should be read from a message file)
X*/
Xstatic char *ldErrorList[] =
X {
X "",
X "The file doesn't have a COFF header", /* 1 */
X "Dynamic Loader cannot allocate enough memory", /* 2 */
X "An error was encountered while reading the file header", /* 3 */
X "An error was encountered while reading the optional header", /* 4 */
X "An error was encountered while reading a section header", /* 5 */
X "An error was encountered while reading section data", /* 6 */
X "An error was encountered while reading relocation information", /* 7 */
X "An error was encountered while reading the symbol table", /* 8 */
X "The following symbols are multiply defined:", /* 9 */
X "The following symbols remain undefined:", /* 10 */
X "Dynamic Loader cannot handle a relocation entry", /* 11 */
X "No such file dynamically loaded", /* 12 */
X 0
X };
X
X#define ELDBADHDR ERROR(ldErrorList, 1) /* invalid a.out header */
X#define ELDNOMEM ERROR(ldErrorList, 2) /* can't allocate enough memory */
X#define ELDFILHDR ERROR(ldErrorList, 3) /* error reading file header */
X#define ELDOPTHDR ERROR(ldErrorList, 4) /* error reading optional header*/
X#define ELDSCNHDR ERROR(ldErrorList, 5) /* error reading section header */
X#define ELDSECTION ERROR(ldErrorList, 6) /* error reading section data */
X#define ELDRELOC ERROR(ldErrorList, 7) /* error reading reloc. entries */
X#define ELDSYMBOL ERROR(ldErrorList, 8) /* error reading symbol table */
X#define ELDMULDEF ERROR(ldErrorList, 9) /* multiply defined symbol(s) */
X#define ELDUNDEF ERROR(ldErrorList, 10) /* unresolved symbol(s) */
X#define ELDRESOLVE ERROR(ldErrorList, 11) /* (internal) unable to resolve */
X#define ELDNOFILE ERROR(ldErrorList, 12) /* file was not loaded */
X
X
X
X/* Dynamic Loader Private
X*/
Xstatic int assort(buffer_t, caddr_t *, char *, int, loader_t);
Xstatic int collect(buffer_t, caddr_t *, char *, SYMENT *, loader_t);
Xstatic int destruct(caddr_t, caddr_t);
X
Xstatic int initialize(int);
Xstatic int process(LDFILE *, buffer_t, caddr_t *, caddr_t *);
Xstatic int profile(LDFILE *, loader_t);
Xstatic int prospect(LDFILE *, buffer_t, caddr_t *, loader_t);
Xstatic int quantum(LDFILE *, buffer_t, char *);
Xstatic int realize(caddr_t, caddr_t *);
Xstatic int resolve(loader_t);
X
Xstatic int selector(caddr_t, caddr_t, caddr_t);
Xstatic int shepherd(caddr_t, caddr_t, caddr_t);
Xstatic int sloven(caddr_t, caddr_t, caddr_t);
Xstatic int solder(caddr_t, caddr_t, caddr_t);
Xstatic int solvent(caddr_t, caddr_t);
X
Xstatic caddr_t Global = (caddr_t) 0; /* symbol table for globals */
X
X
X/* Dynamic Loader Externals
X*/
Xextern char * ldgetname(LDFILE *, SYMENT *);
X#endif /* __LOADER_H__ */
X
SHAR_EOF
$TOUCH -am 0118122491 loader.h &&
chmod 0444 loader.h ||
echo "restore of loader.h failed"
set `wc -c loader.h`;Wc_c=$1
if test "$Wc_c" != "4799"; then
echo original size 4799, current size $Wc_c
fi
# ============= simple.c ==============
echo "x - extracting simple.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > simple.c &&
X
X#include <stdio.h>
X
Xextern char* sys_errlist[];
X
Xchar *module = __FILE__;
Xshort bogus;
X
Xvoyage(char* caller)
X{
X char* routine = "voyage";
X
X (void) printf("<%s line %d> %s: called by, '%s'\n",
X module, __LINE__, routine, caller);
X gossip(routine);
X}
X
Xgossip(char* caller)
X{
X char* routine = "gossip";
X
X (void) printf("<%s line %d> %s: called by, '%s'\n",
X module, __LINE__, routine, caller);
X
X (void) printf("<%s line %d> %s: some extern data, '%s'\n",
X module, __LINE__, routine, sys_errlist[1]);
X
X (void) printf("<%s line %d> %s: some local data, '%d'\n",
X module, __LINE__, routine, bogus=1234);
X}
SHAR_EOF
$TOUCH -am 0116200491 simple.c &&
chmod 0644 simple.c ||
echo "restore of simple.c failed"
set `wc -c simple.c`;Wc_c=$1
if test "$Wc_c" != "676"; then
echo original size 676, current size $Wc_c
fi
exit 0
exit 0 # Just in case...
--
Kent Landfield INTERNET: kent at sparky.IMD.Sterling.COM
Sterling Software, IMD UUCP: uunet!sparky!kent
Phone: (402) 291-8300 FAX: (402) 291-4362
Please send comp.sources.misc-related mail to kent at uunet.uu.net.
More information about the Comp.sources.misc
mailing list