Author: imp
Date: Sat Aug  9 22:51:26 2014
New Revision: 269767
URL: http://svnweb.freebsd.org/changeset/base/269767

Log:
  Per discussion on arm@, the compiler generates misaligned
  relocations. Cope with memcpy when needed.
  
  Submitted by: fabient@ (plus changes suggested by thread)

Modified:
  head/sys/arm/arm/elf_machdep.c

Modified: head/sys/arm/arm/elf_machdep.c
==============================================================================
--- head/sys/arm/arm/elf_machdep.c      Sat Aug  9 21:01:24 2014        
(r269766)
+++ head/sys/arm/arm/elf_machdep.c      Sat Aug  9 22:51:26 2014        
(r269767)
@@ -120,6 +120,34 @@ elf32_dump_thread(struct thread *td __un
 {
 }
 
+/*
+ * 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(Elf_Addr *where)
+{
+       Elf_Addr res;
+
+       if (RELOC_ALIGNED_P(where))
+               return *where;
+       memcpy(&res, where, sizeof(res));
+       return (res);
+}
+
+static __inline void
+store_ptr(Elf_Addr *where, Elf_Addr val)
+{
+       if (RELOC_ALIGNED_P(where))
+               *where = val;
+       else
+               memcpy(where, &val, sizeof(val));
+}
+#undef RELOC_ALIGNED_P
+
 
 /* Process one elf relocation with addend. */
 static int
@@ -137,7 +165,7 @@ elf_reloc_internal(linker_file_t lf, Elf
        case ELF_RELOC_REL:
                rel = (const Elf_Rel *)data;
                where = (Elf_Addr *) (relocbase + rel->r_offset);
-               addend = *where;
+               addend = load_ptr(where);
                rtype = ELF_R_TYPE(rel->r_info);
                symidx = ELF_R_SYM(rel->r_info);
                break;
@@ -155,8 +183,8 @@ elf_reloc_internal(linker_file_t lf, Elf
        if (local) {
                if (rtype == R_ARM_RELATIVE) {  /* A + B */
                        addr = elf_relocaddr(lf, relocbase + addend);
-                       if (*where != addr)
-                               *where = addr;
+                       if (load_ptr(where) != addr)
+                               store_ptr(where, addr);
                }
                return (0);
        }
@@ -170,7 +198,7 @@ elf_reloc_internal(linker_file_t lf, Elf
                        addr = lookup(lf, symidx, 1);
                        if (addr == 0)
                                return -1;
-                       *where += addr;
+                       store_ptr(where, addr + load_ptr(where));
                        break;
 
                case R_ARM_COPY:        /* none */
@@ -185,7 +213,7 @@ elf_reloc_internal(linker_file_t lf, Elf
                case R_ARM_JUMP_SLOT:
                        addr = lookup(lf, symidx, 1);
                        if (addr) {
-                               *where = addr;
+                               store_ptr(where, addr);
                                return (0);
                        }
                        return (-1);
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to