[comp.sources.misc] v18i018: cdl - COFF Dynamic Loader, Part02/02

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.