[PATCH v2 23/23] objtool, kcsan: Remove memory barrier instrumentation from noinstr

Marco Elver
2021-11-18T08:16:48Z

Teach objtool to turn instrumentation required for memory barrier
modeling into nops in noinstr text.

The __tsan_func_entry/exit calls are still emitted by compilers even
with the __no_sanitize_thread attribute. The memory barrier
instrumentation will be inserted explicitly (without compiler help), and
thus needs to also explicitly be removed.

Signed-off-by: Marco Elver <elver@google.com>
---
v2:
* Rewrite after rebase to v5.16-rc1.
---
tools/objtool/check.c | 37 ++++++++++++++++++++++-------
tools/objtool/include/objtool/elf.h | 2 +-
2 files changed, 30 insertions(+), 9 deletions(-)

diff --git a/tools/objtool/check.c b/tools/objtool/check.c
index 61dfb66b30b6..2b2587e5ec69 100644
--- a/tools/objtool/check.c
+++ b/tools/objtool/check.c
@@ -1071,12 +1071,7 @@ static void annotate_call_site(struct objtool_file *file,
return;
}

- /*
- * Many compilers cannot disable KCOV with a function attribute
- * so they need a little help, NOP out any KCOV calls from noinstr
- * text.
- */
- if (insn->sec->noinstr && sym->kcov) {
+ if (insn->sec->noinstr && sym->removable_instr) {
if (reloc) {
reloc->type = R_NONE;
elf_write_reloc(file->elf, reloc);
@@ -1991,6 +1986,32 @@ static int read_intra_function_calls(struct objtool_file *file)
return 0;
}

+static bool is_removable_instr(const char *name)
+{
+ /*
+ * Many compilers cannot disable KCOV with a function attribute so they
+ * need a little help, NOP out any KCOV calls from noinstr text.
+ */
+ if (!strncmp(name, "__sanitizer_cov_", 16))
+ return true;
+
+ /*
+ * Compilers currently do not remove __tsan_func_entry/exit with the
+ * __no_sanitize_thread attribute, remove them.
+ *
+ * Memory barrier instrumentation is not emitted by the compiler, but
+ * inserted explicitly, so we need to also remove them.
+ */
+ if (!strncmp(name, "__tsan_func_", 12) ||
+ !strcmp(name, "__kcsan_mb") ||
+ !strcmp(name, "__kcsan_wmb") ||
+ !strcmp(name, "__kcsan_rmb") ||
+ !strcmp(name, "__kcsan_release"))
+ return true;
+
+ return false;
+}
+
static int classify_symbols(struct objtool_file *file)
{
struct section *sec;
@@ -2011,8 +2032,8 @@ static int classify_symbols(struct objtool_file *file)
if (!strcmp(func->name, "__fentry__"))
func->fentry = true;

- if (!strncmp(func->name, "__sanitizer_cov_", 16))
- func->kcov = true;
+ if (is_removable_instr(func->name))
+ func->removable_instr = true;
}
}

diff --git a/tools/objtool/include/objtool/elf.h b/tools/objtool/include/objtool/elf.h
index cdc739fa9a6f..62e790a09ad2 100644
--- a/tools/objtool/include/objtool/elf.h
+++ b/tools/objtool/include/objtool/elf.h
@@ -58,7 +58,7 @@ struct symbol {
u8 static_call_tramp : 1;
u8 retpoline_thunk : 1;
u8 fentry : 1;
- u8 kcov : 1;
+ u8 removable_instr : 1;
struct list_head pv_target;
};

--
2.34.0.rc2.393.gf8c9666880-goog