summaryrefslogtreecommitdiffstats
path: root/libexec/rtld-aout
diff options
context:
space:
mode:
authorjdp <jdp@FreeBSD.org>1997-01-12 00:16:36 +0000
committerjdp <jdp@FreeBSD.org>1997-01-12 00:16:36 +0000
commit04703241efd557f902b72d1c73a134c4e7814ded (patch)
tree34aa5ccaf594b7246a06e04aea990ffec43ee04c /libexec/rtld-aout
parentcda6305fe1bcf75b59acded6a6ad6e4eeec98f64 (diff)
downloadFreeBSD-src-04703241efd557f902b72d1c73a134c4e7814ded.zip
FreeBSD-src-04703241efd557f902b72d1c73a134c4e7814ded.tar.gz
Add support for the LD_BIND_NOW environment variable. If it is set to a
nonempty string, then function calls are relocated at program start-up rather than lazily. This variable is standard on Sun and SVR4 systems. The dlopen() function now supports both lazy and immediate binding, as determined by its "mode" argument, which can be either 1 (RTLD_LAZY) or 2 (RTLD_NOW). I will add defines of these symbols to <dlfcn.h> as soon as I've done a little more checking to make sure they won't cause collisions or bootstrapping problems that would break "make world". The "LD_*" environment variables which alter dynamic linker behavior are now treated as unset if they are set to the empty string. This agrees with the standard SVR4 conventions for the dynamic linker. Add a work-around for programs compiled with certain buggy versions of crt0.o. The buggy versions failed to set the "crt_ldso" member of the interface structure. This caused certain error messages from the dynamic linker to begin with "(null)" instead of the pathname of the dynamic linker.
Diffstat (limited to 'libexec/rtld-aout')
-rw-r--r--libexec/rtld-aout/rtld.124
-rw-r--r--libexec/rtld-aout/rtld.1aout24
-rw-r--r--libexec/rtld-aout/rtld.c53
3 files changed, 71 insertions, 30 deletions
diff --git a/libexec/rtld-aout/rtld.1 b/libexec/rtld-aout/rtld.1
index 699738c..2f0cb5a 100644
--- a/libexec/rtld-aout/rtld.1
+++ b/libexec/rtld-aout/rtld.1
@@ -1,4 +1,4 @@
-.\" $Id: rtld.1,v 1.6 1996/10/18 04:49:43 jdp Exp $
+.\" $Id: rtld.1,v 1.7 1996/12/26 21:51:09 swallace Exp $
.\"
.\" Copyright (c) 1995 Paul Kranenburg
.\" All rights reserved.
@@ -117,15 +117,25 @@ other shared libraries. If the directory is not specified then
the directories specified by LD_LIBRARY_PATH will be searched first
followed by the set of built-in standard directories.
This is ignored for set-user-ID and set-group-ID programs.
+.It Ev LD_BIND_NOW
+When set to a nonempty string, causes
+.Nm
+to relocate all external function calls before starting execution of the
+program. Normally, function calls are bound lazily, at the first call
+of each function.
+.Ev LD_BIND_NOW
+increases the start-up time of a program, but it avoids run-time
+surprises caused by unexpectedly undefined functions.
.It Ev LD_WARN_NON_PURE_CODE
-When set, issue a warning whenever a link-editing operation requires
-modification of the text segment of some loaded object. This is usually
-indicative of an incorrectly built library.
+When set to a nonempty string, issue a warning whenever a link-editing
+operation requires modification of the text segment of some loaded
+object. This is usually indicative of an incorrectly built library.
.It Ev LD_SUPPRESS_WARNINGS
-When set, no warning messages of any kind are issued. Normally, a warning
-is given if satisfactorily versioned library could not be found.
+When set to a nonempty string, no warning messages of any kind are
+issued. Normally, a warning is given if satisfactorily versioned
+library could not be found.
.It Ev LD_TRACE_LOADED_OBJECTS
-When set, causes
+When set to a nonempty string, causes
.Nm
to exit after loading the shared objects and printing a summary which includes
the absolute pathnames of all objects, to standard output.
diff --git a/libexec/rtld-aout/rtld.1aout b/libexec/rtld-aout/rtld.1aout
index 699738c..2f0cb5a 100644
--- a/libexec/rtld-aout/rtld.1aout
+++ b/libexec/rtld-aout/rtld.1aout
@@ -1,4 +1,4 @@
-.\" $Id: rtld.1,v 1.6 1996/10/18 04:49:43 jdp Exp $
+.\" $Id: rtld.1,v 1.7 1996/12/26 21:51:09 swallace Exp $
.\"
.\" Copyright (c) 1995 Paul Kranenburg
.\" All rights reserved.
@@ -117,15 +117,25 @@ other shared libraries. If the directory is not specified then
the directories specified by LD_LIBRARY_PATH will be searched first
followed by the set of built-in standard directories.
This is ignored for set-user-ID and set-group-ID programs.
+.It Ev LD_BIND_NOW
+When set to a nonempty string, causes
+.Nm
+to relocate all external function calls before starting execution of the
+program. Normally, function calls are bound lazily, at the first call
+of each function.
+.Ev LD_BIND_NOW
+increases the start-up time of a program, but it avoids run-time
+surprises caused by unexpectedly undefined functions.
.It Ev LD_WARN_NON_PURE_CODE
-When set, issue a warning whenever a link-editing operation requires
-modification of the text segment of some loaded object. This is usually
-indicative of an incorrectly built library.
+When set to a nonempty string, issue a warning whenever a link-editing
+operation requires modification of the text segment of some loaded
+object. This is usually indicative of an incorrectly built library.
.It Ev LD_SUPPRESS_WARNINGS
-When set, no warning messages of any kind are issued. Normally, a warning
-is given if satisfactorily versioned library could not be found.
+When set to a nonempty string, no warning messages of any kind are
+issued. Normally, a warning is given if satisfactorily versioned
+library could not be found.
.It Ev LD_TRACE_LOADED_OBJECTS
-When set, causes
+When set to a nonempty string, causes
.Nm
to exit after loading the shared objects and printing a summary which includes
the absolute pathnames of all objects, to standard output.
diff --git a/libexec/rtld-aout/rtld.c b/libexec/rtld-aout/rtld.c
index 9353721..88e5b27 100644
--- a/libexec/rtld-aout/rtld.c
+++ b/libexec/rtld-aout/rtld.c
@@ -27,7 +27,7 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
- * $Id: rtld.c,v 1.39 1996/10/10 23:16:50 jdp Exp $
+ * $Id: rtld.c,v 1.40 1996/10/24 16:24:19 jdp Exp $
*/
#include <sys/param.h>
@@ -186,6 +186,7 @@ static gid_t gid, egid;
static int careful;
static int anon_fd = -1;
+static char *ld_bind_now;
static char *ld_library_path;
static char *ld_preload;
static char *ld_tracing;
@@ -212,7 +213,7 @@ static struct so_map *map_object __P(( char *,
struct so_map *));
static int map_preload __P((void));
static int map_sods __P((struct so_map *));
-static int reloc_and_init __P((struct so_map *));
+static int reloc_and_init __P((struct so_map *, int));
static void unmap_object __P((struct so_map *, int));
static struct so_map *alloc_link_map __P(( char *, struct sod *,
struct so_map *, caddr_t,
@@ -221,7 +222,7 @@ static void free_link_map __P((struct so_map *));
static inline int check_text_reloc __P(( struct relocation_info *,
struct so_map *,
caddr_t));
-static int reloc_map __P((struct so_map *));
+static int reloc_map __P((struct so_map *, int));
static void reloc_copy __P((struct so_map *));
static void init_object __P((struct so_map *));
static void init_sods __P((struct so_list *));
@@ -305,6 +306,10 @@ struct _dynamic *dp;
if (version >= CRT_VERSION_BSD_3)
main_progname = crtp->crt_prog;
+ /* Some buggy versions of crt0.o have crt_ldso filled in as NULL. */
+ if (__progname == NULL)
+ __progname = us;
+
/* Fill in some fields in _DYNAMIC or crt structure */
if (version >= CRT_VERSION_BSD_4)
crtp->crt_ldentry = &ld_entry; /* crt */
@@ -356,7 +361,7 @@ struct _dynamic *dp;
/* Map in LD_PRELOADs before the main program's shared objects so we
can intercept those calls */
- if (ld_preload != NULL && *ld_preload != '\0') {
+ if (ld_preload != NULL) {
if(map_preload() == -1) /* Failed */
die();
}
@@ -373,7 +378,7 @@ struct _dynamic *dp;
crtp->crt_dp->d_un.d_sdt->sdt_loaded = link_map_head->som_next;
/* Relocate and initialize all mapped objects */
- if(reloc_and_init(main_map) == -1) /* Failed */
+ if(reloc_and_init(main_map, ld_bind_now != NULL) == -1) /* Failed */
die();
ddp = crtp->crt_dp->d_debug;
@@ -903,8 +908,9 @@ map_sods(parent)
* an error message can be retrieved via dlerror().
*/
static int
-reloc_and_init(root)
+reloc_and_init(root, bind_now)
struct so_map *root;
+ int bind_now;
{
struct so_map *smp;
@@ -925,7 +931,7 @@ reloc_and_init(root)
*/
for(smp = root; smp != NULL; smp = smp->som_next) {
if(!(LM_PRIVATE(smp)->spd_flags & RTLD_RTLD)) {
- if(reloc_map(smp) < 0)
+ if(reloc_map(smp, bind_now) < 0)
return -1;
}
}
@@ -1066,8 +1072,9 @@ caddr_t addr;
}
static int
-reloc_map(smp)
+reloc_map(smp, bind_now)
struct so_map *smp;
+ int bind_now;
{
/*
* Caching structure for reducing the number of calls to
@@ -1140,7 +1147,7 @@ reloc_map(smp)
struct nzlist *p, *np;
long relocation;
- if (RELOC_LAZY_P(r))
+ if (RELOC_JMPTAB_P(r) && !bind_now)
continue;
p = (struct nzlist *)
@@ -1159,7 +1166,7 @@ reloc_map(smp)
if(np != NULL) /* Symbol already cached */
src_map = symcache[RELOC_SYMBOL(r)].src_map;
else { /* Symbol not cached yet */
- np = lookup(sym, &src_map, 0/*XXX-jumpslots!*/);
+ np = lookup(sym, &src_map, RELOC_JMPTAB_P(r));
/*
* Record the needed information about
* the symbol in the caching vector,
@@ -1184,11 +1191,17 @@ reloc_map(smp)
* Otherwise it's a run-time allocated common
* whose value is already up-to-date.
*/
- relocation = md_get_addend(r, addr);
- relocation += np->nz_value;
+ relocation = np->nz_value;
if (src_map)
relocation += (long)src_map->som_addr;
+ if (RELOC_JMPTAB_P(r)) {
+ md_bind_jmpslot(relocation, addr);
+ continue;
+ }
+
+ relocation += md_get_addend(r, addr);
+
if (RELOC_PCREL_P(r))
relocation -= (long)smp->som_addr;
@@ -1200,8 +1213,8 @@ reloc_map(smp)
np->nz_size, src_map);
continue;
}
- md_relocate(r, relocation, addr, 0);
+ md_relocate(r, relocation, addr, 0);
} else {
md_relocate(r,
#ifdef SUN_COMPAT
@@ -1817,6 +1830,9 @@ __dlopen(path, mode)
{
struct so_map *old_tail = link_map_tail;
struct so_map *smp;
+ int bind_now = mode == 2;
+ /* XXX - s/2/RTLD_NOW/ in the above line, after putting the necessary
+ defines into <dlfcn.h> and testing for problems. */
/*
* path == NULL is handled by map_object()
@@ -1832,7 +1848,7 @@ __dlopen(path, mode)
/* Relocate and initialize all newly-mapped objects */
if(link_map_tail != old_tail) { /* We have mapped some new objects */
- if(reloc_and_init(smp) == -1) /* Failed */
+ if(reloc_and_init(smp, bind_now) == -1) /* Failed */
return NULL;
}
@@ -1989,6 +2005,9 @@ char *fmt;
* except that the environment is scanned once only to pick up all
* known variables, rather than scanned multiple times for each
* variable.
+ *
+ * If an environment variable of interest is set to the empty string, we
+ * treat it as if it were unset.
*/
#define L(n, u, v) { n, sizeof(n) - 1, u, v },
@@ -2001,13 +2020,14 @@ struct env_scan_tab {
L("LD_LIBRARY_PATH=", 1, &ld_library_path)
L("LD_PRELOAD=", 1, &ld_preload)
L("LD_TRACE_LOADED_OBJECTS=", 0, &ld_tracing)
+ L("LD_BIND_NOW=", 0, &ld_bind_now)
L("LD_SUPPRESS_WARNINGS=", 0, &ld_suppress_warnings)
L("LD_WARN_NON_PURE_CODE=", 0, &ld_warn_non_pure_code)
{ NULL, 0, NULL }
};
#undef L
-void
+static void
rt_readenv()
{
char **p = environ;
@@ -2025,7 +2045,8 @@ rt_readenv()
if (careful && t->unsafe)
continue; /* skip for set[ug]id */
if (strncmp(t->name, v, t->len) == 0) {
- *t->value = v + t->len;
+ if (*(v + t->len) != '\0') /* Not empty */
+ *t->value = v + t->len;
break;
}
}
OpenPOWER on IntegriCloud