From 88b232da2e1167031ab8c1e46b0960159422904f Mon Sep 17 00:00:00 2001 From: Pekka Riikonen Date: Tue, 3 Jul 2007 19:44:23 +0000 Subject: [PATCH] Added SILC DLL API for loading/using shared objects/DLLs. --- lib/silcutil/silcdll.c | 85 ++++++++++++++++++++++ lib/silcutil/silcdll.h | 115 ++++++++++++++++++++++++++++++ lib/silcutil/tests/test_silcdll.c | 41 +++++++++++ 3 files changed, 241 insertions(+) create mode 100644 lib/silcutil/silcdll.c create mode 100644 lib/silcutil/silcdll.h create mode 100644 lib/silcutil/tests/test_silcdll.c diff --git a/lib/silcutil/silcdll.c b/lib/silcutil/silcdll.c new file mode 100644 index 00000000..20acef0b --- /dev/null +++ b/lib/silcutil/silcdll.c @@ -0,0 +1,85 @@ +/* + + silcdll.c + + Author: Pekka Riikonen + + Copyright (C) 2007 Pekka Riikonen + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + +*/ + +#include "silc.h" + +/* Load shared object */ + +SilcDll silc_dll_load(const char *object_path) +{ +#ifdef SILC_UNIX +#if defined(HAVE_DLOPEN) +#if defined(RTLD_NOW) + return dlopen(object_path, RTLD_NOW); +#elif defined(RTLD_LAZY) + return dlopen(object_path, RTLD_LAZY); +#else + return dlopen(object_path, 0); +#endif /* RTLD_NOW */ +#endif /* HAVE_DLOPEN */ +#elif SILC_WIN32 + return LoadLibrary(object_path); +#else + /* XXX Symbian */ +#endif /* SILC_UNIX */ + SILC_LOG_ERROR(("Shared objects are not supported on this platform")); + return NULL; +} + +/* Close shared object */ + +void silc_dll_close(SilcDll dll) +{ +#ifdef SILC_UNIX + dlclose(dll); +#elif SILC_WIN32 + FreeLibrary(dll); +#else + /* XXX Symbian */ +#endif /* SILC_UNIX */ +} + +/* Get symbol address from shared object */ + +void *silc_dll_getsym(SilcDll dll, const char *symbol) +{ +#ifdef SILC_UNIX + return (void *)dlsym(dll, symbol); +#elif SILC_WIN32 + return (void *)GetProcAddress(dll, symbol); +#else + /* XXX Symbian */ +#endif /* SILC_UNIX */ + SILC_LOG_ERROR(("Shared objects are not supported on this platform")); + return NULL; +} + +/* Get error string */ + +const char *silc_dll_error(SilcDll dll) +{ +#ifdef SILC_UNIX + return dlerror(); +#elif SILC_WIN32 + return NULL; +#else + /* XXX Symbian */ +#endif /* SILC_UNIX */ + return NULL; +} diff --git a/lib/silcutil/silcdll.h b/lib/silcutil/silcdll.h new file mode 100644 index 00000000..3da325b4 --- /dev/null +++ b/lib/silcutil/silcdll.h @@ -0,0 +1,115 @@ +/* + + silcdll.h + + Author: Pekka Riikonen + + Copyright (C) 2007 Pekka Riikonen + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + +*/ + +/****h* silcutil/Shared Object Interface + * + * DESCRIPTION + * + * Platform independent iterface for loading and using shared objects and + * dynamically linked libraries (DLLs). + * + ***/ + +#ifndef SILCDLL_H +#define SILCDLL_H + +/****s* silcutil/SilcDLLAPI/SilcDll + * + * NAME + * + * typedef void *SilcDll; + * + * DESCRIPTION + * + * This context represents the shared object and it is allocated by + * silc_dll_load and is destroyed with silc_dll_close functions. + * The context is given as argument to all funtions in this interface. + * + ***/ +#ifdef SILC_UNIX +typedef void *SilcDll; +#elif SILC_WIN32 +typedef HMODULE SilcDll; +#else +typedef void *SilcDll; +#endif /* SILC_UNIX */ + +/****f* silcutil/SilcDLLAPI/silc_dll_load + * + * SYNOPSIS + * + * SilcDll silc_dll_load(const char *object_path); + * + * DESCRIPTION + * + * Load shared object or DLL indicated by the `object_path'. The path + * must include the absolute path to the object and the object name. + * Returns the SilcDll context or NULL on error. The actual error + * message may be available by calling silc_dll_error function. Symbols + * may be retrieved from the returned context by calling silc_dll_getsym. + * + ***/ +SilcDll silc_dll_load(const char *object_path); + +/****f* silcutil/SilcDLLAPI/silc_dll_close + * + * SYNOPSIS + * + * void silc_dll_close(SilcDll dll); + * + * DESCRIPTION + * + * Closes the shared object indicated by `dll'. Any symbol retrieved + * from the `dll' with silc_dll_getsym will become invalid and cannot + * be used anymore. + * + ***/ +void silc_dll_close(SilcDll dll); + +/****f* silcutil/SilcDLLAPI/silc_dll_getsym + * + * SYNOPSIS + * + * void *silc_dll_getsym(SilcDll dll, const char *symbol); + * + * DESCRIPTION + * + * Returns the memory address of the symbol indicated by `symbol' from + * the shared object indicated by `dll'. If such symbol does not exist + * this returns NULL. + * + ***/ +void *silc_dll_getsym(SilcDll dll, const char *symbol); + +/****f* silcutil/SilcDLLAPI/silc_dll_error + * + * SYNOPSIS + * + * const char *silc_dll_error(SilcDll dll); + * + * DESCRIPTION + * + * This routine may return error string after an error has occured with + * the shared object indicated by `dll'. If error string is not available + * this will return NULL. + * + ***/ +const char *silc_dll_error(SilcDll dll); + +#endif /* SILCDLL_H */ diff --git a/lib/silcutil/tests/test_silcdll.c b/lib/silcutil/tests/test_silcdll.c new file mode 100644 index 00000000..00cf270f --- /dev/null +++ b/lib/silcutil/tests/test_silcdll.c @@ -0,0 +1,41 @@ +/* SilcDll tests */ + +#include "silc.h" + +int main(int argc, char **argv) +{ + SilcBool success = FALSE; + SilcDll dll; + void *ptr; + + if (argc > 1 && !strcmp(argv[1], "-d")) { + silc_log_debug(TRUE); + silc_log_quick(TRUE); + silc_log_debug_hexdump(TRUE); + silc_log_set_debug_string("*dll*"); + } + + SILC_LOG_DEBUG(("Load shared object /lib/libc.so.6")); + dll = silc_dll_load("/lib/libc.so.6"); + if (!dll) { + SILC_LOG_DEBUG(("Cannot load: %s", silc_dll_error(dll))); + goto err; + } + + SILC_LOG_DEBUG(("Get symbol 'fprintf'")); + ptr = silc_dll_getsym(dll, "fprintf"); + if (!ptr) + goto err; + SILC_LOG_DEBUG(("Symbol address %p", ptr)); + + SILC_LOG_DEBUG(("Close shared object")); + silc_dll_close(dll); + + success = TRUE; + + err: + SILC_LOG_DEBUG(("Testing was %s", success ? "SUCCESS" : "FAILURE")); + fprintf(stderr, "Testing was %s\n", success ? "SUCCESS" : "FAILURE"); + + return success; +} -- 2.24.0