More Dynamic Loading and Stuff.

Jeff P. M. Hultquist hultquis at nas.nasa.gov
Tue May 14 15:45:39 AEST 1991


>>>  rpaul at crow.UUCP (Rodian Paul) writes ...
>
> Has anybody else out there experimented with adding modules to an
> application in a quazi dynamic way? i.e. it being possible to add
> extras into an allready executing program other than using pipes and
> stuff?

Here is some stuff from a small LISP/C package I have been
working on ...  The first file is the top level command define
which call a shell script to create an object file, and the
calls 'load-object-file' to link this new code into the
running app.

Good luck.
-- jeff

--------------------------------------------------
;;; dynload.scm


(define (LOAD-C name #!optional ld-args)
  ;;
  (default ld-args "")
  (let ((mother  "/u/wk/hultquis/flora/bin/flora.bin")
	(tmp-c   "/tmp/fasl.c")
	(tmp-o   "/tmp/fasl.o")
	(scratch "/tmp/scratch.o")
	(opts    "-g -G 0")
	(defs    "-DDO_PRIMS -DIRIS4D")
	(incs    "-I$HOME/flora/src/c"))
    ;;
    (let ((filter  (sprintf "$HOME/flora/etc/lcc %s > %s" name tmp-c))
	  (compile (sprintf "cc %s %s %s -o %s -c %s"
			    opts defs incs tmp-o tmp-c)))
      ;;
      (let ((res (system:command filter)))
	(assert (zero? res)))
      (let ((res (system:command compile)))
	(assert (zero? res)))
      (load-object-file tmp-o mother ld-args scratch))))



;;; end

--------------------------------------------------
#!/bin/csh 
# lcc <file>
#
# This script takes a source file in which some of the routine names
# have been declared as:
#			PRIMITIVE(c_name, scheme-name) 
#
# These declarations are filtered out of the file and are turned into
# commands of the form:
#			prim_install("scheme-name", c_name);
#
# The compiled file is linked and loaded into the running application,
# and the first function is called.  (!! We currently assume that the
# first address of the linked data is the entry-point for the first
# routine in the file.)  This first routine is responsible for calling
# the function `prim-install' for each new primitive.


cat << _EOF_
/* begin */

static int init();
static int real_init();

static int
init() 
{
    real_init();
    return(0); 
}

_EOF_


cat $1


# output the epilogue, including a sequence of
# commands to install the new primitives into 
# the Scheme namespace (using prim_install).
#
cat << _EOF_
static int real_init()
{
_EOF_

sed -n	-e 's/[(,)]/ /g' \
	-e 's/PRIMITIVE//p' $1 |\
awk '{printf "    prim_install(\"%s\", %s);\n", $2,$1}'
	
cat << _EOF_
}
/* end */
_EOF_
 
exit $status


# end

--------------------------------------------------
/* dynload.c */

#include <xscheme/xscheme.h>
#include <stdio.h>
#include <ctype.h>
#include <a.out.h>

struct headers { /* !! why is this here? */
    struct filehdr fhdr;
    struct aouthdr aout;
};

#define ASSERT(cond, msg) ((cond) ? 1 : xlfail(msg))
#define ALIGN   0xf
typedef int (*PFI)();


PRIMITIVE(load_object_file_prim, LOAD-OBJECT-FILE)
{
    PFI load_object_file();
    PFI bootstrap;
    char *newobj = GET_STRING();
    char *mother = GET_STRING();
    char *ldargs = GET_STRING();
    char *tmp    = GET_STRING();
    LAST_ARG();
    
    bootstrap = load_object_file(newobj, mother, ldargs, tmp); 
    if (bootstrap) {
	(*bootstrap)();
    }
    return(true_lval);
}


static PFI
load_object_file (char *newobj,	  /* a compiled object file */
		  char *mother,	  /* the image to link against */
		  char *ldargs,	  /* additional args and libraries */
		  char *tmp)	  /* scratch file */
{
    /* 
    ** This takes an object file and resolves its dangling references
    ** with respect to some larger application.  The linked object
    ** might be larger than was expected from simply checking the
    ** header data, and so we might be required to link this file
    ** twice until the linked image is small enough to fit in the 
    ** image space that had been allocated for it.
    */
    int guess_size;	/* expected size of linked image */
    int num_pass;	/* counter of attempts to link */
    void *bfr;		/* pointer to malloc'd memory */
    void *base;		/* aligned pointer to loabable space */
    char cmd[256];	/* command line to run the linker */
    int  res;		/* result returned by linker */
    FILE *fp;		/* ptr to linked file */
    int i;
    struct headers hdr;  
    struct scnhdr sections[10];
    int actual_size;	/* total size of linked image */

    guess_size = guess_code_size(newobj);
    for (num_pass=1; num_pass<4; num_pass++) {
	fprintf(stderr, "    pass %d of linker ... ", num_pass);
	fflush(stderr);

	bfr = (void *) malloc(guess_size+ALIGN);
	ASSERT(bfr, "Couldn't allocate code space");
	base = (void *) ((((int) bfr) + ALIGN) & ~ALIGN);
	sprintf(cmd, "ld -g -o %s -A %s -T %x -N %s %s",
		tmp, mother, base, newobj, ldargs);
	res = system(cmd);
	ASSERT(res>=0, "Running ld failed");
	fp  = fopen(tmp, "r");
	ASSERT(fp, "Could not open linked file.");

	fread(&hdr, sizeof(hdr), 1, fp);
	for (i=0; i<hdr.fhdr.f_nscns; i++) {
	    fread (&(sections[i]), sizeof(sections[i]), 1, fp);
	}
	for (actual_size=0, i=0; i<hdr.fhdr.f_nscns; i++) {
	    actual_size += sections[i].s_size;
	}
	if (actual_size <= guess_size) {
	    break;
	} else {
	    guess_size = actual_size;
	    fclose(fp);
	    free(bfr);
	    bfr = NULL;
	}
    }
    ASSERT(bfr, "Linked image is still larger than expected.");
    for (i=0; i<hdr.fhdr.f_nscns; i++) {
	fseek (fp, sections[i].s_scnptr, 0);
	fread (sections[i].s_vaddr, sections[i].s_size, 1, fp);
    }
    fclose(fp);
    return((PFI) ((char*) base));  /* "void and func ptrs not convertible" */
}


static int
guess_code_size (char *obj)
{
    /* Read the header of the object file and guess how 
    ** much memory will be needed to store the linked copy
    ** of this compiled data.
    */
    FILE *fp;
    struct headers hdr;  
    int guess;

    fp = fopen(obj, "r");
    ASSERT(fp, "Couldn't open object file");
    fread(&hdr, sizeof(struct headers), 1, fp);
    fclose(fp);
    guess = (hdr.aout.tsize + 
	     hdr.aout.dsize +
	     hdr.aout.bsize + 512);  /* FUDGE-FACTOR */
    return(guess);
}


/* end */
--------------------------------------------------

--
--
Jeff Hultquist				hultquis at nas.nasa.gov
NASA - Ames Research Center		(415) 604-4970
Disclaimer:  "I am not a rocket scientist."



More information about the Comp.sys.sgi mailing list