[comp.unix.wizards] Loading and Executing Object Code at Runtime

flan@cics.Berkeley.EDU (Ian Flanigan) (02/14/91)

Hi,

I tried posting this to comp.unix.questions first, but as I got no answer
I figured this must be a Wizard level question:

I'm wondering how to load an object file (my_functions.o) at execution
time and execute a function contained therein.  I know this is possible
since many flavors of LISP allow you to compile your functions and then
load the compiled versions later.

If it's in TFM, could someone point me in the right direction, or, if it's
trivially simple, could someone please explain how to go about it?

Thanks much.

-- 
Ian Flanigan

flan@cics.wustl.edu              "You can never have too many napkins."
wucs1.wustl.edu!cics!flan@uucp

mike (02/14/91)

In an article, flan@cics.Berkeley.EDU (Ian Flanigan) writes:
>Hi,
>
>I tried posting this to comp.unix.questions first, but as I got no answer
>I figured this must be a Wizard level question:
>
>I'm wondering how to load an object file (my_functions.o) at execution
>time and execute a function contained therein.  I know this is possible
>since many flavors of LISP allow you to compile your functions and then
>load the compiled versions later.

When you are talking about compiling functions and loading the compiled
versions later, are you talking about using a linkage editor to build
a runable image?

If you're trying to do what it looks like you're trying to do, the answer
is "you can't get there from here."  You would have open the object file,
load the function within the context of the current process (a real trick),
allocate the core for data, stack, and bbs, push the stack frame, and
jump to the address of this arbitrary function.  Just ain't no way you
can be doin' this in user mode.

-- 
Michael Stefanik                       | Opinions stated are not even my own.
Systems Engineer, Briareus Corporation | UUCP: ...!uunet!bria!mike
-------------------------------------------------------------------------------
technoignorami (tek'no-ig'no-ram`i) a group of individuals that are constantly
found to be saying things like "Well, it works on my DOS machine ..."

bzs@world.std.com (Barry Shein) (02/14/91)

>I'm wondering how to load an object file (my_functions.o) at execution
>time and execute a function contained therein.  I know this is possible
>since many flavors of LISP allow you to compile your functions and then
>load the compiled versions later.
>
>If it's in TFM, could someone point me in the right direction, or, if it's
>trivially simple, could someone please explain how to go about it?

It's not trivially simple by any means and can be quite subtle to get
right (e.g. loading multiple functions which reference each other and
external functions.)

It also is heavily dependent on the particular version of Unix, this
is not portable, although one solution might work on several different
unixes. BSD-based systems will use "ld -A" for starters. Encore had a
routine to do this which made it relatively easy (dynaload(), which I
think originated at AT&T but was never made part of the regular
distribution? Or do I say this every two years when it comes up and
someone corrects me that it's original to Encore? Anyhow.)

In theory you should be able to do this on any Unix system, barring
hideous ideosyncractic restrictions, it's mostly a matter of how much
of a link-editor you might have to implement yourself. For starters,
if you had a trivial routine that had no external references you can
usually just read it into a malloc'd array of bytes from the .o and
jump to it.  It's the external references that make this harder than
that, you have to resolve the externals against any which are already
in the running image (e.g. printf) and load in any externals from the
libraries (e.g. libc.a) which aren't.

Your best bet is to find a piece of code which does this and read it.
KCL does this and is available in source from various FTP sources.
-- 
        -Barry Shein

Software Tool & Die    | bzs@world.std.com          | uunet!world!bzs
Purveyors to the Trade | Voice: 617-739-0202        | Login: 617-739-WRLD

shore@mtxinu.COM (Melinda Shore) (02/15/91)

In article <BZS.91Feb14044321@world.std.com> bzs@world.std.com (Barry Shein) writes:
>In theory you should be able to do this on any Unix system, barring
>hideous ideosyncractic restrictions

A quite widespread hideous idiosyncratic restriction is that on
some architectures, notably the 386, you can't execute out of data
space.  It's sometimes possible to work around it by playing games
with remapping memory, but only if you have kernel support (as with,
say, Mach).
-- 
               Software longa, hardware brevis
Melinda Shore                                 shore@mtxinu.com
mt Xinu                              ..!uunet!mtxinu.com!shore

tchrist@convex.COM (Tom Christiansen) (02/16/91)

From the keyboard of uunet!bria!mike:
:If you're trying to do what it looks like you're trying to do, the answer
:is "you can't get there from here."  You would have open the object file,
:load the function within the context of the current process (a real trick),
:allocate the core for data, stack, and bbs, push the stack frame, and
:jump to the address of this arbitrary function.  Just ain't no way you
:can be doin' this in user mode.

Never say never.  It certainly is on some architectures.  Just malloc or
mmap in some pages as RWX, then load the position-independently compiled
functions in there from disk, and call through a function pointer.  There
are also overlay schemes available -- that's what I used to do on Z80
machines.  You could also use overlays on PDP-11's.

--tom
--
Tom Christiansen		tchrist@convex.com	convex!tchrist
 "All things are possible, but not all expedient."  (in life, UNIX, and perl)

guy@auspex.auspex.com (Guy Harris) (02/16/91)

>A quite widespread hideous idiosyncratic restriction is that on
>some architectures, notably the 386, you can't execute out of data
>space.

What's "data space", and how is it different from any other sort of
space?  (Most UNIX systems run with a flat address space on 386es.  PTEs
on the 386 only have a "writable" bit.)

um@bologics.UUCP (Ugo Manfredi) (02/21/91)

In article <1991Feb13.212704.7016@cec1.wustl.edu>, flan@cics.Berkeley.EDU (Ian Flanigan) writes:
> I'm wondering how to load an object file (my_functions.o) at execution
> time and execute a function contained therein.  I know this is possible
> since many flavors of LISP allow you to compile your functions and then
> load the compiled versions later.

Ok, what follows are guidelines that show how to realize what you need on SunOS.
I have used such a schema to allow the Prolog system we (at DS Logics) are 
currently developing to call external functions written in C, Fortran, ecc.
This schema works well on SunOS and other BSD-based operating system, while
other schemas are needed, for example, on IBM R6000 AIXV3 operating system. 
I don't know SCO-Unix, so I cannot tell you anything on this regard.

1) Compute current program break point <addr> via the sbrk() routine. 
   Eventually round at a page boundary.

2) Use the link editor ("ld" command) 
   "ld -N -x -A <old_exec> -T <addr> -o <temp_file> <file_list> <lib_list> -lc"
   where the flags means: 
   "-N"  place data section immediately after text (see a.out)  
   "-A <old_exec>"  specifies incremental loading 
   "-T <addr>"  sets the text segment origin at <addr>
   "-x"  do not preserve local symbol
   "<file_list>" is the list of one or more .o containing your functions
   "<lib_list"   additional libraries needed to resolve externals (if any)

3) Inspect the header of <temp_file> to get the size of the executable (text +
   data portions).

4) Allocate new memory via malloc() or valloc() routines to make room for the
   new code.

5) Read the executable in the allocated memory.

6) Finally to call the new functions you must obtain their addresses:
   the address corresponding to a given name can be obtained by reading the
   symbol table of <temp_file> or, in a simpler way, by using the nlist() 
   function.
   
This is the basic schema. Good luck.
If you have problems you can contact me via e-mail at:

um@bologics.uucp	(Ugo Manfredi @ DS Logics) 

mib@geech.ai.mit.edu (Michael I Bushnell) (03/01/91)

Someone asked:

   >I'm wondering how to load an object file (my_functions.o) at execution
   >time and execute a function contained therein.  I know this is possible
   >since many flavors of LISP allow you to compile your functions and then
   >load the compiled versions later.
   >
   >If it's in TFM, could someone point me in the right direction, or, if it's
   >trivially simple, could someone please explain how to go about it?

It should be noted that dld, the dynamic loader, available from the
Free Software Foundation, does this task nicely.  You can get it as
/pub/gnu/dld-3.2.1.tar.Z on prep.ai.mit.edu.

	-mib