diff options
author | Dale Rahn <drahn@cvs.openbsd.org> | 2002-08-23 22:57:04 +0000 |
---|---|---|
committer | Dale Rahn <drahn@cvs.openbsd.org> | 2002-08-23 22:57:04 +0000 |
commit | bfce6caf8080fa2d4f5024cab4059d709567fae4 (patch) | |
tree | 76cf0b5a29cb9439e94d9326ba53457e1dcb7f01 | |
parent | 9958388d0a4d2166f3f7b1acfaae96e99f8843b7 (diff) |
Change arguments to _dl_find_symbol() myself, warnnotfound, and inplt into
a single flags field with bits representing each. Use defines to create
the appropriate masks.
Add a new argument sym_size to warn about symbols which have
the incorrect size. This replaces 'ifdef notyet' code which
was in several of the md files with a single version.
sym_size == 0 means do not check, and symbols of type FUNC are
not checked.
-rw-r--r-- | libexec/ld.so/alpha/rtld_machine.c | 20 | ||||
-rw-r--r-- | libexec/ld.so/dlfcn.c | 5 | ||||
-rw-r--r-- | libexec/ld.so/loader.c | 17 | ||||
-rw-r--r-- | libexec/ld.so/powerpc/rtld_machine.c | 20 | ||||
-rw-r--r-- | libexec/ld.so/resolve.c | 44 | ||||
-rw-r--r-- | libexec/ld.so/resolve.h | 26 | ||||
-rw-r--r-- | libexec/ld.so/sparc/rtld_machine.c | 30 | ||||
-rw-r--r-- | libexec/ld.so/sparc64/rtld_machine.c | 27 |
8 files changed, 121 insertions, 68 deletions
diff --git a/libexec/ld.so/alpha/rtld_machine.c b/libexec/ld.so/alpha/rtld_machine.c index cdc29532a92..c6f27d23d93 100644 --- a/libexec/ld.so/alpha/rtld_machine.c +++ b/libexec/ld.so/alpha/rtld_machine.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rtld_machine.c,v 1.14 2002/08/11 16:51:04 drahn Exp $ */ +/* $OpenBSD: rtld_machine.c,v 1.15 2002/08/23 22:57:03 drahn Exp $ */ /* * Copyright (c) 1999 Dale Rahn @@ -111,8 +111,9 @@ _dl_md_reloc(elf_object_t *object, int rel, int relasz) this = NULL; switch (ELF64_R_TYPE(relas->r_info)) { case R_TYPE(REFQUAD): - ooff = _dl_find_symbol(symn, _dl_objects, &this, 0, 1, - 0); + ooff = _dl_find_symbol(symn, _dl_objects, &this, + SYM_SEARCH_ALL|SYM_WARNNOTFOUND|SYM_NOTPLT, + sym->st_size); if (this == NULL) goto resolve_failed; *r_addr += ooff + this->st_value + relas->r_addend; @@ -135,15 +136,17 @@ _dl_printf("unaligned RELATIVE: %p type: %d %s 0x%lx -> 0x%lx\n", r_addr, *r_addr += loff; break; case R_TYPE(JMP_SLOT): - ooff = _dl_find_symbol(symn, _dl_objects, &this, 0, 1, - 1); + ooff = _dl_find_symbol(symn, _dl_objects, &this, + SYM_SEARCH_ALL|SYM_WARNNOTFOUND|SYM_PLT, + sym->st_size); if (this == NULL) goto resolve_failed; *r_addr = ooff + this->st_value + relas->r_addend; break; case R_TYPE(GLOB_DAT): - ooff = _dl_find_symbol(symn, _dl_objects, &this, 0, 1, - 0); + ooff = _dl_find_symbol(symn, _dl_objects, &this, + SYM_SEARCH_ALL|SYM_WARNNOTFOUND|SYM_NOTPLT, + sym->st_size); if (this == NULL) goto resolve_failed; *r_addr = ooff + this->st_value + relas->r_addend; @@ -194,7 +197,8 @@ _dl_bind(elf_object_t *object, Elf_Word reloff) symn = object->dyn.strtab + sym->st_name; addr = (Elf_Addr *)(object->load_offs + rela->r_offset); - ooff = _dl_find_symbol(symn, _dl_objects, &this, 0, 1, 1); + ooff = _dl_find_symbol(symn, _dl_objects, &this, + SYM_SEARCH_ALL|SYM_WARNNOTFOUND|SYM_PLT, sym->st_size); if (this == NULL) { _dl_printf("lazy binding failed!\n"); *((int *)0) = 0; /* XXX */ diff --git a/libexec/ld.so/dlfcn.c b/libexec/ld.so/dlfcn.c index 8fc1ee588fe..e3ec5317409 100644 --- a/libexec/ld.so/dlfcn.c +++ b/libexec/ld.so/dlfcn.c @@ -1,4 +1,4 @@ -/* $OpenBSD: dlfcn.c,v 1.18 2002/08/11 16:51:04 drahn Exp $ */ +/* $OpenBSD: dlfcn.c,v 1.19 2002/08/23 22:57:03 drahn Exp $ */ /* * Copyright (c) 1998 Per Fogelstrom, Opsycon AB @@ -126,7 +126,8 @@ dlsym(void *handle, const char *name) return(0); } - retval = (void *)_dl_find_symbol(name, object, &sym, 1, 1, 0); + retval = (void *)_dl_find_symbol(name, object, &sym, + SYM_SEARCH_SELF|SYM_WARNNOTFOUND|SYM_NOTPLT, 0); if (sym != NULL) retval += sym->st_value; else diff --git a/libexec/ld.so/loader.c b/libexec/ld.so/loader.c index 819c5c18d22..f9d5151f2e5 100644 --- a/libexec/ld.so/loader.c +++ b/libexec/ld.so/loader.c @@ -1,4 +1,4 @@ -/* $OpenBSD: loader.c,v 1.47 2002/08/12 01:05:23 drahn Exp $ */ +/* $OpenBSD: loader.c,v 1.48 2002/08/23 22:57:03 drahn Exp $ */ /* * Copyright (c) 1998 Per Fogelstrom, Opsycon AB @@ -255,7 +255,8 @@ _dl_boot(const char **argv, char **envp, const long loff, long *dl_data) Elf_Addr ooff; sym = NULL; - ooff = _dl_find_symbol("atexit", _dl_objects, &sym, 0, 0, 1); + ooff = _dl_find_symbol("atexit", _dl_objects, &sym, + SYM_SEARCH_ALL|SYM_NOWARNNOTFOUND|SYM_PLT, 0); if (sym == NULL) { _dl_printf("cannot find atexit, destructors will not be run!\n"); } else { @@ -529,14 +530,16 @@ _dl_call_init(elf_object_t *object) * XXX that should be fixed. */ sym = NULL; - ooff = _dl_find_symbol("__CTOR_LIST__", object, &sym, 1, 1, 1); + ooff = _dl_find_symbol("__CTOR_LIST__", object, &sym, + SYM_SEARCH_SELF|SYM_WARNNOTFOUND|SYM_PLT, 0); if (sym != NULL) { int i = *(int *)(sym->st_value + ooff); while (i--) *(int *)(sym->st_value + ooff + 4 + 4 * i) += ooff; } sym = NULL; - ooff = _dl_find_symbol("__DTOR_LIST__", object, &sym, 1, 1, 1); + ooff = _dl_find_symbol("__DTOR_LIST__", object, &sym, + SYM_SEARCH_SELF|SYM_WARNNOTFOUND|SYM_PLT, 0); if (sym != NULL) { int i = *(int *)(sym->st_value + ooff); while (i--) @@ -549,7 +552,8 @@ _dl_call_init(elf_object_t *object) * XXX Instead we rely on a symbol named '.init' and call it if it exists. */ sym = NULL; - ooff = _dl_find_symbol(".init", object, &sym, 1, 1, 1); + ooff = _dl_find_symbol(".init", object, &sym, + SYM_SEARCH_SELF|SYM_WARNNOTFOUND|SYM_PLT, 0); if (sym != NULL) { DL_DEB(("calling .init in '%s'\n",object->load_name)); (*(void(*)(void))(sym->st_value + ooff))(); @@ -577,8 +581,9 @@ _dl_getenv(const char *var, char **env) if (*vp == '\0' && *ep++ == '=') return((char *)ep); } - return(0); + return(NULL); } + static void _dl_unsetenv(const char *var, char **env) { diff --git a/libexec/ld.so/powerpc/rtld_machine.c b/libexec/ld.so/powerpc/rtld_machine.c index 9ea6e483bf9..4efb4154f92 100644 --- a/libexec/ld.so/powerpc/rtld_machine.c +++ b/libexec/ld.so/powerpc/rtld_machine.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rtld_machine.c,v 1.13 2002/08/11 16:51:04 drahn Exp $ */ +/* $OpenBSD: rtld_machine.c,v 1.14 2002/08/23 22:57:03 drahn Exp $ */ /* * Copyright (c) 1999 Dale Rahn @@ -139,7 +139,7 @@ _dl_printf("object relocation size %x, numrela %x\n", Elf32_Addr ooff; const Elf32_Sym *sym, *this; const char *symn; - int inplt; + int type; if (ELF32_R_SYM(relas->r_info) == 0xffffff) continue; @@ -148,14 +148,18 @@ _dl_printf("object relocation size %x, numrela %x\n", sym += ELF32_R_SYM(relas->r_info); this = sym; symn = object->dyn.strtab + sym->st_name; + type = ELF32_R_TYPE(relas->r_info); ooff = 0; if (ELF32_R_SYM(relas->r_info) && !(ELF32_ST_BIND(sym->st_info) == STB_LOCAL && ELF32_ST_TYPE (sym->st_info) == STT_NOTYPE)) { - inplt = (ELF32_R_TYPE(relas->r_info) == RELOC_JMP_SLOT); - ooff = _dl_find_symbol(symn, _dl_objects, &this, 0, 0, inplt); + ooff = _dl_find_symbol(symn, _dl_objects, &this, + SYM_SEARCH_ALL|SYM_NOWARNNOTFOUND| + ((type == RELOC_JMP_SLOT) ? SYM_PLT:SYM_NOTPLT), + sym->st_size); + if (!this && ELF32_ST_BIND(sym->st_info) == STB_GLOBAL) { _dl_printf("%s: %s :can't resolve reference '%s'\n", _dl_progname, object->load_name, symn); @@ -163,7 +167,7 @@ _dl_printf("object relocation size %x, numrela %x\n", } } - switch (ELF32_R_TYPE(relas->r_info)) { + switch (type) { #if 1 case RELOC_32: if (ELF32_ST_BIND(sym->st_info) == STB_LOCAL && @@ -358,7 +362,11 @@ _dl_dcbf(r_addr); if (object != cobj) { /* only look in this object */ src_loff = _dl_find_symbol(symn, cobj, - &cpysrc, 1, 1, 0); + &cpysrc, + SYM_SEARCH_SELF|SYM_NOWARNNOTFOUND| + ((type == RELOC_JMP_SLOT) ? + SYM_PLT : SYM_NOTPLT), + sym->st_size); } } if (cpysrc == NULL) { diff --git a/libexec/ld.so/resolve.c b/libexec/ld.so/resolve.c index 312401ffbd8..f26cf307181 100644 --- a/libexec/ld.so/resolve.c +++ b/libexec/ld.so/resolve.c @@ -1,4 +1,4 @@ -/* $OpenBSD: resolve.c,v 1.12 2002/08/11 16:51:04 drahn Exp $ */ +/* $OpenBSD: resolve.c,v 1.13 2002/08/23 22:57:03 drahn Exp $ */ /* * Copyright (c) 1998 Per Fogelstrom, Opsycon AB @@ -175,9 +175,10 @@ _dl_lookup_object(const char *name) Elf_Addr _dl_find_symbol(const char *name, elf_object_t *startlook, - const Elf_Sym **ref, int myself, int warnnotfound, int inplt) + const Elf_Sym **ref, int flags, int req_size) { const Elf_Sym *weak_sym = 0; + const char *weak_symn = ""; /* remove warning */ Elf_Addr weak_offs = 0; unsigned long h = 0; const char *p = name; @@ -191,10 +192,13 @@ _dl_find_symbol(const char *name, elf_object_t *startlook, h &= ~g; } - for (object = startlook; object; object = (myself ? 0 : object->next)) { + for (object = startlook; + object; + object = ((flags & SYM_SEARCH_SELF) ? 0 : object->next)) { const Elf_Sym *symt = object->dyn.symtab; const char *strt = object->dyn.strtab; long si; + const char *symn; for (si = object->buckets[h % object->nbuckets]; si != STN_UNDEF; si = object->chains[si]) { @@ -208,29 +212,47 @@ _dl_find_symbol(const char *name, elf_object_t *startlook, ELF_ST_TYPE(sym->st_info) != STT_FUNC) continue; + symn = strt + sym->st_name; if (sym != *ref && - _dl_strcmp(strt + sym->st_name, name)) + _dl_strcmp(symn, name)) continue; + /* allow this symbol if we are referring to a function + * which has a value, even if section is UNDEF. + * this allows &func to refer to PLT as per the + * ELF spec. st_value is checked above. + * if flags has SYM_PLT set, we must have actual + * symbol, so this symbol is skipped. + */ if (sym->st_shndx == SHN_UNDEF) { - if ((inplt || sym->st_value == 0 || - ELF_ST_TYPE(sym->st_info) != STT_FUNC)) { + if ((flags & SYM_PLT) || sym->st_value == 0 || + ELF_ST_TYPE(sym->st_info) != STT_FUNC) { continue; } } if (ELF_ST_BIND(sym->st_info) == STB_GLOBAL) { *ref = sym; + if (req_size != sym->st_size && + req_size != 0 && + (ELF_ST_TYPE(sym->st_info) != STT_FUNC)) { + _dl_printf("%s: %s : WARNING: " + "symbol(%s) size mismatch ", + _dl_progname, object->load_name, + symn); + _dl_printf("relink your program\n"); + } return(object->load_offs); } else if (ELF_ST_BIND(sym->st_info) == STB_WEAK) { if (!weak_sym) { weak_sym = sym; + weak_symn = symn; weak_offs = object->load_offs; } } } } - if (warnnotfound) { + if (flags & SYM_WARNNOTFOUND) { if (!weak_sym && *ref && ELF_ST_BIND((*ref)->st_info) != STB_WEAK) { _dl_printf("%s: undefined symbol '%s'\n", @@ -238,5 +260,13 @@ _dl_find_symbol(const char *name, elf_object_t *startlook, } } *ref = weak_sym; + if (weak_sym && req_size != weak_sym->st_size && + req_size != 0 && (ELF_ST_TYPE(weak_sym->st_info) != STT_FUNC)) { + _dl_printf("%s: %s : WARNING: " + "symbol(%s) size mismatch ", + _dl_progname, object->load_name, + weak_symn); + _dl_printf("relink your program\n"); + } return(weak_offs); } diff --git a/libexec/ld.so/resolve.h b/libexec/ld.so/resolve.h index b0eabad8784..3af79fab45e 100644 --- a/libexec/ld.so/resolve.h +++ b/libexec/ld.so/resolve.h @@ -1,4 +1,4 @@ -/* $OpenBSD: resolve.h,v 1.16 2002/08/11 16:51:04 drahn Exp $ */ +/* $OpenBSD: resolve.h,v 1.17 2002/08/23 22:57:03 drahn Exp $ */ /* * Copyright (c) 1998 Per Fogelstrom, Opsycon AB @@ -134,7 +134,29 @@ extern int _dl_md_reloc(elf_object_t *object, int rel, int relsz); extern void _dl_md_reloc_got(elf_object_t *object, int lazy); Elf_Addr _dl_find_symbol(const char *name, elf_object_t *startlook, - const Elf_Sym **ref, int myself, int warnnotfound, int inplt); + const Elf_Sym **ref, int flags, int sym_size); +/* + * defines for _dl_find_symbol() flag field, three bits of meaning + * myself - clear: search all objects, set: search only this object + * warnnotfound - clear: no warning, set: warn if not found + * inplt - clear: possible plt ref set: real matching function. + * + * inplt - due to how ELF handles function addresses in shared libraries + * &func may actually refer to the plt entry in the main program + * rather than the actual function address in the .so file. + * This rather bizarre behavior is documented in the SVR4 ABI. + * when getting the function address to relocate a PLT entry + * the 'real' function address is necessary, not the possible PLT address. + */ +/* myself */ +#define SYM_SEARCH_ALL 0 +#define SYM_SEARCH_SELF 1 +/* warnnotfound */ +#define SYM_NOWARNNOTFOUND 0 +#define SYM_WARNNOTFOUND 2 +/* inplt */ +#define SYM_NOTPLT 0 +#define SYM_PLT 4 void _dl_rtld(elf_object_t *object); void _dl_call_init(elf_object_t *object); diff --git a/libexec/ld.so/sparc/rtld_machine.c b/libexec/ld.so/sparc/rtld_machine.c index b67826de258..ab5df51b274 100644 --- a/libexec/ld.so/sparc/rtld_machine.c +++ b/libexec/ld.so/sparc/rtld_machine.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rtld_machine.c,v 1.6 2002/08/11 16:51:04 drahn Exp $ */ +/* $OpenBSD: rtld_machine.c,v 1.7 2002/08/23 22:57:03 drahn Exp $ */ /* * Copyright (c) 1999 Dale Rahn @@ -254,8 +254,11 @@ _dl_md_reloc(elf_object_t *object, int rel, int relasz) } else { this = NULL; ooff = _dl_find_symbol(symn, - _dl_objects, &this, 0, 1, - type == R_TYPE(JMP_SLOT)); + _dl_objects, &this, + SYM_SEARCH_ALL|SYM_WARNNOTFOUND| + ((type == R_TYPE(JMP_SLOT)) ? + SYM_PLT : SYM_NOTPLT), + sym->st_size); if (this == NULL) { resolve_failed: _dl_printf("%s: %s: can't resolve " @@ -267,20 +270,6 @@ resolve_failed: continue; } value += (Elf_Addr)(ooff + this->st_value); -#ifdef notyet -/* - * XXX Hmm, we should change the API of _dl_find_symbol and do this in there, - * XXX or maybe make a wrapper. - */ - if (this->st_size != sym->st_size && - sym->st_size != 0) { - _dl_printf("%s: %s : WARNING: " - "symbol(%s) size mismatch ", - _dl_progname, object->load_name, - symn); - _dl_printf("relink your program\n"); - } -#endif } } @@ -292,7 +281,9 @@ resolve_failed: Elf_Addr soff; soff = _dl_find_symbol(symn, object->next, &srcsym, - 0, 2, 0); + SYM_SEARCH_ALL|SYM_WARNNOTFOUND| + ((type == R_TYPE(JMP_SLOT)) ? SYM_PLT : SYM_NOTPLT), + size); if (srcsym == NULL) goto resolve_failed; @@ -349,7 +340,8 @@ _dl_bind(elf_object_t *object, Elf_Word reloff) symn = object->dyn.strtab + sym->st_name; addr = (Elf_Addr *)(object->load_offs + rela->r_offset); - ooff = _dl_find_symbol(symn, _dl_objects, &this, 0, 1, 1); + ooff = _dl_find_symbol(symn, _dl_objects, &this, + SYM_SEARCH_ALL|SYM_WARNNOTFOUND|SYM_PLT, 0); if (this == NULL) { _dl_printf("lazy binding failed!\n"); *((int *)0) = 0; /* XXX */ diff --git a/libexec/ld.so/sparc64/rtld_machine.c b/libexec/ld.so/sparc64/rtld_machine.c index 602d1f33b2a..9bbbce8113f 100644 --- a/libexec/ld.so/sparc64/rtld_machine.c +++ b/libexec/ld.so/sparc64/rtld_machine.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rtld_machine.c,v 1.18 2002/08/11 16:51:04 drahn Exp $ */ +/* $OpenBSD: rtld_machine.c,v 1.19 2002/08/23 22:57:03 drahn Exp $ */ /* * Copyright (c) 1999 Dale Rahn @@ -277,7 +277,10 @@ _dl_md_reloc(elf_object_t *object, int rel, int relasz) } else { this = NULL; ooff = _dl_find_symbol(symn, _dl_objects, - &this, 0, 1, type == R_TYPE(JMP_SLOT)); + &this, SYM_SEARCH_ALL|SYM_WARNNOTFOUND| + ((type == R_TYPE(JMP_SLOT))? + SYM_PLT:SYM_NOTPLT), + sym->st_size); if (this == NULL) { resolve_failed: _dl_printf("%s: %s: can't resolve " @@ -288,20 +291,6 @@ resolve_failed: continue; } value += (Elf_Addr)(ooff + this->st_value); -#ifdef notyet -/* - * XXX Hmm, we should change the API of _dl_find_symbol and do this in there, - * XXX or maybe make a wrapper. - */ - if (this->st_size != sym->st_size && - sym->st_size != 0) { - _dl_printf("%s: %s : WARNING: " - "symbol(%s) size mismatch ", - _dl_progname, object->load_name, - symn); - _dl_printf("relink your program\n"); - } -#endif } } @@ -318,7 +307,8 @@ resolve_failed: Elf_Addr soff; soff = _dl_find_symbol(symn, object->next, &srcsym, - 0, 2, 0); + SYM_SEARCH_SELF|SYM_WARNNOTFOUND|SYM_NOTPLT, + size); if (srcsym == NULL) goto resolve_failed; @@ -643,7 +633,8 @@ _dl_bind(elf_object_t *object, int index) symn = object->dyn.strtab + sym->st_name; addr = (Elf_Word *)(object->load_offs + rela->r_offset); - ooff = _dl_find_symbol(symn, _dl_objects, &this, 0, 1, 1); + ooff = _dl_find_symbol(symn, _dl_objects, &this, + SYM_SEARCH_ALL|SYM_WARNNOTFOUND|SYM_PLT, 0); if (this == NULL) { _dl_printf("lazy binding failed!\n"); *((int *)0) = 0; /* XXX */ |