Commit 26ff6041 authored by Josh Poimboeuf's avatar Josh Poimboeuf Committed by Peter Zijlstra
Browse files

objtool: Don't set 'jump_dest' for sibling calls



For most sibling calls, 'jump_dest' is NULL because objtool treats the
jump like a call and sets 'call_dest'.  But there are a few edge cases
where that's not true.  Make it consistent to avoid unexpected behavior.

Signed-off-by: default avatarJosh Poimboeuf <jpoimboe@redhat.com>
Signed-off-by: default avatarPeter Zijlstra (Intel) <peterz@infradead.org>
Link: https://lkml.kernel.org/r/8737d6b9d1691831aed73375f444f0f42da3e2c9.1649718562.git.jpoimboe@redhat.com
parent 02041b32
Loading
Loading
Loading
Loading
+22 −13
Original line number Diff line number Diff line
@@ -1271,7 +1271,7 @@ static bool is_first_func_insn(struct objtool_file *file, struct instruction *in
 */
static int add_jump_destinations(struct objtool_file *file)
{
	struct instruction *insn;
	struct instruction *insn, *jump_dest;
	struct reloc *reloc;
	struct section *dest_sec;
	unsigned long dest_off;
@@ -1291,7 +1291,10 @@ static int add_jump_destinations(struct objtool_file *file)
			add_retpoline_call(file, insn);
			continue;
		} else if (insn->func) {
			/* internal or external sibling call (with reloc) */
			/*
			 * External sibling call or internal sibling call with
			 * STT_FUNC reloc.
			 */
			add_call_dest(file, insn, reloc->sym, true);
			continue;
		} else if (reloc->sym->sec->idx) {
@@ -1303,8 +1306,8 @@ static int add_jump_destinations(struct objtool_file *file)
			continue;
		}

		insn->jump_dest = find_insn(file, dest_sec, dest_off);
		if (!insn->jump_dest) {
		jump_dest = find_insn(file, dest_sec, dest_off);
		if (!jump_dest) {

			/*
			 * This is a special case where an alt instruction
@@ -1323,8 +1326,8 @@ static int add_jump_destinations(struct objtool_file *file)
		/*
		 * Cross-function jump.
		 */
		if (insn->func && insn->jump_dest->func &&
		    insn->func != insn->jump_dest->func) {
		if (insn->func && jump_dest->func &&
		    insn->func != jump_dest->func) {

			/*
			 * For GCC 8+, create parent/child links for any cold
@@ -1342,16 +1345,22 @@ static int add_jump_destinations(struct objtool_file *file)
			 * subfunction is through a jump table.
			 */
			if (!strstr(insn->func->name, ".cold") &&
			    strstr(insn->jump_dest->func->name, ".cold")) {
				insn->func->cfunc = insn->jump_dest->func;
				insn->jump_dest->func->pfunc = insn->func;
			    strstr(jump_dest->func->name, ".cold")) {
				insn->func->cfunc = jump_dest->func;
				jump_dest->func->pfunc = insn->func;

			} else if (!same_function(insn, insn->jump_dest) &&
				   is_first_func_insn(file, insn->jump_dest)) {
				/* internal sibling call (without reloc) */
				add_call_dest(file, insn, insn->jump_dest->func, true);
			} else if (!same_function(insn, jump_dest) &&
				   is_first_func_insn(file, jump_dest)) {
				/*
				 * Internal sibling call without reloc or with
				 * STT_SECTION reloc.
				 */
				add_call_dest(file, insn, jump_dest->func, true);
				continue;
			}
		}

		insn->jump_dest = jump_dest;
	}

	return 0;