@@ -229,10 +229,18 @@ static void init_cfi_state(struct cfi_state *cfi)
229
229
cfi -> drap_offset = -1 ;
230
230
}
231
231
232
- static void clear_insn_state (struct insn_state * state )
232
+ static void init_insn_state (struct insn_state * state , struct section * sec )
233
233
{
234
234
memset (state , 0 , sizeof (* state ));
235
235
init_cfi_state (& state -> cfi );
236
+
237
+ /*
238
+ * We need the full vmlinux for noinstr validation, otherwise we can
239
+ * not correctly determine insn->call_dest->sec (external symbols do
240
+ * not have a section).
241
+ */
242
+ if (vmlinux && sec )
243
+ state -> noinstr = sec -> noinstr ;
236
244
}
237
245
238
246
/*
@@ -2354,24 +2362,34 @@ static int validate_branch(struct objtool_file *file, struct symbol *func,
2354
2362
return 0 ;
2355
2363
}
2356
2364
2357
- static int validate_unwind_hints (struct objtool_file * file )
2365
+ static int validate_unwind_hints (struct objtool_file * file , struct section * sec )
2358
2366
{
2359
2367
struct instruction * insn ;
2360
- int ret , warnings = 0 ;
2361
2368
struct insn_state state ;
2369
+ int ret , warnings = 0 ;
2362
2370
2363
2371
if (!file -> hints )
2364
2372
return 0 ;
2365
2373
2366
- clear_insn_state (& state );
2374
+ init_insn_state (& state , sec );
2367
2375
2368
- for_each_insn (file , insn ) {
2376
+ if (sec ) {
2377
+ insn = find_insn (file , sec , 0 );
2378
+ if (!insn )
2379
+ return 0 ;
2380
+ } else {
2381
+ insn = list_first_entry (& file -> insn_list , typeof (* insn ), list );
2382
+ }
2383
+
2384
+ while (& insn -> list != & file -> insn_list && (!sec || insn -> sec == sec )) {
2369
2385
if (insn -> hint && !insn -> visited ) {
2370
2386
ret = validate_branch (file , insn -> func , insn , state );
2371
2387
if (ret && backtrace )
2372
2388
BT_FUNC ("<=== (hint)" , insn );
2373
2389
warnings += ret ;
2374
2390
}
2391
+
2392
+ insn = list_next_entry (insn , list );
2375
2393
}
2376
2394
2377
2395
return warnings ;
@@ -2518,19 +2536,11 @@ static int validate_section(struct objtool_file *file, struct section *sec)
2518
2536
struct symbol * func ;
2519
2537
int warnings = 0 ;
2520
2538
2521
- /*
2522
- * We need the full vmlinux for noinstr validation, otherwise we can
2523
- * not correctly determine insn->call_dest->sec (external symbols do
2524
- * not have a section).
2525
- */
2526
- if (vmlinux )
2527
- state .noinstr = sec -> noinstr ;
2528
-
2529
2539
list_for_each_entry (func , & sec -> symbol_list , list ) {
2530
2540
if (func -> type != STT_FUNC )
2531
2541
continue ;
2532
2542
2533
- clear_insn_state (& state );
2543
+ init_insn_state (& state , sec );
2534
2544
state .cfi .cfa = initial_func_cfi .cfa ;
2535
2545
memcpy (& state .cfi .regs , & initial_func_cfi .regs ,
2536
2546
CFI_NUM_REGS * sizeof (struct cfi_reg ));
@@ -2545,12 +2555,16 @@ static int validate_section(struct objtool_file *file, struct section *sec)
2545
2555
static int validate_vmlinux_functions (struct objtool_file * file )
2546
2556
{
2547
2557
struct section * sec ;
2558
+ int warnings = 0 ;
2548
2559
2549
2560
sec = find_section_by_name (file -> elf , ".noinstr.text" );
2550
2561
if (!sec )
2551
2562
return 0 ;
2552
2563
2553
- return validate_section (file , sec );
2564
+ warnings += validate_section (file , sec );
2565
+ warnings += validate_unwind_hints (file , sec );
2566
+
2567
+ return warnings ;
2554
2568
}
2555
2569
2556
2570
static int validate_functions (struct objtool_file * file )
@@ -2635,7 +2649,7 @@ int check(const char *_objname, bool orc)
2635
2649
goto out ;
2636
2650
warnings += ret ;
2637
2651
2638
- ret = validate_unwind_hints (& file );
2652
+ ret = validate_unwind_hints (& file , NULL );
2639
2653
if (ret < 0 )
2640
2654
goto out ;
2641
2655
warnings += ret ;
0 commit comments