diff options
Diffstat (limited to 'scripts')
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 | 
