summaryrefslogtreecommitdiff
path: root/scripts
diff options
context:
space:
mode:
Diffstat (limited to 'scripts')
-rw-r--r--scripts/.gitignore7
-rw-r--r--scripts/Kbuild.include25
-rw-r--r--scripts/Kconfig.include20
-rw-r--r--scripts/Makefile40
-rw-r--r--scripts/Makefile.build29
-rw-r--r--scripts/Makefile.clean5
-rw-r--r--scripts/Makefile.dtbinst26
-rw-r--r--scripts/Makefile.extrawarn2
-rw-r--r--scripts/Makefile.host31
-rw-r--r--scripts/Makefile.lib36
-rw-r--r--scripts/Makefile.modbuiltin57
-rw-r--r--scripts/Makefile.modpost16
-rw-r--r--scripts/Makefile.ubsan16
-rwxr-xr-xscripts/adjust_autoksyms.sh24
-rw-r--r--scripts/basic/.gitignore1
-rw-r--r--scripts/basic/Makefile4
-rw-r--r--scripts/basic/fixdep.c10
-rwxr-xr-xscripts/bpf_helpers_doc.py6
-rwxr-xr-xscripts/check-sysctl-docs181
-rwxr-xr-xscripts/checkpatch.pl155
-rw-r--r--scripts/coccinelle/free/devm_free.cocci8
-rw-r--r--scripts/coccinelle/free/iounmap.cocci2
-rw-r--r--scripts/conmakehash.c290
-rwxr-xr-xscripts/documentation-file-ref-check13
-rw-r--r--scripts/dtc/.gitignore1
-rw-r--r--scripts/dtc/Makefile5
-rw-r--r--scripts/dtc/Makefile.dtc23
-rw-r--r--scripts/dtc/checks.c30
-rw-r--r--scripts/dtc/dtc-lexer.l1
-rw-r--r--scripts/dtc/dtc-parser.y4
-rw-r--r--scripts/dtc/fstree.c2
-rw-r--r--scripts/dtc/libfdt/Makefile.libfdt18
-rw-r--r--scripts/dtc/libfdt/fdt.c108
-rw-r--r--scripts/dtc/libfdt/fdt_addresses.c8
-rw-r--r--scripts/dtc/libfdt/fdt_overlay.c28
-rw-r--r--scripts/dtc/libfdt/fdt_ro.c152
-rw-r--r--scripts/dtc/libfdt/fdt_rw.c42
-rw-r--r--scripts/dtc/libfdt/fdt_sw.c19
-rw-r--r--scripts/dtc/libfdt/libfdt.h13
-rw-r--r--scripts/dtc/libfdt/libfdt_internal.h134
-rw-r--r--scripts/dtc/livetree.c3
-rwxr-xr-xscripts/dtc/update-dtc-source.sh4
-rw-r--r--scripts/dtc/util.c3
-rw-r--r--scripts/dtc/util.h4
-rw-r--r--scripts/dtc/version_gen.h2
-rwxr-xr-xscripts/dummy-tools/gcc91
-rwxr-xr-xscripts/dummy-tools/ld30
l---------scripts/dummy-tools/nm1
l---------scripts/dummy-tools/objcopy1
-rwxr-xr-xscripts/export_report.pl2
-rwxr-xr-xscripts/find-unused-docs.sh2
-rwxr-xr-xscripts/gcc-plugin.sh55
-rw-r--r--scripts/gcc-plugins/.gitignore1
-rw-r--r--scripts/gcc-plugins/Kconfig14
-rw-r--r--scripts/gcc-plugins/Makefile21
-rw-r--r--scripts/gdb/linux/.gitignore1
-rwxr-xr-xscripts/gen_autoksyms.sh52
-rw-r--r--scripts/genksyms/.gitignore1
-rw-r--r--scripts/genksyms/Makefile4
-rwxr-xr-xscripts/get_maintainer.pl32
-rw-r--r--scripts/kallsyms.c133
-rw-r--r--scripts/kconfig/.gitignore4
-rw-r--r--scripts/kconfig/Makefile38
-rw-r--r--scripts/kconfig/conf.c16
-rw-r--r--scripts/kconfig/confdata.c62
-rw-r--r--scripts/kconfig/expr.c3
-rw-r--r--scripts/kconfig/expr.h2
-rw-r--r--scripts/kconfig/gconf.c1
-rw-r--r--scripts/kconfig/lkc.h4
-rw-r--r--scripts/kconfig/mconf.c1
-rw-r--r--scripts/kconfig/menu.c185
-rw-r--r--scripts/kconfig/nconf.c1
-rw-r--r--scripts/kconfig/parser.y21
-rw-r--r--scripts/kconfig/qconf.cc92
-rw-r--r--scripts/kconfig/qconf.h2
-rwxr-xr-xscripts/kconfig/streamline_config.pl4
-rw-r--r--scripts/kconfig/symbol.c31
-rwxr-xr-xscripts/link-vmlinux.sh65
-rwxr-xr-xscripts/mkcompile_h17
-rw-r--r--scripts/mod/.gitignore1
-rw-r--r--scripts/mod/Makefile4
-rw-r--r--scripts/mod/devicetable-offsets.c10
-rw-r--r--scripts/mod/file2alias.c29
-rw-r--r--scripts/mod/modpost.c124
-rw-r--r--scripts/mod/modpost.h14
-rwxr-xr-xscripts/package/builddeb106
-rwxr-xr-xscripts/package/mkdebian5
-rwxr-xr-x[-rw-r--r--]scripts/parse-maintainers.pl31
-rw-r--r--scripts/recordmcount.c17
-rw-r--r--scripts/selinux/genheaders/.gitignore1
-rw-r--r--scripts/selinux/genheaders/Makefile4
-rw-r--r--scripts/selinux/genheaders/genheaders.c11
-rw-r--r--scripts/selinux/mdp/.gitignore2
-rw-r--r--scripts/selinux/mdp/Makefile4
-rw-r--r--scripts/sortextable.h209
-rw-r--r--scripts/sorttable.c (renamed from scripts/sortextable.c)305
-rw-r--r--scripts/sorttable.h380
-rw-r--r--scripts/spelling.txt35
-rwxr-xr-xscripts/sphinx-pre-install19
-rwxr-xr-xscripts/ver_linux24
100 files changed, 2189 insertions, 1744 deletions
diff --git a/scripts/.gitignore b/scripts/.gitignore
index 4aa1806c59c2..0d1c8e217cd7 100644
--- a/scripts/.gitignore
+++ b/scripts/.gitignore
@@ -1,12 +1,9 @@
-#
-# Generated files
-#
+# SPDX-License-Identifier: GPL-2.0-only
bin2c
-conmakehash
kallsyms
unifdef
recordmcount
-sortextable
+sorttable
asn1_compiler
extract-cert
sign-file
diff --git a/scripts/Kbuild.include b/scripts/Kbuild.include
index bc5f25763c1b..6cabf20ce66a 100644
--- a/scripts/Kbuild.include
+++ b/scripts/Kbuild.include
@@ -33,6 +33,10 @@ real-prereqs = $(filter-out $(PHONY), $^)
escsq = $(subst $(squote),'\$(squote)',$1)
###
+# Quote a string to pass it to C files. foo => '"foo"'
+stringify = $(squote)$(quote)$1$(quote)$(squote)
+
+###
# Easy method for doing a status message
kecho := :
quiet_kecho := echo
@@ -55,14 +59,13 @@ kecho := $($(quiet)kecho)
# - stdin is piped in from the first prerequisite ($<) so one has
# to specify a valid file as first prerequisite (often the kbuild file)
define filechk
- $(Q)set -e; \
- mkdir -p $(dir $@); \
- { $(filechk_$(1)); } > $@.tmp; \
- if [ -r $@ ] && cmp -s $@ $@.tmp; then \
- rm -f $@.tmp; \
- else \
- $(kecho) ' UPD $@'; \
- mv -f $@.tmp $@; \
+ $(Q)set -e; \
+ mkdir -p $(dir $@); \
+ trap "rm -f $(dot-target).tmp" EXIT; \
+ { $(filechk_$(1)); } > $(dot-target).tmp; \
+ if [ ! -r $@ ] || ! cmp -s $@ $(dot-target).tmp; then \
+ $(kecho) ' UPD $@'; \
+ mv -f $(dot-target).tmp $@; \
fi
endef
@@ -160,12 +163,6 @@ ld-ifversion = $(shell [ $(ld-version) $(1) $(2) ] && echo $(3) || echo $(4))
build := -f $(srctree)/scripts/Makefile.build obj
###
-# Shorthand for $(Q)$(MAKE) -f scripts/Makefile.modbuiltin obj=
-# Usage:
-# $(Q)$(MAKE) $(modbuiltin)=dir
-modbuiltin := -f $(srctree)/scripts/Makefile.modbuiltin obj
-
-###
# Shorthand for $(Q)$(MAKE) -f scripts/Makefile.dtbinst obj=
# Usage:
# $(Q)$(MAKE) $(dtbinst)=dir
diff --git a/scripts/Kconfig.include b/scripts/Kconfig.include
index d4adfbe42690..c264da2b9b30 100644
--- a/scripts/Kconfig.include
+++ b/scripts/Kconfig.include
@@ -25,12 +25,22 @@ failure = $(if-success,$(1),n,y)
# $(cc-option,<flag>)
# Return y if the compiler supports <flag>, n otherwise
-cc-option = $(success,$(CC) -Werror $(CLANG_FLAGS) $(1) -E -x c /dev/null -o /dev/null)
+cc-option = $(success,$(CC) -Werror $(CLANG_FLAGS) $(1) -S -x c /dev/null -o /dev/null)
# $(ld-option,<flag>)
# Return y if the linker supports <flag>, n otherwise
ld-option = $(success,$(LD) -v $(1))
+# $(as-option,<flag>)
+# /dev/zero is used as output instead of /dev/null as some assembler cribs when
+# both input and output are same. Also both of them have same write behaviour so
+# can be easily substituted.
+as-option = $(success, $(CC) $(CLANG_FLAGS) $(1) -c -x assembler /dev/null -o /dev/zero)
+
+# $(as-instr,<instr>)
+# Return y if the assembler supports <instr>, n otherwise
+as-instr = $(success,printf "%b\n" "$(1)" | $(CC) $(CLANG_FLAGS) -c -x assembler -o /dev/null -)
+
# check if $(CC) and $(LD) exist
$(error-if,$(failure,command -v $(CC)),compiler '$(CC)' not found)
$(error-if,$(failure,command -v $(LD)),linker '$(LD)' not found)
@@ -38,5 +48,9 @@ $(error-if,$(failure,command -v $(LD)),linker '$(LD)' not found)
# Fail if the linker is gold as it's not capable of linking the kernel proper
$(error-if,$(success, $(LD) -v | grep -q gold), gold linker '$(LD)' not supported)
-# gcc version including patch level
-gcc-version := $(shell,$(srctree)/scripts/gcc-version.sh $(CC))
+# machine bit flags
+# $(m32-flag): -m32 if the compiler supports it, or an empty string otherwise.
+# $(m64-flag): -m64 if the compiler supports it, or an empty string otherwise.
+cc-option-bit = $(if-success,$(CC) -Werror $(1) -E -x c /dev/null -o /dev/null,$(1))
+m32-flag := $(cc-option-bit,-m32)
+m64-flag := $(cc-option-bit,-m64)
diff --git a/scripts/Makefile b/scripts/Makefile
index 00c47901cb06..95ecf970c74c 100644
--- a/scripts/Makefile
+++ b/scripts/Makefile
@@ -2,32 +2,34 @@
###
# scripts contains sources for various helper programs used throughout
# the kernel for the build process.
-# ---------------------------------------------------------------------------
-# kallsyms: Find all symbols in vmlinux
-# conmakehash: Create chartable
-# conmakehash: Create arrays for initializing the kernel console tables
-HOST_EXTRACFLAGS += -I$(srctree)/tools/include
+always-$(CONFIG_BUILD_BIN2C) += bin2c
+always-$(CONFIG_KALLSYMS) += kallsyms
+always-$(BUILD_C_RECORDMCOUNT) += recordmcount
+always-$(CONFIG_BUILDTIME_TABLE_SORT) += sorttable
+always-$(CONFIG_ASN1) += asn1_compiler
+always-$(CONFIG_MODULE_SIG_FORMAT) += sign-file
+always-$(CONFIG_SYSTEM_TRUSTED_KEYRING) += extract-cert
+always-$(CONFIG_SYSTEM_EXTRA_CERTIFICATE) += insert-sys-cert
-hostprogs-$(CONFIG_BUILD_BIN2C) += bin2c
-hostprogs-$(CONFIG_KALLSYMS) += kallsyms
-hostprogs-$(CONFIG_VT) += conmakehash
-hostprogs-$(BUILD_C_RECORDMCOUNT) += recordmcount
-hostprogs-$(CONFIG_BUILDTIME_EXTABLE_SORT) += sortextable
-hostprogs-$(CONFIG_ASN1) += asn1_compiler
-hostprogs-$(CONFIG_MODULE_SIG_FORMAT) += sign-file
-hostprogs-$(CONFIG_SYSTEM_TRUSTED_KEYRING) += extract-cert
-hostprogs-$(CONFIG_SYSTEM_EXTRA_CERTIFICATE) += insert-sys-cert
-
-HOSTCFLAGS_sortextable.o = -I$(srctree)/tools/include
+HOSTCFLAGS_sorttable.o = -I$(srctree)/tools/include
HOSTCFLAGS_asn1_compiler.o = -I$(srctree)/include
HOSTLDLIBS_sign-file = -lcrypto
HOSTLDLIBS_extract-cert = -lcrypto
-always := $(hostprogs-y) $(hostprogs-m)
+ifdef CONFIG_UNWINDER_ORC
+ifeq ($(ARCH),x86_64)
+ARCH := x86
+endif
+HOSTCFLAGS_sorttable.o += -I$(srctree)/tools/arch/x86/include
+HOSTCFLAGS_sorttable.o += -DUNWINDER_ORC_ENABLED
+HOSTLDLIBS_sorttable = -lpthread
+endif
+
+hostprogs := $(always-y) $(always-m)
-# The following hostprogs-y programs are only build on demand
-hostprogs-y += unifdef
+# The following programs are only built on demand
+hostprogs += unifdef
subdir-$(CONFIG_GCC_PLUGINS) += gcc-plugins
subdir-$(CONFIG_MODVERSIONS) += genksyms
diff --git a/scripts/Makefile.build b/scripts/Makefile.build
index b734ac8a654e..9fcbfac15d1d 100644
--- a/scripts/Makefile.build
+++ b/scripts/Makefile.build
@@ -16,6 +16,8 @@ obj-m :=
lib-y :=
lib-m :=
always :=
+always-y :=
+always-m :=
targets :=
subdir-y :=
subdir-m :=
@@ -44,7 +46,7 @@ include $(kbuild-file)
include scripts/Makefile.lib
# Do not include host rules unless needed
-ifneq ($(hostprogs-y)$(hostprogs-m)$(hostlibs-y)$(hostlibs-m)$(hostcxxlibs-y)$(hostcxxlibs-m),)
+ifneq ($(hostprogs)$(hostcxxlibs-y)$(hostcxxlibs-m),)
include scripts/Makefile.host
endif
@@ -63,10 +65,9 @@ endif
ifneq ($(strip $(lib-y) $(lib-m) $(lib-)),)
lib-target := $(obj)/lib.a
-real-obj-y += $(obj)/lib-ksyms.o
endif
-ifneq ($(strip $(real-obj-y) $(need-builtin)),)
+ifdef need-builtin
builtin-target := $(obj)/built-in.a
endif
@@ -348,7 +349,7 @@ $(obj)/%.o: $(src)/%.S $(objtool_dep) FORCE
$(call if_changed_rule,as_o_S)
targets += $(filter-out $(subdir-obj-y), $(real-obj-y)) $(real-obj-m) $(lib-y)
-targets += $(extra-y) $(MAKECMDGOALS) $(always)
+targets += $(extra-y) $(always-y) $(MAKECMDGOALS)
# Linker scripts preprocessor (.lds.S -> .lds)
# ---------------------------------------------------------------------------
@@ -372,7 +373,7 @@ $(obj)/%.asn1.c $(obj)/%.asn1.h: $(src)/%.asn1 $(objtree)/scripts/asn1_compiler
# ---------------------------------------------------------------------------
# To build objects in subdirs, we need to descend into the directories
-$(sort $(subdir-obj-y)): $(subdir-ym) ;
+$(obj)/%/built-in.a: $(obj)/% ;
#
# Rule to compile a set of .o files into one .a file (without symbol table)
@@ -408,22 +409,6 @@ $(lib-target): $(lib-y) FORCE
targets += $(lib-target)
-dummy-object = $(obj)/.lib_exports.o
-ksyms-lds = $(dot-target).lds
-
-quiet_cmd_export_list = EXPORTS $@
-cmd_export_list = $(OBJDUMP) -h $< | \
- sed -ne '/___ksymtab/s/.*+\([^ ]*\).*/EXTERN(\1)/p' >$(ksyms-lds);\
- rm -f $(dummy-object);\
- echo | $(CC) $(a_flags) -c -o $(dummy-object) -x assembler -;\
- $(LD) $(ld_flags) -r -o $@ -T $(ksyms-lds) $(dummy-object);\
- rm $(dummy-object) $(ksyms-lds)
-
-$(obj)/lib-ksyms.o: $(lib-target) FORCE
- $(call if_changed,export_list)
-
-targets += $(obj)/lib-ksyms.o
-
endif
# NOTE:
@@ -490,7 +475,7 @@ else
__build: $(if $(KBUILD_BUILTIN),$(builtin-target) $(lib-target) $(extra-y)) \
$(if $(KBUILD_MODULES),$(obj-m) $(mod-targets) $(modorder-target)) \
- $(subdir-ym) $(always)
+ $(subdir-ym) $(always-y)
@:
endif
diff --git a/scripts/Makefile.clean b/scripts/Makefile.clean
index e367eb95c5c0..075f0cc2d8d7 100644
--- a/scripts/Makefile.clean
+++ b/scripts/Makefile.clean
@@ -28,9 +28,8 @@ subdir-ymn := $(addprefix $(obj)/,$(subdir-ymn))
# directory
__clean-files := $(extra-y) $(extra-m) $(extra-) \
- $(always) $(targets) $(clean-files) \
- $(hostprogs-y) $(hostprogs-m) $(hostprogs-) \
- $(hostlibs-y) $(hostlibs-m) $(hostlibs-) \
+ $(always) $(always-y) $(always-m) $(always-) $(targets) $(clean-files) \
+ $(hostprogs) $(hostprogs-y) $(hostprogs-m) $(hostprogs-) \
$(hostcxxlibs-y) $(hostcxxlibs-m)
__clean-files := $(filter-out $(no-clean-files), $(__clean-files))
diff --git a/scripts/Makefile.dtbinst b/scripts/Makefile.dtbinst
index 7301ab5e2e06..50d580d77ae9 100644
--- a/scripts/Makefile.dtbinst
+++ b/scripts/Makefile.dtbinst
@@ -13,28 +13,24 @@ src := $(obj)
PHONY := __dtbs_install
__dtbs_install:
-export dtbinst_root ?= $(obj)
-
include include/config/auto.conf
include scripts/Kbuild.include
include $(src)/Makefile
-dtbinst-files := $(sort $(dtb-y) $(if $(CONFIG_OF_ALL_DTBS), $(dtb-)))
-dtbinst-dirs := $(subdir-y) $(subdir-m)
-
-# Helper targets for Installing DTBs into the boot directory
-quiet_cmd_dtb_install = INSTALL $<
- cmd_dtb_install = mkdir -p $(2); cp $< $(2)
+dtbs := $(addprefix $(dst)/, $(dtb-y) $(if $(CONFIG_OF_ALL_DTBS),$(dtb-)))
+subdirs := $(addprefix $(obj)/, $(subdir-y) $(subdir-m))
-install-dir = $(patsubst $(dtbinst_root)%,$(INSTALL_DTBS_PATH)%,$(obj))
+__dtbs_install: $(dtbs) $(subdirs)
+ @:
-$(dtbinst-files): %.dtb: $(obj)/%.dtb
- $(call cmd,dtb_install,$(install-dir))
+quiet_cmd_dtb_install = INSTALL $@
+ cmd_dtb_install = install -D $< $@
-$(dtbinst-dirs):
- $(Q)$(MAKE) $(dtbinst)=$(obj)/$@
+$(dst)/%.dtb: $(obj)/%.dtb
+ $(call cmd,dtb_install)
-PHONY += $(dtbinst-files) $(dtbinst-dirs)
-__dtbs_install: $(dtbinst-files) $(dtbinst-dirs)
+PHONY += $(subdirs)
+$(subdirs):
+ $(Q)$(MAKE) $(dtbinst)=$@ dst=$(patsubst $(obj)/%,$(dst)/%,$@)
.PHONY: $(PHONY)
diff --git a/scripts/Makefile.extrawarn b/scripts/Makefile.extrawarn
index ecddf83ac142..4aea7cf71d11 100644
--- a/scripts/Makefile.extrawarn
+++ b/scripts/Makefile.extrawarn
@@ -48,6 +48,8 @@ KBUILD_CFLAGS += -Wno-initializer-overrides
KBUILD_CFLAGS += -Wno-format
KBUILD_CFLAGS += -Wno-sign-compare
KBUILD_CFLAGS += -Wno-format-zero-length
+KBUILD_CFLAGS += $(call cc-disable-warning, pointer-to-enum-cast)
+KBUILD_CFLAGS += -Wno-tautological-constant-out-of-range-compare
endif
endif
diff --git a/scripts/Makefile.host b/scripts/Makefile.host
index 4c51c95d40f4..2045855d0b75 100644
--- a/scripts/Makefile.host
+++ b/scripts/Makefile.host
@@ -24,22 +24,21 @@ $(obj)/%.tab.c $(obj)/%.tab.h: $(src)/%.y FORCE
# Both C and C++ are supported, but preferred language is C for such utilities.
#
# Sample syntax (see Documentation/kbuild/makefiles.rst for reference)
-# hostprogs-y := bin2hex
+# hostprogs := bin2hex
# Will compile bin2hex.c and create an executable named bin2hex
#
-# hostprogs-y := lxdialog
+# hostprogs := lxdialog
# lxdialog-objs := checklist.o lxdialog.o
# Will compile lxdialog.c and checklist.c, and then link the executable
# lxdialog, based on checklist.o and lxdialog.o
#
-# hostprogs-y := qconf
+# hostprogs := qconf
# qconf-cxxobjs := qconf.o
# qconf-objs := menu.o
# Will compile qconf as a C++ program, and menu as a C program.
# They are linked as C++ code to the executable qconf
-__hostprogs := $(sort $(hostprogs-y) $(hostprogs-m))
-host-cshlib := $(sort $(hostlibs-y) $(hostlibs-m))
+__hostprogs := $(sort $(hostprogs))
host-cxxshlib := $(sort $(hostcxxlibs-y) $(hostcxxlibs-m))
# C code
@@ -63,7 +62,6 @@ host-cxxmulti := $(foreach m,$(__hostprogs),$(if $($(m)-cxxobjs),$(m)))
host-cxxobjs := $(sort $(foreach m,$(host-cxxmulti),$($(m)-cxxobjs)))
# Object (.o) files used by the shared libaries
-host-cshobjs := $(sort $(foreach m,$(host-cshlib),$($(m:.so=-objs))))
host-cxxshobjs := $(sort $(foreach m,$(host-cxxshlib),$($(m:.so=-objs))))
host-csingle := $(addprefix $(obj)/,$(host-csingle))
@@ -71,9 +69,7 @@ host-cmulti := $(addprefix $(obj)/,$(host-cmulti))
host-cobjs := $(addprefix $(obj)/,$(host-cobjs))
host-cxxmulti := $(addprefix $(obj)/,$(host-cxxmulti))
host-cxxobjs := $(addprefix $(obj)/,$(host-cxxobjs))
-host-cshlib := $(addprefix $(obj)/,$(host-cshlib))
host-cxxshlib := $(addprefix $(obj)/,$(host-cxxshlib))
-host-cshobjs := $(addprefix $(obj)/,$(host-cshobjs))
host-cxxshobjs := $(addprefix $(obj)/,$(host-cxxshobjs))
#####
@@ -141,13 +137,6 @@ $(host-cxxobjs): $(obj)/%.o: $(src)/%.cc FORCE
$(call if_changed_dep,host-cxxobjs)
# Compile .c file, create position independent .o file
-# host-cshobjs -> .o
-quiet_cmd_host-cshobjs = HOSTCC -fPIC $@
- cmd_host-cshobjs = $(HOSTCC) $(hostc_flags) -fPIC -c -o $@ $<
-$(host-cshobjs): $(obj)/%.o: $(src)/%.c FORCE
- $(call if_changed_dep,host-cshobjs)
-
-# Compile .c file, create position independent .o file
# Note that plugin capable gcc versions can be either C or C++ based
# therefore plugin source files have to be compilable in both C and C++ mode.
# This is why a C++ compiler is invoked on a .c file.
@@ -158,16 +147,6 @@ $(host-cxxshobjs): $(obj)/%.o: $(src)/%.c FORCE
$(call if_changed_dep,host-cxxshobjs)
# Link a shared library, based on position independent .o files
-# *.o -> .so shared library (host-cshlib)
-quiet_cmd_host-cshlib = HOSTLLD -shared $@
- cmd_host-cshlib = $(HOSTCC) $(KBUILD_HOSTLDFLAGS) -shared -o $@ \
- $(addprefix $(obj)/, $($(target-stem)-objs)) \
- $(KBUILD_HOSTLDLIBS) $(HOSTLDLIBS_$(target-stem).so)
-$(host-cshlib): FORCE
- $(call if_changed,host-cshlib)
-$(call multi_depend, $(host-cshlib), .so, -objs)
-
-# Link a shared library, based on position independent .o files
# *.o -> .so shared library (host-cxxshlib)
quiet_cmd_host-cxxshlib = HOSTLLD -shared $@
cmd_host-cxxshlib = $(HOSTCXX) $(KBUILD_HOSTLDFLAGS) -shared -o $@ \
@@ -178,4 +157,4 @@ $(host-cxxshlib): FORCE
$(call multi_depend, $(host-cxxshlib), .so, -objs)
targets += $(host-csingle) $(host-cmulti) $(host-cobjs)\
- $(host-cxxmulti) $(host-cxxobjs) $(host-cshlib) $(host-cshobjs) $(host-cxxshlib) $(host-cxxshobjs)
+ $(host-cxxmulti) $(host-cxxobjs) $(host-cxxshlib) $(host-cxxshobjs)
diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib
index 3fa32f83b2d7..97547108ee7f 100644
--- a/scripts/Makefile.lib
+++ b/scripts/Makefile.lib
@@ -4,6 +4,8 @@ asflags-y += $(EXTRA_AFLAGS)
ccflags-y += $(EXTRA_CFLAGS)
cppflags-y += $(EXTRA_CPPFLAGS)
ldflags-y += $(EXTRA_LDFLAGS)
+always-y += $(always)
+hostprogs += $(hostprogs-y) $(hostprogs-m)
# flags that take effect in current and sub directories
KBUILD_AFLAGS += $(subdir-asflags-y)
@@ -35,7 +37,11 @@ __subdir-y := $(patsubst %/,%,$(filter %/, $(obj-y)))
subdir-y += $(__subdir-y)
__subdir-m := $(patsubst %/,%,$(filter %/, $(obj-m)))
subdir-m += $(__subdir-m)
+ifdef need-builtin
obj-y := $(patsubst %/, %/built-in.a, $(obj-y))
+else
+obj-y := $(filter-out %/, $(obj-y))
+endif
obj-m := $(filter-out %/, $(obj-m))
# Subdirectories we need to descend into
@@ -55,6 +61,8 @@ subdir-obj-y := $(filter %/built-in.a, $(obj-y))
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)))
+always-y += $(always-m)
+
# DTB
# If CONFIG_OF_ALL_DTBS is enabled, all DT blobs are built
extra-y += $(dtb-y)
@@ -68,7 +76,7 @@ endif
# Add subdir path
extra-y := $(addprefix $(obj)/,$(extra-y))
-always := $(addprefix $(obj)/,$(always))
+always-y := $(addprefix $(obj)/,$(always-y))
targets := $(addprefix $(obj)/,$(targets))
modorder := $(addprefix $(obj)/,$(modorder))
obj-m := $(addprefix $(obj)/,$(obj-m))
@@ -80,12 +88,14 @@ multi-used-m := $(addprefix $(obj)/,$(multi-used-m))
subdir-ym := $(addprefix $(obj)/,$(subdir-ym))
# Finds the multi-part object the current object will be linked into.
-# If the object belongs to two or more multi-part objects, all of them are
-# concatenated with a colon separator.
-modname-multi = $(subst $(space),:,$(sort $(foreach m,$(multi-used),\
- $(if $(filter $*.o, $($(m:.o=-objs)) $($(m:.o=-y)) $($(m:.o=-m))),$(m:.o=)))))
+# If the object belongs to two or more multi-part objects, list them all.
+modname-multi = $(sort $(foreach m,$(multi-used),\
+ $(if $(filter $*.o, $($(m:.o=-objs)) $($(m:.o=-y)) $($(m:.o=-m))),$(m:.o=))))
+
+__modname = $(if $(modname-multi),$(modname-multi),$(basetarget))
-modname = $(if $(modname-multi),$(modname-multi),$(basetarget))
+modname = $(subst $(space),:,$(__modname))
+modfile = $(addprefix $(obj)/,$(__modname))
# target with $(obj)/ and its suffix stripped
target-stem = $(basename $(patsubst $(obj)/%,%,$@))
@@ -93,9 +103,10 @@ 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 = $(squote)$(quote)$(subst $(comma),_,$(subst -,_,$1))$(quote)$(squote)
+name-fix = $(call stringify,$(subst $(comma),_,$(subst -,_,$1)))
basename_flags = -DKBUILD_BASENAME=$(call name-fix,$(basetarget))
modname_flags = -DKBUILD_MODNAME=$(call name-fix,$(modname))
+modfile_flags = -DKBUILD_MODFILE=$(call stringify,$(modfile))
orig_c_flags = $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS) \
$(ccflags-y) $(CFLAGS_$(target-stem).o)
@@ -154,7 +165,7 @@ quiet_modtag = $(if $(part-of-module),[M], )
modkern_cflags = \
$(if $(part-of-module), \
$(KBUILD_CFLAGS_MODULE) $(CFLAGS_MODULE), \
- $(KBUILD_CFLAGS_KERNEL) $(CFLAGS_KERNEL))
+ $(KBUILD_CFLAGS_KERNEL) $(CFLAGS_KERNEL) $(modfile_flags))
modkern_aflags = $(if $(part-of-module), \
$(KBUILD_AFLAGS_MODULE) $(AFLAGS_MODULE), \
@@ -286,18 +297,19 @@ $(obj)/%.dtb: $(src)/%.dts $(DTC) FORCE
DT_CHECKER ?= dt-validate
DT_BINDING_DIR := Documentation/devicetree/bindings
-DT_TMP_SCHEMA := $(objtree)/$(DT_BINDING_DIR)/processed-schema.yaml
+# DT_TMP_SCHEMA may be overridden from Documentation/devicetree/bindings/Makefile
+DT_TMP_SCHEMA ?= $(objtree)/$(DT_BINDING_DIR)/processed-schema.yaml
quiet_cmd_dtb_check = CHECK $@
- cmd_dtb_check = $(DT_CHECKER) -u $(srctree)/$(DT_BINDING_DIR) -p $(DT_TMP_SCHEMA) $@ ;
+ cmd_dtb_check = $(DT_CHECKER) -u $(srctree)/$(DT_BINDING_DIR) -p $(DT_TMP_SCHEMA) $@
-define rule_dtc_dt_yaml
+define rule_dtc
$(call cmd_and_fixdep,dtc,yaml)
$(call cmd,dtb_check)
endef
$(obj)/%.dt.yaml: $(src)/%.dts $(DTC) $(DT_TMP_SCHEMA) FORCE
- $(call if_changed_rule,dtc_dt_yaml)
+ $(call if_changed_rule,dtc)
dtc-tmp = $(subst $(comma),_,$(dot-target).dts.tmp)
diff --git a/scripts/Makefile.modbuiltin b/scripts/Makefile.modbuiltin
deleted file mode 100644
index 7d4711b88656..000000000000
--- a/scripts/Makefile.modbuiltin
+++ /dev/null
@@ -1,57 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-# ==========================================================================
-# Generating modules.builtin
-# ==========================================================================
-
-src := $(obj)
-
-PHONY := __modbuiltin
-__modbuiltin:
-
-include include/config/auto.conf
-# tristate.conf sets tristate variables to uppercase 'Y' or 'M'
-# That way, we get the list of built-in modules in obj-Y
-include include/config/tristate.conf
-
-include scripts/Kbuild.include
-
-ifdef building_out_of_srctree
-# Create output directory if not already present
-_dummy := $(shell [ -d $(obj) ] || mkdir -p $(obj))
-endif
-
-# The filename Kbuild has precedence over Makefile
-kbuild-dir := $(if $(filter /%,$(src)),$(src),$(srctree)/$(src))
-kbuild-file := $(if $(wildcard $(kbuild-dir)/Kbuild),$(kbuild-dir)/Kbuild,$(kbuild-dir)/Makefile)
-include $(kbuild-file)
-
-include scripts/Makefile.lib
-__subdir-Y := $(patsubst %/,%,$(filter %/, $(obj-Y)))
-subdir-Y += $(__subdir-Y)
-subdir-ym := $(sort $(subdir-y) $(subdir-Y) $(subdir-m))
-subdir-ym := $(addprefix $(obj)/,$(subdir-ym))
-obj-Y := $(addprefix $(obj)/,$(obj-Y))
-
-modbuiltin-subdirs := $(patsubst %,%/modules.builtin, $(subdir-ym))
-modbuiltin-mods := $(filter %.ko, $(obj-Y:.o=.ko))
-modbuiltin-target := $(obj)/modules.builtin
-
-__modbuiltin: $(modbuiltin-target) $(subdir-ym)
- @:
-
-$(modbuiltin-target): $(subdir-ym) FORCE
- $(Q)(for m in $(modbuiltin-mods); do echo $$m; done; \
- cat /dev/null $(modbuiltin-subdirs)) > $@
-
-PHONY += FORCE
-
-FORCE:
-
-# Descending
-# ---------------------------------------------------------------------------
-
-PHONY += $(subdir-ym)
-$(subdir-ym):
- $(Q)$(MAKE) $(modbuiltin)=$@
-
-.PHONY: $(PHONY)
diff --git a/scripts/Makefile.modpost b/scripts/Makefile.modpost
index 69897d5d3a70..957eed6a17a5 100644
--- a/scripts/Makefile.modpost
+++ b/scripts/Makefile.modpost
@@ -46,13 +46,14 @@ include scripts/Kbuild.include
kernelsymfile := $(objtree)/Module.symvers
modulesymfile := $(firstword $(KBUILD_EXTMOD))/Module.symvers
-MODPOST = scripts/mod/modpost \
- $(if $(CONFIG_MODVERSIONS),-m) \
- $(if $(CONFIG_MODULE_SRCVERSION_ALL),-a) \
- $(if $(KBUILD_EXTMOD),-i,-o) $(kernelsymfile) \
- $(if $(KBUILD_EXTMOD),$(addprefix -e ,$(KBUILD_EXTRA_SYMBOLS))) \
- $(if $(KBUILD_EXTMOD),-o $(modulesymfile)) \
- $(if $(CONFIG_SECTION_MISMATCH_WARN_ONLY),,-E) \
+MODPOST = scripts/mod/modpost \
+ $(if $(CONFIG_MODVERSIONS),-m) \
+ $(if $(CONFIG_MODULE_SRCVERSION_ALL),-a) \
+ $(if $(KBUILD_EXTMOD),-i,-o) $(kernelsymfile) \
+ $(if $(KBUILD_EXTMOD),$(addprefix -e ,$(KBUILD_EXTRA_SYMBOLS))) \
+ $(if $(KBUILD_EXTMOD),-o $(modulesymfile)) \
+ $(if $(CONFIG_SECTION_MISMATCH_WARN_ONLY),,-E) \
+ $(if $(CONFIG_MODULE_ALLOW_MISSING_NAMESPACE_IMPORTS)$(KBUILD_NSDEPS),-N) \
$(if $(KBUILD_MODPOST_WARN),-w)
ifdef MODPOST_VMLINUX
@@ -90,7 +91,6 @@ quiet_cmd_modpost = MODPOST $(words $(modules)) modules
cmd_modpost = sed 's/ko$$/o/' $(MODORDER) | $(MODPOST)
__modpost:
- @$(kecho) ' Building modules, stage 2.'
$(call cmd,modpost)
ifneq ($(KBUILD_MODPOST_NOFINAL),1)
$(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modfinal
diff --git a/scripts/Makefile.ubsan b/scripts/Makefile.ubsan
index 019771b845c5..5b15bc425ec9 100644
--- a/scripts/Makefile.ubsan
+++ b/scripts/Makefile.ubsan
@@ -1,16 +1,26 @@
# SPDX-License-Identifier: GPL-2.0
ifdef CONFIG_UBSAN
+
+ifdef CONFIG_UBSAN_ALIGNMENT
+ CFLAGS_UBSAN += $(call cc-option, -fsanitize=alignment)
+endif
+
+ifdef CONFIG_UBSAN_BOUNDS
+ CFLAGS_UBSAN += $(call cc-option, -fsanitize=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=bounds)
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_ALIGNMENT
- CFLAGS_UBSAN += $(call cc-option, -fsanitize=alignment)
+ifdef CONFIG_UBSAN_TRAP
+ CFLAGS_UBSAN += $(call cc-option, -fsanitize-undefined-trap-on-error)
endif
# -fsanitize=* options makes GCC less smart than usual and
diff --git a/scripts/adjust_autoksyms.sh b/scripts/adjust_autoksyms.sh
index a904bf1f5e67..2b366d945ccb 100755
--- a/scripts/adjust_autoksyms.sh
+++ b/scripts/adjust_autoksyms.sh
@@ -1,14 +1,13 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0-only
-# Script to create/update include/generated/autoksyms.h and dependency files
+# Script to update include/generated/autoksyms.h and dependency files
#
# Copyright: (C) 2016 Linaro Limited
# Created by: Nicolas Pitre, January 2016
#
-# Create/update the include/generated/autoksyms.h file from the list
-# of all module's needed symbols as recorded on the second line of *.mod files.
+# Update the include/generated/autoksyms.h file.
#
# For each symbol being added or removed, the corresponding dependency
# file's timestamp is updated to force a rebuild of the affected source
@@ -38,23 +37,8 @@ esac
# We need access to CONFIG_ symbols
. include/config/auto.conf
-# Generate a new ksym list file with symbols needed by the current
-# set of modules.
-cat > "$new_ksyms_file" << EOT
-/*
- * Automatically generated file; DO NOT EDIT.
- */
-
-EOT
-sed 's/ko$/mod/' modules.order |
-xargs -n1 sed -n -e '2{s/ /\n/g;/^$/!p;}' -- |
-sort -u |
-sed -e 's/\(.*\)/#define __KSYM_\1 1/' >> "$new_ksyms_file"
-
-# Special case for modversions (see modpost.c)
-if [ -n "$CONFIG_MODVERSIONS" ]; then
- echo "#define __KSYM_module_layout 1" >> "$new_ksyms_file"
-fi
+# Generate a new symbol list file
+$CONFIG_SHELL $srctree/scripts/gen_autoksyms.sh "$new_ksyms_file"
# Extract changes between old and new list and touch corresponding
# dependency files.
diff --git a/scripts/basic/.gitignore b/scripts/basic/.gitignore
index a776371a3502..98ae1f509592 100644
--- a/scripts/basic/.gitignore
+++ b/scripts/basic/.gitignore
@@ -1 +1,2 @@
+# SPDX-License-Identifier: GPL-2.0-only
fixdep
diff --git a/scripts/basic/Makefile b/scripts/basic/Makefile
index 7c9cb80d097b..290dd27d2809 100644
--- a/scripts/basic/Makefile
+++ b/scripts/basic/Makefile
@@ -2,5 +2,5 @@
#
# fixdep: used to generate dependency information during build process
-hostprogs-y := fixdep
-always := $(hostprogs-y)
+hostprogs := fixdep
+always-y := $(hostprogs)
diff --git a/scripts/basic/fixdep.c b/scripts/basic/fixdep.c
index 9ba47b0a47b9..877ca2c88246 100644
--- a/scripts/basic/fixdep.c
+++ b/scripts/basic/fixdep.c
@@ -77,11 +77,6 @@
* dependencies on include/config/my/option.h for every
* CONFIG_MY_OPTION encountered in any of the prerequisites.
*
- * It will also filter out all the dependencies on *.ver. We need
- * to make sure that the generated version checksum are globally up
- * to date before even starting the recursive build, so it's too late
- * at this point anyway.
- *
* We don't even try to really parse the header files, but
* merely grep, i.e. if CONFIG_FOO is mentioned in a comment, it will
* be picked up as well. It's not a problem with respect to
@@ -251,7 +246,7 @@ static void parse_config_file(const char *p)
}
p += 7;
q = p;
- while (*q && (isalnum(*q) || *q == '_'))
+ while (isalnum(*q) || *q == '_')
q++;
if (str_ends_with(p, q - p, "_MODULE"))
r = q - 7;
@@ -299,8 +294,7 @@ static void *read_file(const char *filename)
static int is_ignored_file(const char *s, int len)
{
return str_ends_with(s, len, "include/generated/autoconf.h") ||
- str_ends_with(s, len, "include/generated/autoksyms.h") ||
- str_ends_with(s, len, ".ver");
+ str_ends_with(s, len, "include/generated/autoksyms.h");
}
/*
diff --git a/scripts/bpf_helpers_doc.py b/scripts/bpf_helpers_doc.py
index 7548569e8076..f43d193aff3a 100755
--- a/scripts/bpf_helpers_doc.py
+++ b/scripts/bpf_helpers_doc.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python3
+#!/usr/bin/env python3
# SPDX-License-Identifier: GPL-2.0-only
#
# Copyright (C) 2018-2019 Netronome Systems, Inc.
@@ -158,8 +158,6 @@ class HeaderParser(object):
break
self.reader.close()
- print('Parsed description of %d helper function(s)' % len(self.helpers),
- file=sys.stderr)
###############################################################################
@@ -402,6 +400,7 @@ class PrinterHelpers(Printer):
'struct bpf_fib_lookup',
'struct bpf_perf_event_data',
'struct bpf_perf_event_value',
+ 'struct bpf_pidns_info',
'struct bpf_sock',
'struct bpf_sock_addr',
'struct bpf_sock_ops',
@@ -437,6 +436,7 @@ class PrinterHelpers(Printer):
'struct bpf_fib_lookup',
'struct bpf_perf_event_data',
'struct bpf_perf_event_value',
+ 'struct bpf_pidns_info',
'struct bpf_sock',
'struct bpf_sock_addr',
'struct bpf_sock_ops',
diff --git a/scripts/check-sysctl-docs b/scripts/check-sysctl-docs
new file mode 100755
index 000000000000..8bcb9e26c7bc
--- /dev/null
+++ b/scripts/check-sysctl-docs
@@ -0,0 +1,181 @@
+#!/usr/bin/gawk -f
+# SPDX-License-Identifier: GPL-2.0
+
+# Script to check sysctl documentation against source files
+#
+# Copyright (c) 2020 Stephen Kitt
+
+# Example invocation:
+# scripts/check-sysctl-docs -vtable="kernel" \
+# Documentation/admin-guide/sysctl/kernel.rst \
+# $(git grep -l register_sysctl_)
+#
+# Specify -vdebug=1 to see debugging information
+
+BEGIN {
+ if (!table) {
+ print "Please specify the table to look for using the table variable" > "/dev/stderr"
+ exit 1
+ }
+}
+
+# The following globals are used:
+# children: maps ctl_table names and procnames to child ctl_table names
+# documented: maps documented entries (each key is an entry)
+# entries: maps ctl_table names and procnames to counts (so
+# enumerating the subkeys for a given ctl_table lists its
+# procnames)
+# files: maps procnames to source file names
+# paths: maps ctl_path names to paths
+# curpath: the name of the current ctl_path struct
+# curtable: the name of the current ctl_table struct
+# curentry: the name of the current proc entry (procname when parsing
+# a ctl_table, constructed path when parsing a ctl_path)
+
+
+# Remove punctuation from the given value
+function trimpunct(value) {
+ while (value ~ /^["&]/) {
+ value = substr(value, 2)
+ }
+ while (value ~ /[]["&,}]$/) {
+ value = substr(value, 1, length(value) - 1)
+ }
+ return value
+}
+
+# Print the information for the given entry
+function printentry(entry) {
+ seen[entry]++
+ printf "* %s from %s", entry, file[entry]
+ if (documented[entry]) {
+ printf " (documented)"
+ }
+ print ""
+}
+
+
+# Stage 1: build the list of documented entries
+FNR == NR && /^=+$/ {
+ if (prevline ~ /Documentation for/) {
+ # This is the main title
+ next
+ }
+
+ # The previous line is a section title, parse it
+ $0 = prevline
+ if (debug) print "Parsing " $0
+ inbrackets = 0
+ for (i = 1; i <= NF; i++) {
+ if (length($i) == 0) {
+ continue
+ }
+ if (!inbrackets && substr($i, 1, 1) == "(") {
+ inbrackets = 1
+ }
+ if (!inbrackets) {
+ token = trimpunct($i)
+ if (length(token) > 0 && token != "and") {
+ if (debug) print trimpunct($i)
+ documented[trimpunct($i)]++
+ }
+ }
+ if (inbrackets && substr($i, length($i), 1) == ")") {
+ inbrackets = 0
+ }
+ }
+}
+
+FNR == NR {
+ prevline = $0
+ next
+}
+
+
+# Stage 2: process each file and find all sysctl tables
+BEGINFILE {
+ delete children
+ delete entries
+ delete paths
+ curpath = ""
+ curtable = ""
+ curentry = ""
+ if (debug) print "Processing file " FILENAME
+}
+
+/^static struct ctl_path/ {
+ match($0, /static struct ctl_path ([^][]+)/, tables)
+ curpath = tables[1]
+ if (debug) print "Processing path " curpath
+}
+
+/^static struct ctl_table/ {
+ match($0, /static struct ctl_table ([^][]+)/, tables)
+ curtable = tables[1]
+ if (debug) print "Processing table " curtable
+}
+
+/^};$/ {
+ curpath = ""
+ curtable = ""
+ curentry = ""
+}
+
+curpath && /\.procname[\t ]*=[\t ]*".+"/ {
+ match($0, /.procname[\t ]*=[\t ]*"([^"]+)"/, names)
+ if (curentry) {
+ curentry = curentry "/" names[1]
+ } else {
+ curentry = names[1]
+ }
+ if (debug) print "Setting path " curpath " to " curentry
+ paths[curpath] = curentry
+}
+
+curtable && /\.procname[\t ]*=[\t ]*".+"/ {
+ match($0, /.procname[\t ]*=[\t ]*"([^"]+)"/, names)
+ curentry = names[1]
+ if (debug) print "Adding entry " curentry " to table " curtable
+ entries[curtable][curentry]++
+ file[curentry] = FILENAME
+}
+
+/\.child[\t ]*=/ {
+ child = trimpunct($NF)
+ if (debug) print "Linking child " child " to table " curtable " entry " curentry
+ children[curtable][curentry] = child
+}
+
+/register_sysctl_table\(.*\)/ {
+ match($0, /register_sysctl_table\(([^)]+)\)/, tables)
+ if (debug) print "Registering table " tables[1]
+ if (children[tables[1]][table]) {
+ for (entry in entries[children[tables[1]][table]]) {
+ printentry(entry)
+ }
+ }
+}
+
+/register_sysctl_paths\(.*\)/ {
+ match($0, /register_sysctl_paths\(([^)]+), ([^)]+)\)/, tables)
+ if (debug) print "Attaching table " tables[2] " to path " tables[1]
+ if (paths[tables[1]] == table) {
+ for (entry in entries[tables[2]]) {
+ printentry(entry)
+ }
+ }
+ split(paths[tables[1]], components, "/")
+ if (length(components) > 1 && components[1] == table) {
+ # Count the first subdirectory as seen
+ seen[components[2]]++
+ }
+}
+
+
+END {
+ for (entry in documented) {
+ if (!seen[entry]) {
+ print "No implementation for " entry
+ }
+ }
+}
diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl
index a63380c6b0d2..d64c67b67e3c 100755
--- a/scripts/checkpatch.pl
+++ b/scripts/checkpatch.pl
@@ -64,6 +64,7 @@ my $color = "auto";
my $allow_c99_comments = 1; # Can be overridden by --ignore C99_COMMENT_TOLERANCE
# git output parsing needs US English output, so first set backtick child process LANGUAGE
my $git_command ='export LANGUAGE=en_US.UTF-8; git';
+my $tabsize = 8;
sub help {
my ($exitcode) = @_;
@@ -98,6 +99,7 @@ Options:
--show-types show the specific message type in the output
--max-line-length=n set the maximum line length, if exceeded, warn
--min-conf-desc-length=n set the min description length, if shorter, warn
+ --tab-size=n set the number of spaces for tab (default 8)
--root=PATH PATH to the kernel tree root
--no-summary suppress the per-file summary
--mailback only produce a report in case of warnings/errors
@@ -215,6 +217,7 @@ GetOptions(
'list-types!' => \$list_types,
'max-line-length=i' => \$max_line_length,
'min-conf-desc-length=i' => \$min_conf_desc_length,
+ 'tab-size=i' => \$tabsize,
'root=s' => \$root,
'summary!' => \$summary,
'mailback!' => \$mailback,
@@ -267,6 +270,9 @@ if ($color =~ /^[01]$/) {
die "Invalid color mode: $color\n";
}
+# skip TAB size 1 to avoid additional checks on $tabsize - 1
+die "Invalid TAB size: $tabsize\n" if ($tabsize < 2);
+
sub hash_save_array_words {
my ($hashRef, $arrayRef) = @_;
@@ -804,12 +810,12 @@ sub build_types {
}x;
$Type = qr{
$NonptrType
- (?:(?:\s|\*|\[\])+\s*const|(?:\s|\*\s*(?:const\s*)?|\[\])+|(?:\s*\[\s*\])+)?
+ (?:(?:\s|\*|\[\])+\s*const|(?:\s|\*\s*(?:const\s*)?|\[\])+|(?:\s*\[\s*\])+){0,4}
(?:\s+$Inline|\s+$Modifier)*
}x;
$TypeMisordered = qr{
$NonptrTypeMisordered
- (?:(?:\s|\*|\[\])+\s*const|(?:\s|\*\s*(?:const\s*)?|\[\])+|(?:\s*\[\s*\])+)?
+ (?:(?:\s|\*|\[\])+\s*const|(?:\s|\*\s*(?:const\s*)?|\[\])+|(?:\s*\[\s*\])+){0,4}
(?:\s+$Inline|\s+$Modifier)*
}x;
$Declare = qr{(?:$Storage\s+(?:$Inline\s+)?)?$Type};
@@ -1118,6 +1124,7 @@ sub parse_email {
my ($formatted_email) = @_;
my $name = "";
+ my $name_comment = "";
my $address = "";
my $comment = "";
@@ -1150,6 +1157,10 @@ sub parse_email {
$name = trim($name);
$name =~ s/^\"|\"$//g;
+ $name =~ s/(\s*\([^\)]+\))\s*//;
+ if (defined($1)) {
+ $name_comment = trim($1);
+ }
$address = trim($address);
$address =~ s/^\<|\>$//g;
@@ -1158,7 +1169,7 @@ sub parse_email {
$name = "\"$name\"";
}
- return ($name, $address, $comment);
+ return ($name, $name_comment, $address, $comment);
}
sub format_email {
@@ -1184,6 +1195,23 @@ sub format_email {
return $formatted_email;
}
+sub reformat_email {
+ my ($email) = @_;
+
+ my ($email_name, $name_comment, $email_address, $comment) = parse_email($email);
+ return format_email($email_name, $email_address);
+}
+
+sub same_email_addresses {
+ 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);
+
+ return $email1_name eq $email2_name &&
+ $email1_address eq $email2_address;
+}
+
sub which {
my ($bin) = @_;
@@ -1217,7 +1245,7 @@ sub expand_tabs {
if ($c eq "\t") {
$res .= ' ';
$n++;
- for (; ($n % 8) != 0; $n++) {
+ for (; ($n % $tabsize) != 0; $n++) {
$res .= ' ';
}
next;
@@ -2230,7 +2258,7 @@ sub string_find_replace {
sub tabify {
my ($leading) = @_;
- my $source_indent = 8;
+ my $source_indent = $tabsize;
my $max_spaces_before_tab = $source_indent - 1;
my $spaces_to_tab = " " x $source_indent;
@@ -2272,6 +2300,19 @@ sub pos_last_openparen {
return length(expand_tabs(substr($line, 0, $last_openparen))) + 1;
}
+sub get_raw_comment {
+ my ($line, $rawline) = @_;
+ my $comment = '';
+
+ for my $i (0 .. (length($line) - 1)) {
+ if (substr($line, $i, 1) eq "$;") {
+ $comment .= substr($rawline, $i, 1);
+ }
+ }
+
+ return $comment;
+}
+
sub process {
my $filename = shift;
@@ -2294,6 +2335,7 @@ sub process {
my $is_binding_patch = -1;
my $in_header_lines = $file ? 0 : 1;
my $in_commit_log = 0; #Scanning lines before patch
+ my $has_patch_separator = 0; #Found a --- line
my $has_commit_log = 0; #Encountered lines before patch
my $commit_log_lines = 0; #Number of commit log lines
my $commit_log_possible_stack_dump = 0;
@@ -2433,6 +2475,7 @@ sub process {
$sline =~ s/$;/ /g; #with comments as spaces
my $rawline = $rawlines[$linenr - 1];
+ my $raw_comment = get_raw_comment($line, $rawline);
# check if it's a mode change, rename or start of a patch
if (!$in_commit_log &&
@@ -2604,21 +2647,26 @@ sub process {
$author = $1;
$author = encode("utf8", $author) if ($line =~ /=\?utf-8\?/i);
$author =~ s/"//g;
+ $author = reformat_email($author);
}
# Check the patch for a signoff:
- if ($line =~ /^\s*signed-off-by:/i) {
+ if ($line =~ /^\s*signed-off-by:\s*(.*)/i) {
$signoff++;
$in_commit_log = 0;
if ($author ne '') {
- my $l = $line;
- $l =~ s/"//g;
- if ($l =~ /^\s*signed-off-by:\s*\Q$author\E/i) {
- $authorsignoff = 1;
+ if (same_email_addresses($1, $author)) {
+ $authorsignoff = 1;
}
}
}
+# Check for patch separator
+ if ($line =~ /^---$/) {
+ $has_patch_separator = 1;
+ $in_commit_log = 0;
+ }
+
# Check if MAINTAINERS is being updated. If so, there's probably no need to
# emit the "does MAINTAINERS need updating?" message on file add/move/delete
if ($line =~ /^\s*MAINTAINERS\s*\|/) {
@@ -2664,7 +2712,7 @@ sub process {
}
}
- my ($email_name, $email_address, $comment) = parse_email($email);
+ my ($email_name, $name_comment, $email_address, $comment) = parse_email($email);
my $suggested_email = format_email(($email_name, $email_address));
if ($suggested_email eq "") {
ERROR("BAD_SIGN_OFF",
@@ -2675,9 +2723,7 @@ sub process {
$dequoted =~ s/" </ </;
# Don't force email to have quotes
# Allow just an angle bracketed address
- if ("$dequoted$comment" ne $email &&
- "<$email_address>$comment" ne $email &&
- "$suggested_email$comment" ne $email) {
+ if (!same_email_addresses($email, $suggested_email)) {
WARN("BAD_SIGN_OFF",
"email address '$email' might be better as '$suggested_email$comment'\n" . $herecurr);
}
@@ -2720,10 +2766,10 @@ sub process {
"A patch subject line should describe the change not the tool that found it\n" . $herecurr);
}
-# Check for unwanted Gerrit info
- if ($in_commit_log && $line =~ /^\s*change-id:/i) {
+# 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);
+ "Remove Gerrit Change-Id's before submitting upstream\n" . $herecurr);
}
# Check if the commit log is in a possible stack dump
@@ -2761,7 +2807,7 @@ sub process {
# 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):/i &&
+ $line !~ /^\s*(?:Link|Patchwork|http|https|BugLink|base-commit):/i &&
$line !~ /^This reverts commit [0-9a-f]{7,40}/ &&
($line =~ /\bcommit\s+[0-9a-f]{5,}\b/i ||
($line =~ /(?:\s|^)[0-9a-f]{12,40}(?:[\s"'\(\[]|$)/i &&
@@ -3087,7 +3133,7 @@ sub process {
$comment = '/*';
} elsif ($realfile =~ /\.(c|dts|dtsi)$/) {
$comment = '//';
- } elsif (($checklicenseline == 2) || $realfile =~ /\.(sh|pl|py|awk|tc)$/) {
+ } elsif (($checklicenseline == 2) || $realfile =~ /\.(sh|pl|py|awk|tc|yaml)$/) {
$comment = '#';
} elsif ($realfile =~ /\.rst$/) {
$comment = '..';
@@ -3111,6 +3157,17 @@ sub process {
WARN("SPDX_LICENSE_TAG",
"'$spdx_license' is not supported in LICENSES/...\n" . $herecurr);
}
+ if ($realfile =~ m@^Documentation/devicetree/bindings/@ &&
+ not $spdx_license =~ /GPL-2\.0.*BSD-2-Clause/) {
+ my $msg_level = \&WARN;
+ $msg_level = \&CHK if ($file);
+ if (&{$msg_level}("SPDX_LICENSE_TAG",
+
+ "DT binding documents should be licensed (GPL-2.0-only OR BSD-2-Clause)\n" . $herecurr) &&
+ $fix) {
+ $fixed[$fixlinenr] =~ s/SPDX-License-Identifier: .*/SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)/;
+ }
+ }
}
}
}
@@ -3198,7 +3255,7 @@ sub process {
next if ($realfile !~ /\.(h|c|pl|dtsi|dts)$/);
# at the beginning of a line any tabs must come first and anything
-# more than 8 must use tabs.
+# more than $tabsize must use tabs.
if ($rawline =~ /^\+\s* \t\s*\S/ ||
$rawline =~ /^\+\s* \s*/) {
my $herevet = "$here\n" . cat_vet($rawline) . "\n";
@@ -3217,7 +3274,7 @@ sub process {
"please, no space before tabs\n" . $herevet) &&
$fix) {
while ($fixed[$fixlinenr] =~
- s/(^\+.*) {8,8}\t/$1\t\t/) {}
+ s/(^\+.*) {$tabsize,$tabsize}\t/$1\t\t/) {}
while ($fixed[$fixlinenr] =~
s/(^\+.*) +\t/$1\t/) {}
}
@@ -3239,11 +3296,11 @@ sub process {
if ($perl_version_ok &&
$sline =~ /^\+\t+( +)(?:$c90_Keywords\b|\{\s*$|\}\s*(?:else\b|while\b|\s*$)|$Declare\s*$Ident\s*[;=])/) {
my $indent = length($1);
- if ($indent % 8) {
+ if ($indent % $tabsize) {
if (WARN("TABSTOP",
"Statements should start on a tabstop\n" . $herecurr) &&
$fix) {
- $fixed[$fixlinenr] =~ s@(^\+\t+) +@$1 . "\t" x ($indent/8)@e;
+ $fixed[$fixlinenr] =~ s@(^\+\t+) +@$1 . "\t" x ($indent/$tabsize)@e;
}
}
}
@@ -3261,8 +3318,8 @@ sub process {
my $newindent = $2;
my $goodtabindent = $oldindent .
- "\t" x ($pos / 8) .
- " " x ($pos % 8);
+ "\t" x ($pos / $tabsize) .
+ " " x ($pos % $tabsize);
my $goodspaceindent = $oldindent . " " x $pos;
if ($newindent ne $goodtabindent &&
@@ -3733,11 +3790,11 @@ sub process {
#print "line<$line> prevline<$prevline> indent<$indent> sindent<$sindent> check<$check> continuation<$continuation> s<$s> cond_lines<$cond_lines> stat_real<$stat_real> stat<$stat>\n";
if ($check && $s ne '' &&
- (($sindent % 8) != 0 ||
+ (($sindent % $tabsize) != 0 ||
($sindent < $indent) ||
($sindent == $indent &&
($s !~ /^\s*(?:\}|\{|else\b)/)) ||
- ($sindent > $indent + 8))) {
+ ($sindent > $indent + $tabsize))) {
WARN("SUSPECT_CODE_INDENT",
"suspect code indent for conditional statements ($indent, $sindent)\n" . $herecurr . "$stat_real\n");
}
@@ -4014,7 +4071,7 @@ sub process {
}
# check for function declarations without arguments like "int foo()"
- if ($line =~ /(\b$Type\s+$Ident)\s*\(\s*\)/) {
+ if ($line =~ /(\b$Type\s*$Ident)\s*\(\s*\)/) {
if (ERROR("FUNCTION_WITHOUT_ARGS",
"Bad function definition - $1() should probably be $1(void)\n" . $herecurr) &&
$fix) {
@@ -4582,7 +4639,7 @@ sub process {
($op eq '>' &&
$ca =~ /<\S+\@\S+$/))
{
- $ok = 1;
+ $ok = 1;
}
# for asm volatile statements
@@ -4917,7 +4974,7 @@ sub process {
# conditional.
substr($s, 0, length($c), '');
$s =~ s/\n.*//g;
- $s =~ s/$;//g; # Remove any comments
+ $s =~ s/$;//g; # Remove any comments
if (length($c) && $s !~ /^\s*{?\s*\\*\s*$/ &&
$c !~ /}\s*while\s*/)
{
@@ -4956,7 +5013,7 @@ sub process {
# if and else should not have general statements after it
if ($line =~ /^.\s*(?:}\s*)?else\b(.*)/) {
my $s = $1;
- $s =~ s/$;//g; # Remove any comments
+ $s =~ s/$;//g; # Remove any comments
if ($s !~ /^\s*(?:\sif|(?:{|)\s*\\?\s*$)/) {
ERROR("TRAILING_STATEMENTS",
"trailing statements should be on next line\n" . $herecurr);
@@ -5132,7 +5189,7 @@ sub process {
{
}
- # Flatten any obvious string concatentation.
+ # Flatten any obvious string concatenation.
while ($dstat =~ s/($String)\s*$Ident/$1/ ||
$dstat =~ s/$Ident\s*($String)/$1/)
{
@@ -6230,13 +6287,17 @@ sub process {
}
# check for function declarations that have arguments without identifier names
+# while avoiding uninitialized_var(x)
if (defined $stat &&
- $stat =~ /^.\s*(?:extern\s+)?$Type\s*(?:$Ident|\(\s*\*\s*$Ident\s*\))\s*\(\s*([^{]+)\s*\)\s*;/s &&
- $1 ne "void") {
- my $args = trim($1);
+ $stat =~ /^.\s*(?:extern\s+)?$Type\s*(?:($Ident)|\(\s*\*\s*$Ident\s*\))\s*\(\s*([^{]+)\s*\)\s*;/s &&
+ (!defined($1) ||
+ (defined($1) && $1 ne "uninitialized_var")) &&
+ $2 ne "void") {
+ my $args = trim($2);
while ($args =~ m/\s*($Type\s*(?:$Ident|\(\s*\*\s*$Ident?\s*\)\s*$balanced_parens)?)/g) {
my $arg = trim($1);
- if ($arg =~ /^$Type$/ && $arg !~ /enum\s+$Ident$/) {
+ if ($arg =~ /^$Type$/ &&
+ $arg !~ /enum\s+$Ident$/) {
WARN("FUNCTION_ARGUMENTS",
"function definition argument '$arg' should also have an identifier name\n" . $herecurr);
}
@@ -6389,6 +6450,28 @@ sub process {
}
}
+# check for /* fallthrough */ like comment, prefer fallthrough;
+ my @fallthroughs = (
+ 'fallthrough',
+ '@fallthrough@',
+ 'lint -fallthrough[ \t]*',
+ 'intentional(?:ly)?[ \t]*fall(?:(?:s | |-)[Tt]|t)hr(?:ough|u|ew)',
+ '(?:else,?\s*)?FALL(?:S | |-)?THR(?:OUGH|U|EW)[ \t.!]*(?:-[^\n\r]*)?',
+ 'Fall(?:(?:s | |-)[Tt]|t)hr(?:ough|u|ew)[ \t.!]*(?:-[^\n\r]*)?',
+ 'fall(?:s | |-)?thr(?:ough|u|ew)[ \t.!]*(?:-[^\n\r]*)?',
+ );
+ if ($raw_comment ne '') {
+ foreach my $ft (@fallthroughs) {
+ if ($raw_comment =~ /$ft/) {
+ my $msg_level = \&WARN;
+ $msg_level = \&CHK if ($file);
+ &{$msg_level}("PREFER_FALLTHROUGH",
+ "Prefer 'fallthrough;' over fallthrough comment\n" . $herecurr);
+ last;
+ }
+ }
+ }
+
# check for switch/default statements without a break;
if ($perl_version_ok &&
defined $stat &&
diff --git a/scripts/coccinelle/free/devm_free.cocci b/scripts/coccinelle/free/devm_free.cocci
index 441799b5359b..3357bf4dbd7c 100644
--- a/scripts/coccinelle/free/devm_free.cocci
+++ b/scripts/coccinelle/free/devm_free.cocci
@@ -52,8 +52,6 @@ expression x;
|
x = devm_ioremap(...)
|
- x = devm_ioremap_nocache(...)
-|
x = devm_ioport_map(...)
)
@@ -85,8 +83,6 @@ position p;
|
x = ioremap(...)
|
- x = ioremap_nocache(...)
-|
x = ioport_map(...)
)
...
@@ -95,8 +91,6 @@ position p;
|
kzfree@p(x)
|
- __krealloc@p(x, ...)
-|
krealloc@p(x, ...)
|
free_pages@p(x, ...)
@@ -120,8 +114,6 @@ position p != safe.p;
|
* kzfree@p(x)
|
-* __krealloc@p(x, ...)
-|
* krealloc@p(x, ...)
|
* free_pages@p(x, ...)
diff --git a/scripts/coccinelle/free/iounmap.cocci b/scripts/coccinelle/free/iounmap.cocci
index 0e60e1113a1d..63b81d0c97b6 100644
--- a/scripts/coccinelle/free/iounmap.cocci
+++ b/scripts/coccinelle/free/iounmap.cocci
@@ -23,7 +23,7 @@ int ret;
position p1,p2,p3;
@@
-e = \(ioremap@p1\|ioremap_nocache@p1\)(...)
+e = \(ioremap@p1\)(...)
... when != iounmap(e)
if (<+...e...+>) S
... when any
diff --git a/scripts/conmakehash.c b/scripts/conmakehash.c
deleted file mode 100644
index cddd789fe46e..000000000000
--- a/scripts/conmakehash.c
+++ /dev/null
@@ -1,290 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * conmakehash.c
- *
- * Create arrays for initializing the kernel folded tables (using a hash
- * table turned out to be to limiting...) Unfortunately we can't simply
- * preinitialize the tables at compile time since kfree() cannot accept
- * memory not allocated by kmalloc(), and doing our own memory management
- * just for this seems like massive overkill.
- *
- * Copyright (C) 1995-1997 H. Peter Anvin
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <sysexits.h>
-#include <string.h>
-#include <ctype.h>
-
-#define MAX_FONTLEN 256
-
-typedef unsigned short unicode;
-
-static void usage(char *argv0)
-{
- fprintf(stderr, "Usage: \n"
- " %s chartable [hashsize] [hashstep] [maxhashlevel]\n", argv0);
- exit(EX_USAGE);
-}
-
-static int getunicode(char **p0)
-{
- char *p = *p0;
-
- while (*p == ' ' || *p == '\t')
- p++;
- if (*p != 'U' || p[1] != '+' ||
- !isxdigit(p[2]) || !isxdigit(p[3]) || !isxdigit(p[4]) ||
- !isxdigit(p[5]) || isxdigit(p[6]))
- return -1;
- *p0 = p+6;
- return strtol(p+2,0,16);
-}
-
-unicode unitable[MAX_FONTLEN][255];
- /* Massive overkill, but who cares? */
-int unicount[MAX_FONTLEN];
-
-static void addpair(int fp, int un)
-{
- int i;
-
- if ( un <= 0xfffe )
- {
- /* Check it isn't a duplicate */
-
- for ( i = 0 ; i < unicount[fp] ; i++ )
- if ( unitable[fp][i] == un )
- return;
-
- /* Add to list */
-
- if ( unicount[fp] > 254 )
- {
- fprintf(stderr, "ERROR: Only 255 unicodes/glyph permitted!\n");
- exit(EX_DATAERR);
- }
-
- unitable[fp][unicount[fp]] = un;
- unicount[fp]++;
- }
-
- /* otherwise: ignore */
-}
-
-int main(int argc, char *argv[])
-{
- FILE *ctbl;
- char *tblname;
- char buffer[65536];
- int fontlen;
- int i, nuni, nent;
- int fp0, fp1, un0, un1;
- char *p, *p1;
-
- if ( argc < 2 || argc > 5 )
- usage(argv[0]);
-
- if ( !strcmp(argv[1],"-") )
- {
- ctbl = stdin;
- tblname = "stdin";
- }
- else
- {
- ctbl = fopen(tblname = argv[1], "r");
- if ( !ctbl )
- {
- perror(tblname);
- exit(EX_NOINPUT);
- }
- }
-
- /* For now we assume the default font is always 256 characters. */
- fontlen = 256;
-
- /* Initialize table */
-
- for ( i = 0 ; i < fontlen ; i++ )
- unicount[i] = 0;
-
- /* Now we come to the tricky part. Parse the input table. */
-
- while ( fgets(buffer, sizeof(buffer), ctbl) != NULL )
- {
- if ( (p = strchr(buffer, '\n')) != NULL )
- *p = '\0';
- else
- fprintf(stderr, "%s: Warning: line too long\n", tblname);
-
- p = buffer;
-
-/*
- * Syntax accepted:
- * <fontpos> <unicode> <unicode> ...
- * <range> idem
- * <range> <unicode range>
- *
- * where <range> ::= <fontpos>-<fontpos>
- * and <unicode> ::= U+<h><h><h><h>
- * and <h> ::= <hexadecimal digit>
- */
-
- while (*p == ' ' || *p == '\t')
- p++;
- if (!*p || *p == '#')
- continue; /* skip comment or blank line */
-
- fp0 = strtol(p, &p1, 0);
- if (p1 == p)
- {
- fprintf(stderr, "Bad input line: %s\n", buffer);
- exit(EX_DATAERR);
- }
- p = p1;
-
- while (*p == ' ' || *p == '\t')
- p++;
- if (*p == '-')
- {
- p++;
- fp1 = strtol(p, &p1, 0);
- if (p1 == p)
- {
- fprintf(stderr, "Bad input line: %s\n", buffer);
- exit(EX_DATAERR);
- }
- p = p1;
- }
- else
- fp1 = 0;
-
- if ( fp0 < 0 || fp0 >= fontlen )
- {
- fprintf(stderr,
- "%s: Glyph number (0x%x) larger than font length\n",
- tblname, fp0);
- exit(EX_DATAERR);
- }
- if ( fp1 && (fp1 < fp0 || fp1 >= fontlen) )
- {
- fprintf(stderr,
- "%s: Bad end of range (0x%x)\n",
- tblname, fp1);
- exit(EX_DATAERR);
- }
-
- if (fp1)
- {
- /* we have a range; expect the word "idem" or a Unicode range of the
- same length */
- while (*p == ' ' || *p == '\t')
- p++;
- if (!strncmp(p, "idem", 4))
- {
- for (i=fp0; i<=fp1; i++)
- addpair(i,i);
- p += 4;
- }
- else
- {
- un0 = getunicode(&p);
- while (*p == ' ' || *p == '\t')
- p++;
- if (*p != '-')
- {
- fprintf(stderr,
-"%s: Corresponding to a range of font positions, there should be a Unicode range\n",
- tblname);
- exit(EX_DATAERR);
- }
- p++;
- un1 = getunicode(&p);
- if (un0 < 0 || un1 < 0)
- {
- fprintf(stderr,
-"%s: Bad Unicode range corresponding to font position range 0x%x-0x%x\n",
- tblname, fp0, fp1);
- exit(EX_DATAERR);
- }
- if (un1 - un0 != fp1 - fp0)
- {
- fprintf(stderr,
-"%s: Unicode range U+%x-U+%x not of the same length as font position range 0x%x-0x%x\n",
- tblname, un0, un1, fp0, fp1);
- exit(EX_DATAERR);
- }
- for(i=fp0; i<=fp1; i++)
- addpair(i,un0-fp0+i);
- }
- }
- else
- {
- /* no range; expect a list of unicode values for a single font position */
-
- while ( (un0 = getunicode(&p)) >= 0 )
- addpair(fp0, un0);
- }
- while (*p == ' ' || *p == '\t')
- p++;
- if (*p && *p != '#')
- fprintf(stderr, "%s: trailing junk (%s) ignored\n", tblname, p);
- }
-
- /* Okay, we hit EOF, now output hash table */
-
- fclose(ctbl);
-
-
- /* Compute total size of Unicode list */
- nuni = 0;
- for ( i = 0 ; i < fontlen ; i++ )
- nuni += unicount[i];
-
- printf("\
-/*\n\
- * Do not edit this file; it was automatically generated by\n\
- *\n\
- * conmakehash %s > [this file]\n\
- *\n\
- */\n\
-\n\
-#include <linux/types.h>\n\
-\n\
-u8 dfont_unicount[%d] = \n\
-{\n\t", argv[1], fontlen);
-
- for ( i = 0 ; i < fontlen ; i++ )
- {
- printf("%3d", unicount[i]);
- if ( i == fontlen-1 )
- printf("\n};\n");
- else if ( i % 8 == 7 )
- printf(",\n\t");
- else
- printf(", ");
- }
-
- printf("\nu16 dfont_unitable[%d] = \n{\n\t", nuni);
-
- fp0 = 0;
- nent = 0;
- for ( i = 0 ; i < nuni ; i++ )
- {
- while ( nent >= unicount[fp0] )
- {
- fp0++;
- nent = 0;
- }
- printf("0x%04x", unitable[fp0][nent++]);
- if ( i == nuni-1 )
- printf("\n};\n");
- else if ( i % 8 == 7 )
- printf(",\n\t");
- else
- printf(", ");
- }
-
- exit(EX_OK);
-}
diff --git a/scripts/documentation-file-ref-check b/scripts/documentation-file-ref-check
index 7784c54aa38b..9a8cc10cffd0 100755
--- a/scripts/documentation-file-ref-check
+++ b/scripts/documentation-file-ref-check
@@ -12,7 +12,7 @@ use Getopt::Long qw(:config no_auto_abbrev);
# to mention a past documentation file, for example, to give credits for
# the original work.
my %false_positives = (
- "Documentation/scsi/scsi_mid_low_api.txt" => "Documentation/Configure.help",
+ "Documentation/scsi/scsi_mid_low_api.rst" => "Documentation/Configure.help",
"drivers/vhost/vhost.c" => "Documentation/virtual/lguest/lguest.c",
);
@@ -51,7 +51,9 @@ open IN, "git grep ':doc:\`' Documentation/|"
or die "Failed to run git grep";
while (<IN>) {
next if (!m,^([^:]+):.*\:doc\:\`([^\`]+)\`,);
+ next if (m,sphinx/,);
+ my $file = $1;
my $d = $1;
my $doc_ref = $2;
@@ -60,7 +62,12 @@ while (<IN>) {
$d =~ s,(.*/).*,$1,;
$f =~ s,.*\<([^\>]+)\>,$1,;
- $f ="$d$f.rst";
+ if ($f =~ m,^/,) {
+ $f = "$f.rst";
+ $f =~ s,^/,Documentation/,;
+ } else {
+ $f = "$d$f.rst";
+ }
next if (grep -e, glob("$f"));
@@ -69,7 +76,7 @@ while (<IN>) {
}
$doc_fix++;
- print STDERR "$f: :doc:`$doc_ref`\n";
+ print STDERR "$file: :doc:`$doc_ref`\n";
}
close IN;
diff --git a/scripts/dtc/.gitignore b/scripts/dtc/.gitignore
index 2e6e60d64ede..b814e6076bdb 100644
--- a/scripts/dtc/.gitignore
+++ b/scripts/dtc/.gitignore
@@ -1 +1,2 @@
+# SPDX-License-Identifier: GPL-2.0-only
dtc
diff --git a/scripts/dtc/Makefile b/scripts/dtc/Makefile
index b5a5b1c548c9..2f3c3a7e1620 100644
--- a/scripts/dtc/Makefile
+++ b/scripts/dtc/Makefile
@@ -1,8 +1,9 @@
# SPDX-License-Identifier: GPL-2.0
# scripts/dtc makefile
-hostprogs-$(CONFIG_DTC) := dtc
-always := $(hostprogs-y)
+hostprogs := dtc
+always-$(CONFIG_DTC) += $(hostprogs)
+always-$(CHECK_DT_BINDING) += $(hostprogs)
dtc-objs := dtc.o flattree.o fstree.o data.o livetree.o treesource.o \
srcpos.o checks.o util.o
diff --git a/scripts/dtc/Makefile.dtc b/scripts/dtc/Makefile.dtc
deleted file mode 100644
index 9c467b096f03..000000000000
--- a/scripts/dtc/Makefile.dtc
+++ /dev/null
@@ -1,23 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0-or-later
-# Makefile.dtc
-#
-# This is not a complete Makefile of itself. Instead, it is designed to
-# be easily embeddable into other systems of Makefiles.
-#
-DTC_SRCS = \
- checks.c \
- data.c \
- dtc.c \
- flattree.c \
- fstree.c \
- livetree.c \
- srcpos.c \
- treesource.c \
- util.c
-
-ifneq ($(NO_YAML),1)
-DTC_SRCS += yamltree.c
-endif
-
-DTC_GEN_SRCS = dtc-lexer.lex.c dtc-parser.tab.c
-DTC_OBJS = $(DTC_SRCS:%.c=%.o) $(DTC_GEN_SRCS:%.c=%.o)
diff --git a/scripts/dtc/checks.c b/scripts/dtc/checks.c
index d7986ee18012..4b3c486f1399 100644
--- a/scripts/dtc/checks.c
+++ b/scripts/dtc/checks.c
@@ -352,7 +352,7 @@ static void check_unit_address_vs_reg(struct check *c, struct dt_info *dti,
FAIL(c, dti, node, "node has a reg or ranges property, but no unit name");
} else {
if (unitname[0])
- FAIL(c, dti, node, "node has a unit name, but no reg property");
+ FAIL(c, dti, node, "node has a unit name, but no reg or ranges property");
}
}
WARNING(unit_address_vs_reg, check_unit_address_vs_reg, NULL);
@@ -691,6 +691,11 @@ static void check_alias_paths(struct check *c, struct dt_info *dti,
return;
for_each_property(node, prop) {
+ if (streq(prop->name, "phandle")
+ || streq(prop->name, "linux,phandle")) {
+ continue;
+ }
+
if (!prop->val.val || !get_node_by_path(dti->dt, prop->val.val)) {
FAIL_PROP(c, dti, node, prop, "aliases property is not a valid node (%s)",
prop->val.val);
@@ -760,13 +765,15 @@ static void check_ranges_format(struct check *c, struct dt_info *dti,
{
struct property *prop;
int c_addr_cells, p_addr_cells, c_size_cells, p_size_cells, entrylen;
+ const char *ranges = c->data;
- prop = get_property(node, "ranges");
+ prop = get_property(node, ranges);
if (!prop)
return;
if (!node->parent) {
- FAIL_PROP(c, dti, node, prop, "Root node has a \"ranges\" property");
+ FAIL_PROP(c, dti, node, prop, "Root node has a \"%s\" property",
+ ranges);
return;
}
@@ -778,23 +785,24 @@ static void check_ranges_format(struct check *c, struct dt_info *dti,
if (prop->val.len == 0) {
if (p_addr_cells != c_addr_cells)
- FAIL_PROP(c, dti, node, prop, "empty \"ranges\" property but its "
+ FAIL_PROP(c, dti, node, prop, "empty \"%s\" property but its "
"#address-cells (%d) differs from %s (%d)",
- c_addr_cells, node->parent->fullpath,
+ ranges, c_addr_cells, node->parent->fullpath,
p_addr_cells);
if (p_size_cells != c_size_cells)
- FAIL_PROP(c, dti, node, prop, "empty \"ranges\" property but its "
+ FAIL_PROP(c, dti, node, prop, "empty \"%s\" property but its "
"#size-cells (%d) differs from %s (%d)",
- c_size_cells, node->parent->fullpath,
+ ranges, c_size_cells, node->parent->fullpath,
p_size_cells);
} else if ((prop->val.len % entrylen) != 0) {
- FAIL_PROP(c, dti, node, prop, "\"ranges\" property has invalid length (%d bytes) "
+ FAIL_PROP(c, dti, node, prop, "\"%s\" property has invalid length (%d bytes) "
"(parent #address-cells == %d, child #address-cells == %d, "
- "#size-cells == %d)", prop->val.len,
+ "#size-cells == %d)", ranges, prop->val.len,
p_addr_cells, c_addr_cells, c_size_cells);
}
}
-WARNING(ranges_format, check_ranges_format, NULL, &addr_size_cells);
+WARNING(ranges_format, check_ranges_format, "ranges", &addr_size_cells);
+WARNING(dma_ranges_format, check_ranges_format, "dma-ranges", &addr_size_cells);
static const struct bus_type pci_bus = {
.name = "PCI",
@@ -1775,7 +1783,7 @@ static struct check *check_table[] = {
&property_name_chars_strict,
&node_name_chars_strict,
- &addr_size_cells, &reg_format, &ranges_format,
+ &addr_size_cells, &reg_format, &ranges_format, &dma_ranges_format,
&unit_address_vs_reg,
&unit_address_format,
diff --git a/scripts/dtc/dtc-lexer.l b/scripts/dtc/dtc-lexer.l
index 5c6c3fd557d7..b3b7270300de 100644
--- a/scripts/dtc/dtc-lexer.l
+++ b/scripts/dtc/dtc-lexer.l
@@ -23,7 +23,6 @@ LINECOMMENT "//".*\n
#include "srcpos.h"
#include "dtc-parser.tab.h"
-YYLTYPE yylloc;
extern bool treesource_error;
/* CAUTION: this will stop working if we ever use yyless() or yyunput() */
diff --git a/scripts/dtc/dtc-parser.y b/scripts/dtc/dtc-parser.y
index 2ed4dc1f07fd..40dcf4f149da 100644
--- a/scripts/dtc/dtc-parser.y
+++ b/scripts/dtc/dtc-parser.y
@@ -2,6 +2,8 @@
/*
* (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation. 2005.
*/
+%locations
+
%{
#include <stdio.h>
#include <inttypes.h>
@@ -17,6 +19,8 @@ extern void yyerror(char const *s);
treesource_error = true; \
} while (0)
+#define YYERROR_CALL(msg) yyerror(msg)
+
extern struct dt_info *parser_output;
extern bool treesource_error;
%}
diff --git a/scripts/dtc/fstree.c b/scripts/dtc/fstree.c
index 9871689b4afb..5e59594ab301 100644
--- a/scripts/dtc/fstree.c
+++ b/scripts/dtc/fstree.c
@@ -30,7 +30,7 @@ static struct node *read_fstree(const char *dirname)
tmpname = join_path(dirname, de->d_name);
- if (lstat(tmpname, &st) < 0)
+ if (stat(tmpname, &st) < 0)
die("stat(%s): %s\n", tmpname, strerror(errno));
if (S_ISREG(st.st_mode)) {
diff --git a/scripts/dtc/libfdt/Makefile.libfdt b/scripts/dtc/libfdt/Makefile.libfdt
deleted file mode 100644
index e54639738c8e..000000000000
--- a/scripts/dtc/libfdt/Makefile.libfdt
+++ /dev/null
@@ -1,18 +0,0 @@
-# SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
-# Makefile.libfdt
-#
-# This is not a complete Makefile of itself. Instead, it is designed to
-# be easily embeddable into other systems of Makefiles.
-#
-LIBFDT_soname = libfdt.$(SHAREDLIB_EXT).1
-LIBFDT_INCLUDES = fdt.h libfdt.h libfdt_env.h
-LIBFDT_VERSION = version.lds
-LIBFDT_SRCS = fdt.c fdt_ro.c fdt_wip.c fdt_sw.c fdt_rw.c fdt_strerror.c fdt_empty_tree.c \
- fdt_addresses.c fdt_overlay.c
-LIBFDT_OBJS = $(LIBFDT_SRCS:%.c=%.o)
-LIBFDT_LIB = libfdt-$(DTC_VERSION).$(SHAREDLIB_EXT)
-
-libfdt_clean:
- @$(VECHO) CLEAN "(libfdt)"
- rm -f $(STD_CLEANFILES:%=$(LIBFDT_dir)/%)
- rm -f $(LIBFDT_dir)/$(LIBFDT_soname)
diff --git a/scripts/dtc/libfdt/fdt.c b/scripts/dtc/libfdt/fdt.c
index 179168ec63e9..c28fcc115771 100644
--- a/scripts/dtc/libfdt/fdt.c
+++ b/scripts/dtc/libfdt/fdt.c
@@ -15,23 +15,34 @@
* that the given buffer contains what appears to be a flattened
* device tree with sane information in its header.
*/
-int fdt_ro_probe_(const void *fdt)
+int32_t fdt_ro_probe_(const void *fdt)
{
+ uint32_t totalsize = fdt_totalsize(fdt);
+
+ if (can_assume(VALID_DTB))
+ return totalsize;
+
if (fdt_magic(fdt) == FDT_MAGIC) {
/* Complete tree */
- if (fdt_version(fdt) < FDT_FIRST_SUPPORTED_VERSION)
- return -FDT_ERR_BADVERSION;
- if (fdt_last_comp_version(fdt) > FDT_LAST_SUPPORTED_VERSION)
- return -FDT_ERR_BADVERSION;
+ if (!can_assume(LATEST)) {
+ if (fdt_version(fdt) < FDT_FIRST_SUPPORTED_VERSION)
+ return -FDT_ERR_BADVERSION;
+ if (fdt_last_comp_version(fdt) >
+ FDT_LAST_SUPPORTED_VERSION)
+ return -FDT_ERR_BADVERSION;
+ }
} else if (fdt_magic(fdt) == FDT_SW_MAGIC) {
/* Unfinished sequential-write blob */
- if (fdt_size_dt_struct(fdt) == 0)
+ if (!can_assume(VALID_INPUT) && fdt_size_dt_struct(fdt) == 0)
return -FDT_ERR_BADSTATE;
} else {
return -FDT_ERR_BADMAGIC;
}
- return 0;
+ if (totalsize < INT32_MAX)
+ return totalsize;
+ else
+ return -FDT_ERR_TRUNCATED;
}
static int check_off_(uint32_t hdrsize, uint32_t totalsize, uint32_t off)
@@ -65,44 +76,59 @@ size_t fdt_header_size_(uint32_t version)
return FDT_V17_SIZE;
}
+size_t fdt_header_size(const void *fdt)
+{
+ return can_assume(LATEST) ? FDT_V17_SIZE :
+ fdt_header_size_(fdt_version(fdt));
+}
+
int fdt_check_header(const void *fdt)
{
size_t hdrsize;
if (fdt_magic(fdt) != FDT_MAGIC)
return -FDT_ERR_BADMAGIC;
+ if (!can_assume(LATEST)) {
+ if ((fdt_version(fdt) < FDT_FIRST_SUPPORTED_VERSION)
+ || (fdt_last_comp_version(fdt) >
+ FDT_LAST_SUPPORTED_VERSION))
+ return -FDT_ERR_BADVERSION;
+ if (fdt_version(fdt) < fdt_last_comp_version(fdt))
+ return -FDT_ERR_BADVERSION;
+ }
hdrsize = fdt_header_size(fdt);
- if ((fdt_version(fdt) < FDT_FIRST_SUPPORTED_VERSION)
- || (fdt_last_comp_version(fdt) > FDT_LAST_SUPPORTED_VERSION))
- return -FDT_ERR_BADVERSION;
- if (fdt_version(fdt) < fdt_last_comp_version(fdt))
- return -FDT_ERR_BADVERSION;
-
- if ((fdt_totalsize(fdt) < hdrsize)
- || (fdt_totalsize(fdt) > INT_MAX))
- return -FDT_ERR_TRUNCATED;
+ if (!can_assume(VALID_DTB)) {
- /* Bounds check memrsv block */
- if (!check_off_(hdrsize, fdt_totalsize(fdt), fdt_off_mem_rsvmap(fdt)))
- return -FDT_ERR_TRUNCATED;
+ if ((fdt_totalsize(fdt) < hdrsize)
+ || (fdt_totalsize(fdt) > INT_MAX))
+ return -FDT_ERR_TRUNCATED;
- /* Bounds check structure block */
- if (fdt_version(fdt) < 17) {
+ /* Bounds check memrsv block */
if (!check_off_(hdrsize, fdt_totalsize(fdt),
- fdt_off_dt_struct(fdt)))
+ fdt_off_mem_rsvmap(fdt)))
return -FDT_ERR_TRUNCATED;
- } else {
+ }
+
+ if (!can_assume(VALID_DTB)) {
+ /* Bounds check structure block */
+ if (!can_assume(LATEST) && fdt_version(fdt) < 17) {
+ if (!check_off_(hdrsize, fdt_totalsize(fdt),
+ fdt_off_dt_struct(fdt)))
+ return -FDT_ERR_TRUNCATED;
+ } else {
+ if (!check_block_(hdrsize, fdt_totalsize(fdt),
+ fdt_off_dt_struct(fdt),
+ fdt_size_dt_struct(fdt)))
+ return -FDT_ERR_TRUNCATED;
+ }
+
+ /* Bounds check strings block */
if (!check_block_(hdrsize, fdt_totalsize(fdt),
- fdt_off_dt_struct(fdt),
- fdt_size_dt_struct(fdt)))
+ fdt_off_dt_strings(fdt),
+ fdt_size_dt_strings(fdt)))
return -FDT_ERR_TRUNCATED;
}
- /* Bounds check strings block */
- if (!check_block_(hdrsize, fdt_totalsize(fdt),
- fdt_off_dt_strings(fdt), fdt_size_dt_strings(fdt)))
- return -FDT_ERR_TRUNCATED;
-
return 0;
}
@@ -110,12 +136,13 @@ const void *fdt_offset_ptr(const void *fdt, int offset, unsigned int len)
{
unsigned absoffset = offset + fdt_off_dt_struct(fdt);
- if ((absoffset < offset)
- || ((absoffset + len) < absoffset)
- || (absoffset + len) > fdt_totalsize(fdt))
- return NULL;
+ if (!can_assume(VALID_INPUT))
+ if ((absoffset < offset)
+ || ((absoffset + len) < absoffset)
+ || (absoffset + len) > fdt_totalsize(fdt))
+ return NULL;
- if (fdt_version(fdt) >= 0x11)
+ if (can_assume(LATEST) || fdt_version(fdt) >= 0x11)
if (((offset + len) < offset)
|| ((offset + len) > fdt_size_dt_struct(fdt)))
return NULL;
@@ -132,7 +159,7 @@ uint32_t fdt_next_tag(const void *fdt, int startoffset, int *nextoffset)
*nextoffset = -FDT_ERR_TRUNCATED;
tagp = fdt_offset_ptr(fdt, offset, FDT_TAGSIZE);
- if (!tagp)
+ if (!can_assume(VALID_DTB) && !tagp)
return FDT_END; /* premature end */
tag = fdt32_to_cpu(*tagp);
offset += FDT_TAGSIZE;
@@ -144,18 +171,19 @@ uint32_t fdt_next_tag(const void *fdt, int startoffset, int *nextoffset)
do {
p = fdt_offset_ptr(fdt, offset++, 1);
} while (p && (*p != '\0'));
- if (!p)
+ if (!can_assume(VALID_DTB) && !p)
return FDT_END; /* premature end */
break;
case FDT_PROP:
lenp = fdt_offset_ptr(fdt, offset, sizeof(*lenp));
- if (!lenp)
+ if (!can_assume(VALID_DTB) && !lenp)
return FDT_END; /* premature end */
/* skip-name offset, length and value */
offset += sizeof(struct fdt_property) - FDT_TAGSIZE
+ fdt32_to_cpu(*lenp);
- if (fdt_version(fdt) < 0x10 && fdt32_to_cpu(*lenp) >= 8 &&
+ if (!can_assume(LATEST) &&
+ fdt_version(fdt) < 0x10 && fdt32_to_cpu(*lenp) >= 8 &&
((offset - fdt32_to_cpu(*lenp)) % 8) != 0)
offset += 4;
break;
@@ -178,6 +206,8 @@ uint32_t fdt_next_tag(const void *fdt, int startoffset, int *nextoffset)
int fdt_check_node_offset_(const void *fdt, int offset)
{
+ if (can_assume(VALID_INPUT))
+ return offset;
if ((offset < 0) || (offset % FDT_TAGSIZE)
|| (fdt_next_tag(fdt, offset, &offset) != FDT_BEGIN_NODE))
return -FDT_ERR_BADOFFSET;
diff --git a/scripts/dtc/libfdt/fdt_addresses.c b/scripts/dtc/libfdt/fdt_addresses.c
index d8ba8ec60c6c..9a82cd0ba2f9 100644
--- a/scripts/dtc/libfdt/fdt_addresses.c
+++ b/scripts/dtc/libfdt/fdt_addresses.c
@@ -14,7 +14,7 @@
static int fdt_cells(const void *fdt, int nodeoffset, const char *name)
{
const fdt32_t *c;
- int val;
+ uint32_t val;
int len;
c = fdt_getprop(fdt, nodeoffset, name, &len);
@@ -25,10 +25,10 @@ static int fdt_cells(const void *fdt, int nodeoffset, const char *name)
return -FDT_ERR_BADNCELLS;
val = fdt32_to_cpu(*c);
- if ((val <= 0) || (val > FDT_MAX_NCELLS))
+ if (val > FDT_MAX_NCELLS)
return -FDT_ERR_BADNCELLS;
- return val;
+ return (int)val;
}
int fdt_address_cells(const void *fdt, int nodeoffset)
@@ -36,6 +36,8 @@ int fdt_address_cells(const void *fdt, int nodeoffset)
int val;
val = fdt_cells(fdt, nodeoffset, "#address-cells");
+ if (val == 0)
+ return -FDT_ERR_BADNCELLS;
if (val == -FDT_ERR_NOTFOUND)
return 2;
return val;
diff --git a/scripts/dtc/libfdt/fdt_overlay.c b/scripts/dtc/libfdt/fdt_overlay.c
index e97f12b1a780..b310e49a698e 100644
--- a/scripts/dtc/libfdt/fdt_overlay.c
+++ b/scripts/dtc/libfdt/fdt_overlay.c
@@ -733,26 +733,36 @@ static int overlay_symbol_update(void *fdt, void *fdto)
/* keep end marker to avoid strlen() */
e = path + path_len;
- /* format: /<fragment-name>/__overlay__/<relative-subnode-path> */
-
if (*path != '/')
return -FDT_ERR_BADVALUE;
/* get fragment name first */
s = strchr(path + 1, '/');
- if (!s)
- return -FDT_ERR_BADOVERLAY;
+ if (!s) {
+ /* Symbol refers to something that won't end
+ * up in the target tree */
+ continue;
+ }
frag_name = path + 1;
frag_name_len = s - path - 1;
/* verify format; safe since "s" lies in \0 terminated prop */
len = sizeof("/__overlay__/") - 1;
- if ((e - s) < len || memcmp(s, "/__overlay__/", len))
- return -FDT_ERR_BADOVERLAY;
-
- rel_path = s + len;
- rel_path_len = e - rel_path;
+ if ((e - s) > len && (memcmp(s, "/__overlay__/", len) == 0)) {
+ /* /<fragment-name>/__overlay__/<relative-subnode-path> */
+ rel_path = s + len;
+ rel_path_len = e - rel_path - 1;
+ } else if ((e - s) == len
+ && (memcmp(s, "/__overlay__", len - 1) == 0)) {
+ /* /<fragment-name>/__overlay__ */
+ rel_path = "";
+ rel_path_len = 0;
+ } else {
+ /* Symbol refers to something that won't end
+ * up in the target tree */
+ continue;
+ }
/* find the fragment index in which the symbol lies */
ret = fdt_subnode_offset_namelen(fdto, 0, frag_name,
diff --git a/scripts/dtc/libfdt/fdt_ro.c b/scripts/dtc/libfdt/fdt_ro.c
index 6fd9ec170dbe..e03570a56eb5 100644
--- a/scripts/dtc/libfdt/fdt_ro.c
+++ b/scripts/dtc/libfdt/fdt_ro.c
@@ -33,24 +33,34 @@ static int fdt_nodename_eq_(const void *fdt, int offset,
const char *fdt_get_string(const void *fdt, int stroffset, int *lenp)
{
- uint32_t absoffset = stroffset + fdt_off_dt_strings(fdt);
+ int32_t totalsize;
+ uint32_t absoffset;
size_t len;
int err;
const char *s, *n;
- err = fdt_ro_probe_(fdt);
- if (err != 0)
+ if (can_assume(VALID_INPUT)) {
+ s = (const char *)fdt + fdt_off_dt_strings(fdt) + stroffset;
+
+ if (lenp)
+ *lenp = strlen(s);
+ return s;
+ }
+ totalsize = fdt_ro_probe_(fdt);
+ err = totalsize;
+ if (totalsize < 0)
goto fail;
err = -FDT_ERR_BADOFFSET;
- if (absoffset >= fdt_totalsize(fdt))
+ absoffset = stroffset + fdt_off_dt_strings(fdt);
+ if (absoffset >= totalsize)
goto fail;
- len = fdt_totalsize(fdt) - absoffset;
+ len = totalsize - absoffset;
if (fdt_magic(fdt) == FDT_MAGIC) {
if (stroffset < 0)
goto fail;
- if (fdt_version(fdt) >= 17) {
+ if (can_assume(LATEST) || fdt_version(fdt) >= 17) {
if (stroffset >= fdt_size_dt_strings(fdt))
goto fail;
if ((fdt_size_dt_strings(fdt) - stroffset) < len)
@@ -150,10 +160,13 @@ static const struct fdt_reserve_entry *fdt_mem_rsv(const void *fdt, int n)
int offset = n * sizeof(struct fdt_reserve_entry);
int absoffset = fdt_off_mem_rsvmap(fdt) + offset;
- if (absoffset < fdt_off_mem_rsvmap(fdt))
- return NULL;
- if (absoffset > fdt_totalsize(fdt) - sizeof(struct fdt_reserve_entry))
- return NULL;
+ if (!can_assume(VALID_INPUT)) {
+ if (absoffset < fdt_off_mem_rsvmap(fdt))
+ return NULL;
+ if (absoffset > fdt_totalsize(fdt) -
+ sizeof(struct fdt_reserve_entry))
+ return NULL;
+ }
return fdt_mem_rsv_(fdt, n);
}
@@ -163,7 +176,7 @@ int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size)
FDT_RO_PROBE(fdt);
re = fdt_mem_rsv(fdt, n);
- if (!re)
+ if (!can_assume(VALID_INPUT) && !re)
return -FDT_ERR_BADOFFSET;
*address = fdt64_ld(&re->address);
@@ -288,13 +301,13 @@ const char *fdt_get_name(const void *fdt, int nodeoffset, int *len)
const char *nameptr;
int err;
- if (((err = fdt_ro_probe_(fdt)) != 0)
+ if (((err = fdt_ro_probe_(fdt)) < 0)
|| ((err = fdt_check_node_offset_(fdt, nodeoffset)) < 0))
goto fail;
nameptr = nh->name;
- if (fdt_version(fdt) < 0x10) {
+ if (!can_assume(LATEST) && fdt_version(fdt) < 0x10) {
/*
* For old FDT versions, match the naming conventions of V16:
* give only the leaf name (after all /). The actual tree
@@ -345,7 +358,8 @@ static const struct fdt_property *fdt_get_property_by_offset_(const void *fdt,
int err;
const struct fdt_property *prop;
- if ((err = fdt_check_prop_offset_(fdt, offset)) < 0) {
+ if (!can_assume(VALID_INPUT) &&
+ (err = fdt_check_prop_offset_(fdt, offset)) < 0) {
if (lenp)
*lenp = err;
return NULL;
@@ -366,7 +380,7 @@ const struct fdt_property *fdt_get_property_by_offset(const void *fdt,
/* Prior to version 16, properties may need realignment
* and this API does not work. fdt_getprop_*() will, however. */
- if (fdt_version(fdt) < 0x10) {
+ if (!can_assume(LATEST) && fdt_version(fdt) < 0x10) {
if (lenp)
*lenp = -FDT_ERR_BADVERSION;
return NULL;
@@ -387,7 +401,8 @@ static const struct fdt_property *fdt_get_property_namelen_(const void *fdt,
(offset = fdt_next_property_offset(fdt, offset))) {
const struct fdt_property *prop;
- if (!(prop = fdt_get_property_by_offset_(fdt, offset, lenp))) {
+ prop = fdt_get_property_by_offset_(fdt, offset, lenp);
+ if (!can_assume(LIBFDT_FLAWLESS) && !prop) {
offset = -FDT_ERR_INTERNAL;
break;
}
@@ -412,7 +427,7 @@ const struct fdt_property *fdt_get_property_namelen(const void *fdt,
{
/* Prior to version 16, properties may need realignment
* and this API does not work. fdt_getprop_*() will, however. */
- if (fdt_version(fdt) < 0x10) {
+ if (!can_assume(LATEST) && fdt_version(fdt) < 0x10) {
if (lenp)
*lenp = -FDT_ERR_BADVERSION;
return NULL;
@@ -443,8 +458,8 @@ const void *fdt_getprop_namelen(const void *fdt, int nodeoffset,
return NULL;
/* Handle realignment */
- if (fdt_version(fdt) < 0x10 && (poffset + sizeof(*prop)) % 8 &&
- fdt32_ld(&prop->len) >= 8)
+ if (!can_assume(LATEST) && fdt_version(fdt) < 0x10 &&
+ (poffset + sizeof(*prop)) % 8 && fdt32_ld(&prop->len) >= 8)
return prop->data + 4;
return prop->data;
}
@@ -460,19 +475,24 @@ const void *fdt_getprop_by_offset(const void *fdt, int offset,
if (namep) {
const char *name;
int namelen;
- name = fdt_get_string(fdt, fdt32_ld(&prop->nameoff),
- &namelen);
- if (!name) {
- if (lenp)
- *lenp = namelen;
- return NULL;
+
+ if (!can_assume(VALID_INPUT)) {
+ name = fdt_get_string(fdt, fdt32_ld(&prop->nameoff),
+ &namelen);
+ if (!name) {
+ if (lenp)
+ *lenp = namelen;
+ return NULL;
+ }
+ *namep = name;
+ } else {
+ *namep = fdt_string(fdt, fdt32_ld(&prop->nameoff));
}
- *namep = name;
}
/* Handle realignment */
- if (fdt_version(fdt) < 0x10 && (offset + sizeof(*prop)) % 8 &&
- fdt32_ld(&prop->len) >= 8)
+ if (!can_assume(LATEST) && fdt_version(fdt) < 0x10 &&
+ (offset + sizeof(*prop)) % 8 && fdt32_ld(&prop->len) >= 8)
return prop->data + 4;
return prop->data;
}
@@ -597,10 +617,12 @@ int fdt_supernode_atdepth_offset(const void *fdt, int nodeoffset,
}
}
- if ((offset == -FDT_ERR_NOTFOUND) || (offset >= 0))
- return -FDT_ERR_BADOFFSET;
- else if (offset == -FDT_ERR_BADOFFSET)
- return -FDT_ERR_BADSTRUCTURE;
+ if (!can_assume(VALID_INPUT)) {
+ if ((offset == -FDT_ERR_NOTFOUND) || (offset >= 0))
+ return -FDT_ERR_BADOFFSET;
+ else if (offset == -FDT_ERR_BADOFFSET)
+ return -FDT_ERR_BADSTRUCTURE;
+ }
return offset; /* error from fdt_next_node() */
}
@@ -612,7 +634,8 @@ int fdt_node_depth(const void *fdt, int nodeoffset)
err = fdt_supernode_atdepth_offset(fdt, nodeoffset, 0, &nodedepth);
if (err)
- return (err < 0) ? err : -FDT_ERR_INTERNAL;
+ return (can_assume(LIBFDT_FLAWLESS) || err < 0) ? err :
+ -FDT_ERR_INTERNAL;
return nodedepth;
}
@@ -832,66 +855,3 @@ int fdt_node_offset_by_compatible(const void *fdt, int startoffset,
return offset; /* error from fdt_next_node() */
}
-
-int fdt_check_full(const void *fdt, size_t bufsize)
-{
- int err;
- int num_memrsv;
- int offset, nextoffset = 0;
- uint32_t tag;
- unsigned depth = 0;
- const void *prop;
- const char *propname;
-
- if (bufsize < FDT_V1_SIZE)
- return -FDT_ERR_TRUNCATED;
- err = fdt_check_header(fdt);
- if (err != 0)
- return err;
- if (bufsize < fdt_totalsize(fdt))
- return -FDT_ERR_TRUNCATED;
-
- num_memrsv = fdt_num_mem_rsv(fdt);
- if (num_memrsv < 0)
- return num_memrsv;
-
- while (1) {
- offset = nextoffset;
- tag = fdt_next_tag(fdt, offset, &nextoffset);
-
- if (nextoffset < 0)
- return nextoffset;
-
- switch (tag) {
- case FDT_NOP:
- break;
-
- case FDT_END:
- if (depth != 0)
- return -FDT_ERR_BADSTRUCTURE;
- return 0;
-
- case FDT_BEGIN_NODE:
- depth++;
- if (depth > INT_MAX)
- return -FDT_ERR_BADSTRUCTURE;
- break;
-
- case FDT_END_NODE:
- if (depth == 0)
- return -FDT_ERR_BADSTRUCTURE;
- depth--;
- break;
-
- case FDT_PROP:
- prop = fdt_getprop_by_offset(fdt, offset, &propname,
- &err);
- if (!prop)
- return err;
- break;
-
- default:
- return -FDT_ERR_INTERNAL;
- }
- }
-}
diff --git a/scripts/dtc/libfdt/fdt_rw.c b/scripts/dtc/libfdt/fdt_rw.c
index 8795947c00dd..524b520c8486 100644
--- a/scripts/dtc/libfdt/fdt_rw.c
+++ b/scripts/dtc/libfdt/fdt_rw.c
@@ -24,14 +24,16 @@ static int fdt_blocks_misordered_(const void *fdt,
static int fdt_rw_probe_(void *fdt)
{
+ if (can_assume(VALID_DTB))
+ return 0;
FDT_RO_PROBE(fdt);
- if (fdt_version(fdt) < 17)
+ if (!can_assume(LATEST) && fdt_version(fdt) < 17)
return -FDT_ERR_BADVERSION;
if (fdt_blocks_misordered_(fdt, sizeof(struct fdt_reserve_entry),
fdt_size_dt_struct(fdt)))
return -FDT_ERR_BADLAYOUT;
- if (fdt_version(fdt) > 17)
+ if (!can_assume(LATEST) && fdt_version(fdt) > 17)
fdt_set_version(fdt, 17);
return 0;
@@ -44,7 +46,7 @@ static int fdt_rw_probe_(void *fdt)
return err_; \
}
-static inline int fdt_data_size_(void *fdt)
+static inline unsigned int fdt_data_size_(void *fdt)
{
return fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt);
}
@@ -52,15 +54,16 @@ static inline int fdt_data_size_(void *fdt)
static int fdt_splice_(void *fdt, void *splicepoint, int oldlen, int newlen)
{
char *p = splicepoint;
- char *end = (char *)fdt + fdt_data_size_(fdt);
+ unsigned int dsize = fdt_data_size_(fdt);
+ size_t soff = p - (char *)fdt;
- if (((p + oldlen) < p) || ((p + oldlen) > end))
+ if ((oldlen < 0) || (soff + oldlen < soff) || (soff + oldlen > dsize))
return -FDT_ERR_BADOFFSET;
- if ((p < (char *)fdt) || ((end - oldlen + newlen) < (char *)fdt))
+ if ((p < (char *)fdt) || (dsize + newlen < oldlen))
return -FDT_ERR_BADOFFSET;
- if ((end - oldlen + newlen) > ((char *)fdt + fdt_totalsize(fdt)))
+ if (dsize - oldlen + newlen > fdt_totalsize(fdt))
return -FDT_ERR_NOSPACE;
- memmove(p + newlen, p + oldlen, end - p - oldlen);
+ memmove(p + newlen, p + oldlen, ((char *)fdt + dsize) - (p + oldlen));
return 0;
}
@@ -112,6 +115,15 @@ static int fdt_splice_string_(void *fdt, int newlen)
return 0;
}
+/**
+ * fdt_find_add_string_() - Find or allocate a string
+ *
+ * @fdt: pointer to the device tree to check/adjust
+ * @s: string to find/add
+ * @allocated: Set to 0 if the string was found, 1 if not found and so
+ * allocated. Ignored if can_assume(NO_ROLLBACK)
+ * @return offset of string in the string table (whether found or added)
+ */
static int fdt_find_add_string_(void *fdt, const char *s, int *allocated)
{
char *strtab = (char *)fdt + fdt_off_dt_strings(fdt);
@@ -120,7 +132,8 @@ static int fdt_find_add_string_(void *fdt, const char *s, int *allocated)
int len = strlen(s) + 1;
int err;
- *allocated = 0;
+ if (!can_assume(NO_ROLLBACK))
+ *allocated = 0;
p = fdt_find_string_(strtab, fdt_size_dt_strings(fdt), s);
if (p)
@@ -132,7 +145,8 @@ static int fdt_find_add_string_(void *fdt, const char *s, int *allocated)
if (err)
return err;
- *allocated = 1;
+ if (!can_assume(NO_ROLLBACK))
+ *allocated = 1;
memcpy(new, s, len);
return (new - strtab);
@@ -206,7 +220,8 @@ static int fdt_add_property_(void *fdt, int nodeoffset, const char *name,
err = fdt_splice_struct_(fdt, *prop, 0, proplen);
if (err) {
- if (allocated)
+ /* Delete the string if we failed to add it */
+ if (!can_assume(NO_ROLLBACK) && allocated)
fdt_del_last_string_(fdt, name);
return err;
}
@@ -411,7 +426,7 @@ int fdt_open_into(const void *fdt, void *buf, int bufsize)
mem_rsv_size = (fdt_num_mem_rsv(fdt)+1)
* sizeof(struct fdt_reserve_entry);
- if (fdt_version(fdt) >= 17) {
+ if (can_assume(LATEST) || fdt_version(fdt) >= 17) {
struct_size = fdt_size_dt_struct(fdt);
} else {
struct_size = 0;
@@ -421,7 +436,8 @@ int fdt_open_into(const void *fdt, void *buf, int bufsize)
return struct_size;
}
- if (!fdt_blocks_misordered_(fdt, mem_rsv_size, struct_size)) {
+ if (can_assume(LIBFDT_ORDER) |
+ !fdt_blocks_misordered_(fdt, mem_rsv_size, struct_size)) {
/* no further work necessary */
err = fdt_move(fdt, buf, bufsize);
if (err)
diff --git a/scripts/dtc/libfdt/fdt_sw.c b/scripts/dtc/libfdt/fdt_sw.c
index 76bea22f734f..26759d5dfb8c 100644
--- a/scripts/dtc/libfdt/fdt_sw.c
+++ b/scripts/dtc/libfdt/fdt_sw.c
@@ -12,10 +12,13 @@
static int fdt_sw_probe_(void *fdt)
{
- if (fdt_magic(fdt) == FDT_MAGIC)
- return -FDT_ERR_BADSTATE;
- else if (fdt_magic(fdt) != FDT_SW_MAGIC)
- return -FDT_ERR_BADMAGIC;
+ if (!can_assume(VALID_INPUT)) {
+ if (fdt_magic(fdt) == FDT_MAGIC)
+ return -FDT_ERR_BADSTATE;
+ else if (fdt_magic(fdt) != FDT_SW_MAGIC)
+ return -FDT_ERR_BADMAGIC;
+ }
+
return 0;
}
@@ -38,7 +41,7 @@ static int fdt_sw_probe_memrsv_(void *fdt)
if (err)
return err;
- if (fdt_off_dt_strings(fdt) != 0)
+ if (!can_assume(VALID_INPUT) && fdt_off_dt_strings(fdt) != 0)
return -FDT_ERR_BADSTATE;
return 0;
}
@@ -64,7 +67,8 @@ static int fdt_sw_probe_struct_(void *fdt)
if (err)
return err;
- if (fdt_off_dt_strings(fdt) != fdt_totalsize(fdt))
+ if (!can_assume(VALID_INPUT) &&
+ fdt_off_dt_strings(fdt) != fdt_totalsize(fdt))
return -FDT_ERR_BADSTATE;
return 0;
}
@@ -151,7 +155,8 @@ int fdt_resize(void *fdt, void *buf, int bufsize)
headsize = fdt_off_dt_struct(fdt) + fdt_size_dt_struct(fdt);
tailsize = fdt_size_dt_strings(fdt);
- if ((headsize + tailsize) > fdt_totalsize(fdt))
+ if (!can_assume(VALID_DTB) &&
+ headsize + tailsize > fdt_totalsize(fdt))
return -FDT_ERR_INTERNAL;
if ((headsize + tailsize) > bufsize)
diff --git a/scripts/dtc/libfdt/libfdt.h b/scripts/dtc/libfdt/libfdt.h
index 7b5ffd13a887..36fadcdea516 100644
--- a/scripts/dtc/libfdt/libfdt.h
+++ b/scripts/dtc/libfdt/libfdt.h
@@ -136,7 +136,7 @@ static inline uint32_t fdt32_ld(const fdt32_t *p)
static inline void fdt32_st(void *property, uint32_t value)
{
- uint8_t *bp = property;
+ uint8_t *bp = (uint8_t *)property;
bp[0] = value >> 24;
bp[1] = (value >> 16) & 0xff;
@@ -160,7 +160,7 @@ static inline uint64_t fdt64_ld(const fdt64_t *p)
static inline void fdt64_st(void *property, uint64_t value)
{
- uint8_t *bp = property;
+ uint8_t *bp = (uint8_t *)property;
bp[0] = value >> 56;
bp[1] = (value >> 48) & 0xff;
@@ -266,11 +266,12 @@ fdt_set_hdr_(size_dt_struct);
* fdt_header_size - return the size of the tree's header
* @fdt: pointer to a flattened device tree
*/
+size_t fdt_header_size(const void *fdt);
+
+/**
+ * fdt_header_size_ - internal function which takes a version number
+ */
size_t fdt_header_size_(uint32_t version);
-static inline size_t fdt_header_size(const void *fdt)
-{
- return fdt_header_size_(fdt_version(fdt));
-}
/**
* fdt_check_header - sanity check a device tree header
diff --git a/scripts/dtc/libfdt/libfdt_internal.h b/scripts/dtc/libfdt/libfdt_internal.h
index 7830e550c37a..d4e0bd49c037 100644
--- a/scripts/dtc/libfdt/libfdt_internal.h
+++ b/scripts/dtc/libfdt/libfdt_internal.h
@@ -10,12 +10,12 @@
#define FDT_ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1))
#define FDT_TAGALIGN(x) (FDT_ALIGN((x), FDT_TAGSIZE))
-int fdt_ro_probe_(const void *fdt);
-#define FDT_RO_PROBE(fdt) \
- { \
- int err_; \
- if ((err_ = fdt_ro_probe_(fdt)) != 0) \
- return err_; \
+int32_t fdt_ro_probe_(const void *fdt);
+#define FDT_RO_PROBE(fdt) \
+ { \
+ int32_t totalsize_; \
+ if ((totalsize_ = fdt_ro_probe_(fdt)) < 0) \
+ return totalsize_; \
}
int fdt_check_node_offset_(const void *fdt, int offset);
@@ -48,4 +48,126 @@ static inline struct fdt_reserve_entry *fdt_mem_rsv_w_(void *fdt, int n)
#define FDT_SW_MAGIC (~FDT_MAGIC)
+/**********************************************************************/
+/* Checking controls */
+/**********************************************************************/
+
+#ifndef FDT_ASSUME_MASK
+#define FDT_ASSUME_MASK 0
+#endif
+
+/*
+ * Defines assumptions which can be enabled. Each of these can be enabled
+ * individually. For maximum safety, don't enable any assumptions!
+ *
+ * For minimal code size and no safety, use ASSUME_PERFECT at your own risk.
+ * You should have another method of validating the device tree, such as a
+ * signature or hash check before using libfdt.
+ *
+ * For situations where security is not a concern it may be safe to enable
+ * ASSUME_SANE.
+ */
+enum {
+ /*
+ * This does essentially no checks. Only the latest device-tree
+ * version is correctly handled. Inconsistencies or errors in the device
+ * tree may cause undefined behaviour or crashes. Invalid parameters
+ * passed to libfdt may do the same.
+ *
+ * If an error occurs when modifying the tree it may leave the tree in
+ * an intermediate (but valid) state. As an example, adding a property
+ * where there is insufficient space may result in the property name
+ * being added to the string table even though the property itself is
+ * not added to the struct section.
+ *
+ * Only use this if you have a fully validated device tree with
+ * the latest supported version and wish to minimise code size.
+ */
+ ASSUME_PERFECT = 0xff,
+
+ /*
+ * This assumes that the device tree is sane. i.e. header metadata
+ * and basic hierarchy are correct.
+ *
+ * With this assumption enabled, normal device trees produced by libfdt
+ * and the compiler should be handled safely. Malicious device trees and
+ * complete garbage may cause libfdt to behave badly or crash. Truncated
+ * device trees (e.g. those only partially loaded) can also cause
+ * problems.
+ *
+ * Note: Only checks that relate exclusively to the device tree itself
+ * (not the parameters passed to libfdt) are disabled by this
+ * assumption. This includes checking headers, tags and the like.
+ */
+ ASSUME_VALID_DTB = 1 << 0,
+
+ /*
+ * This builds on ASSUME_VALID_DTB and further assumes that libfdt
+ * functions are called with valid parameters, i.e. not trigger
+ * FDT_ERR_BADOFFSET or offsets that are out of bounds. It disables any
+ * extensive checking of parameters and the device tree, making various
+ * assumptions about correctness.
+ *
+ * It doesn't make sense to enable this assumption unless
+ * ASSUME_VALID_DTB is also enabled.
+ */
+ ASSUME_VALID_INPUT = 1 << 1,
+
+ /*
+ * This disables checks for device-tree version and removes all code
+ * which handles older versions.
+ *
+ * Only enable this if you know you have a device tree with the latest
+ * version.
+ */
+ ASSUME_LATEST = 1 << 2,
+
+ /*
+ * This assumes that it is OK for a failed addition to the device tree,
+ * due to lack of space or some other problem, to skip any rollback
+ * steps (such as dropping the property name from the string table).
+ * This is safe to enable in most circumstances, even though it may
+ * leave the tree in a sub-optimal state.
+ */
+ ASSUME_NO_ROLLBACK = 1 << 3,
+
+ /*
+ * This assumes that the device tree components appear in a 'convenient'
+ * order, i.e. the memory reservation block first, then the structure
+ * block and finally the string block.
+ *
+ * This order is not specified by the device-tree specification,
+ * but is expected by libfdt. The device-tree compiler always created
+ * device trees with this order.
+ *
+ * This assumption disables a check in fdt_open_into() and removes the
+ * ability to fix the problem there. This is safe if you know that the
+ * device tree is correctly ordered. See fdt_blocks_misordered_().
+ */
+ ASSUME_LIBFDT_ORDER = 1 << 4,
+
+ /*
+ * This assumes that libfdt itself does not have any internal bugs. It
+ * drops certain checks that should never be needed unless libfdt has an
+ * undiscovered bug.
+ *
+ * This can generally be considered safe to enable.
+ */
+ ASSUME_LIBFDT_FLAWLESS = 1 << 5,
+};
+
+/**
+ * can_assume_() - check if a particular assumption is enabled
+ *
+ * @mask: Mask to check (ASSUME_...)
+ * @return true if that assumption is enabled, else false
+ */
+static inline bool can_assume_(int mask)
+{
+ return FDT_ASSUME_MASK & mask;
+}
+
+/** helper macros for checking assumptions */
+#define can_assume(_assume) can_assume_(ASSUME_ ## _assume)
+
#endif /* LIBFDT_INTERNAL_H */
diff --git a/scripts/dtc/livetree.c b/scripts/dtc/livetree.c
index 0c039993953a..032df5878ccc 100644
--- a/scripts/dtc/livetree.c
+++ b/scripts/dtc/livetree.c
@@ -526,8 +526,7 @@ struct node *get_node_by_path(struct node *tree, const char *path)
p = strchr(path, '/');
for_each_child(tree, child) {
- if (p && (strlen(child->name) == p-path) &&
- strprefixeq(path, p - path, child->name))
+ if (p && strprefixeq(path, p - path, child->name))
return get_node_by_path(child, p+1);
else if (!p && streq(path, child->name))
return child;
diff --git a/scripts/dtc/update-dtc-source.sh b/scripts/dtc/update-dtc-source.sh
index 7dd29a0362b8..bc704e2a6a4a 100755
--- a/scripts/dtc/update-dtc-source.sh
+++ b/scripts/dtc/update-dtc-source.sh
@@ -32,9 +32,9 @@ DTC_UPSTREAM_PATH=`pwd`/../dtc
DTC_LINUX_PATH=`pwd`/scripts/dtc
DTC_SOURCE="checks.c data.c dtc.c dtc.h flattree.c fstree.c livetree.c srcpos.c \
- srcpos.h treesource.c util.c util.h version_gen.h yamltree.c Makefile.dtc \
+ srcpos.h treesource.c util.c util.h version_gen.h yamltree.c \
dtc-lexer.l dtc-parser.y"
-LIBFDT_SOURCE="Makefile.libfdt fdt.c fdt.h fdt_addresses.c fdt_empty_tree.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"
diff --git a/scripts/dtc/util.c b/scripts/dtc/util.c
index 48af961dcc8c..40274fb79236 100644
--- a/scripts/dtc/util.c
+++ b/scripts/dtc/util.c
@@ -13,6 +13,7 @@
#include <stdarg.h>
#include <string.h>
#include <assert.h>
+#include <inttypes.h>
#include <errno.h>
#include <fcntl.h>
@@ -393,7 +394,7 @@ void utilfdt_print_data(const char *data, int len)
printf(" = <");
for (i = 0, len /= 4; i < len; i++)
- printf("0x%08x%s", fdt32_to_cpu(cell[i]),
+ printf("0x%08" PRIx32 "%s", fdt32_to_cpu(cell[i]),
i < (len - 1) ? " " : "");
printf(">");
} else {
diff --git a/scripts/dtc/util.h b/scripts/dtc/util.h
index ca5cb52928e3..5a4172dd0f84 100644
--- a/scripts/dtc/util.h
+++ b/scripts/dtc/util.h
@@ -12,7 +12,11 @@
*/
#ifdef __GNUC__
+#ifdef __clang__
#define PRINTF(i, j) __attribute__((format (printf, i, j)))
+#else
+#define PRINTF(i, j) __attribute__((format (gnu_printf, i, j)))
+#endif
#define NORETURN __attribute__((noreturn))
#else
#define PRINTF(i, j)
diff --git a/scripts/dtc/version_gen.h b/scripts/dtc/version_gen.h
index f2761e24cf40..61dd7112d6e4 100644
--- a/scripts/dtc/version_gen.h
+++ b/scripts/dtc/version_gen.h
@@ -1 +1 @@
-#define DTC_VERSION "DTC 1.5.0-g702c1b6c"
+#define DTC_VERSION "DTC 1.6.0-g87a656ae"
diff --git a/scripts/dummy-tools/gcc b/scripts/dummy-tools/gcc
new file mode 100755
index 000000000000..33487e99d83e
--- /dev/null
+++ b/scripts/dummy-tools/gcc
@@ -0,0 +1,91 @@
+#!/bin/sh
+# SPDX-License-Identifier: GPL-2.0-only
+#
+# Staring v4.18, Kconfig evaluates compiler capabilities, and hides CONFIG
+# options your compiler does not support. This works well if you configure and
+# build the kernel on the same host machine.
+#
+# It is inconvenient if you prepare the .config that is carried to a different
+# build environment (typically this happens when you package the kernel for
+# distros) because using a different compiler potentially produces different
+# CONFIG options than the real build environment. So, you probably want to make
+# as many options visible as possible. In other words, you need to create a
+# super-set of CONFIG options that cover any build environment. If some of the
+# CONFIG options turned out to be unsupported on the build machine, they are
+# automatically disabled by the nature of Kconfig.
+#
+# However, it is not feasible to get a full-featured compiler for every arch.
+# Hence these dummy toolchains to make all compiler tests pass.
+#
+# Usage:
+#
+# From the top directory of the source tree, run
+#
+# $ make CROSS_COMPILE=scripts/dummy-tools/ oldconfig
+#
+# Most of compiler features are tested by cc-option, which simply checks the
+# exit code of $(CC). This script does nothing and just exits with 0 in most
+# cases. So, $(cc-option, ...) is evaluated as 'y'.
+#
+# This scripts caters to more checks; handle --version and pre-process __GNUC__
+# etc. to pretend to be GCC, and also do right things to satisfy some scripts.
+
+# Check if the first parameter appears in the rest. Succeeds if found.
+# This helper is useful if a particular option was passed to this script.
+# Typically used like this:
+# arg_contain <word-you-are-searching-for> "$@"
+arg_contain ()
+{
+ search="$1"
+ shift
+
+ while [ $# -gt 0 ]
+ do
+ if [ "$search" = "$1" ]; then
+ return 0
+ fi
+ shift
+ done
+
+ return 1
+}
+
+# To set CONFIG_CC_IS_GCC=y
+if arg_contain --version "$@"; then
+ echo "gcc (scripts/dummy-tools/gcc)"
+ exit 0
+fi
+
+if arg_contain -E "$@"; then
+ # For scripts/gcc-version.sh; This emulates GCC 20.0.0
+ if arg_contain - "$@"; then
+ sed 's/^__GNUC__$/20/; s/^__GNUC_MINOR__$/0/; s/^__GNUC_PATCHLEVEL__$/0/'
+ exit 0
+ else
+ echo "no input files" >&2
+ exit 1
+ fi
+fi
+
+if arg_contain -S "$@"; then
+ # For scripts/gcc-x86-*-has-stack-protector.sh
+ if arg_contain -fstack-protector "$@"; then
+ echo "%gs"
+ exit 0
+ fi
+fi
+
+# For scripts/gcc-plugin.sh
+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
+
+ echo $plugin_dir
+ exit 0
+fi
diff --git a/scripts/dummy-tools/ld b/scripts/dummy-tools/ld
new file mode 100755
index 000000000000..f68233050405
--- /dev/null
+++ b/scripts/dummy-tools/ld
@@ -0,0 +1,30 @@
+#!/bin/sh
+# SPDX-License-Identifier: GPL-2.0-only
+
+# Dummy script that always succeeds.
+
+# Check if the first parameter appears in the rest. Succeeds if found.
+# This helper is useful if a particular option was passed to this script.
+# Typically used like this:
+# arg_contain <word-you-are-searching-for> "$@"
+arg_contain ()
+{
+ search="$1"
+ shift
+
+ while [ $# -gt 0 ]
+ do
+ if [ "$search" = "$1" ]; then
+ return 0
+ fi
+ shift
+ done
+
+ return 1
+}
+
+if arg_contain --version "$@" || arg_contain -v "$@"; then
+ progname=$(basename $0)
+ echo "GNU $progname (scripts/dummy-tools/$progname) 2.50"
+ exit 0
+fi
diff --git a/scripts/dummy-tools/nm b/scripts/dummy-tools/nm
new file mode 120000
index 000000000000..c0648b38dd42
--- /dev/null
+++ b/scripts/dummy-tools/nm
@@ -0,0 +1 @@
+ld \ No newline at end of file
diff --git a/scripts/dummy-tools/objcopy b/scripts/dummy-tools/objcopy
new file mode 120000
index 000000000000..c0648b38dd42
--- /dev/null
+++ b/scripts/dummy-tools/objcopy
@@ -0,0 +1 @@
+ld \ No newline at end of file
diff --git a/scripts/export_report.pl b/scripts/export_report.pl
index 548330e8c4e7..feb3d5542a62 100755
--- a/scripts/export_report.pl
+++ b/scripts/export_report.pl
@@ -94,7 +94,7 @@ if (defined $opt{'o'}) {
#
while ( <$module_symvers> ) {
chomp;
- my (undef, $symbol, $namespace, $module, $gpl) = split('\t');
+ my (undef, $symbol, $module, $gpl, $namespace) = split('\t');
$SYMBOL { $symbol } = [ $module , "0" , $symbol, $gpl];
}
close($module_symvers);
diff --git a/scripts/find-unused-docs.sh b/scripts/find-unused-docs.sh
index 3f46f8977dc4..ee6a50e33aba 100755
--- a/scripts/find-unused-docs.sh
+++ b/scripts/find-unused-docs.sh
@@ -54,7 +54,7 @@ for file in `find $1 -name '*.c'`; do
if [[ ${FILES_INCLUDED[$file]+_} ]]; then
continue;
fi
- str=$(scripts/kernel-doc -text -export "$file" 2>/dev/null)
+ str=$(scripts/kernel-doc -export "$file" 2>/dev/null)
if [[ -n "$str" ]]; then
echo "$file"
fi
diff --git a/scripts/gcc-plugin.sh b/scripts/gcc-plugin.sh
index d3caefe53eab..b79fd0bea838 100755
--- a/scripts/gcc-plugin.sh
+++ b/scripts/gcc-plugin.sh
@@ -1,49 +1,14 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
-srctree=$(dirname "$0")
-
-SHOW_ERROR=
-if [ "$1" = "--show-error" ] ; then
- SHOW_ERROR=1
- shift || true
-fi
-
-gccplugins_dir=$($3 -print-file-name=plugin)
-plugincc=$($1 -E -x c++ - -o /dev/null -I"${srctree}"/gcc-plugins -I"${gccplugins_dir}"/include 2>&1 <<EOF
-#include "gcc-common.h"
-#if BUILDING_GCC_VERSION >= 4008 || defined(ENABLE_BUILD_WITH_CXX)
-#warning $2 CXX
-#else
-#warning $1 CC
-#endif
-EOF
-)
-if [ $? -ne 0 ]
-then
- if [ -n "$SHOW_ERROR" ] ; then
- echo "${plugincc}" >&2
- fi
- exit 1
-fi
+set -e
-case "$plugincc" in
- *"$1 CC"*)
- echo "$1"
- exit 0
- ;;
-
- *"$2 CXX"*)
- # the c++ compiler needs another test, see below
- ;;
+srctree=$(dirname "$0")
- *)
- exit 1
- ;;
-esac
+gccplugins_dir=$($* -print-file-name=plugin)
# we need a c++ compiler that supports the designated initializer GNU extension
-plugincc=$($2 -c -x c++ -std=gnu++98 - -fsyntax-only -I"${srctree}"/gcc-plugins -I"${gccplugins_dir}"/include 2>&1 <<EOF
+$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:
@@ -52,15 +17,3 @@ public:
.test = 1
};
EOF
-)
-
-if [ $? -eq 0 ]
-then
- echo "$2"
- exit 0
-fi
-
-if [ -n "$SHOW_ERROR" ] ; then
- echo "${plugincc}" >&2
-fi
-exit 1
diff --git a/scripts/gcc-plugins/.gitignore b/scripts/gcc-plugins/.gitignore
index de92ed9e3d83..b04e0f0f033e 100644
--- a/scripts/gcc-plugins/.gitignore
+++ b/scripts/gcc-plugins/.gitignore
@@ -1 +1,2 @@
+# SPDX-License-Identifier: GPL-2.0-only
randomize_layout_seed.h
diff --git a/scripts/gcc-plugins/Kconfig b/scripts/gcc-plugins/Kconfig
index e3569543bdac..013ba3a57669 100644
--- a/scripts/gcc-plugins/Kconfig
+++ b/scripts/gcc-plugins/Kconfig
@@ -1,13 +1,4 @@
# SPDX-License-Identifier: GPL-2.0-only
-preferred-plugin-hostcc := $(if-success,[ $(gcc-version) -ge 40800 ],$(HOSTCXX),$(HOSTCC))
-
-config PLUGIN_HOSTCC
- string
- default "$(shell,$(srctree)/scripts/gcc-plugin.sh "$(preferred-plugin-hostcc)" "$(HOSTCXX)" "$(CC)")" if CC_IS_GCC
- help
- Host compiler used to build GCC plugins. This can be $(HOSTCXX),
- $(HOSTCC), or a null string if GCC plugin is unsupported.
-
config HAVE_GCC_PLUGINS
bool
help
@@ -17,13 +8,14 @@ config HAVE_GCC_PLUGINS
menuconfig GCC_PLUGINS
bool "GCC plugins"
depends on HAVE_GCC_PLUGINS
- depends on PLUGIN_HOSTCC != ""
+ depends on CC_IS_GCC && GCC_VERSION >= 40800
+ depends on $(success,$(srctree)/scripts/gcc-plugin.sh $(CC))
default y
help
GCC plugins are loadable modules that provide extra features to the
compiler. They are useful for runtime instrumentation and static analysis.
- See Documentation/core-api/gcc-plugins.rst for details.
+ See Documentation/kbuild/gcc-plugins.rst for details.
if GCC_PLUGINS
diff --git a/scripts/gcc-plugins/Makefile b/scripts/gcc-plugins/Makefile
index aa0d0ec6936d..f22858b2c3d6 100644
--- a/scripts/gcc-plugins/Makefile
+++ b/scripts/gcc-plugins/Makefile
@@ -1,18 +1,9 @@
# SPDX-License-Identifier: GPL-2.0
-PLUGINCC := $(CONFIG_PLUGIN_HOSTCC:"%"=%)
GCC_PLUGINS_DIR := $(shell $(CC) -print-file-name=plugin)
-ifeq ($(PLUGINCC),$(HOSTCC))
- HOSTLIBS := hostlibs
- HOST_EXTRACFLAGS += -I$(GCC_PLUGINS_DIR)/include -I$(src) -std=gnu99 -ggdb
- export HOST_EXTRACFLAGS
-else
- HOSTLIBS := hostcxxlibs
- HOST_EXTRACXXFLAGS += -I$(GCC_PLUGINS_DIR)/include -I$(src) -std=gnu++98 -fno-rtti
- HOST_EXTRACXXFLAGS += -fno-exceptions -fasynchronous-unwind-tables -ggdb
- HOST_EXTRACXXFLAGS += -Wno-narrowing -Wno-unused-variable
- export HOST_EXTRACXXFLAGS
-endif
+HOST_EXTRACXXFLAGS += -I$(GCC_PLUGINS_DIR)/include -I$(src) -std=gnu++98 -fno-rtti
+HOST_EXTRACXXFLAGS += -fno-exceptions -fasynchronous-unwind-tables -ggdb
+HOST_EXTRACXXFLAGS += -Wno-narrowing -Wno-unused-variable -Wno-c++11-compat
$(obj)/randomize_layout_plugin.o: $(objtree)/$(obj)/randomize_layout_seed.h
quiet_cmd_create_randomize_layout_seed = GENSEED $@
@@ -22,9 +13,9 @@ $(objtree)/$(obj)/randomize_layout_seed.h: FORCE
$(call if_changed,create_randomize_layout_seed)
targets = randomize_layout_seed.h randomize_layout_hash.h
-$(HOSTLIBS)-y := $(foreach p,$(GCC_PLUGIN),$(if $(findstring /,$(p)),,$(p)))
-always := $($(HOSTLIBS)-y)
+hostcxxlibs-y := $(foreach p,$(GCC_PLUGIN),$(if $(findstring /,$(p)),,$(p)))
+always-y := $(hostcxxlibs-y)
-$(foreach p,$($(HOSTLIBS)-y:%.so=%),$(eval $(p)-objs := $(p).o))
+$(foreach p,$(hostcxxlibs-y:%.so=%),$(eval $(p)-objs := $(p).o))
clean-files += *.so
diff --git a/scripts/gdb/linux/.gitignore b/scripts/gdb/linux/.gitignore
index 2573543842d0..43234cbcb529 100644
--- a/scripts/gdb/linux/.gitignore
+++ b/scripts/gdb/linux/.gitignore
@@ -1,3 +1,4 @@
+# SPDX-License-Identifier: GPL-2.0-only
*.pyc
*.pyo
constants.py
diff --git a/scripts/gen_autoksyms.sh b/scripts/gen_autoksyms.sh
new file mode 100755
index 000000000000..16c0b2ddaa4c
--- /dev/null
+++ b/scripts/gen_autoksyms.sh
@@ -0,0 +1,52 @@
+#!/bin/sh
+# SPDX-License-Identifier: GPL-2.0-only
+
+# Create an autoksyms.h header file from the list of all module's needed symbols
+# as recorded on the second line of *.mod files and the user-provided symbol
+# whitelist.
+
+set -e
+
+output_file="$1"
+
+# Use "make V=1" to debug this script.
+case "$KBUILD_VERBOSE" in
+*1*)
+ set -x
+ ;;
+esac
+
+# We need access to CONFIG_ symbols
+. include/config/auto.conf
+
+ksym_wl=/dev/null
+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"
+ [ "${ksym_wl}" != "${ksym_wl#/}" ] || ksym_wl="$abs_srctree/$ksym_wl"
+ if [ ! -f "$ksym_wl" ] || [ ! -r "$ksym_wl" ]; then
+ echo "ERROR: '$ksym_wl' whitelist file not found" >&2
+ exit 1
+ fi
+fi
+
+# Generate a new ksym list file with symbols needed by the current
+# set of modules.
+cat > "$output_file" << EOT
+/*
+ * Automatically generated file; DO NOT EDIT.
+ */
+
+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" |
+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/genksyms/.gitignore b/scripts/genksyms/.gitignore
index b119c7da2863..999af710f83d 100644
--- a/scripts/genksyms/.gitignore
+++ b/scripts/genksyms/.gitignore
@@ -1 +1,2 @@
+# SPDX-License-Identifier: GPL-2.0-only
genksyms
diff --git a/scripts/genksyms/Makefile b/scripts/genksyms/Makefile
index 78629f515e78..d328de1e10ee 100644
--- a/scripts/genksyms/Makefile
+++ b/scripts/genksyms/Makefile
@@ -1,7 +1,7 @@
# SPDX-License-Identifier: GPL-2.0
-hostprogs-y := genksyms
-always := $(hostprogs-y)
+hostprogs := genksyms
+always-y := $(hostprogs)
genksyms-objs := genksyms.o parse.tab.o lex.lex.o
diff --git a/scripts/get_maintainer.pl b/scripts/get_maintainer.pl
index 34085d146fa2..6cbcd1a3e113 100755
--- a/scripts/get_maintainer.pl
+++ b/scripts/get_maintainer.pl
@@ -932,10 +932,6 @@ sub get_maintainers {
}
}
- foreach my $fix (@fixes) {
- vcs_add_commit_signers($fix, "blamed_fixes");
- }
-
foreach my $email (@email_to, @list_to) {
$email->[0] = deduplicate_email($email->[0]);
}
@@ -974,6 +970,10 @@ sub get_maintainers {
}
}
+ foreach my $fix (@fixes) {
+ vcs_add_commit_signers($fix, "blamed_fixes");
+ }
+
my @to = ();
if ($email || $email_list) {
if ($email) {
@@ -1341,35 +1341,11 @@ sub add_categories {
}
}
} elsif ($ptype eq "M") {
- my ($name, $address) = parse_email($pvalue);
- if ($name eq "") {
- if ($i > 0) {
- my $tv = $typevalue[$i - 1];
- if ($tv =~ m/^([A-Z]):\s*(.*)/) {
- if ($1 eq "P") {
- $name = $2;
- $pvalue = format_email($name, $address, $email_usename);
- }
- }
- }
- }
if ($email_maintainer) {
my $role = get_maintainer_role($i);
push_email_addresses($pvalue, $role);
}
} elsif ($ptype eq "R") {
- my ($name, $address) = parse_email($pvalue);
- if ($name eq "") {
- if ($i > 0) {
- my $tv = $typevalue[$i - 1];
- if ($tv =~ m/^([A-Z]):\s*(.*)/) {
- if ($1 eq "P") {
- $name = $2;
- $pvalue = format_email($name, $address, $email_usename);
- }
- }
- }
- }
if ($email_reviewer) {
my $subsystem = get_subsystem_name($i);
push_email_addresses($pvalue, "reviewer:$subsystem");
diff --git a/scripts/kallsyms.c b/scripts/kallsyms.c
index 94153732ec00..3e8dea6e0a95 100644
--- a/scripts/kallsyms.c
+++ b/scripts/kallsyms.c
@@ -33,8 +33,8 @@ struct sym_entry {
unsigned long long addr;
unsigned int len;
unsigned int start_pos;
- unsigned char *sym;
unsigned int percpu_absolute;
+ unsigned char sym[0];
};
struct addr_range {
@@ -55,7 +55,7 @@ static struct addr_range percpu_range = {
"__per_cpu_start", "__per_cpu_end", -1ULL, 0
};
-static struct sym_entry *table;
+static struct sym_entry **table;
static unsigned int table_size, table_cnt;
static int all_symbols;
static int absolute_percpu;
@@ -174,49 +174,55 @@ static void check_symbol_range(const char *sym, unsigned long long addr,
}
}
-static int read_symbol(FILE *in, struct sym_entry *s)
+static struct sym_entry *read_symbol(FILE *in)
{
- char sym[500], stype;
+ char name[500], type;
+ unsigned long long addr;
+ unsigned int len;
+ struct sym_entry *sym;
int rc;
- rc = fscanf(in, "%llx %c %499s\n", &s->addr, &stype, sym);
+ rc = fscanf(in, "%llx %c %499s\n", &addr, &type, name);
if (rc != 3) {
- if (rc != EOF && fgets(sym, 500, in) == NULL)
+ if (rc != EOF && fgets(name, 500, in) == NULL)
fprintf(stderr, "Read error or end of file.\n");
- return -1;
+ return NULL;
}
- if (strlen(sym) >= KSYM_NAME_LEN) {
+ if (strlen(name) >= KSYM_NAME_LEN) {
fprintf(stderr, "Symbol %s too long for kallsyms (%zu >= %d).\n"
"Please increase KSYM_NAME_LEN both in kernel and kallsyms.c\n",
- sym, strlen(sym), KSYM_NAME_LEN);
- return -1;
+ name, strlen(name), KSYM_NAME_LEN);
+ return NULL;
}
- if (is_ignored_symbol(sym, stype))
- return -1;
+ if (strcmp(name, "_text") == 0)
+ _text = addr;
/* Ignore most absolute/undefined (?) symbols. */
- if (strcmp(sym, "_text") == 0)
- _text = s->addr;
+ if (is_ignored_symbol(name, type))
+ return NULL;
- check_symbol_range(sym, s->addr, text_ranges, ARRAY_SIZE(text_ranges));
- check_symbol_range(sym, s->addr, &percpu_range, 1);
+ check_symbol_range(name, addr, text_ranges, ARRAY_SIZE(text_ranges));
+ check_symbol_range(name, addr, &percpu_range, 1);
/* include the type field in the symbol name, so that it gets
* compressed together */
- s->len = strlen(sym) + 1;
- s->sym = malloc(s->len + 1);
- if (!s->sym) {
+
+ len = strlen(name) + 1;
+
+ sym = malloc(sizeof(*sym) + len + 1);
+ if (!sym) {
fprintf(stderr, "kallsyms failure: "
"unable to allocate required amount of memory\n");
exit(EXIT_FAILURE);
}
- strcpy(sym_name(s), sym);
- s->sym[0] = stype;
-
- s->percpu_absolute = 0;
+ sym->addr = addr;
+ sym->len = len;
+ sym->sym[0] = type;
+ strcpy(sym_name(sym), name);
+ sym->percpu_absolute = 0;
- return 0;
+ return sym;
}
static int symbol_in_range(const struct sym_entry *s,
@@ -268,12 +274,12 @@ static void shrink_table(void)
pos = 0;
for (i = 0; i < table_cnt; i++) {
- if (symbol_valid(&table[i])) {
+ if (symbol_valid(table[i])) {
if (pos != i)
table[pos] = table[i];
pos++;
} else {
- free(table[i].sym);
+ free(table[i]);
}
}
table_cnt = pos;
@@ -287,7 +293,15 @@ static void shrink_table(void)
static void read_map(FILE *in)
{
+ struct sym_entry *sym;
+
while (!feof(in)) {
+ sym = read_symbol(in);
+ if (!sym)
+ continue;
+
+ sym->start_pos = table_cnt;
+
if (table_cnt >= table_size) {
table_size += 10000;
table = realloc(table, sizeof(*table) * table_size);
@@ -296,10 +310,8 @@ static void read_map(FILE *in)
exit (1);
}
}
- if (read_symbol(in, &table[table_cnt]) == 0) {
- table[table_cnt].start_pos = table_cnt;
- table_cnt++;
- }
+
+ table[table_cnt++] = sym;
}
}
@@ -387,27 +399,27 @@ static void write_src(void)
int overflow;
if (!absolute_percpu) {
- offset = table[i].addr - relative_base;
+ offset = table[i]->addr - relative_base;
overflow = (offset < 0 || offset > UINT_MAX);
- } else if (symbol_absolute(&table[i])) {
- offset = table[i].addr;
+ } else if (symbol_absolute(table[i])) {
+ offset = table[i]->addr;
overflow = (offset < 0 || offset > INT_MAX);
} else {
- offset = relative_base - table[i].addr - 1;
+ offset = relative_base - table[i]->addr - 1;
overflow = (offset < INT_MIN || offset >= 0);
}
if (overflow) {
fprintf(stderr, "kallsyms failure: "
"%s symbol value %#llx out of range in relative mode\n",
- symbol_absolute(&table[i]) ? "absolute" : "relative",
- table[i].addr);
+ symbol_absolute(table[i]) ? "absolute" : "relative",
+ table[i]->addr);
exit(EXIT_FAILURE);
}
printf("\t.long\t%#x\n", (int)offset);
- } else if (!symbol_absolute(&table[i])) {
- output_address(table[i].addr);
+ } else if (!symbol_absolute(table[i])) {
+ output_address(table[i]->addr);
} else {
- printf("\tPTR\t%#llx\n", table[i].addr);
+ printf("\tPTR\t%#llx\n", table[i]->addr);
}
}
printf("\n");
@@ -437,12 +449,12 @@ static void write_src(void)
if ((i & 0xFF) == 0)
markers[i >> 8] = off;
- printf("\t.byte 0x%02x", table[i].len);
- for (k = 0; k < table[i].len; k++)
- printf(", 0x%02x", table[i].sym[k]);
+ printf("\t.byte 0x%02x", table[i]->len);
+ for (k = 0; k < table[i]->len; k++)
+ printf(", 0x%02x", table[i]->sym[k]);
printf("\n");
- off += table[i].len + 1;
+ off += table[i]->len + 1;
}
printf("\n");
@@ -496,7 +508,7 @@ static void build_initial_tok_table(void)
unsigned int i;
for (i = 0; i < table_cnt; i++)
- learn_symbol(table[i].sym, table[i].len);
+ learn_symbol(table[i]->sym, table[i]->len);
}
static unsigned char *find_token(unsigned char *str, int len,
@@ -520,15 +532,15 @@ static void compress_symbols(const unsigned char *str, int idx)
for (i = 0; i < table_cnt; i++) {
- len = table[i].len;
- p1 = table[i].sym;
+ len = table[i]->len;
+ p1 = table[i]->sym;
/* find the token on the symbol */
p2 = find_token(p1, len, str);
if (!p2) continue;
/* decrease the counts for this symbol's tokens */
- forget_symbol(table[i].sym, len);
+ forget_symbol(table[i]->sym, len);
size = len;
@@ -547,10 +559,10 @@ static void compress_symbols(const unsigned char *str, int idx)
} while (p2);
- table[i].len = len;
+ table[i]->len = len;
/* increase the counts for this symbol's new tokens */
- learn_symbol(table[i].sym, len);
+ learn_symbol(table[i]->sym, len);
}
}
@@ -606,8 +618,8 @@ static void insert_real_symbols_in_table(void)
unsigned int i, j, c;
for (i = 0; i < table_cnt; i++) {
- for (j = 0; j < table[i].len; j++) {
- c = table[i].sym[j];
+ for (j = 0; j < table[i]->len; j++) {
+ c = table[i]->sym[j];
best_table[c][0]=c;
best_table_len[c]=1;
}
@@ -660,13 +672,10 @@ static int may_be_linker_script_provide_symbol(const struct sym_entry *se)
static int compare_symbols(const void *a, const void *b)
{
- const struct sym_entry *sa;
- const struct sym_entry *sb;
+ const struct sym_entry *sa = *(const struct sym_entry **)a;
+ const struct sym_entry *sb = *(const struct sym_entry **)b;
int wa, wb;
- sa = a;
- sb = b;
-
/* sort by address first */
if (sa->addr > sb->addr)
return 1;
@@ -697,7 +706,7 @@ static int compare_symbols(const void *a, const void *b)
static void sort_symbols(void)
{
- qsort(table, table_cnt, sizeof(struct sym_entry), compare_symbols);
+ qsort(table, table_cnt, sizeof(table[0]), compare_symbols);
}
static void make_percpus_absolute(void)
@@ -705,14 +714,14 @@ static void make_percpus_absolute(void)
unsigned int i;
for (i = 0; i < table_cnt; i++)
- if (symbol_in_range(&table[i], &percpu_range, 1)) {
+ if (symbol_in_range(table[i], &percpu_range, 1)) {
/*
* Keep the 'A' override for percpu symbols to
* ensure consistent behavior compared to older
* versions of this tool.
*/
- table[i].sym[0] = 'A';
- table[i].percpu_absolute = 1;
+ table[i]->sym[0] = 'A';
+ table[i]->percpu_absolute = 1;
}
}
@@ -722,12 +731,12 @@ static void record_relative_base(void)
unsigned int i;
for (i = 0; i < table_cnt; i++)
- if (!symbol_absolute(&table[i])) {
+ if (!symbol_absolute(table[i])) {
/*
* The table is sorted by address.
* Take the first non-absolute symbol value.
*/
- relative_base = table[i].addr;
+ relative_base = table[i]->addr;
return;
}
}
diff --git a/scripts/kconfig/.gitignore b/scripts/kconfig/.gitignore
index b5bf92f66d11..12a67fdab541 100644
--- a/scripts/kconfig/.gitignore
+++ b/scripts/kconfig/.gitignore
@@ -1,6 +1,4 @@
-#
-# Generated files
-#
+# SPDX-License-Identifier: GPL-2.0-only
*.moc
*conf-cfg
diff --git a/scripts/kconfig/Makefile b/scripts/kconfig/Makefile
index 2f1a59fa5169..c9d0a4a8efb3 100644
--- a/scripts/kconfig/Makefile
+++ b/scripts/kconfig/Makefile
@@ -12,10 +12,6 @@ else
Kconfig := Kconfig
endif
-ifndef KBUILD_DEFCONFIG
-KBUILD_DEFCONFIG := defconfig
-endif
-
ifeq ($(quiet),silent_)
silent := -s
endif
@@ -47,16 +43,16 @@ build_gconfig: $(obj)/gconf
build_xconfig: $(obj)/qconf
localyesconfig localmodconfig: $(obj)/conf
- $(Q)perl $(srctree)/$(src)/streamline_config.pl --$@ $(srctree) $(Kconfig) > .tmp.config
- $(Q)if [ -f .config ]; then \
- cmp -s .tmp.config .config || \
- (mv -f .config .config.old.1; \
- mv -f .tmp.config .config; \
- $< $(silent) --oldconfig $(Kconfig); \
- mv -f .config.old.1 .config.old) \
- else \
- mv -f .tmp.config .config; \
- $< $(silent) --oldconfig $(Kconfig); \
+ $(Q)$(PERL) $(srctree)/$(src)/streamline_config.pl --$@ $(srctree) $(Kconfig) > .tmp.config
+ $(Q)if [ -f .config ]; then \
+ cmp -s .tmp.config .config || \
+ (mv -f .config .config.old.1; \
+ mv -f .tmp.config .config; \
+ $< $(silent) --oldconfig $(Kconfig); \
+ mv -f .config.old.1 .config.old) \
+ else \
+ mv -f .tmp.config .config; \
+ $< $(silent) --oldconfig $(Kconfig); \
fi
$(Q)rm -f .tmp.config
@@ -67,7 +63,7 @@ localyesconfig localmodconfig: $(obj)/conf
# deprecated for external use
simple-targets := oldconfig allnoconfig allyesconfig allmodconfig \
alldefconfig randconfig listnewconfig olddefconfig syncconfig \
- helpnewconfig
+ helpnewconfig yes2modconfig mod2yesconfig
PHONY += $(simple-targets)
@@ -135,6 +131,8 @@ help:
@echo ' allmodconfig - New config selecting modules when possible'
@echo ' alldefconfig - New config with all symbols set to default'
@echo ' randconfig - New config with random answer to all options'
+ @echo ' yes2modconfig - Change answers from yes to mod if possible'
+ @echo ' mod2yesconfig - Change answers from mod to yes if possible'
@echo ' listnewconfig - List new options'
@echo ' helpnewconfig - List new options and help text'
@echo ' olddefconfig - Same as oldconfig but sets new symbols to their'
@@ -155,11 +153,11 @@ HOSTCFLAGS_lexer.lex.o := -I $(srctree)/$(src)
HOSTCFLAGS_parser.tab.o := -I $(srctree)/$(src)
# conf: Used for defconfig, oldconfig and related targets
-hostprogs-y += conf
+hostprogs += conf
conf-objs := conf.o $(common-objs)
# nconf: Used for the nconfig target based on ncurses
-hostprogs-y += nconf
+hostprogs += nconf
nconf-objs := nconf.o nconf.gui.o $(common-objs)
HOSTLDLIBS_nconf = $(shell . $(obj)/nconf-cfg && echo $$libs)
@@ -169,7 +167,7 @@ HOSTCFLAGS_nconf.gui.o = $(shell . $(obj)/nconf-cfg && echo $$cflags)
$(obj)/nconf.o $(obj)/nconf.gui.o: $(obj)/nconf-cfg
# mconf: Used for the menuconfig target based on lxdialog
-hostprogs-y += mconf
+hostprogs += mconf
lxdialog := $(addprefix lxdialog/, \
checklist.o inputbox.o menubox.o textbox.o util.o yesno.o)
mconf-objs := mconf.o $(lxdialog) $(common-objs)
@@ -181,7 +179,7 @@ $(foreach f, mconf.o $(lxdialog), \
$(addprefix $(obj)/, mconf.o $(lxdialog)): $(obj)/mconf-cfg
# qconf: Used for the xconfig target based on Qt
-hostprogs-y += qconf
+hostprogs += qconf
qconf-cxxobjs := qconf.o
qconf-objs := images.o $(common-objs)
@@ -197,7 +195,7 @@ $(obj)/%.moc: $(src)/%.h $(obj)/qconf-cfg
$(call cmd,moc)
# gconf: Used for the gconfig target based on GTK+
-hostprogs-y += gconf
+hostprogs += gconf
gconf-objs := gconf.o images.o $(common-objs)
HOSTLDLIBS_gconf = $(shell . $(obj)/gconf-cfg && echo $$libs)
diff --git a/scripts/kconfig/conf.c b/scripts/kconfig/conf.c
index 1f89bf1558ce..f6e548b8f795 100644
--- a/scripts/kconfig/conf.c
+++ b/scripts/kconfig/conf.c
@@ -34,6 +34,8 @@ enum input_mode {
listnewconfig,
helpnewconfig,
olddefconfig,
+ yes2modconfig,
+ mod2yesconfig,
};
static enum input_mode input_mode = oldaskconfig;
@@ -467,6 +469,8 @@ static struct option long_opts[] = {
{"listnewconfig", no_argument, NULL, listnewconfig},
{"helpnewconfig", no_argument, NULL, helpnewconfig},
{"olddefconfig", no_argument, NULL, olddefconfig},
+ {"yes2modconfig", no_argument, NULL, yes2modconfig},
+ {"mod2yesconfig", no_argument, NULL, mod2yesconfig},
{NULL, 0, NULL, 0}
};
@@ -489,6 +493,8 @@ static void conf_usage(const char *progname)
printf(" --allmodconfig New config where all options are answered with mod\n");
printf(" --alldefconfig New config with all symbols set to default\n");
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");
}
int main(int ac, char **av)
@@ -553,6 +559,8 @@ int main(int ac, char **av)
case listnewconfig:
case helpnewconfig:
case olddefconfig:
+ case yes2modconfig:
+ case mod2yesconfig:
break;
case '?':
conf_usage(progname);
@@ -587,6 +595,8 @@ int main(int ac, char **av)
case listnewconfig:
case helpnewconfig:
case olddefconfig:
+ case yes2modconfig:
+ case mod2yesconfig:
conf_read(NULL);
break;
case allnoconfig:
@@ -660,6 +670,12 @@ int main(int ac, char **av)
break;
case savedefconfig:
break;
+ case yes2modconfig:
+ conf_rewrite_mod_or_yes(def_y2m);
+ break;
+ case mod2yesconfig:
+ conf_rewrite_mod_or_yes(def_m2y);
+ break;
case oldaskconfig:
rootEntry = &rootmenu;
conf(&rootmenu);
diff --git a/scripts/kconfig/confdata.c b/scripts/kconfig/confdata.c
index 3569d2dec37c..a39d93e3c6ae 100644
--- a/scripts/kconfig/confdata.c
+++ b/scripts/kconfig/confdata.c
@@ -710,25 +710,6 @@ static struct conf_printer header_printer_cb =
.print_comment = header_print_comment,
};
-/*
- * Tristate printer
- *
- * This printer is used when generating the `include/config/tristate.conf' file.
- */
-static void
-tristate_print_symbol(FILE *fp, struct symbol *sym, const char *value, void *arg)
-{
-
- if (sym->type == S_TRISTATE && *value != 'n')
- fprintf(fp, "%s%s=%c\n", CONFIG_, sym->name, (char)toupper(*value));
-}
-
-static struct conf_printer tristate_printer_cb =
-{
- .print_symbol = tristate_print_symbol,
- .print_comment = kconfig_print_comment,
-};
-
static void conf_write_symbol(FILE *fp, struct symbol *sym,
struct conf_printer *printer, void *printer_arg)
{
@@ -1062,7 +1043,7 @@ int conf_write_autoconf(int overwrite)
struct symbol *sym;
const char *name;
const char *autoconf_name = conf_get_autoconfig_name();
- FILE *out, *tristate, *out_h;
+ FILE *out, *out_h;
int i;
if (!overwrite && is_present(autoconf_name))
@@ -1077,23 +1058,13 @@ int conf_write_autoconf(int overwrite)
if (!out)
return 1;
- tristate = fopen(".tmpconfig_tristate", "w");
- if (!tristate) {
- fclose(out);
- return 1;
- }
-
out_h = fopen(".tmpconfig.h", "w");
if (!out_h) {
fclose(out);
- fclose(tristate);
return 1;
}
conf_write_heading(out, &kconfig_printer_cb, NULL);
-
- conf_write_heading(tristate, &tristate_printer_cb, NULL);
-
conf_write_heading(out_h, &header_printer_cb, NULL);
for_all_symbols(i, sym) {
@@ -1101,15 +1072,11 @@ int conf_write_autoconf(int overwrite)
if (!(sym->flags & SYMBOL_WRITE) || !sym->name)
continue;
- /* write symbol to auto.conf, tristate and header files */
+ /* write symbols to auto.conf and autoconf.h */
conf_write_symbol(out, sym, &kconfig_printer_cb, (void *)1);
-
- conf_write_symbol(tristate, sym, &tristate_printer_cb, (void *)1);
-
conf_write_symbol(out_h, sym, &header_printer_cb, NULL);
}
fclose(out);
- fclose(tristate);
fclose(out_h);
name = getenv("KCONFIG_AUTOHEADER");
@@ -1120,14 +1087,6 @@ int conf_write_autoconf(int overwrite)
if (rename(".tmpconfig.h", name))
return 1;
- name = getenv("KCONFIG_TRISTATE");
- if (!name)
- name = "include/config/tristate.conf";
- if (make_parent_dir(name))
- return 1;
- if (rename(".tmpconfig_tristate", name))
- return 1;
-
if (make_parent_dir(autoconf_name))
return 1;
/*
@@ -1353,7 +1312,7 @@ bool conf_set_all_new_symbols(enum conf_def_mode mode)
sym_calc_value(csym);
if (mode == def_random)
- has_changed = randomize_choice_values(csym);
+ has_changed |= randomize_choice_values(csym);
else {
set_all_choice_values(csym);
has_changed = true;
@@ -1362,3 +1321,18 @@ bool conf_set_all_new_symbols(enum conf_def_mode mode)
return has_changed;
}
+
+void conf_rewrite_mod_or_yes(enum conf_def_mode mode)
+{
+ struct symbol *sym;
+ int i;
+ tristate old_val = (mode == def_y2m) ? yes : mod;
+ tristate new_val = (mode == def_y2m) ? mod : yes;
+
+ for_all_symbols(i, sym) {
+ if (sym_get_type(sym) == S_TRISTATE &&
+ sym->def[S_DEF_USER].tri == old_val)
+ sym->def[S_DEF_USER].tri = new_val;
+ }
+ sym_clear_all_valid();
+}
diff --git a/scripts/kconfig/expr.c b/scripts/kconfig/expr.c
index 9f1de58e9f0c..81ebf8108ca7 100644
--- a/scripts/kconfig/expr.c
+++ b/scripts/kconfig/expr.c
@@ -13,7 +13,6 @@
#define DEBUG_EXPR 0
-static int expr_eq(struct expr *e1, struct expr *e2);
static struct expr *expr_eliminate_yn(struct expr *e);
struct expr *expr_alloc_symbol(struct symbol *sym)
@@ -250,7 +249,7 @@ void expr_eliminate_eq(struct expr **ep1, struct expr **ep2)
* equals some operand in the other (operands do not need to appear in the same
* order), recursively.
*/
-static int expr_eq(struct expr *e1, struct expr *e2)
+int expr_eq(struct expr *e1, struct expr *e2)
{
int res, old_count;
diff --git a/scripts/kconfig/expr.h b/scripts/kconfig/expr.h
index 017843c9a4f4..5c3443692f34 100644
--- a/scripts/kconfig/expr.h
+++ b/scripts/kconfig/expr.h
@@ -191,7 +191,6 @@ enum prop_type {
struct property {
struct property *next; /* next property - null if last */
- struct symbol *sym; /* the symbol for which the property is associated */
enum prop_type type; /* type of property */
const char *text; /* the prompt value - P_PROMPT, P_MENU, P_COMMENT */
struct expr_value visible;
@@ -301,6 +300,7 @@ struct expr *expr_alloc_or(struct expr *e1, struct expr *e2);
struct expr *expr_copy(const struct expr *org);
void expr_free(struct expr *e);
void expr_eliminate_eq(struct expr **ep1, struct expr **ep2);
+int expr_eq(struct expr *e1, struct expr *e2);
tristate expr_calc_value(struct expr *e);
struct expr *expr_trans_bool(struct expr *e);
struct expr *expr_eliminate_dups(struct expr *e);
diff --git a/scripts/kconfig/gconf.c b/scripts/kconfig/gconf.c
index e36b342f1065..5527482c3077 100644
--- a/scripts/kconfig/gconf.c
+++ b/scripts/kconfig/gconf.c
@@ -18,6 +18,7 @@
#include <stdio.h>
#include <string.h>
+#include <strings.h>
#include <unistd.h>
#include <time.h>
diff --git a/scripts/kconfig/lkc.h b/scripts/kconfig/lkc.h
index 4fb16f316626..d4ca8297364f 100644
--- a/scripts/kconfig/lkc.h
+++ b/scripts/kconfig/lkc.h
@@ -34,6 +34,8 @@ enum conf_def_mode {
def_default,
def_yes,
def_mod,
+ def_y2m,
+ def_m2y,
def_no,
def_random
};
@@ -52,6 +54,7 @@ const char *conf_get_configname(void);
void sym_set_change_count(int count);
void sym_add_change_count(int count);
bool conf_set_all_new_symbols(enum conf_def_mode mode);
+void conf_rewrite_mod_or_yes(enum conf_def_mode mode);
void set_all_choice_values(struct symbol *csym);
/* confdata.c and expr.c */
@@ -112,7 +115,6 @@ struct symbol *sym_choice_default(struct symbol *sym);
struct property *sym_get_range_prop(struct symbol *sym);
const char *sym_get_string_default(struct symbol *sym);
struct symbol *sym_check_deps(struct symbol *sym);
-struct property *prop_alloc(enum prop_type type, struct symbol *sym);
struct symbol *prop_get_symbol(struct property *prop);
static inline tristate sym_get_tristate_value(struct symbol *sym)
diff --git a/scripts/kconfig/mconf.c b/scripts/kconfig/mconf.c
index 49c26ea9dd98..4063dbc1b927 100644
--- a/scripts/kconfig/mconf.c
+++ b/scripts/kconfig/mconf.c
@@ -15,6 +15,7 @@
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
+#include <strings.h>
#include <signal.h>
#include <unistd.h>
diff --git a/scripts/kconfig/menu.c b/scripts/kconfig/menu.c
index d9d16469859a..e436ba44c9c5 100644
--- a/scripts/kconfig/menu.c
+++ b/scripts/kconfig/menu.c
@@ -124,61 +124,76 @@ void menu_set_type(int type)
sym_type_name(sym->type), sym_type_name(type));
}
-static struct property *menu_add_prop(enum prop_type type, char *prompt, struct expr *expr, struct expr *dep)
+static struct property *menu_add_prop(enum prop_type type, struct expr *expr,
+ struct expr *dep)
{
- struct property *prop = prop_alloc(type, current_entry->sym);
+ struct property *prop;
+ prop = xmalloc(sizeof(*prop));
+ memset(prop, 0, sizeof(*prop));
+ prop->type = type;
+ prop->file = current_file;
+ prop->lineno = zconf_lineno();
prop->menu = current_entry;
prop->expr = expr;
prop->visible.expr = dep;
- if (prompt) {
- if (isspace(*prompt)) {
- prop_warn(prop, "leading whitespace ignored");
- while (isspace(*prompt))
- prompt++;
- }
- if (current_entry->prompt && current_entry != &rootmenu)
- prop_warn(prop, "prompt redefined");
+ /* append property to the prop list of symbol */
+ if (current_entry->sym) {
+ struct property **propp;
- /* Apply all upper menus' visibilities to actual prompts. */
- if(type == P_PROMPT) {
- struct menu *menu = current_entry;
+ for (propp = &current_entry->sym->prop;
+ *propp;
+ propp = &(*propp)->next)
+ ;
+ *propp = prop;
+ }
- while ((menu = menu->parent) != NULL) {
- struct expr *dup_expr;
+ return prop;
+}
- if (!menu->visibility)
- continue;
- /*
- * Do not add a reference to the
- * menu's visibility expression but
- * use a copy of it. Otherwise the
- * expression reduction functions
- * will modify expressions that have
- * multiple references which can
- * cause unwanted side effects.
- */
- dup_expr = expr_copy(menu->visibility);
+struct property *menu_add_prompt(enum prop_type type, char *prompt,
+ struct expr *dep)
+{
+ struct property *prop = menu_add_prop(type, NULL, dep);
- prop->visible.expr
- = expr_alloc_and(prop->visible.expr,
- dup_expr);
- }
- }
+ if (isspace(*prompt)) {
+ prop_warn(prop, "leading whitespace ignored");
+ while (isspace(*prompt))
+ prompt++;
+ }
+ if (current_entry->prompt)
+ prop_warn(prop, "prompt redefined");
- current_entry->prompt = prop;
+ /* Apply all upper menus' visibilities to actual prompts. */
+ if (type == P_PROMPT) {
+ struct menu *menu = current_entry;
+
+ while ((menu = menu->parent) != NULL) {
+ struct expr *dup_expr;
+
+ if (!menu->visibility)
+ continue;
+ /*
+ * Do not add a reference to the menu's visibility
+ * expression but use a copy of it. Otherwise the
+ * expression reduction functions will modify
+ * expressions that have multiple references which
+ * can cause unwanted side effects.
+ */
+ dup_expr = expr_copy(menu->visibility);
+
+ prop->visible.expr = expr_alloc_and(prop->visible.expr,
+ dup_expr);
+ }
}
+
+ current_entry->prompt = prop;
prop->text = prompt;
return prop;
}
-struct property *menu_add_prompt(enum prop_type type, char *prompt, struct expr *dep)
-{
- return menu_add_prop(type, prompt, NULL, dep);
-}
-
void menu_add_visibility(struct expr *expr)
{
current_entry->visibility = expr_alloc_and(current_entry->visibility,
@@ -187,12 +202,12 @@ void menu_add_visibility(struct expr *expr)
void menu_add_expr(enum prop_type type, struct expr *expr, struct expr *dep)
{
- menu_add_prop(type, NULL, expr, dep);
+ menu_add_prop(type, expr, dep);
}
void menu_add_symbol(enum prop_type type, struct symbol *sym, struct expr *dep)
{
- menu_add_prop(type, NULL, expr_alloc_symbol(sym), dep);
+ menu_add_prop(type, expr_alloc_symbol(sym), dep);
}
void menu_add_option_modules(void)
@@ -326,12 +341,10 @@ void menu_finalize(struct menu *parent)
* choice value symbols.
*/
parentdep = expr_alloc_symbol(sym);
- } else if (parent->prompt)
- /* Menu node for 'menu' */
- parentdep = parent->prompt->visible.expr;
- else
- /* Menu node for 'if' */
+ } else {
+ /* Menu node for 'menu', 'if' */
parentdep = parent->dep;
+ }
/* For each child menu node... */
for (menu = parent->list; menu; menu = menu->next) {
@@ -698,6 +711,21 @@ const char *menu_get_help(struct menu *menu)
return "";
}
+static void get_def_str(struct gstr *r, struct menu *menu)
+{
+ str_printf(r, "Defined at %s:%d\n",
+ menu->file->name, menu->lineno);
+}
+
+static void get_dep_str(struct gstr *r, struct expr *expr, const char *prefix)
+{
+ if (!expr_is_yes(expr)) {
+ str_append(r, prefix);
+ expr_gstr_print(expr, r);
+ str_append(r, "\n");
+ }
+}
+
static void get_prompt_str(struct gstr *r, struct property *prop,
struct list_head *head)
{
@@ -705,7 +733,20 @@ static void get_prompt_str(struct gstr *r, struct property *prop,
struct menu *submenu[8], *menu, *location = NULL;
struct jump_key *jump = NULL;
- str_printf(r, "Prompt: %s\n", prop->text);
+ str_printf(r, " Prompt: %s\n", prop->text);
+
+ get_dep_str(r, prop->menu->dep, " Depends on: ");
+ /*
+ * Most prompts in Linux have visibility that exactly matches their
+ * dependencies. For these, we print only the dependencies to improve
+ * readability. However, prompts with inline "if" expressions and
+ * prompts with a parent that has a "visible if" expression have
+ * differing dependencies and visibility. In these rare cases, we
+ * print both.
+ */
+ if (!expr_eq(prop->menu->dep, prop->visible.expr))
+ get_dep_str(r, prop->visible.expr, " Visible if: ");
+
menu = prop->menu->parent;
for (i = 0; menu != &rootmenu && i < 8; menu = menu->parent) {
bool accessible = menu_is_visible(menu);
@@ -755,18 +796,6 @@ static void get_prompt_str(struct gstr *r, struct property *prop,
}
}
-/*
- * get property of type P_SYMBOL
- */
-static struct property *get_symbol_prop(struct symbol *sym)
-{
- struct property *prop = NULL;
-
- for_all_properties(sym, prop, P_SYMBOL)
- break;
- return prop;
-}
-
static void get_symbol_props_str(struct gstr *r, struct symbol *sym,
enum prop_type tok, const char *prefix)
{
@@ -806,32 +835,34 @@ static void get_symbol_str(struct gstr *r, struct symbol *sym,
}
}
}
- for_all_prompts(sym, prop)
- get_prompt_str(r, prop, head);
-
- prop = get_symbol_prop(sym);
- if (prop) {
- str_printf(r, " Defined at %s:%d\n", prop->menu->file->name,
- prop->menu->lineno);
- if (!expr_is_yes(prop->visible.expr)) {
- str_append(r, " Depends on: ");
- expr_gstr_print(prop->visible.expr, r);
- str_append(r, "\n");
+
+ /* Print the definitions with prompts before the ones without */
+ for_all_properties(sym, prop, P_SYMBOL) {
+ if (prop->menu->prompt) {
+ get_def_str(r, prop->menu);
+ get_prompt_str(r, prop->menu->prompt, head);
+ }
+ }
+
+ for_all_properties(sym, prop, P_SYMBOL) {
+ if (!prop->menu->prompt) {
+ get_def_str(r, prop->menu);
+ get_dep_str(r, prop->menu->dep, " Depends on: ");
}
}
- get_symbol_props_str(r, sym, P_SELECT, " Selects: ");
+ get_symbol_props_str(r, sym, P_SELECT, "Selects: ");
if (sym->rev_dep.expr) {
- expr_gstr_print_revdep(sym->rev_dep.expr, r, yes, " Selected by [y]:\n");
- expr_gstr_print_revdep(sym->rev_dep.expr, r, mod, " Selected by [m]:\n");
- expr_gstr_print_revdep(sym->rev_dep.expr, r, no, " Selected by [n]:\n");
+ expr_gstr_print_revdep(sym->rev_dep.expr, r, yes, "Selected by [y]:\n");
+ expr_gstr_print_revdep(sym->rev_dep.expr, r, mod, "Selected by [m]:\n");
+ expr_gstr_print_revdep(sym->rev_dep.expr, r, no, "Selected by [n]:\n");
}
- get_symbol_props_str(r, sym, P_IMPLY, " Implies: ");
+ get_symbol_props_str(r, sym, P_IMPLY, "Implies: ");
if (sym->implied.expr) {
- expr_gstr_print_revdep(sym->implied.expr, r, yes, " Implied by [y]:\n");
- expr_gstr_print_revdep(sym->implied.expr, r, mod, " Implied by [m]:\n");
- expr_gstr_print_revdep(sym->implied.expr, r, no, " Implied by [n]:\n");
+ expr_gstr_print_revdep(sym->implied.expr, r, yes, "Implied by [y]:\n");
+ expr_gstr_print_revdep(sym->implied.expr, r, mod, "Implied by [m]:\n");
+ expr_gstr_print_revdep(sym->implied.expr, r, no, "Implied by [n]:\n");
}
str_append(r, "\n\n");
diff --git a/scripts/kconfig/nconf.c b/scripts/kconfig/nconf.c
index b7c1ef757178..daf1c1506ec4 100644
--- a/scripts/kconfig/nconf.c
+++ b/scripts/kconfig/nconf.c
@@ -8,6 +8,7 @@
#define _GNU_SOURCE
#endif
#include <string.h>
+#include <strings.h>
#include <stdlib.h>
#include "lkc.h"
diff --git a/scripts/kconfig/parser.y b/scripts/kconfig/parser.y
index b3eff9613cf8..708b6c4b13ca 100644
--- a/scripts/kconfig/parser.y
+++ b/scripts/kconfig/parser.y
@@ -90,7 +90,6 @@ static struct menu *current_menu, *current_entry;
%left T_LESS T_LESS_EQUAL T_GREATER T_GREATER_EQUAL
%nonassoc T_NOT
-%type <string> prompt
%type <symbol> nonconst_symbol
%type <symbol> symbol
%type <type> type logic_type default
@@ -113,7 +112,7 @@ input: mainmenu_stmt stmt_list | stmt_list;
/* mainmenu entry */
-mainmenu_stmt: T_MAINMENU prompt T_EOL
+mainmenu_stmt: T_MAINMENU T_WORD_QUOTE T_EOL
{
menu_add_prompt(P_MENU, $2, NULL);
};
@@ -181,7 +180,7 @@ config_option: type prompt_stmt_opt T_EOL
$1);
};
-config_option: T_PROMPT prompt if_expr T_EOL
+config_option: T_PROMPT T_WORD_QUOTE if_expr T_EOL
{
menu_add_prompt(P_PROMPT, $2, $3);
printd(DEBUG_PARSE, "%s:%d:prompt\n", zconf_curname(), zconf_lineno());
@@ -265,7 +264,7 @@ choice_option_list:
| choice_option_list help
;
-choice_option: T_PROMPT prompt if_expr T_EOL
+choice_option: T_PROMPT T_WORD_QUOTE if_expr T_EOL
{
menu_add_prompt(P_PROMPT, $2, $3);
printd(DEBUG_PARSE, "%s:%d:prompt\n", zconf_curname(), zconf_lineno());
@@ -334,7 +333,7 @@ if_stmt: if_entry stmt_list if_end
/* menu entry */
-menu: T_MENU prompt T_EOL
+menu: T_MENU T_WORD_QUOTE T_EOL
{
menu_add_entry(NULL);
menu_add_prompt(P_MENU, $2, NULL);
@@ -363,7 +362,7 @@ menu_option_list:
| menu_option_list depends
;
-source_stmt: T_SOURCE prompt T_EOL
+source_stmt: T_SOURCE T_WORD_QUOTE T_EOL
{
printd(DEBUG_PARSE, "%s:%d:source %s\n", zconf_curname(), zconf_lineno(), $2);
zconf_nextfile($2);
@@ -372,7 +371,7 @@ source_stmt: T_SOURCE prompt T_EOL
/* comment entry */
-comment: T_COMMENT prompt T_EOL
+comment: T_COMMENT T_WORD_QUOTE T_EOL
{
menu_add_entry(NULL);
menu_add_prompt(P_COMMENT, $2, NULL);
@@ -429,15 +428,11 @@ visible: T_VISIBLE if_expr T_EOL
prompt_stmt_opt:
/* empty */
- | prompt if_expr
+ | T_WORD_QUOTE if_expr
{
menu_add_prompt(P_PROMPT, $1, $2);
};
-prompt: T_WORD
- | T_WORD_QUOTE
-;
-
end: T_ENDMENU T_EOL { $$ = "menu"; }
| T_ENDCHOICE T_EOL { $$ = "choice"; }
| T_ENDIF T_EOL { $$ = "if"; }
@@ -665,7 +660,7 @@ static void print_symbol(FILE *out, struct menu *menu)
break;
case P_SYMBOL:
fputs( " symbol ", out);
- fprintf(out, "%s\n", prop->sym->name);
+ fprintf(out, "%s\n", prop->menu->sym->name);
break;
default:
fprintf(out, " unknown prop %d!\n", prop->type);
diff --git a/scripts/kconfig/qconf.cc b/scripts/kconfig/qconf.cc
index 82773cc35d35..c0ac8f7b5f1a 100644
--- a/scripts/kconfig/qconf.cc
+++ b/scripts/kconfig/qconf.cc
@@ -154,9 +154,9 @@ void ConfigItem::updateMenu(void)
if (!sym_is_changeable(sym) && list->optMode == normalOpt) {
setPixmap(promptColIdx, QIcon());
- setText(noColIdx, QString::null);
- setText(modColIdx, QString::null);
- setText(yesColIdx, QString::null);
+ setText(noColIdx, QString());
+ setText(modColIdx, QString());
+ setText(yesColIdx, QString());
break;
}
expr = sym_get_tristate_value(sym);
@@ -276,7 +276,7 @@ void ConfigLineEdit::show(ConfigItem* i)
if (sym_get_string_value(item->menu->sym))
setText(QString::fromLocal8Bit(sym_get_string_value(item->menu->sym)));
else
- setText(QString::null);
+ setText(QString());
Parent::show();
setFocus();
}
@@ -309,8 +309,6 @@ ConfigList::ConfigList(ConfigView* p, const char *name)
showName(false), showRange(false), showData(false), mode(singleMode), optMode(normalOpt),
rootEntry(0), headerPopup(0)
{
- int i;
-
setObjectName(name);
setSortingEnabled(false);
setRootIsDecorated(true);
@@ -318,7 +316,10 @@ ConfigList::ConfigList(ConfigView* p, const char *name)
setVerticalScrollMode(ScrollPerPixel);
setHorizontalScrollMode(ScrollPerPixel);
- setHeaderLabels(QStringList() << "Option" << "Name" << "N" << "M" << "Y" << "Value");
+ if (mode == symbolMode)
+ setHeaderLabels(QStringList() << "Item" << "Name" << "N" << "M" << "Y" << "Value");
+ else
+ setHeaderLabels(QStringList() << "Option" << "Name" << "N" << "M" << "Y" << "Value");
connect(this, SIGNAL(itemSelectionChanged(void)),
SLOT(updateSelection(void)));
@@ -399,6 +400,11 @@ void ConfigList::updateSelection(void)
struct menu *menu;
enum prop_type type;
+ if (mode == symbolMode)
+ setHeaderLabels(QStringList() << "Item" << "Name" << "N" << "M" << "Y" << "Value");
+ else
+ setHeaderLabels(QStringList() << "Option" << "Name" << "N" << "M" << "Y" << "Value");
+
if (selectedItems().count() == 0)
return;
@@ -627,7 +633,7 @@ void ConfigList::updateMenuList(ConfigItem *parent, struct menu* menu)
last = item;
continue;
}
- hide:
+hide:
if (item && item->menu == child) {
last = parent->firstChild();
if (last == item)
@@ -692,7 +698,7 @@ void ConfigList::updateMenuList(ConfigList *parent, struct menu* menu)
last = item;
continue;
}
- hide:
+hide:
if (item && item->menu == child) {
last = (ConfigItem*)parent->topLevelItem(0);
if (last == item)
@@ -736,7 +742,10 @@ void ConfigList::keyPressEvent(QKeyEvent* ev)
type = menu->prompt ? menu->prompt->type : P_UNKNOWN;
if (type == P_MENU && rootEntry != menu &&
mode != fullMode && mode != menuMode) {
- emit menuSelected(menu);
+ if (mode == menuMode)
+ emit menuSelected(menu);
+ else
+ emit itemSelected(menu);
break;
}
case Qt::Key_Space:
@@ -828,7 +837,7 @@ void ConfigList::mouseMoveEvent(QMouseEvent* e)
void ConfigList::mouseDoubleClickEvent(QMouseEvent* e)
{
- QPoint p = e->pos(); // TODO: Check if this works(was contentsToViewport).
+ QPoint p = e->pos();
ConfigItem* item = (ConfigItem*)itemAt(p);
struct menu *menu;
enum prop_type ptype;
@@ -843,9 +852,12 @@ void ConfigList::mouseDoubleClickEvent(QMouseEvent* e)
if (!menu)
goto skip;
ptype = menu->prompt ? menu->prompt->type : P_UNKNOWN;
- if (ptype == P_MENU && (mode == singleMode || mode == symbolMode))
- emit menuSelected(menu);
- else if (menu->sym)
+ if (ptype == P_MENU) {
+ if (mode == singleMode)
+ emit itemSelected(menu);
+ else if (mode == symbolMode)
+ emit menuSelected(menu);
+ } else if (menu->sym)
changeValue(item);
skip:
@@ -1225,10 +1237,11 @@ QMenu* ConfigInfoView::createStandardContextMenu(const QPoint & pos)
{
QMenu* popup = Parent::createStandardContextMenu(pos);
QAction* action = new QAction("Show Debug Info", popup);
- action->setCheckable(true);
- connect(action, SIGNAL(toggled(bool)), SLOT(setShowDebug(bool)));
- connect(this, SIGNAL(showDebugChanged(bool)), action, SLOT(setOn(bool)));
- action->setChecked(showDebug());
+
+ action->setCheckable(true);
+ connect(action, SIGNAL(toggled(bool)), SLOT(setShowDebug(bool)));
+ connect(this, SIGNAL(showDebugChanged(bool)), action, SLOT(setOn(bool)));
+ action->setChecked(showDebug());
popup->addSeparator();
popup->addAction(action);
return popup;
@@ -1354,21 +1367,32 @@ ConfigMainWindow::ConfigMainWindow(void)
if ((x.isValid())&&(y.isValid()))
move(x.toInt(), y.toInt());
- split1 = new QSplitter(this);
+ QWidget *widget = new QWidget(this);
+ QVBoxLayout *layout = new QVBoxLayout(widget);
+ setCentralWidget(widget);
+
+ split1 = new QSplitter(widget);
split1->setOrientation(Qt::Horizontal);
- setCentralWidget(split1);
+ split1->setChildrenCollapsible(false);
- menuView = new ConfigView(split1, "menu");
+ menuView = new ConfigView(widget, "menu");
menuList = menuView->list;
- split2 = new QSplitter(split1);
+ split2 = new QSplitter(widget);
+ split2->setChildrenCollapsible(false);
split2->setOrientation(Qt::Vertical);
// create config tree
- configView = new ConfigView(split2, "config");
+ configView = new ConfigView(widget, "config");
configList = configView->list;
- helpText = new ConfigInfoView(split2, "help");
+ helpText = new ConfigInfoView(widget, "help");
+
+ layout->addWidget(split2);
+ split2->addWidget(split1);
+ split1->addWidget(configView);
+ split1->addWidget(menuView);
+ split2->addWidget(helpText);
setTabOrder(configList, helpText);
configList->setFocus();
@@ -1486,6 +1510,8 @@ ConfigMainWindow::ConfigMainWindow(void)
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 *)),
@@ -1582,15 +1608,26 @@ void ConfigMainWindow::searchConfig(void)
searchWindow->show();
}
-void ConfigMainWindow::changeMenu(struct menu *menu)
+void ConfigMainWindow::changeItens(struct menu *menu)
{
configList->setRootMenu(menu);
+
if (configList->rootEntry->parent == &rootmenu)
backAction->setEnabled(false);
else
backAction->setEnabled(true);
}
+void ConfigMainWindow::changeMenu(struct menu *menu)
+{
+ menuList->setRootMenu(menu);
+
+ if (menuList->rootEntry->parent == &rootmenu)
+ backAction->setEnabled(false);
+ else
+ backAction->setEnabled(true);
+}
+
void ConfigMainWindow::setMenuLink(struct menu *menu)
{
struct menu *parent;
@@ -1700,14 +1737,14 @@ void ConfigMainWindow::showSplitView(void)
fullViewAction->setEnabled(true);
fullViewAction->setChecked(false);
- configList->mode = symbolMode;
+ configList->mode = menuMode;
if (configList->rootEntry == &rootmenu)
configList->updateListAll();
else
configList->setRootMenu(&rootmenu);
configList->setAllOpen(true);
configApp->processEvents();
- menuList->mode = menuMode;
+ menuList->mode = symbolMode;
menuList->setRootMenu(&rootmenu);
menuList->setAllOpen(true);
menuView->show();
@@ -1735,7 +1772,6 @@ void ConfigMainWindow::showFullView(void)
/*
* ask for saving configuration before quitting
- * TODO ask only when something changed
*/
void ConfigMainWindow::closeEvent(QCloseEvent* e)
{
diff --git a/scripts/kconfig/qconf.h b/scripts/kconfig/qconf.h
index 45bfe9b2b966..c879d79ce817 100644
--- a/scripts/kconfig/qconf.h
+++ b/scripts/kconfig/qconf.h
@@ -71,6 +71,7 @@ public slots:
signals:
void menuChanged(struct menu *menu);
void menuSelected(struct menu *menu);
+ void itemSelected(struct menu *menu);
void parentSelected(void);
void gotFocus(struct menu *);
@@ -298,6 +299,7 @@ public:
ConfigMainWindow(void);
public slots:
void changeMenu(struct menu *);
+ void changeItens(struct menu *);
void setMenuLink(struct menu *);
void listFocusChanged(void);
void goBack(void);
diff --git a/scripts/kconfig/streamline_config.pl b/scripts/kconfig/streamline_config.pl
index 08d76d7b3b81..e2f8504f5a2d 100755
--- a/scripts/kconfig/streamline_config.pl
+++ b/scripts/kconfig/streamline_config.pl
@@ -56,8 +56,6 @@ sub dprint {
print STDERR @_;
}
-my $config = ".config";
-
my $uname = `uname -r`;
chomp $uname;
@@ -374,7 +372,7 @@ if (defined($lsmod_file)) {
$lsmod = "$dir/lsmod";
last;
}
-}
+ }
if (!defined($lsmod)) {
# try just the path
$lsmod = "lsmod";
diff --git a/scripts/kconfig/symbol.c b/scripts/kconfig/symbol.c
index f56eec5ea4c7..3dc81397d003 100644
--- a/scripts/kconfig/symbol.c
+++ b/scripts/kconfig/symbol.c
@@ -221,7 +221,7 @@ static void sym_calc_visibility(struct symbol *sym)
sym_set_changed(sym);
}
tri = no;
- if (sym->implied.expr && sym->dir_dep.tri != no)
+ if (sym->implied.expr)
tri = expr_calc_value(sym->implied.expr);
if (tri == mod && sym_get_type(sym) == S_BOOLEAN)
tri = yes;
@@ -394,6 +394,8 @@ void sym_calc_value(struct symbol *sym)
if (sym->implied.tri != no) {
sym->flags |= SYMBOL_WRITE;
newval.tri = EXPR_OR(newval.tri, sym->implied.tri);
+ newval.tri = EXPR_AND(newval.tri,
+ sym->dir_dep.tri);
}
}
calc_newval:
@@ -401,8 +403,7 @@ void sym_calc_value(struct symbol *sym)
sym_warn_unmet_dep(sym);
newval.tri = EXPR_OR(newval.tri, sym->rev_dep.tri);
}
- if (newval.tri == mod &&
- (sym_get_type(sym) == S_BOOLEAN || sym->implied.tri == yes))
+ if (newval.tri == mod && sym_get_type(sym) == S_BOOLEAN)
newval.tri = yes;
break;
case S_STRING:
@@ -484,8 +485,6 @@ bool sym_tristate_within_range(struct symbol *sym, tristate val)
return false;
if (sym->visible <= sym->rev_dep.tri)
return false;
- if (sym->implied.tri == yes && val == mod)
- return false;
if (sym_is_choice_value(sym) && sym->visible == yes)
return val == yes;
return val >= sym->rev_dep.tri && val <= sym->visible;
@@ -1273,28 +1272,6 @@ struct symbol *sym_check_deps(struct symbol *sym)
return sym2;
}
-struct property *prop_alloc(enum prop_type type, struct symbol *sym)
-{
- struct property *prop;
- struct property **propp;
-
- prop = xmalloc(sizeof(*prop));
- memset(prop, 0, sizeof(*prop));
- prop->type = type;
- prop->sym = sym;
- prop->file = current_file;
- prop->lineno = zconf_lineno();
-
- /* append property to the prop list of symbol */
- if (sym) {
- for (propp = &sym->prop; *propp; propp = &(*propp)->next)
- ;
- *propp = prop;
- }
-
- return prop;
-}
-
struct symbol *prop_get_symbol(struct property *prop)
{
if (prop->expr && (prop->expr->type == E_SYMBOL ||
diff --git a/scripts/link-vmlinux.sh b/scripts/link-vmlinux.sh
index 436379940356..d09ab4afbda4 100755
--- a/scripts/link-vmlinux.sh
+++ b/scripts/link-vmlinux.sh
@@ -63,12 +63,18 @@ vmlinux_link()
local lds="${objtree}/${KBUILD_LDS}"
local output=${1}
local objects
+ local strip_debug
info LD ${output}
# skip output file argument
shift
+ # The kallsyms linking does not need debug symbols included.
+ if [ "$output" != "${output#.tmp_vmlinux.kallsyms}" ] ; then
+ strip_debug=-Wl,--strip-debug
+ fi
+
if [ "${SRCARCH}" != "um" ]; then
objects="--whole-archive \
${KBUILD_VMLINUX_OBJS} \
@@ -79,6 +85,7 @@ vmlinux_link()
${@}"
${LD} ${KBUILD_LDFLAGS} ${LDFLAGS_vmlinux} \
+ ${strip_debug#-Wl,} \
-o ${output} \
-T ${lds} ${objects}
else
@@ -91,6 +98,7 @@ vmlinux_link()
${@}"
${CC} ${CFLAGS_vmlinux} \
+ ${strip_debug} \
-o ${output} \
-Wl,-T,${lds} \
${objects} \
@@ -105,33 +113,33 @@ vmlinux_link()
gen_btf()
{
local pahole_ver
- local bin_arch
if ! [ -x "$(command -v ${PAHOLE})" ]; then
- info "BTF" "${1}: pahole (${PAHOLE}) is not available"
+ echo >&2 "BTF: ${1}: pahole (${PAHOLE}) is not available"
return 1
fi
pahole_ver=$(${PAHOLE} --version | sed -E 's/v([0-9]+)\.([0-9]+)/\1\2/')
if [ "${pahole_ver}" -lt "113" ]; then
- info "BTF" "${1}: pahole version $(${PAHOLE} --version) is too old, need at least v1.13"
+ echo >&2 "BTF: ${1}: pahole version $(${PAHOLE} --version) is too old, need at least v1.13"
return 1
fi
- info "BTF" ${2}
vmlinux_link ${1}
+
+ info "BTF" ${2}
LLVM_OBJCOPY=${OBJCOPY} ${PAHOLE} -J ${1}
- # dump .BTF section into raw binary file to link with final vmlinux
- bin_arch=$(LANG=C ${OBJDUMP} -f ${1} | grep architecture | \
- cut -d, -f1 | cut -d' ' -f2)
- bin_format=$(LANG=C ${OBJDUMP} -f ${1} | grep 'file format' | \
- awk '{print $4}')
- ${OBJCOPY} --change-section-address .BTF=0 \
- --set-section-flags .BTF=alloc -O binary \
- --only-section=.BTF ${1} .btf.vmlinux.bin
- ${OBJCOPY} -I binary -O ${bin_format} -B ${bin_arch} \
- --rename-section .data=.BTF .btf.vmlinux.bin ${2}
+ # Create ${2} which contains just .BTF section but no symbols. Add
+ # SHF_ALLOC because .BTF will be part of the vmlinux image. --strip-all
+ # deletes all symbols including __start_BTF and __stop_BTF, which will
+ # be redefined in the linker script. Add 2>/dev/null to suppress GNU
+ # objcopy warnings: "empty loadable segment detected at ..."
+ ${OBJCOPY} --only-section=.BTF --set-section-flags .BTF=alloc,readonly \
+ --strip-all ${1} ${2} 2>/dev/null
+ # Change e_type to ET_REL so that it can be used to link final vmlinux.
+ # Unlike GNU ld, lld does not allow an ET_EXEC input.
+ printf '\1' | dd of=${2} conv=notrunc bs=1 seek=16 status=none
}
# Create ${2} .o file with all symbols from the ${1} object file
@@ -166,8 +174,8 @@ kallsyms()
kallsyms_step()
{
kallsymso_prev=${kallsymso}
- kallsymso=.tmp_kallsyms${1}.o
- kallsyms_vmlinux=.tmp_vmlinux${1}
+ kallsyms_vmlinux=.tmp_vmlinux.kallsyms${1}
+ kallsymso=${kallsyms_vmlinux}.o
vmlinux_link ${kallsyms_vmlinux} "${kallsymso_prev}" ${btf_vmlinux_bin_o}
kallsyms ${kallsyms_vmlinux} ${kallsymso}
@@ -180,9 +188,9 @@ mksysmap()
${CONFIG_SHELL} "${srctree}/scripts/mksysmap" ${1} ${2}
}
-sortextable()
+sorttable()
{
- ${objtree}/scripts/sortextable ${1}
+ ${objtree}/scripts/sorttable ${1}
}
# Delete output files in case of error
@@ -190,7 +198,6 @@ cleanup()
{
rm -f .btf.*
rm -f .tmp_System.map
- rm -f .tmp_kallsyms*
rm -f .tmp_vmlinux*
rm -f System.map
rm -f vmlinux
@@ -239,7 +246,7 @@ else
fi;
# final build of init/
-${MAKE} -f "${srctree}/scripts/Makefile.build" obj=init
+${MAKE} -f "${srctree}/scripts/Makefile.build" obj=init need-builtin=1
#link vmlinux.o
info LD vmlinux.o
@@ -250,12 +257,15 @@ ${MAKE} -f "${srctree}/scripts/Makefile.modpost" MODPOST_VMLINUX=1
info MODINFO modules.builtin.modinfo
${OBJCOPY} -j .modinfo -O binary vmlinux.o modules.builtin.modinfo
+info GEN modules.builtin
+# The second line aids cases where multiple modules share the same object.
+tr '\0' '\n' < modules.builtin.modinfo | sed -n 's/^[[:alnum:]:_]*\.file=//p' |
+ tr ' ' '\n' | uniq | sed -e 's:^:kernel/:' -e 's/$/.ko/' > modules.builtin
btf_vmlinux_bin_o=""
if [ -n "${CONFIG_DEBUG_INFO_BTF}" ]; then
- if gen_btf .tmp_vmlinux.btf .btf.vmlinux.bin.o ; then
- btf_vmlinux_bin_o=.btf.vmlinux.bin.o
- else
+ btf_vmlinux_bin_o=.btf.vmlinux.bin.o
+ if ! gen_btf .tmp_vmlinux.btf $btf_vmlinux_bin_o ; then
echo >&2 "Failed to generate BTF for vmlinux"
echo >&2 "Try to disable CONFIG_DEBUG_INFO_BTF"
exit 1
@@ -304,9 +314,12 @@ fi
vmlinux_link vmlinux "${kallsymso}" ${btf_vmlinux_bin_o}
-if [ -n "${CONFIG_BUILDTIME_EXTABLE_SORT}" ]; then
- info SORTEX vmlinux
- sortextable vmlinux
+if [ -n "${CONFIG_BUILDTIME_TABLE_SORT}" ]; then
+ info SORTTAB vmlinux
+ if ! sorttable vmlinux; then
+ echo >&2 Failed to sort kernel tables
+ exit 1
+ fi
fi
info SYSMAP System.map
diff --git a/scripts/mkcompile_h b/scripts/mkcompile_h
index 3a5a4b210c86..5b80a4699740 100755
--- a/scripts/mkcompile_h
+++ b/scripts/mkcompile_h
@@ -7,20 +7,10 @@ SMP=$3
PREEMPT=$4
PREEMPT_RT=$5
CC=$6
+LD=$7
vecho() { [ "${quiet}" = "silent_" ] || echo "$@" ; }
-# If compile.h exists already and we don't own autoconf.h
-# (i.e. we're not the same user who did make *config), don't
-# modify compile.h
-# So "sudo make install" won't change the "compiled by <user>"
-# do "compiled by root"
-
-if [ -r $TARGET -a ! -O include/generated/autoconf.h ]; then
- vecho " SKIPPED $TARGET"
- exit 0
-fi
-
# Do not expand names
set -f
@@ -72,7 +62,10 @@ UTS_VERSION="$(echo $UTS_VERSION $CONFIG_FLAGS $TIMESTAMP | cut -b -$UTS_LEN)"
printf '#define LINUX_COMPILE_BY "%s"\n' "$LINUX_COMPILE_BY"
echo \#define LINUX_COMPILE_HOST \"$LINUX_COMPILE_HOST\"
- echo \#define LINUX_COMPILER \"`$CC -v 2>&1 | grep ' version ' | sed 's/[[:space:]]*$//'`\"
+ CC_VERSION=$($CC -v 2>&1 | grep ' version ' | sed 's/[[:space:]]*$//')
+ LD_VERSION=$($LD -v | head -n1 | sed 's/(compatible with [^)]*)//' \
+ | sed 's/[[:space:]]*$//')
+ printf '#define LINUX_COMPILER "%s"\n' "$CC_VERSION, $LD_VERSION"
} > .tmpcompile
# Only replace the real compile.h if the new one is different,
diff --git a/scripts/mod/.gitignore b/scripts/mod/.gitignore
index 3bd11b603173..07e4a39f90a6 100644
--- a/scripts/mod/.gitignore
+++ b/scripts/mod/.gitignore
@@ -1,3 +1,4 @@
+# SPDX-License-Identifier: GPL-2.0-only
elfconfig.h
mk_elfconfig
modpost
diff --git a/scripts/mod/Makefile b/scripts/mod/Makefile
index 42c5d50f2bcc..296b6a3878b2 100644
--- a/scripts/mod/Makefile
+++ b/scripts/mod/Makefile
@@ -1,8 +1,8 @@
# SPDX-License-Identifier: GPL-2.0
OBJECT_FILES_NON_STANDARD := y
-hostprogs-y := modpost mk_elfconfig
-always := $(hostprogs-y) empty.o
+hostprogs := modpost mk_elfconfig
+always-y := $(hostprogs) empty.o
modpost-objs := modpost.o file2alias.o sumversion.o
diff --git a/scripts/mod/devicetable-offsets.c b/scripts/mod/devicetable-offsets.c
index 054405b90ba4..010be8ba2116 100644
--- a/scripts/mod/devicetable-offsets.c
+++ b/scripts/mod/devicetable-offsets.c
@@ -145,6 +145,13 @@ int main(void)
DEVID(i2c_device_id);
DEVID_FIELD(i2c_device_id, name);
+ DEVID(i3c_device_id);
+ DEVID_FIELD(i3c_device_id, match_flags);
+ DEVID_FIELD(i3c_device_id, dcr);
+ DEVID_FIELD(i3c_device_id, manuf_id);
+ DEVID_FIELD(i3c_device_id, part_id);
+ DEVID_FIELD(i3c_device_id, extra_info);
+
DEVID(spi_device_id);
DEVID_FIELD(spi_device_id, name);
@@ -231,5 +238,8 @@ int main(void)
DEVID(wmi_device_id);
DEVID_FIELD(wmi_device_id, guid_string);
+ DEVID(mhi_device_id);
+ DEVID_FIELD(mhi_device_id, chan);
+
return 0;
}
diff --git a/scripts/mod/file2alias.c b/scripts/mod/file2alias.c
index c91eba751804..02d5d79da284 100644
--- a/scripts/mod/file2alias.c
+++ b/scripts/mod/file2alias.c
@@ -919,6 +919,24 @@ static int do_i2c_entry(const char *filename, void *symval,
return 1;
}
+static int do_i3c_entry(const char *filename, void *symval,
+ char *alias)
+{
+ DEF_FIELD(symval, i3c_device_id, match_flags);
+ DEF_FIELD(symval, i3c_device_id, dcr);
+ DEF_FIELD(symval, i3c_device_id, manuf_id);
+ DEF_FIELD(symval, i3c_device_id, part_id);
+ DEF_FIELD(symval, i3c_device_id, extra_info);
+
+ strcpy(alias, "i3c:");
+ ADD(alias, "dcr", match_flags & I3C_MATCH_DCR, dcr);
+ ADD(alias, "manuf", match_flags & I3C_MATCH_MANUF, manuf_id);
+ ADD(alias, "part", match_flags & I3C_MATCH_PART, part_id);
+ ADD(alias, "ext", match_flags & I3C_MATCH_EXTRA_INFO, extra_info);
+
+ return 1;
+}
+
/* Looks like: spi:S */
static int do_spi_entry(const char *filename, void *symval,
char *alias)
@@ -1335,6 +1353,15 @@ static int do_wmi_entry(const char *filename, void *symval, char *alias)
return 1;
}
+/* Looks like: mhi:S */
+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;
+}
+
/* Does namelen bytes of name exactly match the symbol? */
static bool sym_is(const char *name, unsigned namelen, const char *symbol)
{
@@ -1386,6 +1413,7 @@ static const struct devtable devtable[] = {
{"vmbus", SIZE_hv_vmbus_device_id, do_vmbus_entry},
{"rpmsg", SIZE_rpmsg_device_id, do_rpmsg_entry},
{"i2c", SIZE_i2c_device_id, do_i2c_entry},
+ {"i3c", SIZE_i3c_device_id, do_i3c_entry},
{"spi", SIZE_spi_device_id, do_spi_entry},
{"dmi", SIZE_dmi_system_id, do_dmi_entry},
{"platform", SIZE_platform_device_id, do_platform_entry},
@@ -1407,6 +1435,7 @@ static const struct devtable devtable[] = {
{"typec", SIZE_typec_device_id, do_typec_entry},
{"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},
};
/* Create MODULE_ALIAS() statements.
diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c
index 6e892c93d104..5c3c50c5ec52 100644
--- a/scripts/mod/modpost.c
+++ b/scripts/mod/modpost.c
@@ -12,6 +12,7 @@
*/
#define _GNU_SOURCE
+#include <elf.h>
#include <stdio.h>
#include <ctype.h>
#include <string.h>
@@ -38,6 +39,8 @@ static int sec_mismatch_count = 0;
static int sec_mismatch_fatal = 0;
/* 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;
enum export {
export_plain, export_unused, export_gpl,
@@ -50,41 +53,33 @@ enum export {
#define MODULE_NAME_LEN (64 - sizeof(Elf_Addr))
-#define PRINTF __attribute__ ((format (printf, 1, 2)))
-
-PRINTF void fatal(const char *fmt, ...)
+void __attribute__((format(printf, 2, 3)))
+modpost_log(enum loglevel loglevel, const char *fmt, ...)
{
va_list arglist;
- fprintf(stderr, "FATAL: ");
-
- va_start(arglist, fmt);
- vfprintf(stderr, fmt, arglist);
- va_end(arglist);
-
- exit(1);
-}
-
-PRINTF void warn(const char *fmt, ...)
-{
- va_list arglist;
+ switch (loglevel) {
+ case LOG_WARN:
+ fprintf(stderr, "WARNING: ");
+ break;
+ case LOG_ERROR:
+ fprintf(stderr, "ERROR: ");
+ break;
+ case LOG_FATAL:
+ fprintf(stderr, "FATAL: ");
+ break;
+ default: /* invalid loglevel, ignore */
+ break;
+ }
- fprintf(stderr, "WARNING: ");
+ fprintf(stderr, "modpost: ");
va_start(arglist, fmt);
vfprintf(stderr, fmt, arglist);
va_end(arglist);
-}
-
-PRINTF void merror(const char *fmt, ...)
-{
- va_list arglist;
- fprintf(stderr, "ERROR: ");
-
- va_start(arglist, fmt);
- vfprintf(stderr, fmt, arglist);
- va_end(arglist);
+ if (loglevel == LOG_FATAL)
+ exit(1);
}
static inline bool strends(const char *str, const char *postfix)
@@ -112,7 +107,7 @@ static int is_vmlinux(const char *modname)
void *do_nofail(void *ptr, const char *expr)
{
if (!ptr)
- fatal("modpost: Memory allocation failure: %s.\n", expr);
+ fatal("Memory allocation failure: %s.\n", expr);
return ptr;
}
@@ -307,7 +302,8 @@ static const char *sec_name(struct elf_info *elf, int secindex)
static void *sym_get_data(const struct elf_info *info, const Elf_Sym *sym)
{
- Elf_Shdr *sechdr = &info->sechdrs[sym->st_shndx];
+ unsigned int secindex = get_secindex(info, sym);
+ Elf_Shdr *sechdr = &info->sechdrs[secindex];
unsigned long offset;
offset = sym->st_value;
@@ -729,12 +725,6 @@ static void handle_symbol(struct module *mod, struct elf_info *info,
break;
if (ignore_undef_symbol(info, symname))
break;
-/* cope with newer glibc (2.3.4 or higher) STT_ definition in elf.h */
-#if defined(STT_REGISTER) || defined(STT_SPARC_REGISTER)
-/* add compatibility with older glibc */
-#ifndef STT_SPARC_REGISTER
-#define STT_SPARC_REGISTER STT_REGISTER
-#endif
if (info->hdr->e_machine == EM_SPARC ||
info->hdr->e_machine == EM_SPARCV9) {
/* Ignore register directives. */
@@ -747,7 +737,6 @@ static void handle_symbol(struct module *mod, struct elf_info *info,
symname = munged;
}
}
-#endif
mod->unres = alloc_symbol(symname,
ELF_ST_BIND(sym->st_info) == STB_WEAK,
@@ -2027,7 +2016,7 @@ static void read_symbols(const char *modname)
license = get_modinfo(&info, "license");
if (!license && !is_vmlinux(modname))
- warn("modpost: missing MODULE_LICENSE() in %s\n"
+ warn("missing MODULE_LICENSE() in %s\n"
"see include/linux/module.h for "
"more information\n", modname);
while (license) {
@@ -2158,15 +2147,15 @@ static void check_for_gpl_usage(enum export exp, const char *m, const char *s)
switch (exp) {
case export_gpl:
- fatal("modpost: GPL-incompatible module %s%s "
+ fatal("GPL-incompatible module %s%s "
"uses GPL-only symbol '%s'\n", m, e, s);
break;
case export_unused_gpl:
- fatal("modpost: GPL-incompatible module %s%s "
+ fatal("GPL-incompatible module %s%s "
"uses GPL-only symbol marked UNUSED '%s'\n", m, e, s);
break;
case export_gpl_future:
- warn("modpost: GPL-incompatible module %s%s "
+ warn("GPL-incompatible module %s%s "
"uses future GPL-only symbol '%s'\n", m, e, s);
break;
case export_plain:
@@ -2184,7 +2173,7 @@ static void check_for_unused(enum export exp, const char *m, const char *s)
switch (exp) {
case export_unused:
case export_unused_gpl:
- warn("modpost: module %s%s "
+ warn("module %s%s "
"uses symbol '%s' marked UNUSED\n", m, e, s);
break;
default:
@@ -2203,14 +2192,11 @@ static int check_exports(struct module *mod)
exp = find_symbol(s->name);
if (!exp || exp->module == mod) {
if (have_vmlinux && !s->weak) {
- if (warn_unresolved) {
- warn("\"%s\" [%s.ko] undefined!\n",
- s->name, mod->name);
- } else {
- merror("\"%s\" [%s.ko] undefined!\n",
- s->name, mod->name);
+ modpost_log(warn_unresolved ? LOG_WARN : LOG_ERROR,
+ "\"%s\" [%s.ko] undefined!\n",
+ s->name, mod->name);
+ if (!warn_unresolved)
err = 1;
- }
}
continue;
}
@@ -2222,8 +2208,11 @@ static int check_exports(struct module *mod)
if (exp->namespace &&
!module_imports_namespace(mod, exp->namespace)) {
- warn("module %s uses symbol %s from namespace %s, but does not import it.\n",
- basename, exp->name, exp->namespace);
+ 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);
}
@@ -2257,8 +2246,12 @@ static int check_modname_len(struct module *mod)
**/
static void add_header(struct buffer *b, struct module *mod)
{
- buf_printf(b, "#include <linux/build-salt.h>\n");
buf_printf(b, "#include <linux/module.h>\n");
+ /*
+ * Include build-salt.h after module.h in order to
+ * inherit the definitions.
+ */
+ buf_printf(b, "#include <linux/build-salt.h>\n");
buf_printf(b, "#include <linux/vermagic.h>\n");
buf_printf(b, "#include <linux/compiler.h>\n");
buf_printf(b, "\n");
@@ -2433,7 +2426,7 @@ static void write_if_changed(struct buffer *b, const char *fname)
}
/* parse Module.symvers file. line format:
- * 0x12345678<tab>symbol<tab>module[[<tab>export]<tab>something]
+ * 0x12345678<tab>symbol<tab>module<tab>export<tab>namespace
**/
static void read_dump(const char *fname, unsigned int kernel)
{
@@ -2446,7 +2439,7 @@ static void read_dump(const char *fname, unsigned int kernel)
return;
while ((line = get_next_line(&pos, file, size))) {
- char *symname, *namespace, *modname, *d, *export, *end;
+ char *symname, *namespace, *modname, *d, *export;
unsigned int crc;
struct module *mod;
struct symbol *s;
@@ -2454,16 +2447,16 @@ static void read_dump(const char *fname, unsigned int kernel)
if (!(symname = strchr(line, '\t')))
goto fail;
*symname++ = '\0';
- if (!(namespace = strchr(symname, '\t')))
- goto fail;
- *namespace++ = '\0';
- if (!(modname = strchr(namespace, '\t')))
+ if (!(modname = strchr(symname, '\t')))
goto fail;
*modname++ = '\0';
- if ((export = strchr(modname, '\t')) != NULL)
- *export++ = '\0';
- if (export && ((end = strchr(export, '\t')) != NULL))
- *end = '\0';
+ if (!(export = strchr(modname, '\t')))
+ goto fail;
+ *export++ = '\0';
+ if (!(namespace = strchr(export, '\t')))
+ goto fail;
+ *namespace++ = '\0';
+
crc = strtoul(line, &d, 16);
if (*symname == '\0' || *modname == '\0' || *d != '\0')
goto fail;
@@ -2514,9 +2507,9 @@ static void write_dump(const char *fname)
namespace = symbol->namespace;
buf_printf(&buf, "0x%08x\t%s\t%s\t%s\t%s\n",
symbol->crc, symbol->name,
- namespace ? namespace : "",
symbol->module->name,
- export_str(symbol->export));
+ export_str(symbol->export),
+ namespace ? namespace : "");
}
symbol = symbol->next;
}
@@ -2566,7 +2559,7 @@ int main(int argc, char **argv)
struct ext_sym_list *extsym_iter;
struct ext_sym_list *extsym_start = NULL;
- while ((opt = getopt(argc, argv, "i:e:mnsT:o:awEd:")) != -1) {
+ while ((opt = getopt(argc, argv, "i:e:mnsT:o:awENd:")) != -1) {
switch (opt) {
case 'i':
kernel_read = optarg;
@@ -2604,6 +2597,9 @@ int main(int argc, char **argv)
case 'E':
sec_mismatch_fatal = 1;
break;
+ case 'N':
+ allow_missing_ns_imports = 1;
+ break;
case 'd':
missing_namespace_deps = optarg;
break;
@@ -2659,7 +2655,7 @@ int main(int argc, char **argv)
if (dump_write)
write_dump(dump_write);
if (sec_mismatch_count && sec_mismatch_fatal)
- fatal("modpost: Section mismatches detected.\n"
+ fatal("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;
diff --git a/scripts/mod/modpost.h b/scripts/mod/modpost.h
index 64a82d2d85f6..60dca9b7106b 100644
--- a/scripts/mod/modpost.h
+++ b/scripts/mod/modpost.h
@@ -198,6 +198,14 @@ void *grab_file(const char *filename, unsigned long *size);
char* get_next_line(unsigned long *pos, void *file, unsigned long size);
void release_file(void *file, unsigned long size);
-void fatal(const char *fmt, ...);
-void warn(const char *fmt, ...);
-void merror(const char *fmt, ...);
+enum loglevel {
+ LOG_WARN,
+ LOG_ERROR,
+ LOG_FATAL
+};
+
+void modpost_log(enum loglevel loglevel, const char *fmt, ...);
+
+#define warn(fmt, args...) modpost_log(LOG_WARN, fmt, ##args)
+#define merror(fmt, args...) modpost_log(LOG_ERROR, fmt, ##args)
+#define fatal(fmt, args...) modpost_log(LOG_FATAL, fmt, ##args)
diff --git a/scripts/package/builddeb b/scripts/package/builddeb
index c4c580f547ef..6df3c9f8b2da 100755
--- a/scripts/package/builddeb
+++ b/scripts/package/builddeb
@@ -43,17 +43,66 @@ create_package() {
# Create the package
dpkg-gencontrol -p$pname -P"$pdir"
- dpkg --build "$pdir" ..
+ dpkg-deb ${KDEB_COMPRESS:+-Z$KDEB_COMPRESS} --build "$pdir" ..
+}
+
+deploy_kernel_headers () {
+ pdir=$1
+
+ rm -rf $pdir
+
+ (
+ cd $srctree
+ find . arch/$SRCARCH -maxdepth 1 -name Makefile\*
+ find include scripts -type f -o -type l
+ find arch/$SRCARCH -name module.lds -o -name Kbuild.platforms -o -name Platform
+ find $(find arch/$SRCARCH -name include -o -name scripts -type d) -type f
+ ) > debian/hdrsrcfiles
+
+ {
+ if is_enabled CONFIG_STACK_VALIDATION; then
+ echo tools/objtool/objtool
+ fi
+
+ find arch/$SRCARCH/include Module.symvers include scripts -type f
+
+ if is_enabled CONFIG_GCC_PLUGINS; then
+ find scripts/gcc-plugins -name \*.so
+ fi
+ } > debian/hdrobjfiles
+
+ destdir=$pdir/usr/src/linux-headers-$version
+ mkdir -p $destdir
+ tar -c -f - -C $srctree -T debian/hdrsrcfiles | tar -xf - -C $destdir
+ tar -c -f - -T debian/hdrobjfiles | tar -xf - -C $destdir
+ rm -f debian/hdrsrcfiles debian/hdrobjfiles
+
+ # copy .config manually to be where it's expected to be
+ cp $KCONFIG_CONFIG $destdir/.config
+
+ mkdir -p $pdir/lib/modules/$version/
+ ln -s /usr/src/linux-headers-$version $pdir/lib/modules/$version/build
+}
+
+deploy_libc_headers () {
+ pdir=$1
+
+ rm -rf $pdir
+
+ $MAKE -f $srctree/Makefile headers
+ $MAKE -f $srctree/Makefile headers_install INSTALL_HDR_PATH=$pdir/usr
+
+ # move asm headers to /usr/include/<libc-machine>/asm to match the structure
+ # used by Debian-based distros (to support multi-arch)
+ host_arch=$(dpkg-architecture -a$(cat debian/arch) -qDEB_HOST_MULTIARCH)
+ mkdir $pdir/usr/include/$host_arch
+ mv $pdir/usr/include/asm $pdir/usr/include/$host_arch/
}
version=$KERNELRELEASE
-tmpdir="$objtree/debian/tmp"
-kernel_headers_dir="$objtree/debian/hdrtmp"
-libc_headers_dir="$objtree/debian/headertmp"
-dbg_dir="$objtree/debian/dbgtmp"
+tmpdir=debian/linux-image
+dbg_dir=debian/linux-image-dbg
packagename=linux-image-$version
-kernel_headers_packagename=linux-headers-$version
-libc_headers_packagename=linux-libc-dev
dbg_packagename=$packagename-dbg
if [ "$ARCH" = "um" ] ; then
@@ -77,15 +126,13 @@ esac
BUILD_DEBUG=$(if_enabled_echo CONFIG_DEBUG_INFO Yes)
# Setup the directory structure
-rm -rf "$tmpdir" "$kernel_headers_dir" "$libc_headers_dir" "$dbg_dir" $objtree/debian/files
+rm -rf "$tmpdir" "$dbg_dir" debian/files
mkdir -m 755 -p "$tmpdir/DEBIAN"
mkdir -p "$tmpdir/lib" "$tmpdir/boot"
-mkdir -p "$kernel_headers_dir/lib/modules/$version/"
-# Build and install the kernel
+# Install the kernel
if [ "$ARCH" = "um" ] ; then
mkdir -p "$tmpdir/usr/lib/uml/modules/$version" "$tmpdir/usr/bin" "$tmpdir/usr/share/doc/$packagename"
- $MAKE linux
cp System.map "$tmpdir/usr/lib/uml/modules/$version/System.map"
cp $KCONFIG_CONFIG "$tmpdir/usr/share/doc/$packagename/config"
gzip "$tmpdir/usr/share/doc/$packagename/config"
@@ -129,16 +176,6 @@ if is_enabled CONFIG_MODULES; then
fi
fi
-if [ "$ARCH" != "um" ]; then
- $MAKE -f $srctree/Makefile headers
- $MAKE -f $srctree/Makefile headers_install INSTALL_HDR_PATH="$libc_headers_dir/usr"
- # move asm headers to /usr/include/<libc-machine>/asm to match the structure
- # used by Debian-based distros (to support multi-arch)
- host_arch=$(dpkg-architecture -a$(cat debian/arch) -qDEB_HOST_MULTIARCH)
- mkdir $libc_headers_dir/usr/include/$host_arch
- mv $libc_headers_dir/usr/include/asm $libc_headers_dir/usr/include/$host_arch/
-fi
-
# Install the maintainer scripts
# Note: hook scripts under /etc/kernel are also executed by official Debian
# kernel packages, as well as kernel packages built using make-kpkg.
@@ -164,29 +201,12 @@ EOF
chmod 755 "$tmpdir/DEBIAN/$script"
done
-# Build kernel header package
-(cd $srctree; find . -name Makefile\* -o -name Kconfig\* -o -name \*.pl) > "$objtree/debian/hdrsrcfiles"
-(cd $srctree; find arch/*/include include scripts -type f -o -type l) >> "$objtree/debian/hdrsrcfiles"
-(cd $srctree; find arch/$SRCARCH -name module.lds -o -name Kbuild.platforms -o -name Platform) >> "$objtree/debian/hdrsrcfiles"
-(cd $srctree; find $(find arch/$SRCARCH -name include -o -name scripts -type d) -type f) >> "$objtree/debian/hdrsrcfiles"
-if is_enabled CONFIG_STACK_VALIDATION; then
- (cd $objtree; find tools/objtool -type f -executable) >> "$objtree/debian/hdrobjfiles"
-fi
-(cd $objtree; find arch/$SRCARCH/include Module.symvers include scripts -type f) >> "$objtree/debian/hdrobjfiles"
-if is_enabled CONFIG_GCC_PLUGINS; then
- (cd $objtree; find scripts/gcc-plugins -name \*.so -o -name gcc-common.h) >> "$objtree/debian/hdrobjfiles"
-fi
-destdir=$kernel_headers_dir/usr/src/linux-headers-$version
-mkdir -p "$destdir"
-(cd $srctree; tar -c -f - -T -) < "$objtree/debian/hdrsrcfiles" | (cd $destdir; tar -xf -)
-(cd $objtree; tar -c -f - -T -) < "$objtree/debian/hdrobjfiles" | (cd $destdir; tar -xf -)
-(cd $objtree; cp $KCONFIG_CONFIG $destdir/.config) # copy .config manually to be where it's expected to be
-ln -sf "/usr/src/linux-headers-$version" "$kernel_headers_dir/lib/modules/$version/build"
-rm -f "$objtree/debian/hdrsrcfiles" "$objtree/debian/hdrobjfiles"
-
if [ "$ARCH" != "um" ]; then
- create_package "$kernel_headers_packagename" "$kernel_headers_dir"
- create_package "$libc_headers_packagename" "$libc_headers_dir"
+ deploy_kernel_headers debian/linux-headers
+ create_package linux-headers-$version debian/linux-headers
+
+ deploy_libc_headers debian/linux-libc-dev
+ create_package linux-libc-dev debian/linux-libc-dev
fi
create_package "$packagename" "$tmpdir"
diff --git a/scripts/package/mkdebian b/scripts/package/mkdebian
index 357dc56bcf30..df1adbfb8ead 100755
--- a/scripts/package/mkdebian
+++ b/scripts/package/mkdebian
@@ -198,6 +198,10 @@ Description: Linux support headers for userspace development
This package provides userspaces headers from the Linux kernel. These headers
are used by the installed headers for GNU glibc and other system libraries.
Multi-Arch: same
+EOF
+
+if is_enabled CONFIG_DEBUG_INFO; then
+cat <<EOF >> debian/control
Package: $dbg_packagename
Section: debug
@@ -206,6 +210,7 @@ Description: Linux kernel debugging symbols for $version
This package will come in handy if you need to debug the kernel. It provides
all the necessary debug symbols for the kernel and its modules.
EOF
+fi
cat <<EOF > debian/rules
#!$(command -v $MAKE) -f
diff --git a/scripts/parse-maintainers.pl b/scripts/parse-maintainers.pl
index 255cef1b098d..2ca4eb3f190d 100644..100755
--- a/scripts/parse-maintainers.pl
+++ b/scripts/parse-maintainers.pl
@@ -8,13 +8,14 @@ my $input_file = "MAINTAINERS";
my $output_file = "MAINTAINERS.new";
my $output_section = "SECTION.new";
my $help = 0;
-
+my $order = 0;
my $P = $0;
if (!GetOptions(
'input=s' => \$input_file,
'output=s' => \$output_file,
'section=s' => \$output_section,
+ 'order!' => \$order,
'h|help|usage' => \$help,
)) {
die "$P: invalid argument - use --help if necessary\n";
@@ -32,6 +33,22 @@ usage: $P [options] <pattern matching regexes>
--input => MAINTAINERS file to read (default: MAINTAINERS)
--output => sorted MAINTAINERS file to write (default: MAINTAINERS.new)
--section => new sorted MAINTAINERS file to write to (default: SECTION.new)
+ --order => Use the preferred section content output ordering (default: 0)
+ Preferred ordering of section output is:
+ M: Person acting as a maintainer
+ R: Person acting as a patch reviewer
+ L: Mailing list where patches should be sent
+ S: Maintenance status
+ W: URI for general information
+ Q: URI for patchwork tracking
+ B: URI for bug tracking/submission
+ C: URI for chat
+ P: URI or file for subsystem specific coding styles
+ T: SCM tree type and location
+ F: File and directory pattern
+ X: File and directory exclusion pattern
+ N: File glob
+ K: Keyword - patch content regex
If <pattern match regexes> exist, then the sections that match the
regexes are not written to the output file but are written to the
@@ -56,7 +73,7 @@ sub by_category($$) {
sub by_pattern($$) {
my ($a, $b) = @_;
- my $preferred_order = 'MRPLSWTQBCFXNK';
+ my $preferred_order = 'MRLSWQBCPTFXNK';
my $a1 = uc(substr($a, 0, 1));
my $b1 = uc(substr($b, 0, 1));
@@ -105,8 +122,14 @@ sub alpha_output {
print $file $separator;
}
print $file $key . "\n";
- foreach my $pattern (sort by_pattern split('\n', %$hashref{$key})) {
- print $file ($pattern . "\n");
+ if ($order) {
+ foreach my $pattern (sort by_pattern split('\n', %$hashref{$key})) {
+ print $file ($pattern . "\n");
+ }
+ } else {
+ foreach my $pattern (split('\n', %$hashref{$key})) {
+ print $file ($pattern . "\n");
+ }
}
}
}
diff --git a/scripts/recordmcount.c b/scripts/recordmcount.c
index 612268eabef4..7225107a9aaf 100644
--- a/scripts/recordmcount.c
+++ b/scripts/recordmcount.c
@@ -38,6 +38,10 @@
#define R_AARCH64_ABS64 257
#endif
+#define R_ARM_PC24 1
+#define R_ARM_THM_CALL 10
+#define R_ARM_CALL 28
+
static int fd_map; /* File descriptor for file being modified. */
static int mmap_failed; /* Boolean flag. */
static char gpfx; /* prefix for global symbol name (sometimes '_') */
@@ -418,6 +422,18 @@ static char const *already_has_rel_mcount = "success"; /* our work here is done!
#define RECORD_MCOUNT_64
#include "recordmcount.h"
+static int arm_is_fake_mcount(Elf32_Rel const *rp)
+{
+ switch (ELF32_R_TYPE(w(rp->r_info))) {
+ case R_ARM_THM_CALL:
+ case R_ARM_CALL:
+ case R_ARM_PC24:
+ return 0;
+ }
+
+ return 1;
+}
+
/* 64-bit EM_MIPS has weird ELF64_Rela.r_info.
* http://techpubs.sgi.com/library/manuals/4000/007-4658-001/pdf/007-4658-001.pdf
* We interpret Table 29 Relocation Operation (Elf64_Rel, Elf64_Rela) [p.40]
@@ -523,6 +539,7 @@ static int do_file(char const *const fname)
altmcount = "__gnu_mcount_nc";
make_nop = make_nop_arm;
rel_type_nop = R_ARM_NONE;
+ is_fake_mcount32 = arm_is_fake_mcount;
gpfx = 0;
break;
case EM_AARCH64:
diff --git a/scripts/selinux/genheaders/.gitignore b/scripts/selinux/genheaders/.gitignore
index 4c0b646ff8d5..5fcadd307908 100644
--- a/scripts/selinux/genheaders/.gitignore
+++ b/scripts/selinux/genheaders/.gitignore
@@ -1 +1,2 @@
+# SPDX-License-Identifier: GPL-2.0-only
genheaders
diff --git a/scripts/selinux/genheaders/Makefile b/scripts/selinux/genheaders/Makefile
index e8c533140981..70cf8d95d07c 100644
--- a/scripts/selinux/genheaders/Makefile
+++ b/scripts/selinux/genheaders/Makefile
@@ -1,7 +1,7 @@
# SPDX-License-Identifier: GPL-2.0
-hostprogs-y := genheaders
+hostprogs := genheaders
HOST_EXTRACFLAGS += \
-I$(srctree)/include/uapi -I$(srctree)/include \
-I$(srctree)/security/selinux/include
-always := $(hostprogs-y)
+always-y := $(hostprogs)
diff --git a/scripts/selinux/genheaders/genheaders.c b/scripts/selinux/genheaders/genheaders.c
index 544ca126a8a8..f355b3e0e968 100644
--- a/scripts/selinux/genheaders/genheaders.c
+++ b/scripts/selinux/genheaders/genheaders.c
@@ -67,8 +67,12 @@ int main(int argc, char *argv[])
}
isids_len = sizeof(initial_sid_to_string) / sizeof (char *);
- for (i = 1; i < isids_len; i++)
- initial_sid_to_string[i] = stoupperx(initial_sid_to_string[i]);
+ for (i = 1; i < isids_len; i++) {
+ const char *s = initial_sid_to_string[i];
+
+ if (s)
+ initial_sid_to_string[i] = stoupperx(s);
+ }
fprintf(fout, "/* This file is automatically generated. Do not edit. */\n");
fprintf(fout, "#ifndef _SELINUX_FLASK_H_\n#define _SELINUX_FLASK_H_\n\n");
@@ -82,7 +86,8 @@ int main(int argc, char *argv[])
for (i = 1; i < isids_len; i++) {
const char *s = initial_sid_to_string[i];
- fprintf(fout, "#define SECINITSID_%-39s %2d\n", s, i);
+ if (s)
+ fprintf(fout, "#define SECINITSID_%-39s %2d\n", s, i);
}
fprintf(fout, "\n#define SECINITSID_NUM %d\n", i-1);
fprintf(fout, "\nstatic inline bool security_is_socket_class(u16 kern_tclass)\n");
diff --git a/scripts/selinux/mdp/.gitignore b/scripts/selinux/mdp/.gitignore
index 654546d8dffd..a7482287e77f 100644
--- a/scripts/selinux/mdp/.gitignore
+++ b/scripts/selinux/mdp/.gitignore
@@ -1,2 +1,2 @@
-# Generated file
+# SPDX-License-Identifier: GPL-2.0-only
mdp
diff --git a/scripts/selinux/mdp/Makefile b/scripts/selinux/mdp/Makefile
index 8a1269a9d0ba..3026f3c2aa2b 100644
--- a/scripts/selinux/mdp/Makefile
+++ b/scripts/selinux/mdp/Makefile
@@ -1,8 +1,8 @@
# SPDX-License-Identifier: GPL-2.0
-hostprogs-y := mdp
+hostprogs := mdp
HOST_EXTRACFLAGS += \
-I$(srctree)/include/uapi -I$(srctree)/include \
-I$(srctree)/security/selinux/include -I$(objtree)/include
-always := $(hostprogs-y)
+always-y := $(hostprogs)
clean-files := policy.* file_contexts
diff --git a/scripts/sortextable.h b/scripts/sortextable.h
deleted file mode 100644
index d4b3f6c40f02..000000000000
--- a/scripts/sortextable.h
+++ /dev/null
@@ -1,209 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * sortextable.h
- *
- * Copyright 2011 - 2012 Cavium, Inc.
- *
- * Some of this code was taken out of recordmcount.h written by:
- *
- * Copyright 2009 John F. Reiser <jreiser@BitWagon.com>. All rights reserved.
- * Copyright 2010 Steven Rostedt <srostedt@redhat.com>, Red Hat Inc.
- */
-
-#undef extable_ent_size
-#undef compare_extable
-#undef do_func
-#undef Elf_Addr
-#undef Elf_Ehdr
-#undef Elf_Shdr
-#undef Elf_Rel
-#undef Elf_Rela
-#undef Elf_Sym
-#undef ELF_R_SYM
-#undef Elf_r_sym
-#undef ELF_R_INFO
-#undef Elf_r_info
-#undef ELF_ST_BIND
-#undef ELF_ST_TYPE
-#undef fn_ELF_R_SYM
-#undef fn_ELF_R_INFO
-#undef uint_t
-#undef _r
-#undef _w
-
-#ifdef SORTEXTABLE_64
-# define extable_ent_size 16
-# define compare_extable compare_extable_64
-# define do_func do64
-# define Elf_Addr Elf64_Addr
-# define Elf_Ehdr Elf64_Ehdr
-# define Elf_Shdr Elf64_Shdr
-# define Elf_Rel Elf64_Rel
-# define Elf_Rela Elf64_Rela
-# define Elf_Sym Elf64_Sym
-# define ELF_R_SYM ELF64_R_SYM
-# define Elf_r_sym Elf64_r_sym
-# define ELF_R_INFO ELF64_R_INFO
-# define Elf_r_info Elf64_r_info
-# define ELF_ST_BIND ELF64_ST_BIND
-# define ELF_ST_TYPE ELF64_ST_TYPE
-# define fn_ELF_R_SYM fn_ELF64_R_SYM
-# define fn_ELF_R_INFO fn_ELF64_R_INFO
-# define uint_t uint64_t
-# define _r r8
-# define _w w8
-#else
-# define extable_ent_size 8
-# define compare_extable compare_extable_32
-# define do_func do32
-# define Elf_Addr Elf32_Addr
-# define Elf_Ehdr Elf32_Ehdr
-# define Elf_Shdr Elf32_Shdr
-# define Elf_Rel Elf32_Rel
-# define Elf_Rela Elf32_Rela
-# define Elf_Sym Elf32_Sym
-# define ELF_R_SYM ELF32_R_SYM
-# define Elf_r_sym Elf32_r_sym
-# define ELF_R_INFO ELF32_R_INFO
-# define Elf_r_info Elf32_r_info
-# define ELF_ST_BIND ELF32_ST_BIND
-# define ELF_ST_TYPE ELF32_ST_TYPE
-# define fn_ELF_R_SYM fn_ELF32_R_SYM
-# define fn_ELF_R_INFO fn_ELF32_R_INFO
-# define uint_t uint32_t
-# define _r r
-# define _w w
-#endif
-
-static int compare_extable(const void *a, const void *b)
-{
- Elf_Addr av = _r(a);
- Elf_Addr bv = _r(b);
-
- if (av < bv)
- return -1;
- if (av > bv)
- return 1;
- return 0;
-}
-
-static void
-do_func(Elf_Ehdr *ehdr, char const *const fname, table_sort_t custom_sort)
-{
- Elf_Shdr *shdr;
- Elf_Shdr *shstrtab_sec;
- Elf_Shdr *strtab_sec = NULL;
- Elf_Shdr *symtab_sec = NULL;
- Elf_Shdr *extab_sec = NULL;
- Elf_Sym *sym;
- const Elf_Sym *symtab;
- Elf32_Word *symtab_shndx_start = NULL;
- Elf_Sym *sort_needed_sym;
- Elf_Shdr *sort_needed_sec;
- Elf_Rel *relocs = NULL;
- int relocs_size = 0;
- uint32_t *sort_done_location;
- const char *secstrtab;
- const char *strtab;
- char *extab_image;
- int extab_index = 0;
- int i;
- int idx;
- unsigned int num_sections;
- unsigned int secindex_strings;
-
- shdr = (Elf_Shdr *)((char *)ehdr + _r(&ehdr->e_shoff));
-
- num_sections = r2(&ehdr->e_shnum);
- if (num_sections == SHN_UNDEF)
- num_sections = _r(&shdr[0].sh_size);
-
- secindex_strings = r2(&ehdr->e_shstrndx);
- if (secindex_strings == SHN_XINDEX)
- secindex_strings = r(&shdr[0].sh_link);
-
- shstrtab_sec = shdr + secindex_strings;
- secstrtab = (const char *)ehdr + _r(&shstrtab_sec->sh_offset);
- for (i = 0; i < num_sections; i++) {
- idx = r(&shdr[i].sh_name);
- if (strcmp(secstrtab + idx, "__ex_table") == 0) {
- extab_sec = shdr + i;
- extab_index = i;
- }
- if ((r(&shdr[i].sh_type) == SHT_REL ||
- r(&shdr[i].sh_type) == SHT_RELA) &&
- r(&shdr[i].sh_info) == extab_index) {
- relocs = (void *)ehdr + _r(&shdr[i].sh_offset);
- relocs_size = _r(&shdr[i].sh_size);
- }
- if (strcmp(secstrtab + idx, ".symtab") == 0)
- symtab_sec = shdr + i;
- if (strcmp(secstrtab + idx, ".strtab") == 0)
- strtab_sec = shdr + i;
- if (r(&shdr[i].sh_type) == SHT_SYMTAB_SHNDX)
- symtab_shndx_start = (Elf32_Word *)(
- (const char *)ehdr + _r(&shdr[i].sh_offset));
- }
- if (strtab_sec == NULL) {
- fprintf(stderr, "no .strtab in file: %s\n", fname);
- fail_file();
- }
- if (symtab_sec == NULL) {
- fprintf(stderr, "no .symtab in file: %s\n", fname);
- fail_file();
- }
- symtab = (const Elf_Sym *)((const char *)ehdr +
- _r(&symtab_sec->sh_offset));
- if (extab_sec == NULL) {
- fprintf(stderr, "no __ex_table in file: %s\n", fname);
- fail_file();
- }
- strtab = (const char *)ehdr + _r(&strtab_sec->sh_offset);
-
- extab_image = (void *)ehdr + _r(&extab_sec->sh_offset);
-
- if (custom_sort) {
- custom_sort(extab_image, _r(&extab_sec->sh_size));
- } else {
- int num_entries = _r(&extab_sec->sh_size) / extable_ent_size;
- qsort(extab_image, num_entries,
- extable_ent_size, compare_extable);
- }
- /* If there were relocations, we no longer need them. */
- if (relocs)
- memset(relocs, 0, relocs_size);
-
- /* find main_extable_sort_needed */
- sort_needed_sym = NULL;
- for (i = 0; i < _r(&symtab_sec->sh_size) / sizeof(Elf_Sym); i++) {
- sym = (void *)ehdr + _r(&symtab_sec->sh_offset);
- sym += i;
- if (ELF_ST_TYPE(sym->st_info) != STT_OBJECT)
- continue;
- idx = r(&sym->st_name);
- if (strcmp(strtab + idx, "main_extable_sort_needed") == 0) {
- sort_needed_sym = sym;
- break;
- }
- }
- if (sort_needed_sym == NULL) {
- fprintf(stderr,
- "no main_extable_sort_needed symbol in file: %s\n",
- fname);
- fail_file();
- }
- sort_needed_sec = &shdr[get_secindex(r2(&sym->st_shndx),
- sort_needed_sym - symtab,
- symtab_shndx_start)];
- sort_done_location = (void *)ehdr +
- _r(&sort_needed_sec->sh_offset) +
- _r(&sort_needed_sym->st_value) -
- _r(&sort_needed_sec->sh_addr);
-
-#if 0
- printf("sort done marker at %lx\n",
- (unsigned long)((char *)sort_done_location - (char *)ehdr));
-#endif
- /* We sorted it, clear the flag. */
- w(0, sort_done_location);
-}
diff --git a/scripts/sortextable.c b/scripts/sorttable.c
index 55768654e3c6..ec6b5e81eba1 100644
--- a/scripts/sortextable.c
+++ b/scripts/sorttable.c
@@ -1,6 +1,10 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
- * sortextable.c: Sort the kernel's exception table
+ * sorttable.c: Sort the kernel's table
+ *
+ * Added ORC unwind tables sort support and other updates:
+ * Copyright (C) 1999-2019 Alibaba Group Holding Limited. by:
+ * Shile Zhang <shile.zhang@linux.alibaba.com>
*
* Copyright 2011 - 2012 Cavium, Inc.
*
@@ -9,7 +13,7 @@
* Copyright 2009 John F. Reiser <jreiser@BitWagon.com>. All rights reserved.
*
* Restructured to fit Linux format, as well as other updates:
- * Copyright 2010 Steven Rostedt <srostedt@redhat.com>, Red Hat Inc.
+ * Copyright 2010 Steven Rostedt <srostedt@redhat.com>, Red Hat Inc.
*/
/*
@@ -22,7 +26,6 @@
#include <getopt.h>
#include <elf.h>
#include <fcntl.h>
-#include <setjmp.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -51,34 +54,13 @@
#define EM_ARCV2 195
#endif
-static int fd_map; /* File descriptor for file being modified. */
-static int mmap_failed; /* Boolean flag. */
-static void *ehdr_curr; /* current ElfXX_Ehdr * for resource cleanup */
-static struct stat sb; /* Remember .st_size, etc. */
-static jmp_buf jmpenv; /* setjmp/longjmp per-file error escape */
-
-/* setjmp() return values */
-enum {
- SJ_SETJMP = 0, /* hardwired first return */
- SJ_FAIL,
- SJ_SUCCEED
-};
-
-/* Per-file resource cleanup when multiple files. */
-static void
-cleanup(void)
-{
- if (!mmap_failed)
- munmap(ehdr_curr, sb.st_size);
- close(fd_map);
-}
-
-static void __attribute__((noreturn))
-fail_file(void)
-{
- cleanup();
- longjmp(jmpenv, SJ_FAIL);
-}
+static uint32_t (*r)(const uint32_t *);
+static uint16_t (*r2)(const uint16_t *);
+static uint64_t (*r8)(const uint64_t *);
+static void (*w)(uint32_t, uint32_t *);
+static void (*w2)(uint16_t, uint16_t *);
+static void (*w8)(uint64_t, uint64_t *);
+typedef void (*table_sort_t)(char *, int);
/*
* Get the whole file as a programming convenience in order to avoid
@@ -86,87 +68,98 @@ fail_file(void)
* avoids copying unused pieces; else just read the whole file.
* Open for both read and write.
*/
-static void *mmap_file(char const *fname)
+static void *mmap_file(char const *fname, size_t *size)
{
- void *addr;
+ int fd;
+ struct stat sb;
+ void *addr = NULL;
- fd_map = open(fname, O_RDWR);
- if (fd_map < 0 || fstat(fd_map, &sb) < 0) {
+ fd = open(fname, O_RDWR);
+ if (fd < 0) {
perror(fname);
- fail_file();
+ return NULL;
+ }
+ if (fstat(fd, &sb) < 0) {
+ perror(fname);
+ goto out;
}
if (!S_ISREG(sb.st_mode)) {
fprintf(stderr, "not a regular file: %s\n", fname);
- fail_file();
+ goto out;
}
- addr = mmap(0, sb.st_size, PROT_READ|PROT_WRITE, MAP_SHARED,
- fd_map, 0);
+
+ addr = mmap(0, sb.st_size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
if (addr == MAP_FAILED) {
- mmap_failed = 1;
fprintf(stderr, "Could not mmap file: %s\n", fname);
- fail_file();
+ goto out;
}
+
+ *size = sb.st_size;
+
+out:
+ close(fd);
return addr;
}
-static uint64_t r8be(const uint64_t *x)
-{
- return get_unaligned_be64(x);
-}
static uint32_t rbe(const uint32_t *x)
{
return get_unaligned_be32(x);
}
+
static uint16_t r2be(const uint16_t *x)
{
return get_unaligned_be16(x);
}
-static uint64_t r8le(const uint64_t *x)
+
+static uint64_t r8be(const uint64_t *x)
{
- return get_unaligned_le64(x);
+ return get_unaligned_be64(x);
}
+
static uint32_t rle(const uint32_t *x)
{
return get_unaligned_le32(x);
}
+
static uint16_t r2le(const uint16_t *x)
{
return get_unaligned_le16(x);
}
-static void w8be(uint64_t val, uint64_t *x)
+static uint64_t r8le(const uint64_t *x)
{
- put_unaligned_be64(val, x);
+ return get_unaligned_le64(x);
}
+
static void wbe(uint32_t val, uint32_t *x)
{
put_unaligned_be32(val, x);
}
+
static void w2be(uint16_t val, uint16_t *x)
{
put_unaligned_be16(val, x);
}
-static void w8le(uint64_t val, uint64_t *x)
+
+static void w8be(uint64_t val, uint64_t *x)
{
- put_unaligned_le64(val, x);
+ put_unaligned_be64(val, x);
}
+
static void wle(uint32_t val, uint32_t *x)
{
put_unaligned_le32(val, x);
}
+
static void w2le(uint16_t val, uint16_t *x)
{
put_unaligned_le16(val, x);
}
-static uint64_t (*r8)(const uint64_t *);
-static uint32_t (*r)(const uint32_t *);
-static uint16_t (*r2)(const uint16_t *);
-static void (*w8)(uint64_t, uint64_t *);
-static void (*w)(uint32_t, uint32_t *);
-static void (*w2)(uint16_t, uint16_t *);
-
-typedef void (*table_sort_t)(char *, int);
+static void w8le(uint64_t val, uint64_t *x)
+{
+ put_unaligned_le64(val, x);
+}
/*
* Move reserved section indices SHN_LORESERVE..SHN_HIRESERVE out of
@@ -193,9 +186,9 @@ static inline unsigned int get_secindex(unsigned int shndx,
}
/* 32 bit and 64 bit are very similar */
-#include "sortextable.h"
-#define SORTEXTABLE_64
-#include "sortextable.h"
+#include "sorttable.h"
+#define SORTTABLE_64
+#include "sorttable.h"
static int compare_relative_table(const void *a, const void *b)
{
@@ -209,110 +202,100 @@ static int compare_relative_table(const void *a, const void *b)
return 0;
}
-static void x86_sort_relative_table(char *extab_image, int image_size)
+static void sort_relative_table(char *extab_image, int image_size)
{
- int i;
+ int i = 0;
- i = 0;
+ /*
+ * Do the same thing the runtime sort does, first normalize to
+ * being relative to the start of the section.
+ */
while (i < image_size) {
uint32_t *loc = (uint32_t *)(extab_image + i);
-
w(r(loc) + i, loc);
- w(r(loc + 1) + i + 4, loc + 1);
- w(r(loc + 2) + i + 8, loc + 2);
-
- i += sizeof(uint32_t) * 3;
+ i += 4;
}
- qsort(extab_image, image_size / 12, 12, compare_relative_table);
+ qsort(extab_image, image_size / 8, 8, compare_relative_table);
+ /* Now denormalize. */
i = 0;
while (i < image_size) {
uint32_t *loc = (uint32_t *)(extab_image + i);
-
w(r(loc) - i, loc);
- w(r(loc + 1) - (i + 4), loc + 1);
- w(r(loc + 2) - (i + 8), loc + 2);
-
- i += sizeof(uint32_t) * 3;
+ i += 4;
}
}
-static void sort_relative_table(char *extab_image, int image_size)
+static void x86_sort_relative_table(char *extab_image, int image_size)
{
- int i;
+ int i = 0;
- /*
- * Do the same thing the runtime sort does, first normalize to
- * being relative to the start of the section.
- */
- i = 0;
while (i < image_size) {
uint32_t *loc = (uint32_t *)(extab_image + i);
+
w(r(loc) + i, loc);
- i += 4;
+ w(r(loc + 1) + i + 4, loc + 1);
+ w(r(loc + 2) + i + 8, loc + 2);
+
+ i += sizeof(uint32_t) * 3;
}
- qsort(extab_image, image_size / 8, 8, compare_relative_table);
+ qsort(extab_image, image_size / 12, 12, compare_relative_table);
- /* Now denormalize. */
i = 0;
while (i < image_size) {
uint32_t *loc = (uint32_t *)(extab_image + i);
+
w(r(loc) - i, loc);
- i += 4;
+ w(r(loc + 1) - (i + 4), loc + 1);
+ w(r(loc + 2) - (i + 8), loc + 2);
+
+ i += sizeof(uint32_t) * 3;
}
}
-static void
-do_file(char const *const fname)
+static int do_file(char const *const fname, void *addr)
{
- table_sort_t custom_sort;
- Elf32_Ehdr *ehdr = mmap_file(fname);
+ int rc = -1;
+ Elf32_Ehdr *ehdr = addr;
+ table_sort_t custom_sort = NULL;
- ehdr_curr = ehdr;
switch (ehdr->e_ident[EI_DATA]) {
- default:
- fprintf(stderr, "unrecognized ELF data encoding %d: %s\n",
- ehdr->e_ident[EI_DATA], fname);
- fail_file();
- break;
case ELFDATA2LSB:
- r = rle;
- r2 = r2le;
- r8 = r8le;
- w = wle;
- w2 = w2le;
- w8 = w8le;
+ r = rle;
+ r2 = r2le;
+ r8 = r8le;
+ w = wle;
+ w2 = w2le;
+ w8 = w8le;
break;
case ELFDATA2MSB:
- r = rbe;
- r2 = r2be;
- r8 = r8be;
- w = wbe;
- w2 = w2be;
- w8 = w8be;
+ r = rbe;
+ r2 = r2be;
+ r8 = r8be;
+ w = wbe;
+ w2 = w2be;
+ w8 = w8be;
break;
- } /* end switch */
- if (memcmp(ELFMAG, ehdr->e_ident, SELFMAG) != 0
- || (r2(&ehdr->e_type) != ET_EXEC && r2(&ehdr->e_type) != ET_DYN)
- || ehdr->e_ident[EI_VERSION] != EV_CURRENT) {
+ default:
+ fprintf(stderr, "unrecognized ELF data encoding %d: %s\n",
+ ehdr->e_ident[EI_DATA], fname);
+ return -1;
+ }
+
+ if (memcmp(ELFMAG, ehdr->e_ident, SELFMAG) != 0 ||
+ (r2(&ehdr->e_type) != ET_EXEC && r2(&ehdr->e_type) != ET_DYN) ||
+ ehdr->e_ident[EI_VERSION] != EV_CURRENT) {
fprintf(stderr, "unrecognized ET_EXEC/ET_DYN file %s\n", fname);
- fail_file();
+ return -1;
}
- custom_sort = NULL;
switch (r2(&ehdr->e_machine)) {
- default:
- fprintf(stderr, "unrecognized e_machine %d %s\n",
- r2(&ehdr->e_machine), fname);
- fail_file();
- break;
case EM_386:
case EM_X86_64:
custom_sort = x86_sort_relative_table;
break;
-
case EM_S390:
case EM_AARCH64:
case EM_PARISC:
@@ -327,74 +310,68 @@ do_file(char const *const fname)
case EM_MIPS:
case EM_XTENSA:
break;
- } /* end switch */
+ default:
+ fprintf(stderr, "unrecognized e_machine %d %s\n",
+ r2(&ehdr->e_machine), fname);
+ return -1;
+ }
switch (ehdr->e_ident[EI_CLASS]) {
- default:
- fprintf(stderr, "unrecognized ELF class %d %s\n",
- ehdr->e_ident[EI_CLASS], fname);
- fail_file();
- break;
case ELFCLASS32:
- if (r2(&ehdr->e_ehsize) != sizeof(Elf32_Ehdr)
- || r2(&ehdr->e_shentsize) != sizeof(Elf32_Shdr)) {
+ if (r2(&ehdr->e_ehsize) != sizeof(Elf32_Ehdr) ||
+ r2(&ehdr->e_shentsize) != sizeof(Elf32_Shdr)) {
fprintf(stderr,
"unrecognized ET_EXEC/ET_DYN file: %s\n", fname);
- fail_file();
+ break;
}
- do32(ehdr, fname, custom_sort);
+ rc = do_sort_32(ehdr, fname, custom_sort);
break;
- case ELFCLASS64: {
+ case ELFCLASS64:
+ {
Elf64_Ehdr *const ghdr = (Elf64_Ehdr *)ehdr;
- if (r2(&ghdr->e_ehsize) != sizeof(Elf64_Ehdr)
- || r2(&ghdr->e_shentsize) != sizeof(Elf64_Shdr)) {
+ if (r2(&ghdr->e_ehsize) != sizeof(Elf64_Ehdr) ||
+ r2(&ghdr->e_shentsize) != sizeof(Elf64_Shdr)) {
fprintf(stderr,
- "unrecognized ET_EXEC/ET_DYN file: %s\n", fname);
- fail_file();
+ "unrecognized ET_EXEC/ET_DYN file: %s\n",
+ fname);
+ break;
+ }
+ rc = do_sort_64(ghdr, fname, custom_sort);
}
- do64(ghdr, fname, custom_sort);
+ break;
+ default:
+ fprintf(stderr, "unrecognized ELF class %d %s\n",
+ ehdr->e_ident[EI_CLASS], fname);
break;
}
- } /* end switch */
- cleanup();
+ return rc;
}
-int
-main(int argc, char *argv[])
+int main(int argc, char *argv[])
{
- int n_error = 0; /* gcc-4.3.0 false positive complaint */
- int i;
+ int i, n_error = 0; /* gcc-4.3.0 false positive complaint */
+ size_t size = 0;
+ void *addr = NULL;
if (argc < 2) {
- fprintf(stderr, "usage: sortextable vmlinux...\n");
+ fprintf(stderr, "usage: sorttable vmlinux...\n");
return 0;
}
/* Process each file in turn, allowing deep failure. */
for (i = 1; i < argc; i++) {
- char *file = argv[i];
- int const sjval = setjmp(jmpenv);
+ addr = mmap_file(argv[i], &size);
+ if (!addr) {
+ ++n_error;
+ continue;
+ }
- switch (sjval) {
- default:
- fprintf(stderr, "internal error: %s\n", file);
- exit(1);
- break;
- case SJ_SETJMP: /* normal sequence */
- /* Avoid problems if early cleanup() */
- fd_map = -1;
- ehdr_curr = NULL;
- mmap_failed = 1;
- do_file(file);
- break;
- case SJ_FAIL: /* error in do_file or below */
+ if (do_file(argv[i], addr))
++n_error;
- break;
- case SJ_SUCCEED: /* premature success */
- /* do nothing */
- break;
- } /* end switch */
+
+ munmap(addr, size);
}
+
return !!n_error;
}
diff --git a/scripts/sorttable.h b/scripts/sorttable.h
new file mode 100644
index 000000000000..a2baa2fefb13
--- /dev/null
+++ b/scripts/sorttable.h
@@ -0,0 +1,380 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * sorttable.h
+ *
+ * Added ORC unwind tables sort support and other updates:
+ * Copyright (C) 1999-2019 Alibaba Group Holding Limited. by:
+ * Shile Zhang <shile.zhang@linux.alibaba.com>
+ *
+ * Copyright 2011 - 2012 Cavium, Inc.
+ *
+ * Some of code was taken out of arch/x86/kernel/unwind_orc.c, written by:
+ * Copyright (C) 2017 Josh Poimboeuf <jpoimboe@redhat.com>
+ *
+ * Some of this code was taken out of recordmcount.h written by:
+ *
+ * Copyright 2009 John F. Reiser <jreiser@BitWagon.com>. All rights reserved.
+ * Copyright 2010 Steven Rostedt <srostedt@redhat.com>, Red Hat Inc.
+ */
+
+#undef extable_ent_size
+#undef compare_extable
+#undef do_sort
+#undef Elf_Addr
+#undef Elf_Ehdr
+#undef Elf_Shdr
+#undef Elf_Rel
+#undef Elf_Rela
+#undef Elf_Sym
+#undef ELF_R_SYM
+#undef Elf_r_sym
+#undef ELF_R_INFO
+#undef Elf_r_info
+#undef ELF_ST_BIND
+#undef ELF_ST_TYPE
+#undef fn_ELF_R_SYM
+#undef fn_ELF_R_INFO
+#undef uint_t
+#undef _r
+#undef _w
+
+#ifdef SORTTABLE_64
+# define extable_ent_size 16
+# define compare_extable compare_extable_64
+# define do_sort do_sort_64
+# define Elf_Addr Elf64_Addr
+# define Elf_Ehdr Elf64_Ehdr
+# define Elf_Shdr Elf64_Shdr
+# define Elf_Rel Elf64_Rel
+# define Elf_Rela Elf64_Rela
+# define Elf_Sym Elf64_Sym
+# define ELF_R_SYM ELF64_R_SYM
+# define Elf_r_sym Elf64_r_sym
+# define ELF_R_INFO ELF64_R_INFO
+# define Elf_r_info Elf64_r_info
+# define ELF_ST_BIND ELF64_ST_BIND
+# define ELF_ST_TYPE ELF64_ST_TYPE
+# define fn_ELF_R_SYM fn_ELF64_R_SYM
+# define fn_ELF_R_INFO fn_ELF64_R_INFO
+# define uint_t uint64_t
+# define _r r8
+# define _w w8
+#else
+# define extable_ent_size 8
+# define compare_extable compare_extable_32
+# define do_sort do_sort_32
+# define Elf_Addr Elf32_Addr
+# define Elf_Ehdr Elf32_Ehdr
+# define Elf_Shdr Elf32_Shdr
+# define Elf_Rel Elf32_Rel
+# define Elf_Rela Elf32_Rela
+# define Elf_Sym Elf32_Sym
+# define ELF_R_SYM ELF32_R_SYM
+# define Elf_r_sym Elf32_r_sym
+# define ELF_R_INFO ELF32_R_INFO
+# define Elf_r_info Elf32_r_info
+# define ELF_ST_BIND ELF32_ST_BIND
+# define ELF_ST_TYPE ELF32_ST_TYPE
+# define fn_ELF_R_SYM fn_ELF32_R_SYM
+# define fn_ELF_R_INFO fn_ELF32_R_INFO
+# define uint_t uint32_t
+# define _r r
+# define _w w
+#endif
+
+#if defined(SORTTABLE_64) && defined(UNWINDER_ORC_ENABLED)
+/* ORC unwinder only support X86_64 */
+#include <errno.h>
+#include <pthread.h>
+#include <asm/orc_types.h>
+
+#define ERRSTR_MAXSZ 256
+
+char g_err[ERRSTR_MAXSZ];
+int *g_orc_ip_table;
+struct orc_entry *g_orc_table;
+
+pthread_t orc_sort_thread;
+
+static inline unsigned long orc_ip(const int *ip)
+{
+ return (unsigned long)ip + *ip;
+}
+
+static int orc_sort_cmp(const void *_a, const void *_b)
+{
+ struct orc_entry *orc_a;
+ const int *a = g_orc_ip_table + *(int *)_a;
+ const int *b = g_orc_ip_table + *(int *)_b;
+ unsigned long a_val = orc_ip(a);
+ unsigned long b_val = orc_ip(b);
+
+ if (a_val > b_val)
+ return 1;
+ if (a_val < b_val)
+ return -1;
+
+ /*
+ * The "weak" section terminator entries need to always be on the left
+ * to ensure the lookup code skips them in favor of real entries.
+ * These terminator entries exist to handle any gaps created by
+ * whitelisted .o files which didn't get objtool generation.
+ */
+ orc_a = g_orc_table + (a - g_orc_ip_table);
+ return orc_a->sp_reg == ORC_REG_UNDEFINED && !orc_a->end ? -1 : 1;
+}
+
+static void *sort_orctable(void *arg)
+{
+ int i;
+ int *idxs = NULL;
+ int *tmp_orc_ip_table = NULL;
+ struct orc_entry *tmp_orc_table = NULL;
+ unsigned int *orc_ip_size = (unsigned int *)arg;
+ unsigned int num_entries = *orc_ip_size / sizeof(int);
+ unsigned int orc_size = num_entries * sizeof(struct orc_entry);
+
+ idxs = (int *)malloc(*orc_ip_size);
+ if (!idxs) {
+ snprintf(g_err, ERRSTR_MAXSZ, "malloc idxs: %s",
+ strerror(errno));
+ pthread_exit(g_err);
+ }
+
+ tmp_orc_ip_table = (int *)malloc(*orc_ip_size);
+ if (!tmp_orc_ip_table) {
+ snprintf(g_err, ERRSTR_MAXSZ, "malloc tmp_orc_ip_table: %s",
+ strerror(errno));
+ pthread_exit(g_err);
+ }
+
+ tmp_orc_table = (struct orc_entry *)malloc(orc_size);
+ if (!tmp_orc_table) {
+ snprintf(g_err, ERRSTR_MAXSZ, "malloc tmp_orc_table: %s",
+ strerror(errno));
+ pthread_exit(g_err);
+ }
+
+ /* initialize indices array, convert ip_table to absolute address */
+ for (i = 0; i < num_entries; i++) {
+ idxs[i] = i;
+ tmp_orc_ip_table[i] = g_orc_ip_table[i] + i * sizeof(int);
+ }
+ memcpy(tmp_orc_table, g_orc_table, orc_size);
+
+ qsort(idxs, num_entries, sizeof(int), orc_sort_cmp);
+
+ for (i = 0; i < num_entries; i++) {
+ if (idxs[i] == i)
+ continue;
+
+ /* convert back to relative address */
+ g_orc_ip_table[i] = tmp_orc_ip_table[idxs[i]] - i * sizeof(int);
+ g_orc_table[i] = tmp_orc_table[idxs[i]];
+ }
+
+ free(idxs);
+ free(tmp_orc_ip_table);
+ free(tmp_orc_table);
+ pthread_exit(NULL);
+}
+#endif
+
+static int compare_extable(const void *a, const void *b)
+{
+ Elf_Addr av = _r(a);
+ Elf_Addr bv = _r(b);
+
+ if (av < bv)
+ return -1;
+ if (av > bv)
+ return 1;
+ return 0;
+}
+
+static int do_sort(Elf_Ehdr *ehdr,
+ char const *const fname,
+ table_sort_t custom_sort)
+{
+ int rc = -1;
+ Elf_Shdr *s, *shdr = (Elf_Shdr *)((char *)ehdr + _r(&ehdr->e_shoff));
+ Elf_Shdr *strtab_sec = NULL;
+ Elf_Shdr *symtab_sec = NULL;
+ Elf_Shdr *extab_sec = NULL;
+ Elf_Sym *sym;
+ const Elf_Sym *symtab;
+ Elf32_Word *symtab_shndx = NULL;
+ Elf_Sym *sort_needed_sym = NULL;
+ Elf_Shdr *sort_needed_sec;
+ Elf_Rel *relocs = NULL;
+ int relocs_size = 0;
+ uint32_t *sort_needed_loc;
+ const char *secstrings;
+ const char *strtab;
+ char *extab_image;
+ int extab_index = 0;
+ int i;
+ int idx;
+ unsigned int shnum;
+ unsigned int shstrndx;
+#if defined(SORTTABLE_64) && defined(UNWINDER_ORC_ENABLED)
+ unsigned int orc_ip_size = 0;
+ unsigned int orc_size = 0;
+ unsigned int orc_num_entries = 0;
+#endif
+
+ shstrndx = r2(&ehdr->e_shstrndx);
+ if (shstrndx == SHN_XINDEX)
+ shstrndx = r(&shdr[0].sh_link);
+ secstrings = (const char *)ehdr + _r(&shdr[shstrndx].sh_offset);
+
+ shnum = r2(&ehdr->e_shnum);
+ if (shnum == SHN_UNDEF)
+ shnum = _r(&shdr[0].sh_size);
+
+ for (i = 0, s = shdr; s < shdr + shnum; i++, s++) {
+ idx = r(&s->sh_name);
+ if (!strcmp(secstrings + idx, "__ex_table")) {
+ extab_sec = s;
+ extab_index = i;
+ }
+ if (!strcmp(secstrings + idx, ".symtab"))
+ symtab_sec = s;
+ if (!strcmp(secstrings + idx, ".strtab"))
+ strtab_sec = s;
+
+ if ((r(&s->sh_type) == SHT_REL ||
+ r(&s->sh_type) == SHT_RELA) &&
+ r(&s->sh_info) == extab_index) {
+ relocs = (void *)ehdr + _r(&s->sh_offset);
+ relocs_size = _r(&s->sh_size);
+ }
+ if (r(&s->sh_type) == SHT_SYMTAB_SHNDX)
+ symtab_shndx = (Elf32_Word *)((const char *)ehdr +
+ _r(&s->sh_offset));
+
+#if defined(SORTTABLE_64) && defined(UNWINDER_ORC_ENABLED)
+ /* locate the ORC unwind tables */
+ if (!strcmp(secstrings + idx, ".orc_unwind_ip")) {
+ orc_ip_size = s->sh_size;
+ g_orc_ip_table = (int *)((void *)ehdr +
+ s->sh_offset);
+ }
+ if (!strcmp(secstrings + idx, ".orc_unwind")) {
+ orc_size = s->sh_size;
+ g_orc_table = (struct orc_entry *)((void *)ehdr +
+ s->sh_offset);
+ }
+#endif
+ } /* for loop */
+
+#if defined(SORTTABLE_64) && defined(UNWINDER_ORC_ENABLED)
+ if (!g_orc_ip_table || !g_orc_table) {
+ fprintf(stderr,
+ "incomplete ORC unwind tables in file: %s\n", fname);
+ goto out;
+ }
+
+ orc_num_entries = orc_ip_size / sizeof(int);
+ if (orc_ip_size % sizeof(int) != 0 ||
+ orc_size % sizeof(struct orc_entry) != 0 ||
+ orc_num_entries != orc_size / sizeof(struct orc_entry)) {
+ fprintf(stderr,
+ "inconsistent ORC unwind table entries in file: %s\n",
+ fname);
+ goto out;
+ }
+
+ /* create thread to sort ORC unwind tables concurrently */
+ if (pthread_create(&orc_sort_thread, NULL,
+ sort_orctable, &orc_ip_size)) {
+ fprintf(stderr,
+ "pthread_create orc_sort_thread failed '%s': %s\n",
+ strerror(errno), fname);
+ goto out;
+ }
+#endif
+ if (!extab_sec) {
+ fprintf(stderr, "no __ex_table in file: %s\n", fname);
+ goto out;
+ }
+
+ if (!symtab_sec) {
+ fprintf(stderr, "no .symtab in file: %s\n", fname);
+ goto out;
+ }
+
+ if (!strtab_sec) {
+ fprintf(stderr, "no .strtab in file: %s\n", fname);
+ goto out;
+ }
+
+ extab_image = (void *)ehdr + _r(&extab_sec->sh_offset);
+ strtab = (const char *)ehdr + _r(&strtab_sec->sh_offset);
+ symtab = (const Elf_Sym *)((const char *)ehdr +
+ _r(&symtab_sec->sh_offset));
+
+ if (custom_sort) {
+ custom_sort(extab_image, _r(&extab_sec->sh_size));
+ } else {
+ int num_entries = _r(&extab_sec->sh_size) / extable_ent_size;
+ qsort(extab_image, num_entries,
+ extable_ent_size, compare_extable);
+ }
+
+ /* If there were relocations, we no longer need them. */
+ if (relocs)
+ memset(relocs, 0, relocs_size);
+
+ /* find the flag main_extable_sort_needed */
+ for (sym = (void *)ehdr + _r(&symtab_sec->sh_offset);
+ sym < sym + _r(&symtab_sec->sh_size) / sizeof(Elf_Sym);
+ sym++) {
+ if (ELF_ST_TYPE(sym->st_info) != STT_OBJECT)
+ continue;
+ if (!strcmp(strtab + r(&sym->st_name),
+ "main_extable_sort_needed")) {
+ sort_needed_sym = sym;
+ break;
+ }
+ }
+
+ if (!sort_needed_sym) {
+ fprintf(stderr,
+ "no main_extable_sort_needed symbol in file: %s\n",
+ fname);
+ goto out;
+ }
+
+ sort_needed_sec = &shdr[get_secindex(r2(&sym->st_shndx),
+ sort_needed_sym - symtab,
+ symtab_shndx)];
+ sort_needed_loc = (void *)ehdr +
+ _r(&sort_needed_sec->sh_offset) +
+ _r(&sort_needed_sym->st_value) -
+ _r(&sort_needed_sec->sh_addr);
+
+ /* extable has been sorted, clear the flag */
+ w(0, sort_needed_loc);
+ rc = 0;
+
+out:
+#if defined(SORTTABLE_64) && defined(UNWINDER_ORC_ENABLED)
+ if (orc_sort_thread) {
+ void *retval = NULL;
+ /* wait for ORC tables sort done */
+ rc = pthread_join(orc_sort_thread, &retval);
+ if (rc)
+ fprintf(stderr,
+ "pthread_join failed '%s': %s\n",
+ strerror(errno), fname);
+ else if (retval) {
+ rc = -1;
+ fprintf(stderr,
+ "failed to sort ORC tables '%s': %s\n",
+ (char *)retval, fname);
+ }
+ }
+#endif
+ return rc;
+}
diff --git a/scripts/spelling.txt b/scripts/spelling.txt
index 672b5931bc8d..d9cd24cf0d40 100644
--- a/scripts/spelling.txt
+++ b/scripts/spelling.txt
@@ -39,6 +39,8 @@ accout||account
accquire||acquire
accquired||acquired
accross||across
+accumalate||accumulate
+accumalator||accumulator
acessable||accessible
acess||access
acessing||accessing
@@ -106,6 +108,7 @@ alogrithm||algorithm
alot||a lot
alow||allow
alows||allows
+alreay||already
alredy||already
altough||although
alue||value
@@ -174,7 +177,9 @@ atomatically||automatically
atomicly||atomically
atempt||attempt
attachement||attachment
+attatch||attach
attched||attached
+attemp||attempt
attemps||attempts
attemping||attempting
attepmpt||attempt
@@ -232,15 +237,18 @@ brievely||briefly
brigde||bridge
broadcase||broadcast
broadcat||broadcast
+bufer||buffer
bufufer||buffer
cacluated||calculated
caculate||calculate
caculation||calculation
cadidate||candidate
+cahces||caches
calender||calendar
calescing||coalescing
calle||called
callibration||calibration
+callled||called
calucate||calculate
calulate||calculate
cancelation||cancellation
@@ -311,6 +319,7 @@ compaibility||compatibility
comparsion||comparison
compatability||compatibility
compatable||compatible
+compatibililty||compatibility
compatibiliy||compatibility
compatibilty||compatibility
compatiblity||compatibility
@@ -330,9 +339,9 @@ comunication||communication
conbination||combination
conditionaly||conditionally
conditon||condition
+condtion||condition
conected||connected
conector||connector
-connecetd||connected
configration||configuration
configuartion||configuration
configuation||configuration
@@ -343,7 +352,9 @@ configuretion||configuration
configutation||configuration
conider||consider
conjuction||conjunction
+connecetd||connected
connectinos||connections
+connetor||connector
connnection||connection
connnections||connections
consistancy||consistency
@@ -388,6 +399,8 @@ dafault||default
deafult||default
deamon||daemon
debouce||debounce
+decendant||descendant
+decendants||descendants
decompres||decompress
decsribed||described
decription||description
@@ -411,11 +424,13 @@ delare||declare
delares||declares
delaring||declaring
delemiter||delimiter
+delievered||delivered
demodualtor||demodulator
demension||dimension
dependancies||dependencies
dependancy||dependency
dependant||dependent
+dependend||dependent
depreacted||deprecated
depreacte||deprecate
desactivate||deactivate
@@ -459,6 +474,7 @@ difinition||definition
digial||digital
dimention||dimension
dimesions||dimensions
+disgest||digest
dispalying||displaying
diplay||display
directon||direction
@@ -543,6 +559,7 @@ etsablishment||establishment
etsbalishment||establishment
excecutable||executable
exceded||exceeded
+exceeed||exceed
excellant||excellent
execeeded||exceeded
execeeds||exceeds
@@ -732,6 +749,7 @@ initialzing||initializing
initilization||initialization
initilize||initialize
initliaze||initialize
+initilized||initialized
inofficial||unofficial
inrerface||interface
insititute||institute
@@ -791,6 +809,8 @@ ireelevant||irrelevant
irrelevent||irrelevant
isnt||isn't
isssue||issue
+issus||issues
+iteraions||iterations
iternations||iterations
itertation||iteration
itslef||itself
@@ -817,6 +837,7 @@ libary||library
librairies||libraries
libraris||libraries
licenceing||licencing
+limted||limited
logaritmic||logarithmic
loggging||logging
loggin||login
@@ -913,6 +934,7 @@ nerver||never
nescessary||necessary
nessessary||necessary
noticable||noticeable
+notication||notification
notications||notifications
notifcations||notifications
notifed||notified
@@ -995,6 +1017,8 @@ peice||piece
pendantic||pedantic
peprocessor||preprocessor
perfoming||performing
+perfomring||performing
+periperal||peripheral
peripherial||peripheral
permissons||permissions
peroid||period
@@ -1031,6 +1055,7 @@ prefferably||preferably
premption||preemption
prepaired||prepared
preperation||preparation
+preprare||prepare
pressre||pressure
primative||primitive
princliple||principle
@@ -1052,6 +1077,7 @@ processsed||processed
processsing||processing
procteted||protected
prodecure||procedure
+progamming||programming
progams||programs
progess||progress
programers||programmers
@@ -1139,12 +1165,14 @@ replys||replies
reponse||response
representaion||representation
reqeust||request
+reqister||register
requestied||requested
requiere||require
requirment||requirement
requred||required
requried||required
requst||request
+requsted||requested
reregisteration||reregistration
reseting||resetting
reseved||reserved
@@ -1166,6 +1194,8 @@ retreive||retrieve
retreiving||retrieving
retrive||retrieve
retrived||retrieved
+retrun||return
+retun||return
retuned||returned
reudce||reduce
reuest||request
@@ -1213,10 +1243,12 @@ seqeuncer||sequencer
seqeuencer||sequencer
sequece||sequence
sequencial||sequential
+serivce||service
serveral||several
servive||service
setts||sets
settting||setting
+shapshot||snapshot
shotdown||shutdown
shoud||should
shouldnt||shouldn't
@@ -1314,6 +1346,7 @@ swithcing||switching
swithed||switched
swithing||switching
swtich||switch
+syfs||sysfs
symetric||symmetric
synax||syntax
synchonized||synchronized
diff --git a/scripts/sphinx-pre-install b/scripts/sphinx-pre-install
index 470ccfe678aa..fa3fb05cd54b 100755
--- a/scripts/sphinx-pre-install
+++ b/scripts/sphinx-pre-install
@@ -272,7 +272,7 @@ sub check_sphinx()
open IN, "$sphinx --version 2>&1 |" or die "$sphinx returned an error";
while (<IN>) {
- if (m/^\s*sphinx-build\s+([\d\.]+)$/) {
+ if (m/^\s*sphinx-build\s+([\d\.]+)(\+\/[\da-f]+)?$/) {
$cur_version=$1;
last;
}
@@ -701,11 +701,26 @@ sub check_needs()
} else {
my $rec_activate = "$virtenv_dir/bin/activate";
my $virtualenv = findprog("virtualenv-3");
+ my $rec_python3 = "";
$virtualenv = findprog("virtualenv-3.5") if (!$virtualenv);
$virtualenv = findprog("virtualenv") if (!$virtualenv);
$virtualenv = "virtualenv" if (!$virtualenv);
- printf "\t$virtualenv $virtenv_dir\n";
+ my $rel = "";
+ if (index($system_release, "Ubuntu") != -1) {
+ $rel = $1 if ($system_release =~ /Ubuntu\s+(\d+)[.]/);
+ if ($rel && $rel >= 16) {
+ $rec_python3 = " -p python3";
+ }
+ }
+ if (index($system_release, "Debian") != -1) {
+ $rel = $1 if ($system_release =~ /Debian\s+(\d+)/);
+ if ($rel && $rel >= 7) {
+ $rec_python3 = " -p python3";
+ }
+ }
+
+ printf "\t$virtualenv$rec_python3 $virtenv_dir\n";
printf "\t. $rec_activate\n";
printf "\tpip install -r $requirement_file\n";
deactivate_help();
diff --git a/scripts/ver_linux b/scripts/ver_linux
index 85005d6b7f10..0968a3070eff 100755
--- a/scripts/ver_linux
+++ b/scripts/ver_linux
@@ -14,6 +14,8 @@ BEGIN {
printf("\n")
vernum = "[0-9]+([.]?[0-9]+)+"
+ libc = "libc[.]so[.][0-9]+$"
+ libcpp = "(libg|stdc)[+]+[.]so[.][0-9]+$"
printversion("GNU C", version("gcc -dumpversion"))
printversion("GNU Make", version("make --version"))
@@ -35,26 +37,14 @@ BEGIN {
printversion("Bison", version("bison --version"))
printversion("Flex", version("flex --version"))
- while (getline <"/proc/self/maps" > 0) {
- if (/libc.*\.so$/) {
- n = split($0, procmaps, "/")
- if (match(procmaps[n], vernum)) {
- ver = substr(procmaps[n], RSTART, RLENGTH)
- printversion("Linux C Library", ver)
- break
- }
- }
+ 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)
}
printversion("Dynamic linker (ldd)", version("ldd --version"))
-
- while ("ldconfig -p 2>/dev/null" | getline > 0) {
- if (/(libg|stdc)[+]+\.so/) {
- libcpp = $NF
- break
- }
- }
- printversion("Linux C++ Library", version("readlink " libcpp))
printversion("Procps", version("ps --version"))
printversion("Net-tools", version("ifconfig --version"))
printversion("Kbd", version("loadkeys -V"))