Subject: SymCache optimization (was Re: New ld.elf_so from FreeBSD)
To: Jaromir Dolecek <jdolecek@netbsd.org>
From: Bang Jun-Young <junyoung@mogua.com>
List: tech-toolchain
Date: 09/06/2002 03:51:15
--/04w6evG8XlLl3ft
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
On Thu, Sep 05, 2002 at 07:45:37PM +0900, Bang Jun-Young wrote:
> The problem is that FreeBSD rtld code is now quite different from our
> ld.elf_so, although they were very similar long time ago. To reduce
> pain of modifying it so that it has support for other platforms not
> in the FreeBSD rtld, I'd like to propose to import only necessary
> features into our ld.elf_so, not rtld itself. I think I can do at
> least "SymCache" C++ optimization part myself until the end of this
> week.
I'm attaching a patch that makes use of SymCache for our ld.elf_so.
With a new ld.elf_so, I got tons of "found!" messages on the screen
while loading mozilla (LD_DEBUG=1).
Note that it's still only for i386. However, it wouldn't be difficult
to make it work on other platforms.
Any comments?
Jun-Young
--
Bang Jun-Young <junyoung@mogua.com>
--/04w6evG8XlLl3ft
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="symcache.patch"
Index: reloc.c
===================================================================
RCS file: /usr/local/cvs/prebind/src/libexec/ld.elf_so/reloc.c,v
retrieving revision 1.4
diff -u -r1.4 reloc.c
--- reloc.c 2002/09/05 17:28:45 1.4
+++ reloc.c 2002/09/05 18:29:33
@@ -150,9 +150,10 @@
#if !defined(__sparc__) && !defined(__x86_64__)
int
-_rtld_relocate_nonplt_object(obj, rela, dodebug)
+_rtld_relocate_nonplt_object(obj, rela, cache, dodebug)
Obj_Entry *obj;
const Elf_Rela *rela;
+ SymCache *cache;
bool dodebug;
{
Elf_Addr *where = (Elf_Addr *)(obj->relocbase + rela->r_offset);
@@ -172,7 +173,8 @@
#if defined(__i386__)
case R_TYPE(GOT32):
- def = _rtld_find_symdef(rela->r_info, obj, &defobj, false);
+ def = _rtld_find_symdef(rela->r_info, obj, &defobj, false,
+ cache);
if (def == NULL)
return -1;
@@ -191,7 +193,8 @@
* generate it.
*/
- def = _rtld_find_symdef(rela->r_info, obj, &defobj, false);
+ def = _rtld_find_symdef(rela->r_info, obj, &defobj, false,
+ cache);
if (def == NULL)
return -1;
@@ -203,7 +206,8 @@
break;
case R_TYPE(32):
- def = _rtld_find_symdef(rela->r_info, obj, &defobj, false);
+ def = _rtld_find_symdef(rela->r_info, obj, &defobj, false,
+ cache);
if (def == NULL)
return -1;
@@ -340,7 +344,8 @@
#if defined(__alpha__) || defined(__i386__) || defined(__m68k__) || \
defined(__sh__)
case R_TYPE(GLOB_DAT):
- def = _rtld_find_symdef(rela->r_info, obj, &defobj, false);
+ def = _rtld_find_symdef(rela->r_info, obj, &defobj, false,
+ cache);
if (def == NULL)
return -1;
@@ -621,7 +626,7 @@
#endif /* __hppa__ */
default:
- def = _rtld_find_symdef(rela->r_info, obj, &defobj, true);
+ def = _rtld_find_symdef(rela->r_info, obj, &defobj, true, NULL);
rdbg(dodebug, ("sym = %lu, type = %lu, offset = %p, "
"addend = %p, contents = %p, symbol = %s",
(u_long)ELF_R_SYM(rela->r_info),
@@ -665,7 +670,7 @@
assert(ELF_R_TYPE(rela->r_info) == R_TYPE(JUMP_SLOT));
#endif
- def = _rtld_find_symdef(rela->r_info, obj, &defobj, true);
+ def = _rtld_find_symdef(rela->r_info, obj, &defobj, true, NULL);
if (def == NULL)
return -1;
@@ -769,9 +774,12 @@
bool dodebug;
{
Obj_Entry *obj;
+ SymCache *cache;
int ok = 1;
for (obj = first; obj != NULL; obj = obj->next) {
+ int bytes = obj->nchains * sizeof(SymCache);
+
if (obj->nbuckets == 0 || obj->nchains == 0 ||
obj->buckets == NULL || obj->symtab == NULL ||
obj->strtab == NULL) {
@@ -799,6 +807,14 @@
return -1;
}
}
+
+ cache = mmap(NULL, bytes, PROT_READ|PROT_WRITE, MAP_ANON, -1,
+ 0);
+ if (cache == MAP_FAILED)
+ cache = NULL;
+ if (cache != NULL)
+ memset(cache, 0, bytes);
+
if (obj->rel != NULL) {
/* Process the non-PLT relocations. */
const Elf_Rel *rel;
@@ -817,7 +833,7 @@
rel->r_offset);
if (_rtld_relocate_nonplt_object(obj, &ourrela,
- dodebug) < 0)
+ cache, dodebug) < 0)
ok = 0;
}
}
@@ -826,10 +842,14 @@
const Elf_Rela *rela;
for (rela = obj->rela; rela < obj->relalim; ++rela) {
if (_rtld_relocate_nonplt_object(obj, rela,
- dodebug) < 0)
+ cache, dodebug) < 0)
ok = 0;
}
}
+
+ if (cache)
+ munmap(cache, bytes);
+
if (obj->textrel) { /* Re-protected the text segment. */
if (mprotect(obj->mapbase, obj->textsize,
PROT_READ | PROT_EXEC) == -1) {
Index: rtld.h
===================================================================
RCS file: /usr/local/cvs/prebind/src/libexec/ld.elf_so/rtld.h,v
retrieving revision 1.3
diff -u -r1.3 rtld.h
--- rtld.h 2002/09/05 17:28:45 1.3
+++ rtld.h 2002/09/05 17:50:25
@@ -217,6 +217,15 @@
repeat visits */
} Obj_Entry;
+/*
+ * Symbol cache entry used during relocation to avoid multiple lookups
+ * of the same symbol.
+ */
+typedef struct Struct_SymCache {
+ const Elf_Sym *sym; /* Symbol table entry */
+ const Obj_Entry *obj; /* Shared object which defines it */
+} SymCache;
+
#if defined(_RTLD_SOURCE)
extern struct r_debug _rtld_debug;
@@ -272,7 +281,7 @@
caddr_t _rtld_bind __P((Obj_Entry *, Elf_Word));
int _rtld_relocate_objects __P((Obj_Entry *, bool, bool));
int _rtld_relocate_nonplt_object __P((Obj_Entry *,
- const Elf_Rela *, bool));
+ const Elf_Rela *, SymCache *, bool));
int _rtld_relocate_plt_object __P((Obj_Entry *, const Elf_Rela *,
caddr_t *, bool, bool));
@@ -284,7 +293,7 @@
const Elf_Sym *_rtld_symlook_obj __P((const char *, unsigned long,
const Obj_Entry *, bool));
const Elf_Sym *_rtld_find_symdef __P((Elf_Addr, Obj_Entry *,
- const Obj_Entry **, bool));
+ const Obj_Entry **, bool, SymCache *));
const Elf_Sym *_rtld_symlook_list(const char *, unsigned long,
Objlist *, const Obj_Entry **, bool in_plt);
Index: symbol.c
===================================================================
RCS file: /usr/local/cvs/prebind/src/libexec/ld.elf_so/symbol.c,v
retrieving revision 1.4
diff -u -r1.4 symbol.c
--- symbol.c 2002/09/05 17:28:45 1.4
+++ symbol.c 2002/09/05 18:31:34
@@ -154,11 +154,12 @@
* defining object via the reference parameter DEFOBJ_OUT.
*/
const Elf_Sym *
-_rtld_find_symdef(r_info, refobj, defobj_out, in_plt)
+_rtld_find_symdef(r_info, refobj, defobj_out, in_plt, cache)
Elf_Addr r_info;
Obj_Entry *refobj;
const Obj_Entry **defobj_out;
bool in_plt;
+ SymCache *cache;
{
Elf_Addr symnum = ELF_R_SYM(r_info);
const Elf_Sym *ref;
@@ -170,6 +171,18 @@
const char *name;
unsigned long hash;
+ /*
+ * If we have already found this symbol, get the information from
+ * the cache.
+ */
+ if (symnum >= refobj->nchains)
+ return NULL; /* Bad object */
+ if (cache != NULL && cache[symnum].sym != NULL) {
+ *defobj_out = cache[symnum].obj;
+ dbg(("found!"));
+ return cache[symnum].sym;
+ }
+
ref = refobj->symtab + symnum;
name = refobj->strtab + ref->st_name;
@@ -230,9 +243,14 @@
defobj = _rtld_objmain;
}
- if (def != NULL)
+ if (def != NULL) {
*defobj_out = defobj;
- else if (ELF_R_TYPE(r_info) != R_TYPE(NONE)) {
+ /* Record the information in the cache to avoid subsequent lookups. */
+ if (cache != NULL) {
+ cache[symnum].sym = def;
+ cache[symnum].obj = defobj;
+ }
+ } else if (ELF_R_TYPE(r_info) != R_TYPE(NONE)) {
_rtld_error(
"%s: Undefined %ssymbol \"%s\" (reloc type = %ld, symnum = %ld)",
refobj->path, in_plt ? "PLT " : "", name,
Index: arch/sparc/mdreloc.c
===================================================================
RCS file: /usr/local/cvs/prebind/src/libexec/ld.elf_so/arch/sparc/mdreloc.c,v
retrieving revision 1.3
diff -u -r1.3 mdreloc.c
--- arch/sparc/mdreloc.c 2002/09/05 17:28:50 1.3
+++ arch/sparc/mdreloc.c 2002/09/05 17:50:09
@@ -161,9 +161,10 @@
#define RELOC_VALUE_BITMASK(t) (reloc_target_bitmask[t])
int
-_rtld_relocate_nonplt_object(obj, rela, dodebug)
+_rtld_relocate_nonplt_object(obj, rela, cache, dodebug)
Obj_Entry *obj;
const Elf_Rela *rela;
+ SymCache *cache;
bool dodebug;
{
Elf_Addr *where = (Elf_Addr *) (obj->relocbase + rela->r_offset);
--/04w6evG8XlLl3ft--