objtool: Make noinstr hacks optional
authorJosh Poimboeuf <jpoimboe@redhat.com>
Mon, 18 Apr 2022 16:50:40 +0000 (09:50 -0700)
committerPeter Zijlstra <peterz@infradead.org>
Fri, 22 Apr 2022 10:32:04 +0000 (12:32 +0200)
Objtool has some hacks in place to workaround toolchain limitations
which otherwise would break no-instrumentation rules.  Make the hacks
explicit (and optional for other arches) by turning it into a cmdline
option and kernel config option.

Signed-off-by: Josh Poimboeuf <jpoimboe@redhat.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Reviewed-by: Miroslav Benes <mbenes@suse.cz>
Link: https://lkml.kernel.org/r/b326eeb9c33231b9dfbb925f194ed7ee40edcd7c.1650300597.git.jpoimboe@redhat.com
arch/Kconfig
arch/x86/Kconfig
lib/Kconfig.debug
lib/Kconfig.kcsan
scripts/Makefile.build
scripts/link-vmlinux.sh
tools/objtool/builtin-check.c
tools/objtool/check.c
tools/objtool/include/objtool/builtin.h

index 9dce6d6..6ba6e34 100644 (file)
@@ -1035,6 +1035,9 @@ config HAVE_OBJTOOL
 config HAVE_JUMP_LABEL_HACK
        bool
 
+config HAVE_NOINSTR_HACK
+       bool
+
 config HAVE_STACK_VALIDATION
        bool
        help
index 26d012f..06e7cdd 100644 (file)
@@ -231,6 +231,7 @@ config X86
        select HAVE_MOD_ARCH_SPECIFIC
        select HAVE_MOVE_PMD
        select HAVE_MOVE_PUD
+       select HAVE_NOINSTR_HACK                if HAVE_OBJTOOL
        select HAVE_NMI
        select HAVE_OBJTOOL                     if X86_64
        select HAVE_OPTPROBES
index c0e4e47..7d2bbc3 100644 (file)
@@ -2036,11 +2036,11 @@ config KCOV
        bool "Code coverage for fuzzing"
        depends on ARCH_HAS_KCOV
        depends on CC_HAS_SANCOV_TRACE_PC || GCC_PLUGINS
-       depends on !ARCH_WANTS_NO_INSTR || HAVE_OBJTOOL || \
+       depends on !ARCH_WANTS_NO_INSTR || HAVE_NOINSTR_HACK || \
                   GCC_VERSION >= 120000 || CLANG_VERSION >= 130000
        select DEBUG_FS
        select GCC_PLUGIN_SANCOV if !CC_HAS_SANCOV_TRACE_PC
-       select OBJTOOL if HAVE_OBJTOOL
+       select OBJTOOL if HAVE_NOINSTR_HACK
        help
          KCOV exposes kernel code coverage information in a form suitable
          for coverage-guided fuzzing (randomized testing).
index 901c3b5..47a693c 100644 (file)
@@ -187,8 +187,9 @@ config KCSAN_WEAK_MEMORY
        # We can either let objtool nop __tsan_func_{entry,exit}() and builtin
        # atomics instrumentation in .noinstr.text, or use a compiler that can
        # implement __no_kcsan to really remove all instrumentation.
-       depends on HAVE_OBJTOOL || CC_IS_GCC || CLANG_VERSION >= 140000
-       select OBJTOOL if HAVE_OBJTOOL
+       depends on !ARCH_WANTS_NO_INSTR || HAVE_NOINSTR_HACK || \
+                  CC_IS_GCC || CLANG_VERSION >= 140000
+       select OBJTOOL if HAVE_NOINSTR_HACK
        help
          Enable support for modeling a subset of weak memory, which allows
          detecting a subset of data races due to missing memory barriers.
index f1d2c2e..6c206a1 100644 (file)
@@ -228,6 +228,7 @@ objtool := $(objtree)/tools/objtool/objtool
 
 objtool_args =                                                         \
        $(if $(CONFIG_HAVE_JUMP_LABEL_HACK), --hacks=jump_label)        \
+       $(if $(CONFIG_HAVE_NOINSTR_HACK), --hacks=noinstr)              \
        $(if $(CONFIG_X86_KERNEL_IBT), --lto --ibt)                     \
        $(if $(CONFIG_FTRACE_MCOUNT_USE_OBJTOOL), --mcount)             \
        $(if $(CONFIG_UNWINDER_ORC), --orc)                             \
index fa1f168..90c9c4c 100755 (executable)
@@ -121,6 +121,10 @@ objtool_link()
                        objtoolopt="${objtoolopt} --hacks=jump_label"
                fi
 
+               if is_enabled CONFIG_HAVE_NOINSTR_HACK; then
+                       objtoolopt="${objtoolopt} --hacks=noinstr"
+               fi
+
                if is_enabled CONFIG_X86_KERNEL_IBT; then
                        objtoolopt="${objtoolopt} --ibt"
                fi
index b2c626d..1803a63 100644 (file)
@@ -47,12 +47,17 @@ static int parse_hacks(const struct option *opt, const char *str, int unset)
                found = true;
        }
 
+       if (!str || strstr(str, "noinstr")) {
+               opts.hack_noinstr = true;
+               found = true;
+       }
+
        return found ? 0 : -1;
 }
 
 const struct option check_options[] = {
        OPT_GROUP("Actions:"),
-       OPT_CALLBACK_OPTARG('h', "hacks", NULL, NULL, "jump_label", "patch toolchain bugs/limitations", parse_hacks),
+       OPT_CALLBACK_OPTARG('h', "hacks", NULL, NULL, "jump_label,noinstr", "patch toolchain bugs/limitations", parse_hacks),
        OPT_BOOLEAN('i', "ibt", &opts.ibt, "validate and annotate IBT"),
        OPT_BOOLEAN('m', "mcount", &opts.mcount, "annotate mcount/fentry calls for ftrace"),
        OPT_BOOLEAN('n', "noinstr", &opts.noinstr, "validate noinstr rules"),
@@ -108,6 +113,7 @@ int cmd_parse_options(int argc, const char **argv, const char * const usage[])
 static bool opts_valid(void)
 {
        if (opts.hack_jump_label        ||
+           opts.hack_noinstr           ||
            opts.ibt                    ||
            opts.mcount                 ||
            opts.noinstr                ||
index d157978..30b24dc 100644 (file)
@@ -1144,7 +1144,7 @@ static void annotate_call_site(struct objtool_file *file,
         * attribute so they need a little help, NOP out any such calls from
         * noinstr text.
         */
-       if (insn->sec->noinstr && sym->profiling_func) {
+       if (opts.hack_noinstr && insn->sec->noinstr && sym->profiling_func) {
                if (reloc) {
                        reloc->type = R_NONE;
                        elf_write_reloc(file->elf, reloc);
index c6acf05..f3a1a75 100644 (file)
@@ -13,6 +13,7 @@ struct opts {
        /* actions: */
        bool dump_orc;
        bool hack_jump_label;
+       bool hack_noinstr;
        bool ibt;
        bool mcount;
        bool noinstr;