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.
This commit is contained in:
simonb 2003-11-19 19:41:57 +00:00
parent 130f3bfc26
commit 28817edd35
1 changed files with 47 additions and 30 deletions

View File

@ -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,