#include <jit/jit-dynamic.h>
#include <jit/jit-util.h>
#include <stdio.h>
#include <config.h>
#ifdef JIT_WIN32_PLATFORM
#include <windows.h>
#ifndef JIT_WIN32_NATIVE
#ifdef HAVE_SYS_CYGWIN_H
#include <sys/cygwin.h>
#endif
#endif
#else
#ifdef HAVE_DLFCN_H
#include <dlfcn.h>
#endif
#endif
#ifdef __cplusplus
extern "C" {
#endif
static int dynlib_debug = 0;
void jit_dynlib_set_debug(int flag)
{
dynlib_debug = flag;
}
#if defined(__APPLE__) && defined(__MACH__)
#include <mach-o/dyld.h>
jit_dynlib_handle_t jit_dynlib_open(const char *name)
{
NSObjectFileImage file;
NSObjectFileImageReturnCode result;
NSModule module;
void *image;
const char *msg;
result = NSCreateObjectFileImageFromFile(name, &file);
if(result == NSObjectFileImageInappropriateFile)
{
image = (void *)NSAddImage(name, NSADDIMAGE_OPTION_RETURN_ON_ERROR);
if(image)
{
return image;
}
}
if(result != NSObjectFileImageSuccess)
{
switch(result)
{
case NSObjectFileImageFailure:
msg = " (NSObjectFileImageFailure)"; break;
case NSObjectFileImageInappropriateFile:
msg = " (NSObjectFileImageInappropriateFile)"; break;
case NSObjectFileImageArch:
msg = " (NSObjectFileImageArch)"; break;
case NSObjectFileImageFormat:
msg = " (NSObjectFileImageFormat)"; break;
case NSObjectFileImageAccess:
msg = " (NSObjectFileImageAccess)"; break;
default:
msg = ""; break;
}
if(dynlib_debug)
{
fprintf(stderr, "%s: could not load dynamic library%s\n",
name, msg);
}
return 0;
}
module = NSLinkModule(file, name,
NSLINKMODULE_OPTION_BINDNOW |
NSLINKMODULE_OPTION_PRIVATE |
NSLINKMODULE_OPTION_RETURN_ON_ERROR);
return (void *)module;
}
void jit_dynlib_close(jit_dynlib_handle_t handle)
{
if((((struct mach_header *)handle)->magic == MH_MAGIC) ||
(((struct mach_header *)handle)->magic == MH_CIGAM))
{
return;
}
NSUnLinkModule((NSModule)handle, NSUNLINKMODULE_OPTION_NONE);
}
static void *GetSymbol(jit_dynlib_handle_t handle, const char *symbol)
{
NSSymbol sym;
if((((struct mach_header *)handle)->magic == MH_MAGIC) ||
(((struct mach_header *)handle)->magic == MH_CIGAM))
{
if(NSIsSymbolNameDefinedInImage((struct mach_header *)handle, symbol))
{
sym = NSLookupSymbolInImage((struct mach_header *)handle, symbol,
NSLOOKUPSYMBOLINIMAGE_OPTION_BIND |
NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR);
}
else
{
sym = 0;
}
}
else
{
sym = NSLookupSymbolInModule((NSModule)handle, symbol);
}
if(sym == 0)
{
return 0;
}
return (void *)NSAddressOfSymbol(sym);
}
void *jit_dynlib_get_symbol(jit_dynlib_handle_t handle, const char *symbol)
{
void *value = GetSymbol(handle, (char *)symbol);
char *newName;
if(value)
{
return value;
}
newName = (char *)jit_malloc(jit_strlen(symbol) + 2);
if(newName)
{
newName[0] = '_';
jit_strcpy(newName + 1, symbol);
value = GetSymbol(handle, newName);
if(value)
{
jit_free(newName);
return value;
}
jit_free(newName);
}
if(dynlib_debug)
{
fprintf(stderr, "%s: could not find the specified symbol\n", symbol);
}
return 0;
}
const char *jit_dynlib_get_suffix(void)
{
return "dylib";
}
#elif defined(JIT_WIN32_PLATFORM)
jit_dynlib_handle_t jit_dynlib_open(const char *name)
{
void *libHandle;
char *newName = 0;
#if defined(JIT_WIN32_CYGWIN) && defined(HAVE_SYS_CYGWIN_H) && \
defined(HAVE_CYGWIN_CONV_TO_WIN32_PATH)
{
char buf[4096];
if(cygwin_conv_to_win32_path(name, buf) == 0)
{
newName = jit_strdup(buf);
if(!newName)
{
return 0;
}
}
}
#endif
libHandle = (void *)LoadLibrary((newName ? newName : name));
if(libHandle == 0)
{
if(dynlib_debug)
{
fprintf(stderr, "%s: could not load dynamic library\n",
(newName ? newName : name));
}
if(newName)
{
jit_free(newName);
}
return 0;
}
if(newName)
{
jit_free(newName);
}
return libHandle;
}
void jit_dynlib_close(jit_dynlib_handle_t handle)
{
FreeLibrary((HINSTANCE)handle);
}
void *jit_dynlib_get_symbol(jit_dynlib_handle_t handle, const char *symbol)
{
void *procAddr;
procAddr = (void *)GetProcAddress((HINSTANCE)handle, symbol);
if(procAddr == 0)
{
if(dynlib_debug)
{
fprintf(stderr, "%s: could not resolve symbol", symbol);
}
return 0;
}
return procAddr;
}
const char *jit_dynlib_get_suffix(void)
{
return "dll";
}
#elif defined(HAVE_DLFCN_H) && defined(HAVE_DLOPEN)
jit_dynlib_handle_t jit_dynlib_open(const char *name)
{
jit_dynlib_handle_t handle;
const char *error;
handle = (jit_dynlib_handle_t)dlopen(name, RTLD_LAZY | RTLD_GLOBAL);
if(!handle)
{
if(jit_strncmp(name, "lib", 3) != 0)
{
error = name;
while(*error != '\0' && *error != '/' && *error != '\\')
{
++error;
}
if(*error == '\0')
{
char *temp = (char *)jit_malloc(jit_strlen(name) + 4);
if(temp)
{
jit_strcpy(temp, "lib");
jit_strcat(temp, name);
handle = dlopen(temp, RTLD_LAZY | RTLD_GLOBAL);
jit_free(temp);
if(handle)
{
return handle;
}
}
handle = dlopen(name, RTLD_LAZY | RTLD_GLOBAL);
}
}
if(dynlib_debug)
{
error = dlerror();
fprintf(stderr, "%s: %s\n", name,
(error ? error : "could not load dynamic library"));
}
else
{
dlerror();
}
return 0;
}
else
{
return handle;
}
}
void jit_dynlib_close(jit_dynlib_handle_t handle)
{
dlclose(handle);
}
void *jit_dynlib_get_symbol(jit_dynlib_handle_t handle, const char *symbol)
{
void *value = dlsym(handle, (char *)symbol);
const char *error = dlerror();
char *newName;
if(error == 0)
{
return value;
}
newName = (char *)jit_malloc(jit_strlen(symbol) + 2);
if(newName)
{
newName[0] = '_';
jit_strcpy(newName + 1, symbol);
value = dlsym(handle, newName);
error = dlerror();
if(error == 0)
{
jit_free(newName);
return value;
}
jit_free(newName);
}
if(dynlib_debug)
{
fprintf(stderr, "%s: %s\n", symbol, error);
}
return 0;
}
const char *jit_dynlib_get_suffix(void)
{
return "so";
}
#else
jit_dynlib_handle_t jit_dynlib_open(const char *name)
{
if(dynlib_debug)
{
fprintf(stderr, "%s: dynamic libraries are not available\n", name);
}
return 0;
}
void jit_dynlib_close(jit_dynlib_handle_t handle)
{
}
void *jit_dynlib_get_symbol(jit_dynlib_handle_t handle, const char *symbol)
{
return 0;
}
const char *jit_dynlib_get_suffix(void)
{
return "so";
}
#endif
#ifdef __cplusplus
};
#endif