padpowell@wateng.UUCP (PAD Powell) (07/19/84)
I wish to thank all the helpful people who sent in suggestions on how to do dynamic loading; the Franz Lisp system does it, etc. Having fought my way through the horrible, undocumented, Berkeley style source, I am sending net.sources a horrible, documented, personally generated set of routines to do it. By the way, I suggest that somebody tatoo a copy of the Indian Hill style sheet to each Lisp compiler writer's hands. At least they will look at it as they type... Patrick ("Comments? Why bother? I understand it!") Powell -------------------- Set_program_name, Load_file - support dynamic loading of functions SYNOPSIS struct symbol_references{ char *name; (pointer to entry point name) int (*function)(); (call address) }; Set_program_name( str ) char *str; Load_file( objects, entries, library ) char **objects; struct symbol_references *symbols; char *library; DESCRIPTION The Dynamic Load routines support dynamic loading of func- tions into an already executing program. Set_program_name is called with the name of the currently executing binary file. The PATH environment variable is searched to deter- mine the possible executing files. If PATH was not pro- vided, a default search path is used. If a candidate binary file is not found, then a nonzero value is returned. Load_files is passed a pointer to a list of structures con- taining pointers to strings and corresponding entry point values, a pointer to a list of object of library file names, and a string containing loader options. The structure list is terminated with a structure with a zero entry, as is the object file list (see EXAMPLE below). The UNIX loader ld(1) is invoked, and will search the supplied object files for global entry points of the specified functions or variables. If the load is successful, the entry point values are placed in the structure. The library string can be used to pass additional parameters to the loader, such as a default set of libraries to be searched. EXAMPLE char *objects = { "movies.o", "library.a", 0 }; struct symbol_references look_for[] = { {_good}, {_bad}, {_ugly}, {(char *)0} }; main( argv, argc ) char **argv; int argc; { if( Set_program_name( argv[0] ) == 0 && Load_file(objects, lookfor, "-lmath -ltermlib") == 0 ){ (*look_for[0].function)(); (*look_for[1].function)(); (*look_for[2].function)(); } } Another method of using this would be do have a symbol references table in one of the object files, and to request loading of the table. It is possible to generate the table from a program, by using the C compiler, and to then load the output. If this method is chosen, note that the C com- piler should be run in a writeable directory, like /tmp. SEE ALSO ld(1), lisp(1), cc(1) DIAGNOSTICS Set_program_name and Load_file return 0 upon success, non- zero otherwise. Diagnostic messages are output on stderr using the stdio package. BUGS You must be careful in how you specify your program name. If you are doing peculiar things, you should provide the full path name as the argv[0] value. The entry point names must be specified in ld(2) recogniz- able form. For example, the C compiler will prefix an underscore to external variable names. The F77 compiler will prefix and append underscores. Thus, the variable var will be _var if in a C object file, and _var_ if in a F77 object file. The Load_file routine constructs a command using a fixed size string buffer. If you have lots of entry points, this will overflow, and you will get an error message. One solu- tion to this problem is to create an entry point table as part of an object file. Another solution is to modify the internal function that checks and finds entry points in the symbol table. The code that finds the values of entry points is very crude. It has been partially speeded up to minimize the number of reads that must be done, but will be very slow if a large number of entry points are provided. Again, this may be solved by adding an object file with an entry point table, and determining that table address.