libhugetlbfs redefines shmget() so that it can transparently optionally add the hugepage flag. Unfortunately, it uses dlsym() to to find the next shmget() to call in the dynamic library call chain. This does not work on statically-linked executables.
Work around this by making all references to libdl weak, and testing for its presence. If libdl symbols are not not present, directly make the shmget syscall. Making the dl* symbols weak does not affect dynamic executables as libdl.so is: * Automatically added to the library dependency list when liked with -lhugetlbfs * Mapped into the programs address space when used with LD_PRELOAD. Based on a patch originally authored by Dean Luick <lu...@cray.com>. Signed-off-by: Andrew Hastings <a...@cray.com> on behalf of Cray Inc. --- -Andrew Hastings Cray Inc. diff -ruNp libhugetlbfs-2.11/shm.c libhugetlbfs-2.11-shm/shm.c --- libhugetlbfs-2.11/shm.c 2010-12-16 11:38:22.000000000 -0600 +++ libhugetlbfs-2.11-shm/shm.c 2010-12-28 17:26:00.725063000 -0600 @@ -29,6 +29,37 @@ #include "libhugetlbfs_internal.h" #include "hugetlbfs.h" +#if defined(__x86_64) +/* + * The calls to dlsym() and dlerror() in the shmget() wrapper below force + * a dependency on libdl.so. This does not work for static executables + * as the glibc dynamic library implementation does not automatically + * have static dl* function stubs linked into static executables. + * + * Work around this problem by adding a weak attribute to the declarations + * of dlsym() and dlerror(). (The declaration is otherwise the same as in + * <dlfcn.h>). This allows a static executable to be linked without -ldl. + * If &dlsym is NULL then this is a static executable and a call to the + * system shmget() may be performed without worry as there is no dynamic + * call chain. + * + * Although this problem appears to be platform-independent, the solution + * unfortunately depends on the platform, thus the __x86_64 ifdef. + */ +#include <sys/syscall.h> /* for SYS_xxx definitions */ + +extern void *dlsym (void *__restrict __handle, __const char *__restrict __name) + __attribute__((weak)) __THROW __nonnull ((2)); +extern char *dlerror (void) __attribute__((weak)) __THROW; + + +/* call syscall shmget through the generic syscall mechanism */ +static int syscall_shmget(key_t key, size_t size, int shmflg) +{ + return syscall(SYS_shmget, key, size, shmflg); +} +#endif /* __x86_64 */ + int shmget(key_t key, size_t size, int shmflg) { static int (*real_shmget)(key_t key, size_t size, int shmflg) = NULL; @@ -40,10 +71,18 @@ int shmget(key_t key, size_t size, int s /* Get a handle to the "real" shmget system call */ if (!real_shmget) { - real_shmget = dlsym(RTLD_NEXT, "shmget"); - if ((error = dlerror()) != NULL) { - ERROR("%s", error); - return -1; +#if defined(__x86_64) + if (&dlsym == NULL) { + /* in a static executable, call shmget directly */ + real_shmget = syscall_shmget; + } else +#endif /* __x86_64 */ + { + real_shmget = dlsym(RTLD_NEXT, "shmget"); + if ((error = dlerror()) != NULL) { + ERROR("%s", error); + return -1; + } } } ------------------------------------------------------------------------------ Learn how Oracle Real Application Clusters (RAC) One Node allows customers to consolidate database storage, standardize their database environment, and, should the need arise, upgrade to a full multi-node Oracle RAC database without downtime or disruption http://p.sf.net/sfu/oracle-sfdevnl _______________________________________________ Libhugetlbfs-devel mailing list Libhugetlbfs-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/libhugetlbfs-devel