delorie.com/djgpp/doc/utils/utils_20.html | search |
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
To build a DXE module you will use the dxe3gen
tool.
Now suppose you have some library which you want to turn into a DXE module. To do this inside the makefile for your library add a rule like this:
mylib.dxe: one.o two.o three.o four.o dxe3gen -o $ $^ |
That is, the dxe3gen -o mylib.dxe one.o two.o three.o four.o will build
the `mylib.dxe' dynamically-loadable module. All public (e.g. non-static)
symbols will be exported, and you may query the address for any of them with
the dlsym
API function.
Now suppose you use some functions from the C library, like strcpy
,
strlen
and so on. In this case dxe3gen
will list all those
symbols and will tell you that they are `unresolved', because these functions
are not present in any of the object files you have specified on the command
line. From now on you have several ways to go:
-*- You can link the DXE module with the C library by specifying
-lc on the dxe3gen
command line. This effectively will add all
the unresolved symbols to your DXE module, taking them from the C
library. Drawbacks:
printf
routine. Most file functions and memory allocation functions
are a no-no as well.
dlopen
. The worst case is when
dlopen
fires but calls such a function, which again will try to load
the module and so on. As a workaround, keep such names unexported by
filtering exported names through -E option.
-*- The best way is to leave the symbols unresolved and resolve them at
runtime. To tell dxe3gen
to not fail on unresolved symbols, add the
option -U. This will build a DXE module with unresolved
symbols.
Before loading such a module you should provide somehow the missing symbols
to the DXE loader so that it can fix up all the references to those
missing functions. If it doesn't succeed, the loader will fail.
The easiest way to provide symbol references is using dxe3res
.
There are several ways to provide symbol references to loader. The first one is to provide a explicit pointer to every function you are going to export into dynamically-loadable modules. You can do it with a couple of handy macros:
#include <sys/dxe.h> DXE_EXPORT_TABLE (exported_symbols) DXE_EXPORT (printf) DXE_EXPORT (strcpy) DXE_EXPORT (strcat) ... DXE_EXPORT_END or: #include <sys/dxe.h> extern_asm(_printf); extern_asm(_strcpy); extern_asm(_strcat); ... DXE_EXPORT_TABLE (exported_symbols) DXE_EXPORT_ASM (_printf) DXE_EXPORT_ASM (_strcpy) DXE_EXPORT_ASM (_strcat) ... DXE_EXPORT_END |
Both the above sequences are equivalent. As you can see, DXE_EXPORT_ASM
macro requires its parameter to be previously declared with "extern_asm".
Now you should pass this export table to the dynamic linker:
dlregsym (exported_symbols); |
The loader now knows these symbols so if any loaded module has
references to them, it knows how to resolve them. You may call dlregsym
as much as you want, the symbols are accumulating in a internal table
of the dynamic loader. Also you may unregister symbols with dlunregsym
function.
Another way to resolve symbols is to make all exported symbols in one module global, thus they get added to the global symbol table and when a new module with unresolved symbols is loaded, these shared libraries are searched for the corresponding exported symbol. This allows you to use symbols from one module as regular `extern's in another module. A simple example:
---------- module A void something () { ... } ---------- module B extern void something () void something_else () { something (); } |
When you link module B, you use the -U switch to suppress the warning about symbol `something' being unresolved. Now from your program you first load the module A:
dlopen ("moduleA.dxe", RTLD_GLOBAL); |
then load the module B:
dlopen ("moduleB.dxe", 0); |
The references are now resolved. Note that during first dlopen
call
the RTLD_GLOBAL
flag is specifed so that all exported symbols become
visible to other modules.
The third and most powerful way is to use the dxe3res
tool
(see section 20. dxe3res
). It combines the previous methods and requires minimal
interaction from the user, as the table is built automatically. To be more
specific, dxe3res outputs a valid C source file, which must be compiled and
linked with your application:
dxe3res -o table.c moduleA.dxe moduleB.dxe |
Also sometimes you may want to build a DXE module from a ready
library. For example, you can build DXE modules of `libjpeg.a',
`libpng.a' and `libz.a' without recompiling the libraries. For
this you should specify a special option to the linker: --whole-archive
(this is a GNU ld
option, it is just passed to ld
by
dxe3gen
):
dxe3gen -o z.dxe -Y libz_i.a --whole-archive -U libz.a \ -D "Zlib compression library" dxe3gen -o png.dxe -Y libpng_i.a --whole-archive -U libpng.a \ -D "Portable Network Graphics (PNG) Reference Library" dxe3gen -o jpeg.dxe -Y libjpeg_i.a --whole-archive -U libjpeg.a \ -D "The Independent JPEG Group's JPEG software" |
You should call all import libraries `libsomething_i.a', to avoid confusion.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
webmaster | delorie software privacy |
Copyright © 2004 | Updated Nov 2004 |