diff --git a/src/foreign/foreign.c b/src/foreign/foreign.c index 9b22c39b85..2b7f85d80e 100644 --- a/src/foreign/foreign.c +++ b/src/foreign/foreign.c @@ -257,6 +257,9 @@ static Scheme_Object *foreign_ffi_lib(int argc, Scheme_Object *argv[]) } else handle = LoadLibraryW(WIDE_PATH(name)); # else /* WINDOWS_DYNAMIC_LOAD undefined */ +# ifdef __ANDROID__ + if (!name) handle = RTLD_DEFAULT; else +# endif /* __ANDROID__ */ handle = dlopen(name, RTLD_NOW | (as_global ? RTLD_GLOBAL : RTLD_LOCAL)); # endif /* WINDOWS_DYNAMIC_LOAD */ if (handle == NULL && !null_ok) { @@ -335,6 +338,11 @@ int ffi_obj_FIXUP(void *p) { END_XFORM_SKIP; #endif +#ifdef __ANDROID__ +static int adjustment_set; +static uintptr_t adjustment; +#endif /* __ANDROID__ */ + /* (ffi-obj objname ffi-lib-or-libname) -> ffi-obj */ #define MYNAME "ffi-obj" static Scheme_Object *foreign_ffi_obj(int argc, Scheme_Object *argv[]) @@ -393,6 +401,18 @@ static Scheme_Object *foreign_ffi_obj(int argc, Scheme_Object *argv[]) } # else /* WINDOWS_DYNAMIC_LOAD undefined */ dlobj = dlsym(lib->handle, dlname); +# ifdef __ANDROID__ + if (dlobj && (lib->handle == RTLD_DEFAULT)) { + /* Compensate for a bug in dlsym() that gets the address wrong by + an offset (incorrect use of `link_bias'?): */ + if (!adjustment_set) { + adjustment = ((uintptr_t)scheme_start_atomic_no_break + - (uintptr_t)dlsym(RTLD_DEFAULT, "scheme_start_atomic_no_break")); + adjustment_set = 1; + } + dlobj = (char *)dlobj XFORM_OK_PLUS adjustment; + } +# endif /* __ANDROID__ */ if (!dlobj && lib->is_global) { /* Try every handle in the table of opened libraries. */ int i; diff --git a/src/foreign/foreign.rktc b/src/foreign/foreign.rktc index 1ba089c1e2..d62f5aa383 100755 --- a/src/foreign/foreign.rktc +++ b/src/foreign/foreign.rktc @@ -227,6 +227,7 @@ THREAD_LOCAL_DECL(static Scheme_Hash_Table *opened_libs); } else handle = LoadLibraryW(WIDE_PATH(name)); }{ + @@IFDEF{__ANDROID__}{if (!name) handle = RTLD_DEFAULT; else} handle = dlopen(name, RTLD_NOW | (as_global ? RTLD_GLOBAL : RTLD_LOCAL)); } if (handle == NULL && !null_ok) { @@ -267,6 +268,11 @@ THREAD_LOCAL_DECL(static Scheme_Hash_Table *opened_libs); [name "char*"] [lib "NON_GCBALE_PTR(ffi_lib_struct)"]] +@@IFDEF{__ANDROID__}{ +static int adjustment_set; +static uintptr_t adjustment; +} + /* (ffi-obj objname ffi-lib-or-libname) -> ffi-obj */ @cdefine[ffi-obj 2]{ ffi_obj_struct *obj; @@ -323,6 +329,18 @@ THREAD_LOCAL_DECL(static Scheme_Hash_Table *opened_libs); } }{ dlobj = dlsym(lib->handle, dlname); + @@IFDEF{__ANDROID__}{ + if (dlobj && (lib->handle == RTLD_DEFAULT)) { + /* Compensate for a bug in dlsym() that gets the address wrong by + an offset (incorrect use of `link_bias'?): */ + if (!adjustment_set) { + adjustment = ((uintptr_t)scheme_start_atomic_no_break + - (uintptr_t)dlsym(RTLD_DEFAULT, "scheme_start_atomic_no_break")); + adjustment_set = 1; + } + dlobj = (char *)dlobj XFORM_OK_PLUS adjustment; + } + } if (!dlobj && lib->is_global) { /* Try every handle in the table of opened libraries. */ int i;