summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDale Rahn <drahn@cvs.openbsd.org>2002-08-23 22:57:04 +0000
committerDale Rahn <drahn@cvs.openbsd.org>2002-08-23 22:57:04 +0000
commitbfce6caf8080fa2d4f5024cab4059d709567fae4 (patch)
tree76cf0b5a29cb9439e94d9326ba53457e1dcb7f01
parent9958388d0a4d2166f3f7b1acfaae96e99f8843b7 (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.c20
-rw-r--r--libexec/ld.so/dlfcn.c5
-rw-r--r--libexec/ld.so/loader.c17
-rw-r--r--libexec/ld.so/powerpc/rtld_machine.c20
-rw-r--r--libexec/ld.so/resolve.c44
-rw-r--r--libexec/ld.so/resolve.h26
-rw-r--r--libexec/ld.so/sparc/rtld_machine.c30
-rw-r--r--libexec/ld.so/sparc64/rtld_machine.c27
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 */