mauro@netcom.COM (Mauro DePalma) (04/14/91)
Submitted-by: Mauro DePalma <mauro@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@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@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@uunet.uu.net.