Fixes dynamic symbol loading bug on Mac OS X.

On OS X, when you call dlopen() on a null library, and then call dlsym(),
the most recently loaded symbols are always used, no matter what flags
we seem to pass to dlopen().  The solution is to explicitly find the name
of the running executable, and open that as a library.
This commit is contained in:
Eric Scharff 2008-01-28 16:17:22 -07:00
parent d68c2e6e2c
commit c1f3d28d24
3 changed files with 34 additions and 1 deletions

View File

@ -82,7 +82,7 @@ endif
ifeq ($(platform),darwin)
build-cflags = $(common-cflags) -fPIC -fvisibility=hidden \
-I$(JAVA_HOME)/include/linux -I$(src)
lflags = $(common-lflags) -ldl
lflags = $(common-lflags) -ldl -framework CoreFoundation
strip-all = -S -x
binaryToMacho = $(native-build)/binaryToMacho
endif

View File

@ -1,3 +1,6 @@
#ifdef __APPLE__
#include "CoreFoundation/CoreFoundation.h"
#endif
#include "sys/mman.h"
#include "sys/types.h"
#include "sys/stat.h"
@ -116,6 +119,27 @@ allocate(System* s, unsigned size)
return p;
}
void
pathOfExecutable(System* s, const char** retBuf, unsigned* size)
{
#ifdef __APPLE__
CFBundleRef bundle = CFBundleGetMainBundle();
CFURLRef url = CFBundleCopyExecutableURL(bundle);
CFStringRef path = CFURLCopyPath(url);
CFIndex pathSize = CFStringGetMaximumSizeOfFileSystemRepresentation(path);
char* buffer = reinterpret_cast<char*>(allocate(s, pathSize));
if (CFStringGetFileSystemRepresentation(path, buffer, pathSize)) {
*size = pathSize;
*retBuf = buffer;
} else {
abort();
}
#else
*size = 0;
*retBuf = NULL;
#endif
}
const bool Verbose = false;
const unsigned Waiting = 1 << 0;
@ -646,6 +670,7 @@ class MySystem: public System {
bool mapName)
{
void* p;
bool alreadyAllocated = false;
unsigned nameLength = (name ? strlen(name) : 0);
if (mapName) {
unsigned size = nameLength + 3 + sizeof(SO_SUFFIX);
@ -653,6 +678,10 @@ class MySystem: public System {
snprintf(buffer, size, "lib%s" SO_SUFFIX, name);
p = dlopen(buffer, RTLD_LAZY);
} else {
if (!name) {
pathOfExecutable(this, &name, &nameLength);
alreadyAllocated = true;
}
p = dlopen(name, RTLD_LAZY);
}
@ -665,6 +694,9 @@ class MySystem: public System {
if (name) {
n = static_cast<char*>(allocate(this, nameLength + 1));
memcpy(n, name, nameLength + 1);
if (alreadyAllocated) {
free(name, nameLength, false);
}
} else {
n = 0;
}

View File

@ -134,6 +134,7 @@ expect(System* s, bool v)
#ifdef NDEBUG
# undef assert
# define assert(a, b)
#else // not NDEBUG