Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 28 Dec 2016 21:58:21 +0000 (UTC)
From:      Ed Maste <emaste@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-11@freebsd.org
Subject:   svn commit: r310725 - stable/11/sys/boot/common
Message-ID:  <201612282158.uBSLwL39023677@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: emaste
Date: Wed Dec 28 21:58:20 2016
New Revision: 310725
URL: https://svnweb.freebsd.org/changeset/base/310725

Log:
  Fix EFI self relocation code for rela architectures
  
  MFC r306812 (andrew):
  
  The bootloader self relocation code was slightly wrong for the
  R_AARCH64_RELATIVE relocation found on arm64. It would try to add the
  contents of the memory location being relocated to the base address and
  the relocation addend. This worked when the contents was zero, however
  this now seems to be set to the value of the addend so we add this twice.
  Fix this by just setting the memory to the computed value.
  
  MFC r309360: EFI loaders: parse rela relocations on amd64
  
  Prior to this change the loader self relocation code interpreted amd64's
  rela relocations as if they were rel relocations, discarding the addend.
  This "works" because GNU ld 2.17.50 stores the addend value in both the
  r_addend field of the relocation (as expected) and at the target of the
  relocation.
  
  Other linkers, and possibly other versions of GNU ld, won't have this
  behaviour, so interpret the relocations correctly.

Modified:
  stable/11/sys/boot/common/self_reloc.c
Directory Properties:
  stable/11/   (props changed)

Modified: stable/11/sys/boot/common/self_reloc.c
==============================================================================
--- stable/11/sys/boot/common/self_reloc.c	Wed Dec 28 21:54:33 2016	(r310724)
+++ stable/11/sys/boot/common/self_reloc.c	Wed Dec 28 21:58:20 2016	(r310725)
@@ -31,7 +31,7 @@ __FBSDID("$FreeBSD$");
 #include <elf.h>
 #include <bootstrap.h>
 
-#if defined(__aarch64__)
+#if defined(__aarch64__) || defined(__amd64__)
 #define	ElfW_Rel	Elf64_Rela
 #define	ElfW_Dyn	Elf64_Dyn
 #define	ELFW_R_TYPE	ELF64_R_TYPE
@@ -40,10 +40,6 @@ __FBSDID("$FreeBSD$");
 #define	ElfW_Rel	Elf32_Rel
 #define	ElfW_Dyn	Elf32_Dyn
 #define	ELFW_R_TYPE	ELF32_R_TYPE
-#elif defined(__amd64__)
-#define	ElfW_Rel	Elf64_Rel
-#define	ElfW_Dyn	Elf64_Dyn
-#define	ELFW_R_TYPE	ELF64_R_TYPE
 #else
 #error architecture not supported
 #endif
@@ -99,7 +95,9 @@ self_reloc(Elf_Addr baseaddr, ElfW_Dyn *
 	}
 
 	/*
-	 * Perform the actual relocation.
+	 * Perform the actual relocation. We rely on the object having been
+	 * linked at 0, so that the difference between the load and link
+	 * address is the same as the load address.
 	 */
 	for (; relsz > 0; relsz -= relent) {
 		switch (ELFW_R_TYPE(rel->r_info)) {
@@ -108,12 +106,13 @@ self_reloc(Elf_Addr baseaddr, ElfW_Dyn *
 			break;
 
 		case RELOC_TYPE_RELATIVE:
-			/* Address relative to the base address. */
 			newaddr = (Elf_Addr *)(rel->r_offset + baseaddr);
-			*newaddr += baseaddr;
-			/* Add the addend when the ABI uses them */ 
 #ifdef ELF_RELA
-			*newaddr += rel->r_addend;
+			/* Addend relative to the base address. */
+			*newaddr = baseaddr + rel->r_addend;
+#else
+			/* Address relative to the base address. */
+			*newaddr += baseaddr;
 #endif
 			break;
 		default:



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201612282158.uBSLwL39023677>