git: 1dde3d8d7bb0 - stable/13 - kldxref: Reduce divergence between per-architecture files

From: John Baldwin <jhb_at_FreeBSD.org>
Date: Thu, 18 Jan 2024 22:26:28 UTC
The branch stable/13 has been updated by jhb:

URL: https://cgit.FreeBSD.org/src/commit/?id=1dde3d8d7bb09e14bd44fc567ea5569ae5712894

commit 1dde3d8d7bb09e14bd44fc567ea5569ae5712894
Author:     Jessica Clarke <jrtc27@FreeBSD.org>
AuthorDate: 2023-12-14 20:17:20 +0000
Commit:     John Baldwin <jhb@FreeBSD.org>
CommitDate: 2024-01-18 21:31:00 +0000

    kldxref: Reduce divergence between per-architecture files
    
    Note that relbase is always 0 for DSOs so its omission for __KLD_SHARED
    architectures was not a bug in practice.
    
    Whilst here, also parenthesise the dest offset for where to avoid
    transiently creating an out-of-bounds pointer, which is UB (though even
    on CHERI architectures, where capability bounds compression can result
    in that creating invalid capabilities that will trap on dereference,
    optimisation will reassociate to the correct form in practice and thus
    work just fine).
    
    (cherry picked from commit 2a622f14e8a588de654847ae264cdc3616528c9d)
---
 usr.sbin/kldxref/ef_aarch64.c | 22 +++++++++++++---------
 usr.sbin/kldxref/ef_amd64.c   | 28 ++++++++++++----------------
 usr.sbin/kldxref/ef_arm.c     | 12 ++++++------
 usr.sbin/kldxref/ef_i386.c    | 17 ++++++++---------
 usr.sbin/kldxref/ef_mips.c    | 29 +++++++++++++----------------
 usr.sbin/kldxref/ef_powerpc.c | 39 +++++++++++++++++++++------------------
 usr.sbin/kldxref/ef_riscv.c   | 15 ++++++++++-----
 7 files changed, 83 insertions(+), 79 deletions(-)

diff --git a/usr.sbin/kldxref/ef_aarch64.c b/usr.sbin/kldxref/ef_aarch64.c
index 4365a7ff1f66..b61de3b032ab 100644
--- a/usr.sbin/kldxref/ef_aarch64.c
+++ b/usr.sbin/kldxref/ef_aarch64.c
@@ -47,21 +47,25 @@ ef_aarch64_reloc(struct elf_file *ef, const void *reldata, Elf_Type reltype,
 	GElf_Size rtype, symidx;
 	const GElf_Rela *rela;
 
-	if (reltype != ELF_T_RELA)
+	switch (reltype) {
+	case ELF_T_RELA:
+		rela = (const GElf_Rela *)reldata;
+		where = (char *)dest + (relbase + rela->r_offset - dataoff);
+		addend = rela->r_addend;
+		rtype = GELF_R_TYPE(rela->r_info);
+		symidx = GELF_R_SYM(rela->r_info);
+		break;
+	default:
 		return (EINVAL);
-
-	rela = (const GElf_Rela *)reldata;
-	where = (char *)dest - dataoff + rela->r_offset;
-	addend = rela->r_addend;
-	rtype = GELF_R_TYPE(rela->r_info);
-	symidx = GELF_R_SYM(rela->r_info);
+	}
 
 	if (where < (char *)dest || where >= (char *)dest + len)
 		return (0);
 
-	switch(rtype) {
+	switch (rtype) {
 	case R_AARCH64_RELATIVE:
-		le64enc(where, relbase + addend);
+		addr = relbase + addend;
+		le64enc(where, addr);
 		break;
 	case R_AARCH64_ABS64:
 		addr = EF_SYMADDR(ef, symidx) + addend;
diff --git a/usr.sbin/kldxref/ef_amd64.c b/usr.sbin/kldxref/ef_amd64.c
index 729039daa509..fde032dcabc2 100644
--- a/usr.sbin/kldxref/ef_amd64.c
+++ b/usr.sbin/kldxref/ef_amd64.c
@@ -36,17 +36,16 @@
 #include "ef.h"
 
 /*
- * Apply relocations to the values we got from the file. `relbase' is the
- * target relocation address of the section, and `dataoff' is the target
- * relocation address of the data in `dest'.
+ * Apply relocations to the values obtained from the file. `relbase' is the
+ * target relocation address of the section, and `dataoff/len' is the region
+ * that is to be relocated, and has been copied to *dest
  */
 static int
 ef_amd64_reloc(struct elf_file *ef, const void *reldata, Elf_Type reltype,
     GElf_Addr relbase, GElf_Addr dataoff, size_t len, void *dest)
 {
 	char *where;
-	GElf_Addr val;
-	GElf_Addr addend, addr;
+	GElf_Addr addr, addend;
 	GElf_Size rtype, symidx;
 	const GElf_Rel *rel;
 	const GElf_Rela *rela;
@@ -54,14 +53,14 @@ ef_amd64_reloc(struct elf_file *ef, const void *reldata, Elf_Type reltype,
 	switch (reltype) {
 	case ELF_T_REL:
 		rel = (const GElf_Rel *)reldata;
-		where = (char *)dest + relbase + rel->r_offset - dataoff;
+		where = (char *)dest + (relbase + rel->r_offset - dataoff);
 		addend = 0;
 		rtype = GELF_R_TYPE(rel->r_info);
 		symidx = GELF_R_SYM(rel->r_info);
 		break;
 	case ELF_T_RELA:
 		rela = (const GElf_Rela *)reldata;
-		where = (char *)dest + relbase + rela->r_offset - dataoff;
+		where = (char *)dest + (relbase + rela->r_offset - dataoff);
 		addend = rela->r_addend;
 		rtype = GELF_R_TYPE(rela->r_info);
 		symidx = GELF_R_SYM(rela->r_info);
@@ -90,23 +89,20 @@ ef_amd64_reloc(struct elf_file *ef, const void *reldata, Elf_Type reltype,
 	case R_X86_64_NONE:	/* none */
 		break;
 	case R_X86_64_64:	/* S + A */
-		addr = EF_SYMADDR(ef, symidx);
-		val = addr + addend;
-		le64enc(where, val);
+		addr = EF_SYMADDR(ef, symidx) + addend;
+		le64enc(where, addr);
 		break;
 	case R_X86_64_32S:	/* S + A sign extend */
-		addr = EF_SYMADDR(ef, symidx);
-		val = (Elf32_Addr)(addr + addend);
-		le32enc(where, val);
+		addr = EF_SYMADDR(ef, symidx) + addend;
+		le32enc(where, addr);
 		break;
 	case R_X86_64_GLOB_DAT:	/* S */
 		addr = EF_SYMADDR(ef, symidx);
 		le64enc(where, addr);
 		break;
 	case R_X86_64_RELATIVE:	/* B + A */
-		addr = addend + relbase;
-		val = addr;
-		le64enc(where, val);
+		addr = relbase + addend;
+		le64enc(where, addr);
 		break;
 	default:
 		warnx("unhandled relocation type %d", (int)rtype);
diff --git a/usr.sbin/kldxref/ef_arm.c b/usr.sbin/kldxref/ef_arm.c
index 4b926839ee5d..cc5e265f821e 100644
--- a/usr.sbin/kldxref/ef_arm.c
+++ b/usr.sbin/kldxref/ef_arm.c
@@ -37,9 +37,9 @@
 #include "ef.h"
 
 /*
- * Apply relocations to the values we got from the file. `relbase' is the
- * target relocation address of the section, and `dataoff' is the target
- * relocation address of the data in `dest'.
+ * Apply relocations to the values obtained from the file. `relbase' is the
+ * target relocation address of the section, and `dataoff/len' is the region
+ * that is to be relocated, and has been copied to *dest
  */
 static int
 ef_arm_reloc(struct elf_file *ef, const void *reldata, Elf_Type reltype,
@@ -54,14 +54,14 @@ ef_arm_reloc(struct elf_file *ef, const void *reldata, Elf_Type reltype,
 	switch (reltype) {
 	case ELF_T_REL:
 		rel = (const GElf_Rel *)reldata;
-		where = (char *)dest + relbase + rel->r_offset - dataoff;
+		where = (char *)dest + (relbase + rel->r_offset - dataoff);
 		addend = 0;
 		rtype = GELF_R_TYPE(rel->r_info);
 		symidx = GELF_R_SYM(rel->r_info);
 		break;
 	case ELF_T_RELA:
 		rela = (const GElf_Rela *)reldata;
-		where = (char *)dest + relbase + rela->r_offset - dataoff;
+		where = (char *)dest + (relbase + rela->r_offset - dataoff);
 		addend = rela->r_addend;
 		rtype = GELF_R_TYPE(rela->r_info);
 		symidx = GELF_R_SYM(rela->r_info);
@@ -82,7 +82,7 @@ ef_arm_reloc(struct elf_file *ef, const void *reldata, Elf_Type reltype,
 		le32enc(where, addr);
 		break;
 	case R_ARM_RELATIVE:	/* B + A */
-		addr = addend + relbase;
+		addr = relbase + addend;
 		le32enc(where, addr);
 		break;
 	default:
diff --git a/usr.sbin/kldxref/ef_i386.c b/usr.sbin/kldxref/ef_i386.c
index e4f73877c430..962ed2bc0664 100644
--- a/usr.sbin/kldxref/ef_i386.c
+++ b/usr.sbin/kldxref/ef_i386.c
@@ -36,9 +36,9 @@
 #include "ef.h"
 
 /*
- * Apply relocations to the values we got from the file. `relbase' is the
- * target relocation address of the section, and `dataoff' is the target
- * relocation address of the data in `dest'.
+ * Apply relocations to the values obtained from the file. `relbase' is the
+ * target relocation address of the section, and `dataoff/len' is the region
+ * that is to be relocated, and has been copied to *dest
  */
 static int
 ef_i386_reloc(struct elf_file *ef, const void *reldata, Elf_Type reltype,
@@ -53,14 +53,14 @@ ef_i386_reloc(struct elf_file *ef, const void *reldata, Elf_Type reltype,
 	switch (reltype) {
 	case ELF_T_REL:
 		rel = (const GElf_Rel *)reldata;
-		where = (char *)dest + relbase + rel->r_offset - dataoff;
+		where = (char *)dest + (relbase + rel->r_offset - dataoff);
 		addend = 0;
 		rtype = GELF_R_TYPE(rel->r_info);
 		symidx = GELF_R_SYM(rel->r_info);
 		break;
 	case ELF_T_RELA:
 		rela = (const GElf_Rela *)reldata;
-		where = (char *)dest + relbase + rela->r_offset - dataoff;
+		where = (char *)dest + (relbase + rela->r_offset - dataoff);
 		addend = rela->r_addend;
 		rtype = GELF_R_TYPE(rela->r_info);
 		symidx = GELF_R_SYM(rela->r_info);
@@ -76,13 +76,12 @@ ef_i386_reloc(struct elf_file *ef, const void *reldata, Elf_Type reltype,
 		addend = le32dec(where);
 
 	switch (rtype) {
-	case R_386_RELATIVE:	/* A + B */
-		addr = addend + relbase;
+	case R_386_RELATIVE:	/* B + A */
+		addr = relbase + addend;
 		le32enc(where, addr);
 		break;
 	case R_386_32:	/* S + A - P */
-		addr = EF_SYMADDR(ef, symidx);
-		addr += addend;
+		addr = EF_SYMADDR(ef, symidx) + addend;
 		le32enc(where, addr);
 		break;
 	case R_386_GLOB_DAT:	/* S */
diff --git a/usr.sbin/kldxref/ef_mips.c b/usr.sbin/kldxref/ef_mips.c
index 60fd35390d7e..e4aeedb5c08b 100644
--- a/usr.sbin/kldxref/ef_mips.c
+++ b/usr.sbin/kldxref/ef_mips.c
@@ -39,32 +39,31 @@
 #include "ef.h"
 
 /*
- * Apply relocations to the values we got from the file. `relbase' is the
- * target relocation address of the section, and `dataoff' is the target
- * relocation address of the data in `dest'.
+ * Apply relocations to the values obtained from the file. `relbase' is the
+ * target relocation address of the section, and `dataoff/len' is the region
+ * that is to be relocated, and has been copied to *dest
  */
 static int
 ef_mips_reloc(struct elf_file *ef, const void *reldata, Elf_Type reltype,
     GElf_Addr relbase, GElf_Addr dataoff, size_t len, void *dest)
 {
 	char *where;
-	GElf_Addr val;
+	GElf_Addr addr, addend;
+	GElf_Size rtype, symidx;
 	const GElf_Rel *rel;
 	const GElf_Rela *rela;
-	GElf_Addr addend, addr;
-	GElf_Size rtype, symidx;
 
 	switch (reltype) {
 	case ELF_T_REL:
 		rel = (const GElf_Rel *)reldata;
-		where = (char *)dest + relbase + rel->r_offset - dataoff;
+		where = (char *)dest + (relbase + rel->r_offset - dataoff);
 		addend = 0;
 		rtype = GELF_R_TYPE(rel->r_info);
 		symidx = GELF_R_SYM(rel->r_info);
 		break;
 	case ELF_T_RELA:
 		rela = (const GElf_Rela *)reldata;
-		where = (char *)dest + relbase + rela->r_offset - dataoff;
+		where = (char *)dest + (relbase + rela->r_offset - dataoff);
 		addend = rela->r_addend;
 		rtype = GELF_R_TYPE(rela->r_info);
 		symidx = GELF_R_SYM(rela->r_info);
@@ -92,20 +91,18 @@ ef_mips_reloc(struct elf_file *ef, const void *reldata, Elf_Type reltype,
 
 	switch (rtype) {
 	case R_MIPS_64:		/* S + A */
-		addr = EF_SYMADDR(ef, symidx);
-		val = addr + addend;
+		addr = EF_SYMADDR(ef, symidx) + addend;
 		if (elf_encoding(ef) == ELFDATA2LSB)
-			le64enc(where, val);
+			le64enc(where, addr);
 		else
-			be64enc(where, val);
+			be64enc(where, addr);
 		break;
 	case R_MIPS_32:		/* S + A */
-		addr = EF_SYMADDR(ef, symidx);
-		val = addr + addend;
+		addr = EF_SYMADDR(ef, symidx) + addend;
 		if (elf_encoding(ef) == ELFDATA2LSB)
-			le32enc(where, val);
+			le32enc(where, addr);
 		else
-			be32enc(where, val);
+			be32enc(where, addr);
 		break;
 	default:
 		warnx("unhandled relocation type %d", (int)rtype);
diff --git a/usr.sbin/kldxref/ef_powerpc.c b/usr.sbin/kldxref/ef_powerpc.c
index ab33e170b488..f72cc1d85e20 100644
--- a/usr.sbin/kldxref/ef_powerpc.c
+++ b/usr.sbin/kldxref/ef_powerpc.c
@@ -40,48 +40,51 @@
  * target relocation address of the section, and `dataoff/len' is the region
  * that is to be relocated, and has been copied to *dest
  */
-int
+static int
 ef_ppc_reloc(struct elf_file *ef, const void *reldata, Elf_Type reltype,
     GElf_Addr relbase, GElf_Addr dataoff, size_t len, void *dest)
 {
 	char *where;
-	GElf_Addr addend, val;
+	GElf_Addr addr, addend;
 	GElf_Size rtype, symidx;
 	const GElf_Rela *rela;
 
-	if (reltype != ELF_T_RELA)
+	switch (reltype) {
+	case ELF_T_RELA:
+		rela = (const GElf_Rela *)reldata;
+		where = (char *)dest + (relbase + rela->r_offset - dataoff);
+		addend = rela->r_addend;
+		rtype = GELF_R_TYPE(rela->r_info);
+		symidx = GELF_R_SYM(rela->r_info);
+		break;
+	default:
 		return (EINVAL);
-
-	rela = (const GElf_Rela *)reldata;
-	where = (char *)dest - dataoff + rela->r_offset;
-	addend = rela->r_addend;
-	rtype = GELF_R_TYPE(rela->r_info);
-	symidx = GELF_R_SYM(rela->r_info);
+	}
 
 	if (where < (char *)dest || where >= (char *)dest + len)
 		return (0);
 
 	switch (rtype) {
 	case R_PPC_RELATIVE: /* word32|doubleword64 B + A */
-		val = relbase + addend;
+		addr = relbase + addend;
 		if (elf_class(ef) == ELFCLASS64) {
 			if (elf_encoding(ef) == ELFDATA2LSB)
-				le64enc(where, val);
+				le64enc(where, addr);
 			else
-				be64enc(where, val);
+				be64enc(where, addr);
 		} else
-			be32enc(where, val);
+			be32enc(where, addr);
 		break;
 	case R_PPC_ADDR32:	/* word32 S + A */
-		val = EF_SYMADDR(ef, symidx) + addend;
-		be32enc(where, val);
+		addr = EF_SYMADDR(ef, symidx) + addend;
+		be32enc(where, addr);
 		break;
 	case R_PPC64_ADDR64:	/* doubleword64 S + A */
-		val = EF_SYMADDR(ef, symidx) + addend;
+		addr = EF_SYMADDR(ef, symidx) + addend;
 		if (elf_encoding(ef) == ELFDATA2LSB)
-			le64enc(where, val);
+			le64enc(where, addr);
 		else
-			be64enc(where, val);
+			be64enc(where, addr);
 		break;
 	default:
 		warnx("unhandled relocation type %d", (int)rtype);
diff --git a/usr.sbin/kldxref/ef_riscv.c b/usr.sbin/kldxref/ef_riscv.c
index 38299a1e9b46..46b9b66bee58 100644
--- a/usr.sbin/kldxref/ef_riscv.c
+++ b/usr.sbin/kldxref/ef_riscv.c
@@ -38,19 +38,24 @@
 
 #include "ef.h"
 
-int
+/*
+ * Apply relocations to the values obtained from the file. `relbase' is the
+ * target relocation address of the section, and `dataoff/len' is the region
+ * that is to be relocated, and has been copied to *dest
+ */
+static int
 ef_riscv_reloc(struct elf_file *ef, const void *reldata, Elf_Type reltype,
     GElf_Addr relbase, GElf_Addr dataoff, size_t len, void *dest)
 {
 	char *where;
-	const GElf_Rela *rela;
-	GElf_Addr addend, addr;
+	GElf_Addr addr, addend;
 	GElf_Size rtype, symidx;
+	const GElf_Rela *rela;
 
 	switch (reltype) {
 	case ELF_T_RELA:
 		rela = (const GElf_Rela *)reldata;
-		where = (char *)dest + relbase + rela->r_offset - dataoff;
+		where = (char *)dest + (relbase + rela->r_offset - dataoff);
 		addend = rela->r_addend;
 		rtype = GELF_R_TYPE(rela->r_info);
 		symidx = GELF_R_SYM(rela->r_info);
@@ -68,7 +73,7 @@ ef_riscv_reloc(struct elf_file *ef, const void *reldata, Elf_Type reltype,
 		le64enc(where, addr);
 		break;
 	case R_RISCV_RELATIVE:	/* B + A */
-		addr = addend + relbase;
+		addr = relbase + addend;
 		le64enc(where, addr);
 		break;
 	default: