add support for RTLD_NOLOAD to dlopen
authorRich Felker <dalias@aerifal.cx>
Thu, 24 Jan 2013 03:07:45 +0000 (22:07 -0500)
committerRich Felker <dalias@aerifal.cx>
Thu, 24 Jan 2013 03:07:45 +0000 (22:07 -0500)
based on patch by Pierre Carrier <pierre@gcarrier.fr> that just added
the flag constant, but with minimal additional code so that it
actually works as documented. this is a nonstandard option but some
major software (reportedly, Firefox) uses it and it was easy to add
anyway.

include/dlfcn.h
src/ldso/dynlink.c

index 46c4e18..5b57e8a 100644 (file)
@@ -9,6 +9,7 @@ extern "C" {
 
 #define RTLD_LAZY   1
 #define RTLD_NOW    2
 
 #define RTLD_LAZY   1
 #define RTLD_NOW    2
+#define RTLD_NOLOAD 4
 #define RTLD_GLOBAL 256
 #define RTLD_LOCAL  0
 
 #define RTLD_GLOBAL 256
 #define RTLD_LOCAL  0
 
index e73806c..b1a4409 100644 (file)
@@ -99,6 +99,7 @@ static int ssp_used;
 static int runtime;
 static int ldd_mode;
 static int ldso_fail;
 static int runtime;
 static int ldd_mode;
 static int ldso_fail;
+static int noload;
 static jmp_buf rtld_fail;
 static pthread_rwlock_t lock;
 static struct debug debug;
 static jmp_buf rtld_fail;
 static pthread_rwlock_t lock;
 static struct debug debug;
@@ -508,7 +509,7 @@ static struct dso *load_library(const char *name)
                        return p;
                }
        }
                        return p;
                }
        }
-       map = map_library(fd, &temp_dso);
+       map = noload ? 0 : map_library(fd, &temp_dso);
        close(fd);
        if (!map) return 0;
 
        close(fd);
        if (!map) return 0;
 
@@ -1027,6 +1028,7 @@ void *dlopen(const char *file, int mode)
        orig_tls_offset = tls_offset;
        orig_tls_align = tls_align;
        orig_tail = tail;
        orig_tls_offset = tls_offset;
        orig_tls_align = tls_align;
        orig_tail = tail;
+       noload = mode & RTLD_NOLOAD;
 
        if (setjmp(rtld_fail)) {
                /* Clean up anything new that was (partially) loaded */
 
        if (setjmp(rtld_fail)) {
                /* Clean up anything new that was (partially) loaded */
@@ -1050,8 +1052,10 @@ void *dlopen(const char *file, int mode)
        } else p = load_library(file);
 
        if (!p) {
        } else p = load_library(file);
 
        if (!p) {
-               snprintf(errbuf, sizeof errbuf,
-                       "Error loading shared library %s: %m", file);
+               snprintf(errbuf, sizeof errbuf, noload ?
+                       "Library %s is not already loaded" :
+                       "Error loading shared library %s: %m",
+                       file);
                errflag = 1;
                goto end;
        }
                errflag = 1;
                goto end;
        }