Newsgroups: comp.sys.sgi Path: utzoo!utgpu!news-server.csri.toronto.edu!rpi!zaphod.mps.ohio-state.edu!think.com!snorkelwacker.mit.edu!stanford.edu!agate!usenet.ins.cwru.edu!eagle!data.nas.nasa.gov!sun499.nas.nasa.gov!hultquis From: hultquis@nas.nasa.gov (Jeff P. M. Hultquist) Subject: Re: More Dynamic Loading and Stuff. References: <9105141842.AA06077@crow.omni.co> Date: 14 May 91 15:45:39 Reply-To: hultquis@nas.nasa.gov Organization: NAS - Applied Research Office, NASA Ames Sender: news@nas.nasa.gov In-Reply-To: rpaul@crow.UUCP's message of 14 May 91 18:42:57 GMT Message-ID: Lines: 240 >>> rpaul@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 # # 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 #include #include #include 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