From 97d2a6ec5ca8ace8daed29c8c69aab9595147b3a Mon Sep 17 00:00:00 2001 From: Thomas Martitz Date: Fri, 27 Aug 2010 00:16:26 +0000 Subject: [PATCH] Revert "Introduce a small api for loading code (codecs,plugins) from disk/memory." I don't understand the build error at all, plugin_bss_start is clearly defined in plugin.lds git-svn-id: svn://svn.rockbox.org/rockbox/trunk@27901 a1c6a512-1295-4272-9138-f99709370657 --- apps/codecs.c | 101 ++++++++++++++-------- apps/plugin.c | 108 +++++++++++++++-------- apps/plugins/plugin_crt0.c | 6 -- firmware/SOURCES | 1 - firmware/export/load_code.h | 55 ------------ firmware/load_code.c | 165 ------------------------------------ uisimulator/common/io.c | 113 +++++++++++++++++++++--- 7 files changed, 238 insertions(+), 311 deletions(-) delete mode 100644 firmware/export/load_code.h delete mode 100644 firmware/load_code.c diff --git a/apps/codecs.c b/apps/codecs.c index b072c65f40..9e77dd9099 100644 --- a/apps/codecs.c +++ b/apps/codecs.c @@ -28,7 +28,6 @@ #include #include #include "string-extra.h" -#include "load_code.h" #include "debug.h" #include "button.h" #include "dir.h" @@ -75,13 +74,26 @@ size_t codec_size; extern void* plugin_get_audio_buffer(size_t *buffer_size); -#if (CONFIG_PLATFORM & PLATFORM_NATIVE) && defined(HAVE_RECORDING) #undef open static int open(const char* pathname, int flags, ...) { +#if (CONFIG_PLATFORM & PLATFORM_HOSTED) + int fd; + if (flags & O_CREAT) + { + va_list ap; + va_start(ap, flags); + fd = sim_open(pathname, flags, va_arg(ap, unsigned int)); + va_end(ap); + } + else + fd = sim_open(pathname, flags); + + return fd; +#else return file_open(pathname, flags); -} #endif +} struct codec_api ci = { 0, /* filesize */ @@ -185,46 +197,62 @@ void codec_get_full_path(char *path, const char *codec_root_fn) CODECS_DIR, codec_root_fn); } -static int codec_load_ram(void *handle, struct codec_api *api) +static int codec_load_ram(int size, struct codec_api *api) { - struct codec_header *hdr = lc_get_header(handle); + struct codec_header *hdr; int status; - - if (hdr == NULL +#if (CONFIG_PLATFORM & PLATFORM_NATIVE) + hdr = (struct codec_header *)codecbuf; + + if (size <= (signed)sizeof(struct codec_header) || (hdr->magic != CODEC_MAGIC #ifdef HAVE_RECORDING && hdr->magic != CODEC_ENC_MAGIC #endif ) || hdr->target_id != TARGET_ID -#if (CONFIG_PLATFORM & PLATFORM_NATIVE) || hdr->load_addr != codecbuf - || hdr->end_addr > codecbuf + CODEC_SIZE -#endif - ) + || hdr->end_addr > codecbuf + CODEC_SIZE) { logf("codec header error"); - lc_close(handle); return CODEC_ERROR; } + codec_size = hdr->end_addr - codecbuf; + +#elif (CONFIG_PLATFORM & PLATFORM_HOSTED) + void *pd; + + hdr = sim_codec_load_ram(codecbuf, size, &pd); + + if (pd == NULL) + return CODEC_ERROR; + + if (hdr == NULL + || (hdr->magic != CODEC_MAGIC +#ifdef HAVE_RECORDING + && hdr->magic != CODEC_ENC_MAGIC +#endif + ) + || hdr->target_id != TARGET_ID) { + sim_codec_close(pd); + return CODEC_ERROR; + } + + codec_size = codecbuf - codecbuf; + +#endif /* CONFIG_PLATFORM */ if (hdr->api_version > CODEC_API_VERSION || hdr->api_version < CODEC_MIN_API_VERSION) { - logf("codec api version error"); - lc_close(handle); + sim_codec_close(pd); return CODEC_ERROR; } -#if (CONFIG_PLATFORM & PLATFORM_NATIVE) - codec_size = hdr->end_addr - codecbuf; -#else - codec_size = 0; -#endif - *(hdr->api) = api; + cpucache_invalidate(); status = hdr->entry_point(); - lc_close(handle); + sim_codec_close(pd); return status; } @@ -232,37 +260,36 @@ static int codec_load_ram(void *handle, struct codec_api *api) int codec_load_buf(unsigned int hid, struct codec_api *api) { int rc; - void *handle; rc = bufread(hid, CODEC_SIZE, codecbuf); if (rc < 0) { logf("error loading codec"); return CODEC_ERROR; } - handle = lc_open_from_mem(codecbuf, rc); - if (handle == NULL) - { - logf("error loading codec"); - return CODEC_ERROR; - } - api->discard_codec(); - return codec_load_ram(handle, api); + return codec_load_ram(rc, api); } int codec_load_file(const char *plugin, struct codec_api *api) { char path[MAX_PATH]; - void *handle; + int fd; + int rc; codec_get_full_path(path, plugin); - - handle = lc_open(path, codecbuf, CODEC_SIZE); - - if (handle == NULL) { - logf("Codec load error"); + + fd = open(path, O_RDONLY); + if (fd < 0) { + logf("Codec load error:%d", fd); splashf(HZ*2, "Couldn't load codec: %s", path); + return fd; + } + + rc = read(fd, &codecbuf[0], CODEC_SIZE); + close(fd); + if (rc <= 0) { + logf("Codec read error"); return CODEC_ERROR; } - return codec_load_ram(handle, api); + return codec_load_ram((size_t)rc, api); } diff --git a/apps/plugin.c b/apps/plugin.c index 53a05bf527..cc540cd988 100644 --- a/apps/plugin.c +++ b/apps/plugin.c @@ -42,7 +42,6 @@ #include "errno.h" #include "diacritic.h" #include "filefuncs.h" -#include "load_code.h" #if CONFIG_CHARGING #include "power.h" @@ -76,19 +75,21 @@ static unsigned int open_files; #if (CONFIG_PLATFORM & PLATFORM_HOSTED) static unsigned char pluginbuf[PLUGIN_BUFFER_SIZE]; +void *sim_plugin_load(char *plugin, void **pd); +void sim_plugin_close(void *pd); void sim_lcd_ex_init(unsigned long (*getpixel)(int, int)); void sim_lcd_ex_update_rect(int x, int y, int width, int height); #else +#define sim_plugin_close(x) extern unsigned char pluginbuf[]; #include "bitswap.h" #endif /* for actual plugins only, not for codecs */ +static bool plugin_loaded = false; static int plugin_size = 0; static bool (*pfn_tsr_exit)(bool reenter) = NULL; /* TSR exit callback */ static char current_plugin[MAX_PATH]; -/* NULL if no plugin is loaded, otherwise the handle that lc_open() returned */ -static void *current_plugin_handle; char *plugin_get_current_filename(void); @@ -727,60 +728,98 @@ int plugin_load(const char* plugin, const void* parameter) { int rc, i; struct plugin_header *hdr; +#if (CONFIG_PLATFORM & PLATFORM_HOSTED) + void *pd; +#else /* PLATFOR_NATIVE */ + int fd; + ssize_t readsize; +#if NUM_CORES > 1 + unsigned my_core; +#endif +#endif /* CONFIG_PLATFORM */ #if LCD_DEPTH > 1 fb_data* old_backdrop; #endif - if (current_plugin_handle && pfn_tsr_exit) - { /* if we have a resident old plugin and a callback */ + if (pfn_tsr_exit != NULL) /* if we have a resident old plugin: */ + { if (pfn_tsr_exit(!strcmp(current_plugin, plugin)) == false ) { /* not allowing another plugin to load */ return PLUGIN_OK; } - lc_close(current_plugin_handle); - current_plugin_handle = pfn_tsr_exit = NULL; + pfn_tsr_exit = NULL; + plugin_loaded = false; } splash(0, ID2P(LANG_WAIT)); strcpy(current_plugin, plugin); - current_plugin_handle = lc_open(plugin, pluginbuf, PLUGIN_BUFFER_SIZE); - if (current_plugin_handle == NULL) { +#if (CONFIG_PLATFORM & PLATFORM_HOSTED) + hdr = sim_plugin_load((char *)plugin, &pd); + if (pd == NULL) { splashf(HZ*2, str(LANG_PLUGIN_CANT_OPEN), plugin); return -1; } - - hdr = lc_get_header(current_plugin_handle); - if (hdr == NULL || hdr->magic != PLUGIN_MAGIC - || hdr->target_id != TARGET_ID -#if (CONFIG_PLATFORM & PLATFORM_NATIVE) - || hdr->load_addr != pluginbuf - || hdr->end_addr > pluginbuf + PLUGIN_BUFFER_SIZE -#endif - ) - { - lc_close(current_plugin_handle); + || hdr->target_id != TARGET_ID) { + sim_plugin_close(pd); splash(HZ*2, str(LANG_PLUGIN_WRONG_MODEL)); return -1; } if (hdr->api_version > PLUGIN_API_VERSION - || hdr->api_version < PLUGIN_MIN_API_VERSION) - { - lc_close(current_plugin_handle); + || hdr->api_version < PLUGIN_MIN_API_VERSION) { + sim_plugin_close(pd); splash(HZ*2, str(LANG_PLUGIN_WRONG_VERSION)); return -1; } -#if (CONFIG_PLATFORM & PLATFORM_NATIVE) - plugin_size = hdr->end_addr - pluginbuf; #else - plugin_size = 0; + fd = open(plugin, O_RDONLY); + if (fd < 0) { + splashf(HZ*2, str(LANG_PLUGIN_CANT_OPEN), plugin); + return fd; + } +#if NUM_CORES > 1 + /* Make sure COP cache is flushed and invalidated before loading */ + my_core = switch_core(CURRENT_CORE ^ 1); + cpucache_invalidate(); + switch_core(my_core); +#endif + + readsize = read(fd, pluginbuf, PLUGIN_BUFFER_SIZE); + close(fd); + + if (readsize < 0) { + splashf(HZ*2, str(LANG_READ_FAILED), plugin); + return -1; + } + hdr = (struct plugin_header *)pluginbuf; + + if ((unsigned)readsize <= sizeof(struct plugin_header) + || hdr->magic != PLUGIN_MAGIC + || hdr->target_id != TARGET_ID + || hdr->load_addr != pluginbuf + || hdr->end_addr > pluginbuf + PLUGIN_BUFFER_SIZE) { + splash(HZ*2, str(LANG_PLUGIN_WRONG_MODEL)); + return -1; + } + if (hdr->api_version > PLUGIN_API_VERSION + || hdr->api_version < PLUGIN_MIN_API_VERSION) { + splash(HZ*2, str(LANG_PLUGIN_WRONG_VERSION)); + return -1; + } + plugin_size = hdr->end_addr - pluginbuf; + + /* zero out bss area only, above guards end of pluginbuf */ + if (plugin_size > readsize) + memset(pluginbuf + readsize, 0, plugin_size - readsize); #endif *(hdr->api) = &rockbox_api; + plugin_loaded = true; + #if defined HAVE_LCD_BITMAP && LCD_DEPTH > 1 old_backdrop = lcd_get_backdrop(); @@ -795,6 +834,8 @@ int plugin_load(const char* plugin, const void* parameter) FOR_NB_SCREENS(i) viewportmanager_theme_enable(i, false, NULL); + + cpucache_invalidate(); #ifdef HAVE_TOUCHSCREEN touchscreen_set_mode(TOUCHSCREEN_BUTTON); @@ -806,12 +847,6 @@ int plugin_load(const char* plugin, const void* parameter) rc = hdr->entry_point(parameter); - if (!pfn_tsr_exit) - { /* close handle if plugin is no tsr one */ - lc_close(current_plugin_handle); - current_plugin_handle = NULL; - } - /* Go back to the global setting in case the plugin changed it */ #ifdef HAVE_TOUCHSCREEN touchscreen_set_mode(global_settings.touch_mode); @@ -852,8 +887,11 @@ int plugin_load(const char* plugin, const void* parameter) FOR_NB_SCREENS(i) viewportmanager_theme_undo(i, false); + if (pfn_tsr_exit == NULL) + plugin_loaded = false; + #ifdef HAVE_PLUGIN_CHECK_OPEN_CLOSE - if(open_files != 0 && !current_plugin_handle) + if(open_files != 0 && !plugin_loaded) { int fd; logf("Plugin '%s' leaks file handles", plugin); @@ -871,6 +909,8 @@ int plugin_load(const char* plugin, const void* parameter) } #endif + sim_plugin_close(pd); + if (rc == PLUGIN_ERROR) splash(HZ*2, str(LANG_PLUGIN_ERROR)); @@ -883,7 +923,7 @@ void* plugin_get_buffer(size_t *buffer_size) { int buffer_pos; - if (current_plugin_handle) + if (plugin_loaded) { if (plugin_size >= PLUGIN_BUFFER_SIZE) return NULL; diff --git a/apps/plugins/plugin_crt0.c b/apps/plugins/plugin_crt0.c index e34124c5a2..536eccaffa 100644 --- a/apps/plugins/plugin_crt0.c +++ b/apps/plugins/plugin_crt0.c @@ -32,8 +32,6 @@ PLUGIN_HEADER #define EXIT_MAGIC 0x0CDEBABE extern enum plugin_status plugin_start(const void*); -extern unsigned char plugin_bss_start[]; -extern unsigned char plugin_end_addr[]; static jmp_buf __exit_env; /* only 1 atexit handler for now, chain in the exit handler if you need more */ @@ -63,10 +61,6 @@ enum plugin_status plugin__start(const void *param) int exit_ret; enum plugin_status ret; - /* zero out the bss section */ -#if (CONFIG_PLATFORM & PLATFORM_NATIVE) - rb->memset(plugin_bss_start, 0, plugin_end_addr - plugin_bss_start); -#endif /* we come back here if exit() was called or the plugin returned normally */ exit_ret = setjmp(__exit_env); if (exit_ret == 0) diff --git a/firmware/SOURCES b/firmware/SOURCES index f83b78970e..e6157fa7d0 100644 --- a/firmware/SOURCES +++ b/firmware/SOURCES @@ -3,7 +3,6 @@ events.c backlight.c buffer.c general.c -load_code.c powermgmt.c system.c usb.c diff --git a/firmware/export/load_code.h b/firmware/export/load_code.h deleted file mode 100644 index f4fa8f9b46..0000000000 --- a/firmware/export/load_code.h +++ /dev/null @@ -1,55 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Copyright (C) 2010 by Thomas Martitz - * - * 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; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ - - -#include "config.h" - -#if (CONFIG_PLATFORM & PLATFORM_NATIVE) -#include "system.h" - -extern void *lc_open(const char *filename, char *buf, size_t buf_size); -/* header is always at the beginning of the blob, and handle actually points - * to the start of the blob */ -static inline char *lc_open_from_mem(void* addr, size_t blob_size) -{ - (void)blob_size; - cpucache_invalidate(); - return addr; -} -static inline void *lc_get_header(void *handle) { return handle; } -/* no need to do anything */ -static inline void lc_close(void *handle) { (void)handle; } - -#elif (CONFIG_PLATFORM & PLATFORM_HOSTED) - -/* don't call these directly for loading code - * they're to be wrapped by platform specific functions */ -extern void *_lc_open(const char *filename, char *buf, size_t buf_size); -extern void *_lc_get_header(void *handle); -extern void _lc_close(void *handle); - -extern void *lc_open(const char *filename, char *buf, size_t buf_size); -/* not possiible on hosted platforms */ -extern void *lc_open_from_mem(void *addr, size_t blob_size); -extern void *lc_get_header(void *handle); -extern void lc_close(void *handle); -extern const char* lc_last_error(void); -#endif diff --git a/firmware/load_code.c b/firmware/load_code.c deleted file mode 100644 index 9e8e71f9af..0000000000 --- a/firmware/load_code.c +++ /dev/null @@ -1,165 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Copyright (C) 2010 by Thomas Martitz - * - * 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; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ - -#include "config.h" -#include "system.h" -#include "file.h" -#include "debug.h" -#include "load_code.h" - -#if (CONFIG_PLATFORM & PLATFORM_NATIVE) -/* load binary blob from disk to memory, returning a handle */ -void * lc_open(const char *filename, char *buf, size_t buf_size) -{ - int fd = open(filename, O_RDONLY); - ssize_t read_size; - - if (fd < 0) - { - DEBUGF("Could not open file"); - return NULL; - } - -#if NUM_CORES > 1 - /* Make sure COP cache is flushed and invalidated before loading */ - { - int my_core = switch_core(CURRENT_CORE ^ 1); - cpucache_invalidate(); - switch_core(my_core); - } -#endif - - read_size = read(fd, buf, buf_size); - close(fd); - cpucache_invalidate(); - - if (read_size < 0) - { - DEBUGF("Could not read from file"); - return NULL; - } - return buf; -} - -#elif (CONFIG_PLATFORM & PLATFORM_HOSTED) -/* libdl wrappers */ - - -#ifdef WIN32 -/* win32 */ -#include -#define dlopen(_x_, _y_) LoadLibraryW(_x_) -#define dlsym(_x_, _y_) (void *)GetProcAddress(_x_, _y_) -#define dlclose(_x_) FreeLibrary(_x_) -static inline char *_dlerror(void) -{ - static char err_buf[64]; - FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), 0, - err_buf, sizeof(err_buf), NULL); - return err_buf; -} -#define dlerror _dlerror -#else -/* unix */ -#include -#define O_BINARY 0 -#endif -#include -#include "rbpaths.h" -#include "general.h" - -void * _lc_open(const char *filename, char *buf, size_t buf_size) -{ - (void)buf; - (void)buf_size; - void* dl_handle = dlopen(filename, RTLD_NOW); - return dl_handle; -} - -void *lc_open_from_mem(void *addr, size_t blob_size) -{ - int fd, i; - char temp_filename[MAX_PATH]; - - /* We have to create the dynamic link library file from ram so we - can simulate the codec loading. With voice and crossfade, - multiple codecs may be loaded at the same time, so we need - to find an unused filename */ - for (i = 0; i < 10; i++) - { -#if (CONFIG_PLATFORM & PLATFORM_ANDROID) - /* we need that path fixed, since get_user_file_path() - * gives us the folder on the sdcard where we cannot load libraries - * from (no exec permissions) - */ - snprintf(temp_filename, sizeof(temp_filename), - "/data/data/org.rockbox/app_rockbox/libtemp_binary_%d.so", i); -#else - char name[MAX_PATH]; - const char *_name = get_user_file_path(ROCKBOX_DIR, NEED_WRITE, name, sizeof(name)); - snprintf(temp_filename, sizeof(temp_filename), - "%slibtemp_binary_%d.dll", _name, i); -#endif - fd = open(temp_filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0766); - if (fd >= 0) - break; /* Created a file ok */ - } - - DEBUGF("Creating %s\n", temp_filename); - if (fd < 0) - { - DEBUGF("open failed\n"); - return NULL; - } - - if (write(fd, addr, blob_size) < (ssize_t)blob_size) - { - DEBUGF("Write failed\n"); - close(fd); - remove(temp_filename); - return NULL; - } - - close(fd); - return lc_open(temp_filename, NULL, 0); -} - - -void *_lc_get_header(void *handle) -{ - char *ret = dlsym(handle, "__header"); - if (ret == NULL) - ret = dlsym(handle, "___header"); - - return ret; -} - -void _lc_close(void *handle) -{ - if (handle) - dlclose(handle); -} - -const char *lc_last_error(void) -{ - return dlerror(); -} -#endif diff --git a/uisimulator/common/io.c b/uisimulator/common/io.c index c8d6a8a67d..4c0fa33be5 100644 --- a/uisimulator/common/io.c +++ b/uisimulator/common/io.c @@ -58,7 +58,6 @@ #include "debug.h" #include "ata.h" /* for IF_MV2 et al. */ #include "rbpaths.h" -#include "load_code.h" /* keep this in sync with file.h! */ #undef MAX_PATH /* this avoids problems when building simulator */ @@ -531,28 +530,116 @@ int sim_fsync(int fd) #include #endif - -void *lc_open(const char *filename, char *buf, size_t buf_size) +void *sim_codec_load_ram(char* codecptr, int size, void **pd) { - const char *sim_path = get_sim_pathname(filename); - void *handle = _lc_open((const char*)UTF8_TO_OS(sim_path), buf, buf_size); + void *hdr; + char path[MAX_PATH]; + int fd; + int codec_count; +#ifdef WIN32 + char buf[MAX_PATH]; +#endif - if (handle == NULL) + *pd = NULL; + + /* We have to create the dynamic link library file from ram so we + can simulate the codec loading. With voice and crossfade, + multiple codecs may be loaded at the same time, so we need + to find an unused filename */ + for (codec_count = 0; codec_count < 10; codec_count++) { - DEBUGF("failed to load %s\n", filename); - DEBUGF("lc_open(%s): %s\n", filename, lc_last_error()); +#if (CONFIG_PLATFORM & PLATFORM_ANDROID) + /* we need that path fixed, since get_user_file_path() + * gives us the folder on the sdcard where we cannot load libraries + * from (no exec permissions) + */ + snprintf(path, sizeof(path), + "/data/data/org.rockbox/app_rockbox/libtemp_codec_%d.so", + codec_count); +#else + char name[MAX_PATH]; + const char *_name = get_user_file_path(ROCKBOX_DIR, 0, name, sizeof(name)); + snprintf(path, sizeof(path), "%s/_temp_codec%d.dll", get_sim_pathname(_name), codec_count); +#endif + fd = OPEN(path, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, S_IRWXU); + if (fd >= 0) + break; /* Created a file ok */ } - return handle; + if (fd < 0) + { + DEBUGF("failed to open for write: %s\n", path); + return NULL; + } + + if (write(fd, codecptr, size) != size) + { + DEBUGF("write failed"); + return NULL; + } + close(fd); + + /* Now load the library. */ + *pd = dlopen(path, RTLD_NOW); + if (*pd == NULL) + { + DEBUGF("failed to load %s\n", path); +#ifdef WIN32 + FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), 0, + buf, sizeof buf, NULL); + DEBUGF("dlopen(%s): %s\n", path, buf); +#else + DEBUGF("dlopen(%s): %s\n", path, dlerror()); +#endif + return NULL; + } + + hdr = dlsym(*pd, "__header"); + if (!hdr) + hdr = dlsym(*pd, "___header"); + + return hdr; /* maybe NULL if symbol not present */ } -void *lc_get_header(void *handle) +void sim_codec_close(void *pd) { - return _lc_get_header(handle); + dlclose(pd); } -void lc_close(void *handle) +void *sim_plugin_load(char *plugin, void **pd) { - _lc_close(handle); + void *hdr; + char path[MAX_PATH]; +#ifdef WIN32 + char buf[MAX_PATH]; +#endif + + snprintf(path, sizeof(path), "%s", get_sim_pathname(plugin)); + + *pd = NULL; + + *pd = dlopen(path, RTLD_NOW); + if (*pd == NULL) { + DEBUGF("failed to load %s\n", plugin); +#ifdef WIN32 + FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), 0, + buf, sizeof(buf), NULL); + DEBUGF("dlopen(%s): %s\n", path, buf); +#else + DEBUGF("dlopen(%s): %s\n", path, dlerror()); +#endif + return NULL; + } + + hdr = dlsym(*pd, "__header"); + if (!hdr) + hdr = dlsym(*pd, "___header"); + + return hdr; /* maybe NULL if symbol not present */ +} + +void sim_plugin_close(void *pd) +{ + dlclose(pd); } #ifdef WIN32