objtool: Better handle IRET
[linux-2.6-microblaze.git] / tools / objtool / check.c
index 9e854fd..781b3a3 100644 (file)
@@ -2065,15 +2065,14 @@ static int validate_return(struct symbol *func, struct instruction *insn, struct
  * tools/objtool/Documentation/stack-validation.txt.
  */
 static int validate_branch(struct objtool_file *file, struct symbol *func,
-                          struct instruction *first, struct insn_state state)
+                          struct instruction *insn, struct insn_state state)
 {
        struct alternative *alt;
-       struct instruction *insn, *next_insn;
+       struct instruction *next_insn;
        struct section *sec;
        u8 visited;
        int ret;
 
-       insn = first;
        sec = insn->sec;
 
        if (insn->alt_group && list_empty(&insn->alts)) {
@@ -2126,16 +2125,6 @@ static int validate_branch(struct objtool_file *file, struct symbol *func,
                                }
 
                                if (!save_insn->visited) {
-                                       /*
-                                        * Oops, no state to copy yet.
-                                        * Hopefully we can reach this
-                                        * instruction from another branch
-                                        * after the save insn has been
-                                        * visited.
-                                        */
-                                       if (insn == first)
-                                               return 0;
-
                                        WARN_FUNC("objtool isn't smart enough to handle this CFI save/restore combo",
                                                  sec, insn->offset);
                                        return 1;
@@ -2228,6 +2217,20 @@ static int validate_branch(struct objtool_file *file, struct symbol *func,
 
                        break;
 
+               case INSN_EXCEPTION_RETURN:
+                       if (handle_insn_ops(insn, &state))
+                               return 1;
+
+                       /*
+                        * This handles x86's sync_core() case, where we use an
+                        * IRET to self. All 'normal' IRET instructions are in
+                        * STT_NOTYPE entry symbols.
+                        */
+                       if (func)
+                               break;
+
+                       return 0;
+
                case INSN_CONTEXT_SWITCH:
                        if (func && (!next_insn || !next_insn->hint)) {
                                WARN_FUNC("unsupported instruction in callable function",