summaryrefslogtreecommitdiffstats
path: root/scripts
diff options
context:
space:
mode:
Diffstat (limited to 'scripts')
-rw-r--r--scripts/Kconfig.include5
-rw-r--r--scripts/Makefile2
-rw-r--r--scripts/Makefile.build82
-rw-r--r--scripts/Makefile.clean31
-rw-r--r--scripts/Makefile.extrawarn121
-rw-r--r--scripts/Makefile.host39
-rw-r--r--scripts/Makefile.kasan11
-rw-r--r--scripts/Makefile.lib63
-rw-r--r--scripts/Makefile.modfinal60
-rw-r--r--scripts/Makefile.modpost133
-rw-r--r--scripts/Makefile.package (renamed from scripts/package/Makefile)43
-rw-r--r--scripts/basic/Makefile14
-rwxr-xr-xscripts/checkpatch.pl69
-rw-r--r--scripts/coccinelle/api/atomic_as_refcounter.cocci1
-rw-r--r--scripts/coccinelle/api/platform_get_irq.cocci102
-rw-r--r--scripts/coccinelle/misc/add_namespace.cocci23
-rwxr-xr-xscripts/export_report.pl2
-rw-r--r--scripts/gcc-plugins/randomize_layout_plugin.c10
-rw-r--r--scripts/gdb/linux/symbols.py4
-rw-r--r--scripts/genksyms/Makefile11
-rw-r--r--scripts/genksyms/keywords.c6
-rw-r--r--scripts/genksyms/lex.l32
-rw-r--r--scripts/genksyms/parse.y32
-rwxr-xr-xscripts/headers_install.sh78
-rw-r--r--scripts/kconfig/Makefile10
-rw-r--r--scripts/kconfig/confdata.c4
-rwxr-xr-xscripts/kconfig/merge_config.sh12
-rwxr-xr-xscripts/kernel-doc3
-rwxr-xr-xscripts/link-vmlinux.sh94
-rwxr-xr-xscripts/mkcompile_h4
-rwxr-xr-xscripts/mkmakefile4
-rw-r--r--scripts/mod/file2alias.c5
-rw-r--r--scripts/mod/modpost.c198
-rw-r--r--scripts/mod/modpost.h9
-rw-r--r--scripts/nsdeps58
-rw-r--r--scripts/recordmcount.c321
-rw-r--r--scripts/recordmcount.h150
-rwxr-xr-xscripts/tools-support-relr.sh16
38 files changed, 1204 insertions, 658 deletions
diff --git a/scripts/Kconfig.include b/scripts/Kconfig.include
index 8a5c4d645eb1..d4adfbe42690 100644
--- a/scripts/Kconfig.include
+++ b/scripts/Kconfig.include
@@ -25,7 +25,7 @@ failure = $(if-success,$(1),n,y)
# $(cc-option,<flag>)
# Return y if the compiler supports <flag>, n otherwise
-cc-option = $(success,$(CC) -Werror $(1) -E -x c /dev/null -o /dev/null)
+cc-option = $(success,$(CC) -Werror $(CLANG_FLAGS) $(1) -E -x c /dev/null -o /dev/null)
# $(ld-option,<flag>)
# Return y if the linker supports <flag>, n otherwise
@@ -35,5 +35,8 @@ ld-option = $(success,$(LD) -v $(1))
$(error-if,$(failure,command -v $(CC)),compiler '$(CC)' not found)
$(error-if,$(failure,command -v $(LD)),linker '$(LD)' not found)
+# Fail if the linker is gold as it's not capable of linking the kernel proper
+$(error-if,$(success, $(LD) -v | grep -q gold), gold linker '$(LD)' not supported)
+
# gcc version including patch level
gcc-version := $(shell,$(srctree)/scripts/gcc-version.sh $(CC))
diff --git a/scripts/Makefile b/scripts/Makefile
index 532f7e0915c3..3e86b300f5a1 100644
--- a/scripts/Makefile
+++ b/scripts/Makefile
@@ -36,4 +36,4 @@ subdir-$(CONFIG_MODVERSIONS) += genksyms
subdir-$(CONFIG_SECURITY_SELINUX) += selinux
# Let clean descend into subdirs
-subdir- += basic dtc gdb kconfig mod package
+subdir- += basic dtc gdb kconfig mod
diff --git a/scripts/Makefile.build b/scripts/Makefile.build
index 0d434d0afc0b..f72aba64d611 100644
--- a/scripts/Makefile.build
+++ b/scripts/Makefile.build
@@ -52,6 +52,13 @@ ifndef obj
$(warning kbuild: Makefile.build is included improperly)
endif
+ifeq ($(need-modorder),)
+ifneq ($(obj-m),)
+$(warning $(patsubst %.o,'%.ko',$(obj-m)) will not be built even though obj-m is specified.)
+$(warning You cannot use subdir-y/m to visit a module Makefile. Use obj-y/m instead.)
+endif
+endif
+
# ===========================================================================
ifneq ($(strip $(lib-y) $(lib-m) $(lib-)),)
@@ -69,11 +76,6 @@ endif
mod-targets := $(patsubst %.o, %.mod, $(obj-m))
-__build: $(if $(KBUILD_BUILTIN),$(builtin-target) $(lib-target) $(extra-y)) \
- $(if $(KBUILD_MODULES),$(obj-m) $(mod-targets) $(modorder-target)) \
- $(subdir-ym) $(always)
- @:
-
# Linus' kernel sanity checking tool
ifeq ($(KBUILD_CHECKSRC),1)
quiet_cmd_checksrc = CHECK $<
@@ -83,23 +85,13 @@ else ifeq ($(KBUILD_CHECKSRC),2)
cmd_force_checksrc = $(CHECK) $(CHECKFLAGS) $(c_flags) $<
endif
-ifneq ($(KBUILD_ENABLE_EXTRA_GCC_CHECKS),)
+ifneq ($(KBUILD_EXTRA_WARN),)
cmd_checkdoc = $(srctree)/scripts/kernel-doc -none $<
endif
# Compile C sources (.c)
# ---------------------------------------------------------------------------
-# Default is built-in, unless we know otherwise
-$(foreach x, i ll lst o s symtypes, $(patsubst %.o,%.$(x),$(real-obj-m))): \
- part-of-module := y
-
-modkern_cflags = \
- $(if $(part-of-module), \
- $(KBUILD_CFLAGS_MODULE) $(CFLAGS_MODULE), \
- $(KBUILD_CFLAGS_KERNEL) $(CFLAGS_KERNEL))
-quiet_modtag = $(if $(part-of-module),[M], )
-
quiet_cmd_cc_s_c = CC $(quiet_modtag) $@
cmd_cc_s_c = $(CC) $(filter-out $(DEBUG_CFLAGS), $(c_flags)) $(DISABLE_LTO) -fverbose-asm -S -o $@ $<
@@ -303,11 +295,6 @@ $(obj)/%.h.s: $(src)/%.h FORCE
# Compile assembler sources (.S)
# ---------------------------------------------------------------------------
-modkern_aflags := $(KBUILD_AFLAGS_KERNEL) $(AFLAGS_KERNEL)
-
-$(real-obj-m) : modkern_aflags := $(KBUILD_AFLAGS_MODULE) $(AFLAGS_MODULE)
-$(real-obj-m:.o=.s): modkern_aflags := $(KBUILD_AFLAGS_MODULE) $(AFLAGS_MODULE)
-
# .S file exports must have their C prototypes defined in asm/asm-prototypes.h
# or a file that it includes, in order to get versioned symbols. We build a
# dummy C file that includes asm-prototypes and the EXPORT_SYMBOL lines from
@@ -349,11 +336,7 @@ $(obj)/%.s: $(src)/%.S FORCE
quiet_cmd_as_o_S = AS $(quiet_modtag) $@
cmd_as_o_S = $(CC) $(a_flags) -c -o $@ $<
-ifdef CONFIG_MODVERSIONS
-
-ASM_PROTOTYPES := $(wildcard $(srctree)/arch/$(SRCARCH)/include/asm/asm-prototypes.h)
-
-ifneq ($(ASM_PROTOTYPES),)
+ifdef CONFIG_ASM_MODVERSIONS
# versioning matches the C process described above, with difference that
# we parse asm-prototypes.h C header to get function definitions.
@@ -369,7 +352,6 @@ cmd_modversions_S = \
rm -f $(@D)/.tmp_$(@F:.o=.ver); \
fi
endif
-endif
$(obj)/%.o: $(src)/%.S $(objtool_dep) FORCE
$(call if_changed_rule,as_o_S)
@@ -388,9 +370,9 @@ $(obj)/%.lds: $(src)/%.lds.S FORCE
# ASN.1 grammar
# ---------------------------------------------------------------------------
-quiet_cmd_asn1_compiler = ASN.1 $@
+quiet_cmd_asn1_compiler = ASN.1 $(basename $@).[ch]
cmd_asn1_compiler = $(objtree)/scripts/asn1_compiler $< \
- $(subst .h,.c,$@) $(subst .c,.h,$@)
+ $(basename $@).c $(basename $@).h
$(obj)/%.asn1.c $(obj)/%.asn1.h: $(src)/%.asn1 $(objtree)/scripts/asn1_compiler
$(call cmd,asn1_compiler)
@@ -482,12 +464,52 @@ targets += $(call intermediate_targets, .asn1.o, .asn1.c .asn1.h) \
$(call intermediate_targets, .lex.o, .lex.c) \
$(call intermediate_targets, .tab.o, .tab.c .tab.h)
+# Build
+# ---------------------------------------------------------------------------
+
+ifdef single-build
+
+curdir-single := $(sort $(foreach x, $(KBUILD_SINGLE_TARGETS), \
+ $(if $(filter $(x) $(basename $(x)).o, $(targets)), $(x))))
+
+# Handle single targets without any rule: show "Nothing to be done for ..." or
+# "No rule to make target ..." depending on whether the target exists.
+unknown-single := $(filter-out $(addsuffix /%, $(subdir-ym)), \
+ $(filter $(obj)/%, \
+ $(filter-out $(curdir-single), \
+ $(KBUILD_SINGLE_TARGETS))))
+
+__build: $(curdir-single) $(subdir-ym)
+ifneq ($(unknown-single),)
+ $(Q)$(MAKE) -f /dev/null $(unknown-single)
+endif
+ @:
+
+ifeq ($(curdir-single),)
+# Nothing to do in this directory. Do not include any .*.cmd file for speed-up
+targets :=
+else
+targets += $(curdir-single)
+endif
+
+else
+
+__build: $(if $(KBUILD_BUILTIN),$(builtin-target) $(lib-target) $(extra-y)) \
+ $(if $(KBUILD_MODULES),$(obj-m) $(mod-targets) $(modorder-target)) \
+ $(subdir-ym) $(always)
+ @:
+
+endif
+
# Descending
# ---------------------------------------------------------------------------
PHONY += $(subdir-ym)
$(subdir-ym):
- $(Q)$(MAKE) $(build)=$@ need-builtin=$(if $(findstring $@,$(subdir-obj-y)),1)
+ $(Q)$(MAKE) $(build)=$@ \
+ $(if $(filter $@/, $(KBUILD_SINGLE_TARGETS)),single-build=) \
+ need-builtin=$(if $(filter $@/built-in.a, $(subdir-obj-y)),1) \
+ need-modorder=$(if $(need-modorder),$(if $(filter $@/modules.order, $(modorder)),1))
# Add FORCE to the prequisites of a target to force it to be always rebuilt.
# ---------------------------------------------------------------------------
diff --git a/scripts/Makefile.clean b/scripts/Makefile.clean
index 0b80e3207b20..e367eb95c5c0 100644
--- a/scripts/Makefile.clean
+++ b/scripts/Makefile.clean
@@ -17,17 +17,8 @@ include $(if $(wildcard $(kbuild-dir)/Kbuild), $(kbuild-dir)/Kbuild, $(kbuild-di
# Figure out what we need to build from the various variables
# ==========================================================================
-__subdir-y := $(patsubst %/,%,$(filter %/, $(obj-y)))
-subdir-y += $(__subdir-y)
-__subdir-m := $(patsubst %/,%,$(filter %/, $(obj-m)))
-subdir-m += $(__subdir-m)
-__subdir- := $(patsubst %/,%,$(filter %/, $(obj-)))
-subdir- += $(__subdir-)
-
-# Subdirectories we need to descend into
-
-subdir-ym := $(sort $(subdir-y) $(subdir-m))
-subdir-ymn := $(sort $(subdir-ym) $(subdir-))
+subdir-ymn := $(sort $(subdir-y) $(subdir-m) $(subdir-) \
+ $(patsubst %/,%, $(filter %/, $(obj-y) $(obj-m) $(obj-))))
# Add subdir path
@@ -52,26 +43,14 @@ __clean-files := $(wildcard \
$(addprefix $(obj)/, $(filter-out $(objtree)/%, $(__clean-files))) \
$(filter $(objtree)/%, $(__clean-files)))
-# same as clean-files
-
-__clean-dirs := $(wildcard \
- $(addprefix $(obj)/, $(filter-out $(objtree)/%, $(clean-dirs))) \
- $(filter $(objtree)/%, $(clean-dirs)))
-
# ==========================================================================
-quiet_cmd_clean = CLEAN $(obj)
- cmd_clean = rm -f $(__clean-files)
-quiet_cmd_cleandir = CLEAN $(__clean-dirs)
- cmd_cleandir = rm -rf $(__clean-dirs)
-
+quiet_cmd_clean = CLEAN $(obj)
+ cmd_clean = rm -rf $(__clean-files)
__clean: $(subdir-ymn)
ifneq ($(strip $(__clean-files)),)
- +$(call cmd,clean)
-endif
-ifneq ($(strip $(__clean-dirs)),)
- +$(call cmd,cleandir)
+ $(call cmd,clean)
endif
@:
diff --git a/scripts/Makefile.extrawarn b/scripts/Makefile.extrawarn
index a74ce2e3c33e..ecddf83ac142 100644
--- a/scripts/Makefile.extrawarn
+++ b/scripts/Makefile.extrawarn
@@ -1,74 +1,91 @@
# SPDX-License-Identifier: GPL-2.0
# ==========================================================================
-#
# make W=... settings
#
-# W=1 - warnings that may be relevant and does not occur too often
-# W=2 - warnings that occur quite often but may still be relevant
-# W=3 - the more obscure warnings, can most likely be ignored
-#
-# $(call cc-option, -W...) handles gcc -W.. options which
-# are not supported by all versions of the compiler
+# There are three warning groups enabled by W=1, W=2, W=3.
+# They are independent, and can be combined like W=12 or W=123.
# ==========================================================================
KBUILD_CFLAGS += $(call cc-disable-warning, packed-not-aligned)
+# backward compatibility
+KBUILD_EXTRA_WARN ?= $(KBUILD_ENABLE_EXTRA_GCC_CHECKS)
+
ifeq ("$(origin W)", "command line")
- export KBUILD_ENABLE_EXTRA_GCC_CHECKS := $(W)
+ KBUILD_EXTRA_WARN := $(W)
endif
-ifdef KBUILD_ENABLE_EXTRA_GCC_CHECKS
-warning- := $(empty)
-
-warning-1 := -Wextra -Wunused -Wno-unused-parameter
-warning-1 += -Wmissing-declarations
-warning-1 += -Wmissing-format-attribute
-warning-1 += -Wmissing-prototypes
-warning-1 += -Wold-style-definition
-warning-1 += -Wmissing-include-dirs
-warning-1 += $(call cc-option, -Wunused-but-set-variable)
-warning-1 += $(call cc-option, -Wunused-const-variable)
-warning-1 += $(call cc-option, -Wpacked-not-aligned)
-warning-1 += $(call cc-option, -Wstringop-truncation)
+export KBUILD_EXTRA_WARN
+
+#
+# W=1 - warnings which may be relevant and do not occur too often
+#
+ifneq ($(findstring 1, $(KBUILD_EXTRA_WARN)),)
+
+KBUILD_CFLAGS += -Wextra -Wunused -Wno-unused-parameter
+KBUILD_CFLAGS += -Wmissing-declarations
+KBUILD_CFLAGS += -Wmissing-format-attribute
+KBUILD_CFLAGS += -Wmissing-prototypes
+KBUILD_CFLAGS += -Wold-style-definition
+KBUILD_CFLAGS += -Wmissing-include-dirs
+KBUILD_CFLAGS += $(call cc-option, -Wunused-but-set-variable)
+KBUILD_CFLAGS += $(call cc-option, -Wunused-const-variable)
+KBUILD_CFLAGS += $(call cc-option, -Wpacked-not-aligned)
+KBUILD_CFLAGS += $(call cc-option, -Wstringop-truncation)
# The following turn off the warnings enabled by -Wextra
-warning-1 += -Wno-missing-field-initializers
-warning-1 += -Wno-sign-compare
-
-warning-2 += -Wcast-align
-warning-2 += -Wdisabled-optimization
-warning-2 += -Wnested-externs
-warning-2 += -Wshadow
-warning-2 += $(call cc-option, -Wlogical-op)
-warning-2 += -Wmissing-field-initializers
-warning-2 += -Wsign-compare
-warning-2 += $(call cc-option, -Wmaybe-uninitialized)
-warning-2 += $(call cc-option, -Wunused-macros)
-
-warning-3 := -Wbad-function-cast
-warning-3 += -Wcast-qual
-warning-3 += -Wconversion
-warning-3 += -Wpacked
-warning-3 += -Wpadded
-warning-3 += -Wpointer-arith
-warning-3 += -Wredundant-decls
-warning-3 += -Wswitch-default
-warning-3 += $(call cc-option, -Wpacked-bitfield-compat)
-
-warning := $(warning-$(findstring 1, $(KBUILD_ENABLE_EXTRA_GCC_CHECKS)))
-warning += $(warning-$(findstring 2, $(KBUILD_ENABLE_EXTRA_GCC_CHECKS)))
-warning += $(warning-$(findstring 3, $(KBUILD_ENABLE_EXTRA_GCC_CHECKS)))
-
-ifeq ("$(strip $(warning))","")
- $(error W=$(KBUILD_ENABLE_EXTRA_GCC_CHECKS) is unknown)
-endif
+KBUILD_CFLAGS += -Wno-missing-field-initializers
+KBUILD_CFLAGS += -Wno-sign-compare
+
+KBUILD_CPPFLAGS += -DKBUILD_EXTRA_WARN1
-KBUILD_CFLAGS += $(warning)
else
+# Some diagnostics enabled by default are noisy.
+# Suppress them by using -Wno... except for W=1.
+
ifdef CONFIG_CC_IS_CLANG
KBUILD_CFLAGS += -Wno-initializer-overrides
KBUILD_CFLAGS += -Wno-format
KBUILD_CFLAGS += -Wno-sign-compare
KBUILD_CFLAGS += -Wno-format-zero-length
endif
+
+endif
+
+#
+# W=2 - warnings which occur quite often but may still be relevant
+#
+ifneq ($(findstring 2, $(KBUILD_EXTRA_WARN)),)
+
+KBUILD_CFLAGS += -Wcast-align
+KBUILD_CFLAGS += -Wdisabled-optimization
+KBUILD_CFLAGS += -Wnested-externs
+KBUILD_CFLAGS += -Wshadow
+KBUILD_CFLAGS += $(call cc-option, -Wlogical-op)
+KBUILD_CFLAGS += -Wmissing-field-initializers
+KBUILD_CFLAGS += -Wsign-compare
+KBUILD_CFLAGS += $(call cc-option, -Wmaybe-uninitialized)
+KBUILD_CFLAGS += $(call cc-option, -Wunused-macros)
+
+KBUILD_CPPFLAGS += -DKBUILD_EXTRA_WARN2
+
+endif
+
+#
+# W=3 - more obscure warnings, can most likely be ignored
+#
+ifneq ($(findstring 3, $(KBUILD_EXTRA_WARN)),)
+
+KBUILD_CFLAGS += -Wbad-function-cast
+KBUILD_CFLAGS += -Wcast-qual
+KBUILD_CFLAGS += -Wconversion
+KBUILD_CFLAGS += -Wpacked
+KBUILD_CFLAGS += -Wpadded
+KBUILD_CFLAGS += -Wpointer-arith
+KBUILD_CFLAGS += -Wredundant-decls
+KBUILD_CFLAGS += -Wswitch-default
+KBUILD_CFLAGS += $(call cc-option, -Wpacked-bitfield-compat)
+
+KBUILD_CPPFLAGS += -DKBUILD_EXTRA_WARN3
+
endif
diff --git a/scripts/Makefile.host b/scripts/Makefile.host
index 2208ebbd8c4c..4c51c95d40f4 100644
--- a/scripts/Makefile.host
+++ b/scripts/Makefile.host
@@ -1,4 +1,21 @@
# SPDX-License-Identifier: GPL-2.0
+
+# LEX
+# ---------------------------------------------------------------------------
+quiet_cmd_flex = LEX $@
+ cmd_flex = $(LEX) -o$@ -L $<
+
+$(obj)/%.lex.c: $(src)/%.l FORCE
+ $(call if_changed,flex)
+
+# YACC
+# ---------------------------------------------------------------------------
+quiet_cmd_bison = YACC $(basename $@).[ch]
+ cmd_bison = $(YACC) -o $(basename $@).c --defines=$(basename $@).h -t -l $<
+
+$(obj)/%.tab.c $(obj)/%.tab.h: $(src)/%.y FORCE
+ $(call if_changed,bison)
+
# ==========================================================================
# Building binaries on the host system
# Binaries are used during the compilation of the kernel, for example
@@ -63,9 +80,9 @@ host-cxxshobjs := $(addprefix $(obj)/,$(host-cxxshobjs))
# Handle options to gcc. Support building with separate output directory
_hostc_flags = $(KBUILD_HOSTCFLAGS) $(HOST_EXTRACFLAGS) \
- $(HOSTCFLAGS_$(basetarget).o)
+ $(HOSTCFLAGS_$(target-stem).o)
_hostcxx_flags = $(KBUILD_HOSTCXXFLAGS) $(HOST_EXTRACXXFLAGS) \
- $(HOSTCXXFLAGS_$(basetarget).o)
+ $(HOSTCXXFLAGS_$(target-stem).o)
# $(objtree)/$(obj) for including generated headers from checkin source files
ifeq ($(KBUILD_EXTMOD),)
@@ -85,7 +102,7 @@ hostcxx_flags = -Wp,-MD,$(depfile) $(_hostcxx_flags)
# host-csingle -> Executable
quiet_cmd_host-csingle = HOSTCC $@
cmd_host-csingle = $(HOSTCC) $(hostc_flags) $(KBUILD_HOSTLDFLAGS) -o $@ $< \
- $(KBUILD_HOSTLDLIBS) $(HOSTLDLIBS_$(@F))
+ $(KBUILD_HOSTLDLIBS) $(HOSTLDLIBS_$(target-stem))
$(host-csingle): $(obj)/%: $(src)/%.c FORCE
$(call if_changed_dep,host-csingle)
@@ -93,8 +110,8 @@ $(host-csingle): $(obj)/%: $(src)/%.c FORCE
# host-cmulti -> executable
quiet_cmd_host-cmulti = HOSTLD $@
cmd_host-cmulti = $(HOSTCC) $(KBUILD_HOSTLDFLAGS) -o $@ \
- $(addprefix $(obj)/,$($(@F)-objs)) \
- $(KBUILD_HOSTLDLIBS) $(HOSTLDLIBS_$(@F))
+ $(addprefix $(obj)/, $($(target-stem)-objs)) \
+ $(KBUILD_HOSTLDLIBS) $(HOSTLDLIBS_$(target-stem))
$(host-cmulti): FORCE
$(call if_changed,host-cmulti)
$(call multi_depend, $(host-cmulti), , -objs)
@@ -111,8 +128,8 @@ $(host-cobjs): $(obj)/%.o: $(src)/%.c FORCE
quiet_cmd_host-cxxmulti = HOSTLD $@
cmd_host-cxxmulti = $(HOSTCXX) $(KBUILD_HOSTLDFLAGS) -o $@ \
$(foreach o,objs cxxobjs,\
- $(addprefix $(obj)/,$($(@F)-$(o)))) \
- $(KBUILD_HOSTLDLIBS) $(HOSTLDLIBS_$(@F))
+ $(addprefix $(obj)/, $($(target-stem)-$(o)))) \
+ $(KBUILD_HOSTLDLIBS) $(HOSTLDLIBS_$(target-stem))
$(host-cxxmulti): FORCE
$(call if_changed,host-cxxmulti)
$(call multi_depend, $(host-cxxmulti), , -objs -cxxobjs)
@@ -144,8 +161,8 @@ $(host-cxxshobjs): $(obj)/%.o: $(src)/%.c FORCE
# *.o -> .so shared library (host-cshlib)
quiet_cmd_host-cshlib = HOSTLLD -shared $@
cmd_host-cshlib = $(HOSTCC) $(KBUILD_HOSTLDFLAGS) -shared -o $@ \
- $(addprefix $(obj)/,$($(@F:.so=-objs))) \
- $(KBUILD_HOSTLDLIBS) $(HOSTLDLIBS_$(@F))
+ $(addprefix $(obj)/, $($(target-stem)-objs)) \
+ $(KBUILD_HOSTLDLIBS) $(HOSTLDLIBS_$(target-stem).so)
$(host-cshlib): FORCE
$(call if_changed,host-cshlib)
$(call multi_depend, $(host-cshlib), .so, -objs)
@@ -154,8 +171,8 @@ $(call multi_depend, $(host-cshlib), .so, -objs)
# *.o -> .so shared library (host-cxxshlib)
quiet_cmd_host-cxxshlib = HOSTLLD -shared $@
cmd_host-cxxshlib = $(HOSTCXX) $(KBUILD_HOSTLDFLAGS) -shared -o $@ \
- $(addprefix $(obj)/,$($(@F:.so=-objs))) \
- $(KBUILD_HOSTLDLIBS) $(HOSTLDLIBS_$(@F))
+ $(addprefix $(obj)/, $($(target-stem)-objs)) \
+ $(KBUILD_HOSTLDLIBS) $(HOSTLDLIBS_$(target-stem).so)
$(host-cxxshlib): FORCE
$(call if_changed,host-cxxshlib)
$(call multi_depend, $(host-cxxshlib), .so, -objs)
diff --git a/scripts/Makefile.kasan b/scripts/Makefile.kasan
index 6410bd22fe38..03757cc60e06 100644
--- a/scripts/Makefile.kasan
+++ b/scripts/Makefile.kasan
@@ -1,4 +1,9 @@
# SPDX-License-Identifier: GPL-2.0
+ifdef CONFIG_KASAN
+CFLAGS_KASAN_NOSANITIZE := -fno-builtin
+KASAN_SHADOW_OFFSET ?= $(CONFIG_KASAN_SHADOW_OFFSET)
+endif
+
ifdef CONFIG_KASAN_GENERIC
ifdef CONFIG_KASAN_INLINE
@@ -7,8 +12,6 @@ else
call_threshold := 0
endif
-KASAN_SHADOW_OFFSET ?= $(CONFIG_KASAN_SHADOW_OFFSET)
-
CFLAGS_KASAN_MINIMAL := -fsanitize=kernel-address
cc-param = $(call cc-option, -mllvm -$(1), $(call cc-option, --param $(1)))
@@ -45,7 +48,3 @@ CFLAGS_KASAN := -fsanitize=kernel-hwaddress \
$(instrumentation_flags)
endif # CONFIG_KASAN_SW_TAGS
-
-ifdef CONFIG_KASAN
-CFLAGS_KASAN_NOSANITIZE := -fno-builtin
-endif
diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib
index 41c50f9461e5..4a0cdd6f5909 100644
--- a/scripts/Makefile.lib
+++ b/scripts/Makefile.lib
@@ -41,9 +41,9 @@ obj-m := $(filter-out %/, $(obj-m))
# Subdirectories we need to descend into
subdir-ym := $(sort $(subdir-y) $(subdir-m))
-# if $(foo-objs), $(foo-y), or $(foo-m) exists, foo.o is a composite object
-multi-used-y := $(sort $(foreach m,$(obj-y), $(if $(strip $($(m:.o=-objs)) $($(m:.o=-y))), $(m))))
-multi-used-m := $(sort $(foreach m,$(obj-m), $(if $(strip $($(m:.o=-objs)) $($(m:.o=-y)) $($(m:.o=-m))), $(m))))
+# If $(foo-objs), $(foo-y), $(foo-m), or $(foo-) exists, foo.o is a composite object
+multi-used-y := $(sort $(foreach m,$(obj-y), $(if $(strip $($(m:.o=-objs)) $($(m:.o=-y)) $($(m:.o=-))), $(m))))
+multi-used-m := $(sort $(foreach m,$(obj-m), $(if $(strip $($(m:.o=-objs)) $($(m:.o=-y)) $($(m:.o=-m)) $($(m:.o=-))), $(m))))
multi-used := $(multi-used-y) $(multi-used-m)
# $(subdir-obj-y) is the list of objects in $(obj-y) which uses dir/ to
@@ -52,8 +52,8 @@ subdir-obj-y := $(filter %/built-in.a, $(obj-y))
# Replace multi-part objects by their individual parts,
# including built-in.a from subdirectories
-real-obj-y := $(foreach m, $(obj-y), $(if $(strip $($(m:.o=-objs)) $($(m:.o=-y))),$($(m:.o=-objs)) $($(m:.o=-y)),$(m)))
-real-obj-m := $(foreach m, $(obj-m), $(if $(strip $($(m:.o=-objs)) $($(m:.o=-y)) $($(m:.o=-m))),$($(m:.o=-objs)) $($(m:.o=-y)) $($(m:.o=-m)),$(m)))
+real-obj-y := $(foreach m, $(obj-y), $(if $(strip $($(m:.o=-objs)) $($(m:.o=-y)) $($(m:.o=-))),$($(m:.o=-objs)) $($(m:.o=-y)),$(m)))
+real-obj-m := $(foreach m, $(obj-m), $(if $(strip $($(m:.o=-objs)) $($(m:.o=-y)) $($(m:.o=-m)) $($(m:.o=-))),$($(m:.o=-objs)) $($(m:.o=-y)) $($(m:.o=-m)),$(m)))
# DTB
# If CONFIG_OF_ALL_DTBS is enabled, all DT blobs are built
@@ -101,6 +101,9 @@ modname-multi = $(subst $(space),:,$(sort $(foreach m,$(multi-used),\
modname = $(if $(modname-multi),$(modname-multi),$(basetarget))
+# target with $(obj)/ and its suffix stripped
+target-stem = $(basename $(patsubst $(obj)/%,%,$@))
+
# These flags are needed for modversions and compiling, so we define them here
# $(modname_flags) defines KBUILD_MODNAME as the name of the module it will
# end up in (or would, if it gets compiled in)
@@ -109,12 +112,12 @@ basename_flags = -DKBUILD_BASENAME=$(call name-fix,$(basetarget))
modname_flags = -DKBUILD_MODNAME=$(call name-fix,$(modname))
orig_c_flags = $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS) \
- $(ccflags-y) $(CFLAGS_$(basetarget).o)
-_c_flags = $(filter-out $(CFLAGS_REMOVE_$(basetarget).o), $(orig_c_flags))
+ $(ccflags-y) $(CFLAGS_$(target-stem).o)
+_c_flags = $(filter-out $(CFLAGS_REMOVE_$(target-stem).o), $(orig_c_flags))
orig_a_flags = $(KBUILD_CPPFLAGS) $(KBUILD_AFLAGS) \
- $(asflags-y) $(AFLAGS_$(basetarget).o)
-_a_flags = $(filter-out $(AFLAGS_REMOVE_$(basetarget).o), $(orig_a_flags))
-_cpp_flags = $(KBUILD_CPPFLAGS) $(cppflags-y) $(CPPFLAGS_$(@F))
+ $(asflags-y) $(AFLAGS_$(target-stem).o)
+_a_flags = $(filter-out $(AFLAGS_REMOVE_$(target-stem).o), $(orig_a_flags))
+_cpp_flags = $(KBUILD_CPPFLAGS) $(cppflags-y) $(CPPFLAGS_$(target-stem).lds)
#
# Enable gcov profiling flags for a file, directory or for all files depending
@@ -159,6 +162,18 @@ _cpp_flags += -I $(srctree)/$(src) -I $(objtree)/$(obj)
endif
endif
+part-of-module = $(if $(filter $(basename $@).o, $(real-obj-m)),y)
+quiet_modtag = $(if $(part-of-module),[M], )
+
+modkern_cflags = \
+ $(if $(part-of-module), \
+ $(KBUILD_CFLAGS_MODULE) $(CFLAGS_MODULE), \
+ $(KBUILD_CFLAGS_KERNEL) $(CFLAGS_KERNEL))
+
+modkern_aflags = $(if $(part-of-module), \
+ $(KBUILD_AFLAGS_MODULE) $(AFLAGS_MODULE), \
+ $(KBUILD_AFLAGS_KERNEL) $(AFLAGS_KERNEL))
+
c_flags = -Wp,-MD,$(depfile) $(NOSTDINC_FLAGS) $(LINUXINCLUDE) \
-include $(srctree)/include/linux/compiler_types.h \
$(_c_flags) $(modkern_cflags) \
@@ -187,28 +202,6 @@ $(foreach m, $(notdir $1), \
$(addprefix $(obj)/, $(foreach s, $3, $($(m:%$(strip $2)=%$(s)))))))
endef
-# LEX
-# ---------------------------------------------------------------------------
-quiet_cmd_flex = LEX $@
- cmd_flex = $(LEX) -o$@ -L $<
-
-$(obj)/%.lex.c: $(src)/%.l FORCE
- $(call if_changed,flex)
-
-# YACC
-# ---------------------------------------------------------------------------
-quiet_cmd_bison = YACC $@
- cmd_bison = $(YACC) -o$@ -t -l $<
-
-$(obj)/%.tab.c: $(src)/%.y FORCE
- $(call if_changed,bison)
-
-quiet_cmd_bison_h = YACC $@
- cmd_bison_h = $(YACC) -o/dev/null --defines=$@ -t -l $<
-
-$(obj)/%.tab.h: $(src)/%.y FORCE
- $(call if_changed,bison_h)
-
# Shipped files
# ===========================================================================
@@ -258,7 +251,7 @@ quiet_cmd_gzip = GZIP $@
DTC ?= $(objtree)/scripts/dtc/dtc
# Disable noisy checks by default
-ifeq ($(findstring 1,$(KBUILD_ENABLE_EXTRA_GCC_CHECKS)),)
+ifeq ($(findstring 1,$(KBUILD_EXTRA_WARN)),)
DTC_FLAGS += -Wno-unit_address_vs_reg \
-Wno-unit_address_format \
-Wno-avoid_unnecessary_addr_size \
@@ -269,7 +262,7 @@ DTC_FLAGS += -Wno-unit_address_vs_reg \
-Wno-pci_device_reg
endif
-ifneq ($(findstring 2,$(KBUILD_ENABLE_EXTRA_GCC_CHECKS)),)
+ifneq ($(findstring 2,$(KBUILD_EXTRA_WARN)),)
DTC_FLAGS += -Wnode_name_chars_strict \
-Wproperty_name_chars_strict
endif
@@ -374,7 +367,7 @@ UIMAGE_ENTRYADDR ?= $(UIMAGE_LOADADDR)
UIMAGE_NAME ?= 'Linux-$(KERNELRELEASE)'
quiet_cmd_uimage = UIMAGE $@
- cmd_uimage = $(CONFIG_SHELL) $(MKIMAGE) -A $(UIMAGE_ARCH) -O linux \
+ cmd_uimage = $(BASH) $(MKIMAGE) -A $(UIMAGE_ARCH) -O linux \
-C $(UIMAGE_COMPRESSION) $(UIMAGE_OPTS-y) \
-T $(UIMAGE_TYPE) \
-a $(UIMAGE_LOADADDR) -e $(UIMAGE_ENTRYADDR) \
diff --git a/scripts/Makefile.modfinal b/scripts/Makefile.modfinal
new file mode 100644
index 000000000000..411c1e600e7d
--- /dev/null
+++ b/scripts/Makefile.modfinal
@@ -0,0 +1,60 @@
+# SPDX-License-Identifier: GPL-2.0-only
+# ===========================================================================
+# Module final link
+# ===========================================================================
+
+PHONY := __modfinal
+__modfinal:
+
+include $(srctree)/scripts/Kbuild.include
+
+# for c_flags
+include $(srctree)/scripts/Makefile.lib
+
+# find all modules listed in modules.order
+modules := $(sort $(shell cat $(MODORDER)))
+
+__modfinal: $(modules)
+ @:
+
+# modname and part-of-module are set to make c_flags define proper module flags
+modname = $(notdir $(@:.mod.o=))
+part-of-module = y
+
+quiet_cmd_cc_o_c = CC [M] $@
+ cmd_cc_o_c = $(CC) $(c_flags) -c -o $@ $<
+
+%.mod.o: %.mod.c FORCE
+ $(call if_changed_dep,cc_o_c)
+
+ARCH_POSTLINK := $(wildcard $(srctree)/arch/$(SRCARCH)/Makefile.postlink)
+
+quiet_cmd_ld_ko_o = LD [M] $@
+ cmd_ld_ko_o = \
+ $(LD) -r $(KBUILD_LDFLAGS) \
+ $(KBUILD_LDFLAGS_MODULE) $(LDFLAGS_MODULE) \
+ $(addprefix -T , $(KBUILD_LDS_MODULE)) \
+ -o $@ $(filter %.o, $^); \
+ $(if $(ARCH_POSTLINK), $(MAKE) -f $(ARCH_POSTLINK) $@, true)
+
+$(modules): %.ko: %.o %.mod.o $(KBUILD_LDS_MODULE) FORCE
+ +$(call if_changed,ld_ko_o)
+
+targets += $(modules) $(modules:.ko=.mod.o)
+
+# Add FORCE to the prequisites of a target to force it to be always rebuilt.
+# ---------------------------------------------------------------------------
+
+PHONY += FORCE
+FORCE:
+
+# Read all saved command lines and dependencies for the $(targets) we
+# may be building above, using $(if_changed{,_dep}). As an
+# optimization, we don't need to read them if the target does not
+# exist, we will rebuild anyway in that case.
+
+existing-targets := $(wildcard $(sort $(targets)))
+
+-include $(foreach f,$(existing-targets),$(dir $(f)).$(notdir $(f)).cmd)
+
+.PHONY: $(PHONY)
diff --git a/scripts/Makefile.modpost b/scripts/Makefile.modpost
index 6b19c1a4eae5..952fff485546 100644
--- a/scripts/Makefile.modpost
+++ b/scripts/Makefile.modpost
@@ -15,15 +15,13 @@
# 2) modpost is then used to
# 3) create one <module>.mod.c file pr. module
# 4) create one Module.symvers file with CRC for all exported symbols
-# 5) compile all <module>.mod.c files
-# 6) final link of the module to a <module.ko> file
# Step 3 is used to place certain information in the module's ELF
# section, including information such as:
# Version magic (see include/linux/vermagic.h for full details)
# - Kernel release
# - SMP is CONFIG_SMP
-# - PREEMPT is CONFIG_PREEMPT
+# - PREEMPT is CONFIG_PREEMPT[_RT]
# - GCC Version
# Module info
# - Module version (MODULE_VERSION)
@@ -38,12 +36,37 @@
# symbols in the final module linking stage
# KBUILD_MODPOST_NOFINAL can be set to skip the final link of modules.
# This is solely useful to speed up test compiles
-PHONY := _modpost
-_modpost: __modpost
+
+PHONY := __modpost
+__modpost:
include include/config/auto.conf
include scripts/Kbuild.include
+kernelsymfile := $(objtree)/Module.symvers
+modulesymfile := $(firstword $(KBUILD_EXTMOD))/Module.symvers
+
+MODPOST = scripts/mod/modpost \
+ $(if $(CONFIG_MODVERSIONS),-m) \
+ $(if $(CONFIG_MODULE_SRCVERSION_ALL),-a) \
+ $(if $(KBUILD_EXTMOD),-i,-o) $(kernelsymfile) \
+ $(if $(KBUILD_EXTMOD),-I $(modulesymfile)) \
+ $(if $(KBUILD_EXTMOD),$(addprefix -e ,$(KBUILD_EXTRA_SYMBOLS))) \
+ $(if $(KBUILD_EXTMOD),-o $(modulesymfile)) \
+ $(if $(CONFIG_SECTION_MISMATCH_WARN_ONLY),,-E) \
+ $(if $(KBUILD_MODPOST_WARN),-w) \
+ $(if $(filter nsdeps,$(MAKECMDGOALS)),-d)
+
+ifdef MODPOST_VMLINUX
+
+quiet_cmd_modpost = MODPOST vmlinux.o
+ cmd_modpost = $(MODPOST) vmlinux.o
+
+__modpost:
+ $(call cmd,modpost)
+
+else
+
# When building external modules load the Kbuild file to retrieve EXTRA_SYMBOLS info
ifneq ($(KBUILD_EXTMOD),)
@@ -56,99 +79,25 @@ include $(if $(wildcard $(KBUILD_EXTMOD)/Kbuild), \
$(KBUILD_EXTMOD)/Kbuild, $(KBUILD_EXTMOD)/Makefile)
endif
-include scripts/Makefile.lib
+MODPOST += $(subst -i,-n,$(filter -i,$(MAKEFLAGS))) -s -T - $(wildcard vmlinux)
-kernelsymfile := $(objtree)/Module.symvers
-modulesymfile := $(firstword $(KBUILD_EXTMOD))/Module.symvers
+# find all modules listed in modules.order
+modules := $(sort $(shell cat $(MODORDER)))
-modorder := $(if $(KBUILD_EXTMOD),$(KBUILD_EXTMOD)/)modules.order
+# Read out modules.order instead of expanding $(modules) to pass in modpost.
+# Otherwise, allmodconfig would fail with "Argument list too long".
+quiet_cmd_modpost = MODPOST $(words $(modules)) modules
+ cmd_modpost = sed 's/ko$$/o/' $(MODORDER) | $(MODPOST)
-# Step 1), find all modules listed in modules.order
-ifdef CONFIG_MODULES
-modules := $(sort $(shell cat $(modorder)))
+__modpost:
+ @$(kecho) ' Building modules, stage 2.'
+ $(call cmd,modpost)
+ifneq ($(KBUILD_MODPOST_NOFINAL),1)
+ $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modfinal
endif
-# Stop after building .o files if NOFINAL is set. Makes compile tests quicker
-_modpost: $(if $(KBUILD_MODPOST_NOFINAL), $(modules:.ko:.o),$(modules))
-
-# Step 2), invoke modpost
-# Includes step 3,4
-modpost = scripts/mod/modpost \
- $(if $(CONFIG_MODVERSIONS),-m) \
- $(if $(CONFIG_MODULE_SRCVERSION_ALL),-a,) \
- $(if $(KBUILD_EXTMOD),-i,-o) $(kernelsymfile) \
- $(if $(KBUILD_EXTMOD),-I $(modulesymfile)) \
- $(if $(KBUILD_EXTRA_SYMBOLS), $(patsubst %, -e %,$(KBUILD_EXTRA_SYMBOLS))) \
- $(if $(KBUILD_EXTMOD),-o $(modulesymfile)) \
- $(if $(CONFIG_SECTION_MISMATCH_WARN_ONLY),,-E) \
- $(if $(KBUILD_MODPOST_WARN),-w)
-
-MODPOST_OPT=$(subst -i,-n,$(filter -i,$(MAKEFLAGS)))
-
-# We can go over command line length here, so be careful.
-quiet_cmd_modpost = MODPOST $(words $(filter-out vmlinux FORCE, $^)) modules
- cmd_modpost = sed 's/ko$$/o/' $(modorder) | $(modpost) $(MODPOST_OPT) -s -T -
-
-PHONY += __modpost
-__modpost: $(modules:.ko=.o) FORCE
- $(call cmd,modpost) $(wildcard vmlinux)
-
-quiet_cmd_kernel-mod = MODPOST $@
- cmd_kernel-mod = $(modpost) $@
-
-vmlinux.o: FORCE
- $(call cmd,kernel-mod)
-
-# Declare generated files as targets for modpost
-$(modules:.ko=.mod.c): __modpost ;
-
-
-# Step 5), compile all *.mod.c files
-
-# modname is set to make c_flags define KBUILD_MODNAME
-modname = $(notdir $(@:.mod.o=))
-
-quiet_cmd_cc_o_c = CC $@
- cmd_cc_o_c = $(CC) $(c_flags) $(KBUILD_CFLAGS_MODULE) $(CFLAGS_MODULE) \
- -c -o $@ $<
-
-$(modules:.ko=.mod.o): %.mod.o: %.mod.c FORCE
- $(call if_changed_dep,cc_o_c)
-
-targets += $(modules:.ko=.mod.o)
-
-ARCH_POSTLINK := $(wildcard $(srctree)/arch/$(SRCARCH)/Makefile.postlink)
-
-# Step 6), final link of the modules with optional arch pass after final link
-quiet_cmd_ld_ko_o = LD [M] $@
- cmd_ld_ko_o = \
- $(LD) -r $(KBUILD_LDFLAGS) \
- $(KBUILD_LDFLAGS_MODULE) $(LDFLAGS_MODULE) \
- -o $@ $(real-prereqs) ; \
- $(if $(ARCH_POSTLINK), $(MAKE) -f $(ARCH_POSTLINK) $@, true)
-
-$(modules): %.ko :%.o %.mod.o FORCE
- +$(call if_changed,ld_ko_o)
-
-targets += $(modules)
-
-
-# Add FORCE to the prequisites of a target to force it to be always rebuilt.
-# ---------------------------------------------------------------------------
-
-PHONY += FORCE
-
-FORCE:
-
-# Read all saved command lines and dependencies for the $(targets) we
-# may be building above, using $(if_changed{,_dep}). As an
-# optimization, we don't need to read them if the target does not
-# exist, we will rebuild anyway in that case.
-
-cmd_files := $(wildcard $(foreach f,$(sort $(targets)),$(dir $(f)).$(notdir $(f)).cmd))
+nsdeps: __modpost
-ifneq ($(cmd_files),)
- include $(cmd_files)
endif
.PHONY: $(PHONY)
diff --git a/scripts/package/Makefile b/scripts/Makefile.package
index ca7f46b562a4..56eadcc48d46 100644
--- a/scripts/package/Makefile
+++ b/scripts/Makefile.package
@@ -1,6 +1,7 @@
# SPDX-License-Identifier: GPL-2.0-only
# Makefile for the different targets used to generate full packages of a kernel
-# It uses the generic clean infrastructure of kbuild
+
+include $(srctree)/scripts/Kbuild.include
# RPM target
# ---------------------------------------------------------------------------
@@ -50,7 +51,8 @@ rm -f $(objtree)/.scmversion
# rpm-pkg
# ---------------------------------------------------------------------------
-rpm-pkg: FORCE
+PHONY += rpm-pkg
+rpm-pkg:
$(MAKE) clean
$(CONFIG_SHELL) $(MKSPEC) >$(objtree)/kernel.spec
$(call cmd,src_tar,$(KERNELPATH),kernel.spec)
@@ -59,15 +61,15 @@ rpm-pkg: FORCE
# binrpm-pkg
# ---------------------------------------------------------------------------
-binrpm-pkg: FORCE
+PHONY += binrpm-pkg
+binrpm-pkg:
$(MAKE) -f $(srctree)/Makefile
$(CONFIG_SHELL) $(MKSPEC) prebuilt > $(objtree)/binkernel.spec
+rpmbuild $(RPMOPTS) --define "_builddir $(objtree)" --target \
$(UTS_MACHINE) -bb $(objtree)/binkernel.spec
-clean-files += $(objtree)/*.spec
-
-deb-pkg: FORCE
+PHONY += deb-pkg
+deb-pkg:
$(MAKE) clean
$(CONFIG_SHELL) $(srctree)/scripts/package/mkdebian
$(call cmd,src_tar,$(KDEB_SOURCENAME))
@@ -75,18 +77,19 @@ deb-pkg: FORCE
mv $(KDEB_SOURCENAME).tar.gz ../$(KDEB_SOURCENAME)_$${origversion}.orig.tar.gz
+dpkg-buildpackage -r$(KBUILD_PKG_ROOTCMD) -a$$(cat debian/arch) $(DPKG_FLAGS) -i.git -us -uc
-bindeb-pkg: FORCE
+PHONY += bindeb-pkg
+bindeb-pkg:
$(CONFIG_SHELL) $(srctree)/scripts/package/mkdebian
+dpkg-buildpackage -r$(KBUILD_PKG_ROOTCMD) -a$$(cat debian/arch) $(DPKG_FLAGS) -b -nc -uc
-intdeb-pkg: FORCE
+PHONY += intdeb-pkg
+intdeb-pkg:
+$(CONFIG_SHELL) $(srctree)/scripts/package/builddeb
-clean-dirs += $(objtree)/debian/
-
# snap-pkg
# ---------------------------------------------------------------------------
-snap-pkg: FORCE
+PHONY += snap-pkg
+snap-pkg:
rm -rf $(objtree)/snap
mkdir $(objtree)/snap
$(MAKE) clean
@@ -98,17 +101,14 @@ snap-pkg: FORCE
cd $(objtree)/snap && \
snapcraft --target-arch=$(UTS_MACHINE)
-clean-dirs += $(objtree)/snap/
-
# tarball targets
# ---------------------------------------------------------------------------
-tar%pkg: FORCE
+tar-pkgs := tar-pkg targz-pkg tarbz2-pkg tarxz-pkg
+PHONY += $(tar-pkgs)
+$(tar-pkgs):
$(MAKE) -f $(srctree)/Makefile
+$(CONFIG_SHELL) $(srctree)/scripts/package/buildtar $@
-clean-dirs += $(objtree)/tar-install/
-
-
# perf-pkg - generate a source tarball with perf source
# ---------------------------------------------------------------------------
@@ -133,12 +133,15 @@ $(if $(findstring xz,$@),xz, \
$(error unknown target $@)))) \
-f -9 $(perf-tar).tar)
-perf-%pkg: FORCE
+perf-tar-pkgs := perf-tar-src-pkg perf-targz-src-pkg perf-tarbz2-src-pkg perf-tarxz-src-pkg
+PHONY += $(perf-tar-pkgs)
+$(perf-tar-pkgs):
$(call cmd,perf_tar)
# Help text displayed when executing 'make help'
# ---------------------------------------------------------------------------
-help: FORCE
+PHONY += help
+help:
@echo ' rpm-pkg - Build both source and binary RPM kernel packages'
@echo ' binrpm-pkg - Build only the binary kernel RPM package'
@echo ' deb-pkg - Build both source and binary deb kernel packages'
@@ -152,3 +155,5 @@ help: FORCE
@echo ' perf-targz-src-pkg - Build $(perf-tar).tar.gz source tarball'
@echo ' perf-tarbz2-src-pkg - Build $(perf-tar).tar.bz2 source tarball'
@echo ' perf-tarxz-src-pkg - Build $(perf-tar).tar.xz source tarball'
+
+.PHONY: $(PHONY)
diff --git a/scripts/basic/Makefile b/scripts/basic/Makefile
index 548aeb592806..7c9cb80d097b 100644
--- a/scripts/basic/Makefile
+++ b/scripts/basic/Makefile
@@ -1,16 +1,6 @@
# SPDX-License-Identifier: GPL-2.0-only
-###
-# This Makefile lists the most basic programs used during the build process.
-# The programs listed herein are what are needed to do the basic stuff,
-# such as fix file dependencies.
-# This initial step is needed to avoid files to be recompiled
-# when kernel configuration changes (which is what happens when
-# .config is included by main Makefile.
-# ---------------------------------------------------------------------------
-# fixdep: Used to generate dependency information during build process
+#
+# fixdep: used to generate dependency information during build process
hostprogs-y := fixdep
always := $(hostprogs-y)
-
-# fixdep is needed to compile other host programs
-$(addprefix $(obj)/,$(filter-out fixdep,$(always))): $(obj)/fixdep
diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl
index 93a7edfe0f05..6fcc66afb088 100755
--- a/scripts/checkpatch.pl
+++ b/scripts/checkpatch.pl
@@ -62,6 +62,8 @@ my $conststructsfile = "$D/const_structs.checkpatch";
my $typedefsfile = "";
my $color = "auto";
my $allow_c99_comments = 1; # Can be overridden by --ignore C99_COMMENT_TOLERANCE
+# git output parsing needs US English output, so first set backtick child process LANGUAGE
+my $git_command ='export LANGUAGE=en_US.UTF-8; git';
sub help {
my ($exitcode) = @_;
@@ -904,7 +906,7 @@ sub seed_camelcase_includes {
$camelcase_seeded = 1;
if (-e ".git") {
- my $git_last_include_commit = `git log --no-merges --pretty=format:"%h%n" -1 -- include`;
+ my $git_last_include_commit = `${git_command} log --no-merges --pretty=format:"%h%n" -1 -- include`;
chomp $git_last_include_commit;
$camelcase_cache = ".checkpatch-camelcase.git.$git_last_include_commit";
} else {
@@ -932,7 +934,7 @@ sub seed_camelcase_includes {
}
if (-e ".git") {
- $files = `git ls-files "include/*.h"`;
+ $files = `${git_command} ls-files "include/*.h"`;
@include_files = split('\n', $files);
}
@@ -956,13 +958,13 @@ sub git_commit_info {
return ($id, $desc) if ((which("git") eq "") || !(-e ".git"));
- my $output = `git log --no-color --format='%H %s' -1 $commit 2>&1`;
+ my $output = `${git_command} log --no-color --format='%H %s' -1 $commit 2>&1`;
$output =~ s/^\s*//gm;
my @lines = split("\n", $output);
return ($id, $desc) if ($#lines < 0);
- if ($lines[0] =~ /^error: short SHA1 $commit is ambiguous\./) {
+ if ($lines[0] =~ /^error: short SHA1 $commit is ambiguous/) {
# Maybe one day convert this block of bash into something that returns
# all matching commit ids, but it's very slow...
#
@@ -1006,7 +1008,7 @@ if ($git) {
} else {
$git_range = "-1 $commit_expr";
}
- my $lines = `git log --no-color --no-merges --pretty=format:'%H %s' $git_range`;
+ my $lines = `${git_command} log --no-color --no-merges --pretty=format:'%H %s' $git_range`;
foreach my $line (split(/\n/, $lines)) {
$line =~ /^([0-9a-fA-F]{40,40}) (.*)$/;
next if (!defined($1) || !defined($2));
@@ -2725,8 +2727,10 @@ sub process {
($line =~ /^\s*(?:WARNING:|BUG:)/ ||
$line =~ /^\s*\[\s*\d+\.\d{6,6}\s*\]/ ||
# timestamp
- $line =~ /^\s*\[\<[0-9a-fA-F]{8,}\>\]/)) {
- # stack dump address
+ $line =~ /^\s*\[\<[0-9a-fA-F]{8,}\>\]/) ||
+ $line =~ /^(?:\s+\w+:\s+[0-9a-fA-F]+){3,3}/ ||
+ $line =~ /^\s*\#\d+\s*\[[0-9a-fA-F]+\]\s*\w+ at [0-9a-fA-F]+/) {
+ # stack dump address styles
$commit_log_possible_stack_dump = 1;
}
@@ -2898,6 +2902,17 @@ sub process {
}
}
+# check for invalid commit id
+ if ($in_commit_log && $line =~ /(^fixes:|\bcommit)\s+([0-9a-f]{6,40})\b/i) {
+ my $id;
+ my $description;
+ ($id, $description) = git_commit_info($2, undef, undef);
+ if (!defined($id)) {
+ WARN("UNKNOWN_COMMIT_ID",
+ "Unknown commit id '$2', maybe rebased or not pulled?\n" . $herecurr);
+ }
+ }
+
# ignore non-hunk lines and lines being removed
next if (!$hunk_line || $line =~ /^-/);
@@ -3069,21 +3084,21 @@ sub process {
# check SPDX comment style for .[chsS] files
if ($realfile =~ /\.[chsS]$/ &&
$rawline =~ /SPDX-License-Identifier:/ &&
- $rawline !~ /^\+\s*\Q$comment\E\s*/) {
+ $rawline !~ m@^\+\s*\Q$comment\E\s*@) {
WARN("SPDX_LICENSE_TAG",
"Improper SPDX comment style for '$realfile', please use '$comment' instead\n" . $herecurr);
}
if ($comment !~ /^$/ &&
- $rawline !~ /^\+\Q$comment\E SPDX-License-Identifier: /) {
- WARN("SPDX_LICENSE_TAG",
- "Missing or malformed SPDX-License-Identifier tag in line $checklicenseline\n" . $herecurr);
+ $rawline !~ m@^\+\Q$comment\E SPDX-License-Identifier: @) {
+ WARN("SPDX_LICENSE_TAG",
+ "Missing or malformed SPDX-License-Identifier tag in line $checklicenseline\n" . $herecurr);
} elsif ($rawline =~ /(SPDX-License-Identifier: .*)/) {
- my $spdx_license = $1;
- if (!is_SPDX_License_valid($spdx_license)) {
- WARN("SPDX_LICENSE_TAG",
- "'$spdx_license' is not supported in LICENSES/...\n" . $herecurr);
- }
+ my $spdx_license = $1;
+ if (!is_SPDX_License_valid($spdx_license)) {
+ WARN("SPDX_LICENSE_TAG",
+ "'$spdx_license' is not supported in LICENSES/...\n" . $herecurr);
+ }
}
}
}
@@ -4660,7 +4675,7 @@ sub process {
# closing brace should have a space following it when it has anything
# on the line
- if ($line =~ /}(?!(?:,|;|\)))\S/) {
+ if ($line =~ /}(?!(?:,|;|\)|\}))\S/) {
if (ERROR("SPACING",
"space required after that close brace '}'\n" . $herecurr) &&
$fix) {
@@ -5191,7 +5206,7 @@ sub process {
next if ($arg =~ /\.\.\./);
next if ($arg =~ /^type$/i);
my $tmp_stmt = $define_stmt;
- $tmp_stmt =~ s/\b(typeof|__typeof__|__builtin\w+|typecheck\s*\(\s*$Type\s*,|\#+)\s*\(*\s*$arg\s*\)*\b//g;
+ $tmp_stmt =~ s/\b(sizeof|typeof|__typeof__|__builtin\w+|typecheck\s*\(\s*$Type\s*,|\#+)\s*\(*\s*$arg\s*\)*\b//g;
$tmp_stmt =~ s/\#+\s*$arg\b//g;
$tmp_stmt =~ s/\b$arg\s*\#\#//g;
my $use_cnt = () = $tmp_stmt =~ /\b$arg\b/g;
@@ -5873,6 +5888,18 @@ sub process {
"__aligned(size) is preferred over __attribute__((aligned(size)))\n" . $herecurr);
}
+# Check for __attribute__ section, prefer __section
+ if ($realfile !~ m@\binclude/uapi/@ &&
+ $line =~ /\b__attribute__\s*\(\s*\(.*_*section_*\s*\(\s*("[^"]*")/) {
+ my $old = substr($rawline, $-[1], $+[1] - $-[1]);
+ my $new = substr($old, 1, -1);
+ if (WARN("PREFER_SECTION",
+ "__section($new) is preferred over __attribute__((section($old)))\n" . $herecurr) &&
+ $fix) {
+ $fixed[$fixlinenr] =~ s/\b__attribute__\s*\(\s*\(\s*_*section_*\s*\(\s*\Q$old\E\s*\)\s*\)\s*\)/__section($new)/;
+ }
+ }
+
# Check for __attribute__ format(printf, prefer __printf
if ($realfile !~ m@\binclude/uapi/@ &&
$line =~ /\b__attribute__\s*\(\s*\(\s*format\s*\(\s*printf/) {
@@ -6480,6 +6507,12 @@ sub process {
"Using $1 should generally have parentheses around the comparison\n" . $herecurr);
}
+# nested likely/unlikely calls
+ if ($line =~ /\b(?:(?:un)?likely)\s*\(\s*!?\s*(IS_ERR(?:_OR_NULL|_VALUE)?|WARN)/) {
+ WARN("LIKELY_MISUSE",
+ "nested (un)?likely() calls, $1 already uses unlikely() internally\n" . $herecurr);
+ }
+
# whine mightly about in_atomic
if ($line =~ /\bin_atomic\s*\(/) {
if ($realfile =~ m@^drivers/@) {
diff --git a/scripts/coccinelle/api/atomic_as_refcounter.cocci b/scripts/coccinelle/api/atomic_as_refcounter.cocci
index 988120e0fd67..0f78d94abc35 100644
--- a/scripts/coccinelle/api/atomic_as_refcounter.cocci
+++ b/scripts/coccinelle/api/atomic_as_refcounter.cocci
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0-only
// Check if refcount_t type and API should be used
// instead of atomic_t type when dealing with refcounters
//
diff --git a/scripts/coccinelle/api/platform_get_irq.cocci b/scripts/coccinelle/api/platform_get_irq.cocci
new file mode 100644
index 000000000000..06b6a95e2bfc
--- /dev/null
+++ b/scripts/coccinelle/api/platform_get_irq.cocci
@@ -0,0 +1,102 @@
+// SPDX-License-Identifier: GPL-2.0
+/// Remove dev_err() messages after platform_get_irq*() failures
+//
+// Confidence: Medium
+// Options: --include-headers
+
+virtual patch
+virtual context
+virtual org
+virtual report
+
+@depends on context@
+expression ret;
+struct platform_device *E;
+@@
+
+ret =
+(
+platform_get_irq
+|
+platform_get_irq_byname
+)(E, ...);
+
+if ( \( ret < 0 \| ret <= 0 \) )
+{
+(
+if (ret != -EPROBE_DEFER)
+{ ...
+*dev_err(...);
+... }
+|
+...
+*dev_err(...);
+)
+...
+}
+
+@depends on patch@
+expression ret;
+struct platform_device *E;
+@@
+
+ret =
+(
+platform_get_irq
+|
+platform_get_irq_byname
+)(E, ...);
+
+if ( \( ret < 0 \| ret <= 0 \) )
+{
+(
+-if (ret != -EPROBE_DEFER)
+-{ ...
+-dev_err(...);
+-... }
+|
+...
+-dev_err(...);
+)
+...
+}
+
+@r depends on org || report@
+position p1;
+expression ret;
+struct platform_device *E;
+@@
+
+ret =
+(
+platform_get_irq
+|
+platform_get_irq_byname
+)(E, ...);
+
+if ( \( ret < 0 \| ret <= 0 \) )
+{
+(
+if (ret != -EPROBE_DEFER)
+{ ...
+dev_err@p1(...);
+... }
+|
+...
+dev_err@p1(...);
+)
+...
+}
+
+@script:python depends on org@
+p1 << r.p1;
+@@
+
+cocci.print_main(p1)
+
+@script:python depends on report@
+p1 << r.p1;
+@@
+
+msg = "line %s is redundant because platform_get_irq() already prints an error" % (p1[0].line)
+coccilib.report.print_report(p1[0],msg)
diff --git a/scripts/coccinelle/misc/add_namespace.cocci b/scripts/coccinelle/misc/add_namespace.cocci
new file mode 100644
index 000000000000..c832bb6445a8
--- /dev/null
+++ b/scripts/coccinelle/misc/add_namespace.cocci
@@ -0,0 +1,23 @@
+// SPDX-License-Identifier: GPL-2.0-only
+//
+/// Adds missing MODULE_IMPORT_NS statements to source files
+///
+/// This script is usually called from scripts/nsdeps with -D ns=<namespace> to
+/// add a missing namespace tag to a module source file.
+///
+
+@has_ns_import@
+declarer name MODULE_IMPORT_NS;
+identifier virtual.ns;
+@@
+MODULE_IMPORT_NS(ns);
+
+// Add missing imports, but only adjacent to a MODULE_LICENSE statement.
+// That ensures we are adding it only to the main module source file.
+@do_import depends on !has_ns_import@
+declarer name MODULE_LICENSE;
+expression license;
+identifier virtual.ns;
+@@
+MODULE_LICENSE(license);
++ MODULE_IMPORT_NS(ns);
diff --git a/scripts/export_report.pl b/scripts/export_report.pl
index 7d3030d03a25..548330e8c4e7 100755
--- a/scripts/export_report.pl
+++ b/scripts/export_report.pl
@@ -94,7 +94,7 @@ if (defined $opt{'o'}) {
#
while ( <$module_symvers> ) {
chomp;
- my (undef, $symbol, $module, $gpl) = split;
+ my (undef, $symbol, $namespace, $module, $gpl) = split('\t');
$SYMBOL { $symbol } = [ $module , "0" , $symbol, $gpl];
}
close($module_symvers);
diff --git a/scripts/gcc-plugins/randomize_layout_plugin.c b/scripts/gcc-plugins/randomize_layout_plugin.c
index 6d5bbd31db7f..bd29e4e7a524 100644
--- a/scripts/gcc-plugins/randomize_layout_plugin.c
+++ b/scripts/gcc-plugins/randomize_layout_plugin.c
@@ -443,13 +443,13 @@ static int is_pure_ops_struct(const_tree node)
if (node == fieldtype)
continue;
- if (!is_fptr(fieldtype))
- return 0;
-
- if (code != RECORD_TYPE && code != UNION_TYPE)
+ if (code == RECORD_TYPE || code == UNION_TYPE) {
+ if (!is_pure_ops_struct(fieldtype))
+ return 0;
continue;
+ }
- if (!is_pure_ops_struct(fieldtype))
+ if (!is_fptr(fieldtype))
return 0;
}
diff --git a/scripts/gdb/linux/symbols.py b/scripts/gdb/linux/symbols.py
index 2f5b95f09fa0..34e40e96dee2 100644
--- a/scripts/gdb/linux/symbols.py
+++ b/scripts/gdb/linux/symbols.py
@@ -77,12 +77,12 @@ lx-symbols command."""
gdb.write("scanning for modules in {0}\n".format(path))
for root, dirs, files in os.walk(path):
for name in files:
- if name.endswith(".ko"):
+ if name.endswith(".ko") or name.endswith(".ko.debug"):
self.module_files.append(root + "/" + name)
self.module_files_updated = True
def _get_module_file(self, module_name):
- module_pattern = ".*/{0}\.ko$".format(
+ module_pattern = ".*/{0}\.ko(?:.debug)?$".format(
module_name.replace("_", r"[_\-]"))
for name in self.module_files:
if re.match(module_pattern, name) and os.path.exists(name):
diff --git a/scripts/genksyms/Makefile b/scripts/genksyms/Makefile
index 66c314bc5933..78629f515e78 100644
--- a/scripts/genksyms/Makefile
+++ b/scripts/genksyms/Makefile
@@ -12,22 +12,15 @@ genksyms-objs := genksyms.o parse.tab.o lex.lex.o
#
# Just in case, run "$(YACC) --version" without suppressing stderr
# so that 'bison: not found' will be displayed if it is missing.
-ifeq ($(findstring 1,$(KBUILD_ENABLE_EXTRA_GCC_CHECKS)),)
+ifeq ($(findstring 1,$(KBUILD_EXTRA_WARN)),)
quiet_cmd_bison_no_warn = $(quiet_cmd_bison)
cmd_bison_no_warn = $(YACC) --version >/dev/null; \
$(cmd_bison) 2>/dev/null
-$(obj)/parse.tab.c: $(src)/parse.y FORCE
+$(obj)/pars%.tab.c $(obj)/pars%.tab.h: $(src)/pars%.y FORCE
$(call if_changed,bison_no_warn)
-quiet_cmd_bison_h_no_warn = $(quiet_cmd_bison_h)
- cmd_bison_h_no_warn = $(YACC) --version >/dev/null; \
- $(cmd_bison_h) 2>/dev/null
-
-$(obj)/parse.tab.h: $(src)/parse.y FORCE
- $(call if_changed,bison_h_no_warn)
-
endif
# -I needed for generated C source (shipped source)
diff --git a/scripts/genksyms/keywords.c b/scripts/genksyms/keywords.c
index c586d32dd2c3..7a85c4e21175 100644
--- a/scripts/genksyms/keywords.c
+++ b/scripts/genksyms/keywords.c
@@ -3,11 +3,7 @@ static struct resword {
const char *name;
int token;
} keywords[] = {
- { "EXPORT_SYMBOL", EXPORT_SYMBOL_KEYW },
- { "EXPORT_SYMBOL_GPL", EXPORT_SYMBOL_KEYW },
- { "EXPORT_SYMBOL_GPL_FUTURE", EXPORT_SYMBOL_KEYW },
- { "EXPORT_UNUSED_SYMBOL", EXPORT_SYMBOL_KEYW },
- { "EXPORT_UNUSED_SYMBOL_GPL", EXPORT_SYMBOL_KEYW },
+ { "__GENKSYMS_EXPORT_SYMBOL", EXPORT_SYMBOL_KEYW },
{ "__asm", ASM_KEYW },
{ "__asm__", ASM_KEYW },
{ "__attribute", ATTRIBUTE_KEYW },
diff --git a/scripts/genksyms/lex.l b/scripts/genksyms/lex.l
index d29c774f51b6..e265c5d96861 100644
--- a/scripts/genksyms/lex.l
+++ b/scripts/genksyms/lex.l
@@ -1,25 +1,13 @@
-/* Lexical analysis for genksyms.
- Copyright 1996, 1997 Linux International.
-
- New implementation contributed by Richard Henderson <rth@tamu.edu>
- Based on original work by Bjorn Ekwall <bj0rn@blox.se>
-
- Taken from Linux modutils 2.4.22.
-
- This program is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published by the
- Free Software Foundation; either version 2 of the License, or (at your
- option) any later version.
-
- This program is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software Foundation,
- Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
-
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Lexical analysis for genksyms.
+ * Copyright 1996, 1997 Linux International.
+ *
+ * New implementation contributed by Richard Henderson <rth@tamu.edu>
+ * Based on original work by Bjorn Ekwall <bj0rn@blox.se>
+ *
+ * Taken from Linux modutils 2.4.22.
+ */
%{
diff --git a/scripts/genksyms/parse.y b/scripts/genksyms/parse.y
index 1ebcf52cd0f9..e22b42245bcc 100644
--- a/scripts/genksyms/parse.y
+++ b/scripts/genksyms/parse.y
@@ -1,25 +1,13 @@
-/* C global declaration parser for genksyms.
- Copyright 1996, 1997 Linux International.
-
- New implementation contributed by Richard Henderson <rth@tamu.edu>
- Based on original work by Bjorn Ekwall <bj0rn@blox.se>
-
- This file is part of the Linux modutils.
-
- This program is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published by the
- Free Software Foundation; either version 2 of the License, or (at your
- option) any later version.
-
- This program is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software Foundation,
- Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
-
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * C global declaration parser for genksyms.
+ * Copyright 1996, 1997 Linux International.
+ *
+ * New implementation contributed by Richard Henderson <rth@tamu.edu>
+ * Based on original work by Bjorn Ekwall <bj0rn@blox.se>
+ *
+ * This file is part of the Linux modutils.
+ */
%{
diff --git a/scripts/headers_install.sh b/scripts/headers_install.sh
index 47f6f3ea0771..a07668a5c36b 100755
--- a/scripts/headers_install.sh
+++ b/scripts/headers_install.sh
@@ -23,6 +23,12 @@ TMPFILE=$OUTFILE.tmp
trap 'rm -f $OUTFILE $TMPFILE' EXIT
+# SPDX-License-Identifier with GPL variants must have "WITH Linux-syscall-note"
+if [ -n "$(sed -n -e "/SPDX-License-Identifier:.*GPL-/{/WITH Linux-syscall-note/!p}" $INFILE)" ]; then
+ echo "error: $INFILE: missing \"WITH Linux-syscall-note\" for SPDX-License-Identifier" >&2
+ exit 1
+fi
+
sed -E -e '
s/([[:space:](])(__user|__force|__iomem)[[:space:]]/\1/g
s/__attribute_const__([[:space:]]|$)/\1/g
@@ -35,5 +41,77 @@ sed -E -e '
scripts/unifdef -U__KERNEL__ -D__EXPORTED_HEADERS__ $TMPFILE > $OUTFILE
[ $? -gt 1 ] && exit 1
+# Remove /* ... */ style comments, and find CONFIG_ references in code
+configs=$(sed -e '
+:comment
+ s:/\*[^*][^*]*:/*:
+ s:/\*\*\**\([^/]\):/*\1:
+ t comment
+ s:/\*\*/: :
+ t comment
+ /\/\*/! b check
+ N
+ b comment
+:print
+ P
+ D
+:check
+ s:^\(CONFIG_[[:alnum:]_]*\):\1\n:
+ t print
+ s:^[[:alnum:]_][[:alnum:]_]*::
+ s:^[^[:alnum:]_][^[:alnum:]_]*::
+ t check
+ d
+' $OUTFILE)
+
+# The entries in the following list are not warned.
+# Please do not add a new entry. This list is only for existing ones.
+# The list will be reduced gradually, and deleted eventually. (hopefully)
+#
+# The format is <file-name>:<CONFIG-option> in each line.
+config_leak_ignores="
+arch/alpha/include/uapi/asm/setup.h:CONFIG_ALPHA_LEGACY_START_ADDRESS
+arch/arc/include/uapi/asm/page.h:CONFIG_ARC_PAGE_SIZE_16K
+arch/arc/include/uapi/asm/page.h:CONFIG_ARC_PAGE_SIZE_4K
+arch/arc/include/uapi/asm/swab.h:CONFIG_ARC_HAS_SWAPE
+arch/arm/include/uapi/asm/ptrace.h:CONFIG_CPU_ENDIAN_BE8
+arch/hexagon/include/uapi/asm/ptrace.h:CONFIG_HEXAGON_ARCH_VERSION
+arch/hexagon/include/uapi/asm/user.h:CONFIG_HEXAGON_ARCH_VERSION
+arch/ia64/include/uapi/asm/cmpxchg.h:CONFIG_IA64_DEBUG_CMPXCHG
+arch/m68k/include/uapi/asm/ptrace.h:CONFIG_COLDFIRE
+arch/nios2/include/uapi/asm/swab.h:CONFIG_NIOS2_CI_SWAB_NO
+arch/nios2/include/uapi/asm/swab.h:CONFIG_NIOS2_CI_SWAB_SUPPORT
+arch/sh/include/uapi/asm/ptrace.h:CONFIG_CPU_SH5
+arch/sh/include/uapi/asm/sigcontext.h:CONFIG_CPU_SH5
+arch/sh/include/uapi/asm/stat.h:CONFIG_CPU_SH5
+arch/x86/include/uapi/asm/auxvec.h:CONFIG_IA32_EMULATION
+arch/x86/include/uapi/asm/auxvec.h:CONFIG_X86_64
+arch/x86/include/uapi/asm/mman.h:CONFIG_X86_INTEL_MEMORY_PROTECTION_KEYS
+include/uapi/asm-generic/fcntl.h:CONFIG_64BIT
+include/uapi/linux/atmdev.h:CONFIG_COMPAT
+include/uapi/linux/elfcore.h:CONFIG_BINFMT_ELF_FDPIC
+include/uapi/linux/eventpoll.h:CONFIG_PM_SLEEP
+include/uapi/linux/hw_breakpoint.h:CONFIG_HAVE_MIXED_BREAKPOINTS_REGS
+include/uapi/linux/pktcdvd.h:CONFIG_CDROM_PKTCDVD_WCACHE
+include/uapi/linux/raw.h:CONFIG_MAX_RAW_DEVS
+"
+
+for c in $configs
+do
+ warn=1
+
+ for ignore in $config_leak_ignores
+ do
+ if echo "$INFILE:$c" | grep -q "$ignore$"; then
+ warn=
+ break
+ fi
+ done
+
+ if [ "$warn" = 1 ]; then
+ echo "warning: $INFILE: leak $c to user-space" >&2
+ fi
+done
+
rm -f $TMPFILE
trap - EXIT
diff --git a/scripts/kconfig/Makefile b/scripts/kconfig/Makefile
index 7656e1137b6b..ef2f2336c469 100644
--- a/scripts/kconfig/Makefile
+++ b/scripts/kconfig/Makefile
@@ -114,7 +114,7 @@ testconfig: $(obj)/conf
$(PYTHON3) -B -m pytest $(srctree)/$(src)/tests \
-o cache_dir=$(abspath $(obj)/tests/.cache) \
$(if $(findstring 1,$(KBUILD_VERBOSE)),--capture=no)
-clean-dirs += tests/.cache
+clean-files += tests/.cache
# Help text used by make help
help:
@@ -166,15 +166,15 @@ $(obj)/nconf.o $(obj)/nconf.gui.o: $(obj)/nconf-cfg
# mconf: Used for the menuconfig target based on lxdialog
hostprogs-y += mconf
-lxdialog := checklist.o inputbox.o menubox.o textbox.o util.o yesno.o
-mconf-objs := mconf.o $(addprefix lxdialog/, $(lxdialog)) $(common-objs)
+lxdialog := $(addprefix lxdialog/, \
+ checklist.o inputbox.o menubox.o textbox.o util.o yesno.o)
+mconf-objs := mconf.o $(lxdialog) $(common-objs)
HOSTLDLIBS_mconf = $(shell . $(obj)/mconf-cfg && echo $$libs)
$(foreach f, mconf.o $(lxdialog), \
$(eval HOSTCFLAGS_$f = $$(shell . $(obj)/mconf-cfg && echo $$$$cflags)))
-$(obj)/mconf.o: $(obj)/mconf-cfg
-$(addprefix $(obj)/lxdialog/, $(lxdialog)): $(obj)/mconf-cfg
+$(addprefix $(obj)/, mconf.o $(lxdialog)): $(obj)/mconf-cfg
# qconf: Used for the xconfig target based on Qt
hostprogs-y += qconf
diff --git a/scripts/kconfig/confdata.c b/scripts/kconfig/confdata.c
index 1134892599da..3569d2dec37c 100644
--- a/scripts/kconfig/confdata.c
+++ b/scripts/kconfig/confdata.c
@@ -848,6 +848,7 @@ int conf_write(const char *name)
const char *str;
char tmpname[PATH_MAX + 1], oldname[PATH_MAX + 1];
char *env;
+ int i;
bool need_newline = false;
if (!name)
@@ -930,6 +931,9 @@ next:
}
fclose(out);
+ for_all_symbols(i, sym)
+ sym->flags &= ~SYMBOL_WRITTEN;
+
if (*tmpname) {
if (is_same(name, tmpname)) {
conf_message("No change to %s", name);
diff --git a/scripts/kconfig/merge_config.sh b/scripts/kconfig/merge_config.sh
index d924c51d28b7..63c8565206a4 100755
--- a/scripts/kconfig/merge_config.sh
+++ b/scripts/kconfig/merge_config.sh
@@ -13,12 +13,12 @@
# Copyright (c) 2009-2010 Wind River Systems, Inc.
# Copyright 2011 Linaro
+set -e
+
clean_up() {
rm -f $TMP_FILE
rm -f $MERGE_FILE
- exit
}
-trap clean_up HUP INT TERM
usage() {
echo "Usage: $0 [OPTIONS] [CONFIG [...]]"
@@ -110,6 +110,9 @@ TMP_FILE=$(mktemp ./.tmp.config.XXXXXXXXXX)
MERGE_FILE=$(mktemp ./.merge_tmp.config.XXXXXXXXXX)
echo "Using $INITFILE as base"
+
+trap clean_up EXIT
+
cat $INITFILE > $TMP_FILE
# Merge files, printing warnings on overridden values
@@ -155,7 +158,6 @@ if [ "$RUNMAKE" = "false" ]; then
echo "#"
echo "# merged configuration written to $KCONFIG_CONFIG (needs make)"
echo "#"
- clean_up
exit
fi
@@ -177,7 +179,7 @@ make KCONFIG_ALLCONFIG=$TMP_FILE $OUTPUT_ARG $ALLTARGET
for CFG in $(sed -n -e "$SED_CONFIG_EXP1" -e "$SED_CONFIG_EXP2" $TMP_FILE); do
REQUESTED_VAL=$(grep -w -e "$CFG" $TMP_FILE)
- ACTUAL_VAL=$(grep -w -e "$CFG" "$KCONFIG_CONFIG")
+ ACTUAL_VAL=$(grep -w -e "$CFG" "$KCONFIG_CONFIG" || true)
if [ "x$REQUESTED_VAL" != "x$ACTUAL_VAL" ] ; then
echo "Value requested for $CFG not in final .config"
echo "Requested value: $REQUESTED_VAL"
@@ -185,5 +187,3 @@ for CFG in $(sed -n -e "$SED_CONFIG_EXP1" -e "$SED_CONFIG_EXP2" $TMP_FILE); do
echo ""
fi
done
-
-clean_up
diff --git a/scripts/kernel-doc b/scripts/kernel-doc
index 6b03012750da..81dc91760b23 100755
--- a/scripts/kernel-doc
+++ b/scripts/kernel-doc
@@ -1245,7 +1245,7 @@ sub dump_enum($$) {
# strip #define macros inside enums
$x =~ s@#\s*((define|ifdef)\s+|endif)[^;]*;@@gos;
- if ($x =~ /enum\s+(\w+)\s*\{(.*)\}/) {
+ if ($x =~ /enum\s+(\w*)\s*\{(.*)\}/) {
$declaration_name = $1;
my $members = $2;
my %_members;
@@ -1580,6 +1580,7 @@ sub dump_function($$) {
$prototype =~ s/__must_check +//;
$prototype =~ s/__weak +//;
$prototype =~ s/__sched +//;
+ $prototype =~ s/__printf\s*\(\s*\d*\s*,\s*\d*\s*\) +//;
my $define = $prototype =~ s/^#\s*define\s+//; #ak added
$prototype =~ s/__attribute__\s*\(\(
(?:
diff --git a/scripts/link-vmlinux.sh b/scripts/link-vmlinux.sh
index a7124f895b24..06495379fcd8 100755
--- a/scripts/link-vmlinux.sh
+++ b/scripts/link-vmlinux.sh
@@ -56,13 +56,19 @@ modpost_link()
}
# Link of vmlinux
-# ${1} - optional extra .o files
-# ${2} - output file
+# ${1} - output file
+# ${2}, ${3}, ... - optional extra .o files
vmlinux_link()
{
local lds="${objtree}/${KBUILD_LDS}"
+ local output=${1}
local objects
+ info LD ${output}
+
+ # skip output file argument
+ shift
+
if [ "${SRCARCH}" != "um" ]; then
objects="--whole-archive \
${KBUILD_VMLINUX_OBJS} \
@@ -70,9 +76,10 @@ vmlinux_link()
--start-group \
${KBUILD_VMLINUX_LIBS} \
--end-group \
- ${1}"
+ ${@}"
- ${LD} ${KBUILD_LDFLAGS} ${LDFLAGS_vmlinux} -o ${2} \
+ ${LD} ${KBUILD_LDFLAGS} ${LDFLAGS_vmlinux} \
+ -o ${output} \
-T ${lds} ${objects}
else
objects="-Wl,--whole-archive \
@@ -81,9 +88,10 @@ vmlinux_link()
-Wl,--start-group \
${KBUILD_VMLINUX_LIBS} \
-Wl,--end-group \
- ${1}"
+ ${@}"
- ${CC} ${CFLAGS_vmlinux} -o ${2} \
+ ${CC} ${CFLAGS_vmlinux} \
+ -o ${output} \
-Wl,-T,${lds} \
${objects} \
-lutil -lrt -lpthread
@@ -92,23 +100,36 @@ vmlinux_link()
}
# generate .BTF typeinfo from DWARF debuginfo
+# ${1} - vmlinux image
+# ${2} - file to dump raw BTF data into
gen_btf()
{
- local pahole_ver;
+ local pahole_ver
+ local bin_arch
if ! [ -x "$(command -v ${PAHOLE})" ]; then
info "BTF" "${1}: pahole (${PAHOLE}) is not available"
- return 0
+ return 1
fi
pahole_ver=$(${PAHOLE} --version | sed -E 's/v([0-9]+)\.([0-9]+)/\1\2/')
if [ "${pahole_ver}" -lt "113" ]; then
info "BTF" "${1}: pahole version $(${PAHOLE} --version) is too old, need at least v1.13"
- return 0
+ return 1
fi
- info "BTF" ${1}
+ info "BTF" ${2}
+ vmlinux_link ${1}
LLVM_OBJCOPY=${OBJCOPY} ${PAHOLE} -J ${1}
+
+ # dump .BTF section into raw binary file to link with final vmlinux
+ bin_arch=$(LANG=C ${OBJDUMP} -f ${1} | grep architecture | \
+ cut -d, -f1 | cut -d' ' -f2)
+ bin_format=$(LANG=C ${OBJDUMP} -f ${1} | grep 'file format' | \
+ awk '{print $4}')
+ ${OBJCOPY} --dump-section .BTF=.btf.vmlinux.bin ${1} 2>/dev/null
+ ${OBJCOPY} -I binary -O ${bin_format} -B ${bin_arch} \
+ --rename-section .data=.BTF .btf.vmlinux.bin ${2}
}
# Create ${2} .o file with all symbols from the ${1} object file
@@ -138,6 +159,18 @@ kallsyms()
${CC} ${aflags} -c -o ${2} ${afile}
}
+# Perform one step in kallsyms generation, including temporary linking of
+# vmlinux.
+kallsyms_step()
+{
+ kallsymso_prev=${kallsymso}
+ kallsymso=.tmp_kallsyms${1}.o
+ kallsyms_vmlinux=.tmp_vmlinux${1}
+
+ vmlinux_link ${kallsyms_vmlinux} "${kallsymso_prev}" ${btf_vmlinux_bin_o}
+ kallsyms ${kallsyms_vmlinux} ${kallsymso}
+}
+
# Create map file with all symbols from ${1}
# See mksymap for additional details
mksysmap()
@@ -153,6 +186,7 @@ sortextable()
# Delete output files in case of error
cleanup()
{
+ rm -f .btf.*
rm -f .tmp_System.map
rm -f .tmp_kallsyms*
rm -f .tmp_vmlinux*
@@ -210,12 +244,20 @@ info LD vmlinux.o
modpost_link vmlinux.o
# modpost vmlinux.o to check for section mismatches
-${MAKE} -f "${srctree}/scripts/Makefile.modpost" vmlinux.o
+${MAKE} -f "${srctree}/scripts/Makefile.modpost" MODPOST_VMLINUX=1
info MODINFO modules.builtin.modinfo
${OBJCOPY} -j .modinfo -O binary vmlinux.o modules.builtin.modinfo
+btf_vmlinux_bin_o=""
+if [ -n "${CONFIG_DEBUG_INFO_BTF}" ]; then
+ if gen_btf .tmp_vmlinux.btf .btf.vmlinux.bin.o ; then
+ btf_vmlinux_bin_o=.btf.vmlinux.bin.o
+ fi
+fi
+
kallsymso=""
+kallsymso_prev=""
kallsyms_vmlinux=""
if [ -n "${CONFIG_KALLSYMS}" ]; then
@@ -242,37 +284,19 @@ if [ -n "${CONFIG_KALLSYMS}" ]; then
# a) Verify that the System.map from vmlinux matches the map from
# ${kallsymso}.
- kallsymso=.tmp_kallsyms2.o
- kallsyms_vmlinux=.tmp_vmlinux2
-
- # step 1
- vmlinux_link "" .tmp_vmlinux1
- kallsyms .tmp_vmlinux1 .tmp_kallsyms1.o
-
- # step 2
- vmlinux_link .tmp_kallsyms1.o .tmp_vmlinux2
- kallsyms .tmp_vmlinux2 .tmp_kallsyms2.o
+ kallsyms_step 1
+ kallsyms_step 2
# step 3
- size1=$(${CONFIG_SHELL} "${srctree}/scripts/file-size.sh" .tmp_kallsyms1.o)
- size2=$(${CONFIG_SHELL} "${srctree}/scripts/file-size.sh" .tmp_kallsyms2.o)
+ size1=$(${CONFIG_SHELL} "${srctree}/scripts/file-size.sh" ${kallsymso_prev})
+ size2=$(${CONFIG_SHELL} "${srctree}/scripts/file-size.sh" ${kallsymso})
if [ $size1 -ne $size2 ] || [ -n "${KALLSYMS_EXTRA_PASS}" ]; then
- kallsymso=.tmp_kallsyms3.o
- kallsyms_vmlinux=.tmp_vmlinux3
-
- vmlinux_link .tmp_kallsyms2.o .tmp_vmlinux3
-
- kallsyms .tmp_vmlinux3 .tmp_kallsyms3.o
+ kallsyms_step 3
fi
fi
-info LD vmlinux
-vmlinux_link "${kallsymso}" vmlinux
-
-if [ -n "${CONFIG_DEBUG_INFO_BTF}" ]; then
- gen_btf vmlinux
-fi
+vmlinux_link vmlinux "${kallsymso}" ${btf_vmlinux_bin_o}
if [ -n "${CONFIG_BUILDTIME_EXTABLE_SORT}" ]; then
info SORTEX vmlinux
diff --git a/scripts/mkcompile_h b/scripts/mkcompile_h
index 2339f86126cb..d1d757c6edf4 100755
--- a/scripts/mkcompile_h
+++ b/scripts/mkcompile_h
@@ -5,7 +5,8 @@ TARGET=$1
ARCH=$2
SMP=$3
PREEMPT=$4
-CC=$5
+PREEMPT_RT=$5
+CC=$6
vecho() { [ "${quiet}" = "silent_" ] || echo "$@" ; }
@@ -53,6 +54,7 @@ UTS_VERSION="#$VERSION"
CONFIG_FLAGS=""
if [ -n "$SMP" ] ; then CONFIG_FLAGS="SMP"; fi
if [ -n "$PREEMPT" ] ; then CONFIG_FLAGS="$CONFIG_FLAGS PREEMPT"; fi
+if [ -n "$PREEMPT_RT" ] ; then CONFIG_FLAGS="$CONFIG_FLAGS PREEMPT_RT"; fi
UTS_VERSION="$UTS_VERSION $CONFIG_FLAGS $TIMESTAMP"
# Truncate to maximum length
diff --git a/scripts/mkmakefile b/scripts/mkmakefile
index 4d0faebb1719..1cb174751429 100755
--- a/scripts/mkmakefile
+++ b/scripts/mkmakefile
@@ -12,6 +12,6 @@ if [ "${quiet}" != "silent_" ]; then
fi
cat << EOF > Makefile
-# Automatically generated by $(realpath $0): don't edit
-include $(realpath $1/Makefile)
+# Automatically generated by $0: don't edit
+include $1/Makefile
EOF
diff --git a/scripts/mod/file2alias.c b/scripts/mod/file2alias.c
index e17a29ae2e97..c91eba751804 100644
--- a/scripts/mod/file2alias.c
+++ b/scripts/mod/file2alias.c
@@ -36,6 +36,11 @@ typedef uint16_t __u16;
typedef unsigned char __u8;
typedef struct {
__u8 b[16];
+} guid_t;
+
+/* backwards compatibility, don't use in new code */
+typedef struct {
+ __u8 b[16];
} uuid_le;
typedef struct {
__u8 b[16];
diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c
index f277e116e0eb..3961941e8e7a 100644
--- a/scripts/mod/modpost.c
+++ b/scripts/mod/modpost.c
@@ -38,6 +38,8 @@ static int sec_mismatch_count = 0;
static int sec_mismatch_fatal = 0;
/* ignore missing files */
static int ignore_missing_files;
+/* write namespace dependencies */
+static int write_namespace_deps;
enum export {
export_plain, export_unused, export_gpl,
@@ -164,11 +166,13 @@ struct symbol {
struct module *module;
unsigned int crc;
int crc_valid;
+ const char *namespace;
unsigned int weak:1;
unsigned int vmlinux:1; /* 1 if symbol is defined in vmlinux */
unsigned int kernel:1; /* 1 if symbol is from kernel
* (only for external modules) **/
unsigned int preloaded:1; /* 1 if symbol from Module.symvers, or crc */
+ unsigned int is_static:1; /* 1 if symbol is not global */
enum export export; /* Type of export */
char name[0];
};
@@ -201,6 +205,7 @@ static struct symbol *alloc_symbol(const char *name, unsigned int weak,
strcpy(s->name, name);
s->weak = weak;
s->next = next;
+ s->is_static = 1;
return s;
}
@@ -233,6 +238,37 @@ static struct symbol *find_symbol(const char *name)
return NULL;
}
+static bool contains_namespace(struct namespace_list *list,
+ const char *namespace)
+{
+ struct namespace_list *ns_entry;
+
+ for (ns_entry = list; ns_entry != NULL; ns_entry = ns_entry->next)
+ if (strcmp(ns_entry->namespace, namespace) == 0)
+ return true;
+
+ return false;
+}
+
+static void add_namespace(struct namespace_list **list, const char *namespace)
+{
+ struct namespace_list *ns_entry;
+
+ if (!contains_namespace(*list, namespace)) {
+ ns_entry = NOFAIL(malloc(sizeof(struct namespace_list) +
+ strlen(namespace) + 1));
+ strcpy(ns_entry->namespace, namespace);
+ ns_entry->next = *list;
+ *list = ns_entry;
+ }
+}
+
+static bool module_imports_namespace(struct module *module,
+ const char *namespace)
+{
+ return contains_namespace(module->imported_namespaces, namespace);
+}
+
static const struct {
const char *str;
enum export export;
@@ -312,23 +348,39 @@ static enum export export_from_sec(struct elf_info *elf, unsigned int sec)
return export_unknown;
}
+static const char *sym_extract_namespace(const char **symname)
+{
+ size_t n;
+ char *dupsymname;
+
+ n = strcspn(*symname, ".");
+ if (n < strlen(*symname) - 1) {
+ dupsymname = NOFAIL(strdup(*symname));
+ dupsymname[n] = '\0';
+ *symname = dupsymname;
+ return dupsymname + n + 1;
+ }
+
+ return NULL;
+}
+
/**
* Add an exported symbol - it may have already been added without a
* CRC, in this case just update the CRC
**/
-static struct symbol *sym_add_exported(const char *name, struct module *mod,
- enum export export)
+static struct symbol *sym_add_exported(const char *name, const char *namespace,
+ struct module *mod, enum export export)
{
struct symbol *s = find_symbol(name);
if (!s) {
s = new_symbol(name, mod, export);
+ s->namespace = namespace;
} else {
if (!s->preloaded) {
- warn("%s: '%s' exported twice. Previous export "
- "was in %s%s\n", mod->name, name,
- s->module->name,
- is_vmlinux(s->module->name) ?"":".ko");
+ warn("%s: '%s' exported twice. Previous export was in %s%s\n",
+ mod->name, name, s->module->name,
+ is_vmlinux(s->module->name) ? "" : ".ko");
} else {
/* In case Module.symvers was out of date */
s->module = mod;
@@ -620,6 +672,7 @@ static void handle_modversions(struct module *mod, struct elf_info *info,
unsigned int crc;
enum export export;
bool is_crc = false;
+ const char *name, *namespace;
if ((!is_vmlinux(mod->name) || mod->is_dot_o) &&
strstarts(symname, "__ksymtab"))
@@ -691,8 +744,9 @@ static void handle_modversions(struct module *mod, struct elf_info *info,
default:
/* All exported symbols */
if (strstarts(symname, "__ksymtab_")) {
- sym_add_exported(symname + strlen("__ksymtab_"), mod,
- export);
+ name = symname + strlen("__ksymtab_");
+ namespace = sym_extract_namespace(&name);
+ sym_add_exported(name, namespace, mod, export);
}
if (strcmp(symname, "init_module") == 0)
mod->has_init = 1;
@@ -795,9 +849,9 @@ static int match(const char *sym, const char * const pat[])
/* "*foo*" */
if (*p == '*' && *endp == '*') {
- char *here, *bare = strndup(p + 1, strlen(p) - 2);
+ char *bare = NOFAIL(strndup(p + 1, strlen(p) - 2));
+ char *here = strstr(sym, bare);
- here = strstr(sym, bare);
free(bare);
if (here != NULL)
return 1;
@@ -1943,6 +1997,7 @@ static void read_symbols(const char *modname)
const char *symname;
char *version;
char *license;
+ char *namespace;
struct module *mod;
struct elf_info info = { };
Elf_Sym *sym;
@@ -1974,12 +2029,33 @@ static void read_symbols(const char *modname)
license = get_next_modinfo(&info, "license", license);
}
+ namespace = get_modinfo(&info, "import_ns");
+ while (namespace) {
+ add_namespace(&mod->imported_namespaces, namespace);
+ namespace = get_next_modinfo(&info, "import_ns", namespace);
+ }
+
for (sym = info.symtab_start; sym < info.symtab_stop; sym++) {
symname = remove_dot(info.strtab + sym->st_name);
handle_modversions(mod, &info, sym, symname);
handle_moddevtable(mod, &info, sym, symname);
}
+
+ // check for static EXPORT_SYMBOL_* functions && global vars
+ for (sym = info.symtab_start; sym < info.symtab_stop; sym++) {
+ unsigned char bind = ELF_ST_BIND(sym->st_info);
+
+ if (bind == STB_GLOBAL || bind == STB_WEAK) {
+ struct symbol *s =
+ find_symbol(remove_dot(info.strtab +
+ sym->st_name));
+
+ if (s)
+ s->is_static = 0;
+ }
+ }
+
if (!is_vmlinux(modname) || vmlinux_section_warnings)
check_sec_ref(mod, modname, &info);
@@ -2118,6 +2194,18 @@ static int check_exports(struct module *mod)
basename++;
else
basename = mod->name;
+
+ if (exp->namespace) {
+ add_namespace(&mod->required_namespaces,
+ exp->namespace);
+
+ if (!write_namespace_deps &&
+ !module_imports_namespace(mod, exp->namespace)) {
+ warn("module %s uses symbol %s from namespace %s, but does not import it.\n",
+ basename, exp->name, exp->namespace);
+ }
+ }
+
if (!mod->gpl_compatible)
check_for_gpl_usage(exp->export, basename, exp->name);
check_for_unused(exp->export, basename, exp->name);
@@ -2159,7 +2247,7 @@ static void add_header(struct buffer *b, struct module *mod)
buf_printf(b, "MODULE_INFO(name, KBUILD_MODNAME);\n");
buf_printf(b, "\n");
buf_printf(b, "__visible struct module __this_module\n");
- buf_printf(b, "__attribute__((section(\".gnu.linkonce.this_module\"))) = {\n");
+ buf_printf(b, "__section(.gnu.linkonce.this_module) = {\n");
buf_printf(b, "\t.name = KBUILD_MODNAME,\n");
if (mod->has_init)
buf_printf(b, "\t.init = init_module,\n");
@@ -2213,8 +2301,7 @@ static int add_versions(struct buffer *b, struct module *mod)
buf_printf(b, "\n");
buf_printf(b, "static const struct modversion_info ____versions[]\n");
- buf_printf(b, "__used\n");
- buf_printf(b, "__attribute__((section(\"__versions\"))) = {\n");
+ buf_printf(b, "__used __section(__versions) = {\n");
for (s = mod->unres; s; s = s->next) {
if (!s->module)
@@ -2250,10 +2337,7 @@ static void add_depends(struct buffer *b, struct module *mod)
s->module->seen = is_vmlinux(s->module->name);
buf_printf(b, "\n");
- buf_printf(b, "static const char __module_depends[]\n");
- buf_printf(b, "__used\n");
- buf_printf(b, "__attribute__((section(\".modinfo\"))) =\n");
- buf_printf(b, "\"depends=");
+ buf_printf(b, "MODULE_INFO(depends, \"");
for (s = mod->unres; s; s = s->next) {
const char *p;
if (!s->module)
@@ -2271,7 +2355,7 @@ static void add_depends(struct buffer *b, struct module *mod)
buf_printf(b, "%s%s", first ? "" : ",", p);
first = 0;
}
- buf_printf(b, "\";\n");
+ buf_printf(b, "\");\n");
}
static void add_srcversion(struct buffer *b, struct module *mod)
@@ -2341,7 +2425,7 @@ static void read_dump(const char *fname, unsigned int kernel)
return;
while ((line = get_next_line(&pos, file, size))) {
- char *symname, *modname, *d, *export, *end;
+ char *symname, *namespace, *modname, *d, *export, *end;
unsigned int crc;
struct module *mod;
struct symbol *s;
@@ -2349,7 +2433,10 @@ static void read_dump(const char *fname, unsigned int kernel)
if (!(symname = strchr(line, '\t')))
goto fail;
*symname++ = '\0';
- if (!(modname = strchr(symname, '\t')))
+ if (!(namespace = strchr(symname, '\t')))
+ goto fail;
+ *namespace++ = '\0';
+ if (!(modname = strchr(namespace, '\t')))
goto fail;
*modname++ = '\0';
if ((export = strchr(modname, '\t')) != NULL)
@@ -2366,9 +2453,11 @@ static void read_dump(const char *fname, unsigned int kernel)
mod = new_module(modname);
mod->skip = 1;
}
- s = sym_add_exported(symname, mod, export_no(export));
+ s = sym_add_exported(symname, namespace, mod,
+ export_no(export));
s->kernel = kernel;
s->preloaded = 1;
+ s->is_static = 0;
sym_update_crc(symname, mod, crc, export_no(export));
}
release_file(file, size);
@@ -2395,16 +2484,20 @@ static void write_dump(const char *fname)
{
struct buffer buf = { };
struct symbol *symbol;
+ const char *namespace;
int n;
for (n = 0; n < SYMBOL_HASH_SIZE ; n++) {
symbol = symbolhash[n];
while (symbol) {
- if (dump_sym(symbol))
- buf_printf(&buf, "0x%08x\t%s\t%s\t%s\n",
- symbol->crc, symbol->name,
- symbol->module->name,
- export_str(symbol->export));
+ if (dump_sym(symbol)) {
+ namespace = symbol->namespace;
+ buf_printf(&buf, "0x%08x\t%s\t%s\t%s\t%s\n",
+ symbol->crc, symbol->name,
+ namespace ? namespace : "",
+ symbol->module->name,
+ export_str(symbol->export));
+ }
symbol = symbol->next;
}
}
@@ -2412,6 +2505,31 @@ static void write_dump(const char *fname)
free(buf.p);
}
+static void write_namespace_deps_files(void)
+{
+ struct module *mod;
+ struct namespace_list *ns;
+ struct buffer ns_deps_buf = {};
+
+ for (mod = modules; mod; mod = mod->next) {
+ char fname[PATH_MAX];
+
+ if (mod->skip)
+ continue;
+
+ ns_deps_buf.pos = 0;
+
+ for (ns = mod->required_namespaces; ns; ns = ns->next)
+ buf_printf(&ns_deps_buf, "%s\n", ns->namespace);
+
+ if (ns_deps_buf.pos == 0)
+ continue;
+
+ sprintf(fname, "%s.ns_deps", mod->name);
+ write_if_changed(&ns_deps_buf, fname);
+ }
+}
+
struct ext_sym_list {
struct ext_sym_list *next;
const char *file;
@@ -2425,10 +2543,11 @@ int main(int argc, char **argv)
char *dump_write = NULL, *files_source = NULL;
int opt;
int err;
+ int n;
struct ext_sym_list *extsym_iter;
struct ext_sym_list *extsym_start = NULL;
- while ((opt = getopt(argc, argv, "i:I:e:mnsT:o:awE")) != -1) {
+ while ((opt = getopt(argc, argv, "i:I:e:mnsT:o:awEd")) != -1) {
switch (opt) {
case 'i':
kernel_read = optarg;
@@ -2469,6 +2588,9 @@ int main(int argc, char **argv)
case 'E':
sec_mismatch_fatal = 1;
break;
+ case 'd':
+ write_namespace_deps = 1;
+ break;
default:
exit(1);
}
@@ -2503,6 +2625,9 @@ int main(int argc, char **argv)
err |= check_modname_len(mod);
err |= check_exports(mod);
+ if (write_namespace_deps)
+ continue;
+
add_header(&buf, mod);
add_intree_flag(&buf, !external_module);
add_retpoline(&buf);
@@ -2515,11 +2640,30 @@ int main(int argc, char **argv)
sprintf(fname, "%s.mod.c", mod->name);
write_if_changed(&buf, fname);
}
+
+ if (write_namespace_deps) {
+ write_namespace_deps_files();
+ return 0;
+ }
+
if (dump_write)
write_dump(dump_write);
if (sec_mismatch_count && sec_mismatch_fatal)
fatal("modpost: Section mismatches detected.\n"
"Set CONFIG_SECTION_MISMATCH_WARN_ONLY=y to allow them.\n");
+ for (n = 0; n < SYMBOL_HASH_SIZE; n++) {
+ struct symbol *s = symbolhash[n];
+
+ while (s) {
+ if (s->is_static)
+ warn("\"%s\" [%s] is a static %s\n",
+ s->name, s->module->name,
+ export_str(s->export));
+
+ s = s->next;
+ }
+ }
+
free(buf.p);
return err;
diff --git a/scripts/mod/modpost.h b/scripts/mod/modpost.h
index 8453d6ac2f77..92a926d375d2 100644
--- a/scripts/mod/modpost.h
+++ b/scripts/mod/modpost.h
@@ -109,6 +109,11 @@ buf_printf(struct buffer *buf, const char *fmt, ...);
void
buf_write(struct buffer *buf, const char *s, int len);
+struct namespace_list {
+ struct namespace_list *next;
+ char namespace[0];
+};
+
struct module {
struct module *next;
const char *name;
@@ -121,6 +126,10 @@ struct module {
struct buffer dev_table_buf;
char srcversion[25];
int is_dot_o;
+ // Required namespace dependencies
+ struct namespace_list *required_namespaces;
+ // Actual imported namespaces
+ struct namespace_list *imported_namespaces;
};
struct elf_info {
diff --git a/scripts/nsdeps b/scripts/nsdeps
new file mode 100644
index 000000000000..ac2b6031dd13
--- /dev/null
+++ b/scripts/nsdeps
@@ -0,0 +1,58 @@
+#!/bin/bash
+# SPDX-License-Identifier: GPL-2.0
+# Linux kernel symbol namespace import generator
+#
+# This script requires a minimum spatch version.
+SPATCH_REQ_VERSION="1.0.4"
+
+DIR="$(dirname $(readlink -f $0))/.."
+SPATCH="`which ${SPATCH:=spatch}`"
+if [ ! -x "$SPATCH" ]; then
+ echo 'spatch is part of the Coccinelle project and is available at http://coccinelle.lip6.fr/'
+ exit 1
+fi
+
+SPATCH_REQ_VERSION_NUM=$(echo $SPATCH_REQ_VERSION | ${DIR}/scripts/ld-version.sh)
+SPATCH_VERSION=$($SPATCH --version | head -1 | awk '{print $3}')
+SPATCH_VERSION_NUM=$(echo $SPATCH_VERSION | ${DIR}/scripts/ld-version.sh)
+
+if [ "$SPATCH_VERSION_NUM" -lt "$SPATCH_REQ_VERSION_NUM" ] ; then
+ echo "spatch needs to be version $SPATCH_REQ_VERSION or higher"
+ exit 1
+fi
+
+generate_deps_for_ns() {
+ $SPATCH --very-quiet --in-place --sp-file \
+ $srctree/scripts/coccinelle/misc/add_namespace.cocci -D ns=$1 $2
+}
+
+generate_deps() {
+ local mod_name=`basename $@ .ko`
+ local mod_file=`echo $@ | sed -e 's/\.ko/\.mod/'`
+ local ns_deps_file=`echo $@ | sed -e 's/\.ko/\.ns_deps/'`
+ if [ ! -f "$ns_deps_file" ]; then return; fi
+ local mod_source_files=`cat $mod_file | sed -n 1p \
+ | sed -e 's/\.o/\.c/g' \
+ | sed "s/[^ ]* */${srctree}\/&/g"`
+ for ns in `cat $ns_deps_file`; do
+ echo "Adding namespace $ns to module $mod_name (if needed)."
+ generate_deps_for_ns $ns $mod_source_files
+ # sort the imports
+ for source_file in $mod_source_files; do
+ sed '/MODULE_IMPORT_NS/Q' $source_file > ${source_file}.tmp
+ offset=$(wc -l ${source_file}.tmp | awk '{print $1;}')
+ cat $source_file | grep MODULE_IMPORT_NS | sort -u >> ${source_file}.tmp
+ tail -n +$((offset +1)) ${source_file} | grep -v MODULE_IMPORT_NS >> ${source_file}.tmp
+ if ! diff -q ${source_file} ${source_file}.tmp; then
+ mv ${source_file}.tmp ${source_file}
+ else
+ rm ${source_file}.tmp
+ fi
+ done
+ done
+}
+
+for f in `cat $objtree/modules.order`; do
+ generate_deps $f
+done
+
diff --git a/scripts/recordmcount.c b/scripts/recordmcount.c
index 8387a9bc064a..612268eabef4 100644
--- a/scripts/recordmcount.c
+++ b/scripts/recordmcount.c
@@ -27,7 +27,6 @@
#include <getopt.h>
#include <elf.h>
#include <fcntl.h>
-#include <setjmp.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -43,56 +42,37 @@ static int fd_map; /* File descriptor for file being modified. */
static int mmap_failed; /* Boolean flag. */
static char gpfx; /* prefix for global symbol name (sometimes '_') */
static struct stat sb; /* Remember .st_size, etc. */
-static jmp_buf jmpenv; /* setjmp/longjmp per-file error escape */
static const char *altmcount; /* alternate mcount symbol name */
static int warn_on_notrace_sect; /* warn when section has mcount not being recorded */
static void *file_map; /* pointer of the mapped file */
static void *file_end; /* pointer to the end of the mapped file */
static int file_updated; /* flag to state file was changed */
static void *file_ptr; /* current file pointer location */
+
static void *file_append; /* added to the end of the file */
static size_t file_append_size; /* how much is added to end of file */
-/* setjmp() return values */
-enum {
- SJ_SETJMP = 0, /* hardwired first return */
- SJ_FAIL,
- SJ_SUCCEED
-};
-
/* Per-file resource cleanup when multiple files. */
-static void
-cleanup(void)
+static void file_append_cleanup(void)
{
- if (!mmap_failed)
- munmap(file_map, sb.st_size);
- else
- free(file_map);
- file_map = NULL;
free(file_append);
file_append = NULL;
file_append_size = 0;
file_updated = 0;
}
-static void __attribute__((noreturn))
-fail_file(void)
+static void mmap_cleanup(void)
{
- cleanup();
- longjmp(jmpenv, SJ_FAIL);
-}
-
-static void __attribute__((noreturn))
-succeed_file(void)
-{
- cleanup();
- longjmp(jmpenv, SJ_SUCCEED);
+ if (!mmap_failed)
+ munmap(file_map, sb.st_size);
+ else
+ free(file_map);
+ file_map = NULL;
}
-/* ulseek, uread, ...: Check return value for errors. */
+/* ulseek, uwrite, ...: Check return value for errors. */
-static off_t
-ulseek(int const fd, off_t const offset, int const whence)
+static off_t ulseek(off_t const offset, int const whence)
{
switch (whence) {
case SEEK_SET:
@@ -107,24 +87,12 @@ ulseek(int const fd, off_t const offset, int const whence)
}
if (file_ptr < file_map) {
fprintf(stderr, "lseek: seek before file\n");
- fail_file();
+ return -1;
}
return file_ptr - file_map;
}
-static size_t
-uread(int const fd, void *const buf, size_t const count)
-{
- size_t const n = read(fd, buf, count);
- if (n != count) {
- perror("read");
- fail_file();
- }
- return n;
-}
-
-static size_t
-uwrite(int const fd, void const *const buf, size_t const count)
+static ssize_t uwrite(void const *const buf, size_t const count)
{
size_t cnt = count;
off_t idx = 0;
@@ -140,7 +108,9 @@ uwrite(int const fd, void const *const buf, size_t const count)
}
if (!file_append) {
perror("write");
- fail_file();
+ file_append_cleanup();
+ mmap_cleanup();
+ return -1;
}
if (file_ptr < file_end) {
cnt = file_end - file_ptr;
@@ -160,17 +130,81 @@ uwrite(int const fd, void const *const buf, size_t const count)
return count;
}
-static void *
-umalloc(size_t size)
+static void * umalloc(size_t size)
{
void *const addr = malloc(size);
if (addr == 0) {
fprintf(stderr, "malloc failed: %zu bytes\n", size);
- fail_file();
+ file_append_cleanup();
+ mmap_cleanup();
+ return NULL;
}
return addr;
}
+/*
+ * Get the whole file as a programming convenience in order to avoid
+ * malloc+lseek+read+free of many pieces. If successful, then mmap
+ * avoids copying unused pieces; else just read the whole file.
+ * Open for both read and write; new info will be appended to the file.
+ * Use MAP_PRIVATE so that a few changes to the in-memory ElfXX_Ehdr
+ * do not propagate to the file until an explicit overwrite at the last.
+ * This preserves most aspects of consistency (all except .st_size)
+ * for simultaneous readers of the file while we are appending to it.
+ * However, multiple writers still are bad. We choose not to use
+ * locking because it is expensive and the use case of kernel build
+ * makes multiple writers unlikely.
+ */
+static void *mmap_file(char const *fname)
+{
+ /* Avoid problems if early cleanup() */
+ fd_map = -1;
+ mmap_failed = 1;
+ file_map = NULL;
+ file_ptr = NULL;
+ file_updated = 0;
+ sb.st_size = 0;
+
+ fd_map = open(fname, O_RDONLY);
+ if (fd_map < 0) {
+ perror(fname);
+ return NULL;
+ }
+ if (fstat(fd_map, &sb) < 0) {
+ perror(fname);
+ goto out;
+ }
+ if (!S_ISREG(sb.st_mode)) {
+ fprintf(stderr, "not a regular file: %s\n", fname);
+ goto out;
+ }
+ file_map = mmap(0, sb.st_size, PROT_READ|PROT_WRITE, MAP_PRIVATE,
+ fd_map, 0);
+ if (file_map == MAP_FAILED) {
+ mmap_failed = 1;
+ file_map = umalloc(sb.st_size);
+ if (!file_map) {
+ perror(fname);
+ goto out;
+ }
+ if (read(fd_map, file_map, sb.st_size) != sb.st_size) {
+ perror(fname);
+ free(file_map);
+ file_map = NULL;
+ goto out;
+ }
+ } else
+ mmap_failed = 0;
+out:
+ close(fd_map);
+ fd_map = -1;
+
+ file_end = file_map + sb.st_size;
+
+ return file_map;
+}
+
+
static unsigned char ideal_nop5_x86_64[5] = { 0x0f, 0x1f, 0x44, 0x00, 0x00 };
static unsigned char ideal_nop5_x86_32[5] = { 0x3e, 0x8d, 0x74, 0x26, 0x00 };
static unsigned char *ideal_nop;
@@ -194,8 +228,10 @@ static int make_nop_x86(void *map, size_t const offset)
return -1;
/* convert to nop */
- ulseek(fd_map, offset - 1, SEEK_SET);
- uwrite(fd_map, ideal_nop, 5);
+ if (ulseek(offset - 1, SEEK_SET) < 0)
+ return -1;
+ if (uwrite(ideal_nop, 5) < 0)
+ return -1;
return 0;
}
@@ -243,10 +279,12 @@ static int make_nop_arm(void *map, size_t const offset)
return -1;
/* Convert to nop */
- ulseek(fd_map, off, SEEK_SET);
+ if (ulseek(off, SEEK_SET) < 0)
+ return -1;
do {
- uwrite(fd_map, ideal_nop, nop_size);
+ if (uwrite(ideal_nop, nop_size) < 0)
+ return -1;
} while (--cnt > 0);
return 0;
@@ -263,57 +301,20 @@ static int make_nop_arm64(void *map, size_t const offset)
return -1;
/* Convert to nop */
- ulseek(fd_map, offset, SEEK_SET);
- uwrite(fd_map, ideal_nop, 4);
+ if (ulseek(offset, SEEK_SET) < 0)
+ return -1;
+ if (uwrite(ideal_nop, 4) < 0)
+ return -1;
return 0;
}
-/*
- * Get the whole file as a programming convenience in order to avoid
- * malloc+lseek+read+free of many pieces. If successful, then mmap
- * avoids copying unused pieces; else just read the whole file.
- * Open for both read and write; new info will be appended to the file.
- * Use MAP_PRIVATE so that a few changes to the in-memory ElfXX_Ehdr
- * do not propagate to the file until an explicit overwrite at the last.
- * This preserves most aspects of consistency (all except .st_size)
- * for simultaneous readers of the file while we are appending to it.
- * However, multiple writers still are bad. We choose not to use
- * locking because it is expensive and the use case of kernel build
- * makes multiple writers unlikely.
- */
-static void *mmap_file(char const *fname)
-{
- fd_map = open(fname, O_RDONLY);
- if (fd_map < 0 || fstat(fd_map, &sb) < 0) {
- perror(fname);
- fail_file();
- }
- if (!S_ISREG(sb.st_mode)) {
- fprintf(stderr, "not a regular file: %s\n", fname);
- fail_file();
- }
- file_map = mmap(0, sb.st_size, PROT_READ|PROT_WRITE, MAP_PRIVATE,
- fd_map, 0);
- mmap_failed = 0;
- if (file_map == MAP_FAILED) {
- mmap_failed = 1;
- file_map = umalloc(sb.st_size);
- uread(fd_map, file_map, sb.st_size);
- }
- close(fd_map);
-
- file_end = file_map + sb.st_size;
-
- return file_map;
-}
-
-static void write_file(const char *fname)
+static int write_file(const char *fname)
{
char tmp_file[strlen(fname) + 4];
size_t n;
if (!file_updated)
- return;
+ return 0;
sprintf(tmp_file, "%s.rc", fname);
@@ -325,25 +326,28 @@ static void write_file(const char *fname)
fd_map = open(tmp_file, O_WRONLY | O_TRUNC | O_CREAT, sb.st_mode);
if (fd_map < 0) {
perror(fname);
- fail_file();
+ return -1;
}
n = write(fd_map, file_map, sb.st_size);
if (n != sb.st_size) {
perror("write");
- fail_file();
+ close(fd_map);
+ return -1;
}
if (file_append_size) {
n = write(fd_map, file_append, file_append_size);
if (n != file_append_size) {
perror("write");
- fail_file();
+ close(fd_map);
+ return -1;
}
}
close(fd_map);
if (rename(tmp_file, fname) < 0) {
perror(fname);
- fail_file();
+ return -1;
}
+ return 0;
}
/* w8rev, w8nat, ...: Handle endianness. */
@@ -394,8 +398,7 @@ static uint32_t (*w)(uint32_t);
static uint32_t (*w2)(uint16_t);
/* Names of the sections that could contain calls to mcount. */
-static int
-is_mcounted_section_name(char const *const txtname)
+static int is_mcounted_section_name(char const *const txtname)
{
return strncmp(".text", txtname, 5) == 0 ||
strcmp(".init.text", txtname) == 0 ||
@@ -405,10 +408,11 @@ 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(".text.unlikely", txtname) == 0;
+ strcmp(".cpuidle.text", txtname) == 0;
}
+static char const *already_has_rel_mcount = "success"; /* our work here is done! */
+
/* 32 bit and 64 bit are very similar */
#include "recordmcount.h"
#define RECORD_MCOUNT_64
@@ -447,11 +451,15 @@ static void MIPS64_r_info(Elf64_Rel *const rp, unsigned sym, unsigned type)
}).r_info;
}
-static void
-do_file(char const *const fname)
+static int do_file(char const *const fname)
{
- Elf32_Ehdr *const ehdr = mmap_file(fname);
unsigned int reltype = 0;
+ Elf32_Ehdr *ehdr;
+ int rc = -1;
+
+ ehdr = mmap_file(fname);
+ if (!ehdr)
+ goto out;
w = w4nat;
w2 = w2nat;
@@ -461,8 +469,7 @@ do_file(char const *const fname)
default:
fprintf(stderr, "unrecognized ELF data encoding %d: %s\n",
ehdr->e_ident[EI_DATA], fname);
- fail_file();
- break;
+ goto out;
case ELFDATA2LSB:
if (*(unsigned char const *)&endian != 1) {
/* main() is big endian, file.o is little endian. */
@@ -490,52 +497,54 @@ do_file(char const *const fname)
push_bl_mcount_thumb = push_bl_mcount_thumb_be;
break;
} /* end switch */
- if (memcmp(ELFMAG, ehdr->e_ident, SELFMAG) != 0
- || w2(ehdr->e_type) != ET_REL
- || ehdr->e_ident[EI_VERSION] != EV_CURRENT) {
+ if (memcmp(ELFMAG, ehdr->e_ident, SELFMAG) != 0 ||
+ w2(ehdr->e_type) != ET_REL ||
+ ehdr->e_ident[EI_VERSION] != EV_CURRENT) {
fprintf(stderr, "unrecognized ET_REL file %s\n", fname);
- fail_file();
+ goto out;
}
- gpfx = 0;
+ gpfx = '_';
switch (w2(ehdr->e_machine)) {
default:
fprintf(stderr, "unrecognized e_machine %u %s\n",
w2(ehdr->e_machine), fname);
- fail_file();
- break;
+ goto out;
case EM_386:
reltype = R_386_32;
rel_type_nop = R_386_NONE;
make_nop = make_nop_x86;
ideal_nop = ideal_nop5_x86_32;
mcount_adjust_32 = -1;
+ gpfx = 0;
+ break;
+ case EM_ARM:
+ reltype = R_ARM_ABS32;
+ altmcount = "__gnu_mcount_nc";
+ make_nop = make_nop_arm;
+ rel_type_nop = R_ARM_NONE;
+ gpfx = 0;
break;
- case EM_ARM: reltype = R_ARM_ABS32;
- altmcount = "__gnu_mcount_nc";
- make_nop = make_nop_arm;
- rel_type_nop = R_ARM_NONE;
- break;
case EM_AARCH64:
- reltype = R_AARCH64_ABS64;
- make_nop = make_nop_arm64;
- rel_type_nop = R_AARCH64_NONE;
- ideal_nop = ideal_nop4_arm64;
- gpfx = '_';
- break;
- case EM_IA_64: reltype = R_IA64_IMM64; gpfx = '_'; break;
- case EM_MIPS: /* reltype: e_class */ gpfx = '_'; break;
- case EM_PPC: reltype = R_PPC_ADDR32; gpfx = '_'; break;
- case EM_PPC64: reltype = R_PPC64_ADDR64; gpfx = '_'; break;
- case EM_S390: /* reltype: e_class */ gpfx = '_'; break;
- case EM_SH: reltype = R_SH_DIR32; break;
- case EM_SPARCV9: reltype = R_SPARC_64; gpfx = '_'; break;
+ reltype = R_AARCH64_ABS64;
+ make_nop = make_nop_arm64;
+ rel_type_nop = R_AARCH64_NONE;
+ ideal_nop = ideal_nop4_arm64;
+ break;
+ case EM_IA_64: reltype = R_IA64_IMM64; break;
+ case EM_MIPS: /* reltype: e_class */ break;
+ case EM_PPC: reltype = R_PPC_ADDR32; break;
+ case EM_PPC64: reltype = R_PPC64_ADDR64; break;
+ case EM_S390: /* reltype: e_class */ break;
+ case EM_SH: reltype = R_SH_DIR32; gpfx = 0; break;
+ case EM_SPARCV9: reltype = R_SPARC_64; break;
case EM_X86_64:
make_nop = make_nop_x86;
ideal_nop = ideal_nop5_x86_64;
reltype = R_X86_64_64;
rel_type_nop = R_X86_64_NONE;
mcount_adjust_64 = -1;
+ gpfx = 0;
break;
} /* end switch */
@@ -543,20 +552,20 @@ do_file(char const *const fname)
default:
fprintf(stderr, "unrecognized ELF class %d %s\n",
ehdr->e_ident[EI_CLASS], fname);
- fail_file();
- break;
+ goto out;
case ELFCLASS32:
if (w2(ehdr->e_ehsize) != sizeof(Elf32_Ehdr)
|| w2(ehdr->e_shentsize) != sizeof(Elf32_Shdr)) {
fprintf(stderr,
"unrecognized ET_REL file: %s\n", fname);
- fail_file();
+ goto out;
}
if (w2(ehdr->e_machine) == EM_MIPS) {
reltype = R_MIPS_32;
is_fake_mcount32 = MIPS32_is_fake_mcount;
}
- do32(ehdr, fname, reltype);
+ if (do32(ehdr, fname, reltype) < 0)
+ goto out;
break;
case ELFCLASS64: {
Elf64_Ehdr *const ghdr = (Elf64_Ehdr *)ehdr;
@@ -564,7 +573,7 @@ do_file(char const *const fname)
|| w2(ghdr->e_shentsize) != sizeof(Elf64_Shdr)) {
fprintf(stderr,
"unrecognized ET_REL file: %s\n", fname);
- fail_file();
+ goto out;
}
if (w2(ghdr->e_machine) == EM_S390) {
reltype = R_390_64;
@@ -576,17 +585,20 @@ do_file(char const *const fname)
Elf64_r_info = MIPS64_r_info;
is_fake_mcount64 = MIPS64_is_fake_mcount;
}
- do64(ghdr, fname, reltype);
+ if (do64(ghdr, fname, reltype) < 0)
+ goto out;
break;
}
} /* end switch */
- write_file(fname);
- cleanup();
+ rc = write_file(fname);
+out:
+ file_append_cleanup();
+ mmap_cleanup();
+ return rc;
}
-int
-main(int argc, char *argv[])
+int main(int argc, char *argv[])
{
const char ftrace[] = "/ftrace.o";
int ftrace_size = sizeof(ftrace) - 1;
@@ -613,7 +625,6 @@ main(int argc, char *argv[])
/* Process each file in turn, allowing deep failure. */
for (i = optind; i < argc; i++) {
char *file = argv[i];
- int const sjval = setjmp(jmpenv);
int len;
/*
@@ -626,28 +637,10 @@ main(int argc, char *argv[])
strcmp(file + (len - ftrace_size), ftrace) == 0)
continue;
- switch (sjval) {
- default:
- fprintf(stderr, "internal error: %s\n", file);
- exit(1);
- break;
- case SJ_SETJMP: /* normal sequence */
- /* Avoid problems if early cleanup() */
- fd_map = -1;
- mmap_failed = 1;
- file_map = NULL;
- file_ptr = NULL;
- file_updated = 0;
- do_file(file);
- break;
- case SJ_FAIL: /* error in do_file or below */
+ if (do_file(file)) {
fprintf(stderr, "%s: failed\n", file);
++n_error;
- break;
- case SJ_SUCCEED: /* premature success */
- /* do nothing */
- break;
- } /* end switch */
+ }
}
return !!n_error;
}
diff --git a/scripts/recordmcount.h b/scripts/recordmcount.h
index 47fca2c69a73..8f0a278ce0af 100644
--- a/scripts/recordmcount.h
+++ b/scripts/recordmcount.h
@@ -174,7 +174,7 @@ static int MIPS_is_fake_mcount(Elf_Rel const *rp)
}
/* Append the new shstrtab, Elf_Shdr[], __mcount_loc and its relocations. */
-static void append_func(Elf_Ehdr *const ehdr,
+static int append_func(Elf_Ehdr *const ehdr,
Elf_Shdr *const shstr,
uint_t const *const mloc0,
uint_t const *const mlocp,
@@ -202,15 +202,20 @@ static void append_func(Elf_Ehdr *const ehdr,
new_e_shoff = t;
/* body for new shstrtab */
- ulseek(fd_map, sb.st_size, SEEK_SET);
- uwrite(fd_map, old_shstr_sh_offset + (void *)ehdr, old_shstr_sh_size);
- uwrite(fd_map, mc_name, 1 + strlen(mc_name));
+ if (ulseek(sb.st_size, SEEK_SET) < 0)
+ return -1;
+ if (uwrite(old_shstr_sh_offset + (void *)ehdr, old_shstr_sh_size) < 0)
+ return -1;
+ if (uwrite(mc_name, 1 + strlen(mc_name)) < 0)
+ return -1;
/* old(modified) Elf_Shdr table, word-byte aligned */
- ulseek(fd_map, t, SEEK_SET);
+ if (ulseek(t, SEEK_SET) < 0)
+ return -1;
t += sizeof(Elf_Shdr) * old_shnum;
- uwrite(fd_map, old_shoff + (void *)ehdr,
- sizeof(Elf_Shdr) * old_shnum);
+ if (uwrite(old_shoff + (void *)ehdr,
+ sizeof(Elf_Shdr) * old_shnum) < 0)
+ return -1;
/* new sections __mcount_loc and .rel__mcount_loc */
t += 2*sizeof(mcsec);
@@ -225,7 +230,8 @@ static void append_func(Elf_Ehdr *const ehdr,
mcsec.sh_info = 0;
mcsec.sh_addralign = _w(_size);
mcsec.sh_entsize = _w(_size);
- uwrite(fd_map, &mcsec, sizeof(mcsec));
+ if (uwrite(&mcsec, sizeof(mcsec)) < 0)
+ return -1;
mcsec.sh_name = w(old_shstr_sh_size);
mcsec.sh_type = (sizeof(Elf_Rela) == rel_entsize)
@@ -239,15 +245,22 @@ static void append_func(Elf_Ehdr *const ehdr,
mcsec.sh_info = w(old_shnum);
mcsec.sh_addralign = _w(_size);
mcsec.sh_entsize = _w(rel_entsize);
- uwrite(fd_map, &mcsec, sizeof(mcsec));
- uwrite(fd_map, mloc0, (void *)mlocp - (void *)mloc0);
- uwrite(fd_map, mrel0, (void *)mrelp - (void *)mrel0);
+ if (uwrite(&mcsec, sizeof(mcsec)) < 0)
+ return -1;
+
+ if (uwrite(mloc0, (void *)mlocp - (void *)mloc0) < 0)
+ return -1;
+ if (uwrite(mrel0, (void *)mrelp - (void *)mrel0) < 0)
+ return -1;
ehdr->e_shoff = _w(new_e_shoff);
ehdr->e_shnum = w2(2 + w2(ehdr->e_shnum)); /* {.rel,}__mcount_loc */
- ulseek(fd_map, 0, SEEK_SET);
- uwrite(fd_map, ehdr, sizeof(*ehdr));
+ if (ulseek(0, SEEK_SET) < 0)
+ return -1;
+ if (uwrite(ehdr, sizeof(*ehdr)) < 0)
+ return -1;
+ return 0;
}
static unsigned get_mcountsym(Elf_Sym const *const sym0,
@@ -351,9 +364,9 @@ static uint_t *sift_rel_mcount(uint_t *mlocp,
* that are not going to be traced. The mcount calls here will be converted
* into nops.
*/
-static void nop_mcount(Elf_Shdr const *const relhdr,
- Elf_Ehdr const *const ehdr,
- const char *const txtname)
+static int nop_mcount(Elf_Shdr const *const relhdr,
+ Elf_Ehdr const *const ehdr,
+ const char *const txtname)
{
Elf_Shdr *const shdr0 = (Elf_Shdr *)(_w(ehdr->e_shoff)
+ (void *)ehdr);
@@ -376,15 +389,18 @@ static void nop_mcount(Elf_Shdr const *const relhdr,
mcountsym = get_mcountsym(sym0, relp, str0);
if (mcountsym == Elf_r_sym(relp) && !is_fake_mcount(relp)) {
- if (make_nop)
+ if (make_nop) {
ret = make_nop((void *)ehdr, _w(shdr->sh_offset) + _w(relp->r_offset));
+ if (ret < 0)
+ return -1;
+ }
if (warn_on_notrace_sect && !once) {
printf("Section %s has mcount callers being ignored\n",
txtname);
once = 1;
/* just warn? */
if (!make_nop)
- return;
+ return 0;
}
}
@@ -396,14 +412,16 @@ static void nop_mcount(Elf_Shdr const *const relhdr,
Elf_Rel rel;
rel = *(Elf_Rel *)relp;
Elf_r_info(&rel, Elf_r_sym(relp), rel_type_nop);
- ulseek(fd_map, (void *)relp - (void *)ehdr, SEEK_SET);
- uwrite(fd_map, &rel, sizeof(rel));
+ if (ulseek((void *)relp - (void *)ehdr, SEEK_SET) < 0)
+ return -1;
+ if (uwrite(&rel, sizeof(rel)) < 0)
+ return -1;
}
relp = (Elf_Rel const *)(rel_entsize + (void *)relp);
}
+ return 0;
}
-
/*
* Find a symbol in the given section, to be used as the base for relocating
* the table of offsets of calls to mcount. A local or global symbol suffices,
@@ -414,9 +432,10 @@ static void nop_mcount(Elf_Shdr const *const relhdr,
* Num: Value Size Type Bind Vis Ndx Name
* 2: 00000000 0 SECTION LOCAL DEFAULT 1
*/
-static unsigned find_secsym_ndx(unsigned const txtndx,
+static int find_secsym_ndx(unsigned const txtndx,
char const *const txtname,
uint_t *const recvalp,
+ unsigned int *sym_index,
Elf_Shdr const *const symhdr,
Elf_Ehdr const *const ehdr)
{
@@ -438,21 +457,20 @@ static unsigned find_secsym_ndx(unsigned const txtndx,
continue;
*recvalp = _w(symp->st_value);
- return symp - sym0;
+ *sym_index = symp - sym0;
+ return 0;
}
}
fprintf(stderr, "Cannot find symbol for section %u: %s.\n",
txtndx, txtname);
- fail_file();
+ return -1;
}
-
/* Evade ISO C restriction: no declaration after statement in has_rel_mcount. */
-static char const *
-__has_rel_mcount(Elf_Shdr const *const relhdr, /* is SHT_REL or SHT_RELA */
- Elf_Shdr const *const shdr0,
- char const *const shstrtab,
- char const *const fname)
+static char const * __has_rel_mcount(Elf_Shdr const *const relhdr, /* reltype */
+ Elf_Shdr const *const shdr0,
+ char const *const shstrtab,
+ char const *const fname)
{
/* .sh_info depends on .sh_type == SHT_REL[,A] */
Elf_Shdr const *const txthdr = &shdr0[w(relhdr->sh_info)];
@@ -461,7 +479,7 @@ __has_rel_mcount(Elf_Shdr const *const relhdr, /* is SHT_REL or SHT_RELA */
if (strcmp("__mcount_loc", txtname) == 0) {
fprintf(stderr, "warning: __mcount_loc already exists: %s\n",
fname);
- succeed_file();
+ return already_has_rel_mcount;
}
if (w(txthdr->sh_type) != SHT_PROGBITS ||
!(_w(txthdr->sh_flags) & SHF_EXECINSTR))
@@ -491,6 +509,10 @@ static unsigned tot_relsize(Elf_Shdr const *const shdr0,
for (; nhdr; --nhdr, ++shdrp) {
txtname = has_rel_mcount(shdrp, shdr0, shstrtab, fname);
+ if (txtname == already_has_rel_mcount) {
+ totrelsz = 0;
+ break;
+ }
if (txtname && is_mcounted_section_name(txtname))
totrelsz += _w(shdrp->sh_size);
}
@@ -499,8 +521,8 @@ static unsigned tot_relsize(Elf_Shdr const *const shdr0,
/* Overall supervision for Elf32 ET_REL file. */
-static void
-do_func(Elf_Ehdr *const ehdr, char const *const fname, unsigned const reltype)
+static int do_func(Elf_Ehdr *const ehdr, char const *const fname,
+ unsigned const reltype)
{
Elf_Shdr *const shdr0 = (Elf_Shdr *)(_w(ehdr->e_shoff)
+ (void *)ehdr);
@@ -513,26 +535,54 @@ do_func(Elf_Ehdr *const ehdr, char const *const fname, unsigned const reltype)
unsigned k;
/* Upper bound on space: assume all relevant relocs are for mcount. */
- unsigned const totrelsz = tot_relsize(shdr0, nhdr, shstrtab, fname);
- Elf_Rel *const mrel0 = umalloc(totrelsz);
- Elf_Rel * mrelp = mrel0;
+ unsigned totrelsz;
- /* 2*sizeof(address) <= sizeof(Elf_Rel) */
- uint_t *const mloc0 = umalloc(totrelsz>>1);
- uint_t * mlocp = mloc0;
+ Elf_Rel * mrel0;
+ Elf_Rel * mrelp;
+
+ uint_t * mloc0;
+ uint_t * mlocp;
unsigned rel_entsize = 0;
unsigned symsec_sh_link = 0;
+ int result = 0;
+
+ totrelsz = tot_relsize(shdr0, nhdr, shstrtab, fname);
+ if (totrelsz == 0)
+ return 0;
+ mrel0 = umalloc(totrelsz);
+ mrelp = mrel0;
+ if (!mrel0)
+ return -1;
+
+ /* 2*sizeof(address) <= sizeof(Elf_Rel) */
+ mloc0 = umalloc(totrelsz>>1);
+ mlocp = mloc0;
+ if (!mloc0) {
+ free(mrel0);
+ return -1;
+ }
+
for (relhdr = shdr0, k = nhdr; k; --k, ++relhdr) {
char const *const txtname = has_rel_mcount(relhdr, shdr0,
shstrtab, fname);
+ if (txtname == already_has_rel_mcount) {
+ result = 0;
+ file_updated = 0;
+ goto out; /* Nothing to be done; don't append! */
+ }
if (txtname && is_mcounted_section_name(txtname)) {
+ unsigned int recsym;
uint_t recval = 0;
- unsigned const recsym = find_secsym_ndx(
- w(relhdr->sh_info), txtname, &recval,
- &shdr0[symsec_sh_link = w(relhdr->sh_link)],
- ehdr);
+
+ symsec_sh_link = w(relhdr->sh_link);
+ result = find_secsym_ndx(w(relhdr->sh_info), txtname,
+ &recval, &recsym,
+ &shdr0[symsec_sh_link],
+ ehdr);
+ if (result)
+ goto out;
rel_entsize = _w(relhdr->sh_entsize);
mlocp = sift_rel_mcount(mlocp,
@@ -543,13 +593,17 @@ do_func(Elf_Ehdr *const ehdr, char const *const fname, unsigned const reltype)
* This section is ignored by ftrace, but still
* has mcount calls. Convert them to nops now.
*/
- nop_mcount(relhdr, ehdr, txtname);
+ if (nop_mcount(relhdr, ehdr, txtname) < 0) {
+ result = -1;
+ goto out;
+ }
}
}
- if (mloc0 != mlocp) {
- append_func(ehdr, shstr, mloc0, mlocp, mrel0, mrelp,
- rel_entsize, symsec_sh_link);
- }
+ if (!result && mloc0 != mlocp)
+ result = append_func(ehdr, shstr, mloc0, mlocp, mrel0, mrelp,
+ rel_entsize, symsec_sh_link);
+out:
free(mrel0);
free(mloc0);
+ return result;
}
diff --git a/scripts/tools-support-relr.sh b/scripts/tools-support-relr.sh
new file mode 100755
index 000000000000..97a2c844a95e
--- /dev/null
+++ b/scripts/tools-support-relr.sh
@@ -0,0 +1,16 @@
+#!/bin/sh -eu
+# SPDX-License-Identifier: GPL-2.0
+
+tmp_file=$(mktemp)
+trap "rm -f $tmp_file.o $tmp_file $tmp_file.bin" EXIT
+
+cat << "END" | "$CC" -c -x c - -o $tmp_file.o >/dev/null 2>&1
+void *p = &p;
+END
+"$LD" $tmp_file.o -shared -Bsymbolic --pack-dyn-relocs=relr -o $tmp_file
+
+# Despite printing an error message, GNU nm still exits with exit code 0 if it
+# sees a relr section. So we need to check that nothing is printed to stderr.
+test -z "$("$NM" $tmp_file 2>&1 >/dev/null)"
+
+"$OBJCOPY" -O binary $tmp_file $tmp_file.bin