diff options
| author | simonb <simonb@NetBSD.org> | 2003-11-19 19:41:57 +0000 |
|---|---|---|
| committer | simonb <simonb@NetBSD.org> | 2003-11-19 19:41:57 +0000 |
| commit | 28817edd35ce968e00a573fac65d8d99c6c94c87 (patch) | |
| tree | acbc31f4fc8289fac5395596a8227aab04910f67 /libexec/ld.elf_so | |
| parent | 130f3bfc2675b83674db15ba8ef8e8903254b84e (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.c | 77 |
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, |
