@@ -559,12 +559,12 @@ static int add_dead_ends(struct objtool_file *file)
559
559
else if (reloc -> addend == reloc -> sym -> sec -> sh .sh_size ) {
560
560
insn = find_last_insn (file , reloc -> sym -> sec );
561
561
if (!insn ) {
562
- WARN ("can't find unreachable insn at %s+0x%x " ,
562
+ WARN ("can't find unreachable insn at %s+0x%lx " ,
563
563
reloc -> sym -> sec -> name , reloc -> addend );
564
564
return -1 ;
565
565
}
566
566
} else {
567
- WARN ("can't find unreachable insn at %s+0x%x " ,
567
+ WARN ("can't find unreachable insn at %s+0x%lx " ,
568
568
reloc -> sym -> sec -> name , reloc -> addend );
569
569
return -1 ;
570
570
}
@@ -594,12 +594,12 @@ static int add_dead_ends(struct objtool_file *file)
594
594
else if (reloc -> addend == reloc -> sym -> sec -> sh .sh_size ) {
595
595
insn = find_last_insn (file , reloc -> sym -> sec );
596
596
if (!insn ) {
597
- WARN ("can't find reachable insn at %s+0x%x " ,
597
+ WARN ("can't find reachable insn at %s+0x%lx " ,
598
598
reloc -> sym -> sec -> name , reloc -> addend );
599
599
return -1 ;
600
600
}
601
601
} else {
602
- WARN ("can't find reachable insn at %s+0x%x " ,
602
+ WARN ("can't find reachable insn at %s+0x%lx " ,
603
603
reloc -> sym -> sec -> name , reloc -> addend );
604
604
return -1 ;
605
605
}
@@ -1271,12 +1271,19 @@ static bool is_first_func_insn(struct objtool_file *file, struct instruction *in
1271
1271
*/
1272
1272
static int add_jump_destinations (struct objtool_file * file )
1273
1273
{
1274
- struct instruction * insn ;
1274
+ struct instruction * insn , * jump_dest ;
1275
1275
struct reloc * reloc ;
1276
1276
struct section * dest_sec ;
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
@@ -1291,7 +1298,10 @@ static int add_jump_destinations(struct objtool_file *file)
1291
1298
add_retpoline_call (file , insn );
1292
1299
continue ;
1293
1300
} 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
+ */
1295
1305
add_call_dest (file , insn , reloc -> sym , true);
1296
1306
continue ;
1297
1307
} else if (reloc -> sym -> sec -> idx ) {
@@ -1303,17 +1313,8 @@ static int add_jump_destinations(struct objtool_file *file)
1303
1313
continue ;
1304
1314
}
1305
1315
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 ) {
1317
1318
WARN_FUNC ("can't find jump dest instruction at %s+0x%lx" ,
1318
1319
insn -> sec , insn -> offset , dest_sec -> name ,
1319
1320
dest_off );
@@ -1323,8 +1324,8 @@ static int add_jump_destinations(struct objtool_file *file)
1323
1324
/*
1324
1325
* Cross-function jump.
1325
1326
*/
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 ) {
1328
1329
1329
1330
/*
1330
1331
* For GCC 8+, create parent/child links for any cold
@@ -1342,16 +1343,22 @@ static int add_jump_destinations(struct objtool_file *file)
1342
1343
* subfunction is through a jump table.
1343
1344
*/
1344
1345
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 ;
1348
1349
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 ;
1353
1358
}
1354
1359
}
1360
+
1361
+ insn -> jump_dest = jump_dest ;
1355
1362
}
1356
1363
1357
1364
return 0 ;
@@ -1540,13 +1547,13 @@ static int handle_group_alt(struct objtool_file *file,
1540
1547
continue ;
1541
1548
1542
1549
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 ) {
1544
1551
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
+ }
1550
1557
}
1551
1558
}
1552
1559
@@ -2245,14 +2252,14 @@ static int decode_sections(struct objtool_file *file)
2245
2252
return ret ;
2246
2253
2247
2254
/*
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 .
2250
2257
*/
2251
- ret = add_jump_destinations (file );
2258
+ ret = add_special_section_alts (file );
2252
2259
if (ret )
2253
2260
return ret ;
2254
2261
2255
- ret = add_special_section_alts (file );
2262
+ ret = add_jump_destinations (file );
2256
2263
if (ret )
2257
2264
return ret ;
2258
2265
@@ -3303,7 +3310,7 @@ static int validate_branch(struct objtool_file *file, struct symbol *func,
3303
3310
while (1 ) {
3304
3311
next_insn = next_insn_to_validate (file , insn );
3305
3312
3306
- if (file -> c_file && func && insn -> func && func != insn -> func -> pfunc ) {
3313
+ if (func && insn -> func && func != insn -> func -> pfunc ) {
3307
3314
WARN ("%s() falls through to next function %s()" ,
3308
3315
func -> name , insn -> func -> name );
3309
3316
return 1 ;
0 commit comments