Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/libexec/ld.elf_so Implement negative cache checks for symbol...
details: https://anonhg.NetBSD.org/src/rev/9ea7163c6de6
branches: trunk
changeset: 752476:9ea7163c6de6
user: roy <roy%NetBSD.org@localhost>
date: Sat Feb 27 11:16:38 2010 +0000
description:
Implement negative cache checks for symbol lookups.
Uses the Donelist idea from FreeBSD.
diffstat:
libexec/ld.elf_so/load.c | 5 ++-
libexec/ld.elf_so/rtld.c | 27 ++++++++++++++++++----
libexec/ld.elf_so/rtld.h | 25 ++++++++++++++++++--
libexec/ld.elf_so/symbol.c | 56 ++++++++++++++++++++++++++++++++++++---------
4 files changed, 92 insertions(+), 21 deletions(-)
diffs (truncated from 337 to 300 lines):
diff -r 244098980fe7 -r 9ea7163c6de6 libexec/ld.elf_so/load.c
--- a/libexec/ld.elf_so/load.c Sat Feb 27 10:49:58 2010 +0000
+++ b/libexec/ld.elf_so/load.c Sat Feb 27 11:16:38 2010 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: load.c,v 1.36 2009/05/19 20:44:52 christos Exp $ */
+/* $NetBSD: load.c,v 1.37 2010/02/27 11:16:38 roy Exp $ */
/*
* Copyright 1996 John D. Polstra.
@@ -40,7 +40,7 @@
#include <sys/cdefs.h>
#ifndef lint
-__RCSID("$NetBSD: load.c,v 1.36 2009/05/19 20:44:52 christos Exp $");
+__RCSID("$NetBSD: load.c,v 1.37 2010/02/27 11:16:38 roy Exp $");
#endif /* not lint */
#include <err.h>
@@ -155,6 +155,7 @@
*_rtld_objtail = obj;
_rtld_objtail = &obj->next;
+ _rtld_objcount++;
#ifdef RTLD_LOADER
_rtld_linkmap_add(obj); /* for GDB */
#endif
diff -r 244098980fe7 -r 9ea7163c6de6 libexec/ld.elf_so/rtld.c
--- a/libexec/ld.elf_so/rtld.c Sat Feb 27 10:49:58 2010 +0000
+++ b/libexec/ld.elf_so/rtld.c Sat Feb 27 11:16:38 2010 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: rtld.c,v 1.128 2010/01/10 06:37:32 skrll Exp $ */
+/* $NetBSD: rtld.c,v 1.129 2010/02/27 11:16:38 roy Exp $ */
/*
* Copyright 1996 John D. Polstra.
@@ -40,7 +40,7 @@
#include <sys/cdefs.h>
#ifndef lint
-__RCSID("$NetBSD: rtld.c,v 1.128 2010/01/10 06:37:32 skrll Exp $");
+__RCSID("$NetBSD: rtld.c,v 1.129 2010/02/27 11:16:38 roy Exp $");
#endif /* not lint */
#include <err.h>
@@ -83,6 +83,7 @@
bool _rtld_trust; /* False for setuid and setgid programs */
Obj_Entry *_rtld_objlist; /* Head of linked list of shared objects */
Obj_Entry **_rtld_objtail; /* Link field of last object in list */
+int _rtld_objcount; /* Number of shared objects */
Obj_Entry *_rtld_objmain; /* The main program shared object */
Obj_Entry _rtld_objself; /* The dynamic linker shared object */
const char _rtld_path[] = _PATH_RTLD;
@@ -271,6 +272,7 @@
/* Make the object list empty again. */
_rtld_objlist = NULL;
_rtld_objtail = &_rtld_objlist;
+ _rtld_objcount = 0;
_rtld_debug.r_brk = _rtld_debug_state;
_rtld_debug.r_state = RT_CONSISTENT;
@@ -705,6 +707,7 @@
_rtld_objlist_remove(&_rtld_list_global, obj);
_rtld_linkmap_delete(obj);
*linkp = obj->next;
+ _rtld_objcount--;
_rtld_obj_free(obj);
} else
linkp = &obj->next;
@@ -810,11 +813,16 @@
unsigned long hash;
const Elf_Sym *def;
const Obj_Entry *obj;
+ DoneList donelist;
hash = _rtld_elf_hash(name);
obj = _rtld_objmain;
+ _rtld_donelist_init(&donelist);
- def = _rtld_symlook_list(name, hash, &_rtld_list_main, &obj, false);
+ def = _rtld_symlook_list(name, hash, &_rtld_list_main, &obj, false,
+ &donelist);
+
+ _rtld_donelist_clear(&donelist);
if (def != NULL)
return obj->relocbase + def->st_value;
@@ -838,6 +846,7 @@
const Elf_Sym *def;
const Obj_Entry *defobj;
void *retaddr;
+ DoneList donelist;
hash = _rtld_elf_hash(name);
def = NULL;
@@ -892,20 +901,28 @@
if ((obj = _rtld_dlcheck(handle)) == NULL)
return NULL;
+ _rtld_donelist_init(&donelist);
+
if (obj->mainprog) {
/* Search main program and all libraries loaded by it */
def = _rtld_symlook_list(name, hash, &_rtld_list_main,
- &defobj, false);
+ &defobj, false, &donelist);
} else {
Needed_Entry fake;
+ DoneList depth;
/* Search the object and all the libraries loaded by it. */
fake.next = NULL;
fake.obj = __UNCONST(obj);
fake.name = 0;
+
+ _rtld_donelist_init(&depth);
def = _rtld_symlook_needed(name, hash, &fake, &defobj,
- false);
+ false, &donelist, &depth);
+ _rtld_donelist_clear(&depth);
}
+
+ _rtld_donelist_clear(&donelist);
break;
}
diff -r 244098980fe7 -r 9ea7163c6de6 libexec/ld.elf_so/rtld.h
--- a/libexec/ld.elf_so/rtld.h Sat Feb 27 10:49:58 2010 +0000
+++ b/libexec/ld.elf_so/rtld.h Sat Feb 27 11:16:38 2010 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: rtld.h,v 1.88 2010/01/17 08:04:20 skrll Exp $ */
+/* $NetBSD: rtld.h,v 1.89 2010/02/27 11:16:38 roy Exp $ */
/*
* Copyright 1996 John D. Polstra.
@@ -59,6 +59,16 @@
#define NEW(type) ((type *) xmalloc(sizeof(type)))
#define CNEW(type) ((type *) xcalloc(sizeof(type)))
+/*
+ * Fill in a DoneList with an allocation large enough to hold all of
+ * the currently-loaded objects.
+ */
+#define _rtld_donelist_init(dlp) \
+ ((dlp)->objs = xmalloc(_rtld_objcount * sizeof((dlp)->objs[0])), \
+ (dlp)->num_alloc = _rtld_objcount, \
+ (dlp)->num_used = 0)
+#define _rtld_donelist_clear(dlp) xfree((dlp)->objs)
+
#endif /* _RTLD_SOURCE */
/*
@@ -198,12 +208,20 @@
void *ehdr;
} Obj_Entry;
+typedef struct Struct_DoneList {
+ const Obj_Entry **objs; /* Array of object pointers */
+ unsigned int num_alloc; /* Allocated size of the array */
+ unsigned int num_used; /* Number of array slots used */
+} DoneList;
+
+
#if defined(_RTLD_SOURCE)
extern struct r_debug _rtld_debug;
extern Search_Path *_rtld_default_paths;
extern Obj_Entry *_rtld_objlist;
extern Obj_Entry **_rtld_objtail;
+extern int _rtld_objcount;
extern Obj_Entry *_rtld_objmain;
extern Obj_Entry _rtld_objself;
extern Search_Path *_rtld_paths;
@@ -276,11 +294,12 @@
const Obj_Entry **, bool);
const Elf_Sym *_rtld_symlook_list(const char *, unsigned long,
- const Objlist *, const Obj_Entry **, bool);
+ const Objlist *, const Obj_Entry **, bool, DoneList *);
const Elf_Sym *_rtld_symlook_default(const char *, unsigned long,
const Obj_Entry *, const Obj_Entry **, bool);
const Elf_Sym *_rtld_symlook_needed(const char *, unsigned long,
- const Needed_Entry *, const Obj_Entry **, bool);
+ const Needed_Entry *, const Obj_Entry **, bool,
+ DoneList *, DoneList *);
#ifdef COMBRELOC
void _rtld_combreloc_reset(const Obj_Entry *);
#endif
diff -r 244098980fe7 -r 9ea7163c6de6 libexec/ld.elf_so/symbol.c
--- a/libexec/ld.elf_so/symbol.c Sat Feb 27 10:49:58 2010 +0000
+++ b/libexec/ld.elf_so/symbol.c Sat Feb 27 11:16:38 2010 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: symbol.c,v 1.50 2010/01/13 20:17:21 christos Exp $ */
+/* $NetBSD: symbol.c,v 1.51 2010/02/27 11:16:38 roy Exp $ */
/*
* Copyright 1996 John D. Polstra.
@@ -40,7 +40,7 @@
#include <sys/cdefs.h>
#ifndef lint
-__RCSID("$NetBSD: symbol.c,v 1.50 2010/01/13 20:17:21 christos Exp $");
+__RCSID("$NetBSD: symbol.c,v 1.51 2010/02/27 11:16:38 roy Exp $");
#endif /* not lint */
#include <err.h>
@@ -60,6 +60,27 @@
typedef void (*fptr_t)(void);
+/*
+ * If the given object is already in the donelist, return true. Otherwise
+ * add the object to the list and return false.
+ */
+static bool
+_rtld_donelist_check(DoneList *dlp, const Obj_Entry *obj)
+{
+ unsigned int i;
+
+ for (i = 0; i < dlp->num_used; i++)
+ if (dlp->objs[i] == obj)
+ return true;
+ /*
+ * Our donelist allocation may not always be sufficient as we're not
+ * thread safe. We'll handle it properly anyway.
+ */
+ if (dlp->num_used < dlp->num_alloc)
+ dlp->objs[dlp->num_used++] = obj;
+ return false;
+}
+
static bool
_rtld_is_exported(const Elf_Sym *def)
{
@@ -108,7 +129,7 @@
const Elf_Sym *
_rtld_symlook_list(const char *name, unsigned long hash, const Objlist *objlist,
- const Obj_Entry **defobj_out, bool in_plt)
+ const Obj_Entry **defobj_out, bool in_plt, DoneList *dlp)
{
const Elf_Sym *symp;
const Elf_Sym *def;
@@ -118,6 +139,8 @@
def = NULL;
defobj = NULL;
SIMPLEQ_FOREACH(elm, objlist, link) {
+ if (_rtld_donelist_check(dlp, elm->obj))
+ continue;
rdbg(("search object %p (%s) for %s", elm->obj, elm->obj->path,
name));
if ((symp = _rtld_symlook_obj(name, hash, elm->obj, in_plt))
@@ -143,7 +166,8 @@
*/
const Elf_Sym *
_rtld_symlook_needed(const char *name, unsigned long hash,
- const Needed_Entry *needed, const Obj_Entry **defobj_out, bool inplt)
+ const Needed_Entry *needed, const Obj_Entry **defobj_out, bool inplt,
+ DoneList *breadth, DoneList *depth)
{
const Elf_Sym *def, *def_w;
const Needed_Entry *n;
@@ -152,8 +176,11 @@
def = def_w = NULL;
defobj = NULL;
for (n = needed; n != NULL; n = n->next) {
- if ((obj = n->obj) == NULL ||
- (def = _rtld_symlook_obj(name, hash, obj, inplt)) == NULL)
+ if ((obj = n->obj) == NULL)
+ continue;
+ if (_rtld_donelist_check(breadth, obj))
+ continue;
+ if ((def = _rtld_symlook_obj(name, hash, obj, inplt)) == NULL)
continue;
defobj = obj;
if (ELF_ST_BIND(def->st_info) != STB_WEAK) {
@@ -169,8 +196,10 @@
for (n = needed; n != NULL; n = n->next) {
if ((obj = n->obj) == NULL)
continue;
+ if (_rtld_donelist_check(depth, obj))
+ continue;
def_w = _rtld_symlook_needed(name, hash, obj->needed, &defobj1,
- inplt);
+ inplt, breadth, depth);
if (def_w == NULL)
continue;
if (def == NULL || ELF_ST_BIND(def_w->st_info) != STB_WEAK) {
@@ -381,9 +410,12 @@
const Objlist_Entry *elm;
def = NULL;
defobj = NULL;
+ DoneList donelist;
+
+ _rtld_donelist_init(&donelist);
/* Look first in the referencing object if linked symbolically. */
- if (refobj->symbolic) {
+ if (refobj->symbolic && !_rtld_donelist_check(&donelist, refobj)) {
rdbg(("search referencing object for %s", name));
symp = _rtld_symlook_obj(name, hash, refobj, in_plt);
Home |
Main Index |
Thread Index |
Old Index