www.delorie.com/djgpp/doc/utils/utils_20.html   search  
DJGPP Utilities Reference

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

19.1 Building a DXE

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:

-*- 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   donations   bookstore     delorie software   privacy  
  Copyright 2004   by DJ Delorie     Updated Nov 2004