Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 9 Aug 2014 22:51:27 +0000 (UTC)
From:      Warner Losh <imp@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r269767 - head/sys/arm/arm
Message-ID:  <53e6a5ef.2fbb.3bbe0e71@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
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);



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?53e6a5ef.2fbb.3bbe0e71>