aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJosh Poimboeuf <jpoimboe@redhat.com>2016-10-13 17:22:53 -0400
committerIngo Molnar <mingo@kernel.org>2016-10-16 03:12:36 -0400
commit9cfffb116887b1b7c51cd4e3fa5790dc52a0758f (patch)
tree1a5e59f34f0035e78e18fbfac9f6a4d791476598
parent3732710ff6f2ce2b1b7f044937a422b717d4f953 (diff)
objtool: Skip all "unreachable instruction" warnings for gcov kernels
Recently objtool has started reporting a few "unreachable instruction" warnings when CONFIG_GCOV is enabled for newer versions of GCC. Usually this warning means there's some new control flow that objtool doesn't understand. But in this case, objtool is correct and the instructions really are inaccessible. It's an annoying quirk of gcov, but it's harmless, so it's ok to just silence the warnings. With older versions of GCC, it was relatively easy to detect gcov-specific instructions and to skip any unreachable warnings produced by them. But GCC 6 has gotten craftier. Instead of continuing to play whack-a-mole with gcov, just use a bigger, more permanent hammer and disable unreachable warnings for the whole file when gcov is enabled. This is fine to do because a) unreachable warnings are usually of questionable value; and b) gcov isn't used for production kernels and we can relax the checks a bit there. Reported-by: kbuild test robot <fengguang.wu@intel.com> Signed-off-by: Josh Poimboeuf <jpoimboe@redhat.com> Cc: Andy Lutomirski <luto@kernel.org> Cc: Arnd Bergmann <arnd@arndb.de> Cc: Borislav Petkov <bp@alien8.de> Cc: Brian Gerst <brgerst@gmail.com> Cc: Denys Vlasenko <dvlasenk@redhat.com> Cc: H. Peter Anvin <hpa@zytor.com> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Thomas Gleixner <tglx@linutronix.de> Link: http://lkml.kernel.org/r/38d5c87d61d9cd46486dd2c86f46603dff0df86f.1476393584.git.jpoimboe@redhat.com Signed-off-by: Ingo Molnar <mingo@kernel.org>
-rw-r--r--tools/objtool/builtin-check.c57
1 files changed, 26 insertions, 31 deletions
diff --git a/tools/objtool/builtin-check.c b/tools/objtool/builtin-check.c
index a00a05d287e7..4490601a9235 100644
--- a/tools/objtool/builtin-check.c
+++ b/tools/objtool/builtin-check.c
@@ -97,6 +97,19 @@ static struct instruction *next_insn_same_sec(struct objtool_file *file,
97 return next; 97 return next;
98} 98}
99 99
100static bool gcov_enabled(struct objtool_file *file)
101{
102 struct section *sec;
103 struct symbol *sym;
104
105 list_for_each_entry(sec, &file->elf->sections, list)
106 list_for_each_entry(sym, &sec->symbol_list, list)
107 if (!strncmp(sym->name, "__gcov_.", 8))
108 return true;
109
110 return false;
111}
112
100#define for_each_insn(file, insn) \ 113#define for_each_insn(file, insn) \
101 list_for_each_entry(insn, &file->insn_list, list) 114 list_for_each_entry(insn, &file->insn_list, list)
102 115
@@ -1041,34 +1054,6 @@ static int validate_branch(struct objtool_file *file,
1041 return 0; 1054 return 0;
1042} 1055}
1043 1056
1044static bool is_gcov_insn(struct instruction *insn)
1045{
1046 struct rela *rela;
1047 struct section *sec;
1048 struct symbol *sym;
1049 unsigned long offset;
1050
1051 rela = find_rela_by_dest_range(insn->sec, insn->offset, insn->len);
1052 if (!rela)
1053 return false;
1054
1055 if (rela->sym->type != STT_SECTION)
1056 return false;
1057
1058 sec = rela->sym->sec;
1059 offset = rela->addend + insn->offset + insn->len - rela->offset;
1060
1061 list_for_each_entry(sym, &sec->symbol_list, list) {
1062 if (sym->type != STT_OBJECT)
1063 continue;
1064
1065 if (offset >= sym->offset && offset < sym->offset + sym->len)
1066 return (!memcmp(sym->name, "__gcov0.", 8));
1067 }
1068
1069 return false;
1070}
1071
1072static bool is_kasan_insn(struct instruction *insn) 1057static bool is_kasan_insn(struct instruction *insn)
1073{ 1058{
1074 return (insn->type == INSN_CALL && 1059 return (insn->type == INSN_CALL &&
@@ -1090,9 +1075,6 @@ static bool ignore_unreachable_insn(struct symbol *func,
1090 if (insn->type == INSN_NOP) 1075 if (insn->type == INSN_NOP)
1091 return true; 1076 return true;
1092 1077
1093 if (is_gcov_insn(insn))
1094 return true;
1095
1096 /* 1078 /*
1097 * Check if this (or a subsequent) instruction is related to 1079 * Check if this (or a subsequent) instruction is related to
1098 * CONFIG_UBSAN or CONFIG_KASAN. 1080 * CONFIG_UBSAN or CONFIG_KASAN.
@@ -1153,6 +1135,19 @@ static int validate_functions(struct objtool_file *file)
1153 ignore_unreachable_insn(func, insn)) 1135 ignore_unreachable_insn(func, insn))
1154 continue; 1136 continue;
1155 1137
1138 /*
1139 * gcov produces a lot of unreachable
1140 * instructions. If we get an unreachable
1141 * warning and the file has gcov enabled, just
1142 * ignore it, and all other such warnings for
1143 * the file.
1144 */
1145 if (!file->ignore_unreachables &&
1146 gcov_enabled(file)) {
1147 file->ignore_unreachables = true;
1148 continue;
1149 }
1150
1156 WARN_FUNC("function has unreachable instruction", insn->sec, insn->offset); 1151 WARN_FUNC("function has unreachable instruction", insn->sec, insn->offset);
1157 warnings++; 1152 warnings++;
1158 } 1153 }