@@ -2307,16 +2307,9 @@ static int read_unwind_hints(struct objtool_file *file)
2307
2307
WARN_FUNC ("UNWIND_HINT_IRET_REGS without ENDBR" ,
2308
2308
insn -> sec , insn -> offset );
2309
2309
}
2310
-
2311
- insn -> entry = 1 ;
2312
2310
}
2313
2311
}
2314
2312
2315
- if (hint -> type == UNWIND_HINT_TYPE_ENTRY ) {
2316
- hint -> type = UNWIND_HINT_TYPE_CALL ;
2317
- insn -> entry = 1 ;
2318
- }
2319
-
2320
2313
if (hint -> type == UNWIND_HINT_TYPE_FUNC ) {
2321
2314
insn -> cfi = & func_cfi ;
2322
2315
continue ;
@@ -2449,6 +2442,34 @@ static int read_instr_hints(struct objtool_file *file)
2449
2442
return 0 ;
2450
2443
}
2451
2444
2445
+ static int read_validate_unret_hints (struct objtool_file * file )
2446
+ {
2447
+ struct section * sec ;
2448
+ struct instruction * insn ;
2449
+ struct reloc * reloc ;
2450
+
2451
+ sec = find_section_by_name (file -> elf , ".rela.discard.validate_unret" );
2452
+ if (!sec )
2453
+ return 0 ;
2454
+
2455
+ list_for_each_entry (reloc , & sec -> reloc_list , list ) {
2456
+ if (reloc -> sym -> type != STT_SECTION ) {
2457
+ WARN ("unexpected relocation symbol type in %s" , sec -> name );
2458
+ return -1 ;
2459
+ }
2460
+
2461
+ insn = find_insn (file , reloc -> sym -> sec , reloc -> addend );
2462
+ if (!insn ) {
2463
+ WARN ("bad .discard.instr_end entry" );
2464
+ return -1 ;
2465
+ }
2466
+ insn -> unret = 1 ;
2467
+ }
2468
+
2469
+ return 0 ;
2470
+ }
2471
+
2472
+
2452
2473
static int read_intra_function_calls (struct objtool_file * file )
2453
2474
{
2454
2475
struct instruction * insn ;
@@ -2667,6 +2688,10 @@ static int decode_sections(struct objtool_file *file)
2667
2688
if (ret )
2668
2689
return ret ;
2669
2690
2691
+ ret = read_validate_unret_hints (file );
2692
+ if (ret )
2693
+ return ret ;
2694
+
2670
2695
return 0 ;
2671
2696
}
2672
2697
@@ -3863,21 +3888,21 @@ static int validate_unwind_hints(struct objtool_file *file, struct section *sec)
3863
3888
/*
3864
3889
* Validate rethunk entry constraint: must untrain RET before the first RET.
3865
3890
*
3866
- * Follow every branch (intra-function) and ensure ANNOTATE_UNRET_END comes
3891
+ * Follow every branch (intra-function) and ensure VALIDATE_UNRET_END comes
3867
3892
* before an actual RET instruction.
3868
3893
*/
3869
- static int validate_entry (struct objtool_file * file , struct instruction * insn )
3894
+ static int validate_unret (struct objtool_file * file , struct instruction * insn )
3870
3895
{
3871
3896
struct instruction * next , * dest ;
3872
3897
int ret , warnings = 0 ;
3873
3898
3874
3899
for (;;) {
3875
3900
next = next_insn_to_validate (file , insn );
3876
3901
3877
- if (insn -> visited & VISITED_ENTRY )
3902
+ if (insn -> visited & VISITED_UNRET )
3878
3903
return 0 ;
3879
3904
3880
- insn -> visited |= VISITED_ENTRY ;
3905
+ insn -> visited |= VISITED_UNRET ;
3881
3906
3882
3907
if (!insn -> ignore_alts && insn -> alts ) {
3883
3908
struct alternative * alt ;
@@ -3887,7 +3912,7 @@ static int validate_entry(struct objtool_file *file, struct instruction *insn)
3887
3912
if (alt -> skip_orig )
3888
3913
skip_orig = true;
3889
3914
3890
- ret = validate_entry (file , alt -> insn );
3915
+ ret = validate_unret (file , alt -> insn );
3891
3916
if (ret ) {
3892
3917
if (opts .backtrace )
3893
3918
BT_FUNC ("(alt)" , insn );
@@ -3915,7 +3940,7 @@ static int validate_entry(struct objtool_file *file, struct instruction *insn)
3915
3940
insn -> sec , insn -> offset );
3916
3941
return -1 ;
3917
3942
}
3918
- ret = validate_entry (file , insn -> jump_dest );
3943
+ ret = validate_unret (file , insn -> jump_dest );
3919
3944
if (ret ) {
3920
3945
if (opts .backtrace ) {
3921
3946
BT_FUNC ("(branch%s)" , insn ,
@@ -3940,7 +3965,7 @@ static int validate_entry(struct objtool_file *file, struct instruction *insn)
3940
3965
return -1 ;
3941
3966
}
3942
3967
3943
- ret = validate_entry (file , dest );
3968
+ ret = validate_unret (file , dest );
3944
3969
if (ret ) {
3945
3970
if (opts .backtrace )
3946
3971
BT_FUNC ("(call)" , insn );
@@ -3976,19 +4001,19 @@ static int validate_entry(struct objtool_file *file, struct instruction *insn)
3976
4001
}
3977
4002
3978
4003
/*
3979
- * Validate that all branches starting at 'insn->entry' encounter UNRET_END
3980
- * before RET.
4004
+ * Validate that all branches starting at VALIDATE_UNRET_BEGIN encounter
4005
+ * VALIDATE_UNRET_END before RET.
3981
4006
*/
3982
- static int validate_unret (struct objtool_file * file )
4007
+ static int validate_unrets (struct objtool_file * file )
3983
4008
{
3984
4009
struct instruction * insn ;
3985
4010
int ret , warnings = 0 ;
3986
4011
3987
4012
for_each_insn (file , insn ) {
3988
- if (!insn -> entry )
4013
+ if (!insn -> unret )
3989
4014
continue ;
3990
4015
3991
- ret = validate_entry (file , insn );
4016
+ ret = validate_unret (file , insn );
3992
4017
if (ret < 0 ) {
3993
4018
WARN_FUNC ("Failed UNRET validation" , insn -> sec , insn -> offset );
3994
4019
return ret ;
@@ -4607,7 +4632,7 @@ int check(struct objtool_file *file)
4607
4632
* Must be after validate_branch() and friends, it plays
4608
4633
* further games with insn->visited.
4609
4634
*/
4610
- ret = validate_unret (file );
4635
+ ret = validate_unrets (file );
4611
4636
if (ret < 0 )
4612
4637
return ret ;
4613
4638
warnings += ret ;
0 commit comments