The Dynamic Loader

This utility allows you to load an object file from disk and link it to a running executable. This facility consists of the following parts:

·        The dynloader.dll file, which should be in your PATH variable

·        The bind utility

The dynloader.dll exports three functions that are of interest here:

1.      LoadObjectFile

2.      GetProcedureAddress

3.      UnloadObjectFile

The interface is very similar to that of LoadLibrary, since the functionality is quite similar.

The dynamic loader operates by opening the given object, allocating space in RAM for the data and the code stored in there, copying the contents of the data and code sections, then fixing up everything.

To resolve external references, the loader relies first on the symbol table of the running executable. If that symbol table exists, it will be used to resolve external references from the object file.

If the symbol table is absent in the running executable, or a symbol is found that does not match any executable symbols, the dynamic loader will rely on the imports table generated by the bind utility. This table contains the DLLs used by the object file, and all the imported functions that are needed.

The bind utility will construct this table from the “apilist.txt” file, which is present in the lcc-win32 distribution in the “lib” directory. This file contains a list of all known DLLs and their exported functions. Using this list, the bind utility appends a list of needed DLLs to the object file, that will be used by the dynloader.dll library.

Note that if you wish to add a DLL of your own to the list, you can do so by modifying apilist.txt.

Binding an object file

Before loading an object file it must be "bound" using the "bind.exe" utility. The syntax of the "bind" command is very simple:

            bind <object file>

This will build a list of the DLLs needed by the object file so that it can be quickly loaded later.

Loading an Object File

An object file is loaded using the LoadObjectFile function. The result can be either NULL, meaning the object file could not be found, or a pointer to an OBJECT_FILE structure, containing information about the loaded object. Please note that the members of the structure will probably change in future releases, so it is not a very good idea to use them in your code. You can still look at them and they are provided for debugging purposes.

Getting a Function Pointer

This is accomplished with the GetProcedureAddress function. The pointer returned (that can be NULL if the name is not found) should be cast to match the function prototype. Note that the name of the procedure to be found should match the name as exported from the object file, i.e., you should add the leading underscore and the _stdcall decoration if any. For instance for the function

void hello(void)

you should pass _hello to the loader. For a _stdcall function, you should add ‘@’ and the size of the function stack.

Unloading the Object File

This is accomplished using the UnloadObjectFile function. All memory used by the object file and its descriptors is reclaimed. You should ensure that no further uses of the object file occur.

 

A Complete Example

#include <dynloader.h>

int main(void)

{

        OBJECT_FILE *obj = LoadObjectFile("hello.obj");

        void (*fn)(void);

 

        fn = GetProcedureAddress(obj,"_hello");

        (*fn)();

        UnloadObjectFile(obj);

        return 0;

}