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