RLD(3)RLD(3)NAME
rld_load, rld_load_from_memory, rld_unload, rld_lookup,
rld_forget_symbol, rld_unload_all, rld_load_basefile, rld_address_func
- programmatically link edit and load object files
SYNOPSIS
#include <rld.h>
extern long rld_load(
NXStream *stream,
struct mach_header **header_addr,
const char * const *object_filenames,
const char *output_filename);
extern long rld_load_from_memory(
NXStream *stream,
struct mach_header **header_addr,
const char *object_name,
char *object_addr,
long *object_size,
const char *output_filename);
extern long rld_unload(
NXStream *stream);
extern long rld_lookup(
NXStream *stream,
const char *symbol_name,
unsigned long *value);
extern long rld_forget_symbol(
NXStream *stream,
const char *symbol_name);
extern long rld_unload_all(
NXStream *stream,
long deallocate_sets);
extern long rld_load_basefile(
NXStream *stream,
const char *base_filename);
extern void rld_address_func(
unsigned long (*func)(unsigned long size, unsigned long headers_size));
DESCRIPTION
rld_load link edits and loads the files specified by the NULL-
terminated array object_filenames into the program that called it.
Alternatively, it can be used to load into another program. An object
name can be an archive, in which case only those members defining
undefined symbols will be loaded.
If the program is to allow the loaded object files to use symbols from
itself, it must be built with the -seglinkedit option of the link
editor, ld(1), in order to have its symbol table mapped into memory.
The symbol table may be trimmed to limit which symbols are allowed to
be referenced by loaded objects. This can be accomplished with the -s
filename option to strip(1). For the routines described here, only
global symbols are used, so local symbols can be removed with the -x
option to ld(1) or strip(1). Doing so saves space in the final program
and vastly decreases the time spent by the first call to rld_load.
(This is true of the first call in the program, as well as the first
call after an invocation of rld_unload_all). The first call to
rld_load must go through all the symbols of the program, so if the
program has been compiled for debugging (for example), it can take
orders of magnitude longer.
Since the objects loaded with rld_load can only use symbols that appear
in the executable program, if the program uses a library and wants to
make all the symbols in that library available to the loaded objects,
it must force all of the library symbols into the executable. This can
be done for all libraries with the -all_load option to ld(1) when
building the executable. For libraries that aren't shared, however,
this will copy all the library code into the executable. Thus this
approach may be desirable only for the shared libraries, where the
library code isn't copied into the executable. This can be done easily
for shared libraries by having the executable program reference the
shared library reference symbol for each of the shared libraries it
uses. The shared library reference symbol is named after the base name
of the target library (its name up to the first '.'). For example, the
target shared library /usr/shlib/libsys_s.B.shlib has the shared
library reference symbol libsys_s. This name intentionally doesn't
start with an underscore, '_', in order to be out of the normal name
space for C external symbols. So to reference the symbol in this
example, ld(1) would be invoked with the flag -u libsys_s when linking
the program, and this flag would come before the library on the link
edit command line. If new routines and data are added to the target
shared library, they will be unavailable to objects loaded with
rld_load until the program is relinked against the host shared library
that matches the target shared library. This approach is necessary to
avoid link editing and loading errors that would otherwise be very hard
to detect.
The set of object files being loaded will only be successful if there
are no link edit errors (undefined symbols, etc.). If an error occurs,
the set of object files is unloaded automatically. If errors occur,
and the value specified for stream isn't NULL, error messages are
printed on that stream. If the link editing and loading is successful,
the address of the header of what was loaded is returned through the
pointer header_addr (if it isn't NULL). If rld_load is successful and
the parameter output_filename isn't NULL, an object file is written to
that filename. This file can be used with the gdb(1) add-file command
to debug the code in the dynamically loaded set of objects. When the
program being debugged is using rld to load into itself, the debugger
knows how to get the symbols automatically in most cases, and the
output_filename parameter isn't needed. However, if some other program
is using rld to load into the program being debugged, or if the
specified objects don't contain full paths, the debugger can't do this
automatically. The rld_load function returns 1 for success and 0 for
failure. If a fatal system error (out of memory, etc.) occurs, all
future calls to rld_load and the other routines described here will
fail.
rld_load_from_memory() is similar to rld_load(), but works on memory
rather than a file. The argument object_name is the name associated
with the memory and is used for messages. (It must not be NULL.) The
arguments object_addr and object_size are the memory address and size
of the object file. rld_load_from_memory() only allows one thin object
file (not an archive or ``fat'' file) to be loaded.
rld_unload() unlinks and unloads the last set of objects that were
loaded. It returns 1 if it is successful and 0 otherwise. If any
errors occur and stream isn't zero, the error messages are printed on
that stream. It's the caller's responsibility not to have any pointers
into the data areas of the object set, as well as to deallocate any
memory which that set of objects may have allocated.
rld_lookup() looks up the specified symbol name and returns its value
indirectly through the pointer value. It returns 1 if it finds the
symbol, and 0 otherwise. If any errors occur and stream isn't zero,
the error messages are printed on that stream. (For this routine,
only internal errors can result.)
rld_forget_symbol() causes this package to forget the existence of the
specified symbol name. This allows a new object to be loaded that
defines this symbol. All objects loaded before this call will continue
to use the value of the symbol in effect at the time the object was
loaded. It returns 1 if it finds the symbol and 0 otherwise. If any
errors occur and stream isn't zero, the error messages are printed on
that stream. (For this routine, only internal errors can result.)
rld_unload_all() clears out all allocated data structures used by these
routines. If the parameter deallocate_sets is non-zero, the function
also unloads all object sets that were loaded. If deallocate_sets is
zero the object sets aren't unloaded, and the program can continue to
use the code and data loaded. However, further calls to the routines
described here will no longer know about the symbols in those sets. If
object sets aren't to be allowed access to each other's symbols, an
rld_unload_all call between calls to rld_load allows the objects sets
to be loaded without fear of global symbol names' clashing.
rld_unload_all returns 1 if it is successful and 0 otherwise. If any
errors occur and stream isn't zero, the error messages are printed on
that stream.
The second argument to rld_load_basefile specifies a base file, whose
symbol table is taken as the basis for subsequent rld_load's. The base
file may be a ``fat'' file, and must contain an architecture that would
execute on the host; otherwise, it is an error. If the file is a fat
file, the ``best'' architecture (as defined by what the kernel exec(2)
would select) is used as the base file. rld_load_basefile must be
invoked before any call to rld_load. Alternatively, it can be called
after rld_unload_all, which unloads the base file. This call is
intended to be used when a program is dynamically loading object sets
into a program other than itself, where base_filename contains the
symbol table of the target program. The routine rld_address_func,
described next, would also be used.
rld_address_func is passed a pointer to a function, func, that will be
called from rld_load. The parameter values that rld_load will supply
to func are the size of the memory required for the object set being
loaded, and the size of the headers (which are also included in the
calculation of size). The function specified by func should return the
address where the output is to be link edited. rld_address_func is
intended to be used when a program is dynamically loading object sets
into a program other than itself; the function allows it to pick the
place in the address space of the target program.
FAT FILE SUPPORT
All functions that accept object files or archives also accept ``fat''
files, except for the restrictions noted above for rld_load_from_memory
and rld_load_basefile.
CPU SUBTYPE HANDLING
For compatibility (and due to existing bugs in the the CPU subtype
handling), the rld(3) package will function as if the ld(1)-force_cpusubtype_ALL option were specified. As of the NEXTSTEP 3.0
release, the rld(3) package doesn't do the same checking as exec(2)
does with regard to the handling of the CPU subtype. In the case of
the m68k architecture, if an object file with the 68040 CPU subtype is
used with the rld(3) package on a 68030 machine, no error is generated.
This ``bug'' has the same effect as the ld(1)-force_cpusubtype_ALL
option, but it lacks the error detection supported by exec(2). Since
adding the error detection could break existing uses of rld(3), the
rld(3) package functions as though the -force_cpusubtype_ALL option to
ld(1) were specified.
SEE ALSOld(1), strip(1), gdb(1)BUGS
There exists one semantic link edit problem with respect to common
symbols. If a set of object files are loaded that have common symbols
left after the symbols have been merged, rld_load has to allocate
storage for these symbols for the code to run without error. The
problem occurs if, on a later call to rld_load, one of the common
symbols that rld_load allocated appears in an object file as a defining
symbol (not a common or undefined symbol). In this case, rld_load will
report the symbol as being multiply defined. However, if this
combination of object files were statically linked, no error would
occur.
NeXT, Inc. July 30, 1993 RLD(3)