@@ -2307,16 +2307,9 @@ static int read_unwind_hints(struct objtool_file *file)
23072307 WARN_FUNC ("UNWIND_HINT_IRET_REGS without ENDBR" ,
23082308 insn -> sec , insn -> offset );
23092309 }
2310-
2311- insn -> entry = 1 ;
23122310 }
23132311 }
23142312
2315- if (hint -> type == UNWIND_HINT_TYPE_ENTRY ) {
2316- hint -> type = UNWIND_HINT_TYPE_CALL ;
2317- insn -> entry = 1 ;
2318- }
2319-
23202313 if (hint -> type == UNWIND_HINT_TYPE_FUNC ) {
23212314 insn -> cfi = & func_cfi ;
23222315 continue ;
@@ -2449,6 +2442,34 @@ static int read_instr_hints(struct objtool_file *file)
24492442 return 0 ;
24502443}
24512444
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+
24522473static int read_intra_function_calls (struct objtool_file * file )
24532474{
24542475 struct instruction * insn ;
@@ -2667,6 +2688,10 @@ static int decode_sections(struct objtool_file *file)
26672688 if (ret )
26682689 return ret ;
26692690
2691+ ret = read_validate_unret_hints (file );
2692+ if (ret )
2693+ return ret ;
2694+
26702695 return 0 ;
26712696}
26722697
@@ -3863,21 +3888,21 @@ static int validate_unwind_hints(struct objtool_file *file, struct section *sec)
38633888/*
38643889 * Validate rethunk entry constraint: must untrain RET before the first RET.
38653890 *
3866- * Follow every branch (intra-function) and ensure ANNOTATE_UNRET_END comes
3891+ * Follow every branch (intra-function) and ensure VALIDATE_UNRET_END comes
38673892 * before an actual RET instruction.
38683893 */
3869- static int validate_entry (struct objtool_file * file , struct instruction * insn )
3894+ static int validate_unret (struct objtool_file * file , struct instruction * insn )
38703895{
38713896 struct instruction * next , * dest ;
38723897 int ret , warnings = 0 ;
38733898
38743899 for (;;) {
38753900 next = next_insn_to_validate (file , insn );
38763901
3877- if (insn -> visited & VISITED_ENTRY )
3902+ if (insn -> visited & VISITED_UNRET )
38783903 return 0 ;
38793904
3880- insn -> visited |= VISITED_ENTRY ;
3905+ insn -> visited |= VISITED_UNRET ;
38813906
38823907 if (!insn -> ignore_alts && insn -> alts ) {
38833908 struct alternative * alt ;
@@ -3887,7 +3912,7 @@ static int validate_entry(struct objtool_file *file, struct instruction *insn)
38873912 if (alt -> skip_orig )
38883913 skip_orig = true;
38893914
3890- ret = validate_entry (file , alt -> insn );
3915+ ret = validate_unret (file , alt -> insn );
38913916 if (ret ) {
38923917 if (opts .backtrace )
38933918 BT_FUNC ("(alt)" , insn );
@@ -3915,7 +3940,7 @@ static int validate_entry(struct objtool_file *file, struct instruction *insn)
39153940 insn -> sec , insn -> offset );
39163941 return -1 ;
39173942 }
3918- ret = validate_entry (file , insn -> jump_dest );
3943+ ret = validate_unret (file , insn -> jump_dest );
39193944 if (ret ) {
39203945 if (opts .backtrace ) {
39213946 BT_FUNC ("(branch%s)" , insn ,
@@ -3940,7 +3965,7 @@ static int validate_entry(struct objtool_file *file, struct instruction *insn)
39403965 return -1 ;
39413966 }
39423967
3943- ret = validate_entry (file , dest );
3968+ ret = validate_unret (file , dest );
39443969 if (ret ) {
39453970 if (opts .backtrace )
39463971 BT_FUNC ("(call)" , insn );
@@ -3976,19 +4001,19 @@ static int validate_entry(struct objtool_file *file, struct instruction *insn)
39764001}
39774002
39784003/*
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.
39814006 */
3982- static int validate_unret (struct objtool_file * file )
4007+ static int validate_unrets (struct objtool_file * file )
39834008{
39844009 struct instruction * insn ;
39854010 int ret , warnings = 0 ;
39864011
39874012 for_each_insn (file , insn ) {
3988- if (!insn -> entry )
4013+ if (!insn -> unret )
39894014 continue ;
39904015
3991- ret = validate_entry (file , insn );
4016+ ret = validate_unret (file , insn );
39924017 if (ret < 0 ) {
39934018 WARN_FUNC ("Failed UNRET validation" , insn -> sec , insn -> offset );
39944019 return ret ;
@@ -4607,7 +4632,7 @@ int check(struct objtool_file *file)
46074632 * Must be after validate_branch() and friends, it plays
46084633 * further games with insn->visited.
46094634 */
4610- ret = validate_unret (file );
4635+ ret = validate_unrets (file );
46114636 if (ret < 0 )
46124637 return ret ;
46134638 warnings += ret ;
0 commit comments