Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 21 Jan 2020 17:45:49 +0000 (UTC)
From:      Mark Johnston <markj@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r356947 - head/sys/arm64/arm64
Message-ID:  <202001211745.00LHjnbK074896@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: markj
Date: Tue Jan 21 17:45:49 2020
New Revision: 356947
URL: https://svnweb.freebsd.org/changeset/base/356947

Log:
  Add relocation handling required for -zifunc-noplt to work on arm64.
  
  Static relocations for the immediate operand of a branch instruction
  must be applied.
  
  In a patch which implements LSE-based atomic(9) operations using ifuncs,
  -zifunc-noplt reduces system CPU usage during a buildkernel by several
  percent.
  
  Also fix elf_reloc_internal() to return an error if symbol lookup fails.
  
  Reviewed by:	andrew
  MFC after:	2 weeks
  Sponsored by:	The FreeBSD Foundation
  Differential Revision:	https://reviews.freebsd.org/D17392

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

Modified: head/sys/arm64/arm64/elf_machdep.c
==============================================================================
--- head/sys/arm64/arm64/elf_machdep.c	Tue Jan 21 17:28:36 2020	(r356946)
+++ head/sys/arm64/arm64/elf_machdep.c	Tue Jan 21 17:45:49 2020	(r356947)
@@ -125,6 +125,23 @@ elf_is_ifunc_reloc(Elf_Size r_info __unused)
 }
 
 static int
+reloc_instr_imm(Elf32_Addr *where, Elf_Addr val, u_int msb, u_int lsb)
+{
+
+	/* Check bounds: upper bits must be all ones or all zeros. */
+	if ((uint64_t)((int64_t)val >> (msb + 1)) + 1 > 1)
+		return (-1);
+	val >>= lsb;
+	val &= (1 << (msb - lsb + 1)) - 1;
+	*where |= (Elf32_Addr)val;
+	return (0);
+}
+
+/*
+ * Process a relocation.  Support for some static relocations is required
+ * in order for the -zifunc-noplt optimization to work.
+ */
+static int
 elf_reloc_internal(linker_file_t lf, Elf_Addr relocbase, const void *data,
     int type, int local, elf_lookup_fn lookup)
 {
@@ -159,10 +176,33 @@ elf_reloc_internal(linker_file_t lf, Elf_Addr relocbas
 		return (0);
 	}
 
+	error = 0;
 	switch (rtype) {
 	case R_AARCH64_NONE:
 	case R_AARCH64_RELATIVE:
 		break;
+	case R_AARCH64_TSTBR14:
+		error = lookup(lf, symidx, 1, &addr);
+		if (error != 0)
+			return (-1);
+		error = reloc_instr_imm((Elf32_Addr *)where,
+		    addr + addend - (Elf_Addr)where, 15, 2);
+		break;
+	case R_AARCH64_CONDBR19:
+		error = lookup(lf, symidx, 1, &addr);
+		if (error != 0)
+			return (-1);
+		error = reloc_instr_imm((Elf32_Addr *)where,
+		    addr + addend - (Elf_Addr)where, 20, 2);
+		break;
+	case R_AARCH64_JUMP26:
+	case R_AARCH64_CALL26:
+		error = lookup(lf, symidx, 1, &addr);
+		if (error != 0)
+			return (-1);
+		error = reloc_instr_imm((Elf32_Addr *)where,
+		    addr + addend - (Elf_Addr)where, 27, 2);
+		break;
 	case R_AARCH64_ABS64:
 	case R_AARCH64_GLOB_DAT:
 	case R_AARCH64_JUMP_SLOT:
@@ -181,7 +221,7 @@ elf_reloc_internal(linker_file_t lf, Elf_Addr relocbas
 		printf("kldload: unexpected relocation type %d\n", rtype);
 		return (-1);
 	}
-	return (0);
+	return (error);
 }
 
 int



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