diff options
-rw-r--r-- | tools/objtool/builtin-check.c | 57 |
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 | ||
100 | static 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 | ||
1044 | static 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 | |||
1072 | static bool is_kasan_insn(struct instruction *insn) | 1057 | static 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 | } |