Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

objtool: Fix sibling call detection in alternatives

In add_jump_destinations(), sibling call detection requires 'insn->func'
to be valid. But alternative instructions get their 'func' set in
handle_group_alt(), which runs *after* add_jump_destinations(). So
sibling calls in alternatives code don't get properly detected.

Fix that by changing the initialization order: call
add_special_section_alts() *before* add_jump_destinations().

This also means the special case for a missing 'jump_dest' in
add_jump_destinations() can be removed, as it has already been dealt
with.

Signed-off-by: Josh Poimboeuf <jpoimboe@redhat.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Link: https://lkml.kernel.org/r/c02e0a0a2a4286b5f848d17c77fdcb7e0caf709c.1649718562.git.jpoimboe@redhat.com

authored by

Josh Poimboeuf and committed by
Peter Zijlstra
34c861e8 26ff6041

+17 -19
+17 -19
tools/objtool/check.c
··· 1277 1277 unsigned long dest_off; 1278 1278 1279 1279 for_each_insn(file, insn) { 1280 + if (insn->jump_dest) { 1281 + /* 1282 + * handle_group_alt() may have previously set 1283 + * 'jump_dest' for some alternatives. 1284 + */ 1285 + continue; 1286 + } 1280 1287 if (!is_static_jump(insn)) 1281 1288 continue; 1282 1289 ··· 1315 1308 1316 1309 jump_dest = find_insn(file, dest_sec, dest_off); 1317 1310 if (!jump_dest) { 1318 - 1319 - /* 1320 - * This is a special case where an alt instruction 1321 - * jumps past the end of the section. These are 1322 - * handled later in handle_group_alt(). 1323 - */ 1324 - if (!strcmp(insn->sec->name, ".altinstr_replacement")) 1325 - continue; 1326 - 1327 1311 WARN_FUNC("can't find jump dest instruction at %s+0x%lx", 1328 1312 insn->sec, insn->offset, dest_sec->name, 1329 1313 dest_off); ··· 1547 1549 continue; 1548 1550 1549 1551 dest_off = arch_jump_destination(insn); 1550 - if (dest_off == special_alt->new_off + special_alt->new_len) 1552 + if (dest_off == special_alt->new_off + special_alt->new_len) { 1551 1553 insn->jump_dest = next_insn_same_sec(file, last_orig_insn); 1552 - 1553 - if (!insn->jump_dest) { 1554 - WARN_FUNC("can't find alternative jump destination", 1555 - insn->sec, insn->offset); 1556 - return -1; 1554 + if (!insn->jump_dest) { 1555 + WARN_FUNC("can't find alternative jump destination", 1556 + insn->sec, insn->offset); 1557 + return -1; 1558 + } 1557 1559 } 1558 1560 } 1559 1561 ··· 2252 2254 return ret; 2253 2255 2254 2256 /* 2255 - * Must be before add_special_section_alts() as that depends on 2256 - * jump_dest being set. 2257 + * Must be before add_jump_destinations(), which depends on 'func' 2258 + * being set for alternatives, to enable proper sibling call detection. 2257 2259 */ 2258 - ret = add_jump_destinations(file); 2260 + ret = add_special_section_alts(file); 2259 2261 if (ret) 2260 2262 return ret; 2261 2263 2262 - ret = add_special_section_alts(file); 2264 + ret = add_jump_destinations(file); 2263 2265 if (ret) 2264 2266 return ret; 2265 2267