diff options
author | Josh Poimboeuf <jpoimboe@redhat.com> | 2016-03-09 01:07:01 -0500 |
---|---|---|
committer | Ingo Molnar <mingo@kernel.org> | 2016-03-09 04:48:10 -0500 |
commit | 1bcb58a099938c33acda78b212ed67b06b3359ef (patch) | |
tree | 24dfb31e7f6c4c953314afdf4cfdefc5147be5bc /tools | |
parent | 042ba73fe7eb63872ee2d6ac86410052210c1f16 (diff) |
objtool: Only print one warning per function
When objtool discovers an issue, it's very common for it to flood the
terminal with a lot of duplicate warnings. For example:
warning: objtool: rtlwifi_rate_mapping()+0x2e7: frame pointer state mismatch
warning: objtool: rtlwifi_rate_mapping()+0x2f3: frame pointer state mismatch
warning: objtool: rtlwifi_rate_mapping()+0x2ff: frame pointer state mismatch
warning: objtool: rtlwifi_rate_mapping()+0x30b: frame pointer state mismatch
...
The first warning is usually all you need. Change it to only warn once
per function.
Suggested-by: Ingo Molnar <mingo@kernel.org>
Signed-off-by: Josh Poimboeuf <jpoimboe@redhat.com>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Andy Lutomirski <luto@kernel.org>
Cc: Arnaldo Carvalho de Melo <acme@infradead.org>
Cc: Arnaldo Carvalho de Melo <acme@kernel.org>
Cc: Bernd Petrovitsch <bernd@petrovitsch.priv.at>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Chris J Arges <chris.j.arges@canonical.com>
Cc: Jiri Slaby <jslaby@suse.cz>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Michal Marek <mmarek@suse.cz>
Cc: Namhyung Kim <namhyung@gmail.com>
Cc: Pedro Alves <palves@redhat.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: live-patching@vger.kernel.org
Link: http://lkml.kernel.org/r/c47f3ca38aa01e2a9b6601f9e38efd414c3f3c18.1457502970.git.jpoimboe@redhat.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'tools')
-rw-r--r-- | tools/objtool/builtin-check.c | 48 |
1 files changed, 25 insertions, 23 deletions
diff --git a/tools/objtool/builtin-check.c b/tools/objtool/builtin-check.c index bfeee227aaab..7515cb2e879a 100644 --- a/tools/objtool/builtin-check.c +++ b/tools/objtool/builtin-check.c | |||
@@ -800,7 +800,7 @@ static int validate_branch(struct objtool_file *file, | |||
800 | struct instruction *insn; | 800 | struct instruction *insn; |
801 | struct section *sec; | 801 | struct section *sec; |
802 | unsigned char state; | 802 | unsigned char state; |
803 | int ret, warnings = 0; | 803 | int ret; |
804 | 804 | ||
805 | insn = first; | 805 | insn = first; |
806 | sec = insn->sec; | 806 | sec = insn->sec; |
@@ -809,7 +809,7 @@ static int validate_branch(struct objtool_file *file, | |||
809 | if (insn->alt_group && list_empty(&insn->alts)) { | 809 | if (insn->alt_group && list_empty(&insn->alts)) { |
810 | WARN_FUNC("don't know how to handle branch to middle of alternative instruction group", | 810 | WARN_FUNC("don't know how to handle branch to middle of alternative instruction group", |
811 | sec, insn->offset); | 811 | sec, insn->offset); |
812 | warnings++; | 812 | return 1; |
813 | } | 813 | } |
814 | 814 | ||
815 | while (1) { | 815 | while (1) { |
@@ -817,10 +817,10 @@ static int validate_branch(struct objtool_file *file, | |||
817 | if (frame_state(insn->state) != frame_state(state)) { | 817 | if (frame_state(insn->state) != frame_state(state)) { |
818 | WARN_FUNC("frame pointer state mismatch", | 818 | WARN_FUNC("frame pointer state mismatch", |
819 | sec, insn->offset); | 819 | sec, insn->offset); |
820 | warnings++; | 820 | return 1; |
821 | } | 821 | } |
822 | 822 | ||
823 | return warnings; | 823 | return 0; |
824 | } | 824 | } |
825 | 825 | ||
826 | /* | 826 | /* |
@@ -828,14 +828,15 @@ static int validate_branch(struct objtool_file *file, | |||
828 | * the next function. | 828 | * the next function. |
829 | */ | 829 | */ |
830 | if (is_fentry_call(insn) && (state & STATE_FENTRY)) | 830 | if (is_fentry_call(insn) && (state & STATE_FENTRY)) |
831 | return warnings; | 831 | return 0; |
832 | 832 | ||
833 | insn->visited = true; | 833 | insn->visited = true; |
834 | insn->state = state; | 834 | insn->state = state; |
835 | 835 | ||
836 | list_for_each_entry(alt, &insn->alts, list) { | 836 | list_for_each_entry(alt, &insn->alts, list) { |
837 | ret = validate_branch(file, alt->insn, state); | 837 | ret = validate_branch(file, alt->insn, state); |
838 | warnings += ret; | 838 | if (ret) |
839 | return 1; | ||
839 | } | 840 | } |
840 | 841 | ||
841 | switch (insn->type) { | 842 | switch (insn->type) { |
@@ -845,7 +846,7 @@ static int validate_branch(struct objtool_file *file, | |||
845 | if (state & STATE_FP_SAVED) { | 846 | if (state & STATE_FP_SAVED) { |
846 | WARN_FUNC("duplicate frame pointer save", | 847 | WARN_FUNC("duplicate frame pointer save", |
847 | sec, insn->offset); | 848 | sec, insn->offset); |
848 | warnings++; | 849 | return 1; |
849 | } | 850 | } |
850 | state |= STATE_FP_SAVED; | 851 | state |= STATE_FP_SAVED; |
851 | } | 852 | } |
@@ -856,7 +857,7 @@ static int validate_branch(struct objtool_file *file, | |||
856 | if (state & STATE_FP_SETUP) { | 857 | if (state & STATE_FP_SETUP) { |
857 | WARN_FUNC("duplicate frame pointer setup", | 858 | WARN_FUNC("duplicate frame pointer setup", |
858 | sec, insn->offset); | 859 | sec, insn->offset); |
859 | warnings++; | 860 | return 1; |
860 | } | 861 | } |
861 | state |= STATE_FP_SETUP; | 862 | state |= STATE_FP_SETUP; |
862 | } | 863 | } |
@@ -875,9 +876,9 @@ static int validate_branch(struct objtool_file *file, | |||
875 | if (!nofp && has_modified_stack_frame(insn)) { | 876 | if (!nofp && has_modified_stack_frame(insn)) { |
876 | WARN_FUNC("return without frame pointer restore", | 877 | WARN_FUNC("return without frame pointer restore", |
877 | sec, insn->offset); | 878 | sec, insn->offset); |
878 | warnings++; | 879 | return 1; |
879 | } | 880 | } |
880 | return warnings; | 881 | return 0; |
881 | 882 | ||
882 | case INSN_CALL: | 883 | case INSN_CALL: |
883 | if (is_fentry_call(insn)) { | 884 | if (is_fentry_call(insn)) { |
@@ -887,16 +888,16 @@ static int validate_branch(struct objtool_file *file, | |||
887 | 888 | ||
888 | ret = dead_end_function(file, insn->call_dest); | 889 | ret = dead_end_function(file, insn->call_dest); |
889 | if (ret == 1) | 890 | if (ret == 1) |
890 | return warnings; | 891 | return 0; |
891 | if (ret == -1) | 892 | if (ret == -1) |
892 | warnings++; | 893 | return 1; |
893 | 894 | ||
894 | /* fallthrough */ | 895 | /* fallthrough */ |
895 | case INSN_CALL_DYNAMIC: | 896 | case INSN_CALL_DYNAMIC: |
896 | if (!nofp && !has_valid_stack_frame(insn)) { | 897 | if (!nofp && !has_valid_stack_frame(insn)) { |
897 | WARN_FUNC("call without frame pointer save/setup", | 898 | WARN_FUNC("call without frame pointer save/setup", |
898 | sec, insn->offset); | 899 | sec, insn->offset); |
899 | warnings++; | 900 | return 1; |
900 | } | 901 | } |
901 | break; | 902 | break; |
902 | 903 | ||
@@ -905,15 +906,16 @@ static int validate_branch(struct objtool_file *file, | |||
905 | if (insn->jump_dest) { | 906 | if (insn->jump_dest) { |
906 | ret = validate_branch(file, insn->jump_dest, | 907 | ret = validate_branch(file, insn->jump_dest, |
907 | state); | 908 | state); |
908 | warnings += ret; | 909 | if (ret) |
910 | return 1; | ||
909 | } else if (has_modified_stack_frame(insn)) { | 911 | } else if (has_modified_stack_frame(insn)) { |
910 | WARN_FUNC("sibling call from callable instruction with changed frame pointer", | 912 | WARN_FUNC("sibling call from callable instruction with changed frame pointer", |
911 | sec, insn->offset); | 913 | sec, insn->offset); |
912 | warnings++; | 914 | return 1; |
913 | } /* else it's a sibling call */ | 915 | } /* else it's a sibling call */ |
914 | 916 | ||
915 | if (insn->type == INSN_JUMP_UNCONDITIONAL) | 917 | if (insn->type == INSN_JUMP_UNCONDITIONAL) |
916 | return warnings; | 918 | return 0; |
917 | 919 | ||
918 | break; | 920 | break; |
919 | 921 | ||
@@ -922,13 +924,13 @@ static int validate_branch(struct objtool_file *file, | |||
922 | has_modified_stack_frame(insn)) { | 924 | has_modified_stack_frame(insn)) { |
923 | WARN_FUNC("sibling call from callable instruction with changed frame pointer", | 925 | WARN_FUNC("sibling call from callable instruction with changed frame pointer", |
924 | sec, insn->offset); | 926 | sec, insn->offset); |
925 | warnings++; | 927 | return 1; |
926 | } | 928 | } |
927 | 929 | ||
928 | return warnings; | 930 | return 0; |
929 | 931 | ||
930 | case INSN_BUG: | 932 | case INSN_BUG: |
931 | return warnings; | 933 | return 0; |
932 | 934 | ||
933 | default: | 935 | default: |
934 | break; | 936 | break; |
@@ -937,12 +939,11 @@ static int validate_branch(struct objtool_file *file, | |||
937 | insn = next_insn_same_sec(file, insn); | 939 | insn = next_insn_same_sec(file, insn); |
938 | if (!insn) { | 940 | if (!insn) { |
939 | WARN("%s: unexpected end of section", sec->name); | 941 | WARN("%s: unexpected end of section", sec->name); |
940 | warnings++; | 942 | return 1; |
941 | return warnings; | ||
942 | } | 943 | } |
943 | } | 944 | } |
944 | 945 | ||
945 | return warnings; | 946 | return 0; |
946 | } | 947 | } |
947 | 948 | ||
948 | static bool is_gcov_insn(struct instruction *insn) | 949 | static bool is_gcov_insn(struct instruction *insn) |
@@ -1055,7 +1056,8 @@ static int validate_functions(struct objtool_file *file) | |||
1055 | if (insn->visited) | 1056 | if (insn->visited) |
1056 | continue; | 1057 | continue; |
1057 | 1058 | ||
1058 | if (!ignore_unreachable_insn(func, insn)) { | 1059 | if (!ignore_unreachable_insn(func, insn) && |
1060 | !warnings) { | ||
1059 | WARN_FUNC("function has unreachable instruction", insn->sec, insn->offset); | 1061 | WARN_FUNC("function has unreachable instruction", insn->sec, insn->offset); |
1060 | warnings++; | 1062 | warnings++; |
1061 | } | 1063 | } |