summaryrefslogtreecommitdiff
path: root/libexec/ld.elf_so
diff options
context:
space:
mode:
authorsimonb <simonb@NetBSD.org>2003-11-19 19:41:57 +0000
committersimonb <simonb@NetBSD.org>2003-11-19 19:41:57 +0000
commit28817edd35ce968e00a573fac65d8d99c6c94c87 (patch)
treeacbc31f4fc8289fac5395596a8227aab04910f67 /libexec/ld.elf_so
parent130f3bfc2675b83674db15ba8ef8e8903254b84e (diff)
Restore handling of reloc entries that point to unaligned locations
that seems to have disappeared in rev 1.34. Thanks to Jason Thorpe for suggesting where to look. Fixes the simple test case in PR port-mips/23366.
Diffstat (limited to 'libexec/ld.elf_so')
-rw-r--r--libexec/ld.elf_so/arch/mips/mips_reloc.c77
1 files changed, 47 insertions, 30 deletions
diff --git a/libexec/ld.elf_so/arch/mips/mips_reloc.c b/libexec/ld.elf_so/arch/mips/mips_reloc.c
index cdddf69c75c..fb6d4c31c27 100644
--- a/libexec/ld.elf_so/arch/mips/mips_reloc.c
+++ b/libexec/ld.elf_so/arch/mips/mips_reloc.c
@@ -1,4 +1,4 @@
-/* $NetBSD: mips_reloc.c,v 1.44 2003/09/24 10:25:26 mycroft Exp $ */
+/* $NetBSD: mips_reloc.c,v 1.45 2003/11/19 19:41:57 simonb Exp $ */
/*
* Copyright 1997 Michael L. Hitch <mhitch@montana.edu>
@@ -43,6 +43,31 @@ void _rtld_bind_start(void);
void _rtld_relocate_nonplt_self(Elf_Dyn *, Elf_Addr);
caddr_t _rtld_bind(Elf_Word, Elf_Addr, Elf_Addr, Elf_Addr);
+/*
+ * It is possible for the compiler to emit relocations for unaligned data.
+ * We handle this situation with these inlines.
+ */
+#define RELOC_ALIGNED_P(x) \
+ (((uintptr_t)(x) & (sizeof(void *) - 1)) == 0)
+
+static __inline Elf_Addr
+load_ptr(void *where)
+{
+ Elf_Addr res;
+
+ memcpy(&res, where, sizeof(res));
+
+ return res;
+}
+
+static __inline void
+store_ptr(void *where, Elf_Addr val)
+{
+
+ memcpy(where, &val, sizeof(val));
+}
+
+
void
_rtld_setup_pltgot(const Obj_Entry *obj)
{
@@ -114,7 +139,11 @@ _rtld_relocate_nonplt_self(Elf_Dyn *dynp, Elf_Addr relocbase)
sym = symtab + ELF_R_SYM(rel->r_info);
assert(sym->st_info ==
ELF_ST_INFO(STB_LOCAL, STT_SECTION));
- *where += (Elf_Addr)(sym->st_value + relocbase);
+ if (__predict_true(RELOC_ALIGNED_P(where)))
+ *where += (Elf_Addr)(sym->st_value + relocbase);
+ else
+ store_ptr(where, load_ptr(where) +
+ (Elf_Addr)(sym->st_value + relocbase));
break;
default:
@@ -123,30 +152,6 @@ _rtld_relocate_nonplt_self(Elf_Dyn *dynp, Elf_Addr relocbase)
}
}
-/*
- * It is possible for the compiler to emit relocations for unaligned data.
- * We handle this situation with these inlines.
- */
-#define RELOC_ALIGNED_P(x) \
- (((uintptr_t)(x) & (sizeof(void *) - 1)) == 0)
-
-static __inline Elf_Addr
-load_ptr(void *where)
-{
- Elf_Addr res;
-
- memcpy(&res, where, sizeof(res));
-
- return (res);
-}
-
-static __inline void
-store_ptr(void *where, Elf_Addr val)
-{
-
- memcpy(where, &val, sizeof(val));
-}
-
int
_rtld_relocate_nonplt_objects(const Obj_Entry *obj)
{
@@ -252,9 +257,15 @@ _rtld_relocate_nonplt_objects(const Obj_Entry *obj)
def = obj->symtab + symnum;
if (symnum >= obj->gotsym) {
- tmp = *where;
+ if (__predict_true(RELOC_ALIGNED_P(where)))
+ tmp = *where;
+ else
+ tmp = load_ptr(where);
tmp += got[obj->local_gotno + symnum - obj->gotsym];
- *where = tmp;
+ if (__predict_true(RELOC_ALIGNED_P(where)))
+ *where = tmp;
+ else
+ store_ptr(where, tmp);
rdbg(("REL32/G %s in %s --> %p in %s",
obj->strtab + def->st_name, obj->path,
@@ -276,7 +287,10 @@ _rtld_relocate_nonplt_objects(const Obj_Entry *obj)
*
* --rkb, Oct 6, 2001
*/
- tmp = *where;
+ if (__predict_true(RELOC_ALIGNED_P(where)))
+ tmp = *where;
+ else
+ tmp = load_ptr(where);
if (def->st_info ==
ELF_ST_INFO(STB_LOCAL, STT_SECTION)
@@ -287,7 +301,10 @@ _rtld_relocate_nonplt_objects(const Obj_Entry *obj)
tmp += (Elf_Addr)def->st_value;
tmp += (Elf_Addr)obj->relocbase;
- *where = tmp;
+ if (__predict_true(RELOC_ALIGNED_P(where)))
+ *where = tmp;
+ else
+ store_ptr(where, tmp);
rdbg(("REL32/L %s in %s --> %p in %s",
obj->strtab + def->st_name, obj->path,