--- arm/arm/elf_machdep.c.orig 2012-12-04 14:31:29.000000000 +0000 +++ arm/arm/elf_machdep.c 2012-12-04 14:34:08.000000000 +0000 @@ -120,6 +120,30 @@ { } +/* + * 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)); +} + /* Process one elf relocation with addend. */ static int @@ -136,7 +160,10 @@ case ELF_RELOC_REL: rel = (const Elf_Rel *)data; where = (Elf_Addr *) (relocbase + rel->r_offset); - addend = *where; + if (RELOC_ALIGNED_P(where)) + addend = *where; + else + addend = load_ptr(where); rtype = ELF_R_TYPE(rel->r_info); symidx = ELF_R_SYM(rel->r_info); break; @@ -154,8 +181,13 @@ if (local) { if (rtype == R_ARM_RELATIVE) { /* A + B */ addr = elf_relocaddr(lf, relocbase + addend); - if (*where != addr) - *where = addr; + if (RELOC_ALIGNED_P(where)) { + if (*where != addr) + *where = addr; + } else { + if (load_ptr(where) != addr) + store_ptr(where, addr); + } } return (0); } @@ -169,7 +201,10 @@ addr = lookup(lf, symidx, 1); if (addr == 0) return -1; - *where += addr; + if (RELOC_ALIGNED_P(where)) + *where += addr; + else + store_ptr(where, addr + load_ptr(where)); break; case R_ARM_COPY: /* none */ @@ -184,7 +219,10 @@ case R_ARM_JUMP_SLOT: addr = lookup(lf, symidx, 1); if (addr) { - *where = addr; + if (RELOC_ALIGNED_P(where)) + *where = addr; + else + store_ptr(where, addr); return (0); } return (-1);