summaryrefslogtreecommitdiff
path: root/scripts
diff options
context:
space:
mode:
Diffstat (limited to 'scripts')
-rw-r--r--scripts/Kbuild.include6
-rw-r--r--scripts/Kconfig.include13
-rw-r--r--scripts/Makefile9
-rw-r--r--scripts/Makefile.build68
-rw-r--r--scripts/Makefile.clean3
-rw-r--r--scripts/Makefile.dtbinst3
-rw-r--r--scripts/Makefile.extrawarn1
-rw-r--r--scripts/Makefile.lib63
-rw-r--r--scripts/Makefile.modfinal49
-rw-r--r--scripts/Makefile.modpost25
-rw-r--r--scripts/Makefile.ubsan47
-rwxr-xr-xscripts/adjust_autoksyms.sh3
-rwxr-xr-xscripts/atomic/gen-atomic-fallback.sh63
-rwxr-xr-xscripts/atomic/gen-atomic-instrumented.sh29
-rwxr-xr-x[-rw-r--r--]scripts/atomic/gen-atomics.sh0
-rwxr-xr-xscripts/bloat-o-meter2
-rwxr-xr-xscripts/bpf_helpers_doc.py8
-rwxr-xr-xscripts/cc-version.sh82
-rwxr-xr-xscripts/checkpatch.pl594
-rwxr-xr-xscripts/clang-tools/gen_compile_commands.py14
-rwxr-xr-xscripts/clang-tools/run-clang-tools.py2
-rwxr-xr-xscripts/clang-version.sh19
-rwxr-xr-xscripts/coccicheck26
-rw-r--r--scripts/coccinelle/api/ptr_ret.cocci97
-rw-r--r--scripts/coccinelle/free/put_device.cocci1
-rw-r--r--scripts/coccinelle/misc/boolinit.cocci195
-rwxr-xr-xscripts/config3
-rwxr-xr-xscripts/depmod.sh2
-rwxr-xr-xscripts/diffconfig2
-rw-r--r--scripts/dtc/.gitignore1
-rw-r--r--scripts/dtc/Makefile9
-rw-r--r--scripts/dtc/data.c6
-rw-r--r--scripts/dtc/dtc.c4
-rw-r--r--scripts/dtc/dtc.h8
-rw-r--r--scripts/dtc/fdtdump.c163
-rw-r--r--scripts/dtc/fdtoverlay.c208
-rw-r--r--scripts/dtc/flattree.c8
l---------scripts/dtc/include-prefixes/c6x1
-rw-r--r--scripts/dtc/libfdt/fdt.c4
-rw-r--r--scripts/dtc/libfdt/fdt_ro.c20
-rw-r--r--scripts/dtc/libfdt/fdt_rw.c4
-rw-r--r--scripts/dtc/libfdt/fdt_sw.c2
-rw-r--r--scripts/dtc/libfdt/libfdt.h126
-rw-r--r--scripts/dtc/libfdt/libfdt_internal.h19
-rw-r--r--scripts/dtc/livetree.c2
-rw-r--r--scripts/dtc/srcpos.c2
-rwxr-xr-xscripts/dtc/update-dtc-source.sh3
-rw-r--r--scripts/dtc/version_gen.h2
-rw-r--r--scripts/dtc/yamltree.c6
-rwxr-xr-xscripts/dummy-tools/gcc28
-rwxr-xr-xscripts/gcc-plugin.sh19
-rw-r--r--scripts/gcc-plugins/Kconfig2
-rw-r--r--scripts/gcc-plugins/Makefile5
-rw-r--r--scripts/gcc-plugins/gcc-common.h407
-rw-r--r--scripts/gcc-plugins/gcc-generate-gimple-pass.h12
-rw-r--r--scripts/gcc-plugins/gcc-generate-ipa-pass.h23
-rw-r--r--scripts/gcc-plugins/gcc-generate-rtl-pass.h17
-rw-r--r--scripts/gcc-plugins/gcc-generate-simple_ipa-pass.h17
-rw-r--r--scripts/gcc-plugins/latent_entropy_plugin.c14
-rw-r--r--scripts/gcc-plugins/randomize_layout_plugin.c4
-rw-r--r--scripts/gcc-plugins/sancov_plugin.c6
-rw-r--r--scripts/gcc-plugins/stackleak_plugin.c4
-rw-r--r--scripts/gcc-plugins/structleak_plugin.c7
-rwxr-xr-xscripts/gcc-version.sh20
-rw-r--r--scripts/gdb/linux/Makefile4
-rw-r--r--scripts/gdb/linux/lists.py5
-rwxr-xr-xscripts/gen_autoksyms.sh38
-rwxr-xr-xscripts/generate_initcall_order.pl270
-rw-r--r--scripts/genksyms/genksyms.c2
-rw-r--r--scripts/genksyms/genksyms.h2
-rw-r--r--scripts/genksyms/keywords.c3
-rw-r--r--scripts/genksyms/lex.l69
-rw-r--r--scripts/genksyms/parse.y7
-rwxr-xr-xscripts/get_abi.pl2
-rwxr-xr-xscripts/get_feat.pl630
-rwxr-xr-xscripts/jobserver-exec2
-rw-r--r--scripts/kallsyms.c6
-rw-r--r--scripts/kconfig/Makefile46
-rw-r--r--scripts/kconfig/conf.c77
-rw-r--r--scripts/kconfig/confdata.c1
-rw-r--r--scripts/kconfig/lexer.l1
-rw-r--r--scripts/kconfig/lkc.h4
-rwxr-xr-xscripts/kconfig/mconf-cfg.sh4
-rw-r--r--scripts/kconfig/preprocess.c2
-rwxr-xr-xscripts/kconfig/qconf-cfg.sh14
-rw-r--r--scripts/kconfig/qconf.cc141
-rw-r--r--scripts/kconfig/symbol.c2
-rwxr-xr-xscripts/kernel-doc69
-rwxr-xr-xscripts/ld-version.sh88
-rwxr-xr-xscripts/link-vmlinux.sh98
-rwxr-xr-xscripts/lld-version.sh20
-rw-r--r--scripts/mod/Makefile1
-rw-r--r--scripts/mod/devicetable-offsets.c15
-rw-r--r--scripts/mod/file2alias.c44
-rw-r--r--scripts/mod/modpost.c137
-rw-r--r--scripts/mod/modpost.h27
-rw-r--r--scripts/mod/sumversion.c6
-rw-r--r--scripts/module.lds.S30
-rw-r--r--scripts/nsdeps4
-rw-r--r--scripts/recordmcount.c2
-rwxr-xr-xscripts/recordmcount.pl9
-rwxr-xr-xscripts/show_delta2
-rwxr-xr-xscripts/spdxcheck.py2
-rw-r--r--scripts/spelling.txt30
-rwxr-xr-xscripts/sphinx-pre-install6
-rwxr-xr-xscripts/split-man.pl2
-rwxr-xr-xscripts/syscallhdr.sh98
-rwxr-xr-xscripts/syscalltbl.sh73
-rwxr-xr-xscripts/test_dwarf5_support.sh8
-rwxr-xr-xscripts/tracing/draw_functrace.py2
-rwxr-xr-xscripts/ver_linux12
111 files changed, 2939 insertions, 1790 deletions
diff --git a/scripts/Kbuild.include b/scripts/Kbuild.include
index 08e011175b4c..509e0856d653 100644
--- a/scripts/Kbuild.include
+++ b/scripts/Kbuild.include
@@ -141,13 +141,9 @@ cc-ifversion = $(shell [ $(CONFIG_GCC_VERSION)0 $(1) $(2)000 ] && echo $(3) || e
# Usage: KBUILD_LDFLAGS += $(call ld-option, -X, -Y)
ld-option = $(call try-run, $(LD) $(KBUILD_LDFLAGS) $(1) -v,$(1),$(2),$(3))
-# ld-version
-# Note this is mainly for HJ Lu's 3 number binutil versions
-ld-version = $(shell $(LD) --version | $(srctree)/scripts/ld-version.sh)
-
# ld-ifversion
# Usage: $(call ld-ifversion, -ge, 22252, y)
-ld-ifversion = $(shell [ $(ld-version) $(1) $(2) ] && echo $(3) || echo $(4))
+ld-ifversion = $(shell [ $(CONFIG_LD_VERSION)0 $(1) $(2)0 ] && echo $(3) || echo $(4))
######
diff --git a/scripts/Kconfig.include b/scripts/Kconfig.include
index a5fe72c504ff..58fdb5308725 100644
--- a/scripts/Kconfig.include
+++ b/scripts/Kconfig.include
@@ -39,8 +39,17 @@ as-instr = $(success,printf "%b\n" "$(1)" | $(CC) $(CLANG_FLAGS) -c -x assembler
$(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)
+# Get the compiler name, version, and error out if it is not supported.
+cc-info := $(shell,$(srctree)/scripts/cc-version.sh $(CC))
+$(error-if,$(success,test -z "$(cc-info)"),Sorry$(comma) this compiler is not supported.)
+cc-name := $(shell,set -- $(cc-info) && echo $1)
+cc-version := $(shell,set -- $(cc-info) && echo $2)
+
+# Get the linker name, version, and error out if it is not supported.
+ld-info := $(shell,$(srctree)/scripts/ld-version.sh $(LD))
+$(error-if,$(success,test -z "$(ld-info)"),Sorry$(comma) this linker is not supported.)
+ld-name := $(shell,set -- $(ld-info) && echo $1)
+ld-version := $(shell,set -- $(ld-info) && echo $2)
# machine bit flags
# $(m32-flag): -m32 if the compiler supports it, or an empty string otherwise.
diff --git a/scripts/Makefile b/scripts/Makefile
index b5418ec587fb..c36106bce80e 100644
--- a/scripts/Makefile
+++ b/scripts/Makefile
@@ -3,6 +3,9 @@
# scripts contains sources for various helper programs used throughout
# the kernel for the build process.
+CRYPTO_LIBS = $(shell pkg-config --libs libcrypto 2> /dev/null || echo -lcrypto)
+CRYPTO_CFLAGS = $(shell pkg-config --cflags libcrypto 2> /dev/null)
+
hostprogs-always-$(CONFIG_BUILD_BIN2C) += bin2c
hostprogs-always-$(CONFIG_KALLSYMS) += kallsyms
hostprogs-always-$(BUILD_C_RECORDMCOUNT) += recordmcount
@@ -14,8 +17,10 @@ hostprogs-always-$(CONFIG_SYSTEM_EXTRA_CERTIFICATE) += insert-sys-cert
HOSTCFLAGS_sorttable.o = -I$(srctree)/tools/include
HOSTCFLAGS_asn1_compiler.o = -I$(srctree)/include
-HOSTLDLIBS_sign-file = -lcrypto
-HOSTLDLIBS_extract-cert = -lcrypto
+HOSTCFLAGS_sign-file.o = $(CRYPTO_CFLAGS)
+HOSTLDLIBS_sign-file = $(CRYPTO_LIBS)
+HOSTCFLAGS_extract-cert.o = $(CRYPTO_CFLAGS)
+HOSTLDLIBS_extract-cert = $(CRYPTO_LIBS)
ifdef CONFIG_UNWINDER_ORC
ifeq ($(ARCH),x86_64)
diff --git a/scripts/Makefile.build b/scripts/Makefile.build
index 4c058f12dd73..1b6094a13034 100644
--- a/scripts/Makefile.build
+++ b/scripts/Makefile.build
@@ -15,7 +15,6 @@ obj-y :=
obj-m :=
lib-y :=
lib-m :=
-always :=
always-y :=
always-m :=
targets :=
@@ -111,7 +110,7 @@ endif
# ---------------------------------------------------------------------------
quiet_cmd_cc_s_c = CC $(quiet_modtag) $@
- cmd_cc_s_c = $(CC) $(filter-out $(DEBUG_CFLAGS), $(c_flags)) -fverbose-asm -S -o $@ $<
+ cmd_cc_s_c = $(CC) $(filter-out $(DEBUG_CFLAGS) $(CC_FLAGS_LTO), $(c_flags)) -fverbose-asm -S -o $@ $<
$(obj)/%.s: $(src)/%.c FORCE
$(call if_changed_dep,cc_s_c)
@@ -166,6 +165,15 @@ ifdef CONFIG_MODVERSIONS
# the actual value of the checksum generated by genksyms
# o remove .tmp_<file>.o to <file>.o
+ifdef CONFIG_LTO_CLANG
+# Generate .o.symversions files for each .o with exported symbols, and link these
+# to the kernel and/or modules at the end.
+cmd_modversions_c = \
+ if $(NM) $@ 2>/dev/null | grep -q __ksymtab; then \
+ $(call cmd_gensymtypes_c,$(KBUILD_SYMTYPES),$(@:.o=.symtypes)) \
+ > $@.symversions; \
+ fi;
+else
cmd_modversions_c = \
if $(OBJDUMP) -h $@ | grep -q __ksymtab; then \
$(call cmd_gensymtypes_c,$(KBUILD_SYMTYPES),$(@:.o=.symtypes)) \
@@ -177,9 +185,9 @@ cmd_modversions_c = \
rm -f $(@D)/.tmp_$(@F:.o=.ver); \
fi
endif
+endif
-ifdef CONFIG_FTRACE_MCOUNT_RECORD
-ifndef CC_USING_RECORD_MCOUNT
+ifdef CONFIG_FTRACE_MCOUNT_USE_RECORDMCOUNT
# compiler will not generate __mcount_loc use recordmcount or recordmcount.pl
ifdef BUILD_C_RECORDMCOUNT
ifeq ("$(origin RECORDMCOUNT_WARN)", "command line")
@@ -206,31 +214,14 @@ recordmcount_source := $(srctree)/scripts/recordmcount.pl
endif # BUILD_C_RECORDMCOUNT
cmd_record_mcount = $(if $(findstring $(strip $(CC_FLAGS_FTRACE)),$(_c_flags)), \
$(sub_cmd_record_mcount))
-endif # CC_USING_RECORD_MCOUNT
-endif # CONFIG_FTRACE_MCOUNT_RECORD
+endif # CONFIG_FTRACE_MCOUNT_USE_RECORDMCOUNT
ifdef CONFIG_STACK_VALIDATION
+ifndef CONFIG_LTO_CLANG
ifneq ($(SKIP_STACK_VALIDATION),1)
__objtool_obj := $(objtree)/tools/objtool/objtool
-objtool_args = $(if $(CONFIG_UNWINDER_ORC),orc generate,check)
-
-objtool_args += $(if $(part-of-module), --module,)
-
-ifndef CONFIG_FRAME_POINTER
-objtool_args += --no-fp
-endif
-ifdef CONFIG_GCOV_KERNEL
-objtool_args += --no-unreachable
-endif
-ifdef CONFIG_RETPOLINE
- objtool_args += --retpoline
-endif
-ifdef CONFIG_X86_SMAP
- objtool_args += --uaccess
-endif
-
# 'OBJECT_FILES_NON_STANDARD := y': skip objtool checking for a directory
# 'OBJECT_FILES_NON_STANDARD_foo.o := 'y': skip objtool checking for a file
# 'OBJECT_FILES_NON_STANDARD_foo.o := 'n': override directory skip for a file
@@ -242,6 +233,7 @@ objtool_obj = $(if $(patsubst y%,, \
$(__objtool_obj))
endif # SKIP_STACK_VALIDATION
+endif # CONFIG_LTO_CLANG
endif # CONFIG_STACK_VALIDATION
# Rebuild all objects when objtool changes, or is enabled/disabled.
@@ -388,6 +380,18 @@ $(obj)/%.asn1.c $(obj)/%.asn1.h: $(src)/%.asn1 $(objtree)/scripts/asn1_compiler
$(subdir-builtin): $(obj)/%/built-in.a: $(obj)/% ;
$(subdir-modorder): $(obj)/%/modules.order: $(obj)/% ;
+# combine symversions for later processing
+quiet_cmd_update_lto_symversions = SYMVER $@
+ifeq ($(CONFIG_LTO_CLANG) $(CONFIG_MODVERSIONS),y y)
+ cmd_update_lto_symversions = \
+ rm -f $@.symversions \
+ $(foreach n, $(filter-out FORCE,$^), \
+ $(if $(wildcard $(n).symversions), \
+ ; cat $(n).symversions >> $@.symversions))
+else
+ cmd_update_lto_symversions = echo >/dev/null
+endif
+
#
# Rule to compile a set of .o files into one .a file (without symbol table)
#
@@ -395,8 +399,11 @@ $(subdir-modorder): $(obj)/%/modules.order: $(obj)/% ;
quiet_cmd_ar_builtin = AR $@
cmd_ar_builtin = rm -f $@; $(AR) cDPrST $@ $(real-prereqs)
+quiet_cmd_ar_and_symver = AR $@
+ cmd_ar_and_symver = $(cmd_update_lto_symversions); $(cmd_ar_builtin)
+
$(obj)/built-in.a: $(real-obj-y) FORCE
- $(call if_changed,ar_builtin)
+ $(call if_changed,ar_and_symver)
#
# Rule to create modules.order file
@@ -416,15 +423,26 @@ $(obj)/modules.order: $(obj-m) FORCE
#
# Rule to compile a set of .o files into one .a file (with symbol table)
#
+quiet_cmd_ar_lib = AR $@
+ cmd_ar_lib = $(cmd_update_lto_symversions); $(cmd_ar)
+
$(obj)/lib.a: $(lib-y) FORCE
- $(call if_changed,ar)
+ $(call if_changed,ar_lib)
# NOTE:
# Do not replace $(filter %.o,^) with $(real-prereqs). When a single object
# module is turned into a multi object module, $^ will contain header file
# dependencies recorded in the .*.cmd file.
+ifdef CONFIG_LTO_CLANG
+quiet_cmd_link_multi-m = AR [M] $@
+cmd_link_multi-m = \
+ $(cmd_update_lto_symversions); \
+ rm -f $@; \
+ $(AR) cDPrsT $@ $(filter %.o,$^)
+else
quiet_cmd_link_multi-m = LD [M] $@
cmd_link_multi-m = $(LD) $(ld_flags) -r -o $@ $(filter %.o,$^)
+endif
$(multi-used-m): FORCE
$(call if_changed,link_multi-m)
diff --git a/scripts/Makefile.clean b/scripts/Makefile.clean
index d9e0ceace6a6..22a8172bce1f 100644
--- a/scripts/Makefile.clean
+++ b/scripts/Makefile.clean
@@ -34,9 +34,6 @@ __clean-files := \
$(hostprogs-always-y) $(hostprogs-always-m) $(hostprogs-always-) \
$(userprogs-always-y) $(userprogs-always-m) $(userprogs-always-)
-# deprecated
-__clean-files += $(always) $(hostprogs-y) $(hostprogs-m) $(hostprogs-)
-
__clean-files := $(filter-out $(no-clean-files), $(__clean-files))
# clean-files is given relative to the current directory, unless it
diff --git a/scripts/Makefile.dtbinst b/scripts/Makefile.dtbinst
index 50d580d77ae9..ba01f5ba2517 100644
--- a/scripts/Makefile.dtbinst
+++ b/scripts/Makefile.dtbinst
@@ -29,6 +29,9 @@ quiet_cmd_dtb_install = INSTALL $@
$(dst)/%.dtb: $(obj)/%.dtb
$(call cmd,dtb_install)
+$(dst)/%.dtbo: $(obj)/%.dtbo
+ $(call cmd,dtb_install)
+
PHONY += $(subdirs)
$(subdirs):
$(Q)$(MAKE) $(dtbinst)=$@ dst=$(patsubst $(obj)/%,$(dst)/%,$@)
diff --git a/scripts/Makefile.extrawarn b/scripts/Makefile.extrawarn
index 6baee1200615..d53825503874 100644
--- a/scripts/Makefile.extrawarn
+++ b/scripts/Makefile.extrawarn
@@ -61,7 +61,6 @@ endif
ifneq ($(findstring 2, $(KBUILD_EXTRA_WARN)),)
KBUILD_CFLAGS += -Wdisabled-optimization
-KBUILD_CFLAGS += -Wnested-externs
KBUILD_CFLAGS += -Wshadow
KBUILD_CFLAGS += $(call cc-option, -Wlogical-op)
KBUILD_CFLAGS += -Wmissing-field-initializers
diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib
index 94133708889d..8cd67b1b6d15 100644
--- a/scripts/Makefile.lib
+++ b/scripts/Makefile.lib
@@ -4,18 +4,6 @@ asflags-y += $(EXTRA_AFLAGS)
ccflags-y += $(EXTRA_CFLAGS)
cppflags-y += $(EXTRA_CPPFLAGS)
ldflags-y += $(EXTRA_LDFLAGS)
-ifneq ($(always),)
-$(warning 'always' is deprecated. Please use 'always-y' instead)
-always-y += $(always)
-endif
-ifneq ($(hostprogs-y),)
-$(warning 'hostprogs-y' is deprecated. Please use 'hostprogs' instead)
-hostprogs += $(hostprogs-y)
-endif
-ifneq ($(hostprogs-m),)
-$(warning 'hostprogs-m' is deprecated. Please use 'hostprogs' instead)
-hostprogs += $(hostprogs-m)
-endif
# flags that take effect in current and sub directories
KBUILD_AFLAGS += $(subdir-asflags-y)
@@ -56,15 +44,19 @@ else
obj-y := $(filter-out %/, $(obj-y))
endif
+# Expand $(foo-objs) $(foo-y) by calling $(call suffix-search,foo.o,-objs -y)
+suffix-search = $(foreach s,$(2),$($(1:.o=$s)))
# 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-search = $(sort $(foreach m,$(1), $(if $(strip $(call suffix-search,$(m),$(2) -)), $(m))))
+multi-used-y := $(call multi-search,$(obj-y),-objs -y)
+multi-used-m := $(call multi-search,$(obj-m),-objs -y -m)
multi-used := $(multi-used-y) $(multi-used-m)
# 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=-))),$($(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)))
+real-search = $(foreach m,$(1), $(if $(strip $(call suffix-search,$(m),$(2) -)),$(call suffix-search,$(m),$(2)),$(m)))
+real-obj-y := $(call real-search, $(obj-y),-objs -y)
+real-obj-m := $(call real-search, $(obj-m),-objs -y -m)
always-y += $(always-m)
@@ -81,12 +73,14 @@ always-y += $(userprogs-always-y) $(userprogs-always-m)
# DTB
# If CONFIG_OF_ALL_DTBS is enabled, all DT blobs are built
-extra-y += $(dtb-y)
-extra-$(CONFIG_OF_ALL_DTBS) += $(dtb-)
+always-y += $(dtb-y)
+always-$(CONFIG_OF_ALL_DTBS) += $(dtb-)
ifneq ($(CHECK_DTBS),)
-extra-y += $(patsubst %.dtb,%.dt.yaml, $(dtb-y))
-extra-$(CONFIG_OF_ALL_DTBS) += $(patsubst %.dtb,%.dt.yaml, $(dtb-))
+always-y += $(patsubst %.dtb,%.dt.yaml, $(dtb-y))
+always-y += $(patsubst %.dtbo,%.dt.yaml, $(dtb-y))
+always-$(CONFIG_OF_ALL_DTBS) += $(patsubst %.dtb,%.dt.yaml, $(dtb-))
+always-$(CONFIG_OF_ALL_DTBS) += $(patsubst %.dtbo,%.dt.yaml, $(dtb-))
endif
# Add subdir path
@@ -117,9 +111,11 @@ 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)
-name-fix = $(call stringify,$(subst $(comma),_,$(subst -,_,$1)))
+name-fix-token = $(subst $(comma),_,$(subst -,_,$1))
+name-fix = $(call stringify,$(call name-fix-token,$1))
basename_flags = -DKBUILD_BASENAME=$(call name-fix,$(basetarget))
-modname_flags = -DKBUILD_MODNAME=$(call name-fix,$(modname))
+modname_flags = -DKBUILD_MODNAME=$(call name-fix,$(modname)) \
+ -D__KBUILD_MODNAME=kmod_$(call name-fix-token,$(modname))
modfile_flags = -DKBUILD_MODFILE=$(call stringify,$(modfile))
_c_flags = $(filter-out $(CFLAGS_REMOVE_$(target-stem).o), \
@@ -148,10 +144,12 @@ endif
# we don't want to check (depends on variables KASAN_SANITIZE_obj.o, KASAN_SANITIZE)
#
ifeq ($(CONFIG_KASAN),y)
+ifneq ($(CONFIG_KASAN_HW_TAGS),y)
_c_flags += $(if $(patsubst n%,, \
$(KASAN_SANITIZE_$(basetarget).o)$(KASAN_SANITIZE)y), \
$(CFLAGS_KASAN), $(CFLAGS_KASAN_NOSANITIZE))
endif
+endif
ifeq ($(CONFIG_UBSAN),y)
_c_flags += $(if $(patsubst n%,, \
@@ -216,6 +214,18 @@ dtc_cpp_flags = -Wp,-MMD,$(depfile).pre.tmp -nostdinc \
$(addprefix -I,$(DTC_INCLUDE)) \
-undef -D__DTS__
+# Objtool arguments are also needed for modfinal with LTO, so we define
+# then here to avoid duplication.
+objtool_args = \
+ $(if $(CONFIG_UNWINDER_ORC),orc generate,check) \
+ $(if $(part-of-module), --module,) \
+ $(if $(CONFIG_FRAME_POINTER),, --no-fp) \
+ $(if $(or $(CONFIG_GCOV_KERNEL),$(CONFIG_LTO_CLANG)), \
+ --no-unreachable,) \
+ $(if $(CONFIG_RETPOLINE), --retpoline,) \
+ $(if $(CONFIG_X86_SMAP), --uaccess,) \
+ $(if $(CONFIG_FTRACE_MCOUNT_USE_OBJTOOL), --mcount,)
+
# Useful for describing the dependency of composite objects
# Usage:
# $(call multi_depend, multi_used_targets, suffix_to_remove, suffix_to_add)
@@ -245,7 +255,7 @@ $(obj)/%: $(src)/%_shipped
# target: source(s) FORCE
# $(if_changed,ld/objcopy/gzip)
#
-# and add target to extra-y so that we know we have to
+# and add target to 'targets' so that we know we have to
# read in the saved command line
# Linking
@@ -317,7 +327,7 @@ $(obj)/%.dtb.S: $(obj)/%.dtb FORCE
quiet_cmd_dtc = DTC $@
cmd_dtc = $(HOSTCC) -E $(dtc_cpp_flags) -x assembler-with-cpp -o $(dtc-tmp) $< ; \
- $(DTC) -O $(patsubst .%,%,$(suffix $@)) -o $@ -b 0 \
+ $(DTC) -o $@ -b 0 \
$(addprefix -i,$(dir $<) $(DTC_INCLUDE)) $(DTC_FLAGS) \
-d $(depfile).dtc.tmp $(dtc-tmp) ; \
cat $(depfile).pre.tmp $(depfile).dtc.tmp > $(depfile)
@@ -325,6 +335,9 @@ cmd_dtc = $(HOSTCC) -E $(dtc_cpp_flags) -x assembler-with-cpp -o $(dtc-tmp) $< ;
$(obj)/%.dtb: $(src)/%.dts $(DTC) FORCE
$(call if_changed_dep,dtc)
+$(obj)/%.dtbo: $(src)/%.dts $(DTC) FORCE
+ $(call if_changed_dep,dtc)
+
DT_CHECKER ?= dt-validate
DT_BINDING_DIR := Documentation/devicetree/bindings
# DT_TMP_SCHEMA may be overridden from Documentation/devicetree/bindings/Makefile
@@ -339,7 +352,7 @@ define rule_dtc
endef
$(obj)/%.dt.yaml: $(src)/%.dts $(DTC) $(DT_TMP_SCHEMA) FORCE
- $(call if_changed_rule,dtc,yaml)
+ $(call if_changed_rule,dtc)
dtc-tmp = $(subst $(comma),_,$(dot-target).dts.tmp)
diff --git a/scripts/Makefile.modfinal b/scripts/Makefile.modfinal
index ae01baf96f4e..735e11e9041b 100644
--- a/scripts/Makefile.modfinal
+++ b/scripts/Makefile.modfinal
@@ -6,9 +6,10 @@
PHONY := __modfinal
__modfinal:
+include include/config/auto.conf
include $(srctree)/scripts/Kbuild.include
-# for c_flags
+# for c_flags and objtool_args
include $(srctree)/scripts/Makefile.lib
# find all modules listed in modules.order
@@ -29,15 +30,55 @@ quiet_cmd_cc_o_c = CC [M] $@
ARCH_POSTLINK := $(wildcard $(srctree)/arch/$(SRCARCH)/Makefile.postlink)
+ifdef CONFIG_LTO_CLANG
+# With CONFIG_LTO_CLANG, reuse the object file we compiled for modpost to
+# avoid a second slow LTO link
+prelink-ext := .lto
+
+# ELF processing was skipped earlier because we didn't have native code,
+# so let's now process the prelinked binary before we link the module.
+
+ifdef CONFIG_STACK_VALIDATION
+ifneq ($(SKIP_STACK_VALIDATION),1)
+cmd_ld_ko_o += \
+ $(objtree)/tools/objtool/objtool $(objtool_args) \
+ $(@:.ko=$(prelink-ext).o);
+
+endif # SKIP_STACK_VALIDATION
+endif # CONFIG_STACK_VALIDATION
+
+endif # CONFIG_LTO_CLANG
+
quiet_cmd_ld_ko_o = LD [M] $@
- cmd_ld_ko_o = \
+ cmd_ld_ko_o += \
$(LD) -r $(KBUILD_LDFLAGS) \
$(KBUILD_LDFLAGS_MODULE) $(LDFLAGS_MODULE) \
-T scripts/module.lds -o $@ $(filter %.o, $^); \
$(if $(ARCH_POSTLINK), $(MAKE) -f $(ARCH_POSTLINK) $@, true)
-$(modules): %.ko: %.o %.mod.o scripts/module.lds FORCE
- +$(call if_changed,ld_ko_o)
+quiet_cmd_btf_ko = BTF [M] $@
+ cmd_btf_ko = \
+ if [ -f vmlinux ]; then \
+ LLVM_OBJCOPY=$(OBJCOPY) $(PAHOLE) -J --btf_base vmlinux $@; \
+ else \
+ printf "Skipping BTF generation for %s due to unavailability of vmlinux\n" $@ 1>&2; \
+ fi;
+
+# Same as newer-prereqs, but allows to exclude specified extra dependencies
+newer_prereqs_except = $(filter-out $(PHONY) $(1),$?)
+
+# Same as if_changed, but allows to exclude specified extra dependencies
+if_changed_except = $(if $(call newer_prereqs_except,$(2))$(cmd-check), \
+ $(cmd); \
+ printf '%s\n' 'cmd_$@ := $(make-cmd)' > $(dot-target).cmd, @:)
+
+
+# Re-generate module BTFs if either module's .ko or vmlinux changed
+$(modules): %.ko: %$(prelink-ext).o %.mod.o scripts/module.lds $(if $(KBUILD_BUILTIN),vmlinux) FORCE
+ +$(call if_changed_except,ld_ko_o,vmlinux)
+ifdef CONFIG_DEBUG_INFO_BTF_MODULES
+ +$(if $(newer-prereqs),$(call cmd,btf_ko))
+endif
targets += $(modules) $(modules:.ko=.mod.o)
diff --git a/scripts/Makefile.modpost b/scripts/Makefile.modpost
index f54b6ac37ac2..066beffca09a 100644
--- a/scripts/Makefile.modpost
+++ b/scripts/Makefile.modpost
@@ -43,6 +43,9 @@ __modpost:
include include/config/auto.conf
include scripts/Kbuild.include
+# for ld_flags
+include scripts/Makefile.lib
+
MODPOST = scripts/mod/modpost \
$(if $(CONFIG_MODVERSIONS),-m) \
$(if $(CONFIG_MODULE_SRCVERSION_ALL),-a) \
@@ -102,12 +105,30 @@ $(input-symdump):
@echo >&2 'WARNING: Symbol version dump "$@" is missing.'
@echo >&2 ' Modules may not have dependencies or modversions.'
+ifdef CONFIG_LTO_CLANG
+# With CONFIG_LTO_CLANG, .o files might be LLVM bitcode, so we need to run
+# LTO to compile them into native code before running modpost
+prelink-ext := .lto
+
+quiet_cmd_cc_lto_link_modules = LTO [M] $@
+cmd_cc_lto_link_modules = \
+ $(LD) $(ld_flags) -r -o $@ \
+ $(shell [ -s $(@:.lto.o=.o.symversions) ] && \
+ echo -T $(@:.lto.o=.o.symversions)) \
+ --whole-archive $^
+
+%.lto.o: %.o
+ $(call if_changed,cc_lto_link_modules)
+endif
+
+modules := $(sort $(shell cat $(MODORDER)))
+
# Read out modules.order to pass in modpost.
# Otherwise, allmodconfig would fail with "Argument list too long".
quiet_cmd_modpost = MODPOST $@
- cmd_modpost = sed 's/ko$$/o/' $< | $(MODPOST) -T -
+ cmd_modpost = sed 's/\.ko$$/$(prelink-ext)\.o/' $< | $(MODPOST) -T -
-$(output-symdump): $(MODORDER) $(input-symdump) FORCE
+$(output-symdump): $(MODORDER) $(input-symdump) $(modules:.ko=$(prelink-ext).o) FORCE
$(call if_changed,modpost)
targets += $(output-symdump)
diff --git a/scripts/Makefile.ubsan b/scripts/Makefile.ubsan
index 9716dab06bc7..9e2092fd5206 100644
--- a/scripts/Makefile.ubsan
+++ b/scripts/Makefile.ubsan
@@ -1,37 +1,16 @@
# SPDX-License-Identifier: GPL-2.0
-export CFLAGS_UBSAN :=
+# Enable available and selected UBSAN features.
+ubsan-cflags-$(CONFIG_UBSAN_ALIGNMENT) += -fsanitize=alignment
+ubsan-cflags-$(CONFIG_UBSAN_ONLY_BOUNDS) += -fsanitize=bounds
+ubsan-cflags-$(CONFIG_UBSAN_ARRAY_BOUNDS) += -fsanitize=array-bounds
+ubsan-cflags-$(CONFIG_UBSAN_LOCAL_BOUNDS) += -fsanitize=local-bounds
+ubsan-cflags-$(CONFIG_UBSAN_SHIFT) += -fsanitize=shift
+ubsan-cflags-$(CONFIG_UBSAN_DIV_ZERO) += -fsanitize=integer-divide-by-zero
+ubsan-cflags-$(CONFIG_UBSAN_UNREACHABLE) += -fsanitize=unreachable
+ubsan-cflags-$(CONFIG_UBSAN_OBJECT_SIZE) += -fsanitize=object-size
+ubsan-cflags-$(CONFIG_UBSAN_BOOL) += -fsanitize=bool
+ubsan-cflags-$(CONFIG_UBSAN_ENUM) += -fsanitize=enum
+ubsan-cflags-$(CONFIG_UBSAN_TRAP) += -fsanitize-undefined-trap-on-error
-ifdef CONFIG_UBSAN_ALIGNMENT
- CFLAGS_UBSAN += $(call cc-option, -fsanitize=alignment)
-endif
-
-ifdef CONFIG_UBSAN_BOUNDS
- ifdef CONFIG_CC_IS_CLANG
- CFLAGS_UBSAN += -fsanitize=array-bounds
- else
- CFLAGS_UBSAN += $(call cc-option, -fsanitize=bounds)
- endif
-endif
-
-ifdef CONFIG_UBSAN_LOCAL_BOUNDS
- CFLAGS_UBSAN += -fsanitize=local-bounds
-endif
-
-ifdef CONFIG_UBSAN_MISC
- CFLAGS_UBSAN += $(call cc-option, -fsanitize=shift)
- CFLAGS_UBSAN += $(call cc-option, -fsanitize=integer-divide-by-zero)
- CFLAGS_UBSAN += $(call cc-option, -fsanitize=unreachable)
- CFLAGS_UBSAN += $(call cc-option, -fsanitize=signed-integer-overflow)
- CFLAGS_UBSAN += $(call cc-option, -fsanitize=object-size)
- CFLAGS_UBSAN += $(call cc-option, -fsanitize=bool)
- CFLAGS_UBSAN += $(call cc-option, -fsanitize=enum)
-endif
-
-ifdef CONFIG_UBSAN_TRAP
- CFLAGS_UBSAN += $(call cc-option, -fsanitize-undefined-trap-on-error)
-endif
-
- # -fsanitize=* options makes GCC less smart than usual and
- # increase number of 'maybe-uninitialized false-positives
- CFLAGS_UBSAN += $(call cc-option, -Wno-maybe-uninitialized)
+export CFLAGS_UBSAN := $(ubsan-cflags-y)
diff --git a/scripts/adjust_autoksyms.sh b/scripts/adjust_autoksyms.sh
index 2b366d945ccb..d8f6f9c63043 100755
--- a/scripts/adjust_autoksyms.sh
+++ b/scripts/adjust_autoksyms.sh
@@ -34,9 +34,6 @@ case "$KBUILD_VERBOSE" in
;;
esac
-# We need access to CONFIG_ symbols
-. include/config/auto.conf
-
# Generate a new symbol list file
$CONFIG_SHELL $srctree/scripts/gen_autoksyms.sh "$new_ksyms_file"
diff --git a/scripts/atomic/gen-atomic-fallback.sh b/scripts/atomic/gen-atomic-fallback.sh
index 693dfa1de430..317a6cec76e1 100755
--- a/scripts/atomic/gen-atomic-fallback.sh
+++ b/scripts/atomic/gen-atomic-fallback.sh
@@ -144,15 +144,11 @@ gen_proto_order_variants()
printf "#endif /* ${basename}_relaxed */\n\n"
}
-gen_xchg_fallbacks()
+gen_order_fallbacks()
{
local xchg="$1"; shift
+
cat <<EOF
-#ifndef ${xchg}_relaxed
-#define ${xchg}_relaxed ${xchg}
-#define ${xchg}_acquire ${xchg}
-#define ${xchg}_release ${xchg}
-#else /* ${xchg}_relaxed */
#ifndef ${xchg}_acquire
#define ${xchg}_acquire(...) \\
@@ -169,11 +165,62 @@ cat <<EOF
__atomic_op_fence(${xchg}, __VA_ARGS__)
#endif
-#endif /* ${xchg}_relaxed */
+EOF
+}
+
+gen_xchg_fallbacks()
+{
+ local xchg="$1"; shift
+ printf "#ifndef ${xchg}_relaxed\n"
+
+ gen_basic_fallbacks ${xchg}
+
+ printf "#else /* ${xchg}_relaxed */\n"
+
+ gen_order_fallbacks ${xchg}
+
+ printf "#endif /* ${xchg}_relaxed */\n\n"
+}
+
+gen_try_cmpxchg_fallback()
+{
+ local order="$1"; shift;
+
+cat <<EOF
+#ifndef ${ARCH}try_cmpxchg${order}
+#define ${ARCH}try_cmpxchg${order}(_ptr, _oldp, _new) \\
+({ \\
+ typeof(*(_ptr)) *___op = (_oldp), ___o = *___op, ___r; \\
+ ___r = ${ARCH}cmpxchg${order}((_ptr), ___o, (_new)); \\
+ if (unlikely(___r != ___o)) \\
+ *___op = ___r; \\
+ likely(___r == ___o); \\
+})
+#endif /* ${ARCH}try_cmpxchg${order} */
EOF
}
+gen_try_cmpxchg_fallbacks()
+{
+ printf "#ifndef ${ARCH}try_cmpxchg_relaxed\n"
+ printf "#ifdef ${ARCH}try_cmpxchg\n"
+
+ gen_basic_fallbacks "${ARCH}try_cmpxchg"
+
+ printf "#endif /* ${ARCH}try_cmpxchg */\n\n"
+
+ for order in "" "_acquire" "_release" "_relaxed"; do
+ gen_try_cmpxchg_fallback "${order}"
+ done
+
+ printf "#else /* ${ARCH}try_cmpxchg_relaxed */\n"
+
+ gen_order_fallbacks "${ARCH}try_cmpxchg"
+
+ printf "#endif /* ${ARCH}try_cmpxchg_relaxed */\n\n"
+}
+
cat << EOF
// SPDX-License-Identifier: GPL-2.0
@@ -191,6 +238,8 @@ for xchg in "${ARCH}xchg" "${ARCH}cmpxchg" "${ARCH}cmpxchg64"; do
gen_xchg_fallbacks "${xchg}"
done
+gen_try_cmpxchg_fallbacks
+
grep '^[a-z]' "$1" | while read name meta args; do
gen_proto "${meta}" "${name}" "${ARCH}" "atomic" "int" ${args}
done
diff --git a/scripts/atomic/gen-atomic-instrumented.sh b/scripts/atomic/gen-atomic-instrumented.sh
index 2b7fec7e6abc..5766ffcec7c5 100755
--- a/scripts/atomic/gen-atomic-instrumented.sh
+++ b/scripts/atomic/gen-atomic-instrumented.sh
@@ -112,14 +112,31 @@ gen_xchg()
local xchg="$1"; shift
local mult="$1"; shift
+ if [ "${xchg%${xchg#try_cmpxchg}}" = "try_cmpxchg" ] ; then
+
+cat <<EOF
+#define ${xchg}(ptr, oldp, ...) \\
+({ \\
+ typeof(ptr) __ai_ptr = (ptr); \\
+ typeof(oldp) __ai_oldp = (oldp); \\
+ instrument_atomic_write(__ai_ptr, ${mult}sizeof(*__ai_ptr)); \\
+ instrument_atomic_write(__ai_oldp, ${mult}sizeof(*__ai_oldp)); \\
+ arch_${xchg}(__ai_ptr, __ai_oldp, __VA_ARGS__); \\
+})
+EOF
+
+ else
+
cat <<EOF
-#define ${xchg}(ptr, ...) \\
-({ \\
- typeof(ptr) __ai_ptr = (ptr); \\
- instrument_atomic_write(__ai_ptr, ${mult}sizeof(*__ai_ptr)); \\
- arch_${xchg}(__ai_ptr, __VA_ARGS__); \\
+#define ${xchg}(ptr, ...) \\
+({ \\
+ typeof(ptr) __ai_ptr = (ptr); \\
+ instrument_atomic_write(__ai_ptr, ${mult}sizeof(*__ai_ptr)); \\
+ arch_${xchg}(__ai_ptr, __VA_ARGS__); \\
})
EOF
+
+ fi
}
gen_optional_xchg()
@@ -169,7 +186,7 @@ grep '^[a-z]' "$1" | while read name meta args; do
gen_proto "${meta}" "${name}" "atomic64" "s64" ${args}
done
-for xchg in "xchg" "cmpxchg" "cmpxchg64"; do
+for xchg in "xchg" "cmpxchg" "cmpxchg64" "try_cmpxchg"; do
for order in "" "_acquire" "_release" "_relaxed"; do
gen_optional_xchg "${xchg}" "${order}"
done
diff --git a/scripts/atomic/gen-atomics.sh b/scripts/atomic/gen-atomics.sh
index d29e159ef489..d29e159ef489 100644..100755
--- a/scripts/atomic/gen-atomics.sh
+++ b/scripts/atomic/gen-atomics.sh
diff --git a/scripts/bloat-o-meter b/scripts/bloat-o-meter
index d7ca46c612b3..dcd8d8750b8b 100755
--- a/scripts/bloat-o-meter
+++ b/scripts/bloat-o-meter
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
#
# Copyright 2004 Matt Mackall <mpm@selenic.com>
#
diff --git a/scripts/bpf_helpers_doc.py b/scripts/bpf_helpers_doc.py
index 31484377b8b1..867ada23281c 100755
--- a/scripts/bpf_helpers_doc.py
+++ b/scripts/bpf_helpers_doc.py
@@ -418,6 +418,7 @@ class PrinterHelpers(Printer):
'struct bpf_tcp_sock',
'struct bpf_tunnel_key',
'struct bpf_xfrm_state',
+ 'struct linux_binprm',
'struct pt_regs',
'struct sk_reuseport_md',
'struct sockaddr',
@@ -435,6 +436,9 @@ class PrinterHelpers(Printer):
'struct xdp_md',
'struct path',
'struct btf_ptr',
+ 'struct inode',
+ 'struct socket',
+ 'struct file',
]
known_types = {
'...',
@@ -465,6 +469,7 @@ class PrinterHelpers(Printer):
'struct bpf_tcp_sock',
'struct bpf_tunnel_key',
'struct bpf_xfrm_state',
+ 'struct linux_binprm',
'struct pt_regs',
'struct sk_reuseport_md',
'struct sockaddr',
@@ -478,6 +483,9 @@ class PrinterHelpers(Printer):
'struct task_struct',
'struct path',
'struct btf_ptr',
+ 'struct inode',
+ 'struct socket',
+ 'struct file',
}
mapped_types = {
'u8': '__u8',
diff --git a/scripts/cc-version.sh b/scripts/cc-version.sh
new file mode 100755
index 000000000000..3f2ee885b116
--- /dev/null
+++ b/scripts/cc-version.sh
@@ -0,0 +1,82 @@
+#!/bin/sh
+# SPDX-License-Identifier: GPL-2.0
+#
+# Print the compiler name and its version in a 5 or 6-digit form.
+# Also, perform the minimum version check.
+
+set -e
+
+# When you raise the minimum compiler version, please update
+# Documentation/process/changes.rst as well.
+gcc_min_version=4.9.0
+clang_min_version=10.0.1
+icc_min_version=16.0.3 # temporary
+
+# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=63293
+# https://lore.kernel.org/r/20210107111841.GN1551@shell.armlinux.org.uk
+if [ "$SRCARCH" = arm64 ]; then
+ gcc_min_version=5.1.0
+fi
+
+# Print the compiler name and some version components.
+get_compiler_info()
+{
+ cat <<- EOF | "$@" -E -P -x c - 2>/dev/null
+ #if defined(__clang__)
+ Clang __clang_major__ __clang_minor__ __clang_patchlevel__
+ #elif defined(__INTEL_COMPILER)
+ ICC __INTEL_COMPILER __INTEL_COMPILER_UPDATE
+ #elif defined(__GNUC__)
+ GCC __GNUC__ __GNUC_MINOR__ __GNUC_PATCHLEVEL__
+ #else
+ unknown
+ #endif
+ EOF
+}
+
+# Convert the version string x.y.z to a canonical 5 or 6-digit form.
+get_canonical_version()
+{
+ IFS=.
+ set -- $1
+ echo $((10000 * $1 + 100 * $2 + $3))
+}
+
+# $@ instead of $1 because multiple words might be given, e.g. CC="ccache gcc".
+orig_args="$@"
+set -- $(get_compiler_info "$@")
+
+name=$1
+
+case "$name" in
+GCC)
+ version=$2.$3.$4
+ min_version=$gcc_min_version
+ ;;
+Clang)
+ version=$2.$3.$4
+ min_version=$clang_min_version
+ ;;
+ICC)
+ version=$(($2 / 100)).$(($2 % 100)).$3
+ min_version=$icc_min_version
+ ;;
+*)
+ echo "$orig_args: unknown compiler" >&2
+ exit 1
+ ;;
+esac
+
+cversion=$(get_canonical_version $version)
+min_cversion=$(get_canonical_version $min_version)
+
+if [ "$cversion" -lt "$min_cversion" ]; then
+ echo >&2 "***"
+ echo >&2 "*** Compiler is too old."
+ echo >&2 "*** Your $name version: $version"
+ echo >&2 "*** Minimum $name version: $min_version"
+ echo >&2 "***"
+ exit 1
+fi
+
+echo $name $cversion
diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl
index fab38b493cef..df8b23dc1eb0 100755
--- a/scripts/checkpatch.pl
+++ b/scripts/checkpatch.pl
@@ -382,6 +382,7 @@ our $InitAttribute = qr{$InitAttributeData|$InitAttributeConst|$InitAttributeIni
# We need \b after 'init' otherwise 'initconst' will cause a false positive in a check
our $Attribute = qr{
const|
+ volatile|
__percpu|
__nocast|
__safe|
@@ -486,7 +487,7 @@ our $logFunctions = qr{(?x:
our $allocFunctions = qr{(?x:
(?:(?:devm_)?
- (?:kv|k|v)[czm]alloc(?:_node|_array)? |
+ (?:kv|k|v)[czm]alloc(?:_array)?(?:_node)? |
kstrdup(?:_const)? |
kmemdup(?:_nul)?) |
(?:\w+)?alloc_skb(?:_ip_align)? |
@@ -506,6 +507,88 @@ our $signature_tags = qr{(?xi:
Cc:
)};
+our $tracing_logging_tags = qr{(?xi:
+ [=-]*> |
+ <[=-]* |
+ \[ |
+ \] |
+ start |
+ called |
+ entered |
+ entry |
+ enter |
+ in |
+ inside |
+ here |
+ begin |
+ exit |
+ end |
+ done |
+ leave |
+ completed |
+ out |
+ return |
+ [\.\!:\s]*
+)};
+
+sub edit_distance_min {
+ my (@arr) = @_;
+ my $len = scalar @arr;
+ if ((scalar @arr) < 1) {
+ # if underflow, return
+ return;
+ }
+ my $min = $arr[0];
+ for my $i (0 .. ($len-1)) {
+ if ($arr[$i] < $min) {
+ $min = $arr[$i];
+ }
+ }
+ return $min;
+}
+
+sub get_edit_distance {
+ my ($str1, $str2) = @_;
+ $str1 = lc($str1);
+ $str2 = lc($str2);
+ $str1 =~ s/-//g;
+ $str2 =~ s/-//g;
+ my $len1 = length($str1);
+ my $len2 = length($str2);
+ # two dimensional array storing minimum edit distance
+ my @distance;
+ for my $i (0 .. $len1) {
+ for my $j (0 .. $len2) {
+ if ($i == 0) {
+ $distance[$i][$j] = $j;
+ } elsif ($j == 0) {
+ $distance[$i][$j] = $i;
+ } elsif (substr($str1, $i-1, 1) eq substr($str2, $j-1, 1)) {
+ $distance[$i][$j] = $distance[$i - 1][$j - 1];
+ } else {
+ my $dist1 = $distance[$i][$j - 1]; #insert distance
+ my $dist2 = $distance[$i - 1][$j]; # remove
+ my $dist3 = $distance[$i - 1][$j - 1]; #replace
+ $distance[$i][$j] = 1 + edit_distance_min($dist1, $dist2, $dist3);
+ }
+ }
+ }
+ return $distance[$len1][$len2];
+}
+
+sub find_standard_signature {
+ my ($sign_off) = @_;
+ my @standard_signature_tags = (
+ 'Signed-off-by:', 'Co-developed-by:', 'Acked-by:', 'Tested-by:',
+ 'Reviewed-by:', 'Reported-by:', 'Suggested-by:'
+ );
+ foreach my $signature (@standard_signature_tags) {
+ return $signature if (get_edit_distance($sign_off, $signature) <= 2);
+ }
+
+ return "";
+}
+
our @typeListMisordered = (
qr{char\s+(?:un)?signed},
qr{int\s+(?:(?:un)?signed\s+)?short\s},
@@ -853,6 +936,13 @@ our $declaration_macros = qr{(?x:
(?:SKCIPHER_REQUEST|SHASH_DESC|AHASH_REQUEST)_ON_STACK\s*\(
)};
+our %allow_repeated_words = (
+ add => '',
+ added => '',
+ bad => '',
+ be => '',
+);
+
sub deparenthesize {
my ($string) = @_;
return "" if (!defined($string));
@@ -1152,6 +1242,7 @@ sub parse_email {
my ($formatted_email) = @_;
my $name = "";
+ my $quoted = "";
my $name_comment = "";
my $address = "";
my $comment = "";
@@ -1183,14 +1274,20 @@ sub parse_email {
}
}
- $comment = trim($comment);
- $name = trim($name);
- $name =~ s/^\"|\"$//g;
- if ($name =~ s/(\s*\([^\)]+\))\s*//) {
- $name_comment = trim($1);
+ # Extract comments from names excluding quoted parts
+ # "John D. (Doe)" - Do not extract
+ if ($name =~ s/\"(.+)\"//) {
+ $quoted = $1;
}
+ while ($name =~ s/\s*($balanced_parens)\s*/ /) {
+ $name_comment .= trim($1);
+ }
+ $name =~ s/^[ \"]+|[ \"]+$//g;
+ $name = trim("$quoted $name");
+
$address = trim($address);
$address =~ s/^\<|\>$//g;
+ $comment = trim($comment);
if ($name =~ /[^\w \-]/i) { ##has "must quote" chars
$name =~ s/(?<!\\)"/\\"/g; ##escape quotes
@@ -1205,17 +1302,20 @@ sub format_email {
my $formatted_email;
- $name_comment = trim($name_comment);
- $comment = trim($comment);
- $name = trim($name);
- $name =~ s/^\"|\"$//g;
+ $name =~ s/^[ \"]+|[ \"]+$//g;
$address = trim($address);
+ $address =~ s/(?:\.|\,|\")+$//; ##trailing commas, dots or quotes
if ($name =~ /[^\w \-]/i) { ##has "must quote" chars
$name =~ s/(?<!\\)"/\\"/g; ##escape quotes
$name = "\"$name\"";
}
+ $name_comment = trim($name_comment);
+ $name_comment = " $name_comment" if ($name_comment ne "");
+ $comment = trim($comment);
+ $comment = " $comment" if ($comment ne "");
+
if ("$name" eq "") {
$formatted_email = "$address";
} else {
@@ -1233,15 +1333,11 @@ sub reformat_email {
}
sub same_email_addresses {
- my ($email1, $email2, $match_comment) = @_;
+ my ($email1, $email2) = @_;
my ($email1_name, $name1_comment, $email1_address, $comment1) = parse_email($email1);
my ($email2_name, $name2_comment, $email2_address, $comment2) = parse_email($email2);
- if ($match_comment != 1) {
- return $email1_name eq $email2_name &&
- $email1_address eq $email2_address;
- }
return $email1_name eq $email2_name &&
$email1_address eq $email2_address &&
$name1_comment eq $name2_comment &&
@@ -2357,6 +2453,15 @@ sub get_raw_comment {
return $comment;
}
+sub exclude_global_initialisers {
+ my ($realfile) = @_;
+
+ # Do not check for BPF programs (tools/testing/selftests/bpf/progs/*.c, samples/bpf/*_kern.c, *.bpf.c).
+ return $realfile =~ m@^tools/testing/selftests/bpf/progs/.*\.c$@ ||
+ $realfile =~ m@^samples/bpf/.*_kern\.c$@ ||
+ $realfile =~ m@/bpf/.*\.bpf\.c$@;
+}
+
sub process {
my $filename = shift;
@@ -2704,7 +2809,7 @@ sub process {
$signoff++;
$in_commit_log = 0;
if ($author ne '' && $authorsignoff != 1) {
- if (same_email_addresses($1, $author, 1)) {
+ if (same_email_addresses($1, $author)) {
$authorsignoff = 1;
} else {
my $ctx = $1;
@@ -2760,8 +2865,17 @@ sub process {
my $ucfirst_sign_off = ucfirst(lc($sign_off));
if ($sign_off !~ /$signature_tags/) {
- WARN("BAD_SIGN_OFF",
- "Non-standard signature: $sign_off\n" . $herecurr);
+ my $suggested_signature = find_standard_signature($sign_off);
+ if ($suggested_signature eq "") {
+ WARN("BAD_SIGN_OFF",
+ "Non-standard signature: $sign_off\n" . $herecurr);
+ } else {
+ if (WARN("BAD_SIGN_OFF",
+ "Non-standard signature: '$sign_off' - perhaps '$suggested_signature'?\n" . $herecurr) &&
+ $fix) {
+ $fixed[$fixlinenr] =~ s/$sign_off/$suggested_signature/;
+ }
+ }
}
if (defined $space_before && $space_before ne "") {
if (WARN("BAD_SIGN_OFF",
@@ -2800,9 +2914,77 @@ sub process {
$dequoted =~ s/" </ </;
# Don't force email to have quotes
# Allow just an angle bracketed address
- if (!same_email_addresses($email, $suggested_email, 0)) {
+ if (!same_email_addresses($email, $suggested_email)) {
+ if (WARN("BAD_SIGN_OFF",
+ "email address '$email' might be better as '$suggested_email'\n" . $herecurr) &&
+ $fix) {
+ $fixed[$fixlinenr] =~ s/\Q$email\E/$suggested_email/;
+ }
+ }
+
+ # Address part shouldn't have comments
+ my $stripped_address = $email_address;
+ $stripped_address =~ s/\([^\(\)]*\)//g;
+ if ($email_address ne $stripped_address) {
+ if (WARN("BAD_SIGN_OFF",
+ "address part of email should not have comments: '$email_address'\n" . $herecurr) &&
+ $fix) {
+ $fixed[$fixlinenr] =~ s/\Q$email_address\E/$stripped_address/;
+ }
+ }
+
+ # Only one name comment should be allowed
+ my $comment_count = () = $name_comment =~ /\([^\)]+\)/g;
+ if ($comment_count > 1) {
WARN("BAD_SIGN_OFF",
- "email address '$email' might be better as '$suggested_email'\n" . $herecurr);
+ "Use a single name comment in email: '$email'\n" . $herecurr);
+ }
+
+
+ # stable@vger.kernel.org or stable@kernel.org shouldn't
+ # have an email name. In addition comments should strictly
+ # begin with a #
+ if ($email =~ /^.*stable\@(?:vger\.)?kernel\.org/i) {
+ if (($comment ne "" && $comment !~ /^#.+/) ||
+ ($email_name ne "")) {
+ my $cur_name = $email_name;
+ my $new_comment = $comment;
+ $cur_name =~ s/[a-zA-Z\s\-\"]+//g;
+
+ # Remove brackets enclosing comment text
+ # and # from start of comments to get comment text
+ $new_comment =~ s/^\((.*)\)$/$1/;
+ $new_comment =~ s/^\[(.*)\]$/$1/;
+ $new_comment =~ s/^[\s\#]+|\s+$//g;
+
+ $new_comment = trim("$new_comment $cur_name") if ($cur_name ne $new_comment);
+ $new_comment = " # $new_comment" if ($new_comment ne "");
+ my $new_email = "$email_address$new_comment";
+
+ if (WARN("BAD_STABLE_ADDRESS_STYLE",
+ "Invalid email format for stable: '$email', prefer '$new_email'\n" . $herecurr) &&
+ $fix) {
+ $fixed[$fixlinenr] =~ s/\Q$email\E/$new_email/;
+ }
+ }
+ } elsif ($comment ne "" && $comment !~ /^(?:#.+|\(.+\))$/) {
+ my $new_comment = $comment;
+
+ # Extract comment text from within brackets or
+ # c89 style /*...*/ comments
+ $new_comment =~ s/^\[(.*)\]$/$1/;
+ $new_comment =~ s/^\/\*(.*)\*\/$/$1/;
+
+ $new_comment = trim($new_comment);
+ $new_comment =~ s/^[^\w]$//; # Single lettered comment with non word character is usually a typo
+ $new_comment = "($new_comment)" if ($new_comment ne "");
+ my $new_email = format_email($email_name, $name_comment, $email_address, $new_comment);
+
+ if (WARN("BAD_SIGN_OFF",
+ "Unexpected content after email: '$email', should be: '$new_email'\n" . $herecurr) &&
+ $fix) {
+ $fixed[$fixlinenr] =~ s/\Q$email\E/$new_email/;
+ }
}
}
@@ -2825,7 +3007,7 @@ sub process {
}
if (!defined $lines[$linenr]) {
WARN("BAD_SIGN_OFF",
- "Co-developed-by: must be immediately followed by Signed-off-by:\n" . "$here\n" . $rawline);
+ "Co-developed-by: must be immediately followed by Signed-off-by:\n" . "$here\n" . $rawline);
} elsif ($rawlines[$linenr] !~ /^\s*signed-off-by:\s*(.*)/i) {
WARN("BAD_SIGN_OFF",
"Co-developed-by: must be immediately followed by Signed-off-by:\n" . "$here\n" . $rawline . "\n" .$rawlines[$linenr]);
@@ -2845,8 +3027,11 @@ sub process {
# Check for Gerrit Change-Ids not in any patch context
if ($realfile eq '' && !$has_patch_separator && $line =~ /^\s*change-id:/i) {
- ERROR("GERRIT_CHANGE_ID",
- "Remove Gerrit Change-Id's before submitting upstream\n" . $herecurr);
+ if (ERROR("GERRIT_CHANGE_ID",
+ "Remove Gerrit Change-Id's before submitting upstream\n" . $herecurr) &&
+ $fix) {
+ fix_delete_line($fixlinenr, $rawline);
+ }
}
# Check if the commit log is in a possible stack dump
@@ -2868,8 +3053,8 @@ sub process {
# file delta changes
$line =~ /^\s*(?:[\w\.\-]+\/)++[\w\.\-]+:/ ||
# filename then :
- $line =~ /^\s*(?:Fixes:|Link:)/i ||
- # A Fixes: or Link: line
+ $line =~ /^\s*(?:Fixes:|Link:|$signature_tags)/i ||
+ # A Fixes: or Link: line or signature tag line
$commit_log_possible_stack_dump)) {
WARN("COMMIT_LOG_LONG_LINE",
"Possible unwrapped commit description (prefer a maximum 75 chars per line)\n" . $herecurr);
@@ -2882,6 +3067,15 @@ sub process {
$commit_log_possible_stack_dump = 0;
}
+# Check for lines starting with a #
+ if ($in_commit_log && $line =~ /^#/) {
+ if (WARN("COMMIT_COMMENT_SYMBOL",
+ "Commit log lines starting with '#' are dropped by git as comments\n" . $herecurr) &&
+ $fix) {
+ $fixed[$fixlinenr] =~ s/^/ /;
+ }
+ }
+
# Check for git id commit length and improperly formed commit descriptions
if ($in_commit_log && !$commit_log_possible_stack_dump &&
$line !~ /^\s*(?:Link|Patchwork|http|https|BugLink|base-commit):/i &&
@@ -3022,15 +3216,18 @@ sub process {
# Check for various typo / spelling mistakes
if (defined($misspellings) &&
($in_commit_log || $line =~ /^(?:\+|Subject:)/i)) {
- while ($rawline =~ /(?:^|[^a-z@])($misspellings)(?:\b|$|[^a-z@])/gi) {
+ while ($rawline =~ /(?:^|[^\w\-'`])($misspellings)(?:[^\w\-'`]|$)/gi) {
my $typo = $1;
+ my $blank = copy_spacing($rawline);
+ my $ptr = substr($blank, 0, $-[1]) . "^" x length($typo);
+ my $hereptr = "$hereline$ptr\n";
my $typo_fix = $spelling_fix{lc($typo)};
$typo_fix = ucfirst($typo_fix) if ($typo =~ /^[A-Z]/);
$typo_fix = uc($typo_fix) if ($typo =~ /^[A-Z]+$/);
my $msg_level = \&WARN;
$msg_level = \&CHK if ($file);
if (&{$msg_level}("TYPO_SPELLING",
- "'$typo' may be misspelled - perhaps '$typo_fix'?\n" . $herecurr) &&
+ "'$typo' may be misspelled - perhaps '$typo_fix'?\n" . $hereptr) &&
$fix) {
$fixed[$fixlinenr] =~ s/(^|[^A-Za-z@])($typo)($|[^A-Za-z@])/$1$typo_fix$3/;
}
@@ -3049,20 +3246,38 @@ sub process {
}
# check for repeated words separated by a single space
- if ($rawline =~ /^\+/ || $in_commit_log) {
+# avoid false positive from list command eg, '-rw-r--r-- 1 root root'
+ if (($rawline =~ /^\+/ || $in_commit_log) &&
+ $rawline !~ /[bcCdDlMnpPs\?-][rwxsStT-]{9}/) {
+ pos($rawline) = 1 if (!$in_commit_log);
while ($rawline =~ /\b($word_pattern) (?=($word_pattern))/g) {
my $first = $1;
my $second = $2;
-
+ my $start_pos = $-[1];
+ my $end_pos = $+[2];
if ($first =~ /(?:struct|union|enum)/) {
pos($rawline) += length($first) + length($second) + 1;
next;
}
- next if ($first ne $second);
+ next if (lc($first) ne lc($second));
next if ($first eq 'long');
+ # check for character before and after the word matches
+ my $start_char = '';
+ my $end_char = '';
+ $start_char = substr($rawline, $start_pos - 1, 1) if ($start_pos > ($in_commit_log ? 0 : 1));
+ $end_char = substr($rawline, $end_pos, 1) if ($end_pos < length($rawline));
+
+ next if ($start_char =~ /^\S$/);
+ next if (index(" \t.,;?!", $end_char) == -1);
+
+ # avoid repeating hex occurrences like 'ff ff fe 09 ...'
+ if ($first =~ /\b[0-9a-f]{2,}\b/i) {
+ next if (!exists($allow_repeated_words{lc($first)}));
+ }
+
if (WARN("REPEATED_WORD",
"Possible repeated word: '$first'\n" . $herecurr) &&
$fix) {
@@ -3209,13 +3424,6 @@ sub process {
}
}
-# discourage the use of boolean for type definition attributes of Kconfig options
- if ($realfile =~ /Kconfig/ &&
- $line =~ /^\+\s*\bboolean\b/) {
- WARN("CONFIG_TYPE_BOOLEAN",
- "Use of boolean is deprecated, please use bool instead.\n" . $herecurr);
- }
-
if (($realfile =~ /Makefile.*/ || $realfile =~ /Kbuild.*/) &&
($line =~ /\+(EXTRA_[A-Z]+FLAGS).*/)) {
my $flag = $1;
@@ -3393,8 +3601,18 @@ sub process {
# check for adding lines without a newline.
if ($line =~ /^\+/ && defined $lines[$linenr] && $lines[$linenr] =~ /^\\ No newline at end of file/) {
- WARN("MISSING_EOF_NEWLINE",
- "adding a line without newline at end of file\n" . $herecurr);
+ if (WARN("MISSING_EOF_NEWLINE",
+ "adding a line without newline at end of file\n" . $herecurr) &&
+ $fix) {
+ fix_delete_line($fixlinenr+1, "No newline at end of file");
+ }
+ }
+
+# check for .L prefix local symbols in .S files
+ if ($realfile =~ /\.S$/ &&
+ $line =~ /^\+\s*(?:[A-Z]+_)?SYM_[A-Z]+_(?:START|END)(?:_[A-Z_]+)?\s*\(\s*\.L/) {
+ WARN("AVOID_L_PREFIX",
+ "Avoid using '.L' prefixed local symbol names for denoting a range of code via 'SYM_*_START/END' annotations; see Documentation/asm-annotations.rst\n" . $herecurr);
}
# check we are in a valid source file C or perl if not then ignore this hunk
@@ -3428,14 +3646,28 @@ sub process {
# check for assignments on the start of a line
if ($sline =~ /^\+\s+($Assignment)[^=]/) {
- CHK("ASSIGNMENT_CONTINUATIONS",
- "Assignment operator '$1' should be on the previous line\n" . $hereprev);
+ my $operator = $1;
+ if (CHK("ASSIGNMENT_CONTINUATIONS",
+ "Assignment operator '$1' should be on the previous line\n" . $hereprev) &&
+ $fix && $prevrawline =~ /^\+/) {
+ # add assignment operator to the previous line, remove from current line
+ $fixed[$fixlinenr - 1] .= " $operator";
+ $fixed[$fixlinenr] =~ s/\Q$operator\E\s*//;
+ }
}
# check for && or || at the start of a line
if ($rawline =~ /^\+\s*(&&|\|\|)/) {
- CHK("LOGICAL_CONTINUATIONS",
- "Logical continuations should be on the previous line\n" . $hereprev);
+ my $operator = $1;
+ if (CHK("LOGICAL_CONTINUATIONS",
+ "Logical continuations should be on the previous line\n" . $hereprev) &&
+ $fix && $prevrawline =~ /^\+/) {
+ # insert logical operator at last non-comment, non-whitepsace char on previous line
+ $prevline =~ /[\s$;]*$/;
+ my $line_end = substr($prevrawline, $-[0]);
+ $fixed[$fixlinenr - 1] =~ s/\Q$line_end\E$/ $operator$line_end/;
+ $fixed[$fixlinenr] =~ s/\Q$operator\E\s*//;
+ }
}
# check indentation starts on a tab stop
@@ -3585,43 +3817,48 @@ sub process {
}
# check for missing blank lines after declarations
- if ($sline =~ /^\+\s+\S/ && #Not at char 1
- # actual declarations
- ($prevline =~ /^\+\s+$Declare\s*$Ident\s*[=,;:\[]/ ||
+# (declarations must have the same indentation and not be at the start of line)
+ if (($prevline =~ /\+(\s+)\S/) && $sline =~ /^\+$1\S/) {
+ # use temporaries
+ my $sl = $sline;
+ my $pl = $prevline;
+ # remove $Attribute/$Sparse uses to simplify comparisons
+ $sl =~ s/\b(?:$Attribute|$Sparse)\b//g;
+ $pl =~ s/\b(?:$Attribute|$Sparse)\b//g;
+ if (($pl =~ /^\+\s+$Declare\s*$Ident\s*[=,;:\[]/ ||
# function pointer declarations
- $prevline =~ /^\+\s+$Declare\s*\(\s*\*\s*$Ident\s*\)\s*[=,;:\[\(]/ ||
+ $pl =~ /^\+\s+$Declare\s*\(\s*\*\s*$Ident\s*\)\s*[=,;:\[\(]/ ||
# foo bar; where foo is some local typedef or #define
- $prevline =~ /^\+\s+$Ident(?:\s+|\s*\*\s*)$Ident\s*[=,;\[]/ ||
+ $pl =~ /^\+\s+$Ident(?:\s+|\s*\*\s*)$Ident\s*[=,;\[]/ ||
# known declaration macros
- $prevline =~ /^\+\s+$declaration_macros/) &&
+ $pl =~ /^\+\s+$declaration_macros/) &&
# for "else if" which can look like "$Ident $Ident"
- !($prevline =~ /^\+\s+$c90_Keywords\b/ ||
+ !($pl =~ /^\+\s+$c90_Keywords\b/ ||
# other possible extensions of declaration lines
- $prevline =~ /(?:$Compare|$Assignment|$Operators)\s*$/ ||
+ $pl =~ /(?:$Compare|$Assignment|$Operators)\s*$/ ||
# not starting a section or a macro "\" extended line
- $prevline =~ /(?:\{\s*|\\)$/) &&
+ $pl =~ /(?:\{\s*|\\)$/) &&
# looks like a declaration
- !($sline =~ /^\+\s+$Declare\s*$Ident\s*[=,;:\[]/ ||
+ !($sl =~ /^\+\s+$Declare\s*$Ident\s*[=,;:\[]/ ||
# function pointer declarations
- $sline =~ /^\+\s+$Declare\s*\(\s*\*\s*$Ident\s*\)\s*[=,;:\[\(]/ ||
+ $sl =~ /^\+\s+$Declare\s*\(\s*\*\s*$Ident\s*\)\s*[=,;:\[\(]/ ||
# foo bar; where foo is some local typedef or #define
- $sline =~ /^\+\s+$Ident(?:\s+|\s*\*\s*)$Ident\s*[=,;\[]/ ||
+ $sl =~ /^\+\s+$Ident(?:\s+|\s*\*\s*)$Ident\s*[=,;\[]/ ||
# known declaration macros
- $sline =~ /^\+\s+$declaration_macros/ ||
+ $sl =~ /^\+\s+$declaration_macros/ ||
# start of struct or union or enum
- $sline =~ /^\+\s+(?:static\s+)?(?:const\s+)?(?:union|struct|enum|typedef)\b/ ||
+ $sl =~ /^\+\s+(?:static\s+)?(?:const\s+)?(?:union|struct|enum|typedef)\b/ ||
# start or end of block or continuation of declaration
- $sline =~ /^\+\s+(?:$|[\{\}\.\#\"\?\:\(\[])/ ||
+ $sl =~ /^\+\s+(?:$|[\{\}\.\#\"\?\:\(\[])/ ||
# bitfield continuation
- $sline =~ /^\+\s+$Ident\s*:\s*\d+\s*[,;]/ ||
+ $sl =~ /^\+\s+$Ident\s*:\s*\d+\s*[,;]/ ||
# other possible extensions of declaration lines
- $sline =~ /^\+\s+\(?\s*(?:$Compare|$Assignment|$Operators)/) &&
- # indentation of previous and current line are the same
- (($prevline =~ /\+(\s+)\S/) && $sline =~ /^\+$1\S/)) {
- if (WARN("LINE_SPACING",
- "Missing a blank line after declarations\n" . $hereprev) &&
- $fix) {
- fix_insert_line($fixlinenr, "\+");
+ $sl =~ /^\+\s+\(?\s*(?:$Compare|$Assignment|$Operators)/)) {
+ if (WARN("LINE_SPACING",
+ "Missing a blank line after declarations\n" . $hereprev) &&
+ $fix) {
+ fix_insert_line($fixlinenr, "\+");
+ }
}
}
@@ -3674,12 +3911,16 @@ sub process {
}
# check indentation of a line with a break;
-# if the previous line is a goto or return and is indented the same # of tabs
+# if the previous line is a goto, return or break
+# and is indented the same # of tabs
if ($sline =~ /^\+([\t]+)break\s*;\s*$/) {
my $tabs = $1;
- if ($prevline =~ /^\+$tabs(?:goto|return)\b/) {
- WARN("UNNECESSARY_BREAK",
- "break is not useful after a goto or return\n" . $hereprev);
+ if ($prevline =~ /^\+$tabs(goto|return|break)\b/) {
+ if (WARN("UNNECESSARY_BREAK",
+ "break is not useful after a $1\n" . $hereprev) &&
+ $fix) {
+ fix_delete_line($fixlinenr, $rawline);
+ }
}
}
@@ -4088,8 +4329,7 @@ sub process {
if (defined $realline_next &&
exists $lines[$realline_next - 1] &&
!defined $suppress_export{$realline_next} &&
- ($lines[$realline_next - 1] =~ /EXPORT_SYMBOL.*\((.*)\)/ ||
- $lines[$realline_next - 1] =~ /EXPORT_UNUSED_SYMBOL.*\((.*)\)/)) {
+ ($lines[$realline_next - 1] =~ /EXPORT_SYMBOL.*\((.*)\)/)) {
# Handle definitions which produce identifiers with
# a prefix:
# XXX(foo);
@@ -4116,8 +4356,7 @@ sub process {
}
if (!defined $suppress_export{$linenr} &&
$prevline =~ /^.\s*$/ &&
- ($line =~ /EXPORT_SYMBOL.*\((.*)\)/ ||
- $line =~ /EXPORT_UNUSED_SYMBOL.*\((.*)\)/)) {
+ ($line =~ /EXPORT_SYMBOL.*\((.*)\)/)) {
#print "FOO B <$lines[$linenr - 1]>\n";
$suppress_export{$linenr} = 2;
}
@@ -4128,7 +4367,8 @@ sub process {
}
# check for global initialisers.
- if ($line =~ /^\+$Type\s*$Ident(?:\s+$Modifier)*\s*=\s*($zero_initializer)\s*;/) {
+ if ($line =~ /^\+$Type\s*$Ident(?:\s+$Modifier)*\s*=\s*($zero_initializer)\s*;/ &&
+ !exclude_global_initialisers($realfile)) {
if (ERROR("GLOBAL_INITIALISERS",
"do not initialise globals to $1\n" . $herecurr) &&
$fix) {
@@ -4207,12 +4447,24 @@ sub process {
}
}
+# check for const static or static <non ptr type> const declarations
+# prefer 'static const <foo>' over 'const static <foo>' and 'static <foo> const'
+ if ($sline =~ /^\+\s*const\s+static\s+($Type)\b/ ||
+ $sline =~ /^\+\s*static\s+($BasicType)\s+const\b/) {
+ if (WARN("STATIC_CONST",
+ "Move const after static - use 'static const $1'\n" . $herecurr) &&
+ $fix) {
+ $fixed[$fixlinenr] =~ s/\bconst\s+static\b/static const/;
+ $fixed[$fixlinenr] =~ s/\bstatic\s+($BasicType)\s+const\b/static const $1/;
+ }
+ }
+
# check for non-global char *foo[] = {"bar", ...} declarations.
if ($line =~ /^.\s+(?:static\s+|const\s+)?char\s+\*\s*\w+\s*\[\s*\]\s*=\s*\{/) {
WARN("STATIC_CONST_CHAR_ARRAY",
"char * array declaration might be better as static const\n" .
$herecurr);
- }
+ }
# check for sizeof(foo)/sizeof(foo[0]) that could be ARRAY_SIZE(foo)
if ($line =~ m@\bsizeof\s*\(\s*($Lval)\s*\)@) {
@@ -4329,16 +4581,23 @@ sub process {
"printk() should include KERN_<LEVEL> facility level\n" . $herecurr);
}
- if ($line =~ /\bprintk\s*\(\s*KERN_([A-Z]+)/) {
- my $orig = $1;
+# prefer variants of (subsystem|netdev|dev|pr)_<level> to printk(KERN_<LEVEL>
+ if ($line =~ /\b(printk(_once|_ratelimited)?)\s*\(\s*KERN_([A-Z]+)/) {
+ my $printk = $1;
+ my $modifier = $2;
+ my $orig = $3;
+ $modifier = "" if (!defined($modifier));
my $level = lc($orig);
$level = "warn" if ($level eq "warning");
my $level2 = $level;
$level2 = "dbg" if ($level eq "debug");
+ $level .= $modifier;
+ $level2 .= $modifier;
WARN("PREFER_PR_LEVEL",
- "Prefer [subsystem eg: netdev]_$level2([subsystem]dev, ... then dev_$level2(dev, ... then pr_$level(... to printk(KERN_$orig ...\n" . $herecurr);
+ "Prefer [subsystem eg: netdev]_$level2([subsystem]dev, ... then dev_$level2(dev, ... then pr_$level(... to $printk(KERN_$orig ...\n" . $herecurr);
}
+# prefer dev_<level> to dev_printk(KERN_<LEVEL>
if ($line =~ /\bdev_printk\s*\(\s*KERN_([A-Z]+)/) {
my $orig = $1;
my $level = lc($orig);
@@ -4384,7 +4643,7 @@ sub process {
$fix) {
fix_delete_line($fixlinenr, $rawline);
my $fixed_line = $rawline;
- $fixed_line =~ /(^..*$Type\s*$Ident\(.*\)\s*){(.*)$/;
+ $fixed_line =~ /(^..*$Type\s*$Ident\(.*\)\s*)\{(.*)$/;
my $line1 = $1;
my $line2 = $2;
fix_insert_line($fixlinenr, ltrim($line1));
@@ -4795,7 +5054,7 @@ sub process {
# A colon needs no spaces before when it is
# terminating a case value or a label.
} elsif ($opv eq ':C' || $opv eq ':L') {
- if ($ctx =~ /Wx./) {
+ if ($ctx =~ /Wx./ and $realfile !~ m@.*\.lds\.h$@) {
if (ERROR("SPACING",
"space prohibited before that '$op' $at\n" . $hereptr)) {
$good = rtrim($fix_elements[$n]) . trim($fix_elements[$n + 1]);
@@ -4879,7 +5138,7 @@ sub process {
## $line !~ /^.\s*$Type\s+$Ident(?:\s*=[^,{]*)?\s*,\s*$Type\s*$Ident.*/) {
##
## # Remove any bracketed sections to ensure we do not
-## # falsly report the parameters of functions.
+## # falsely report the parameters of functions.
## my $ln = $line;
## while ($ln =~ s/\([^\(\)]*\)//g) {
## }
@@ -5058,7 +5317,7 @@ sub process {
$lines[$linenr - 3] !~ /^[ +]\s*$Ident\s*:/) {
WARN("RETURN_VOID",
"void function return statements are not generally useful\n" . $hereprev);
- }
+ }
# if statements using unnecessary parentheses - ie: if ((foo == bar))
if ($perl_version_ok &&
@@ -5295,6 +5554,8 @@ sub process {
#CamelCase
if ($var !~ /^$Constant$/ &&
$var =~ /[A-Z][a-z]|[a-z][A-Z]/ &&
+#Ignore some autogenerated defines and enum values
+ $var !~ /^(?:[A-Z]+_){1,5}[A-Z]{1,3}[a-z]/ &&
#Ignore Page<foo> variants
$var !~ /^(?:Clear|Set|TestClear|TestSet|)Page[A-Z]/ &&
#Ignore SI style variants like nS, mV and dB
@@ -5752,6 +6013,17 @@ sub process {
"Prefer using '\"%s...\", __func__' to using '$context_function', this function's name, in a string\n" . $herecurr);
}
+# check for unnecessary function tracing like uses
+# This does not use $logFunctions because there are many instances like
+# 'dprintk(FOO, "%s()\n", __func__);' which do not match $logFunctions
+ if ($rawline =~ /^\+.*\([^"]*"$tracing_logging_tags{0,3}%s(?:\s*\(\s*\)\s*)?$tracing_logging_tags{0,3}(?:\\n)?"\s*,\s*__func__\s*\)\s*;/) {
+ if (WARN("TRACING_LOGGING",
+ "Unnecessary ftrace-like logging - prefer using ftrace\n" . $herecurr) &&
+ $fix) {
+ fix_delete_line($fixlinenr, $rawline);
+ }
+ }
+
# check for spaces before a quoted newline
if ($rawline =~ /^.*\".*\s\\n/) {
if (WARN("QUOTED_WHITESPACE_BEFORE_NEWLINE",
@@ -5898,6 +6170,28 @@ sub process {
"Avoid logging continuation uses where feasible\n" . $herecurr);
}
+# check for unnecessary use of %h[xudi] and %hh[xudi] in logging functions
+ if (defined $stat &&
+ $line =~ /\b$logFunctions\s*\(/ &&
+ index($stat, '"') >= 0) {
+ my $lc = $stat =~ tr@\n@@;
+ $lc = $lc + $linenr;
+ my $stat_real = get_stat_real($linenr, $lc);
+ pos($stat_real) = index($stat_real, '"');
+ while ($stat_real =~ /[^\"%]*(%[\#\d\.\*\-]*(h+)[idux])/g) {
+ my $pspec = $1;
+ my $h = $2;
+ my $lineoff = substr($stat_real, 0, $-[1]) =~ tr@\n@@;
+ if (WARN("UNNECESSARY_MODIFIER",
+ "Integer promotion: Using '$h' in '$pspec' is unnecessary\n" . "$here\n$stat_real\n") &&
+ $fix && $fixed[$fixlinenr + $lineoff] =~ /^\+/) {
+ my $nspec = $pspec;
+ $nspec =~ s/h//g;
+ $fixed[$fixlinenr + $lineoff] =~ s/\Q$pspec\E/$nspec/;
+ }
+ }
+ }
+
# check for mask then right shift without a parentheses
if ($perl_version_ok &&
$line =~ /$LvalOrFunc\s*\&\s*($LvalOrFunc)\s*>>/ &&
@@ -6144,50 +6438,68 @@ sub process {
}
}
-# Check for __attribute__ packed, prefer __packed
+# Check for compiler attributes
if ($realfile !~ m@\binclude/uapi/@ &&
- $line =~ /\b__attribute__\s*\(\s*\(.*\bpacked\b/) {
- WARN("PREFER_PACKED",
- "__packed is preferred over __attribute__((packed))\n" . $herecurr);
- }
-
-# Check for __attribute__ aligned, prefer __aligned
- if ($realfile !~ m@\binclude/uapi/@ &&
- $line =~ /\b__attribute__\s*\(\s*\(.*aligned/) {
- WARN("PREFER_ALIGNED",
- "__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)/;
- }
- }
+ $rawline =~ /\b__attribute__\s*\(\s*($balanced_parens)\s*\)/) {
+ my $attr = $1;
+ $attr =~ s/\s*\(\s*(.*)\)\s*/$1/;
-# Check for __attribute__ format(printf, prefer __printf
- if ($realfile !~ m@\binclude/uapi/@ &&
- $line =~ /\b__attribute__\s*\(\s*\(\s*format\s*\(\s*printf/) {
- if (WARN("PREFER_PRINTF",
- "__printf(string-index, first-to-check) is preferred over __attribute__((format(printf, string-index, first-to-check)))\n" . $herecurr) &&
- $fix) {
- $fixed[$fixlinenr] =~ s/\b__attribute__\s*\(\s*\(\s*format\s*\(\s*printf\s*,\s*(.*)\)\s*\)\s*\)/"__printf(" . trim($1) . ")"/ex;
+ my %attr_list = (
+ "alias" => "__alias",
+ "aligned" => "__aligned",
+ "always_inline" => "__always_inline",
+ "assume_aligned" => "__assume_aligned",
+ "cold" => "__cold",
+ "const" => "__attribute_const__",
+ "copy" => "__copy",
+ "designated_init" => "__designated_init",
+ "externally_visible" => "__visible",
+ "format" => "printf|scanf",
+ "gnu_inline" => "__gnu_inline",
+ "malloc" => "__malloc",
+ "mode" => "__mode",
+ "no_caller_saved_registers" => "__no_caller_saved_registers",
+ "noclone" => "__noclone",
+ "noinline" => "noinline",
+ "nonstring" => "__nonstring",
+ "noreturn" => "__noreturn",
+ "packed" => "__packed",
+ "pure" => "__pure",
+ "section" => "__section",
+ "used" => "__used",
+ "weak" => "__weak"
+ );
+ while ($attr =~ /\s*(\w+)\s*(${balanced_parens})?/g) {
+ my $orig_attr = $1;
+ my $params = '';
+ $params = $2 if defined($2);
+ my $curr_attr = $orig_attr;
+ $curr_attr =~ s/^[\s_]+|[\s_]+$//g;
+ if (exists($attr_list{$curr_attr})) {
+ my $new = $attr_list{$curr_attr};
+ if ($curr_attr eq "format" && $params) {
+ $params =~ /^\s*\(\s*(\w+)\s*,\s*(.*)/;
+ $new = "__$1\($2";
+ } else {
+ $new = "$new$params";
+ }
+ if (WARN("PREFER_DEFINED_ATTRIBUTE_MACRO",
+ "Prefer $new over __attribute__(($orig_attr$params))\n" . $herecurr) &&
+ $fix) {
+ my $remove = "\Q$orig_attr\E" . '\s*' . "\Q$params\E" . '(?:\s*,\s*)?';
+ $fixed[$fixlinenr] =~ s/$remove//;
+ $fixed[$fixlinenr] =~ s/\b__attribute__/$new __attribute__/;
+ $fixed[$fixlinenr] =~ s/\}\Q$new\E/} $new/;
+ $fixed[$fixlinenr] =~ s/ __attribute__\s*\(\s*\(\s*\)\s*\)//;
+ }
+ }
}
- }
-# Check for __attribute__ format(scanf, prefer __scanf
- if ($realfile !~ m@\binclude/uapi/@ &&
- $line =~ /\b__attribute__\s*\(\s*\(\s*format\s*\(\s*scanf\b/) {
- if (WARN("PREFER_SCANF",
- "__scanf(string-index, first-to-check) is preferred over __attribute__((format(scanf, string-index, first-to-check)))\n" . $herecurr) &&
- $fix) {
- $fixed[$fixlinenr] =~ s/\b__attribute__\s*\(\s*\(\s*format\s*\(\s*scanf\s*,\s*(.*)\)\s*\)\s*\)/"__scanf(" . trim($1) . ")"/ex;
+ # Check for __attribute__ unused, prefer __always_unused or __maybe_unused
+ if ($attr =~ /^_*unused/) {
+ WARN("PREFER_DEFINED_ATTRIBUTE_MACRO",
+ "__always_unused or __maybe_unused is preferred over __attribute__((__unused__))\n" . $herecurr);
}
}
@@ -6223,18 +6535,18 @@ sub process {
if ($line =~ /(\(\s*$C90_int_types\s*\)\s*)($Constant)\b/) {
my $cast = $1;
my $const = $2;
+ my $suffix = "";
+ my $newconst = $const;
+ $newconst =~ s/${Int_type}$//;
+ $suffix .= 'U' if ($cast =~ /\bunsigned\b/);
+ if ($cast =~ /\blong\s+long\b/) {
+ $suffix .= 'LL';
+ } elsif ($cast =~ /\blong\b/) {
+ $suffix .= 'L';
+ }
if (WARN("TYPECAST_INT_CONSTANT",
- "Unnecessary typecast of c90 int constant\n" . $herecurr) &&
+ "Unnecessary typecast of c90 int constant - '$cast$const' could be '$const$suffix'\n" . $herecurr) &&
$fix) {
- my $suffix = "";
- my $newconst = $const;
- $newconst =~ s/${Int_type}$//;
- $suffix .= 'U' if ($cast =~ /\bunsigned\b/);
- if ($cast =~ /\blong\s+long\b/) {
- $suffix .= 'LL';
- } elsif ($cast =~ /\blong\b/) {
- $suffix .= 'L';
- }
$fixed[$fixlinenr] =~ s/\Q$cast\E$const\b/$newconst$suffix/;
}
}
@@ -6383,6 +6695,12 @@ sub process {
# }
# }
+# strlcpy uses that should likely be strscpy
+ if ($line =~ /\bstrlcpy\s*\(/) {
+ WARN("STRLCPY",
+ "Prefer strscpy over strlcpy - see: https://lore.kernel.org/r/CAHk-=wgfRnXz0W3D37d01q3JFkr_i_uTL=V6A6G1oUZcprmknw\@mail.gmail.com/\n" . $herecurr);
+ }
+
# typecasts on min/max could be min_t/max_t
if ($perl_version_ok &&
defined $stat &&
@@ -6759,12 +7077,14 @@ sub process {
# use of NR_CPUS is usually wrong
# ignore definitions of NR_CPUS and usage to define arrays as likely right
+# ignore designated initializers using NR_CPUS
if ($line =~ /\bNR_CPUS\b/ &&
$line !~ /^.\s*\s*#\s*if\b.*\bNR_CPUS\b/ &&
$line !~ /^.\s*\s*#\s*define\b.*\bNR_CPUS\b/ &&
$line !~ /^.\s*$Declare\s.*\[[^\]]*NR_CPUS[^\]]*\]/ &&
$line !~ /\[[^\]]*\.\.\.[^\]]*NR_CPUS[^\]]*\]/ &&
- $line !~ /\[[^\]]*NR_CPUS[^\]]*\.\.\.[^\]]*\]/)
+ $line !~ /\[[^\]]*NR_CPUS[^\]]*\.\.\.[^\]]*\]/ &&
+ $line !~ /^.\s*\.\w+\s*=\s*.*\bNR_CPUS\b/)
{
WARN("NR_CPUS",
"usage of NR_CPUS is often wrong - consider using cpu_possible(), num_possible_cpus(), for_each_possible_cpu(), etc\n" . $herecurr);
@@ -6800,12 +7120,6 @@ sub process {
}
}
-# check for mutex_trylock_recursive usage
- if ($line =~ /mutex_trylock_recursive/) {
- ERROR("LOCKING",
- "recursive locking is bad, do not use this ever.\n" . $herecurr);
- }
-
# check for lockdep_set_novalidate_class
if ($line =~ /^.\s*lockdep_set_novalidate_class\s*\(/ ||
$line =~ /__lockdep_no_validate__\s*\)/ ) {
@@ -6968,7 +7282,7 @@ sub process {
exit(0);
}
- # This is not a patch, and we are are in 'no-patch' mode so
+ # This is not a patch, and we are in 'no-patch' mode so
# just keep quiet.
if (!$chk_patch && !$is_patch) {
exit(0);
diff --git a/scripts/clang-tools/gen_compile_commands.py b/scripts/clang-tools/gen_compile_commands.py
index 19963708bcf8..b7e9ecf16e56 100755
--- a/scripts/clang-tools/gen_compile_commands.py
+++ b/scripts/clang-tools/gen_compile_commands.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
# SPDX-License-Identifier: GPL-2.0
#
# Copyright (C) Google LLC, 2018
@@ -20,7 +20,9 @@ _DEFAULT_LOG_LEVEL = 'WARNING'
_FILENAME_PATTERN = r'^\..*\.cmd$'
_LINE_PATTERN = r'^cmd_[^ ]*\.o := (.* )([^ ]*\.c)$'
_VALID_LOG_LEVELS = ['DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL']
-
+# The tools/ directory adopts a different build system, and produces .cmd
+# files in a different format. Do not support it.
+_EXCLUDE_DIRS = ['.git', 'Documentation', 'include', 'tools']
def parse_arguments():
"""Sets up and parses command-line arguments.
@@ -80,8 +82,14 @@ def cmdfiles_in_dir(directory):
"""
filename_matcher = re.compile(_FILENAME_PATTERN)
+ exclude_dirs = [ os.path.join(directory, d) for d in _EXCLUDE_DIRS ]
+
+ for dirpath, dirnames, filenames in os.walk(directory, topdown=True):
+ # Prune unwanted directories.
+ if dirpath in exclude_dirs:
+ dirnames[:] = []
+ continue
- for dirpath, _, filenames in os.walk(directory):
for filename in filenames:
if filename_matcher.match(filename):
yield os.path.join(dirpath, filename)
diff --git a/scripts/clang-tools/run-clang-tools.py b/scripts/clang-tools/run-clang-tools.py
index fa7655c7cec0..f754415af398 100755
--- a/scripts/clang-tools/run-clang-tools.py
+++ b/scripts/clang-tools/run-clang-tools.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
# SPDX-License-Identifier: GPL-2.0
#
# Copyright (C) Google LLC, 2020
diff --git a/scripts/clang-version.sh b/scripts/clang-version.sh
deleted file mode 100755
index 6fabf0695761..000000000000
--- a/scripts/clang-version.sh
+++ /dev/null
@@ -1,19 +0,0 @@
-#!/bin/sh
-# SPDX-License-Identifier: GPL-2.0
-#
-# clang-version clang-command
-#
-# Print the compiler version of `clang-command' in a 5 or 6-digit form
-# such as `50001' for clang-5.0.1 etc.
-
-compiler="$*"
-
-if ! ( $compiler --version | grep -q clang) ; then
- echo 0
- exit 1
-fi
-
-MAJOR=$(echo __clang_major__ | $compiler -E -x c - | tail -n 1)
-MINOR=$(echo __clang_minor__ | $compiler -E -x c - | tail -n 1)
-PATCHLEVEL=$(echo __clang_patchlevel__ | $compiler -E -x c - | tail -n 1)
-printf "%d%02d%02d\\n" $MAJOR $MINOR $PATCHLEVEL
diff --git a/scripts/coccicheck b/scripts/coccicheck
index 209bb0427b43..65fee63aeadb 100755
--- a/scripts/coccicheck
+++ b/scripts/coccicheck
@@ -16,7 +16,6 @@ if [ ! -x "$SPATCH" ]; then
fi
SPATCH_VERSION=$($SPATCH --version | head -1 | awk '{print $3}')
-SPATCH_VERSION_NUM=$(echo $SPATCH_VERSION | ${DIR}/scripts/ld-version.sh)
USE_JOBS="no"
$SPATCH --help | grep "\-\-jobs" > /dev/null && USE_JOBS="yes"
@@ -61,6 +60,18 @@ COCCIINCLUDE=${COCCIINCLUDE// -include/ --include}
if [ "$C" = "1" -o "$C" = "2" ]; then
ONLINE=1
+ if [[ $# -le 0 ]]; then
+ echo ''
+ echo 'Specifying both the variable "C" and rule "coccicheck" in the make
+command results in a shift count error.'
+ echo ''
+ echo 'Try specifying "scripts/coccicheck" as a value for the CHECK variable instead.'
+ echo ''
+ echo 'Example: make C=2 CHECK=scripts/coccicheck drivers/net/ethernet/ethoc.o'
+ echo ''
+ exit 1
+ fi
+
# Take only the last argument, which is the C file to test
shift $(( $# - 1 ))
OPTIONS="$COCCIINCLUDE $1"
@@ -186,14 +197,11 @@ coccinelle () {
OPT=`grep "Options:" $COCCI | cut -d':' -f2`
REQ=`grep "Requires:" $COCCI | cut -d':' -f2 | sed "s| ||"`
- REQ_NUM=$(echo $REQ | ${DIR}/scripts/ld-version.sh)
- if [ "$REQ_NUM" != "0" ] ; then
- if [ "$SPATCH_VERSION_NUM" -lt "$REQ_NUM" ] ; then
- echo "Skipping coccinelle SmPL patch: $COCCI"
- echo "You have coccinelle: $SPATCH_VERSION"
- echo "This SmPL patch requires: $REQ"
- return
- fi
+ if [ -n "$REQ" ] && ! { echo "$REQ"; echo "$SPATCH_VERSION"; } | sort -CV ; then
+ echo "Skipping coccinelle SmPL patch: $COCCI"
+ echo "You have coccinelle: $SPATCH_VERSION"
+ echo "This SmPL patch requires: $REQ"
+ return
fi
# The option '--parse-cocci' can be used to syntactically check the SmPL files.
diff --git a/scripts/coccinelle/api/ptr_ret.cocci b/scripts/coccinelle/api/ptr_ret.cocci
deleted file mode 100644
index e76cd5d90a8a..000000000000
--- a/scripts/coccinelle/api/ptr_ret.cocci
+++ /dev/null
@@ -1,97 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-///
-/// Use PTR_ERR_OR_ZERO rather than if(IS_ERR(...)) + PTR_ERR
-///
-// Confidence: High
-// Copyright: (C) 2012 Julia Lawall, INRIA/LIP6.
-// Copyright: (C) 2012 Gilles Muller, INRIA/LiP6.
-// URL: http://coccinelle.lip6.fr/
-// Options: --no-includes --include-headers
-//
-// Keywords: ERR_PTR, PTR_ERR, PTR_ERR_OR_ZERO
-// Version min: 2.6.39
-//
-
-virtual context
-virtual patch
-virtual org
-virtual report
-
-@depends on patch@
-expression ptr;
-@@
-
-- if (IS_ERR(ptr)) return PTR_ERR(ptr); else return 0;
-+ return PTR_ERR_OR_ZERO(ptr);
-
-@depends on patch@
-expression ptr;
-@@
-
-- if (IS_ERR(ptr)) return PTR_ERR(ptr); return 0;
-+ return PTR_ERR_OR_ZERO(ptr);
-
-@depends on patch@
-expression ptr;
-@@
-
-- (IS_ERR(ptr) ? PTR_ERR(ptr) : 0)
-+ PTR_ERR_OR_ZERO(ptr)
-
-@r1 depends on !patch@
-expression ptr;
-position p1;
-@@
-
-* if@p1 (IS_ERR(ptr)) return PTR_ERR(ptr); else return 0;
-
-@r2 depends on !patch@
-expression ptr;
-position p2;
-@@
-
-* if@p2 (IS_ERR(ptr)) return PTR_ERR(ptr); return 0;
-
-@r3 depends on !patch@
-expression ptr;
-position p3;
-@@
-
-* IS_ERR@p3(ptr) ? PTR_ERR(ptr) : 0
-
-@script:python depends on org@
-p << r1.p1;
-@@
-
-coccilib.org.print_todo(p[0], "WARNING: PTR_ERR_OR_ZERO can be used")
-
-
-@script:python depends on org@
-p << r2.p2;
-@@
-
-coccilib.org.print_todo(p[0], "WARNING: PTR_ERR_OR_ZERO can be used")
-
-@script:python depends on org@
-p << r3.p3;
-@@
-
-coccilib.org.print_todo(p[0], "WARNING: PTR_ERR_OR_ZERO can be used")
-
-@script:python depends on report@
-p << r1.p1;
-@@
-
-coccilib.report.print_report(p[0], "WARNING: PTR_ERR_OR_ZERO can be used")
-
-@script:python depends on report@
-p << r2.p2;
-@@
-
-coccilib.report.print_report(p[0], "WARNING: PTR_ERR_OR_ZERO can be used")
-
-@script:python depends on report@
-p << r3.p3;
-@@
-
-coccilib.report.print_report(p[0], "WARNING: PTR_ERR_OR_ZERO can be used")
diff --git a/scripts/coccinelle/free/put_device.cocci b/scripts/coccinelle/free/put_device.cocci
index 120921366e84..f09f1e79bfa6 100644
--- a/scripts/coccinelle/free/put_device.cocci
+++ b/scripts/coccinelle/free/put_device.cocci
@@ -21,7 +21,6 @@ id = of_find_device_by_node@p1(x)
if (id == NULL || ...) { ... return ...; }
... when != put_device(&id->dev)
when != platform_device_put(id)
- when != of_dev_put(id)
when != if (id) { ... put_device(&id->dev) ... }
when != e1 = (T)id
when != e1 = (T)(&id->dev)
diff --git a/scripts/coccinelle/misc/boolinit.cocci b/scripts/coccinelle/misc/boolinit.cocci
deleted file mode 100644
index fed6126e2b9d..000000000000
--- a/scripts/coccinelle/misc/boolinit.cocci
+++ /dev/null
@@ -1,195 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/// Bool initializations should use true and false. Bool tests don't need
-/// comparisons. Based on contributions from Joe Perches, Rusty Russell
-/// and Bruce W Allan.
-///
-// Confidence: High
-// Copyright: (C) 2012 Julia Lawall, INRIA/LIP6.
-// Copyright: (C) 2012 Gilles Muller, INRIA/LiP6.
-// URL: http://coccinelle.lip6.fr/
-// Options: --include-headers
-
-virtual patch
-virtual context
-virtual org
-virtual report
-
-@boolok@
-symbol true,false;
-@@
-(
-true
-|
-false
-)
-
-@depends on patch@
-bool t;
-@@
-
-(
-- t == true
-+ t
-|
-- true == t
-+ t
-|
-- t != true
-+ !t
-|
-- true != t
-+ !t
-|
-- t == false
-+ !t
-|
-- false == t
-+ !t
-|
-- t != false
-+ t
-|
-- false != t
-+ t
-)
-
-@depends on patch disable is_zero, isnt_zero@
-bool t;
-@@
-
-(
-- t == 1
-+ t
-|
-- t != 1
-+ !t
-|
-- t == 0
-+ !t
-|
-- t != 0
-+ t
-)
-
-@depends on patch && boolok@
-bool b;
-@@
-(
- b =
-- 0
-+ false
-|
- b =
-- 1
-+ true
-)
-
-// ---------------------------------------------------------------------
-
-@r1 depends on !patch@
-bool t;
-position p;
-@@
-
-(
-* t@p == true
-|
-* true == t@p
-|
-* t@p != true
-|
-* true != t@p
-|
-* t@p == false
-|
-* false == t@p
-|
-* t@p != false
-|
-* false != t@p
-)
-
-@r2 depends on !patch disable is_zero, isnt_zero@
-bool t;
-position p;
-@@
-
-(
-* t@p == 1
-|
-* t@p != 1
-|
-* t@p == 0
-|
-* t@p != 0
-)
-
-@r3 depends on !patch && boolok@
-bool b;
-position p1;
-@@
-(
-*b@p1 = 0
-|
-*b@p1 = 1
-)
-
-@r4 depends on !patch@
-bool b;
-position p2;
-identifier i;
-constant c != {0,1};
-@@
-(
- b = i
-|
-*b@p2 = c
-)
-
-@script:python depends on org@
-p << r1.p;
-@@
-
-cocci.print_main("WARNING: Comparison to bool",p)
-
-@script:python depends on org@
-p << r2.p;
-@@
-
-cocci.print_main("WARNING: Comparison of 0/1 to bool variable",p)
-
-@script:python depends on org@
-p1 << r3.p1;
-@@
-
-cocci.print_main("WARNING: Assignment of 0/1 to bool variable",p1)
-
-@script:python depends on org@
-p2 << r4.p2;
-@@
-
-cocci.print_main("ERROR: Assignment of non-0/1 constant to bool variable",p2)
-
-@script:python depends on report@
-p << r1.p;
-@@
-
-coccilib.report.print_report(p[0],"WARNING: Comparison to bool")
-
-@script:python depends on report@
-p << r2.p;
-@@
-
-coccilib.report.print_report(p[0],"WARNING: Comparison of 0/1 to bool variable")
-
-@script:python depends on report@
-p1 << r3.p1;
-@@
-
-coccilib.report.print_report(p1[0],"WARNING: Assignment of 0/1 to bool variable")
-
-@script:python depends on report@
-p2 << r4.p2;
-@@
-
-coccilib.report.print_report(p2[0],"ERROR: Assignment of non-0/1 constant to bool variable")
diff --git a/scripts/config b/scripts/config
index eee5b7f3a092..ff88e2faefd3 100755
--- a/scripts/config
+++ b/scripts/config
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/usr/bin/env bash
# SPDX-License-Identifier: GPL-2.0
# Manipulate options in a .config file from the command line
@@ -223,6 +223,7 @@ while [ "$1" != "" ] ; do
;;
*)
+ echo "bad command: $CMD" >&2
usage
;;
esac
diff --git a/scripts/depmod.sh b/scripts/depmod.sh
index e083bcae343f..3643b4f896ed 100755
--- a/scripts/depmod.sh
+++ b/scripts/depmod.sh
@@ -15,6 +15,8 @@ if ! test -r System.map ; then
exit 0
fi
+# legacy behavior: "depmod" in /sbin, no /sbin in PATH
+PATH="$PATH:/sbin"
if [ -z $(command -v $DEPMOD) ]; then
echo "Warning: 'make modules_install' requires $DEPMOD. Please install it." >&2
echo "This is probably in the kmod package." >&2
diff --git a/scripts/diffconfig b/scripts/diffconfig
index 89abf777f197..d5da5fa05d1d 100755
--- a/scripts/diffconfig
+++ b/scripts/diffconfig
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
# SPDX-License-Identifier: GPL-2.0
#
# diffconfig - a tool to compare .config files.
diff --git a/scripts/dtc/.gitignore b/scripts/dtc/.gitignore
index b814e6076bdb..8a8b62bf3d3c 100644
--- a/scripts/dtc/.gitignore
+++ b/scripts/dtc/.gitignore
@@ -1,2 +1,3 @@
# SPDX-License-Identifier: GPL-2.0-only
dtc
+fdtoverlay
diff --git a/scripts/dtc/Makefile b/scripts/dtc/Makefile
index 4852bf44e913..95aaf7431bff 100644
--- a/scripts/dtc/Makefile
+++ b/scripts/dtc/Makefile
@@ -1,13 +1,20 @@
# SPDX-License-Identifier: GPL-2.0
# scripts/dtc makefile
-hostprogs-always-$(CONFIG_DTC) += dtc
+# *** Also keep .gitignore in sync when changing ***
+hostprogs-always-$(CONFIG_DTC) += dtc fdtoverlay
hostprogs-always-$(CHECK_DT_BINDING) += dtc
dtc-objs := dtc.o flattree.o fstree.o data.o livetree.o treesource.o \
srcpos.o checks.o util.o
dtc-objs += dtc-lexer.lex.o dtc-parser.tab.o
+# The upstream project builds libfdt as a separate library. We are choosing to
+# instead directly link the libfdt object files into fdtoverlay.
+libfdt-objs := fdt.o fdt_ro.o fdt_wip.o fdt_sw.o fdt_rw.o fdt_strerror.o fdt_empty_tree.o fdt_addresses.o fdt_overlay.o
+libfdt = $(addprefix libfdt/,$(libfdt-objs))
+fdtoverlay-objs := $(libfdt) fdtoverlay.o util.o
+
# Source files need to get at the userspace version of libfdt_env.h to compile
HOST_EXTRACFLAGS += -I $(srctree)/$(src)/libfdt
diff --git a/scripts/dtc/data.c b/scripts/dtc/data.c
index 0a43b6de3264..14734233ad8b 100644
--- a/scripts/dtc/data.c
+++ b/scripts/dtc/data.c
@@ -21,10 +21,10 @@ void data_free(struct data d)
free(d.val);
}
-struct data data_grow_for(struct data d, int xlen)
+struct data data_grow_for(struct data d, unsigned int xlen)
{
struct data nd;
- int newsize;
+ unsigned int newsize;
if (xlen == 0)
return d;
@@ -84,7 +84,7 @@ struct data data_copy_file(FILE *f, size_t maxlen)
while (!feof(f) && (d.len < maxlen)) {
size_t chunksize, ret;
- if (maxlen == -1)
+ if (maxlen == (size_t)-1)
chunksize = 4096;
else
chunksize = maxlen - d.len;
diff --git a/scripts/dtc/dtc.c b/scripts/dtc/dtc.c
index bdb3f5945699..838c5df96c00 100644
--- a/scripts/dtc/dtc.c
+++ b/scripts/dtc/dtc.c
@@ -122,6 +122,8 @@ static const char *guess_type_by_name(const char *fname, const char *fallback)
return "dts";
if (!strcasecmp(s, ".yaml"))
return "yaml";
+ if (!strcasecmp(s, ".dtbo"))
+ return "dtb";
if (!strcasecmp(s, ".dtb"))
return "dtb";
return fallback;
@@ -357,6 +359,8 @@ int main(int argc, char *argv[])
#endif
} else if (streq(outform, "dtb")) {
dt_to_blob(outf, dti, outversion);
+ } else if (streq(outform, "dtbo")) {
+ dt_to_blob(outf, dti, outversion);
} else if (streq(outform, "asm")) {
dt_to_asm(outf, dti, outversion);
} else if (streq(outform, "null")) {
diff --git a/scripts/dtc/dtc.h b/scripts/dtc/dtc.h
index a08f4159cd03..d3e82fb8e3db 100644
--- a/scripts/dtc/dtc.h
+++ b/scripts/dtc/dtc.h
@@ -105,13 +105,13 @@ extern const char *markername(enum markertype markertype);
struct marker {
enum markertype type;
- int offset;
+ unsigned int offset;
char *ref;
struct marker *next;
};
struct data {
- int len;
+ unsigned int len;
char *val;
struct marker *markers;
};
@@ -129,7 +129,7 @@ size_t type_marker_length(struct marker *m);
void data_free(struct data d);
-struct data data_grow_for(struct data d, int xlen);
+struct data data_grow_for(struct data d, unsigned int xlen);
struct data data_copy_mem(const char *mem, int len);
struct data data_copy_escape_string(const char *s, int len);
@@ -253,7 +253,7 @@ void append_to_property(struct node *node,
const char *get_unitname(struct node *node);
struct property *get_property(struct node *node, const char *propname);
cell_t propval_cell(struct property *prop);
-cell_t propval_cell_n(struct property *prop, int n);
+cell_t propval_cell_n(struct property *prop, unsigned int n);
struct property *get_property_by_label(struct node *tree, const char *label,
struct node **node);
struct marker *get_marker_label(struct node *tree, const char *label,
diff --git a/scripts/dtc/fdtdump.c b/scripts/dtc/fdtdump.c
deleted file mode 100644
index 7d460a50b513..000000000000
--- a/scripts/dtc/fdtdump.c
+++ /dev/null
@@ -1,163 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * fdtdump.c - Contributed by Pantelis Antoniou <pantelis.antoniou AT gmail.com>
- */
-
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-
-#include <fdt.h>
-#include <libfdt_env.h>
-
-#include "util.h"
-
-#define ALIGN(x, a) (((x) + ((a) - 1)) & ~((a) - 1))
-#define PALIGN(p, a) ((void *)(ALIGN((unsigned long)(p), (a))))
-#define GET_CELL(p) (p += 4, *((const uint32_t *)(p-4)))
-
-static void print_data(const char *data, int len)
-{
- int i;
- const char *p = data;
-
- /* no data, don't print */
- if (len == 0)
- return;
-
- if (util_is_printable_string(data, len)) {
- printf(" = \"%s\"", (const char *)data);
- } else if ((len % 4) == 0) {
- printf(" = <");
- for (i = 0; i < len; i += 4)
- printf("0x%08x%s", fdt32_to_cpu(GET_CELL(p)),
- i < (len - 4) ? " " : "");
- printf(">");
- } else {
- printf(" = [");
- for (i = 0; i < len; i++)
- printf("%02x%s", *p++, i < len - 1 ? " " : "");
- printf("]");
- }
-}
-
-static void dump_blob(void *blob)
-{
- struct fdt_header *bph = blob;
- uint32_t off_mem_rsvmap = fdt32_to_cpu(bph->off_mem_rsvmap);
- uint32_t off_dt = fdt32_to_cpu(bph->off_dt_struct);
- uint32_t off_str = fdt32_to_cpu(bph->off_dt_strings);
- struct fdt_reserve_entry *p_rsvmap =
- (struct fdt_reserve_entry *)((char *)blob + off_mem_rsvmap);
- const char *p_struct = (const char *)blob + off_dt;
- const char *p_strings = (const char *)blob + off_str;
- uint32_t version = fdt32_to_cpu(bph->version);
- uint32_t totalsize = fdt32_to_cpu(bph->totalsize);
- uint32_t tag;
- const char *p, *s, *t;
- int depth, sz, shift;
- int i;
- uint64_t addr, size;
-
- depth = 0;
- shift = 4;
-
- printf("/dts-v1/;\n");
- printf("// magic:\t\t0x%x\n", fdt32_to_cpu(bph->magic));
- printf("// totalsize:\t\t0x%x (%d)\n", totalsize, totalsize);
- printf("// off_dt_struct:\t0x%x\n", off_dt);
- printf("// off_dt_strings:\t0x%x\n", off_str);
- printf("// off_mem_rsvmap:\t0x%x\n", off_mem_rsvmap);
- printf("// version:\t\t%d\n", version);
- printf("// last_comp_version:\t%d\n",
- fdt32_to_cpu(bph->last_comp_version));
- if (version >= 2)
- printf("// boot_cpuid_phys:\t0x%x\n",
- fdt32_to_cpu(bph->boot_cpuid_phys));
-
- if (version >= 3)
- printf("// size_dt_strings:\t0x%x\n",
- fdt32_to_cpu(bph->size_dt_strings));
- if (version >= 17)
- printf("// size_dt_struct:\t0x%x\n",
- fdt32_to_cpu(bph->size_dt_struct));
- printf("\n");
-
- for (i = 0; ; i++) {
- addr = fdt64_to_cpu(p_rsvmap[i].address);
- size = fdt64_to_cpu(p_rsvmap[i].size);
- if (addr == 0 && size == 0)
- break;
-
- printf("/memreserve/ %llx %llx;\n",
- (unsigned long long)addr, (unsigned long long)size);
- }
-
- p = p_struct;
- while ((tag = fdt32_to_cpu(GET_CELL(p))) != FDT_END) {
-
- /* printf("tag: 0x%08x (%d)\n", tag, p - p_struct); */
-
- if (tag == FDT_BEGIN_NODE) {
- s = p;
- p = PALIGN(p + strlen(s) + 1, 4);
-
- if (*s == '\0')
- s = "/";
-
- printf("%*s%s {\n", depth * shift, "", s);
-
- depth++;
- continue;
- }
-
- if (tag == FDT_END_NODE) {
- depth--;
-
- printf("%*s};\n", depth * shift, "");
- continue;
- }
-
- if (tag == FDT_NOP) {
- printf("%*s// [NOP]\n", depth * shift, "");
- continue;
- }
-
- if (tag != FDT_PROP) {
- fprintf(stderr, "%*s ** Unknown tag 0x%08x\n", depth * shift, "", tag);
- break;
- }
- sz = fdt32_to_cpu(GET_CELL(p));
- s = p_strings + fdt32_to_cpu(GET_CELL(p));
- if (version < 16 && sz >= 8)
- p = PALIGN(p, 8);
- t = p;
-
- p = PALIGN(p + sz, 4);
-
- printf("%*s%s", depth * shift, "", s);
- print_data(t, sz);
- printf(";\n");
- }
-}
-
-
-int main(int argc, char *argv[])
-{
- char *buf;
-
- if (argc < 2) {
- fprintf(stderr, "supply input filename\n");
- return 5;
- }
-
- buf = utilfdt_read(argv[1]);
- if (buf)
- dump_blob(buf);
- else
- return 10;
-
- return 0;
-}
diff --git a/scripts/dtc/fdtoverlay.c b/scripts/dtc/fdtoverlay.c
new file mode 100644
index 000000000000..5350af65679f
--- /dev/null
+++ b/scripts/dtc/fdtoverlay.c
@@ -0,0 +1,208 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2017 Konsulko Group Inc. All rights reserved.
+ *
+ * Author:
+ * Pantelis Antoniou <pantelis.antoniou@konsulko.com>
+ */
+
+#include <assert.h>
+#include <ctype.h>
+#include <getopt.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <inttypes.h>
+
+#include <libfdt.h>
+
+#include "util.h"
+
+#define BUF_INCREMENT 65536
+
+/* Usage related data. */
+static const char usage_synopsis[] =
+ "apply a number of overlays to a base blob\n"
+ " fdtoverlay <options> [<overlay.dtbo> [<overlay.dtbo>]]\n"
+ "\n"
+ USAGE_TYPE_MSG;
+static const char usage_short_opts[] = "i:o:v" USAGE_COMMON_SHORT_OPTS;
+static struct option const usage_long_opts[] = {
+ {"input", required_argument, NULL, 'i'},
+ {"output", required_argument, NULL, 'o'},
+ {"verbose", no_argument, NULL, 'v'},
+ USAGE_COMMON_LONG_OPTS,
+};
+static const char * const usage_opts_help[] = {
+ "Input base DT blob",
+ "Output DT blob",
+ "Verbose messages",
+ USAGE_COMMON_OPTS_HELP
+};
+
+int verbose = 0;
+
+static void *apply_one(char *base, const char *overlay, size_t *buf_len,
+ const char *name)
+{
+ char *tmp = NULL;
+ char *tmpo;
+ int ret;
+
+ /*
+ * We take a copies first, because a a failed apply can trash
+ * both the base blob and the overlay
+ */
+ tmpo = xmalloc(fdt_totalsize(overlay));
+
+ do {
+ tmp = xrealloc(tmp, *buf_len);
+ ret = fdt_open_into(base, tmp, *buf_len);
+ if (ret) {
+ fprintf(stderr,
+ "\nFailed to make temporary copy: %s\n",
+ fdt_strerror(ret));
+ goto fail;
+ }
+
+ memcpy(tmpo, overlay, fdt_totalsize(overlay));
+
+ ret = fdt_overlay_apply(tmp, tmpo);
+ if (ret == -FDT_ERR_NOSPACE) {
+ *buf_len += BUF_INCREMENT;
+ }
+ } while (ret == -FDT_ERR_NOSPACE);
+
+ if (ret) {
+ fprintf(stderr, "\nFailed to apply '%s': %s\n",
+ name, fdt_strerror(ret));
+ goto fail;
+ }
+
+ free(base);
+ free(tmpo);
+ return tmp;
+
+fail:
+ free(tmpo);
+ if (tmp)
+ free(tmp);
+
+ return NULL;
+}
+static int do_fdtoverlay(const char *input_filename,
+ const char *output_filename,
+ int argc, char *argv[])
+{
+ char *blob = NULL;
+ char **ovblob = NULL;
+ size_t buf_len;
+ int i, ret = -1;
+
+ blob = utilfdt_read(input_filename, &buf_len);
+ if (!blob) {
+ fprintf(stderr, "\nFailed to read '%s'\n", input_filename);
+ goto out_err;
+ }
+ if (fdt_totalsize(blob) > buf_len) {
+ fprintf(stderr,
+ "\nBase blob is incomplete (%lu / %" PRIu32 " bytes read)\n",
+ (unsigned long)buf_len, fdt_totalsize(blob));
+ goto out_err;
+ }
+
+ /* allocate blob pointer array */
+ ovblob = xmalloc(sizeof(*ovblob) * argc);
+ memset(ovblob, 0, sizeof(*ovblob) * argc);
+
+ /* read and keep track of the overlay blobs */
+ for (i = 0; i < argc; i++) {
+ size_t ov_len;
+ ovblob[i] = utilfdt_read(argv[i], &ov_len);
+ if (!ovblob[i]) {
+ fprintf(stderr, "\nFailed to read '%s'\n", argv[i]);
+ goto out_err;
+ }
+ if (fdt_totalsize(ovblob[i]) > ov_len) {
+ fprintf(stderr,
+"\nOverlay '%s' is incomplete (%lu / %" PRIu32 " bytes read)\n",
+ argv[i], (unsigned long)ov_len,
+ fdt_totalsize(ovblob[i]));
+ goto out_err;
+ }
+ }
+
+ buf_len = fdt_totalsize(blob);
+
+ /* apply the overlays in sequence */
+ for (i = 0; i < argc; i++) {
+ blob = apply_one(blob, ovblob[i], &buf_len, argv[i]);
+ if (!blob)
+ goto out_err;
+ }
+
+ fdt_pack(blob);
+ ret = utilfdt_write(output_filename, blob);
+ if (ret)
+ fprintf(stderr, "\nFailed to write '%s'\n",
+ output_filename);
+
+out_err:
+ if (ovblob) {
+ for (i = 0; i < argc; i++) {
+ if (ovblob[i])
+ free(ovblob[i]);
+ }
+ free(ovblob);
+ }
+ free(blob);
+
+ return ret;
+}
+
+int main(int argc, char *argv[])
+{
+ int opt, i;
+ char *input_filename = NULL;
+ char *output_filename = NULL;
+
+ while ((opt = util_getopt_long()) != EOF) {
+ switch (opt) {
+ case_USAGE_COMMON_FLAGS
+
+ case 'i':
+ input_filename = optarg;
+ break;
+ case 'o':
+ output_filename = optarg;
+ break;
+ case 'v':
+ verbose = 1;
+ break;
+ }
+ }
+
+ if (!input_filename)
+ usage("missing input file");
+
+ if (!output_filename)
+ usage("missing output file");
+
+ argv += optind;
+ argc -= optind;
+
+ if (argc <= 0)
+ usage("missing overlay file(s)");
+
+ if (verbose) {
+ printf("input = %s\n", input_filename);
+ printf("output = %s\n", output_filename);
+ for (i = 0; i < argc; i++)
+ printf("overlay[%d] = %s\n", i, argv[i]);
+ }
+
+ if (do_fdtoverlay(input_filename, output_filename, argc, argv))
+ return 1;
+
+ return 0;
+}
diff --git a/scripts/dtc/flattree.c b/scripts/dtc/flattree.c
index 07f10d2b5d79..4659afbfcbab 100644
--- a/scripts/dtc/flattree.c
+++ b/scripts/dtc/flattree.c
@@ -149,7 +149,7 @@ static void asm_emit_align(void *e, int a)
static void asm_emit_data(void *e, struct data d)
{
FILE *f = e;
- int off = 0;
+ unsigned int off = 0;
struct marker *m = d.markers;
for_each_marker_of_type(m, LABEL)
@@ -219,7 +219,7 @@ static struct emitter asm_emitter = {
static int stringtable_insert(struct data *d, const char *str)
{
- int i;
+ unsigned int i;
/* FIXME: do this more efficiently? */
@@ -345,7 +345,7 @@ static void make_fdt_header(struct fdt_header *fdt,
void dt_to_blob(FILE *f, struct dt_info *dti, int version)
{
struct version_info *vi = NULL;
- int i;
+ unsigned int i;
struct data blob = empty_data;
struct data reservebuf = empty_data;
struct data dtbuf = empty_data;
@@ -446,7 +446,7 @@ static void dump_stringtable_asm(FILE *f, struct data strbuf)
void dt_to_asm(FILE *f, struct dt_info *dti, int version)
{
struct version_info *vi = NULL;
- int i;
+ unsigned int i;
struct data strbuf = empty_data;
struct reserve_info *re;
const char *symprefix = "dt";
diff --git a/scripts/dtc/include-prefixes/c6x b/scripts/dtc/include-prefixes/c6x
deleted file mode 120000
index 49ded4cae2be..000000000000
--- a/scripts/dtc/include-prefixes/c6x
+++ /dev/null
@@ -1 +0,0 @@
-../../../arch/c6x/boot/dts \ No newline at end of file
diff --git a/scripts/dtc/libfdt/fdt.c b/scripts/dtc/libfdt/fdt.c
index 6cf2fa03b037..3e893073da05 100644
--- a/scripts/dtc/libfdt/fdt.c
+++ b/scripts/dtc/libfdt/fdt.c
@@ -22,6 +22,10 @@ int32_t fdt_ro_probe_(const void *fdt)
if (can_assume(VALID_DTB))
return totalsize;
+ /* The device tree must be at an 8-byte aligned address */
+ if ((uintptr_t)fdt & 7)
+ return -FDT_ERR_ALIGNMENT;
+
if (fdt_magic(fdt) == FDT_MAGIC) {
/* Complete tree */
if (!can_assume(LATEST)) {
diff --git a/scripts/dtc/libfdt/fdt_ro.c b/scripts/dtc/libfdt/fdt_ro.c
index 91cc6fefe374..17584da25760 100644
--- a/scripts/dtc/libfdt/fdt_ro.c
+++ b/scripts/dtc/libfdt/fdt_ro.c
@@ -181,8 +181,8 @@ int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size)
if (!can_assume(VALID_INPUT) && !re)
return -FDT_ERR_BADOFFSET;
- *address = fdt64_ld(&re->address);
- *size = fdt64_ld(&re->size);
+ *address = fdt64_ld_(&re->address);
+ *size = fdt64_ld_(&re->size);
return 0;
}
@@ -192,7 +192,7 @@ int fdt_num_mem_rsv(const void *fdt)
const struct fdt_reserve_entry *re;
for (i = 0; (re = fdt_mem_rsv(fdt, i)) != NULL; i++) {
- if (fdt64_ld(&re->size) == 0)
+ if (fdt64_ld_(&re->size) == 0)
return i;
}
return -FDT_ERR_TRUNCATED;
@@ -370,7 +370,7 @@ static const struct fdt_property *fdt_get_property_by_offset_(const void *fdt,
prop = fdt_offset_ptr_(fdt, offset);
if (lenp)
- *lenp = fdt32_ld(&prop->len);
+ *lenp = fdt32_ld_(&prop->len);
return prop;
}
@@ -408,7 +408,7 @@ static const struct fdt_property *fdt_get_property_namelen_(const void *fdt,
offset = -FDT_ERR_INTERNAL;
break;
}
- if (fdt_string_eq_(fdt, fdt32_ld(&prop->nameoff),
+ if (fdt_string_eq_(fdt, fdt32_ld_(&prop->nameoff),
name, namelen)) {
if (poffset)
*poffset = offset;
@@ -461,7 +461,7 @@ const void *fdt_getprop_namelen(const void *fdt, int nodeoffset,
/* Handle realignment */
if (!can_assume(LATEST) && fdt_version(fdt) < 0x10 &&
- (poffset + sizeof(*prop)) % 8 && fdt32_ld(&prop->len) >= 8)
+ (poffset + sizeof(*prop)) % 8 && fdt32_ld_(&prop->len) >= 8)
return prop->data + 4;
return prop->data;
}
@@ -479,7 +479,7 @@ const void *fdt_getprop_by_offset(const void *fdt, int offset,
int namelen;
if (!can_assume(VALID_INPUT)) {
- name = fdt_get_string(fdt, fdt32_ld(&prop->nameoff),
+ name = fdt_get_string(fdt, fdt32_ld_(&prop->nameoff),
&namelen);
if (!name) {
if (lenp)
@@ -488,13 +488,13 @@ const void *fdt_getprop_by_offset(const void *fdt, int offset,
}
*namep = name;
} else {
- *namep = fdt_string(fdt, fdt32_ld(&prop->nameoff));
+ *namep = fdt_string(fdt, fdt32_ld_(&prop->nameoff));
}
}
/* Handle realignment */
if (!can_assume(LATEST) && fdt_version(fdt) < 0x10 &&
- (offset + sizeof(*prop)) % 8 && fdt32_ld(&prop->len) >= 8)
+ (offset + sizeof(*prop)) % 8 && fdt32_ld_(&prop->len) >= 8)
return prop->data + 4;
return prop->data;
}
@@ -519,7 +519,7 @@ uint32_t fdt_get_phandle(const void *fdt, int nodeoffset)
return 0;
}
- return fdt32_ld(php);
+ return fdt32_ld_(php);
}
const char *fdt_get_alias_namelen(const void *fdt,
diff --git a/scripts/dtc/libfdt/fdt_rw.c b/scripts/dtc/libfdt/fdt_rw.c
index 68887b969a45..f13458d165d4 100644
--- a/scripts/dtc/libfdt/fdt_rw.c
+++ b/scripts/dtc/libfdt/fdt_rw.c
@@ -428,12 +428,14 @@ int fdt_open_into(const void *fdt, void *buf, int bufsize)
if (can_assume(LATEST) || fdt_version(fdt) >= 17) {
struct_size = fdt_size_dt_struct(fdt);
- } else {
+ } else if (fdt_version(fdt) == 16) {
struct_size = 0;
while (fdt_next_tag(fdt, struct_size, &struct_size) != FDT_END)
;
if (struct_size < 0)
return struct_size;
+ } else {
+ return -FDT_ERR_BADVERSION;
}
if (can_assume(LIBFDT_ORDER) ||
diff --git a/scripts/dtc/libfdt/fdt_sw.c b/scripts/dtc/libfdt/fdt_sw.c
index 68b543c4dfa2..4c569ee7eb0d 100644
--- a/scripts/dtc/libfdt/fdt_sw.c
+++ b/scripts/dtc/libfdt/fdt_sw.c
@@ -377,7 +377,7 @@ int fdt_finish(void *fdt)
fdt_set_totalsize(fdt, newstroffset + fdt_size_dt_strings(fdt));
/* And fix up fields that were keeping intermediate state. */
- fdt_set_last_comp_version(fdt, FDT_FIRST_SUPPORTED_VERSION);
+ fdt_set_last_comp_version(fdt, FDT_LAST_COMPATIBLE_VERSION);
fdt_set_magic(fdt, FDT_MAGIC);
return 0;
diff --git a/scripts/dtc/libfdt/libfdt.h b/scripts/dtc/libfdt/libfdt.h
index fe49b5d78938..c42807a7663e 100644
--- a/scripts/dtc/libfdt/libfdt.h
+++ b/scripts/dtc/libfdt/libfdt.h
@@ -14,6 +14,7 @@ extern "C" {
#endif
#define FDT_FIRST_SUPPORTED_VERSION 0x02
+#define FDT_LAST_COMPATIBLE_VERSION 0x10
#define FDT_LAST_SUPPORTED_VERSION 0x11
/* Error codes: informative error codes */
@@ -101,7 +102,11 @@ extern "C" {
/* FDT_ERR_BADFLAGS: The function was passed a flags field that
* contains invalid flags or an invalid combination of flags. */
-#define FDT_ERR_MAX 18
+#define FDT_ERR_ALIGNMENT 19
+ /* FDT_ERR_ALIGNMENT: The device tree base address is not 8-byte
+ * aligned. */
+
+#define FDT_ERR_MAX 19
/* constants */
#define FDT_MAX_PHANDLE 0xfffffffe
@@ -122,12 +127,10 @@ static inline void *fdt_offset_ptr_w(void *fdt, int offset, int checklen)
uint32_t fdt_next_tag(const void *fdt, int offset, int *nextoffset);
/*
- * Alignment helpers:
- * These helpers access words from a device tree blob. They're
- * built to work even with unaligned pointers on platforms (ike
- * ARM) that don't like unaligned loads and stores
+ * External helpers to access words from a device tree blob. They're built
+ * to work even with unaligned pointers on platforms (such as ARMv5) that don't
+ * like unaligned loads and stores.
*/
-
static inline uint32_t fdt32_ld(const fdt32_t *p)
{
const uint8_t *bp = (const uint8_t *)p;
@@ -184,23 +187,23 @@ int fdt_next_node(const void *fdt, int offset, int *depth);
/**
* fdt_first_subnode() - get offset of first direct subnode
- *
* @fdt: FDT blob
* @offset: Offset of node to check
- * @return offset of first subnode, or -FDT_ERR_NOTFOUND if there is none
+ *
+ * Return: offset of first subnode, or -FDT_ERR_NOTFOUND if there is none
*/
int fdt_first_subnode(const void *fdt, int offset);
/**
* fdt_next_subnode() - get offset of next direct subnode
+ * @fdt: FDT blob
+ * @offset: Offset of previous subnode
*
* After first calling fdt_first_subnode(), call this function repeatedly to
* get direct subnodes of a parent node.
*
- * @fdt: FDT blob
- * @offset: Offset of previous subnode
- * @return offset of next subnode, or -FDT_ERR_NOTFOUND if there are no more
- * subnodes
+ * Return: offset of next subnode, or -FDT_ERR_NOTFOUND if there are no more
+ * subnodes
*/
int fdt_next_subnode(const void *fdt, int offset);
@@ -225,7 +228,6 @@ int fdt_next_subnode(const void *fdt, int offset);
* Note that this is implemented as a macro and @node is used as
* iterator in the loop. The parent variable be constant or even a
* literal.
- *
*/
#define fdt_for_each_subnode(node, fdt, parent) \
for (node = fdt_first_subnode(fdt, parent); \
@@ -269,17 +271,21 @@ fdt_set_hdr_(size_dt_struct);
/**
* fdt_header_size - return the size of the tree's header
* @fdt: pointer to a flattened device tree
+ *
+ * Return: size of DTB header in bytes
*/
size_t fdt_header_size(const void *fdt);
/**
- * fdt_header_size_ - internal function which takes a version number
+ * fdt_header_size_ - internal function to get header size from a version number
+ * @version: devicetree version number
+ *
+ * Return: size of DTB header in bytes
*/
size_t fdt_header_size_(uint32_t version);
/**
* fdt_check_header - sanity check a device tree header
-
* @fdt: pointer to data which might be a flattened device tree
*
* fdt_check_header() checks that the given buffer contains what
@@ -404,8 +410,7 @@ static inline uint32_t fdt_get_max_phandle(const void *fdt)
* highest phandle value in the device tree blob) will be returned in the
* @phandle parameter.
*
- * Returns:
- * 0 on success or a negative error-code on failure
+ * Return: 0 on success or a negative error-code on failure
*/
int fdt_generate_phandle(const void *fdt, uint32_t *phandle);
@@ -425,9 +430,11 @@ int fdt_num_mem_rsv(const void *fdt);
/**
* fdt_get_mem_rsv - retrieve one memory reserve map entry
* @fdt: pointer to the device tree blob
- * @address, @size: pointers to 64-bit variables
+ * @n: index of reserve map entry
+ * @address: pointer to 64-bit variable to hold the start address
+ * @size: pointer to 64-bit variable to hold the size of the entry
*
- * On success, *address and *size will contain the address and size of
+ * On success, @address and @size will contain the address and size of
* the n-th reserve map entry from the device tree blob, in
* native-endian format.
*
@@ -450,6 +457,8 @@ int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size);
* namelen characters of name for matching the subnode name. This is
* useful for finding subnodes based on a portion of a larger string,
* such as a full path.
+ *
+ * Return: offset of the subnode or -FDT_ERR_NOTFOUND if name not found.
*/
#ifndef SWIG /* Not available in Python */
int fdt_subnode_offset_namelen(const void *fdt, int parentoffset,
@@ -489,6 +498,8 @@ int fdt_subnode_offset(const void *fdt, int parentoffset, const char *name);
*
* Identical to fdt_path_offset(), but only consider the first namelen
* characters of path as the path name.
+ *
+ * Return: offset of the node or negative libfdt error value otherwise
*/
#ifndef SWIG /* Not available in Python */
int fdt_path_offset_namelen(const void *fdt, const char *path, int namelen);
@@ -588,9 +599,9 @@ int fdt_next_property_offset(const void *fdt, int offset);
/**
* fdt_for_each_property_offset - iterate over all properties of a node
*
- * @property_offset: property offset (int, lvalue)
- * @fdt: FDT blob (const void *)
- * @node: node offset (int)
+ * @property: property offset (int, lvalue)
+ * @fdt: FDT blob (const void *)
+ * @node: node offset (int)
*
* This is actually a wrapper around a for loop and would be used like so:
*
@@ -653,6 +664,9 @@ const struct fdt_property *fdt_get_property_by_offset(const void *fdt,
*
* Identical to fdt_get_property(), but only examine the first namelen
* characters of name for matching the property name.
+ *
+ * Return: pointer to the structure representing the property, or NULL
+ * if not found
*/
#ifndef SWIG /* Not available in Python */
const struct fdt_property *fdt_get_property_namelen(const void *fdt,
@@ -745,6 +759,8 @@ const void *fdt_getprop_by_offset(const void *fdt, int offset,
*
* Identical to fdt_getprop(), but only examine the first namelen
* characters of name for matching the property name.
+ *
+ * Return: pointer to the property's value or NULL on error
*/
#ifndef SWIG /* Not available in Python */
const void *fdt_getprop_namelen(const void *fdt, int nodeoffset,
@@ -766,10 +782,10 @@ static inline void *fdt_getprop_namelen_w(void *fdt, int nodeoffset,
* @lenp: pointer to an integer variable (will be overwritten) or NULL
*
* fdt_getprop() retrieves a pointer to the value of the property
- * named 'name' of the node at offset nodeoffset (this will be a
+ * named @name of the node at offset @nodeoffset (this will be a
* pointer to within the device blob itself, not a copy of the value).
- * If lenp is non-NULL, the length of the property value is also
- * returned, in the integer pointed to by lenp.
+ * If @lenp is non-NULL, the length of the property value is also
+ * returned, in the integer pointed to by @lenp.
*
* returns:
* pointer to the property's value
@@ -814,8 +830,11 @@ uint32_t fdt_get_phandle(const void *fdt, int nodeoffset);
* @name: name of the alias th look up
* @namelen: number of characters of name to consider
*
- * Identical to fdt_get_alias(), but only examine the first namelen
- * characters of name for matching the alias name.
+ * Identical to fdt_get_alias(), but only examine the first @namelen
+ * characters of @name for matching the alias name.
+ *
+ * Return: a pointer to the expansion of the alias named @name, if it exists,
+ * NULL otherwise
*/
#ifndef SWIG /* Not available in Python */
const char *fdt_get_alias_namelen(const void *fdt,
@@ -828,7 +847,7 @@ const char *fdt_get_alias_namelen(const void *fdt,
* @name: name of the alias th look up
*
* fdt_get_alias() retrieves the value of a given alias. That is, the
- * value of the property named 'name' in the node /aliases.
+ * value of the property named @name in the node /aliases.
*
* returns:
* a pointer to the expansion of the alias named 'name', if it exists
@@ -1004,14 +1023,13 @@ int fdt_node_offset_by_prop_value(const void *fdt, int startoffset,
int fdt_node_offset_by_phandle(const void *fdt, uint32_t phandle);
/**
- * fdt_node_check_compatible: check a node's compatible property
+ * fdt_node_check_compatible - check a node's compatible property
* @fdt: pointer to the device tree blob
* @nodeoffset: offset of a tree node
* @compatible: string to match against
*
- *
* fdt_node_check_compatible() returns 0 if the given node contains a
- * 'compatible' property with the given string as one of its elements,
+ * @compatible property with the given string as one of its elements,
* it returns non-zero otherwise, or on error.
*
* returns:
@@ -1075,7 +1093,7 @@ int fdt_node_offset_by_compatible(const void *fdt, int startoffset,
* one or more strings, each terminated by \0, as is found in a device tree
* "compatible" property.
*
- * @return: 1 if the string is found in the list, 0 not found, or invalid list
+ * Return: 1 if the string is found in the list, 0 not found, or invalid list
*/
int fdt_stringlist_contains(const char *strlist, int listlen, const char *str);
@@ -1084,7 +1102,8 @@ int fdt_stringlist_contains(const char *strlist, int listlen, const char *str);
* @fdt: pointer to the device tree blob
* @nodeoffset: offset of a tree node
* @property: name of the property containing the string list
- * @return:
+ *
+ * Return:
* the number of strings in the given property
* -FDT_ERR_BADVALUE if the property value is not NUL-terminated
* -FDT_ERR_NOTFOUND if the property does not exist
@@ -1104,7 +1123,7 @@ int fdt_stringlist_count(const void *fdt, int nodeoffset, const char *property);
* small-valued cell properties, such as #address-cells, when searching for
* the empty string.
*
- * @return:
+ * return:
* the index of the string in the list of strings
* -FDT_ERR_BADVALUE if the property value is not NUL-terminated
* -FDT_ERR_NOTFOUND if the property does not exist or does not contain
@@ -1128,7 +1147,7 @@ int fdt_stringlist_search(const void *fdt, int nodeoffset, const char *property,
* If non-NULL, the length of the string (on success) or a negative error-code
* (on failure) will be stored in the integer pointer to by lenp.
*
- * @return:
+ * Return:
* A pointer to the string at the given index in the string list or NULL on
* failure. On success the length of the string will be stored in the memory
* location pointed to by the lenp parameter, if non-NULL. On failure one of
@@ -1217,6 +1236,8 @@ int fdt_size_cells(const void *fdt, int nodeoffset);
* starting from the given index, and using only the first characters
* of the name. It is useful when you want to manipulate only one value of
* an array and you have a string that doesn't end with \0.
+ *
+ * Return: 0 on success, negative libfdt error value otherwise
*/
#ifndef SWIG /* Not available in Python */
int fdt_setprop_inplace_namelen_partial(void *fdt, int nodeoffset,
@@ -1330,8 +1351,13 @@ static inline int fdt_setprop_inplace_u64(void *fdt, int nodeoffset,
/**
* fdt_setprop_inplace_cell - change the value of a single-cell property
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node containing the property
+ * @name: name of the property to change the value of
+ * @val: new value of the 32-bit cell
*
* This is an alternative name for fdt_setprop_inplace_u32()
+ * Return: 0 on success, negative libfdt error number otherwise.
*/
static inline int fdt_setprop_inplace_cell(void *fdt, int nodeoffset,
const char *name, uint32_t val)
@@ -1403,7 +1429,7 @@ int fdt_nop_node(void *fdt, int nodeoffset);
/**
* fdt_create_with_flags - begin creation of a new fdt
- * @fdt: pointer to memory allocated where fdt will be created
+ * @buf: pointer to memory allocated where fdt will be created
* @bufsize: size of the memory space at fdt
* @flags: a valid combination of FDT_CREATE_FLAG_ flags, or 0.
*
@@ -1421,7 +1447,7 @@ int fdt_create_with_flags(void *buf, int bufsize, uint32_t flags);
/**
* fdt_create - begin creation of a new fdt
- * @fdt: pointer to memory allocated where fdt will be created
+ * @buf: pointer to memory allocated where fdt will be created
* @bufsize: size of the memory space at fdt
*
* fdt_create() is equivalent to fdt_create_with_flags() with flags=0.
@@ -1486,7 +1512,8 @@ int fdt_pack(void *fdt);
/**
* fdt_add_mem_rsv - add one memory reserve map entry
* @fdt: pointer to the device tree blob
- * @address, @size: 64-bit values (native endian)
+ * @address: 64-bit start address of the reserve map entry
+ * @size: 64-bit size of the reserved region
*
* Adds a reserve map entry to the given blob reserving a region at
* address address of length size.
@@ -1691,8 +1718,14 @@ static inline int fdt_setprop_u64(void *fdt, int nodeoffset, const char *name,
/**
* fdt_setprop_cell - set a property to a single cell value
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node whose property to change
+ * @name: name of the property to change
+ * @val: 32-bit integer value for the property (native endian)
*
* This is an alternative name for fdt_setprop_u32()
+ *
+ * Return: 0 on success, negative libfdt error value otherwise.
*/
static inline int fdt_setprop_cell(void *fdt, int nodeoffset, const char *name,
uint32_t val)
@@ -1863,8 +1896,14 @@ static inline int fdt_appendprop_u64(void *fdt, int nodeoffset,
/**
* fdt_appendprop_cell - append a single cell value to a property
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node whose property to change
+ * @name: name of the property to change
+ * @val: 32-bit integer value to append to the property (native endian)
*
* This is an alternative name for fdt_appendprop_u32()
+ *
+ * Return: 0 on success, negative libfdt error value otherwise.
*/
static inline int fdt_appendprop_cell(void *fdt, int nodeoffset,
const char *name, uint32_t val)
@@ -1967,13 +2006,16 @@ int fdt_delprop(void *fdt, int nodeoffset, const char *name);
* fdt_add_subnode_namelen - creates a new node based on substring
* @fdt: pointer to the device tree blob
* @parentoffset: structure block offset of a node
- * @name: name of the subnode to locate
+ * @name: name of the subnode to create
* @namelen: number of characters of name to consider
*
- * Identical to fdt_add_subnode(), but use only the first namelen
- * characters of name as the name of the new node. This is useful for
+ * Identical to fdt_add_subnode(), but use only the first @namelen
+ * characters of @name as the name of the new node. This is useful for
* creating subnodes based on a portion of a larger string, such as a
* full path.
+ *
+ * Return: structure block offset of the created subnode (>=0),
+ * negative libfdt error value otherwise
*/
#ifndef SWIG /* Not available in Python */
int fdt_add_subnode_namelen(void *fdt, int parentoffset,
@@ -1992,7 +2034,7 @@ int fdt_add_subnode_namelen(void *fdt, int parentoffset,
*
* This function will insert data into the blob, and will therefore
* change the offsets of some existing nodes.
-
+ *
* returns:
* structure block offset of the created nodeequested subnode (>=0), on
* success
diff --git a/scripts/dtc/libfdt/libfdt_internal.h b/scripts/dtc/libfdt/libfdt_internal.h
index d4e0bd49c037..16bda1906a7b 100644
--- a/scripts/dtc/libfdt/libfdt_internal.h
+++ b/scripts/dtc/libfdt/libfdt_internal.h
@@ -46,6 +46,25 @@ static inline struct fdt_reserve_entry *fdt_mem_rsv_w_(void *fdt, int n)
return (void *)(uintptr_t)fdt_mem_rsv_(fdt, n);
}
+/*
+ * Internal helpers to access tructural elements of the device tree
+ * blob (rather than for exaple reading integers from within property
+ * values). We assume that we are either given a naturally aligned
+ * address for the platform or if we are not, we are on a platform
+ * where unaligned memory reads will be handled in a graceful manner.
+ * If not the external helpers fdtXX_ld() from libfdt.h can be used
+ * instead.
+ */
+static inline uint32_t fdt32_ld_(const fdt32_t *p)
+{
+ return fdt32_to_cpu(*p);
+}
+
+static inline uint64_t fdt64_ld_(const fdt64_t *p)
+{
+ return fdt64_to_cpu(*p);
+}
+
#define FDT_SW_MAGIC (~FDT_MAGIC)
/**********************************************************************/
diff --git a/scripts/dtc/livetree.c b/scripts/dtc/livetree.c
index 032df5878ccc..7eacd0248641 100644
--- a/scripts/dtc/livetree.c
+++ b/scripts/dtc/livetree.c
@@ -438,7 +438,7 @@ cell_t propval_cell(struct property *prop)
return fdt32_to_cpu(*((fdt32_t *)prop->val.val));
}
-cell_t propval_cell_n(struct property *prop, int n)
+cell_t propval_cell_n(struct property *prop, unsigned int n)
{
assert(prop->val.len / sizeof(cell_t) >= n);
return fdt32_to_cpu(*((fdt32_t *)prop->val.val + n));
diff --git a/scripts/dtc/srcpos.c b/scripts/dtc/srcpos.c
index f5205fb9c1ff..4fdb22a019bd 100644
--- a/scripts/dtc/srcpos.c
+++ b/scripts/dtc/srcpos.c
@@ -20,7 +20,7 @@ struct search_path {
static struct search_path *search_path_head, **search_path_tail;
/* Detect infinite include recursion. */
-#define MAX_SRCFILE_DEPTH (100)
+#define MAX_SRCFILE_DEPTH (200)
static int srcfile_depth; /* = 0 */
static char *get_dirname(const char *path)
diff --git a/scripts/dtc/update-dtc-source.sh b/scripts/dtc/update-dtc-source.sh
index bc704e2a6a4a..32ff17ffd089 100755
--- a/scripts/dtc/update-dtc-source.sh
+++ b/scripts/dtc/update-dtc-source.sh
@@ -37,6 +37,7 @@ DTC_SOURCE="checks.c data.c dtc.c dtc.h flattree.c fstree.c livetree.c srcpos.c
LIBFDT_SOURCE="fdt.c fdt.h fdt_addresses.c fdt_empty_tree.c \
fdt_overlay.c fdt_ro.c fdt_rw.c fdt_strerror.c fdt_sw.c \
fdt_wip.c libfdt.h libfdt_env.h libfdt_internal.h"
+FDTOVERLAY_SOURCE=fdtoverlay.c
get_last_dtc_version() {
git log --oneline scripts/dtc/ | grep 'upstream' | head -1 | sed -e 's/^.* \(.*\)/\1/'
@@ -54,7 +55,7 @@ dtc_log=$(git log --oneline ${last_dtc_ver}..)
# Copy the files into the Linux tree
cd $DTC_LINUX_PATH
-for f in $DTC_SOURCE; do
+for f in $DTC_SOURCE $FDTOVERLAY_SOURCE; do
cp ${DTC_UPSTREAM_PATH}/${f} ${f}
git add ${f}
done
diff --git a/scripts/dtc/version_gen.h b/scripts/dtc/version_gen.h
index 054cdd0fdbe8..73a7839603f1 100644
--- a/scripts/dtc/version_gen.h
+++ b/scripts/dtc/version_gen.h
@@ -1 +1 @@
-#define DTC_VERSION "DTC 1.6.0-gcbca977e"
+#define DTC_VERSION "DTC 1.6.0-g183df9e9"
diff --git a/scripts/dtc/yamltree.c b/scripts/dtc/yamltree.c
index 4e93c12dc658..e63d32fe142a 100644
--- a/scripts/dtc/yamltree.c
+++ b/scripts/dtc/yamltree.c
@@ -29,11 +29,11 @@ char *yaml_error_name[] = {
(emitter)->problem, __func__, __LINE__); \
})
-static void yaml_propval_int(yaml_emitter_t *emitter, struct marker *markers, char *data, int len, int width)
+static void yaml_propval_int(yaml_emitter_t *emitter, struct marker *markers, char *data, unsigned int len, int width)
{
yaml_event_t event;
void *tag;
- int off, start_offset = markers->offset;
+ unsigned int off, start_offset = markers->offset;
switch(width) {
case 1: tag = "!u8"; break;
@@ -112,7 +112,7 @@ static void yaml_propval_string(yaml_emitter_t *emitter, char *str, int len)
static void yaml_propval(yaml_emitter_t *emitter, struct property *prop)
{
yaml_event_t event;
- int len = prop->val.len;
+ unsigned int len = prop->val.len;
struct marker *m = prop->val.markers;
/* Emit the property name */
diff --git a/scripts/dummy-tools/gcc b/scripts/dummy-tools/gcc
index 33487e99d83e..39e65fee59bd 100755
--- a/scripts/dummy-tools/gcc
+++ b/scripts/dummy-tools/gcc
@@ -57,9 +57,9 @@ if arg_contain --version "$@"; then
fi
if arg_contain -E "$@"; then
- # For scripts/gcc-version.sh; This emulates GCC 20.0.0
+ # For scripts/cc-version.sh; This emulates GCC 20.0.0
if arg_contain - "$@"; then
- sed 's/^__GNUC__$/20/; s/^__GNUC_MINOR__$/0/; s/^__GNUC_PATCHLEVEL__$/0/'
+ sed -n '/^GCC/{s/__GNUC__/20/; s/__GNUC_MINOR__/0/; s/__GNUC_PATCHLEVEL__/0/; p;}'
exit 0
else
echo "no input files" >&2
@@ -73,19 +73,29 @@ if arg_contain -S "$@"; then
echo "%gs"
exit 0
fi
+
+ # For arch/powerpc/tools/gcc-check-mprofile-kernel.sh
+ if arg_contain -m64 "$@" && arg_contain -mlittle-endian "$@" &&
+ arg_contain -mprofile-kernel "$@"; then
+ if ! test -t 0 && ! grep -q notrace; then
+ echo "_mcount"
+ fi
+ exit 0
+ fi
fi
-# For scripts/gcc-plugin.sh
+# To set GCC_PLUGINS
if arg_contain -print-file-name=plugin "$@"; then
plugin_dir=$(mktemp -d)
- sed -n 's/.*#include "\(.*\)"/\1/p' $(dirname $0)/../gcc-plugins/gcc-common.h |
- while read header
- do
- mkdir -p $plugin_dir/include/$(dirname $header)
- touch $plugin_dir/include/$header
- done
+ mkdir -p $plugin_dir/include
+ touch $plugin_dir/include/plugin-version.h
echo $plugin_dir
exit 0
fi
+
+# inverted return value
+if arg_contain -D__SIZEOF_INT128__=0 "$@"; then
+ exit 1
+fi
diff --git a/scripts/gcc-plugin.sh b/scripts/gcc-plugin.sh
deleted file mode 100755
index b79fd0bea838..000000000000
--- a/scripts/gcc-plugin.sh
+++ /dev/null
@@ -1,19 +0,0 @@
-#!/bin/sh
-# SPDX-License-Identifier: GPL-2.0
-
-set -e
-
-srctree=$(dirname "$0")
-
-gccplugins_dir=$($* -print-file-name=plugin)
-
-# we need a c++ compiler that supports the designated initializer GNU extension
-$HOSTCC -c -x c++ -std=gnu++98 - -fsyntax-only -I $srctree/gcc-plugins -I $gccplugins_dir/include 2>/dev/null <<EOF
-#include "gcc-common.h"
-class test {
-public:
- int test;
-} test = {
- .test = 1
-};
-EOF
diff --git a/scripts/gcc-plugins/Kconfig b/scripts/gcc-plugins/Kconfig
index ae19fb0243b9..ab9eb4cbe33a 100644
--- a/scripts/gcc-plugins/Kconfig
+++ b/scripts/gcc-plugins/Kconfig
@@ -9,7 +9,7 @@ menuconfig GCC_PLUGINS
bool "GCC plugins"
depends on HAVE_GCC_PLUGINS
depends on CC_IS_GCC
- depends on $(success,$(srctree)/scripts/gcc-plugin.sh $(CC))
+ depends on $(success,test -e $(shell,$(CC) -print-file-name=plugin)/include/plugin-version.h)
default y
help
GCC plugins are loadable modules that provide extra features to the
diff --git a/scripts/gcc-plugins/Makefile b/scripts/gcc-plugins/Makefile
index d66949bfeba4..1952d3bb80c6 100644
--- a/scripts/gcc-plugins/Makefile
+++ b/scripts/gcc-plugins/Makefile
@@ -22,9 +22,10 @@ always-y += $(GCC_PLUGIN)
GCC_PLUGINS_DIR = $(shell $(CC) -print-file-name=plugin)
plugin_cxxflags = -Wp,-MMD,$(depfile) $(KBUILD_HOSTCXXFLAGS) -fPIC \
- -I $(GCC_PLUGINS_DIR)/include -I $(obj) -std=gnu++98 \
+ -include $(srctree)/include/linux/compiler-version.h \
+ -I $(GCC_PLUGINS_DIR)/include -I $(obj) -std=gnu++11 \
-fno-rtti -fno-exceptions -fasynchronous-unwind-tables \
- -ggdb -Wno-narrowing -Wno-unused-variable -Wno-c++11-compat \
+ -ggdb -Wno-narrowing -Wno-unused-variable \
-Wno-format-diag
plugin_ldflags = -shared
diff --git a/scripts/gcc-plugins/gcc-common.h b/scripts/gcc-plugins/gcc-common.h
index 9ad76b7f3f10..0c087614fc3e 100644
--- a/scripts/gcc-plugins/gcc-common.h
+++ b/scripts/gcc-plugins/gcc-common.h
@@ -55,47 +55,17 @@
#include "cfgloop.h"
#include "cgraph.h"
#include "opts.h"
-
-#if BUILDING_GCC_VERSION == 4005
-#include <sys/mman.h>
-#endif
-
-#if BUILDING_GCC_VERSION >= 4007
#include "tree-pretty-print.h"
#include "gimple-pretty-print.h"
-#endif
-
-#if BUILDING_GCC_VERSION >= 4006
-/*
- * The c-family headers were moved into a subdirectory in GCC version
- * 4.7, but most plugin-building users of GCC 4.6 are using the Debian
- * or Ubuntu package, which has an out-of-tree patch to move this to the
- * same location as found in 4.7 and later:
- * https://sources.debian.net/src/gcc-4.6/4.6.3-14/debian/patches/pr45078.diff/
- */
#include "c-family/c-common.h"
-#else
-#include "c-common.h"
-#endif
-
-#if BUILDING_GCC_VERSION <= 4008
-#include "tree-flow.h"
-#else
#include "tree-cfgcleanup.h"
#include "tree-ssa-operands.h"
#include "tree-into-ssa.h"
-#endif
-
-#if BUILDING_GCC_VERSION >= 4008
#include "is-a.h"
-#endif
-
#include "diagnostic.h"
#include "tree-dump.h"
#include "tree-pass.h"
-#if BUILDING_GCC_VERSION >= 4009
#include "pass_manager.h"
-#endif
#include "predict.h"
#include "ipa-utils.h"
@@ -103,7 +73,6 @@
#include "stringpool.h"
#endif
-#if BUILDING_GCC_VERSION >= 4009
#include "attribs.h"
#include "varasm.h"
#include "stor-layout.h"
@@ -122,18 +91,13 @@
#include "tree-eh.h"
#include "stmt.h"
#include "gimplify.h"
-#endif
-
#include "gimple.h"
-
-#if BUILDING_GCC_VERSION >= 4009
#include "tree-ssa-operands.h"
#include "tree-phinodes.h"
#include "tree-cfg.h"
#include "gimple-iterator.h"
#include "gimple-ssa.h"
#include "ssa-iterators.h"
-#endif
#if BUILDING_GCC_VERSION >= 5000
#include "builtins.h"
@@ -143,15 +107,6 @@
void debug_dominance_info(enum cdi_direction dir);
void debug_dominance_tree(enum cdi_direction dir, basic_block root);
-#if BUILDING_GCC_VERSION == 4006
-void debug_gimple_stmt(gimple);
-void debug_gimple_seq(gimple_seq);
-void print_gimple_seq(FILE *, gimple_seq, int, int);
-void print_gimple_stmt(FILE *, gimple, int, int);
-void print_gimple_expr(FILE *, gimple, int, int);
-void dump_gimple_stmt(pretty_printer *, gimple, int, int);
-#endif
-
#ifndef __unused
#define __unused __attribute__((__unused__))
#endif
@@ -190,372 +145,12 @@ struct register_pass_info NAME##_pass_info = { \
.pos_op = POS, \
}
-#if BUILDING_GCC_VERSION == 4005
-#define FOR_EACH_LOCAL_DECL(FUN, I, D) \
- for (tree vars = (FUN)->local_decls, (I) = 0; \
- vars && ((D) = TREE_VALUE(vars)); \
- vars = TREE_CHAIN(vars), (I)++)
-#define DECL_CHAIN(NODE) (TREE_CHAIN(DECL_MINIMAL_CHECK(NODE)))
-#define FOR_EACH_VEC_ELT(T, V, I, P) \
- for (I = 0; VEC_iterate(T, (V), (I), (P)); ++(I))
-#define TODO_rebuild_cgraph_edges 0
-#define SCOPE_FILE_SCOPE_P(EXP) (!(EXP))
-
-#ifndef O_BINARY
-#define O_BINARY 0
-#endif
-
-typedef struct varpool_node *varpool_node_ptr;
-
-static inline bool gimple_call_builtin_p(gimple stmt, enum built_in_function code)
-{
- tree fndecl;
-
- if (!is_gimple_call(stmt))
- return false;
- fndecl = gimple_call_fndecl(stmt);
- if (!fndecl || DECL_BUILT_IN_CLASS(fndecl) != BUILT_IN_NORMAL)
- return false;
- return DECL_FUNCTION_CODE(fndecl) == code;
-}
-
-static inline bool is_simple_builtin(tree decl)
-{
- if (decl && DECL_BUILT_IN_CLASS(decl) != BUILT_IN_NORMAL)
- return false;
-
- switch (DECL_FUNCTION_CODE(decl)) {
- /* Builtins that expand to constants. */
- case BUILT_IN_CONSTANT_P:
- case BUILT_IN_EXPECT:
- case BUILT_IN_OBJECT_SIZE:
- case BUILT_IN_UNREACHABLE:
- /* Simple register moves or loads from stack. */
- case BUILT_IN_RETURN_ADDRESS:
- case BUILT_IN_EXTRACT_RETURN_ADDR:
- case BUILT_IN_FROB_RETURN_ADDR:
- case BUILT_IN_RETURN:
- case BUILT_IN_AGGREGATE_INCOMING_ADDRESS:
- case BUILT_IN_FRAME_ADDRESS:
- case BUILT_IN_VA_END:
- case BUILT_IN_STACK_SAVE:
- case BUILT_IN_STACK_RESTORE:
- /* Exception state returns or moves registers around. */
- case BUILT_IN_EH_FILTER:
- case BUILT_IN_EH_POINTER:
- case BUILT_IN_EH_COPY_VALUES:
- return true;
-
- default:
- return false;
- }
-}
-
-static inline void add_local_decl(struct function *fun, tree d)
-{
- gcc_assert(TREE_CODE(d) == VAR_DECL);
- fun->local_decls = tree_cons(NULL_TREE, d, fun->local_decls);
-}
-#endif
-
-#if BUILDING_GCC_VERSION <= 4006
-#define ANY_RETURN_P(rtx) (GET_CODE(rtx) == RETURN)
-#define C_DECL_REGISTER(EXP) DECL_LANG_FLAG_4(EXP)
-#define EDGE_PRESERVE 0ULL
-#define HOST_WIDE_INT_PRINT_HEX_PURE "%" HOST_WIDE_INT_PRINT "x"
-#define flag_fat_lto_objects true
-
-#define get_random_seed(noinit) ({ \
- unsigned HOST_WIDE_INT seed; \
- sscanf(get_random_seed(noinit), "%" HOST_WIDE_INT_PRINT "x", &seed); \
- seed * seed; })
-
-#define int_const_binop(code, arg1, arg2) \
- int_const_binop((code), (arg1), (arg2), 0)
-
-static inline bool gimple_clobber_p(gimple s __unused)
-{
- return false;
-}
-
-static inline bool gimple_asm_clobbers_memory_p(const_gimple stmt)
-{
- unsigned i;
-
- for (i = 0; i < gimple_asm_nclobbers(stmt); i++) {
- tree op = gimple_asm_clobber_op(stmt, i);
-
- if (!strcmp(TREE_STRING_POINTER(TREE_VALUE(op)), "memory"))
- return true;
- }
-
- return false;
-}
-
-static inline tree builtin_decl_implicit(enum built_in_function fncode)
-{
- return implicit_built_in_decls[fncode];
-}
-
-static inline int ipa_reverse_postorder(struct cgraph_node **order)
-{
- return cgraph_postorder(order);
-}
-
-static inline struct cgraph_node *cgraph_create_node(tree decl)
-{
- return cgraph_node(decl);
-}
-
-static inline struct cgraph_node *cgraph_get_create_node(tree decl)
-{
- struct cgraph_node *node = cgraph_get_node(decl);
-
- return node ? node : cgraph_node(decl);
-}
-
-static inline bool cgraph_function_with_gimple_body_p(struct cgraph_node *node)
-{
- return node->analyzed && !node->thunk.thunk_p && !node->alias;
-}
-
-static inline struct cgraph_node *cgraph_first_function_with_gimple_body(void)
-{
- struct cgraph_node *node;
-
- for (node = cgraph_nodes; node; node = node->next)
- if (cgraph_function_with_gimple_body_p(node))
- return node;
- return NULL;
-}
-
-static inline struct cgraph_node *cgraph_next_function_with_gimple_body(struct cgraph_node *node)
-{
- for (node = node->next; node; node = node->next)
- if (cgraph_function_with_gimple_body_p(node))
- return node;
- return NULL;
-}
-
-static inline bool cgraph_for_node_and_aliases(cgraph_node_ptr node, bool (*callback)(cgraph_node_ptr, void *), void *data, bool include_overwritable)
-{
- cgraph_node_ptr alias;
-
- if (callback(node, data))
- return true;
-
- for (alias = node->same_body; alias; alias = alias->next) {
- if (include_overwritable || cgraph_function_body_availability(alias) > AVAIL_OVERWRITABLE)
- if (cgraph_for_node_and_aliases(alias, callback, data, include_overwritable))
- return true;
- }
-
- return false;
-}
-
-#define FOR_EACH_FUNCTION_WITH_GIMPLE_BODY(node) \
- for ((node) = cgraph_first_function_with_gimple_body(); (node); \
- (node) = cgraph_next_function_with_gimple_body(node))
-
-static inline void varpool_add_new_variable(tree decl)
-{
- varpool_finalize_decl(decl);
-}
-#endif
-
-#if BUILDING_GCC_VERSION <= 4007
-#define FOR_EACH_FUNCTION(node) \
- for (node = cgraph_nodes; node; node = node->next)
-#define FOR_EACH_VARIABLE(node) \
- for (node = varpool_nodes; node; node = node->next)
-#define PROP_loops 0
-#define NODE_SYMBOL(node) (node)
-#define NODE_DECL(node) (node)->decl
-#define INSN_LOCATION(INSN) RTL_LOCATION(INSN)
-#define vNULL NULL
-
-static inline int bb_loop_depth(const_basic_block bb)
-{
- return bb->loop_father ? loop_depth(bb->loop_father) : 0;
-}
-
-static inline bool gimple_store_p(gimple gs)
-{
- tree lhs = gimple_get_lhs(gs);
-
- return lhs && !is_gimple_reg(lhs);
-}
-
-static inline void gimple_init_singleton(gimple g __unused)
-{
-}
-#endif
-
-#if BUILDING_GCC_VERSION == 4007 || BUILDING_GCC_VERSION == 4008
-static inline struct cgraph_node *cgraph_alias_target(struct cgraph_node *n)
-{
- return cgraph_alias_aliased_node(n);
-}
-#endif
-
-#if BUILDING_GCC_VERSION <= 4008
-#define ENTRY_BLOCK_PTR_FOR_FN(FN) ENTRY_BLOCK_PTR_FOR_FUNCTION(FN)
-#define EXIT_BLOCK_PTR_FOR_FN(FN) EXIT_BLOCK_PTR_FOR_FUNCTION(FN)
-#define basic_block_info_for_fn(FN) ((FN)->cfg->x_basic_block_info)
-#define n_basic_blocks_for_fn(FN) ((FN)->cfg->x_n_basic_blocks)
-#define n_edges_for_fn(FN) ((FN)->cfg->x_n_edges)
-#define last_basic_block_for_fn(FN) ((FN)->cfg->x_last_basic_block)
-#define label_to_block_map_for_fn(FN) ((FN)->cfg->x_label_to_block_map)
-#define profile_status_for_fn(FN) ((FN)->cfg->x_profile_status)
-#define BASIC_BLOCK_FOR_FN(FN, N) BASIC_BLOCK_FOR_FUNCTION((FN), (N))
-#define NODE_IMPLICIT_ALIAS(node) (node)->same_body_alias
-#define VAR_P(NODE) (TREE_CODE(NODE) == VAR_DECL)
-
-static inline bool tree_fits_shwi_p(const_tree t)
-{
- if (t == NULL_TREE || TREE_CODE(t) != INTEGER_CST)
- return false;
-
- if (TREE_INT_CST_HIGH(t) == 0 && (HOST_WIDE_INT)TREE_INT_CST_LOW(t) >= 0)
- return true;
-
- if (TREE_INT_CST_HIGH(t) == -1 && (HOST_WIDE_INT)TREE_INT_CST_LOW(t) < 0 && !TYPE_UNSIGNED(TREE_TYPE(t)))
- return true;
-
- return false;
-}
-
-static inline bool tree_fits_uhwi_p(const_tree t)
-{
- if (t == NULL_TREE || TREE_CODE(t) != INTEGER_CST)
- return false;
-
- return TREE_INT_CST_HIGH(t) == 0;
-}
-
-static inline HOST_WIDE_INT tree_to_shwi(const_tree t)
-{
- gcc_assert(tree_fits_shwi_p(t));
- return TREE_INT_CST_LOW(t);
-}
-
-static inline unsigned HOST_WIDE_INT tree_to_uhwi(const_tree t)
-{
- gcc_assert(tree_fits_uhwi_p(t));
- return TREE_INT_CST_LOW(t);
-}
-
-static inline const char *get_tree_code_name(enum tree_code code)
-{
- gcc_assert(code < MAX_TREE_CODES);
- return tree_code_name[code];
-}
-
-#define ipa_remove_stmt_references(cnode, stmt)
-
-typedef union gimple_statement_d gasm;
-typedef union gimple_statement_d gassign;
-typedef union gimple_statement_d gcall;
-typedef union gimple_statement_d gcond;
-typedef union gimple_statement_d gdebug;
-typedef union gimple_statement_d ggoto;
-typedef union gimple_statement_d gphi;
-typedef union gimple_statement_d greturn;
-
-static inline gasm *as_a_gasm(gimple stmt)
-{
- return stmt;
-}
-
-static inline const gasm *as_a_const_gasm(const_gimple stmt)
-{
- return stmt;
-}
-
-static inline gassign *as_a_gassign(gimple stmt)
-{
- return stmt;
-}
-
-static inline const gassign *as_a_const_gassign(const_gimple stmt)
-{
- return stmt;
-}
-
-static inline gcall *as_a_gcall(gimple stmt)
-{
- return stmt;
-}
-
-static inline const gcall *as_a_const_gcall(const_gimple stmt)
-{
- return stmt;
-}
-
-static inline gcond *as_a_gcond(gimple stmt)
-{
- return stmt;
-}
-
-static inline const gcond *as_a_const_gcond(const_gimple stmt)
-{
- return stmt;
-}
-
-static inline gdebug *as_a_gdebug(gimple stmt)
-{
- return stmt;
-}
-
-static inline const gdebug *as_a_const_gdebug(const_gimple stmt)
-{
- return stmt;
-}
-
-static inline ggoto *as_a_ggoto(gimple stmt)
-{
- return stmt;
-}
-
-static inline const ggoto *as_a_const_ggoto(const_gimple stmt)
-{
- return stmt;
-}
-
-static inline gphi *as_a_gphi(gimple stmt)
-{
- return stmt;
-}
-
-static inline const gphi *as_a_const_gphi(const_gimple stmt)
-{
- return stmt;
-}
-
-static inline greturn *as_a_greturn(gimple stmt)
-{
- return stmt;
-}
-
-static inline const greturn *as_a_const_greturn(const_gimple stmt)
-{
- return stmt;
-}
-#endif
-
-#if BUILDING_GCC_VERSION == 4008
-#define NODE_SYMBOL(node) (&(node)->symbol)
-#define NODE_DECL(node) (node)->symbol.decl
-#endif
-
-#if BUILDING_GCC_VERSION >= 4008
#define add_referenced_var(var)
#define mark_sym_for_renaming(var)
#define varpool_mark_needed_node(node)
#define create_var_ann(var)
#define TODO_dump_func 0
#define TODO_dump_cgraph 0
-#endif
#if BUILDING_GCC_VERSION <= 4009
#define TODO_verify_il 0
@@ -676,7 +271,6 @@ static inline const greturn *as_a_const_greturn(const_gimple stmt)
}
#endif
-#if BUILDING_GCC_VERSION >= 4009
#define TODO_ggc_collect 0
#define NODE_SYMBOL(node) (node)
#define NODE_DECL(node) (node)->decl
@@ -687,7 +281,6 @@ static inline opt_pass *get_pass_for_id(int id)
{
return g->get_passes()->get_pass_for_id(id);
}
-#endif
#if BUILDING_GCC_VERSION >= 5000 && BUILDING_GCC_VERSION < 6000
/* gimple related */
diff --git a/scripts/gcc-plugins/gcc-generate-gimple-pass.h b/scripts/gcc-plugins/gcc-generate-gimple-pass.h
index f20797e80b6d..51780828734e 100644
--- a/scripts/gcc-plugins/gcc-generate-gimple-pass.h
+++ b/scripts/gcc-plugins/gcc-generate-gimple-pass.h
@@ -73,18 +73,11 @@
#define TODO_FLAGS_FINISH 0
#endif
-#if BUILDING_GCC_VERSION >= 4009
namespace {
static const pass_data _PASS_NAME_PASS_DATA = {
-#else
-static struct gimple_opt_pass _PASS_NAME_PASS = {
- .pass = {
-#endif
.type = GIMPLE_PASS,
.name = _PASS_NAME_NAME,
-#if BUILDING_GCC_VERSION >= 4008
.optinfo_flags = OPTGROUP_NONE,
-#endif
#if BUILDING_GCC_VERSION >= 5000
#elif BUILDING_GCC_VERSION == 4009
.has_gate = _HAS_GATE,
@@ -102,12 +95,8 @@ static struct gimple_opt_pass _PASS_NAME_PASS = {
.properties_destroyed = PROPERTIES_DESTROYED,
.todo_flags_start = TODO_FLAGS_START,
.todo_flags_finish = TODO_FLAGS_FINISH,
-#if BUILDING_GCC_VERSION < 4009
- }
-#endif
};
-#if BUILDING_GCC_VERSION >= 4009
class _PASS_NAME_PASS : public gimple_opt_pass {
public:
_PASS_NAME_PASS() : gimple_opt_pass(_PASS_NAME_PASS_DATA, g) {}
@@ -128,7 +117,6 @@ public:
#else
virtual unsigned int execute(void) { return _EXECUTE(); }
#endif
-#endif
};
}
diff --git a/scripts/gcc-plugins/gcc-generate-ipa-pass.h b/scripts/gcc-plugins/gcc-generate-ipa-pass.h
index 92bb4f3a87a4..c34ffec035bf 100644
--- a/scripts/gcc-plugins/gcc-generate-ipa-pass.h
+++ b/scripts/gcc-plugins/gcc-generate-ipa-pass.h
@@ -141,18 +141,11 @@
#define FUNCTION_TRANSFORM_TODO_FLAGS_START 0
#endif
-#if BUILDING_GCC_VERSION >= 4009
namespace {
static const pass_data _PASS_NAME_PASS_DATA = {
-#else
-static struct ipa_opt_pass_d _PASS_NAME_PASS = {
- .pass = {
-#endif
.type = IPA_PASS,
.name = _PASS_NAME_NAME,
-#if BUILDING_GCC_VERSION >= 4008
.optinfo_flags = OPTGROUP_NONE,
-#endif
#if BUILDING_GCC_VERSION >= 5000
#elif BUILDING_GCC_VERSION == 4009
.has_gate = _HAS_GATE,
@@ -170,23 +163,8 @@ static struct ipa_opt_pass_d _PASS_NAME_PASS = {
.properties_destroyed = PROPERTIES_DESTROYED,
.todo_flags_start = TODO_FLAGS_START,
.todo_flags_finish = TODO_FLAGS_FINISH,
-#if BUILDING_GCC_VERSION < 4009
- },
- .generate_summary = _GENERATE_SUMMARY,
- .write_summary = _WRITE_SUMMARY,
- .read_summary = _READ_SUMMARY,
-#if BUILDING_GCC_VERSION >= 4006
- .write_optimization_summary = _WRITE_OPTIMIZATION_SUMMARY,
- .read_optimization_summary = _READ_OPTIMIZATION_SUMMARY,
-#endif
- .stmt_fixup = _STMT_FIXUP,
- .function_transform_todo_flags_start = FUNCTION_TRANSFORM_TODO_FLAGS_START,
- .function_transform = _FUNCTION_TRANSFORM,
- .variable_transform = _VARIABLE_TRANSFORM,
-#endif
};
-#if BUILDING_GCC_VERSION >= 4009
class _PASS_NAME_PASS : public ipa_opt_pass_d {
public:
_PASS_NAME_PASS() : ipa_opt_pass_d(_PASS_NAME_PASS_DATA,
@@ -207,7 +185,6 @@ public:
#else
virtual bool gate(void) { return _GATE(); }
#endif
-#endif
virtual opt_pass *clone() { return new _PASS_NAME_PASS(); }
diff --git a/scripts/gcc-plugins/gcc-generate-rtl-pass.h b/scripts/gcc-plugins/gcc-generate-rtl-pass.h
index d69cd80b6c10..d14614f4b139 100644
--- a/scripts/gcc-plugins/gcc-generate-rtl-pass.h
+++ b/scripts/gcc-plugins/gcc-generate-rtl-pass.h
@@ -73,18 +73,11 @@
#define TODO_FLAGS_FINISH 0
#endif
-#if BUILDING_GCC_VERSION >= 4009
namespace {
static const pass_data _PASS_NAME_PASS_DATA = {
-#else
-static struct rtl_opt_pass _PASS_NAME_PASS = {
- .pass = {
-#endif
.type = RTL_PASS,
.name = _PASS_NAME_NAME,
-#if BUILDING_GCC_VERSION >= 4008
.optinfo_flags = OPTGROUP_NONE,
-#endif
#if BUILDING_GCC_VERSION >= 5000
#elif BUILDING_GCC_VERSION == 4009
.has_gate = _HAS_GATE,
@@ -102,12 +95,8 @@ static struct rtl_opt_pass _PASS_NAME_PASS = {
.properties_destroyed = PROPERTIES_DESTROYED,
.todo_flags_start = TODO_FLAGS_START,
.todo_flags_finish = TODO_FLAGS_FINISH,
-#if BUILDING_GCC_VERSION < 4009
- }
-#endif
};
-#if BUILDING_GCC_VERSION >= 4009
class _PASS_NAME_PASS : public rtl_opt_pass {
public:
_PASS_NAME_PASS() : rtl_opt_pass(_PASS_NAME_PASS_DATA, g) {}
@@ -136,12 +125,6 @@ opt_pass *_MAKE_PASS_NAME_PASS(void)
{
return new _PASS_NAME_PASS();
}
-#else
-struct opt_pass *_MAKE_PASS_NAME_PASS(void)
-{
- return &_PASS_NAME_PASS.pass;
-}
-#endif
/* clean up user provided defines */
#undef PASS_NAME
diff --git a/scripts/gcc-plugins/gcc-generate-simple_ipa-pass.h b/scripts/gcc-plugins/gcc-generate-simple_ipa-pass.h
index 06800bc477e0..ef6f4c2cb6fa 100644
--- a/scripts/gcc-plugins/gcc-generate-simple_ipa-pass.h
+++ b/scripts/gcc-plugins/gcc-generate-simple_ipa-pass.h
@@ -73,18 +73,11 @@
#define TODO_FLAGS_FINISH 0
#endif
-#if BUILDING_GCC_VERSION >= 4009
namespace {
static const pass_data _PASS_NAME_PASS_DATA = {
-#else
-static struct simple_ipa_opt_pass _PASS_NAME_PASS = {
- .pass = {
-#endif
.type = SIMPLE_IPA_PASS,
.name = _PASS_NAME_NAME,
-#if BUILDING_GCC_VERSION >= 4008
.optinfo_flags = OPTGROUP_NONE,
-#endif
#if BUILDING_GCC_VERSION >= 5000
#elif BUILDING_GCC_VERSION == 4009
.has_gate = _HAS_GATE,
@@ -102,12 +95,8 @@ static struct simple_ipa_opt_pass _PASS_NAME_PASS = {
.properties_destroyed = PROPERTIES_DESTROYED,
.todo_flags_start = TODO_FLAGS_START,
.todo_flags_finish = TODO_FLAGS_FINISH,
-#if BUILDING_GCC_VERSION < 4009
- }
-#endif
};
-#if BUILDING_GCC_VERSION >= 4009
class _PASS_NAME_PASS : public simple_ipa_opt_pass {
public:
_PASS_NAME_PASS() : simple_ipa_opt_pass(_PASS_NAME_PASS_DATA, g) {}
@@ -136,12 +125,6 @@ opt_pass *_MAKE_PASS_NAME_PASS(void)
{
return new _PASS_NAME_PASS();
}
-#else
-struct opt_pass *_MAKE_PASS_NAME_PASS(void)
-{
- return &_PASS_NAME_PASS.pass;
-}
-#endif
/* clean up user provided defines */
#undef PASS_NAME
diff --git a/scripts/gcc-plugins/latent_entropy_plugin.c b/scripts/gcc-plugins/latent_entropy_plugin.c
index cbe1d6c4b1a5..589454bce930 100644
--- a/scripts/gcc-plugins/latent_entropy_plugin.c
+++ b/scripts/gcc-plugins/latent_entropy_plugin.c
@@ -125,11 +125,7 @@ static tree handle_latent_entropy_attribute(tree *node, tree name,
bool *no_add_attrs)
{
tree type;
-#if BUILDING_GCC_VERSION <= 4007
- VEC(constructor_elt, gc) *vals;
-#else
vec<constructor_elt, va_gc> *vals;
-#endif
switch (TREE_CODE(*node)) {
default:
@@ -181,11 +177,7 @@ static tree handle_latent_entropy_attribute(tree *node, tree name,
if (fld)
break;
-#if BUILDING_GCC_VERSION <= 4007
- vals = VEC_alloc(constructor_elt, gc, nelt);
-#else
vec_alloc(vals, nelt);
-#endif
for (fld = lst; fld; fld = TREE_CHAIN(fld)) {
tree random_const, fld_t = TREE_TYPE(fld);
@@ -225,11 +217,7 @@ static tree handle_latent_entropy_attribute(tree *node, tree name,
elt_size_int = TREE_INT_CST_LOW(elt_size);
nelt = array_size_int / elt_size_int;
-#if BUILDING_GCC_VERSION <= 4007
- vals = VEC_alloc(constructor_elt, gc, nelt);
-#else
vec_alloc(vals, nelt);
-#endif
for (i = 0; i < nelt; i++) {
tree cst = size_int(i);
@@ -536,7 +524,7 @@ static unsigned int latent_entropy_execute(void)
while (bb != EXIT_BLOCK_PTR_FOR_FN(cfun)) {
perturb_local_entropy(bb, local_entropy);
bb = bb->next_bb;
- };
+ }
/* 4. mix local entropy into the global entropy variable */
perturb_latent_entropy(local_entropy);
diff --git a/scripts/gcc-plugins/randomize_layout_plugin.c b/scripts/gcc-plugins/randomize_layout_plugin.c
index bd29e4e7a524..334741a31d0a 100644
--- a/scripts/gcc-plugins/randomize_layout_plugin.c
+++ b/scripts/gcc-plugins/randomize_layout_plugin.c
@@ -590,16 +590,12 @@ static void register_attributes(void *event_data, void *data)
randomize_layout_attr.name = "randomize_layout";
randomize_layout_attr.type_required = true;
randomize_layout_attr.handler = handle_randomize_layout_attr;
-#if BUILDING_GCC_VERSION >= 4007
randomize_layout_attr.affects_type_identity = true;
-#endif
no_randomize_layout_attr.name = "no_randomize_layout";
no_randomize_layout_attr.type_required = true;
no_randomize_layout_attr.handler = handle_randomize_layout_attr;
-#if BUILDING_GCC_VERSION >= 4007
no_randomize_layout_attr.affects_type_identity = true;
-#endif
randomize_considered_attr.name = "randomize_considered";
randomize_considered_attr.type_required = true;
diff --git a/scripts/gcc-plugins/sancov_plugin.c b/scripts/gcc-plugins/sancov_plugin.c
index caff4a6c7e9a..23bd023a283b 100644
--- a/scripts/gcc-plugins/sancov_plugin.c
+++ b/scripts/gcc-plugins/sancov_plugin.c
@@ -80,10 +80,8 @@ static void sancov_start_unit(void __unused *gcc_data, void __unused *user_data)
nothrow_attr = tree_cons(get_identifier("nothrow"), NULL, NULL);
decl_attributes(&sancov_fndecl, nothrow_attr, 0);
gcc_assert(TREE_NOTHROW(sancov_fndecl));
-#if BUILDING_GCC_VERSION > 4005
leaf_attr = tree_cons(get_identifier("leaf"), NULL, NULL);
decl_attributes(&sancov_fndecl, leaf_attr, 0);
-#endif
}
__visible int plugin_init(struct plugin_name_args *plugin_info, struct plugin_gcc_version *version)
@@ -106,11 +104,7 @@ __visible int plugin_init(struct plugin_name_args *plugin_info, struct plugin_gc
};
/* BBs can be split afterwards?? */
-#if BUILDING_GCC_VERSION >= 4009
PASS_INFO(sancov, "asan", 0, PASS_POS_INSERT_BEFORE);
-#else
- PASS_INFO(sancov, "nrv", 1, PASS_POS_INSERT_BEFORE);
-#endif
if (!plugin_default_version_check(version, &gcc_version)) {
error(G_("incompatible gcc/plugin versions"));
diff --git a/scripts/gcc-plugins/stackleak_plugin.c b/scripts/gcc-plugins/stackleak_plugin.c
index 48e141e07956..e9db7dcb3e5f 100644
--- a/scripts/gcc-plugins/stackleak_plugin.c
+++ b/scripts/gcc-plugins/stackleak_plugin.c
@@ -80,10 +80,8 @@ static bool is_alloca(gimple stmt)
if (gimple_call_builtin_p(stmt, BUILT_IN_ALLOCA))
return true;
-#if BUILDING_GCC_VERSION >= 4007
if (gimple_call_builtin_p(stmt, BUILT_IN_ALLOCA_WITH_ALIGN))
return true;
-#endif
return false;
}
@@ -322,7 +320,7 @@ static void remove_stack_tracking_gcall(void)
/* Delete the stackleak_track_stack() call */
delete_insn_and_edges(insn);
-#if BUILDING_GCC_VERSION >= 4007 && BUILDING_GCC_VERSION < 8000
+#if BUILDING_GCC_VERSION < 8000
if (GET_CODE(next) == NOTE &&
NOTE_KIND(next) == NOTE_INSN_CALL_ARG_LOCATION) {
insn = next;
diff --git a/scripts/gcc-plugins/structleak_plugin.c b/scripts/gcc-plugins/structleak_plugin.c
index b9ef2e162107..d7190e443a14 100644
--- a/scripts/gcc-plugins/structleak_plugin.c
+++ b/scripts/gcc-plugins/structleak_plugin.c
@@ -68,9 +68,7 @@ static void register_attributes(void *event_data, void *data)
{
user_attr.name = "user";
user_attr.handler = handle_user_attribute;
-#if BUILDING_GCC_VERSION >= 4007
user_attr.affects_type_identity = true;
-#endif
register_attribute(&user_attr);
}
@@ -137,11 +135,9 @@ static void initialize(tree var)
if (!gimple_assign_single_p(stmt))
continue;
rhs1 = gimple_assign_rhs1(stmt);
-#if BUILDING_GCC_VERSION >= 4007
/* ... of a non-clobbering expression... */
if (TREE_CLOBBER_P(rhs1))
continue;
-#endif
/* ... to our variable... */
if (gimple_get_lhs(stmt) != var)
continue;
@@ -174,7 +170,6 @@ static void initialize(tree var)
static unsigned int structleak_execute(void)
{
basic_block bb;
- unsigned int ret = 0;
tree var;
unsigned int i;
@@ -204,7 +199,7 @@ static unsigned int structleak_execute(void)
initialize(var);
}
- return ret;
+ return 0;
}
#define PASS_NAME structleak
diff --git a/scripts/gcc-version.sh b/scripts/gcc-version.sh
deleted file mode 100755
index ae353432539b..000000000000
--- a/scripts/gcc-version.sh
+++ /dev/null
@@ -1,20 +0,0 @@
-#!/bin/sh
-# SPDX-License-Identifier: GPL-2.0
-#
-# gcc-version gcc-command
-#
-# Print the gcc version of `gcc-command' in a 5 or 6-digit form
-# such as `29503' for gcc-2.95.3, `30301' for gcc-3.3.1, etc.
-
-compiler="$*"
-
-if [ ${#compiler} -eq 0 ]; then
- echo "Error: No compiler specified." >&2
- printf "Usage:\n\t$0 <gcc-command>\n" >&2
- exit 1
-fi
-
-MAJOR=$(echo __GNUC__ | $compiler -E -x c - | tail -n 1)
-MINOR=$(echo __GNUC_MINOR__ | $compiler -E -x c - | tail -n 1)
-PATCHLEVEL=$(echo __GNUC_PATCHLEVEL__ | $compiler -E -x c - | tail -n 1)
-printf "%d%02d%02d\\n" $MAJOR $MINOR $PATCHLEVEL
diff --git a/scripts/gdb/linux/Makefile b/scripts/gdb/linux/Makefile
index 124755087510..48941faa6ea6 100644
--- a/scripts/gdb/linux/Makefile
+++ b/scripts/gdb/linux/Makefile
@@ -7,7 +7,7 @@ symlinks := $(patsubst $(srctree)/$(src)/%,%,$(wildcard $(srctree)/$(src)/*.py))
quiet_cmd_symlink = SYMLINK $@
cmd_symlink = ln -fsn $(patsubst $(obj)/%,$(abspath $(srctree))/$(src)/%,$@) $@
-extra-y += $(symlinks)
+always-y += $(symlinks)
$(addprefix $(obj)/, $(symlinks)): FORCE
$(call if_changed,symlink)
@@ -18,7 +18,7 @@ quiet_cmd_gen_constants_py = GEN $@
$(CPP) -E -x c -P $(c_flags) $< > $@ ;\
sed -i '1,/<!-- end-c-headers -->/d;' $@
-extra-y += constants.py
+always-y += constants.py
$(obj)/constants.py: $(src)/constants.py.in FORCE
$(call if_changed_dep,gen_constants_py)
diff --git a/scripts/gdb/linux/lists.py b/scripts/gdb/linux/lists.py
index c487ddf09d38..bae4d70b7eae 100644
--- a/scripts/gdb/linux/lists.py
+++ b/scripts/gdb/linux/lists.py
@@ -27,6 +27,11 @@ def list_for_each(head):
raise TypeError("Must be struct list_head not {}"
.format(head.type))
+ if head['next'] == 0:
+ gdb.write("list_for_each: Uninitialized list '{}' treated as empty\n"
+ .format(head.address))
+ return
+
node = head['next'].dereference()
while node.address != head.address:
yield node.address
diff --git a/scripts/gen_autoksyms.sh b/scripts/gen_autoksyms.sh
index 16c0b2ddaa4c..da320151e7c3 100755
--- a/scripts/gen_autoksyms.sh
+++ b/scripts/gen_autoksyms.sh
@@ -19,7 +19,26 @@ esac
# We need access to CONFIG_ symbols
. include/config/auto.conf
-ksym_wl=/dev/null
+needed_symbols=
+
+# Special case for modversions (see modpost.c)
+if [ -n "$CONFIG_MODVERSIONS" ]; then
+ needed_symbols="$needed_symbols module_layout"
+fi
+
+# With CONFIG_LTO_CLANG, LLVM bitcode has not yet been compiled into a binary
+# when the .mod files are generated, which means they don't yet contain
+# references to certain symbols that will be present in the final binaries.
+if [ -n "$CONFIG_LTO_CLANG" ]; then
+ # intrinsic functions
+ needed_symbols="$needed_symbols memcpy memmove memset"
+ # ftrace
+ needed_symbols="$needed_symbols _mcount"
+ # stack protector symbols
+ needed_symbols="$needed_symbols __stack_chk_fail __stack_chk_guard"
+fi
+
+ksym_wl=
if [ -n "$CONFIG_UNUSED_KSYMS_WHITELIST" ]; then
# Use 'eval' to expand the whitelist path and check if it is relative
eval ksym_wl="$CONFIG_UNUSED_KSYMS_WHITELIST"
@@ -40,13 +59,14 @@ cat > "$output_file" << EOT
EOT
[ -f modules.order ] && modlist=modules.order || modlist=/dev/null
-sed 's/ko$/mod/' $modlist |
-xargs -n1 sed -n -e '2{s/ /\n/g;/^$/!p;}' -- |
-cat - "$ksym_wl" |
+
+{
+ sed 's/ko$/mod/' $modlist | xargs -n1 sed -n -e '2p'
+ echo "$needed_symbols"
+ [ -n "$ksym_wl" ] && cat "$ksym_wl"
+} | sed -e 's/ /\n/g' | sed -n -e '/^$/!p' |
+# Remove the dot prefix for ppc64; symbol names with a dot (.) hold entry
+# point addresses.
+sed -e 's/^\.//' |
sort -u |
sed -e 's/\(.*\)/#define __KSYM_\1 1/' >> "$output_file"
-
-# Special case for modversions (see modpost.c)
-if [ -n "$CONFIG_MODVERSIONS" ]; then
- echo "#define __KSYM_module_layout 1" >> "$output_file"
-fi
diff --git a/scripts/generate_initcall_order.pl b/scripts/generate_initcall_order.pl
new file mode 100755
index 000000000000..1a88d3f1b913
--- /dev/null
+++ b/scripts/generate_initcall_order.pl
@@ -0,0 +1,270 @@
+#!/usr/bin/env perl
+# SPDX-License-Identifier: GPL-2.0
+#
+# Generates a linker script that specifies the correct initcall order.
+#
+# Copyright (C) 2019 Google LLC
+
+use strict;
+use warnings;
+use IO::Handle;
+use IO::Select;
+use POSIX ":sys_wait_h";
+
+my $nm = $ENV{'NM'} || die "$0: ERROR: NM not set?";
+my $objtree = $ENV{'objtree'} || '.';
+
+## currently active child processes
+my $jobs = {}; # child process pid -> file handle
+## results from child processes
+my $results = {}; # object index -> [ { level, secname }, ... ]
+
+## reads _NPROCESSORS_ONLN to determine the maximum number of processes to
+## start
+sub get_online_processors {
+ open(my $fh, "getconf _NPROCESSORS_ONLN 2>/dev/null |")
+ or die "$0: ERROR: failed to execute getconf: $!";
+ my $procs = <$fh>;
+ close($fh);
+
+ if (!($procs =~ /^\d+$/)) {
+ return 1;
+ }
+
+ return int($procs);
+}
+
+## writes results to the parent process
+## format: <file index> <initcall level> <base initcall section name>
+sub write_results {
+ my ($index, $initcalls) = @_;
+
+ # sort by the counter value to ensure the order of initcalls within
+ # each object file is correct
+ foreach my $counter (sort { $a <=> $b } keys(%{$initcalls})) {
+ my $level = $initcalls->{$counter}->{'level'};
+
+ # section name for the initcall function
+ my $secname = $initcalls->{$counter}->{'module'} . '__' .
+ $counter . '_' .
+ $initcalls->{$counter}->{'line'} . '_' .
+ $initcalls->{$counter}->{'function'};
+
+ print "$index $level $secname\n";
+ }
+}
+
+## reads a result line from a child process and adds it to the $results array
+sub read_results{
+ my ($fh) = @_;
+
+ # each child prints out a full line w/ autoflush and exits after the
+ # last line, so even if buffered I/O blocks here, it shouldn't block
+ # very long
+ my $data = <$fh>;
+
+ if (!defined($data)) {
+ return 0;
+ }
+
+ chomp($data);
+
+ my ($index, $level, $secname) = $data =~
+ /^(\d+)\ ([^\ ]+)\ (.*)$/;
+
+ if (!defined($index) ||
+ !defined($level) ||
+ !defined($secname)) {
+ die "$0: ERROR: child process returned invalid data: $data\n";
+ }
+
+ $index = int($index);
+
+ if (!exists($results->{$index})) {
+ $results->{$index} = [];
+ }
+
+ push (@{$results->{$index}}, {
+ 'level' => $level,
+ 'secname' => $secname
+ });
+
+ return 1;
+}
+
+## finds initcalls from an object file or all object files in an archive, and
+## writes results back to the parent process
+sub find_initcalls {
+ my ($index, $file) = @_;
+
+ die "$0: ERROR: file $file doesn't exist?" if (! -f $file);
+
+ open(my $fh, "\"$nm\" --defined-only \"$file\" 2>/dev/null |")
+ or die "$0: ERROR: failed to execute \"$nm\": $!";
+
+ my $initcalls = {};
+
+ while (<$fh>) {
+ chomp;
+
+ # check for the start of a new object file (if processing an
+ # archive)
+ my ($path)= $_ =~ /^(.+)\:$/;
+
+ if (defined($path)) {
+ write_results($index, $initcalls);
+ $initcalls = {};
+ next;
+ }
+
+ # look for an initcall
+ my ($module, $counter, $line, $symbol) = $_ =~
+ /[a-z]\s+__initcall__(\S*)__(\d+)_(\d+)_(.*)$/;
+
+ if (!defined($module)) {
+ $module = ''
+ }
+
+ if (!defined($counter) ||
+ !defined($line) ||
+ !defined($symbol)) {
+ next;
+ }
+
+ # parse initcall level
+ my ($function, $level) = $symbol =~
+ /^(.*)((early|rootfs|con|[0-9])s?)$/;
+
+ die "$0: ERROR: invalid initcall name $symbol in $file($path)"
+ if (!defined($function) || !defined($level));
+
+ $initcalls->{$counter} = {
+ 'module' => $module,
+ 'line' => $line,
+ 'function' => $function,
+ 'level' => $level,
+ };
+ }
+
+ close($fh);
+ write_results($index, $initcalls);
+}
+
+## waits for any child process to complete, reads the results, and adds them to
+## the $results array for later processing
+sub wait_for_results {
+ my ($select) = @_;
+
+ my $pid = 0;
+ do {
+ # unblock children that may have a full write buffer
+ foreach my $fh ($select->can_read(0)) {
+ read_results($fh);
+ }
+
+ # check for children that have exited, read the remaining data
+ # from them, and clean up
+ $pid = waitpid(-1, WNOHANG);
+ if ($pid > 0) {
+ if (!exists($jobs->{$pid})) {
+ next;
+ }
+
+ my $fh = $jobs->{$pid};
+ $select->remove($fh);
+
+ while (read_results($fh)) {
+ # until eof
+ }
+
+ close($fh);
+ delete($jobs->{$pid});
+ }
+ } while ($pid > 0);
+}
+
+## forks a child to process each file passed in the command line and collects
+## the results
+sub process_files {
+ my $index = 0;
+ my $njobs = $ENV{'PARALLELISM'} || get_online_processors();
+ my $select = IO::Select->new();
+
+ while (my $file = shift(@ARGV)) {
+ # fork a child process and read it's stdout
+ my $pid = open(my $fh, '-|');
+
+ if (!defined($pid)) {
+ die "$0: ERROR: failed to fork: $!";
+ } elsif ($pid) {
+ # save the child process pid and the file handle
+ $select->add($fh);
+ $jobs->{$pid} = $fh;
+ } else {
+ # in the child process
+ STDOUT->autoflush(1);
+ find_initcalls($index, "$objtree/$file");
+ exit;
+ }
+
+ $index++;
+
+ # limit the number of children to $njobs
+ if (scalar(keys(%{$jobs})) >= $njobs) {
+ wait_for_results($select);
+ }
+ }
+
+ # wait for the remaining children to complete
+ while (scalar(keys(%{$jobs})) > 0) {
+ wait_for_results($select);
+ }
+}
+
+sub generate_initcall_lds() {
+ process_files();
+
+ my $sections = {}; # level -> [ secname, ...]
+
+ # sort results to retain link order and split to sections per
+ # initcall level
+ foreach my $index (sort { $a <=> $b } keys(%{$results})) {
+ foreach my $result (@{$results->{$index}}) {
+ my $level = $result->{'level'};
+
+ if (!exists($sections->{$level})) {
+ $sections->{$level} = [];
+ }
+
+ push(@{$sections->{$level}}, $result->{'secname'});
+ }
+ }
+
+ die "$0: ERROR: no initcalls?" if (!keys(%{$sections}));
+
+ # print out a linker script that defines the order of initcalls for
+ # each level
+ print "SECTIONS {\n";
+
+ foreach my $level (sort(keys(%{$sections}))) {
+ my $section;
+
+ if ($level eq 'con') {
+ $section = '.con_initcall.init';
+ } else {
+ $section = ".initcall${level}.init";
+ }
+
+ print "\t${section} : {\n";
+
+ foreach my $secname (@{$sections->{$level}}) {
+ print "\t\t*(${section}..${secname}) ;\n";
+ }
+
+ print "\t}\n";
+ }
+
+ print "}\n";
+}
+
+generate_initcall_lds();
diff --git a/scripts/genksyms/genksyms.c b/scripts/genksyms/genksyms.c
index 23eff234184f..4827c5abe5b7 100644
--- a/scripts/genksyms/genksyms.c
+++ b/scripts/genksyms/genksyms.c
@@ -29,7 +29,7 @@ static struct symbol *symtab[HASH_BUCKETS];
static FILE *debugfile;
int cur_line = 1;
-char *cur_filename, *source_file;
+char *cur_filename;
int in_source_file;
static int flag_debug, flag_dump_defs, flag_reference, flag_dump_types,
diff --git a/scripts/genksyms/genksyms.h b/scripts/genksyms/genksyms.h
index 2bcdb9bebab4..21ed2ec2d98c 100644
--- a/scripts/genksyms/genksyms.h
+++ b/scripts/genksyms/genksyms.h
@@ -47,7 +47,7 @@ typedef struct string_list **yystype;
#define YYSTYPE yystype
extern int cur_line;
-extern char *cur_filename, *source_file;
+extern char *cur_filename;
extern int in_source_file;
struct symbol *find_symbol(const char *name, enum symbol_type ns, int exact);
diff --git a/scripts/genksyms/keywords.c b/scripts/genksyms/keywords.c
index 057c6cabad1d..b85e0979a00c 100644
--- a/scripts/genksyms/keywords.c
+++ b/scripts/genksyms/keywords.c
@@ -32,6 +32,9 @@ static struct resword {
{ "restrict", RESTRICT_KEYW },
{ "asm", ASM_KEYW },
+ // c11 keywords that can be used at module scope
+ { "_Static_assert", STATIC_ASSERT_KEYW },
+
// attribute commented out in modutils 2.4.2. People are using 'attribute' as a
// field name which breaks the genksyms parser. It is not a gcc keyword anyway.
// KAO. },
diff --git a/scripts/genksyms/lex.l b/scripts/genksyms/lex.l
index e265c5d96861..a4d7495eaf75 100644
--- a/scripts/genksyms/lex.l
+++ b/scripts/genksyms/lex.l
@@ -118,13 +118,12 @@ yylex(void)
{
static enum {
ST_NOTSTARTED, ST_NORMAL, ST_ATTRIBUTE, ST_ASM, ST_TYPEOF, ST_TYPEOF_1,
- ST_BRACKET, ST_BRACE, ST_EXPRESSION,
- ST_TABLE_1, ST_TABLE_2, ST_TABLE_3, ST_TABLE_4,
- ST_TABLE_5, ST_TABLE_6
+ ST_BRACKET, ST_BRACE, ST_EXPRESSION, ST_STATIC_ASSERT,
} lexstate = ST_NOTSTARTED;
static int suppress_type_lookup, dont_want_brace_phrase;
static struct string_list *next_node;
+ static char *source_file;
int token, count = 0;
struct string_list *cur_node;
@@ -201,6 +200,11 @@ repeat:
case EXPORT_SYMBOL_KEYW:
goto fini;
+
+ case STATIC_ASSERT_KEYW:
+ lexstate = ST_STATIC_ASSERT;
+ count = 0;
+ goto repeat;
}
}
if (!suppress_type_lookup)
@@ -230,7 +234,6 @@ repeat:
lexstate = ST_EXPRESSION;
break;
- case DOTS:
default:
APP;
break;
@@ -401,55 +404,23 @@ repeat:
}
break;
- case ST_TABLE_1:
- goto repeat;
-
- case ST_TABLE_2:
- if (token == IDENT && yyleng == 1 && yytext[0] == 'X')
- {
- token = EXPORT_SYMBOL_KEYW;
- lexstate = ST_TABLE_5;
- APP;
- break;
- }
- lexstate = ST_TABLE_6;
- /* FALLTHRU */
-
- case ST_TABLE_6:
+ case ST_STATIC_ASSERT:
+ APP;
switch (token)
{
- case '{': case '[': case '(':
+ case '(':
++count;
- break;
- case '}': case ']': case ')':
- --count;
- break;
- case ',':
- if (count == 0)
- lexstate = ST_TABLE_2;
- break;
- };
- goto repeat;
-
- case ST_TABLE_3:
- goto repeat;
-
- case ST_TABLE_4:
- if (token == ';')
- lexstate = ST_NORMAL;
- goto repeat;
-
- case ST_TABLE_5:
- switch (token)
- {
- case ',':
- token = ';';
- lexstate = ST_TABLE_2;
- APP;
- break;
+ goto repeat;
+ case ')':
+ if (--count == 0)
+ {
+ lexstate = ST_NORMAL;
+ token = STATIC_ASSERT_PHRASE;
+ break;
+ }
+ goto repeat;
default:
- APP;
- break;
+ goto repeat;
}
break;
diff --git a/scripts/genksyms/parse.y b/scripts/genksyms/parse.y
index e22b42245bcc..8e9b5e69e8f0 100644
--- a/scripts/genksyms/parse.y
+++ b/scripts/genksyms/parse.y
@@ -80,6 +80,7 @@ static void record_compound(struct string_list **keyw,
%token SHORT_KEYW
%token SIGNED_KEYW
%token STATIC_KEYW
+%token STATIC_ASSERT_KEYW
%token STRUCT_KEYW
%token TYPEDEF_KEYW
%token UNION_KEYW
@@ -97,6 +98,7 @@ static void record_compound(struct string_list **keyw,
%token BRACE_PHRASE
%token BRACKET_PHRASE
%token EXPRESSION_PHRASE
+%token STATIC_ASSERT_PHRASE
%token CHAR
%token DOTS
@@ -130,6 +132,7 @@ declaration1:
| function_definition
| asm_definition
| export_definition
+ | static_assert
| error ';' { $$ = $2; }
| error '}' { $$ = $2; }
;
@@ -493,6 +496,10 @@ export_definition:
{ export_symbol((*$3)->string); $$ = $5; }
;
+/* Ignore any module scoped _Static_assert(...) */
+static_assert:
+ STATIC_ASSERT_PHRASE ';' { $$ = $2; }
+ ;
%%
diff --git a/scripts/get_abi.pl b/scripts/get_abi.pl
index 68dab828a722..92d9aa6cc4f5 100755
--- a/scripts/get_abi.pl
+++ b/scripts/get_abi.pl
@@ -1,4 +1,4 @@
-#!/usr/bin/perl
+#!/usr/bin/env perl
# SPDX-License-Identifier: GPL-2.0
use strict;
diff --git a/scripts/get_feat.pl b/scripts/get_feat.pl
new file mode 100755
index 000000000000..457712355676
--- /dev/null
+++ b/scripts/get_feat.pl
@@ -0,0 +1,630 @@
+#!/usr/bin/perl
+# SPDX-License-Identifier: GPL-2.0
+
+use strict;
+use Pod::Usage;
+use Getopt::Long;
+use File::Find;
+use Fcntl ':mode';
+use Cwd 'abs_path';
+
+my $help;
+my $man;
+my $debug;
+my $arch;
+my $feat;
+
+my $basename = abs_path($0);
+$basename =~ s,/[^/]+$,/,;
+
+my $prefix=$basename . "../Documentation/features";
+
+# Used only at for full features output. The script will auto-adjust
+# such values for the minimal possible values
+my $status_size = 1;
+my $description_size = 1;
+
+GetOptions(
+ "debug|d+" => \$debug,
+ "dir=s" => \$prefix,
+ 'help|?' => \$help,
+ 'arch=s' => \$arch,
+ 'feat=s' => \$feat,
+ 'feature=s' => \$feat,
+ man => \$man
+) or pod2usage(2);
+
+pod2usage(1) if $help;
+pod2usage(-exitstatus => 0, -verbose => 2) if $man;
+
+pod2usage(1) if (scalar @ARGV < 1 || @ARGV > 2);
+
+my ($cmd, $arg) = @ARGV;
+
+pod2usage(2) if ($cmd ne "current" && $cmd ne "rest" && $cmd ne "validate"
+ && $cmd ne "ls" && $cmd ne "list");
+
+require Data::Dumper if ($debug);
+
+my %data;
+my %archs;
+
+#
+# Displays an error message, printing file name and line
+#
+sub parse_error($$$$) {
+ my ($file, $ln, $msg, $data) = @_;
+
+ $data =~ s/\s+$/\n/;
+
+ print STDERR "Warning: file $file#$ln:\n\t$msg";
+
+ if ($data ne "") {
+ print STDERR ". Line\n\t\t$data";
+ } else {
+ print STDERR "\n";
+ }
+}
+
+#
+# Parse a features file, storing its contents at %data
+#
+
+my $h_name = "Feature";
+my $h_kconfig = "Kconfig";
+my $h_description = "Description";
+my $h_subsys = "Subsystem";
+my $h_status = "Status";
+my $h_arch = "Architecture";
+
+my $max_size_name = length($h_name);
+my $max_size_kconfig = length($h_kconfig);
+my $max_size_description = length($h_description);
+my $max_size_subsys = length($h_subsys);
+my $max_size_status = length($h_status);
+
+my $max_size_arch = 0;
+my $max_size_arch_with_header;
+my $max_description_word = 0;
+
+sub parse_feat {
+ my $file = $File::Find::name;
+
+ my $mode = (stat($file))[2];
+ return if ($mode & S_IFDIR);
+ return if ($file =~ m,($prefix)/arch-support.txt,);
+ return if (!($file =~ m,arch-support.txt$,));
+
+ my $subsys = "";
+ $subsys = $2 if ( m,.*($prefix)/([^/]+).*,);
+
+ if (length($subsys) > $max_size_subsys) {
+ $max_size_subsys = length($subsys);
+ }
+
+ my $name;
+ my $kconfig;
+ my $description;
+ my $comments = "";
+ my $last_status;
+ my $ln;
+ my %arch_table;
+
+ print STDERR "Opening $file\n" if ($debug > 1);
+ open IN, $file;
+
+ while(<IN>) {
+ $ln++;
+
+ if (m/^\#\s+Feature\s+name:\s*(.*\S)/) {
+ $name = $1;
+ if (length($name) > $max_size_name) {
+ $max_size_name = length($name);
+ }
+ next;
+ }
+ if (m/^\#\s+Kconfig:\s*(.*\S)/) {
+ $kconfig = $1;
+ if (length($kconfig) > $max_size_kconfig) {
+ $max_size_kconfig = length($kconfig);
+ }
+ next;
+ }
+ if (m/^\#\s+description:\s*(.*\S)/) {
+ $description = $1;
+ if (length($description) > $max_size_description) {
+ $max_size_description = length($description);
+ }
+
+ foreach my $word (split /\s+/, $description) {
+ if (length($word) > $max_description_word) {
+ $max_description_word = length($word);
+ }
+ }
+
+ next;
+ }
+ next if (m/^\\s*$/);
+ next if (m/^\s*\-+\s*$/);
+ next if (m/^\s*\|\s*arch\s*\|\s*status\s*\|\s*$/);
+
+ if (m/^\#\s*(.*)/) {
+ $comments .= "$1\n";
+ next;
+ }
+ if (m/^\s*\|\s*(\S+):\s*\|\s*(\S+)\s*\|\s*$/) {
+ my $a = $1;
+ my $status = $2;
+
+ if (length($status) > $max_size_status) {
+ $max_size_status = length($status);
+ }
+ if (length($a) > $max_size_arch) {
+ $max_size_arch = length($a);
+ }
+
+ $status = "---" if ($status =~ m/^\.\.$/);
+
+ $archs{$a} = 1;
+ $arch_table{$a} = $status;
+ next;
+ }
+
+ #Everything else is an error
+ parse_error($file, $ln, "line is invalid", $_);
+ }
+ close IN;
+
+ if (!$name) {
+ parse_error($file, $ln, "Feature name not found", "");
+ return;
+ }
+
+ parse_error($file, $ln, "Subsystem not found", "") if (!$subsys);
+ parse_error($file, $ln, "Kconfig not found", "") if (!$kconfig);
+ parse_error($file, $ln, "Description not found", "") if (!$description);
+
+ if (!%arch_table) {
+ parse_error($file, $ln, "Architecture table not found", "");
+ return;
+ }
+
+ $data{$name}->{where} = $file;
+ $data{$name}->{subsys} = $subsys;
+ $data{$name}->{kconfig} = $kconfig;
+ $data{$name}->{description} = $description;
+ $data{$name}->{comments} = $comments;
+ $data{$name}->{table} = \%arch_table;
+
+ $max_size_arch_with_header = $max_size_arch + length($h_arch);
+}
+
+#
+# Output feature(s) for a given architecture
+#
+sub output_arch_table {
+ my $title = "Feature status on $arch architecture";
+
+ print "=" x length($title) . "\n";
+ print "$title\n";
+ print "=" x length($title) . "\n\n";
+
+ print "=" x $max_size_subsys;
+ print " ";
+ print "=" x $max_size_name;
+ print " ";
+ print "=" x $max_size_kconfig;
+ print " ";
+ print "=" x $max_size_status;
+ print " ";
+ print "=" x $max_size_description;
+ print "\n";
+ printf "%-${max_size_subsys}s ", $h_subsys;
+ printf "%-${max_size_name}s ", $h_name;
+ printf "%-${max_size_kconfig}s ", $h_kconfig;
+ printf "%-${max_size_status}s ", $h_status;
+ printf "%-${max_size_description}s\n", $h_description;
+ print "=" x $max_size_subsys;
+ print " ";
+ print "=" x $max_size_name;
+ print " ";
+ print "=" x $max_size_kconfig;
+ print " ";
+ print "=" x $max_size_status;
+ print " ";
+ print "=" x $max_size_description;
+ print "\n";
+
+ foreach my $name (sort {
+ ($data{$a}->{subsys} cmp $data{$b}->{subsys}) ||
+ ("\L$a" cmp "\L$b")
+ } keys %data) {
+ next if ($feat && $name ne $feat);
+
+ my %arch_table = %{$data{$name}->{table}};
+ printf "%-${max_size_subsys}s ", $data{$name}->{subsys};
+ printf "%-${max_size_name}s ", $name;
+ printf "%-${max_size_kconfig}s ", $data{$name}->{kconfig};
+ printf "%-${max_size_status}s ", $arch_table{$arch};
+ printf "%-s\n", $data{$name}->{description};
+ }
+
+ print "=" x $max_size_subsys;
+ print " ";
+ print "=" x $max_size_name;
+ print " ";
+ print "=" x $max_size_kconfig;
+ print " ";
+ print "=" x $max_size_status;
+ print " ";
+ print "=" x $max_size_description;
+ print "\n";
+}
+
+#
+# list feature(s) for a given architecture
+#
+sub list_arch_features {
+ print "#\n# Kernel feature support matrix of the '$arch' architecture:\n#\n";
+
+ foreach my $name (sort {
+ ($data{$a}->{subsys} cmp $data{$b}->{subsys}) ||
+ ("\L$a" cmp "\L$b")
+ } keys %data) {
+ next if ($feat && $name ne $feat);
+
+ my %arch_table = %{$data{$name}->{table}};
+
+ my $status = $arch_table{$arch};
+ $status = " " x ((4 - length($status)) / 2) . $status;
+
+ printf " %${max_size_subsys}s/ ", $data{$name}->{subsys};
+ printf "%-${max_size_name}s: ", $name;
+ printf "%-5s| ", $status;
+ printf "%${max_size_kconfig}s # ", $data{$name}->{kconfig};
+ printf " %s\n", $data{$name}->{description};
+ }
+}
+
+#
+# Output a feature on all architectures
+#
+sub output_feature {
+ my $title = "Feature $feat";
+
+ print "=" x length($title) . "\n";
+ print "$title\n";
+ print "=" x length($title) . "\n\n";
+
+ print ":Subsystem: $data{$feat}->{subsys} \n" if ($data{$feat}->{subsys});
+ print ":Kconfig: $data{$feat}->{kconfig} \n" if ($data{$feat}->{kconfig});
+
+ my $desc = $data{$feat}->{description};
+ $desc =~ s/^([a-z])/\U$1/;
+ $desc =~ s/\.?\s*//;
+ print "\n$desc.\n\n";
+
+ my $com = $data{$feat}->{comments};
+ $com =~ s/^\s+//;
+ $com =~ s/\s+$//;
+ if ($com) {
+ print "Comments\n";
+ print "--------\n\n";
+ print "$com\n\n";
+ }
+
+ print "=" x $max_size_arch_with_header;
+ print " ";
+ print "=" x $max_size_status;
+ print "\n";
+
+ printf "%-${max_size_arch}s ", $h_arch;
+ printf "%-${max_size_status}s", $h_status . "\n";
+
+ print "=" x $max_size_arch_with_header;
+ print " ";
+ print "=" x $max_size_status;
+ print "\n";
+
+ my %arch_table = %{$data{$feat}->{table}};
+ foreach my $arch (sort keys %arch_table) {
+ printf "%-${max_size_arch}s ", $arch;
+ printf "%-${max_size_status}s\n", $arch_table{$arch};
+ }
+
+ print "=" x $max_size_arch_with_header;
+ print " ";
+ print "=" x $max_size_status;
+ print "\n";
+}
+
+#
+# Output all features for all architectures
+#
+
+sub matrix_lines($$$) {
+ my $desc_size = shift;
+ my $status_size = shift;
+ my $header = shift;
+ my $fill;
+ my $ln_marker;
+
+ if ($header) {
+ $ln_marker = "=";
+ } else {
+ $ln_marker = "-";
+ }
+
+ $fill = $ln_marker;
+
+ print "+";
+ print $fill x $max_size_name;
+ print "+";
+ print $fill x $desc_size;
+ print "+";
+ print $ln_marker x $status_size;
+ print "+\n";
+}
+
+sub output_matrix {
+ my $title = "Feature status on all architectures";
+ my $notcompat = "Not compatible";
+
+ print "=" x length($title) . "\n";
+ print "$title\n";
+ print "=" x length($title) . "\n\n";
+
+ my $desc_title = "$h_kconfig / $h_description";
+
+ my $desc_size = $max_size_kconfig + 4;
+ if (!$description_size) {
+ $desc_size = $max_size_description if ($max_size_description > $desc_size);
+ } else {
+ $desc_size = $description_size if ($description_size > $desc_size);
+ }
+ $desc_size = $max_description_word if ($max_description_word > $desc_size);
+
+ $desc_size = length($desc_title) if (length($desc_title) > $desc_size);
+
+ $max_size_status = length($notcompat) if (length($notcompat) > $max_size_status);
+
+ # Ensure that the status will fit
+ my $min_status_size = $max_size_status + $max_size_arch + 6;
+ $status_size = $min_status_size if ($status_size < $min_status_size);
+
+
+ my $cur_subsys = "";
+ foreach my $name (sort {
+ ($data{$a}->{subsys} cmp $data{$b}->{subsys}) or
+ ("\L$a" cmp "\L$b")
+ } keys %data) {
+
+ if ($cur_subsys ne $data{$name}->{subsys}) {
+ if ($cur_subsys ne "") {
+ printf "\n";
+ }
+
+ $cur_subsys = $data{$name}->{subsys};
+
+ my $title = "Subsystem: $cur_subsys";
+ print "$title\n";
+ print "=" x length($title) . "\n\n";
+
+
+ matrix_lines($desc_size, $status_size, 0);
+
+ printf "|%-${max_size_name}s", $h_name;
+ printf "|%-${desc_size}s", $desc_title;
+
+ printf "|%-${status_size}s|\n", "Status per architecture";
+ matrix_lines($desc_size, $status_size, 1);
+ }
+
+ my %arch_table = %{$data{$name}->{table}};
+ my $cur_status = "";
+
+ my (@lines, @descs);
+ my $line = "";
+ foreach my $arch (sort {
+ ($arch_table{$b} cmp $arch_table{$a}) or
+ ("\L$a" cmp "\L$b")
+ } keys %arch_table) {
+
+ my $status = $arch_table{$arch};
+
+ if ($status eq "---") {
+ $status = $notcompat;
+ }
+
+ if ($status ne $cur_status) {
+ if ($line ne "") {
+ push @lines, $line;
+ $line = "";
+ }
+ $line = "- **" . $status . "**: " . $arch;
+ } elsif (length($line) + length ($arch) + 2 < $status_size) {
+ $line .= ", " . $arch;
+ } else {
+ push @lines, $line;
+ $line = " " . $arch;
+ }
+ $cur_status = $status;
+ }
+ push @lines, $line if ($line ne "");
+
+ my $description = $data{$name}->{description};
+ while (length($description) > $desc_size) {
+ my $d = substr $description, 0, $desc_size;
+
+ # Ensure that it will end on a space
+ # if it can't, it means that the size is too small
+ # Instead of aborting it, let's print what we have
+ if (!($d =~ s/^(.*)\s+.*/$1/)) {
+ $d = substr $d, 0, -1;
+ push @descs, "$d\\";
+ $description =~ s/^\Q$d\E//;
+ } else {
+ push @descs, $d;
+ $description =~ s/^\Q$d\E\s+//;
+ }
+ }
+ push @descs, $description;
+
+ # Ensure that the full description will be printed
+ push @lines, "" while (scalar(@lines) < 2 + scalar(@descs));
+
+ my $ln = 0;
+ for my $line(@lines) {
+ if (!$ln) {
+ printf "|%-${max_size_name}s", $name;
+ printf "|%-${desc_size}s", "``" . $data{$name}->{kconfig} . "``";
+ } elsif ($ln >= 2 && scalar(@descs)) {
+ printf "|%-${max_size_name}s", "";
+ printf "|%-${desc_size}s", shift @descs;
+ } else {
+ printf "|%-${max_size_name}s", "";
+ printf "|%-${desc_size}s", "";
+ }
+
+ printf "|%-${status_size}s|\n", $line;
+
+ $ln++;
+ }
+ matrix_lines($desc_size, $status_size, 0);
+ }
+}
+
+
+#
+# Parses all feature files located at $prefix dir
+#
+find({wanted =>\&parse_feat, no_chdir => 1}, $prefix);
+
+print STDERR Data::Dumper->Dump([\%data], [qw(*data)]) if ($debug);
+
+#
+# Handles the command
+#
+if ($cmd eq "current") {
+ $arch = qx(uname -m | sed 's/x86_64/x86/' | sed 's/i386/x86/');
+ $arch =~s/\s+$//;
+}
+
+if ($cmd eq "ls" or $cmd eq "list") {
+ if (!$arch) {
+ $arch = qx(uname -m | sed 's/x86_64/x86/' | sed 's/i386/x86/');
+ $arch =~s/\s+$//;
+ }
+
+ list_arch_features;
+
+ exit;
+}
+
+if ($cmd ne "validate") {
+ if ($arch) {
+ output_arch_table;
+ } elsif ($feat) {
+ output_feature;
+ } else {
+ output_matrix;
+ }
+}
+
+__END__
+
+=head1 NAME
+
+get_feat.pl - parse the Linux Feature files and produce a ReST book.
+
+=head1 SYNOPSIS
+
+B<get_feat.pl> [--debug] [--man] [--help] [--dir=<dir>] [--arch=<arch>]
+ [--feature=<feature>|--feat=<feature>] <COMAND> [<ARGUMENT>]
+
+Where <COMMAND> can be:
+
+=over 8
+
+B<current> - output table in ReST compatible ASCII format
+ with features for this machine's architecture
+
+B<rest> - output table(s) in ReST compatible ASCII format
+ with features in ReST markup language. The output
+ is affected by --arch or --feat/--feature flags.
+
+B<validate> - validate the contents of the files under
+ Documentation/features.
+
+B<ls> or B<list> - list features for this machine's architecture,
+ using an easier to parse format.
+ The output is affected by --arch flag.
+
+=back
+
+=head1 OPTIONS
+
+=over 8
+
+=item B<--arch>
+
+Output features for an specific architecture, optionally filtering for
+a single specific feature.
+
+=item B<--feat> or B<--feature>
+
+Output features for a single specific feature.
+
+=item B<--dir>
+
+Changes the location of the Feature files. By default, it uses
+the Documentation/features directory.
+
+=item B<--debug>
+
+Put the script in verbose mode, useful for debugging. Can be called multiple
+times, to increase verbosity.
+
+=item B<--help>
+
+Prints a brief help message and exits.
+
+=item B<--man>
+
+Prints the manual page and exits.
+
+=back
+
+=head1 DESCRIPTION
+
+Parse the Linux feature files from Documentation/features (by default),
+optionally producing results at ReST format.
+
+It supports output data per architecture, per feature or a
+feature x arch matrix.
+
+When used with B<rest> command, it will use either one of the tree formats:
+
+If neither B<--arch> or B<--feature> arguments are used, it will output a
+matrix with features per architecture.
+
+If B<--arch> argument is used, it will output the features availability for
+a given architecture.
+
+If B<--feat> argument is used, it will output the content of the feature
+file using ReStructured Text markup.
+
+=head1 BUGS
+
+Report bugs to Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
+
+=head1 COPYRIGHT
+
+Copyright (c) 2019 by Mauro Carvalho Chehab <mchehab+samsung@kernel.org>.
+
+License GPLv2: GNU GPL version 2 <http://gnu.org/licenses/gpl.html>.
+
+This is free software: you are free to change and redistribute it.
+There is NO WARRANTY, to the extent permitted by law.
+
+=cut
diff --git a/scripts/jobserver-exec b/scripts/jobserver-exec
index 0fdb31a790a8..48d141e3ec56 100755
--- a/scripts/jobserver-exec
+++ b/scripts/jobserver-exec
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
# SPDX-License-Identifier: GPL-2.0+
#
# This determines how many parallel tasks "make" is expecting, as it is
diff --git a/scripts/kallsyms.c b/scripts/kallsyms.c
index 7ecd2ccba531..54ad86d13784 100644
--- a/scripts/kallsyms.c
+++ b/scripts/kallsyms.c
@@ -112,6 +112,12 @@ static bool is_ignored_symbol(const char *name, char type)
"__crc_", /* modversions */
"__efistub_", /* arm64 EFI stub namespace */
"__kvm_nvhe_", /* arm64 non-VHE KVM namespace */
+ "__AArch64ADRPThunk_", /* arm64 lld */
+ "__ARMV5PILongThunk_", /* arm lld */
+ "__ARMV7PILongThunk_",
+ "__ThumbV7PILongThunk_",
+ "__LA25Thunk_", /* mips lld */
+ "__microLA25Thunk_",
NULL
};
diff --git a/scripts/kconfig/Makefile b/scripts/kconfig/Makefile
index e46df0a2d4f9..8c19b82c6035 100644
--- a/scripts/kconfig/Makefile
+++ b/scripts/kconfig/Makefile
@@ -3,9 +3,6 @@
# Kernel configuration targets
# These targets are used from top-level makefile
-PHONY += xconfig gconfig menuconfig config localmodconfig localyesconfig \
- build_menuconfig build_nconfig build_gconfig build_xconfig
-
ifdef KBUILD_KCONFIG
Kconfig := $(KBUILD_KCONFIG)
else
@@ -19,29 +16,24 @@ endif
# We need this, in case the user has it in its environment
unexport CONFIG_
-xconfig: $(obj)/qconf
- $(Q)$< $(silent) $(Kconfig)
-
-gconfig: $(obj)/gconf
- $(Q)$< $(silent) $(Kconfig)
-
-menuconfig: $(obj)/mconf
- $(Q)$< $(silent) $(Kconfig)
-
-config: $(obj)/conf
- $(Q)$< $(silent) --oldaskconfig $(Kconfig)
+config-prog := conf
+menuconfig-prog := mconf
+nconfig-prog := nconf
+gconfig-prog := gconf
+xconfig-prog := qconf
-nconfig: $(obj)/nconf
- $(Q)$< $(silent) $(Kconfig)
+define config_rule
+PHONY += $(1)
+$(1): $(obj)/$($(1)-prog)
+ $(Q)$$< $(silent) $(Kconfig)
-build_menuconfig: $(obj)/mconf
+PHONY += build_$(1)
+build_$(1): $(obj)/$($(1)-prog)
+endef
-build_nconfig: $(obj)/nconf
-
-build_gconfig: $(obj)/gconf
-
-build_xconfig: $(obj)/qconf
+$(foreach c, config menuconfig nconfig gconfig xconfig, $(eval $(call config_rule,$(c))))
+PHONY += localmodconfig localyesconfig
localyesconfig localmodconfig: $(obj)/conf
$(Q)$(PERL) $(srctree)/$(src)/streamline_config.pl --$@ $(srctree) $(Kconfig) > .tmp.config
$(Q)if [ -f .config ]; then \
@@ -94,16 +86,6 @@ configfiles=$(wildcard $(srctree)/kernel/configs/$@ $(srctree)/arch/$(SRCARCH)/c
$(Q)$(CONFIG_SHELL) $(srctree)/scripts/kconfig/merge_config.sh -m .config $(configfiles)
$(Q)$(MAKE) -f $(srctree)/Makefile olddefconfig
-PHONY += kvmconfig
-kvmconfig: kvm_guest.config
- @echo >&2 "WARNING: 'make $@' will be removed after Linux 5.10"
- @echo >&2 " Please use 'make $<' instead."
-
-PHONY += xenconfig
-xenconfig: xen.config
- @echo >&2 "WARNING: 'make $@' will be removed after Linux 5.10"
- @echo >&2 " Please use 'make $<' instead."
-
PHONY += tinyconfig
tinyconfig:
$(Q)$(MAKE) -f $(srctree)/Makefile allnoconfig tiny.config
diff --git a/scripts/kconfig/conf.c b/scripts/kconfig/conf.c
index f6e548b8f795..957d2a0832f7 100644
--- a/scripts/kconfig/conf.c
+++ b/scripts/kconfig/conf.c
@@ -11,7 +11,6 @@
#include <time.h>
#include <unistd.h>
#include <getopt.h>
-#include <sys/stat.h>
#include <sys/time.h>
#include <errno.h>
@@ -85,8 +84,6 @@ static void xfgets(char *str, int size, FILE *in)
static int conf_askvalue(struct symbol *sym, const char *def)
{
- enum symbol_type type = sym_get_type(sym);
-
if (!sym_has_value(sym))
printf("(NEW) ");
@@ -108,24 +105,12 @@ static int conf_askvalue(struct symbol *sym, const char *def)
return 0;
}
/* fall through */
- case oldaskconfig:
+ default:
fflush(stdout);
xfgets(line, sizeof(line), stdin);
- return 1;
- default:
break;
}
- switch (type) {
- case S_INT:
- case S_HEX:
- case S_STRING:
- printf("%s\n", def);
- return 1;
- default:
- ;
- }
- printf("%s", line);
return 1;
}
@@ -138,7 +123,7 @@ static int conf_string(struct menu *menu)
printf("%*s%s ", indent - 1, "", menu->prompt->text);
printf("(%s) ", sym->name);
def = sym_get_string_value(sym);
- if (sym_get_string_value(sym))
+ if (def)
printf("[%s] ", def);
if (!conf_askvalue(sym, def))
return 0;
@@ -420,34 +405,37 @@ static void check_conf(struct menu *menu)
return;
sym = menu->sym;
- if (sym && !sym_has_value(sym)) {
- if (sym_is_changeable(sym) ||
- (sym_is_choice(sym) && sym_get_tristate_value(sym) == yes)) {
- if (input_mode == listnewconfig) {
- if (sym->name) {
- const char *str;
+ if (sym && !sym_has_value(sym) &&
+ (sym_is_changeable(sym) ||
+ (sym_is_choice(sym) && sym_get_tristate_value(sym) == yes))) {
- if (sym->type == S_STRING) {
- str = sym_get_string_value(sym);
- str = sym_escape_string_value(str);
- printf("%s%s=%s\n", CONFIG_, sym->name, str);
- free((void *)str);
- } else {
- str = sym_get_string_value(sym);
- printf("%s%s=%s\n", CONFIG_, sym->name, str);
- }
- }
- } else if (input_mode == helpnewconfig) {
- printf("-----\n");
- print_help(menu);
- printf("-----\n");
+ switch (input_mode) {
+ case listnewconfig:
+ if (sym->name) {
+ const char *str;
- } else {
- if (!conf_cnt++)
- printf("*\n* Restart config...\n*\n");
- rootEntry = menu_get_parent_menu(menu);
- conf(rootEntry);
+ if (sym->type == S_STRING) {
+ str = sym_get_string_value(sym);
+ str = sym_escape_string_value(str);
+ printf("%s%s=%s\n", CONFIG_, sym->name, str);
+ free((void *)str);
+ } else {
+ str = sym_get_string_value(sym);
+ printf("%s%s=%s\n", CONFIG_, sym->name, str);
+ }
}
+ break;
+ case helpnewconfig:
+ printf("-----\n");
+ print_help(menu);
+ printf("-----\n");
+ break;
+ default:
+ if (!conf_cnt++)
+ printf("*\n* Restart config...\n*\n");
+ rootEntry = menu_get_parent_menu(menu);
+ conf(rootEntry);
+ break;
}
}
@@ -495,6 +483,7 @@ static void conf_usage(const char *progname)
printf(" --randconfig New config with random answer to all options\n");
printf(" --yes2modconfig Change answers from yes to mod if possible\n");
printf(" --mod2yesconfig Change answers from mod to yes if possible\n");
+ printf(" (If none of the above is given, --oldaskconfig is the default)\n");
}
int main(int ac, char **av)
@@ -506,7 +495,7 @@ int main(int ac, char **av)
tty_stdio = isatty(0) && isatty(1);
- while ((opt = getopt_long(ac, av, "s", long_opts, NULL)) != -1) {
+ while ((opt = getopt_long(ac, av, "hs", long_opts, NULL)) != -1) {
if (opt == 's') {
conf_set_message_callback(NULL);
continue;
@@ -562,7 +551,7 @@ int main(int ac, char **av)
case yes2modconfig:
case mod2yesconfig:
break;
- case '?':
+ case 'h':
conf_usage(progname);
exit(1);
break;
diff --git a/scripts/kconfig/confdata.c b/scripts/kconfig/confdata.c
index a39d93e3c6ae..2568dbe16ed6 100644
--- a/scripts/kconfig/confdata.c
+++ b/scripts/kconfig/confdata.c
@@ -5,6 +5,7 @@
#include <sys/mman.h>
#include <sys/stat.h>
+#include <sys/types.h>
#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
diff --git a/scripts/kconfig/lexer.l b/scripts/kconfig/lexer.l
index 240109f965ae..9c22cb554673 100644
--- a/scripts/kconfig/lexer.l
+++ b/scripts/kconfig/lexer.l
@@ -12,7 +12,6 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <unistd.h>
#include "lkc.h"
#include "parser.tab.h"
diff --git a/scripts/kconfig/lkc.h b/scripts/kconfig/lkc.h
index 8454649b17bd..bee2413bda63 100644
--- a/scripts/kconfig/lkc.h
+++ b/scripts/kconfig/lkc.h
@@ -6,6 +6,10 @@
#ifndef LKC_H
#define LKC_H
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+
#include "expr.h"
#ifdef __cplusplus
diff --git a/scripts/kconfig/mconf-cfg.sh b/scripts/kconfig/mconf-cfg.sh
index aa68ec95620d..b520e407a8eb 100755
--- a/scripts/kconfig/mconf-cfg.sh
+++ b/scripts/kconfig/mconf-cfg.sh
@@ -33,7 +33,9 @@ if [ -f /usr/include/ncurses/ncurses.h ]; then
exit 0
fi
-if [ -f /usr/include/ncurses.h ]; then
+# As a final fallback before giving up, check if $HOSTCC knows of a default
+# ncurses installation (e.g. from a vendor-specific sysroot).
+if echo '#include <ncurses.h>' | ${HOSTCC} -E - >/dev/null 2>&1; then
echo cflags=\"-D_GNU_SOURCE\"
echo libs=\"-lncurses\"
exit 0
diff --git a/scripts/kconfig/preprocess.c b/scripts/kconfig/preprocess.c
index 0243086fb168..0590f86df6e4 100644
--- a/scripts/kconfig/preprocess.c
+++ b/scripts/kconfig/preprocess.c
@@ -114,7 +114,7 @@ static char *do_error_if(int argc, char *argv[])
if (!strcmp(argv[0], "y"))
pperror("%s", argv[1]);
- return NULL;
+ return xstrdup("");
}
static char *do_filename(int argc, char *argv[])
diff --git a/scripts/kconfig/qconf-cfg.sh b/scripts/kconfig/qconf-cfg.sh
index 02ccc0ae1031..fa564cd795b7 100755
--- a/scripts/kconfig/qconf-cfg.sh
+++ b/scripts/kconfig/qconf-cfg.sh
@@ -2,7 +2,6 @@
# SPDX-License-Identifier: GPL-2.0
PKG="Qt5Core Qt5Gui Qt5Widgets"
-PKG2="QtCore QtGui"
if [ -z "$(command -v pkg-config)" ]; then
echo >&2 "*"
@@ -12,21 +11,14 @@ if [ -z "$(command -v pkg-config)" ]; then
fi
if pkg-config --exists $PKG; then
- echo cflags=\"-std=c++11 -fPIC $(pkg-config --cflags Qt5Core Qt5Gui Qt5Widgets)\"
+ echo cflags=\"-std=c++11 -fPIC $(pkg-config --cflags $PKG)\"
echo libs=\"$(pkg-config --libs $PKG)\"
echo moc=\"$(pkg-config --variable=host_bins Qt5Core)/moc\"
exit 0
fi
-if pkg-config --exists $PKG2; then
- echo cflags=\"$(pkg-config --cflags $PKG2)\"
- echo libs=\"$(pkg-config --libs $PKG2)\"
- echo moc=\"$(pkg-config --variable=moc_location QtCore)\"
- exit 0
-fi
-
echo >&2 "*"
-echo >&2 "* Could not find Qt via pkg-config."
-echo >&2 "* Please install either Qt 4.8 or 5.x. and make sure it's in PKG_CONFIG_PATH"
+echo >&2 "* Could not find Qt5 via pkg-config."
+echo >&2 "* Please install Qt5 and make sure it's in PKG_CONFIG_PATH"
echo >&2 "*"
exit 1
diff --git a/scripts/kconfig/qconf.cc b/scripts/kconfig/qconf.cc
index f7eb093614f2..d000869b787c 100644
--- a/scripts/kconfig/qconf.cc
+++ b/scripts/kconfig/qconf.cc
@@ -310,15 +310,16 @@ ConfigList::ConfigList(QWidget *parent, const char *name)
setHeaderLabels(QStringList() << "Option" << "Name" << "Value");
- connect(this, SIGNAL(itemSelectionChanged(void)),
- SLOT(updateSelection(void)));
+ connect(this, &ConfigList::itemSelectionChanged,
+ this, &ConfigList::updateSelection);
if (name) {
configSettings->beginGroup(name);
showName = configSettings->value("/showName", false).toBool();
optMode = (enum optionMode)configSettings->value("/optionMode", 0).toInt();
configSettings->endGroup();
- connect(configApp, SIGNAL(aboutToQuit()), SLOT(saveSettings()));
+ connect(configApp, &QApplication::aboutToQuit,
+ this, &ConfigList::saveSettings);
}
showColumn(promptColIdx);
@@ -888,10 +889,10 @@ void ConfigList::contextMenuEvent(QContextMenuEvent *e)
headerPopup = new QMenu(this);
action = new QAction("Show Name", this);
action->setCheckable(true);
- connect(action, SIGNAL(toggled(bool)),
- SLOT(setShowName(bool)));
- connect(this, SIGNAL(showNameChanged(bool)),
- action, SLOT(setChecked(bool)));
+ connect(action, &QAction::toggled,
+ this, &ConfigList::setShowName);
+ connect(this, &ConfigList::showNameChanged,
+ action, &QAction::setChecked);
action->setChecked(showName);
headerPopup->addAction(action);
}
@@ -936,15 +937,18 @@ ConfigInfoView::ConfigInfoView(QWidget* parent, const char *name)
configSettings->beginGroup(objectName());
setShowDebug(configSettings->value("/showDebug", false).toBool());
configSettings->endGroup();
- connect(configApp, SIGNAL(aboutToQuit()), SLOT(saveSettings()));
+ connect(configApp, &QApplication::aboutToQuit,
+ this, &ConfigInfoView::saveSettings);
}
contextMenu = createStandardContextMenu();
QAction *action = new QAction("Show Debug Info", contextMenu);
action->setCheckable(true);
- connect(action, SIGNAL(toggled(bool)), SLOT(setShowDebug(bool)));
- connect(this, SIGNAL(showDebugChanged(bool)), action, SLOT(setChecked(bool)));
+ connect(action, &QAction::toggled,
+ this, &ConfigInfoView::setShowDebug);
+ connect(this, &ConfigInfoView::showDebugChanged,
+ action, &QAction::setChecked);
action->setChecked(showDebug());
contextMenu->addSeparator();
contextMenu->addAction(action);
@@ -1231,11 +1235,13 @@ ConfigSearchWindow::ConfigSearchWindow(ConfigMainWindow *parent)
layout2->setSpacing(6);
layout2->addWidget(new QLabel("Find:", this));
editField = new QLineEdit(this);
- connect(editField, SIGNAL(returnPressed()), SLOT(search()));
+ connect(editField, &QLineEdit::returnPressed,
+ this, &ConfigSearchWindow::search);
layout2->addWidget(editField);
searchButton = new QPushButton("Search", this);
searchButton->setAutoDefault(false);
- connect(searchButton, SIGNAL(clicked()), SLOT(search()));
+ connect(searchButton, &QPushButton::clicked,
+ this, &ConfigSearchWindow::search);
layout2->addWidget(searchButton);
layout1->addLayout(layout2);
@@ -1244,10 +1250,10 @@ ConfigSearchWindow::ConfigSearchWindow(ConfigMainWindow *parent)
list = new ConfigList(split, "search");
list->mode = listMode;
info = new ConfigInfoView(split, "search");
- connect(list, SIGNAL(menuChanged(struct menu *)),
- info, SLOT(setInfo(struct menu *)));
- connect(list, SIGNAL(menuChanged(struct menu *)),
- parent, SLOT(setMenuLink(struct menu *)));
+ connect(list, &ConfigList::menuChanged,
+ info, &ConfigInfoView::setInfo);
+ connect(list, &ConfigList::menuChanged,
+ parent, &ConfigMainWindow::setMenuLink);
layout1->addWidget(split);
@@ -1267,7 +1273,8 @@ ConfigSearchWindow::ConfigSearchWindow(ConfigMainWindow *parent)
if (ok)
split->setSizes(sizes);
configSettings->endGroup();
- connect(configApp, SIGNAL(aboutToQuit()), SLOT(saveSettings()));
+ connect(configApp, &QApplication::aboutToQuit,
+ this, &ConfigSearchWindow::saveSettings);
}
void ConfigSearchWindow::saveSettings(void)
@@ -1367,19 +1374,23 @@ ConfigMainWindow::ConfigMainWindow(void)
configList->setFocus();
backAction = new QAction(QPixmap(xpm_back), "Back", this);
- connect(backAction, SIGNAL(triggered(bool)), SLOT(goBack()));
+ connect(backAction, &QAction::triggered,
+ this, &ConfigMainWindow::goBack);
QAction *quitAction = new QAction("&Quit", this);
quitAction->setShortcut(Qt::CTRL + Qt::Key_Q);
- connect(quitAction, SIGNAL(triggered(bool)), SLOT(close()));
+ connect(quitAction, &QAction::triggered,
+ this, &ConfigMainWindow::close);
QAction *loadAction = new QAction(QPixmap(xpm_load), "&Load", this);
loadAction->setShortcut(Qt::CTRL + Qt::Key_L);
- connect(loadAction, SIGNAL(triggered(bool)), SLOT(loadConfig()));
+ connect(loadAction, &QAction::triggered,
+ this, &ConfigMainWindow::loadConfig);
saveAction = new QAction(QPixmap(xpm_save), "&Save", this);
saveAction->setShortcut(Qt::CTRL + Qt::Key_S);
- connect(saveAction, SIGNAL(triggered(bool)), SLOT(saveConfig()));
+ connect(saveAction, &QAction::triggered,
+ this, &ConfigMainWindow::saveConfig);
conf_set_changed_callback(conf_changed);
@@ -1388,31 +1399,37 @@ ConfigMainWindow::ConfigMainWindow(void)
configname = xstrdup(conf_get_configname());
QAction *saveAsAction = new QAction("Save &As...", this);
- connect(saveAsAction, SIGNAL(triggered(bool)), SLOT(saveConfigAs()));
+ connect(saveAsAction, &QAction::triggered,
+ this, &ConfigMainWindow::saveConfigAs);
QAction *searchAction = new QAction("&Find", this);
searchAction->setShortcut(Qt::CTRL + Qt::Key_F);
- connect(searchAction, SIGNAL(triggered(bool)), SLOT(searchConfig()));
+ connect(searchAction, &QAction::triggered,
+ this, &ConfigMainWindow::searchConfig);
singleViewAction = new QAction(QPixmap(xpm_single_view), "Single View", this);
singleViewAction->setCheckable(true);
- connect(singleViewAction, SIGNAL(triggered(bool)), SLOT(showSingleView()));
+ connect(singleViewAction, &QAction::triggered,
+ this, &ConfigMainWindow::showSingleView);
splitViewAction = new QAction(QPixmap(xpm_split_view), "Split View", this);
splitViewAction->setCheckable(true);
- connect(splitViewAction, SIGNAL(triggered(bool)), SLOT(showSplitView()));
+ connect(splitViewAction, &QAction::triggered,
+ this, &ConfigMainWindow::showSplitView);
fullViewAction = new QAction(QPixmap(xpm_tree_view), "Full View", this);
fullViewAction->setCheckable(true);
- connect(fullViewAction, SIGNAL(triggered(bool)), SLOT(showFullView()));
+ connect(fullViewAction, &QAction::triggered,
+ this, &ConfigMainWindow::showFullView);
QAction *showNameAction = new QAction("Show Name", this);
showNameAction->setCheckable(true);
- connect(showNameAction, SIGNAL(toggled(bool)), configList, SLOT(setShowName(bool)));
+ connect(showNameAction, &QAction::toggled,
+ configList, &ConfigList::setShowName);
showNameAction->setChecked(configList->showName);
QActionGroup *optGroup = new QActionGroup(this);
optGroup->setExclusive(true);
- connect(optGroup, SIGNAL(triggered(QAction*)), configList,
- SLOT(setOptionMode(QAction *)));
- connect(optGroup, SIGNAL(triggered(QAction *)), menuList,
- SLOT(setOptionMode(QAction *)));
+ connect(optGroup, &QActionGroup::triggered,
+ configList, &ConfigList::setOptionMode);
+ connect(optGroup, &QActionGroup::triggered,
+ menuList, &ConfigList::setOptionMode);
ConfigList::showNormalAction = new QAction("Show Normal Options", optGroup);
ConfigList::showNormalAction->setCheckable(true);
@@ -1423,13 +1440,16 @@ ConfigMainWindow::ConfigMainWindow(void)
QAction *showDebugAction = new QAction("Show Debug Info", this);
showDebugAction->setCheckable(true);
- connect(showDebugAction, SIGNAL(toggled(bool)), helpText, SLOT(setShowDebug(bool)));
+ connect(showDebugAction, &QAction::toggled,
+ helpText, &ConfigInfoView::setShowDebug);
showDebugAction->setChecked(helpText->showDebug());
QAction *showIntroAction = new QAction("Introduction", this);
- connect(showIntroAction, SIGNAL(triggered(bool)), SLOT(showIntro()));
+ connect(showIntroAction, &QAction::triggered,
+ this, &ConfigMainWindow::showIntro);
QAction *showAboutAction = new QAction("About", this);
- connect(showAboutAction, SIGNAL(triggered(bool)), SLOT(showAbout()));
+ connect(showAboutAction, &QAction::triggered,
+ this, &ConfigMainWindow::showAbout);
// init tool bar
QToolBar *toolBar = addToolBar("Tools");
@@ -1467,30 +1487,30 @@ ConfigMainWindow::ConfigMainWindow(void)
menu->addAction(showIntroAction);
menu->addAction(showAboutAction);
- connect (helpText, SIGNAL (anchorClicked (const QUrl &)),
- helpText, SLOT (clicked (const QUrl &)) );
+ connect(helpText, &ConfigInfoView::anchorClicked,
+ helpText, &ConfigInfoView::clicked);
- connect(configList, SIGNAL(menuChanged(struct menu *)),
- helpText, SLOT(setInfo(struct menu *)));
- connect(configList, SIGNAL(menuSelected(struct menu *)),
- SLOT(changeMenu(struct menu *)));
- connect(configList, SIGNAL(itemSelected(struct menu *)),
- SLOT(changeItens(struct menu *)));
- connect(configList, SIGNAL(parentSelected()),
- SLOT(goBack()));
- connect(menuList, SIGNAL(menuChanged(struct menu *)),
- helpText, SLOT(setInfo(struct menu *)));
- connect(menuList, SIGNAL(menuSelected(struct menu *)),
- SLOT(changeMenu(struct menu *)));
+ connect(configList, &ConfigList::menuChanged,
+ helpText, &ConfigInfoView::setInfo);
+ connect(configList, &ConfigList::menuSelected,
+ this, &ConfigMainWindow::changeMenu);
+ connect(configList, &ConfigList::itemSelected,
+ this, &ConfigMainWindow::changeItens);
+ connect(configList, &ConfigList::parentSelected,
+ this, &ConfigMainWindow::goBack);
+ connect(menuList, &ConfigList::menuChanged,
+ helpText, &ConfigInfoView::setInfo);
+ connect(menuList, &ConfigList::menuSelected,
+ this, &ConfigMainWindow::changeMenu);
- connect(configList, SIGNAL(gotFocus(struct menu *)),
- helpText, SLOT(setInfo(struct menu *)));
- connect(menuList, SIGNAL(gotFocus(struct menu *)),
- helpText, SLOT(setInfo(struct menu *)));
- connect(menuList, SIGNAL(gotFocus(struct menu *)),
- SLOT(listFocusChanged(void)));
- connect(helpText, SIGNAL(menuSelected(struct menu *)),
- SLOT(setMenuLink(struct menu *)));
+ connect(configList, &ConfigList::gotFocus,
+ helpText, &ConfigInfoView::setInfo);
+ connect(menuList, &ConfigList::gotFocus,
+ helpText, &ConfigInfoView::setInfo);
+ connect(menuList, &ConfigList::gotFocus,
+ this, &ConfigMainWindow::listFocusChanged);
+ connect(helpText, &ConfigInfoView::menuSelected,
+ this, &ConfigMainWindow::setMenuLink);
QString listMode = configSettings->value("/listMode", "symbol").toString();
if (listMode == "single")
@@ -1779,10 +1799,13 @@ void ConfigMainWindow::showIntro(void)
void ConfigMainWindow::showAbout(void)
{
static const QString str = "qconf is Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>.\n"
- "Copyright (C) 2015 Boris Barbulovski <bbarbulovski@gmail.com>.\n\n"
- "Bug reports and feature request can also be entered at http://bugzilla.kernel.org/\n";
+ "Copyright (C) 2015 Boris Barbulovski <bbarbulovski@gmail.com>.\n"
+ "\n"
+ "Bug reports and feature request can also be entered at http://bugzilla.kernel.org/\n"
+ "\n"
+ "Qt Version: ";
- QMessageBox::information(this, "qconf", str);
+ QMessageBox::information(this, "qconf", str + qVersion());
}
void ConfigMainWindow::saveSettings(void)
diff --git a/scripts/kconfig/symbol.c b/scripts/kconfig/symbol.c
index ffa3ec65cc90..fe38e6fd2c2a 100644
--- a/scripts/kconfig/symbol.c
+++ b/scripts/kconfig/symbol.c
@@ -3,11 +3,11 @@
* Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
*/
+#include <sys/types.h>
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
#include <regex.h>
-#include <sys/utsname.h>
#include "lkc.h"
diff --git a/scripts/kernel-doc b/scripts/kernel-doc
index f699cf05d409..8b5bc7bf4bb8 100755
--- a/scripts/kernel-doc
+++ b/scripts/kernel-doc
@@ -382,6 +382,9 @@ my $inline_doc_state;
# 'function', 'struct', 'union', 'enum', 'typedef'
my $decl_type;
+# Name of the kernel-doc identifier for non-DOC markups
+my $identifier;
+
my $doc_start = '^/\*\*\s*$'; # Allow whitespace at end of comment start.
my $doc_end = '\*/';
my $doc_com = '\s*\*\s*';
@@ -833,6 +836,7 @@ sub output_blockhead_rst(%) {
next if (defined($nosymbol_table{$section}));
if ($output_selection != OUTPUT_INCLUDE) {
+ print ".. _$section:\n\n";
print "**$section**\n\n";
}
print_lineno($section_start_lines{$section});
@@ -1203,6 +1207,11 @@ sub dump_struct($$) {
$declaration_name = $2;
my $members = $3;
+ if ($identifier ne $declaration_name) {
+ print STDERR "${file}:$.: warning: expecting prototype for $decl_type $identifier. Prototype was for $decl_type $declaration_name instead\n";
+ return;
+ }
+
# ignore members marked private:
$members =~ s/\/\*\s*private:.*?\/\*\s*public:.*?\*\///gosi;
$members =~ s/\/\*\s*private:.*//gosi;
@@ -1390,7 +1399,12 @@ sub dump_enum($$) {
$members = $2;
}
- if ($declaration_name) {
+ if ($members) {
+ if ($identifier ne $declaration_name) {
+ print STDERR "${file}:$.: warning: expecting prototype for enum $identifier. Prototype was for enum $declaration_name instead\n";
+ return;
+ }
+
my %_members;
$members =~ s/\s+$//;
@@ -1431,7 +1445,7 @@ sub dump_enum($$) {
}
}
-my $typedef_type = qr { ((?:\s+[\w\*]+){1,8})\s* }x;
+my $typedef_type = qr { ((?:\s+[\w\*]+\b){1,8})\s* }x;
my $typedef_ident = qr { \*?\s*(\w\S+)\s* }x;
my $typedef_args = qr { \s*\((.*)\); }x;
@@ -1451,6 +1465,11 @@ sub dump_typedef($$) {
my $args = $3;
$return_type =~ s/^\s+//;
+ if ($identifier ne $declaration_name) {
+ print STDERR "${file}:$.: warning: expecting prototype for typedef $identifier. Prototype was for typedef $declaration_name instead\n";
+ return;
+ }
+
create_parameterlist($args, ',', $file, $declaration_name);
output_declaration($declaration_name,
@@ -1477,6 +1496,11 @@ sub dump_typedef($$) {
if ($x =~ /typedef.*\s+(\w+)\s*;/) {
$declaration_name = $1;
+ if ($identifier ne $declaration_name) {
+ print STDERR "${file}:$.: warning: expecting prototype for typedef $identifier. Prototype was for typedef $declaration_name instead\n";
+ return;
+ }
+
output_declaration($declaration_name,
'typedef',
{'typedef' => $declaration_name,
@@ -1529,7 +1553,7 @@ sub create_parameterlist($$$$) {
} elsif ($arg =~ m/\(.+\)\s*\(/) {
# pointer-to-function
$arg =~ tr/#/,/;
- $arg =~ m/[^\(]+\(\*?\s*([\w\.]*)\s*\)/;
+ $arg =~ m/[^\(]+\(\*?\s*([\w\[\]\.]*)\s*\)/;
$param = $1;
$type = $arg;
$type =~ s/([^\(]+\(\*?)\s*$param/$1/;
@@ -1796,6 +1820,11 @@ sub dump_function($$) {
return;
}
+ if ($identifier ne $declaration_name) {
+ print STDERR "${file}:$.: warning: expecting prototype for $identifier(). Prototype was for $declaration_name() instead\n";
+ return;
+ }
+
my $prms = join " ", @parameterlist;
check_sections($file, $declaration_name, "function", $sectcheck, $prms);
@@ -1878,6 +1907,7 @@ sub tracepoint_munge($) {
"$prototype\n";
} else {
$prototype = "static inline void trace_$tracepointname($tracepointargs)";
+ $identifier = "trace_$identifier";
}
}
@@ -2041,7 +2071,6 @@ sub process_normal() {
#
sub process_name($$) {
my $file = shift;
- my $identifier;
my $descr;
if (/$doc_block/o) {
@@ -2054,12 +2083,19 @@ sub process_name($$) {
} else {
$section = $1;
}
- }
- elsif (/$doc_decl/o) {
+ } elsif (/$doc_decl/o) {
$identifier = $1;
- if (/\s*([\w\s]+?)(\(\))?\s*-/) {
+ if (/\s*([\w\s]+?)(\(\))?\s*([-:].*)?$/) {
$identifier = $1;
}
+ if ($identifier =~ m/^(struct|union|enum|typedef)\b\s*(\S*)/) {
+ $decl_type = $1;
+ $identifier = $2;
+ } else {
+ $decl_type = 'function';
+ $identifier =~ s/^define\s+//;
+ }
+ $identifier =~ s/\s+$//;
$state = STATE_BODY;
# if there's no @param blocks need to set up default section
@@ -2067,7 +2103,7 @@ sub process_name($$) {
$contents = "";
$section = $section_default;
$new_start_line = $. + 1;
- if (/-(.*)/) {
+ if (/[-:](.*)/) {
# strip leading/trailing/multiple spaces
$descr= $1;
$descr =~ s/^\s*//;
@@ -2085,20 +2121,15 @@ sub process_name($$) {
++$warnings;
}
- if ($identifier =~ m/^struct\b/) {
- $decl_type = 'struct';
- } elsif ($identifier =~ m/^union\b/) {
- $decl_type = 'union';
- } elsif ($identifier =~ m/^enum\b/) {
- $decl_type = 'enum';
- } elsif ($identifier =~ m/^typedef\b/) {
- $decl_type = 'typedef';
- } else {
- $decl_type = 'function';
+ if ($identifier eq "") {
+ print STDERR "${file}:$.: warning: wrong kernel-doc identifier on line:\n";
+ print STDERR $_;
+ ++$warnings;
+ $state = STATE_NORMAL;
}
if ($verbose) {
- print STDERR "${file}:$.: info: Scanning doc for $identifier\n";
+ print STDERR "${file}:$.: info: Scanning doc for $decl_type $identifier\n";
}
} else {
print STDERR "${file}:$.: warning: Cannot understand $_ on line $.",
diff --git a/scripts/ld-version.sh b/scripts/ld-version.sh
index f2be0ff9a738..1bf3aadde9de 100755
--- a/scripts/ld-version.sh
+++ b/scripts/ld-version.sh
@@ -1,11 +1,79 @@
-#!/usr/bin/awk -f
+#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
-# extract linker version number from stdin and turn into single number
- {
- gsub(".*\\)", "");
- gsub(".*version ", "");
- gsub("-.*", "");
- split($1,a, ".");
- print a[1]*100000000 + a[2]*1000000 + a[3]*10000;
- exit
- }
+#
+# Print the linker name and its version in a 5 or 6-digit form.
+# Also, perform the minimum version check.
+
+set -e
+
+# When you raise the minimum linker version, please update
+# Documentation/process/changes.rst as well.
+bfd_min_version=2.23.0
+lld_min_version=10.0.1
+
+# Convert the version string x.y.z to a canonical 5 or 6-digit form.
+get_canonical_version()
+{
+ IFS=.
+ set -- $1
+
+ # If the 2nd or 3rd field is missing, fill it with a zero.
+ #
+ # The 4th field, if present, is ignored.
+ # This occurs in development snapshots as in 2.35.1.20201116
+ echo $((10000 * $1 + 100 * ${2:-0} + ${3:-0}))
+}
+
+orig_args="$@"
+
+# Get the first line of the --version output.
+IFS='
+'
+set -- $(LC_ALL=C "$@" --version)
+
+# Split the line on spaces.
+IFS=' '
+set -- $1
+
+if [ "$1" = GNU -a "$2" = ld ]; then
+ shift $(($# - 1))
+ version=$1
+ min_version=$bfd_min_version
+ name=BFD
+ disp_name="GNU ld"
+elif [ "$1" = GNU -a "$2" = gold ]; then
+ echo "gold linker is not supported as it is not capable of linking the kernel proper." >&2
+ exit 1
+else
+ while [ $# -gt 1 -a "$1" != "LLD" ]; do
+ shift
+ done
+
+ if [ "$1" = LLD ]; then
+ version=$2
+ min_version=$lld_min_version
+ name=LLD
+ disp_name=LLD
+ else
+ echo "$orig_args: unknown linker" >&2
+ exit 1
+ fi
+fi
+
+# Some distributions append a package release number, as in 2.34-4.fc32
+# Trim the hyphen and any characters that follow.
+version=${version%-*}
+
+cversion=$(get_canonical_version $version)
+min_cversion=$(get_canonical_version $min_version)
+
+if [ "$cversion" -lt "$min_cversion" ]; then
+ echo >&2 "***"
+ echo >&2 "*** Linker is too old."
+ echo >&2 "*** Your $disp_name version: $version"
+ echo >&2 "*** Minimum $disp_name version: $min_version"
+ echo >&2 "***"
+ exit 1
+fi
+
+echo $name $cversion
diff --git a/scripts/link-vmlinux.sh b/scripts/link-vmlinux.sh
index 6eded325c837..3b261b0f74f0 100755
--- a/scripts/link-vmlinux.sh
+++ b/scripts/link-vmlinux.sh
@@ -43,11 +43,37 @@ info()
fi
}
+# Generate a linker script to ensure correct ordering of initcalls.
+gen_initcalls()
+{
+ info GEN .tmp_initcalls.lds
+
+ ${PYTHON} ${srctree}/scripts/jobserver-exec \
+ ${PERL} ${srctree}/scripts/generate_initcall_order.pl \
+ ${KBUILD_VMLINUX_OBJS} ${KBUILD_VMLINUX_LIBS} \
+ > .tmp_initcalls.lds
+}
+
+# If CONFIG_LTO_CLANG is selected, collect generated symbol versions into
+# .tmp_symversions.lds
+gen_symversions()
+{
+ info GEN .tmp_symversions.lds
+ rm -f .tmp_symversions.lds
+
+ for o in ${KBUILD_VMLINUX_OBJS} ${KBUILD_VMLINUX_LIBS}; do
+ if [ -f ${o}.symversions ]; then
+ cat ${o}.symversions >> .tmp_symversions.lds
+ fi
+ done
+}
+
# Link of vmlinux.o used for section mismatch analysis
# ${1} output file
modpost_link()
{
local objects
+ local lds=""
objects="--whole-archive \
${KBUILD_VMLINUX_OBJS} \
@@ -56,19 +82,57 @@ modpost_link()
${KBUILD_VMLINUX_LIBS} \
--end-group"
- ${LD} ${KBUILD_LDFLAGS} -r -o ${1} ${objects}
+ if [ -n "${CONFIG_LTO_CLANG}" ]; then
+ gen_initcalls
+ lds="-T .tmp_initcalls.lds"
+
+ if [ -n "${CONFIG_MODVERSIONS}" ]; then
+ gen_symversions
+ lds="${lds} -T .tmp_symversions.lds"
+ fi
+
+ # This might take a while, so indicate that we're doing
+ # an LTO link
+ info LTO ${1}
+ else
+ info LD ${1}
+ fi
+
+ ${LD} ${KBUILD_LDFLAGS} -r -o ${1} ${lds} ${objects}
}
objtool_link()
{
+ local objtoolcmd;
local objtoolopt;
+ if [ "${CONFIG_LTO_CLANG} ${CONFIG_STACK_VALIDATION}" = "y y" ]; then
+ # Don't perform vmlinux validation unless explicitly requested,
+ # but run objtool on vmlinux.o now that we have an object file.
+ if [ -n "${CONFIG_UNWINDER_ORC}" ]; then
+ objtoolcmd="orc generate"
+ fi
+
+ objtoolopt="${objtoolopt} --duplicate"
+
+ if [ -n "${CONFIG_FTRACE_MCOUNT_USE_OBJTOOL}" ]; then
+ objtoolopt="${objtoolopt} --mcount"
+ fi
+ fi
+
if [ -n "${CONFIG_VMLINUX_VALIDATION}" ]; then
- objtoolopt="check"
+ objtoolopt="${objtoolopt} --noinstr"
+ fi
+
+ if [ -n "${objtoolopt}" ]; then
+ if [ -z "${objtoolcmd}" ]; then
+ objtoolcmd="check"
+ fi
+ objtoolopt="${objtoolopt} --vmlinux"
if [ -z "${CONFIG_FRAME_POINTER}" ]; then
objtoolopt="${objtoolopt} --no-fp"
fi
- if [ -n "${CONFIG_GCOV_KERNEL}" ]; then
+ if [ -n "${CONFIG_GCOV_KERNEL}" ] || [ -n "${CONFIG_LTO_CLANG}" ]; then
objtoolopt="${objtoolopt} --no-unreachable"
fi
if [ -n "${CONFIG_RETPOLINE}" ]; then
@@ -78,7 +142,7 @@ objtool_link()
objtoolopt="${objtoolopt} --uaccess"
fi
info OBJTOOL ${1}
- tools/objtool/objtool ${objtoolopt} ${1}
+ tools/objtool/objtool ${objtoolcmd} ${objtoolopt} ${1}
fi
}
@@ -103,13 +167,22 @@ vmlinux_link()
fi
if [ "${SRCARCH}" != "um" ]; then
- objects="--whole-archive \
- ${KBUILD_VMLINUX_OBJS} \
- --no-whole-archive \
- --start-group \
- ${KBUILD_VMLINUX_LIBS} \
- --end-group \
- ${@}"
+ if [ -n "${CONFIG_LTO_CLANG}" ]; then
+ # Use vmlinux.o instead of performing the slow LTO
+ # link again.
+ objects="--whole-archive \
+ vmlinux.o \
+ --no-whole-archive \
+ ${@}"
+ else
+ objects="--whole-archive \
+ ${KBUILD_VMLINUX_OBJS} \
+ --no-whole-archive \
+ --start-group \
+ ${KBUILD_VMLINUX_LIBS} \
+ --end-group \
+ ${@}"
+ fi
${LD} ${KBUILD_LDFLAGS} ${LDFLAGS_vmlinux} \
${strip_debug#-Wl,} \
@@ -225,6 +298,8 @@ cleanup()
{
rm -f .btf.*
rm -f .tmp_System.map
+ rm -f .tmp_initcalls.lds
+ rm -f .tmp_symversions.lds
rm -f .tmp_vmlinux*
rm -f System.map
rm -f vmlinux
@@ -274,7 +349,6 @@ fi;
${MAKE} -f "${srctree}/scripts/Makefile.build" obj=init need-builtin=1
#link vmlinux.o
-info LD vmlinux.o
modpost_link vmlinux.o
objtool_link vmlinux.o
diff --git a/scripts/lld-version.sh b/scripts/lld-version.sh
deleted file mode 100755
index d70edb4d8a4f..000000000000
--- a/scripts/lld-version.sh
+++ /dev/null
@@ -1,20 +0,0 @@
-#!/bin/sh
-# SPDX-License-Identifier: GPL-2.0
-#
-# Usage: $ ./scripts/lld-version.sh ld.lld
-#
-# Print the linker version of `ld.lld' in a 5 or 6-digit form
-# such as `100001' for ld.lld 10.0.1 etc.
-
-linker_string="$($* --version)"
-
-if ! ( echo $linker_string | grep -q LLD ); then
- echo 0
- exit 1
-fi
-
-VERSION=$(echo $linker_string | cut -d ' ' -f 2)
-MAJOR=$(echo $VERSION | cut -d . -f 1)
-MINOR=$(echo $VERSION | cut -d . -f 2)
-PATCHLEVEL=$(echo $VERSION | cut -d . -f 3)
-printf "%d%02d%02d\\n" $MAJOR $MINOR $PATCHLEVEL
diff --git a/scripts/mod/Makefile b/scripts/mod/Makefile
index 78071681d924..c9e38ad937fd 100644
--- a/scripts/mod/Makefile
+++ b/scripts/mod/Makefile
@@ -1,5 +1,6 @@
# SPDX-License-Identifier: GPL-2.0
OBJECT_FILES_NON_STANDARD := y
+CFLAGS_REMOVE_empty.o += $(CC_FLAGS_LTO)
hostprogs-always-y += modpost mk_elfconfig
always-y += empty.o
diff --git a/scripts/mod/devicetable-offsets.c b/scripts/mod/devicetable-offsets.c
index 27007c18e754..9bb6c7edccc4 100644
--- a/scripts/mod/devicetable-offsets.c
+++ b/scripts/mod/devicetable-offsets.c
@@ -243,5 +243,20 @@ int main(void)
DEVID(mhi_device_id);
DEVID_FIELD(mhi_device_id, chan);
+ DEVID(auxiliary_device_id);
+ DEVID_FIELD(auxiliary_device_id, name);
+
+ DEVID(ssam_device_id);
+ DEVID_FIELD(ssam_device_id, match_flags);
+ DEVID_FIELD(ssam_device_id, domain);
+ DEVID_FIELD(ssam_device_id, category);
+ DEVID_FIELD(ssam_device_id, target);
+ DEVID_FIELD(ssam_device_id, instance);
+ DEVID_FIELD(ssam_device_id, function);
+
+ DEVID(dfl_device_id);
+ DEVID_FIELD(dfl_device_id, type);
+ DEVID_FIELD(dfl_device_id, feature_id);
+
return 0;
}
diff --git a/scripts/mod/file2alias.c b/scripts/mod/file2alias.c
index 2417dd1dee33..7c97fa8e36bc 100644
--- a/scripts/mod/file2alias.c
+++ b/scripts/mod/file2alias.c
@@ -1364,7 +1364,48 @@ static int do_mhi_entry(const char *filename, void *symval, char *alias)
{
DEF_FIELD_ADDR(symval, mhi_device_id, chan);
sprintf(alias, MHI_DEVICE_MODALIAS_FMT, *chan);
+ return 1;
+}
+
+static int do_auxiliary_entry(const char *filename, void *symval, char *alias)
+{
+ DEF_FIELD_ADDR(symval, auxiliary_device_id, name);
+ sprintf(alias, AUXILIARY_MODULE_PREFIX "%s", *name);
+
+ return 1;
+}
+
+/*
+ * Looks like: ssam:dNcNtNiNfN
+ *
+ * N is exactly 2 digits, where each is an upper-case hex digit.
+ */
+static int do_ssam_entry(const char *filename, void *symval, char *alias)
+{
+ DEF_FIELD(symval, ssam_device_id, match_flags);
+ DEF_FIELD(symval, ssam_device_id, domain);
+ DEF_FIELD(symval, ssam_device_id, category);
+ DEF_FIELD(symval, ssam_device_id, target);
+ DEF_FIELD(symval, ssam_device_id, instance);
+ DEF_FIELD(symval, ssam_device_id, function);
+
+ sprintf(alias, "ssam:d%02Xc%02X", domain, category);
+ ADD(alias, "t", match_flags & SSAM_MATCH_TARGET, target);
+ ADD(alias, "i", match_flags & SSAM_MATCH_INSTANCE, instance);
+ ADD(alias, "f", match_flags & SSAM_MATCH_FUNCTION, function);
+
+ return 1;
+}
+
+/* Looks like: dfl:tNfN */
+static int do_dfl_entry(const char *filename, void *symval, char *alias)
+{
+ DEF_FIELD(symval, dfl_device_id, type);
+ DEF_FIELD(symval, dfl_device_id, feature_id);
+ sprintf(alias, "dfl:t%04Xf%04X", type, feature_id);
+
+ add_wildcard(alias);
return 1;
}
@@ -1442,6 +1483,9 @@ static const struct devtable devtable[] = {
{"tee", SIZE_tee_client_device_id, do_tee_entry},
{"wmi", SIZE_wmi_device_id, do_wmi_entry},
{"mhi", SIZE_mhi_device_id, do_mhi_entry},
+ {"auxiliary", SIZE_auxiliary_device_id, do_auxiliary_entry},
+ {"ssam", SIZE_ssam_device_id, do_ssam_entry},
+ {"dfl", SIZE_dfl_device_id, do_dfl_entry},
};
/* Create MODULE_ALIAS() statements.
diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c
index f882ce0d9327..24725e50c7b4 100644
--- a/scripts/mod/modpost.c
+++ b/scripts/mod/modpost.c
@@ -17,7 +17,6 @@
#include <ctype.h>
#include <string.h>
#include <limits.h>
-#include <stdbool.h>
#include <errno.h>
#include "modpost.h"
#include "../../include/linux/license.h"
@@ -34,15 +33,18 @@ static int external_module = 0;
static int warn_unresolved = 0;
/* How a symbol is exported */
static int sec_mismatch_count = 0;
-static int sec_mismatch_fatal = 0;
+static int sec_mismatch_warn_only = true;
/* ignore missing files */
static int ignore_missing_files;
/* If set to 1, only warn (instead of error) about missing ns imports */
static int allow_missing_ns_imports;
+static bool error_occurred;
+
enum export {
- export_plain, export_unused, export_gpl,
- export_unused_gpl, export_gpl_future, export_unknown
+ export_plain,
+ export_gpl,
+ export_unknown
};
/* In kernel, this size is defined in linux/module.h;
@@ -78,14 +80,8 @@ modpost_log(enum loglevel loglevel, const char *fmt, ...)
if (loglevel == LOG_FATAL)
exit(1);
-}
-
-static inline bool strends(const char *str, const char *postfix)
-{
- if (strlen(str) < strlen(postfix))
- return false;
-
- return strcmp(str + strlen(str) - strlen(postfix), postfix) == 0;
+ if (loglevel == LOG_ERROR)
+ error_occurred = true;
}
void *do_nofail(void *ptr, const char *expr)
@@ -297,10 +293,7 @@ static const struct {
enum export export;
} export_list[] = {
{ .str = "EXPORT_SYMBOL", .export = export_plain },
- { .str = "EXPORT_UNUSED_SYMBOL", .export = export_unused },
{ .str = "EXPORT_SYMBOL_GPL", .export = export_gpl },
- { .str = "EXPORT_UNUSED_SYMBOL_GPL", .export = export_unused_gpl },
- { .str = "EXPORT_SYMBOL_GPL_FUTURE", .export = export_gpl_future },
{ .str = "(unknown)", .export = export_unknown },
};
@@ -359,14 +352,8 @@ static enum export export_from_secname(struct elf_info *elf, unsigned int sec)
if (strstarts(secname, "___ksymtab+"))
return export_plain;
- else if (strstarts(secname, "___ksymtab_unused+"))
- return export_unused;
else if (strstarts(secname, "___ksymtab_gpl+"))
return export_gpl;
- else if (strstarts(secname, "___ksymtab_unused_gpl+"))
- return export_unused_gpl;
- else if (strstarts(secname, "___ksymtab_gpl_future+"))
- return export_gpl_future;
else
return export_unknown;
}
@@ -375,14 +362,8 @@ static enum export export_from_sec(struct elf_info *elf, unsigned int sec)
{
if (sec == elf->export_sec)
return export_plain;
- else if (sec == elf->export_unused_sec)
- return export_unused;
else if (sec == elf->export_gpl_sec)
return export_gpl;
- else if (sec == elf->export_unused_gpl_sec)
- return export_unused_gpl;
- else if (sec == elf->export_gpl_future_sec)
- return export_gpl_future;
else
return export_unknown;
}
@@ -403,8 +384,8 @@ static void sym_update_namespace(const char *symname, const char *namespace)
* actually an assertion.
*/
if (!s) {
- merror("Could not update namespace(%s) for symbol %s\n",
- namespace, symname);
+ error("Could not update namespace(%s) for symbol %s\n",
+ namespace, symname);
return;
}
@@ -586,14 +567,8 @@ static int parse_elf(struct elf_info *info, const char *filename)
info->modinfo_len = sechdrs[i].sh_size;
} else if (strcmp(secname, "__ksymtab") == 0)
info->export_sec = i;
- else if (strcmp(secname, "__ksymtab_unused") == 0)
- info->export_unused_sec = i;
else if (strcmp(secname, "__ksymtab_gpl") == 0)
info->export_gpl_sec = i;
- else if (strcmp(secname, "__ksymtab_unused_gpl") == 0)
- info->export_unused_gpl_sec = i;
- else if (strcmp(secname, "__ksymtab_gpl_future") == 0)
- info->export_gpl_future_sec = i;
if (sechdrs[i].sh_type == SHT_SYMTAB) {
unsigned int sh_link_idx;
@@ -1984,6 +1959,10 @@ static char *remove_dot(char *s)
size_t m = strspn(s + n + 1, "0123456789");
if (m && (s[n + m] == '.' || s[n + m] == 0))
s[n] = 0;
+
+ /* strip trailing .lto */
+ if (strends(s, ".lto"))
+ s[strlen(s) - 4] = '\0';
}
return s;
}
@@ -2007,6 +1986,9 @@ static void read_symbols(const char *modname)
/* strip trailing .o */
tmp = NOFAIL(strdup(modname));
tmp[strlen(tmp) - 2] = '\0';
+ /* strip trailing .lto */
+ if (strends(tmp, ".lto"))
+ tmp[strlen(tmp) - 4] = '\0';
mod = new_module(tmp);
free(tmp);
}
@@ -2014,7 +1996,7 @@ static void read_symbols(const char *modname)
if (!mod->is_vmlinux) {
license = get_modinfo(&info, "license");
if (!license)
- warn("missing MODULE_LICENSE() in %s\n", modname);
+ error("missing MODULE_LICENSE() in %s\n", modname);
while (license) {
if (license_is_gpl_compatible(license))
mod->gpl_compatible = 1;
@@ -2141,55 +2123,28 @@ static void check_for_gpl_usage(enum export exp, const char *m, const char *s)
{
switch (exp) {
case export_gpl:
- fatal("GPL-incompatible module %s.ko uses GPL-only symbol '%s'\n",
- m, s);
- break;
- case export_unused_gpl:
- fatal("GPL-incompatible module %s.ko uses GPL-only symbol marked UNUSED '%s'\n",
+ error("GPL-incompatible module %s.ko uses GPL-only symbol '%s'\n",
m, s);
break;
- case export_gpl_future:
- warn("GPL-incompatible module %s.ko uses future GPL-only symbol '%s'\n",
- m, s);
- break;
case export_plain:
- case export_unused:
case export_unknown:
/* ignore */
break;
}
}
-static void check_for_unused(enum export exp, const char *m, const char *s)
-{
- switch (exp) {
- case export_unused:
- case export_unused_gpl:
- warn("module %s.ko uses symbol '%s' marked UNUSED\n",
- m, s);
- break;
- default:
- /* ignore */
- break;
- }
-}
-
-static int check_exports(struct module *mod)
+static void check_exports(struct module *mod)
{
struct symbol *s, *exp;
- int err = 0;
for (s = mod->unres; s; s = s->next) {
const char *basename;
exp = find_symbol(s->name);
if (!exp || exp->module == mod) {
- if (have_vmlinux && !s->weak) {
+ if (have_vmlinux && !s->weak)
modpost_log(warn_unresolved ? LOG_WARN : LOG_ERROR,
"\"%s\" [%s.ko] undefined!\n",
s->name, mod->name);
- if (!warn_unresolved)
- err = 1;
- }
continue;
}
basename = strrchr(mod->name, '/');
@@ -2203,20 +2158,15 @@ static int check_exports(struct module *mod)
modpost_log(allow_missing_ns_imports ? LOG_WARN : LOG_ERROR,
"module %s uses symbol %s from namespace %s, but does not import it.\n",
basename, exp->name, exp->namespace);
- if (!allow_missing_ns_imports)
- err = 1;
add_namespace(&mod->missing_namespaces, exp->namespace);
}
if (!mod->gpl_compatible)
check_for_gpl_usage(exp->export, basename, exp->name);
- check_for_unused(exp->export, basename, exp->name);
}
-
- return err;
}
-static int check_modname_len(struct module *mod)
+static void check_modname_len(struct module *mod)
{
const char *mod_name;
@@ -2225,12 +2175,8 @@ static int check_modname_len(struct module *mod)
mod_name = mod->name;
else
mod_name++;
- if (strlen(mod_name) >= MODULE_NAME_LEN) {
- merror("module name is too long [%s.ko]\n", mod->name);
- return 1;
- }
-
- return 0;
+ if (strlen(mod_name) >= MODULE_NAME_LEN)
+ error("module name is too long [%s.ko]\n", mod->name);
}
/**
@@ -2289,10 +2235,9 @@ static void add_staging_flag(struct buffer *b, const char *name)
/**
* Record CRCs for unresolved symbols
**/
-static int add_versions(struct buffer *b, struct module *mod)
+static void add_versions(struct buffer *b, struct module *mod)
{
struct symbol *s, *exp;
- int err = 0;
for (s = mod->unres; s; s = s->next) {
exp = find_symbol(s->name);
@@ -2304,7 +2249,7 @@ static int add_versions(struct buffer *b, struct module *mod)
}
if (!modversions)
- return err;
+ return;
buf_printf(b, "\n");
buf_printf(b, "static const struct modversion_info ____versions[]\n");
@@ -2319,9 +2264,8 @@ static int add_versions(struct buffer *b, struct module *mod)
continue;
}
if (strlen(s->name) >= MODULE_NAME_LEN) {
- merror("too long symbol \"%s\" [%s.ko]\n",
- s->name, mod->name);
- err = 1;
+ error("too long symbol \"%s\" [%s.ko]\n",
+ s->name, mod->name);
break;
}
buf_printf(b, "\t{ %#8x, \"%s\" },\n",
@@ -2329,8 +2273,6 @@ static int add_versions(struct buffer *b, struct module *mod)
}
buf_printf(b, "};\n");
-
- return err;
}
static void add_depends(struct buffer *b, struct module *mod)
@@ -2554,7 +2496,6 @@ int main(int argc, char **argv)
char *missing_namespace_deps = NULL;
char *dump_write = NULL, *files_source = NULL;
int opt;
- int err;
int n;
struct dump_list *dump_read_start = NULL;
struct dump_list **dump_read_iter = &dump_read_start;
@@ -2589,7 +2530,7 @@ int main(int argc, char **argv)
warn_unresolved = 1;
break;
case 'E':
- sec_mismatch_fatal = 1;
+ sec_mismatch_warn_only = false;
break;
case 'N':
allow_missing_ns_imports = 1;
@@ -2624,8 +2565,6 @@ int main(int argc, char **argv)
if (!have_vmlinux)
warn("Symbol info of vmlinux is missing. Unresolved symbol check will be entirely skipped.\n");
- err = 0;
-
for (mod = modules; mod; mod = mod->next) {
char fname[PATH_MAX];
@@ -2634,14 +2573,14 @@ int main(int argc, char **argv)
buf.pos = 0;
- err |= check_modname_len(mod);
- err |= check_exports(mod);
+ check_modname_len(mod);
+ check_exports(mod);
add_header(&buf, mod);
add_intree_flag(&buf, !external_module);
add_retpoline(&buf);
add_staging_flag(&buf, mod->name);
- err |= add_versions(&buf, mod);
+ add_versions(&buf, mod);
add_depends(&buf, mod);
add_moddevtable(&buf, mod);
add_srcversion(&buf, mod);
@@ -2655,21 +2594,21 @@ int main(int argc, char **argv)
if (dump_write)
write_dump(dump_write);
- if (sec_mismatch_count && sec_mismatch_fatal)
- fatal("Section mismatches detected.\n"
+ if (sec_mismatch_count && !sec_mismatch_warn_only)
+ error("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;
for (s = symbolhash[n]; s; s = s->next) {
if (s->is_static)
- warn("\"%s\" [%s] is a static %s\n",
- s->name, s->module->name,
- export_str(s->export));
+ error("\"%s\" [%s] is a static %s\n",
+ s->name, s->module->name,
+ export_str(s->export));
}
}
free(buf.p);
- return err;
+ return error_occurred ? 1 : 0;
}
diff --git a/scripts/mod/modpost.h b/scripts/mod/modpost.h
index 3aa052722233..c1a895c0d682 100644
--- a/scripts/mod/modpost.h
+++ b/scripts/mod/modpost.h
@@ -2,6 +2,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
+#include <stdbool.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
@@ -139,10 +140,7 @@ struct elf_info {
Elf_Sym *symtab_start;
Elf_Sym *symtab_stop;
Elf_Section export_sec;
- Elf_Section export_unused_sec;
Elf_Section export_gpl_sec;
- Elf_Section export_unused_gpl_sec;
- Elf_Section export_gpl_future_sec;
char *strtab;
char *modinfo;
unsigned int modinfo_len;
@@ -180,6 +178,14 @@ static inline unsigned int get_secindex(const struct elf_info *info,
return info->symtab_shndx_start[sym - info->symtab_start];
}
+static inline bool strends(const char *str, const char *postfix)
+{
+ if (strlen(str) < strlen(postfix))
+ return false;
+
+ return strcmp(str + strlen(str) - strlen(postfix), postfix) == 0;
+}
+
/* file2alias.c */
extern unsigned int cross_build;
void handle_moddevtable(struct module *mod, struct elf_info *info,
@@ -201,6 +207,19 @@ enum loglevel {
void modpost_log(enum loglevel loglevel, const char *fmt, ...);
+/*
+ * warn - show the given message, then let modpost continue running, still
+ * allowing modpost to exit successfully. This should be used when
+ * we still allow to generate vmlinux and modules.
+ *
+ * error - show the given message, then let modpost continue running, but fail
+ * in the end. This should be used when we should stop building vmlinux
+ * or modules, but we can continue running modpost to catch as many
+ * issues as possible.
+ *
+ * fatal - show the given message, and bail out immediately. This should be
+ * used when there is no point to continue running modpost.
+ */
#define warn(fmt, args...) modpost_log(LOG_WARN, fmt, ##args)
-#define merror(fmt, args...) modpost_log(LOG_ERROR, fmt, ##args)
+#define error(fmt, args...) modpost_log(LOG_ERROR, fmt, ##args)
#define fatal(fmt, args...) modpost_log(LOG_FATAL, fmt, ##args)
diff --git a/scripts/mod/sumversion.c b/scripts/mod/sumversion.c
index d587f40f1117..760e6baa7eda 100644
--- a/scripts/mod/sumversion.c
+++ b/scripts/mod/sumversion.c
@@ -391,10 +391,14 @@ void get_src_version(const char *modname, char sum[], unsigned sumlen)
struct md4_ctx md;
char *fname;
char filelist[PATH_MAX + 1];
+ int postfix_len = 1;
+
+ if (strends(modname, ".lto.o"))
+ postfix_len = 5;
/* objects for a module are listed in the first line of *.mod file. */
snprintf(filelist, sizeof(filelist), "%.*smod",
- (int)strlen(modname) - 1, modname);
+ (int)strlen(modname) - postfix_len, modname);
buf = read_text_file(filelist);
diff --git a/scripts/module.lds.S b/scripts/module.lds.S
index 69b9b71a6a47..168cd27e6122 100644
--- a/scripts/module.lds.S
+++ b/scripts/module.lds.S
@@ -11,18 +11,36 @@ SECTIONS {
__ksymtab 0 : { *(SORT(___ksymtab+*)) }
__ksymtab_gpl 0 : { *(SORT(___ksymtab_gpl+*)) }
- __ksymtab_unused 0 : { *(SORT(___ksymtab_unused+*)) }
- __ksymtab_unused_gpl 0 : { *(SORT(___ksymtab_unused_gpl+*)) }
- __ksymtab_gpl_future 0 : { *(SORT(___ksymtab_gpl_future+*)) }
__kcrctab 0 : { *(SORT(___kcrctab+*)) }
__kcrctab_gpl 0 : { *(SORT(___kcrctab_gpl+*)) }
- __kcrctab_unused 0 : { *(SORT(___kcrctab_unused+*)) }
- __kcrctab_unused_gpl 0 : { *(SORT(___kcrctab_unused_gpl+*)) }
- __kcrctab_gpl_future 0 : { *(SORT(___kcrctab_gpl_future+*)) }
.init_array 0 : ALIGN(8) { *(SORT(.init_array.*)) *(.init_array) }
__jump_table 0 : ALIGN(8) { KEEP(*(__jump_table)) }
+
+ __patchable_function_entries : { *(__patchable_function_entries) }
+
+ /*
+ * With CONFIG_LTO_CLANG, LLD always enables -fdata-sections and
+ * -ffunction-sections, which increases the size of the final module.
+ * Merge the split sections in the final binary.
+ */
+ .bss : {
+ *(.bss .bss.[0-9a-zA-Z_]*)
+ *(.bss..L*)
+ }
+
+ .data : {
+ *(.data .data.[0-9a-zA-Z_]*)
+ *(.data..L*)
+ }
+
+ .rodata : {
+ *(.rodata .rodata.[0-9a-zA-Z_]*)
+ *(.rodata..L*)
+ }
+
+ .text : { *(.text .text.[0-9a-zA-Z_]*) }
}
/* bring in arch-specific sections */
diff --git a/scripts/nsdeps b/scripts/nsdeps
index dab4c1a0e27d..e8ce2a4d704a 100644
--- a/scripts/nsdeps
+++ b/scripts/nsdeps
@@ -12,11 +12,9 @@ if [ ! -x "$SPATCH" ]; then
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
+if ! { echo "$SPATCH_REQ_VERSION"; echo "$SPATCH_VERSION"; } | sort -CV ; then
echo "spatch needs to be version $SPATCH_REQ_VERSION or higher"
exit 1
fi
diff --git a/scripts/recordmcount.c b/scripts/recordmcount.c
index b9c2ee7ab43f..cce12e1971d8 100644
--- a/scripts/recordmcount.c
+++ b/scripts/recordmcount.c
@@ -438,7 +438,7 @@ static int arm_is_fake_mcount(Elf32_Rel const *rp)
static int arm64_is_fake_mcount(Elf64_Rel const *rp)
{
- return ELF64_R_TYPE(w(rp->r_info)) != R_AARCH64_CALL26;
+ return ELF64_R_TYPE(w8(rp->r_info)) != R_AARCH64_CALL26;
}
/* 64-bit EM_MIPS has weird ELF64_Rela.r_info.
diff --git a/scripts/recordmcount.pl b/scripts/recordmcount.pl
index 3f77a5d695c1..867860ea57da 100755
--- a/scripts/recordmcount.pl
+++ b/scripts/recordmcount.pl
@@ -254,9 +254,6 @@ if ($arch eq "x86_64") {
if ($cc =~ /-DCC_USING_HOTPATCH/) {
$mcount_regex = "^\\s*([0-9a-fA-F]+):\\s*c0 04 00 00 00 00\\s*brcl\\s*0,[0-9a-f]+ <([^\+]*)>\$";
$mcount_adjust = 0;
- } else {
- $mcount_regex = "^\\s*([0-9a-fA-F]+):\\s*R_390_(PC|PLT)32DBL\\s+_mcount\\+0x2\$";
- $mcount_adjust = -14;
}
$alignment = 8;
$type = ".quad";
@@ -268,7 +265,11 @@ if ($arch eq "x86_64") {
# force flags for this arch
$ld .= " -m shlelf_linux";
- $objcopy .= " -O elf32-sh-linux";
+ if ($endian eq "big") {
+ $objcopy .= " -O elf32-shbig-linux";
+ } else {
+ $objcopy .= " -O elf32-sh-linux";
+ }
} elsif ($arch eq "powerpc") {
my $ldemulation;
diff --git a/scripts/show_delta b/scripts/show_delta
index 264399307c4f..28e67e178194 100755
--- a/scripts/show_delta
+++ b/scripts/show_delta
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python
# SPDX-License-Identifier: GPL-2.0-only
#
# show_deltas: Read list of printk messages instrumented with
diff --git a/scripts/spdxcheck.py b/scripts/spdxcheck.py
index bc87200f9c7c..cbdb5c83c08f 100755
--- a/scripts/spdxcheck.py
+++ b/scripts/spdxcheck.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
# SPDX-License-Identifier: GPL-2.0
# Copyright Thomas Gleixner <tglx@linutronix.de>
diff --git a/scripts/spelling.txt b/scripts/spelling.txt
index 953f4a2de1e5..2e3ba91a5072 100644
--- a/scripts/spelling.txt
+++ b/scripts/spelling.txt
@@ -103,6 +103,7 @@ alloated||allocated
allocatote||allocate
allocatrd||allocated
allocte||allocate
+allocted||allocated
allpication||application
alocate||allocate
alogirhtms||algorithms
@@ -339,6 +340,7 @@ comppatible||compatible
compres||compress
compresion||compression
comression||compression
+comunicate||communicate
comunication||communication
conbination||combination
conditionaly||conditionally
@@ -466,6 +468,7 @@ developpment||development
deveolpment||development
devided||divided
deviece||device
+devision||division
diable||disable
dicline||decline
dictionnary||dictionary
@@ -479,6 +482,7 @@ difinition||definition
digial||digital
dimention||dimension
dimesions||dimensions
+diconnected||disconnected
disgest||digest
dispalying||displaying
diplay||display
@@ -518,6 +522,7 @@ downlads||downloads
droped||dropped
droput||dropout
druing||during
+dyanmic||dynamic
dynmaic||dynamic
eanable||enable
eanble||enable
@@ -542,6 +547,7 @@ encrupted||encrypted
encrypiton||encryption
encryptio||encryption
endianess||endianness
+enpoint||endpoint
enhaced||enhanced
enlightnment||enlightenment
enqueing||enqueuing
@@ -566,6 +572,7 @@ estbalishment||establishment
etsablishment||establishment
etsbalishment||establishment
evalution||evaluation
+exeeds||exceeds
excecutable||executable
exceded||exceeded
exceds||exceeds
@@ -574,6 +581,7 @@ excellant||excellent
execeeded||exceeded
execeeds||exceeds
exeed||exceed
+exeeds||exceeds
exeuction||execution
existance||existence
existant||existent
@@ -641,6 +649,7 @@ forwardig||forwarding
frambuffer||framebuffer
framming||framing
framwork||framework
+frequence||frequency
frequncy||frequency
frequancy||frequency
frome||from
@@ -683,10 +692,12 @@ handfull||handful
hanlde||handle
hanled||handled
happend||happened
+hardare||hardware
harware||hardware
havind||having
heirarchically||hierarchically
helpfull||helpful
+heterogenous||heterogeneous
hexdecimal||hexadecimal
hybernate||hibernate
hierachy||hierarchy
@@ -731,6 +742,7 @@ inconsistant||inconsistent
increas||increase
incremeted||incremented
incrment||increment
+incuding||including
inculde||include
indendation||indentation
indended||intended
@@ -741,6 +753,7 @@ indiate||indicate
indicat||indicate
inexpect||inexpected
inferface||interface
+infinit||infinite
infomation||information
informatiom||information
informations||information
@@ -771,6 +784,7 @@ instace||instance
instal||install
instanciate||instantiate
instanciated||instantiated
+instuments||instruments
insufficent||insufficient
inteface||interface
integreated||integrated
@@ -869,12 +883,14 @@ mailformed||malformed
malplaced||misplaced
malplace||misplace
managable||manageable
+managament||management
managment||management
mangement||management
manger||manager
manoeuvering||maneuvering
manufaucturing||manufacturing
mappping||mapping
+maping||mapping
matchs||matches
mathimatical||mathematical
mathimatic||mathematic
@@ -886,6 +902,7 @@ meetign||meeting
memeory||memory
memmber||member
memoery||memory
+memroy||memory
ment||meant
mergable||mergeable
mesage||message
@@ -999,6 +1016,7 @@ overlaping||overlapping
overide||override
overrided||overridden
overriden||overridden
+overrrun||overrun
overun||overrun
overwritting||overwriting
overwriten||overwritten
@@ -1035,6 +1053,7 @@ peforming||performing
peice||piece
pendantic||pedantic
peprocessor||preprocessor
+perfomance||performance
perfoming||performing
perfomring||performing
periperal||peripheral
@@ -1100,6 +1119,7 @@ prodecure||procedure
progamming||programming
progams||programs
progess||progress
+programable||programmable
programers||programmers
programm||program
programms||programs
@@ -1144,6 +1164,7 @@ recieved||received
recieve||receive
reciever||receiver
recieves||receives
+recieving||receiving
recogniced||recognised
recognizeable||recognizable
recommanded||recommended
@@ -1247,6 +1268,7 @@ searchs||searches
secquence||sequence
secund||second
segement||segment
+seleted||selected
semaphone||semaphore
senario||scenario
senarios||scenarios
@@ -1263,6 +1285,7 @@ seqeunce||sequence
seqeuncer||sequencer
seqeuencer||sequencer
sequece||sequence
+sequemce||sequence
sequencial||sequential
serivce||service
serveral||several
@@ -1333,6 +1356,7 @@ suble||subtle
substract||subtract
submited||submitted
submition||submission
+succeded||succeeded
suceed||succeed
succesfully||successfully
succesful||successful
@@ -1353,6 +1377,7 @@ supportin||supporting
suppoted||supported
suppported||supported
suppport||support
+supprot||support
supress||suppress
surpressed||suppressed
surpresses||suppresses
@@ -1401,6 +1426,7 @@ thresold||threshold
throught||through
trackling||tracking
troughput||throughput
+trys||tries
thses||these
tiggers||triggers
tiggered||triggered
@@ -1414,7 +1440,9 @@ traking||tracking
tramsmitted||transmitted
tramsmit||transmit
tranasction||transaction
+tranceiver||transceiver
tranfer||transfer
+tranmission||transmission
transcevier||transceiver
transciever||transceiver
transferd||transferred
@@ -1468,6 +1496,7 @@ unnecesary||unnecessary
unneedingly||unnecessarily
unnsupported||unsupported
unmached||unmatched
+unprecise||imprecise
unregester||unregister
unresgister||unregister
unrgesiter||unregister
@@ -1503,6 +1532,7 @@ varient||variant
vaule||value
verbse||verbose
veify||verify
+veriosn||version
verisons||versions
verison||version
verson||version
diff --git a/scripts/sphinx-pre-install b/scripts/sphinx-pre-install
index 40fa6923e80a..b5f9fd5b2880 100755
--- a/scripts/sphinx-pre-install
+++ b/scripts/sphinx-pre-install
@@ -1,4 +1,4 @@
-#!/usr/bin/perl
+#!/usr/bin/env perl
# SPDX-License-Identifier: GPL-2.0-or-later
use strict;
@@ -728,8 +728,8 @@ sub check_needs()
$need_virtualenv = 1;
}
if ($1 < 3) {
- # Complain if it finds python2 (or worse)
- printf "Warning: python$1 support is deprecated. Use it with caution!\n";
+ # Fail if it finds python2 (or worse)
+ die "Python 3 is required to build the kernel docs\n";
}
} else {
die "Warning: couldn't identify $python_cmd version!";
diff --git a/scripts/split-man.pl b/scripts/split-man.pl
index c3db607ee9ec..96bd99dc977a 100755
--- a/scripts/split-man.pl
+++ b/scripts/split-man.pl
@@ -1,4 +1,4 @@
-#!/usr/bin/perl
+#!/usr/bin/env perl
# SPDX-License-Identifier: GPL-2.0
#
# Author: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
diff --git a/scripts/syscallhdr.sh b/scripts/syscallhdr.sh
new file mode 100755
index 000000000000..848ac2735115
--- /dev/null
+++ b/scripts/syscallhdr.sh
@@ -0,0 +1,98 @@
+#!/bin/sh
+# SPDX-License-Identifier: GPL-2.0-only
+#
+# Generate a syscall number header.
+#
+# Each line of the syscall table should have the following format:
+#
+# NR ABI NAME [NATIVE] [COMPAT]
+#
+# NR syscall number
+# ABI ABI name
+# NAME syscall name
+# NATIVE native entry point (optional)
+# COMPAT compat entry point (optional)
+
+set -e
+
+usage() {
+ echo >&2 "usage: $0 [--abis ABIS] [--emit-nr] [--offset OFFSET] [--prefix PREFIX] INFILE OUTFILE" >&2
+ echo >&2
+ echo >&2 " INFILE input syscall table"
+ echo >&2 " OUTFILE output header file"
+ echo >&2
+ echo >&2 "options:"
+ echo >&2 " --abis ABIS ABI(s) to handle (By default, all lines are handled)"
+ echo >&2 " --emit-nr Emit the macro of the number of syscalls (__NR_syscalls)"
+ echo >&2 " --offset OFFSET The offset of syscall numbers"
+ echo >&2 " --prefix PREFIX The prefix to the macro like __NR_<PREFIX><NAME>"
+ exit 1
+}
+
+# default unless specified by options
+abis=
+emit_nr=
+offset=
+prefix=
+
+while [ $# -gt 0 ]
+do
+ case $1 in
+ --abis)
+ abis=$(echo "($2)" | tr ',' '|')
+ shift 2;;
+ --emit-nr)
+ emit_nr=1
+ shift 1;;
+ --offset)
+ offset=$2
+ shift 2;;
+ --prefix)
+ prefix=$2
+ shift 2;;
+ -*)
+ echo "$1: unknown option" >&2
+ usage;;
+ *)
+ break;;
+ esac
+done
+
+if [ $# -ne 2 ]; then
+ usage
+fi
+
+infile="$1"
+outfile="$2"
+
+guard=_UAPI_ASM_$(basename "$outfile" |
+ sed -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/' \
+ -e 's/[^A-Z0-9_]/_/g' -e 's/__/_/g')
+
+grep -E "^[0-9A-Fa-fXx]+[[:space:]]+$abis" "$infile" | sort -n | {
+ echo "#ifndef $guard"
+ echo "#define $guard"
+ echo
+
+ max=0
+ while read nr abi name native compat ; do
+
+ max=$nr
+
+ if [ -n "$offset" ]; then
+ nr="($offset + $nr)"
+ fi
+
+ echo "#define __NR_$prefix$name $nr"
+ done
+
+ if [ -n "$emit_nr" ]; then
+ echo
+ echo "#ifdef __KERNEL__"
+ echo "#define __NR_${prefix}syscalls $(($max + 1))"
+ echo "#endif"
+ fi
+
+ echo
+ echo "#endif /* $guard */"
+} > "$outfile"
diff --git a/scripts/syscalltbl.sh b/scripts/syscalltbl.sh
new file mode 100755
index 000000000000..aa6ab156301c
--- /dev/null
+++ b/scripts/syscalltbl.sh
@@ -0,0 +1,73 @@
+#!/bin/sh
+# SPDX-License-Identifier: GPL-2.0-only
+#
+# Generate a syscall table header.
+#
+# Each line of the syscall table should have the following format:
+#
+# NR ABI NAME [NATIVE] [COMPAT]
+#
+# NR syscall number
+# ABI ABI name
+# NAME syscall name
+# NATIVE native entry point (optional)
+# COMPAT compat entry point (optional)
+
+set -e
+
+usage() {
+ echo >&2 "usage: $0 [--abis ABIS] INFILE OUTFILE" >&2
+ echo >&2
+ echo >&2 " INFILE input syscall table"
+ echo >&2 " OUTFILE output header file"
+ echo >&2
+ echo >&2 "options:"
+ echo >&2 " --abis ABIS ABI(s) to handle (By default, all lines are handled)"
+ exit 1
+}
+
+# default unless specified by options
+abis=
+
+while [ $# -gt 0 ]
+do
+ case $1 in
+ --abis)
+ abis=$(echo "($2)" | tr ',' '|')
+ shift 2;;
+ -*)
+ echo "$1: unknown option" >&2
+ usage;;
+ *)
+ break;;
+ esac
+done
+
+if [ $# -ne 2 ]; then
+ usage
+fi
+
+infile="$1"
+outfile="$2"
+
+nxt=0
+
+grep -E "^[0-9]+[[:space:]]+$abis" "$infile" | sort -n | {
+
+ while read nr abi name native compat ; do
+
+ while [ $nxt -lt $nr ]; do
+ echo "__SYSCALL($nxt, sys_ni_syscall)"
+ nxt=$((nxt + 1))
+ done
+
+ if [ -n "$compat" ]; then
+ echo "__SYSCALL_WITH_COMPAT($nr, $native, $compat)"
+ elif [ -n "$native" ]; then
+ echo "__SYSCALL($nr, $native)"
+ else
+ echo "__SYSCALL($nr, sys_ni_syscall)"
+ fi
+ nxt=$((nr + 1))
+ done
+} > "$outfile"
diff --git a/scripts/test_dwarf5_support.sh b/scripts/test_dwarf5_support.sh
new file mode 100755
index 000000000000..c46e2456b47a
--- /dev/null
+++ b/scripts/test_dwarf5_support.sh
@@ -0,0 +1,8 @@
+#!/bin/sh
+# SPDX-License-Identifier: GPL-2.0
+
+# Test that the assembler doesn't need -Wa,-gdwarf-5 when presented with DWARF
+# v5 input, such as `.file 0` and `md5 0x00`. Should be fixed in GNU binutils
+# 2.35.2. https://sourceware.org/bugzilla/show_bug.cgi?id=25611
+echo '.file 0 "filename" md5 0x7a0b65214090b6693bd1dc24dd248245' | \
+ $* -gdwarf-5 -Wno-unused-command-line-argument -c -x assembler -o /dev/null -
diff --git a/scripts/tracing/draw_functrace.py b/scripts/tracing/draw_functrace.py
index b65735758520..74f8aadfd4cb 100755
--- a/scripts/tracing/draw_functrace.py
+++ b/scripts/tracing/draw_functrace.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python
# SPDX-License-Identifier: GPL-2.0-only
"""
diff --git a/scripts/ver_linux b/scripts/ver_linux
index 0968a3070eff..a92acc703f9b 100755
--- a/scripts/ver_linux
+++ b/scripts/ver_linux
@@ -15,7 +15,7 @@ BEGIN {
vernum = "[0-9]+([.]?[0-9]+)+"
libc = "libc[.]so[.][0-9]+$"
- libcpp = "(libg|stdc)[+]+[.]so[.][0-9]+$"
+ libcpp = "(libg|stdc)[+]+[.]so([.][0-9]+)+$"
printversion("GNU C", version("gcc -dumpversion"))
printversion("GNU Make", version("make --version"))
@@ -37,12 +37,10 @@ BEGIN {
printversion("Bison", version("bison --version"))
printversion("Flex", version("flex --version"))
- while ("ldconfig -p 2>/dev/null" | getline > 0) {
- if ($NF ~ libc && !seen[ver = version("readlink " $NF)]++)
- printversion("Linux C Library", ver)
- else if ($NF ~ libcpp && !seen[ver = version("readlink " $NF)]++)
- printversion("Linux C++ Library", ver)
- }
+ while ("ldconfig -p 2>/dev/null" | getline > 0)
+ if ($NF ~ libc || $NF ~ libcpp)
+ if (!seen[ver = version("readlink " $NF)]++)
+ printversion("Linux C" ($NF ~ libcpp? "++" : "") " Library", ver)
printversion("Dynamic linker (ldd)", version("ldd --version"))
printversion("Procps", version("ps --version"))