diff options
author | Sami Tolvanen <samitolvanen@google.com> | 2019-05-08 13:53:41 -0700 |
---|---|---|
committer | Alistair Delva <adelva@google.com> | 2019-11-26 13:27:41 -0800 |
commit | c4fa71e25126d32473493b648af0767e4492a85b (patch) | |
tree | 9a3d50a769da1eefb9724c9e0e4a664a6e2409d1 | |
parent | 310afefe71d480d563f3691b74bff61a53ba81ca (diff) |
ANDROID: kbuild: fix dynamic ftrace with clang LTO
With CONFIG_LTO_CLANG enabled, LLVM IR won't be compiled into object
files until modpost_link. This change postpones calls to recordmcount
until after this step.
In order to exclude ftrace_process_locs from inspection, we add a new
code section .text..ftrace, which we tell recordmcount to ignore, and
a __norecordmcount attribute for moving functions to this section.
Bug: 145210207
Change-Id: Ib77f7c431fce54243c46d584b55761ed2342965c
Signed-off-by: Sami Tolvanen <samitolvanen@google.com>
-rw-r--r-- | arch/Kconfig | 2 | ||||
-rw-r--r-- | include/asm-generic/vmlinux.lds.h | 1 | ||||
-rw-r--r-- | include/linux/compiler-clang.h | 7 | ||||
-rw-r--r-- | include/linux/compiler_types.h | 4 | ||||
-rw-r--r-- | kernel/trace/ftrace.c | 6 | ||||
-rw-r--r-- | scripts/Makefile.build | 11 | ||||
-rw-r--r-- | scripts/Makefile.modfinal | 4 | ||||
-rwxr-xr-x | scripts/link-vmlinux.sh | 18 | ||||
-rw-r--r-- | scripts/recordmcount.c | 4 |
9 files changed, 52 insertions, 5 deletions
diff --git a/arch/Kconfig b/arch/Kconfig index 1766abf2f5c2..12f11fcba9cd 100644 --- a/arch/Kconfig +++ b/arch/Kconfig @@ -590,7 +590,7 @@ config LTO_CLANG bool "Use Clang's Link Time Optimization (LTO) (EXPERIMENTAL)" depends on ARCH_SUPPORTS_LTO_CLANG depends on !KASAN - depends on !FTRACE_MCOUNT_RECORD + depends on !FTRACE_MCOUNT_RECORD || HAVE_C_RECORDMCOUNT depends on CC_IS_CLANG && CLANG_VERSION >= 100000 && LD_IS_LLD select LTO help diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h index ec4827773569..73a215a7d33f 100644 --- a/include/asm-generic/vmlinux.lds.h +++ b/include/asm-generic/vmlinux.lds.h @@ -521,6 +521,7 @@ ALIGN_FUNCTION(); \ *(.text.hot TEXT_MAIN .text.fixup .text.unlikely) \ *(.text..refcount) \ + *(.text..ftrace) \ *(.ref.text) \ MEM_KEEP(init.text*) \ MEM_KEEP(exit.text*) \ diff --git a/include/linux/compiler-clang.h b/include/linux/compiler-clang.h index 18fc4d29ef27..5e97289e1e67 100644 --- a/include/linux/compiler-clang.h +++ b/include/linux/compiler-clang.h @@ -48,3 +48,10 @@ #else # define __noscs #endif + +#ifdef CONFIG_LTO_CLANG +#ifdef CONFIG_FTRACE_MCOUNT_RECORD +#define __norecordmcount \ + __attribute__((__section__(".text..ftrace"))) +#endif +#endif diff --git a/include/linux/compiler_types.h b/include/linux/compiler_types.h index be5d5be4b1ae..48e7e3396656 100644 --- a/include/linux/compiler_types.h +++ b/include/linux/compiler_types.h @@ -206,6 +206,10 @@ struct ftrace_likely_data { # define __noscs #endif +#ifndef __norecordmcount +# define __norecordmcount +#endif + #ifndef asm_volatile_goto #define asm_volatile_goto(x...) asm goto(x) #endif diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c index f296d89be757..3feec7020891 100644 --- a/kernel/trace/ftrace.c +++ b/kernel/trace/ftrace.c @@ -5564,9 +5564,9 @@ static int ftrace_cmp_ips(const void *a, const void *b) return 0; } -static int ftrace_process_locs(struct module *mod, - unsigned long *start, - unsigned long *end) +static int __norecordmcount ftrace_process_locs(struct module *mod, + unsigned long *start, + unsigned long *end) { struct ftrace_page *start_pg; struct ftrace_page *pg; diff --git a/scripts/Makefile.build b/scripts/Makefile.build index 7aefd2a1347e..827945fc381d 100644 --- a/scripts/Makefile.build +++ b/scripts/Makefile.build @@ -177,6 +177,12 @@ ifdef BUILD_C_RECORDMCOUNT ifeq ("$(origin RECORDMCOUNT_WARN)", "command line") RECORDMCOUNT_FLAGS = -w endif + +ifdef CONFIG_LTO_CLANG +# With LTO, we postpone running recordmcount until after the LTO link step, so +# let's export the parameters for the link script. +export RECORDMCOUNT_FLAGS +else # Due to recursion, we must skip empty.o. # The empty.o file is created in the make process in order to determine # the target endianness and word size. It is made before all other C @@ -185,6 +191,8 @@ sub_cmd_record_mcount = \ if [ $(@) != "scripts/mod/empty.o" ]; then \ $(objtree)/scripts/recordmcount $(RECORDMCOUNT_FLAGS) "$(@)"; \ fi; +endif + recordmcount_source := $(srctree)/scripts/recordmcount.c \ $(srctree)/scripts/recordmcount.h else @@ -194,10 +202,13 @@ sub_cmd_record_mcount = perl $(srctree)/scripts/recordmcount.pl "$(ARCH)" \ "$(OBJDUMP)" "$(OBJCOPY)" "$(CC) $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS)" \ "$(LD) $(KBUILD_LDFLAGS)" "$(NM)" "$(RM)" "$(MV)" \ "$(if $(part-of-module),1,0)" "$(@)"; + recordmcount_source := $(srctree)/scripts/recordmcount.pl endif # BUILD_C_RECORDMCOUNT +ifndef CONFIG_LTO_CLANG cmd_record_mcount = $(if $(findstring $(strip $(CC_FLAGS_FTRACE)),$(_c_flags)), \ $(sub_cmd_record_mcount)) +endif # CONFIG_LTO_CLANG endif # CC_USING_RECORD_MCOUNT endif # CONFIG_FTRACE_MCOUNT_RECORD diff --git a/scripts/Makefile.modfinal b/scripts/Makefile.modfinal index 147ed6c243ef..6eb343ed0cad 100644 --- a/scripts/Makefile.modfinal +++ b/scripts/Makefile.modfinal @@ -41,6 +41,10 @@ ifdef CONFIG_LTO_CLANG -o $@ --whole-archive \ $(filter-out FORCE,$(^:$(modpost-ext).o=.o)); \ $(if $(ARCH_POSTLINK), $(MAKE) -f $(ARCH_POSTLINK) $@, true) + + ifdef CONFIG_FTRACE_MCOUNT_RECORD + cmd_ld_ko_o += ; $(objtree)/scripts/recordmcount $(RECORDMCOUNT_FLAGS) $@ + endif else cmd_ld_ko_o = \ $(LD) -r $(KBUILD_LDFLAGS) \ diff --git a/scripts/link-vmlinux.sh b/scripts/link-vmlinux.sh index 22aaec3e4604..1e19c800bfa2 100755 --- a/scripts/link-vmlinux.sh +++ b/scripts/link-vmlinux.sh @@ -87,6 +87,19 @@ modpost_link() ${LD} ${KBUILD_LDFLAGS} -r -o ${1} $(modversions) ${objects} } +# If CONFIG_LTO_CLANG is selected, we postpone running recordmcount until +# we have compiled LLVM IR to an object file. +recordmcount() +{ + if [ -z "${CONFIG_LTO_CLANG}" ]; then + return + fi + + if [ -n "${CONFIG_FTRACE_MCOUNT_RECORD}" ]; then + scripts/recordmcount ${RECORDMCOUNT_FLAGS} $* + fi +} + # Link of vmlinux # ${1} - output file # ${2}, ${3}, ... - optional extra .o files @@ -287,6 +300,11 @@ modpost_link vmlinux.o # modpost vmlinux.o to check for section mismatches ${MAKE} -f "${srctree}/scripts/Makefile.modpost" MODPOST_VMLINUX=1 +if [ -n "${CONFIG_LTO_CLANG}" ]; then + # Call recordmcount if needed + recordmcount vmlinux.o +fi + info MODINFO modules.builtin.modinfo ${OBJCOPY} -j .modinfo -O binary vmlinux.o modules.builtin.modinfo diff --git a/scripts/recordmcount.c b/scripts/recordmcount.c index 612268eabef4..a9fa776fb881 100644 --- a/scripts/recordmcount.c +++ b/scripts/recordmcount.c @@ -408,7 +408,9 @@ static int is_mcounted_section_name(char const *const txtname) strcmp(".irqentry.text", txtname) == 0 || strcmp(".softirqentry.text", txtname) == 0 || strcmp(".kprobes.text", txtname) == 0 || - strcmp(".cpuidle.text", txtname) == 0; + strcmp(".cpuidle.text", txtname) == 0 || + (strncmp(".text.", txtname, 6) == 0 && + strcmp(".text..ftrace", txtname) != 0); } static char const *already_has_rel_mcount = "success"; /* our work here is done! */ |