Enhanced
Dynamic Linking Library
for MinGW under MS-Windows
Reference Manual (Version 0.6)
Introduction
The edll is a C library with
only a few functions you can use to load
modules dynamically under MS-Windows. It requires you to have the BFD
library for the final linking.
Summary
License
Requirements
Versioning your application and modules
#define's
EDLL_ADDLIB
EDLL_VERSION
Typedef's
edll_check_version
edll_errno_t
edll_module
edll_mutex_geterror
edll_mutex_lock
edll_mutex_seterror
edll_mutex_unlock
edll_ptr
Functions
edll_alloc
edll_callback_register
edll_close
edll_exit
edll_free
edll_geterror
edll_getsearchpath
edll_getversion
edll_init
edll_module_version
edll_msym
edll_mutex_register
edll_open
edll_realloc
edll_seterror
edll_setsearchpath
edll_setunixsearchpath
edll_set_self_version
edll_strerror
edll_sym
Undefined Symbols and Unresolved Symbols
Known Bugs & Limitations
License
This document is covered by the GNU
documentation license.
Copyright (c) 2005-2006 Alexis Wilke.
Permission is granted to copy, distribute and/or modify this document
under the terms of the GNU Free Documentation License, Version 1.1
or any later version published by the Free Software Foundation;
with the Invariant Sections being "Introduction" and "License",
with no Front-Cover Texts, and with no Back-Cover Texts.
A copy of the license is included in the section entitled "GNU
Free Documentation License".
The edll library is covered by
the LGPL plus the following paragraph:
I hereby authorize anyone to use this library in closed source
software. However, if you make any modification to the library,
you must make these changes available to everyone (preferably
sent to me, but this is not a requirement.)
Different files included in this package are covered by
different licenses as explained in the Project
Licenses page.
Requirements
The following is what you need to use the edll project.
I added some version information. Older versions may still work with
edll.
- MinGW 5.0.0 and MSYS 1.1
- The gcc compiler (v3.4.2)
- To try the C++ tests, the g++ compiler (v3.4.2)
- The libbfd.a library (binutils 2.15.91)
- 32bits MS-Windows (but that's secondary)
- And finally: a lot of time, patience and courage! (until version
1.0, you know...)
Since version 0.3, edll uses
a GNU Compatible configure script. For this reason, you will need the
MSYS environment in order to create the library.
A quick How To Install MinGW and edll
- Install MSYS somewhere (i.e. "D:\Development\1.1")
- Install MinGW 5.0.0 in the directory named mingw inside
your newly installed MSYS and not where the installer suggests by
default. (i.e. "D:\Development\1.1\mingw") Make sure the installer does
not add a version at the end of your path (just erase if it does.)
- Create your HOME directory (i.e. "D:\Development\1.1\home\alexis")
- Setup the HOME variable to that new home directory in msys.bat
(search for "start rxvt ..." and just before add: "set
HOME=D:\Development\1.1\home\alexis")
- Upload edll-0.6.tar.gz in your home directory
- Start MSYS and type:
gunzip edll-0.6.tar.gz
(if it does not work, your installation did not quite work...)
NOTE: you cannot use tar xzf ... because pipes do not work under
MS-Windows.
tar xvf edll-0.6.tar
cd edll-0.6
- if you want to support the version feature, apply the
dev/version.patch
now
./configure [--<options>]
make
make install
There is an ltdl.c/h set of files from some old binutils
(binutils-2.13.90-20030111-1.tar.gz). It still compiles
and works fine. If you have an application written in Unix which uses
the
ltdl to load modules, then you should not have to change anything to
use edll. It is otherwise not
required to use ltdl.
See the README file for more information about the options available to
the edll configure script.
If you have any problems with some older versions of some of these
tools, update them first. Note that newer versions may also break
the library. It is very sensitive to the BFD library...
WARNING: in order for the
version feature to be available you have to make sure you configured
the library with the --enable-versioncheck option; if not you will need
to recompile it (you do not need to reconfigure, you can just edit the
configuration file and change the #undef VERSION_CHECK by #define
VERSION_CHECK 1)
The edll library can now read
the .version section of you
executable and modules. For this feature to work, you need to have a .version section. However, by
default, your linker will remove the .version
section since it does not know anything about and it will assume that
once linked, the program does not need it.
I offer two solutions to this problem.
- The simplest one is to make a call to the edll_set_self_version() function.
This function saves a version string for later use by the edll library to check the modules.
- The slightly more complicated solution is to modify the linker
scripts. The GNU linker from the binutils uses a script to describe how
the linker is supposed to handle the different sections. There are
different scripts and it could be that you need to include that in
different scripts. At this time, I tried and it worked by only changing
the
i386pe.x
script. I include a patch in the edll
package (dev/version.patch
) that you can apply to that
file. Though you can easilly fix any problems by reinstalling the
binutils if something goes wrong, I suggest you make a copy of the file
before you apply the patch.
The second solution is of course the neatest since you will have
nothing more than to use EDLL_VERSION() in your source file to print
the version in your application.
The other problem with the versioning is that by default the library
will compare versions with strcmp(). They need to be strictly equal for
the module to be acceptable and thus loaded. If that fails, you will
not be able to load that plugin. You can, however, create your own
function to compare two versions. The function will be called each time
a module is loaded. You define that function with a call to the edll_callback_register() function.
LIBRARY
edll
NAME
EDLL_ADDLIB — add a library reference
in a plug-in
EDLL_VERSION — define the version of a module
SYNOPSIS
#define EDLL_ADDLIB(name) ...
#define EDLL_VERSION(version) ...
PARAMETERS
name — the name of the library to load
so the plug-in symbols can be resolved
version — a string representing the library version (i.e. "1.0")
DESCRIPTION
The
EDLL_ADDLIB()
macro was created to enable the users to create a .load section with
the names of the libraries and other plug-ins to load before this
plug-in symbols can all be resolved. It is strongly recommended that
only
the libraries and other plug-ins which are required be included in this
section. The
edll always loads
all of the dependencies defined in a
.load section and it can use a lot of memory to specify too many
entries here.
The
EDLL_VERSION() macro is a
helper to define the version of a module. At this time, the macro
creates a string that it saves in a section named
.version. When
an application or a module attempts to load a module and the versions
do not match, then an error is generated and the loading fails.
With
edll_callback_register, the
user can specify the comparison function if a strictly equal algorightm
would be to stringent.
NOTES
The EDLL_ADDLIB()
will ultimatly be replaced by the use of the -l option on the linker
command line as it would be expected. Also, at that time, the linker
could test whether a library is used to resolve any symbol. If not, it
could then be removed from the list of dependencies.
RETURN VALUE
These macros declare data. There is no
returned value.
BUGS
The
EDLL_VERSION()
macro works, but by default the linker will remove the
.version section when linking an
executable. Thus your application can find itself without a
version and in that case no comparison will take place. You have two
ways to fix that problem: (a) you apply the dev/version.patch to your
ldscripts/i386pe.x file. This will
prevent the loader from losing the
.version
section and (b) you can use the
edll_set_self_version()
function to define the version of the application.
SEE ALSO
LIBRARY
edll
NAME
edll_module — the edll module handle
SYNOPSIS
typedef struct edll_module_struct
edll_module;
DESCRIPTION
The
edll_module
type defines an
edll module.
The structure itself is
private. You will only be able to use pointers to
edll modules.
You get a new pointer whenever you call the
edll_open() function. You
get rid of the pointer whenever you call the
edll_close() or
edll_exit()
functions.
SEE ALSO
edll
NAME
edll_ptr — edll non-specific pointers
SYNOPSIS
typedef void
*edll_ptr;
DESCRIPTION
The edll_ptr
type defines a non-specific data pointer.
This type is used to return symbol address pointers. Also the different
memory functions use it.
SEE ALSO
edll
NAME
edll_check_version — function used to
compare two versions for validity
SYNOPSIS
typedef int
(*edll_check_version)(const char *self_version, const char
*module_version);
DESCRIPTION
The edll_check_version
type is used whenever a version is defined in a module being loaded.
When
this function is not defined, the system uses
strcmp() and both versions
need to be exactly equal. If you need a better test so as to allow
older
or newer versions too, then you will need to write your own.
The function is called with two strings. The self version which
represents the version of the application. And the module
version
which is the one version you want to validate.
The function needs to return zero (0) if the versions do not match
(i.e.
you want to refuse this module) and return any other values to say that
the version is valid (the loading of the module will proceed.)
SEE ALSO
edll
NAME
edll_errno_t — edll error type
SYNOPSIS
typedef enum edll_errno_num { ...
} edll_errno_t;
DESCRIPTION
The edll_errno_t
type is used by the edll
library to define error numbers.
Whenever a function returns a value which represents an error (-1 when
int is returned and NULL when a pointer is returned), an error is set
in the edll library. The type
of this error is always edll_errno_t.
The errors are handled by the edll_geterror(),
edll_seterror() and edll_strerror() functions.
SEE ALSO
edll
NAME
edll_mutex_geterror — a function used
to rerieve the last error set in the current thread
edll_mutex_lock — a function used to
prevent multiple threads from using the library at the same time
edll_mutex_seterror — function used to change the error code in the
current thread
edll_mutex_unlock — the function to undo a lock
SYNOPSIS
typedef void
(*edll_mutex_lock)(edll_ptr userdata);
typedef void (*edll_mutex_seterror)(edll_ptr userdata, edll_errno_t
err);
typedef void (*edll_mutex_unlock)(edll_ptr userdata);
PARAMETERS
userdata — a pointer to some data you
specify to the registration function
err — the error number representing what just happened
DESCRIPTION
The
edll_mutex_lock
type defines a function used to protect areas of code in the library so
multiple threads can use it safely. All the common data managed calling
these functions. The way
the lock itself is done it not specified in the
edll library.
The
edll_mutex_unlock type
defines the function which undoes the lock created with the
edll_mutex_lock.
The
edll_mutex_seterror type
defines a function used to save an error code specific to a thread.
Note that you do not have to save the error code, you may use it right
away. In that case you do not have to define an
edll_mutex_geterror since it would
not be in sync anyway. The function receives the error code as its
second parameter.
The
edll_mutex_geterror type
defines a function used to retrieve an error previously saved calling
the
edll_mutex_seterror
function. Note that the library doesn't test whether you set one or
both of the error functions. It is suggested that you set either only
the set or both. Defining only the get would not make sense.
Note that all of these functions can't fail. The userdata is the same
as the
one passed to the registration function
edll_mutex_register().
EXAMPLE
If you are using the pthread library,
then the lock and unlock can be as simple as follow:
my_mutex_lock(edll_ptr mutex)
{
pthread_mutex_lock((pthread_mutex_t *) mutex);
}
my_mutex_unlock(edll_ptr mutex)
{
pthread_mutex_unlock((pthread_mutex_t *) mutex);
}
Note that this code assumes you register the lock & unlock
functions using
the pthread mutex variable as the userdata pointer.
RETURN VALUE
Note that none of these functions can
fail.
Only the edll_mutex_geterror
function returns a value which has to be the last error set with edll_mutex_seterror.
SEE ALSO
edll
NAME
edll_getversion — retrieve the library
version
edll_init — the library initialization
function
edll_exit — the library clean up function
SYNOPSIS
extern const char
*edll_getversion(void);
extern int edll_init(void);
extern int edll_exit(void);
DESCRIPTION
If you want to make sure that the
proper version of the edll library is available at runtime, then call edll_getversion() and test the
returned string version. The latest version string is "0.6". (See
the Internet version of this documentation for a valid version string
here.)
Before to use the edll
library, you must call the edll_init()
function. Some functions
will fail if the library wasn't first initialized.
Once you are finished with the edll
library, call the edll_exit()
to release all the resources used by the library. This function has the
side effect of closing all the plug-ins. This means you need to make
sure you won't use any of the plug-ins after this call and also that
the function isn't being called from a plug-in.
For your information, the initialization call will initialize the BFD
library as well. Note that there are no function to clean up the BFD
library. I do not know whether there is a need to clean up anything
though.
You can call the edll_init()
multiple times. For each time you called the initialization function,
you need to call the edll_exit()
function. The last call to edll_exit()
will release the plugins. The other calls merely decrement a reference
counter.
RETURN VALUE
edll_init returns 0 when the
initialization succeeds
edll_exit returns 0 when it can properly close the library, -1
otherwise; the function returns 0 even if the plugins are not removed
(i.e. the reference counter didn't reach 0 yet)
edll_getversion returns a read-only string with the current version of
the library
BUGS
You have to make sure that you do not
use DLLs and plug-ins which have been loaded with the edll library after you called the edll_exit() function.
SEE ALSO
edll
NAME
edll_alloc — allocate a block of memory
edll_realloc — reallocate a block of memory (usually to resize it)
edll_free — free a block of memory allocated with edll_alloc or
edll_realloc
SYNOPSIS
extern
edll_ptr
edll_alloc(int size, int clear);
extern
edll_ptr
edll_realloc(edll_ptr rptr,
int size, int oldsize);
extern void edll_free(edll_ptr ptr);
PARAMETERS
size — the size in bytes of the block of memory to be allocated
clear — whether to clear the allocated buffer
rptr — the pointer to the buffer to resize
oldsize — the size of the buffer before this allocation happens
ptr — a memory buffer pointer to free
DESCRIPTION
The edll
library manages memory using the edll
commands edll_alloc(), edll_realloc() and edll_free().
There is one exception: the memory used to load the section content
directly calls the VirtualAlloc().
However, this shouldn't be a problem since you don't have direct access
to section start pointers.
All memory pointers allocated by the edll
library and returned to you
need to be freed using the edll_free()
function.
The edll_alloc() function
allocates a buffer of at least size bytes. Whenever the parameter clear
is true (non-zero), the buffer is cleared before the function returns.
The edll_realloc() function is
very similar to the edll_alloc()
function. It will allocate a new buffer of memory if the rptr parameter is zero. The new size
is specified in the size
parameter. If the new size is larger than the old size of the buffer
(and the old size parameter is specified) then the memory area used to
enlarge the buffer will be cleared. Use an old size of -1 to avoid this
effect.
The edll_free() function frees
a buffer of memory which has been allocated with either of edll_alloc() and edll_realloc().
NOTES
The memory management functions are
currently available before you call the edll_init() function. This may
change in the future.
SEE ALSO
edll
NAME
edll_callback_register — register a set
of callbacks
SYNOPSIS
extern void
edll_callback_register(edll_check_version check_version_func);
PARAMETERS
check_version_func — the version function to call to compare versions
DESCRIPTION
The edll
supports some callbacks which are explained here.
The
edll
library can determine the version of your application and of each
module that
it loads.
If the application has no version, then no version will ever be checked.
By default, the
edll will
compare
the version strings with strcmp() and if not strictly equal, it will
fail
the loading of the module.
In order to make the comparison more complex, you can write your own
function
to, for instance, accept any older or any newer version of the module.
Please, see the definition of the callback function
edll_check_version for more
information
on how you can define your own function.
NOTES
The version feature is optional. You
have
to make sure that your edll
library was configured with the --enable-versioncheck option.
You can look in the edll-config.h file and seach for
#undef VERSION_CHECK
(no version support) or
#define VERSION_CHECK 1
(version support
enabled).
BUGS
By default, the version of the
application will not stick to your .exe file. This is because the
linker removes the
.version section when it
creates the .exe file. You have two solutions to fix the problem: (a)
you can call the
edll_set_self_version() function
to define the version at run time or (b) apply dev/version.patch to
your ldscripts/i386pe.x file.
SEE ALSO
edll
NAME
edll_open — load a plug-in in memory
and reallocate it
edll_close — close a module which has previously been opened with
edll_open
SYNOPSIS
extern
edll_module *
edll_open(const
char *filename);
extern int
edll_close(edll_module *module);
PARAMETERS
filename — the name of the plug-in or DLL to load with edll
module — the module to be closed
DESCRIPTION
The
edll library loads modules
with the
edll_open() function.
That function searches for the filename in the different directories as
specified by the search path. The
edll_open()
function returns a module pointer. You should always call the
edll_close() with all the modules
that you open with
edll_open().
The close is automatically called whenever you exit the library (see
edll_exit())
SEE ALSO
edll
NAME
edll_sym — search for a symbol in the
specified module
edll_msym — search for a symbol in all the module
SYNOPSIS
extern
edll_ptr *
edll_sym(edll_module
*module, const char *name);
extern edll_ptr *
edll_msym(edll_module **module_ptr, const
char *name);
PARAMETERS
name — the name of the symbol to search
module — the module where the symbol is searched (dependency modules
can't be reached from this variable); if NULL, search all the modules
module_ptr — a pointer to a module pointer; if NULL, does not return
the pointer to the module found and search all the modules
DESCRIPTION
The edll library loads all the
modules in a list which is globally managed. When you need to find a
symbol you can either specify the module in which you want to search or
use NULL as the module pointer (i.e. search in all modules).
Note that edll keeps a single
list with all the symbols. This means is does a single binary search
to find the symbol (the symbols are kept in alphabetical order.) Also,
since we have that unique list, even when you request a search in a
single module, it will still take the same amount of time to find the
symbol (it can actually be slightly slower to search a single module.)
The edll_sym() function
searches for the specified symbol in the list of symbols of the
specified module. Note that if the module is a DLL, the names are not
currently being cached by the edll.
The edll_msym() function (it
could have been called: edll_module_sym())
uses a pointer to a module which is filled by the lower level search
function. It specifies in which module the symbol can be found.
Note that both functions can be used with the module pointer set to
zero (0 or NULL). In that case, it will return a pointer to the symbol
that it finds searching all the DLLs and plug-ins already loaded by
the application.
RETURN VALUE
Both functions will return a NULL
pointer
when an error occurs (usually, symbol not found.)
BUGS
Symbols should be unique among all the
modules compositing one application. The
edll won't fail loading such
applications, however, there is no guarantee that the same symbol will
be returned by the edll_sym()
and edll_msym() functions
unless you force which module needs to be searched.
There is a potential bug with symbols: their value can change without
your knowledge. [if I think about it later, I will elaborate about
this one...]
SEE ALSO
edll
NAME
edll_seterror — set the current
edll error
edll_geterror — get the current
edll error
edll_strerror — get a string for the current
edll error
SYNOPSIS
extern
edll_ptr *
edll_seterror(edll_errno_t
err);
extern edll_errno_t *
edll_geterror(void);
extern const char *edll_strerror(void);
PARAMETERS
err — a valid edll error
number
DESCRIPTION
The
edll library maintains its
own private error number variable.
The error number can be set with
edll_seterror()
and checked out by the
edll_geterror().
A string corresponding to the error number can also be queried for.
This is done using the
edll_strerror()
function.
In multi-thread application you need to specify a function to set
errors and one to get errors (see
edll_mutex_register()
for more information about how to define these functions.) You can
either act immediately on errors when your set function is called, or
save the error in a thread specific array of some sort. If you act
immediately, you will certainly not need to have a get function.
Otherwise, the get function needs to retrieve the error specific to the
running thread.
RETURN VALUE
The edll_seterror()
function doesn't return anything.
The edll_geterror() function
returns the current error number
The edll_strerror() function
returns a static const string from
SEE ALSO
edll
NAME
edll_setunixsearchpath — set a Unix
like set of paths to use to find the specified modules
edll_setsearchpath — set a MS-Windows set of paths to use to find the
specified modules
edll_getsearchpath — get a copy of the current search path
SYNOPSIS
extern int
edll_setunixsearchpath(const
char *unix_paths);
extern int
edll_setsearchpath(const char *paths);
extern char *edll_getsearchpath(void);
PARAMETERS
unix_paths — a list of paths separated by colons (:)
paths — a list of paths
separated by semi-colons (;)
DESCRIPTION
The edll library accepts a
search path that will be used to search for modules.
By default the edll determine
the search path as the current environment variable %PATH% with "."
prepended as in:".;%PATH%".
RETURN VALUE
The
edll_setunixpath()
function returns 0 on success
The
edll_setpath() function
returns 0 on success
The
edll_getsearchpath()
function returns a string pointer that you will need to free
(
edll_free) once you're done
BUGS
The search path is unique on a per
process basis. This means in a multi-threads environment changing it
in one thread, changes it for all threads. It is strongly adviced that
you set it once at the start and do not change it.
SEE ALSO
edll
NAME
edll_set_self_version — set the
version of the application (.exe file)
SYNOPSIS
extern void
edll_set_self_version(const char *version);
PARAMETERS
version — the application version (i.e. "1.0", "0.3.1c", etc.)
DESCRIPTION
The
edll library is now
capable
of retrieving a version in a module by reading the section named
.version.
Because by default the
.version
section cannot be kept in the .exe file (i.e. the linker drops it,)
edll has a function for your
application version to be given to the lower level functions. Another
solution is to patch the linker script (see the dev/version.patch file.)
The version of the application is later checked against the version
of any loaded modules. This is done with strcmp() by default. If you
want, you can specify a callback so as to be able to write your
own comparison function. See the
edll_callback_register function
to know how to register your version function and
edll_check_version typedef describes
what your function declaration is expected to look like.
BUGS
You MUST define the version of the
application before you call any of the
edll functions. It is a bug
not to do so. At this time the library doesn't enforce it though.
The version defined on the very first
call is the only one kept (also assuming no module was loaded before
this call.)
The linker loses sections it does not
know about when creating a .exe file. This is certainly the normal
behavior for the linker. To circumvent that problem with the .version section, you can apply the
dev/version.patch to your ldscripts/i386pe.x file. You may want to edit
the patch or your script file and do the pacthing by hand if you do not
have the same version of ld.
SEE ALSO
edll
NAME
edll_module_version — returns the
version string of the specified module
SYNOPSIS
extern const char
*edll_module_version(edll_module *module);
PARAMETERS
module — the module you want the version from or NULL for the self
module version
DESCRIPTION
The edll library recognizes
a section named .version which
includes a null terminated version
string.
The library will automatically compare each module version against
the version of the application. Once a module was loaded, you can
further check the version string of a module by calling this
function.
Note that you get in return the actual string saved in the module.
Do not change nor free that pointer. It will crash your application.
Passing NULL as the module pointer returns the application version
(also called self module.)
RETURN VALUE
The edll_module_version()
function returns 0 if the module has no version, a constant nul
terminated
C string otherwise
BUGS
The version of the application will not
be loaded until you load that module or some other module. Querying for
that version will return a NULL pointer until that happens. This may
get fixed in later versions.
SEE ALSO
edll
NAME
edll_mutex_register — register mutex
information for multi-thread usage
SYNOPSIS
extern int
edll_mutex_register(edll_mutex_lock
lock_func,
edll_mutex_unlock unlock_func,
edll_mutex_seterror seterror_func,
edll_mutex_geterror geterror_func,
edll_ptr userdata);
PARAMETERS
lock_func — the function to call to lock resources
unlock_func — the function to release resources
seterror_func — the function to set thread specific errors
geterror_func — the function to get thread specific errors
userdata — a pointer to some user data
DESCRIPTION
The edll library can be used
in a multi-thread environment. For that, you need to setup a lock and
an unlock function.
The library doesn't itself try to lock/unlock anything (thus we avoid
dependencies to any threading system).
The error handling was added also to make sure that the library doesn't
have any dependency on any threading system. It makes you responsible
to save error numbers and to be capable of retrieving them later.
Any of these functions should be setup once by one thread before
any others access the library and then it should never be changed.
It is legal to set any of these functions to NULL.
RETURN VALUE
The edll_mutex_register()
function returns 0 on success
BUGS
Changing the function pointers while
another thread is using the library can cause crashes and deadlocks.
SEE ALSO
Undefined Symbols and Unresolved
Symbols
The edll does link your plug-ins at runtime. This means you may get
errors of symbols that it can't define. This will especially happens
when you run a C program and try to load C++ plug-ins because C++ needs
a wealth of symbols and these symbols are not all too clearly named.
The following table is an attempt to define different symbols you most
certainly will have problems with at some point. Note that you can use
the list.sh script (under the dev sub-directory) to generate a list of
all the symbols in all the libraries available on your platform.
Symbol Name
|
Purpose
|
Comment
|
__imp__<name>
|
compiler introducer
|
For some reason, gcc/g++ will
add __imp__ in front of some symbols. The library is supposed to
search for these and report them as equal to symbols without the
__imp__ introducer. I searched the linker and I could not find anything
like this, so I do not have any real ground to believe that this is
correct other than the fact that it actually works. If you see a
symbol starting with __imp__... failing, then it can come from a
mistake in the comparison with that symbol and some system
symbol.
|
__CRT_MT
|
Multi-thread availability
|
This is a flag which tells the
pthread library whether the process was linked with the proper support
or not (i.e. the pthread library will leak without the proper support).
This is part of the mtcrt.o file.
|
_Znaj, _Zdaj
|
New and delete array
|
These are the new and delete
operators used with the square brackets:
array = new int[256];
This is part of the stdlibc++.a file.
|
Known Bugs & Limitations
The following list shows you what I know can cause problems with
the edll library.
- All the plugin filenames need to be defined in ASCII (character
32 to 127, not all characters are allowed though)
- All the files need to be compiled with the same version of gcc or
g++ (otherwise the resolution may break)
- The filename may be limited to MAX_PATH (usually around 240
characters)
- The automatic versioning feature is not yet functional because
the linker
clears out the .version section.
- The main application cannot have its symbols stripped if it is
to use multi-threading. This is because each module needs to link back
to some thread variables which will only be available in your main
application. Of course, it also cannot be stripped if you want your
plugins to be able to link back to some of your application functions.
- Linking COMMON sections and running with edll is not equivalent. The COMMON
sections of multiple object files will be merged by the linker. It will
keep the largest of each symbol. For instance, if you create a table (
char
tbl[100]
) in file a.c and a table with the same name in file b.c
(char tbl[200]
) but larger, then the linker will create
one table in ab.o when you link both files together which has the
largest size (200 char's in our example). If you use edll to first load a.o and then b.o,
when loading b.o edll will not
look at the symbols of a.o to know how to resolve tbl
and
thus you will have two tables one of 200 bytes in b.o and one of 100
bytes in a.o (see the edll-two-bss test). Not only that,
it also will not share the same memory location. It seems to me that
for a plugin, this is the correct behavior.
- strip cannot be used on any of your executable files. Later, I
will provide a modified version of strip (edll-strip) which will be
gentle to our sections.
- If you load the msvcr70.dll in your plugin, the stdout, stdin and
stderr streams are re-initialized (it seems to me). This means printf()'s
will not be synchronized between your main application and you plugins. Fun!
This file was last modified on September 17, 2007 at 20:38
Copyright (c) 2005-2006
Alexis Wilke