Process the ignore macros earlier and associate them with their
corresponding instructions.  This allows ignores to be checked in
get_jump_destinations() which is needed for some funky xen code which
introduces fake instructions (XEN_EMULATE_PREFIX).

Signed-off-by: Josh Poimboeuf <jpoim...@redhat.com>
---
 scripts/stackvalidate/stackvalidate.c | 77 +++++++++++++++++++++++++----------
 1 file changed, 56 insertions(+), 21 deletions(-)

diff --git a/scripts/stackvalidate/stackvalidate.c 
b/scripts/stackvalidate/stackvalidate.c
index a817130..6173412 100644
--- a/scripts/stackvalidate/stackvalidate.c
+++ b/scripts/stackvalidate/stackvalidate.c
@@ -49,7 +49,7 @@ struct instruction {
        unsigned int len, state;
        unsigned char type;
        unsigned long immediate;
-       bool alt_group, visited;
+       bool alt_group, visited, ignore;
        struct symbol *call_dest;
        struct instruction *jump_dest;
        struct list_head alts;
@@ -106,8 +106,7 @@ static struct argp argp = { options, parse_opt, args_doc, 0 
};
 /*
  * Check for the STACKVALIDATE_IGNORE_INSN macro.
  */
-static bool ignore_insn(struct elf *elf, struct section *sec,
-                       unsigned long offset)
+static bool ignore_insn(struct elf *elf, struct instruction *insn)
 {
        struct section *macro_sec;
        struct rela *rela;
@@ -118,8 +117,8 @@ static bool ignore_insn(struct elf *elf, struct section 
*sec,
 
        list_for_each_entry(rela, &macro_sec->rela->relas, list)
                if (rela->sym->type == STT_SECTION &&
-                   rela->sym == sec->sym &&
-                   rela->addend == offset)
+                   rela->sym == insn->sec->sym &&
+                   rela->addend == insn->offset)
                        return true;
 
        return false;
@@ -138,9 +137,11 @@ static bool ignore_func(struct elf *elf, struct symbol 
*func)
                return false;
 
        list_for_each_entry(rela, &macro_sec->rela->relas, list)
-               if (rela->sym == func)
+               if (rela->sym->sec == func->sec &&
+                   rela->addend == func->offset)
                        return true;
 
+
        return false;
 }
 
@@ -266,6 +267,44 @@ static int decode_instructions(struct elf *elf)
 }
 
 /*
+ * Warnings shouldn't be reported for ignored instructions.  Set insn->ignore
+ * for each ignored instruction and each instruction contained in an ignored
+ * function.
+ */
+static void get_ignores(struct elf *elf)
+{
+       struct instruction *insn;
+       struct section *sec;
+       struct symbol *func;
+
+       list_for_each_entry(insn, &insns, list)
+               insn->ignore = ignore_insn(elf, insn);
+
+       list_for_each_entry(sec, &elf->sections, list) {
+               list_for_each_entry(func, &sec->symbols, list) {
+                       if (func->type != STT_FUNC)
+                               continue;
+
+                       if (!ignore_func(elf, func))
+                               continue;
+
+                       insn = find_instruction(sec, func->offset);
+                       if (!insn)
+                               continue;
+
+                       list_for_each_entry_from(insn, &insns, list) {
+                               if (insn->sec != func->sec ||
+                                   insn->offset >= func->offset + func->len)
+                                       break;
+
+                               insn->ignore = true;
+                               insn->visited = true;
+                       }
+               }
+       }
+}
+
+/*
  * Find the destination instructions for all jumps.
  */
 static int get_jump_destinations(struct elf *elf)
@@ -300,7 +339,7 @@ static int get_jump_destinations(struct elf *elf)
                }
 
                insn->jump_dest = find_instruction(dest_sec, dest_off);
-               if (!insn->jump_dest) {
+               if (!insn->jump_dest && !insn->ignore) {
 
                        /*
                         * This is a special case where an alt instruction
@@ -591,6 +630,8 @@ static int decode_sections(struct elf *elf)
        if (ret)
                return ret;
 
+       get_ignores(elf);
+
        ret = get_jump_destinations(elf);
        if (ret)
                return ret;
@@ -734,7 +775,8 @@ static int validate_branch(struct elf *elf, struct 
instruction *first,
                        break;
 
                case INSN_JUMP_DYNAMIC:
-                       if (list_empty(&insn->alts) && insn->state) {
+                       if (list_empty(&insn->alts) && insn->state &&
+                           !insn->ignore) {
                                WARN("%s: sibling call from callable 
instruction with changed frame pointer",
                                     offstr(sec, insn->offset));
                                warnings++;
@@ -743,9 +785,11 @@ static int validate_branch(struct elf *elf, struct 
instruction *first,
                        return warnings;
 
                case INSN_CONTEXT_SWITCH:
-                       WARN("%s: kernel entry/exit from callable instruction",
-                            offstr(sec, insn->offset));
-                       warnings++;
+                       if (!insn->ignore) {
+                               WARN("%s: kernel entry/exit from callable 
instruction",
+                                    offstr(sec, insn->offset));
+                               warnings++;
+                       }
 
                        return warnings;
 
@@ -786,15 +830,6 @@ static int validate_functions(struct elf *elf)
                                continue;
                        }
 
-                       if (ignore_func(elf, func)) {
-                               list_for_each_entry_from(insn, &insns, list) {
-                                       if (insn->sec != func->sec ||
-                                           insn->offset >= func->offset + 
func->len)
-                                               break;
-                                       insn->visited = true;
-                               }
-                       }
-
                        ret = validate_branch(elf, insn, 0);
                        warnings += ret;
                }
@@ -835,7 +870,7 @@ static int validate_uncallable_instructions(struct elf *elf)
 
        list_for_each_entry(insn, &insns, list) {
                if (!insn->visited && insn->type == INSN_RETURN &&
-                   !ignore_insn(elf, insn->sec, insn->offset)) {
+                   !insn->ignore) {
                        WARN("%s: return instruction outside of a callable 
function",
                             offstr(insn->sec, insn->offset));
                        warnings++;
-- 
2.1.0

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to