linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [RFC][PATCH 0/3] objtool: Support implicit addend relocations
@ 2020-05-27 16:42 Matt Helsley
  2020-05-27 16:42 ` [RFC][PATCH 1/3] objtool: Rename rela to reloc Matt Helsley
                   ` (2 more replies)
  0 siblings, 3 replies; 12+ messages in thread
From: Matt Helsley @ 2020-05-27 16:42 UTC (permalink / raw)
  To: linux-kernel; +Cc: Josh Poimboeuf, Peter Zijlstra, Steven Rostedt, Matt Helsley

Future tools that use objtool to process ELF object files may require
reading or even modifying relocations with implicit addends. This
series cleans up the naming of the relocation struct in objtool,
variable names, and function names to be consistent with a more
generic use rather than being specific to those applying explicit
addends.

From there we switch to the specification compliant method of
finding the section the relocations apply to and fall back to the
old naming-heuristic basis if that's not available.

Finally, add support for implicit addends. Note that we don't
completely convert the orc tools to work with both kinds of
relocations. I'm hoping to get feedback on whether it makes more
sense to convert it or leave it as-is.

Matt Helsley (3):
  objtool: Rename rela to reloc
  objtool: Find relocation base section using sh_info
  objtool: Add support for relocations without addends

 tools/objtool/arch.h            |   2 +-
 tools/objtool/arch/x86/decode.c |   2 +-
 tools/objtool/check.c           | 196 +++++++++++++-------------
 tools/objtool/check.h           |   2 +-
 tools/objtool/elf.c             | 237 +++++++++++++++++++++-----------
 tools/objtool/elf.h             |  27 ++--
 tools/objtool/orc_gen.c         |  46 +++----
 tools/objtool/special.c         |  28 ++--
 8 files changed, 311 insertions(+), 229 deletions(-)


base-commit: 7c0577f4e609f7278ebd6d21e2de82b42f110944
prerequisite-patch-id: 387905b1da8b1293e7736b28fcc1585583e3e7cf
prerequisite-patch-id: 2fd7ac6c4dfd717ab117fc771623c01040188b4e
prerequisite-patch-id: bfeefd995e3f80d6fa0edfa2205d98be31fbee4e
prerequisite-patch-id: abcb5732607ad17f4c99c06b8bb83c9db1b15c42
prerequisite-patch-id: 5179e659d828bed48051d365f669a8ba3a36c206
-- 
2.20.1


^ permalink raw reply	[flat|nested] 12+ messages in thread

* [RFC][PATCH 1/3] objtool: Rename rela to reloc
  2020-05-27 16:42 [RFC][PATCH 0/3] objtool: Support implicit addend relocations Matt Helsley
@ 2020-05-27 16:42 ` Matt Helsley
  2020-05-28 14:04   ` Josh Poimboeuf
  2020-05-27 16:42 ` [RFC][PATCH 2/3] objtool: Find relocation base section using sh_info Matt Helsley
  2020-05-27 16:42 ` [RFC][PATCH 3/3] objtool: Add support for relocations without addends Matt Helsley
  2 siblings, 1 reply; 12+ messages in thread
From: Matt Helsley @ 2020-05-27 16:42 UTC (permalink / raw)
  To: linux-kernel; +Cc: Josh Poimboeuf, Peter Zijlstra, Steven Rostedt, Matt Helsley

Before supporting additional relocation types rename the relevant
types and functions from "rela" to "reloc". This work can largely
be done with the following regex:

Notable exceptions include gelf_* library calls and
standard/expected section names which still use "rela" because
they encode the type of relocation expected. Also, keep "rela"
in the struct because it encodes a specify type of relocation
we currently expect.

It will eventually turn into a member of an anonymous union when a
susequent patch adds implicit addend, or "rel", relocation support.

Signed-off-by: Matt Helsley <mhelsley@vmware.com>
---
 tools/objtool/arch.h            |   2 +-
 tools/objtool/arch/x86/decode.c |   2 +-
 tools/objtool/check.c           | 196 ++++++++++++++++----------------
 tools/objtool/check.h           |   2 +-
 tools/objtool/elf.c             | 138 +++++++++++-----------
 tools/objtool/elf.h             |  22 ++--
 tools/objtool/orc_gen.c         |  46 ++++----
 tools/objtool/special.c         |  28 ++---
 8 files changed, 218 insertions(+), 218 deletions(-)

diff --git a/tools/objtool/arch.h b/tools/objtool/arch.h
index eda15a5a285e..d0969a9328c2 100644
--- a/tools/objtool/arch.h
+++ b/tools/objtool/arch.h
@@ -82,6 +82,6 @@ bool arch_callee_saved_reg(unsigned char reg);
 
 unsigned long arch_jump_destination(struct instruction *insn);
 
-unsigned long arch_dest_rela_offset(int addend);
+unsigned long arch_dest_reloc_offset(int addend);
 
 #endif /* _ARCH_H */
diff --git a/tools/objtool/arch/x86/decode.c b/tools/objtool/arch/x86/decode.c
index 4b504fc90bbb..fe83d4c92825 100644
--- a/tools/objtool/arch/x86/decode.c
+++ b/tools/objtool/arch/x86/decode.c
@@ -67,7 +67,7 @@ bool arch_callee_saved_reg(unsigned char reg)
 	}
 }
 
-unsigned long arch_dest_rela_offset(int addend)
+unsigned long arch_dest_reloc_offset(int addend)
 {
 	return addend + 4;
 }
diff --git a/tools/objtool/check.c b/tools/objtool/check.c
index 63d65a702900..28ce311ea90c 100644
--- a/tools/objtool/check.c
+++ b/tools/objtool/check.c
@@ -352,7 +352,7 @@ static struct instruction *find_last_insn(struct objtool_file *file,
 static int add_dead_ends(struct objtool_file *file)
 {
 	struct section *sec;
-	struct rela *rela;
+	struct reloc *reloc;
 	struct instruction *insn;
 
 	/*
@@ -370,24 +370,24 @@ static int add_dead_ends(struct objtool_file *file)
 	if (!sec)
 		goto reachable;
 
-	list_for_each_entry(rela, &sec->rela_list, list) {
-		if (rela->sym->type != STT_SECTION) {
+	list_for_each_entry(reloc, &sec->reloc_list, list) {
+		if (reloc->sym->type != STT_SECTION) {
 			WARN("unexpected relocation symbol type in %s", sec->name);
 			return -1;
 		}
-		insn = find_insn(file, rela->sym->sec, rela->addend);
+		insn = find_insn(file, reloc->sym->sec, reloc->addend);
 		if (insn)
 			insn = list_prev_entry(insn, list);
-		else if (rela->addend == rela->sym->sec->len) {
-			insn = find_last_insn(file, rela->sym->sec);
+		else if (reloc->addend == reloc->sym->sec->len) {
+			insn = find_last_insn(file, reloc->sym->sec);
 			if (!insn) {
 				WARN("can't find unreachable insn at %s+0x%x",
-				     rela->sym->sec->name, rela->addend);
+				     reloc->sym->sec->name, reloc->addend);
 				return -1;
 			}
 		} else {
 			WARN("can't find unreachable insn at %s+0x%x",
-			     rela->sym->sec->name, rela->addend);
+			     reloc->sym->sec->name, reloc->addend);
 			return -1;
 		}
 
@@ -405,24 +405,24 @@ static int add_dead_ends(struct objtool_file *file)
 	if (!sec)
 		return 0;
 
-	list_for_each_entry(rela, &sec->rela_list, list) {
-		if (rela->sym->type != STT_SECTION) {
+	list_for_each_entry(reloc, &sec->reloc_list, list) {
+		if (reloc->sym->type != STT_SECTION) {
 			WARN("unexpected relocation symbol type in %s", sec->name);
 			return -1;
 		}
-		insn = find_insn(file, rela->sym->sec, rela->addend);
+		insn = find_insn(file, reloc->sym->sec, reloc->addend);
 		if (insn)
 			insn = list_prev_entry(insn, list);
-		else if (rela->addend == rela->sym->sec->len) {
-			insn = find_last_insn(file, rela->sym->sec);
+		else if (reloc->addend == reloc->sym->sec->len) {
+			insn = find_last_insn(file, reloc->sym->sec);
 			if (!insn) {
 				WARN("can't find reachable insn at %s+0x%x",
-				     rela->sym->sec->name, rela->addend);
+				     reloc->sym->sec->name, reloc->addend);
 				return -1;
 			}
 		} else {
 			WARN("can't find reachable insn at %s+0x%x",
-			     rela->sym->sec->name, rela->addend);
+			     reloc->sym->sec->name, reloc->addend);
 			return -1;
 		}
 
@@ -440,26 +440,26 @@ static void add_ignores(struct objtool_file *file)
 	struct instruction *insn;
 	struct section *sec;
 	struct symbol *func;
-	struct rela *rela;
+	struct reloc *reloc;
 
 	sec = find_section_by_name(file->elf, ".rela.discard.func_stack_frame_non_standard");
 	if (!sec)
 		return;
 
-	list_for_each_entry(rela, &sec->rela_list, list) {
-		switch (rela->sym->type) {
+	list_for_each_entry(reloc, &sec->reloc_list, list) {
+		switch (reloc->sym->type) {
 		case STT_FUNC:
-			func = rela->sym;
+			func = reloc->sym;
 			break;
 
 		case STT_SECTION:
-			func = find_func_by_offset(rela->sym->sec, rela->addend);
+			func = find_func_by_offset(reloc->sym->sec, reloc->addend);
 			if (!func)
 				continue;
 			break;
 
 		default:
-			WARN("unexpected relocation symbol type in %s: %d", sec->name, rela->sym->type);
+			WARN("unexpected relocation symbol type in %s: %d", sec->name, reloc->sym->type);
 			continue;
 		}
 
@@ -557,20 +557,20 @@ static void add_uaccess_safe(struct objtool_file *file)
 static int add_ignore_alternatives(struct objtool_file *file)
 {
 	struct section *sec;
-	struct rela *rela;
+	struct reloc *reloc;
 	struct instruction *insn;
 
 	sec = find_section_by_name(file->elf, ".rela.discard.ignore_alts");
 	if (!sec)
 		return 0;
 
-	list_for_each_entry(rela, &sec->rela_list, list) {
-		if (rela->sym->type != STT_SECTION) {
+	list_for_each_entry(reloc, &sec->reloc_list, list) {
+		if (reloc->sym->type != STT_SECTION) {
 			WARN("unexpected relocation symbol type in %s", sec->name);
 			return -1;
 		}
 
-		insn = find_insn(file, rela->sym->sec, rela->addend);
+		insn = find_insn(file, reloc->sym->sec, reloc->addend);
 		if (!insn) {
 			WARN("bad .discard.ignore_alts entry");
 			return -1;
@@ -588,7 +588,7 @@ static int add_ignore_alternatives(struct objtool_file *file)
 static int add_jump_destinations(struct objtool_file *file)
 {
 	struct instruction *insn;
-	struct rela *rela;
+	struct reloc *reloc;
 	struct section *dest_sec;
 	unsigned long dest_off;
 
@@ -599,19 +599,19 @@ static int add_jump_destinations(struct objtool_file *file)
 		if (insn->ignore || insn->offset == FAKE_JUMP_OFFSET)
 			continue;
 
-		rela = find_rela_by_dest_range(file->elf, insn->sec,
+		reloc = find_reloc_by_dest_range(file->elf, insn->sec,
 					       insn->offset, insn->len);
-		if (!rela) {
+		if (!reloc) {
 			dest_sec = insn->sec;
 			dest_off = arch_jump_destination(insn);
-		} else if (rela->sym->type == STT_SECTION) {
-			dest_sec = rela->sym->sec;
-			dest_off = arch_dest_rela_offset(rela->addend);
-		} else if (rela->sym->sec->idx) {
-			dest_sec = rela->sym->sec;
-			dest_off = rela->sym->sym.st_value +
-				   arch_dest_rela_offset(rela->addend);
-		} else if (strstr(rela->sym->name, "_indirect_thunk_")) {
+		} else if (reloc->sym->type == STT_SECTION) {
+			dest_sec = reloc->sym->sec;
+			dest_off = arch_dest_reloc_offset(reloc->addend);
+		} else if (reloc->sym->sec->idx) {
+			dest_sec = reloc->sym->sec;
+			dest_off = reloc->sym->sym.st_value +
+				   arch_dest_reloc_offset(reloc->addend);
+		} else if (strstr(reloc->sym->name, "_indirect_thunk_")) {
 			/*
 			 * Retpoline jumps are really dynamic jumps in
 			 * disguise, so convert them accordingly.
@@ -625,7 +625,7 @@ static int add_jump_destinations(struct objtool_file *file)
 			continue;
 		} else {
 			/* external sibling call */
-			insn->call_dest = rela->sym;
+			insn->call_dest = reloc->sym;
 			continue;
 		}
 
@@ -701,15 +701,15 @@ static int add_call_destinations(struct objtool_file *file)
 {
 	struct instruction *insn;
 	unsigned long dest_off;
-	struct rela *rela;
+	struct reloc *reloc;
 
 	for_each_insn(file, insn) {
 		if (insn->type != INSN_CALL)
 			continue;
 
-		rela = find_rela_by_dest_range(file->elf, insn->sec,
+		reloc = find_reloc_by_dest_range(file->elf, insn->sec,
 					       insn->offset, insn->len);
-		if (!rela) {
+		if (!reloc) {
 			dest_off = arch_jump_destination(insn);
 			insn->call_dest = find_func_by_offset(insn->sec, dest_off);
 			if (!insn->call_dest)
@@ -729,19 +729,19 @@ static int add_call_destinations(struct objtool_file *file)
 				return -1;
 			}
 
-		} else if (rela->sym->type == STT_SECTION) {
-			dest_off = arch_dest_rela_offset(rela->addend);
-			insn->call_dest = find_func_by_offset(rela->sym->sec,
+		} else if (reloc->sym->type == STT_SECTION) {
+			dest_off = arch_dest_reloc_offset(reloc->addend);
+			insn->call_dest = find_func_by_offset(reloc->sym->sec,
 							      dest_off);
 			if (!insn->call_dest) {
 				WARN_FUNC("can't find call dest symbol at %s+0x%lx",
 					  insn->sec, insn->offset,
-					  rela->sym->sec->name,
+					  reloc->sym->sec->name,
 					  dest_off);
 				return -1;
 			}
 		} else
-			insn->call_dest = rela->sym;
+			insn->call_dest = reloc->sym;
 
 		/*
 		 * Whatever stack impact regular CALLs have, should be undone
@@ -849,7 +849,7 @@ static int handle_group_alt(struct objtool_file *file,
 		 */
 		if ((insn->offset != special_alt->new_off ||
 		    (insn->type != INSN_CALL && !is_static_jump(insn))) &&
-		    find_rela_by_dest_range(file->elf, insn->sec, insn->offset, insn->len)) {
+		    find_reloc_by_dest_range(file->elf, insn->sec, insn->offset, insn->len)) {
 
 			WARN_FUNC("unsupported relocation in alternatives section",
 				  insn->sec, insn->offset);
@@ -995,34 +995,34 @@ static int add_special_section_alts(struct objtool_file *file)
 }
 
 static int add_jump_table(struct objtool_file *file, struct instruction *insn,
-			    struct rela *table)
+			    struct reloc *table)
 {
-	struct rela *rela = table;
+	struct reloc *reloc = table;
 	struct instruction *dest_insn;
 	struct alternative *alt;
 	struct symbol *pfunc = insn->func->pfunc;
 	unsigned int prev_offset = 0;
 
 	/*
-	 * Each @rela is a switch table relocation which points to the target
+	 * Each @reloc is a switch table relocation which points to the target
 	 * instruction.
 	 */
-	list_for_each_entry_from(rela, &table->sec->rela_list, list) {
+	list_for_each_entry_from(reloc, &table->sec->reloc_list, list) {
 
 		/* Check for the end of the table: */
-		if (rela != table && rela->jump_table_start)
+		if (reloc != table && reloc->jump_table_start)
 			break;
 
 		/* Make sure the table entries are consecutive: */
-		if (prev_offset && rela->offset != prev_offset + 8)
+		if (prev_offset && reloc->offset != prev_offset + 8)
 			break;
 
 		/* Detect function pointers from contiguous objects: */
-		if (rela->sym->sec == pfunc->sec &&
-		    rela->addend == pfunc->offset)
+		if (reloc->sym->sec == pfunc->sec &&
+		    reloc->addend == pfunc->offset)
 			break;
 
-		dest_insn = find_insn(file, rela->sym->sec, rela->addend);
+		dest_insn = find_insn(file, reloc->sym->sec, reloc->addend);
 		if (!dest_insn)
 			break;
 
@@ -1038,7 +1038,7 @@ static int add_jump_table(struct objtool_file *file, struct instruction *insn,
 
 		alt->insn = dest_insn;
 		list_add_tail(&alt->list, &insn->alts);
-		prev_offset = rela->offset;
+		prev_offset = reloc->offset;
 	}
 
 	if (!prev_offset) {
@@ -1093,11 +1093,11 @@ static int add_jump_table(struct objtool_file *file, struct instruction *insn,
  *
  *    NOTE: RETPOLINE made it harder still to decode dynamic jumps.
  */
-static struct rela *find_jump_table(struct objtool_file *file,
+static struct reloc *find_jump_table(struct objtool_file *file,
 				      struct symbol *func,
 				      struct instruction *insn)
 {
-	struct rela *text_rela, *table_rela;
+	struct reloc *text_reloc, *table_reloc;
 	struct instruction *dest_insn, *orig_insn = insn;
 	struct section *table_sec;
 	unsigned long table_offset;
@@ -1122,16 +1122,16 @@ static struct rela *find_jump_table(struct objtool_file *file,
 		    break;
 
 		/* look for a relocation which references .rodata */
-		text_rela = find_rela_by_dest_range(file->elf, insn->sec,
+		text_reloc = find_reloc_by_dest_range(file->elf, insn->sec,
 						    insn->offset, insn->len);
-		if (!text_rela || text_rela->sym->type != STT_SECTION ||
-		    !text_rela->sym->sec->rodata)
+		if (!text_reloc || text_reloc->sym->type != STT_SECTION ||
+		    !text_reloc->sym->sec->rodata)
 			continue;
 
-		table_offset = text_rela->addend;
-		table_sec = text_rela->sym->sec;
+		table_offset = text_reloc->addend;
+		table_sec = text_reloc->sym->sec;
 
-		if (text_rela->type == R_X86_64_PC32)
+		if (text_reloc->type == R_X86_64_PC32)
 			table_offset += 4;
 
 		/*
@@ -1148,14 +1148,14 @@ static struct rela *find_jump_table(struct objtool_file *file,
 			continue;
 
 		/*
-		 * Each table entry has a rela associated with it.  The rela
+		 * Each table entry has a reloc associated with it.  The reloc
 		 * should reference text in the same function as the original
 		 * instruction.
 		 */
-		table_rela = find_rela_by_dest(file->elf, table_sec, table_offset);
-		if (!table_rela)
+		table_reloc = find_reloc_by_dest(file->elf, table_sec, table_offset);
+		if (!table_reloc)
 			continue;
-		dest_insn = find_insn(file, table_rela->sym->sec, table_rela->addend);
+		dest_insn = find_insn(file, table_reloc->sym->sec, table_reloc->addend);
 		if (!dest_insn || !dest_insn->func || dest_insn->func->pfunc != func)
 			continue;
 
@@ -1164,10 +1164,10 @@ static struct rela *find_jump_table(struct objtool_file *file,
 		 * indicates a rare GCC quirk/bug which can leave dead code
 		 * behind.
 		 */
-		if (text_rela->type == R_X86_64_PC32)
+		if (text_reloc->type == R_X86_64_PC32)
 			file->ignore_unreachables = true;
 
-		return table_rela;
+		return table_reloc;
 	}
 
 	return NULL;
@@ -1181,7 +1181,7 @@ static void mark_func_jump_tables(struct objtool_file *file,
 				    struct symbol *func)
 {
 	struct instruction *insn, *last = NULL;
-	struct rela *rela;
+	struct reloc *reloc;
 
 	func_for_each_insn(file, func, insn) {
 		if (!last)
@@ -1204,10 +1204,10 @@ static void mark_func_jump_tables(struct objtool_file *file,
 		if (insn->type != INSN_JUMP_DYNAMIC)
 			continue;
 
-		rela = find_jump_table(file, func, insn);
-		if (rela) {
-			rela->jump_table_start = true;
-			insn->jump_table = rela;
+		reloc = find_jump_table(file, func, insn);
+		if (reloc) {
+			reloc->jump_table_start = true;
+			insn->jump_table = reloc;
 		}
 	}
 }
@@ -1261,8 +1261,8 @@ static int add_jump_table_alts(struct objtool_file *file)
 
 static int read_unwind_hints(struct objtool_file *file)
 {
-	struct section *sec, *relasec;
-	struct rela *rela;
+	struct section *sec, *relocsec;
+	struct reloc *reloc;
 	struct unwind_hint *hint;
 	struct instruction *insn;
 	struct cfi_reg *cfa;
@@ -1272,8 +1272,8 @@ static int read_unwind_hints(struct objtool_file *file)
 	if (!sec)
 		return 0;
 
-	relasec = sec->rela;
-	if (!relasec) {
+	relocsec = sec->reloc;
+	if (!relocsec) {
 		WARN("missing .rela.discard.unwind_hints section");
 		return -1;
 	}
@@ -1288,13 +1288,13 @@ static int read_unwind_hints(struct objtool_file *file)
 	for (i = 0; i < sec->len / sizeof(struct unwind_hint); i++) {
 		hint = (struct unwind_hint *)sec->data->d_buf + i;
 
-		rela = find_rela_by_dest(file->elf, sec, i * sizeof(*hint));
-		if (!rela) {
-			WARN("can't find rela for unwind_hints[%d]", i);
+		reloc = find_reloc_by_dest(file->elf, sec, i * sizeof(*hint));
+		if (!reloc) {
+			WARN("can't find reloc for unwind_hints[%d]", i);
 			return -1;
 		}
 
-		insn = find_insn(file, rela->sym->sec, rela->addend);
+		insn = find_insn(file, reloc->sym->sec, reloc->addend);
 		if (!insn) {
 			WARN("can't find insn for unwind_hints[%d]", i);
 			return -1;
@@ -1352,19 +1352,19 @@ static int read_retpoline_hints(struct objtool_file *file)
 {
 	struct section *sec;
 	struct instruction *insn;
-	struct rela *rela;
+	struct reloc *reloc;
 
 	sec = find_section_by_name(file->elf, ".rela.discard.retpoline_safe");
 	if (!sec)
 		return 0;
 
-	list_for_each_entry(rela, &sec->rela_list, list) {
-		if (rela->sym->type != STT_SECTION) {
+	list_for_each_entry(reloc, &sec->reloc_list, list) {
+		if (reloc->sym->type != STT_SECTION) {
 			WARN("unexpected relocation symbol type in %s", sec->name);
 			return -1;
 		}
 
-		insn = find_insn(file, rela->sym->sec, rela->addend);
+		insn = find_insn(file, reloc->sym->sec, reloc->addend);
 		if (!insn) {
 			WARN("bad .discard.retpoline_safe entry");
 			return -1;
@@ -1387,19 +1387,19 @@ static int read_instr_hints(struct objtool_file *file)
 {
 	struct section *sec;
 	struct instruction *insn;
-	struct rela *rela;
+	struct reloc *reloc;
 
 	sec = find_section_by_name(file->elf, ".rela.discard.instr_end");
 	if (!sec)
 		return 0;
 
-	list_for_each_entry(rela, &sec->rela_list, list) {
-		if (rela->sym->type != STT_SECTION) {
+	list_for_each_entry(reloc, &sec->reloc_list, list) {
+		if (reloc->sym->type != STT_SECTION) {
 			WARN("unexpected relocation symbol type in %s", sec->name);
 			return -1;
 		}
 
-		insn = find_insn(file, rela->sym->sec, rela->addend);
+		insn = find_insn(file, reloc->sym->sec, reloc->addend);
 		if (!insn) {
 			WARN("bad .discard.instr_end entry");
 			return -1;
@@ -1412,13 +1412,13 @@ static int read_instr_hints(struct objtool_file *file)
 	if (!sec)
 		return 0;
 
-	list_for_each_entry(rela, &sec->rela_list, list) {
-		if (rela->sym->type != STT_SECTION) {
+	list_for_each_entry(reloc, &sec->reloc_list, list) {
+		if (reloc->sym->type != STT_SECTION) {
 			WARN("unexpected relocation symbol type in %s", sec->name);
 			return -1;
 		}
 
-		insn = find_insn(file, rela->sym->sec, rela->addend);
+		insn = find_insn(file, reloc->sym->sec, reloc->addend);
 		if (!insn) {
 			WARN("bad .discard.instr_begin entry");
 			return -1;
@@ -1434,22 +1434,22 @@ static int read_intra_function_calls(struct objtool_file *file)
 {
 	struct instruction *insn;
 	struct section *sec;
-	struct rela *rela;
+	struct reloc *reloc;
 
 	sec = find_section_by_name(file->elf, ".rela.discard.intra_function_calls");
 	if (!sec)
 		return 0;
 
-	list_for_each_entry(rela, &sec->rela_list, list) {
+	list_for_each_entry(reloc, &sec->reloc_list, list) {
 		unsigned long dest_off;
 
-		if (rela->sym->type != STT_SECTION) {
+		if (reloc->sym->type != STT_SECTION) {
 			WARN("unexpected relocation symbol type in %s",
 			     sec->name);
 			return -1;
 		}
 
-		insn = find_insn(file, rela->sym->sec, rela->addend);
+		insn = find_insn(file, reloc->sym->sec, reloc->addend);
 		if (!insn) {
 			WARN("bad .discard.intra_function_call entry");
 			return -1;
diff --git a/tools/objtool/check.h b/tools/objtool/check.h
index 906b5210f7ca..061aa96e15d3 100644
--- a/tools/objtool/check.h
+++ b/tools/objtool/check.h
@@ -37,7 +37,7 @@ struct instruction {
 	struct symbol *call_dest;
 	struct instruction *jump_dest;
 	struct instruction *first_jump_src;
-	struct rela *jump_table;
+	struct reloc *jump_table;
 	struct list_head alts;
 	struct symbol *func;
 	struct list_head stack_ops;
diff --git a/tools/objtool/elf.c b/tools/objtool/elf.c
index 84225679f96d..6fb9f83f7f66 100644
--- a/tools/objtool/elf.c
+++ b/tools/objtool/elf.c
@@ -228,26 +228,26 @@ struct symbol *find_symbol_by_name(const struct elf *elf, const char *name)
 	return NULL;
 }
 
-struct rela *find_rela_by_dest_range(const struct elf *elf, struct section *sec,
+struct reloc *find_reloc_by_dest_range(const struct elf *elf, struct section *sec,
 				     unsigned long offset, unsigned int len)
 {
-	struct rela *rela, *r = NULL;
+	struct reloc *reloc, *r = NULL;
 	unsigned long o;
 
-	if (!sec->rela)
+	if (!sec->reloc)
 		return NULL;
 
-	sec = sec->rela;
+	sec = sec->reloc;
 
 	for_offset_range(o, offset, offset + len) {
-		elf_hash_for_each_possible(elf->rela_hash, rela, hash,
+		elf_hash_for_each_possible(elf->reloc_hash, reloc, hash,
 				       sec_offset_hash(sec, o)) {
-			if (rela->sec != sec)
+			if (reloc->sec != sec)
 				continue;
 
-			if (rela->offset >= offset && rela->offset < offset + len) {
-				if (!r || rela->offset < r->offset)
-					r = rela;
+			if (reloc->offset >= offset && reloc->offset < offset + len) {
+				if (!r || reloc->offset < r->offset)
+					r = reloc;
 			}
 		}
 		if (r)
@@ -257,9 +257,9 @@ struct rela *find_rela_by_dest_range(const struct elf *elf, struct section *sec,
 	return NULL;
 }
 
-struct rela *find_rela_by_dest(const struct elf *elf, struct section *sec, unsigned long offset)
+struct reloc *find_reloc_by_dest(const struct elf *elf, struct section *sec, unsigned long offset)
 {
-	return find_rela_by_dest_range(elf, sec, offset, 1);
+	return find_reloc_by_dest_range(elf, sec, offset, 1);
 }
 
 static int read_sections(struct elf *elf)
@@ -288,7 +288,7 @@ static int read_sections(struct elf *elf)
 		memset(sec, 0, sizeof(*sec));
 
 		INIT_LIST_HEAD(&sec->symbol_list);
-		INIT_LIST_HEAD(&sec->rela_list);
+		INIT_LIST_HEAD(&sec->reloc_list);
 
 		s = elf_getscn(elf->elf, i);
 		if (!s) {
@@ -482,21 +482,21 @@ static int read_symbols(struct elf *elf)
 	return -1;
 }
 
-void elf_add_rela(struct elf *elf, struct rela *rela)
+void elf_add_reloc(struct elf *elf, struct reloc *reloc)
 {
-	struct section *sec = rela->sec;
+	struct section *sec = reloc->sec;
 
-	list_add_tail(&rela->list, &sec->rela_list);
-	elf_hash_add(elf->rela_hash, &rela->hash, rela_hash(rela));
+	list_add_tail(&reloc->list, &sec->reloc_list);
+	elf_hash_add(elf->reloc_hash, &reloc->hash, reloc_hash(reloc));
 }
 
-static int read_relas(struct elf *elf)
+static int read_relocs(struct elf *elf)
 {
 	struct section *sec;
-	struct rela *rela;
+	struct reloc *reloc;
 	int i;
 	unsigned int symndx;
-	unsigned long nr_rela, max_rela = 0, tot_rela = 0;
+	unsigned long nr_reloc, max_reloc = 0, tot_reloc = 0;
 
 	list_for_each_entry(sec, &elf->sections, list) {
 		if (sec->sh.sh_type != SHT_RELA)
@@ -504,49 +504,49 @@ static int read_relas(struct elf *elf)
 
 		sec->base = find_section_by_name(elf, sec->name + 5);
 		if (!sec->base) {
-			WARN("can't find base section for rela section %s",
+			WARN("can't find base section for reloc section %s",
 			     sec->name);
 			return -1;
 		}
 
-		sec->base->rela = sec;
+		sec->base->reloc = sec;
 
-		nr_rela = 0;
+		nr_reloc = 0;
 		for (i = 0; i < sec->sh.sh_size / sec->sh.sh_entsize; i++) {
-			rela = malloc(sizeof(*rela));
-			if (!rela) {
+			reloc = malloc(sizeof(*reloc));
+			if (!reloc) {
 				perror("malloc");
 				return -1;
 			}
-			memset(rela, 0, sizeof(*rela));
+			memset(reloc, 0, sizeof(*reloc));
 
-			if (!gelf_getrela(sec->data, i, &rela->rela)) {
+			if (!gelf_getrela(sec->data, i, &reloc->rela)) {
 				WARN_ELF("gelf_getrela");
 				return -1;
 			}
 
-			rela->type = GELF_R_TYPE(rela->rela.r_info);
-			rela->addend = rela->rela.r_addend;
-			rela->offset = rela->rela.r_offset;
-			symndx = GELF_R_SYM(rela->rela.r_info);
-			rela->sym = find_symbol_by_index(elf, symndx);
-			rela->sec = sec;
-			if (!rela->sym) {
-				WARN("can't find rela entry symbol %d for %s",
+			reloc->type = GELF_R_TYPE(reloc->rela.r_info);
+			reloc->addend = reloc->rela.r_addend;
+			reloc->offset = reloc->rela.r_offset;
+			symndx = GELF_R_SYM(reloc->rela.r_info);
+			reloc->sym = find_symbol_by_index(elf, symndx);
+			reloc->sec = sec;
+			if (!reloc->sym) {
+				WARN("can't find reloc entry symbol %d for %s",
 				     symndx, sec->name);
 				return -1;
 			}
 
-			elf_add_rela(elf, rela);
-			nr_rela++;
+			elf_add_reloc(elf, reloc);
+			nr_reloc++;
 		}
-		max_rela = max(max_rela, nr_rela);
-		tot_rela += nr_rela;
+		max_reloc = max(max_reloc, nr_reloc);
+		tot_reloc += nr_reloc;
 	}
 
 	if (stats) {
-		printf("max_rela: %lu\n", max_rela);
-		printf("tot_rela: %lu\n", tot_rela);
+		printf("max_reloc: %lu\n", max_reloc);
+		printf("tot_reloc: %lu\n", tot_reloc);
 	}
 
 	return 0;
@@ -572,7 +572,7 @@ struct elf *elf_open_read(const char *name, int flags)
 	elf_hash_init(elf->symbol_name_hash);
 	elf_hash_init(elf->section_hash);
 	elf_hash_init(elf->section_name_hash);
-	elf_hash_init(elf->rela_hash);
+	elf_hash_init(elf->reloc_hash);
 
 	elf->fd = open(name, flags);
 	if (elf->fd == -1) {
@@ -605,7 +605,7 @@ struct elf *elf_open_read(const char *name, int flags)
 	if (read_symbols(elf))
 		goto err;
 
-	if (read_relas(elf))
+	if (read_relocs(elf))
 		goto err;
 
 	return elf;
@@ -631,7 +631,7 @@ struct section *elf_create_section(struct elf *elf, const char *name,
 	memset(sec, 0, sizeof(*sec));
 
 	INIT_LIST_HEAD(&sec->symbol_list);
-	INIT_LIST_HEAD(&sec->rela_list);
+	INIT_LIST_HEAD(&sec->reloc_list);
 
 	s = elf_newscn(elf->elf);
 	if (!s) {
@@ -716,25 +716,25 @@ struct section *elf_create_section(struct elf *elf, const char *name,
 	return sec;
 }
 
-struct section *elf_create_rela_section(struct elf *elf, struct section *base)
+struct section *elf_create_reloc_section(struct elf *elf, struct section *base)
 {
-	char *relaname;
+	char *relocname;
 	struct section *sec;
 
-	relaname = malloc(strlen(base->name) + strlen(".rela") + 1);
-	if (!relaname) {
+	relocname = malloc(strlen(base->name) + strlen(".rela") + 1);
+	if (!relocname) {
 		perror("malloc");
 		return NULL;
 	}
-	strcpy(relaname, ".rela");
-	strcat(relaname, base->name);
+	strcpy(relocname, ".rela");
+	strcat(relocname, base->name);
 
-	sec = elf_create_section(elf, relaname, sizeof(GElf_Rela), 0);
-	free(relaname);
+	sec = elf_create_section(elf, relocname, sizeof(GElf_Rela), 0);
+	free(relocname);
 	if (!sec)
 		return NULL;
 
-	base->rela = sec;
+	base->reloc = sec;
 	sec->base = base;
 
 	sec->sh.sh_type = SHT_RELA;
@@ -746,33 +746,33 @@ struct section *elf_create_rela_section(struct elf *elf, struct section *base)
 	return sec;
 }
 
-int elf_rebuild_rela_section(struct section *sec)
+int elf_rebuild_reloc_section(struct section *sec)
 {
-	struct rela *rela;
+	struct reloc *reloc;
 	int nr, idx = 0, size;
-	GElf_Rela *relas;
+	GElf_Rela *relocs;
 
 	nr = 0;
-	list_for_each_entry(rela, &sec->rela_list, list)
+	list_for_each_entry(reloc, &sec->reloc_list, list)
 		nr++;
 
-	size = nr * sizeof(*relas);
-	relas = malloc(size);
-	if (!relas) {
+	size = nr * sizeof(*relocs);
+	relocs = malloc(size);
+	if (!relocs) {
 		perror("malloc");
 		return -1;
 	}
 
-	sec->data->d_buf = relas;
+	sec->data->d_buf = relocs;
 	sec->data->d_size = size;
 
 	sec->sh.sh_size = size;
 
 	idx = 0;
-	list_for_each_entry(rela, &sec->rela_list, list) {
-		relas[idx].r_offset = rela->offset;
-		relas[idx].r_addend = rela->addend;
-		relas[idx].r_info = GELF_R_INFO(rela->sym->idx, rela->type);
+	list_for_each_entry(reloc, &sec->reloc_list, list) {
+		relocs[idx].r_offset = reloc->offset;
+		relocs[idx].r_addend = reloc->addend;
+		relocs[idx].r_info = GELF_R_INFO(reloc->sym->idx, reloc->type);
 		idx++;
 	}
 
@@ -815,7 +815,7 @@ void elf_close(struct elf *elf)
 {
 	struct section *sec, *tmpsec;
 	struct symbol *sym, *tmpsym;
-	struct rela *rela, *tmprela;
+	struct reloc *reloc, *tmpreloc;
 
 	if (elf->elf)
 		elf_end(elf->elf);
@@ -829,10 +829,10 @@ void elf_close(struct elf *elf)
 			hash_del(&sym->hash);
 			free(sym);
 		}
-		list_for_each_entry_safe(rela, tmprela, &sec->rela_list, list) {
-			list_del(&rela->list);
-			hash_del(&rela->hash);
-			free(rela);
+		list_for_each_entry_safe(reloc, tmpreloc, &sec->reloc_list, list) {
+			list_del(&reloc->list);
+			hash_del(&reloc->hash);
+			free(reloc);
 		}
 		list_del(&sec->list);
 		free(sec);
diff --git a/tools/objtool/elf.h b/tools/objtool/elf.h
index f4fe1d6ea392..6ad759fd778e 100644
--- a/tools/objtool/elf.h
+++ b/tools/objtool/elf.h
@@ -32,8 +32,8 @@ struct section {
 	GElf_Shdr sh;
 	struct rb_root symbol_tree;
 	struct list_head symbol_list;
-	struct list_head rela_list;
-	struct section *base, *rela;
+	struct list_head reloc_list;
+	struct section *base, *reloc;
 	struct symbol *sym;
 	Elf_Data *data;
 	char *name;
@@ -58,7 +58,7 @@ struct symbol {
 	bool uaccess_safe;
 };
 
-struct rela {
+struct reloc {
 	struct list_head list;
 	struct hlist_node hash;
 	GElf_Rela rela;
@@ -82,7 +82,7 @@ struct elf {
 	DECLARE_HASHTABLE(symbol_name_hash, ELF_HASH_BITS);
 	DECLARE_HASHTABLE(section_hash, ELF_HASH_BITS);
 	DECLARE_HASHTABLE(section_name_hash, ELF_HASH_BITS);
-	DECLARE_HASHTABLE(rela_hash, ELF_HASH_BITS);
+	DECLARE_HASHTABLE(reloc_hash, ELF_HASH_BITS);
 };
 
 #define OFFSET_STRIDE_BITS	4
@@ -109,15 +109,15 @@ static inline u32 sec_offset_hash(struct section *sec, unsigned long offset)
 	return ol;
 }
 
-static inline u32 rela_hash(struct rela *rela)
+static inline u32 reloc_hash(struct reloc *reloc)
 {
-	return sec_offset_hash(rela->sec, rela->offset);
+	return sec_offset_hash(reloc->sec, reloc->offset);
 }
 
 struct elf *elf_open_read(const char *name, int flags);
 struct section *elf_create_section(struct elf *elf, const char *name, size_t entsize, int nr);
-struct section *elf_create_rela_section(struct elf *elf, struct section *base);
-void elf_add_rela(struct elf *elf, struct rela *rela);
+struct section *elf_create_reloc_section(struct elf *elf, struct section *base);
+void elf_add_reloc(struct elf *elf, struct reloc *reloc);
 int elf_write(const struct elf *elf);
 void elf_close(struct elf *elf);
 
@@ -126,11 +126,11 @@ struct symbol *find_func_by_offset(struct section *sec, unsigned long offset);
 struct symbol *find_symbol_by_offset(struct section *sec, unsigned long offset);
 struct symbol *find_symbol_by_name(const struct elf *elf, const char *name);
 struct symbol *find_symbol_containing(const struct section *sec, unsigned long offset);
-struct rela *find_rela_by_dest(const struct elf *elf, struct section *sec, unsigned long offset);
-struct rela *find_rela_by_dest_range(const struct elf *elf, struct section *sec,
+struct reloc *find_reloc_by_dest(const struct elf *elf, struct section *sec, unsigned long offset);
+struct reloc *find_reloc_by_dest_range(const struct elf *elf, struct section *sec,
 				     unsigned long offset, unsigned int len);
 struct symbol *find_func_containing(struct section *sec, unsigned long offset);
-int elf_rebuild_rela_section(struct section *sec);
+int elf_rebuild_reloc_section(struct section *sec);
 
 #define for_each_sec(file, sec)						\
 	list_for_each_entry(sec, &file->elf->sections, list)
diff --git a/tools/objtool/orc_gen.c b/tools/objtool/orc_gen.c
index c9549988121a..93c720baea66 100644
--- a/tools/objtool/orc_gen.c
+++ b/tools/objtool/orc_gen.c
@@ -80,56 +80,56 @@ int create_orc(struct objtool_file *file)
 	return 0;
 }
 
-static int create_orc_entry(struct elf *elf, struct section *u_sec, struct section *ip_relasec,
+static int create_orc_entry(struct elf *elf, struct section *u_sec, struct section *ip_relocsec,
 				unsigned int idx, struct section *insn_sec,
 				unsigned long insn_off, struct orc_entry *o)
 {
 	struct orc_entry *orc;
-	struct rela *rela;
+	struct reloc *reloc;
 
 	/* populate ORC data */
 	orc = (struct orc_entry *)u_sec->data->d_buf + idx;
 	memcpy(orc, o, sizeof(*orc));
 
-	/* populate rela for ip */
-	rela = malloc(sizeof(*rela));
-	if (!rela) {
+	/* populate reloc for ip */
+	reloc = malloc(sizeof(*reloc));
+	if (!reloc) {
 		perror("malloc");
 		return -1;
 	}
-	memset(rela, 0, sizeof(*rela));
+	memset(reloc, 0, sizeof(*reloc));
 
 	if (insn_sec->sym) {
-		rela->sym = insn_sec->sym;
-		rela->addend = insn_off;
+		reloc->sym = insn_sec->sym;
+		reloc->addend = insn_off;
 	} else {
 		/*
 		 * The Clang assembler doesn't produce section symbols, so we
 		 * have to reference the function symbol instead:
 		 */
-		rela->sym = find_symbol_containing(insn_sec, insn_off);
-		if (!rela->sym) {
+		reloc->sym = find_symbol_containing(insn_sec, insn_off);
+		if (!reloc->sym) {
 			/*
 			 * Hack alert.  This happens when we need to reference
 			 * the NOP pad insn immediately after the function.
 			 */
-			rela->sym = find_symbol_containing(insn_sec,
+			reloc->sym = find_symbol_containing(insn_sec,
 							   insn_off - 1);
 		}
-		if (!rela->sym) {
+		if (!reloc->sym) {
 			WARN("missing symbol for insn at offset 0x%lx\n",
 			     insn_off);
 			return -1;
 		}
 
-		rela->addend = insn_off - rela->sym->offset;
+		reloc->addend = insn_off - reloc->sym->offset;
 	}
 
-	rela->type = R_X86_64_PC32;
-	rela->offset = idx * sizeof(int);
-	rela->sec = ip_relasec;
+	reloc->type = R_X86_64_PC32;
+	reloc->offset = idx * sizeof(int);
+	reloc->sec = ip_relocsec;
 
-	elf_add_rela(elf, rela);
+	elf_add_reloc(elf, reloc);
 
 	return 0;
 }
@@ -137,7 +137,7 @@ static int create_orc_entry(struct elf *elf, struct section *u_sec, struct secti
 int create_orc_sections(struct objtool_file *file)
 {
 	struct instruction *insn, *prev_insn;
-	struct section *sec, *u_sec, *ip_relasec;
+	struct section *sec, *u_sec, *ip_relocsec;
 	unsigned int idx;
 
 	struct orc_entry empty = {
@@ -181,8 +181,8 @@ int create_orc_sections(struct objtool_file *file)
 	if (!sec)
 		return -1;
 
-	ip_relasec = elf_create_rela_section(file->elf, sec);
-	if (!ip_relasec)
+	ip_relocsec = elf_create_reloc_section(file->elf, sec);
+	if (!ip_relocsec)
 		return -1;
 
 	/* create .orc_unwind section */
@@ -200,7 +200,7 @@ int create_orc_sections(struct objtool_file *file)
 			if (!prev_insn || memcmp(&insn->orc, &prev_insn->orc,
 						 sizeof(struct orc_entry))) {
 
-				if (create_orc_entry(file->elf, u_sec, ip_relasec, idx,
+				if (create_orc_entry(file->elf, u_sec, ip_relocsec, idx,
 						     insn->sec, insn->offset,
 						     &insn->orc))
 					return -1;
@@ -212,7 +212,7 @@ int create_orc_sections(struct objtool_file *file)
 
 		/* section terminator */
 		if (prev_insn) {
-			if (create_orc_entry(file->elf, u_sec, ip_relasec, idx,
+			if (create_orc_entry(file->elf, u_sec, ip_relocsec, idx,
 					     prev_insn->sec,
 					     prev_insn->offset + prev_insn->len,
 					     &empty))
@@ -222,7 +222,7 @@ int create_orc_sections(struct objtool_file *file)
 		}
 	}
 
-	if (elf_rebuild_rela_section(ip_relasec))
+	if (elf_rebuild_reloc_section(ip_relocsec))
 		return -1;
 
 	return 0;
diff --git a/tools/objtool/special.c b/tools/objtool/special.c
index e74e0189de22..e893f1e48e44 100644
--- a/tools/objtool/special.c
+++ b/tools/objtool/special.c
@@ -72,7 +72,7 @@ static int get_alt_entry(struct elf *elf, struct special_entry *entry,
 			 struct section *sec, int idx,
 			 struct special_alt *alt)
 {
-	struct rela *orig_rela, *new_rela;
+	struct reloc *orig_reloc, *new_reloc;
 	unsigned long offset;
 
 	offset = idx * entry->size;
@@ -118,30 +118,30 @@ static int get_alt_entry(struct elf *elf, struct special_entry *entry,
 		}
 	}
 
-	orig_rela = find_rela_by_dest(elf, sec, offset + entry->orig);
-	if (!orig_rela) {
-		WARN_FUNC("can't find orig rela", sec, offset + entry->orig);
+	orig_reloc = find_reloc_by_dest(elf, sec, offset + entry->orig);
+	if (!orig_reloc) {
+		WARN_FUNC("can't find orig reloc", sec, offset + entry->orig);
 		return -1;
 	}
-	if (orig_rela->sym->type != STT_SECTION) {
-		WARN_FUNC("don't know how to handle non-section rela symbol %s",
-			   sec, offset + entry->orig, orig_rela->sym->name);
+	if (orig_reloc->sym->type != STT_SECTION) {
+		WARN_FUNC("don't know how to handle non-section reloc symbol %s",
+			   sec, offset + entry->orig, orig_reloc->sym->name);
 		return -1;
 	}
 
-	alt->orig_sec = orig_rela->sym->sec;
-	alt->orig_off = orig_rela->addend;
+	alt->orig_sec = orig_reloc->sym->sec;
+	alt->orig_off = orig_reloc->addend;
 
 	if (!entry->group || alt->new_len) {
-		new_rela = find_rela_by_dest(elf, sec, offset + entry->new);
-		if (!new_rela) {
-			WARN_FUNC("can't find new rela",
+		new_reloc = find_reloc_by_dest(elf, sec, offset + entry->new);
+		if (!new_reloc) {
+			WARN_FUNC("can't find new reloc",
 				  sec, offset + entry->new);
 			return -1;
 		}
 
-		alt->new_sec = new_rela->sym->sec;
-		alt->new_off = (unsigned int)new_rela->addend;
+		alt->new_sec = new_reloc->sym->sec;
+		alt->new_off = (unsigned int)new_reloc->addend;
 
 		/* _ASM_EXTABLE_EX hack */
 		if (alt->new_off >= 0x7ffffff0)
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [RFC][PATCH 2/3] objtool: Find relocation base section using sh_info
  2020-05-27 16:42 [RFC][PATCH 0/3] objtool: Support implicit addend relocations Matt Helsley
  2020-05-27 16:42 ` [RFC][PATCH 1/3] objtool: Rename rela to reloc Matt Helsley
@ 2020-05-27 16:42 ` Matt Helsley
  2020-05-28 14:09   ` Josh Poimboeuf
  2020-05-27 16:42 ` [RFC][PATCH 3/3] objtool: Add support for relocations without addends Matt Helsley
  2 siblings, 1 reply; 12+ messages in thread
From: Matt Helsley @ 2020-05-27 16:42 UTC (permalink / raw)
  To: linux-kernel; +Cc: Josh Poimboeuf, Peter Zijlstra, Steven Rostedt, Matt Helsley

Currently objtool uses a naming heuristic to find the "base"
section to apply the relocation(s) to. The standard defines
the SHF_INFO_LINK flag (SHF => in the section header flags)
which indicates when the section header's sh_info field can
be used to find the necessary section.

Warns when the heuristic is used as a fallback and changes
the name heuristic calculation to handle rela (explicit
addend) and now rel (implicit addend) relocations.

Signed-off-by: Matt Helsley <mhelsley@vmware.com>
---
 tools/objtool/elf.c | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/tools/objtool/elf.c b/tools/objtool/elf.c
index 6fb9f83f7f66..a162bc383945 100644
--- a/tools/objtool/elf.c
+++ b/tools/objtool/elf.c
@@ -502,7 +502,13 @@ static int read_relocs(struct elf *elf)
 		if (sec->sh.sh_type != SHT_RELA)
 			continue;
 
-		sec->base = find_section_by_name(elf, sec->name + 5);
+		if (sec->sh.sh_flags & SHF_INFO_LINK) {
+			sec->base = find_section_by_index(elf, sec->sh.sh_info);
+		} else if (strncmp(sec->name, ".rel", 4) == 0) {
+			WARN("Using naming heuristic to find base of reloc section %s",
+			     sec->name);
+			sec->base = find_section_by_name(elf, sec->name + 5);
+		}
 		if (!sec->base) {
 			WARN("can't find base section for reloc section %s",
 			     sec->name);
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [RFC][PATCH 3/3] objtool: Add support for relocations without addends
  2020-05-27 16:42 [RFC][PATCH 0/3] objtool: Support implicit addend relocations Matt Helsley
  2020-05-27 16:42 ` [RFC][PATCH 1/3] objtool: Rename rela to reloc Matt Helsley
  2020-05-27 16:42 ` [RFC][PATCH 2/3] objtool: Find relocation base section using sh_info Matt Helsley
@ 2020-05-27 16:42 ` Matt Helsley
  2020-05-28 14:24   ` Josh Poimboeuf
  2 siblings, 1 reply; 12+ messages in thread
From: Matt Helsley @ 2020-05-27 16:42 UTC (permalink / raw)
  To: linux-kernel; +Cc: Josh Poimboeuf, Peter Zijlstra, Steven Rostedt, Matt Helsley

Currently objtool only collects information about relocations with
addends. In recordmcount, which we are about to merge into objtool,
some supported architectures do not use rela relocations. Since
object files use one or the other the list can be reused.

Signed-off-by: Matt Helsley <mhelsley@vmware.com>
---
 tools/objtool/elf.c | 109 ++++++++++++++++++++++++++++++++++++--------
 tools/objtool/elf.h |   5 +-
 2 files changed, 95 insertions(+), 19 deletions(-)

diff --git a/tools/objtool/elf.c b/tools/objtool/elf.c
index a162bc383945..cc7b628b1566 100644
--- a/tools/objtool/elf.c
+++ b/tools/objtool/elf.c
@@ -7,6 +7,7 @@
  * Copyright (C) 2014 Seth Jennings <sjenning@redhat.com>
  */
 
+#define _GNU_SOURCE
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <fcntl.h>
@@ -490,6 +491,32 @@ void elf_add_reloc(struct elf *elf, struct reloc *reloc)
 	elf_hash_add(elf->reloc_hash, &reloc->hash, reloc_hash(reloc));
 }
 
+static int read_rel_reloc(struct section *sec, int i, struct reloc *reloc, unsigned int *symndx)
+{
+	if (!gelf_getrel(sec->data, i, &reloc->rel)) {
+		WARN_ELF("gelf_getrel");
+		return -1;
+	}
+	reloc->type = GELF_R_TYPE(reloc->rel.r_info);
+	reloc->addend = 0;
+	reloc->offset = reloc->rel.r_offset;
+	*symndx = GELF_R_SYM(reloc->rel.r_info);
+	return 0;
+}
+
+static int read_rela_reloc(struct section *sec, int i, struct reloc *reloc, unsigned int *symndx)
+{
+	if (!gelf_getrela(sec->data, i, &reloc->rela)) {
+		WARN_ELF("gelf_getrela");
+		return -1;
+	}
+	reloc->type = GELF_R_TYPE(reloc->rela.r_info);
+	reloc->addend = reloc->rela.r_addend;
+	reloc->offset = reloc->rela.r_offset;
+	*symndx = GELF_R_SYM(reloc->rela.r_info);
+	return 0;
+}
+
 static int read_relocs(struct elf *elf)
 {
 	struct section *sec;
@@ -497,17 +524,21 @@ static int read_relocs(struct elf *elf)
 	int i;
 	unsigned int symndx;
 	unsigned long nr_reloc, max_reloc = 0, tot_reloc = 0;
+	int (*read_reloc)(struct section *, int, struct reloc *, unsigned int *);
 
 	list_for_each_entry(sec, &elf->sections, list) {
-		if (sec->sh.sh_type != SHT_RELA)
-			continue;
+		switch(sec->sh.sh_type) {
+		case SHT_REL: read_reloc = read_rel_reloc; break;
+		case SHT_RELA: read_reloc = read_rela_reloc; break;
+		default: continue;
+		}
 
 		if (sec->sh.sh_flags & SHF_INFO_LINK) {
 			sec->base = find_section_by_index(elf, sec->sh.sh_info);
 		} else if (strncmp(sec->name, ".rel", 4) == 0) {
 			WARN("Using naming heuristic to find base of reloc section %s",
 			     sec->name);
-			sec->base = find_section_by_name(elf, sec->name + 5);
+			sec->base = find_section_by_name(elf, strchrnul(sec->name + 1, '.'));
 		}
 		if (!sec->base) {
 			WARN("can't find base section for reloc section %s",
@@ -525,16 +556,8 @@ static int read_relocs(struct elf *elf)
 				return -1;
 			}
 			memset(reloc, 0, sizeof(*reloc));
-
-			if (!gelf_getrela(sec->data, i, &reloc->rela)) {
-				WARN_ELF("gelf_getrela");
+			if (read_reloc(sec, i, reloc, &symndx))
 				return -1;
-			}
-
-			reloc->type = GELF_R_TYPE(reloc->rela.r_info);
-			reloc->addend = reloc->rela.r_addend;
-			reloc->offset = reloc->rela.r_offset;
-			symndx = GELF_R_SYM(reloc->rela.r_info);
 			reloc->sym = find_symbol_by_index(elf, symndx);
 			reloc->sec = sec;
 			if (!reloc->sym) {
@@ -752,16 +775,50 @@ struct section *elf_create_reloc_section(struct elf *elf, struct section *base)
 	return sec;
 }
 
-int elf_rebuild_reloc_section(struct section *sec)
+static int elf_rebuild_rel_reloc_section(struct section *sec, int nr)
 {
 	struct reloc *reloc;
-	int nr, idx = 0, size;
-	GElf_Rela *relocs;
+	int idx = 0, size;
+	GElf_Rel *relocs;
+
+	/*
+	 * Allocate a buffer for relocations with addends but also use
+	 * it for other relocations too. The section type determines
+	 * the size of the section, the buffer used, and the entries.
+	 */
+	size = nr * sizeof(*relocs);
+	relocs = malloc(size);
+	if (!relocs) {
+		perror("malloc");
+		return -1;
+	}
 
-	nr = 0;
-	list_for_each_entry(reloc, &sec->reloc_list, list)
-		nr++;
+	sec->data->d_buf = relocs;
+	sec->data->d_size = size;
+
+	sec->sh.sh_size = size;
+
+	idx = 0;
+	list_for_each_entry(reloc, &sec->reloc_list, list) {
+		relocs[idx].r_offset = reloc->offset;
+		relocs[idx].r_info = GELF_R_INFO(reloc->sym->idx, reloc->type);
+		idx++;
+	}
+
+	return 0;
+}
+
+static int elf_rebuild_rela_reloc_section(struct section *sec, int nr)
+{
+	struct reloc *reloc;
+	int idx = 0, size;
+	GElf_Rela *relocs;
 
+	/*
+	 * Allocate a buffer for relocations with addends but also use
+	 * it for other relocations too. The section type determines
+	 * the size of the section, the buffer used, and the entries.
+	 */
 	size = nr * sizeof(*relocs);
 	relocs = malloc(size);
 	if (!relocs) {
@@ -785,6 +842,22 @@ int elf_rebuild_reloc_section(struct section *sec)
 	return 0;
 }
 
+int elf_rebuild_reloc_section(struct section *sec)
+{
+	struct reloc *reloc;
+	int nr;
+
+	nr = 0;
+	list_for_each_entry(reloc, &sec->reloc_list, list)
+		nr++;
+
+	switch(sec->sh.sh_type) {
+	case SHT_REL:  return elf_rebuild_rel_reloc_section(sec, nr);
+	case SHT_RELA: return elf_rebuild_rela_reloc_section(sec, nr);
+	default:       return -1;
+	}
+}
+
 int elf_write(const struct elf *elf)
 {
 	struct section *sec;
diff --git a/tools/objtool/elf.h b/tools/objtool/elf.h
index 6ad759fd778e..048200af8267 100644
--- a/tools/objtool/elf.h
+++ b/tools/objtool/elf.h
@@ -61,7 +61,10 @@ struct symbol {
 struct reloc {
 	struct list_head list;
 	struct hlist_node hash;
-	GElf_Rela rela;
+	union {
+		GElf_Rela rela;
+		GElf_Rel  rel;
+	};
 	struct section *sec;
 	struct symbol *sym;
 	unsigned int type;
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* Re: [RFC][PATCH 1/3] objtool: Rename rela to reloc
  2020-05-27 16:42 ` [RFC][PATCH 1/3] objtool: Rename rela to reloc Matt Helsley
@ 2020-05-28 14:04   ` Josh Poimboeuf
  2020-05-28 16:00     ` Matt Helsley
  0 siblings, 1 reply; 12+ messages in thread
From: Josh Poimboeuf @ 2020-05-28 14:04 UTC (permalink / raw)
  To: Matt Helsley; +Cc: linux-kernel, Peter Zijlstra, Steven Rostedt

On Wed, May 27, 2020 at 09:42:31AM -0700, Matt Helsley wrote:
> Before supporting additional relocation types rename the relevant
> types and functions from "rela" to "reloc". This work can largely
> be done with the following regex:
> 
> Notable exceptions include gelf_* library calls and
> standard/expected section names which still use "rela" because
> they encode the type of relocation expected. Also, keep "rela"
> in the struct because it encodes a specify type of relocation

Missing regex?

BTW it would be really nice if the regex were exact if possible, for
stable backporting reasons.

-- 
Josh


^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [RFC][PATCH 2/3] objtool: Find relocation base section using sh_info
  2020-05-27 16:42 ` [RFC][PATCH 2/3] objtool: Find relocation base section using sh_info Matt Helsley
@ 2020-05-28 14:09   ` Josh Poimboeuf
  2020-05-28 16:02     ` Matt Helsley
  0 siblings, 1 reply; 12+ messages in thread
From: Josh Poimboeuf @ 2020-05-28 14:09 UTC (permalink / raw)
  To: Matt Helsley; +Cc: linux-kernel, Peter Zijlstra, Steven Rostedt

On Wed, May 27, 2020 at 09:42:32AM -0700, Matt Helsley wrote:
> Currently objtool uses a naming heuristic to find the "base"
> section to apply the relocation(s) to. The standard defines
> the SHF_INFO_LINK flag (SHF => in the section header flags)
> which indicates when the section header's sh_info field can
> be used to find the necessary section.
> 
> Warns when the heuristic is used as a fallback and changes
> the name heuristic calculation to handle rela (explicit
> addend) and now rel (implicit addend) relocations.

Does this fallback case actually happen?

-- 
Josh


^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [RFC][PATCH 3/3] objtool: Add support for relocations without addends
  2020-05-27 16:42 ` [RFC][PATCH 3/3] objtool: Add support for relocations without addends Matt Helsley
@ 2020-05-28 14:24   ` Josh Poimboeuf
  2020-05-28 16:05     ` Matt Helsley
  0 siblings, 1 reply; 12+ messages in thread
From: Josh Poimboeuf @ 2020-05-28 14:24 UTC (permalink / raw)
  To: Matt Helsley; +Cc: linux-kernel, Peter Zijlstra, Steven Rostedt

On Wed, May 27, 2020 at 09:42:33AM -0700, Matt Helsley wrote:
> @@ -525,16 +556,8 @@ static int read_relocs(struct elf *elf)
>  				return -1;
>  			}
>  			memset(reloc, 0, sizeof(*reloc));
> -
> -			if (!gelf_getrela(sec->data, i, &reloc->rela)) {
> -				WARN_ELF("gelf_getrela");
> +			if (read_reloc(sec, i, reloc, &symndx))
>  				return -1;
> -			}

I try to avoid function pointers, them being slow and ugly and all.

Since it's just a single call site, I'd rather a direct call.  For
example, call read_reloc(), which has an if-then to decide which
subfunction to call.

-- 
Josh


^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [RFC][PATCH 1/3] objtool: Rename rela to reloc
  2020-05-28 14:04   ` Josh Poimboeuf
@ 2020-05-28 16:00     ` Matt Helsley
  0 siblings, 0 replies; 12+ messages in thread
From: Matt Helsley @ 2020-05-28 16:00 UTC (permalink / raw)
  To: Josh Poimboeuf; +Cc: linux-kernel, Peter Zijlstra, Steven Rostedt

On Thu, May 28, 2020 at 09:04:44AM -0500, Josh Poimboeuf wrote:
> On Wed, May 27, 2020 at 09:42:31AM -0700, Matt Helsley wrote:
> > Before supporting additional relocation types rename the relevant
> > types and functions from "rela" to "reloc". This work can largely
> > be done with the following regex:
> > 
> > Notable exceptions include gelf_* library calls and
> > standard/expected section names which still use "rela" because
> > they encode the type of relocation expected. Also, keep "rela"
> > in the struct because it encodes a specify type of relocation
> 
> Missing regex?

I briefly looked into it and went with a manual process instead. I can
try and work backwards to reproduce the patch with a regex though.

> BTW it would be really nice if the regex were exact if possible, for
> stable backporting reasons.

Agreed. I'll see what I can come up with and put it and any necessary
details in the commit message for the next posting.

Cheers,
	-Matt Helsley

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [RFC][PATCH 2/3] objtool: Find relocation base section using sh_info
  2020-05-28 14:09   ` Josh Poimboeuf
@ 2020-05-28 16:02     ` Matt Helsley
  2020-05-28 17:00       ` Josh Poimboeuf
  0 siblings, 1 reply; 12+ messages in thread
From: Matt Helsley @ 2020-05-28 16:02 UTC (permalink / raw)
  To: Josh Poimboeuf; +Cc: linux-kernel, Peter Zijlstra, Steven Rostedt

On Thu, May 28, 2020 at 09:09:16AM -0500, Josh Poimboeuf wrote:
> On Wed, May 27, 2020 at 09:42:32AM -0700, Matt Helsley wrote:
> > Currently objtool uses a naming heuristic to find the "base"
> > section to apply the relocation(s) to. The standard defines
> > the SHF_INFO_LINK flag (SHF => in the section header flags)
> > which indicates when the section header's sh_info field can
> > be used to find the necessary section.
> > 
> > Warns when the heuristic is used as a fallback and changes
> > the name heuristic calculation to handle rela (explicit
> > addend) and now rel (implicit addend) relocations.
> 
> Does this fallback case actually happen?

Not that I could see. I was thinking about taking it out but
I haven't tried this set with clang or other toolchains. So
I was wondering if you think holding off before removing it
would be wise or if you'd rather just remove it.

Cheers,
    -Matt Helsley

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [RFC][PATCH 3/3] objtool: Add support for relocations without addends
  2020-05-28 14:24   ` Josh Poimboeuf
@ 2020-05-28 16:05     ` Matt Helsley
  0 siblings, 0 replies; 12+ messages in thread
From: Matt Helsley @ 2020-05-28 16:05 UTC (permalink / raw)
  To: Josh Poimboeuf; +Cc: linux-kernel, Peter Zijlstra, Steven Rostedt

On Thu, May 28, 2020 at 09:24:14AM -0500, Josh Poimboeuf wrote:
> On Wed, May 27, 2020 at 09:42:33AM -0700, Matt Helsley wrote:
> > @@ -525,16 +556,8 @@ static int read_relocs(struct elf *elf)
> >  				return -1;
> >  			}
> >  			memset(reloc, 0, sizeof(*reloc));
> > -
> > -			if (!gelf_getrela(sec->data, i, &reloc->rela)) {
> > -				WARN_ELF("gelf_getrela");
> > +			if (read_reloc(sec, i, reloc, &symndx))
> >  				return -1;
> > -			}
> 
> I try to avoid function pointers, them being slow and ugly and all.
> 
> Since it's just a single call site, I'd rather a direct call.  For
> example, call read_reloc(), which has an if-then to decide which
> subfunction to call.

OK, I'll take the function pointers out in favor of switches.

Cheers,
	-Matt Helsley

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [RFC][PATCH 2/3] objtool: Find relocation base section using sh_info
  2020-05-28 16:02     ` Matt Helsley
@ 2020-05-28 17:00       ` Josh Poimboeuf
  2020-05-28 19:15         ` Matt Helsley
  0 siblings, 1 reply; 12+ messages in thread
From: Josh Poimboeuf @ 2020-05-28 17:00 UTC (permalink / raw)
  To: Matt Helsley; +Cc: linux-kernel, Peter Zijlstra, Steven Rostedt

On Thu, May 28, 2020 at 09:02:47AM -0700, Matt Helsley wrote:
> On Thu, May 28, 2020 at 09:09:16AM -0500, Josh Poimboeuf wrote:
> > On Wed, May 27, 2020 at 09:42:32AM -0700, Matt Helsley wrote:
> > > Currently objtool uses a naming heuristic to find the "base"
> > > section to apply the relocation(s) to. The standard defines
> > > the SHF_INFO_LINK flag (SHF => in the section header flags)
> > > which indicates when the section header's sh_info field can
> > > be used to find the necessary section.
> > > 
> > > Warns when the heuristic is used as a fallback and changes
> > > the name heuristic calculation to handle rela (explicit
> > > addend) and now rel (implicit addend) relocations.
> > 
> > Does this fallback case actually happen?
> 
> Not that I could see. I was thinking about taking it out but
> I haven't tried this set with clang or other toolchains. So
> I was wondering if you think holding off before removing it
> would be wise or if you'd rather just remove it.

I just realized somebody already submitted an almost identical patch:

  https://lkml.kernel.org/r/20200421182501.149101-1-samitolvanen@google.com

Which I'll be merging soon... so you can just drop this one.

Then you can base your next version of this set on top of that patch, if
it hasn't been merged yet.

-- 
Josh


^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [RFC][PATCH 2/3] objtool: Find relocation base section using sh_info
  2020-05-28 17:00       ` Josh Poimboeuf
@ 2020-05-28 19:15         ` Matt Helsley
  0 siblings, 0 replies; 12+ messages in thread
From: Matt Helsley @ 2020-05-28 19:15 UTC (permalink / raw)
  To: Josh Poimboeuf; +Cc: linux-kernel, Peter Zijlstra, Steven Rostedt

On Thu, May 28, 2020 at 12:00:10PM -0500, Josh Poimboeuf wrote:
> On Thu, May 28, 2020 at 09:02:47AM -0700, Matt Helsley wrote:
> > On Thu, May 28, 2020 at 09:09:16AM -0500, Josh Poimboeuf wrote:
> > > On Wed, May 27, 2020 at 09:42:32AM -0700, Matt Helsley wrote:
> > > > Currently objtool uses a naming heuristic to find the "base"
> > > > section to apply the relocation(s) to. The standard defines
> > > > the SHF_INFO_LINK flag (SHF => in the section header flags)
> > > > which indicates when the section header's sh_info field can
> > > > be used to find the necessary section.
> > > > 
> > > > Warns when the heuristic is used as a fallback and changes
> > > > the name heuristic calculation to handle rela (explicit
> > > > addend) and now rel (implicit addend) relocations.
> > > 
> > > Does this fallback case actually happen?
> > 
> > Not that I could see. I was thinking about taking it out but
> > I haven't tried this set with clang or other toolchains. So
> > I was wondering if you think holding off before removing it
> > would be wise or if you'd rather just remove it.
> 
> I just realized somebody already submitted an almost identical patch:
> 
>   https://lkml.kernel.org/r/20200421182501.149101-1-samitolvanen@google.com
> 
> Which I'll be merging soon... so you can just drop this one.

OK, I'll drop this patch.

Cheers,
	-Matt

^ permalink raw reply	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2020-05-28 19:15 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-05-27 16:42 [RFC][PATCH 0/3] objtool: Support implicit addend relocations Matt Helsley
2020-05-27 16:42 ` [RFC][PATCH 1/3] objtool: Rename rela to reloc Matt Helsley
2020-05-28 14:04   ` Josh Poimboeuf
2020-05-28 16:00     ` Matt Helsley
2020-05-27 16:42 ` [RFC][PATCH 2/3] objtool: Find relocation base section using sh_info Matt Helsley
2020-05-28 14:09   ` Josh Poimboeuf
2020-05-28 16:02     ` Matt Helsley
2020-05-28 17:00       ` Josh Poimboeuf
2020-05-28 19:15         ` Matt Helsley
2020-05-27 16:42 ` [RFC][PATCH 3/3] objtool: Add support for relocations without addends Matt Helsley
2020-05-28 14:24   ` Josh Poimboeuf
2020-05-28 16:05     ` Matt Helsley

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).