FFI: Resolve ld script redirection in ffi.load().

This commit is contained in:
Mike Pall 2011-03-01 12:31:16 +01:00
parent e1aa8d0d97
commit 6c43767c23

View File

@ -22,6 +22,7 @@
#if LJ_TARGET_DLOPEN #if LJ_TARGET_DLOPEN
#include <dlfcn.h> #include <dlfcn.h>
#include <stdio.h>
#if defined(RTLD_DEFAULT) #if defined(RTLD_DEFAULT)
#define CLIB_DEFHANDLE RTLD_DEFAULT #define CLIB_DEFHANDLE RTLD_DEFAULT
@ -59,11 +60,41 @@ static const char *clib_extname(lua_State *L, const char *name)
return name; return name;
} }
/* Quick and dirty solution to resolve shared library name from ld script. */
static const char *clib_resolve_lds(lua_State *L, const char *name)
{
FILE *fp = fopen(name, "r");
if (fp) {
char *p, *e, buf[256];
if (fgets(buf, sizeof(buf), fp) && !strncmp(buf, "/* GNU ld script", 16)) {
while (fgets(buf, sizeof(buf), fp)) {
if (!strncmp(buf, "GROUP", 5) && (p = strchr(buf, '('))) {
while (*++p == ' ') ;
for (e = p; *e && *e != ' ' && *e != ')'; e++) ;
fclose(fp);
return strdata(lj_str_new(L, p, e-p));
}
}
}
fclose(fp);
}
return NULL;
}
static void *clib_loadlib(lua_State *L, const char *name, int global) static void *clib_loadlib(lua_State *L, const char *name, int global)
{ {
void *h = dlopen(clib_extname(L, name), void *h = dlopen(clib_extname(L, name),
RTLD_LAZY | (global?RTLD_GLOBAL:RTLD_LOCAL)); RTLD_LAZY | (global?RTLD_GLOBAL:RTLD_LOCAL));
if (!h) clib_error_(L); if (!h) {
const char *e, *err = dlerror();
if (*err == '/' && (e = strchr(err, ':')) &&
(name = clib_resolve_lds(L, strdata(lj_str_new(L, err, e-err))))) {
h = dlopen(name, RTLD_LAZY | (global?RTLD_GLOBAL:RTLD_LOCAL));
if (h) return h;
err = dlerror();
}
lj_err_callermsg(L, err);
}
return h; return h;
} }