@@ -559,12 +559,12 @@ static int add_dead_ends(struct objtool_file *file)
559559 else if (reloc -> addend == reloc -> sym -> sec -> sh .sh_size ) {
560560 insn = find_last_insn (file , reloc -> sym -> sec );
561561 if (!insn ) {
562- WARN ("can't find unreachable insn at %s+0x%x " ,
562+ WARN ("can't find unreachable insn at %s+0x%lx " ,
563563 reloc -> sym -> sec -> name , reloc -> addend );
564564 return -1 ;
565565 }
566566 } else {
567- WARN ("can't find unreachable insn at %s+0x%x " ,
567+ WARN ("can't find unreachable insn at %s+0x%lx " ,
568568 reloc -> sym -> sec -> name , reloc -> addend );
569569 return -1 ;
570570 }
@@ -594,12 +594,12 @@ static int add_dead_ends(struct objtool_file *file)
594594 else if (reloc -> addend == reloc -> sym -> sec -> sh .sh_size ) {
595595 insn = find_last_insn (file , reloc -> sym -> sec );
596596 if (!insn ) {
597- WARN ("can't find reachable insn at %s+0x%x " ,
597+ WARN ("can't find reachable insn at %s+0x%lx " ,
598598 reloc -> sym -> sec -> name , reloc -> addend );
599599 return -1 ;
600600 }
601601 } else {
602- WARN ("can't find reachable insn at %s+0x%x " ,
602+ WARN ("can't find reachable insn at %s+0x%lx " ,
603603 reloc -> sym -> sec -> name , reloc -> addend );
604604 return -1 ;
605605 }
@@ -1271,12 +1271,19 @@ static bool is_first_func_insn(struct objtool_file *file, struct instruction *in
12711271 */
12721272static int add_jump_destinations (struct objtool_file * file )
12731273{
1274- struct instruction * insn ;
1274+ struct instruction * insn , * jump_dest ;
12751275 struct reloc * reloc ;
12761276 struct section * dest_sec ;
12771277 unsigned long dest_off ;
12781278
12791279 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+ }
12801287 if (!is_static_jump (insn ))
12811288 continue ;
12821289
@@ -1291,7 +1298,10 @@ static int add_jump_destinations(struct objtool_file *file)
12911298 add_retpoline_call (file , insn );
12921299 continue ;
12931300 } else if (insn -> func ) {
1294- /* internal or external sibling call (with reloc) */
1301+ /*
1302+ * External sibling call or internal sibling call with
1303+ * STT_FUNC reloc.
1304+ */
12951305 add_call_dest (file , insn , reloc -> sym , true);
12961306 continue ;
12971307 } else if (reloc -> sym -> sec -> idx ) {
@@ -1303,17 +1313,8 @@ static int add_jump_destinations(struct objtool_file *file)
13031313 continue ;
13041314 }
13051315
1306- insn -> jump_dest = find_insn (file , dest_sec , dest_off );
1307- if (!insn -> jump_dest ) {
1308-
1309- /*
1310- * This is a special case where an alt instruction
1311- * jumps past the end of the section. These are
1312- * handled later in handle_group_alt().
1313- */
1314- if (!strcmp (insn -> sec -> name , ".altinstr_replacement" ))
1315- continue ;
1316-
1316+ jump_dest = find_insn (file , dest_sec , dest_off );
1317+ if (!jump_dest ) {
13171318 WARN_FUNC ("can't find jump dest instruction at %s+0x%lx" ,
13181319 insn -> sec , insn -> offset , dest_sec -> name ,
13191320 dest_off );
@@ -1323,8 +1324,8 @@ static int add_jump_destinations(struct objtool_file *file)
13231324 /*
13241325 * Cross-function jump.
13251326 */
1326- if (insn -> func && insn -> jump_dest -> func &&
1327- insn -> func != insn -> jump_dest -> func ) {
1327+ if (insn -> func && jump_dest -> func &&
1328+ insn -> func != jump_dest -> func ) {
13281329
13291330 /*
13301331 * For GCC 8+, create parent/child links for any cold
@@ -1342,16 +1343,22 @@ static int add_jump_destinations(struct objtool_file *file)
13421343 * subfunction is through a jump table.
13431344 */
13441345 if (!strstr (insn -> func -> name , ".cold" ) &&
1345- strstr (insn -> jump_dest -> func -> name , ".cold" )) {
1346- insn -> func -> cfunc = insn -> jump_dest -> func ;
1347- insn -> jump_dest -> func -> pfunc = insn -> func ;
1346+ strstr (jump_dest -> func -> name , ".cold" )) {
1347+ insn -> func -> cfunc = jump_dest -> func ;
1348+ jump_dest -> func -> pfunc = insn -> func ;
13481349
1349- } else if (!same_function (insn , insn -> jump_dest ) &&
1350- is_first_func_insn (file , insn -> jump_dest )) {
1351- /* internal sibling call (without reloc) */
1352- add_call_dest (file , insn , insn -> jump_dest -> func , true);
1350+ } else if (!same_function (insn , jump_dest ) &&
1351+ is_first_func_insn (file , jump_dest )) {
1352+ /*
1353+ * Internal sibling call without reloc or with
1354+ * STT_SECTION reloc.
1355+ */
1356+ add_call_dest (file , insn , jump_dest -> func , true);
1357+ continue ;
13531358 }
13541359 }
1360+
1361+ insn -> jump_dest = jump_dest ;
13551362 }
13561363
13571364 return 0 ;
@@ -1540,13 +1547,13 @@ static int handle_group_alt(struct objtool_file *file,
15401547 continue ;
15411548
15421549 dest_off = arch_jump_destination (insn );
1543- if (dest_off == special_alt -> new_off + special_alt -> new_len )
1550+ if (dest_off == special_alt -> new_off + special_alt -> new_len ) {
15441551 insn -> jump_dest = next_insn_same_sec (file , last_orig_insn );
1545-
1546- if (! insn -> jump_dest ) {
1547- WARN_FUNC ( "can't find alternative jump destination" ,
1548- insn -> sec , insn -> offset ) ;
1549- return -1 ;
1552+ if (! insn -> jump_dest ) {
1553+ WARN_FUNC ( "can't find alternative jump destination" ,
1554+ insn -> sec , insn -> offset );
1555+ return -1 ;
1556+ }
15501557 }
15511558 }
15521559
@@ -2245,14 +2252,14 @@ static int decode_sections(struct objtool_file *file)
22452252 return ret ;
22462253
22472254 /*
2248- * Must be before add_special_section_alts() as that depends on
2249- * jump_dest being set.
2255+ * Must be before add_jump_destinations(), which depends on 'func'
2256+ * being set for alternatives, to enable proper sibling call detection .
22502257 */
2251- ret = add_jump_destinations (file );
2258+ ret = add_special_section_alts (file );
22522259 if (ret )
22532260 return ret ;
22542261
2255- ret = add_special_section_alts (file );
2262+ ret = add_jump_destinations (file );
22562263 if (ret )
22572264 return ret ;
22582265
@@ -3303,7 +3310,7 @@ static int validate_branch(struct objtool_file *file, struct symbol *func,
33033310 while (1 ) {
33043311 next_insn = next_insn_to_validate (file , insn );
33053312
3306- if (file -> c_file && func && insn -> func && func != insn -> func -> pfunc ) {
3313+ if (func && insn -> func && func != insn -> func -> pfunc ) {
33073314 WARN ("%s() falls through to next function %s()" ,
33083315 func -> name , insn -> func -> name );
33093316 return 1 ;
0 commit comments