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: Josh Poimboeuf <jpoimboe@redhat.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Link: https://lkml.kernel.org/r/8737d6b9d1691831aed73375f444f0f42da3e2c9.1649718562.git.jpoimboe@redhat.com
This commit is contained in:
Josh Poimboeuf 2022-04-11 16:10:30 -07:00 committed by Peter Zijlstra
parent 02041b3225
commit 26ff604102

View File

@ -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) static int add_jump_destinations(struct objtool_file *file)
{ {
struct instruction *insn; struct instruction *insn, *jump_dest;
struct reloc *reloc; struct reloc *reloc;
struct section *dest_sec; struct section *dest_sec;
unsigned long dest_off; unsigned long dest_off;
@ -1291,7 +1291,10 @@ static int add_jump_destinations(struct objtool_file *file)
add_retpoline_call(file, insn); add_retpoline_call(file, insn);
continue; continue;
} else if (insn->func) { } 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); add_call_dest(file, insn, reloc->sym, true);
continue; continue;
} else if (reloc->sym->sec->idx) { } else if (reloc->sym->sec->idx) {
@ -1303,8 +1306,8 @@ static int add_jump_destinations(struct objtool_file *file)
continue; continue;
} }
insn->jump_dest = find_insn(file, dest_sec, dest_off); jump_dest = find_insn(file, dest_sec, dest_off);
if (!insn->jump_dest) { if (!jump_dest) {
/* /*
* This is a special case where an alt instruction * 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. * Cross-function jump.
*/ */
if (insn->func && insn->jump_dest->func && if (insn->func && jump_dest->func &&
insn->func != insn->jump_dest->func) { insn->func != jump_dest->func) {
/* /*
* For GCC 8+, create parent/child links for any cold * 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. * subfunction is through a jump table.
*/ */
if (!strstr(insn->func->name, ".cold") && if (!strstr(insn->func->name, ".cold") &&
strstr(insn->jump_dest->func->name, ".cold")) { strstr(jump_dest->func->name, ".cold")) {
insn->func->cfunc = insn->jump_dest->func; insn->func->cfunc = jump_dest->func;
insn->jump_dest->func->pfunc = insn->func; jump_dest->func->pfunc = insn->func;
} else if (!same_function(insn, insn->jump_dest) && } else if (!same_function(insn, jump_dest) &&
is_first_func_insn(file, insn->jump_dest)) { is_first_func_insn(file, jump_dest)) {
/* internal sibling call (without reloc) */ /*
add_call_dest(file, insn, insn->jump_dest->func, true); * 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; return 0;