diff options
Diffstat (limited to 'backends/plugins/elf-provider.h')
-rw-r--r-- | backends/plugins/elf-provider.h | 52 |
1 files changed, 52 insertions, 0 deletions
diff --git a/backends/plugins/elf-provider.h b/backends/plugins/elf-provider.h index a6b55d97f3..981d0d0638 100644 --- a/backends/plugins/elf-provider.h +++ b/backends/plugins/elf-provider.h @@ -27,9 +27,61 @@ #define BACKENDS_PLUGINS_ELF_PROVIDER_H #include "base/plugins.h" +#include "backends/plugins/dynamic-plugin.h" +#include "common/fs.h" + +#include "backends/plugins/elf-loader.h" #if defined(DYNAMIC_MODULES) && defined(ELF_LOADER_TARGET) +class ELFPlugin : public DynamicPlugin { +protected: + DLObject *_dlHandle; + Common::String _filename; + + //FIXME: The code for this method should be in elf-provider.cpp, + // but VoidFunc isn't recognized if we do that as is. + virtual VoidFunc findSymbol(const char *symbol) { + void *func; + bool handleNull; + if (_dlHandle == NULL) { + func = NULL; + handleNull = true; + } else { + func = _dlHandle->symbol(symbol); + } + if (!func) { + if (handleNull) { + warning("Failed loading symbol '%s' from plugin '%s' (Handle is NULL)", symbol, _filename.c_str()); + } else { + warning("Failed loading symbol '%s' from plugin '%s'", symbol, _filename.c_str()); + } + } + + // FIXME HACK: This is a HACK to circumvent a clash between the ISO C++ + // standard and POSIX: ISO C++ disallows casting between function pointers + // and data pointers, but dlsym always returns a void pointer. For details, + // see e.g. <http://www.trilithium.com/johan/2004/12/problem-with-dlsym/>. + assert(sizeof(VoidFunc) == sizeof(func)); + VoidFunc tmp; + memcpy(&tmp, &func, sizeof(VoidFunc)); + return tmp;; + } + +public: + ELFPlugin(const Common::String &filename) + : _dlHandle(0), _filename(filename) {} + + ~ELFPlugin() { + if (_dlHandle) + unloadPlugin(); + } + + bool loadPlugin(); + void unloadPlugin(); + +}; + class ELFPluginProvider : public FilePluginProvider { protected: Plugin* createPlugin(const Common::FSNode &node) const; |