Note: The Object Loader package does not support all processor
architectures at present.
The Object Loader package provides support for dynamically loading
executable modules into an eCos system. Modules may be loaded into
memory from a variety of sources, linked in to the running system and
entry points invoked to execute the code of the module. When the
module is no longer required, it may be unloaded and the memory reused
for other purposes or other modules.
This system is modelled most closely on the Linux kernel module
mechanism, rather than Windows DLLs or Unix shared objects. As a
result, it has a number of restrictions:
Only modules written in C are supported. The Object Loader does not
currently provide support for invoking static constructors and
destructors, C++ exceptions, RTTI and other parts of the C++
runtime system.
Automatic symbol resolution only works for references from a module
into the main executable. References between modules are not
supported, and resolution of unresolved symbols in the main executable
to module symbols is not supported.
Loaded modules need to be built using the same, or similar,
configuration to the main system.
Loaded modules should be built with the same or compatible compiler
flags as the main system. There is one important exception. Some
architectures including MIPS and Nios II implement a global pointer
register. Small global variables are placed in an area of memory up to
64K. The gp register points at this area of memory, allowing the
variables to be accessed directly using a single instruction instead
of the two or more instructions that would otherwise be required. This
technique cannot be used for a dynamically loaded module. Hence the
use of gp-relative addressing must be suppressed with a compiler flag,
typically -G0.
Creating Loadable Modules
Modules can be just object files as generated by the compiler. In a
Makefile including
the $(INSTALL_DIR)/include/pkgconf/ecos.mak
definitions file, the entry to build module.o
might be:
The compile line generates a .o file. The
-I option allows includes to be fetched from
the eCos installation. The command prefix and global flags are stored
in the ecos.mak file by the eCos build
process. If the compile flags include -g or some
other debug option then to save memory and maybe load time it is
useful to pass the finished module through strip to
limit the file contents to just the loadable ELF sections.
It is possible to create a module out of several object files by using
the linker's ability to perform a partial link:
The module.ld linker script is defined by the
Object Loader package and is copied out to the install lib
directory. It should be used when combining multiple files, or when
advanced features such as HAL tables are used in a single object file.
If the module makes use of float, double,
long long and some long arithmetic
operations, then it should be partially linked against
libgcc before loading. This can be done with the
following makefile fragments:
The function cyg_ldr_open() is used to
load a module into memory. It takes two arguments. The first argument
defines a module loader, while the second argument is a
generic data item whose value depends on the
loader. If the load is successful, then a non-NULL handle will be
returned. A NULL pointer will be returned on failure.
If there is an error in the loading process, then the
function cyg_ldr_error() will return a string
describing the last error that occurred. Note that this is not
thread-safe since there is only a single last error recorded for all
load operations.
At present the following loaders are implemented:
CYG_LDR_FILESYSTEM
This loader uses FILEIO operations to read an ELF file from a named
file in a filesystem. For example, to read a module from the file
"/lib/modules/module.o":
This loader is included by default if
the CYGPKG_IO_FILEIO package is included, although
it can be omitted by
disabling CYGPKG_OBJLOADER_LOADER_FS.
CYG_LDR_MEMORY
This loader uses memory access primitives to read an ELF file from any
addressable memory such as ROM, FLASH or RAM.
For example to read a module from the location module_base:
This loader is included by default, although
it can be omitted by
disabling CYGPKG_OBJLOADER_LOADER_MEM.
Loaders CYG_LDR_FTP, CYG_LDR_TFTP, CYG_LDR_HTTP
and CYG_LDR_FLASH are defined, but not currently
implemented.
Unloading Modules
A module may be unloaded by
calling cyg_ldr_close(), passing it the handle
returned from cyg_ldr_open(). This will cause the
memory occupied by the loader to be released. Any pointers into the
code or data of the module will be rendered invalid and should not be
used.
Referencing Module Symbols
When a module is loaded, a symbol table listing all the external
symbols that it defines is loaded with it. The
function cyg_ldr_find_symbol() searches this
table and returns a pointer to the location defined by a symbol.
For example, to create a thread running from a function in a module:
Both functions and variables may be accessed in this way.
There is no mechanism for resolving dangling references in the main
eCos application, or other modules, to symbols in a newly loaded
module. The main eCos application must have all references resolved at
link time. However, it is possible to simulate the effect of dynamic
resolution by using function pointers. For example define a global
function pointer to an initial dummy function:
typedef int module_fn_t(int a, int b);
module_fn_t dummy_fn;
module_fn_t *module_fn = dummy_fn;
int dummy_fn( int a, int b )
{
return -1;
}
When the module is loaded the function pointer can be pointed at the
function within the module, and pointed back to the dummy function
when it is unloaded:
One could even implement a form of demand loading by
combining dummy_fn and load_module:
int dummy_fn( int a, int b )
{
mod_handle = cyg_ldr_open( CYG_LDR_FILESYSTEM, (CYG_ADDRWORD)"/lib/modules/module.o");
module_fn = cyg_ldr_find_symbol( mod_handle, "module_fn");
return module_fn( a, b );
}
Module Open and Close Functions
When a module is loaded the Object Loader will look for a symbol with
the name "module_open" and if found will call it with the following
prototype:
void module_open( void );
Similarly, when cyg_ldr_close() is called, the
Object Loader will look for a symbol named "module_close" and call it,
with the same prototype.
External References
When a module is loaded, the Object Loader package performs any
relocations it requires and resolves any unresolved symbol references
it contains. The load only succeeds if all of these can be
completed. For these symbols to be resolved it is necessary for the
main eCos executable to contain a symbol table defining the symbols to
be resolved. Normal eCos executables do not contain such a symbol
table since it would occupy an unreasonably large amount of
memory. There is also no mechanism to persuade the linker to include a
loadable symbol table into the executable. Hence it is necessary for
the application to explicitly define a symbol table that maps symbol
names to addresses.
The loader provides an empty table; the user can then define additional
entries required by any loadable modules. In order to keep the size of
the table to a minimum, the user can selectively include only those
functions that are expected to be used by the loader to resolve all
references. There are several macros defined
in objload.h for defining table entries:
CYG_LDR_TABLE_FUN( name )
This macro defines a table entry for a function with the
given name.
CYG_LDR_TABLE_VAR( name )
This macro defines a table entry for a data variable with the
given name.
This is a low level macro that allow all aspects of a symbol table
entry to be controlled. The entry_name argument
defines the table entry object name (a C language requirement since
anonymous objects are not permitted).
The symbol_name argument is a string giving the
symbol that will be matched by the loader.
The address argument gives the memory location
to which this symbol will resolve.
The objload.h file contains a number of macros
that collect together groups of functions as a convenient way to
include blocks of Kernel, C Library and FILEIO functionality. These
include the following: