Update Linux to v5.4.2
Change-Id: Idf6911045d9d382da2cfe01b1edff026404ac8fd
diff --git a/scripts/.gitignore b/scripts/.gitignore
index 12d302d..17f8cef 100644
--- a/scripts/.gitignore
+++ b/scripts/.gitignore
@@ -6,9 +6,7 @@
kallsyms
pnmtologo
unifdef
-ihex2fw
recordmcount
-check-lc_ctype
sortextable
asn1_compiler
extract-cert
diff --git a/scripts/Kbuild.include b/scripts/Kbuild.include
index ce53639..10ba926 100644
--- a/scripts/Kbuild.include
+++ b/scripts/Kbuild.include
@@ -1,3 +1,4 @@
+# SPDX-License-Identifier: GPL-2.0
####
# kbuild: Generic definitions
@@ -24,8 +25,8 @@
basetarget = $(basename $(notdir $@))
###
-# filename of first prerequisite with directory and extension stripped
-baseprereq = $(basename $(notdir $<))
+# real prerequisites without phony targets
+real-prereqs = $(filter-out $(PHONY), $^)
###
# Escape single quote for use in echo statements
@@ -41,11 +42,11 @@
###
# filechk is used to check if the content of a generated file is updated.
# Sample usage:
-# define filechk_sample
-# echo $KERNELRELEASE
-# endef
-# version.h : Makefile
+#
+# filechk_sample = echo $(KERNELRELEASE)
+# version.h: FORCE
# $(call filechk,sample)
+#
# The rule defined shall write to stdout the content of the new file.
# The existing file will be compared with the new one.
# - If no file exist it is created
@@ -56,7 +57,7 @@
define filechk
$(Q)set -e; \
mkdir -p $(dir $@); \
- $(filechk_$(1)) > $@.tmp; \
+ { $(filechk_$(1)); } > $@.tmp; \
if [ -r $@ ] && cmp -s $@ $@.tmp; then \
rm -f $@.tmp; \
else \
@@ -67,18 +68,19 @@
######
# gcc support functions
-# See documentation in Documentation/kbuild/makefiles.txt
+# See documentation in Documentation/kbuild/makefiles.rst
# cc-cross-prefix
# Usage: CROSS_COMPILE := $(call cc-cross-prefix, m68k-linux-gnu- m68k-linux-)
-# Return first prefix where a prefix$(CC) is found in PATH.
-# If no $(CC) found in PATH with listed prefixes return nothing
-cc-cross-prefix = \
- $(word 1, $(foreach c,$(1), \
- $(shell set -e; \
- if (which $(strip $(c))$(CC)) > /dev/null 2>&1 ; then \
- echo $(c); \
- fi)))
+# Return first <prefix> where a <prefix>gcc is found in PATH.
+# If no gcc found in PATH with listed prefixes return nothing
+#
+# Note: '2>/dev/null' is here to force Make to invoke a shell. Otherwise, it
+# would try to directly execute the shell builtin 'command'. This workaround
+# should be kept for a long time since this issue was fixed only after the
+# GNU Make 4.2.1 release.
+cc-cross-prefix = $(firstword $(foreach c, $(1), \
+ $(if $(shell command -v -- $(c)gcc 2>/dev/null), $(c))))
# output directory for tests below
TMPOUT := $(if $(KBUILD_EXTMOD),$(firstword $(KBUILD_EXTMOD))/)
@@ -123,11 +125,6 @@
cc-option = $(call __cc-option, $(CC),\
$(KBUILD_CPPFLAGS) $(CC_OPTION_CFLAGS),$(1),$(2))
-# hostcc-option
-# Usage: cflags-y += $(call hostcc-option,-march=winchip-c6,-march=i586)
-hostcc-option = $(call __cc-option, $(HOSTCC),\
- $(KBUILD_HOSTCFLAGS) $(HOST_EXTRACFLAGS),$(1),$(2))
-
# cc-option-yn
# Usage: flag := $(call cc-option-yn,-march=winchip-c6)
cc-option-yn = $(call try-run,\
@@ -138,35 +135,14 @@
cc-disable-warning = $(call try-run,\
$(CC) -Werror $(KBUILD_CPPFLAGS) $(CC_OPTION_CFLAGS) -W$(strip $(1)) -c -x c /dev/null -o "$$TMP",-Wno-$(strip $(1)))
-# cc-name
-# Expands to either gcc or clang
-cc-name = $(shell $(CC) -v 2>&1 | grep -q "clang version" && echo clang || echo gcc)
-
-# cc-version
-cc-version = $(shell $(CONFIG_SHELL) $(srctree)/scripts/gcc-version.sh $(CC))
-
-# cc-fullversion
-cc-fullversion = $(shell $(CONFIG_SHELL) \
- $(srctree)/scripts/gcc-version.sh -p $(CC))
-
# cc-ifversion
# Usage: EXTRA_CFLAGS += $(call cc-ifversion, -lt, 0402, -O1)
-cc-ifversion = $(shell [ $(cc-version) $(1) $(2) ] && echo $(3) || echo $(4))
-
-# cc-ldoption
-# Usage: ldflags += $(call cc-ldoption, -Wl$(comma)--hash-style=both)
-cc-ldoption = $(call try-run,\
- $(CC) $(1) $(KBUILD_CPPFLAGS) $(CC_OPTION_CFLAGS) -nostdlib -x c /dev/null -o "$$TMP",$(1),$(2))
+cc-ifversion = $(shell [ $(CONFIG_GCC_VERSION)0 $(1) $(2)000 ] && echo $(3) || echo $(4))
# ld-option
# Usage: KBUILD_LDFLAGS += $(call ld-option, -X, -Y)
ld-option = $(call try-run, $(LD) $(KBUILD_LDFLAGS) $(1) -v,$(1),$(2),$(3))
-# ar-option
-# Usage: KBUILD_ARFLAGS := $(call ar-option,D)
-# Important: no spaces around options
-ar-option = $(call try-run, $(AR) rc$(1) "$$TMP",$(1),$(2))
-
# ld-version
# Note this is mainly for HJ Lu's 3 number binutil versions
ld-version = $(shell $(LD) --version | $(srctree)/scripts/ld-version.sh)
@@ -193,7 +169,7 @@
# Shorthand for $(Q)$(MAKE) -f scripts/Makefile.dtbinst obj=
# Usage:
# $(Q)$(MAKE) $(dtbinst)=dir
-dtbinst := -f $(if $(KBUILD_SRC),$(srctree)/)scripts/Makefile.dtbinst obj
+dtbinst := -f $(srctree)/scripts/Makefile.dtbinst obj
###
# Shorthand for $(Q)$(MAKE) -f scripts/Makefile.clean obj=
@@ -201,30 +177,13 @@
# $(Q)$(MAKE) $(clean)=dir
clean := -f $(srctree)/scripts/Makefile.clean obj
-###
-# Shorthand for $(Q)$(MAKE) -f scripts/Makefile.headersinst obj=
-# Usage:
-# $(Q)$(MAKE) $(hdr-inst)=dir
-hdr-inst := -f $(srctree)/scripts/Makefile.headersinst obj
-
-# Prefix -I with $(srctree) if it is not an absolute path.
-# skip if -I has no parameter
-addtree = $(if $(patsubst -I%,%,$(1)), \
-$(if $(filter-out -I/% -I./% -I../%,$(1)),$(patsubst -I%,-I$(srctree)/%,$(1)),$(1)),$(1))
-
-# Find all -I options and call addtree
-flags = $(foreach o,$($(1)),$(if $(filter -I%,$(o)),$(call addtree,$(o)),$(o)))
-
# echo command.
# Short version is used, if $(quiet) equals `quiet_', otherwise full one.
echo-cmd = $(if $($(quiet)cmd_$(1)),\
echo ' $(call escsq,$($(quiet)cmd_$(1)))$(echo-why)';)
# printing commands
-cmd = @$(echo-cmd) $(cmd_$(1))
-
-# Add $(obj)/ for paths that are not absolute
-objectify = $(foreach o,$(1),$(if $(filter /%,$(o)),$(o),$(obj)/$(o)))
+cmd = @set -e; $(echo-cmd) $(cmd_$(1))
###
# if_changed - execute command if any prerequisite is newer than
@@ -232,15 +191,15 @@
# if_changed_dep - as if_changed, but uses fixdep to reveal dependencies
# including used config symbols
# if_changed_rule - as if_changed but execute rule instead
-# See Documentation/kbuild/makefiles.txt for more info
+# See Documentation/kbuild/makefiles.rst for more info
ifneq ($(KBUILD_NOCMDDEP),1)
-# Check if both arguments are the same including their order. Result is empty
+# Check if both commands are the same including their order. Result is empty
# string if equal. User may override this check using make KBUILD_NOCMDDEP=1
-arg-check = $(filter-out $(subst $(space),$(space_escape),$(strip $(cmd_$@))), \
+cmd-check = $(filter-out $(subst $(space),$(space_escape),$(strip $(cmd_$@))), \
$(subst $(space),$(space_escape),$(strip $(cmd_$1))))
else
-arg-check = $(if $(strip $(cmd_$@)),,1)
+cmd-check = $(if $(strip $(cmd_$@)),,1)
endif
# Replace >$< with >$$< to preserve $ when reloading the .cmd file
@@ -253,60 +212,25 @@
# Find any prerequisites that is newer than target or that does not exist.
# PHONY targets skipped in both cases.
-any-prereq = $(filter-out $(PHONY),$?) $(filter-out $(PHONY) $(wildcard $^),$^)
+any-prereq = $(filter-out $(PHONY),$?)$(filter-out $(PHONY) $(wildcard $^),$^)
# Execute command if command has changed or prerequisite(s) are updated.
-if_changed = $(if $(strip $(any-prereq) $(arg-check)), \
- @set -e; \
- $(echo-cmd) $(cmd_$(1)); \
+if_changed = $(if $(any-prereq)$(cmd-check), \
+ $(cmd); \
printf '%s\n' 'cmd_$@ := $(make-cmd)' > $(dot-target).cmd, @:)
# Execute the command and also postprocess generated .d dependencies file.
-if_changed_dep = $(if $(strip $(any-prereq) $(arg-check) ), \
- @set -e; \
- $(cmd_and_fixdep), @:)
-
-ifndef CONFIG_TRIM_UNUSED_KSYMS
+if_changed_dep = $(if $(any-prereq)$(cmd-check),$(cmd_and_fixdep),@:)
cmd_and_fixdep = \
- $(echo-cmd) $(cmd_$(1)); \
- scripts/basic/fixdep $(depfile) $@ '$(make-cmd)' > $(dot-target).tmp;\
- rm -f $(depfile); \
- mv -f $(dot-target).tmp $(dot-target).cmd;
-
-else
-
-# Filter out exported kernel symbol names from the preprocessor output.
-# See also __KSYM_DEPS__ in include/linux/export.h.
-# We disable the depfile generation here, so as not to overwrite the existing
-# depfile while fixdep is parsing it.
-flags_nodeps = $(filter-out -Wp$(comma)-M%, $($(1)))
-ksym_dep_filter = \
- case "$(1)" in \
- cc_*_c|cpp_i_c) \
- $(CPP) $(call flags_nodeps,c_flags) -D__KSYM_DEPS__ $< ;; \
- as_*_S|cpp_s_S) \
- $(CPP) $(call flags_nodeps,a_flags) -D__KSYM_DEPS__ $< ;; \
- boot*|build*|cpp_its_S|*cpp_lds_S|dtc|host*|vdso*) : ;; \
- *) echo "Don't know how to preprocess $(1)" >&2; false ;; \
- esac | tr ";" "\n" | sed -n 's/^.*=== __KSYM_\(.*\) ===.*$$/_\1/p'
-
-cmd_and_fixdep = \
- $(echo-cmd) $(cmd_$(1)); \
- $(ksym_dep_filter) | \
- scripts/basic/fixdep -e $(depfile) $@ '$(make-cmd)' \
- > $(dot-target).tmp; \
- rm -f $(depfile); \
- mv -f $(dot-target).tmp $(dot-target).cmd;
-
-endif
+ $(cmd); \
+ scripts/basic/fixdep $(depfile) $@ '$(make-cmd)' > $(dot-target).cmd;\
+ rm -f $(depfile)
# Usage: $(call if_changed_rule,foo)
# Will check if $(cmd_foo) or any of the prerequisites changed,
# and if so will execute $(rule_foo).
-if_changed_rule = $(if $(strip $(any-prereq) $(arg-check) ), \
- @set -e; \
- $(rule_$(1)), @:)
+if_changed_rule = $(if $(any-prereq)$(cmd-check),$(rule_$(1)),@:)
###
# why - tell why a target got built
@@ -331,8 +255,8 @@
why = \
$(if $(filter $@, $(PHONY)),- due to target is PHONY, \
$(if $(wildcard $@), \
- $(if $(strip $(any-prereq)),- due to: $(any-prereq), \
- $(if $(arg-check), \
+ $(if $(any-prereq),- due to: $(any-prereq), \
+ $(if $(cmd-check), \
$(if $(cmd_$@),- due to command line change, \
$(if $(filter $@, $(targets)), \
- due to missing .cmd file, \
@@ -399,3 +323,6 @@
# delete partially updated (i.e. corrupted) files on error
.DELETE_ON_ERROR:
+
+# do not delete intermediate files automatically
+.SECONDARY:
diff --git a/scripts/Kconfig.include b/scripts/Kconfig.include
index dad5583..d4adfbe 100644
--- a/scripts/Kconfig.include
+++ b/scripts/Kconfig.include
@@ -1,3 +1,4 @@
+# SPDX-License-Identifier: GPL-2.0-only
# Kconfig helper macros
# Convenient variables
@@ -18,13 +19,24 @@
# Return y if <command> exits with 0, n otherwise
success = $(if-success,$(1),y,n)
+# $(failure,<command>)
+# Return n if <command> exits with 0, y otherwise
+failure = $(if-success,$(1),n,y)
+
# $(cc-option,<flag>)
# Return y if the compiler supports <flag>, n otherwise
-cc-option = $(success,$(CC) -Werror $(1) -E -x c /dev/null -o /dev/null)
+cc-option = $(success,$(CC) -Werror $(CLANG_FLAGS) $(1) -E -x c /dev/null -o /dev/null)
# $(ld-option,<flag>)
# Return y if the linker supports <flag>, n otherwise
ld-option = $(success,$(LD) -v $(1))
+# 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)
+
+# 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 -p $(CC) | sed 's/^0*//')
+gcc-version := $(shell,$(srctree)/scripts/gcc-version.sh $(CC))
diff --git a/scripts/Makefile b/scripts/Makefile
index 61affa3..3e86b30 100644
--- a/scripts/Makefile
+++ b/scripts/Makefile
@@ -17,7 +17,7 @@
hostprogs-$(BUILD_C_RECORDMCOUNT) += recordmcount
hostprogs-$(CONFIG_BUILDTIME_EXTABLE_SORT) += sortextable
hostprogs-$(CONFIG_ASN1) += asn1_compiler
-hostprogs-$(CONFIG_MODULE_SIG) += sign-file
+hostprogs-$(CONFIG_MODULE_SIG_FORMAT) += sign-file
hostprogs-$(CONFIG_SYSTEM_TRUSTED_KEYRING) += extract-cert
hostprogs-$(CONFIG_SYSTEM_EXTRA_CERTIFICATE) += insert-sys-cert
@@ -31,16 +31,9 @@
# The following hostprogs-y programs are only build on demand
hostprogs-y += unifdef
-# These targets are used internally to avoid "is up to date" messages
-PHONY += build_unifdef
-build_unifdef: $(obj)/unifdef
- @:
-
+subdir-$(CONFIG_GCC_PLUGINS) += gcc-plugins
subdir-$(CONFIG_MODVERSIONS) += genksyms
-subdir-y += mod
subdir-$(CONFIG_SECURITY_SELINUX) += selinux
-subdir-$(CONFIG_DTC) += dtc
-subdir-$(CONFIG_GDB_SCRIPTS) += gdb
# Let clean descend into subdirs
-subdir- += basic kconfig package gcc-plugins
+subdir- += basic dtc gdb kconfig mod
diff --git a/scripts/Makefile.asm-generic b/scripts/Makefile.asm-generic
index 32ad8e9..82ad63d 100644
--- a/scripts/Makefile.asm-generic
+++ b/scripts/Makefile.asm-generic
@@ -2,41 +2,57 @@
# include/asm-generic contains a lot of files that are used
# verbatim by several architectures.
#
-# This Makefile reads the file arch/$(SRCARCH)/include/$(src)/Kbuild
+# This Makefile reads the file arch/$(SRCARCH)/include/(uapi/)/asm/Kbuild
# and for each file listed in this file with generic-y creates
-# a small wrapper file in $(obj) (arch/$(SRCARCH)/include/generated/$(src))
+# a small wrapper file in arch/$(SRCARCH)/include/generated/(uapi/)/asm.
PHONY := all
all:
-kbuild-file := $(srctree)/arch/$(SRCARCH)/include/$(src)/Kbuild
--include $(kbuild-file)
+src := $(subst /generated,,$(obj))
+-include $(src)/Kbuild
+
+# $(generic)/Kbuild lists mandatory-y. Exclude um since it is a special case.
+ifneq ($(SRCARCH),um)
+include $(generic)/Kbuild
+endif
include scripts/Kbuild.include
-# Create output directory if not already present
-_dummy := $(shell [ -d $(obj) ] || mkdir -p $(obj))
+redundant := $(filter $(mandatory-y) $(generated-y), $(generic-y))
+redundant += $(foreach f, $(generic-y), $(if $(wildcard $(srctree)/$(src)/$(f)),$(f)))
+redundant := $(sort $(redundant))
+$(if $(redundant),\
+ $(warning redundant generic-y found in $(src)/Kbuild: $(redundant)))
-# Stale wrappers when the corresponding files are removed from generic-y
-# need removing.
-generated-y := $(generic-y) $(generated-y)
-all-files := $(patsubst %, $(obj)/%, $(generated-y))
-old-headers := $(wildcard $(obj)/*.h)
-unwanted := $(filter-out $(all-files),$(old-headers))
+# If arch does not implement mandatory headers, fallback to asm-generic ones.
+mandatory-y := $(filter-out $(generated-y), $(mandatory-y))
+generic-y += $(foreach f, $(mandatory-y), $(if $(wildcard $(srctree)/$(src)/$(f)),,$(f)))
+
+generic-y := $(addprefix $(obj)/, $(generic-y))
+generated-y := $(addprefix $(obj)/, $(generated-y))
+
+# Remove stale wrappers when the corresponding files are removed from generic-y
+old-headers := $(wildcard $(obj)/*.h)
+unwanted := $(filter-out $(generic-y) $(generated-y),$(old-headers))
quiet_cmd_wrap = WRAP $@
-cmd_wrap = echo "\#include <asm-generic/$*.h>" >$@
+ cmd_wrap = echo "\#include <asm-generic/$*.h>" > $@
quiet_cmd_remove = REMOVE $(unwanted)
-cmd_remove = rm -f $(unwanted)
+ cmd_remove = rm -f $(unwanted)
-all: $(patsubst %, $(obj)/%, $(generic-y)) FORCE
- $(if $(unwanted),$(call cmd,remove),)
+all: $(generic-y)
+ $(if $(unwanted),$(call cmd,remove))
@:
$(obj)/%.h:
$(call cmd,wrap)
-PHONY += FORCE
+# Create output directory. Skip it if at least one old header exists
+# since we know the output directory already exists.
+ifeq ($(old-headers),)
+$(shell mkdir -p $(obj))
+endif
+
.PHONY: $(PHONY)
-FORCE: ;
diff --git a/scripts/Makefile.build b/scripts/Makefile.build
index 64fac0a..a9e4795 100644
--- a/scripts/Makefile.build
+++ b/scripts/Makefile.build
@@ -36,21 +36,11 @@
include scripts/Kbuild.include
-# For backward compatibility check that these variables do not change
-save-cflags := $(CFLAGS)
-
# 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)
-# If the save-* variables changed error out
-ifeq ($(KBUILD_NOPEDANTIC),)
- ifneq ("$(save-cflags)","$(CFLAGS)")
- $(error CFLAGS was changed in "$(kbuild-file)". Fix it to use ccflags-y)
- endif
-endif
-
include scripts/Makefile.lib
# Do not include host rules unless needed
@@ -62,6 +52,13 @@
$(warning kbuild: Makefile.build is included improperly)
endif
+ifeq ($(need-modorder),)
+ifneq ($(obj-m),)
+$(warning $(patsubst %.o,'%.ko',$(obj-m)) will not be built even though obj-m is specified.)
+$(warning You cannot use subdir-y/m to visit a module Makefile. Use obj-y/m instead.)
+endif
+endif
+
# ===========================================================================
ifneq ($(strip $(lib-y) $(lib-m) $(lib-)),)
@@ -73,59 +70,30 @@
builtin-target := $(obj)/built-in.a
endif
+ifeq ($(CONFIG_MODULES)$(need-modorder),y1)
modorder-target := $(obj)/modules.order
+endif
-# We keep a list of all modules in $(MODVERDIR)
-
-__build: $(if $(KBUILD_BUILTIN),$(builtin-target) $(lib-target) $(extra-y)) \
- $(if $(KBUILD_MODULES),$(obj-m) $(modorder-target)) \
- $(subdir-ym) $(always)
- @:
+mod-targets := $(patsubst %.o, %.mod, $(obj-m))
# Linus' kernel sanity checking tool
-ifneq ($(KBUILD_CHECKSRC),0)
- ifeq ($(KBUILD_CHECKSRC),2)
- quiet_cmd_force_checksrc = CHECK $<
- cmd_force_checksrc = $(CHECK) $(CHECKFLAGS) $(c_flags) $< ;
- else
- quiet_cmd_checksrc = CHECK $<
- cmd_checksrc = $(CHECK) $(CHECKFLAGS) $(c_flags) $< ;
- endif
+ifeq ($(KBUILD_CHECKSRC),1)
+ quiet_cmd_checksrc = CHECK $<
+ cmd_checksrc = $(CHECK) $(CHECKFLAGS) $(c_flags) $<
+else ifeq ($(KBUILD_CHECKSRC),2)
+ quiet_cmd_force_checksrc = CHECK $<
+ cmd_force_checksrc = $(CHECK) $(CHECKFLAGS) $(c_flags) $<
endif
-ifneq ($(KBUILD_ENABLE_EXTRA_GCC_CHECKS),)
- cmd_checkdoc = $(srctree)/scripts/kernel-doc -none $< ;
-endif
-
-# Do section mismatch analysis for each module/built-in.a
-ifdef CONFIG_DEBUG_SECTION_MISMATCH
- cmd_secanalysis = ; scripts/mod/modpost $@
+ifneq ($(KBUILD_EXTRA_WARN),)
+ cmd_checkdoc = $(srctree)/scripts/kernel-doc -none $<
endif
# Compile C sources (.c)
# ---------------------------------------------------------------------------
-# Default is built-in, unless we know otherwise
-modkern_cflags = \
- $(if $(part-of-module), \
- $(KBUILD_CFLAGS_MODULE) $(CFLAGS_MODULE), \
- $(KBUILD_CFLAGS_KERNEL) $(CFLAGS_KERNEL))
-quiet_modtag := $(empty) $(empty)
-
-$(real-obj-m) : part-of-module := y
-$(real-obj-m:.o=.i) : part-of-module := y
-$(real-obj-m:.o=.s) : part-of-module := y
-$(real-obj-m:.o=.lst): part-of-module := y
-
-$(real-obj-m) : quiet_modtag := [M]
-$(real-obj-m:.o=.i) : quiet_modtag := [M]
-$(real-obj-m:.o=.s) : quiet_modtag := [M]
-$(real-obj-m:.o=.lst): quiet_modtag := [M]
-
-$(obj-m) : quiet_modtag := [M]
-
quiet_cmd_cc_s_c = CC $(quiet_modtag) $@
-cmd_cc_s_c = $(CC) $(c_flags) $(DISABLE_LTO) -fverbose-asm -S -o $@ $<
+ cmd_cc_s_c = $(CC) $(filter-out $(DEBUG_CFLAGS), $(c_flags)) $(DISABLE_LTO) -fverbose-asm -S -o $@ $<
$(obj)/%.s: $(src)/%.c FORCE
$(call if_changed_dep,cc_s_c)
@@ -139,14 +107,13 @@
# These mirror gensymtypes_S and co below, keep them in synch.
cmd_gensymtypes_c = \
$(CPP) -D__GENKSYMS__ $(c_flags) $< | \
- $(GENKSYMS) $(if $(1), -T $(2)) \
+ scripts/genksyms/genksyms $(if $(1), -T $(2)) \
$(patsubst y,-R,$(CONFIG_MODULE_REL_CRCS)) \
$(if $(KBUILD_PRESERVE),-p) \
-r $(firstword $(wildcard $(2:.symtypes=.symref) /dev/null))
quiet_cmd_cc_symtypes_c = SYM $(quiet_modtag) $@
cmd_cc_symtypes_c = \
- set -e; \
$(call cmd_gensymtypes_c,true,$@) >/dev/null; \
test -s $@ || rm -f $@
@@ -166,36 +133,31 @@
# (See cmd_cc_o_c + relevant part of rule_cc_o_c)
quiet_cmd_cc_o_c = CC $(quiet_modtag) $@
+ cmd_cc_o_c = $(CC) $(c_flags) -c -o $@ $<
-ifndef CONFIG_MODVERSIONS
-cmd_cc_o_c = $(CC) $(c_flags) -c -o $@ $<
-
-else
+ifdef CONFIG_MODVERSIONS
# When module versioning is enabled the following steps are executed:
-# o compile a .tmp_<file>.o from <file>.c
-# o if .tmp_<file>.o doesn't contain a __ksymtab version, i.e. does
-# not export symbols, we just rename .tmp_<file>.o to <file>.o and
-# are done.
+# o compile a <file>.o from <file>.c
+# o if <file>.o doesn't contain a __ksymtab version, i.e. does
+# not export symbols, it's done.
# o otherwise, we calculate symbol versions using the good old
# genksyms on the preprocessed source and postprocess them in a way
# that they are usable as a linker script
-# o generate <file>.o from .tmp_<file>.o using the linker to
+# o generate .tmp_<file>.o from <file>.o using the linker to
# replace the unresolved symbols __crc_exported_symbol with
# the actual value of the checksum generated by genksyms
-
-cmd_cc_o_c = $(CC) $(c_flags) -c -o $(@D)/.tmp_$(@F) $<
+# o remove .tmp_<file>.o to <file>.o
cmd_modversions_c = \
- if $(OBJDUMP) -h $(@D)/.tmp_$(@F) | grep -q __ksymtab; then \
+ if $(OBJDUMP) -h $@ | grep -q __ksymtab; then \
$(call cmd_gensymtypes_c,$(KBUILD_SYMTYPES),$(@:.o=.symtypes)) \
> $(@D)/.tmp_$(@F:.o=.ver); \
\
- $(LD) $(KBUILD_LDFLAGS) -r -o $@ $(@D)/.tmp_$(@F) \
+ $(LD) $(KBUILD_LDFLAGS) -r -o $(@D)/.tmp_$(@F) $@ \
-T $(@D)/.tmp_$(@F:.o=.ver); \
- rm -f $(@D)/.tmp_$(@F) $(@D)/.tmp_$(@F:.o=.ver); \
- else \
mv -f $(@D)/.tmp_$(@F) $@; \
- fi;
+ rm -f $(@D)/.tmp_$(@F:.o=.ver); \
+ fi
endif
ifdef CONFIG_FTRACE_MCOUNT_RECORD
@@ -216,7 +178,7 @@
recordmcount_source := $(srctree)/scripts/recordmcount.c \
$(srctree)/scripts/recordmcount.h
else
-sub_cmd_record_mcount = set -e ; perl $(srctree)/scripts/recordmcount.pl "$(ARCH)" \
+sub_cmd_record_mcount = perl $(srctree)/scripts/recordmcount.pl "$(ARCH)" \
"$(if $(CONFIG_CPU_BIG_ENDIAN),big,little)" \
"$(if $(CONFIG_64BIT),64,32)" \
"$(OBJDUMP)" "$(OBJCOPY)" "$(CC) $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS)" \
@@ -224,11 +186,8 @@
"$(if $(part-of-module),1,0)" "$(@)";
recordmcount_source := $(srctree)/scripts/recordmcount.pl
endif # BUILD_C_RECORDMCOUNT
-cmd_record_mcount = \
- if [ "$(findstring $(CC_FLAGS_FTRACE),$(_c_flags))" = \
- "$(CC_FLAGS_FTRACE)" ]; then \
- $(sub_cmd_record_mcount) \
- fi;
+cmd_record_mcount = $(if $(findstring $(strip $(CC_FLAGS_FTRACE)),$(_c_flags)), \
+ $(sub_cmd_record_mcount))
endif # CC_USING_RECORD_MCOUNT
endif # CONFIG_FTRACE_MCOUNT_RECORD
@@ -250,12 +209,8 @@
ifdef CONFIG_RETPOLINE
objtool_args += --retpoline
endif
-
-
-ifdef CONFIG_MODVERSIONS
-objtool_o = $(@D)/.tmp_$(@F)
-else
-objtool_o = $(@)
+ifdef CONFIG_X86_SMAP
+ objtool_args += --uaccess
endif
# 'OBJECT_FILES_NON_STANDARD := y': skip objtool checking for a directory
@@ -263,7 +218,7 @@
# 'OBJECT_FILES_NON_STANDARD_foo.o := 'n': override directory skip for a file
cmd_objtool = $(if $(patsubst y%,, \
$(OBJECT_FILES_NON_STANDARD_$(basetarget).o)$(OBJECT_FILES_NON_STANDARD)n), \
- $(__objtool_obj) $(objtool_args) "$(objtool_o)";)
+ $(__objtool_obj) $(objtool_args) $@)
objtool_obj = $(if $(patsubst y%,, \
$(OBJECT_FILES_NON_STANDARD_$(basetarget).o)$(OBJECT_FILES_NON_STANDARD)n), \
$(__objtool_obj))
@@ -276,24 +231,31 @@
$(wildcard include/config/orc/unwinder.h \
include/config/stack/validation.h)
+ifdef CONFIG_TRIM_UNUSED_KSYMS
+cmd_gen_ksymdeps = \
+ $(CONFIG_SHELL) $(srctree)/scripts/gen_ksymdeps.sh $@ >> $(dot-target).cmd
+endif
+
define rule_cc_o_c
- $(call echo-cmd,checksrc) $(cmd_checksrc) \
- $(call cmd_and_fixdep,cc_o_c) \
- $(cmd_checkdoc) \
- $(call echo-cmd,objtool) $(cmd_objtool) \
- $(cmd_modversions_c) \
- $(call echo-cmd,record_mcount) $(cmd_record_mcount)
+ $(call cmd,checksrc)
+ $(call cmd_and_fixdep,cc_o_c)
+ $(call cmd,gen_ksymdeps)
+ $(call cmd,checkdoc)
+ $(call cmd,objtool)
+ $(call cmd,modversions_c)
+ $(call cmd,record_mcount)
endef
define rule_as_o_S
- $(call cmd_and_fixdep,as_o_S) \
- $(call echo-cmd,objtool) $(cmd_objtool) \
- $(cmd_modversions_S)
+ $(call cmd_and_fixdep,as_o_S)
+ $(call cmd,gen_ksymdeps)
+ $(call cmd,objtool)
+ $(call cmd,modversions_S)
endef
# List module undefined symbols (or empty line if not enabled)
ifdef CONFIG_TRIM_UNUSED_KSYMS
-cmd_undef_syms = $(NM) $@ | sed -n 's/^ *U //p' | xargs echo
+cmd_undef_syms = $(NM) $< | sed -n 's/^ *U //p' | xargs echo
else
cmd_undef_syms = echo
endif
@@ -303,13 +265,15 @@
$(call cmd,force_checksrc)
$(call if_changed_rule,cc_o_c)
-# Single-part modules are special since we need to mark them in $(MODVERDIR)
+cmd_mod = { \
+ echo $(if $($*-objs)$($*-y)$($*-m), $(addprefix $(obj)/, $($*-objs) $($*-y) $($*-m)), $(@:.mod=.o)); \
+ $(cmd_undef_syms); \
+ } > $@
-$(single-used-m): $(obj)/%.o: $(src)/%.c $(recordmcount_source) $(objtool_dep) FORCE
- $(call cmd,force_checksrc)
- $(call if_changed_rule,cc_o_c)
- @{ echo $(@:.o=.ko); echo $@; \
- $(cmd_undef_syms); } > $(MODVERDIR)/$(@F:.o=.mod)
+$(obj)/%.mod: $(obj)/%.o FORCE
+ $(call if_changed,mod)
+
+targets += $(mod-targets)
quiet_cmd_cc_lst_c = MKLST $@
cmd_cc_lst_c = $(CC) $(c_flags) -g -c -o $*.o $< && \
@@ -319,13 +283,17 @@
$(obj)/%.lst: $(src)/%.c FORCE
$(call if_changed_dep,cc_lst_c)
-# Compile assembler sources (.S)
+# header test (header-test-y, header-test-m target)
# ---------------------------------------------------------------------------
-modkern_aflags := $(KBUILD_AFLAGS_KERNEL) $(AFLAGS_KERNEL)
+quiet_cmd_cc_s_h = CC $@
+ cmd_cc_s_h = $(CC) $(c_flags) -S -o $@ -x c /dev/null -include $<
-$(real-obj-m) : modkern_aflags := $(KBUILD_AFLAGS_MODULE) $(AFLAGS_MODULE)
-$(real-obj-m:.o=.s): modkern_aflags := $(KBUILD_AFLAGS_MODULE) $(AFLAGS_MODULE)
+$(obj)/%.h.s: $(src)/%.h FORCE
+ $(call if_changed_dep,cc_s_h)
+
+# Compile assembler sources (.S)
+# ---------------------------------------------------------------------------
# .S file exports must have their C prototypes defined in asm/asm-prototypes.h
# or a file that it includes, in order to get versioned symbols. We build a
@@ -339,20 +307,19 @@
#
# These mirror gensymtypes_c and co above, keep them in synch.
cmd_gensymtypes_S = \
- (echo "\#include <linux/kernel.h>" ; \
+ { echo "\#include <linux/kernel.h>" ; \
echo "\#include <asm/asm-prototypes.h>" ; \
$(CPP) $(a_flags) $< | \
grep "\<___EXPORT_SYMBOL\>" | \
- sed 's/.*___EXPORT_SYMBOL[[:space:]]*\([a-zA-Z0-9_]*\)[[:space:]]*,.*/EXPORT_SYMBOL(\1);/' ) | \
+ sed 's/.*___EXPORT_SYMBOL[[:space:]]*\([a-zA-Z0-9_]*\)[[:space:]]*,.*/EXPORT_SYMBOL(\1);/' ; } | \
$(CPP) -D__GENKSYMS__ $(c_flags) -xc - | \
- $(GENKSYMS) $(if $(1), -T $(2)) \
+ scripts/genksyms/genksyms $(if $(1), -T $(2)) \
$(patsubst y,-R,$(CONFIG_MODULE_REL_CRCS)) \
$(if $(KBUILD_PRESERVE),-p) \
-r $(firstword $(wildcard $(2:.symtypes=.symref) /dev/null))
quiet_cmd_cc_symtypes_S = SYM $(quiet_modtag) $@
cmd_cc_symtypes_S = \
- set -e; \
$(call cmd_gensymtypes_S,true,$@) >/dev/null; \
test -s $@ || rm -f $@
@@ -367,36 +334,23 @@
$(call if_changed_dep,cpp_s_S)
quiet_cmd_as_o_S = AS $(quiet_modtag) $@
+ cmd_as_o_S = $(CC) $(a_flags) -c -o $@ $<
-ifndef CONFIG_MODVERSIONS
-cmd_as_o_S = $(CC) $(a_flags) -c -o $@ $<
-
-else
-
-ASM_PROTOTYPES := $(wildcard $(srctree)/arch/$(SRCARCH)/include/asm/asm-prototypes.h)
-
-ifeq ($(ASM_PROTOTYPES),)
-cmd_as_o_S = $(CC) $(a_flags) -c -o $@ $<
-
-else
+ifdef CONFIG_ASM_MODVERSIONS
# versioning matches the C process described above, with difference that
# we parse asm-prototypes.h C header to get function definitions.
-cmd_as_o_S = $(CC) $(a_flags) -c -o $(@D)/.tmp_$(@F) $<
-
cmd_modversions_S = \
- if $(OBJDUMP) -h $(@D)/.tmp_$(@F) | grep -q __ksymtab; then \
+ if $(OBJDUMP) -h $@ | grep -q __ksymtab; then \
$(call cmd_gensymtypes_S,$(KBUILD_SYMTYPES),$(@:.o=.symtypes)) \
> $(@D)/.tmp_$(@F:.o=.ver); \
\
- $(LD) $(KBUILD_LDFLAGS) -r -o $@ $(@D)/.tmp_$(@F) \
+ $(LD) $(KBUILD_LDFLAGS) -r -o $(@D)/.tmp_$(@F) $@ \
-T $(@D)/.tmp_$(@F:.o=.ver); \
- rm -f $(@D)/.tmp_$(@F) $(@D)/.tmp_$(@F:.o=.ver); \
- else \
mv -f $(@D)/.tmp_$(@F) $@; \
- fi;
-endif
+ rm -f $(@D)/.tmp_$(@F:.o=.ver); \
+ fi
endif
$(obj)/%.o: $(src)/%.S $(objtool_dep) FORCE
@@ -416,9 +370,9 @@
# ASN.1 grammar
# ---------------------------------------------------------------------------
-quiet_cmd_asn1_compiler = ASN.1 $@
+quiet_cmd_asn1_compiler = ASN.1 $(basename $@).[ch]
cmd_asn1_compiler = $(objtree)/scripts/asn1_compiler $< \
- $(subst .h,.c,$@) $(subst .c,.h,$@)
+ $(basename $@).c $(basename $@).h
$(obj)/%.asn1.c $(obj)/%.asn1.h: $(src)/%.asn1 $(objtree)/scripts/asn1_compiler
$(call cmd,asn1_compiler)
@@ -430,17 +384,12 @@
$(sort $(subdir-obj-y)): $(subdir-ym) ;
#
-# Rule to compile a set of .o files into one .o file
+# Rule to compile a set of .o files into one .a file (without symbol table)
#
ifdef builtin-target
-# built-in.a archives are made with no symbol table or index which
-# makes them small and fast, but unable to be used by the linker.
-# scripts/link-vmlinux.sh builds an aggregate built-in.a with a symbol
-# table and index.
quiet_cmd_ar_builtin = AR $@
- cmd_ar_builtin = rm -f $@; \
- $(AR) rcSTP$(KBUILD_ARFLAGS) $@ $(filter $(real-obj-y), $^)
+ cmd_ar_builtin = rm -f $@; $(AR) cDPrST $@ $(real-prereqs)
$(builtin-target): $(real-obj-y) FORCE
$(call if_changed,ar_builtin)
@@ -453,25 +402,18 @@
#
# Create commands to either record .ko file or cat modules.order from
# a subdirectory
-modorder-cmds = \
- $(foreach m, $(modorder), \
- $(if $(filter %/modules.order, $m), \
- cat $m;, echo kernel/$m;))
-
$(modorder-target): $(subdir-ym) FORCE
- $(Q)(cat /dev/null; $(modorder-cmds)) > $@
+ $(Q){ $(foreach m, $(modorder), \
+ $(if $(filter %/modules.order, $m), cat $m, echo $m);) :; } \
+ | $(AWK) '!x[$$0]++' - > $@
#
-# Rule to compile a set of .o files into one .a file
+# Rule to compile a set of .o files into one .a file (with symbol table)
#
ifdef lib-target
-quiet_cmd_link_l_target = AR $@
-
-# lib target archives do get a symbol table and index
-cmd_link_l_target = rm -f $@; $(AR) rcsTP$(KBUILD_ARFLAGS) $@ $(lib-y)
$(lib-target): $(lib-y) FORCE
- $(call if_changed,link_l_target)
+ $(call if_changed,ar)
targets += $(lib-target)
@@ -493,29 +435,15 @@
endif
-#
-# Rule to link composite objects
-#
-# Composite objects are specified in kbuild makefile as follows:
-# <composite-object>-objs := <list of .o files>
-# or
-# <composite-object>-y := <list of .o files>
-# or
-# <composite-object>-m := <list of .o files>
-# The -m syntax only works if <composite object> is a module
-link_multi_deps = \
-$(filter $(addprefix $(obj)/, \
-$($(subst $(obj)/,,$(@:.o=-objs))) \
-$($(subst $(obj)/,,$(@:.o=-y))) \
-$($(subst $(obj)/,,$(@:.o=-m)))), $^)
-
+# NOTE:
+# Do not replace $(filter %.o,^) with $(real-prereqs). When a single object
+# module is turned into a multi object module, $^ will contain header file
+# dependencies recorded in the .*.cmd file.
quiet_cmd_link_multi-m = LD [M] $@
-cmd_link_multi-m = $(LD) $(ld_flags) -r -o $@ $(link_multi_deps) $(cmd_secanalysis)
+ cmd_link_multi-m = $(LD) $(ld_flags) -r -o $@ $(filter %.o,$^)
$(multi-used-m): FORCE
$(call if_changed,link_multi-m)
- @{ echo $(@:.o=.ko); echo $(link_multi_deps); \
- $(cmd_undef_syms); } > $(MODVERDIR)/$(@F:.o=.mod)
$(call multi_depend, $(multi-used-m), .o, -objs -y -m)
targets += $(multi-used-m)
@@ -536,12 +464,52 @@
$(call intermediate_targets, .lex.o, .lex.c) \
$(call intermediate_targets, .tab.o, .tab.c .tab.h)
+# Build
+# ---------------------------------------------------------------------------
+
+ifdef single-build
+
+curdir-single := $(sort $(foreach x, $(KBUILD_SINGLE_TARGETS), \
+ $(if $(filter $(x) $(basename $(x)).o, $(targets)), $(x))))
+
+# Handle single targets without any rule: show "Nothing to be done for ..." or
+# "No rule to make target ..." depending on whether the target exists.
+unknown-single := $(filter-out $(addsuffix /%, $(subdir-ym)), \
+ $(filter $(obj)/%, \
+ $(filter-out $(curdir-single), \
+ $(KBUILD_SINGLE_TARGETS))))
+
+__build: $(curdir-single) $(subdir-ym)
+ifneq ($(unknown-single),)
+ $(Q)$(MAKE) -f /dev/null $(unknown-single)
+endif
+ @:
+
+ifeq ($(curdir-single),)
+# Nothing to do in this directory. Do not include any .*.cmd file for speed-up
+targets :=
+else
+targets += $(curdir-single)
+endif
+
+else
+
+__build: $(if $(KBUILD_BUILTIN),$(builtin-target) $(lib-target) $(extra-y)) \
+ $(if $(KBUILD_MODULES),$(obj-m) $(mod-targets) $(modorder-target)) \
+ $(subdir-ym) $(always)
+ @:
+
+endif
+
# Descending
# ---------------------------------------------------------------------------
PHONY += $(subdir-ym)
$(subdir-ym):
- $(Q)$(MAKE) $(build)=$@ need-builtin=$(if $(findstring $@,$(subdir-obj-y)),1)
+ $(Q)$(MAKE) $(build)=$@ \
+ $(if $(filter $@/, $(KBUILD_SINGLE_TARGETS)),single-build=) \
+ need-builtin=$(if $(filter $@/built-in.a, $(subdir-obj-y)),1) \
+ need-modorder=$(if $(need-modorder),$(if $(filter $@/modules.order, $(modorder)),1))
# Add FORCE to the prequisites of a target to force it to be always rebuilt.
# ---------------------------------------------------------------------------
@@ -555,25 +523,19 @@
# optimization, we don't need to read them if the target does not
# exist, we will rebuild anyway in that case.
-cmd_files := $(wildcard $(foreach f,$(sort $(targets)),$(dir $(f)).$(notdir $(f)).cmd))
+existing-targets := $(wildcard $(sort $(targets)))
-ifneq ($(cmd_files),)
- include $(cmd_files)
-endif
+-include $(foreach f,$(existing-targets),$(dir $(f)).$(notdir $(f)).cmd)
-ifneq ($(KBUILD_SRC),)
+ifdef building_out_of_srctree
# Create directories for object files if they do not exist
obj-dirs := $(sort $(obj) $(patsubst %/,%, $(dir $(targets))))
-# If cmd_files exist, their directories apparently exist. Skip mkdir.
-exist-dirs := $(sort $(patsubst %/,%, $(dir $(cmd_files))))
-obj-dirs := $(strip $(filter-out $(exist-dirs), $(obj-dirs)))
+# If targets exist, their directories apparently exist. Skip mkdir.
+existing-dirs := $(sort $(patsubst %/,%, $(dir $(existing-targets))))
+obj-dirs := $(strip $(filter-out $(existing-dirs), $(obj-dirs)))
ifneq ($(obj-dirs),)
$(shell mkdir -p $(obj-dirs))
endif
endif
-# Some files contained in $(targets) are intermediate artifacts.
-# We never want them to be removed automatically.
-.SECONDARY: $(targets)
-
.PHONY: $(PHONY)
diff --git a/scripts/Makefile.clean b/scripts/Makefile.clean
index 0b80e32..e367eb9 100644
--- a/scripts/Makefile.clean
+++ b/scripts/Makefile.clean
@@ -17,17 +17,8 @@
# Figure out what we need to build from the various variables
# ==========================================================================
-__subdir-y := $(patsubst %/,%,$(filter %/, $(obj-y)))
-subdir-y += $(__subdir-y)
-__subdir-m := $(patsubst %/,%,$(filter %/, $(obj-m)))
-subdir-m += $(__subdir-m)
-__subdir- := $(patsubst %/,%,$(filter %/, $(obj-)))
-subdir- += $(__subdir-)
-
-# Subdirectories we need to descend into
-
-subdir-ym := $(sort $(subdir-y) $(subdir-m))
-subdir-ymn := $(sort $(subdir-ym) $(subdir-))
+subdir-ymn := $(sort $(subdir-y) $(subdir-m) $(subdir-) \
+ $(patsubst %/,%, $(filter %/, $(obj-y) $(obj-m) $(obj-))))
# Add subdir path
@@ -52,26 +43,14 @@
$(addprefix $(obj)/, $(filter-out $(objtree)/%, $(__clean-files))) \
$(filter $(objtree)/%, $(__clean-files)))
-# same as clean-files
-
-__clean-dirs := $(wildcard \
- $(addprefix $(obj)/, $(filter-out $(objtree)/%, $(clean-dirs))) \
- $(filter $(objtree)/%, $(clean-dirs)))
-
# ==========================================================================
-quiet_cmd_clean = CLEAN $(obj)
- cmd_clean = rm -f $(__clean-files)
-quiet_cmd_cleandir = CLEAN $(__clean-dirs)
- cmd_cleandir = rm -rf $(__clean-dirs)
-
+quiet_cmd_clean = CLEAN $(obj)
+ cmd_clean = rm -rf $(__clean-files)
__clean: $(subdir-ymn)
ifneq ($(strip $(__clean-files)),)
- +$(call cmd,clean)
-endif
-ifneq ($(strip $(__clean-dirs)),)
- +$(call cmd,cleandir)
+ $(call cmd,clean)
endif
@:
diff --git a/scripts/Makefile.extrawarn b/scripts/Makefile.extrawarn
index 8d53570..ecddf83 100644
--- a/scripts/Makefile.extrawarn
+++ b/scripts/Makefile.extrawarn
@@ -1,76 +1,91 @@
# SPDX-License-Identifier: GPL-2.0
# ==========================================================================
-#
# make W=... settings
#
-# W=1 - warnings that may be relevant and does not occur too often
-# W=2 - warnings that occur quite often but may still be relevant
-# W=3 - the more obscure warnings, can most likely be ignored
-#
-# $(call cc-option, -W...) handles gcc -W.. options which
-# are not supported by all versions of the compiler
+# There are three warning groups enabled by W=1, W=2, W=3.
+# They are independent, and can be combined like W=12 or W=123.
# ==========================================================================
KBUILD_CFLAGS += $(call cc-disable-warning, packed-not-aligned)
+# backward compatibility
+KBUILD_EXTRA_WARN ?= $(KBUILD_ENABLE_EXTRA_GCC_CHECKS)
+
ifeq ("$(origin W)", "command line")
- export KBUILD_ENABLE_EXTRA_GCC_CHECKS := $(W)
+ KBUILD_EXTRA_WARN := $(W)
endif
-ifdef KBUILD_ENABLE_EXTRA_GCC_CHECKS
-warning- := $(empty)
+export KBUILD_EXTRA_WARN
-warning-1 := -Wextra -Wunused -Wno-unused-parameter
-warning-1 += -Wmissing-declarations
-warning-1 += -Wmissing-format-attribute
-warning-1 += $(call cc-option, -Wmissing-prototypes)
-warning-1 += -Wold-style-definition
-warning-1 += $(call cc-option, -Wmissing-include-dirs)
-warning-1 += $(call cc-option, -Wunused-but-set-variable)
-warning-1 += $(call cc-option, -Wunused-const-variable)
-warning-1 += $(call cc-option, -Wpacked-not-aligned)
-warning-1 += $(call cc-disable-warning, missing-field-initializers)
-warning-1 += $(call cc-disable-warning, sign-compare)
+#
+# W=1 - warnings which may be relevant and do not occur too often
+#
+ifneq ($(findstring 1, $(KBUILD_EXTRA_WARN)),)
-warning-2 := -Waggregate-return
-warning-2 += -Wcast-align
-warning-2 += -Wdisabled-optimization
-warning-2 += -Wnested-externs
-warning-2 += -Wshadow
-warning-2 += $(call cc-option, -Wlogical-op)
-warning-2 += $(call cc-option, -Wmissing-field-initializers)
-warning-2 += $(call cc-option, -Wsign-compare)
-warning-2 += $(call cc-option, -Wmaybe-uninitialized)
-warning-2 += $(call cc-option, -Wunused-macros)
+KBUILD_CFLAGS += -Wextra -Wunused -Wno-unused-parameter
+KBUILD_CFLAGS += -Wmissing-declarations
+KBUILD_CFLAGS += -Wmissing-format-attribute
+KBUILD_CFLAGS += -Wmissing-prototypes
+KBUILD_CFLAGS += -Wold-style-definition
+KBUILD_CFLAGS += -Wmissing-include-dirs
+KBUILD_CFLAGS += $(call cc-option, -Wunused-but-set-variable)
+KBUILD_CFLAGS += $(call cc-option, -Wunused-const-variable)
+KBUILD_CFLAGS += $(call cc-option, -Wpacked-not-aligned)
+KBUILD_CFLAGS += $(call cc-option, -Wstringop-truncation)
+# The following turn off the warnings enabled by -Wextra
+KBUILD_CFLAGS += -Wno-missing-field-initializers
+KBUILD_CFLAGS += -Wno-sign-compare
-warning-3 := -Wbad-function-cast
-warning-3 += -Wcast-qual
-warning-3 += -Wconversion
-warning-3 += -Wpacked
-warning-3 += -Wpadded
-warning-3 += -Wpointer-arith
-warning-3 += -Wredundant-decls
-warning-3 += -Wswitch-default
-warning-3 += $(call cc-option, -Wpacked-bitfield-compat)
-warning-3 += $(call cc-option, -Wvla)
+KBUILD_CPPFLAGS += -DKBUILD_EXTRA_WARN1
-warning := $(warning-$(findstring 1, $(KBUILD_ENABLE_EXTRA_GCC_CHECKS)))
-warning += $(warning-$(findstring 2, $(KBUILD_ENABLE_EXTRA_GCC_CHECKS)))
-warning += $(warning-$(findstring 3, $(KBUILD_ENABLE_EXTRA_GCC_CHECKS)))
-
-ifeq ("$(strip $(warning))","")
- $(error W=$(KBUILD_ENABLE_EXTRA_GCC_CHECKS) is unknown)
-endif
-
-KBUILD_CFLAGS += $(warning)
else
-ifeq ($(cc-name),clang)
-KBUILD_CFLAGS += $(call cc-disable-warning, initializer-overrides)
-KBUILD_CFLAGS += $(call cc-disable-warning, unused-value)
-KBUILD_CFLAGS += $(call cc-disable-warning, format)
-KBUILD_CFLAGS += $(call cc-disable-warning, sign-compare)
-KBUILD_CFLAGS += $(call cc-disable-warning, format-zero-length)
-KBUILD_CFLAGS += $(call cc-disable-warning, uninitialized)
+# Some diagnostics enabled by default are noisy.
+# Suppress them by using -Wno... except for W=1.
+
+ifdef CONFIG_CC_IS_CLANG
+KBUILD_CFLAGS += -Wno-initializer-overrides
+KBUILD_CFLAGS += -Wno-format
+KBUILD_CFLAGS += -Wno-sign-compare
+KBUILD_CFLAGS += -Wno-format-zero-length
endif
+
+endif
+
+#
+# W=2 - warnings which occur quite often but may still be relevant
+#
+ifneq ($(findstring 2, $(KBUILD_EXTRA_WARN)),)
+
+KBUILD_CFLAGS += -Wcast-align
+KBUILD_CFLAGS += -Wdisabled-optimization
+KBUILD_CFLAGS += -Wnested-externs
+KBUILD_CFLAGS += -Wshadow
+KBUILD_CFLAGS += $(call cc-option, -Wlogical-op)
+KBUILD_CFLAGS += -Wmissing-field-initializers
+KBUILD_CFLAGS += -Wsign-compare
+KBUILD_CFLAGS += $(call cc-option, -Wmaybe-uninitialized)
+KBUILD_CFLAGS += $(call cc-option, -Wunused-macros)
+
+KBUILD_CPPFLAGS += -DKBUILD_EXTRA_WARN2
+
+endif
+
+#
+# W=3 - more obscure warnings, can most likely be ignored
+#
+ifneq ($(findstring 3, $(KBUILD_EXTRA_WARN)),)
+
+KBUILD_CFLAGS += -Wbad-function-cast
+KBUILD_CFLAGS += -Wcast-qual
+KBUILD_CFLAGS += -Wconversion
+KBUILD_CFLAGS += -Wpacked
+KBUILD_CFLAGS += -Wpadded
+KBUILD_CFLAGS += -Wpointer-arith
+KBUILD_CFLAGS += -Wredundant-decls
+KBUILD_CFLAGS += -Wswitch-default
+KBUILD_CFLAGS += $(call cc-option, -Wpacked-bitfield-compat)
+
+KBUILD_CPPFLAGS += -DKBUILD_EXTRA_WARN3
+
endif
diff --git a/scripts/Makefile.gcc-plugins b/scripts/Makefile.gcc-plugins
index 0a482f3..5f7df50 100644
--- a/scripts/Makefile.gcc-plugins
+++ b/scripts/Makefile.gcc-plugins
@@ -15,6 +15,8 @@
gcc-plugin-$(CONFIG_GCC_PLUGIN_STRUCTLEAK) += structleak_plugin.so
gcc-plugin-cflags-$(CONFIG_GCC_PLUGIN_STRUCTLEAK_VERBOSE) \
+= -fplugin-arg-structleak_plugin-verbose
+gcc-plugin-cflags-$(CONFIG_GCC_PLUGIN_STRUCTLEAK_BYREF) \
+ += -fplugin-arg-structleak_plugin-byref
gcc-plugin-cflags-$(CONFIG_GCC_PLUGIN_STRUCTLEAK_BYREF_ALL) \
+= -fplugin-arg-structleak_plugin-byref-all
gcc-plugin-cflags-$(CONFIG_GCC_PLUGIN_STRUCTLEAK) \
@@ -26,6 +28,22 @@
gcc-plugin-cflags-$(CONFIG_GCC_PLUGIN_RANDSTRUCT_PERFORMANCE) \
+= -fplugin-arg-randomize_layout_plugin-performance-mode
+gcc-plugin-$(CONFIG_GCC_PLUGIN_STACKLEAK) += stackleak_plugin.so
+gcc-plugin-cflags-$(CONFIG_GCC_PLUGIN_STACKLEAK) \
+ += -DSTACKLEAK_PLUGIN
+gcc-plugin-cflags-$(CONFIG_GCC_PLUGIN_STACKLEAK) \
+ += -fplugin-arg-stackleak_plugin-track-min-size=$(CONFIG_STACKLEAK_TRACK_MIN_SIZE)
+ifdef CONFIG_GCC_PLUGIN_STACKLEAK
+ DISABLE_STACKLEAK_PLUGIN += -fplugin-arg-stackleak_plugin-disable
+endif
+export DISABLE_STACKLEAK_PLUGIN
+
+gcc-plugin-$(CONFIG_GCC_PLUGIN_ARM_SSP_PER_TASK) += arm_ssp_per_task_plugin.so
+ifdef CONFIG_GCC_PLUGIN_ARM_SSP_PER_TASK
+ DISABLE_ARM_SSP_PER_TASK_PLUGIN += -fplugin-arg-arm_ssp_per_task_plugin-disable
+endif
+export DISABLE_ARM_SSP_PER_TASK_PLUGIN
+
# All the plugin CFLAGS are collected here in case a build target needs to
# filter them out of the KBUILD_CFLAGS.
GCC_PLUGINS_CFLAGS := $(strip $(addprefix -fplugin=$(objtree)/scripts/gcc-plugins/, $(gcc-plugin-y)) $(gcc-plugin-cflags-y))
@@ -39,11 +57,3 @@
# All enabled GCC plugins are collected here for building below.
GCC_PLUGIN := $(gcc-plugin-y)
export GCC_PLUGIN
-
-# Actually do the build, if requested.
-PHONY += gcc-plugins
-gcc-plugins: scripts_basic
-ifdef CONFIG_GCC_PLUGINS
- $(Q)$(MAKE) $(build)=scripts/gcc-plugins
-endif
- @:
diff --git a/scripts/Makefile.headersinst b/scripts/Makefile.headersinst
index d5e1314..1b405a7 100644
--- a/scripts/Makefile.headersinst
+++ b/scripts/Makefile.headersinst
@@ -14,117 +14,89 @@
include scripts/Kbuild.include
-srcdir := $(srctree)/$(obj)
+src := $(srctree)/$(obj)
+gen := $(objtree)/$(subst include/,include/generated/,$(obj))
+dst := usr/include
-# When make is run under a fakechroot environment, the function
-# $(wildcard $(srcdir)/*/.) doesn't only return directories, but also regular
-# files. So, we are using a combination of sort/dir/wildcard which works
-# with fakechroot.
-subdirs := $(patsubst $(srcdir)/%/,%,\
- $(filter-out $(srcdir)/,\
- $(sort $(dir $(wildcard $(srcdir)/*/)))))
+-include $(src)/Kbuild
-# Recursion
-__headers: $(subdirs)
+# $(filter %/, ...) is a workaround for GNU Make <= 4.2.1, where
+# $(wildcard $(src)/*/) contains not only directories but also regular files.
+src-subdirs := $(patsubst $(src)/%/,%,$(filter %/, $(wildcard $(src)/*/)))
+gen-subdirs := $(patsubst $(gen)/%/,%,$(filter %/, $(wildcard $(gen)/*/)))
+all-subdirs := $(sort $(src-subdirs) $(gen-subdirs))
-PHONY += $(subdirs)
-$(subdirs):
- $(Q)$(MAKE) $(hdr-inst)=$(obj)/$@ dst=$(dst)/$@
+src-headers := $(if $(src-subdirs), $(shell cd $(src) && find $(src-subdirs) -name '*.h'))
+src-headers := $(filter-out $(no-export-headers), $(src-headers))
+gen-headers := $(if $(gen-subdirs), $(shell cd $(gen) && find $(gen-subdirs) -name '*.h'))
+gen-headers := $(filter-out $(no-export-headers), $(gen-headers))
-# Skip header install/check for include/uapi and arch/$(SRCARCH)/include/uapi.
-# We have only sub-directories there.
-skip-inst := $(if $(filter %/uapi,$(obj)),1)
+# If the same header is exported from source and generated directories,
+# the former takes precedence, but this should be warned.
+duplicated := $(filter $(gen-headers), $(src-headers))
+$(if $(duplicated), $(warning duplicated header export: $(duplicated)))
-ifeq ($(skip-inst),)
+gen-headers := $(filter-out $(duplicated), $(gen-headers))
-# Kbuild file is optional
-kbuild-file := $(srctree)/$(obj)/Kbuild
--include $(kbuild-file)
-
-installdir := $(INSTALL_HDR_PATH)/$(dst)
-gendir := $(objtree)/$(subst include/,include/generated/,$(obj))
-header-files := $(notdir $(wildcard $(srcdir)/*.h))
-header-files += $(notdir $(wildcard $(srcdir)/*.agh))
-header-files := $(filter-out $(no-export-headers), $(header-files))
-genhdr-files := $(notdir $(wildcard $(gendir)/*.h))
-genhdr-files := $(filter-out $(header-files), $(genhdr-files))
-
-# files used to track state of install/check
-install-file := $(installdir)/.install
-check-file := $(installdir)/.check
-
-# all headers files for this dir
-all-files := $(header-files) $(genhdr-files)
-output-files := $(addprefix $(installdir)/, $(all-files))
-
-ifneq ($(mandatory-y),)
-missing := $(filter-out $(all-files),$(mandatory-y))
-ifneq ($(missing),)
-$(error Some mandatory headers ($(missing)) are missing in $(obj))
-endif
-endif
+# Add dst path prefix
+all-subdirs := $(addprefix $(dst)/, $(all-subdirs))
+src-headers := $(addprefix $(dst)/, $(src-headers))
+gen-headers := $(addprefix $(dst)/, $(gen-headers))
+all-headers := $(src-headers) $(gen-headers)
# Work out what needs to be removed
-oldheaders := $(patsubst $(installdir)/%,%,$(wildcard $(installdir)/*.h))
-unwanted := $(filter-out $(all-files),$(oldheaders))
+old-subdirs := $(wildcard $(all-subdirs))
+old-headers := $(if $(old-subdirs),$(shell find $(old-subdirs) -name '*.h'))
+unwanted := $(filter-out $(all-headers), $(old-headers))
-# Prefix unwanted with full paths to $(INSTALL_HDR_PATH)
-unwanted-file := $(addprefix $(installdir)/, $(unwanted))
+# Create directories
+existing-dirs := $(sort $(dir $(old-headers)))
+wanted-dirs := $(sort $(dir $(all-headers)))
+new-dirs := $(filter-out $(existing-dirs), $(wanted-dirs))
+$(if $(new-dirs), $(shell mkdir -p $(new-dirs)))
-printdir = $(patsubst $(INSTALL_HDR_PATH)/%/,%,$(dir $@))
-
-quiet_cmd_install = INSTALL $(printdir) ($(words $(all-files))\
- file$(if $(word 2, $(all-files)),s))
- cmd_install = \
- $(CONFIG_SHELL) $< $(installdir) $(srcdir) $(header-files); \
- $(CONFIG_SHELL) $< $(installdir) $(gendir) $(genhdr-files); \
- touch $@
-
-quiet_cmd_remove = REMOVE $(unwanted)
- cmd_remove = rm -f $(unwanted-file)
-
-quiet_cmd_check = CHECK $(printdir) ($(words $(all-files)) files)
-# Headers list can be pretty long, xargs helps to avoid
-# the "Argument list too long" error.
- cmd_check = for f in $(all-files); do \
- echo "$(installdir)/$${f}"; done \
- | xargs \
- $(PERL) $< $(INSTALL_HDR_PATH)/include $(SRCARCH); \
- touch $@
+# Rules
ifndef HDRCHECK
-# Rules for installing headers
-__headers: $(install-file)
- @:
-targets += $(install-file)
-$(install-file): scripts/headers_install.sh \
- $(addprefix $(srcdir)/,$(header-files)) \
- $(addprefix $(gendir)/,$(genhdr-files)) FORCE
- $(if $(unwanted),$(call cmd,remove),)
- $(if $(wildcard $(dir $@)),,$(shell mkdir -p $(dir $@)))
+quiet_cmd_install = HDRINST $@
+ cmd_install = $(CONFIG_SHELL) $(srctree)/scripts/headers_install.sh $< $@
+
+$(src-headers): $(dst)/%.h: $(src)/%.h $(srctree)/scripts/headers_install.sh FORCE
$(call if_changed,install)
-else
-__headers: $(check-file)
+$(gen-headers): $(dst)/%.h: $(gen)/%.h $(srctree)/scripts/headers_install.sh FORCE
+ $(call if_changed,install)
+
+quiet_cmd_remove = REMOVE $(unwanted)
+ cmd_remove = rm -f $(unwanted)
+
+__headers: $(all-headers)
+ifneq ($(unwanted),)
+ $(call cmd,remove)
+endif
@:
-targets += $(check-file)
-$(check-file): scripts/headers_check.pl $(output-files) FORCE
- $(call if_changed,check)
+existing-headers := $(filter $(old-headers), $(all-headers))
+
+-include $(foreach f,$(existing-headers),$(dir $(f)).$(notdir $(f)).cmd)
+
+else
+
+quiet_cmd_check = HDRCHK $<
+ cmd_check = $(PERL) $(srctree)/scripts/headers_check.pl $(dst) $(SRCARCH) $<; touch $@
+
+check-files := $(addsuffix .chk, $(all-headers))
+
+$(check-files): $(dst)/%.chk : $(dst)/% $(srctree)/scripts/headers_check.pl
+ $(call cmd,check)
+
+__headers: $(check-files)
+ @:
endif
-cmd_files := $(wildcard \
- $(foreach f,$(sort $(targets)),$(dir $(f)).$(notdir $(f)).cmd))
-
-ifneq ($(cmd_files),)
- include $(cmd_files)
-endif
-
-endif # skip-inst
-
PHONY += FORCE
-FORCE: ;
+FORCE:
.PHONY: $(PHONY)
diff --git a/scripts/Makefile.host b/scripts/Makefile.host
index 0393f75..4c51c95 100644
--- a/scripts/Makefile.host
+++ b/scripts/Makefile.host
@@ -1,4 +1,21 @@
# SPDX-License-Identifier: GPL-2.0
+
+# LEX
+# ---------------------------------------------------------------------------
+quiet_cmd_flex = LEX $@
+ cmd_flex = $(LEX) -o$@ -L $<
+
+$(obj)/%.lex.c: $(src)/%.l FORCE
+ $(call if_changed,flex)
+
+# YACC
+# ---------------------------------------------------------------------------
+quiet_cmd_bison = YACC $(basename $@).[ch]
+ cmd_bison = $(YACC) -o $(basename $@).c --defines=$(basename $@).h -t -l $<
+
+$(obj)/%.tab.c $(obj)/%.tab.h: $(src)/%.y FORCE
+ $(call if_changed,bison)
+
# ==========================================================================
# Building binaries on the host system
# Binaries are used during the compilation of the kernel, for example
@@ -6,7 +23,7 @@
#
# Both C and C++ are supported, but preferred language is C for such utilities.
#
-# Sample syntax (see Documentation/kbuild/makefiles.txt for reference)
+# Sample syntax (see Documentation/kbuild/makefiles.rst for reference)
# hostprogs-y := bin2hex
# Will compile bin2hex.c and create an executable named bin2hex
#
@@ -63,20 +80,20 @@
# Handle options to gcc. Support building with separate output directory
_hostc_flags = $(KBUILD_HOSTCFLAGS) $(HOST_EXTRACFLAGS) \
- $(HOSTCFLAGS_$(basetarget).o)
+ $(HOSTCFLAGS_$(target-stem).o)
_hostcxx_flags = $(KBUILD_HOSTCXXFLAGS) $(HOST_EXTRACXXFLAGS) \
- $(HOSTCXXFLAGS_$(basetarget).o)
+ $(HOSTCXXFLAGS_$(target-stem).o)
-ifeq ($(KBUILD_SRC),)
-__hostc_flags = $(_hostc_flags)
-__hostcxx_flags = $(_hostcxx_flags)
-else
-__hostc_flags = -I$(obj) $(call flags,_hostc_flags)
-__hostcxx_flags = -I$(obj) $(call flags,_hostcxx_flags)
+# $(objtree)/$(obj) for including generated headers from checkin source files
+ifeq ($(KBUILD_EXTMOD),)
+ifdef building_out_of_srctree
+_hostc_flags += -I $(objtree)/$(obj)
+_hostcxx_flags += -I $(objtree)/$(obj)
+endif
endif
-hostc_flags = -Wp,-MD,$(depfile) $(__hostc_flags)
-hostcxx_flags = -Wp,-MD,$(depfile) $(__hostcxx_flags)
+hostc_flags = -Wp,-MD,$(depfile) $(_hostc_flags)
+hostcxx_flags = -Wp,-MD,$(depfile) $(_hostcxx_flags)
#####
# Compile programs on the host
@@ -85,7 +102,7 @@
# host-csingle -> Executable
quiet_cmd_host-csingle = HOSTCC $@
cmd_host-csingle = $(HOSTCC) $(hostc_flags) $(KBUILD_HOSTLDFLAGS) -o $@ $< \
- $(KBUILD_HOSTLDLIBS) $(HOSTLDLIBS_$(@F))
+ $(KBUILD_HOSTLDLIBS) $(HOSTLDLIBS_$(target-stem))
$(host-csingle): $(obj)/%: $(src)/%.c FORCE
$(call if_changed_dep,host-csingle)
@@ -93,8 +110,8 @@
# host-cmulti -> executable
quiet_cmd_host-cmulti = HOSTLD $@
cmd_host-cmulti = $(HOSTCC) $(KBUILD_HOSTLDFLAGS) -o $@ \
- $(addprefix $(obj)/,$($(@F)-objs)) \
- $(KBUILD_HOSTLDLIBS) $(HOSTLDLIBS_$(@F))
+ $(addprefix $(obj)/, $($(target-stem)-objs)) \
+ $(KBUILD_HOSTLDLIBS) $(HOSTLDLIBS_$(target-stem))
$(host-cmulti): FORCE
$(call if_changed,host-cmulti)
$(call multi_depend, $(host-cmulti), , -objs)
@@ -111,8 +128,8 @@
quiet_cmd_host-cxxmulti = HOSTLD $@
cmd_host-cxxmulti = $(HOSTCXX) $(KBUILD_HOSTLDFLAGS) -o $@ \
$(foreach o,objs cxxobjs,\
- $(addprefix $(obj)/,$($(@F)-$(o)))) \
- $(KBUILD_HOSTLDLIBS) $(HOSTLDLIBS_$(@F))
+ $(addprefix $(obj)/, $($(target-stem)-$(o)))) \
+ $(KBUILD_HOSTLDLIBS) $(HOSTLDLIBS_$(target-stem))
$(host-cxxmulti): FORCE
$(call if_changed,host-cxxmulti)
$(call multi_depend, $(host-cxxmulti), , -objs -cxxobjs)
@@ -144,8 +161,8 @@
# *.o -> .so shared library (host-cshlib)
quiet_cmd_host-cshlib = HOSTLLD -shared $@
cmd_host-cshlib = $(HOSTCC) $(KBUILD_HOSTLDFLAGS) -shared -o $@ \
- $(addprefix $(obj)/,$($(@F:.so=-objs))) \
- $(KBUILD_HOSTLDLIBS) $(HOSTLDLIBS_$(@F))
+ $(addprefix $(obj)/, $($(target-stem)-objs)) \
+ $(KBUILD_HOSTLDLIBS) $(HOSTLDLIBS_$(target-stem).so)
$(host-cshlib): FORCE
$(call if_changed,host-cshlib)
$(call multi_depend, $(host-cshlib), .so, -objs)
@@ -154,8 +171,8 @@
# *.o -> .so shared library (host-cxxshlib)
quiet_cmd_host-cxxshlib = HOSTLLD -shared $@
cmd_host-cxxshlib = $(HOSTCXX) $(KBUILD_HOSTLDFLAGS) -shared -o $@ \
- $(addprefix $(obj)/,$($(@F:.so=-objs))) \
- $(KBUILD_HOSTLDLIBS) $(HOSTLDLIBS_$(@F))
+ $(addprefix $(obj)/, $($(target-stem)-objs)) \
+ $(KBUILD_HOSTLDLIBS) $(HOSTLDLIBS_$(target-stem).so)
$(host-cxxshlib): FORCE
$(call if_changed,host-cxxshlib)
$(call multi_depend, $(host-cxxshlib), .so, -objs)
diff --git a/scripts/Makefile.kasan b/scripts/Makefile.kasan
index 69552a3..03757cc 100644
--- a/scripts/Makefile.kasan
+++ b/scripts/Makefile.kasan
@@ -1,47 +1,50 @@
# SPDX-License-Identifier: GPL-2.0
ifdef CONFIG_KASAN
+CFLAGS_KASAN_NOSANITIZE := -fno-builtin
+KASAN_SHADOW_OFFSET ?= $(CONFIG_KASAN_SHADOW_OFFSET)
+endif
+
+ifdef CONFIG_KASAN_GENERIC
+
ifdef CONFIG_KASAN_INLINE
call_threshold := 10000
else
call_threshold := 0
endif
-KASAN_SHADOW_OFFSET ?= $(CONFIG_KASAN_SHADOW_OFFSET)
-
CFLAGS_KASAN_MINIMAL := -fsanitize=kernel-address
cc-param = $(call cc-option, -mllvm -$(1), $(call cc-option, --param $(1)))
-ifeq ($(call cc-option, $(CFLAGS_KASAN_MINIMAL) -Werror),)
- ifneq ($(CONFIG_COMPILE_TEST),y)
- $(warning Cannot use CONFIG_KASAN: \
- -fsanitize=kernel-address is not supported by compiler)
- endif
-else
- # -fasan-shadow-offset fails without -fsanitize
- CFLAGS_KASAN_SHADOW := $(call cc-option, -fsanitize=kernel-address \
+# -fasan-shadow-offset fails without -fsanitize
+CFLAGS_KASAN_SHADOW := $(call cc-option, -fsanitize=kernel-address \
-fasan-shadow-offset=$(KASAN_SHADOW_OFFSET), \
$(call cc-option, -fsanitize=kernel-address \
-mllvm -asan-mapping-offset=$(KASAN_SHADOW_OFFSET)))
- ifeq ($(strip $(CFLAGS_KASAN_SHADOW)),)
- CFLAGS_KASAN := $(CFLAGS_KASAN_MINIMAL)
- else
- # Now add all the compiler specific options that are valid standalone
- CFLAGS_KASAN := $(CFLAGS_KASAN_SHADOW) \
- $(call cc-param,asan-globals=1) \
- $(call cc-param,asan-instrumentation-with-call-threshold=$(call_threshold)) \
- $(call cc-param,asan-stack=1) \
- $(call cc-param,asan-use-after-scope=1) \
- $(call cc-param,asan-instrument-allocas=1)
- endif
-
+ifeq ($(strip $(CFLAGS_KASAN_SHADOW)),)
+ CFLAGS_KASAN := $(CFLAGS_KASAN_MINIMAL)
+else
+ # Now add all the compiler specific options that are valid standalone
+ CFLAGS_KASAN := $(CFLAGS_KASAN_SHADOW) \
+ $(call cc-param,asan-globals=1) \
+ $(call cc-param,asan-instrumentation-with-call-threshold=$(call_threshold)) \
+ $(call cc-param,asan-stack=$(CONFIG_KASAN_STACK)) \
+ $(call cc-param,asan-instrument-allocas=1)
endif
-ifdef CONFIG_KASAN_EXTRA
-CFLAGS_KASAN += $(call cc-option, -fsanitize-address-use-after-scope)
+endif # CONFIG_KASAN_GENERIC
+
+ifdef CONFIG_KASAN_SW_TAGS
+
+ifdef CONFIG_KASAN_INLINE
+ instrumentation_flags := -mllvm -hwasan-mapping-offset=$(KASAN_SHADOW_OFFSET)
+else
+ instrumentation_flags := -mllvm -hwasan-instrument-with-calls=1
endif
-CFLAGS_KASAN_NOSANITIZE := -fno-builtin
+CFLAGS_KASAN := -fsanitize=kernel-hwaddress \
+ -mllvm -hwasan-instrument-stack=0 \
+ $(instrumentation_flags)
-endif
+endif # CONFIG_KASAN_SW_TAGS
diff --git a/scripts/Makefile.kcov b/scripts/Makefile.kcov
index 3d61c4b..52b1133 100644
--- a/scripts/Makefile.kcov
+++ b/scripts/Makefile.kcov
@@ -1,3 +1,4 @@
+# SPDX-License-Identifier: GPL-2.0-only
ifdef CONFIG_KCOV
kcov-flags-$(CONFIG_CC_HAS_SANCOV_TRACE_PC) += -fsanitize-coverage=trace-pc
diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib
index 61e5966..179d55a 100644
--- a/scripts/Makefile.lib
+++ b/scripts/Makefile.lib
@@ -41,11 +41,10 @@
# Subdirectories we need to descend into
subdir-ym := $(sort $(subdir-y) $(subdir-m))
-# if $(foo-objs), $(foo-y), or $(foo-m) exists, foo.o is a composite object
-multi-used-y := $(sort $(foreach m,$(obj-y), $(if $(strip $($(m:.o=-objs)) $($(m:.o=-y))), $(m))))
-multi-used-m := $(sort $(foreach m,$(obj-m), $(if $(strip $($(m:.o=-objs)) $($(m:.o=-y)) $($(m:.o=-m))), $(m))))
+# If $(foo-objs), $(foo-y), $(foo-m), or $(foo-) exists, foo.o is a composite object
+multi-used-y := $(sort $(foreach m,$(obj-y), $(if $(strip $($(m:.o=-objs)) $($(m:.o=-y)) $($(m:.o=-))), $(m))))
+multi-used-m := $(sort $(foreach m,$(obj-m), $(if $(strip $($(m:.o=-objs)) $($(m:.o=-y)) $($(m:.o=-m)) $($(m:.o=-))), $(m))))
multi-used := $(multi-used-y) $(multi-used-m)
-single-used-m := $(sort $(filter-out $(multi-used-m),$(obj-m)))
# $(subdir-obj-y) is the list of objects in $(obj-y) which uses dir/ to
# tell kbuild to descend
@@ -53,14 +52,33 @@
# Replace multi-part objects by their individual parts,
# including built-in.a from subdirectories
-real-obj-y := $(foreach m, $(obj-y), $(if $(strip $($(m:.o=-objs)) $($(m:.o=-y))),$($(m:.o=-objs)) $($(m:.o=-y)),$(m)))
-real-obj-m := $(foreach m, $(obj-m), $(if $(strip $($(m:.o=-objs)) $($(m:.o=-y)) $($(m:.o=-m))),$($(m:.o=-objs)) $($(m:.o=-y)) $($(m:.o=-m)),$(m)))
+real-obj-y := $(foreach m, $(obj-y), $(if $(strip $($(m:.o=-objs)) $($(m:.o=-y)) $($(m:.o=-))),$($(m:.o=-objs)) $($(m:.o=-y)),$(m)))
+real-obj-m := $(foreach m, $(obj-m), $(if $(strip $($(m:.o=-objs)) $($(m:.o=-y)) $($(m:.o=-m)) $($(m:.o=-))),$($(m:.o=-objs)) $($(m:.o=-y)) $($(m:.o=-m)),$(m)))
# DTB
# If CONFIG_OF_ALL_DTBS is enabled, all DT blobs are built
extra-y += $(dtb-y)
extra-$(CONFIG_OF_ALL_DTBS) += $(dtb-)
+ifneq ($(CHECK_DTBS),)
+extra-y += $(patsubst %.dtb,%.dt.yaml, $(dtb-y))
+extra-$(CONFIG_OF_ALL_DTBS) += $(patsubst %.dtb,%.dt.yaml, $(dtb-))
+endif
+
+# Test self-contained headers
+
+# Wildcard searches in $(srctree)/$(src)/, but not in $(objtree)/$(obj)/.
+# Stale generated headers are often left over, so pattern matching should
+# be avoided. Please notice $(srctree)/$(src)/ and $(objtree)/$(obj) point
+# to the same location for in-tree building. So, header-test-pattern-y should
+# be used with care.
+header-test-y += $(filter-out $(header-test-), \
+ $(patsubst $(srctree)/$(src)/%, %, \
+ $(wildcard $(addprefix $(srctree)/$(src)/, \
+ $(header-test-pattern-y)))))
+
+extra-$(CONFIG_HEADER_TEST) += $(addsuffix .s, $(header-test-y) $(header-test-m))
+
# Add subdir path
extra-y := $(addprefix $(obj)/,$(extra-y))
@@ -72,7 +90,6 @@
subdir-obj-y := $(addprefix $(obj)/,$(subdir-obj-y))
real-obj-y := $(addprefix $(obj)/,$(real-obj-y))
real-obj-m := $(addprefix $(obj)/,$(real-obj-m))
-single-used-m := $(addprefix $(obj)/,$(single-used-m))
multi-used-m := $(addprefix $(obj)/,$(multi-used-m))
subdir-ym := $(addprefix $(obj)/,$(subdir-ym))
@@ -84,6 +101,9 @@
modname = $(if $(modname-multi),$(modname-multi),$(basetarget))
+# target with $(obj)/ and its suffix stripped
+target-stem = $(basename $(patsubst $(obj)/%,%,$@))
+
# These flags are needed for modversions and compiling, so we define them here
# $(modname_flags) defines KBUILD_MODNAME as the name of the module it will
# end up in (or would, if it gets compiled in)
@@ -92,12 +112,12 @@
modname_flags = -DKBUILD_MODNAME=$(call name-fix,$(modname))
orig_c_flags = $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS) \
- $(ccflags-y) $(CFLAGS_$(basetarget).o)
-_c_flags = $(filter-out $(CFLAGS_REMOVE_$(basetarget).o), $(orig_c_flags))
+ $(ccflags-y) $(CFLAGS_$(target-stem).o)
+_c_flags = $(filter-out $(CFLAGS_REMOVE_$(target-stem).o), $(orig_c_flags))
orig_a_flags = $(KBUILD_CPPFLAGS) $(KBUILD_AFLAGS) \
- $(asflags-y) $(AFLAGS_$(basetarget).o)
-_a_flags = $(filter-out $(AFLAGS_REMOVE_$(basetarget).o), $(orig_a_flags))
-_cpp_flags = $(KBUILD_CPPFLAGS) $(cppflags-y) $(CPPFLAGS_$(@F))
+ $(asflags-y) $(AFLAGS_$(target-stem).o)
+_a_flags = $(filter-out $(AFLAGS_REMOVE_$(target-stem).o), $(orig_a_flags))
+_cpp_flags = $(KBUILD_CPPFLAGS) $(cppflags-y) $(CPPFLAGS_$(target-stem).lds)
#
# Enable gcov profiling flags for a file, directory or for all files depending
@@ -132,35 +152,38 @@
$(CFLAGS_KCOV))
endif
-# If building the kernel in a separate objtree expand all occurrences
-# of -Idir to -I$(srctree)/dir except for absolute paths (starting with '/').
-
-ifeq ($(KBUILD_SRC),)
-__c_flags = $(_c_flags)
-__a_flags = $(_a_flags)
-__cpp_flags = $(_cpp_flags)
-else
-
-# -I$(obj) locates generated .h files
-# $(call addtree,-I$(obj)) locates .h files in srctree, from generated .c files
-# and locates generated .h files
-# FIXME: Replace both with specific CFLAGS* statements in the makefiles
-__c_flags = $(if $(obj),$(call addtree,-I$(src)) -I$(obj)) \
- $(call flags,_c_flags)
-__a_flags = $(call flags,_a_flags)
-__cpp_flags = $(call flags,_cpp_flags)
+# $(srctree)/$(src) for including checkin headers from generated source files
+# $(objtree)/$(obj) for including generated headers from checkin source files
+ifeq ($(KBUILD_EXTMOD),)
+ifdef building_out_of_srctree
+_c_flags += -I $(srctree)/$(src) -I $(objtree)/$(obj)
+_a_flags += -I $(srctree)/$(src) -I $(objtree)/$(obj)
+_cpp_flags += -I $(srctree)/$(src) -I $(objtree)/$(obj)
endif
+endif
+
+part-of-module = $(if $(filter $(basename $@).o, $(real-obj-m)),y)
+quiet_modtag = $(if $(part-of-module),[M], )
+
+modkern_cflags = \
+ $(if $(part-of-module), \
+ $(KBUILD_CFLAGS_MODULE) $(CFLAGS_MODULE), \
+ $(KBUILD_CFLAGS_KERNEL) $(CFLAGS_KERNEL))
+
+modkern_aflags = $(if $(part-of-module), \
+ $(KBUILD_AFLAGS_MODULE) $(AFLAGS_MODULE), \
+ $(KBUILD_AFLAGS_KERNEL) $(AFLAGS_KERNEL))
c_flags = -Wp,-MD,$(depfile) $(NOSTDINC_FLAGS) $(LINUXINCLUDE) \
-include $(srctree)/include/linux/compiler_types.h \
- $(__c_flags) $(modkern_cflags) \
+ $(_c_flags) $(modkern_cflags) \
$(basename_flags) $(modname_flags)
a_flags = -Wp,-MD,$(depfile) $(NOSTDINC_FLAGS) $(LINUXINCLUDE) \
- $(__a_flags) $(modkern_aflags)
+ $(_a_flags) $(modkern_aflags)
cpp_flags = -Wp,-MD,$(depfile) $(NOSTDINC_FLAGS) $(LINUXINCLUDE) \
- $(__cpp_flags)
+ $(_cpp_flags)
ld_flags = $(KBUILD_LDFLAGS) $(ldflags-y) $(LDFLAGS_$(@F))
@@ -179,28 +202,6 @@
$(addprefix $(obj)/, $(foreach s, $3, $($(m:%$(strip $2)=%$(s)))))))
endef
-# LEX
-# ---------------------------------------------------------------------------
-quiet_cmd_flex = LEX $@
- cmd_flex = $(LEX) -o$@ -L $<
-
-$(obj)/%.lex.c: $(src)/%.l FORCE
- $(call if_changed,flex)
-
-# YACC
-# ---------------------------------------------------------------------------
-quiet_cmd_bison = YACC $@
- cmd_bison = $(YACC) -o$@ -t -l $<
-
-$(obj)/%.tab.c: $(src)/%.y FORCE
- $(call if_changed,bison)
-
-quiet_cmd_bison_h = YACC $@
- cmd_bison_h = $(YACC) -o/dev/null --defines=$@ -t -l $<
-
-$(obj)/%.tab.h: $(src)/%.y FORCE
- $(call if_changed,bison_h)
-
# Shipped files
# ===========================================================================
@@ -225,7 +226,13 @@
# ---------------------------------------------------------------------------
quiet_cmd_ld = LD $@
-cmd_ld = $(LD) $(ld_flags) $(filter-out FORCE,$^) -o $@
+ cmd_ld = $(LD) $(ld_flags) $(real-prereqs) -o $@
+
+# Archive
+# ---------------------------------------------------------------------------
+
+quiet_cmd_ar = AR $@
+ cmd_ar = rm -f $@; $(AR) cDPrsT $@ $(real-prereqs)
# Objcopy
# ---------------------------------------------------------------------------
@@ -237,26 +244,25 @@
# ---------------------------------------------------------------------------
quiet_cmd_gzip = GZIP $@
-cmd_gzip = (cat $(filter-out FORCE,$^) | gzip -n -f -9 > $@) || \
- (rm -f $@ ; false)
+ cmd_gzip = cat $(real-prereqs) | gzip -n -f -9 > $@
# DTC
# ---------------------------------------------------------------------------
DTC ?= $(objtree)/scripts/dtc/dtc
# Disable noisy checks by default
-ifeq ($(findstring 1,$(KBUILD_ENABLE_EXTRA_GCC_CHECKS)),)
+ifeq ($(findstring 1,$(KBUILD_EXTRA_WARN)),)
DTC_FLAGS += -Wno-unit_address_vs_reg \
-Wno-unit_address_format \
-Wno-avoid_unnecessary_addr_size \
-Wno-alias_paths \
-Wno-graph_child_address \
- -Wno-graph_port \
+ -Wno-simple_bus_reg \
-Wno-unique_unit_address \
-Wno-pci_device_reg
endif
-ifneq ($(findstring 2,$(KBUILD_ENABLE_EXTRA_GCC_CHECKS)),)
+ifneq ($(findstring 2,$(KBUILD_EXTRA_WARN)),)
DTC_FLAGS += -Wnode_name_chars_strict \
-Wproperty_name_chars_strict
endif
@@ -266,7 +272,7 @@
# Generate an assembly file to wrap the output of the device tree compiler
quiet_cmd_dt_S_dtb= DTB $@
cmd_dt_S_dtb= \
-( \
+{ \
echo '\#include <asm-generic/vmlinux.lds.h>'; \
echo '.section .dtb.init.rodata,"a"'; \
echo '.balign STRUCT_ALIGNMENT'; \
@@ -276,21 +282,36 @@
echo '__dtb_$(subst -,_,$(*F))_end:'; \
echo '.global __dtb_$(subst -,_,$(*F))_end'; \
echo '.balign STRUCT_ALIGNMENT'; \
-) > $@
+} > $@
$(obj)/%.dtb.S: $(obj)/%.dtb FORCE
$(call if_changed,dt_S_dtb)
quiet_cmd_dtc = DTC $@
cmd_dtc = mkdir -p $(dir ${dtc-tmp}) ; \
- $(CPP) $(dtc_cpp_flags) -x assembler-with-cpp -o $(dtc-tmp) $< ; \
- $(DTC) -O dtb -o $@ -b 0 \
+ $(HOSTCC) -E $(dtc_cpp_flags) -x assembler-with-cpp -o $(dtc-tmp) $< ; \
+ $(DTC) -O $(2) -o $@ -b 0 \
$(addprefix -i,$(dir $<) $(DTC_INCLUDE)) $(DTC_FLAGS) \
-d $(depfile).dtc.tmp $(dtc-tmp) ; \
cat $(depfile).pre.tmp $(depfile).dtc.tmp > $(depfile)
$(obj)/%.dtb: $(src)/%.dts $(DTC) FORCE
- $(call if_changed_dep,dtc)
+ $(call if_changed_dep,dtc,dtb)
+
+DT_CHECKER ?= dt-validate
+DT_BINDING_DIR := Documentation/devicetree/bindings
+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) $@ ;
+
+define rule_dtc_dt_yaml
+ $(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)
dtc-tmp = $(subst $(comma),_,$(dot-target).dts.tmp)
@@ -301,7 +322,7 @@
# append the size as a 32-bit littleendian number as gzip does.
size_append = printf $(shell \
dec_size=0; \
-for F in $1; do \
+for F in $(real-prereqs); do \
fsize=$$($(CONFIG_SHELL) $(srctree)/scripts/file-size.sh $$F); \
dec_size=$$(expr $$dec_size + $$fsize); \
done; \
@@ -315,27 +336,20 @@
)
quiet_cmd_bzip2 = BZIP2 $@
-cmd_bzip2 = (cat $(filter-out FORCE,$^) | \
- bzip2 -9 && $(call size_append, $(filter-out FORCE,$^))) > $@ || \
- (rm -f $@ ; false)
+ cmd_bzip2 = { cat $(real-prereqs) | bzip2 -9; $(size_append); } > $@
# Lzma
# ---------------------------------------------------------------------------
quiet_cmd_lzma = LZMA $@
-cmd_lzma = (cat $(filter-out FORCE,$^) | \
- lzma -9 && $(call size_append, $(filter-out FORCE,$^))) > $@ || \
- (rm -f $@ ; false)
+ cmd_lzma = { cat $(real-prereqs) | lzma -9; $(size_append); } > $@
quiet_cmd_lzo = LZO $@
-cmd_lzo = (cat $(filter-out FORCE,$^) | \
- lzop -9 && $(call size_append, $(filter-out FORCE,$^))) > $@ || \
- (rm -f $@ ; false)
+ cmd_lzo = { cat $(real-prereqs) | lzop -9; $(size_append); } > $@
quiet_cmd_lz4 = LZ4 $@
-cmd_lz4 = (cat $(filter-out FORCE,$^) | \
- lz4c -l -c1 stdin stdout && $(call size_append, $(filter-out FORCE,$^))) > $@ || \
- (rm -f $@ ; false)
+ cmd_lz4 = { cat $(real-prereqs) | lz4c -l -c1 stdin stdout; \
+ $(size_append); } > $@
# U-Boot mkimage
# ---------------------------------------------------------------------------
@@ -351,15 +365,13 @@
UIMAGE_LOADADDR ?= arch_must_set_this
UIMAGE_ENTRYADDR ?= $(UIMAGE_LOADADDR)
UIMAGE_NAME ?= 'Linux-$(KERNELRELEASE)'
-UIMAGE_IN ?= $<
-UIMAGE_OUT ?= $@
-quiet_cmd_uimage = UIMAGE $(UIMAGE_OUT)
- cmd_uimage = $(CONFIG_SHELL) $(MKIMAGE) -A $(UIMAGE_ARCH) -O linux \
+quiet_cmd_uimage = UIMAGE $@
+ cmd_uimage = $(BASH) $(MKIMAGE) -A $(UIMAGE_ARCH) -O linux \
-C $(UIMAGE_COMPRESSION) $(UIMAGE_OPTS-y) \
-T $(UIMAGE_TYPE) \
-a $(UIMAGE_LOADADDR) -e $(UIMAGE_ENTRYADDR) \
- -n $(UIMAGE_NAME) -d $(UIMAGE_IN) $(UIMAGE_OUT)
+ -n $(UIMAGE_NAME) -d $< $@
# XZ
# ---------------------------------------------------------------------------
@@ -379,15 +391,11 @@
# big dictionary would increase the memory usage too much in the multi-call
# decompression mode. A BCJ filter isn't used either.
quiet_cmd_xzkern = XZKERN $@
-cmd_xzkern = (cat $(filter-out FORCE,$^) | \
- sh $(srctree)/scripts/xz_wrap.sh && \
- $(call size_append, $(filter-out FORCE,$^))) > $@ || \
- (rm -f $@ ; false)
+ cmd_xzkern = { cat $(real-prereqs) | sh $(srctree)/scripts/xz_wrap.sh; \
+ $(size_append); } > $@
quiet_cmd_xzmisc = XZMISC $@
-cmd_xzmisc = (cat $(filter-out FORCE,$^) | \
- xz --check=crc32 --lzma2=dict=1MiB) > $@ || \
- (rm -f $@ ; false)
+ cmd_xzmisc = cat $(real-prereqs) | xz --check=crc32 --lzma2=dict=1MiB > $@
# ASM offsets
# ---------------------------------------------------------------------------
@@ -406,7 +414,6 @@
# Use filechk to avoid rebuilds when a header changes, but the resulting file
# does not
define filechk_offsets
- (set -e; \
echo "#ifndef $2"; \
echo "#define $2"; \
echo "/*"; \
@@ -417,5 +424,5 @@
echo ""; \
sed -ne $(sed-offsets) < $<; \
echo ""; \
- echo "#endif" )
+ echo "#endif"
endef
diff --git a/scripts/Makefile.modbuiltin b/scripts/Makefile.modbuiltin
index a072a42..7d4711b 100644
--- a/scripts/Makefile.modbuiltin
+++ b/scripts/Makefile.modbuiltin
@@ -15,7 +15,7 @@
include scripts/Kbuild.include
-ifneq ($(KBUILD_SRC),)
+ifdef building_out_of_srctree
# Create output directory if not already present
_dummy := $(shell [ -d $(obj) ] || mkdir -p $(obj))
endif
@@ -40,7 +40,7 @@
@:
$(modbuiltin-target): $(subdir-ym) FORCE
- $(Q)(for m in $(modbuiltin-mods); do echo kernel/$$m; done; \
+ $(Q)(for m in $(modbuiltin-mods); do echo $$m; done; \
cat /dev/null $(modbuiltin-subdirs)) > $@
PHONY += FORCE
diff --git a/scripts/Makefile.modfinal b/scripts/Makefile.modfinal
new file mode 100644
index 0000000..411c1e6
--- /dev/null
+++ b/scripts/Makefile.modfinal
@@ -0,0 +1,60 @@
+# SPDX-License-Identifier: GPL-2.0-only
+# ===========================================================================
+# Module final link
+# ===========================================================================
+
+PHONY := __modfinal
+__modfinal:
+
+include $(srctree)/scripts/Kbuild.include
+
+# for c_flags
+include $(srctree)/scripts/Makefile.lib
+
+# find all modules listed in modules.order
+modules := $(sort $(shell cat $(MODORDER)))
+
+__modfinal: $(modules)
+ @:
+
+# modname and part-of-module are set to make c_flags define proper module flags
+modname = $(notdir $(@:.mod.o=))
+part-of-module = y
+
+quiet_cmd_cc_o_c = CC [M] $@
+ cmd_cc_o_c = $(CC) $(c_flags) -c -o $@ $<
+
+%.mod.o: %.mod.c FORCE
+ $(call if_changed_dep,cc_o_c)
+
+ARCH_POSTLINK := $(wildcard $(srctree)/arch/$(SRCARCH)/Makefile.postlink)
+
+quiet_cmd_ld_ko_o = LD [M] $@
+ cmd_ld_ko_o = \
+ $(LD) -r $(KBUILD_LDFLAGS) \
+ $(KBUILD_LDFLAGS_MODULE) $(LDFLAGS_MODULE) \
+ $(addprefix -T , $(KBUILD_LDS_MODULE)) \
+ -o $@ $(filter %.o, $^); \
+ $(if $(ARCH_POSTLINK), $(MAKE) -f $(ARCH_POSTLINK) $@, true)
+
+$(modules): %.ko: %.o %.mod.o $(KBUILD_LDS_MODULE) FORCE
+ +$(call if_changed,ld_ko_o)
+
+targets += $(modules) $(modules:.ko=.mod.o)
+
+# Add FORCE to the prequisites of a target to force it to be always rebuilt.
+# ---------------------------------------------------------------------------
+
+PHONY += FORCE
+FORCE:
+
+# Read all saved command lines and dependencies for the $(targets) we
+# may be building above, using $(if_changed{,_dep}). As an
+# optimization, we don't need to read them if the target does not
+# exist, we will rebuild anyway in that case.
+
+existing-targets := $(wildcard $(sort $(targets)))
+
+-include $(foreach f,$(existing-targets),$(dir $(f)).$(notdir $(f)).cmd)
+
+.PHONY: $(PHONY)
diff --git a/scripts/Makefile.modinst b/scripts/Makefile.modinst
index ff5ca98..5a4579e 100644
--- a/scripts/Makefile.modinst
+++ b/scripts/Makefile.modinst
@@ -8,10 +8,7 @@
include scripts/Kbuild.include
-#
-
-__modules := $(sort $(shell grep -h '\.ko$$' /dev/null $(wildcard $(MODVERDIR)/*.mod)))
-modules := $(patsubst %.o,%.ko,$(wildcard $(__modules:.ko=.o)))
+modules := $(sort $(shell cat $(if $(KBUILD_EXTMOD),$(KBUILD_EXTMOD)/)modules.order))
PHONY += $(modules)
__modinst: $(modules)
@@ -23,7 +20,7 @@
mkdir -p $(2) ; \
cp $@ $(2) ; \
$(mod_strip_cmd) $(2)/$(notdir $@) ; \
- $(mod_sign_cmd) $(2)/$(notdir $@) $(patsubst %,|| true,$(KBUILD_EXTMOD)) && \
+ $(mod_sign_cmd) $(2)/$(notdir $@) $(patsubst %,|| true,$(KBUILD_EXTMOD)) ; \
$(mod_compress_cmd) $(2)/$(notdir $@)
# Modules built outside the kernel source tree go into extra by default
diff --git a/scripts/Makefile.modpost b/scripts/Makefile.modpost
index 7d4af0d..952fff4 100644
--- a/scripts/Makefile.modpost
+++ b/scripts/Makefile.modpost
@@ -6,23 +6,22 @@
# Stage one of module building created the following:
# a) The individual .o files used for the module
# b) A <module>.o file which is the .o files above linked together
-# c) A <module>.mod file in $(MODVERDIR)/, listing the name of the
-# the preliminary <module>.o file, plus all .o files
+# c) A <module>.mod file, listing the name of the preliminary <module>.o file,
+# plus all .o files
+# d) modules.order, which lists all the modules
# Stage 2 is handled by this file and does the following
-# 1) Find all modules from the files listed in $(MODVERDIR)/
+# 1) Find all modules listed in modules.order
# 2) modpost is then used to
# 3) create one <module>.mod.c file pr. module
# 4) create one Module.symvers file with CRC for all exported symbols
-# 5) compile all <module>.mod.c files
-# 6) final link of the module to a <module.ko> file
# Step 3 is used to place certain information in the module's ELF
# section, including information such as:
# Version magic (see include/linux/vermagic.h for full details)
# - Kernel release
# - SMP is CONFIG_SMP
-# - PREEMPT is CONFIG_PREEMPT
+# - PREEMPT is CONFIG_PREEMPT[_RT]
# - GCC Version
# Module info
# - Module version (MODULE_VERSION)
@@ -37,12 +36,37 @@
# symbols in the final module linking stage
# KBUILD_MODPOST_NOFINAL can be set to skip the final link of modules.
# This is solely useful to speed up test compiles
-PHONY := _modpost
-_modpost: __modpost
+
+PHONY := __modpost
+__modpost:
include include/config/auto.conf
include scripts/Kbuild.include
+kernelsymfile := $(objtree)/Module.symvers
+modulesymfile := $(firstword $(KBUILD_EXTMOD))/Module.symvers
+
+MODPOST = scripts/mod/modpost \
+ $(if $(CONFIG_MODVERSIONS),-m) \
+ $(if $(CONFIG_MODULE_SRCVERSION_ALL),-a) \
+ $(if $(KBUILD_EXTMOD),-i,-o) $(kernelsymfile) \
+ $(if $(KBUILD_EXTMOD),-I $(modulesymfile)) \
+ $(if $(KBUILD_EXTMOD),$(addprefix -e ,$(KBUILD_EXTRA_SYMBOLS))) \
+ $(if $(KBUILD_EXTMOD),-o $(modulesymfile)) \
+ $(if $(CONFIG_SECTION_MISMATCH_WARN_ONLY),,-E) \
+ $(if $(KBUILD_MODPOST_WARN),-w) \
+ $(if $(filter nsdeps,$(MAKECMDGOALS)),-d)
+
+ifdef MODPOST_VMLINUX
+
+quiet_cmd_modpost = MODPOST vmlinux.o
+ cmd_modpost = $(MODPOST) vmlinux.o
+
+__modpost:
+ $(call cmd,modpost)
+
+else
+
# When building external modules load the Kbuild file to retrieve EXTRA_SYMBOLS info
ifneq ($(KBUILD_EXTMOD),)
@@ -55,98 +79,25 @@
$(KBUILD_EXTMOD)/Kbuild, $(KBUILD_EXTMOD)/Makefile)
endif
-include scripts/Makefile.lib
+MODPOST += $(subst -i,-n,$(filter -i,$(MAKEFLAGS))) -s -T - $(wildcard vmlinux)
-kernelsymfile := $(objtree)/Module.symvers
-modulesymfile := $(firstword $(KBUILD_EXTMOD))/Module.symvers
+# find all modules listed in modules.order
+modules := $(sort $(shell cat $(MODORDER)))
-# Step 1), find all modules listed in $(MODVERDIR)/
-MODLISTCMD := find $(MODVERDIR) -name '*.mod' | xargs -r grep -h '\.ko$$' | sort -u
-__modules := $(shell $(MODLISTCMD))
-modules := $(patsubst %.o,%.ko, $(wildcard $(__modules:.ko=.o)))
+# Read out modules.order instead of expanding $(modules) to pass in modpost.
+# Otherwise, allmodconfig would fail with "Argument list too long".
+quiet_cmd_modpost = MODPOST $(words $(modules)) modules
+ cmd_modpost = sed 's/ko$$/o/' $(MODORDER) | $(MODPOST)
-# Stop after building .o files if NOFINAL is set. Makes compile tests quicker
-_modpost: $(if $(KBUILD_MODPOST_NOFINAL), $(modules:.ko:.o),$(modules))
+__modpost:
+ @$(kecho) ' Building modules, stage 2.'
+ $(call cmd,modpost)
+ifneq ($(KBUILD_MODPOST_NOFINAL),1)
+ $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modfinal
+endif
-# Step 2), invoke modpost
-# Includes step 3,4
-modpost = scripts/mod/modpost \
- $(if $(CONFIG_MODVERSIONS),-m) \
- $(if $(CONFIG_MODULE_SRCVERSION_ALL),-a,) \
- $(if $(KBUILD_EXTMOD),-i,-o) $(kernelsymfile) \
- $(if $(KBUILD_EXTMOD),-I $(modulesymfile)) \
- $(if $(KBUILD_EXTRA_SYMBOLS), $(patsubst %, -e %,$(KBUILD_EXTRA_SYMBOLS))) \
- $(if $(KBUILD_EXTMOD),-o $(modulesymfile)) \
- $(if $(CONFIG_DEBUG_SECTION_MISMATCH),,-S) \
- $(if $(CONFIG_SECTION_MISMATCH_WARN_ONLY),,-E) \
- $(if $(KBUILD_EXTMOD)$(KBUILD_MODPOST_WARN),-w)
+nsdeps: __modpost
-MODPOST_OPT=$(subst -i,-n,$(filter -i,$(MAKEFLAGS)))
-
-# We can go over command line length here, so be careful.
-quiet_cmd_modpost = MODPOST $(words $(filter-out vmlinux FORCE, $^)) modules
- cmd_modpost = $(MODLISTCMD) | sed 's/\.ko$$/.o/' | $(modpost) $(MODPOST_OPT) -s -T -
-
-PHONY += __modpost
-__modpost: $(modules:.ko=.o) FORCE
- $(call cmd,modpost) $(wildcard vmlinux)
-
-quiet_cmd_kernel-mod = MODPOST $@
- cmd_kernel-mod = $(modpost) $@
-
-vmlinux.o: FORCE
- $(call cmd,kernel-mod)
-
-# Declare generated files as targets for modpost
-$(modules:.ko=.mod.c): __modpost ;
-
-
-# Step 5), compile all *.mod.c files
-
-# modname is set to make c_flags define KBUILD_MODNAME
-modname = $(notdir $(@:.mod.o=))
-
-quiet_cmd_cc_o_c = CC $@
- cmd_cc_o_c = $(CC) $(c_flags) $(KBUILD_CFLAGS_MODULE) $(CFLAGS_MODULE) \
- -c -o $@ $<
-
-$(modules:.ko=.mod.o): %.mod.o: %.mod.c FORCE
- $(call if_changed_dep,cc_o_c)
-
-targets += $(modules:.ko=.mod.o)
-
-ARCH_POSTLINK := $(wildcard $(srctree)/arch/$(SRCARCH)/Makefile.postlink)
-
-# Step 6), final link of the modules with optional arch pass after final link
-quiet_cmd_ld_ko_o = LD [M] $@
- cmd_ld_ko_o = \
- $(LD) -r $(KBUILD_LDFLAGS) \
- $(KBUILD_LDFLAGS_MODULE) $(LDFLAGS_MODULE) \
- -o $@ $(filter-out FORCE,$^) ; \
- $(if $(ARCH_POSTLINK), $(MAKE) -f $(ARCH_POSTLINK) $@, true)
-
-$(modules): %.ko :%.o %.mod.o FORCE
- +$(call if_changed,ld_ko_o)
-
-targets += $(modules)
-
-
-# Add FORCE to the prequisites of a target to force it to be always rebuilt.
-# ---------------------------------------------------------------------------
-
-PHONY += FORCE
-
-FORCE:
-
-# Read all saved command lines and dependencies for the $(targets) we
-# may be building above, using $(if_changed{,_dep}). As an
-# optimization, we don't need to read them if the target does not
-# exist, we will rebuild anyway in that case.
-
-cmd_files := $(wildcard $(foreach f,$(sort $(targets)),$(dir $(f)).$(notdir $(f)).cmd))
-
-ifneq ($(cmd_files),)
- include $(cmd_files)
endif
.PHONY: $(PHONY)
diff --git a/scripts/Makefile.modsign b/scripts/Makefile.modsign
index da56aa7..d7325ce 100644
--- a/scripts/Makefile.modsign
+++ b/scripts/Makefile.modsign
@@ -8,8 +8,7 @@
include scripts/Kbuild.include
-__modules := $(sort $(shell grep -h '\.ko$$' /dev/null $(wildcard $(MODVERDIR)/*.mod)))
-modules := $(patsubst %.o,%.ko,$(wildcard $(__modules:.ko=.o)))
+modules := $(sort $(shell cat modules.order))
PHONY += $(modules)
__modsign: $(modules)
diff --git a/scripts/package/Makefile b/scripts/Makefile.package
similarity index 88%
rename from scripts/package/Makefile
rename to scripts/Makefile.package
index 73503eb..56eadcc 100644
--- a/scripts/package/Makefile
+++ b/scripts/Makefile.package
@@ -1,5 +1,7 @@
+# SPDX-License-Identifier: GPL-2.0-only
# Makefile for the different targets used to generate full packages of a kernel
-# It uses the generic clean infrastructure of kbuild
+
+include $(srctree)/scripts/Kbuild.include
# RPM target
# ---------------------------------------------------------------------------
@@ -33,7 +35,6 @@
quiet_cmd_src_tar = TAR $(2).tar.gz
cmd_src_tar = \
-set -e; \
if test "$(objtree)" != "$(srctree)"; then \
echo >&2; \
echo >&2 " ERROR:"; \
@@ -50,7 +51,8 @@
# rpm-pkg
# ---------------------------------------------------------------------------
-rpm-pkg: FORCE
+PHONY += rpm-pkg
+rpm-pkg:
$(MAKE) clean
$(CONFIG_SHELL) $(MKSPEC) >$(objtree)/kernel.spec
$(call cmd,src_tar,$(KERNELPATH),kernel.spec)
@@ -59,34 +61,35 @@
# binrpm-pkg
# ---------------------------------------------------------------------------
-binrpm-pkg: FORCE
- $(MAKE) KBUILD_SRC=
+PHONY += binrpm-pkg
+binrpm-pkg:
+ $(MAKE) -f $(srctree)/Makefile
$(CONFIG_SHELL) $(MKSPEC) prebuilt > $(objtree)/binkernel.spec
+rpmbuild $(RPMOPTS) --define "_builddir $(objtree)" --target \
$(UTS_MACHINE) -bb $(objtree)/binkernel.spec
-clean-files += $(objtree)/*.spec
-
-deb-pkg: FORCE
+PHONY += deb-pkg
+deb-pkg:
$(MAKE) clean
$(CONFIG_SHELL) $(srctree)/scripts/package/mkdebian
$(call cmd,src_tar,$(KDEB_SOURCENAME))
origversion=$$(dpkg-parsechangelog -SVersion |sed 's/-[^-]*$$//');\
mv $(KDEB_SOURCENAME).tar.gz ../$(KDEB_SOURCENAME)_$${origversion}.orig.tar.gz
- +dpkg-buildpackage -r$(KBUILD_PKG_ROOTCMD) -a$$(cat debian/arch) -i.git -us -uc
+ +dpkg-buildpackage -r$(KBUILD_PKG_ROOTCMD) -a$$(cat debian/arch) $(DPKG_FLAGS) -i.git -us -uc
-bindeb-pkg: FORCE
+PHONY += bindeb-pkg
+bindeb-pkg:
$(CONFIG_SHELL) $(srctree)/scripts/package/mkdebian
- +dpkg-buildpackage -r$(KBUILD_PKG_ROOTCMD) -a$$(cat debian/arch) -b -nc -uc
+ +dpkg-buildpackage -r$(KBUILD_PKG_ROOTCMD) -a$$(cat debian/arch) $(DPKG_FLAGS) -b -nc -uc
-intdeb-pkg: FORCE
+PHONY += intdeb-pkg
+intdeb-pkg:
+$(CONFIG_SHELL) $(srctree)/scripts/package/builddeb
-clean-dirs += $(objtree)/debian/
-
# snap-pkg
# ---------------------------------------------------------------------------
-snap-pkg: FORCE
+PHONY += snap-pkg
+snap-pkg:
rm -rf $(objtree)/snap
mkdir $(objtree)/snap
$(MAKE) clean
@@ -98,16 +101,13 @@
cd $(objtree)/snap && \
snapcraft --target-arch=$(UTS_MACHINE)
-clean-dirs += $(objtree)/snap/
-
# tarball targets
# ---------------------------------------------------------------------------
-tar%pkg: FORCE
- $(MAKE) KBUILD_SRC=
- $(CONFIG_SHELL) $(srctree)/scripts/package/buildtar $@
-
-clean-dirs += $(objtree)/tar-install/
-
+tar-pkgs := tar-pkg targz-pkg tarbz2-pkg tarxz-pkg
+PHONY += $(tar-pkgs)
+$(tar-pkgs):
+ $(MAKE) -f $(srctree)/Makefile
+ +$(CONFIG_SHELL) $(srctree)/scripts/package/buildtar $@
# perf-pkg - generate a source tarball with perf source
# ---------------------------------------------------------------------------
@@ -133,12 +133,15 @@
$(error unknown target $@)))) \
-f -9 $(perf-tar).tar)
-perf-%pkg: FORCE
+perf-tar-pkgs := perf-tar-src-pkg perf-targz-src-pkg perf-tarbz2-src-pkg perf-tarxz-src-pkg
+PHONY += $(perf-tar-pkgs)
+$(perf-tar-pkgs):
$(call cmd,perf_tar)
# Help text displayed when executing 'make help'
# ---------------------------------------------------------------------------
-help: FORCE
+PHONY += help
+help:
@echo ' rpm-pkg - Build both source and binary RPM kernel packages'
@echo ' binrpm-pkg - Build only the binary kernel RPM package'
@echo ' deb-pkg - Build both source and binary deb kernel packages'
@@ -152,3 +155,5 @@
@echo ' perf-targz-src-pkg - Build $(perf-tar).tar.gz source tarball'
@echo ' perf-tarbz2-src-pkg - Build $(perf-tar).tar.bz2 source tarball'
@echo ' perf-tarxz-src-pkg - Build $(perf-tar).tar.xz source tarball'
+
+.PHONY: $(PHONY)
diff --git a/scripts/Makefile.ubsan b/scripts/Makefile.ubsan
index 38b2b48..019771b 100644
--- a/scripts/Makefile.ubsan
+++ b/scripts/Makefile.ubsan
@@ -3,7 +3,6 @@
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=vla-bound)
CFLAGS_UBSAN += $(call cc-option, -fsanitize=signed-integer-overflow)
CFLAGS_UBSAN += $(call cc-option, -fsanitize=bounds)
CFLAGS_UBSAN += $(call cc-option, -fsanitize=object-size)
diff --git a/scripts/adjust_autoksyms.sh b/scripts/adjust_autoksyms.sh
index 6e6d639..a904bf1 100755
--- a/scripts/adjust_autoksyms.sh
+++ b/scripts/adjust_autoksyms.sh
@@ -1,17 +1,14 @@
#!/bin/sh
+# SPDX-License-Identifier: GPL-2.0-only
# Script to create/update include/generated/autoksyms.h and dependency files
#
# Copyright: (C) 2016 Linaro Limited
# Created by: Nicolas Pitre, January 2016
#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License version 2 as
-# published by the Free Software Foundation.
# Create/update the include/generated/autoksyms.h file from the list
-# of all module's needed symbols as recorded on the third line of
-# .tmp_versions/*.mod files.
+# of all module's needed symbols as recorded on the second line of *.mod files.
#
# For each symbol being added or removed, the corresponding dependency
# file's timestamp is updated to force a rebuild of the affected source
@@ -39,14 +36,7 @@
esac
# We need access to CONFIG_ symbols
-case "${KCONFIG_CONFIG}" in
-*/*)
- . "${KCONFIG_CONFIG}"
- ;;
-*)
- # Force using a file from the current directory
- . "./${KCONFIG_CONFIG}"
-esac
+. include/config/auto.conf
# Generate a new ksym list file with symbols needed by the current
# set of modules.
@@ -56,13 +46,10 @@
*/
EOT
-[ "$(ls -A "$MODVERDIR")" ] &&
-for mod in "$MODVERDIR"/*.mod; do
- sed -n -e '3{s/ /\n/g;/^$/!p;}' "$mod"
-done | sort -u |
-while read sym; do
- echo "#define __KSYM_${sym} 1"
-done >> "$new_ksyms_file"
+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
diff --git a/scripts/asn1_compiler.c b/scripts/asn1_compiler.c
index c146020..adabd41 100644
--- a/scripts/asn1_compiler.c
+++ b/scripts/asn1_compiler.c
@@ -1,12 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
/* Simplified ASN.1 notation parser
*
* Copyright (C) 2012 Red Hat, Inc. All Rights Reserved.
* Written by David Howells (dhowells@redhat.com)
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public Licence
- * as published by the Free Software Foundation; either version
- * 2 of the Licence, or (at your option) any later version.
*/
#include <stdarg.h>
@@ -413,7 +409,7 @@
/* Handle string tokens */
if (isalpha(*p)) {
- const char **dir, *start = p;
+ const char **dir;
/* Can be a directive, type name or element
* name. Find the end of the name.
diff --git a/scripts/atomic/atomic-tbl.sh b/scripts/atomic/atomic-tbl.sh
new file mode 100755
index 0000000..81d5c32
--- /dev/null
+++ b/scripts/atomic/atomic-tbl.sh
@@ -0,0 +1,186 @@
+#!/bin/sh
+# SPDX-License-Identifier: GPL-2.0
+# helpers for dealing with atomics.tbl
+
+#meta_in(meta, match)
+meta_in()
+{
+ case "$1" in
+ [$2]) return 0;;
+ esac
+
+ return 1
+}
+
+#meta_has_ret(meta)
+meta_has_ret()
+{
+ meta_in "$1" "bBiIfFlR"
+}
+
+#meta_has_acquire(meta)
+meta_has_acquire()
+{
+ meta_in "$1" "BFIlR"
+}
+
+#meta_has_release(meta)
+meta_has_release()
+{
+ meta_in "$1" "BFIRs"
+}
+
+#meta_has_relaxed(meta)
+meta_has_relaxed()
+{
+ meta_in "$1" "BFIR"
+}
+
+#find_fallback_template(pfx, name, sfx, order)
+find_fallback_template()
+{
+ local pfx="$1"; shift
+ local name="$1"; shift
+ local sfx="$1"; shift
+ local order="$1"; shift
+
+ local base=""
+ local file=""
+
+ # We may have fallbacks for a specific case (e.g. read_acquire()), or
+ # an entire class, e.g. *inc*().
+ #
+ # Start at the most specific, and fall back to the most general. Once
+ # we find a specific fallback, don't bother looking for more.
+ for base in "${pfx}${name}${sfx}${order}" "${name}"; do
+ file="${ATOMICDIR}/fallbacks/${base}"
+
+ if [ -f "${file}" ]; then
+ printf "${file}"
+ break
+ fi
+ done
+}
+
+#gen_ret_type(meta, int)
+gen_ret_type() {
+ local meta="$1"; shift
+ local int="$1"; shift
+
+ case "${meta}" in
+ [sv]) printf "void";;
+ [bB]) printf "bool";;
+ [aiIfFlR]) printf "${int}";;
+ esac
+}
+
+#gen_ret_stmt(meta)
+gen_ret_stmt()
+{
+ if meta_has_ret "${meta}"; then
+ printf "return ";
+ fi
+}
+
+# gen_param_name(arg)
+gen_param_name()
+{
+ # strip off the leading 'c' for 'cv'
+ local name="${1#c}"
+ printf "${name#*:}"
+}
+
+# gen_param_type(arg, int, atomic)
+gen_param_type()
+{
+ local type="${1%%:*}"; shift
+ local int="$1"; shift
+ local atomic="$1"; shift
+
+ case "${type}" in
+ i) type="${int} ";;
+ p) type="${int} *";;
+ v) type="${atomic}_t *";;
+ cv) type="const ${atomic}_t *";;
+ esac
+
+ printf "${type}"
+}
+
+#gen_param(arg, int, atomic)
+gen_param()
+{
+ local arg="$1"; shift
+ local int="$1"; shift
+ local atomic="$1"; shift
+ local name="$(gen_param_name "${arg}")"
+ local type="$(gen_param_type "${arg}" "${int}" "${atomic}")"
+
+ printf "${type}${name}"
+}
+
+#gen_params(int, atomic, arg...)
+gen_params()
+{
+ local int="$1"; shift
+ local atomic="$1"; shift
+
+ while [ "$#" -gt 0 ]; do
+ gen_param "$1" "${int}" "${atomic}"
+ [ "$#" -gt 1 ] && printf ", "
+ shift;
+ done
+}
+
+#gen_args(arg...)
+gen_args()
+{
+ while [ "$#" -gt 0 ]; do
+ printf "$(gen_param_name "$1")"
+ [ "$#" -gt 1 ] && printf ", "
+ shift;
+ done
+}
+
+#gen_proto_order_variants(meta, pfx, name, sfx, ...)
+gen_proto_order_variants()
+{
+ local meta="$1"; shift
+ local pfx="$1"; shift
+ local name="$1"; shift
+ local sfx="$1"; shift
+
+ gen_proto_order_variant "${meta}" "${pfx}" "${name}" "${sfx}" "" "$@"
+
+ if meta_has_acquire "${meta}"; then
+ gen_proto_order_variant "${meta}" "${pfx}" "${name}" "${sfx}" "_acquire" "$@"
+ fi
+ if meta_has_release "${meta}"; then
+ gen_proto_order_variant "${meta}" "${pfx}" "${name}" "${sfx}" "_release" "$@"
+ fi
+ if meta_has_relaxed "${meta}"; then
+ gen_proto_order_variant "${meta}" "${pfx}" "${name}" "${sfx}" "_relaxed" "$@"
+ fi
+}
+
+#gen_proto_variants(meta, name, ...)
+gen_proto_variants()
+{
+ local meta="$1"; shift
+ local name="$1"; shift
+ local pfx=""
+ local sfx=""
+
+ meta_in "${meta}" "fF" && pfx="fetch_"
+ meta_in "${meta}" "R" && sfx="_return"
+
+ gen_proto_order_variants "${meta}" "${pfx}" "${name}" "${sfx}" "$@"
+}
+
+#gen_proto(meta, ...)
+gen_proto() {
+ local meta="$1"; shift
+ for m in $(echo "${meta}" | grep -o .); do
+ gen_proto_variants "${m}" "$@"
+ done
+}
diff --git a/scripts/atomic/atomics.tbl b/scripts/atomic/atomics.tbl
new file mode 100755
index 0000000..fbee2f6
--- /dev/null
+++ b/scripts/atomic/atomics.tbl
@@ -0,0 +1,41 @@
+# name meta args...
+#
+# Where meta contains a string of variants to generate.
+# Upper-case implies _{acquire,release,relaxed} variants.
+# Valid meta values are:
+# * B/b - bool: returns bool
+# * v - void: returns void
+# * I/i - int: returns base type
+# * R - return: returns base type (has _return variants)
+# * F/f - fetch: returns base type (has fetch_ variants)
+# * l - load: returns base type (has _acquire order variant)
+# * s - store: returns void (has _release order variant)
+#
+# Where args contains list of type[:name], where type is:
+# * cv - const pointer to atomic base type (atomic_t/atomic64_t/atomic_long_t)
+# * v - pointer to atomic base type (atomic_t/atomic64_t/atomic_long_t)
+# * i - base type (int/s64/long)
+# * p - pointer to base type (int/s64/long)
+#
+read l cv
+set s v i
+add vRF i v
+sub vRF i v
+inc vRF v
+dec vRF v
+and vF i v
+andnot vF i v
+or vF i v
+xor vF i v
+xchg I v i
+cmpxchg I v i:old i:new
+try_cmpxchg B v p:old i:new
+sub_and_test b i v
+dec_and_test b v
+inc_and_test b v
+add_negative b i v
+add_unless fb v i:a i:u
+inc_not_zero b v
+inc_unless_negative b v
+dec_unless_positive b v
+dec_if_positive i v
diff --git a/scripts/atomic/check-atomics.sh b/scripts/atomic/check-atomics.sh
new file mode 100755
index 0000000..8378c63
--- /dev/null
+++ b/scripts/atomic/check-atomics.sh
@@ -0,0 +1,33 @@
+#!/bin/sh
+# SPDX-License-Identifier: GPL-2.0
+#
+# Check if atomic headers are up-to-date
+
+ATOMICDIR=$(dirname $0)
+ATOMICTBL=${ATOMICDIR}/atomics.tbl
+LINUXDIR=${ATOMICDIR}/../..
+
+echo '' | sha1sum - > /dev/null 2>&1
+if [ $? -ne 0 ]; then
+ printf "sha1sum not available, skipping atomic header checks.\n"
+ exit 0
+fi
+
+cat <<EOF |
+asm-generic/atomic-instrumented.h
+asm-generic/atomic-long.h
+linux/atomic-fallback.h
+EOF
+while read header; do
+ OLDSUM="$(tail -n 1 ${LINUXDIR}/include/${header})"
+ OLDSUM="${OLDSUM#// }"
+
+ NEWSUM="$(sed '$d' ${LINUXDIR}/include/${header} | sha1sum)"
+ NEWSUM="${NEWSUM%% *}"
+
+ if [ "${OLDSUM}" != "${NEWSUM}" ]; then
+ printf "warning: generated include/${header} has been modified.\n"
+ fi
+done
+
+exit 0
diff --git a/scripts/atomic/fallbacks/acquire b/scripts/atomic/fallbacks/acquire
new file mode 100755
index 0000000..e38871e
--- /dev/null
+++ b/scripts/atomic/fallbacks/acquire
@@ -0,0 +1,9 @@
+cat <<EOF
+static inline ${ret}
+${atomic}_${pfx}${name}${sfx}_acquire(${params})
+{
+ ${ret} ret = ${atomic}_${pfx}${name}${sfx}_relaxed(${args});
+ __atomic_acquire_fence();
+ return ret;
+}
+EOF
diff --git a/scripts/atomic/fallbacks/add_negative b/scripts/atomic/fallbacks/add_negative
new file mode 100755
index 0000000..e6f4815
--- /dev/null
+++ b/scripts/atomic/fallbacks/add_negative
@@ -0,0 +1,16 @@
+cat <<EOF
+/**
+ * ${atomic}_add_negative - add and test if negative
+ * @i: integer value to add
+ * @v: pointer of type ${atomic}_t
+ *
+ * Atomically adds @i to @v and returns true
+ * if the result is negative, or false when
+ * result is greater than or equal to zero.
+ */
+static inline bool
+${atomic}_add_negative(${int} i, ${atomic}_t *v)
+{
+ return ${atomic}_add_return(i, v) < 0;
+}
+EOF
diff --git a/scripts/atomic/fallbacks/add_unless b/scripts/atomic/fallbacks/add_unless
new file mode 100755
index 0000000..7925338
--- /dev/null
+++ b/scripts/atomic/fallbacks/add_unless
@@ -0,0 +1,16 @@
+cat << EOF
+/**
+ * ${atomic}_add_unless - add unless the number is already a given value
+ * @v: pointer of type ${atomic}_t
+ * @a: the amount to add to v...
+ * @u: ...unless v is equal to u.
+ *
+ * Atomically adds @a to @v, if @v was not already @u.
+ * Returns true if the addition was done.
+ */
+static inline bool
+${atomic}_add_unless(${atomic}_t *v, ${int} a, ${int} u)
+{
+ return ${atomic}_fetch_add_unless(v, a, u) != u;
+}
+EOF
diff --git a/scripts/atomic/fallbacks/andnot b/scripts/atomic/fallbacks/andnot
new file mode 100755
index 0000000..9f3a321
--- /dev/null
+++ b/scripts/atomic/fallbacks/andnot
@@ -0,0 +1,7 @@
+cat <<EOF
+static inline ${ret}
+${atomic}_${pfx}andnot${sfx}${order}(${int} i, ${atomic}_t *v)
+{
+ ${retstmt}${atomic}_${pfx}and${sfx}${order}(~i, v);
+}
+EOF
diff --git a/scripts/atomic/fallbacks/dec b/scripts/atomic/fallbacks/dec
new file mode 100755
index 0000000..10bbc82
--- /dev/null
+++ b/scripts/atomic/fallbacks/dec
@@ -0,0 +1,7 @@
+cat <<EOF
+static inline ${ret}
+${atomic}_${pfx}dec${sfx}${order}(${atomic}_t *v)
+{
+ ${retstmt}${atomic}_${pfx}sub${sfx}${order}(1, v);
+}
+EOF
diff --git a/scripts/atomic/fallbacks/dec_and_test b/scripts/atomic/fallbacks/dec_and_test
new file mode 100755
index 0000000..0ce7103
--- /dev/null
+++ b/scripts/atomic/fallbacks/dec_and_test
@@ -0,0 +1,15 @@
+cat <<EOF
+/**
+ * ${atomic}_dec_and_test - decrement and test
+ * @v: pointer of type ${atomic}_t
+ *
+ * Atomically decrements @v by 1 and
+ * returns true if the result is 0, or false for all other
+ * cases.
+ */
+static inline bool
+${atomic}_dec_and_test(${atomic}_t *v)
+{
+ return ${atomic}_dec_return(v) == 0;
+}
+EOF
diff --git a/scripts/atomic/fallbacks/dec_if_positive b/scripts/atomic/fallbacks/dec_if_positive
new file mode 100755
index 0000000..c52eace
--- /dev/null
+++ b/scripts/atomic/fallbacks/dec_if_positive
@@ -0,0 +1,15 @@
+cat <<EOF
+static inline ${ret}
+${atomic}_dec_if_positive(${atomic}_t *v)
+{
+ ${int} dec, c = ${atomic}_read(v);
+
+ do {
+ dec = c - 1;
+ if (unlikely(dec < 0))
+ break;
+ } while (!${atomic}_try_cmpxchg(v, &c, dec));
+
+ return dec;
+}
+EOF
diff --git a/scripts/atomic/fallbacks/dec_unless_positive b/scripts/atomic/fallbacks/dec_unless_positive
new file mode 100755
index 0000000..8a2578f
--- /dev/null
+++ b/scripts/atomic/fallbacks/dec_unless_positive
@@ -0,0 +1,14 @@
+cat <<EOF
+static inline bool
+${atomic}_dec_unless_positive(${atomic}_t *v)
+{
+ ${int} c = ${atomic}_read(v);
+
+ do {
+ if (unlikely(c > 0))
+ return false;
+ } while (!${atomic}_try_cmpxchg(v, &c, c - 1));
+
+ return true;
+}
+EOF
diff --git a/scripts/atomic/fallbacks/fence b/scripts/atomic/fallbacks/fence
new file mode 100755
index 0000000..82f68fa
--- /dev/null
+++ b/scripts/atomic/fallbacks/fence
@@ -0,0 +1,11 @@
+cat <<EOF
+static inline ${ret}
+${atomic}_${pfx}${name}${sfx}(${params})
+{
+ ${ret} ret;
+ __atomic_pre_full_fence();
+ ret = ${atomic}_${pfx}${name}${sfx}_relaxed(${args});
+ __atomic_post_full_fence();
+ return ret;
+}
+EOF
diff --git a/scripts/atomic/fallbacks/fetch_add_unless b/scripts/atomic/fallbacks/fetch_add_unless
new file mode 100755
index 0000000..d2c091d
--- /dev/null
+++ b/scripts/atomic/fallbacks/fetch_add_unless
@@ -0,0 +1,23 @@
+cat << EOF
+/**
+ * ${atomic}_fetch_add_unless - add unless the number is already a given value
+ * @v: pointer of type ${atomic}_t
+ * @a: the amount to add to v...
+ * @u: ...unless v is equal to u.
+ *
+ * Atomically adds @a to @v, so long as @v was not already @u.
+ * Returns original value of @v
+ */
+static inline ${int}
+${atomic}_fetch_add_unless(${atomic}_t *v, ${int} a, ${int} u)
+{
+ ${int} c = ${atomic}_read(v);
+
+ do {
+ if (unlikely(c == u))
+ break;
+ } while (!${atomic}_try_cmpxchg(v, &c, c + a));
+
+ return c;
+}
+EOF
diff --git a/scripts/atomic/fallbacks/inc b/scripts/atomic/fallbacks/inc
new file mode 100755
index 0000000..f866b3a
--- /dev/null
+++ b/scripts/atomic/fallbacks/inc
@@ -0,0 +1,7 @@
+cat <<EOF
+static inline ${ret}
+${atomic}_${pfx}inc${sfx}${order}(${atomic}_t *v)
+{
+ ${retstmt}${atomic}_${pfx}add${sfx}${order}(1, v);
+}
+EOF
diff --git a/scripts/atomic/fallbacks/inc_and_test b/scripts/atomic/fallbacks/inc_and_test
new file mode 100755
index 0000000..4e20688
--- /dev/null
+++ b/scripts/atomic/fallbacks/inc_and_test
@@ -0,0 +1,15 @@
+cat <<EOF
+/**
+ * ${atomic}_inc_and_test - increment and test
+ * @v: pointer of type ${atomic}_t
+ *
+ * Atomically increments @v by 1
+ * and returns true if the result is zero, or false for all
+ * other cases.
+ */
+static inline bool
+${atomic}_inc_and_test(${atomic}_t *v)
+{
+ return ${atomic}_inc_return(v) == 0;
+}
+EOF
diff --git a/scripts/atomic/fallbacks/inc_not_zero b/scripts/atomic/fallbacks/inc_not_zero
new file mode 100755
index 0000000..a7c45c8
--- /dev/null
+++ b/scripts/atomic/fallbacks/inc_not_zero
@@ -0,0 +1,14 @@
+cat <<EOF
+/**
+ * ${atomic}_inc_not_zero - increment unless the number is zero
+ * @v: pointer of type ${atomic}_t
+ *
+ * Atomically increments @v by 1, if @v is non-zero.
+ * Returns true if the increment was done.
+ */
+static inline bool
+${atomic}_inc_not_zero(${atomic}_t *v)
+{
+ return ${atomic}_add_unless(v, 1, 0);
+}
+EOF
diff --git a/scripts/atomic/fallbacks/inc_unless_negative b/scripts/atomic/fallbacks/inc_unless_negative
new file mode 100755
index 0000000..0c266e7
--- /dev/null
+++ b/scripts/atomic/fallbacks/inc_unless_negative
@@ -0,0 +1,14 @@
+cat <<EOF
+static inline bool
+${atomic}_inc_unless_negative(${atomic}_t *v)
+{
+ ${int} c = ${atomic}_read(v);
+
+ do {
+ if (unlikely(c < 0))
+ return false;
+ } while (!${atomic}_try_cmpxchg(v, &c, c + 1));
+
+ return true;
+}
+EOF
diff --git a/scripts/atomic/fallbacks/read_acquire b/scripts/atomic/fallbacks/read_acquire
new file mode 100755
index 0000000..75863b5
--- /dev/null
+++ b/scripts/atomic/fallbacks/read_acquire
@@ -0,0 +1,7 @@
+cat <<EOF
+static inline ${ret}
+${atomic}_read_acquire(const ${atomic}_t *v)
+{
+ return smp_load_acquire(&(v)->counter);
+}
+EOF
diff --git a/scripts/atomic/fallbacks/release b/scripts/atomic/fallbacks/release
new file mode 100755
index 0000000..3f628a3
--- /dev/null
+++ b/scripts/atomic/fallbacks/release
@@ -0,0 +1,8 @@
+cat <<EOF
+static inline ${ret}
+${atomic}_${pfx}${name}${sfx}_release(${params})
+{
+ __atomic_release_fence();
+ ${retstmt}${atomic}_${pfx}${name}${sfx}_relaxed(${args});
+}
+EOF
diff --git a/scripts/atomic/fallbacks/set_release b/scripts/atomic/fallbacks/set_release
new file mode 100755
index 0000000..45bb5e0
--- /dev/null
+++ b/scripts/atomic/fallbacks/set_release
@@ -0,0 +1,7 @@
+cat <<EOF
+static inline void
+${atomic}_set_release(${atomic}_t *v, ${int} i)
+{
+ smp_store_release(&(v)->counter, i);
+}
+EOF
diff --git a/scripts/atomic/fallbacks/sub_and_test b/scripts/atomic/fallbacks/sub_and_test
new file mode 100755
index 0000000..289ef17
--- /dev/null
+++ b/scripts/atomic/fallbacks/sub_and_test
@@ -0,0 +1,16 @@
+cat <<EOF
+/**
+ * ${atomic}_sub_and_test - subtract value from variable and test result
+ * @i: integer value to subtract
+ * @v: pointer of type ${atomic}_t
+ *
+ * Atomically subtracts @i from @v and returns
+ * true if the result is zero, or false for all
+ * other cases.
+ */
+static inline bool
+${atomic}_sub_and_test(${int} i, ${atomic}_t *v)
+{
+ return ${atomic}_sub_return(i, v) == 0;
+}
+EOF
diff --git a/scripts/atomic/fallbacks/try_cmpxchg b/scripts/atomic/fallbacks/try_cmpxchg
new file mode 100755
index 0000000..4ed85e2
--- /dev/null
+++ b/scripts/atomic/fallbacks/try_cmpxchg
@@ -0,0 +1,11 @@
+cat <<EOF
+static inline bool
+${atomic}_try_cmpxchg${order}(${atomic}_t *v, ${int} *old, ${int} new)
+{
+ ${int} r, o = *old;
+ r = ${atomic}_cmpxchg${order}(v, o, new);
+ if (unlikely(r != o))
+ *old = r;
+ return likely(r == o);
+}
+EOF
diff --git a/scripts/atomic/gen-atomic-fallback.sh b/scripts/atomic/gen-atomic-fallback.sh
new file mode 100755
index 0000000..1bd7c17
--- /dev/null
+++ b/scripts/atomic/gen-atomic-fallback.sh
@@ -0,0 +1,181 @@
+#!/bin/sh
+# SPDX-License-Identifier: GPL-2.0
+
+ATOMICDIR=$(dirname $0)
+
+. ${ATOMICDIR}/atomic-tbl.sh
+
+#gen_template_fallback(template, meta, pfx, name, sfx, order, atomic, int, args...)
+gen_template_fallback()
+{
+ local template="$1"; shift
+ local meta="$1"; shift
+ local pfx="$1"; shift
+ local name="$1"; shift
+ local sfx="$1"; shift
+ local order="$1"; shift
+ local atomic="$1"; shift
+ local int="$1"; shift
+
+ local atomicname="${atomic}_${pfx}${name}${sfx}${order}"
+
+ local ret="$(gen_ret_type "${meta}" "${int}")"
+ local retstmt="$(gen_ret_stmt "${meta}")"
+ local params="$(gen_params "${int}" "${atomic}" "$@")"
+ local args="$(gen_args "$@")"
+
+ if [ ! -z "${template}" ]; then
+ printf "#ifndef ${atomicname}\n"
+ . ${template}
+ printf "#define ${atomicname} ${atomicname}\n"
+ printf "#endif\n\n"
+ fi
+}
+
+#gen_proto_fallback(meta, pfx, name, sfx, order, atomic, int, args...)
+gen_proto_fallback()
+{
+ local meta="$1"; shift
+ local pfx="$1"; shift
+ local name="$1"; shift
+ local sfx="$1"; shift
+ local order="$1"; shift
+
+ local tmpl="$(find_fallback_template "${pfx}" "${name}" "${sfx}" "${order}")"
+ gen_template_fallback "${tmpl}" "${meta}" "${pfx}" "${name}" "${sfx}" "${order}" "$@"
+}
+
+#gen_basic_fallbacks(basename)
+gen_basic_fallbacks()
+{
+ local basename="$1"; shift
+cat << EOF
+#define ${basename}_acquire ${basename}
+#define ${basename}_release ${basename}
+#define ${basename}_relaxed ${basename}
+EOF
+}
+
+#gen_proto_order_variants(meta, pfx, name, sfx, atomic, int, args...)
+gen_proto_order_variants()
+{
+ local meta="$1"; shift
+ local pfx="$1"; shift
+ local name="$1"; shift
+ local sfx="$1"; shift
+ local atomic="$1"
+
+ local basename="${atomic}_${pfx}${name}${sfx}"
+
+ local template="$(find_fallback_template "${pfx}" "${name}" "${sfx}" "${order}")"
+
+ # If we don't have relaxed atomics, then we don't bother with ordering fallbacks
+ # read_acquire and set_release need to be templated, though
+ if ! meta_has_relaxed "${meta}"; then
+ gen_proto_fallback "${meta}" "${pfx}" "${name}" "${sfx}" "" "$@"
+
+ if meta_has_acquire "${meta}"; then
+ gen_proto_fallback "${meta}" "${pfx}" "${name}" "${sfx}" "_acquire" "$@"
+ fi
+
+ if meta_has_release "${meta}"; then
+ gen_proto_fallback "${meta}" "${pfx}" "${name}" "${sfx}" "_release" "$@"
+ fi
+
+ return
+ fi
+
+ printf "#ifndef ${basename}_relaxed\n"
+
+ if [ ! -z "${template}" ]; then
+ printf "#ifdef ${basename}\n"
+ fi
+
+ gen_basic_fallbacks "${basename}"
+
+ if [ ! -z "${template}" ]; then
+ printf "#endif /* ${atomic}_${pfx}${name}${sfx} */\n\n"
+ gen_proto_fallback "${meta}" "${pfx}" "${name}" "${sfx}" "" "$@"
+ gen_proto_fallback "${meta}" "${pfx}" "${name}" "${sfx}" "_acquire" "$@"
+ gen_proto_fallback "${meta}" "${pfx}" "${name}" "${sfx}" "_release" "$@"
+ gen_proto_fallback "${meta}" "${pfx}" "${name}" "${sfx}" "_relaxed" "$@"
+ fi
+
+ printf "#else /* ${basename}_relaxed */\n\n"
+
+ gen_template_fallback "${ATOMICDIR}/fallbacks/acquire" "${meta}" "${pfx}" "${name}" "${sfx}" "_acquire" "$@"
+ gen_template_fallback "${ATOMICDIR}/fallbacks/release" "${meta}" "${pfx}" "${name}" "${sfx}" "_release" "$@"
+ gen_template_fallback "${ATOMICDIR}/fallbacks/fence" "${meta}" "${pfx}" "${name}" "${sfx}" "" "$@"
+
+ printf "#endif /* ${basename}_relaxed */\n\n"
+}
+
+gen_xchg_fallbacks()
+{
+ local xchg="$1"; shift
+cat <<EOF
+#ifndef ${xchg}_relaxed
+#define ${xchg}_relaxed ${xchg}
+#define ${xchg}_acquire ${xchg}
+#define ${xchg}_release ${xchg}
+#else /* ${xchg}_relaxed */
+
+#ifndef ${xchg}_acquire
+#define ${xchg}_acquire(...) \\
+ __atomic_op_acquire(${xchg}, __VA_ARGS__)
+#endif
+
+#ifndef ${xchg}_release
+#define ${xchg}_release(...) \\
+ __atomic_op_release(${xchg}, __VA_ARGS__)
+#endif
+
+#ifndef ${xchg}
+#define ${xchg}(...) \\
+ __atomic_op_fence(${xchg}, __VA_ARGS__)
+#endif
+
+#endif /* ${xchg}_relaxed */
+
+EOF
+}
+
+cat << EOF
+// SPDX-License-Identifier: GPL-2.0
+
+// Generated by $0
+// DO NOT MODIFY THIS FILE DIRECTLY
+
+#ifndef _LINUX_ATOMIC_FALLBACK_H
+#define _LINUX_ATOMIC_FALLBACK_H
+
+EOF
+
+for xchg in "xchg" "cmpxchg" "cmpxchg64"; do
+ gen_xchg_fallbacks "${xchg}"
+done
+
+grep '^[a-z]' "$1" | while read name meta args; do
+ gen_proto "${meta}" "${name}" "atomic" "int" ${args}
+done
+
+cat <<EOF
+#define atomic_cond_read_acquire(v, c) smp_cond_load_acquire(&(v)->counter, (c))
+#define atomic_cond_read_relaxed(v, c) smp_cond_load_relaxed(&(v)->counter, (c))
+
+#ifdef CONFIG_GENERIC_ATOMIC64
+#include <asm-generic/atomic64.h>
+#endif
+
+EOF
+
+grep '^[a-z]' "$1" | while read name meta args; do
+ gen_proto "${meta}" "${name}" "atomic64" "s64" ${args}
+done
+
+cat <<EOF
+#define atomic64_cond_read_acquire(v, c) smp_cond_load_acquire(&(v)->counter, (c))
+#define atomic64_cond_read_relaxed(v, c) smp_cond_load_relaxed(&(v)->counter, (c))
+
+#endif /* _LINUX_ATOMIC_FALLBACK_H */
+EOF
diff --git a/scripts/atomic/gen-atomic-instrumented.sh b/scripts/atomic/gen-atomic-instrumented.sh
new file mode 100755
index 0000000..e098123
--- /dev/null
+++ b/scripts/atomic/gen-atomic-instrumented.sh
@@ -0,0 +1,182 @@
+#!/bin/sh
+# SPDX-License-Identifier: GPL-2.0
+
+ATOMICDIR=$(dirname $0)
+
+. ${ATOMICDIR}/atomic-tbl.sh
+
+#gen_param_check(arg)
+gen_param_check()
+{
+ local arg="$1"; shift
+ local type="${arg%%:*}"
+ local name="$(gen_param_name "${arg}")"
+ local rw="write"
+
+ case "${type#c}" in
+ i) return;;
+ esac
+
+ # We don't write to constant parameters
+ [ ${type#c} != ${type} ] && rw="read"
+
+ printf "\tkasan_check_${rw}(${name}, sizeof(*${name}));\n"
+}
+
+#gen_param_check(arg...)
+gen_params_checks()
+{
+ while [ "$#" -gt 0 ]; do
+ gen_param_check "$1"
+ shift;
+ done
+}
+
+# gen_guard(meta, atomic, pfx, name, sfx, order)
+gen_guard()
+{
+ local meta="$1"; shift
+ local atomic="$1"; shift
+ local pfx="$1"; shift
+ local name="$1"; shift
+ local sfx="$1"; shift
+ local order="$1"; shift
+
+ local atomicname="arch_${atomic}_${pfx}${name}${sfx}${order}"
+
+ local template="$(find_fallback_template "${pfx}" "${name}" "${sfx}" "${order}")"
+
+ # We definitely need a preprocessor symbol for this atomic if it is an
+ # ordering variant, or if there's a generic fallback.
+ if [ ! -z "${order}" ] || [ ! -z "${template}" ]; then
+ printf "defined(${atomicname})"
+ return
+ fi
+
+ # If this is a base variant, but a relaxed variant *may* exist, then we
+ # only have a preprocessor symbol if the relaxed variant isn't defined
+ if meta_has_relaxed "${meta}"; then
+ printf "!defined(${atomicname}_relaxed) || defined(${atomicname})"
+ fi
+}
+
+#gen_proto_order_variant(meta, pfx, name, sfx, order, atomic, int, arg...)
+gen_proto_order_variant()
+{
+ local meta="$1"; shift
+ local pfx="$1"; shift
+ local name="$1"; shift
+ local sfx="$1"; shift
+ local order="$1"; shift
+ local atomic="$1"; shift
+ local int="$1"; shift
+
+ local atomicname="${atomic}_${pfx}${name}${sfx}${order}"
+
+ local guard="$(gen_guard "${meta}" "${atomic}" "${pfx}" "${name}" "${sfx}" "${order}")"
+
+ local ret="$(gen_ret_type "${meta}" "${int}")"
+ local params="$(gen_params "${int}" "${atomic}" "$@")"
+ local checks="$(gen_params_checks "$@")"
+ local args="$(gen_args "$@")"
+ local retstmt="$(gen_ret_stmt "${meta}")"
+
+ [ ! -z "${guard}" ] && printf "#if ${guard}\n"
+
+cat <<EOF
+static inline ${ret}
+${atomicname}(${params})
+{
+${checks}
+ ${retstmt}arch_${atomicname}(${args});
+}
+#define ${atomicname} ${atomicname}
+EOF
+
+ [ ! -z "${guard}" ] && printf "#endif\n"
+
+ printf "\n"
+}
+
+gen_xchg()
+{
+ local xchg="$1"; shift
+ local mult="$1"; shift
+
+cat <<EOF
+#define ${xchg}(ptr, ...) \\
+({ \\
+ typeof(ptr) __ai_ptr = (ptr); \\
+ kasan_check_write(__ai_ptr, ${mult}sizeof(*__ai_ptr)); \\
+ arch_${xchg}(__ai_ptr, __VA_ARGS__); \\
+})
+EOF
+}
+
+gen_optional_xchg()
+{
+ local name="$1"; shift
+ local sfx="$1"; shift
+ local guard="defined(arch_${name}${sfx})"
+
+ [ -z "${sfx}" ] && guard="!defined(arch_${name}_relaxed) || defined(arch_${name})"
+
+ printf "#if ${guard}\n"
+ gen_xchg "${name}${sfx}" ""
+ printf "#endif\n\n"
+}
+
+cat << EOF
+// SPDX-License-Identifier: GPL-2.0
+
+// Generated by $0
+// DO NOT MODIFY THIS FILE DIRECTLY
+
+/*
+ * This file provides wrappers with KASAN instrumentation for atomic operations.
+ * To use this functionality an arch's atomic.h file needs to define all
+ * atomic operations with arch_ prefix (e.g. arch_atomic_read()) and include
+ * this file at the end. This file provides atomic_read() that forwards to
+ * arch_atomic_read() for actual atomic operation.
+ * Note: if an arch atomic operation is implemented by means of other atomic
+ * operations (e.g. atomic_read()/atomic_cmpxchg() loop), then it needs to use
+ * arch_ variants (i.e. arch_atomic_read()/arch_atomic_cmpxchg()) to avoid
+ * double instrumentation.
+ */
+#ifndef _ASM_GENERIC_ATOMIC_INSTRUMENTED_H
+#define _ASM_GENERIC_ATOMIC_INSTRUMENTED_H
+
+#include <linux/build_bug.h>
+#include <linux/kasan-checks.h>
+
+EOF
+
+grep '^[a-z]' "$1" | while read name meta args; do
+ gen_proto "${meta}" "${name}" "atomic" "int" ${args}
+done
+
+grep '^[a-z]' "$1" | while read name meta args; do
+ gen_proto "${meta}" "${name}" "atomic64" "s64" ${args}
+done
+
+for xchg in "xchg" "cmpxchg" "cmpxchg64"; do
+ for order in "" "_acquire" "_release" "_relaxed"; do
+ gen_optional_xchg "${xchg}" "${order}"
+ done
+done
+
+for xchg in "cmpxchg_local" "cmpxchg64_local" "sync_cmpxchg"; do
+ gen_xchg "${xchg}" ""
+ printf "\n"
+done
+
+gen_xchg "cmpxchg_double" "2 * "
+
+printf "\n\n"
+
+gen_xchg "cmpxchg_double_local" "2 * "
+
+cat <<EOF
+
+#endif /* _ASM_GENERIC_ATOMIC_INSTRUMENTED_H */
+EOF
diff --git a/scripts/atomic/gen-atomic-long.sh b/scripts/atomic/gen-atomic-long.sh
new file mode 100755
index 0000000..c240a72
--- /dev/null
+++ b/scripts/atomic/gen-atomic-long.sh
@@ -0,0 +1,101 @@
+#!/bin/sh
+# SPDX-License-Identifier: GPL-2.0
+
+ATOMICDIR=$(dirname $0)
+
+. ${ATOMICDIR}/atomic-tbl.sh
+
+#gen_cast(arg, int, atomic)
+gen_cast()
+{
+ local arg="$1"; shift
+ local int="$1"; shift
+ local atomic="$1"; shift
+
+ [ "${arg%%:*}" = "p" ] || return
+
+ printf "($(gen_param_type "${arg}" "${int}" "${atomic}"))"
+}
+
+#gen_args_cast(int, atomic, arg...)
+gen_args_cast()
+{
+ local int="$1"; shift
+ local atomic="$1"; shift
+
+ while [ "$#" -gt 0 ]; do
+ local cast="$(gen_cast "$1" "${int}" "${atomic}")"
+ local arg="$(gen_param_name "$1")"
+ printf "${cast}${arg}"
+ [ "$#" -gt 1 ] && printf ", "
+ shift;
+ done
+}
+
+#gen_proto_order_variant(meta, pfx, name, sfx, order, atomic, int, arg...)
+gen_proto_order_variant()
+{
+ local meta="$1"; shift
+ local name="$1$2$3$4"; shift; shift; shift; shift
+ local atomic="$1"; shift
+ local int="$1"; shift
+
+ local ret="$(gen_ret_type "${meta}" "long")"
+ local params="$(gen_params "long" "atomic_long" "$@")"
+ local argscast="$(gen_args_cast "${int}" "${atomic}" "$@")"
+ local retstmt="$(gen_ret_stmt "${meta}")"
+
+cat <<EOF
+static inline ${ret}
+atomic_long_${name}(${params})
+{
+ ${retstmt}${atomic}_${name}(${argscast});
+}
+
+EOF
+}
+
+cat << EOF
+// SPDX-License-Identifier: GPL-2.0
+
+// Generated by $0
+// DO NOT MODIFY THIS FILE DIRECTLY
+
+#ifndef _ASM_GENERIC_ATOMIC_LONG_H
+#define _ASM_GENERIC_ATOMIC_LONG_H
+
+#include <asm/types.h>
+
+#ifdef CONFIG_64BIT
+typedef atomic64_t atomic_long_t;
+#define ATOMIC_LONG_INIT(i) ATOMIC64_INIT(i)
+#define atomic_long_cond_read_acquire atomic64_cond_read_acquire
+#define atomic_long_cond_read_relaxed atomic64_cond_read_relaxed
+#else
+typedef atomic_t atomic_long_t;
+#define ATOMIC_LONG_INIT(i) ATOMIC_INIT(i)
+#define atomic_long_cond_read_acquire atomic_cond_read_acquire
+#define atomic_long_cond_read_relaxed atomic_cond_read_relaxed
+#endif
+
+#ifdef CONFIG_64BIT
+
+EOF
+
+grep '^[a-z]' "$1" | while read name meta args; do
+ gen_proto "${meta}" "${name}" "atomic64" "s64" ${args}
+done
+
+cat <<EOF
+#else /* CONFIG_64BIT */
+
+EOF
+
+grep '^[a-z]' "$1" | while read name meta args; do
+ gen_proto "${meta}" "${name}" "atomic" "int" ${args}
+done
+
+cat <<EOF
+#endif /* CONFIG_64BIT */
+#endif /* _ASM_GENERIC_ATOMIC_LONG_H */
+EOF
diff --git a/scripts/atomic/gen-atomics.sh b/scripts/atomic/gen-atomics.sh
new file mode 100644
index 0000000..000dc64
--- /dev/null
+++ b/scripts/atomic/gen-atomics.sh
@@ -0,0 +1,20 @@
+#!/bin/sh
+# SPDX-License-Identifier: GPL-2.0
+#
+# Generate atomic headers
+
+ATOMICDIR=$(dirname $0)
+ATOMICTBL=${ATOMICDIR}/atomics.tbl
+LINUXDIR=${ATOMICDIR}/../..
+
+cat <<EOF |
+gen-atomic-instrumented.sh asm-generic/atomic-instrumented.h
+gen-atomic-long.sh asm-generic/atomic-long.h
+gen-atomic-fallback.sh linux/atomic-fallback.h
+EOF
+while read script header; do
+ /bin/sh ${ATOMICDIR}/${script} ${ATOMICTBL} > ${LINUXDIR}/include/${header}
+ HASH="$(sha1sum ${LINUXDIR}/include/${header})"
+ HASH="${HASH%% *}"
+ printf "// %s\n" "${HASH}" >> ${LINUXDIR}/include/${header}
+done
diff --git a/scripts/basic/Makefile b/scripts/basic/Makefile
index af49b44..7c9cb80 100644
--- a/scripts/basic/Makefile
+++ b/scripts/basic/Makefile
@@ -1,15 +1,6 @@
-###
-# This Makefile lists the most basic programs used during the build process.
-# The programs listed herein are what are needed to do the basic stuff,
-# such as fix file dependencies.
-# This initial step is needed to avoid files to be recompiled
-# when kernel configuration changes (which is what happens when
-# .config is included by main Makefile.
-# ---------------------------------------------------------------------------
-# fixdep: Used to generate dependency information during build process
+# SPDX-License-Identifier: GPL-2.0-only
+#
+# fixdep: used to generate dependency information during build process
hostprogs-y := fixdep
always := $(hostprogs-y)
-
-# fixdep is needed to compile other host programs
-$(addprefix $(obj)/,$(filter-out fixdep,$(always))): $(obj)/fixdep
diff --git a/scripts/basic/fixdep.c b/scripts/basic/fixdep.c
index 850966f..9ba47b0 100644
--- a/scripts/basic/fixdep.c
+++ b/scripts/basic/fixdep.c
@@ -99,25 +99,55 @@
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
+#include <stdarg.h>
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
static void usage(void)
{
- fprintf(stderr, "Usage: fixdep [-e] <depfile> <target> <cmdline>\n");
- fprintf(stderr, " -e insert extra dependencies given on stdin\n");
+ fprintf(stderr, "Usage: fixdep <depfile> <target> <cmdline>\n");
exit(1);
}
/*
+ * In the intended usage of this program, the stdout is redirected to .*.cmd
+ * files. The return value of printf() and putchar() must be checked to catch
+ * any error, e.g. "No space left on device".
+ */
+static void xprintf(const char *format, ...)
+{
+ va_list ap;
+ int ret;
+
+ va_start(ap, format);
+ ret = vprintf(format, ap);
+ if (ret < 0) {
+ perror("fixdep");
+ exit(1);
+ }
+ va_end(ap);
+}
+
+static void xputchar(int c)
+{
+ int ret;
+
+ ret = putchar(c);
+ if (ret == EOF) {
+ perror("fixdep");
+ exit(1);
+ }
+}
+
+/*
* Print out a dependency path from a symbol name
*/
static void print_dep(const char *m, int slen, const char *dir)
{
int c, prev_c = '/', i;
- printf(" $(wildcard %s/", dir);
+ xprintf(" $(wildcard %s/", dir);
for (i = 0; i < slen; i++) {
c = m[i];
if (c == '_')
@@ -125,25 +155,10 @@
else
c = tolower(c);
if (c != '/' || prev_c != '/')
- putchar(c);
+ xputchar(c);
prev_c = c;
}
- printf(".h) \\\n");
-}
-
-static void do_extra_deps(void)
-{
- char buf[80];
-
- while (fgets(buf, sizeof(buf), stdin)) {
- int len = strlen(buf);
-
- if (len < 2 || buf[len - 1] != '\n') {
- fprintf(stderr, "fixdep: bad data on stdin\n");
- exit(1);
- }
- print_dep(buf, len - 1, "include/ksym");
- }
+ xprintf(".h) \\\n");
}
struct item {
@@ -293,7 +308,7 @@
* assignments are parsed not only by make, but also by the rather simple
* parser in scripts/mod/sumversion.c.
*/
-static void parse_dep_file(char *m, const char *target, int insert_extra_deps)
+static void parse_dep_file(char *m, const char *target)
{
char *p;
int is_last, is_target;
@@ -340,13 +355,13 @@
*/
if (!saw_any_target) {
saw_any_target = 1;
- printf("source_%s := %s\n\n",
- target, m);
- printf("deps_%s := \\\n", target);
+ xprintf("source_%s := %s\n\n",
+ target, m);
+ xprintf("deps_%s := \\\n", target);
}
is_first_dep = 0;
} else {
- printf(" %s \\\n", m);
+ xprintf(" %s \\\n", m);
}
buf = read_file(m);
@@ -369,33 +384,26 @@
exit(1);
}
- if (insert_extra_deps)
- do_extra_deps();
-
- printf("\n%s: $(deps_%s)\n\n", target, target);
- printf("$(deps_%s):\n", target);
+ xprintf("\n%s: $(deps_%s)\n\n", target, target);
+ xprintf("$(deps_%s):\n", target);
}
int main(int argc, char *argv[])
{
const char *depfile, *target, *cmdline;
- int insert_extra_deps = 0;
void *buf;
- if (argc == 5 && !strcmp(argv[1], "-e")) {
- insert_extra_deps = 1;
- argv++;
- } else if (argc != 4)
+ if (argc != 4)
usage();
depfile = argv[1];
target = argv[2];
cmdline = argv[3];
- printf("cmd_%s := %s\n\n", target, cmdline);
+ xprintf("cmd_%s := %s\n\n", target, cmdline);
buf = read_file(depfile);
- parse_dep_file(buf, target, insert_extra_deps);
+ parse_dep_file(buf, target);
free(buf);
return 0;
diff --git a/scripts/bloat-o-meter b/scripts/bloat-o-meter
index a923f05..8c965f6 100755
--- a/scripts/bloat-o-meter
+++ b/scripts/bloat-o-meter
@@ -32,6 +32,7 @@
if name.startswith("__mod_"): continue
if name.startswith("__se_sys"): continue
if name.startswith("__se_compat_sys"): continue
+ if name.startswith("__addressable_"): continue
if name == "linux_banner": continue
# statics and some other optimizations adds random .NUMBER
name = re_NUMBER.sub('', name)
diff --git a/scripts/bootgraph.pl b/scripts/bootgraph.pl
index 594c5554..79c9032 100755
--- a/scripts/bootgraph.pl
+++ b/scripts/bootgraph.pl
@@ -1,24 +1,10 @@
#!/usr/bin/env perl
+# SPDX-License-Identifier: GPL-2.0-only
# Copyright 2008, Intel Corporation
#
# This file is part of the Linux kernel
#
-# This program file is free software; you can redistribute it and/or modify it
-# under the terms of the GNU General Public License as published by the
-# Free Software Foundation; version 2 of the License.
-#
-# This program is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-# for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program in a file named COPYING; if not, write to the
-# Free Software Foundation, Inc.,
-# 51 Franklin Street, Fifth Floor,
-# Boston, MA 02110-1301 USA
-#
# Authors:
# Arjan van de Ven <arjan@linux.intel.com>
diff --git a/scripts/bpf_helpers_doc.py b/scripts/bpf_helpers_doc.py
index 5010a4d..894cc58 100755
--- a/scripts/bpf_helpers_doc.py
+++ b/scripts/bpf_helpers_doc.py
@@ -1,7 +1,7 @@
#!/usr/bin/python3
# SPDX-License-Identifier: GPL-2.0-only
#
-# Copyright (C) 2018 Netronome Systems, Inc.
+# Copyright (C) 2018-2019 Netronome Systems, Inc.
# In case user attempts to run with Python 2.
from __future__ import print_function
@@ -39,7 +39,7 @@
Break down helper function protocol into smaller chunks: return type,
name, distincts arguments.
"""
- arg_re = re.compile('((const )?(struct )?(\w+|...))( (\**)(\w+))?$')
+ arg_re = re.compile('((\w+ )*?(\w+|...))( (\**)(\w+))?$')
res = {}
proto_re = re.compile('(.+) (\**)(\w+)\(((([^,]+)(, )?){1,5})\)$')
@@ -54,8 +54,8 @@
capture = arg_re.match(a)
res['args'].append({
'type' : capture.group(1),
- 'star' : capture.group(6),
- 'name' : capture.group(7)
+ 'star' : capture.group(5),
+ 'name' : capture.group(6)
})
return res
diff --git a/scripts/check_00index.sh b/scripts/check_00index.sh
deleted file mode 100755
index aa47f59..0000000
--- a/scripts/check_00index.sh
+++ /dev/null
@@ -1,67 +0,0 @@
-#!/bin/bash
-# SPDX-License-Identifier: GPL-2.0
-
-cd Documentation/
-
-# Check entries that should be removed
-
-obsolete=""
-for i in $(tail -n +12 00-INDEX |grep -E '^[a-zA-Z0-9]+'); do
- if [ ! -e $i ]; then
- obsolete="$obsolete $i"
- fi
-done
-
-# Check directory entries that should be added
-search=""
-dir=""
-for i in $(find . -maxdepth 1 -type d); do
- if [ "$i" != "." ]; then
- new=$(echo $i|perl -ne 's,./(.*),$1/,; print $_')
- search="$search $new"
- fi
-done
-
-for i in $search; do
- if [ "$(grep -P "^$i" 00-INDEX)" == "" ]; then
- dir="$dir $i"
- fi
-done
-
-# Check file entries that should be added
-search=""
-file=""
-for i in $(find . -maxdepth 1 -type f); do
- if [ "$i" != "./.gitignore" ]; then
- new=$(echo $i|perl -ne 's,./(.*),$1,; print $_')
- search="$search $new"
- fi
-done
-
-for i in $search; do
- if [ "$(grep -P "^$i\$" 00-INDEX)" == "" ]; then
- file="$file $i"
- fi
-done
-
-# Output its findings
-
-echo -e "Documentation/00-INDEX check results:\n"
-
-if [ "$obsolete" != "" ]; then
- echo -e "- Should remove those entries:\n\t$obsolete\n"
-else
- echo -e "- No obsolete entries\n"
-fi
-
-if [ "$dir" != "" ]; then
- echo -e "- Should document those directories:\n\t$dir\n"
-else
- echo -e "- No new directories to add\n"
-fi
-
-if [ "$file" != "" ]; then
- echo -e "- Should document those files:\n\t$file"
-else
- echo "- No new files to add"
-fi
diff --git a/scripts/checkkconfigsymbols.py b/scripts/checkkconfigsymbols.py
index 8cd16c6..00a10a2 100755
--- a/scripts/checkkconfigsymbols.py
+++ b/scripts/checkkconfigsymbols.py
@@ -1,11 +1,11 @@
#!/usr/bin/env python3
+# SPDX-License-Identifier: GPL-2.0-only
"""Find Kconfig symbols that are referenced but not defined."""
# (c) 2014-2017 Valentin Rothberg <valentinrothberg@gmail.com>
# (c) 2014 Stefan Hengelein <stefan.hengelein@fau.de>
#
-# Licensed under the terms of the GNU GPL License version 2
import argparse
diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl
index 161b022..6fcc66a 100755
--- a/scripts/checkpatch.pl
+++ b/scripts/checkpatch.pl
@@ -61,7 +61,9 @@
my $conststructsfile = "$D/const_structs.checkpatch";
my $typedefsfile = "";
my $color = "auto";
-my $allow_c99_comments = 1;
+my $allow_c99_comments = 1; # Can be overridden by --ignore C99_COMMENT_TOLERANCE
+# git output parsing needs US English output, so first set backtick child process LANGUAGE
+my $git_command ='export LANGUAGE=en_US.UTF-8; git';
sub help {
my ($exitcode) = @_;
@@ -466,8 +468,19 @@
seq_vprintf|seq_printf|seq_puts
)};
+our $allocFunctions = qr{(?x:
+ (?:(?:devm_)?
+ (?:kv|k|v)[czm]alloc(?:_node|_array)? |
+ kstrdup(?:_const)? |
+ kmemdup(?:_nul)?) |
+ (?:\w+)?alloc_skb(?:ip_align)? |
+ # dev_alloc_skb/netdev_alloc_skb, et al
+ dma_alloc_coherent
+)};
+
our $signature_tags = qr{(?xi:
Signed-off-by:|
+ Co-developed-by:|
Acked-by:|
Tested-by:|
Reviewed-by:|
@@ -573,6 +586,27 @@
}
$mode_perms_search = "(?:${mode_perms_search})";
+our %deprecated_apis = (
+ "synchronize_rcu_bh" => "synchronize_rcu",
+ "synchronize_rcu_bh_expedited" => "synchronize_rcu_expedited",
+ "call_rcu_bh" => "call_rcu",
+ "rcu_barrier_bh" => "rcu_barrier",
+ "synchronize_sched" => "synchronize_rcu",
+ "synchronize_sched_expedited" => "synchronize_rcu_expedited",
+ "call_rcu_sched" => "call_rcu",
+ "rcu_barrier_sched" => "rcu_barrier",
+ "get_state_synchronize_sched" => "get_state_synchronize_rcu",
+ "cond_synchronize_sched" => "cond_synchronize_rcu",
+);
+
+#Create a search pattern for all these strings to speed up a loop below
+our $deprecated_apis_search = "";
+foreach my $entry (keys %deprecated_apis) {
+ $deprecated_apis_search .= '|' if ($deprecated_apis_search ne "");
+ $deprecated_apis_search .= $entry;
+}
+$deprecated_apis_search = "(?:${deprecated_apis_search})";
+
our $mode_perms_world_writable = qr{
S_IWUGO |
S_IWOTH |
@@ -872,7 +906,7 @@
$camelcase_seeded = 1;
if (-e ".git") {
- my $git_last_include_commit = `git log --no-merges --pretty=format:"%h%n" -1 -- include`;
+ my $git_last_include_commit = `${git_command} log --no-merges --pretty=format:"%h%n" -1 -- include`;
chomp $git_last_include_commit;
$camelcase_cache = ".checkpatch-camelcase.git.$git_last_include_commit";
} else {
@@ -900,7 +934,7 @@
}
if (-e ".git") {
- $files = `git ls-files "include/*.h"`;
+ $files = `${git_command} ls-files "include/*.h"`;
@include_files = split('\n', $files);
}
@@ -924,13 +958,13 @@
return ($id, $desc) if ((which("git") eq "") || !(-e ".git"));
- my $output = `git log --no-color --format='%H %s' -1 $commit 2>&1`;
+ my $output = `${git_command} log --no-color --format='%H %s' -1 $commit 2>&1`;
$output =~ s/^\s*//gm;
my @lines = split("\n", $output);
return ($id, $desc) if ($#lines < 0);
- if ($lines[0] =~ /^error: short SHA1 $commit is ambiguous\./) {
+ if ($lines[0] =~ /^error: short SHA1 $commit is ambiguous/) {
# Maybe one day convert this block of bash into something that returns
# all matching commit ids, but it's very slow...
#
@@ -974,7 +1008,7 @@
} else {
$git_range = "-1 $commit_expr";
}
- my $lines = `git log --no-color --no-merges --pretty=format:'%H %s' $git_range`;
+ my $lines = `${git_command} log --no-color --no-merges --pretty=format:'%H %s' $git_range`;
foreach my $line (split(/\n/, $lines)) {
$line =~ /^([0-9a-fA-F]{40,40}) (.*)$/;
next if (!defined($1) || !defined($2));
@@ -989,6 +1023,7 @@
}
my $vname;
+$allow_c99_comments = !defined $ignore_type{"C99_COMMENT_TOLERANCE"};
for my $filename (@ARGV) {
my $FILE;
if ($git) {
@@ -2654,6 +2689,24 @@
} else {
$signatures{$sig_nospace} = 1;
}
+
+# Check Co-developed-by: immediately followed by Signed-off-by: with same name and email
+ if ($sign_off =~ /^co-developed-by:$/i) {
+ if ($email eq $author) {
+ WARN("BAD_SIGN_OFF",
+ "Co-developed-by: should not be used to attribute nominal patch author '$author'\n" . "$here\n" . $rawline);
+ }
+ if (!defined $lines[$linenr]) {
+ WARN("BAD_SIGN_OFF",
+ "Co-developed-by: must be immediately followed by Signed-off-by:\n" . "$here\n" . $rawline);
+ } elsif ($rawlines[$linenr] !~ /^\s*signed-off-by:\s*(.*)/i) {
+ WARN("BAD_SIGN_OFF",
+ "Co-developed-by: must be immediately followed by Signed-off-by:\n" . "$here\n" . $rawline . "\n" .$rawlines[$linenr]);
+ } elsif ($1 ne $email) {
+ WARN("BAD_SIGN_OFF",
+ "Co-developed-by and Signed-off-by: name/email do not match \n" . "$here\n" . $rawline . "\n" .$rawlines[$linenr]);
+ }
+ }
}
# Check email subject for common tools that don't need to be mentioned
@@ -2674,8 +2727,10 @@
($line =~ /^\s*(?:WARNING:|BUG:)/ ||
$line =~ /^\s*\[\s*\d+\.\d{6,6}\s*\]/ ||
# timestamp
- $line =~ /^\s*\[\<[0-9a-fA-F]{8,}\>\]/)) {
- # stack dump address
+ $line =~ /^\s*\[\<[0-9a-fA-F]{8,}\>\]/) ||
+ $line =~ /^(?:\s+\w+:\s+[0-9a-fA-F]+){3,3}/ ||
+ $line =~ /^\s*\#\d+\s*\[[0-9a-fA-F]+\]\s*\w+ at [0-9a-fA-F]+/) {
+ # stack dump address styles
$commit_log_possible_stack_dump = 1;
}
@@ -2847,6 +2902,17 @@
}
}
+# check for invalid commit id
+ if ($in_commit_log && $line =~ /(^fixes:|\bcommit)\s+([0-9a-f]{6,40})\b/i) {
+ my $id;
+ my $description;
+ ($id, $description) = git_commit_info($2, undef, undef);
+ if (!defined($id)) {
+ WARN("UNKNOWN_COMMIT_ID",
+ "Unknown commit id '$2', maybe rebased or not pulled?\n" . $herecurr);
+ }
+ }
+
# ignore non-hunk lines and lines being removed
next if (!$hunk_line || $line =~ /^-/);
@@ -2976,7 +3042,7 @@
my @compats = $rawline =~ /\"([a-zA-Z0-9\-\,\.\+_]+)\"/g;
my $dt_path = $root . "/Documentation/devicetree/bindings/";
- my $vp_file = $dt_path . "vendor-prefixes.txt";
+ my $vp_file = $dt_path . "vendor-prefixes.yaml";
foreach my $compat (@compats) {
my $compat2 = $compat;
@@ -2991,7 +3057,7 @@
next if $compat !~ /^([a-zA-Z0-9\-]+)\,/;
my $vendor = $1;
- `grep -Eq "^$vendor\\b" $vp_file`;
+ `grep -Eq "\\"\\^\Q$vendor\E,\\.\\*\\":" $vp_file`;
if ( $? >> 8 ) {
WARN("UNDOCUMENTED_DT_STRING",
"DT compatible string vendor \"$vendor\" appears un-documented -- check $vp_file\n" . $herecurr);
@@ -3015,16 +3081,24 @@
$comment = '..';
}
+# check SPDX comment style for .[chsS] files
+ if ($realfile =~ /\.[chsS]$/ &&
+ $rawline =~ /SPDX-License-Identifier:/ &&
+ $rawline !~ m@^\+\s*\Q$comment\E\s*@) {
+ WARN("SPDX_LICENSE_TAG",
+ "Improper SPDX comment style for '$realfile', please use '$comment' instead\n" . $herecurr);
+ }
+
if ($comment !~ /^$/ &&
- $rawline !~ /^\+\Q$comment\E SPDX-License-Identifier: /) {
- WARN("SPDX_LICENSE_TAG",
- "Missing or malformed SPDX-License-Identifier tag in line $checklicenseline\n" . $herecurr);
+ $rawline !~ m@^\+\Q$comment\E SPDX-License-Identifier: @) {
+ WARN("SPDX_LICENSE_TAG",
+ "Missing or malformed SPDX-License-Identifier tag in line $checklicenseline\n" . $herecurr);
} elsif ($rawline =~ /(SPDX-License-Identifier: .*)/) {
- my $spdx_license = $1;
- if (!is_SPDX_License_valid($spdx_license)) {
- WARN("SPDX_LICENSE_TAG",
- "'$spdx_license' is not supported in LICENSES/...\n" . $herecurr);
- }
+ my $spdx_license = $1;
+ if (!is_SPDX_License_valid($spdx_license)) {
+ WARN("SPDX_LICENSE_TAG",
+ "'$spdx_license' is not supported in LICENSES/...\n" . $herecurr);
+ }
}
}
}
@@ -3032,6 +3106,14 @@
# check we are in a valid source file if not then ignore this hunk
next if ($realfile !~ /\.(h|c|s|S|sh|dtsi|dts)$/);
+# check for using SPDX-License-Identifier on the wrong line number
+ if ($realline != $checklicenseline &&
+ $rawline =~ /\bSPDX-License-Identifier:/ &&
+ substr($line, @-, @+ - @-) eq "$;" x (@+ - @-)) {
+ WARN("SPDX_LICENSE_TAG",
+ "Misplaced SPDX-License-Identifier tag - use line $checklicenseline instead\n" . $herecurr);
+ }
+
# line length limit (with some exclusions)
#
# There are a few types of lines that may extend beyond $max_line_length:
@@ -3869,14 +3951,23 @@
WARN("STATIC_CONST_CHAR_ARRAY",
"static const char * array should probably be static const char * const\n" .
$herecurr);
- }
+ }
+
+# check for initialized const char arrays that should be static const
+ if ($line =~ /^\+\s*const\s+(char|unsigned\s+char|_*u8|(?:[us]_)?int8_t)\s+\w+\s*\[\s*(?:\w+\s*)?\]\s*=\s*"/) {
+ if (WARN("STATIC_CONST_CHAR_ARRAY",
+ "const array should probably be static const\n" . $herecurr) &&
+ $fix) {
+ $fixed[$fixlinenr] =~ s/(^.\s*)const\b/${1}static const/;
+ }
+ }
# check for static char foo[] = "bar" declarations.
if ($line =~ /\bstatic\s+char\s+(\w+)\s*\[\s*\]\s*=\s*"/) {
WARN("STATIC_CONST_CHAR_ARRAY",
"static char array declaration should probably be static const char\n" .
$herecurr);
- }
+ }
# check for const <foo> const where <foo> is not a pointer or array type
if ($sline =~ /\bconst\s+($BasicType)\s+const\b/) {
@@ -4584,7 +4675,7 @@
# closing brace should have a space following it when it has anything
# on the line
- if ($line =~ /}(?!(?:,|;|\)))\S/) {
+ if ($line =~ /}(?!(?:,|;|\)|\}))\S/) {
if (ERROR("SPACING",
"space required after that close brace '}'\n" . $herecurr) &&
$fix) {
@@ -4934,17 +5025,6 @@
while ($line =~ m{($Constant|$Lval)}g) {
my $var = $1;
-#gcc binary extension
- if ($var =~ /^$Binary$/) {
- if (WARN("GCC_BINARY_CONSTANT",
- "Avoid gcc v4.3+ binary constant extension: <$var>\n" . $herecurr) &&
- $fix) {
- my $hexval = sprintf("0x%x", oct($var));
- $fixed[$fixlinenr] =~
- s/\b$var\b/$hexval/;
- }
- }
-
#CamelCase
if ($var !~ /^$Constant$/ &&
$var =~ /[A-Z][a-z]|[a-z][A-Z]/ &&
@@ -5126,7 +5206,7 @@
next if ($arg =~ /\.\.\./);
next if ($arg =~ /^type$/i);
my $tmp_stmt = $define_stmt;
- $tmp_stmt =~ s/\b(typeof|__typeof__|__builtin\w+|typecheck\s*\(\s*$Type\s*,|\#+)\s*\(*\s*$arg\s*\)*\b//g;
+ $tmp_stmt =~ s/\b(sizeof|typeof|__typeof__|__builtin\w+|typecheck\s*\(\s*$Type\s*,|\#+)\s*\(*\s*$arg\s*\)*\b//g;
$tmp_stmt =~ s/\#+\s*$arg\b//g;
$tmp_stmt =~ s/\b$arg\s*\#\#//g;
my $use_cnt = () = $tmp_stmt =~ /\b$arg\b/g;
@@ -5525,7 +5605,8 @@
my ($s, $c) = ctx_statement_block($linenr - 3, $realcnt, 0);
# print("line: <$line>\nprevline: <$prevline>\ns: <$s>\nc: <$c>\n\n\n");
- if ($s =~ /(?:^|\n)[ \+]\s*(?:$Type\s*)?\Q$testval\E\s*=\s*(?:\([^\)]*\)\s*)?\s*(?:devm_)?(?:[kv][czm]alloc(?:_node|_array)?\b|kstrdup|kmemdup|(?:dev_)?alloc_skb)/) {
+ if ($s =~ /(?:^|\n)[ \+]\s*(?:$Type\s*)?\Q$testval\E\s*=\s*(?:\([^\)]*\)\s*)?\s*$allocFunctions\s*\(/ &&
+ $s !~ /\b__GFP_NOWARN\b/ ) {
WARN("OOM_MESSAGE",
"Possible unnecessary 'out of memory' message\n" . $hereprev);
}
@@ -5646,7 +5727,7 @@
# ignore udelay's < 10, however
if (! ($delay < 10) ) {
CHK("USLEEP_RANGE",
- "usleep_range is preferred over udelay; see Documentation/timers/timers-howto.txt\n" . $herecurr);
+ "usleep_range is preferred over udelay; see Documentation/timers/timers-howto.rst\n" . $herecurr);
}
if ($delay > 2000) {
WARN("LONG_UDELAY",
@@ -5658,7 +5739,7 @@
if ($line =~ /\bmsleep\s*\((\d+)\);/) {
if ($1 < 20) {
WARN("MSLEEP",
- "msleep < 20ms can sleep for up to 20ms; see Documentation/timers/timers-howto.txt\n" . $herecurr);
+ "msleep < 20ms can sleep for up to 20ms; see Documentation/timers/timers-howto.rst\n" . $herecurr);
}
}
@@ -5807,6 +5888,18 @@
"__aligned(size) is preferred over __attribute__((aligned(size)))\n" . $herecurr);
}
+# Check for __attribute__ section, prefer __section
+ if ($realfile !~ m@\binclude/uapi/@ &&
+ $line =~ /\b__attribute__\s*\(\s*\(.*_*section_*\s*\(\s*("[^"]*")/) {
+ my $old = substr($rawline, $-[1], $+[1] - $-[1]);
+ my $new = substr($old, 1, -1);
+ if (WARN("PREFER_SECTION",
+ "__section($new) is preferred over __attribute__((section($old)))\n" . $herecurr) &&
+ $fix) {
+ $fixed[$fixlinenr] =~ s/\b__attribute__\s*\(\s*\(\s*_*section_*\s*\(\s*\Q$old\E\s*\)\s*\)\s*\)/__section($new)/;
+ }
+ }
+
# Check for __attribute__ format(printf, prefer __printf
if ($realfile !~ m@\binclude/uapi/@ &&
$line =~ /\b__attribute__\s*\(\s*\(\s*format\s*\(\s*printf/) {
@@ -5929,7 +6022,7 @@
while ($fmt =~ /(\%[\*\d\.]*p(\w))/g) {
$specifier = $1;
$extension = $2;
- if ($extension !~ /[SsBKRraEhMmIiUDdgVCbGNOx]/) {
+ if ($extension !~ /[SsBKRraEhMmIiUDdgVCbGNOxt]/) {
$bad_specifier = $specifier;
last;
}
@@ -6049,11 +6142,11 @@
my $max = $7;
if ($min eq $max) {
WARN("USLEEP_RANGE",
- "usleep_range should not use min == max args; see Documentation/timers/timers-howto.txt\n" . "$here\n$stat\n");
+ "usleep_range should not use min == max args; see Documentation/timers/timers-howto.rst\n" . "$here\n$stat\n");
} elsif ($min =~ /^\d+$/ && $max =~ /^\d+$/ &&
$min > $max) {
WARN("USLEEP_RANGE",
- "usleep_range args reversed, use min then max; see Documentation/timers/timers-howto.txt\n" . "$here\n$stat\n");
+ "usleep_range args reversed, use min then max; see Documentation/timers/timers-howto.rst\n" . "$here\n$stat\n");
}
}
@@ -6176,8 +6269,8 @@
}
}
-# check for pointless casting of kmalloc return
- if ($line =~ /\*\s*\)\s*[kv][czm]alloc(_node){0,1}\b/) {
+# check for pointless casting of alloc functions
+ if ($line =~ /\*\s*\)\s*$allocFunctions\b/) {
WARN("UNNECESSARY_CASTS",
"unnecessary cast may hide bugs, see http://c-faq.com/malloc/mallocnocast.html\n" . $herecurr);
}
@@ -6185,7 +6278,7 @@
# alloc style
# p = alloc(sizeof(struct foo), ...) should be p = alloc(sizeof(*p), ...)
if ($perl_version_ok &&
- $line =~ /\b($Lval)\s*\=\s*(?:$balanced_parens)?\s*([kv][mz]alloc(?:_node)?)\s*\(\s*(sizeof\s*\(\s*struct\s+$Lval\s*\))/) {
+ $line =~ /\b($Lval)\s*\=\s*(?:$balanced_parens)?\s*((?:kv|k|v)[mz]alloc(?:_node)?)\s*\(\s*(sizeof\s*\(\s*struct\s+$Lval\s*\))/) {
CHK("ALLOC_SIZEOF_STRUCT",
"Prefer $3(sizeof(*$1)...) over $3($4...)\n" . $herecurr);
}
@@ -6348,19 +6441,6 @@
}
}
-# check for bool bitfields
- if ($sline =~ /^.\s+bool\s*$Ident\s*:\s*\d+\s*;/) {
- WARN("BOOL_BITFIELD",
- "Avoid using bool as bitfield. Prefer bool bitfields as unsigned int or u<8|16|32>\n" . $herecurr);
- }
-
-# check for bool use in .h files
- if ($realfile =~ /\.h$/ &&
- $sline =~ /^.\s+bool\s*$Ident\s*(?::\s*d+\s*)?;/) {
- CHK("BOOL_MEMBER",
- "Avoid using bool structure members because of possible alignment issues - see: https://lkml.org/lkml/2017/11/21/384\n" . $herecurr);
- }
-
# check for semaphores initialized locked
if ($line =~ /^.\s*sema_init.+,\W?0\W?\)/) {
WARN("CONSIDER_COMPLETION",
@@ -6379,6 +6459,20 @@
"please use device_initcall() or more appropriate function instead of __initcall() (see include/linux/init.h)\n" . $herecurr);
}
+# check for spin_is_locked(), suggest lockdep instead
+ if ($line =~ /\bspin_is_locked\(/) {
+ WARN("USE_LOCKDEP",
+ "Where possible, use lockdep_assert_held instead of assertions based on spin_is_locked\n" . $herecurr);
+ }
+
+# check for deprecated apis
+ if ($line =~ /\b($deprecated_apis_search)\b\s*\(/) {
+ my $deprecated_api = $1;
+ my $new_api = $deprecated_apis{$deprecated_api};
+ WARN("DEPRECATED_API",
+ "Deprecated use of '$deprecated_api', prefer '$new_api' instead\n" . $herecurr);
+ }
+
# check for various structs that are normally const (ops, kgdb, device_tree)
# and avoid what seem like struct definitions 'struct foo {'
if ($line !~ /\bconst\b/ &&
@@ -6413,6 +6507,12 @@
"Using $1 should generally have parentheses around the comparison\n" . $herecurr);
}
+# nested likely/unlikely calls
+ if ($line =~ /\b(?:(?:un)?likely)\s*\(\s*!?\s*(IS_ERR(?:_OR_NULL|_VALUE)?|WARN)/) {
+ WARN("LIKELY_MISUSE",
+ "nested (un)?likely() calls, $1 already uses unlikely() internally\n" . $herecurr);
+ }
+
# whine mightly about in_atomic
if ($line =~ /\bin_atomic\s*\(/) {
if ($realfile =~ m@^drivers/@) {
@@ -6572,6 +6672,12 @@
"unknown module license " . $extracted_string . "\n" . $herecurr);
}
}
+
+# check for sysctl duplicate constants
+ if ($line =~ /\.extra[12]\s*=\s*&(zero|one|int_max)\b/) {
+ WARN("DUPLICATED_SYSCTL_CONST",
+ "duplicated sysctl range checking value '$1', consider using the shared one in include/linux/sysctl.h\n" . $herecurr);
+ }
}
# If we have no input at all, then there is nothing to report on
diff --git a/scripts/checkstack.pl b/scripts/checkstack.pl
index 8081b6c..371bd17 100755
--- a/scripts/checkstack.pl
+++ b/scripts/checkstack.pl
@@ -46,9 +46,11 @@
$x = "[0-9a-f]"; # hex character
$xs = "[0-9a-f ]"; # hex character or space
$funcre = qr/^$x* <(.*)>:$/;
- if ($arch eq 'aarch64') {
- #ffffffc0006325cc: a9bb7bfd stp x29, x30, [sp,#-80]!
- $re = qr/^.*stp.*sp,\#-([0-9]{1,8})\]\!/o;
+ if ($arch =~ '^(aarch|arm)64$') {
+ #ffffffc0006325cc: a9bb7bfd stp x29, x30, [sp, #-80]!
+ #a110: d11643ff sub sp, sp, #0x590
+ $re = qr/^.*stp.*sp, \#-([0-9]{1,8})\]\!/o;
+ $dre = qr/^.*sub.*sp, sp, #(0x$x{1,8})/o;
} elsif ($arch eq 'arm') {
#c0008ffc: e24dd064 sub sp, sp, #100 ; 0x64
$re = qr/.*sub.*sp, sp, #(([0-9]{2}|[3-9])[0-9]{2})/o;
diff --git a/scripts/checksyscalls.sh b/scripts/checksyscalls.sh
index ee3dfb5..a18b476 100755
--- a/scripts/checksyscalls.sh
+++ b/scripts/checksyscalls.sh
@@ -30,12 +30,14 @@
#define __IGNORE_readlink /* readlinkat */
#define __IGNORE_symlink /* symlinkat */
#define __IGNORE_utimes /* futimesat */
-#if BITS_PER_LONG == 64
#define __IGNORE_stat /* fstatat */
#define __IGNORE_lstat /* fstatat */
-#else
#define __IGNORE_stat64 /* fstatat64 */
#define __IGNORE_lstat64 /* fstatat64 */
+
+#ifndef __ARCH_WANT_SET_GET_RLIMIT
+#define __IGNORE_getrlimit /* getrlimit */
+#define __IGNORE_setrlimit /* setrlimit */
#endif
/* Missing flags argument */
@@ -84,6 +86,26 @@
#define __IGNORE_statfs64
#define __IGNORE_llseek
#define __IGNORE_mmap2
+#define __IGNORE_clock_gettime64
+#define __IGNORE_clock_settime64
+#define __IGNORE_clock_adjtime64
+#define __IGNORE_clock_getres_time64
+#define __IGNORE_clock_nanosleep_time64
+#define __IGNORE_timer_gettime64
+#define __IGNORE_timer_settime64
+#define __IGNORE_timerfd_gettime64
+#define __IGNORE_timerfd_settime64
+#define __IGNORE_utimensat_time64
+#define __IGNORE_pselect6_time64
+#define __IGNORE_ppoll_time64
+#define __IGNORE_io_pgetevents_time64
+#define __IGNORE_recvmmsg_time64
+#define __IGNORE_mq_timedsend_time64
+#define __IGNORE_mq_timedreceive_time64
+#define __IGNORE_semtimedop_time64
+#define __IGNORE_rt_sigtimedwait_time64
+#define __IGNORE_futex_time64
+#define __IGNORE_sched_rr_get_interval_time64
#else
#define __IGNORE_sendfile
#define __IGNORE_ftruncate
@@ -98,6 +120,33 @@
#define __IGNORE_statfs
#define __IGNORE_lseek
#define __IGNORE_mmap
+#define __IGNORE_clock_gettime
+#define __IGNORE_clock_settime
+#define __IGNORE_clock_adjtime
+#define __IGNORE_clock_getres
+#define __IGNORE_clock_nanosleep
+#define __IGNORE_timer_gettime
+#define __IGNORE_timer_settime
+#define __IGNORE_timerfd_gettime
+#define __IGNORE_timerfd_settime
+#define __IGNORE_utimensat
+#define __IGNORE_pselect6
+#define __IGNORE_ppoll
+#define __IGNORE_io_pgetevents
+#define __IGNORE_recvmmsg
+#define __IGNORE_mq_timedsend
+#define __IGNORE_mq_timedreceive
+#define __IGNORE_semtimedop
+#define __IGNORE_rt_sigtimedwait
+#define __IGNORE_futex
+#define __IGNORE_sched_rr_get_interval
+#define __IGNORE_gettimeofday
+#define __IGNORE_settimeofday
+#define __IGNORE_wait4
+#define __IGNORE_adjtimex
+#define __IGNORE_nanosleep
+#define __IGNORE_io_getevents
+#define __IGNORE_recvmmsg
#endif
/* i386-specific or historical system calls */
@@ -150,6 +199,7 @@
#define __IGNORE_uselib
#define __IGNORE__sysctl
#define __IGNORE_arch_prctl
+#define __IGNORE_nfsservctl
/* ... including the "new" 32-bit uid syscalls */
#define __IGNORE_lchown32
diff --git a/scripts/clang-version.sh b/scripts/clang-version.sh
index e65fbc3..6fabf06 100755
--- a/scripts/clang-version.sh
+++ b/scripts/clang-version.sh
@@ -1,14 +1,10 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
#
-# clang-version [-p] clang-command
+# clang-version clang-command
#
-# Prints the compiler version of `clang-command' in a canonical 4-digit form
-# such as `0500' for clang-5.0 etc.
-#
-# With the -p option, prints the patchlevel as well, for example `050001' for
-# clang-5.0.1 etc.
-#
+# Print the compiler version of `clang-command' in a 5 or 6-digit form
+# such as `50001' for clang-5.0.1 etc.
compiler="$*"
diff --git a/scripts/coccinelle/api/alloc/alloc_cast.cocci b/scripts/coccinelle/api/alloc/alloc_cast.cocci
index 408ee38..f6f0ccd 100644
--- a/scripts/coccinelle/api/alloc/alloc_cast.cocci
+++ b/scripts/coccinelle/api/alloc/alloc_cast.cocci
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0-only
/// Remove casting the values returned by memory allocation functions
/// like kmalloc, kzalloc, kmem_cache_alloc, kmem_cache_zalloc etc.
///
@@ -8,8 +9,8 @@
//# need some reformatting.
//
// Confidence: High
-// Copyright: (C) 2014 Himangi Saraogi GPLv2.
-// Copyright: (C) 2017 Himanshu Jha GPLv2.
+// Copyright: (C) 2014 Himangi Saraogi
+// Copyright: (C) 2017 Himanshu Jha
// Comments:
// Options: --no-includes --include-headers
//
@@ -32,7 +33,7 @@
(T *)
\(kmalloc\|kzalloc\|kcalloc\|kmem_cache_alloc\|kmem_cache_zalloc\|
kmem_cache_alloc_node\|kmalloc_node\|kzalloc_node\|vmalloc\|vzalloc\|
- dma_alloc_coherent\|dma_zalloc_coherent\|devm_kmalloc\|devm_kzalloc\|
+ dma_alloc_coherent\|devm_kmalloc\|devm_kzalloc\|
kvmalloc\|kvzalloc\|kvmalloc_node\|kvzalloc_node\|pci_alloc_consistent\|
pci_zalloc_consistent\|kmem_alloc\|kmem_zalloc\|kmem_zone_alloc\|
kmem_zone_zalloc\|vmalloc_node\|vzalloc_node\)(...)
@@ -55,7 +56,7 @@
* (T *)
\(kmalloc\|kzalloc\|kcalloc\|kmem_cache_alloc\|kmem_cache_zalloc\|
kmem_cache_alloc_node\|kmalloc_node\|kzalloc_node\|vmalloc\|vzalloc\|
- dma_alloc_coherent\|dma_zalloc_coherent\|devm_kmalloc\|devm_kzalloc\|
+ dma_alloc_coherent\|devm_kmalloc\|devm_kzalloc\|
kvmalloc\|kvzalloc\|kvmalloc_node\|kvzalloc_node\|pci_alloc_consistent\|
pci_zalloc_consistent\|kmem_alloc\|kmem_zalloc\|kmem_zone_alloc\|
kmem_zone_zalloc\|vmalloc_node\|vzalloc_node\)(...)
@@ -78,7 +79,7 @@
- (T *)
\(kmalloc\|kzalloc\|kcalloc\|kmem_cache_alloc\|kmem_cache_zalloc\|
kmem_cache_alloc_node\|kmalloc_node\|kzalloc_node\|vmalloc\|vzalloc\|
- dma_alloc_coherent\|dma_zalloc_coherent\|devm_kmalloc\|devm_kzalloc\|
+ dma_alloc_coherent\|devm_kmalloc\|devm_kzalloc\|
kvmalloc\|kvzalloc\|kvmalloc_node\|kvzalloc_node\|pci_alloc_consistent\|
pci_zalloc_consistent\|kmem_alloc\|kmem_zalloc\|kmem_zone_alloc\|
kmem_zone_zalloc\|vmalloc_node\|vzalloc_node\)(...)
@@ -95,7 +96,7 @@
(T@p *)
\(kmalloc\|kzalloc\|kcalloc\|kmem_cache_alloc\|kmem_cache_zalloc\|
kmem_cache_alloc_node\|kmalloc_node\|kzalloc_node\|vmalloc\|vzalloc\|
- dma_alloc_coherent\|dma_zalloc_coherent\|devm_kmalloc\|devm_kzalloc\|
+ dma_alloc_coherent\|devm_kmalloc\|devm_kzalloc\|
kvmalloc\|kvzalloc\|kvmalloc_node\|kvzalloc_node\|pci_alloc_consistent\|
pci_zalloc_consistent\|kmem_alloc\|kmem_zalloc\|kmem_zone_alloc\|
kmem_zone_zalloc\|vmalloc_node\|vzalloc_node\)(...)
diff --git a/scripts/coccinelle/api/alloc/pool_zalloc-simple.cocci b/scripts/coccinelle/api/alloc/pool_zalloc-simple.cocci
index 9b7eb32..9c61a23 100644
--- a/scripts/coccinelle/api/alloc/pool_zalloc-simple.cocci
+++ b/scripts/coccinelle/api/alloc/pool_zalloc-simple.cocci
@@ -1,7 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0-only
///
/// Use *_pool_zalloc rather than *_pool_alloc followed by memset with 0
///
-// Copyright: (C) 2015 Intel Corp. GPLv2.
+// Copyright: (C) 2015 Intel Corp.
// Options: --no-includes --include-headers
//
// Keywords: dma_pool_zalloc, pci_pool_zalloc
diff --git a/scripts/coccinelle/api/alloc/zalloc-simple.cocci b/scripts/coccinelle/api/alloc/zalloc-simple.cocci
index d819275..26cda3f 100644
--- a/scripts/coccinelle/api/alloc/zalloc-simple.cocci
+++ b/scripts/coccinelle/api/alloc/zalloc-simple.cocci
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0-only
///
/// Use zeroing allocator rather than allocator followed by memset with 0
///
@@ -6,9 +7,9 @@
/// matched code has to be contiguous
///
// Confidence: High
-// Copyright: (C) 2009-2010 Julia Lawall, Nicolas Palix, DIKU. GPLv2.
-// Copyright: (C) 2009-2010 Gilles Muller, INRIA/LiP6. GPLv2.
-// Copyright: (C) 2017 Himanshu Jha GPLv2.
+// Copyright: (C) 2009-2010 Julia Lawall, Nicolas Palix, DIKU.
+// Copyright: (C) 2009-2010 Gilles Muller, INRIA/LiP6.
+// Copyright: (C) 2017 Himanshu Jha
// URL: http://coccinelle.lip6.fr/rules/kzalloc.html
// Options: --no-includes --include-headers
//
@@ -69,15 +70,6 @@
- x = (T)vmalloc(E1);
+ x = (T)vzalloc(E1);
|
-- x = dma_alloc_coherent(E2,E1,E3,E4);
-+ x = dma_zalloc_coherent(E2,E1,E3,E4);
-|
-- x = (T *)dma_alloc_coherent(E2,E1,E3,E4);
-+ x = dma_zalloc_coherent(E2,E1,E3,E4);
-|
-- x = (T)dma_alloc_coherent(E2,E1,E3,E4);
-+ x = (T)dma_zalloc_coherent(E2,E1,E3,E4);
-|
- x = kmalloc_node(E1,E2,E3);
+ x = kzalloc_node(E1,E2,E3);
|
@@ -225,7 +217,7 @@
x << r2.x;
@@
-msg="WARNING: dma_zalloc_coherent should be used for %s, instead of dma_alloc_coherent/memset" % (x)
+msg="WARNING: dma_alloc_coherent use in %s already zeroes out memory, so memset is not needed" % (x)
coccilib.report.print_report(p[0], msg)
//-----------------------------------------------------------------
diff --git a/scripts/coccinelle/api/atomic_as_refcounter.cocci b/scripts/coccinelle/api/atomic_as_refcounter.cocci
index 988120e..0f78d94 100644
--- a/scripts/coccinelle/api/atomic_as_refcounter.cocci
+++ b/scripts/coccinelle/api/atomic_as_refcounter.cocci
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0-only
// Check if refcount_t type and API should be used
// instead of atomic_t type when dealing with refcounters
//
diff --git a/scripts/coccinelle/api/check_bq27xxx_data.cocci b/scripts/coccinelle/api/check_bq27xxx_data.cocci
index 9212b85..fae539e 100644
--- a/scripts/coccinelle/api/check_bq27xxx_data.cocci
+++ b/scripts/coccinelle/api/check_bq27xxx_data.cocci
@@ -1,10 +1,11 @@
+// SPDX-License-Identifier: GPL-2.0-only
/// Detect BQ27XXX_DATA structures with identical registers, dm registers or
/// properties.
//# Doesn't unfold macros used in register or property fields.
//# Requires OCaml scripting
///
// Confidence: High
-// Copyright: (C) 2017 Julia Lawall, Inria/LIP6, GPLv2.
+// Copyright: (C) 2017 Julia Lawall, Inria/LIP6,
// URL: http://coccinelle.lip6.fr/
// Requires: 1.0.7
// Keywords: BQ27XXX_DATA
diff --git a/scripts/coccinelle/api/drm-get-put.cocci b/scripts/coccinelle/api/drm-get-put.cocci
deleted file mode 100644
index 3a09c97..0000000
--- a/scripts/coccinelle/api/drm-get-put.cocci
+++ /dev/null
@@ -1,78 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-///
-/// Use drm_*_get() and drm_*_put() helpers instead of drm_*_reference() and
-/// drm_*_unreference() helpers.
-///
-// Confidence: High
-// Copyright: (C) 2017 NVIDIA Corporation
-// Options: --no-includes --include-headers
-//
-
-virtual patch
-virtual report
-
-@depends on patch@
-expression object;
-@@
-
-(
-- drm_connector_reference(object)
-+ drm_connector_get(object)
-|
-- drm_connector_unreference(object)
-+ drm_connector_put(object)
-|
-- drm_framebuffer_reference(object)
-+ drm_framebuffer_get(object)
-|
-- drm_framebuffer_unreference(object)
-+ drm_framebuffer_put(object)
-|
-- drm_gem_object_reference(object)
-+ drm_gem_object_get(object)
-|
-- drm_gem_object_unreference(object)
-+ drm_gem_object_put(object)
-|
-- __drm_gem_object_unreference(object)
-+ __drm_gem_object_put(object)
-|
-- drm_gem_object_unreference_unlocked(object)
-+ drm_gem_object_put_unlocked(object)
-|
-- drm_dev_unref(object)
-+ drm_dev_put(object)
-)
-
-@r depends on report@
-expression object;
-position p;
-@@
-
-(
-drm_connector_unreference@p(object)
-|
-drm_connector_reference@p(object)
-|
-drm_framebuffer_unreference@p(object)
-|
-drm_framebuffer_reference@p(object)
-|
-drm_gem_object_unreference@p(object)
-|
-drm_gem_object_reference@p(object)
-|
-__drm_gem_object_unreference(object)
-|
-drm_gem_object_unreference_unlocked(object)
-|
-drm_dev_unref@p(object)
-)
-
-@script:python depends on report@
-object << r.object;
-p << r.p;
-@@
-
-msg="WARNING: use get/put helpers to reference and dereference %s" % (object)
-coccilib.report.print_report(p[0], msg)
diff --git a/scripts/coccinelle/api/err_cast.cocci b/scripts/coccinelle/api/err_cast.cocci
index 2ce1150..0e661c8 100644
--- a/scripts/coccinelle/api/err_cast.cocci
+++ b/scripts/coccinelle/api/err_cast.cocci
@@ -1,10 +1,11 @@
+// SPDX-License-Identifier: GPL-2.0-only
///
/// Use ERR_CAST inlined function instead of ERR_PTR(PTR_ERR(...))
///
// Confidence: High
-// Copyright: (C) 2009, 2010 Nicolas Palix, DIKU. GPLv2.
-// Copyright: (C) 2009, 2010 Julia Lawall, DIKU. GPLv2.
-// Copyright: (C) 2009, 2010 Gilles Muller, INRIA/LiP6. GPLv2.
+// Copyright: (C) 2009, 2010 Nicolas Palix, DIKU.
+// Copyright: (C) 2009, 2010 Julia Lawall, DIKU.
+// Copyright: (C) 2009, 2010 Gilles Muller, INRIA/LiP6.
// URL: http://coccinelle.lip6.fr/
// Options:
//
diff --git a/scripts/coccinelle/api/kstrdup.cocci b/scripts/coccinelle/api/kstrdup.cocci
index 09cba54..19f2645 100644
--- a/scripts/coccinelle/api/kstrdup.cocci
+++ b/scripts/coccinelle/api/kstrdup.cocci
@@ -1,9 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0-only
/// Use kstrdup rather than duplicating its implementation
///
// Confidence: High
-// Copyright: (C) 2010-2012 Nicolas Palix. GPLv2.
-// Copyright: (C) 2010-2012 Julia Lawall, INRIA/LIP6. GPLv2.
-// Copyright: (C) 2010-2012 Gilles Muller, INRIA/LiP6. GPLv2.
+// Copyright: (C) 2010-2012 Nicolas Palix.
+// Copyright: (C) 2010-2012 Julia Lawall, INRIA/LIP6.
+// Copyright: (C) 2010-2012 Gilles Muller, INRIA/LiP6.
// URL: http://coccinelle.lip6.fr/
// Comments:
// Options: --no-includes --include-headers
@@ -76,7 +77,7 @@
p2 << r1.p2;
@@
-cocci.print_main("WARNING opportunity for kstrdep",p1)
+cocci.print_main("WARNING opportunity for kstrdup",p1)
cocci.print_secs("strcpy",p2)
@script:python depends on org@
@@ -84,7 +85,7 @@
p2 << r2.p2;
@@
-cocci.print_main("WARNING opportunity for kstrdep",p1)
+cocci.print_main("WARNING opportunity for kstrdup",p1)
cocci.print_secs("memcpy",p2)
@script:python depends on report@
@@ -92,7 +93,7 @@
p2 << r1.p2;
@@
-msg = "WARNING opportunity for kstrdep (strcpy on line %s)" % (p2[0].line)
+msg = "WARNING opportunity for kstrdup (strcpy on line %s)" % (p2[0].line)
coccilib.report.print_report(p1[0], msg)
@script:python depends on report@
@@ -100,5 +101,5 @@
p2 << r2.p2;
@@
-msg = "WARNING opportunity for kstrdep (memcpy on line %s)" % (p2[0].line)
+msg = "WARNING opportunity for kstrdup (memcpy on line %s)" % (p2[0].line)
coccilib.report.print_report(p1[0], msg)
diff --git a/scripts/coccinelle/api/memdup.cocci b/scripts/coccinelle/api/memdup.cocci
index 8fd6437..30b15df 100644
--- a/scripts/coccinelle/api/memdup.cocci
+++ b/scripts/coccinelle/api/memdup.cocci
@@ -1,9 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0-only
/// Use kmemdup rather than duplicating its implementation
///
// Confidence: High
-// Copyright: (C) 2010-2012 Nicolas Palix. GPLv2.
-// Copyright: (C) 2010-2012 Julia Lawall, INRIA/LIP6. GPLv2.
-// Copyright: (C) 2010-2012 Gilles Muller, INRIA/LiP6. GPLv2.
+// Copyright: (C) 2010-2012 Nicolas Palix.
+// Copyright: (C) 2010-2012 Julia Lawall, INRIA/LIP6.
+// Copyright: (C) 2010-2012 Gilles Muller, INRIA/LiP6.
// URL: http://coccinelle.lip6.fr/
// Comments:
// Options: --no-includes --include-headers
diff --git a/scripts/coccinelle/api/memdup_user.cocci b/scripts/coccinelle/api/memdup_user.cocci
index 2a5aea8..c809ab1 100644
--- a/scripts/coccinelle/api/memdup_user.cocci
+++ b/scripts/coccinelle/api/memdup_user.cocci
@@ -1,10 +1,11 @@
+// SPDX-License-Identifier: GPL-2.0-only
/// Use memdup_user rather than duplicating its implementation
/// This is a little bit restricted to reduce false positives
///
// Confidence: High
-// Copyright: (C) 2010-2012 Nicolas Palix. GPLv2.
-// Copyright: (C) 2010-2012 Julia Lawall, INRIA/LIP6. GPLv2.
-// Copyright: (C) 2010-2012 Gilles Muller, INRIA/LiP6. GPLv2.
+// Copyright: (C) 2010-2012 Nicolas Palix.
+// Copyright: (C) 2010-2012 Julia Lawall, INRIA/LIP6.
+// Copyright: (C) 2010-2012 Gilles Muller, INRIA/LiP6.
// URL: http://coccinelle.lip6.fr/
// Comments:
// Options: --no-includes --include-headers
diff --git a/scripts/coccinelle/api/platform_get_irq.cocci b/scripts/coccinelle/api/platform_get_irq.cocci
new file mode 100644
index 0000000..06b6a95
--- /dev/null
+++ b/scripts/coccinelle/api/platform_get_irq.cocci
@@ -0,0 +1,102 @@
+// SPDX-License-Identifier: GPL-2.0
+/// Remove dev_err() messages after platform_get_irq*() failures
+//
+// Confidence: Medium
+// Options: --include-headers
+
+virtual patch
+virtual context
+virtual org
+virtual report
+
+@depends on context@
+expression ret;
+struct platform_device *E;
+@@
+
+ret =
+(
+platform_get_irq
+|
+platform_get_irq_byname
+)(E, ...);
+
+if ( \( ret < 0 \| ret <= 0 \) )
+{
+(
+if (ret != -EPROBE_DEFER)
+{ ...
+*dev_err(...);
+... }
+|
+...
+*dev_err(...);
+)
+...
+}
+
+@depends on patch@
+expression ret;
+struct platform_device *E;
+@@
+
+ret =
+(
+platform_get_irq
+|
+platform_get_irq_byname
+)(E, ...);
+
+if ( \( ret < 0 \| ret <= 0 \) )
+{
+(
+-if (ret != -EPROBE_DEFER)
+-{ ...
+-dev_err(...);
+-... }
+|
+...
+-dev_err(...);
+)
+...
+}
+
+@r depends on org || report@
+position p1;
+expression ret;
+struct platform_device *E;
+@@
+
+ret =
+(
+platform_get_irq
+|
+platform_get_irq_byname
+)(E, ...);
+
+if ( \( ret < 0 \| ret <= 0 \) )
+{
+(
+if (ret != -EPROBE_DEFER)
+{ ...
+dev_err@p1(...);
+... }
+|
+...
+dev_err@p1(...);
+)
+...
+}
+
+@script:python depends on org@
+p1 << r.p1;
+@@
+
+cocci.print_main(p1)
+
+@script:python depends on report@
+p1 << r.p1;
+@@
+
+msg = "line %s is redundant because platform_get_irq() already prints an error" % (p1[0].line)
+coccilib.report.print_report(p1[0],msg)
diff --git a/scripts/coccinelle/api/platform_no_drv_owner.cocci b/scripts/coccinelle/api/platform_no_drv_owner.cocci
index c5e3f73..8fa050e 100644
--- a/scripts/coccinelle/api/platform_no_drv_owner.cocci
+++ b/scripts/coccinelle/api/platform_no_drv_owner.cocci
@@ -1,7 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0-only
/// Remove .owner field if calls are used which set it automatically
///
// Confidence: High
-// Copyright: (C) 2014 Wolfram Sang. GPL v2.
+// Copyright: (C) 2014 Wolfram Sang.
virtual patch
virtual context
diff --git a/scripts/coccinelle/api/pm_runtime.cocci b/scripts/coccinelle/api/pm_runtime.cocci
index d67ccf5..1ccce3f 100644
--- a/scripts/coccinelle/api/pm_runtime.cocci
+++ b/scripts/coccinelle/api/pm_runtime.cocci
@@ -1,8 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0-only
/// Make sure pm_runtime_* calls does not use unnecessary IS_ERR_VALUE
///
// Keywords: pm_runtime
// Confidence: Medium
-// Copyright (C) 2013 Texas Instruments Incorporated - GPLv2.
+// Copyright (C) 2013 Texas Instruments Incorporated -
// URL: http://coccinelle.lip6.fr/
// Options: --include-headers
diff --git a/scripts/coccinelle/api/ptr_ret.cocci b/scripts/coccinelle/api/ptr_ret.cocci
index dd58dab..e76cd5d 100644
--- a/scripts/coccinelle/api/ptr_ret.cocci
+++ b/scripts/coccinelle/api/ptr_ret.cocci
@@ -1,9 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0-only
///
/// Use PTR_ERR_OR_ZERO rather than if(IS_ERR(...)) + PTR_ERR
///
// Confidence: High
-// Copyright: (C) 2012 Julia Lawall, INRIA/LIP6. GPLv2.
-// Copyright: (C) 2012 Gilles Muller, INRIA/LiP6. GPLv2.
+// Copyright: (C) 2012 Julia Lawall, INRIA/LIP6.
+// Copyright: (C) 2012 Gilles Muller, INRIA/LiP6.
// URL: http://coccinelle.lip6.fr/
// Options: --no-includes --include-headers
//
diff --git a/scripts/coccinelle/api/resource_size.cocci b/scripts/coccinelle/api/resource_size.cocci
index 1935a58..a9a571a 100644
--- a/scripts/coccinelle/api/resource_size.cocci
+++ b/scripts/coccinelle/api/resource_size.cocci
@@ -1,11 +1,12 @@
+// SPDX-License-Identifier: GPL-2.0-only
///
/// Use resource_size function on resource object
/// instead of explicit computation.
///
// Confidence: High
-// Copyright: (C) 2009, 2010 Nicolas Palix, DIKU. GPLv2.
-// Copyright: (C) 2009, 2010 Julia Lawall, DIKU. GPLv2.
-// Copyright: (C) 2009, 2010 Gilles Muller, INRIA/LiP6. GPLv2.
+// Copyright: (C) 2009, 2010 Nicolas Palix, DIKU.
+// Copyright: (C) 2009, 2010 Julia Lawall, DIKU.
+// Copyright: (C) 2009, 2010 Gilles Muller, INRIA/LiP6.
// URL: http://coccinelle.lip6.fr/
// Options:
//
diff --git a/scripts/coccinelle/api/stream_open.cocci b/scripts/coccinelle/api/stream_open.cocci
new file mode 100644
index 0000000..df00d66
--- /dev/null
+++ b/scripts/coccinelle/api/stream_open.cocci
@@ -0,0 +1,370 @@
+// SPDX-License-Identifier: GPL-2.0
+// Author: Kirill Smelkov (kirr@nexedi.com)
+//
+// Search for stream-like files that are using nonseekable_open and convert
+// them to stream_open. A stream-like file is a file that does not use ppos in
+// its read and write. Rationale for the conversion is to avoid deadlock in
+// between read and write.
+
+virtual report
+virtual patch
+virtual explain // explain decisions in the patch (SPFLAGS="-D explain")
+
+// stream-like reader & writer - ones that do not depend on f_pos.
+@ stream_reader @
+identifier readstream, ppos;
+identifier f, buf, len;
+type loff_t;
+@@
+ ssize_t readstream(struct file *f, char *buf, size_t len, loff_t *ppos)
+ {
+ ... when != ppos
+ }
+
+@ stream_writer @
+identifier writestream, ppos;
+identifier f, buf, len;
+type loff_t;
+@@
+ ssize_t writestream(struct file *f, const char *buf, size_t len, loff_t *ppos)
+ {
+ ... when != ppos
+ }
+
+
+// a function that blocks
+@ blocks @
+identifier block_f;
+identifier wait =~ "^wait_.*";
+@@
+ block_f(...) {
+ ... when exists
+ wait(...)
+ ... when exists
+ }
+
+// stream_reader that can block inside.
+//
+// XXX wait_* can be called not directly from current function (e.g. func -> f -> g -> wait())
+// XXX currently reader_blocks supports only direct and 1-level indirect cases.
+@ reader_blocks_direct @
+identifier stream_reader.readstream;
+identifier wait =~ "^wait_.*";
+@@
+ readstream(...)
+ {
+ ... when exists
+ wait(...)
+ ... when exists
+ }
+
+@ reader_blocks_1 @
+identifier stream_reader.readstream;
+identifier blocks.block_f;
+@@
+ readstream(...)
+ {
+ ... when exists
+ block_f(...)
+ ... when exists
+ }
+
+@ reader_blocks depends on reader_blocks_direct || reader_blocks_1 @
+identifier stream_reader.readstream;
+@@
+ readstream(...) {
+ ...
+ }
+
+
+// file_operations + whether they have _any_ .read, .write, .llseek ... at all.
+//
+// XXX add support for file_operations xxx[N] = ... (sound/core/pcm_native.c)
+@ fops0 @
+identifier fops;
+@@
+ struct file_operations fops = {
+ ...
+ };
+
+@ has_read @
+identifier fops0.fops;
+identifier read_f;
+@@
+ struct file_operations fops = {
+ .read = read_f,
+ };
+
+@ has_read_iter @
+identifier fops0.fops;
+identifier read_iter_f;
+@@
+ struct file_operations fops = {
+ .read_iter = read_iter_f,
+ };
+
+@ has_write @
+identifier fops0.fops;
+identifier write_f;
+@@
+ struct file_operations fops = {
+ .write = write_f,
+ };
+
+@ has_write_iter @
+identifier fops0.fops;
+identifier write_iter_f;
+@@
+ struct file_operations fops = {
+ .write_iter = write_iter_f,
+ };
+
+@ has_llseek @
+identifier fops0.fops;
+identifier llseek_f;
+@@
+ struct file_operations fops = {
+ .llseek = llseek_f,
+ };
+
+@ has_no_llseek @
+identifier fops0.fops;
+@@
+ struct file_operations fops = {
+ .llseek = no_llseek,
+ };
+
+@ has_noop_llseek @
+identifier fops0.fops;
+@@
+ struct file_operations fops = {
+ .llseek = noop_llseek,
+ };
+
+@ has_mmap @
+identifier fops0.fops;
+identifier mmap_f;
+@@
+ struct file_operations fops = {
+ .mmap = mmap_f,
+ };
+
+@ has_copy_file_range @
+identifier fops0.fops;
+identifier copy_file_range_f;
+@@
+ struct file_operations fops = {
+ .copy_file_range = copy_file_range_f,
+ };
+
+@ has_remap_file_range @
+identifier fops0.fops;
+identifier remap_file_range_f;
+@@
+ struct file_operations fops = {
+ .remap_file_range = remap_file_range_f,
+ };
+
+@ has_splice_read @
+identifier fops0.fops;
+identifier splice_read_f;
+@@
+ struct file_operations fops = {
+ .splice_read = splice_read_f,
+ };
+
+@ has_splice_write @
+identifier fops0.fops;
+identifier splice_write_f;
+@@
+ struct file_operations fops = {
+ .splice_write = splice_write_f,
+ };
+
+
+// file_operations that is candidate for stream_open conversion - it does not
+// use mmap and other methods that assume @offset access to file.
+//
+// XXX for simplicity require no .{read/write}_iter and no .splice_{read/write} for now.
+// XXX maybe_steam.fops cannot be used in other rules - it gives "bad rule maybe_stream or bad variable fops".
+@ maybe_stream depends on (!has_llseek || has_no_llseek || has_noop_llseek) && !has_mmap && !has_copy_file_range && !has_remap_file_range && !has_read_iter && !has_write_iter && !has_splice_read && !has_splice_write @
+identifier fops0.fops;
+@@
+ struct file_operations fops = {
+ };
+
+
+// ---- conversions ----
+
+// XXX .open = nonseekable_open -> .open = stream_open
+// XXX .open = func -> openfunc -> nonseekable_open
+
+// read & write
+//
+// if both are used in the same file_operations together with an opener -
+// under that conditions we can use stream_open instead of nonseekable_open.
+@ fops_rw depends on maybe_stream @
+identifier fops0.fops, openfunc;
+identifier stream_reader.readstream;
+identifier stream_writer.writestream;
+@@
+ struct file_operations fops = {
+ .open = openfunc,
+ .read = readstream,
+ .write = writestream,
+ };
+
+@ report_rw depends on report @
+identifier fops_rw.openfunc;
+position p1;
+@@
+ openfunc(...) {
+ <...
+ nonseekable_open@p1
+ ...>
+ }
+
+@ script:python depends on report && reader_blocks @
+fops << fops0.fops;
+p << report_rw.p1;
+@@
+coccilib.report.print_report(p[0],
+ "ERROR: %s: .read() can deadlock .write(); change nonseekable_open -> stream_open to fix." % (fops,))
+
+@ script:python depends on report && !reader_blocks @
+fops << fops0.fops;
+p << report_rw.p1;
+@@
+coccilib.report.print_report(p[0],
+ "WARNING: %s: .read() and .write() have stream semantic; safe to change nonseekable_open -> stream_open." % (fops,))
+
+
+@ explain_rw_deadlocked depends on explain && reader_blocks @
+identifier fops_rw.openfunc;
+@@
+ openfunc(...) {
+ <...
+- nonseekable_open
++ nonseekable_open /* read & write (was deadlock) */
+ ...>
+ }
+
+
+@ explain_rw_nodeadlock depends on explain && !reader_blocks @
+identifier fops_rw.openfunc;
+@@
+ openfunc(...) {
+ <...
+- nonseekable_open
++ nonseekable_open /* read & write (no direct deadlock) */
+ ...>
+ }
+
+@ patch_rw depends on patch @
+identifier fops_rw.openfunc;
+@@
+ openfunc(...) {
+ <...
+- nonseekable_open
++ stream_open
+ ...>
+ }
+
+
+// read, but not write
+@ fops_r depends on maybe_stream && !has_write @
+identifier fops0.fops, openfunc;
+identifier stream_reader.readstream;
+@@
+ struct file_operations fops = {
+ .open = openfunc,
+ .read = readstream,
+ };
+
+@ report_r depends on report @
+identifier fops_r.openfunc;
+position p1;
+@@
+ openfunc(...) {
+ <...
+ nonseekable_open@p1
+ ...>
+ }
+
+@ script:python depends on report @
+fops << fops0.fops;
+p << report_r.p1;
+@@
+coccilib.report.print_report(p[0],
+ "WARNING: %s: .read() has stream semantic; safe to change nonseekable_open -> stream_open." % (fops,))
+
+@ explain_r depends on explain @
+identifier fops_r.openfunc;
+@@
+ openfunc(...) {
+ <...
+- nonseekable_open
++ nonseekable_open /* read only */
+ ...>
+ }
+
+@ patch_r depends on patch @
+identifier fops_r.openfunc;
+@@
+ openfunc(...) {
+ <...
+- nonseekable_open
++ stream_open
+ ...>
+ }
+
+
+// write, but not read
+@ fops_w depends on maybe_stream && !has_read @
+identifier fops0.fops, openfunc;
+identifier stream_writer.writestream;
+@@
+ struct file_operations fops = {
+ .open = openfunc,
+ .write = writestream,
+ };
+
+@ report_w depends on report @
+identifier fops_w.openfunc;
+position p1;
+@@
+ openfunc(...) {
+ <...
+ nonseekable_open@p1
+ ...>
+ }
+
+@ script:python depends on report @
+fops << fops0.fops;
+p << report_w.p1;
+@@
+coccilib.report.print_report(p[0],
+ "WARNING: %s: .write() has stream semantic; safe to change nonseekable_open -> stream_open." % (fops,))
+
+@ explain_w depends on explain @
+identifier fops_w.openfunc;
+@@
+ openfunc(...) {
+ <...
+- nonseekable_open
++ nonseekable_open /* write only */
+ ...>
+ }
+
+@ patch_w depends on patch @
+identifier fops_w.openfunc;
+@@
+ openfunc(...) {
+ <...
+- nonseekable_open
++ stream_open
+ ...>
+ }
+
+
+// no read, no write - don't change anything
diff --git a/scripts/coccinelle/free/clk_put.cocci b/scripts/coccinelle/free/clk_put.cocci
index 46747ad..7237b49 100644
--- a/scripts/coccinelle/free/clk_put.cocci
+++ b/scripts/coccinelle/free/clk_put.cocci
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0-only
/// Find missing clk_puts.
///
//# This only signals a missing clk_put when there is a clk_put later
@@ -5,8 +6,8 @@
//# False positives can be due to loops.
//
// Confidence: Moderate
-// Copyright: (C) 2012 Julia Lawall, INRIA/LIP6. GPLv2.
-// Copyright: (C) 2012 Gilles Muller, INRIA/LiP6. GPLv2.
+// Copyright: (C) 2012 Julia Lawall, INRIA/LIP6.
+// Copyright: (C) 2012 Gilles Muller, INRIA/LiP6.
// URL: http://coccinelle.lip6.fr/
// Comments:
// Options:
diff --git a/scripts/coccinelle/free/devm_free.cocci b/scripts/coccinelle/free/devm_free.cocci
index b2a2cf8..441799b 100644
--- a/scripts/coccinelle/free/devm_free.cocci
+++ b/scripts/coccinelle/free/devm_free.cocci
@@ -1,8 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0-only
/// Find uses of standard freeing functons on values allocated using devm_
/// functions. Values allocated using the devm_functions are freed when
/// the device is detached, and thus the use of the standard freeing
/// function would cause a double free.
-/// See Documentation/driver-model/devres.txt for more information.
+/// See Documentation/driver-api/driver-model/devres.rst for more information.
///
/// A difficulty of detecting this problem is that the standard freeing
/// function might be called from a different function than the one
@@ -14,8 +15,8 @@
/// less reliable in these cases.
///
// Confidence: Moderate
-// Copyright: (C) 2011 Julia Lawall, INRIA/LIP6. GPLv2.
-// Copyright: (C) 2011 Gilles Muller, INRIA/LiP6. GPLv2.
+// Copyright: (C) 2011 Julia Lawall, INRIA/LIP6.
+// Copyright: (C) 2011 Gilles Muller, INRIA/LiP6.
// URL: http://coccinelle.lip6.fr/
// Comments:
// Options: --no-includes --include-headers
diff --git a/scripts/coccinelle/free/ifnullfree.cocci b/scripts/coccinelle/free/ifnullfree.cocci
index a70e123..b3290c4 100644
--- a/scripts/coccinelle/free/ifnullfree.cocci
+++ b/scripts/coccinelle/free/ifnullfree.cocci
@@ -1,10 +1,11 @@
+// SPDX-License-Identifier: GPL-2.0-only
/// NULL check before some freeing functions is not needed.
///
/// Based on checkpatch warning
/// "kfree(NULL) is safe this check is probably not required"
/// and kfreeaddr.cocci by Julia Lawall.
///
-// Copyright: (C) 2014 Fabian Frederick. GPLv2.
+// Copyright: (C) 2014 Fabian Frederick.
// Comments: -
// Options: --no-includes --include-headers
diff --git a/scripts/coccinelle/free/iounmap.cocci b/scripts/coccinelle/free/iounmap.cocci
index 5384f4b..0e60e11 100644
--- a/scripts/coccinelle/free/iounmap.cocci
+++ b/scripts/coccinelle/free/iounmap.cocci
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0-only
/// Find missing iounmaps.
///
//# This only signals a missing iounmap when there is an iounmap later
@@ -5,8 +6,8 @@
//# False positives can be due to loops.
//
// Confidence: Moderate
-// Copyright: (C) 2012 Julia Lawall, INRIA/LIP6. GPLv2.
-// Copyright: (C) 2012 Gilles Muller, INRIA/LiP6. GPLv2.
+// Copyright: (C) 2012 Julia Lawall, INRIA/LIP6.
+// Copyright: (C) 2012 Gilles Muller, INRIA/LiP6.
// URL: http://coccinelle.lip6.fr/
// Comments:
// Options:
diff --git a/scripts/coccinelle/free/kfree.cocci b/scripts/coccinelle/free/kfree.cocci
index ac438da..e9d50e7 100644
--- a/scripts/coccinelle/free/kfree.cocci
+++ b/scripts/coccinelle/free/kfree.cocci
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0-only
/// Find a use after free.
//# Values of variables may imply that some
//# execution paths are not possible, resulting in false positives.
@@ -5,9 +6,9 @@
//# SCTP_DBG_OBJCNT_DEC that do not actually evaluate their argument
///
// Confidence: Moderate
-// Copyright: (C) 2010-2012 Nicolas Palix. GPLv2.
-// Copyright: (C) 2010-2012 Julia Lawall, INRIA/LIP6. GPLv2.
-// Copyright: (C) 2010-2012 Gilles Muller, INRIA/LiP6. GPLv2.
+// Copyright: (C) 2010-2012 Nicolas Palix.
+// Copyright: (C) 2010-2012 Julia Lawall, INRIA/LIP6.
+// Copyright: (C) 2010-2012 Gilles Muller, INRIA/LiP6.
// URL: http://coccinelle.lip6.fr/
// Comments:
// Options: --no-includes --include-headers
diff --git a/scripts/coccinelle/free/kfreeaddr.cocci b/scripts/coccinelle/free/kfreeaddr.cocci
index d46063b..cfaf308 100644
--- a/scripts/coccinelle/free/kfreeaddr.cocci
+++ b/scripts/coccinelle/free/kfreeaddr.cocci
@@ -1,7 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0-only
/// Free of a structure field
///
// Confidence: High
-// Copyright: (C) 2013 Julia Lawall, INRIA/LIP6. GPLv2.
+// Copyright: (C) 2013 Julia Lawall, INRIA/LIP6.
// URL: http://coccinelle.lip6.fr/
// Comments:
// Options: --no-includes --include-headers
diff --git a/scripts/coccinelle/free/pci_free_consistent.cocci b/scripts/coccinelle/free/pci_free_consistent.cocci
index 43600cc..d51e925 100644
--- a/scripts/coccinelle/free/pci_free_consistent.cocci
+++ b/scripts/coccinelle/free/pci_free_consistent.cocci
@@ -1,7 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0-only
/// Find missing pci_free_consistent for every pci_alloc_consistent.
///
// Confidence: Moderate
-// Copyright: (C) 2013 Petr Strnad. GPLv2.
+// Copyright: (C) 2013 Petr Strnad.
// URL: http://coccinelle.lip6.fr/
// Keywords: pci_free_consistent, pci_alloc_consistent
// Options: --no-includes --include-headers
diff --git a/scripts/coccinelle/free/put_device.cocci b/scripts/coccinelle/free/put_device.cocci
new file mode 100644
index 0000000..1209213
--- /dev/null
+++ b/scripts/coccinelle/free/put_device.cocci
@@ -0,0 +1,56 @@
+// SPDX-License-Identifier: GPL-2.0
+/// Find missing put_device for every of_find_device_by_node.
+///
+// Confidence: Moderate
+// Copyright: (C) 2018-2019 Wen Yang, ZTE.
+// Comments:
+// Options: --no-includes --include-headers
+
+virtual report
+virtual org
+
+@search exists@
+local idexpression id;
+expression x,e,e1;
+position p1,p2;
+type T,T1,T2,T3;
+@@
+
+id = of_find_device_by_node@p1(x)
+... when != e = id
+if (id == NULL || ...) { ... return ...; }
+... when != put_device(&id->dev)
+ when != platform_device_put(id)
+ when != of_dev_put(id)
+ when != if (id) { ... put_device(&id->dev) ... }
+ when != e1 = (T)id
+ when != e1 = (T)(&id->dev)
+ when != e1 = get_device(&id->dev)
+ when != e1 = (T1)platform_get_drvdata(id)
+(
+ return
+( id
+| (T2)dev_get_drvdata(&id->dev)
+| (T3)platform_get_drvdata(id)
+| &id->dev
+);
+| return@p2 ...;
+)
+
+@script:python depends on report@
+p1 << search.p1;
+p2 << search.p2;
+@@
+
+coccilib.report.print_report(p2[0],
+ "ERROR: missing put_device; call of_find_device_by_node on line "
+ + p1[0].line
+ + ", but without a corresponding object release within this function.")
+
+@script:python depends on org@
+p1 << search.p1;
+p2 << search.p2;
+@@
+
+cocci.print_main("of_find_device_by_node", p1)
+cocci.print_secs("needed put_device", p2)
diff --git a/scripts/coccinelle/iterators/device_node_continue.cocci b/scripts/coccinelle/iterators/device_node_continue.cocci
index a36c16d..f8cd14d 100644
--- a/scripts/coccinelle/iterators/device_node_continue.cocci
+++ b/scripts/coccinelle/iterators/device_node_continue.cocci
@@ -1,8 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0-only
/// Device node iterators put the previous value of the index variable, so an
/// explicit put causes a double put.
///
// Confidence: High
-// Copyright: (C) 2015 Julia Lawall, Inria. GPLv2.
+// Copyright: (C) 2015 Julia Lawall, Inria.
// URL: http://coccinelle.lip6.fr/
// Options: --no-includes --include-headers
// Requires: 1.0.4
diff --git a/scripts/coccinelle/iterators/fen.cocci b/scripts/coccinelle/iterators/fen.cocci
index 48c152f..b69f966 100644
--- a/scripts/coccinelle/iterators/fen.cocci
+++ b/scripts/coccinelle/iterators/fen.cocci
@@ -1,10 +1,11 @@
+// SPDX-License-Identifier: GPL-2.0-only
/// These iterators only exit normally when the loop cursor is NULL, so there
/// is no point to call of_node_put on the final value.
///
// Confidence: High
-// Copyright: (C) 2010-2012 Nicolas Palix. GPLv2.
-// Copyright: (C) 2010-2012 Julia Lawall, INRIA/LIP6. GPLv2.
-// Copyright: (C) 2010-2012 Gilles Muller, INRIA/LiP6. GPLv2.
+// Copyright: (C) 2010-2012 Nicolas Palix.
+// Copyright: (C) 2010-2012 Julia Lawall, INRIA/LIP6.
+// Copyright: (C) 2010-2012 Gilles Muller, INRIA/LiP6.
// URL: http://coccinelle.lip6.fr/
// Comments:
// Options: --no-includes --include-headers
diff --git a/scripts/coccinelle/iterators/itnull.cocci b/scripts/coccinelle/iterators/itnull.cocci
index f58732b..9b362b9 100644
--- a/scripts/coccinelle/iterators/itnull.cocci
+++ b/scripts/coccinelle/iterators/itnull.cocci
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0-only
/// Many iterators have the property that the first argument is always bound
/// to a real list element, never NULL.
//# False positives arise for some iterators that do not have this property,
@@ -6,9 +7,9 @@
//# or return).
///
// Confidence: Moderate
-// Copyright: (C) 2010-2012 Nicolas Palix. GPLv2.
-// Copyright: (C) 2010-2012 Julia Lawall, INRIA/LIP6. GPLv2.
-// Copyright: (C) 2010-2012 Gilles Muller, INRIA/LiP6. GPLv2.
+// Copyright: (C) 2010-2012 Nicolas Palix.
+// Copyright: (C) 2010-2012 Julia Lawall, INRIA/LIP6.
+// Copyright: (C) 2010-2012 Gilles Muller, INRIA/LiP6.
// URL: http://coccinelle.lip6.fr/
// Comments:
// Options: --no-includes --include-headers
diff --git a/scripts/coccinelle/iterators/list_entry_update.cocci b/scripts/coccinelle/iterators/list_entry_update.cocci
index be6f9f1..d62e8a1 100644
--- a/scripts/coccinelle/iterators/list_entry_update.cocci
+++ b/scripts/coccinelle/iterators/list_entry_update.cocci
@@ -1,12 +1,13 @@
+// SPDX-License-Identifier: GPL-2.0-only
/// list_for_each_entry uses its first argument to get from one element of
/// the list to the next, so it is usually not a good idea to reassign it.
/// The first rule finds such a reassignment and the second rule checks
/// that there is a path from the reassignment back to the top of the loop.
///
// Confidence: High
-// Copyright: (C) 2010 Nicolas Palix, DIKU. GPLv2.
-// Copyright: (C) 2010 Julia Lawall, DIKU. GPLv2.
-// Copyright: (C) 2010 Gilles Muller, INRIA/LiP6. GPLv2.
+// Copyright: (C) 2010 Nicolas Palix, DIKU.
+// Copyright: (C) 2010 Julia Lawall, DIKU.
+// Copyright: (C) 2010 Gilles Muller, INRIA/LiP6.
// URL: http://coccinelle.lip6.fr/
// Comments:
// Options: --no-includes --include-headers
diff --git a/scripts/coccinelle/iterators/use_after_iter.cocci b/scripts/coccinelle/iterators/use_after_iter.cocci
index ce8cc9c..9be48b5 100644
--- a/scripts/coccinelle/iterators/use_after_iter.cocci
+++ b/scripts/coccinelle/iterators/use_after_iter.cocci
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0-only
/// If list_for_each_entry, etc complete a traversal of the list, the iterator
/// variable ends up pointing to an address at an offset from the list head,
/// and not a meaningful structure. Thus this value should not be used after
@@ -7,8 +8,8 @@
//#may also cause a report to be a false positive.
///
// Confidence: Moderate
-// Copyright: (C) 2012 Julia Lawall, INRIA/LIP6. GPLv2.
-// Copyright: (C) 2012 Gilles Muller, INRIA/LIP6. GPLv2.
+// Copyright: (C) 2012 Julia Lawall, INRIA/LIP6.
+// Copyright: (C) 2012 Gilles Muller, INRIA/LIP6.
// URL: http://coccinelle.lip6.fr/
// Comments:
// Options: --no-includes --include-headers
@@ -35,6 +36,7 @@
iterator name hlist_for_each_entry_safe;
statement S;
position p1,p2;
+type T;
@@
(
@@ -125,6 +127,8 @@
|
&c->member
|
+T c;
+|
c = E
|
*c@p2
diff --git a/scripts/coccinelle/locks/call_kern.cocci b/scripts/coccinelle/locks/call_kern.cocci
index 669b244..5ca0d81b 100644
--- a/scripts/coccinelle/locks/call_kern.cocci
+++ b/scripts/coccinelle/locks/call_kern.cocci
@@ -1,12 +1,13 @@
+// SPDX-License-Identifier: GPL-2.0-only
/// Find functions that refer to GFP_KERNEL but are called with locks held.
//# The proposed change of converting the GFP_KERNEL is not necessarily the
//# correct one. It may be desired to unlock the lock, or to not call the
//# function under the lock in the first place.
///
// Confidence: Moderate
-// Copyright: (C) 2012 Nicolas Palix. GPLv2.
-// Copyright: (C) 2012 Julia Lawall, INRIA/LIP6. GPLv2.
-// Copyright: (C) 2012 Gilles Muller, INRIA/LiP6. GPLv2.
+// Copyright: (C) 2012 Nicolas Palix.
+// Copyright: (C) 2012 Julia Lawall, INRIA/LIP6.
+// Copyright: (C) 2012 Gilles Muller, INRIA/LiP6.
// URL: http://coccinelle.lip6.fr/
// Comments:
// Options: --no-includes --include-headers
diff --git a/scripts/coccinelle/locks/double_lock.cocci b/scripts/coccinelle/locks/double_lock.cocci
index 002752f..9e88a57 100644
--- a/scripts/coccinelle/locks/double_lock.cocci
+++ b/scripts/coccinelle/locks/double_lock.cocci
@@ -1,11 +1,12 @@
+// SPDX-License-Identifier: GPL-2.0-only
/// Find double locks. False positives may occur when some paths cannot
/// occur at execution, due to the values of variables, and when there is
/// an intervening function call that releases the lock.
///
// Confidence: Moderate
-// Copyright: (C) 2010 Nicolas Palix, DIKU. GPLv2.
-// Copyright: (C) 2010 Julia Lawall, DIKU. GPLv2.
-// Copyright: (C) 2010 Gilles Muller, INRIA/LiP6. GPLv2.
+// Copyright: (C) 2010 Nicolas Palix, DIKU.
+// Copyright: (C) 2010 Julia Lawall, DIKU.
+// Copyright: (C) 2010 Gilles Muller, INRIA/LiP6.
// URL: http://coccinelle.lip6.fr/
// Comments:
// Options: --no-includes --include-headers
diff --git a/scripts/coccinelle/locks/flags.cocci b/scripts/coccinelle/locks/flags.cocci
index debd70e..7f990cd 100644
--- a/scripts/coccinelle/locks/flags.cocci
+++ b/scripts/coccinelle/locks/flags.cocci
@@ -1,9 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0-only
/// Find nested lock+irqsave functions that use the same flags variables
///
// Confidence: High
-// Copyright: (C) 2010-2012 Nicolas Palix. GPLv2.
-// Copyright: (C) 2010-2012 Julia Lawall, INRIA/LIP6. GPLv2.
-// Copyright: (C) 2010-2012 Gilles Muller, INRIA/LiP6. GPLv2.
+// Copyright: (C) 2010-2012 Nicolas Palix.
+// Copyright: (C) 2010-2012 Julia Lawall, INRIA/LIP6.
+// Copyright: (C) 2010-2012 Gilles Muller, INRIA/LiP6.
// URL: http://coccinelle.lip6.fr/
// Comments:
// Options: --no-includes --include-headers
diff --git a/scripts/coccinelle/locks/mini_lock.cocci b/scripts/coccinelle/locks/mini_lock.cocci
index 19c6ee5..c3ad098 100644
--- a/scripts/coccinelle/locks/mini_lock.cocci
+++ b/scripts/coccinelle/locks/mini_lock.cocci
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0-only
/// Find missing unlocks. This semantic match considers the specific case
/// where the unlock is missing from an if branch, and there is a lock
/// before the if and an unlock after the if. False positives are due to
@@ -6,9 +7,9 @@
/// function call that releases the lock.
///
// Confidence: Moderate
-// Copyright: (C) 2010-2012 Nicolas Palix. GPLv2.
-// Copyright: (C) 2010-2012 Julia Lawall, INRIA/LIP6. GPLv2.
-// Copyright: (C) 2010-2012 Gilles Muller, INRIA/LiP6. GPLv2.
+// Copyright: (C) 2010-2012 Nicolas Palix.
+// Copyright: (C) 2010-2012 Julia Lawall, INRIA/LIP6.
+// Copyright: (C) 2010-2012 Gilles Muller, INRIA/LiP6.
// URL: http://coccinelle.lip6.fr/
// Comments:
// Options: --no-includes --include-headers
diff --git a/scripts/coccinelle/misc/add_namespace.cocci b/scripts/coccinelle/misc/add_namespace.cocci
new file mode 100644
index 0000000..99e93a6
--- /dev/null
+++ b/scripts/coccinelle/misc/add_namespace.cocci
@@ -0,0 +1,25 @@
+// SPDX-License-Identifier: GPL-2.0-only
+//
+/// Adds missing MODULE_IMPORT_NS statements to source files
+///
+/// This script is usually called from scripts/nsdeps with -D ns=<namespace> to
+/// add a missing namespace tag to a module source file.
+///
+
+virtual report
+
+@has_ns_import@
+declarer name MODULE_IMPORT_NS;
+identifier virtual.ns;
+@@
+MODULE_IMPORT_NS(ns);
+
+// Add missing imports, but only adjacent to a MODULE_LICENSE statement.
+// That ensures we are adding it only to the main module source file.
+@do_import depends on !has_ns_import@
+declarer name MODULE_LICENSE;
+expression license;
+identifier virtual.ns;
+@@
+MODULE_LICENSE(license);
++ MODULE_IMPORT_NS(ns);
diff --git a/scripts/coccinelle/misc/array_size.cocci b/scripts/coccinelle/misc/array_size.cocci
index 09520f0..4d25187 100644
--- a/scripts/coccinelle/misc/array_size.cocci
+++ b/scripts/coccinelle/misc/array_size.cocci
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0-only
/// Use ARRAY_SIZE instead of dividing sizeof array with sizeof an element
///
//# This makes an effort to find cases where ARRAY_SIZE can be used such as
@@ -6,7 +7,7 @@
//# division of the two sizeofs by ARRAY_SIZE.
//
// Confidence: High
-// Copyright: (C) 2014 Himangi Saraogi. GPLv2.
+// Copyright: (C) 2014 Himangi Saraogi.
// Comments:
// Options: --no-includes --include-headers
diff --git a/scripts/coccinelle/misc/badty.cocci b/scripts/coccinelle/misc/badty.cocci
index 481cf30..ed3e0b8 100644
--- a/scripts/coccinelle/misc/badty.cocci
+++ b/scripts/coccinelle/misc/badty.cocci
@@ -1,4 +1,5 @@
-/// Use ARRAY_SIZE instead of dividing sizeof array with sizeof an element
+// SPDX-License-Identifier: GPL-2.0-only
+/// Correct the size argument to alloc functions
///
//# This makes an effort to find cases where the argument to sizeof is wrong
//# in memory allocation functions by checking the type of the allocated memory
@@ -8,7 +9,7 @@
//# may need some reformatting.
//
// Confidence: Moderate
-// Copyright: (C) 2014 Himangi Saraogi. GPLv2.
+// Copyright: (C) 2014 Himangi Saraogi.
// Comments:
// Options:
diff --git a/scripts/coccinelle/misc/boolconv.cocci b/scripts/coccinelle/misc/boolconv.cocci
index 33c464d..392994e 100644
--- a/scripts/coccinelle/misc/boolconv.cocci
+++ b/scripts/coccinelle/misc/boolconv.cocci
@@ -1,9 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0-only
/// Remove unneeded conversion to bool
///
//# Relational and logical operators evaluate to bool,
//# explicit conversion is overly verbose and unneeded.
//
-// Copyright: (C) 2016 Andrew F. Davis <afd@ti.com> GPLv2.
+// Copyright: (C) 2016 Andrew F. Davis <afd@ti.com>
virtual patch
virtual context
diff --git a/scripts/coccinelle/misc/boolinit.cocci b/scripts/coccinelle/misc/boolinit.cocci
index b9abed4..fed6126 100644
--- a/scripts/coccinelle/misc/boolinit.cocci
+++ b/scripts/coccinelle/misc/boolinit.cocci
@@ -1,10 +1,11 @@
+// SPDX-License-Identifier: GPL-2.0-only
/// Bool initializations should use true and false. Bool tests don't need
/// comparisons. Based on contributions from Joe Perches, Rusty Russell
/// and Bruce W Allan.
///
// Confidence: High
-// Copyright: (C) 2012 Julia Lawall, INRIA/LIP6. GPLv2.
-// Copyright: (C) 2012 Gilles Muller, INRIA/LiP6. GPLv2.
+// Copyright: (C) 2012 Julia Lawall, INRIA/LIP6.
+// Copyright: (C) 2012 Gilles Muller, INRIA/LiP6.
// URL: http://coccinelle.lip6.fr/
// Options: --include-headers
@@ -13,10 +14,17 @@
virtual org
virtual report
+@boolok@
+symbol true,false;
+@@
+(
+true
+|
+false
+)
+
@depends on patch@
bool t;
-symbol true;
-symbol false;
@@
(
@@ -63,7 +71,7 @@
+ t
)
-@depends on patch@
+@depends on patch && boolok@
bool b;
@@
(
@@ -116,15 +124,24 @@
* t@p != 0
)
-@r3 depends on !patch@
+@r3 depends on !patch && boolok@
bool b;
-position p1,p2;
-constant c;
+position p1;
@@
(
*b@p1 = 0
|
*b@p1 = 1
+)
+
+@r4 depends on !patch@
+bool b;
+position p2;
+identifier i;
+constant c != {0,1};
+@@
+(
+ b = i
|
*b@p2 = c
)
@@ -139,19 +156,19 @@
p << r2.p;
@@
-cocci.print_main("WARNING: Comparison of bool to 0/1",p)
+cocci.print_main("WARNING: Comparison of 0/1 to bool variable",p)
@script:python depends on org@
p1 << r3.p1;
@@
-cocci.print_main("WARNING: Assignment of bool to 0/1",p1)
+cocci.print_main("WARNING: Assignment of 0/1 to bool variable",p1)
@script:python depends on org@
-p2 << r3.p2;
+p2 << r4.p2;
@@
-cocci.print_main("ERROR: Assignment of bool to non-0/1 constant",p2)
+cocci.print_main("ERROR: Assignment of non-0/1 constant to bool variable",p2)
@script:python depends on report@
p << r1.p;
@@ -163,16 +180,16 @@
p << r2.p;
@@
-coccilib.report.print_report(p[0],"WARNING: Comparison of bool to 0/1")
+coccilib.report.print_report(p[0],"WARNING: Comparison of 0/1 to bool variable")
@script:python depends on report@
p1 << r3.p1;
@@
-coccilib.report.print_report(p1[0],"WARNING: Assignment of bool to 0/1")
+coccilib.report.print_report(p1[0],"WARNING: Assignment of 0/1 to bool variable")
@script:python depends on report@
-p2 << r3.p2;
+p2 << r4.p2;
@@
-coccilib.report.print_report(p2[0],"ERROR: Assignment of bool to non-0/1 constant")
+coccilib.report.print_report(p2[0],"ERROR: Assignment of non-0/1 constant to bool variable")
diff --git a/scripts/coccinelle/misc/bugon.cocci b/scripts/coccinelle/misc/bugon.cocci
index 7415860..8d595c3 100644
--- a/scripts/coccinelle/misc/bugon.cocci
+++ b/scripts/coccinelle/misc/bugon.cocci
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0-only
/// Use BUG_ON instead of a if condition followed by BUG.
///
//# This makes an effort to find cases where BUG() follows an if
@@ -6,7 +7,7 @@
//# as argument.
//
// Confidence: High
-// Copyright: (C) 2014 Himangi Saraogi. GPLv2.
+// Copyright: (C) 2014 Himangi Saraogi.
// Comments:
// Options: --no-includes --include-headers
diff --git a/scripts/coccinelle/misc/cond_no_effect.cocci b/scripts/coccinelle/misc/cond_no_effect.cocci
index 8467dbd..91d16a8 100644
--- a/scripts/coccinelle/misc/cond_no_effect.cocci
+++ b/scripts/coccinelle/misc/cond_no_effect.cocci
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0-only
///Find conditions where if and else branch are functionally
// identical.
//
@@ -37,7 +38,7 @@
// All other cases look like bugs or at least lack of documentation
//
// Confidence: Moderate
-// Copyright: (C) 2016 Nicholas Mc Guire, OSADL. GPLv2.
+// Copyright: (C) 2016 Nicholas Mc Guire, OSADL.
// Comments:
// Options: --no-includes --include-headers
diff --git a/scripts/coccinelle/misc/cstptr.cocci b/scripts/coccinelle/misc/cstptr.cocci
index f0368b3..c52e3c8 100644
--- a/scripts/coccinelle/misc/cstptr.cocci
+++ b/scripts/coccinelle/misc/cstptr.cocci
@@ -1,9 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0-only
/// PTR_ERR should be applied before its argument is reassigned, typically
/// to NULL
///
// Confidence: High
-// Copyright: (C) 2012 Julia Lawall, INRIA/LIP6. GPLv2.
-// Copyright: (C) 2012 Gilles Muller, INRIA/LiP6. GPLv2.
+// Copyright: (C) 2012 Julia Lawall, INRIA/LIP6.
+// Copyright: (C) 2012 Gilles Muller, INRIA/LiP6.
// URL: http://coccinelle.lip6.fr/
// Comments:
// Options: --no-includes --include-headers
diff --git a/scripts/coccinelle/misc/doubleinit.cocci b/scripts/coccinelle/misc/doubleinit.cocci
index c0c3371..2f80d3a 100644
--- a/scripts/coccinelle/misc/doubleinit.cocci
+++ b/scripts/coccinelle/misc/doubleinit.cocci
@@ -1,11 +1,12 @@
+// SPDX-License-Identifier: GPL-2.0-only
/// Find duplicate field initializations. This has a high rate of false
/// positives due to #ifdefs, which Coccinelle is not aware of in a structure
/// initialization.
///
// Confidence: Low
-// Copyright: (C) 2010-2012 Nicolas Palix. GPLv2.
-// Copyright: (C) 2010-2012 Julia Lawall, INRIA/LIP6. GPLv2.
-// Copyright: (C) 2010-2012 Gilles Muller, INRIA/LiP6. GPLv2.
+// Copyright: (C) 2010-2012 Nicolas Palix.
+// Copyright: (C) 2010-2012 Julia Lawall, INRIA/LIP6.
+// Copyright: (C) 2010-2012 Gilles Muller, INRIA/LiP6.
// URL: http://coccinelle.lip6.fr/
// Comments: requires at least Coccinelle 0.2.4, lex or parse error otherwise
// Options: --no-includes --include-headers
diff --git a/scripts/coccinelle/misc/ifaddr.cocci b/scripts/coccinelle/misc/ifaddr.cocci
index c2663c6..fc92e8f 100644
--- a/scripts/coccinelle/misc/ifaddr.cocci
+++ b/scripts/coccinelle/misc/ifaddr.cocci
@@ -1,8 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0-only
/// The address of a variable or field is likely always to be non-zero.
///
// Confidence: High
-// Copyright: (C) 2012 Julia Lawall, INRIA/LIP6. GPLv2.
-// Copyright: (C) 2012 Gilles Muller, INRIA/LiP6. GPLv2.
+// Copyright: (C) 2012 Julia Lawall, INRIA/LIP6.
+// Copyright: (C) 2012 Gilles Muller, INRIA/LiP6.
// URL: http://coccinelle.lip6.fr/
// Comments:
// Options: --no-includes --include-headers
diff --git a/scripts/coccinelle/misc/ifcol.cocci b/scripts/coccinelle/misc/ifcol.cocci
index ffe7540..da0351e 100644
--- a/scripts/coccinelle/misc/ifcol.cocci
+++ b/scripts/coccinelle/misc/ifcol.cocci
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0-only
/// Find confusingly indented code in or after an if. An if branch should
/// be indented. The code following an if should not be indented.
/// Sometimes, code after an if that is indented is actually intended to be
@@ -8,9 +9,9 @@
//# is not visually aligned may be considered to be in the same column.
//
// Confidence: Low
-// Copyright: (C) 2010 Nicolas Palix, DIKU. GPLv2.
-// Copyright: (C) 2010 Julia Lawall, DIKU. GPLv2.
-// Copyright: (C) 2010 Gilles Muller, INRIA/LiP6. GPLv2.
+// Copyright: (C) 2010 Nicolas Palix, DIKU.
+// Copyright: (C) 2010 Julia Lawall, DIKU.
+// Copyright: (C) 2010 Gilles Muller, INRIA/LiP6.
// URL: http://coccinelle.lip6.fr/
// Comments:
// Options: --no-includes --include-headers
diff --git a/scripts/coccinelle/misc/noderef.cocci b/scripts/coccinelle/misc/noderef.cocci
index 007f0de..72de62a 100644
--- a/scripts/coccinelle/misc/noderef.cocci
+++ b/scripts/coccinelle/misc/noderef.cocci
@@ -1,9 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0-only
/// sizeof when applied to a pointer typed expression gives the size of
/// the pointer
///
// Confidence: High
-// Copyright: (C) 2012 Julia Lawall, INRIA/LIP6. GPLv2.
-// Copyright: (C) 2012 Gilles Muller, INRIA/LiP6. GPLv2.
+// Copyright: (C) 2012 Julia Lawall, INRIA/LIP6.
+// Copyright: (C) 2012 Gilles Muller, INRIA/LiP6.
// URL: http://coccinelle.lip6.fr/
// Comments:
// Options: --no-includes --include-headers
diff --git a/scripts/coccinelle/misc/orplus.cocci b/scripts/coccinelle/misc/orplus.cocci
index 08de5be..52203dc 100644
--- a/scripts/coccinelle/misc/orplus.cocci
+++ b/scripts/coccinelle/misc/orplus.cocci
@@ -1,10 +1,11 @@
+// SPDX-License-Identifier: GPL-2.0-only
/// Check for constants that are added but are used elsewhere as bitmasks
/// The results should be checked manually to ensure that the nonzero
/// bits in the two constants are actually disjoint.
///
// Confidence: Moderate
-// Copyright: (C) 2013 Julia Lawall, INRIA/LIP6. GPLv2.
-// Copyright: (C) 2013 Gilles Muller, INRIA/LIP6. GPLv2.
+// Copyright: (C) 2013 Julia Lawall, INRIA/LIP6.
+// Copyright: (C) 2013 Gilles Muller, INRIA/LIP6.
// URL: http://coccinelle.lip6.fr/
// Comments:
// Options: --no-includes --include-headers
diff --git a/scripts/coccinelle/misc/returnvar.cocci b/scripts/coccinelle/misc/returnvar.cocci
index d8286ef..ce0d9ee 100644
--- a/scripts/coccinelle/misc/returnvar.cocci
+++ b/scripts/coccinelle/misc/returnvar.cocci
@@ -1,8 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0-only
///
/// Remove unneeded variable used to store return value.
///
// Confidence: Moderate
-// Copyright: (C) 2012 Peter Senna Tschudin, INRIA/LIP6. GPLv2.
+// Copyright: (C) 2012 Peter Senna Tschudin, INRIA/LIP6.
// URL: http://coccinelle.lip6.fr/
// Comments: Comments on code can be deleted if near code that is removed.
// "when strict" can be removed to get more hits, but adds false
diff --git a/scripts/coccinelle/misc/semicolon.cocci b/scripts/coccinelle/misc/semicolon.cocci
index 6740c65..a53edb0 100644
--- a/scripts/coccinelle/misc/semicolon.cocci
+++ b/scripts/coccinelle/misc/semicolon.cocci
@@ -1,8 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0-only
///
/// Remove unneeded semicolon.
///
// Confidence: Moderate
-// Copyright: (C) 2012 Peter Senna Tschudin, INRIA/LIP6. GPLv2.
+// Copyright: (C) 2012 Peter Senna Tschudin, INRIA/LIP6.
// URL: http://coccinelle.lip6.fr/
// Comments: Some false positives on empty default cases in switch statements.
// Options: --no-includes --include-headers
diff --git a/scripts/coccinelle/misc/warn.cocci b/scripts/coccinelle/misc/warn.cocci
index d2e5b6c..e379661 100644
--- a/scripts/coccinelle/misc/warn.cocci
+++ b/scripts/coccinelle/misc/warn.cocci
@@ -1,8 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0-only
/// Use WARN(1,...) rather than printk followed by WARN_ON(1)
///
// Confidence: High
-// Copyright: (C) 2012 Julia Lawall, INRIA/LIP6. GPLv2.
-// Copyright: (C) 2012 Gilles Muller, INRIA/LiP6. GPLv2.
+// Copyright: (C) 2012 Julia Lawall, INRIA/LIP6.
+// Copyright: (C) 2012 Gilles Muller, INRIA/LiP6.
// URL: http://coccinelle.lip6.fr/
// Comments:
// Options: --no-includes --include-headers
diff --git a/scripts/coccinelle/null/badzero.cocci b/scripts/coccinelle/null/badzero.cocci
index f597c80..882dd65 100644
--- a/scripts/coccinelle/null/badzero.cocci
+++ b/scripts/coccinelle/null/badzero.cocci
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0-only
/// Compare pointer-typed values to NULL rather than 0
///
//# This makes an effort to choose between !x and x == NULL. !x is used
@@ -7,8 +8,8 @@
//# include path.
//
// Confidence: High
-// Copyright: (C) 2012 Julia Lawall, INRIA/LIP6. GPLv2.
-// Copyright: (C) 2012 Gilles Muller, INRIA/LiP6. GPLv2.
+// Copyright: (C) 2012 Julia Lawall, INRIA/LIP6.
+// Copyright: (C) 2012 Gilles Muller, INRIA/LiP6.
// URL: http://coccinelle.lip6.fr/
// Requires: 1.0.0
// Options:
diff --git a/scripts/coccinelle/null/deref_null.cocci b/scripts/coccinelle/null/deref_null.cocci
index cbc6184..98f1e7f 100644
--- a/scripts/coccinelle/null/deref_null.cocci
+++ b/scripts/coccinelle/null/deref_null.cocci
@@ -1,11 +1,12 @@
+// SPDX-License-Identifier: GPL-2.0-only
///
/// A variable is dereferenced under a NULL test.
/// Even though it is known to be NULL.
///
// Confidence: Moderate
-// Copyright: (C) 2010 Nicolas Palix, DIKU. GPLv2.
-// Copyright: (C) 2010 Julia Lawall, DIKU. GPLv2.
-// Copyright: (C) 2010 Gilles Muller, INRIA/LiP6. GPLv2.
+// Copyright: (C) 2010 Nicolas Palix, DIKU.
+// Copyright: (C) 2010 Julia Lawall, DIKU.
+// Copyright: (C) 2010 Gilles Muller, INRIA/LiP6.
// URL: http://coccinelle.lip6.fr/
// Comments: -I ... -all_includes can give more complete results
// Options:
diff --git a/scripts/coccinelle/null/eno.cocci b/scripts/coccinelle/null/eno.cocci
index 9bd29aa..81584ff 100644
--- a/scripts/coccinelle/null/eno.cocci
+++ b/scripts/coccinelle/null/eno.cocci
@@ -1,9 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0-only
/// The various basic memory allocation functions don't return ERR_PTR
///
// Confidence: High
-// Copyright: (C) 2010-2012 Nicolas Palix. GPLv2.
-// Copyright: (C) 2010-2012 Julia Lawall, INRIA/LIP6. GPLv2.
-// Copyright: (C) 2010-2012 Gilles Muller, INRIA/LiP6. GPLv2.
+// Copyright: (C) 2010-2012 Nicolas Palix.
+// Copyright: (C) 2010-2012 Julia Lawall, INRIA/LIP6.
+// Copyright: (C) 2010-2012 Gilles Muller, INRIA/LiP6.
// URL: http://coccinelle.lip6.fr/
// Comments:
// Options: --no-includes --include-headers
diff --git a/scripts/coccinelle/null/kmerr.cocci b/scripts/coccinelle/null/kmerr.cocci
index 5354a79..d0e004d 100644
--- a/scripts/coccinelle/null/kmerr.cocci
+++ b/scripts/coccinelle/null/kmerr.cocci
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0-only
/// This semantic patch looks for kmalloc etc that are not followed by a
/// NULL check. It only gives a report in the case where there is some
/// error handling code later in the function, which may be helpful
@@ -5,9 +6,9 @@
/// should be.
///
// Confidence: High
-// Copyright: (C) 2010 Nicolas Palix, DIKU. GPLv2.
-// Copyright: (C) 2010 Julia Lawall, DIKU. GPLv2.
-// Copyright: (C) 2010 Gilles Muller, INRIA/LiP6. GPLv2.
+// Copyright: (C) 2010 Nicolas Palix, DIKU.
+// Copyright: (C) 2010 Julia Lawall, DIKU.
+// Copyright: (C) 2010 Gilles Muller, INRIA/LiP6.
// URL: http://coccinelle.lip6.fr/
// Comments:
// Options: --no-includes --include-headers
diff --git a/scripts/coccinelle/tests/doublebitand.cocci b/scripts/coccinelle/tests/doublebitand.cocci
index 72f1572..0f0b94e 100644
--- a/scripts/coccinelle/tests/doublebitand.cocci
+++ b/scripts/coccinelle/tests/doublebitand.cocci
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0-only
/// Find bit operations that include the same argument more than once
//# One source of false positives is when the argument performs a side
//# effect. Another source of false positives is when a neutral value
@@ -5,9 +6,9 @@
//# same structure as other similar expressions
///
// Confidence: Moderate
-// Copyright: (C) 2010 Nicolas Palix, DIKU. GPLv2.
-// Copyright: (C) 2010 Julia Lawall, DIKU. GPLv2.
-// Copyright: (C) 2010 Gilles Muller, INRIA/LiP6. GPLv2.
+// Copyright: (C) 2010 Nicolas Palix, DIKU.
+// Copyright: (C) 2010 Julia Lawall, DIKU.
+// Copyright: (C) 2010 Gilles Muller, INRIA/LiP6.
// URL: http://coccinelle.lip6.fr/
// Comments:
// Options: --no-includes --include-headers
diff --git a/scripts/coccinelle/tests/doubletest.cocci b/scripts/coccinelle/tests/doubletest.cocci
index 7af2ce7..b35519c 100644
--- a/scripts/coccinelle/tests/doubletest.cocci
+++ b/scripts/coccinelle/tests/doubletest.cocci
@@ -1,12 +1,13 @@
+// SPDX-License-Identifier: GPL-2.0-only
/// Find &&/|| operations that include the same argument more than once
//# A common source of false positives is when the expression, or
//# another expresssion in the same && or || operation, performs a
//# side effect.
///
// Confidence: Moderate
-// Copyright: (C) 2010 Nicolas Palix, DIKU. GPLv2.
-// Copyright: (C) 2010 Julia Lawall, DIKU. GPLv2.
-// Copyright: (C) 2010 Gilles Muller, INRIA/LiP6. GPLv2.
+// Copyright: (C) 2010 Nicolas Palix, DIKU.
+// Copyright: (C) 2010 Julia Lawall, DIKU.
+// Copyright: (C) 2010 Gilles Muller, INRIA/LiP6.
// URL: http://coccinelle.lip6.fr/
// Comments:
// Options: --no-includes --include-headers
diff --git a/scripts/coccinelle/tests/odd_ptr_err.cocci b/scripts/coccinelle/tests/odd_ptr_err.cocci
index dfc6b40..11d4e2b 100644
--- a/scripts/coccinelle/tests/odd_ptr_err.cocci
+++ b/scripts/coccinelle/tests/odd_ptr_err.cocci
@@ -1,10 +1,11 @@
+// SPDX-License-Identifier: GPL-2.0-only
/// PTR_ERR should access the value just tested by IS_ERR
//# There can be false positives in the patch case, where it is the call to
//# IS_ERR that is wrong.
///
// Confidence: High
-// Copyright: (C) 2012, 2015 Julia Lawall, INRIA. GPLv2.
-// Copyright: (C) 2012, 2015 Gilles Muller, INRIA. GPLv2.
+// Copyright: (C) 2012, 2015 Julia Lawall, INRIA.
+// Copyright: (C) 2012, 2015 Gilles Muller, INRIA.
// URL: http://coccinelle.lip6.fr/
// Options: --no-includes --include-headers
diff --git a/scripts/coccinelle/tests/unsigned_lesser_than_zero.cocci b/scripts/coccinelle/tests/unsigned_lesser_than_zero.cocci
index 8fa5a3c..91e286a 100644
--- a/scripts/coccinelle/tests/unsigned_lesser_than_zero.cocci
+++ b/scripts/coccinelle/tests/unsigned_lesser_than_zero.cocci
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0-only
/// Unsigned expressions cannot be lesser than zero. Presence of
/// comparisons 'unsigned (<|<=|>|>=) 0' often indicates a bug,
/// usually wrong type of variable.
@@ -11,7 +12,7 @@
/// result is used to avoid false positives difficult to detect by other ways
///
// Confidence: Average
-// Copyright: (C) 2015 Andrzej Hajda, Samsung Electronics Co., Ltd. GPLv2.
+// Copyright: (C) 2015 Andrzej Hajda, Samsung Electronics Co., Ltd.
// URL: http://coccinelle.lip6.fr/
// Options: --all-includes
diff --git a/scripts/conmakehash.c b/scripts/conmakehash.c
index 61bbda5..cddd789 100644
--- a/scripts/conmakehash.c
+++ b/scripts/conmakehash.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
/*
* conmakehash.c
*
@@ -8,10 +9,6 @@
* just for this seems like massive overkill.
*
* Copyright (C) 1995-1997 H. Peter Anvin
- *
- * This program is a part of the Linux kernel, and may be freely
- * copied under the terms of the GNU General Public License (GPL),
- * version 2, or at your option any later version.
*/
#include <stdio.h>
diff --git a/scripts/decode_stacktrace.sh b/scripts/decode_stacktrace.sh
index 64220e3..13e5fba 100755
--- a/scripts/decode_stacktrace.sh
+++ b/scripts/decode_stacktrace.sh
@@ -28,7 +28,7 @@
local objfile=${modcache[$module]}
else
[[ $modpath == "" ]] && return
- local objfile=$(find "$modpath" -name $module.ko -print -quit)
+ local objfile=$(find "$modpath" -name "${module//_/[-_]}.ko*" -print -quit)
[[ $objfile == "" ]] && return
modcache[$module]=$objfile
fi
@@ -37,6 +37,13 @@
symbol=${symbol#\(}
symbol=${symbol%\)}
+ # Strip segment
+ local segment
+ if [[ $symbol == *:* ]] ; then
+ segment=${symbol%%:*}:
+ symbol=${symbol#*:}
+ fi
+
# Strip the symbol name so that we could look it up
local name=${symbol%+*}
@@ -66,7 +73,7 @@
if [[ "${cache[$module,$address]+isset}" == "isset" ]]; then
local code=${cache[$module,$address]}
else
- local code=$(addr2line -i -e "$objfile" "$address")
+ local code=$(${CROSS_COMPILE}addr2line -i -e "$objfile" "$address")
cache[$module,$address]=$code
fi
@@ -78,13 +85,13 @@
fi
# Strip out the base of the path
- code=${code//$basepath/""}
+ code=${code#$basepath/}
# In the case of inlines, move everything to same line
code=${code//$'\n'/' '}
# Replace old address with pretty line numbers
- symbol="$name ($code)"
+ symbol="$segment$name ($code)"
}
decode_code() {
diff --git a/scripts/decodecode b/scripts/decodecode
index 9cef558..ba8b8d5 100755
--- a/scripts/decodecode
+++ b/scripts/decodecode
@@ -60,6 +60,13 @@
4) type=4byte ;;
esac
+if [ -z "$ARCH" ]; then
+ case `uname -m` in
+ aarch64*) ARCH=arm64 ;;
+ arm*) ARCH=arm ;;
+ esac
+fi
+
disas() {
${CROSS_COMPILE}as $AFLAGS -o $1.o $1.s > /dev/null 2>&1
diff --git a/scripts/documentation-file-ref-check b/scripts/documentation-file-ref-check
index ad9db68..7784c54 100755
--- a/scripts/documentation-file-ref-check
+++ b/scripts/documentation-file-ref-check
@@ -8,15 +8,30 @@
use strict;
use Getopt::Long qw(:config no_auto_abbrev);
+# NOTE: only add things here when the file was gone, but the text wants
+# 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",
+ "drivers/vhost/vhost.c" => "Documentation/virtual/lguest/lguest.c",
+);
+
my $scriptname = $0;
$scriptname =~ s,.*/([^/]+/),$1,;
# Parse arguments
my $help = 0;
my $fix = 0;
+my $warn = 0;
+
+if (! -d ".git") {
+ printf "Warning: can't check if file exists, as this is not a git tree";
+ exit 0;
+}
GetOptions(
'fix' => \$fix,
+ 'warn' => \$warn,
'h|help|usage' => \$help,
);
@@ -30,6 +45,34 @@
my %broken_ref;
+my $doc_fix = 0;
+
+open IN, "git grep ':doc:\`' Documentation/|"
+ or die "Failed to run git grep";
+while (<IN>) {
+ next if (!m,^([^:]+):.*\:doc\:\`([^\`]+)\`,);
+
+ my $d = $1;
+ my $doc_ref = $2;
+
+ my $f = $doc_ref;
+
+ $d =~ s,(.*/).*,$1,;
+ $f =~ s,.*\<([^\>]+)\>,$1,;
+
+ $f ="$d$f.rst";
+
+ next if (grep -e, glob("$f"));
+
+ if ($fix && !$doc_fix) {
+ print STDERR "\nWARNING: Currently, can't fix broken :doc:`` fields\n";
+ }
+ $doc_fix++;
+
+ print STDERR "$f: :doc:`$doc_ref`\n";
+}
+close IN;
+
open IN, "git grep 'Documentation/'|"
or die "Failed to run git grep";
while (<IN>) {
@@ -38,12 +81,18 @@
my $f = $1;
my $ln = $2;
+ # On linux-next, discard the Next/ directory
+ next if ($f =~ m,^Next/,);
+
# Makefiles and scripts contain nasty expressions to parse docs
next if ($f =~ m/Makefile/ || $f =~ m/\.sh$/);
# Skip this script
next if ($f eq $scriptname);
+ # Ignore the dir where documentation will be built
+ next if ($ln =~ m,\b(\S*)Documentation/output,);
+
if ($ln =~ m,\b(\S*)(Documentation/[A-Za-z0-9\_\.\,\~/\*\[\]\?+-]*)(.*),) {
my $prefix = $1;
my $ref = $2;
@@ -78,7 +127,7 @@
# Remove sched-pelt false-positive
next if ($fulref =~ m,^Documentation/scheduler/sched-pelt$,);
- # Discard some build examples from Documentation/target/tcm_mod_builder.txt
+ # Discard some build examples from Documentation/target/tcm_mod_builder.rst
next if ($fulref =~ m,mnt/sdb/lio-core-2.6.git/Documentation/target,);
# Check if exists, evaluating wildcards
@@ -88,18 +137,26 @@
if ($f =~ m/tools/) {
my $path = $f;
$path =~ s,(.*)/.*,$1,;
- next if (grep -e, glob("$path/$ref $path/$fulref"));
+ next if (grep -e, glob("$path/$ref $path/../$ref $path/$fulref"));
+ }
+
+ # Discard known false-positives
+ if (defined($false_positives{$f})) {
+ next if ($false_positives{$f} eq $fulref);
}
if ($fix) {
if (!($ref =~ m/(scripts|Kconfig|Kbuild)/)) {
$broken_ref{$ref}++;
}
+ } elsif ($warn) {
+ print STDERR "Warning: $f references a file that doesn't exist: $fulref\n";
} else {
print STDERR "$f: $fulref\n";
}
}
}
+close IN;
exit 0 if (!$fix);
@@ -109,6 +166,10 @@
foreach my $ref (keys %broken_ref) {
my $new =$ref;
+ my $basedir = ".";
+ # On translations, only seek inside the translations directory
+ $basedir = $1 if ($ref =~ m,(Documentation/translations/[^/]+),);
+
# get just the basename
$new =~ s,.*/,,;
@@ -116,31 +177,40 @@
# usual reason for breakage: DT file moved around
if ($ref =~ /devicetree/) {
- my $search = $new;
- $search =~ s,^.*/,,;
- $f = qx(find Documentation/devicetree/ -iname "*$search*") if ($search);
+ # usual reason for breakage: DT file renamed to .yaml
if (!$f) {
- # Manufacturer name may have changed
- $search =~ s/^.*,//;
+ my $new_ref = $ref;
+ $new_ref =~ s/\.txt$/.yaml/;
+ $f=$new_ref if (-f $new_ref);
+ }
+
+ if (!$f) {
+ my $search = $new;
+ $search =~ s,^.*/,,;
$f = qx(find Documentation/devicetree/ -iname "*$search*") if ($search);
+ if (!$f) {
+ # Manufacturer name may have changed
+ $search =~ s/^.*,//;
+ $f = qx(find Documentation/devicetree/ -iname "*$search*") if ($search);
+ }
}
}
# usual reason for breakage: file renamed to .rst
if (!$f) {
$new =~ s/\.txt$/.rst/;
- $f=qx(find . -iname $new) if ($new);
+ $f=qx(find $basedir -iname $new) if ($new);
}
# usual reason for breakage: use dash or underline
if (!$f) {
$new =~ s/[-_]/[-_]/g;
- $f=qx(find . -iname $new) if ($new);
+ $f=qx(find $basedir -iname $new) if ($new);
}
# Wild guess: seek for the same name on another place
if (!$f) {
- $f = qx(find . -iname $new) if ($new);
+ $f = qx(find $basedir -iname $new) if ($new);
}
my @find = split /\s+/, $f;
diff --git a/scripts/dtc/Makefile b/scripts/dtc/Makefile
index 1c943e0..8216080 100644
--- a/scripts/dtc/Makefile
+++ b/scripts/dtc/Makefile
@@ -1,7 +1,7 @@
# SPDX-License-Identifier: GPL-2.0
# scripts/dtc makefile
-hostprogs-y := dtc
+hostprogs-$(CONFIG_DTC) := dtc
always := $(hostprogs-y)
dtc-objs := dtc.o flattree.o fstree.o data.o livetree.o treesource.o \
@@ -9,11 +9,22 @@
dtc-objs += dtc-lexer.lex.o dtc-parser.tab.o
# Source files need to get at the userspace version of libfdt_env.h to compile
-HOST_EXTRACFLAGS := -I$(src)/libfdt
+HOST_EXTRACFLAGS := -I $(srctree)/$(src)/libfdt
+
+ifeq ($(wildcard /usr/include/yaml.h),)
+ifneq ($(CHECK_DTBS),)
+$(error dtc needs libyaml for DT schema validation support. \
+ Install the necessary libyaml development package.)
+endif
+HOST_EXTRACFLAGS += -DNO_YAML
+else
+dtc-objs += yamltree.o
+HOSTLDLIBS_dtc := -lyaml
+endif
# Generated files need one more search path to include headers in source tree
-HOSTCFLAGS_dtc-lexer.lex.o := -I$(src)
-HOSTCFLAGS_dtc-parser.tab.o := -I$(src)
+HOSTCFLAGS_dtc-lexer.lex.o := -I $(srctree)/$(src)
+HOSTCFLAGS_dtc-parser.tab.o := -I $(srctree)/$(src)
# dependencies on generated files need to be listed explicitly
$(obj)/dtc-lexer.lex.o: $(obj)/dtc-parser.tab.h
diff --git a/scripts/dtc/Makefile.dtc b/scripts/dtc/Makefile.dtc
index bece49b..9c467b0 100644
--- a/scripts/dtc/Makefile.dtc
+++ b/scripts/dtc/Makefile.dtc
@@ -1,3 +1,4 @@
+# SPDX-License-Identifier: GPL-2.0-or-later
# Makefile.dtc
#
# This is not a complete Makefile of itself. Instead, it is designed to
@@ -14,5 +15,9 @@
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 a2cc103..d7986ee 100644
--- a/scripts/dtc/checks.c
+++ b/scripts/dtc/checks.c
@@ -1,24 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
/*
* (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation. 2007.
- *
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
- * USA
*/
#include "dtc.h"
+#include "srcpos.h"
#ifdef TRACE_CHECKS
#define TRACE(c, ...) \
@@ -78,23 +64,56 @@
const char *fmt, ...)
{
va_list ap;
- va_start(ap, fmt);
+ char *str = NULL;
+ struct srcpos *pos = NULL;
+ char *file_str;
- if ((c->warn && (quiet < 1))
- || (c->error && (quiet < 2))) {
- fprintf(stderr, "%s: %s (%s): ",
- strcmp(dti->outname, "-") ? dti->outname : "<stdout>",
- (c->error) ? "ERROR" : "Warning", c->name);
- if (node) {
- fprintf(stderr, "%s", node->fullpath);
- if (prop)
- fprintf(stderr, ":%s", prop->name);
- fputs(": ", stderr);
- }
- vfprintf(stderr, fmt, ap);
- fprintf(stderr, "\n");
+ if (!(c->warn && (quiet < 1)) && !(c->error && (quiet < 2)))
+ return;
+
+ if (prop && prop->srcpos)
+ pos = prop->srcpos;
+ else if (node && node->srcpos)
+ pos = node->srcpos;
+
+ if (pos) {
+ file_str = srcpos_string(pos);
+ xasprintf(&str, "%s", file_str);
+ free(file_str);
+ } else if (streq(dti->outname, "-")) {
+ xasprintf(&str, "<stdout>");
+ } else {
+ xasprintf(&str, "%s", dti->outname);
}
+
+ xasprintf_append(&str, ": %s (%s): ",
+ (c->error) ? "ERROR" : "Warning", c->name);
+
+ if (node) {
+ if (prop)
+ xasprintf_append(&str, "%s:%s: ", node->fullpath, prop->name);
+ else
+ xasprintf_append(&str, "%s: ", node->fullpath);
+ }
+
+ va_start(ap, fmt);
+ xavsprintf_append(&str, fmt, ap);
va_end(ap);
+
+ xasprintf_append(&str, "\n");
+
+ if (!prop && pos) {
+ pos = node->srcpos;
+ while (pos->next) {
+ pos = pos->next;
+
+ file_str = srcpos_string(pos);
+ xasprintf_append(&str, " also defined at %s\n", file_str);
+ free(file_str);
+ }
+ }
+
+ fputs(str, stderr);
}
#define FAIL(c, dti, node, ...) \
@@ -626,6 +645,8 @@
static void fixup_omit_unused_nodes(struct check *c, struct dt_info *dti,
struct node *node)
{
+ if (generate_symbols && node->labels)
+ return;
if (node->omit_if_unused && !node->is_referenced)
delete_node(node);
}
@@ -910,7 +931,7 @@
for (str = prop->val.val, end = str + prop->val.len; str < end;
str += strnlen(str, end - str) + 1) {
- if (strprefixeq(str, end - str, compat))
+ if (streq(str, compat))
return true;
}
return false;
@@ -921,7 +942,8 @@
if (node_is_compatible(node, "simple-bus"))
node->bus = &simple_bus;
}
-WARNING(simple_bus_bridge, check_simple_bus_bridge, NULL, &addr_size_cells);
+WARNING(simple_bus_bridge, check_simple_bus_bridge, NULL,
+ &addr_size_cells, &compatible_is_string_list);
static void check_simple_bus_reg(struct check *c, struct dt_info *dti, struct node *node)
{
@@ -962,6 +984,149 @@
}
WARNING(simple_bus_reg, check_simple_bus_reg, NULL, ®_format, &simple_bus_bridge);
+static const struct bus_type i2c_bus = {
+ .name = "i2c-bus",
+};
+
+static void check_i2c_bus_bridge(struct check *c, struct dt_info *dti, struct node *node)
+{
+ if (strprefixeq(node->name, node->basenamelen, "i2c-bus") ||
+ strprefixeq(node->name, node->basenamelen, "i2c-arb")) {
+ node->bus = &i2c_bus;
+ } else if (strprefixeq(node->name, node->basenamelen, "i2c")) {
+ struct node *child;
+ for_each_child(node, child) {
+ if (strprefixeq(child->name, node->basenamelen, "i2c-bus"))
+ return;
+ }
+ node->bus = &i2c_bus;
+ } else
+ return;
+
+ if (!node->children)
+ return;
+
+ if (node_addr_cells(node) != 1)
+ FAIL(c, dti, node, "incorrect #address-cells for I2C bus");
+ if (node_size_cells(node) != 0)
+ FAIL(c, dti, node, "incorrect #size-cells for I2C bus");
+
+}
+WARNING(i2c_bus_bridge, check_i2c_bus_bridge, NULL, &addr_size_cells);
+
+static void check_i2c_bus_reg(struct check *c, struct dt_info *dti, struct node *node)
+{
+ struct property *prop;
+ const char *unitname = get_unitname(node);
+ char unit_addr[17];
+ uint32_t reg = 0;
+ int len;
+ cell_t *cells = NULL;
+
+ if (!node->parent || (node->parent->bus != &i2c_bus))
+ return;
+
+ prop = get_property(node, "reg");
+ if (prop)
+ cells = (cell_t *)prop->val.val;
+
+ if (!cells) {
+ FAIL(c, dti, node, "missing or empty reg property");
+ return;
+ }
+
+ reg = fdt32_to_cpu(*cells);
+ snprintf(unit_addr, sizeof(unit_addr), "%x", reg);
+ if (!streq(unitname, unit_addr))
+ FAIL(c, dti, node, "I2C bus unit address format error, expected \"%s\"",
+ unit_addr);
+
+ for (len = prop->val.len; len > 0; len -= 4) {
+ reg = fdt32_to_cpu(*(cells++));
+ if (reg > 0x3ff)
+ FAIL_PROP(c, dti, node, prop, "I2C address must be less than 10-bits, got \"0x%x\"",
+ reg);
+
+ }
+}
+WARNING(i2c_bus_reg, check_i2c_bus_reg, NULL, ®_format, &i2c_bus_bridge);
+
+static const struct bus_type spi_bus = {
+ .name = "spi-bus",
+};
+
+static void check_spi_bus_bridge(struct check *c, struct dt_info *dti, struct node *node)
+{
+ int spi_addr_cells = 1;
+
+ if (strprefixeq(node->name, node->basenamelen, "spi")) {
+ node->bus = &spi_bus;
+ } else {
+ /* Try to detect SPI buses which don't have proper node name */
+ struct node *child;
+
+ if (node_addr_cells(node) != 1 || node_size_cells(node) != 0)
+ return;
+
+ for_each_child(node, child) {
+ struct property *prop;
+ for_each_property(child, prop) {
+ if (strprefixeq(prop->name, 4, "spi-")) {
+ node->bus = &spi_bus;
+ break;
+ }
+ }
+ if (node->bus == &spi_bus)
+ break;
+ }
+
+ if (node->bus == &spi_bus && get_property(node, "reg"))
+ FAIL(c, dti, node, "node name for SPI buses should be 'spi'");
+ }
+ if (node->bus != &spi_bus || !node->children)
+ return;
+
+ if (get_property(node, "spi-slave"))
+ spi_addr_cells = 0;
+ if (node_addr_cells(node) != spi_addr_cells)
+ FAIL(c, dti, node, "incorrect #address-cells for SPI bus");
+ if (node_size_cells(node) != 0)
+ FAIL(c, dti, node, "incorrect #size-cells for SPI bus");
+
+}
+WARNING(spi_bus_bridge, check_spi_bus_bridge, NULL, &addr_size_cells);
+
+static void check_spi_bus_reg(struct check *c, struct dt_info *dti, struct node *node)
+{
+ struct property *prop;
+ const char *unitname = get_unitname(node);
+ char unit_addr[9];
+ uint32_t reg = 0;
+ cell_t *cells = NULL;
+
+ if (!node->parent || (node->parent->bus != &spi_bus))
+ return;
+
+ if (get_property(node->parent, "spi-slave"))
+ return;
+
+ prop = get_property(node, "reg");
+ if (prop)
+ cells = (cell_t *)prop->val.val;
+
+ if (!cells) {
+ FAIL(c, dti, node, "missing or empty reg property");
+ return;
+ }
+
+ reg = fdt32_to_cpu(*cells);
+ snprintf(unit_addr, sizeof(unit_addr), "%x", reg);
+ if (!streq(unitname, unit_addr))
+ FAIL(c, dti, node, "SPI bus unit address format error, expected \"%s\"",
+ unit_addr);
+}
+WARNING(spi_bus_reg, check_spi_bus_reg, NULL, ®_format, &spi_bus_bridge);
+
static void check_unit_address_format(struct check *c, struct dt_info *dti,
struct node *node)
{
@@ -1034,8 +1199,24 @@
}
WARNING(avoid_unnecessary_addr_size, check_avoid_unnecessary_addr_size, NULL, &avoid_default_addr_size);
-static void check_unique_unit_address(struct check *c, struct dt_info *dti,
- struct node *node)
+static bool node_is_disabled(struct node *node)
+{
+ struct property *prop;
+
+ prop = get_property(node, "status");
+ if (prop) {
+ char *str = prop->val.val;
+ if (streq("disabled", str))
+ return true;
+ }
+
+ return false;
+}
+
+static void check_unique_unit_address_common(struct check *c,
+ struct dt_info *dti,
+ struct node *node,
+ bool disable_check)
{
struct node *childa;
@@ -1052,18 +1233,38 @@
if (!strlen(addr_a))
continue;
+ if (disable_check && node_is_disabled(childa))
+ continue;
+
for_each_child(node, childb) {
const char *addr_b = get_unitname(childb);
if (childa == childb)
break;
+ if (disable_check && node_is_disabled(childb))
+ continue;
+
if (streq(addr_a, addr_b))
FAIL(c, dti, childb, "duplicate unit-address (also used in node %s)", childa->fullpath);
}
}
}
+
+static void check_unique_unit_address(struct check *c, struct dt_info *dti,
+ struct node *node)
+{
+ check_unique_unit_address_common(c, dti, node, false);
+}
WARNING(unique_unit_address, check_unique_unit_address, NULL, &avoid_default_addr_size);
+static void check_unique_unit_address_if_enabled(struct check *c, struct dt_info *dti,
+ struct node *node)
+{
+ check_unique_unit_address_common(c, dti, node, true);
+}
+CHECK_ENTRY(unique_unit_address_if_enabled, check_unique_unit_address_if_enabled,
+ NULL, false, false, &avoid_default_addr_size);
+
static void check_obsolete_chosen_interrupt_controller(struct check *c,
struct dt_info *dti,
struct node *node)
@@ -1364,10 +1565,14 @@
prop = get_property(parent, "interrupt-parent");
if (prop) {
phandle = propval_cell(prop);
- /* Give up if this is an overlay with external references */
- if ((phandle == 0 || phandle == -1) &&
- (dti->dtsflags & DTSF_PLUGIN))
+ if ((phandle == 0) || (phandle == -1)) {
+ /* Give up if this is an overlay with
+ * external references */
+ if (dti->dtsflags & DTSF_PLUGIN)
return;
+ FAIL_PROP(c, dti, parent, prop, "Invalid phandle");
+ continue;
+ }
irq_node = get_node_by_phandle(root, phandle);
if (!irq_node) {
@@ -1536,7 +1741,7 @@
return;
if (!strprefixeq(node->name, node->basenamelen, "endpoint"))
- FAIL(c, dti, node, "graph endpont node name should be 'endpoint'");
+ FAIL(c, dti, node, "graph endpoint node name should be 'endpoint'");
check_graph_reg(c, dti, node);
@@ -1582,9 +1787,16 @@
&simple_bus_bridge,
&simple_bus_reg,
+ &i2c_bus_bridge,
+ &i2c_bus_reg,
+
+ &spi_bus_bridge,
+ &spi_bus_reg,
+
&avoid_default_addr_size,
&avoid_unnecessary_addr_size,
&unique_unit_address,
+ &unique_unit_address_if_enabled,
&obsolete_chosen_interrupt_controller,
&chosen_node_is_root, &chosen_node_bootargs, &chosen_node_stdout_path,
diff --git a/scripts/dtc/data.c b/scripts/dtc/data.c
index aa37a16..0a43b6d 100644
--- a/scripts/dtc/data.c
+++ b/scripts/dtc/data.c
@@ -1,21 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
/*
* (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation. 2005.
- *
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
- * USA
*/
#include "dtc.h"
@@ -74,7 +59,8 @@
struct data d;
char *q;
- d = data_grow_for(empty_data, len + 1);
+ d = data_add_marker(empty_data, TYPE_STRING, NULL);
+ d = data_grow_for(d, len + 1);
q = d.val;
while (i < len) {
@@ -94,6 +80,7 @@
{
struct data d = empty_data;
+ d = data_add_marker(d, TYPE_NONE, NULL);
while (!feof(f) && (d.len < maxlen)) {
size_t chunksize, ret;
diff --git a/scripts/dtc/dt_to_config b/scripts/dtc/dt_to_config
index 5dfd1bf..299d1c2 100755
--- a/scripts/dtc/dt_to_config
+++ b/scripts/dtc/dt_to_config
@@ -1,10 +1,9 @@
#!/usr/bin/env perl
+# SPDX-License-Identifier: GPL-2.0-only
# Copyright 2016 by Frank Rowand
# Copyright 2016 by Gaurav Minocha
#
-# This file is subject to the terms and conditions of the GNU General Public
-# License v2.
use strict 'refs';
use strict subs;
diff --git a/scripts/dtc/dtc-lexer.l b/scripts/dtc/dtc-lexer.l
index 615b7ec..5c6c3fd 100644
--- a/scripts/dtc/dtc-lexer.l
+++ b/scripts/dtc/dtc-lexer.l
@@ -1,21 +1,6 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
* (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation. 2005.
- *
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
- * USA
*/
%option noyywrap nounput noinput never-interactive
@@ -213,14 +198,14 @@
<*>\&{LABEL} { /* label reference */
DPRINT("Ref: %s\n", yytext+1);
yylval.labelref = xstrdup(yytext+1);
- return DT_REF;
+ return DT_LABEL_REF;
}
<*>"&{/"{PATHCHAR}*\} { /* new-style path reference */
yytext[yyleng-1] = '\0';
DPRINT("Ref: %s\n", yytext+2);
yylval.labelref = xstrdup(yytext+2);
- return DT_REF;
+ return DT_PATH_REF;
}
<BYTESTRING>[0-9a-fA-F]{2} {
diff --git a/scripts/dtc/dtc-parser.y b/scripts/dtc/dtc-parser.y
index 011a5b2..2ed4dc1 100644
--- a/scripts/dtc/dtc-parser.y
+++ b/scripts/dtc/dtc-parser.y
@@ -1,21 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
/*
* (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation. 2005.
- *
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
- * USA
*/
%{
#include <stdio.h>
@@ -70,7 +55,8 @@
%token <byte> DT_BYTE
%token <data> DT_STRING
%token <labelref> DT_LABEL
-%token <labelref> DT_REF
+%token <labelref> DT_LABEL_REF
+%token <labelref> DT_PATH_REF
%token DT_INCBIN
%type <data> propdata
@@ -83,6 +69,7 @@
%type <data> bytestring
%type <prop> propdef
%type <proplist> proplist
+%type <labelref> dt_ref
%type <node> devicetree
%type <node> nodedef
@@ -158,6 +145,8 @@
}
;
+dt_ref: DT_LABEL_REF | DT_PATH_REF;
+
devicetree:
'/' nodedef
{
@@ -167,7 +156,7 @@
{
$$ = merge_nodes($1, $3);
}
- | DT_REF nodedef
+ | dt_ref nodedef
{
/*
* We rely on the rule being always:
@@ -176,9 +165,12 @@
*/
if (!($<flags>-1 & DTSF_PLUGIN))
ERROR(&@2, "Label or path %s not found", $1);
- $$ = add_orphan_node(name_node(build_node(NULL, NULL), ""), $2, $1);
+ $$ = add_orphan_node(
+ name_node(build_node(NULL, NULL, NULL),
+ ""),
+ $2, $1);
}
- | devicetree DT_LABEL DT_REF nodedef
+ | devicetree DT_LABEL dt_ref nodedef
{
struct node *target = get_node_by_ref($1, $3);
@@ -189,7 +181,7 @@
ERROR(&@3, "Label or path %s not found", $3);
$$ = $1;
}
- | devicetree DT_REF nodedef
+ | devicetree DT_PATH_REF nodedef
{
/*
* We rely on the rule being always:
@@ -208,7 +200,26 @@
}
$$ = $1;
}
- | devicetree DT_DEL_NODE DT_REF ';'
+ | devicetree DT_LABEL_REF nodedef
+ {
+ struct node *target = get_node_by_ref($1, $2);
+
+ if (target) {
+ merge_nodes(target, $3);
+ } else {
+ /*
+ * We rely on the rule being always:
+ * versioninfo plugindecl memreserves devicetree
+ * so $-1 is what we want (plugindecl)
+ */
+ if ($<flags>-1 & DTSF_PLUGIN)
+ add_orphan_node($1, $3, $2);
+ else
+ ERROR(&@2, "Label or path %s not found", $2);
+ }
+ $$ = $1;
+ }
+ | devicetree DT_DEL_NODE dt_ref ';'
{
struct node *target = get_node_by_ref($1, $3);
@@ -220,7 +231,7 @@
$$ = $1;
}
- | devicetree DT_OMIT_NO_REF DT_REF ';'
+ | devicetree DT_OMIT_NO_REF dt_ref ';'
{
struct node *target = get_node_by_ref($1, $3);
@@ -237,7 +248,7 @@
nodedef:
'{' proplist subnodes '}' ';'
{
- $$ = build_node($2, $3);
+ $$ = build_node($2, $3, &@$);
}
;
@@ -255,11 +266,11 @@
propdef:
DT_PROPNODENAME '=' propdata ';'
{
- $$ = build_property($1, $3);
+ $$ = build_property($1, $3, &@$);
}
| DT_PROPNODENAME ';'
{
- $$ = build_property($1, empty_data);
+ $$ = build_property($1, empty_data, &@$);
}
| DT_DEL_PROP DT_PROPNODENAME ';'
{
@@ -285,8 +296,9 @@
{
$$ = data_merge($1, $3);
}
- | propdataprefix DT_REF
+ | propdataprefix dt_ref
{
+ $1 = data_add_marker($1, TYPE_STRING, $2);
$$ = data_add_marker($1, REF_PATH, $2);
}
| propdataprefix DT_INCBIN '(' DT_STRING ',' integer_prim ',' integer_prim ')'
@@ -340,22 +352,27 @@
DT_BITS DT_LITERAL '<'
{
unsigned long long bits;
+ enum markertype type = TYPE_UINT32;
bits = $2;
- if ((bits != 8) && (bits != 16) &&
- (bits != 32) && (bits != 64)) {
+ switch (bits) {
+ case 8: type = TYPE_UINT8; break;
+ case 16: type = TYPE_UINT16; break;
+ case 32: type = TYPE_UINT32; break;
+ case 64: type = TYPE_UINT64; break;
+ default:
ERROR(&@2, "Array elements must be"
" 8, 16, 32 or 64-bits");
bits = 32;
}
- $$.data = empty_data;
+ $$.data = data_add_marker(empty_data, type, NULL);
$$.bits = bits;
}
| '<'
{
- $$.data = empty_data;
+ $$.data = data_add_marker(empty_data, TYPE_UINT32, NULL);
$$.bits = 32;
}
| arrayprefix integer_prim
@@ -377,7 +394,7 @@
$$.data = data_append_integer($1.data, $2, $1.bits);
}
- | arrayprefix DT_REF
+ | arrayprefix dt_ref
{
uint64_t val = ~0ULL >> (64 - $1.bits);
@@ -499,7 +516,7 @@
bytestring:
/* empty */
{
- $$ = empty_data;
+ $$ = data_add_marker(empty_data, TYPE_UINT8, NULL);
}
| bytestring DT_BYTE
{
@@ -534,7 +551,7 @@
}
| DT_DEL_NODE DT_PROPNODENAME ';'
{
- $$ = name_node(build_node_delete(), $2);
+ $$ = name_node(build_node_delete(&@$), $2);
}
| DT_OMIT_NO_REF subnode
{
diff --git a/scripts/dtc/dtc.c b/scripts/dtc/dtc.c
index c36994e..bdb3f59 100644
--- a/scripts/dtc/dtc.c
+++ b/scripts/dtc/dtc.c
@@ -1,21 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
/*
* (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation. 2005.
- *
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
- * USA
*/
#include <sys/stat.h>
@@ -35,6 +20,8 @@
int generate_symbols; /* enable symbols & fixup support */
int generate_fixups; /* suppress generation of fixups on symbol support */
int auto_label_aliases; /* auto generate labels -> aliases */
+int annotate; /* Level of annotation: 1 for input source location
+ >1 for full input source location. */
static int is_power_of_2(int x)
{
@@ -60,7 +47,7 @@
/* Usage related data. */
static const char usage_synopsis[] = "dtc [options] <input file>";
-static const char usage_short_opts[] = "qI:O:o:V:d:R:S:p:a:fb:i:H:sW:E:@Ahv";
+static const char usage_short_opts[] = "qI:O:o:V:d:R:S:p:a:fb:i:H:sW:E:@AThv";
static struct option const usage_long_opts[] = {
{"quiet", no_argument, NULL, 'q'},
{"in-format", a_argument, NULL, 'I'},
@@ -81,6 +68,7 @@
{"error", a_argument, NULL, 'E'},
{"symbols", no_argument, NULL, '@'},
{"auto-alias", no_argument, NULL, 'A'},
+ {"annotate", no_argument, NULL, 'T'},
{"help", no_argument, NULL, 'h'},
{"version", no_argument, NULL, 'v'},
{NULL, no_argument, NULL, 0x0},
@@ -95,6 +83,9 @@
"\n\tOutput formats are:\n"
"\t\tdts - device tree source text\n"
"\t\tdtb - device tree blob\n"
+#ifndef NO_YAML
+ "\t\tyaml - device tree encoded as YAML\n"
+#endif
"\t\tasm - assembler source",
"\n\tBlob version to produce, defaults to "stringify(DEFAULT_FDT_VERSION)" (for dtb and asm output)",
"\n\tOutput dependency file",
@@ -114,6 +105,7 @@
"\n\tEnable/disable errors (prefix with \"no-\")",
"\n\tEnable generation of symbols",
"\n\tEnable auto-alias of labels",
+ "\n\tAnnotate output .dts with input source file and line (-T -T for more details)",
"\n\tPrint this help and exit",
"\n\tPrint version and exit",
NULL,
@@ -128,6 +120,8 @@
return fallback;
if (!strcasecmp(s, ".dts"))
return "dts";
+ if (!strcasecmp(s, ".yaml"))
+ return "yaml";
if (!strcasecmp(s, ".dtb"))
return "dtb";
return fallback;
@@ -259,6 +253,9 @@
case 'A':
auto_label_aliases = 1;
break;
+ case 'T':
+ annotate++;
+ break;
case 'h':
usage(NULL);
@@ -297,6 +294,8 @@
outform = "dts";
}
}
+ if (annotate && (!streq(inform, "dts") || !streq(outform, "dts")))
+ die("--annotate requires -I dts -O dts\n");
if (streq(inform, "dts"))
dti = dt_from_source(arg);
else if (streq(inform, "fs"))
@@ -350,6 +349,12 @@
if (streq(outform, "dts")) {
dt_to_source(outf, dti);
+#ifndef NO_YAML
+ } else if (streq(outform, "yaml")) {
+ if (!streq(inform, "dts"))
+ die("YAML output format requires dts input format\n");
+ dt_to_yaml(outf, dti);
+#endif
} else if (streq(outform, "dtb")) {
dt_to_blob(outf, dti, outversion);
} else if (streq(outform, "asm")) {
diff --git a/scripts/dtc/dtc.h b/scripts/dtc/dtc.h
index 6d66770..6e74ece 100644
--- a/scripts/dtc/dtc.h
+++ b/scripts/dtc/dtc.h
@@ -1,24 +1,9 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
#ifndef DTC_H
#define DTC_H
/*
* (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation. 2005.
- *
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
- * USA
*/
#include <stdio.h>
@@ -58,6 +43,7 @@
extern int generate_symbols; /* generate symbols for nodes with labels */
extern int generate_fixups; /* generate fixups */
extern int auto_label_aliases; /* auto generate labels -> aliases */
+extern int annotate; /* annotate .dts with input source location */
#define PHANDLE_LEGACY 0x1
#define PHANDLE_EPAPR 0x2
@@ -74,10 +60,17 @@
/* Data blobs */
enum markertype {
+ TYPE_NONE,
REF_PHANDLE,
REF_PATH,
LABEL,
+ TYPE_UINT8,
+ TYPE_UINT16,
+ TYPE_UINT32,
+ TYPE_UINT64,
+ TYPE_STRING,
};
+extern const char *markername(enum markertype markertype);
struct marker {
enum markertype type;
@@ -101,6 +94,8 @@
for_each_marker(m) \
if ((m)->type == (t))
+size_t type_marker_length(struct marker *m);
+
void data_free(struct data d);
struct data data_grow_for(struct data d, int xlen);
@@ -149,6 +144,7 @@
struct property *next;
struct label *labels;
+ struct srcpos *srcpos;
};
struct node {
@@ -168,6 +164,7 @@
struct label *labels;
const struct bus_type *bus;
+ struct srcpos *srcpos;
bool omit_if_unused, is_referenced;
};
@@ -196,13 +193,15 @@
void add_label(struct label **labels, char *label);
void delete_labels(struct label **labels);
-struct property *build_property(char *name, struct data val);
+struct property *build_property(char *name, struct data val,
+ struct srcpos *srcpos);
struct property *build_property_delete(char *name);
struct property *chain_property(struct property *first, struct property *list);
struct property *reverse_properties(struct property *first);
-struct node *build_node(struct property *proplist, struct node *children);
-struct node *build_node_delete(void);
+struct node *build_node(struct property *proplist, struct node *children,
+ struct srcpos *srcpos);
+struct node *build_node_delete(struct srcpos *srcpos);
struct node *name_node(struct node *node, char *name);
struct node *omit_node_if_unused(struct node *node);
struct node *reference_node(struct node *node);
@@ -217,7 +216,8 @@
void delete_node_by_name(struct node *parent, char *name);
void delete_node(struct node *node);
void append_to_property(struct node *node,
- char *name, const void *data, int len);
+ char *name, const void *data, int len,
+ enum markertype type);
const char *get_unitname(struct node *node);
struct property *get_property(struct node *node, const char *propname);
@@ -290,6 +290,10 @@
void dt_to_source(FILE *f, struct dt_info *dti);
struct dt_info *dt_from_source(const char *f);
+/* YAML source */
+
+void dt_to_yaml(FILE *f, struct dt_info *dti);
+
/* FS trees */
struct dt_info *dt_from_fs(const char *dirname);
diff --git a/scripts/dtc/dtx_diff b/scripts/dtc/dtx_diff
index 8c4fbad..00fd473 100755
--- a/scripts/dtc/dtx_diff
+++ b/scripts/dtc/dtx_diff
@@ -1,10 +1,8 @@
#! /bin/bash
+# SPDX-License-Identifier: GPL-2.0-only
# Copyright (C) 2015 Frank Rowand
#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; version 2 of the License.
usage() {
@@ -21,6 +19,7 @@
diff DTx_1 and DTx_2
+ --annotate synonym for -T
-f print full dts in diff (--unified=99999)
-h synonym for --help
-help synonym for --help
@@ -28,6 +27,7 @@
-s SRCTREE linux kernel source tree is at path SRCTREE
(default is current directory)
-S linux kernel source tree is at root of current git repo
+ -T Annotate output .dts with input source file and line (-T -T for more details)
-u unsorted, do not sort DTx
@@ -174,6 +174,7 @@
# ----- start of script
+annotate=""
cmd_diff=0
diff_flags="-u"
dtx_file_1=""
@@ -208,6 +209,14 @@
shift
;;
+ -T | --annotate )
+ if [ "${annotate}" = "" ] ; then
+ annotate="-T"
+ elif [ "${annotate}" = "-T" ] ; then
+ annotate="-T -T"
+ fi
+ shift
+ ;;
-u )
dtc_sort=""
shift
@@ -327,7 +336,7 @@
DTC="\
${DTC} \
-i ${srctree}/scripts/dtc/include-prefixes \
- -O dts -qq -f ${dtc_sort} -o -"
+ -O dts -qq -f ${dtc_sort} ${annotate} -o -"
# ----- do the diff or decompile
diff --git a/scripts/dtc/fdtget.c b/scripts/dtc/fdtget.c
index c2fbab2..c922f82 100644
--- a/scripts/dtc/fdtget.c
+++ b/scripts/dtc/fdtget.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
*
@@ -6,21 +7,6 @@
* Based on code written by:
* Pantelis Antoniou <pantelis.antoniou@gmail.com> and
* Matthew McClintock <msm@freescale.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
- * MA 02111-1307 USA
*/
#include <assert.h>
diff --git a/scripts/dtc/fdtput.c b/scripts/dtc/fdtput.c
index f2197f5..a363c3c 100644
--- a/scripts/dtc/fdtput.c
+++ b/scripts/dtc/fdtput.c
@@ -1,20 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
- * MA 02111-1307 USA
*/
#include <assert.h>
diff --git a/scripts/dtc/flattree.c b/scripts/dtc/flattree.c
index 8d268fb..bd6977e 100644
--- a/scripts/dtc/flattree.c
+++ b/scripts/dtc/flattree.c
@@ -1,21 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
/*
* (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation. 2005.
- *
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
- * USA
*/
#include "dtc.h"
@@ -393,7 +378,7 @@
padlen = 0;
if (quiet < 1)
fprintf(stderr,
- "Warning: blob size %d >= minimum size %d\n",
+ "Warning: blob size %"PRIu32" >= minimum size %d\n",
fdt32_to_cpu(fdt.totalsize), minsize);
}
}
@@ -525,7 +510,7 @@
fprintf(f, "/* Memory reserve map from source file */\n");
/*
- * Use .long on high and low halfs of u64s to avoid .quad
+ * Use .long on high and low halves of u64s to avoid .quad
* as it appears .quad isn't available in some assemblers.
*/
for (re = dti->reservelist; re; re = re->next) {
@@ -692,7 +677,7 @@
val = flat_read_data(dtbuf, proplen);
- return build_property(name, val);
+ return build_property(name, val, NULL);
}
@@ -750,7 +735,7 @@
char *flatname;
uint32_t val;
- node = build_node(NULL, NULL);
+ node = build_node(NULL, NULL, NULL);
flatname = flat_read_string(dtbuf);
diff --git a/scripts/dtc/fstree.c b/scripts/dtc/fstree.c
index ae7d06c..9871689 100644
--- a/scripts/dtc/fstree.c
+++ b/scripts/dtc/fstree.c
@@ -1,21 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
/*
* (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation. 2005.
- *
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
- * USA
*/
#include "dtc.h"
@@ -34,7 +19,7 @@
if (!d)
die("Couldn't opendir() \"%s\": %s\n", dirname, strerror(errno));
- tree = build_node(NULL, NULL);
+ tree = build_node(NULL, NULL, NULL);
while ((de = readdir(d)) != NULL) {
char *tmpname;
@@ -60,7 +45,8 @@
} else {
prop = build_property(xstrdup(de->d_name),
data_copy_file(pfile,
- st.st_size));
+ st.st_size),
+ NULL);
add_property(tree, prop);
fclose(pfile);
}
diff --git a/scripts/dtc/libfdt/Makefile.libfdt b/scripts/dtc/libfdt/Makefile.libfdt
index 098b3f3..e546397 100644
--- a/scripts/dtc/libfdt/Makefile.libfdt
+++ b/scripts/dtc/libfdt/Makefile.libfdt
@@ -1,3 +1,4 @@
+# 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
@@ -9,3 +10,9 @@
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 7855a17..179168e 100644
--- a/scripts/dtc/libfdt/fdt.c
+++ b/scripts/dtc/libfdt/fdt.c
@@ -1,52 +1,7 @@
+// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
/*
* libfdt - Flat Device Tree manipulation
* Copyright (C) 2006 David Gibson, IBM Corporation.
- *
- * libfdt is dual licensed: you can use it either under the terms of
- * the GPL, or the BSD license, at your option.
- *
- * a) This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public
- * License along with this library; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
- * MA 02110-1301 USA
- *
- * Alternatively,
- *
- * b) Redistribution and use in source and binary forms, with or
- * without modification, are permitted provided that the following
- * conditions are met:
- *
- * 1. Redistributions of source code must retain the above
- * copyright notice, this list of conditions and the following
- * disclaimer.
- * 2. Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials
- * provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
- * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
- * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "libfdt_env.h"
@@ -55,7 +10,12 @@
#include "libfdt_internal.h"
-int fdt_check_header(const void *fdt)
+/*
+ * Minimal sanity check for a read-only tree. fdt_ro_probe_() checks
+ * 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)
{
if (fdt_magic(fdt) == FDT_MAGIC) {
/* Complete tree */
@@ -74,6 +34,78 @@
return 0;
}
+static int check_off_(uint32_t hdrsize, uint32_t totalsize, uint32_t off)
+{
+ return (off >= hdrsize) && (off <= totalsize);
+}
+
+static int check_block_(uint32_t hdrsize, uint32_t totalsize,
+ uint32_t base, uint32_t size)
+{
+ if (!check_off_(hdrsize, totalsize, base))
+ return 0; /* block start out of bounds */
+ if ((base + size) < base)
+ return 0; /* overflow */
+ if (!check_off_(hdrsize, totalsize, base + size))
+ return 0; /* block end out of bounds */
+ return 1;
+}
+
+size_t fdt_header_size_(uint32_t version)
+{
+ if (version <= 1)
+ return FDT_V1_SIZE;
+ else if (version <= 2)
+ return FDT_V2_SIZE;
+ else if (version <= 3)
+ return FDT_V3_SIZE;
+ else if (version <= 16)
+ return FDT_V16_SIZE;
+ else
+ return FDT_V17_SIZE;
+}
+
+int fdt_check_header(const void *fdt)
+{
+ size_t hdrsize;
+
+ if (fdt_magic(fdt) != FDT_MAGIC)
+ return -FDT_ERR_BADMAGIC;
+ 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;
+
+ /* Bounds check memrsv block */
+ if (!check_off_(hdrsize, fdt_totalsize(fdt), fdt_off_mem_rsvmap(fdt)))
+ return -FDT_ERR_TRUNCATED;
+
+ /* Bounds check structure block */
+ if (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_strings(fdt), fdt_size_dt_strings(fdt)))
+ return -FDT_ERR_TRUNCATED;
+
+ return 0;
+}
+
const void *fdt_offset_ptr(const void *fdt, int offset, unsigned int len)
{
unsigned absoffset = offset + fdt_off_dt_struct(fdt);
@@ -244,7 +276,7 @@
int fdt_move(const void *fdt, void *buf, int bufsize)
{
- FDT_CHECK_HEADER(fdt);
+ FDT_RO_PROBE(fdt);
if (fdt_totalsize(fdt) > bufsize)
return -FDT_ERR_NOSPACE;
diff --git a/scripts/dtc/libfdt/fdt.h b/scripts/dtc/libfdt/fdt.h
index 74961f9..f2e6880 100644
--- a/scripts/dtc/libfdt/fdt.h
+++ b/scripts/dtc/libfdt/fdt.h
@@ -1,55 +1,10 @@
+/* SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) */
#ifndef FDT_H
#define FDT_H
/*
* libfdt - Flat Device Tree manipulation
* Copyright (C) 2006 David Gibson, IBM Corporation.
* Copyright 2012 Kim Phillips, Freescale Semiconductor.
- *
- * libfdt is dual licensed: you can use it either under the terms of
- * the GPL, or the BSD license, at your option.
- *
- * a) This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public
- * License along with this library; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
- * MA 02110-1301 USA
- *
- * Alternatively,
- *
- * b) Redistribution and use in source and binary forms, with or
- * without modification, are permitted provided that the following
- * conditions are met:
- *
- * 1. Redistributions of source code must retain the above
- * copyright notice, this list of conditions and the following
- * disclaimer.
- * 2. Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials
- * provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
- * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
- * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __ASSEMBLY__
diff --git a/scripts/dtc/libfdt/fdt_addresses.c b/scripts/dtc/libfdt/fdt_addresses.c
index eff4dbc..d8ba8ec 100644
--- a/scripts/dtc/libfdt/fdt_addresses.c
+++ b/scripts/dtc/libfdt/fdt_addresses.c
@@ -1,52 +1,8 @@
+// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
/*
* libfdt - Flat Device Tree manipulation
* Copyright (C) 2014 David Gibson <david@gibson.dropbear.id.au>
- *
- * libfdt is dual licensed: you can use it either under the terms of
- * the GPL, or the BSD license, at your option.
- *
- * a) This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public
- * License along with this library; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
- * MA 02110-1301 USA
- *
- * Alternatively,
- *
- * b) Redistribution and use in source and binary forms, with or
- * without modification, are permitted provided that the following
- * conditions are met:
- *
- * 1. Redistributions of source code must retain the above
- * copyright notice, this list of conditions and the following
- * disclaimer.
- * 2. Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials
- * provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
- * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
- * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * Copyright (C) 2018 embedded brains GmbH
*/
#include "libfdt_env.h"
@@ -55,42 +11,89 @@
#include "libfdt_internal.h"
-int fdt_address_cells(const void *fdt, int nodeoffset)
+static int fdt_cells(const void *fdt, int nodeoffset, const char *name)
{
- const fdt32_t *ac;
+ const fdt32_t *c;
int val;
int len;
- ac = fdt_getprop(fdt, nodeoffset, "#address-cells", &len);
- if (!ac)
- return 2;
+ c = fdt_getprop(fdt, nodeoffset, name, &len);
+ if (!c)
+ return len;
- if (len != sizeof(*ac))
+ if (len != sizeof(*c))
return -FDT_ERR_BADNCELLS;
- val = fdt32_to_cpu(*ac);
+ val = fdt32_to_cpu(*c);
if ((val <= 0) || (val > FDT_MAX_NCELLS))
return -FDT_ERR_BADNCELLS;
return val;
}
+int fdt_address_cells(const void *fdt, int nodeoffset)
+{
+ int val;
+
+ val = fdt_cells(fdt, nodeoffset, "#address-cells");
+ if (val == -FDT_ERR_NOTFOUND)
+ return 2;
+ return val;
+}
+
int fdt_size_cells(const void *fdt, int nodeoffset)
{
- const fdt32_t *sc;
int val;
- int len;
- sc = fdt_getprop(fdt, nodeoffset, "#size-cells", &len);
- if (!sc)
- return 2;
-
- if (len != sizeof(*sc))
- return -FDT_ERR_BADNCELLS;
-
- val = fdt32_to_cpu(*sc);
- if ((val < 0) || (val > FDT_MAX_NCELLS))
- return -FDT_ERR_BADNCELLS;
-
+ val = fdt_cells(fdt, nodeoffset, "#size-cells");
+ if (val == -FDT_ERR_NOTFOUND)
+ return 1;
return val;
}
+
+/* This function assumes that [address|size]_cells is 1 or 2 */
+int fdt_appendprop_addrrange(void *fdt, int parent, int nodeoffset,
+ const char *name, uint64_t addr, uint64_t size)
+{
+ int addr_cells, size_cells, ret;
+ uint8_t data[sizeof(fdt64_t) * 2], *prop;
+
+ ret = fdt_address_cells(fdt, parent);
+ if (ret < 0)
+ return ret;
+ addr_cells = ret;
+
+ ret = fdt_size_cells(fdt, parent);
+ if (ret < 0)
+ return ret;
+ size_cells = ret;
+
+ /* check validity of address */
+ prop = data;
+ if (addr_cells == 1) {
+ if ((addr > UINT32_MAX) || ((UINT32_MAX + 1 - addr) < size))
+ return -FDT_ERR_BADVALUE;
+
+ fdt32_st(prop, (uint32_t)addr);
+ } else if (addr_cells == 2) {
+ fdt64_st(prop, addr);
+ } else {
+ return -FDT_ERR_BADNCELLS;
+ }
+
+ /* check validity of size */
+ prop += addr_cells * sizeof(fdt32_t);
+ if (size_cells == 1) {
+ if (size > UINT32_MAX)
+ return -FDT_ERR_BADVALUE;
+
+ fdt32_st(prop, (uint32_t)size);
+ } else if (size_cells == 2) {
+ fdt64_st(prop, size);
+ } else {
+ return -FDT_ERR_BADNCELLS;
+ }
+
+ return fdt_appendprop(fdt, nodeoffset, name, data,
+ (addr_cells + size_cells) * sizeof(fdt32_t));
+}
diff --git a/scripts/dtc/libfdt/fdt_empty_tree.c b/scripts/dtc/libfdt/fdt_empty_tree.c
index f2ae9b7..49d54d4 100644
--- a/scripts/dtc/libfdt/fdt_empty_tree.c
+++ b/scripts/dtc/libfdt/fdt_empty_tree.c
@@ -1,52 +1,7 @@
+// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
/*
* libfdt - Flat Device Tree manipulation
* Copyright (C) 2012 David Gibson, IBM Corporation.
- *
- * libfdt is dual licensed: you can use it either under the terms of
- * the GPL, or the BSD license, at your option.
- *
- * a) This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public
- * License along with this library; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
- * MA 02110-1301 USA
- *
- * Alternatively,
- *
- * b) Redistribution and use in source and binary forms, with or
- * without modification, are permitted provided that the following
- * conditions are met:
- *
- * 1. Redistributions of source code must retain the above
- * copyright notice, this list of conditions and the following
- * disclaimer.
- * 2. Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials
- * provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
- * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
- * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "libfdt_env.h"
diff --git a/scripts/dtc/libfdt/fdt_overlay.c b/scripts/dtc/libfdt/fdt_overlay.c
index bf75388..e97f12b 100644
--- a/scripts/dtc/libfdt/fdt_overlay.c
+++ b/scripts/dtc/libfdt/fdt_overlay.c
@@ -1,53 +1,8 @@
+// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
/*
* libfdt - Flat Device Tree manipulation
* Copyright (C) 2016 Free Electrons
* Copyright (C) 2016 NextThing Co.
- *
- * libfdt is dual licensed: you can use it either under the terms of
- * the GPL, or the BSD license, at your option.
- *
- * a) This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public
- * License along with this library; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
- * MA 02110-1301 USA
- *
- * Alternatively,
- *
- * b) Redistribution and use in source and binary forms, with or
- * without modification, are permitted provided that the following
- * conditions are met:
- *
- * 1. Redistributions of source code must retain the above
- * copyright notice, this list of conditions and the following
- * disclaimer.
- * 2. Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials
- * provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
- * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
- * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "libfdt_env.h"
@@ -93,11 +48,11 @@
* @pathp: pointer which receives the path of the target (or NULL)
*
* overlay_get_target() retrieves the target offset in the base
- * device tree of a fragment, no matter how the actual targetting is
+ * device tree of a fragment, no matter how the actual targeting is
* done (through a phandle or a path)
*
* returns:
- * the targetted node offset in the base device tree
+ * the targeted node offset in the base device tree
* Negative error code on error
*/
static int overlay_get_target(const void *fdt, const void *fdto,
@@ -697,7 +652,7 @@
int len = 0, namelen;
const char *name;
- FDT_CHECK_HEADER(fdt);
+ FDT_RO_PROBE(fdt);
for (;;) {
name = fdt_get_name(fdt, nodeoffset, &namelen);
@@ -863,11 +818,15 @@
int fdt_overlay_apply(void *fdt, void *fdto)
{
- uint32_t delta = fdt_get_max_phandle(fdt);
+ uint32_t delta;
int ret;
- FDT_CHECK_HEADER(fdt);
- FDT_CHECK_HEADER(fdto);
+ FDT_RO_PROBE(fdt);
+ FDT_RO_PROBE(fdto);
+
+ ret = fdt_find_max_phandle(fdt, &delta);
+ if (ret)
+ goto err;
ret = overlay_adjust_local_phandles(fdto, delta);
if (ret)
diff --git a/scripts/dtc/libfdt/fdt_ro.c b/scripts/dtc/libfdt/fdt_ro.c
index dfb3236..6fd9ec1 100644
--- a/scripts/dtc/libfdt/fdt_ro.c
+++ b/scripts/dtc/libfdt/fdt_ro.c
@@ -1,52 +1,7 @@
+// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
/*
* libfdt - Flat Device Tree manipulation
* Copyright (C) 2006 David Gibson, IBM Corporation.
- *
- * libfdt is dual licensed: you can use it either under the terms of
- * the GPL, or the BSD license, at your option.
- *
- * a) This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public
- * License along with this library; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
- * MA 02110-1301 USA
- *
- * Alternatively,
- *
- * b) Redistribution and use in source and binary forms, with or
- * without modification, are permitted provided that the following
- * conditions are met:
- *
- * 1. Redistributions of source code must retain the above
- * copyright notice, this list of conditions and the following
- * disclaimer.
- * 2. Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials
- * provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
- * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
- * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "libfdt_env.h"
@@ -76,60 +31,156 @@
return 0;
}
+const char *fdt_get_string(const void *fdt, int stroffset, int *lenp)
+{
+ uint32_t absoffset = stroffset + fdt_off_dt_strings(fdt);
+ size_t len;
+ int err;
+ const char *s, *n;
+
+ err = fdt_ro_probe_(fdt);
+ if (err != 0)
+ goto fail;
+
+ err = -FDT_ERR_BADOFFSET;
+ if (absoffset >= fdt_totalsize(fdt))
+ goto fail;
+ len = fdt_totalsize(fdt) - absoffset;
+
+ if (fdt_magic(fdt) == FDT_MAGIC) {
+ if (stroffset < 0)
+ goto fail;
+ if (fdt_version(fdt) >= 17) {
+ if (stroffset >= fdt_size_dt_strings(fdt))
+ goto fail;
+ if ((fdt_size_dt_strings(fdt) - stroffset) < len)
+ len = fdt_size_dt_strings(fdt) - stroffset;
+ }
+ } else if (fdt_magic(fdt) == FDT_SW_MAGIC) {
+ if ((stroffset >= 0)
+ || (stroffset < -fdt_size_dt_strings(fdt)))
+ goto fail;
+ if ((-stroffset) < len)
+ len = -stroffset;
+ } else {
+ err = -FDT_ERR_INTERNAL;
+ goto fail;
+ }
+
+ s = (const char *)fdt + absoffset;
+ n = memchr(s, '\0', len);
+ if (!n) {
+ /* missing terminating NULL */
+ err = -FDT_ERR_TRUNCATED;
+ goto fail;
+ }
+
+ if (lenp)
+ *lenp = n - s;
+ return s;
+
+fail:
+ if (lenp)
+ *lenp = err;
+ return NULL;
+}
+
const char *fdt_string(const void *fdt, int stroffset)
{
- return (const char *)fdt + fdt_off_dt_strings(fdt) + stroffset;
+ return fdt_get_string(fdt, stroffset, NULL);
}
static int fdt_string_eq_(const void *fdt, int stroffset,
const char *s, int len)
{
- const char *p = fdt_string(fdt, stroffset);
+ int slen;
+ const char *p = fdt_get_string(fdt, stroffset, &slen);
- return (strlen(p) == len) && (memcmp(p, s, len) == 0);
+ return p && (slen == len) && (memcmp(p, s, len) == 0);
}
-uint32_t fdt_get_max_phandle(const void *fdt)
+int fdt_find_max_phandle(const void *fdt, uint32_t *phandle)
{
- uint32_t max_phandle = 0;
- int offset;
+ uint32_t max = 0;
+ int offset = -1;
- for (offset = fdt_next_node(fdt, -1, NULL);;
- offset = fdt_next_node(fdt, offset, NULL)) {
- uint32_t phandle;
+ while (true) {
+ uint32_t value;
- if (offset == -FDT_ERR_NOTFOUND)
- return max_phandle;
+ offset = fdt_next_node(fdt, offset, NULL);
+ if (offset < 0) {
+ if (offset == -FDT_ERR_NOTFOUND)
+ break;
- if (offset < 0)
- return (uint32_t)-1;
+ return offset;
+ }
- phandle = fdt_get_phandle(fdt, offset);
- if (phandle == (uint32_t)-1)
- continue;
+ value = fdt_get_phandle(fdt, offset);
- if (phandle > max_phandle)
- max_phandle = phandle;
+ if (value > max)
+ max = value;
}
+ if (phandle)
+ *phandle = max;
+
return 0;
}
+int fdt_generate_phandle(const void *fdt, uint32_t *phandle)
+{
+ uint32_t max;
+ int err;
+
+ err = fdt_find_max_phandle(fdt, &max);
+ if (err < 0)
+ return err;
+
+ if (max == FDT_MAX_PHANDLE)
+ return -FDT_ERR_NOPHANDLES;
+
+ if (phandle)
+ *phandle = max + 1;
+
+ return 0;
+}
+
+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;
+ return fdt_mem_rsv_(fdt, n);
+}
+
int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size)
{
- FDT_CHECK_HEADER(fdt);
- *address = fdt64_to_cpu(fdt_mem_rsv_(fdt, n)->address);
- *size = fdt64_to_cpu(fdt_mem_rsv_(fdt, n)->size);
+ const struct fdt_reserve_entry *re;
+
+ FDT_RO_PROBE(fdt);
+ re = fdt_mem_rsv(fdt, n);
+ if (!re)
+ return -FDT_ERR_BADOFFSET;
+
+ *address = fdt64_ld(&re->address);
+ *size = fdt64_ld(&re->size);
return 0;
}
int fdt_num_mem_rsv(const void *fdt)
{
- int i = 0;
+ int i;
+ const struct fdt_reserve_entry *re;
- while (fdt64_to_cpu(fdt_mem_rsv_(fdt, i)->size) != 0)
- i++;
- return i;
+ for (i = 0; (re = fdt_mem_rsv(fdt, i)) != NULL; i++) {
+ if (fdt64_ld(&re->size) == 0)
+ return i;
+ }
+ return -FDT_ERR_TRUNCATED;
}
static int nextprop_(const void *fdt, int offset)
@@ -161,7 +212,7 @@
{
int depth;
- FDT_CHECK_HEADER(fdt);
+ FDT_RO_PROBE(fdt);
for (depth = 0;
(offset >= 0) && (depth >= 0);
@@ -187,7 +238,7 @@
const char *p = path;
int offset = 0;
- FDT_CHECK_HEADER(fdt);
+ FDT_RO_PROBE(fdt);
/* see if we have an alias */
if (*path != '/') {
@@ -237,7 +288,7 @@
const char *nameptr;
int err;
- if (((err = fdt_check_header(fdt)) != 0)
+ if (((err = fdt_ro_probe_(fdt)) != 0)
|| ((err = fdt_check_node_offset_(fdt, nodeoffset)) < 0))
goto fail;
@@ -303,7 +354,7 @@
prop = fdt_offset_ptr_(fdt, offset);
if (lenp)
- *lenp = fdt32_to_cpu(prop->len);
+ *lenp = fdt32_ld(&prop->len);
return prop;
}
@@ -340,7 +391,7 @@
offset = -FDT_ERR_INTERNAL;
break;
}
- if (fdt_string_eq_(fdt, fdt32_to_cpu(prop->nameoff),
+ if (fdt_string_eq_(fdt, fdt32_ld(&prop->nameoff),
name, namelen)) {
if (poffset)
*poffset = offset;
@@ -393,7 +444,7 @@
/* Handle realignment */
if (fdt_version(fdt) < 0x10 && (poffset + sizeof(*prop)) % 8 &&
- fdt32_to_cpu(prop->len) >= 8)
+ fdt32_ld(&prop->len) >= 8)
return prop->data + 4;
return prop->data;
}
@@ -406,12 +457,22 @@
prop = fdt_get_property_by_offset_(fdt, offset, lenp);
if (!prop)
return NULL;
- if (namep)
- *namep = fdt_string(fdt, fdt32_to_cpu(prop->nameoff));
+ 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;
+ }
+ *namep = name;
+ }
/* Handle realignment */
if (fdt_version(fdt) < 0x10 && (offset + sizeof(*prop)) % 8 &&
- fdt32_to_cpu(prop->len) >= 8)
+ fdt32_ld(&prop->len) >= 8)
return prop->data + 4;
return prop->data;
}
@@ -436,7 +497,7 @@
return 0;
}
- return fdt32_to_cpu(*php);
+ return fdt32_ld(php);
}
const char *fdt_get_alias_namelen(const void *fdt,
@@ -462,7 +523,7 @@
int offset, depth, namelen;
const char *name;
- FDT_CHECK_HEADER(fdt);
+ FDT_RO_PROBE(fdt);
if (buflen < 2)
return -FDT_ERR_NOSPACE;
@@ -514,7 +575,7 @@
int offset, depth;
int supernodeoffset = -FDT_ERR_INTERNAL;
- FDT_CHECK_HEADER(fdt);
+ FDT_RO_PROBE(fdt);
if (supernodedepth < 0)
return -FDT_ERR_NOTFOUND;
@@ -573,7 +634,7 @@
const void *val;
int len;
- FDT_CHECK_HEADER(fdt);
+ FDT_RO_PROBE(fdt);
/* FIXME: The algorithm here is pretty horrible: we scan each
* property of a node in fdt_getprop(), then if that didn't
@@ -599,7 +660,7 @@
if ((phandle == 0) || (phandle == -1))
return -FDT_ERR_BADPHANDLE;
- FDT_CHECK_HEADER(fdt);
+ FDT_RO_PROBE(fdt);
/* FIXME: The algorithm here is pretty horrible: we
* potentially scan each property of a node in
@@ -752,7 +813,7 @@
{
int offset, err;
- FDT_CHECK_HEADER(fdt);
+ FDT_RO_PROBE(fdt);
/* FIXME: The algorithm here is pretty horrible: we scan each
* property of a node in fdt_node_check_compatible(), then if
@@ -771,3 +832,66 @@
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 9b82905..8795947 100644
--- a/scripts/dtc/libfdt/fdt_rw.c
+++ b/scripts/dtc/libfdt/fdt_rw.c
@@ -1,52 +1,7 @@
+// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
/*
* libfdt - Flat Device Tree manipulation
* Copyright (C) 2006 David Gibson, IBM Corporation.
- *
- * libfdt is dual licensed: you can use it either under the terms of
- * the GPL, or the BSD license, at your option.
- *
- * a) This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public
- * License along with this library; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
- * MA 02110-1301 USA
- *
- * Alternatively,
- *
- * b) Redistribution and use in source and binary forms, with or
- * without modification, are permitted provided that the following
- * conditions are met:
- *
- * 1. Redistributions of source code must retain the above
- * copyright notice, this list of conditions and the following
- * disclaimer.
- * 2. Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials
- * provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
- * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
- * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "libfdt_env.h"
@@ -67,9 +22,9 @@
(fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt)));
}
-static int fdt_rw_check_header_(void *fdt)
+static int fdt_rw_probe_(void *fdt)
{
- FDT_CHECK_HEADER(fdt);
+ FDT_RO_PROBE(fdt);
if (fdt_version(fdt) < 17)
return -FDT_ERR_BADVERSION;
@@ -82,10 +37,10 @@
return 0;
}
-#define FDT_RW_CHECK_HEADER(fdt) \
+#define FDT_RW_PROBE(fdt) \
{ \
int err_; \
- if ((err_ = fdt_rw_check_header_(fdt)) != 0) \
+ if ((err_ = fdt_rw_probe_(fdt)) != 0) \
return err_; \
}
@@ -136,6 +91,14 @@
return 0;
}
+/* Must only be used to roll back in case of error */
+static void fdt_del_last_string_(void *fdt, const char *s)
+{
+ int newlen = strlen(s) + 1;
+
+ fdt_set_size_dt_strings(fdt, fdt_size_dt_strings(fdt) - newlen);
+}
+
static int fdt_splice_string_(void *fdt, int newlen)
{
void *p = (char *)fdt
@@ -149,7 +112,7 @@
return 0;
}
-static int fdt_find_add_string_(void *fdt, const char *s)
+static int fdt_find_add_string_(void *fdt, const char *s, int *allocated)
{
char *strtab = (char *)fdt + fdt_off_dt_strings(fdt);
const char *p;
@@ -157,6 +120,8 @@
int len = strlen(s) + 1;
int err;
+ *allocated = 0;
+
p = fdt_find_string_(strtab, fdt_size_dt_strings(fdt), s);
if (p)
/* found it */
@@ -167,6 +132,8 @@
if (err)
return err;
+ *allocated = 1;
+
memcpy(new, s, len);
return (new - strtab);
}
@@ -176,7 +143,7 @@
struct fdt_reserve_entry *re;
int err;
- FDT_RW_CHECK_HEADER(fdt);
+ FDT_RW_PROBE(fdt);
re = fdt_mem_rsv_w_(fdt, fdt_num_mem_rsv(fdt));
err = fdt_splice_mem_rsv_(fdt, re, 0, 1);
@@ -192,7 +159,7 @@
{
struct fdt_reserve_entry *re = fdt_mem_rsv_w_(fdt, n);
- FDT_RW_CHECK_HEADER(fdt);
+ FDT_RW_PROBE(fdt);
if (n >= fdt_num_mem_rsv(fdt))
return -FDT_ERR_NOTFOUND;
@@ -225,11 +192,12 @@
int nextoffset;
int namestroff;
int err;
+ int allocated;
if ((nextoffset = fdt_check_node_offset_(fdt, nodeoffset)) < 0)
return nextoffset;
- namestroff = fdt_find_add_string_(fdt, name);
+ namestroff = fdt_find_add_string_(fdt, name, &allocated);
if (namestroff < 0)
return namestroff;
@@ -237,8 +205,11 @@
proplen = sizeof(**prop) + FDT_TAGALIGN(len);
err = fdt_splice_struct_(fdt, *prop, 0, proplen);
- if (err)
+ if (err) {
+ if (allocated)
+ fdt_del_last_string_(fdt, name);
return err;
+ }
(*prop)->tag = cpu_to_fdt32(FDT_PROP);
(*prop)->nameoff = cpu_to_fdt32(namestroff);
@@ -252,7 +223,7 @@
int oldlen, newlen;
int err;
- FDT_RW_CHECK_HEADER(fdt);
+ FDT_RW_PROBE(fdt);
namep = (char *)(uintptr_t)fdt_get_name(fdt, nodeoffset, &oldlen);
if (!namep)
@@ -275,7 +246,7 @@
struct fdt_property *prop;
int err;
- FDT_RW_CHECK_HEADER(fdt);
+ FDT_RW_PROBE(fdt);
err = fdt_resize_property_(fdt, nodeoffset, name, len, &prop);
if (err == -FDT_ERR_NOTFOUND)
@@ -308,7 +279,7 @@
struct fdt_property *prop;
int err, oldlen, newlen;
- FDT_RW_CHECK_HEADER(fdt);
+ FDT_RW_PROBE(fdt);
prop = fdt_get_property_w(fdt, nodeoffset, name, &oldlen);
if (prop) {
@@ -334,7 +305,7 @@
struct fdt_property *prop;
int len, proplen;
- FDT_RW_CHECK_HEADER(fdt);
+ FDT_RW_PROBE(fdt);
prop = fdt_get_property_w(fdt, nodeoffset, name, &len);
if (!prop)
@@ -354,7 +325,7 @@
uint32_t tag;
fdt32_t *endtag;
- FDT_RW_CHECK_HEADER(fdt);
+ FDT_RW_PROBE(fdt);
offset = fdt_subnode_offset_namelen(fdt, parentoffset, name, namelen);
if (offset >= 0)
@@ -394,7 +365,7 @@
{
int endoffset;
- FDT_RW_CHECK_HEADER(fdt);
+ FDT_RW_PROBE(fdt);
endoffset = fdt_node_end_offset_(fdt, nodeoffset);
if (endoffset < 0)
@@ -435,7 +406,7 @@
const char *fdtend = fdtstart + fdt_totalsize(fdt);
char *tmp;
- FDT_CHECK_HEADER(fdt);
+ FDT_RO_PROBE(fdt);
mem_rsv_size = (fdt_num_mem_rsv(fdt)+1)
* sizeof(struct fdt_reserve_entry);
@@ -494,7 +465,7 @@
{
int mem_rsv_size;
- FDT_RW_CHECK_HEADER(fdt);
+ FDT_RW_PROBE(fdt);
mem_rsv_size = (fdt_num_mem_rsv(fdt)+1)
* sizeof(struct fdt_reserve_entry);
diff --git a/scripts/dtc/libfdt/fdt_strerror.c b/scripts/dtc/libfdt/fdt_strerror.c
index 9677a18..768db66 100644
--- a/scripts/dtc/libfdt/fdt_strerror.c
+++ b/scripts/dtc/libfdt/fdt_strerror.c
@@ -1,51 +1,7 @@
+// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
/*
* libfdt - Flat Device Tree manipulation
* Copyright (C) 2006 David Gibson, IBM Corporation.
- *
- * libfdt is dual licensed: you can use it either under the terms of
- * the GPL, or the BSD license, at your option.
- *
- * a) This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public
- * License along with this library; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
- * MA 02110-1301 USA
- *
- * Alternatively,
- *
- * b) Redistribution and use in source and binary forms, with or
- * without modification, are permitted provided that the following
- * conditions are met:
- *
- * 1. Redistributions of source code must retain the above
- * copyright notice, this list of conditions and the following
- * disclaimer.
- * 2. Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials
- * provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
- * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "libfdt_env.h"
@@ -82,6 +38,7 @@
FDT_ERRTABENT(FDT_ERR_BADVALUE),
FDT_ERRTABENT(FDT_ERR_BADOVERLAY),
FDT_ERRTABENT(FDT_ERR_NOPHANDLES),
+ FDT_ERRTABENT(FDT_ERR_BADFLAGS),
};
#define FDT_ERRTABSIZE (sizeof(fdt_errtable) / sizeof(fdt_errtable[0]))
diff --git a/scripts/dtc/libfdt/fdt_sw.c b/scripts/dtc/libfdt/fdt_sw.c
index 6d33cc2..76bea22 100644
--- a/scripts/dtc/libfdt/fdt_sw.c
+++ b/scripts/dtc/libfdt/fdt_sw.c
@@ -1,52 +1,7 @@
+// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
/*
* libfdt - Flat Device Tree manipulation
* Copyright (C) 2006 David Gibson, IBM Corporation.
- *
- * libfdt is dual licensed: you can use it either under the terms of
- * the GPL, or the BSD license, at your option.
- *
- * a) This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public
- * License along with this library; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
- * MA 02110-1301 USA
- *
- * Alternatively,
- *
- * b) Redistribution and use in source and binary forms, with or
- * without modification, are permitted provided that the following
- * conditions are met:
- *
- * 1. Redistributions of source code must retain the above
- * copyright notice, this list of conditions and the following
- * disclaimer.
- * 2. Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials
- * provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
- * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
- * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "libfdt_env.h"
@@ -55,21 +10,83 @@
#include "libfdt_internal.h"
-static int fdt_sw_check_header_(void *fdt)
+static int fdt_sw_probe_(void *fdt)
{
- if (fdt_magic(fdt) != FDT_SW_MAGIC)
+ if (fdt_magic(fdt) == FDT_MAGIC)
+ return -FDT_ERR_BADSTATE;
+ else if (fdt_magic(fdt) != FDT_SW_MAGIC)
return -FDT_ERR_BADMAGIC;
- /* FIXME: should check more details about the header state */
return 0;
}
-#define FDT_SW_CHECK_HEADER(fdt) \
+#define FDT_SW_PROBE(fdt) \
{ \
int err; \
- if ((err = fdt_sw_check_header_(fdt)) != 0) \
+ if ((err = fdt_sw_probe_(fdt)) != 0) \
return err; \
}
+/* 'memrsv' state: Initial state after fdt_create()
+ *
+ * Allowed functions:
+ * fdt_add_reservmap_entry()
+ * fdt_finish_reservemap() [moves to 'struct' state]
+ */
+static int fdt_sw_probe_memrsv_(void *fdt)
+{
+ int err = fdt_sw_probe_(fdt);
+ if (err)
+ return err;
+
+ if (fdt_off_dt_strings(fdt) != 0)
+ return -FDT_ERR_BADSTATE;
+ return 0;
+}
+
+#define FDT_SW_PROBE_MEMRSV(fdt) \
+ { \
+ int err; \
+ if ((err = fdt_sw_probe_memrsv_(fdt)) != 0) \
+ return err; \
+ }
+
+/* 'struct' state: Enter this state after fdt_finish_reservemap()
+ *
+ * Allowed functions:
+ * fdt_begin_node()
+ * fdt_end_node()
+ * fdt_property*()
+ * fdt_finish() [moves to 'complete' state]
+ */
+static int fdt_sw_probe_struct_(void *fdt)
+{
+ int err = fdt_sw_probe_(fdt);
+ if (err)
+ return err;
+
+ if (fdt_off_dt_strings(fdt) != fdt_totalsize(fdt))
+ return -FDT_ERR_BADSTATE;
+ return 0;
+}
+
+#define FDT_SW_PROBE_STRUCT(fdt) \
+ { \
+ int err; \
+ if ((err = fdt_sw_probe_struct_(fdt)) != 0) \
+ return err; \
+ }
+
+static inline uint32_t sw_flags(void *fdt)
+{
+ /* assert: (fdt_magic(fdt) == FDT_SW_MAGIC) */
+ return fdt_last_comp_version(fdt);
+}
+
+/* 'complete' state: Enter this state after fdt_finish()
+ *
+ * Allowed functions: none
+ */
+
static void *fdt_grab_space_(void *fdt, size_t len)
{
int offset = fdt_size_dt_struct(fdt);
@@ -85,38 +102,58 @@
return fdt_offset_ptr_w_(fdt, offset);
}
-int fdt_create(void *buf, int bufsize)
+int fdt_create_with_flags(void *buf, int bufsize, uint32_t flags)
{
+ const size_t hdrsize = FDT_ALIGN(sizeof(struct fdt_header),
+ sizeof(struct fdt_reserve_entry));
void *fdt = buf;
- if (bufsize < sizeof(struct fdt_header))
+ if (bufsize < hdrsize)
return -FDT_ERR_NOSPACE;
+ if (flags & ~FDT_CREATE_FLAGS_ALL)
+ return -FDT_ERR_BADFLAGS;
+
memset(buf, 0, bufsize);
+ /*
+ * magic and last_comp_version keep intermediate state during the fdt
+ * creation process, which is replaced with the proper FDT format by
+ * fdt_finish().
+ *
+ * flags should be accessed with sw_flags().
+ */
fdt_set_magic(fdt, FDT_SW_MAGIC);
fdt_set_version(fdt, FDT_LAST_SUPPORTED_VERSION);
- fdt_set_last_comp_version(fdt, FDT_FIRST_SUPPORTED_VERSION);
+ fdt_set_last_comp_version(fdt, flags);
+
fdt_set_totalsize(fdt, bufsize);
- fdt_set_off_mem_rsvmap(fdt, FDT_ALIGN(sizeof(struct fdt_header),
- sizeof(struct fdt_reserve_entry)));
+ fdt_set_off_mem_rsvmap(fdt, hdrsize);
fdt_set_off_dt_struct(fdt, fdt_off_mem_rsvmap(fdt));
- fdt_set_off_dt_strings(fdt, bufsize);
+ fdt_set_off_dt_strings(fdt, 0);
return 0;
}
+int fdt_create(void *buf, int bufsize)
+{
+ return fdt_create_with_flags(buf, bufsize, 0);
+}
+
int fdt_resize(void *fdt, void *buf, int bufsize)
{
size_t headsize, tailsize;
char *oldtail, *newtail;
- FDT_SW_CHECK_HEADER(fdt);
+ FDT_SW_PROBE(fdt);
- headsize = fdt_off_dt_struct(fdt);
+ headsize = fdt_off_dt_struct(fdt) + fdt_size_dt_struct(fdt);
tailsize = fdt_size_dt_strings(fdt);
+ if ((headsize + tailsize) > fdt_totalsize(fdt))
+ return -FDT_ERR_INTERNAL;
+
if ((headsize + tailsize) > bufsize)
return -FDT_ERR_NOSPACE;
@@ -133,8 +170,9 @@
memmove(buf, fdt, headsize);
}
- fdt_set_off_dt_strings(buf, bufsize);
fdt_set_totalsize(buf, bufsize);
+ if (fdt_off_dt_strings(buf))
+ fdt_set_off_dt_strings(buf, bufsize);
return 0;
}
@@ -144,10 +182,7 @@
struct fdt_reserve_entry *re;
int offset;
- FDT_SW_CHECK_HEADER(fdt);
-
- if (fdt_size_dt_struct(fdt))
- return -FDT_ERR_BADSTATE;
+ FDT_SW_PROBE_MEMRSV(fdt);
offset = fdt_off_dt_struct(fdt);
if ((offset + sizeof(*re)) > fdt_totalsize(fdt))
@@ -164,16 +199,23 @@
int fdt_finish_reservemap(void *fdt)
{
- return fdt_add_reservemap_entry(fdt, 0, 0);
+ int err = fdt_add_reservemap_entry(fdt, 0, 0);
+
+ if (err)
+ return err;
+
+ fdt_set_off_dt_strings(fdt, fdt_totalsize(fdt));
+ return 0;
}
int fdt_begin_node(void *fdt, const char *name)
{
struct fdt_node_header *nh;
- int namelen = strlen(name) + 1;
+ int namelen;
- FDT_SW_CHECK_HEADER(fdt);
+ FDT_SW_PROBE_STRUCT(fdt);
+ namelen = strlen(name) + 1;
nh = fdt_grab_space_(fdt, sizeof(*nh) + FDT_TAGALIGN(namelen));
if (! nh)
return -FDT_ERR_NOSPACE;
@@ -187,7 +229,7 @@
{
fdt32_t *en;
- FDT_SW_CHECK_HEADER(fdt);
+ FDT_SW_PROBE_STRUCT(fdt);
en = fdt_grab_space_(fdt, FDT_TAGSIZE);
if (! en)
@@ -197,19 +239,13 @@
return 0;
}
-static int fdt_find_add_string_(void *fdt, const char *s)
+static int fdt_add_string_(void *fdt, const char *s)
{
char *strtab = (char *)fdt + fdt_totalsize(fdt);
- const char *p;
int strtabsize = fdt_size_dt_strings(fdt);
int len = strlen(s) + 1;
int struct_top, offset;
- p = fdt_find_string_(strtab - strtabsize, strtabsize, s);
- if (p)
- return p - strtab;
-
- /* Add it */
offset = -strtabsize - len;
struct_top = fdt_off_dt_struct(fdt) + fdt_size_dt_struct(fdt);
if (fdt_totalsize(fdt) + offset < struct_top)
@@ -220,20 +256,56 @@
return offset;
}
+/* Must only be used to roll back in case of error */
+static void fdt_del_last_string_(void *fdt, const char *s)
+{
+ int strtabsize = fdt_size_dt_strings(fdt);
+ int len = strlen(s) + 1;
+
+ fdt_set_size_dt_strings(fdt, strtabsize - len);
+}
+
+static int fdt_find_add_string_(void *fdt, const char *s, int *allocated)
+{
+ char *strtab = (char *)fdt + fdt_totalsize(fdt);
+ int strtabsize = fdt_size_dt_strings(fdt);
+ const char *p;
+
+ *allocated = 0;
+
+ p = fdt_find_string_(strtab - strtabsize, strtabsize, s);
+ if (p)
+ return p - strtab;
+
+ *allocated = 1;
+
+ return fdt_add_string_(fdt, s);
+}
+
int fdt_property_placeholder(void *fdt, const char *name, int len, void **valp)
{
struct fdt_property *prop;
int nameoff;
+ int allocated;
- FDT_SW_CHECK_HEADER(fdt);
+ FDT_SW_PROBE_STRUCT(fdt);
- nameoff = fdt_find_add_string_(fdt, name);
+ /* String de-duplication can be slow, _NO_NAME_DEDUP skips it */
+ if (sw_flags(fdt) & FDT_CREATE_FLAG_NO_NAME_DEDUP) {
+ allocated = 1;
+ nameoff = fdt_add_string_(fdt, name);
+ } else {
+ nameoff = fdt_find_add_string_(fdt, name, &allocated);
+ }
if (nameoff == 0)
return -FDT_ERR_NOSPACE;
prop = fdt_grab_space_(fdt, sizeof(*prop) + FDT_TAGALIGN(len));
- if (! prop)
+ if (! prop) {
+ if (allocated)
+ fdt_del_last_string_(fdt, name);
return -FDT_ERR_NOSPACE;
+ }
prop->tag = cpu_to_fdt32(FDT_PROP);
prop->nameoff = cpu_to_fdt32(nameoff);
@@ -262,7 +334,7 @@
uint32_t tag;
int offset, nextoffset;
- FDT_SW_CHECK_HEADER(fdt);
+ FDT_SW_PROBE_STRUCT(fdt);
/* Add terminator */
end = fdt_grab_space_(fdt, sizeof(*end));
@@ -295,6 +367,10 @@
/* Finally, adjust the header */
fdt_set_totalsize(fdt, newstroffset + fdt_size_dt_strings(fdt));
+
+ /* And fix up fields that were keeping intermediate state. */
+ fdt_set_last_comp_version(fdt, FDT_FIRST_SUPPORTED_VERSION);
fdt_set_magic(fdt, FDT_MAGIC);
+
return 0;
}
diff --git a/scripts/dtc/libfdt/fdt_wip.c b/scripts/dtc/libfdt/fdt_wip.c
index 534c1cb..f64139e 100644
--- a/scripts/dtc/libfdt/fdt_wip.c
+++ b/scripts/dtc/libfdt/fdt_wip.c
@@ -1,52 +1,7 @@
+// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
/*
* libfdt - Flat Device Tree manipulation
* Copyright (C) 2006 David Gibson, IBM Corporation.
- *
- * libfdt is dual licensed: you can use it either under the terms of
- * the GPL, or the BSD license, at your option.
- *
- * a) This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public
- * License along with this library; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
- * MA 02110-1301 USA
- *
- * Alternatively,
- *
- * b) Redistribution and use in source and binary forms, with or
- * without modification, are permitted provided that the following
- * conditions are met:
- *
- * 1. Redistributions of source code must retain the above
- * copyright notice, this list of conditions and the following
- * disclaimer.
- * 2. Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials
- * provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
- * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
- * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "libfdt_env.h"
diff --git a/scripts/dtc/libfdt/libfdt.h b/scripts/dtc/libfdt/libfdt.h
index 1e27780..7b5ffd1 100644
--- a/scripts/dtc/libfdt/libfdt.h
+++ b/scripts/dtc/libfdt/libfdt.h
@@ -1,54 +1,9 @@
+/* SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) */
#ifndef LIBFDT_H
#define LIBFDT_H
/*
* libfdt - Flat Device Tree manipulation
* Copyright (C) 2006 David Gibson, IBM Corporation.
- *
- * libfdt is dual licensed: you can use it either under the terms of
- * the GPL, or the BSD license, at your option.
- *
- * a) This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public
- * License along with this library; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
- * MA 02110-1301 USA
- *
- * Alternatively,
- *
- * b) Redistribution and use in source and binary forms, with or
- * without modification, are permitted provided that the following
- * conditions are met:
- *
- * 1. Redistributions of source code must retain the above
- * copyright notice, this list of conditions and the following
- * disclaimer.
- * 2. Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials
- * provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
- * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
- * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "libfdt_env.h"
@@ -90,8 +45,9 @@
/* Error codes: codes for bad device tree blobs */
#define FDT_ERR_TRUNCATED 8
- /* FDT_ERR_TRUNCATED: Structure block of the given device tree
- * ends without an FDT_END tag. */
+ /* FDT_ERR_TRUNCATED: FDT or a sub-block is improperly
+ * terminated (overflows, goes outside allowed bounds, or
+ * isn't properly terminated). */
#define FDT_ERR_BADMAGIC 9
/* FDT_ERR_BADMAGIC: Given "device tree" appears not to be a
* device tree at all - it is missing the flattened device
@@ -137,7 +93,15 @@
/* FDT_ERR_NOPHANDLES: The device tree doesn't have any
* phandle available anymore without causing an overflow */
-#define FDT_ERR_MAX 17
+#define FDT_ERR_BADFLAGS 18
+ /* FDT_ERR_BADFLAGS: The function was passed a flags field that
+ * contains invalid flags or an invalid combination of flags. */
+
+#define FDT_ERR_MAX 18
+
+/* constants */
+#define FDT_MAX_PHANDLE 0xfffffffe
+ /* Valid values for phandles range from 1 to 2^32-2. */
/**********************************************************************/
/* Low-level functions (you probably don't need these) */
@@ -153,6 +117,61 @@
uint32_t fdt_next_tag(const void *fdt, int offset, int *nextoffset);
+/*
+ * Alignment helpers:
+ * These helpers access words from a device tree blob. They're
+ * built to work even with unaligned pointers on platforms (ike
+ * ARM) that don't like unaligned loads and stores
+ */
+
+static inline uint32_t fdt32_ld(const fdt32_t *p)
+{
+ const uint8_t *bp = (const uint8_t *)p;
+
+ return ((uint32_t)bp[0] << 24)
+ | ((uint32_t)bp[1] << 16)
+ | ((uint32_t)bp[2] << 8)
+ | bp[3];
+}
+
+static inline void fdt32_st(void *property, uint32_t value)
+{
+ uint8_t *bp = property;
+
+ bp[0] = value >> 24;
+ bp[1] = (value >> 16) & 0xff;
+ bp[2] = (value >> 8) & 0xff;
+ bp[3] = value & 0xff;
+}
+
+static inline uint64_t fdt64_ld(const fdt64_t *p)
+{
+ const uint8_t *bp = (const uint8_t *)p;
+
+ return ((uint64_t)bp[0] << 56)
+ | ((uint64_t)bp[1] << 48)
+ | ((uint64_t)bp[2] << 40)
+ | ((uint64_t)bp[3] << 32)
+ | ((uint64_t)bp[4] << 24)
+ | ((uint64_t)bp[5] << 16)
+ | ((uint64_t)bp[6] << 8)
+ | bp[7];
+}
+
+static inline void fdt64_st(void *property, uint64_t value)
+{
+ uint8_t *bp = property;
+
+ bp[0] = value >> 56;
+ bp[1] = (value >> 48) & 0xff;
+ bp[2] = (value >> 40) & 0xff;
+ bp[3] = (value >> 32) & 0xff;
+ bp[4] = (value >> 24) & 0xff;
+ bp[5] = (value >> 16) & 0xff;
+ bp[6] = (value >> 8) & 0xff;
+ bp[7] = value & 0xff;
+}
+
/**********************************************************************/
/* Traversal functions */
/**********************************************************************/
@@ -195,7 +214,7 @@
* ...
* }
*
- * if ((node < 0) && (node != -FDT_ERR_NOT_FOUND)) {
+ * if ((node < 0) && (node != -FDT_ERR_NOTFOUND)) {
* Error handling
* }
*
@@ -213,7 +232,7 @@
/* General functions */
/**********************************************************************/
#define fdt_get_header(fdt, field) \
- (fdt32_to_cpu(((const struct fdt_header *)(fdt))->field))
+ (fdt32_ld(&((const struct fdt_header *)(fdt))->field))
#define fdt_magic(fdt) (fdt_get_header(fdt, magic))
#define fdt_totalsize(fdt) (fdt_get_header(fdt, totalsize))
#define fdt_off_dt_struct(fdt) (fdt_get_header(fdt, off_dt_struct))
@@ -244,18 +263,31 @@
#undef fdt_set_hdr_
/**
- * fdt_check_header - sanity check a device tree or possible device tree
+ * fdt_header_size - return the size of the tree's header
+ * @fdt: pointer to a flattened device tree
+ */
+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
+
* @fdt: pointer to data which might be a flattened device tree
*
* fdt_check_header() checks that the given buffer contains what
- * appears to be a flattened device tree with sane information in its
- * header.
+ * appears to be a flattened device tree, and that the header contains
+ * valid information (to the extent that can be determined from the
+ * header alone).
*
* returns:
* 0, if the buffer appears to contain a valid device tree
* -FDT_ERR_BADMAGIC,
* -FDT_ERR_BADVERSION,
- * -FDT_ERR_BADSTATE, standard meanings, as above
+ * -FDT_ERR_BADSTATE,
+ * -FDT_ERR_TRUNCATED, standard meanings, as above
*/
int fdt_check_header(const void *fdt);
@@ -284,6 +316,24 @@
/* Read-only functions */
/**********************************************************************/
+int fdt_check_full(const void *fdt, size_t bufsize);
+
+/**
+ * fdt_get_string - retrieve a string from the strings block of a device tree
+ * @fdt: pointer to the device tree blob
+ * @stroffset: offset of the string within the strings block (native endian)
+ * @lenp: optional pointer to return the string's length
+ *
+ * fdt_get_string() retrieves a pointer to a single string from the
+ * strings block of the device tree blob at fdt, and optionally also
+ * returns the string's length in *lenp.
+ *
+ * returns:
+ * a pointer to the string, on success
+ * NULL, if stroffset is out of bounds, or doesn't point to a valid string
+ */
+const char *fdt_get_string(const void *fdt, int stroffset, int *lenp);
+
/**
* fdt_string - retrieve a string from the strings block of a device tree
* @fdt: pointer to the device tree blob
@@ -294,11 +344,25 @@
*
* returns:
* a pointer to the string, on success
- * NULL, if stroffset is out of bounds
+ * NULL, if stroffset is out of bounds, or doesn't point to a valid string
*/
const char *fdt_string(const void *fdt, int stroffset);
/**
+ * fdt_find_max_phandle - find and return the highest phandle in a tree
+ * @fdt: pointer to the device tree blob
+ * @phandle: return location for the highest phandle value found in the tree
+ *
+ * fdt_find_max_phandle() finds the highest phandle value in the given device
+ * tree. The value returned in @phandle is only valid if the function returns
+ * success.
+ *
+ * returns:
+ * 0 on success or a negative error code on failure
+ */
+int fdt_find_max_phandle(const void *fdt, uint32_t *phandle);
+
+/**
* fdt_get_max_phandle - retrieves the highest phandle in a tree
* @fdt: pointer to the device tree blob
*
@@ -306,12 +370,39 @@
* device tree. This will ignore badly formatted phandles, or phandles
* with a value of 0 or -1.
*
+ * This function is deprecated in favour of fdt_find_max_phandle().
+ *
* returns:
* the highest phandle on success
* 0, if no phandle was found in the device tree
* -1, if an error occurred
*/
-uint32_t fdt_get_max_phandle(const void *fdt);
+static inline uint32_t fdt_get_max_phandle(const void *fdt)
+{
+ uint32_t phandle;
+ int err;
+
+ err = fdt_find_max_phandle(fdt, &phandle);
+ if (err < 0)
+ return (uint32_t)-1;
+
+ return phandle;
+}
+
+/**
+ * fdt_generate_phandle - return a new, unused phandle for a device tree blob
+ * @fdt: pointer to the device tree blob
+ * @phandle: return location for the new phandle
+ *
+ * Walks the device tree blob and looks for the highest phandle value. On
+ * success, the new, unused phandle value (one higher than the previously
+ * highest phandle value in the device tree blob) will be returned in the
+ * @phandle parameter.
+ *
+ * Returns:
+ * 0 on success or a negative error-code on failure
+ */
+int fdt_generate_phandle(const void *fdt, uint32_t *phandle);
/**
* fdt_num_mem_rsv - retrieve the number of memory reserve map entries
@@ -503,7 +594,7 @@
* ...
* }
*
- * if ((property < 0) && (property != -FDT_ERR_NOT_FOUND)) {
+ * if ((property < 0) && (property != -FDT_ERR_NOTFOUND)) {
* Error handling
* }
*
@@ -606,7 +697,7 @@
/**
* fdt_getprop_by_offset - retrieve the value of a property at a given offset
* @fdt: pointer to the device tree blob
- * @ffset: offset of the property to read
+ * @offset: offset of the property to read
* @namep: pointer to a string variable (will be overwritten) or NULL
* @lenp: pointer to an integer variable (will be overwritten) or NULL
*
@@ -1090,7 +1181,7 @@
*
* returns:
* 0 <= n < FDT_MAX_NCELLS, on success
- * 2, if the node has no #address-cells property
+ * 1, if the node has no #size-cells property
* -FDT_ERR_BADNCELLS, if the node has a badly formatted or invalid
* #size-cells property
* -FDT_ERR_BADMAGIC,
@@ -1297,7 +1388,45 @@
/* Sequential write functions */
/**********************************************************************/
+/* fdt_create_with_flags flags */
+#define FDT_CREATE_FLAG_NO_NAME_DEDUP 0x1
+ /* FDT_CREATE_FLAG_NO_NAME_DEDUP: Do not try to de-duplicate property
+ * names in the fdt. This can result in faster creation times, but
+ * a larger fdt. */
+
+#define FDT_CREATE_FLAGS_ALL (FDT_CREATE_FLAG_NO_NAME_DEDUP)
+
+/**
+ * fdt_create_with_flags - begin creation of a new fdt
+ * @fdt: pointer to memory allocated where fdt will be created
+ * @bufsize: size of the memory space at fdt
+ * @flags: a valid combination of FDT_CREATE_FLAG_ flags, or 0.
+ *
+ * fdt_create_with_flags() begins the process of creating a new fdt with
+ * the sequential write interface.
+ *
+ * fdt creation process must end with fdt_finished() to produce a valid fdt.
+ *
+ * returns:
+ * 0, on success
+ * -FDT_ERR_NOSPACE, bufsize is insufficient for a minimal fdt
+ * -FDT_ERR_BADFLAGS, flags is not valid
+ */
+int fdt_create_with_flags(void *buf, int bufsize, uint32_t flags);
+
+/**
+ * fdt_create - begin creation of a new fdt
+ * @fdt: pointer to memory allocated where fdt will be created
+ * @bufsize: size of the memory space at fdt
+ *
+ * fdt_create() is equivalent to fdt_create_with_flags() with flags=0.
+ *
+ * returns:
+ * 0, on success
+ * -FDT_ERR_NOSPACE, bufsize is insufficient for a minimal fdt
+ */
int fdt_create(void *buf, int bufsize);
+
int fdt_resize(void *fdt, void *buf, int bufsize);
int fdt_add_reservemap_entry(void *fdt, uint64_t addr, uint64_t size);
int fdt_finish_reservemap(void *fdt);
@@ -1313,10 +1442,13 @@
fdt64_t tmp = cpu_to_fdt64(val);
return fdt_property(fdt, name, &tmp, sizeof(tmp));
}
+
+#ifndef SWIG /* Not available in Python */
static inline int fdt_property_cell(void *fdt, const char *name, uint32_t val)
{
return fdt_property_u32(fdt, name, val);
}
+#endif
/**
* fdt_property_placeholder - add a new property and return a ptr to its value
@@ -1766,6 +1898,43 @@
fdt_appendprop((fdt), (nodeoffset), (name), (str), strlen(str)+1)
/**
+ * fdt_appendprop_addrrange - append a address range property
+ * @fdt: pointer to the device tree blob
+ * @parent: offset of the parent node
+ * @nodeoffset: offset of the node to add a property at
+ * @name: name of property
+ * @addr: start address of a given range
+ * @size: size of a given range
+ *
+ * fdt_appendprop_addrrange() appends an address range value (start
+ * address and size) to the value of the named property in the given
+ * node, or creates a new property with that value if it does not
+ * already exist.
+ * If "name" is not specified, a default "reg" is used.
+ * Cell sizes are determined by parent's #address-cells and #size-cells.
+ *
+ * This function may insert data into the blob, and will therefore
+ * change the offsets of some existing nodes.
+ *
+ * returns:
+ * 0, on success
+ * -FDT_ERR_BADLAYOUT,
+ * -FDT_ERR_BADMAGIC,
+ * -FDT_ERR_BADNCELLS, if the node has a badly formatted or invalid
+ * #address-cells property
+ * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
+ * -FDT_ERR_BADSTATE,
+ * -FDT_ERR_BADSTRUCTURE,
+ * -FDT_ERR_BADVERSION,
+ * -FDT_ERR_BADVALUE, addr or size doesn't fit to respective cells size
+ * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to
+ * contain a new property
+ * -FDT_ERR_TRUNCATED, standard meanings
+ */
+int fdt_appendprop_addrrange(void *fdt, int parent, int nodeoffset,
+ const char *name, uint64_t addr, uint64_t size);
+
+/**
* fdt_delprop - delete a property
* @fdt: pointer to the device tree blob
* @nodeoffset: offset of the node whose property to nop
diff --git a/scripts/dtc/libfdt/libfdt_env.h b/scripts/dtc/libfdt/libfdt_env.h
index bd24746..73b6d40 100644
--- a/scripts/dtc/libfdt/libfdt_env.h
+++ b/scripts/dtc/libfdt/libfdt_env.h
@@ -1,61 +1,18 @@
+/* SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) */
#ifndef LIBFDT_ENV_H
#define LIBFDT_ENV_H
/*
* libfdt - Flat Device Tree manipulation
* Copyright (C) 2006 David Gibson, IBM Corporation.
* Copyright 2012 Kim Phillips, Freescale Semiconductor.
- *
- * libfdt is dual licensed: you can use it either under the terms of
- * the GPL, or the BSD license, at your option.
- *
- * a) This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public
- * License along with this library; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
- * MA 02110-1301 USA
- *
- * Alternatively,
- *
- * b) Redistribution and use in source and binary forms, with or
- * without modification, are permitted provided that the following
- * conditions are met:
- *
- * 1. Redistributions of source code must retain the above
- * copyright notice, this list of conditions and the following
- * disclaimer.
- * 2. Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials
- * provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
- * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
- * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
+#include <limits.h>
#ifdef __CHECKER__
#define FDT_FORCE __attribute__((force))
diff --git a/scripts/dtc/libfdt/libfdt_internal.h b/scripts/dtc/libfdt/libfdt_internal.h
index 7681e19..7830e55 100644
--- a/scripts/dtc/libfdt/libfdt_internal.h
+++ b/scripts/dtc/libfdt/libfdt_internal.h
@@ -1,64 +1,20 @@
+/* SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) */
#ifndef LIBFDT_INTERNAL_H
#define LIBFDT_INTERNAL_H
/*
* libfdt - Flat Device Tree manipulation
* Copyright (C) 2006 David Gibson, IBM Corporation.
- *
- * libfdt is dual licensed: you can use it either under the terms of
- * the GPL, or the BSD license, at your option.
- *
- * a) This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public
- * License along with this library; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
- * MA 02110-1301 USA
- *
- * Alternatively,
- *
- * b) Redistribution and use in source and binary forms, with or
- * without modification, are permitted provided that the following
- * conditions are met:
- *
- * 1. Redistributions of source code must retain the above
- * copyright notice, this list of conditions and the following
- * disclaimer.
- * 2. Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials
- * provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
- * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
- * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <fdt.h>
#define FDT_ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1))
#define FDT_TAGALIGN(x) (FDT_ALIGN((x), FDT_TAGSIZE))
-#define FDT_CHECK_HEADER(fdt) \
+int fdt_ro_probe_(const void *fdt);
+#define FDT_RO_PROBE(fdt) \
{ \
int err_; \
- if ((err_ = fdt_check_header(fdt)) != 0) \
+ if ((err_ = fdt_ro_probe_(fdt)) != 0) \
return err_; \
}
diff --git a/scripts/dtc/livetree.c b/scripts/dtc/livetree.c
index 6e4c367..0c03999 100644
--- a/scripts/dtc/livetree.c
+++ b/scripts/dtc/livetree.c
@@ -1,24 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
/*
* (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation. 2005.
- *
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
- * USA
*/
#include "dtc.h"
+#include "srcpos.h"
/*
* Tree building functions
@@ -50,7 +36,8 @@
label->deleted = 1;
}
-struct property *build_property(char *name, struct data val)
+struct property *build_property(char *name, struct data val,
+ struct srcpos *srcpos)
{
struct property *new = xmalloc(sizeof(*new));
@@ -58,6 +45,7 @@
new->name = name;
new->val = val;
+ new->srcpos = srcpos_copy(srcpos);
return new;
}
@@ -97,7 +85,8 @@
return head;
}
-struct node *build_node(struct property *proplist, struct node *children)
+struct node *build_node(struct property *proplist, struct node *children,
+ struct srcpos *srcpos)
{
struct node *new = xmalloc(sizeof(*new));
struct node *child;
@@ -106,6 +95,7 @@
new->proplist = reverse_properties(proplist);
new->children = children;
+ new->srcpos = srcpos_copy(srcpos);
for_each_child(new, child) {
child->parent = new;
@@ -114,13 +104,14 @@
return new;
}
-struct node *build_node_delete(void)
+struct node *build_node_delete(struct srcpos *srcpos)
{
struct node *new = xmalloc(sizeof(*new));
memset(new, 0, sizeof(*new));
new->deleted = 1;
+ new->srcpos = srcpos_copy(srcpos);
return new;
}
@@ -183,6 +174,8 @@
old_prop->val = new_prop->val;
old_prop->deleted = 0;
+ free(old_prop->srcpos);
+ old_prop->srcpos = new_prop->srcpos;
free(new_prop);
new_prop = NULL;
break;
@@ -223,6 +216,8 @@
add_child(old_node, new_child);
}
+ old_node->srcpos = srcpos_extend(old_node->srcpos, new_node->srcpos);
+
/* The new node contents are now merged into the old node. Free
* the new node. */
free(new_node);
@@ -239,20 +234,21 @@
char *name;
if (ref[0] == '/') {
+ d = data_add_marker(d, TYPE_STRING, ref);
d = data_append_data(d, ref, strlen(ref) + 1);
- p = build_property("target-path", d);
+ p = build_property("target-path", d, NULL);
} else {
d = data_add_marker(d, REF_PHANDLE, ref);
d = data_append_integer(d, 0xffffffff, 32);
- p = build_property("target", d);
+ p = build_property("target", d, NULL);
}
xasprintf(&name, "fragment@%u",
next_orphan_fragment++);
name_node(new_node, "__overlay__");
- node = build_node(p, new_node);
+ node = build_node(p, new_node, NULL);
name_node(node, name);
add_child(dt, node);
@@ -340,18 +336,21 @@
}
void append_to_property(struct node *node,
- char *name, const void *data, int len)
+ char *name, const void *data, int len,
+ enum markertype type)
{
struct data d;
struct property *p;
p = get_property(node, name);
if (p) {
- d = data_append_data(p->val, data, len);
+ d = data_add_marker(p->val, type, name);
+ d = data_append_data(d, data, len);
p->val = d;
} else {
- d = data_append_data(empty_data, data, len);
- p = build_property(name, d);
+ d = data_add_marker(empty_data, type, name);
+ d = data_append_data(d, data, len);
+ p = build_property(name, d, NULL);
add_property(node, p);
}
}
@@ -594,6 +593,7 @@
cell_t get_node_phandle(struct node *root, struct node *node)
{
static cell_t phandle = 1; /* FIXME: ick, static local */
+ struct data d = empty_data;
if ((node->phandle != 0) && (node->phandle != -1))
return node->phandle;
@@ -603,17 +603,16 @@
node->phandle = phandle;
+ d = data_add_marker(d, TYPE_UINT32, NULL);
+ d = data_append_cell(d, phandle);
+
if (!get_property(node, "linux,phandle")
&& (phandle_format & PHANDLE_LEGACY))
- add_property(node,
- build_property("linux,phandle",
- data_append_cell(empty_data, phandle)));
+ add_property(node, build_property("linux,phandle", d, NULL));
if (!get_property(node, "phandle")
&& (phandle_format & PHANDLE_EPAPR))
- add_property(node,
- build_property("phandle",
- data_append_cell(empty_data, phandle)));
+ add_property(node, build_property("phandle", d, NULL));
/* If the node *does* have a phandle property, we must
* be dealing with a self-referencing phandle, which will be
@@ -787,7 +786,7 @@
{
struct node *node;
- node = build_node(NULL, NULL);
+ node = build_node(NULL, NULL, NULL);
name_node(node, xstrdup(name));
add_child(parent, node);
@@ -848,8 +847,9 @@
/* insert it */
p = build_property(l->label,
- data_copy_mem(node->fullpath,
- strlen(node->fullpath) + 1));
+ data_copy_escape_string(node->fullpath,
+ strlen(node->fullpath)),
+ NULL);
add_property(an, p);
}
@@ -899,7 +899,7 @@
xasprintf(&entry, "%s:%s:%u",
node->fullpath, prop->name, m->offset);
- append_to_property(fn, m->ref, entry, strlen(entry) + 1);
+ append_to_property(fn, m->ref, entry, strlen(entry) + 1, TYPE_STRING);
free(entry);
}
@@ -959,7 +959,7 @@
char **compp;
int i, depth;
- /* walk back retreiving depth */
+ /* walk back retrieving depth */
depth = 0;
for (wn = node; wn; wn = wn->parent)
depth++;
@@ -982,7 +982,7 @@
free(compp);
value_32 = cpu_to_fdt32(m->offset);
- append_to_property(wn, prop->name, &value_32, sizeof(value_32));
+ append_to_property(wn, prop->name, &value_32, sizeof(value_32), TYPE_UINT32);
}
static void generate_local_fixups_tree_internal(struct dt_info *dti,
diff --git a/scripts/dtc/srcpos.c b/scripts/dtc/srcpos.c
index cb6ed0e..f5205fb 100644
--- a/scripts/dtc/srcpos.c
+++ b/scripts/dtc/srcpos.c
@@ -1,20 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright 2007 Jon Loeliger, Freescale Semiconductor, Inc.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
- * USA
*/
#define _GNU_SOURCE
@@ -33,6 +19,9 @@
/* This is the list of directories that we search for source files */
static struct search_path *search_path_head, **search_path_tail;
+/* Detect infinite include recursion. */
+#define MAX_SRCFILE_DEPTH (100)
+static int srcfile_depth; /* = 0 */
static char *get_dirname(const char *path)
{
@@ -51,11 +40,51 @@
FILE *depfile; /* = NULL */
struct srcfile_state *current_srcfile; /* = NULL */
+static char *initial_path; /* = NULL */
+static int initial_pathlen; /* = 0 */
+static bool initial_cpp = true;
-/* Detect infinite include recursion. */
-#define MAX_SRCFILE_DEPTH (100)
-static int srcfile_depth; /* = 0 */
+static void set_initial_path(char *fname)
+{
+ int i, len = strlen(fname);
+ xasprintf(&initial_path, "%s", fname);
+ initial_pathlen = 0;
+ for (i = 0; i != len; i++)
+ if (initial_path[i] == '/')
+ initial_pathlen++;
+}
+
+static char *shorten_to_initial_path(char *fname)
+{
+ char *p1, *p2, *prevslash1 = NULL;
+ int slashes = 0;
+
+ for (p1 = fname, p2 = initial_path; *p1 && *p2; p1++, p2++) {
+ if (*p1 != *p2)
+ break;
+ if (*p1 == '/') {
+ prevslash1 = p1;
+ slashes++;
+ }
+ }
+ p1 = prevslash1 + 1;
+ if (prevslash1) {
+ int diff = initial_pathlen - slashes, i, j;
+ int restlen = strlen(fname) - (p1 - fname);
+ char *res;
+
+ res = xmalloc((3 * diff) + restlen + 1);
+ for (i = 0, j = 0; i != diff; i++) {
+ res[j++] = '.';
+ res[j++] = '.';
+ res[j++] = '/';
+ }
+ strcpy(res + j, p1);
+ return res;
+ }
+ return NULL;
+}
/**
* Try to open a file in a given directory.
@@ -157,6 +186,9 @@
srcfile->colno = 1;
current_srcfile = srcfile;
+
+ if (srcfile_depth == 1)
+ set_initial_path(srcfile->name);
}
bool srcfile_pop(void)
@@ -197,18 +229,6 @@
search_path_tail = &node->next;
}
-/*
- * The empty source position.
- */
-
-struct srcpos srcpos_empty = {
- .first_line = 0,
- .first_column = 0,
- .last_line = 0,
- .last_column = 0,
- .file = NULL,
-};
-
void srcpos_update(struct srcpos *pos, const char *text, int len)
{
int i;
@@ -234,13 +254,35 @@
srcpos_copy(struct srcpos *pos)
{
struct srcpos *pos_new;
+ struct srcfile_state *srcfile_state;
+
+ if (!pos)
+ return NULL;
pos_new = xmalloc(sizeof(struct srcpos));
+ assert(pos->next == NULL);
memcpy(pos_new, pos, sizeof(struct srcpos));
+ /* allocate without free */
+ srcfile_state = xmalloc(sizeof(struct srcfile_state));
+ memcpy(srcfile_state, pos->file, sizeof(struct srcfile_state));
+ pos_new->file = srcfile_state;
+
return pos_new;
}
+struct srcpos *srcpos_extend(struct srcpos *pos, struct srcpos *newtail)
+{
+ struct srcpos *p;
+
+ if (!pos)
+ return newtail;
+
+ for (p = pos; p->next != NULL; p = p->next);
+ p->next = newtail;
+ return pos;
+}
+
char *
srcpos_string(struct srcpos *pos)
{
@@ -266,6 +308,68 @@
return pos_str;
}
+static char *
+srcpos_string_comment(struct srcpos *pos, bool first_line, int level)
+{
+ char *pos_str, *fname, *first, *rest;
+ bool fresh_fname = false;
+
+ if (!pos) {
+ if (level > 1) {
+ xasprintf(&pos_str, "<no-file>:<no-line>");
+ return pos_str;
+ } else {
+ return NULL;
+ }
+ }
+
+ if (!pos->file)
+ fname = "<no-file>";
+ else if (!pos->file->name)
+ fname = "<no-filename>";
+ else if (level > 1)
+ fname = pos->file->name;
+ else {
+ fname = shorten_to_initial_path(pos->file->name);
+ if (fname)
+ fresh_fname = true;
+ else
+ fname = pos->file->name;
+ }
+
+ if (level > 1)
+ xasprintf(&first, "%s:%d:%d-%d:%d", fname,
+ pos->first_line, pos->first_column,
+ pos->last_line, pos->last_column);
+ else
+ xasprintf(&first, "%s:%d", fname,
+ first_line ? pos->first_line : pos->last_line);
+
+ if (fresh_fname)
+ free(fname);
+
+ if (pos->next != NULL) {
+ rest = srcpos_string_comment(pos->next, first_line, level);
+ xasprintf(&pos_str, "%s, %s", first, rest);
+ free(first);
+ free(rest);
+ } else {
+ pos_str = first;
+ }
+
+ return pos_str;
+}
+
+char *srcpos_string_first(struct srcpos *pos, int level)
+{
+ return srcpos_string_comment(pos, true, level);
+}
+
+char *srcpos_string_last(struct srcpos *pos, int level)
+{
+ return srcpos_string_comment(pos, false, level);
+}
+
void srcpos_verror(struct srcpos *pos, const char *prefix,
const char *fmt, va_list va)
{
@@ -294,4 +398,9 @@
{
current_srcfile->name = f;
current_srcfile->lineno = l;
+
+ if (initial_cpp) {
+ initial_cpp = false;
+ set_initial_path(f);
+ }
}
diff --git a/scripts/dtc/srcpos.h b/scripts/dtc/srcpos.h
index 9ded12a..4318d7a 100644
--- a/scripts/dtc/srcpos.h
+++ b/scripts/dtc/srcpos.h
@@ -1,20 +1,6 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
* Copyright 2007 Jon Loeliger, Freescale Semiconductor, Inc.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
- * USA
*/
#ifndef SRCPOS_H
@@ -74,6 +60,7 @@
int last_line;
int last_column;
struct srcfile_state *file;
+ struct srcpos *next;
};
#define YYLTYPE struct srcpos
@@ -93,19 +80,18 @@
YYRHSLOC(Rhs, 0).last_column; \
(Current).file = YYRHSLOC (Rhs, 0).file; \
} \
+ (Current).next = NULL; \
} while (0)
-/*
- * Fictional source position used for IR nodes that are
- * created without otherwise knowing a true source position.
- * For example,constant definitions from the command line.
- */
-extern struct srcpos srcpos_empty;
-
extern void srcpos_update(struct srcpos *pos, const char *text, int len);
extern struct srcpos *srcpos_copy(struct srcpos *pos);
+extern struct srcpos *srcpos_extend(struct srcpos *new_srcpos,
+ struct srcpos *old_srcpos);
extern char *srcpos_string(struct srcpos *pos);
+extern char *srcpos_string_first(struct srcpos *pos, int level);
+extern char *srcpos_string_last(struct srcpos *pos, int level);
+
extern void PRINTF(3, 0) srcpos_verror(struct srcpos *pos, const char *prefix,
const char *fmt, va_list va);
diff --git a/scripts/dtc/treesource.c b/scripts/dtc/treesource.c
index 2461a3d..c9d980c 100644
--- a/scripts/dtc/treesource.c
+++ b/scripts/dtc/treesource.c
@@ -1,21 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
/*
* (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation. 2005.
- *
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
- * USA
*/
#include "dtc.h"
@@ -61,24 +46,18 @@
|| strchr("\a\b\t\n\v\f\r", c));
}
-static void write_propval_string(FILE *f, struct data val)
+static void write_propval_string(FILE *f, const char *s, size_t len)
{
- const char *str = val.val;
- int i;
- struct marker *m = val.markers;
+ const char *end = s + len - 1;
- assert(str[val.len-1] == '\0');
+ if (!len)
+ return;
- while (m && (m->offset == 0)) {
- if (m->type == LABEL)
- fprintf(f, "%s: ", m->ref);
- m = m->next;
- }
+ assert(*end == '\0');
+
fprintf(f, "\"");
-
- for (i = 0; i < (val.len-1); i++) {
- char c = str[i];
-
+ while (s < end) {
+ char c = *s++;
switch (c) {
case '\a':
fprintf(f, "\\a");
@@ -108,91 +87,80 @@
fprintf(f, "\\\"");
break;
case '\0':
- fprintf(f, "\", ");
- while (m && (m->offset <= (i + 1))) {
- if (m->type == LABEL) {
- assert(m->offset == (i+1));
- fprintf(f, "%s: ", m->ref);
- }
- m = m->next;
- }
- fprintf(f, "\"");
+ fprintf(f, "\\0");
break;
default:
if (isprint((unsigned char)c))
fprintf(f, "%c", c);
else
- fprintf(f, "\\x%02hhx", c);
+ fprintf(f, "\\x%02"PRIx8, c);
}
}
fprintf(f, "\"");
-
- /* Wrap up any labels at the end of the value */
- for_each_marker_of_type(m, LABEL) {
- assert (m->offset == val.len);
- fprintf(f, " %s:", m->ref);
- }
}
-static void write_propval_cells(FILE *f, struct data val)
+static void write_propval_int(FILE *f, const char *p, size_t len, size_t width)
{
- void *propend = val.val + val.len;
- fdt32_t *cp = (fdt32_t *)val.val;
- struct marker *m = val.markers;
+ const char *end = p + len;
+ assert(len % width == 0);
- fprintf(f, "<");
- for (;;) {
- while (m && (m->offset <= ((char *)cp - val.val))) {
- if (m->type == LABEL) {
- assert(m->offset == ((char *)cp - val.val));
- fprintf(f, "%s: ", m->ref);
- }
- m = m->next;
- }
-
- fprintf(f, "0x%x", fdt32_to_cpu(*cp++));
- if ((void *)cp >= propend)
+ for (; p < end; p += width) {
+ switch (width) {
+ case 1:
+ fprintf(f, "%02"PRIx8, *(const uint8_t*)p);
break;
- fprintf(f, " ");
+ case 2:
+ fprintf(f, "0x%02"PRIx16, fdt16_to_cpu(*(const fdt16_t*)p));
+ break;
+ case 4:
+ fprintf(f, "0x%02"PRIx32, fdt32_to_cpu(*(const fdt32_t*)p));
+ break;
+ case 8:
+ fprintf(f, "0x%02"PRIx64, fdt64_to_cpu(*(const fdt64_t*)p));
+ break;
+ }
+ if (p + width < end)
+ fputc(' ', f);
}
-
- /* Wrap up any labels at the end of the value */
- for_each_marker_of_type(m, LABEL) {
- assert (m->offset == val.len);
- fprintf(f, " %s:", m->ref);
- }
- fprintf(f, ">");
}
-static void write_propval_bytes(FILE *f, struct data val)
+static bool has_data_type_information(struct marker *m)
{
- void *propend = val.val + val.len;
- const char *bp = val.val;
- struct marker *m = val.markers;
-
- fprintf(f, "[");
- for (;;) {
- while (m && (m->offset == (bp-val.val))) {
- if (m->type == LABEL)
- fprintf(f, "%s: ", m->ref);
- m = m->next;
- }
-
- fprintf(f, "%02hhx", (unsigned char)(*bp++));
- if ((const void *)bp >= propend)
- break;
- fprintf(f, " ");
- }
-
- /* Wrap up any labels at the end of the value */
- for_each_marker_of_type(m, LABEL) {
- assert (m->offset == val.len);
- fprintf(f, " %s:", m->ref);
- }
- fprintf(f, "]");
+ return m->type >= TYPE_UINT8;
}
-static void write_propval(FILE *f, struct property *prop)
+static struct marker *next_type_marker(struct marker *m)
+{
+ while (m && !has_data_type_information(m))
+ m = m->next;
+ return m;
+}
+
+size_t type_marker_length(struct marker *m)
+{
+ struct marker *next = next_type_marker(m->next);
+
+ if (next)
+ return next->offset - m->offset;
+ return 0;
+}
+
+static const char *delim_start[] = {
+ [TYPE_UINT8] = "[",
+ [TYPE_UINT16] = "/bits/ 16 <",
+ [TYPE_UINT32] = "<",
+ [TYPE_UINT64] = "/bits/ 64 <",
+ [TYPE_STRING] = "",
+};
+static const char *delim_end[] = {
+ [TYPE_UINT8] = "]",
+ [TYPE_UINT16] = ">",
+ [TYPE_UINT32] = ">",
+ [TYPE_UINT64] = ">",
+ [TYPE_STRING] = "",
+};
+
+static enum markertype guess_value_type(struct property *prop)
{
int len = prop->val.len;
const char *p = prop->val.val;
@@ -201,11 +169,6 @@
int nnotstringlbl = 0, nnotcelllbl = 0;
int i;
- if (len == 0) {
- fprintf(f, ";\n");
- return;
- }
-
for (i = 0; i < len; i++) {
if (! isstring(p[i]))
nnotstring++;
@@ -220,17 +183,99 @@
nnotcelllbl++;
}
- fprintf(f, " = ");
if ((p[len-1] == '\0') && (nnotstring == 0) && (nnul < (len-nnul))
&& (nnotstringlbl == 0)) {
- write_propval_string(f, prop->val);
+ return TYPE_STRING;
} else if (((len % sizeof(cell_t)) == 0) && (nnotcelllbl == 0)) {
- write_propval_cells(f, prop->val);
- } else {
- write_propval_bytes(f, prop->val);
+ return TYPE_UINT32;
}
- fprintf(f, ";\n");
+ return TYPE_UINT8;
+}
+
+static void write_propval(FILE *f, struct property *prop)
+{
+ size_t len = prop->val.len;
+ struct marker *m = prop->val.markers;
+ struct marker dummy_marker;
+ enum markertype emit_type = TYPE_NONE;
+ char *srcstr;
+
+ if (len == 0) {
+ fprintf(f, ";");
+ if (annotate) {
+ srcstr = srcpos_string_first(prop->srcpos, annotate);
+ if (srcstr) {
+ fprintf(f, " /* %s */", srcstr);
+ free(srcstr);
+ }
+ }
+ fprintf(f, "\n");
+ return;
+ }
+
+ fprintf(f, " =");
+
+ if (!next_type_marker(m)) {
+ /* data type information missing, need to guess */
+ dummy_marker.type = guess_value_type(prop);
+ dummy_marker.next = prop->val.markers;
+ dummy_marker.offset = 0;
+ dummy_marker.ref = NULL;
+ m = &dummy_marker;
+ }
+
+ for_each_marker(m) {
+ size_t chunk_len = (m->next ? m->next->offset : len) - m->offset;
+ size_t data_len = type_marker_length(m) ? : len - m->offset;
+ const char *p = &prop->val.val[m->offset];
+
+ if (has_data_type_information(m)) {
+ emit_type = m->type;
+ fprintf(f, " %s", delim_start[emit_type]);
+ } else if (m->type == LABEL)
+ fprintf(f, " %s:", m->ref);
+ else if (m->offset)
+ fputc(' ', f);
+
+ if (emit_type == TYPE_NONE) {
+ assert(chunk_len == 0);
+ continue;
+ }
+
+ switch(emit_type) {
+ case TYPE_UINT16:
+ write_propval_int(f, p, chunk_len, 2);
+ break;
+ case TYPE_UINT32:
+ write_propval_int(f, p, chunk_len, 4);
+ break;
+ case TYPE_UINT64:
+ write_propval_int(f, p, chunk_len, 8);
+ break;
+ case TYPE_STRING:
+ write_propval_string(f, p, chunk_len);
+ break;
+ default:
+ write_propval_int(f, p, chunk_len, 1);
+ }
+
+ if (chunk_len == data_len) {
+ size_t pos = m->offset + chunk_len;
+ fprintf(f, pos == len ? "%s" : "%s,",
+ delim_end[emit_type] ? : "");
+ emit_type = TYPE_NONE;
+ }
+ }
+ fprintf(f, ";");
+ if (annotate) {
+ srcstr = srcpos_string_first(prop->srcpos, annotate);
+ if (srcstr) {
+ fprintf(f, " /* %s */", srcstr);
+ free(srcstr);
+ }
+ }
+ fprintf(f, "\n");
}
static void write_tree_source_node(FILE *f, struct node *tree, int level)
@@ -238,14 +283,24 @@
struct property *prop;
struct node *child;
struct label *l;
+ char *srcstr;
write_prefix(f, level);
for_each_label(tree->labels, l)
fprintf(f, "%s: ", l->label);
if (tree->name && (*tree->name))
- fprintf(f, "%s {\n", tree->name);
+ fprintf(f, "%s {", tree->name);
else
- fprintf(f, "/ {\n");
+ fprintf(f, "/ {");
+
+ if (annotate) {
+ srcstr = srcpos_string_first(tree->srcpos, annotate);
+ if (srcstr) {
+ fprintf(f, " /* %s */", srcstr);
+ free(srcstr);
+ }
+ }
+ fprintf(f, "\n");
for_each_property(tree, prop) {
write_prefix(f, level+1);
@@ -259,10 +314,17 @@
write_tree_source_node(f, child, level+1);
}
write_prefix(f, level);
- fprintf(f, "};\n");
+ fprintf(f, "};");
+ if (annotate) {
+ srcstr = srcpos_string_last(tree->srcpos, annotate);
+ if (srcstr) {
+ fprintf(f, " /* %s */", srcstr);
+ free(srcstr);
+ }
+ }
+ fprintf(f, "\n");
}
-
void dt_to_source(FILE *f, struct dt_info *dti)
{
struct reserve_info *re;
@@ -281,4 +343,3 @@
write_tree_source_node(f, dti->dt, 0);
}
-
diff --git a/scripts/dtc/update-dtc-source.sh b/scripts/dtc/update-dtc-source.sh
index 1a009fd..7dd29a0 100755
--- a/scripts/dtc/update-dtc-source.sh
+++ b/scripts/dtc/update-dtc-source.sh
@@ -32,7 +32,7 @@
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 Makefile.dtc \
+ srcpos.h treesource.c util.c util.h version_gen.h yamltree.c Makefile.dtc \
dtc-lexer.l dtc-parser.y"
LIBFDT_SOURCE="Makefile.libfdt 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 \
diff --git a/scripts/dtc/util.c b/scripts/dtc/util.c
index 9953c32..48af961 100644
--- a/scripts/dtc/util.c
+++ b/scripts/dtc/util.c
@@ -1,24 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright 2011 The Chromium Authors, All Rights Reserved.
* Copyright 2008 Jon Loeliger, Freescale Semiconductor, Inc.
*
* util_is_printable_string contributed by
* Pantelis Antoniou <pantelis.antoniou AT gmail.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
- * USA
*/
#include <ctype.h>
@@ -46,36 +32,54 @@
return d;
}
-/* based in part from (3) vsnprintf */
-int xasprintf(char **strp, const char *fmt, ...)
+int xavsprintf_append(char **strp, const char *fmt, va_list ap)
{
- int n, size = 128; /* start with 128 bytes */
+ int n, size = 0; /* start with 128 bytes */
char *p;
- va_list ap;
+ va_list ap_copy;
- /* initial pointer is NULL making the fist realloc to be malloc */
- p = NULL;
- while (1) {
- p = xrealloc(p, size);
+ p = *strp;
+ if (p)
+ size = strlen(p);
- /* Try to print in the allocated space. */
- va_start(ap, fmt);
- n = vsnprintf(p, size, fmt, ap);
- va_end(ap);
+ va_copy(ap_copy, ap);
+ n = vsnprintf(NULL, 0, fmt, ap_copy) + 1;
+ va_end(ap_copy);
- /* If that worked, return the string. */
- if (n > -1 && n < size)
- break;
- /* Else try again with more space. */
- if (n > -1) /* glibc 2.1 */
- size = n + 1; /* precisely what is needed */
- else /* glibc 2.0 */
- size *= 2; /* twice the old size */
- }
+ p = xrealloc(p, size + n);
+
+ n = vsnprintf(p + size, n, fmt, ap);
+
*strp = p;
return strlen(p);
}
+int xasprintf_append(char **strp, const char *fmt, ...)
+{
+ int n;
+ va_list ap;
+
+ va_start(ap, fmt);
+ n = xavsprintf_append(strp, fmt, ap);
+ va_end(ap);
+
+ return n;
+}
+
+int xasprintf(char **strp, const char *fmt, ...)
+{
+ int n;
+ va_list ap;
+
+ *strp = NULL;
+
+ va_start(ap, fmt);
+ n = xavsprintf_append(strp, fmt, ap);
+ va_end(ap);
+
+ return n;
+}
+
char *join_path(const char *path, const char *name)
{
int lenp = strlen(path);
@@ -227,11 +231,11 @@
return val;
}
-int utilfdt_read_err_len(const char *filename, char **buffp, off_t *len)
+int utilfdt_read_err(const char *filename, char **buffp, size_t *len)
{
int fd = 0; /* assume stdin */
char *buf = NULL;
- off_t bufsize = 1024, offset = 0;
+ size_t bufsize = 1024, offset = 0;
int ret = 0;
*buffp = NULL;
@@ -264,20 +268,15 @@
free(buf);
else
*buffp = buf;
- *len = bufsize;
+ if (len)
+ *len = bufsize;
return ret;
}
-int utilfdt_read_err(const char *filename, char **buffp)
-{
- off_t len;
- return utilfdt_read_err_len(filename, buffp, &len);
-}
-
-char *utilfdt_read_len(const char *filename, off_t *len)
+char *utilfdt_read(const char *filename, size_t *len)
{
char *buff;
- int ret = utilfdt_read_err_len(filename, &buff, len);
+ int ret = utilfdt_read_err(filename, &buff, len);
if (ret) {
fprintf(stderr, "Couldn't open blob from '%s': %s\n", filename,
@@ -288,12 +287,6 @@
return buff;
}
-char *utilfdt_read(const char *filename)
-{
- off_t len;
- return utilfdt_read_len(filename, &len);
-}
-
int utilfdt_write_err(const char *filename, const void *blob)
{
int fd = 1; /* assume stdout */
diff --git a/scripts/dtc/util.h b/scripts/dtc/util.h
index 66fba8e..ca5cb52 100644
--- a/scripts/dtc/util.h
+++ b/scripts/dtc/util.h
@@ -1,3 +1,4 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
#ifndef UTIL_H
#define UTIL_H
@@ -8,21 +9,6 @@
/*
* Copyright 2011 The Chromium Authors, All Rights Reserved.
* Copyright 2008 Jon Loeliger, Freescale Semiconductor, Inc.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
- * USA
*/
#ifdef __GNUC__
@@ -72,6 +58,8 @@
extern char *xstrdup(const char *s);
extern int PRINTF(2, 3) xasprintf(char **strp, const char *fmt, ...);
+extern int PRINTF(2, 3) xasprintf_append(char **strp, const char *fmt, ...);
+extern int xavsprintf_append(char **strp, const char *fmt, va_list ap);
extern char *join_path(const char *path, const char *name);
/**
@@ -98,16 +86,10 @@
* stderr.
*
* @param filename The filename to read, or - for stdin
+ * @param len If non-NULL, the amount of data we managed to read
* @return Pointer to allocated buffer containing fdt, or NULL on error
*/
-char *utilfdt_read(const char *filename);
-
-/**
- * Like utilfdt_read(), but also passes back the size of the file read.
- *
- * @param len If non-NULL, the amount of data we managed to read
- */
-char *utilfdt_read_len(const char *filename, off_t *len);
+char *utilfdt_read(const char *filename, size_t *len);
/**
* Read a device tree file into a buffer. Does not report errors, but only
@@ -116,23 +98,17 @@
*
* @param filename The filename to read, or - for stdin
* @param buffp Returns pointer to buffer containing fdt
+ * @param len If non-NULL, the amount of data we managed to read
* @return 0 if ok, else an errno value representing the error
*/
-int utilfdt_read_err(const char *filename, char **buffp);
-
-/**
- * Like utilfdt_read_err(), but also passes back the size of the file read.
- *
- * @param len If non-NULL, the amount of data we managed to read
- */
-int utilfdt_read_err_len(const char *filename, char **buffp, off_t *len);
+int utilfdt_read_err(const char *filename, char **buffp, size_t *len);
/**
* Write a device tree buffer to a file. This will report any errors on
* stderr.
*
* @param filename The filename to write, or - for stdout
- * @param blob Poiner to buffer containing fdt
+ * @param blob Pointer to buffer containing fdt
* @return 0 if ok, -1 on error
*/
int utilfdt_write(const char *filename, const void *blob);
@@ -143,7 +119,7 @@
* an error message for the user.
*
* @param filename The filename to write, or - for stdout
- * @param blob Poiner to buffer containing fdt
+ * @param blob Pointer to buffer containing fdt
* @return 0 if ok, else an errno value representing the error
*/
int utilfdt_write_err(const char *filename, const void *blob);
diff --git a/scripts/dtc/version_gen.h b/scripts/dtc/version_gen.h
index b00f14f..f2761e2 100644
--- a/scripts/dtc/version_gen.h
+++ b/scripts/dtc/version_gen.h
@@ -1 +1 @@
-#define DTC_VERSION "DTC 1.4.6-g84e414b0"
+#define DTC_VERSION "DTC 1.5.0-g702c1b6c"
diff --git a/scripts/dtc/yamltree.c b/scripts/dtc/yamltree.c
new file mode 100644
index 0000000..5b6ea8e
--- /dev/null
+++ b/scripts/dtc/yamltree.c
@@ -0,0 +1,233 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * (C) Copyright Linaro, Ltd. 2018
+ * (C) Copyright Arm Holdings. 2017
+ * (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation. 2005.
+ */
+
+#include <stdlib.h>
+#include <yaml.h>
+#include "dtc.h"
+#include "srcpos.h"
+
+char *yaml_error_name[] = {
+ [YAML_NO_ERROR] = "no error",
+ [YAML_MEMORY_ERROR] = "memory error",
+ [YAML_READER_ERROR] = "reader error",
+ [YAML_SCANNER_ERROR] = "scanner error",
+ [YAML_PARSER_ERROR] = "parser error",
+ [YAML_COMPOSER_ERROR] = "composer error",
+ [YAML_WRITER_ERROR] = "writer error",
+ [YAML_EMITTER_ERROR] = "emitter error",
+};
+
+#define yaml_emitter_emit_or_die(emitter, event) ( \
+{ \
+ if (!yaml_emitter_emit(emitter, event)) \
+ die("yaml '%s': %s in %s, line %i\n", \
+ yaml_error_name[(emitter)->error], \
+ (emitter)->problem, __func__, __LINE__); \
+})
+
+static void yaml_propval_int(yaml_emitter_t *emitter, struct marker *markers, char *data, int len, int width)
+{
+ yaml_event_t event;
+ void *tag;
+ int off, start_offset = markers->offset;
+
+ switch(width) {
+ case 1: tag = "!u8"; break;
+ case 2: tag = "!u16"; break;
+ case 4: tag = "!u32"; break;
+ case 8: tag = "!u64"; break;
+ default:
+ die("Invalid width %i", width);
+ }
+ assert(len % width == 0);
+
+ yaml_sequence_start_event_initialize(&event, NULL,
+ (yaml_char_t *)tag, width == 4, YAML_FLOW_SEQUENCE_STYLE);
+ yaml_emitter_emit_or_die(emitter, &event);
+
+ for (off = 0; off < len; off += width) {
+ char buf[32];
+ struct marker *m;
+ bool is_phandle = false;
+
+ switch(width) {
+ case 1:
+ sprintf(buf, "0x%"PRIx8, *(uint8_t*)(data + off));
+ break;
+ case 2:
+ sprintf(buf, "0x%"PRIx16, fdt16_to_cpu(*(fdt16_t*)(data + off)));
+ break;
+ case 4:
+ sprintf(buf, "0x%"PRIx32, fdt32_to_cpu(*(fdt32_t*)(data + off)));
+ m = markers;
+ is_phandle = false;
+ for_each_marker_of_type(m, REF_PHANDLE) {
+ if (m->offset == (start_offset + off)) {
+ is_phandle = true;
+ break;
+ }
+ }
+ break;
+ case 8:
+ sprintf(buf, "0x%"PRIx64, fdt64_to_cpu(*(fdt64_t*)(data + off)));
+ break;
+ }
+
+ if (is_phandle)
+ yaml_scalar_event_initialize(&event, NULL,
+ (yaml_char_t*)"!phandle", (yaml_char_t *)buf,
+ strlen(buf), 0, 0, YAML_PLAIN_SCALAR_STYLE);
+ else
+ yaml_scalar_event_initialize(&event, NULL,
+ (yaml_char_t*)YAML_INT_TAG, (yaml_char_t *)buf,
+ strlen(buf), 1, 1, YAML_PLAIN_SCALAR_STYLE);
+ yaml_emitter_emit_or_die(emitter, &event);
+ }
+
+ yaml_sequence_end_event_initialize(&event);
+ yaml_emitter_emit_or_die(emitter, &event);
+}
+
+static void yaml_propval_string(yaml_emitter_t *emitter, char *str, int len)
+{
+ yaml_event_t event;
+ int i;
+
+ assert(str[len-1] == '\0');
+
+ /* Make sure the entire string is in the lower 7-bit ascii range */
+ for (i = 0; i < len; i++)
+ assert(isascii(str[i]));
+
+ yaml_scalar_event_initialize(&event, NULL,
+ (yaml_char_t *)YAML_STR_TAG, (yaml_char_t*)str,
+ len-1, 0, 1, YAML_DOUBLE_QUOTED_SCALAR_STYLE);
+ yaml_emitter_emit_or_die(emitter, &event);
+}
+
+static void yaml_propval(yaml_emitter_t *emitter, struct property *prop)
+{
+ yaml_event_t event;
+ int len = prop->val.len;
+ struct marker *m = prop->val.markers;
+
+ /* Emit the property name */
+ yaml_scalar_event_initialize(&event, NULL,
+ (yaml_char_t *)YAML_STR_TAG, (yaml_char_t*)prop->name,
+ strlen(prop->name), 1, 1, YAML_PLAIN_SCALAR_STYLE);
+ yaml_emitter_emit_or_die(emitter, &event);
+
+ /* Boolean properties are easiest to deal with. Length is zero, so just emit 'true' */
+ if (len == 0) {
+ yaml_scalar_event_initialize(&event, NULL,
+ (yaml_char_t *)YAML_BOOL_TAG,
+ (yaml_char_t*)"true",
+ strlen("true"), 1, 0, YAML_PLAIN_SCALAR_STYLE);
+ yaml_emitter_emit_or_die(emitter, &event);
+ return;
+ }
+
+ if (!m)
+ die("No markers present in property '%s' value\n", prop->name);
+
+ yaml_sequence_start_event_initialize(&event, NULL,
+ (yaml_char_t *)YAML_SEQ_TAG, 1, YAML_FLOW_SEQUENCE_STYLE);
+ yaml_emitter_emit_or_die(emitter, &event);
+
+ for_each_marker(m) {
+ int chunk_len;
+ char *data = &prop->val.val[m->offset];
+
+ if (m->type < TYPE_UINT8)
+ continue;
+
+ chunk_len = type_marker_length(m) ? : len;
+ assert(chunk_len > 0);
+ len -= chunk_len;
+
+ switch(m->type) {
+ case TYPE_UINT16:
+ yaml_propval_int(emitter, m, data, chunk_len, 2);
+ break;
+ case TYPE_UINT32:
+ yaml_propval_int(emitter, m, data, chunk_len, 4);
+ break;
+ case TYPE_UINT64:
+ yaml_propval_int(emitter, m, data, chunk_len, 8);
+ break;
+ case TYPE_STRING:
+ yaml_propval_string(emitter, data, chunk_len);
+ break;
+ default:
+ yaml_propval_int(emitter, m, data, chunk_len, 1);
+ break;
+ }
+ }
+
+ yaml_sequence_end_event_initialize(&event);
+ yaml_emitter_emit_or_die(emitter, &event);
+}
+
+
+static void yaml_tree(struct node *tree, yaml_emitter_t *emitter)
+{
+ struct property *prop;
+ struct node *child;
+ yaml_event_t event;
+
+ if (tree->deleted)
+ return;
+
+ yaml_mapping_start_event_initialize(&event, NULL,
+ (yaml_char_t *)YAML_MAP_TAG, 1, YAML_ANY_MAPPING_STYLE);
+ yaml_emitter_emit_or_die(emitter, &event);
+
+ for_each_property(tree, prop)
+ yaml_propval(emitter, prop);
+
+ /* Loop over all the children, emitting them into the map */
+ for_each_child(tree, child) {
+ yaml_scalar_event_initialize(&event, NULL,
+ (yaml_char_t *)YAML_STR_TAG, (yaml_char_t*)child->name,
+ strlen(child->name), 1, 0, YAML_PLAIN_SCALAR_STYLE);
+ yaml_emitter_emit_or_die(emitter, &event);
+ yaml_tree(child, emitter);
+ }
+
+ yaml_mapping_end_event_initialize(&event);
+ yaml_emitter_emit_or_die(emitter, &event);
+}
+
+void dt_to_yaml(FILE *f, struct dt_info *dti)
+{
+ yaml_emitter_t emitter;
+ yaml_event_t event;
+
+ yaml_emitter_initialize(&emitter);
+ yaml_emitter_set_output_file(&emitter, f);
+ yaml_stream_start_event_initialize(&event, YAML_UTF8_ENCODING);
+ yaml_emitter_emit_or_die(&emitter, &event);
+
+ yaml_document_start_event_initialize(&event, NULL, NULL, NULL, 0);
+ yaml_emitter_emit_or_die(&emitter, &event);
+
+ yaml_sequence_start_event_initialize(&event, NULL, (yaml_char_t *)YAML_SEQ_TAG, 1, YAML_ANY_SEQUENCE_STYLE);
+ yaml_emitter_emit_or_die(&emitter, &event);
+
+ yaml_tree(dti->dt, &emitter);
+
+ yaml_sequence_end_event_initialize(&event);
+ yaml_emitter_emit_or_die(&emitter, &event);
+
+ yaml_document_end_event_initialize(&event, 0);
+ yaml_emitter_emit_or_die(&emitter, &event);
+
+ yaml_stream_end_event_initialize(&event);
+ yaml_emitter_emit_or_die(&emitter, &event);
+
+ yaml_emitter_delete(&emitter);
+}
diff --git a/scripts/export_report.pl b/scripts/export_report.pl
index 68ff426..548330e 100755
--- a/scripts/export_report.pl
+++ b/scripts/export_report.pl
@@ -1,7 +1,7 @@
#!/usr/bin/env perl
+# SPDX-License-Identifier: GPL-2.0-only
#
# (C) Copyright IBM Corporation 2006.
-# Released under GPL v2.
# Author : Ram Pai (linuxram@us.ibm.com)
#
# Usage: export_report.pl -k Module.symvers [-o report_file ] -f *.mod.c
@@ -52,13 +52,12 @@
sub collectcfiles {
my @file;
- while (<.tmp_versions/*.mod>) {
- open my $fh, '<', $_ or die "cannot open $_: $!\n";
- push (@file,
- grep s/\.ko/.mod.c/, # change the suffix
- grep m/.+\.ko/, # find the .ko path
- <$fh>); # lines in opened file
+ open my $fh, '< modules.order' or die "cannot open modules.order: $!\n";
+ while (<$fh>) {
+ s/\.ko$/.mod.c/;
+ push (@file, $_)
}
+ close($fh);
chomp @file;
return @file;
}
@@ -95,7 +94,7 @@
#
while ( <$module_symvers> ) {
chomp;
- my (undef, $symbol, $module, $gpl) = split;
+ my (undef, $symbol, $namespace, $module, $gpl) = split('\t');
$SYMBOL { $symbol } = [ $module , "0" , $symbol, $gpl];
}
close($module_symvers);
diff --git a/scripts/extract-vmlinux b/scripts/extract-vmlinux
index e6239f3..8995cd3 100755
--- a/scripts/extract-vmlinux
+++ b/scripts/extract-vmlinux
@@ -1,4 +1,5 @@
#!/bin/sh
+# SPDX-License-Identifier: GPL-2.0-only
# ----------------------------------------------------------------------
# extract-vmlinux - Extract uncompressed vmlinux from a kernel image
#
@@ -7,7 +8,6 @@
#
# (c) 2011 Corentin Chary <corentin.chary@gmail.com>
#
-# Licensed under the GNU General Public License, version 2 (GPLv2).
# ----------------------------------------------------------------------
check_vmlinux()
@@ -48,9 +48,6 @@
tmp=$(mktemp /tmp/vmlinux-XXX)
trap "rm -f $tmp" 0
-# Initial attempt for uncompressed images or objects:
-check_vmlinux $img
-
# That didn't work, so retry after decompression.
try_decompress '\037\213\010' xy gunzip
try_decompress '\3757zXZ\000' abcde unxz
@@ -60,5 +57,8 @@
try_decompress '\002!L\030' xxx 'lz4 -d'
try_decompress '(\265/\375' xxx unzstd
+# Finally check for uncompressed images or objects:
+check_vmlinux $img
+
# Bail out:
echo "$me: Cannot find vmlinux." >&2
diff --git a/scripts/extract_xc3028.pl b/scripts/extract_xc3028.pl
index a1c51b7..e1c9af2 100755
--- a/scripts/extract_xc3028.pl
+++ b/scripts/extract_xc3028.pl
@@ -1,7 +1,7 @@
#!/usr/bin/env perl
+# SPDX-License-Identifier: GPL-2.0-only
# Copyright (c) Mauro Carvalho Chehab <mchehab@kernel.org>
-# Released under GPLv2
#
# In order to use, you need to:
# 1) Download the windows driver with something like:
diff --git a/scripts/faddr2line b/scripts/faddr2line
index a0149db..6c6439f 100755
--- a/scripts/faddr2line
+++ b/scripts/faddr2line
@@ -71,7 +71,7 @@
# Try to figure out the source directory prefix so we can remove it from the
# addr2line output. HACK ALERT: This assumes that start_kernel() is in
-# kernel/init.c! This only works for vmlinux. Otherwise it falls back to
+# init/main.c! This only works for vmlinux. Otherwise it falls back to
# printing the absolute path.
find_dir_prefix() {
local objfile=$1
diff --git a/scripts/gcc-goto.sh b/scripts/gcc-goto.sh
index 083c526..8b980fb 100755
--- a/scripts/gcc-goto.sh
+++ b/scripts/gcc-goto.sh
@@ -3,7 +3,7 @@
# Test for gcc 'asm goto' support
# Copyright (C) 2010, Jason Baron <jbaron@redhat.com>
-cat << "END" | $@ -x c - -c -o /dev/null >/dev/null 2>&1 && echo "y"
+cat << "END" | $@ -x c - -fno-PIE -c -o /dev/null
int main(void)
{
#if defined(__arm__) || defined(__aarch64__)
diff --git a/scripts/gcc-plugins/Kconfig b/scripts/gcc-plugins/Kconfig
index cb0c889..d33de0b 100644
--- a/scripts/gcc-plugins/Kconfig
+++ b/scripts/gcc-plugins/Kconfig
@@ -1,3 +1,4 @@
+# SPDX-License-Identifier: GPL-2.0-only
preferred-plugin-hostcc := $(if-success,[ $(gcc-version) -ge 40800 ],$(HOSTCXX),$(HOSTCC))
config PLUGIN_HOSTCC
@@ -13,17 +14,19 @@
An arch should select this symbol if it supports building with
GCC plugins.
-menuconfig GCC_PLUGINS
- bool "GCC plugins"
+config GCC_PLUGINS
+ bool
depends on HAVE_GCC_PLUGINS
depends on PLUGIN_HOSTCC != ""
+ 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/gcc-plugins.txt for details.
+ See Documentation/core-api/gcc-plugins.rst for details.
-if GCC_PLUGINS
+menu "GCC plugins"
+ depends on GCC_PLUGINS
config GCC_PLUGIN_CYC_COMPLEXITY
bool "Compute the cyclomatic complexity of a function" if EXPERT
@@ -66,39 +69,6 @@
* https://grsecurity.net/
* https://pax.grsecurity.net/
-config GCC_PLUGIN_STRUCTLEAK
- bool "Force initialization of variables containing userspace addresses"
- # Currently STRUCTLEAK inserts initialization out of live scope of
- # variables from KASAN point of view. This leads to KASAN false
- # positive reports. Prohibit this combination for now.
- depends on !KASAN_EXTRA
- help
- This plugin zero-initializes any structures containing a
- __user attribute. This can prevent some classes of information
- exposures.
-
- This plugin was ported from grsecurity/PaX. More information at:
- * https://grsecurity.net/
- * https://pax.grsecurity.net/
-
-config GCC_PLUGIN_STRUCTLEAK_BYREF_ALL
- bool "Force initialize all struct type variables passed by reference"
- depends on GCC_PLUGIN_STRUCTLEAK
- depends on !COMPILE_TEST
- help
- Zero initialize any struct type local variable that may be passed by
- reference without having been initialized.
-
-config GCC_PLUGIN_STRUCTLEAK_VERBOSE
- bool "Report forcefully initialized variables"
- depends on GCC_PLUGIN_STRUCTLEAK
- depends on !COMPILE_TEST # too noisy
- help
- This option will cause a warning to be printed each time the
- structleak plugin finds a variable it thinks needs to be
- initialized. Since not all existing initializers are detected
- by the plugin, this can produce false positive warnings.
-
config GCC_PLUGIN_RANDSTRUCT
bool "Randomize layout of sensitive kernel structures"
select MODVERSIONS if MODULES
@@ -139,4 +109,8 @@
in structures. This reduces the performance hit of RANDSTRUCT
at the cost of weakened randomization.
-endif
+config GCC_PLUGIN_ARM_SSP_PER_TASK
+ bool
+ depends on GCC_PLUGINS && ARM
+
+endmenu
diff --git a/scripts/gcc-plugins/arm_ssp_per_task_plugin.c b/scripts/gcc-plugins/arm_ssp_per_task_plugin.c
new file mode 100644
index 0000000..8c1af9b
--- /dev/null
+++ b/scripts/gcc-plugins/arm_ssp_per_task_plugin.c
@@ -0,0 +1,122 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include "gcc-common.h"
+
+__visible int plugin_is_GPL_compatible;
+
+static unsigned int sp_mask, canary_offset;
+
+static unsigned int arm_pertask_ssp_rtl_execute(void)
+{
+ rtx_insn *insn;
+
+ for (insn = get_insns(); insn; insn = NEXT_INSN(insn)) {
+ const char *sym;
+ rtx body;
+ rtx mask, masked_sp;
+
+ /*
+ * Find a SET insn involving a SYMBOL_REF to __stack_chk_guard
+ */
+ if (!INSN_P(insn))
+ continue;
+ body = PATTERN(insn);
+ if (GET_CODE(body) != SET ||
+ GET_CODE(SET_SRC(body)) != SYMBOL_REF)
+ continue;
+ sym = XSTR(SET_SRC(body), 0);
+ if (strcmp(sym, "__stack_chk_guard"))
+ continue;
+
+ /*
+ * Replace the source of the SET insn with an expression that
+ * produces the address of the copy of the stack canary value
+ * stored in struct thread_info
+ */
+ mask = GEN_INT(sext_hwi(sp_mask, GET_MODE_PRECISION(Pmode)));
+ masked_sp = gen_reg_rtx(Pmode);
+
+ emit_insn_before(gen_rtx_set(masked_sp,
+ gen_rtx_AND(Pmode,
+ stack_pointer_rtx,
+ mask)),
+ insn);
+
+ SET_SRC(body) = gen_rtx_PLUS(Pmode, masked_sp,
+ GEN_INT(canary_offset));
+ }
+ return 0;
+}
+
+#define PASS_NAME arm_pertask_ssp_rtl
+
+#define NO_GATE
+#include "gcc-generate-rtl-pass.h"
+
+#if BUILDING_GCC_VERSION >= 9000
+static bool no(void)
+{
+ return false;
+}
+
+static void arm_pertask_ssp_start_unit(void *gcc_data, void *user_data)
+{
+ targetm.have_stack_protect_combined_set = no;
+ targetm.have_stack_protect_combined_test = no;
+}
+#endif
+
+__visible int plugin_init(struct plugin_name_args *plugin_info,
+ struct plugin_gcc_version *version)
+{
+ const char * const plugin_name = plugin_info->base_name;
+ const int argc = plugin_info->argc;
+ const struct plugin_argument *argv = plugin_info->argv;
+ int tso = 0;
+ int i;
+
+ if (!plugin_default_version_check(version, &gcc_version)) {
+ error(G_("incompatible gcc/plugin versions"));
+ return 1;
+ }
+
+ for (i = 0; i < argc; ++i) {
+ if (!strcmp(argv[i].key, "disable"))
+ return 0;
+
+ /* all remaining options require a value */
+ if (!argv[i].value) {
+ error(G_("no value supplied for option '-fplugin-arg-%s-%s'"),
+ plugin_name, argv[i].key);
+ return 1;
+ }
+
+ if (!strcmp(argv[i].key, "tso")) {
+ tso = atoi(argv[i].value);
+ continue;
+ }
+
+ if (!strcmp(argv[i].key, "offset")) {
+ canary_offset = atoi(argv[i].value);
+ continue;
+ }
+ error(G_("unknown option '-fplugin-arg-%s-%s'"),
+ plugin_name, argv[i].key);
+ return 1;
+ }
+
+ /* create the mask that produces the base of the stack */
+ sp_mask = ~((1U << (12 + tso)) - 1);
+
+ PASS_INFO(arm_pertask_ssp_rtl, "expand", 1, PASS_POS_INSERT_AFTER);
+
+ register_callback(plugin_info->base_name, PLUGIN_PASS_MANAGER_SETUP,
+ NULL, &arm_pertask_ssp_rtl_pass_info);
+
+#if BUILDING_GCC_VERSION >= 9000
+ register_callback(plugin_info->base_name, PLUGIN_START_UNIT,
+ arm_pertask_ssp_start_unit, NULL);
+#endif
+
+ return 0;
+}
diff --git a/scripts/gcc-plugins/gcc-common.h b/scripts/gcc-plugins/gcc-common.h
index 552d5ef..17f0607 100644
--- a/scripts/gcc-plugins/gcc-common.h
+++ b/scripts/gcc-plugins/gcc-common.h
@@ -150,8 +150,12 @@
void dump_gimple_stmt(pretty_printer *, gimple, int, int);
#endif
+#ifndef __unused
#define __unused __attribute__((__unused__))
+#endif
+#ifndef __visible
#define __visible __attribute__((visibility("default")))
+#endif
#define DECL_NAME_POINTER(node) IDENTIFIER_POINTER(DECL_NAME(node))
#define DECL_NAME_LENGTH(node) IDENTIFIER_LENGTH(DECL_NAME(node))
diff --git a/scripts/gcc-plugins/randomize_layout_plugin.c b/scripts/gcc-plugins/randomize_layout_plugin.c
index 6d5bbd3..bd29e4e 100644
--- a/scripts/gcc-plugins/randomize_layout_plugin.c
+++ b/scripts/gcc-plugins/randomize_layout_plugin.c
@@ -443,13 +443,13 @@
if (node == fieldtype)
continue;
- if (!is_fptr(fieldtype))
- return 0;
-
- if (code != RECORD_TYPE && code != UNION_TYPE)
+ if (code == RECORD_TYPE || code == UNION_TYPE) {
+ if (!is_pure_ops_struct(fieldtype))
+ return 0;
continue;
+ }
- if (!is_pure_ops_struct(fieldtype))
+ if (!is_fptr(fieldtype))
return 0;
}
diff --git a/scripts/gcc-plugins/stackleak_plugin.c b/scripts/gcc-plugins/stackleak_plugin.c
new file mode 100644
index 0000000..dbd3746
--- /dev/null
+++ b/scripts/gcc-plugins/stackleak_plugin.c
@@ -0,0 +1,429 @@
+/*
+ * Copyright 2011-2017 by the PaX Team <pageexec@freemail.hu>
+ * Modified by Alexander Popov <alex.popov@linux.com>
+ * Licensed under the GPL v2
+ *
+ * Note: the choice of the license means that the compilation process is
+ * NOT 'eligible' as defined by gcc's library exception to the GPL v3,
+ * but for the kernel it doesn't matter since it doesn't link against
+ * any of the gcc libraries
+ *
+ * This gcc plugin is needed for tracking the lowest border of the kernel stack.
+ * It instruments the kernel code inserting stackleak_track_stack() calls:
+ * - after alloca();
+ * - for the functions with a stack frame size greater than or equal
+ * to the "track-min-size" plugin parameter.
+ *
+ * This plugin is ported from grsecurity/PaX. For more information see:
+ * https://grsecurity.net/
+ * https://pax.grsecurity.net/
+ *
+ * Debugging:
+ * - use fprintf() to stderr, debug_generic_expr(), debug_gimple_stmt(),
+ * print_rtl() and print_simple_rtl();
+ * - add "-fdump-tree-all -fdump-rtl-all" to the plugin CFLAGS in
+ * Makefile.gcc-plugins to see the verbose dumps of the gcc passes;
+ * - use gcc -E to understand the preprocessing shenanigans;
+ * - use gcc with enabled CFG/GIMPLE/SSA verification (--enable-checking).
+ */
+
+#include "gcc-common.h"
+
+__visible int plugin_is_GPL_compatible;
+
+static int track_frame_size = -1;
+static const char track_function[] = "stackleak_track_stack";
+
+/*
+ * Mark these global variables (roots) for gcc garbage collector since
+ * they point to the garbage-collected memory.
+ */
+static GTY(()) tree track_function_decl;
+
+static struct plugin_info stackleak_plugin_info = {
+ .version = "201707101337",
+ .help = "track-min-size=nn\ttrack stack for functions with a stack frame size >= nn bytes\n"
+ "disable\t\tdo not activate the plugin\n"
+};
+
+static void stackleak_add_track_stack(gimple_stmt_iterator *gsi, bool after)
+{
+ gimple stmt;
+ gcall *stackleak_track_stack;
+ cgraph_node_ptr node;
+ int frequency;
+ basic_block bb;
+
+ /* Insert call to void stackleak_track_stack(void) */
+ stmt = gimple_build_call(track_function_decl, 0);
+ stackleak_track_stack = as_a_gcall(stmt);
+ if (after) {
+ gsi_insert_after(gsi, stackleak_track_stack,
+ GSI_CONTINUE_LINKING);
+ } else {
+ gsi_insert_before(gsi, stackleak_track_stack, GSI_SAME_STMT);
+ }
+
+ /* Update the cgraph */
+ bb = gimple_bb(stackleak_track_stack);
+ node = cgraph_get_create_node(track_function_decl);
+ gcc_assert(node);
+ frequency = compute_call_stmt_bb_frequency(current_function_decl, bb);
+ cgraph_create_edge(cgraph_get_node(current_function_decl), node,
+ stackleak_track_stack, bb->count, frequency);
+}
+
+static bool is_alloca(gimple stmt)
+{
+ if (gimple_call_builtin_p(stmt, BUILT_IN_ALLOCA))
+ return true;
+
+#if BUILDING_GCC_VERSION >= 4007
+ if (gimple_call_builtin_p(stmt, BUILT_IN_ALLOCA_WITH_ALIGN))
+ return true;
+#endif
+
+ return false;
+}
+
+/*
+ * Work with the GIMPLE representation of the code. Insert the
+ * stackleak_track_stack() call after alloca() and into the beginning
+ * of the function if it is not instrumented.
+ */
+static unsigned int stackleak_instrument_execute(void)
+{
+ basic_block bb, entry_bb;
+ bool prologue_instrumented = false, is_leaf = true;
+ gimple_stmt_iterator gsi;
+
+ /*
+ * ENTRY_BLOCK_PTR is a basic block which represents possible entry
+ * point of a function. This block does not contain any code and
+ * has a CFG edge to its successor.
+ */
+ gcc_assert(single_succ_p(ENTRY_BLOCK_PTR_FOR_FN(cfun)));
+ entry_bb = single_succ(ENTRY_BLOCK_PTR_FOR_FN(cfun));
+
+ /*
+ * Loop through the GIMPLE statements in each of cfun basic blocks.
+ * cfun is a global variable which represents the function that is
+ * currently processed.
+ */
+ FOR_EACH_BB_FN(bb, cfun) {
+ for (gsi = gsi_start_bb(bb); !gsi_end_p(gsi); gsi_next(&gsi)) {
+ gimple stmt;
+
+ stmt = gsi_stmt(gsi);
+
+ /* Leaf function is a function which makes no calls */
+ if (is_gimple_call(stmt))
+ is_leaf = false;
+
+ if (!is_alloca(stmt))
+ continue;
+
+ /* Insert stackleak_track_stack() call after alloca() */
+ stackleak_add_track_stack(&gsi, true);
+ if (bb == entry_bb)
+ prologue_instrumented = true;
+ }
+ }
+
+ if (prologue_instrumented)
+ return 0;
+
+ /*
+ * Special cases to skip the instrumentation.
+ *
+ * Taking the address of static inline functions materializes them,
+ * but we mustn't instrument some of them as the resulting stack
+ * alignment required by the function call ABI will break other
+ * assumptions regarding the expected (but not otherwise enforced)
+ * register clobbering ABI.
+ *
+ * Case in point: native_save_fl on amd64 when optimized for size
+ * clobbers rdx if it were instrumented here.
+ *
+ * TODO: any more special cases?
+ */
+ if (is_leaf &&
+ !TREE_PUBLIC(current_function_decl) &&
+ DECL_DECLARED_INLINE_P(current_function_decl)) {
+ return 0;
+ }
+
+ if (is_leaf &&
+ !strncmp(IDENTIFIER_POINTER(DECL_NAME(current_function_decl)),
+ "_paravirt_", 10)) {
+ return 0;
+ }
+
+ /* Insert stackleak_track_stack() call at the function beginning */
+ bb = entry_bb;
+ if (!single_pred_p(bb)) {
+ /* gcc_assert(bb_loop_depth(bb) ||
+ (bb->flags & BB_IRREDUCIBLE_LOOP)); */
+ split_edge(single_succ_edge(ENTRY_BLOCK_PTR_FOR_FN(cfun)));
+ gcc_assert(single_succ_p(ENTRY_BLOCK_PTR_FOR_FN(cfun)));
+ bb = single_succ(ENTRY_BLOCK_PTR_FOR_FN(cfun));
+ }
+ gsi = gsi_after_labels(bb);
+ stackleak_add_track_stack(&gsi, false);
+
+ return 0;
+}
+
+static bool large_stack_frame(void)
+{
+#if BUILDING_GCC_VERSION >= 8000
+ return maybe_ge(get_frame_size(), track_frame_size);
+#else
+ return (get_frame_size() >= track_frame_size);
+#endif
+}
+
+/*
+ * Work with the RTL representation of the code.
+ * Remove the unneeded stackleak_track_stack() calls from the functions
+ * which don't call alloca() and don't have a large enough stack frame size.
+ */
+static unsigned int stackleak_cleanup_execute(void)
+{
+ rtx_insn *insn, *next;
+
+ if (cfun->calls_alloca)
+ return 0;
+
+ if (large_stack_frame())
+ return 0;
+
+ /*
+ * Find stackleak_track_stack() calls. Loop through the chain of insns,
+ * which is an RTL representation of the code for a function.
+ *
+ * The example of a matching insn:
+ * (call_insn 8 4 10 2 (call (mem (symbol_ref ("stackleak_track_stack")
+ * [flags 0x41] <function_decl 0x7f7cd3302a80 stackleak_track_stack>)
+ * [0 stackleak_track_stack S1 A8]) (0)) 675 {*call} (expr_list
+ * (symbol_ref ("stackleak_track_stack") [flags 0x41] <function_decl
+ * 0x7f7cd3302a80 stackleak_track_stack>) (expr_list (0) (nil))) (nil))
+ */
+ for (insn = get_insns(); insn; insn = next) {
+ rtx body;
+
+ next = NEXT_INSN(insn);
+
+ /* Check the expression code of the insn */
+ if (!CALL_P(insn))
+ continue;
+
+ /*
+ * Check the expression code of the insn body, which is an RTL
+ * Expression (RTX) describing the side effect performed by
+ * that insn.
+ */
+ body = PATTERN(insn);
+
+ if (GET_CODE(body) == PARALLEL)
+ body = XVECEXP(body, 0, 0);
+
+ if (GET_CODE(body) != CALL)
+ continue;
+
+ /*
+ * Check the first operand of the call expression. It should
+ * be a mem RTX describing the needed subroutine with a
+ * symbol_ref RTX.
+ */
+ body = XEXP(body, 0);
+ if (GET_CODE(body) != MEM)
+ continue;
+
+ body = XEXP(body, 0);
+ if (GET_CODE(body) != SYMBOL_REF)
+ continue;
+
+ if (SYMBOL_REF_DECL(body) != track_function_decl)
+ continue;
+
+ /* Delete the stackleak_track_stack() call */
+ delete_insn_and_edges(insn);
+#if BUILDING_GCC_VERSION >= 4007 && BUILDING_GCC_VERSION < 8000
+ if (GET_CODE(next) == NOTE &&
+ NOTE_KIND(next) == NOTE_INSN_CALL_ARG_LOCATION) {
+ insn = next;
+ next = NEXT_INSN(insn);
+ delete_insn_and_edges(insn);
+ }
+#endif
+ }
+
+ return 0;
+}
+
+static bool stackleak_gate(void)
+{
+ tree section;
+
+ section = lookup_attribute("section",
+ DECL_ATTRIBUTES(current_function_decl));
+ if (section && TREE_VALUE(section)) {
+ section = TREE_VALUE(TREE_VALUE(section));
+
+ if (!strncmp(TREE_STRING_POINTER(section), ".init.text", 10))
+ return false;
+ if (!strncmp(TREE_STRING_POINTER(section), ".devinit.text", 13))
+ return false;
+ if (!strncmp(TREE_STRING_POINTER(section), ".cpuinit.text", 13))
+ return false;
+ if (!strncmp(TREE_STRING_POINTER(section), ".meminit.text", 13))
+ return false;
+ }
+
+ return track_frame_size >= 0;
+}
+
+/* Build the function declaration for stackleak_track_stack() */
+static void stackleak_start_unit(void *gcc_data __unused,
+ void *user_data __unused)
+{
+ tree fntype;
+
+ /* void stackleak_track_stack(void) */
+ fntype = build_function_type_list(void_type_node, NULL_TREE);
+ track_function_decl = build_fn_decl(track_function, fntype);
+ DECL_ASSEMBLER_NAME(track_function_decl); /* for LTO */
+ TREE_PUBLIC(track_function_decl) = 1;
+ TREE_USED(track_function_decl) = 1;
+ DECL_EXTERNAL(track_function_decl) = 1;
+ DECL_ARTIFICIAL(track_function_decl) = 1;
+ DECL_PRESERVE_P(track_function_decl) = 1;
+}
+
+/*
+ * Pass gate function is a predicate function that gets executed before the
+ * corresponding pass. If the return value is 'true' the pass gets executed,
+ * otherwise, it is skipped.
+ */
+static bool stackleak_instrument_gate(void)
+{
+ return stackleak_gate();
+}
+
+#define PASS_NAME stackleak_instrument
+#define PROPERTIES_REQUIRED PROP_gimple_leh | PROP_cfg
+#define TODO_FLAGS_START TODO_verify_ssa | TODO_verify_flow | TODO_verify_stmts
+#define TODO_FLAGS_FINISH TODO_verify_ssa | TODO_verify_stmts | TODO_dump_func \
+ | TODO_update_ssa | TODO_rebuild_cgraph_edges
+#include "gcc-generate-gimple-pass.h"
+
+static bool stackleak_cleanup_gate(void)
+{
+ return stackleak_gate();
+}
+
+#define PASS_NAME stackleak_cleanup
+#define TODO_FLAGS_FINISH TODO_dump_func
+#include "gcc-generate-rtl-pass.h"
+
+/*
+ * Every gcc plugin exports a plugin_init() function that is called right
+ * after the plugin is loaded. This function is responsible for registering
+ * the plugin callbacks and doing other required initialization.
+ */
+__visible int plugin_init(struct plugin_name_args *plugin_info,
+ struct plugin_gcc_version *version)
+{
+ const char * const plugin_name = plugin_info->base_name;
+ const int argc = plugin_info->argc;
+ const struct plugin_argument * const argv = plugin_info->argv;
+ int i = 0;
+
+ /* Extra GGC root tables describing our GTY-ed data */
+ static const struct ggc_root_tab gt_ggc_r_gt_stackleak[] = {
+ {
+ .base = &track_function_decl,
+ .nelt = 1,
+ .stride = sizeof(track_function_decl),
+ .cb = >_ggc_mx_tree_node,
+ .pchw = >_pch_nx_tree_node
+ },
+ LAST_GGC_ROOT_TAB
+ };
+
+ /*
+ * The stackleak_instrument pass should be executed before the
+ * "optimized" pass, which is the control flow graph cleanup that is
+ * performed just before expanding gcc trees to the RTL. In former
+ * versions of the plugin this new pass was inserted before the
+ * "tree_profile" pass, which is currently called "profile".
+ */
+ PASS_INFO(stackleak_instrument, "optimized", 1,
+ PASS_POS_INSERT_BEFORE);
+
+ /*
+ * The stackleak_cleanup pass should be executed before the "*free_cfg"
+ * pass. It's the moment when the stack frame size is already final,
+ * function prologues and epilogues are generated, and the
+ * machine-dependent code transformations are not done.
+ */
+ PASS_INFO(stackleak_cleanup, "*free_cfg", 1, PASS_POS_INSERT_BEFORE);
+
+ if (!plugin_default_version_check(version, &gcc_version)) {
+ error(G_("incompatible gcc/plugin versions"));
+ return 1;
+ }
+
+ /* Parse the plugin arguments */
+ for (i = 0; i < argc; i++) {
+ if (!strcmp(argv[i].key, "disable"))
+ return 0;
+
+ if (!strcmp(argv[i].key, "track-min-size")) {
+ if (!argv[i].value) {
+ error(G_("no value supplied for option '-fplugin-arg-%s-%s'"),
+ plugin_name, argv[i].key);
+ return 1;
+ }
+
+ track_frame_size = atoi(argv[i].value);
+ if (track_frame_size < 0) {
+ error(G_("invalid option argument '-fplugin-arg-%s-%s=%s'"),
+ plugin_name, argv[i].key, argv[i].value);
+ return 1;
+ }
+ } else {
+ error(G_("unknown option '-fplugin-arg-%s-%s'"),
+ plugin_name, argv[i].key);
+ return 1;
+ }
+ }
+
+ /* Give the information about the plugin */
+ register_callback(plugin_name, PLUGIN_INFO, NULL,
+ &stackleak_plugin_info);
+
+ /* Register to be called before processing a translation unit */
+ register_callback(plugin_name, PLUGIN_START_UNIT,
+ &stackleak_start_unit, NULL);
+
+ /* Register an extra GCC garbage collector (GGC) root table */
+ register_callback(plugin_name, PLUGIN_REGISTER_GGC_ROOTS, NULL,
+ (void *)>_ggc_r_gt_stackleak);
+
+ /*
+ * Hook into the Pass Manager to register new gcc passes.
+ *
+ * The stack frame size info is available only at the last RTL pass,
+ * when it's too late to insert complex code like a function call.
+ * So we register two gcc passes to instrument every function at first
+ * and remove the unneeded instrumentation later.
+ */
+ register_callback(plugin_name, PLUGIN_PASS_MANAGER_SETUP, NULL,
+ &stackleak_instrument_pass_info);
+ register_callback(plugin_name, PLUGIN_PASS_MANAGER_SETUP, NULL,
+ &stackleak_cleanup_pass_info);
+
+ return 0;
+}
diff --git a/scripts/gcc-plugins/structleak_plugin.c b/scripts/gcc-plugins/structleak_plugin.c
index 10292f7..e89be8f 100644
--- a/scripts/gcc-plugins/structleak_plugin.c
+++ b/scripts/gcc-plugins/structleak_plugin.c
@@ -16,6 +16,7 @@
* Options:
* -fplugin-arg-structleak_plugin-disable
* -fplugin-arg-structleak_plugin-verbose
+ * -fplugin-arg-structleak_plugin-byref
* -fplugin-arg-structleak_plugin-byref-all
*
* Usage:
@@ -26,7 +27,6 @@
* $ gcc -fplugin=./structleak_plugin.so test.c -O2
*
* TODO: eliminate redundant initializers
- * increase type coverage
*/
#include "gcc-common.h"
@@ -37,13 +37,18 @@
__visible int plugin_is_GPL_compatible;
static struct plugin_info structleak_plugin_info = {
- .version = "201607271510vanilla",
+ .version = "20190125vanilla",
.help = "disable\tdo not activate plugin\n"
- "verbose\tprint all initialized variables\n",
+ "byref\tinit structs passed by reference\n"
+ "byref-all\tinit anything passed by reference\n"
+ "verbose\tprint all initialized variables\n",
};
+#define BYREF_STRUCT 1
+#define BYREF_ALL 2
+
static bool verbose;
-static bool byref_all;
+static int byref;
static tree handle_user_attribute(tree *node, tree name, tree args, int flags, bool *no_add_attrs)
{
@@ -118,6 +123,7 @@
gimple_stmt_iterator gsi;
tree initializer;
gimple init_stmt;
+ tree type;
/* this is the original entry bb before the forced split */
bb = single_succ(ENTRY_BLOCK_PTR_FOR_FN(cfun));
@@ -148,11 +154,15 @@
if (verbose)
inform(DECL_SOURCE_LOCATION(var),
"%s variable will be forcibly initialized",
- (byref_all && TREE_ADDRESSABLE(var)) ? "byref"
- : "userspace");
+ (byref && TREE_ADDRESSABLE(var)) ? "byref"
+ : "userspace");
/* build the initializer expression */
- initializer = build_constructor(TREE_TYPE(var), NULL);
+ type = TREE_TYPE(var);
+ if (AGGREGATE_TYPE_P(type))
+ initializer = build_constructor(type, NULL);
+ else
+ initializer = fold_convert(type, integer_zero_node);
/* build the initializer stmt */
init_stmt = gimple_build_assign(var, initializer);
@@ -184,13 +194,13 @@
if (!auto_var_in_fn_p(var, current_function_decl))
continue;
- /* only care about structure types */
- if (TREE_CODE(type) != RECORD_TYPE && TREE_CODE(type) != UNION_TYPE)
+ /* only care about structure types unless byref-all */
+ if (byref != BYREF_ALL && TREE_CODE(type) != RECORD_TYPE && TREE_CODE(type) != UNION_TYPE)
continue;
/* if the type is of interest, examine the variable */
if (TYPE_USERSPACE(type) ||
- (byref_all && TREE_ADDRESSABLE(var)))
+ (byref && TREE_ADDRESSABLE(var)))
initialize(var);
}
@@ -232,8 +242,12 @@
verbose = true;
continue;
}
+ if (!strcmp(argv[i].key, "byref")) {
+ byref = BYREF_STRUCT;
+ continue;
+ }
if (!strcmp(argv[i].key, "byref-all")) {
- byref_all = true;
+ byref = BYREF_ALL;
continue;
}
error(G_("unknown option '-fplugin-arg-%s-%s'"), plugin_name, argv[i].key);
diff --git a/scripts/gcc-version.sh b/scripts/gcc-version.sh
index 11bb909..ae35343 100755
--- a/scripts/gcc-version.sh
+++ b/scripts/gcc-version.sh
@@ -1,33 +1,20 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
#
-# gcc-version [-p] gcc-command
+# gcc-version gcc-command
#
-# Prints the gcc version of `gcc-command' in a canonical 4-digit form
-# such as `0295' for gcc-2.95, `0303' for gcc-3.3, etc.
-#
-# With the -p option, prints the patchlevel as well, for example `029503' for
-# gcc-2.95.3, `030301' for gcc-3.3.1, etc.
-#
-
-if [ "$1" = "-p" ] ; then
- with_patchlevel=1;
- shift;
-fi
+# Print the gcc version of `gcc-command' in a 5 or 6-digit form
+# such as `29503' for gcc-2.95.3, `30301' for gcc-3.3.1, etc.
compiler="$*"
if [ ${#compiler} -eq 0 ]; then
- echo "Error: No compiler specified."
- printf "Usage:\n\t$0 <gcc-command>\n"
+ echo "Error: No compiler specified." >&2
+ printf "Usage:\n\t$0 <gcc-command>\n" >&2
exit 1
fi
MAJOR=$(echo __GNUC__ | $compiler -E -x c - | tail -n 1)
MINOR=$(echo __GNUC_MINOR__ | $compiler -E -x c - | tail -n 1)
-if [ "x$with_patchlevel" != "x" ] ; then
- PATCHLEVEL=$(echo __GNUC_PATCHLEVEL__ | $compiler -E -x c - | tail -n 1)
- printf "%02d%02d%02d\\n" $MAJOR $MINOR $PATCHLEVEL
-else
- printf "%02d%02d\\n" $MAJOR $MINOR
-fi
+PATCHLEVEL=$(echo __GNUC_PATCHLEVEL__ | $compiler -E -x c - | tail -n 1)
+printf "%d%02d%02d\\n" $MAJOR $MINOR $PATCHLEVEL
diff --git a/scripts/gdb/Makefile b/scripts/gdb/Makefile
index 62f5f65..3fca193 100644
--- a/scripts/gdb/Makefile
+++ b/scripts/gdb/Makefile
@@ -1 +1,2 @@
+# SPDX-License-Identifier: GPL-2.0-only
subdir-y := linux
diff --git a/scripts/gdb/linux/Makefile b/scripts/gdb/linux/Makefile
index aba23be..1247550 100644
--- a/scripts/gdb/linux/Makefile
+++ b/scripts/gdb/linux/Makefile
@@ -1,24 +1,25 @@
# SPDX-License-Identifier: GPL-2.0
-always := gdb-scripts
-SRCTREE := $(abspath $(srctree))
+ifdef building_out_of_srctree
-$(obj)/gdb-scripts:
-ifneq ($(KBUILD_SRC),)
- $(Q)ln -fsn $(SRCTREE)/$(obj)/*.py $(objtree)/$(obj)
+symlinks := $(patsubst $(srctree)/$(src)/%,%,$(wildcard $(srctree)/$(src)/*.py))
+
+quiet_cmd_symlink = SYMLINK $@
+ cmd_symlink = ln -fsn $(patsubst $(obj)/%,$(abspath $(srctree))/$(src)/%,$@) $@
+
+extra-y += $(symlinks)
+$(addprefix $(obj)/, $(symlinks)): FORCE
+ $(call if_changed,symlink)
+
endif
- @:
quiet_cmd_gen_constants_py = GEN $@
cmd_gen_constants_py = \
$(CPP) -E -x c -P $(c_flags) $< > $@ ;\
sed -i '1,/<!-- end-c-headers -->/d;' $@
-targets += constants.py
-$(obj)/constants.py: $(SRCTREE)/$(obj)/constants.py.in FORCE
+extra-y += constants.py
+$(obj)/constants.py: $(src)/constants.py.in FORCE
$(call if_changed_dep,gen_constants_py)
-build_constants_py: $(obj)/constants.py
- @:
-
-clean-files := *.pyc *.pyo $(if $(KBUILD_SRC),*.py) $(obj)/constants.py
+clean-files := *.pyc *.pyo
diff --git a/scripts/gdb/linux/clk.py b/scripts/gdb/linux/clk.py
new file mode 100644
index 0000000..061aecf
--- /dev/null
+++ b/scripts/gdb/linux/clk.py
@@ -0,0 +1,76 @@
+# SPDX-License-Identifier: GPL-2.0
+#
+# Copyright (c) NXP 2019
+
+import gdb
+import sys
+
+from linux import utils, lists, constants
+
+clk_core_type = utils.CachedType("struct clk_core")
+
+
+def clk_core_for_each_child(hlist_head):
+ return lists.hlist_for_each_entry(hlist_head,
+ clk_core_type.get_type().pointer(), "child_node")
+
+
+class LxClkSummary(gdb.Command):
+ """Print clk tree summary
+
+Output is a subset of /sys/kernel/debug/clk/clk_summary
+
+No calls are made during printing, instead a (c) if printed after values which
+are cached and potentially out of date"""
+
+ def __init__(self):
+ super(LxClkSummary, self).__init__("lx-clk-summary", gdb.COMMAND_DATA)
+
+ def show_subtree(self, clk, level):
+ gdb.write("%*s%-*s %7d %8d %8d %11lu%s\n" % (
+ level * 3 + 1, "",
+ 30 - level * 3,
+ clk['name'].string(),
+ clk['enable_count'],
+ clk['prepare_count'],
+ clk['protect_count'],
+ clk['rate'],
+ '(c)' if clk['flags'] & constants.LX_CLK_GET_RATE_NOCACHE else ' '))
+
+ for child in clk_core_for_each_child(clk['children']):
+ self.show_subtree(child, level + 1)
+
+ def invoke(self, arg, from_tty):
+ gdb.write(" enable prepare protect \n")
+ gdb.write(" clock count count count rate \n")
+ gdb.write("------------------------------------------------------------------------\n")
+ for clk in clk_core_for_each_child(gdb.parse_and_eval("clk_root_list")):
+ self.show_subtree(clk, 0)
+ for clk in clk_core_for_each_child(gdb.parse_and_eval("clk_orphan_list")):
+ self.show_subtree(clk, 0)
+
+
+LxClkSummary()
+
+
+class LxClkCoreLookup(gdb.Function):
+ """Find struct clk_core by name"""
+
+ def __init__(self):
+ super(LxClkCoreLookup, self).__init__("lx_clk_core_lookup")
+
+ def lookup_hlist(self, hlist_head, name):
+ for child in clk_core_for_each_child(hlist_head):
+ if child['name'].string() == name:
+ return child
+ result = self.lookup_hlist(child['children'], name)
+ if result:
+ return result
+
+ def invoke(self, name):
+ name = name.string()
+ return (self.lookup_hlist(gdb.parse_and_eval("clk_root_list"), name) or
+ self.lookup_hlist(gdb.parse_and_eval("clk_orphan_list"), name))
+
+
+LxClkCoreLookup()
diff --git a/scripts/gdb/linux/config.py b/scripts/gdb/linux/config.py
new file mode 100644
index 0000000..90e1565
--- /dev/null
+++ b/scripts/gdb/linux/config.py
@@ -0,0 +1,44 @@
+# SPDX-License-Identifier: GPL-2.0
+#
+# Copyright 2019 Google LLC.
+
+import gdb
+import zlib
+
+from linux import utils
+
+
+class LxConfigDump(gdb.Command):
+ """Output kernel config to the filename specified as the command
+ argument. Equivalent to 'zcat /proc/config.gz > config.txt' on
+ a running target"""
+
+ def __init__(self):
+ super(LxConfigDump, self).__init__("lx-configdump", gdb.COMMAND_DATA,
+ gdb.COMPLETE_FILENAME)
+
+ def invoke(self, arg, from_tty):
+ if len(arg) == 0:
+ filename = "config.txt"
+ else:
+ filename = arg
+
+ try:
+ py_config_ptr = gdb.parse_and_eval("kernel_config_data + 8")
+ py_config_size = gdb.parse_and_eval(
+ "sizeof(kernel_config_data) - 1 - 8 * 2")
+ except gdb.error as e:
+ raise gdb.GdbError("Can't find config, enable CONFIG_IKCONFIG?")
+
+ inf = gdb.inferiors()[0]
+ zconfig_buf = utils.read_memoryview(inf, py_config_ptr,
+ py_config_size).tobytes()
+
+ config_buf = zlib.decompress(zconfig_buf, 16)
+ with open(filename, 'wb') as f:
+ f.write(config_buf)
+
+ gdb.write("Dumped config to " + filename + "\n")
+
+
+LxConfigDump()
diff --git a/scripts/gdb/linux/constants.py.in b/scripts/gdb/linux/constants.py.in
index 7aad824..2efbec6 100644
--- a/scripts/gdb/linux/constants.py.in
+++ b/scripts/gdb/linux/constants.py.in
@@ -12,9 +12,12 @@
*
*/
+#include <linux/clk-provider.h>
#include <linux/fs.h>
+#include <linux/hrtimer.h>
#include <linux/mount.h>
#include <linux/of_fdt.h>
+#include <linux/threads.h>
/* We need to stringify expanded macros so that they can be parsed */
@@ -36,13 +39,20 @@
import gdb
+/* linux/clk-provider.h */
+if IS_BUILTIN(CONFIG_COMMON_CLK):
+ LX_GDBPARSED(CLK_GET_RATE_NOCACHE)
+
/* linux/fs.h */
-LX_VALUE(MS_RDONLY)
-LX_VALUE(MS_SYNCHRONOUS)
-LX_VALUE(MS_MANDLOCK)
-LX_VALUE(MS_DIRSYNC)
-LX_VALUE(MS_NOATIME)
-LX_VALUE(MS_NODIRATIME)
+LX_VALUE(SB_RDONLY)
+LX_VALUE(SB_SYNCHRONOUS)
+LX_VALUE(SB_MANDLOCK)
+LX_VALUE(SB_DIRSYNC)
+LX_VALUE(SB_NOATIME)
+LX_VALUE(SB_NODIRATIME)
+
+/* linux/htimer.h */
+LX_GDBPARSED(hrtimer_resolution)
/* linux/mount.h */
LX_VALUE(MNT_NOSUID)
@@ -52,8 +62,16 @@
LX_VALUE(MNT_NODIRATIME)
LX_VALUE(MNT_RELATIME)
+/* linux/threads.h */
+LX_VALUE(NR_CPUS)
+
/* linux/of_fdt.h> */
LX_VALUE(OF_DT_HEADER)
/* Kernel Configs */
+LX_CONFIG(CONFIG_GENERIC_CLOCKEVENTS)
+LX_CONFIG(CONFIG_GENERIC_CLOCKEVENTS_BROADCAST)
+LX_CONFIG(CONFIG_HIGH_RES_TIMERS)
+LX_CONFIG(CONFIG_NR_CPUS)
LX_CONFIG(CONFIG_OF)
+LX_CONFIG(CONFIG_TICK_ONESHOT)
diff --git a/scripts/gdb/linux/cpus.py b/scripts/gdb/linux/cpus.py
index ca11e8d..008e62f 100644
--- a/scripts/gdb/linux/cpus.py
+++ b/scripts/gdb/linux/cpus.py
@@ -135,6 +135,7 @@
gdb.write("Online CPUs : {}\n".format(list(each_online_cpu())))
gdb.write("Active CPUs : {}\n".format(list(each_active_cpu())))
+
LxCpus()
diff --git a/scripts/gdb/linux/device.py b/scripts/gdb/linux/device.py
new file mode 100644
index 0000000..16376c5
--- /dev/null
+++ b/scripts/gdb/linux/device.py
@@ -0,0 +1,182 @@
+# SPDX-License-Identifier: GPL-2.0
+#
+# Copyright (c) NXP 2019
+
+import gdb
+
+from linux.utils import CachedType
+from linux.utils import container_of
+from linux.lists import list_for_each_entry
+
+
+device_private_type = CachedType('struct device_private')
+device_type = CachedType('struct device')
+
+subsys_private_type = CachedType('struct subsys_private')
+kobject_type = CachedType('struct kobject')
+kset_type = CachedType('struct kset')
+
+bus_type = CachedType('struct bus_type')
+class_type = CachedType('struct class')
+
+
+def dev_name(dev):
+ dev_init_name = dev['init_name']
+ if dev_init_name:
+ return dev_init_name.string()
+ return dev['kobj']['name'].string()
+
+
+def kset_for_each_object(kset):
+ return list_for_each_entry(kset['list'],
+ kobject_type.get_type().pointer(), "entry")
+
+
+def for_each_bus():
+ for kobj in kset_for_each_object(gdb.parse_and_eval('bus_kset')):
+ subsys = container_of(kobj, kset_type.get_type().pointer(), 'kobj')
+ subsys_priv = container_of(subsys, subsys_private_type.get_type().pointer(), 'subsys')
+ yield subsys_priv['bus']
+
+
+def for_each_class():
+ for kobj in kset_for_each_object(gdb.parse_and_eval('class_kset')):
+ subsys = container_of(kobj, kset_type.get_type().pointer(), 'kobj')
+ subsys_priv = container_of(subsys, subsys_private_type.get_type().pointer(), 'subsys')
+ yield subsys_priv['class']
+
+
+def get_bus_by_name(name):
+ for item in for_each_bus():
+ if item['name'].string() == name:
+ return item
+ raise gdb.GdbError("Can't find bus type {!r}".format(name))
+
+
+def get_class_by_name(name):
+ for item in for_each_class():
+ if item['name'].string() == name:
+ return item
+ raise gdb.GdbError("Can't find device class {!r}".format(name))
+
+
+klist_type = CachedType('struct klist')
+klist_node_type = CachedType('struct klist_node')
+
+
+def klist_for_each(klist):
+ return list_for_each_entry(klist['k_list'],
+ klist_node_type.get_type().pointer(), 'n_node')
+
+
+def bus_for_each_device(bus):
+ for kn in klist_for_each(bus['p']['klist_devices']):
+ dp = container_of(kn, device_private_type.get_type().pointer(), 'knode_bus')
+ yield dp['device']
+
+
+def class_for_each_device(cls):
+ for kn in klist_for_each(cls['p']['klist_devices']):
+ dp = container_of(kn, device_private_type.get_type().pointer(), 'knode_class')
+ yield dp['device']
+
+
+def device_for_each_child(dev):
+ for kn in klist_for_each(dev['p']['klist_children']):
+ dp = container_of(kn, device_private_type.get_type().pointer(), 'knode_parent')
+ yield dp['device']
+
+
+def _show_device(dev, level=0, recursive=False):
+ gdb.write('{}dev {}:\t{}\n'.format('\t' * level, dev_name(dev), dev))
+ if recursive:
+ for child in device_for_each_child(dev):
+ _show_device(child, level + 1, recursive)
+
+
+class LxDeviceListBus(gdb.Command):
+ '''Print devices on a bus (or all buses if not specified)'''
+
+ def __init__(self):
+ super(LxDeviceListBus, self).__init__('lx-device-list-bus', gdb.COMMAND_DATA)
+
+ def invoke(self, arg, from_tty):
+ if not arg:
+ for bus in for_each_bus():
+ gdb.write('bus {}:\t{}\n'.format(bus['name'].string(), bus))
+ for dev in bus_for_each_device(bus):
+ _show_device(dev, level=1)
+ else:
+ bus = get_bus_by_name(arg)
+ if not bus:
+ raise gdb.GdbError("Can't find bus {!r}".format(arg))
+ for dev in bus_for_each_device(bus):
+ _show_device(dev)
+
+
+class LxDeviceListClass(gdb.Command):
+ '''Print devices in a class (or all classes if not specified)'''
+
+ def __init__(self):
+ super(LxDeviceListClass, self).__init__('lx-device-list-class', gdb.COMMAND_DATA)
+
+ def invoke(self, arg, from_tty):
+ if not arg:
+ for cls in for_each_class():
+ gdb.write("class {}:\t{}\n".format(cls['name'].string(), cls))
+ for dev in class_for_each_device(cls):
+ _show_device(dev, level=1)
+ else:
+ cls = get_class_by_name(arg)
+ for dev in class_for_each_device(cls):
+ _show_device(dev)
+
+
+class LxDeviceListTree(gdb.Command):
+ '''Print a device and its children recursively'''
+
+ def __init__(self):
+ super(LxDeviceListTree, self).__init__('lx-device-list-tree', gdb.COMMAND_DATA)
+
+ def invoke(self, arg, from_tty):
+ if not arg:
+ raise gdb.GdbError('Please provide pointer to struct device')
+ dev = gdb.parse_and_eval(arg)
+ if dev.type != device_type.get_type().pointer():
+ raise gdb.GdbError('Please provide pointer to struct device')
+ _show_device(dev, level=0, recursive=True)
+
+
+class LxDeviceFindByBusName(gdb.Function):
+ '''Find struct device by bus and name (both strings)'''
+
+ def __init__(self):
+ super(LxDeviceFindByBusName, self).__init__('lx_device_find_by_bus_name')
+
+ def invoke(self, bus, name):
+ name = name.string()
+ bus = get_bus_by_name(bus.string())
+ for dev in bus_for_each_device(bus):
+ if dev_name(dev) == name:
+ return dev
+
+
+class LxDeviceFindByClassName(gdb.Function):
+ '''Find struct device by class and name (both strings)'''
+
+ def __init__(self):
+ super(LxDeviceFindByClassName, self).__init__('lx_device_find_by_class_name')
+
+ def invoke(self, cls, name):
+ name = name.string()
+ cls = get_class_by_name(cls.string())
+ for dev in class_for_each_device(cls):
+ if dev_name(dev) == name:
+ return dev
+
+
+LxDeviceListBus()
+LxDeviceListClass()
+LxDeviceListTree()
+LxDeviceFindByBusName()
+LxDeviceFindByClassName()
diff --git a/scripts/gdb/linux/dmesg.py b/scripts/gdb/linux/dmesg.py
index 6d2e09a..2fa7bb8 100644
--- a/scripts/gdb/linux/dmesg.py
+++ b/scripts/gdb/linux/dmesg.py
@@ -16,6 +16,8 @@
from linux import utils
+printk_log_type = utils.CachedType("struct printk_log")
+
class LxDmesg(gdb.Command):
"""Print Linux kernel log buffer."""
@@ -42,9 +44,14 @@
b = utils.read_memoryview(inf, log_buf_addr, log_next_idx)
log_buf = a.tobytes() + b.tobytes()
+ length_offset = printk_log_type.get_type()['len'].bitpos // 8
+ text_len_offset = printk_log_type.get_type()['text_len'].bitpos // 8
+ time_stamp_offset = printk_log_type.get_type()['ts_nsec'].bitpos // 8
+ text_offset = printk_log_type.get_type().sizeof
+
pos = 0
while pos < log_buf.__len__():
- length = utils.read_u16(log_buf[pos + 8:pos + 10])
+ length = utils.read_u16(log_buf, pos + length_offset)
if length == 0:
if log_buf_2nd_half == -1:
gdb.write("Corrupted log buffer!\n")
@@ -52,10 +59,11 @@
pos = log_buf_2nd_half
continue
- text_len = utils.read_u16(log_buf[pos + 10:pos + 12])
- text = log_buf[pos + 16:pos + 16 + text_len].decode(
+ text_len = utils.read_u16(log_buf, pos + text_len_offset)
+ text_start = pos + text_offset
+ text = log_buf[text_start:text_start + text_len].decode(
encoding='utf8', errors='replace')
- time_stamp = utils.read_u64(log_buf[pos:pos + 8])
+ time_stamp = utils.read_u64(log_buf, pos + time_stamp_offset)
for line in text.splitlines():
msg = u"[{time:12.6f}] {line}\n".format(
diff --git a/scripts/gdb/linux/genpd.py b/scripts/gdb/linux/genpd.py
new file mode 100644
index 0000000..6ca93bd
--- /dev/null
+++ b/scripts/gdb/linux/genpd.py
@@ -0,0 +1,83 @@
+# SPDX-License-Identifier: GPL-2.0
+#
+# Copyright (c) NXP 2019
+
+import gdb
+import sys
+
+from linux.utils import CachedType
+from linux.lists import list_for_each_entry
+
+generic_pm_domain_type = CachedType('struct generic_pm_domain')
+pm_domain_data_type = CachedType('struct pm_domain_data')
+device_link_type = CachedType('struct device_link')
+
+
+def kobject_get_path(kobj):
+ path = kobj['name'].string()
+ parent = kobj['parent']
+ if parent:
+ path = kobject_get_path(parent) + '/' + path
+ return path
+
+
+def rtpm_status_str(dev):
+ if dev['power']['runtime_error']:
+ return 'error'
+ if dev['power']['disable_depth']:
+ return 'unsupported'
+ _RPM_STATUS_LOOKUP = [
+ "active",
+ "resuming",
+ "suspended",
+ "suspending"
+ ]
+ return _RPM_STATUS_LOOKUP[dev['power']['runtime_status']]
+
+
+class LxGenPDSummary(gdb.Command):
+ '''Print genpd summary
+
+Output is similar to /sys/kernel/debug/pm_genpd/pm_genpd_summary'''
+
+ def __init__(self):
+ super(LxGenPDSummary, self).__init__('lx-genpd-summary', gdb.COMMAND_DATA)
+
+ def summary_one(self, genpd):
+ if genpd['status'] == 0:
+ status_string = 'on'
+ else:
+ status_string = 'off-{}'.format(genpd['state_idx'])
+
+ slave_names = []
+ for link in list_for_each_entry(
+ genpd['master_links'],
+ device_link_type.get_type().pointer(),
+ 'master_node'):
+ slave_names.apend(link['slave']['name'])
+
+ gdb.write('%-30s %-15s %s\n' % (
+ genpd['name'].string(),
+ status_string,
+ ', '.join(slave_names)))
+
+ # Print devices in domain
+ for pm_data in list_for_each_entry(genpd['dev_list'],
+ pm_domain_data_type.get_type().pointer(),
+ 'list_node'):
+ dev = pm_data['dev']
+ kobj_path = kobject_get_path(dev['kobj'])
+ gdb.write(' %-50s %s\n' % (kobj_path, rtpm_status_str(dev)))
+
+ def invoke(self, arg, from_tty):
+ gdb.write('domain status slaves\n');
+ gdb.write(' /device runtime status\n');
+ gdb.write('----------------------------------------------------------------------\n');
+ for genpd in list_for_each_entry(
+ gdb.parse_and_eval('&gpd_list'),
+ generic_pm_domain_type.get_type().pointer(),
+ 'gpd_list_node'):
+ self.summary_one(genpd)
+
+
+LxGenPDSummary()
diff --git a/scripts/gdb/linux/lists.py b/scripts/gdb/linux/lists.py
index 2f335fb..c487ddf 100644
--- a/scripts/gdb/linux/lists.py
+++ b/scripts/gdb/linux/lists.py
@@ -16,13 +16,15 @@
from linux import utils
list_head = utils.CachedType("struct list_head")
+hlist_head = utils.CachedType("struct hlist_head")
+hlist_node = utils.CachedType("struct hlist_node")
def list_for_each(head):
if head.type == list_head.get_type().pointer():
head = head.dereference()
elif head.type != list_head.get_type():
- raise gdb.GdbError("Must be struct list_head not {}"
+ raise TypeError("Must be struct list_head not {}"
.format(head.type))
node = head['next'].dereference()
@@ -33,9 +35,24 @@
def list_for_each_entry(head, gdbtype, member):
for node in list_for_each(head):
- if node.type != list_head.get_type().pointer():
- raise TypeError("Type {} found. Expected struct list_head *."
- .format(node.type))
+ yield utils.container_of(node, gdbtype, member)
+
+
+def hlist_for_each(head):
+ if head.type == hlist_head.get_type().pointer():
+ head = head.dereference()
+ elif head.type != hlist_head.get_type():
+ raise TypeError("Must be struct hlist_head not {}"
+ .format(head.type))
+
+ node = head['first'].dereference()
+ while node.address:
+ yield node.address
+ node = node['next'].dereference()
+
+
+def hlist_for_each_entry(head, gdbtype, member):
+ for node in hlist_for_each(head):
yield utils.container_of(node, gdbtype, member)
@@ -110,4 +127,5 @@
raise gdb.GdbError("lx-list-check takes one argument")
list_check(gdb.parse_and_eval(argv[0]))
+
LxListChk()
diff --git a/scripts/gdb/linux/proc.py b/scripts/gdb/linux/proc.py
index 086d272..6a56bba 100644
--- a/scripts/gdb/linux/proc.py
+++ b/scripts/gdb/linux/proc.py
@@ -29,6 +29,7 @@
def invoke(self, arg, from_tty):
gdb.write(gdb.parse_and_eval("saved_command_line").string() + "\n")
+
LxCmdLine()
@@ -41,7 +42,8 @@
def invoke(self, arg, from_tty):
# linux_banner should contain a newline
- gdb.write(gdb.parse_and_eval("linux_banner").string())
+ gdb.write(gdb.parse_and_eval("(char *)linux_banner").string())
+
LxVersion()
@@ -86,6 +88,7 @@
def invoke(self, arg, from_tty):
return show_lx_resources("iomem_resource")
+
LxIOMem()
@@ -100,6 +103,7 @@
def invoke(self, arg, from_tty):
return show_lx_resources("ioport_resource")
+
LxIOPorts()
@@ -114,11 +118,11 @@
return opts
-FS_INFO = {constants.LX_MS_SYNCHRONOUS: ",sync",
- constants.LX_MS_MANDLOCK: ",mand",
- constants.LX_MS_DIRSYNC: ",dirsync",
- constants.LX_MS_NOATIME: ",noatime",
- constants.LX_MS_NODIRATIME: ",nodiratime"}
+FS_INFO = {constants.LX_SB_SYNCHRONOUS: ",sync",
+ constants.LX_SB_MANDLOCK: ",mand",
+ constants.LX_SB_DIRSYNC: ",dirsync",
+ constants.LX_SB_NOATIME: ",noatime",
+ constants.LX_SB_NODIRATIME: ",nodiratime"}
MNT_INFO = {constants.LX_MNT_NOSUID: ",nosuid",
constants.LX_MNT_NODEV: ",nodev",
@@ -149,7 +153,7 @@
if len(argv) >= 1:
try:
pid = int(argv[0])
- except:
+ except gdb.error:
raise gdb.GdbError("Provide a PID as integer value")
else:
pid = 1
@@ -184,7 +188,7 @@
fstype = superblock['s_type']['name'].string()
s_flags = int(superblock['s_flags'])
m_flags = int(vfs['mnt']['mnt_flags'])
- rd = "ro" if (s_flags & constants.LX_MS_RDONLY) else "rw"
+ rd = "ro" if (s_flags & constants.LX_SB_RDONLY) else "rw"
gdb.write(
"{} {} {} {}{}{} 0 0\n"
@@ -195,6 +199,7 @@
info_opts(FS_INFO, s_flags),
info_opts(MNT_INFO, m_flags)))
+
LxMounts()
@@ -259,7 +264,7 @@
try:
f = open(filename, 'wb')
- except:
+ except gdb.error:
raise gdb.GdbError("Could not open file to dump fdt")
f.write(fdt_buf)
@@ -267,4 +272,5 @@
gdb.write("Dumped fdt blob to " + filename + "\n")
+
LxFdtDump()
diff --git a/scripts/gdb/linux/rbtree.py b/scripts/gdb/linux/rbtree.py
new file mode 100644
index 0000000..39db889
--- /dev/null
+++ b/scripts/gdb/linux/rbtree.py
@@ -0,0 +1,177 @@
+# SPDX-License-Identifier: GPL-2.0
+#
+# Copyright 2019 Google LLC.
+
+import gdb
+
+from linux import utils
+
+rb_root_type = utils.CachedType("struct rb_root")
+rb_node_type = utils.CachedType("struct rb_node")
+
+
+def rb_first(root):
+ if root.type == rb_root_type.get_type():
+ node = node.address.cast(rb_root_type.get_type().pointer())
+ elif root.type != rb_root_type.get_type().pointer():
+ raise gdb.GdbError("Must be struct rb_root not {}".format(root.type))
+
+ node = root['rb_node']
+ if node is 0:
+ return None
+
+ while node['rb_left']:
+ node = node['rb_left']
+
+ return node
+
+
+def rb_last(root):
+ if root.type == rb_root_type.get_type():
+ node = node.address.cast(rb_root_type.get_type().pointer())
+ elif root.type != rb_root_type.get_type().pointer():
+ raise gdb.GdbError("Must be struct rb_root not {}".format(root.type))
+
+ node = root['rb_node']
+ if node is 0:
+ return None
+
+ while node['rb_right']:
+ node = node['rb_right']
+
+ return node
+
+
+def rb_parent(node):
+ parent = gdb.Value(node['__rb_parent_color'] & ~3)
+ return parent.cast(rb_node_type.get_type().pointer())
+
+
+def rb_empty_node(node):
+ return node['__rb_parent_color'] == node.address
+
+
+def rb_next(node):
+ if node.type == rb_node_type.get_type():
+ node = node.address.cast(rb_node_type.get_type().pointer())
+ elif node.type != rb_node_type.get_type().pointer():
+ raise gdb.GdbError("Must be struct rb_node not {}".format(node.type))
+
+ if rb_empty_node(node):
+ return None
+
+ if node['rb_right']:
+ node = node['rb_right']
+ while node['rb_left']:
+ node = node['rb_left']
+ return node
+
+ parent = rb_parent(node)
+ while parent and node == parent['rb_right']:
+ node = parent
+ parent = rb_parent(node)
+
+ return parent
+
+
+def rb_prev(node):
+ if node.type == rb_node_type.get_type():
+ node = node.address.cast(rb_node_type.get_type().pointer())
+ elif node.type != rb_node_type.get_type().pointer():
+ raise gdb.GdbError("Must be struct rb_node not {}".format(node.type))
+
+ if rb_empty_node(node):
+ return None
+
+ if node['rb_left']:
+ node = node['rb_left']
+ while node['rb_right']:
+ node = node['rb_right']
+ return node.dereference()
+
+ parent = rb_parent(node)
+ while parent and node == parent['rb_left'].dereference():
+ node = parent
+ parent = rb_parent(node)
+
+ return parent
+
+
+class LxRbFirst(gdb.Function):
+ """Lookup and return a node from an RBTree
+
+$lx_rb_first(root): Return the node at the given index.
+If index is omitted, the root node is dereferenced and returned."""
+
+ def __init__(self):
+ super(LxRbFirst, self).__init__("lx_rb_first")
+
+ def invoke(self, root):
+ result = rb_first(root)
+ if result is None:
+ raise gdb.GdbError("No entry in tree")
+
+ return result
+
+
+LxRbFirst()
+
+
+class LxRbLast(gdb.Function):
+ """Lookup and return a node from an RBTree.
+
+$lx_rb_last(root): Return the node at the given index.
+If index is omitted, the root node is dereferenced and returned."""
+
+ def __init__(self):
+ super(LxRbLast, self).__init__("lx_rb_last")
+
+ def invoke(self, root):
+ result = rb_last(root)
+ if result is None:
+ raise gdb.GdbError("No entry in tree")
+
+ return result
+
+
+LxRbLast()
+
+
+class LxRbNext(gdb.Function):
+ """Lookup and return a node from an RBTree.
+
+$lx_rb_next(node): Return the node at the given index.
+If index is omitted, the root node is dereferenced and returned."""
+
+ def __init__(self):
+ super(LxRbNext, self).__init__("lx_rb_next")
+
+ def invoke(self, node):
+ result = rb_next(node)
+ if result is None:
+ raise gdb.GdbError("No entry in tree")
+
+ return result
+
+
+LxRbNext()
+
+
+class LxRbPrev(gdb.Function):
+ """Lookup and return a node from an RBTree.
+
+$lx_rb_prev(node): Return the node at the given index.
+If index is omitted, the root node is dereferenced and returned."""
+
+ def __init__(self):
+ super(LxRbPrev, self).__init__("lx_rb_prev")
+
+ def invoke(self, node):
+ result = rb_prev(node)
+ if result is None:
+ raise gdb.GdbError("No entry in tree")
+
+ return result
+
+
+LxRbPrev()
diff --git a/scripts/gdb/linux/symbols.py b/scripts/gdb/linux/symbols.py
index 004b0ac..be984aa 100644
--- a/scripts/gdb/linux/symbols.py
+++ b/scripts/gdb/linux/symbols.py
@@ -15,7 +15,7 @@
import os
import re
-from linux import modules
+from linux import modules, utils
if hasattr(gdb, 'Breakpoint'):
@@ -77,12 +77,12 @@
gdb.write("scanning for modules in {0}\n".format(path))
for root, dirs, files in os.walk(path):
for name in files:
- if name.endswith(".ko"):
+ if name.endswith(".ko") or name.endswith(".ko.debug"):
self.module_files.append(root + "/" + name)
self.module_files_updated = True
def _get_module_file(self, module_name):
- module_pattern = ".*/{0}\.ko$".format(
+ module_pattern = ".*/{0}\.ko(?:.debug)?$".format(
module_name.replace("_", r"[_\-]"))
for name in self.module_files:
if re.match(module_pattern, name) and os.path.exists(name):
@@ -99,7 +99,8 @@
attrs[n]['name'].string(): attrs[n]['address']
for n in range(int(sect_attrs['nsections']))}
args = []
- for section_name in [".data", ".data..read_mostly", ".rodata", ".bss"]:
+ for section_name in [".data", ".data..read_mostly", ".rodata", ".bss",
+ ".text", ".text.hot", ".text.unlikely"]:
address = section_name_to_address.get(section_name)
if address:
args.append(" -s {name} {addr}".format(
@@ -116,6 +117,12 @@
module_file = self._get_module_file(module_name)
if module_file:
+ if utils.is_target_arch('s390'):
+ # Module text is preceded by PLT stubs on s390.
+ module_arch = module['arch']
+ plt_offset = int(module_arch['plt_offset'])
+ plt_size = int(module_arch['plt_size'])
+ module_addr = hex(int(module_addr, 0) + plt_offset + plt_size)
gdb.write("loading @{addr}: {filename}\n".format(
addr=module_addr, filename=module_file))
cmdline = "add-symbol-file {filename} {addr}{sections}".format(
@@ -139,8 +146,12 @@
saved_states.append({'breakpoint': bp, 'enabled': bp.enabled})
# drop all current symbols and reload vmlinux
+ orig_vmlinux = 'vmlinux'
+ for obj in gdb.objfiles():
+ if obj.filename.endswith('vmlinux'):
+ orig_vmlinux = obj.filename
gdb.execute("symbol-file", to_string=True)
- gdb.execute("symbol-file vmlinux")
+ gdb.execute("symbol-file {0}".format(orig_vmlinux))
self.loaded_modules = []
module_list = modules.module_list()
diff --git a/scripts/gdb/linux/tasks.py b/scripts/gdb/linux/tasks.py
index f6ab3cc..0301dc1 100644
--- a/scripts/gdb/linux/tasks.py
+++ b/scripts/gdb/linux/tasks.py
@@ -79,6 +79,7 @@
pid=task["pid"],
comm=task["comm"].string()))
+
LxPs()
@@ -134,4 +135,5 @@
else:
raise gdb.GdbError("No task of PID " + str(pid))
+
LxThreadInfoByPidFunc()
diff --git a/scripts/gdb/linux/timerlist.py b/scripts/gdb/linux/timerlist.py
new file mode 100644
index 0000000..071d0dd
--- /dev/null
+++ b/scripts/gdb/linux/timerlist.py
@@ -0,0 +1,219 @@
+# SPDX-License-Identifier: GPL-2.0
+#
+# Copyright 2019 Google LLC.
+
+import binascii
+import gdb
+
+from linux import constants
+from linux import cpus
+from linux import rbtree
+from linux import utils
+
+timerqueue_node_type = utils.CachedType("struct timerqueue_node").get_type()
+hrtimer_type = utils.CachedType("struct hrtimer").get_type()
+
+
+def ktime_get():
+ """Returns the current time, but not very accurately
+
+ We can't read the hardware timer itself to add any nanoseconds
+ that need to be added since we last stored the time in the
+ timekeeper. But this is probably good enough for debug purposes."""
+ tk_core = gdb.parse_and_eval("&tk_core")
+
+ return tk_core['timekeeper']['tkr_mono']['base']
+
+
+def print_timer(rb_node, idx):
+ timerqueue = utils.container_of(rb_node, timerqueue_node_type.pointer(),
+ "node")
+ timer = utils.container_of(timerqueue, hrtimer_type.pointer(), "node")
+
+ function = str(timer['function']).split(" ")[1].strip("<>")
+ softexpires = timer['_softexpires']
+ expires = timer['node']['expires']
+ now = ktime_get()
+
+ text = " #{}: <{}>, {}, ".format(idx, timer, function)
+ text += "S:{:02x}\n".format(int(timer['state']))
+ text += " # expires at {}-{} nsecs [in {} to {} nsecs]\n".format(
+ softexpires, expires, softexpires - now, expires - now)
+ return text
+
+
+def print_active_timers(base):
+ curr = base['active']['next']['node']
+ curr = curr.address.cast(rbtree.rb_node_type.get_type().pointer())
+ idx = 0
+ while curr:
+ yield print_timer(curr, idx)
+ curr = rbtree.rb_next(curr)
+ idx += 1
+
+
+def print_base(base):
+ text = " .base: {}\n".format(base.address)
+ text += " .index: {}\n".format(base['index'])
+
+ text += " .resolution: {} nsecs\n".format(constants.LX_hrtimer_resolution)
+
+ text += " .get_time: {}\n".format(base['get_time'])
+ if constants.LX_CONFIG_HIGH_RES_TIMERS:
+ text += " .offset: {} nsecs\n".format(base['offset'])
+ text += "active timers:\n"
+ text += "".join([x for x in print_active_timers(base)])
+ return text
+
+
+def print_cpu(hrtimer_bases, cpu, max_clock_bases):
+ cpu_base = cpus.per_cpu(hrtimer_bases, cpu)
+ jiffies = gdb.parse_and_eval("jiffies_64")
+ tick_sched_ptr = gdb.parse_and_eval("&tick_cpu_sched")
+ ts = cpus.per_cpu(tick_sched_ptr, cpu)
+
+ text = "cpu: {}\n".format(cpu)
+ for i in xrange(max_clock_bases):
+ text += " clock {}:\n".format(i)
+ text += print_base(cpu_base['clock_base'][i])
+
+ if constants.LX_CONFIG_HIGH_RES_TIMERS:
+ fmts = [(" .{} : {} nsecs", 'expires_next'),
+ (" .{} : {}", 'hres_active'),
+ (" .{} : {}", 'nr_events'),
+ (" .{} : {}", 'nr_retries'),
+ (" .{} : {}", 'nr_hangs'),
+ (" .{} : {}", 'max_hang_time')]
+ text += "\n".join([s.format(f, cpu_base[f]) for s, f in fmts])
+ text += "\n"
+
+ if constants.LX_CONFIG_TICK_ONESHOT:
+ fmts = [(" .{} : {}", 'nohz_mode'),
+ (" .{} : {} nsecs", 'last_tick'),
+ (" .{} : {}", 'tick_stopped'),
+ (" .{} : {}", 'idle_jiffies'),
+ (" .{} : {}", 'idle_calls'),
+ (" .{} : {}", 'idle_sleeps'),
+ (" .{} : {} nsecs", 'idle_entrytime'),
+ (" .{} : {} nsecs", 'idle_waketime'),
+ (" .{} : {} nsecs", 'idle_exittime'),
+ (" .{} : {} nsecs", 'idle_sleeptime'),
+ (" .{}: {} nsecs", 'iowait_sleeptime'),
+ (" .{} : {}", 'last_jiffies'),
+ (" .{} : {}", 'next_timer'),
+ (" .{} : {} nsecs", 'idle_expires')]
+ text += "\n".join([s.format(f, ts[f]) for s, f in fmts])
+ text += "\njiffies: {}\n".format(jiffies)
+
+ text += "\n"
+
+ return text
+
+
+def print_tickdevice(td, cpu):
+ dev = td['evtdev']
+ text = "Tick Device: mode: {}\n".format(td['mode'])
+ if cpu < 0:
+ text += "Broadcast device\n"
+ else:
+ text += "Per CPU device: {}\n".format(cpu)
+
+ text += "Clock Event Device: "
+ if dev == 0:
+ text += "<NULL>\n"
+ return text
+
+ text += "{}\n".format(dev['name'])
+ text += " max_delta_ns: {}\n".format(dev['max_delta_ns'])
+ text += " min_delta_ns: {}\n".format(dev['min_delta_ns'])
+ text += " mult: {}\n".format(dev['mult'])
+ text += " shift: {}\n".format(dev['shift'])
+ text += " mode: {}\n".format(dev['state_use_accessors'])
+ text += " next_event: {} nsecs\n".format(dev['next_event'])
+
+ text += " set_next_event: {}\n".format(dev['set_next_event'])
+
+ members = [('set_state_shutdown', " shutdown: {}\n"),
+ ('set_state_periodic', " periodic: {}\n"),
+ ('set_state_oneshot', " oneshot: {}\n"),
+ ('set_state_oneshot_stopped', " oneshot stopped: {}\n"),
+ ('tick_resume', " resume: {}\n")]
+ for member, fmt in members:
+ if dev[member]:
+ text += fmt.format(dev[member])
+
+ text += " event_handler: {}\n".format(dev['event_handler'])
+ text += " retries: {}\n".format(dev['retries'])
+
+ return text
+
+
+def pr_cpumask(mask):
+ nr_cpu_ids = 1
+ if constants.LX_NR_CPUS > 1:
+ nr_cpu_ids = gdb.parse_and_eval("nr_cpu_ids")
+
+ inf = gdb.inferiors()[0]
+ bits = mask['bits']
+ num_bytes = (nr_cpu_ids + 7) / 8
+ buf = utils.read_memoryview(inf, bits, num_bytes).tobytes()
+ buf = binascii.b2a_hex(buf)
+
+ chunks = []
+ i = num_bytes
+ while i > 0:
+ i -= 1
+ start = i * 2
+ end = start + 2
+ chunks.append(buf[start:end])
+ if i != 0 and i % 4 == 0:
+ chunks.append(',')
+
+ extra = nr_cpu_ids % 8
+ if 0 < extra <= 4:
+ chunks[0] = chunks[0][0] # Cut off the first 0
+
+ return "".join(chunks)
+
+
+class LxTimerList(gdb.Command):
+ """Print /proc/timer_list"""
+
+ def __init__(self):
+ super(LxTimerList, self).__init__("lx-timerlist", gdb.COMMAND_DATA)
+
+ def invoke(self, arg, from_tty):
+ hrtimer_bases = gdb.parse_and_eval("&hrtimer_bases")
+ max_clock_bases = gdb.parse_and_eval("HRTIMER_MAX_CLOCK_BASES")
+
+ text = "Timer List Version: gdb scripts\n"
+ text += "HRTIMER_MAX_CLOCK_BASES: {}\n".format(max_clock_bases)
+ text += "now at {} nsecs\n".format(ktime_get())
+
+ for cpu in cpus.each_online_cpu():
+ text += print_cpu(hrtimer_bases, cpu, max_clock_bases)
+
+ if constants.LX_CONFIG_GENERIC_CLOCKEVENTS:
+ if constants.LX_CONFIG_GENERIC_CLOCKEVENTS_BROADCAST:
+ bc_dev = gdb.parse_and_eval("&tick_broadcast_device")
+ text += print_tickdevice(bc_dev, -1)
+ text += "\n"
+ mask = gdb.parse_and_eval("tick_broadcast_mask")
+ mask = pr_cpumask(mask)
+ text += "tick_broadcast_mask: {}\n".format(mask)
+ if constants.LX_CONFIG_TICK_ONESHOT:
+ mask = gdb.parse_and_eval("tick_broadcast_oneshot_mask")
+ mask = pr_cpumask(mask)
+ text += "tick_broadcast_oneshot_mask: {}\n".format(mask)
+ text += "\n"
+
+ tick_cpu_devices = gdb.parse_and_eval("&tick_cpu_device")
+ for cpu in cpus.each_online_cpu():
+ tick_dev = cpus.per_cpu(tick_cpu_devices, cpu)
+ text += print_tickdevice(tick_dev, cpu)
+ text += "\n"
+
+ gdb.write(text)
+
+
+LxTimerList()
diff --git a/scripts/gdb/linux/utils.py b/scripts/gdb/linux/utils.py
index 5080587..ea94221 100644
--- a/scripts/gdb/linux/utils.py
+++ b/scripts/gdb/linux/utils.py
@@ -66,6 +66,7 @@
return container_of(ptr, gdb.lookup_type(typename.string()).pointer(),
elementname.string())
+
ContainerOf()
@@ -91,15 +92,16 @@
return memoryview(inf.read_memory(start, length))
-def read_u16(buffer):
+def read_u16(buffer, offset):
+ buffer_val = buffer[offset:offset + 2]
value = [0, 0]
- if type(buffer[0]) is str:
- value[0] = ord(buffer[0])
- value[1] = ord(buffer[1])
+ if type(buffer_val[0]) is str:
+ value[0] = ord(buffer_val[0])
+ value[1] = ord(buffer_val[1])
else:
- value[0] = buffer[0]
- value[1] = buffer[1]
+ value[0] = buffer_val[0]
+ value[1] = buffer_val[1]
if get_target_endianness() == LITTLE_ENDIAN:
return value[0] + (value[1] << 8)
@@ -107,18 +109,18 @@
return value[1] + (value[0] << 8)
-def read_u32(buffer):
+def read_u32(buffer, offset):
if get_target_endianness() == LITTLE_ENDIAN:
- return read_u16(buffer[0:2]) + (read_u16(buffer[2:4]) << 16)
+ return read_u16(buffer, offset) + (read_u16(buffer, offset + 2) << 16)
else:
- return read_u16(buffer[2:4]) + (read_u16(buffer[0:2]) << 16)
+ return read_u16(buffer, offset + 2) + (read_u16(buffer, offset) << 16)
-def read_u64(buffer):
+def read_u64(buffer, offset):
if get_target_endianness() == LITTLE_ENDIAN:
- return read_u32(buffer[0:4]) + (read_u32(buffer[4:8]) << 32)
+ return read_u32(buffer, offset) + (read_u32(buffer, offset + 4) << 32)
else:
- return read_u32(buffer[4:8]) + (read_u32(buffer[0:4]) << 32)
+ return read_u32(buffer, offset + 4) + (read_u32(buffer, offset) << 32)
target_arch = None
@@ -148,14 +150,14 @@
def probe_qemu():
try:
return gdb.execute("monitor info version", to_string=True) != ""
- except:
+ except gdb.error:
return False
def probe_kgdb():
try:
thread_info = gdb.execute("info thread 2", to_string=True)
return "shadowCPU0" in thread_info
- except:
+ except gdb.error:
return False
global gdbserver_type
@@ -172,7 +174,7 @@
def gdb_eval_or_none(expresssion):
try:
return gdb.parse_and_eval(expresssion)
- except:
+ except gdb.error:
return None
diff --git a/scripts/gdb/vmlinux-gdb.py b/scripts/gdb/vmlinux-gdb.py
index 6e0b0af..4136dc2 100644
--- a/scripts/gdb/vmlinux-gdb.py
+++ b/scripts/gdb/vmlinux-gdb.py
@@ -27,7 +27,13 @@
import linux.modules
import linux.dmesg
import linux.tasks
+ import linux.config
import linux.cpus
import linux.lists
+ import linux.rbtree
import linux.proc
import linux.constants
+ import linux.timerlist
+ import linux.clk
+ import linux.genpd
+ import linux.device
diff --git a/scripts/gen_compile_commands.py b/scripts/gen_compile_commands.py
new file mode 100755
index 0000000..c458696
--- /dev/null
+++ b/scripts/gen_compile_commands.py
@@ -0,0 +1,151 @@
+#!/usr/bin/env python
+# SPDX-License-Identifier: GPL-2.0
+#
+# Copyright (C) Google LLC, 2018
+#
+# Author: Tom Roeder <tmroeder@google.com>
+#
+"""A tool for generating compile_commands.json in the Linux kernel."""
+
+import argparse
+import json
+import logging
+import os
+import re
+
+_DEFAULT_OUTPUT = 'compile_commands.json'
+_DEFAULT_LOG_LEVEL = 'WARNING'
+
+_FILENAME_PATTERN = r'^\..*\.cmd$'
+_LINE_PATTERN = r'^cmd_[^ ]*\.o := (.* )([^ ]*\.c)$'
+_VALID_LOG_LEVELS = ['DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL']
+
+# A kernel build generally has over 2000 entries in its compile_commands.json
+# database. If this code finds 300 or fewer, then warn the user that they might
+# not have all the .cmd files, and they might need to compile the kernel.
+_LOW_COUNT_THRESHOLD = 300
+
+
+def parse_arguments():
+ """Sets up and parses command-line arguments.
+
+ Returns:
+ log_level: A logging level to filter log output.
+ directory: The directory to search for .cmd files.
+ output: Where to write the compile-commands JSON file.
+ """
+ usage = 'Creates a compile_commands.json database from kernel .cmd files'
+ parser = argparse.ArgumentParser(description=usage)
+
+ directory_help = ('Path to the kernel source directory to search '
+ '(defaults to the working directory)')
+ parser.add_argument('-d', '--directory', type=str, help=directory_help)
+
+ output_help = ('The location to write compile_commands.json (defaults to '
+ 'compile_commands.json in the search directory)')
+ parser.add_argument('-o', '--output', type=str, help=output_help)
+
+ log_level_help = ('The level of log messages to produce (one of ' +
+ ', '.join(_VALID_LOG_LEVELS) + '; defaults to ' +
+ _DEFAULT_LOG_LEVEL + ')')
+ parser.add_argument(
+ '--log_level', type=str, default=_DEFAULT_LOG_LEVEL,
+ help=log_level_help)
+
+ args = parser.parse_args()
+
+ log_level = args.log_level
+ if log_level not in _VALID_LOG_LEVELS:
+ raise ValueError('%s is not a valid log level' % log_level)
+
+ directory = args.directory or os.getcwd()
+ output = args.output or os.path.join(directory, _DEFAULT_OUTPUT)
+ directory = os.path.abspath(directory)
+
+ return log_level, directory, output
+
+
+def process_line(root_directory, file_directory, command_prefix, relative_path):
+ """Extracts information from a .cmd line and creates an entry from it.
+
+ Args:
+ root_directory: The directory that was searched for .cmd files. Usually
+ used directly in the "directory" entry in compile_commands.json.
+ file_directory: The path to the directory the .cmd file was found in.
+ command_prefix: The extracted command line, up to the last element.
+ relative_path: The .c file from the end of the extracted command.
+ Usually relative to root_directory, but sometimes relative to
+ file_directory and sometimes neither.
+
+ Returns:
+ An entry to append to compile_commands.
+
+ Raises:
+ ValueError: Could not find the extracted file based on relative_path and
+ root_directory or file_directory.
+ """
+ # The .cmd files are intended to be included directly by Make, so they
+ # escape the pound sign '#', either as '\#' or '$(pound)' (depending on the
+ # kernel version). The compile_commands.json file is not interepreted
+ # by Make, so this code replaces the escaped version with '#'.
+ prefix = command_prefix.replace('\#', '#').replace('$(pound)', '#')
+
+ cur_dir = root_directory
+ expected_path = os.path.join(cur_dir, relative_path)
+ if not os.path.exists(expected_path):
+ # Try using file_directory instead. Some of the tools have a different
+ # style of .cmd file than the kernel.
+ cur_dir = file_directory
+ expected_path = os.path.join(cur_dir, relative_path)
+ if not os.path.exists(expected_path):
+ raise ValueError('File %s not in %s or %s' %
+ (relative_path, root_directory, file_directory))
+ return {
+ 'directory': cur_dir,
+ 'file': relative_path,
+ 'command': prefix + relative_path,
+ }
+
+
+def main():
+ """Walks through the directory and finds and parses .cmd files."""
+ log_level, directory, output = parse_arguments()
+
+ level = getattr(logging, log_level)
+ logging.basicConfig(format='%(levelname)s: %(message)s', level=level)
+
+ filename_matcher = re.compile(_FILENAME_PATTERN)
+ line_matcher = re.compile(_LINE_PATTERN)
+
+ compile_commands = []
+ for dirpath, _, filenames in os.walk(directory):
+ for filename in filenames:
+ if not filename_matcher.match(filename):
+ continue
+ filepath = os.path.join(dirpath, filename)
+
+ with open(filepath, 'rt') as f:
+ for line in f:
+ result = line_matcher.match(line)
+ if not result:
+ continue
+
+ try:
+ entry = process_line(directory, dirpath,
+ result.group(1), result.group(2))
+ compile_commands.append(entry)
+ except ValueError as err:
+ logging.info('Could not add line from %s: %s',
+ filepath, err)
+
+ with open(output, 'wt') as f:
+ json.dump(compile_commands, f, indent=2, sort_keys=True)
+
+ count = len(compile_commands)
+ if count < _LOW_COUNT_THRESHOLD:
+ logging.warning(
+ 'Found %s entries. Have you compiled the kernel?', count)
+
+
+if __name__ == '__main__':
+ main()
diff --git a/scripts/gen_ksymdeps.sh b/scripts/gen_ksymdeps.sh
new file mode 100755
index 0000000..1324986
--- /dev/null
+++ b/scripts/gen_ksymdeps.sh
@@ -0,0 +1,25 @@
+#!/bin/sh
+# SPDX-License-Identifier: GPL-2.0
+
+set -e
+
+# List of exported symbols
+ksyms=$($NM $1 | sed -n 's/.*__ksym_marker_\(.*\)/\1/p' | tr A-Z a-z)
+
+if [ -z "$ksyms" ]; then
+ exit 0
+fi
+
+echo
+echo "ksymdeps_$1 := \\"
+
+for s in $ksyms
+do
+ echo $s | sed -e 's:^_*: $(wildcard include/ksym/:' \
+ -e 's:__*:/:g' -e 's/$/.h) \\/'
+done
+
+echo
+echo "$1: \$(ksymdeps_$1)"
+echo
+echo "\$(ksymdeps_$1):"
diff --git a/scripts/genksyms/Makefile b/scripts/genksyms/Makefile
index 03b7ce9..78629f5 100644
--- a/scripts/genksyms/Makefile
+++ b/scripts/genksyms/Makefile
@@ -12,27 +12,20 @@
#
# Just in case, run "$(YACC) --version" without suppressing stderr
# so that 'bison: not found' will be displayed if it is missing.
-ifeq ($(findstring 1,$(KBUILD_ENABLE_EXTRA_GCC_CHECKS)),)
+ifeq ($(findstring 1,$(KBUILD_EXTRA_WARN)),)
quiet_cmd_bison_no_warn = $(quiet_cmd_bison)
cmd_bison_no_warn = $(YACC) --version >/dev/null; \
$(cmd_bison) 2>/dev/null
-$(obj)/parse.tab.c: $(src)/parse.y FORCE
+$(obj)/pars%.tab.c $(obj)/pars%.tab.h: $(src)/pars%.y FORCE
$(call if_changed,bison_no_warn)
-quiet_cmd_bison_h_no_warn = $(quiet_cmd_bison_h)
- cmd_bison_h_no_warn = $(YACC) --version >/dev/null; \
- $(cmd_bison_h) 2>/dev/null
-
-$(obj)/parse.tab.h: $(src)/parse.y FORCE
- $(call if_changed,bison_h_no_warn)
-
endif
# -I needed for generated C source (shipped source)
-HOSTCFLAGS_parse.tab.o := -I$(src)
-HOSTCFLAGS_lex.lex.o := -I$(src)
+HOSTCFLAGS_parse.tab.o := -I $(srctree)/$(src)
+HOSTCFLAGS_lex.lex.o := -I $(srctree)/$(src)
# dependencies on generated files need to be listed explicitly
$(obj)/lex.lex.o: $(obj)/parse.tab.h
diff --git a/scripts/genksyms/genksyms.c b/scripts/genksyms/genksyms.c
index e007840..23eff23 100644
--- a/scripts/genksyms/genksyms.c
+++ b/scripts/genksyms/genksyms.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
/* Generate kernel symbol version hashes.
Copyright 1996, 1997 Linux International.
@@ -7,19 +8,7 @@
This file was part of the Linux modutils 2.4.22: moved back into the
kernel sources by Rusty Russell/Kai Germaschewski.
- This program is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published by the
- Free Software Foundation; either version 2 of the License, or (at your
- option) any later version.
-
- This program is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software Foundation,
- Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+ */
#include <stdio.h>
#include <string.h>
diff --git a/scripts/genksyms/genksyms.h b/scripts/genksyms/genksyms.h
index b724a02..2bcdb9b 100644
--- a/scripts/genksyms/genksyms.h
+++ b/scripts/genksyms/genksyms.h
@@ -1,3 +1,4 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
/* Generate kernel symbol version hashes.
Copyright 1996, 1997 Linux International.
@@ -6,19 +7,7 @@
This file is part of the Linux modutils.
- This program is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published by the
- Free Software Foundation; either version 2 of the License, or (at your
- option) any later version.
-
- This program is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software Foundation,
- Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+ */
#ifndef MODUTILS_GENKSYMS_H
#define MODUTILS_GENKSYMS_H 1
diff --git a/scripts/genksyms/keywords.c b/scripts/genksyms/keywords.c
index 9f40bcd..7a85c4e 100644
--- a/scripts/genksyms/keywords.c
+++ b/scripts/genksyms/keywords.c
@@ -1,12 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0-only
static struct resword {
const char *name;
int token;
} keywords[] = {
- { "EXPORT_SYMBOL", EXPORT_SYMBOL_KEYW },
- { "EXPORT_SYMBOL_GPL", EXPORT_SYMBOL_KEYW },
- { "EXPORT_SYMBOL_GPL_FUTURE", EXPORT_SYMBOL_KEYW },
- { "EXPORT_UNUSED_SYMBOL", EXPORT_SYMBOL_KEYW },
- { "EXPORT_UNUSED_SYMBOL_GPL", EXPORT_SYMBOL_KEYW },
+ { "__GENKSYMS_EXPORT_SYMBOL", EXPORT_SYMBOL_KEYW },
{ "__asm", ASM_KEYW },
{ "__asm__", ASM_KEYW },
{ "__attribute", ATTRIBUTE_KEYW },
@@ -24,6 +21,10 @@
{ "__volatile__", VOLATILE_KEYW },
{ "__builtin_va_list", VA_LIST_KEYW },
+ { "__int128", BUILTIN_INT_KEYW },
+ { "__int128_t", BUILTIN_INT_KEYW },
+ { "__uint128_t", BUILTIN_INT_KEYW },
+
// According to rth, c99 defines "_Bool", __restrict", __restrict__", "restrict". KAO
{ "_Bool", BOOL_KEYW },
{ "_restrict", RESTRICT_KEYW },
diff --git a/scripts/genksyms/lex.l b/scripts/genksyms/lex.l
index d29c774..e265c5d 100644
--- a/scripts/genksyms/lex.l
+++ b/scripts/genksyms/lex.l
@@ -1,25 +1,13 @@
-/* Lexical analysis for genksyms.
- Copyright 1996, 1997 Linux International.
-
- New implementation contributed by Richard Henderson <rth@tamu.edu>
- Based on original work by Bjorn Ekwall <bj0rn@blox.se>
-
- Taken from Linux modutils 2.4.22.
-
- This program is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published by the
- Free Software Foundation; either version 2 of the License, or (at your
- option) any later version.
-
- This program is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software Foundation,
- Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
-
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Lexical analysis for genksyms.
+ * Copyright 1996, 1997 Linux International.
+ *
+ * New implementation contributed by Richard Henderson <rth@tamu.edu>
+ * Based on original work by Bjorn Ekwall <bj0rn@blox.se>
+ *
+ * Taken from Linux modutils 2.4.22.
+ */
%{
diff --git a/scripts/genksyms/parse.y b/scripts/genksyms/parse.y
index 00a6d7e..e22b4224 100644
--- a/scripts/genksyms/parse.y
+++ b/scripts/genksyms/parse.y
@@ -1,25 +1,13 @@
-/* C global declaration parser for genksyms.
- Copyright 1996, 1997 Linux International.
-
- New implementation contributed by Richard Henderson <rth@tamu.edu>
- Based on original work by Bjorn Ekwall <bj0rn@blox.se>
-
- This file is part of the Linux modutils.
-
- This program is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published by the
- Free Software Foundation; either version 2 of the License, or (at your
- option) any later version.
-
- This program is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software Foundation,
- Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
-
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * C global declaration parser for genksyms.
+ * Copyright 1996, 1997 Linux International.
+ *
+ * New implementation contributed by Richard Henderson <rth@tamu.edu>
+ * Based on original work by Bjorn Ekwall <bj0rn@blox.se>
+ *
+ * This file is part of the Linux modutils.
+ */
%{
@@ -76,6 +64,7 @@
%token ATTRIBUTE_KEYW
%token AUTO_KEYW
%token BOOL_KEYW
+%token BUILTIN_INT_KEYW
%token CHAR_KEYW
%token CONST_KEYW
%token DOUBLE_KEYW
@@ -263,6 +252,7 @@
| VOID_KEYW
| BOOL_KEYW
| VA_LIST_KEYW
+ | BUILTIN_INT_KEYW
| TYPE { (*$1)->tag = SYM_TYPEDEF; $$ = $1; }
;
diff --git a/scripts/get_abi.pl b/scripts/get_abi.pl
new file mode 100755
index 0000000..c738cb7
--- /dev/null
+++ b/scripts/get_abi.pl
@@ -0,0 +1,468 @@
+#!/usr/bin/perl
+# SPDX-License-Identifier: GPL-2.0
+
+use strict;
+use Pod::Usage;
+use Getopt::Long;
+use File::Find;
+use Fcntl ':mode';
+
+my $help;
+my $man;
+my $debug;
+my $prefix="Documentation/ABI";
+
+GetOptions(
+ "debug|d+" => \$debug,
+ "dir=s" => \$prefix,
+ 'help|?' => \$help,
+ man => \$man
+) or pod2usage(2);
+
+pod2usage(1) if $help;
+pod2usage(-exitstatus => 0, -verbose => 2) if $man;
+
+pod2usage(2) if (scalar @ARGV < 1 || @ARGV > 2);
+
+my ($cmd, $arg) = @ARGV;
+
+pod2usage(2) if ($cmd ne "search" && $cmd ne "rest" && $cmd ne "validate");
+pod2usage(2) if ($cmd eq "search" && !$arg);
+
+require Data::Dumper if ($debug);
+
+my %data;
+
+#
+# Displays an error message, printing file name and line
+#
+sub parse_error($$$$) {
+ my ($file, $ln, $msg, $data) = @_;
+
+ print STDERR "file $file#$ln: $msg at\n\t$data";
+}
+
+#
+# Parse an ABI file, storing its contents at %data
+#
+sub parse_abi {
+ my $file = $File::Find::name;
+
+ my $mode = (stat($file))[2];
+ return if ($mode & S_IFDIR);
+ return if ($file =~ m,/README,);
+
+ my $name = $file;
+ $name =~ s,.*/,,;
+
+ my $nametag = "File $name";
+ $data{$nametag}->{what} = "File $name";
+ $data{$nametag}->{type} = "File";
+ $data{$nametag}->{file} = $name;
+ $data{$nametag}->{filepath} = $file;
+ $data{$nametag}->{is_file} = 1;
+
+ my $type = $file;
+ $type =~ s,.*/(.*)/.*,$1,;
+
+ my $what;
+ my $new_what;
+ my $tag;
+ my $ln;
+ my $xrefs;
+ my $space;
+ my @labels;
+ my $label;
+
+ print STDERR "Opening $file\n" if ($debug > 1);
+ open IN, $file;
+ while(<IN>) {
+ $ln++;
+ if (m/^(\S+)(:\s*)(.*)/i) {
+ my $new_tag = lc($1);
+ my $sep = $2;
+ my $content = $3;
+
+ if (!($new_tag =~ m/(what|where|date|kernelversion|contact|description|users)/)) {
+ if ($tag eq "description") {
+ # New "tag" is actually part of
+ # description. Don't consider it a tag
+ $new_tag = "";
+ } elsif ($tag ne "") {
+ parse_error($file, $ln, "tag '$tag' is invalid", $_);
+ }
+ }
+
+ # Invalid, but it is a common mistake
+ if ($new_tag eq "where") {
+ parse_error($file, $ln, "tag 'Where' is invalid. Should be 'What:' instead", $_);
+ $new_tag = "what";
+ }
+
+ if ($new_tag =~ m/what/) {
+ $space = "";
+ if ($tag =~ m/what/) {
+ $what .= ", " . $content;
+ } else {
+ parse_error($file, $ln, "What '$what' doesn't have a description", "") if ($what && !$data{$what}->{description});
+
+ $what = $content;
+ $label = $content;
+ $new_what = 1;
+ }
+ push @labels, [($content, $label)];
+ $tag = $new_tag;
+
+ push @{$data{$nametag}->{xrefs}}, [($content, $label)] if ($data{$nametag}->{what});
+ next;
+ }
+
+ if ($tag ne "" && $new_tag) {
+ $tag = $new_tag;
+
+ if ($new_what) {
+ @{$data{$what}->{label}} = @labels if ($data{$nametag}->{what});
+ @labels = ();
+ $label = "";
+ $new_what = 0;
+
+ $data{$what}->{type} = $type;
+ $data{$what}->{file} = $name;
+ $data{$what}->{filepath} = $file;
+ print STDERR "\twhat: $what\n" if ($debug > 1);
+ }
+
+ if (!$what) {
+ parse_error($file, $ln, "'What:' should come first:", $_);
+ next;
+ }
+ if ($tag eq "description") {
+ next if ($content =~ m/^\s*$/);
+ if ($content =~ m/^(\s*)(.*)/) {
+ my $new_content = $2;
+ $space = $new_tag . $sep . $1;
+ while ($space =~ s/\t+/' ' x (length($&) * 8 - length($`) % 8)/e) {}
+ $space =~ s/./ /g;
+ $data{$what}->{$tag} .= "$new_content\n";
+ }
+ } else {
+ $data{$what}->{$tag} = $content;
+ }
+ next;
+ }
+ }
+
+ # Store any contents before tags at the database
+ if (!$tag && $data{$nametag}->{what}) {
+ $data{$nametag}->{description} .= $_;
+ next;
+ }
+
+ if ($tag eq "description") {
+ if (!$data{$what}->{description}) {
+ next if (m/^\s*\n/);
+ if (m/^(\s*)(.*)/) {
+ $space = $1;
+ while ($space =~ s/\t+/' ' x (length($&) * 8 - length($`) % 8)/e) {}
+ $data{$what}->{$tag} .= "$2\n";
+ }
+ } else {
+ my $content = $_;
+ if (m/^\s*\n/) {
+ $data{$what}->{$tag} .= $content;
+ next;
+ }
+
+ while ($content =~ s/\t+/' ' x (length($&) * 8 - length($`) % 8)/e) {}
+ $space = "" if (!($content =~ s/^($space)//));
+
+ # Compress spaces with tabs
+ $content =~ s<^ {8}> <\t>;
+ $content =~ s<^ {1,7}\t> <\t>;
+ $content =~ s< {1,7}\t> <\t>;
+ $data{$what}->{$tag} .= $content;
+ }
+ next;
+ }
+ if (m/^\s*(.*)/) {
+ $data{$what}->{$tag} .= "\n$1";
+ $data{$what}->{$tag} =~ s/\n+$//;
+ next;
+ }
+
+ # Everything else is error
+ parse_error($file, $ln, "Unexpected line:", $_);
+ }
+ $data{$nametag}->{description} =~ s/^\n+//;
+ close IN;
+}
+
+#
+# Outputs the book on ReST format
+#
+
+my %labels;
+
+sub output_rest {
+ foreach my $what (sort {
+ ($data{$a}->{type} eq "File") cmp ($data{$b}->{type} eq "File") ||
+ $a cmp $b
+ } keys %data) {
+ my $type = $data{$what}->{type};
+ my $file = $data{$what}->{file};
+ my $filepath = $data{$what}->{filepath};
+
+ my $w = $what;
+ $w =~ s/([\(\)\_\-\*\=\^\~\\])/\\$1/g;
+
+
+ foreach my $p (@{$data{$what}->{label}}) {
+ my ($content, $label) = @{$p};
+ $label = "abi_" . $label . " ";
+ $label =~ tr/A-Z/a-z/;
+
+ # Convert special chars to "_"
+ $label =~s/([\x00-\x2f\x3a-\x40\x5b-\x60\x7b-\xff])/_/g;
+ $label =~ s,_+,_,g;
+ $label =~ s,_$,,;
+
+ # Avoid duplicated labels
+ while (defined($labels{$label})) {
+ my @chars = ("A".."Z", "a".."z");
+ $label .= $chars[rand @chars];
+ }
+ $labels{$label} = 1;
+
+ $data{$what}->{label} .= $label;
+
+ printf ".. _%s:\n\n", $label;
+
+ # only one label is enough
+ last;
+ }
+
+
+ $filepath =~ s,.*/(.*/.*),\1,;;
+ $filepath =~ s,[/\-],_,g;;
+ my $fileref = "abi_file_".$filepath;
+
+ if ($type eq "File") {
+ my $bar = $w;
+ $bar =~ s/./-/g;
+
+ print ".. _$fileref:\n\n";
+ print "$w\n$bar\n\n";
+ } else {
+ my @names = split /\s*,\s*/,$w;
+
+ my $len = 0;
+
+ foreach my $name (@names) {
+ $len = length($name) if (length($name) > $len);
+ }
+
+ print "What:\n\n";
+
+ print "+-" . "-" x $len . "-+\n";
+ foreach my $name (@names) {
+ printf "| %s", $name . " " x ($len - length($name)) . " |\n";
+ print "+-" . "-" x $len . "-+\n";
+ }
+ print "\n";
+ }
+
+ print "Defined on file :ref:`$file <$fileref>`\n\n" if ($type ne "File");
+
+ my $desc = $data{$what}->{description};
+ $desc =~ s/^\s+//;
+
+ # Remove title markups from the description, as they won't work
+ $desc =~ s/\n[\-\*\=\^\~]+\n/\n/g;
+
+ if (!($desc =~ /^\s*$/)) {
+ if ($desc =~ m/\:\n/ || $desc =~ m/\n[\t ]+/ || $desc =~ m/[\x00-\x08\x0b-\x1f\x7b-\xff]/) {
+ # put everything inside a code block
+ $desc =~ s/\n/\n /g;
+
+ print "::\n\n";
+ print " $desc\n\n";
+ } else {
+ # Escape any special chars from description
+ $desc =~s/([\x00-\x08\x0b-\x1f\x21-\x2a\x2d\x2f\x3c-\x40\x5c\x5e-\x60\x7b-\xff])/\\$1/g;
+
+ print "$desc\n\n";
+ }
+ } else {
+ print "DESCRIPTION MISSING for $what\n\n" if (!$data{$what}->{is_file});
+ }
+
+ if ($data{$what}->{xrefs}) {
+ printf "Has the following ABI:\n\n";
+
+ foreach my $p(@{$data{$what}->{xrefs}}) {
+ my ($content, $label) = @{$p};
+ $label = "abi_" . $label . " ";
+ $label =~ tr/A-Z/a-z/;
+
+ # Convert special chars to "_"
+ $label =~s/([\x00-\x2f\x3a-\x40\x5b-\x60\x7b-\xff])/_/g;
+ $label =~ s,_+,_,g;
+ $label =~ s,_$,,;
+
+ # Escape special chars from content
+ $content =~s/([\x00-\x1f\x21-\x2f\x3a-\x40\x7b-\xff])/\\$1/g;
+
+ print "- :ref:`$content <$label>`\n\n";
+ }
+ }
+ }
+}
+
+#
+# Searches for ABI symbols
+#
+sub search_symbols {
+ foreach my $what (sort keys %data) {
+ next if (!($what =~ m/($arg)/));
+
+ my $type = $data{$what}->{type};
+ next if ($type eq "File");
+
+ my $file = $data{$what}->{filepath};
+
+ my $bar = $what;
+ $bar =~ s/./-/g;
+
+ print "\n$what\n$bar\n\n";
+
+ my $kernelversion = $data{$what}->{kernelversion};
+ my $contact = $data{$what}->{contact};
+ my $users = $data{$what}->{users};
+ my $date = $data{$what}->{date};
+ my $desc = $data{$what}->{description};
+ $kernelversion =~ s/^\s+//;
+ $contact =~ s/^\s+//;
+ $users =~ s/^\s+//;
+ $users =~ s/\n//g;
+ $date =~ s/^\s+//;
+ $desc =~ s/^\s+//;
+
+ printf "Kernel version:\t\t%s\n", $kernelversion if ($kernelversion);
+ printf "Date:\t\t\t%s\n", $date if ($date);
+ printf "Contact:\t\t%s\n", $contact if ($contact);
+ printf "Users:\t\t\t%s\n", $users if ($users);
+ print "Defined on file:\t$file\n\n";
+ print "Description:\n\n$desc";
+ }
+}
+
+
+#
+# Parses all ABI files located at $prefix dir
+#
+find({wanted =>\&parse_abi, no_chdir => 1}, $prefix);
+
+print STDERR Data::Dumper->Dump([\%data], [qw(*data)]) if ($debug);
+
+#
+# Handles the command
+#
+if ($cmd eq "rest") {
+ output_rest;
+} elsif ($cmd eq "search") {
+ search_symbols;
+}
+
+
+__END__
+
+=head1 NAME
+
+abi_book.pl - parse the Linux ABI files and produce a ReST book.
+
+=head1 SYNOPSIS
+
+B<abi_book.pl> [--debug] [--man] [--help] [--dir=<dir>] <COMAND> [<ARGUMENT>]
+
+Where <COMMAND> can be:
+
+=over 8
+
+B<search> [SEARCH_REGEX] - search for [SEARCH_REGEX] inside ABI
+
+B<rest> - output the ABI in ReST markup language
+
+B<validate> - validate the ABI contents
+
+=back
+
+=head1 OPTIONS
+
+=over 8
+
+=item B<--dir>
+
+Changes the location of the ABI search. By default, it uses
+the Documentation/ABI directory.
+
+=item B<--debug>
+
+Put the script in verbose mode, useful for debugging. Can be called multiple
+times, to increase verbosity.
+
+=item B<--help>
+
+Prints a brief help message and exits.
+
+=item B<--man>
+
+Prints the manual page and exits.
+
+=back
+
+=head1 DESCRIPTION
+
+Parse the Linux ABI files from ABI DIR (usually located at Documentation/ABI),
+allowing to search for ABI symbols or to produce a ReST book containing
+the Linux ABI documentation.
+
+=head1 EXAMPLES
+
+Search for all stable symbols with the word "usb":
+
+=over 8
+
+$ scripts/get_abi.pl search usb --dir Documentation/ABI/stable
+
+=back
+
+Search for all symbols that match the regex expression "usb.*cap":
+
+=over 8
+
+$ scripts/get_abi.pl search usb.*cap
+
+=back
+
+Output all obsoleted symbols in ReST format
+
+=over 8
+
+$ scripts/get_abi.pl rest --dir Documentation/ABI/obsolete
+
+=back
+
+=head1 BUGS
+
+Report bugs to Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
+
+=head1 COPYRIGHT
+
+Copyright (c) 2016-2019 by Mauro Carvalho Chehab <mchehab+samsung@kernel.org>.
+
+License GPLv2: GNU GPL version 2 <http://gnu.org/licenses/gpl.html>.
+
+This is free software: you are free to change and redistribute it.
+There is NO WARRANTY, to the extent permitted by law.
+
+=cut
diff --git a/scripts/get_dvb_firmware b/scripts/get_dvb_firmware
index f3f2302..1a90802 100755
--- a/scripts/get_dvb_firmware
+++ b/scripts/get_dvb_firmware
@@ -1,22 +1,9 @@
#!/usr/bin/env perl
+# SPDX-License-Identifier: GPL-2.0-or-later
# DVB firmware extractor
#
# (c) 2004 Andrew de Quincey
#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-#
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
use File::Temp qw/ tempdir /;
use IO::Handle;
diff --git a/scripts/get_maintainer.pl b/scripts/get_maintainer.pl
index c1c088e..5ef5921 100755
--- a/scripts/get_maintainer.pl
+++ b/scripts/get_maintainer.pl
@@ -27,6 +27,7 @@
my $email_maintainer = 1;
my $email_reviewer = 1;
my $email_list = 1;
+my $email_moderated_list = 1;
my $email_subscriber_list = 0;
my $email_git_penguin_chiefs = 0;
my $email_git = 0;
@@ -248,6 +249,7 @@
'r!' => \$email_reviewer,
'n!' => \$email_usename,
'l!' => \$email_list,
+ 'moderated!' => \$email_moderated_list,
's!' => \$email_subscriber_list,
'multiline!' => \$output_multiline,
'roles!' => \$output_roles,
@@ -1023,7 +1025,8 @@
--r => include reviewer(s) if any
--n => include name 'Full Name <addr\@domain.tld>'
--l => include list(s) if any
- --s => include subscriber only list(s) if any
+ --moderated => include moderated lists(s) if any (default: true)
+ --s => include subscriber only list(s) if any (default: false)
--remove-duplicates => minimize duplicate email names/addresses
--roles => show roles (status:subsystem, git-signer, list, etc...)
--rolestats => show roles and statistics (commits/total_commits, %)
@@ -1313,11 +1316,14 @@
} else {
if ($email_list) {
if (!$hash_list_to{lc($list_address)}) {
- $hash_list_to{lc($list_address)} = 1;
if ($list_additional =~ m/moderated/) {
- push(@list_to, [$list_address,
- "moderated list${list_role}"]);
+ if ($email_moderated_list) {
+ $hash_list_to{lc($list_address)} = 1;
+ push(@list_to, [$list_address,
+ "moderated list${list_role}"]);
+ }
} else {
+ $hash_list_to{lc($list_address)} = 1;
push(@list_to, [$list_address,
"open list${list_role}"]);
}
diff --git a/scripts/gfp-translate b/scripts/gfp-translate
index c9230e1..b2ce416 100755
--- a/scripts/gfp-translate
+++ b/scripts/gfp-translate
@@ -1,7 +1,7 @@
#!/bin/bash
+# SPDX-License-Identifier: GPL-2.0-only
# Translate the bits making up a GFP mask
# (c) 2009, Mel Gorman <mel@csn.ul.ie>
-# Licensed under the terms of the GNU GPL License version 2
SOURCE=
GFPMASK=none
diff --git a/scripts/headers.sh b/scripts/headers.sh
deleted file mode 100755
index e0f883e..0000000
--- a/scripts/headers.sh
+++ /dev/null
@@ -1,29 +0,0 @@
-#!/bin/sh
-# SPDX-License-Identifier: GPL-2.0
-# Run headers_$1 command for all suitable architectures
-
-# Stop on error
-set -e
-
-do_command()
-{
- if [ -f ${srctree}/arch/$2/include/asm/Kbuild ]; then
- make ARCH=$2 KBUILD_HEADERS=$1 headers_$1
- else
- printf "Ignoring arch: %s\n" ${arch}
- fi
-}
-
-archs=${HDR_ARCH_LIST:-$(ls ${srctree}/arch)}
-
-for arch in ${archs}; do
- case ${arch} in
- um) # no userspace export
- ;;
- *)
- if [ -d ${srctree}/arch/${arch} ]; then
- do_command $1 ${arch}
- fi
- ;;
- esac
-done
diff --git a/scripts/headers_install.sh b/scripts/headers_install.sh
index 593f887..a07668a 100755
--- a/scripts/headers_install.sh
+++ b/scripts/headers_install.sh
@@ -1,47 +1,117 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
-if [ $# -lt 2 ]
+if [ $# -ne 2 ]
then
- echo "Usage: headers_install.sh OUTDIR SRCDIR [FILES...]"
+ echo "Usage: headers_install.sh INFILE OUTFILE"
echo
echo "Prepares kernel header files for use by user space, by removing"
echo "all compiler.h definitions and #includes, removing any"
echo "#ifdef __KERNEL__ sections, and putting __underscores__ around"
echo "asm/inline/volatile keywords."
echo
- echo "OUTDIR: directory to write each userspace header FILE to."
- echo "SRCDIR: source directory where files are picked."
- echo "FILES: list of header files to operate on."
+ echo "INFILE: header file to operate on"
+ echo "OUTFILE: output file which the processed header is writen to"
exit 1
fi
# Grab arguments
+INFILE=$1
+OUTFILE=$2
+TMPFILE=$OUTFILE.tmp
-OUTDIR="$1"
-shift
-SRCDIR="$1"
-shift
+trap 'rm -f $OUTFILE $TMPFILE' EXIT
-# Iterate through files listed on command line
+# SPDX-License-Identifier with GPL variants must have "WITH Linux-syscall-note"
+if [ -n "$(sed -n -e "/SPDX-License-Identifier:.*GPL-/{/WITH Linux-syscall-note/!p}" $INFILE)" ]; then
+ echo "error: $INFILE: missing \"WITH Linux-syscall-note\" for SPDX-License-Identifier" >&2
+ exit 1
+fi
-FILE=
-trap 'rm -f "$OUTDIR/$FILE" "$OUTDIR/$FILE.sed"' EXIT
-for i in "$@"
+sed -E -e '
+ s/([[:space:](])(__user|__force|__iomem)[[:space:]]/\1/g
+ s/__attribute_const__([[:space:]]|$)/\1/g
+ s@^#include <linux/compiler(|_types).h>@@
+ s/(^|[^a-zA-Z0-9])__packed([^a-zA-Z0-9_]|$)/\1__attribute__((packed))\2/g
+ s/(^|[[:space:](])(inline|asm|volatile)([[:space:](]|$)/\1__\2__\3/g
+ s@#(ifndef|define|endif[[:space:]]*/[*])[[:space:]]*_UAPI@#\1 @
+' $INFILE > $TMPFILE || exit 1
+
+scripts/unifdef -U__KERNEL__ -D__EXPORTED_HEADERS__ $TMPFILE > $OUTFILE
+[ $? -gt 1 ] && exit 1
+
+# Remove /* ... */ style comments, and find CONFIG_ references in code
+configs=$(sed -e '
+:comment
+ s:/\*[^*][^*]*:/*:
+ s:/\*\*\**\([^/]\):/*\1:
+ t comment
+ s:/\*\*/: :
+ t comment
+ /\/\*/! b check
+ N
+ b comment
+:print
+ P
+ D
+:check
+ s:^\(CONFIG_[[:alnum:]_]*\):\1\n:
+ t print
+ s:^[[:alnum:]_][[:alnum:]_]*::
+ s:^[^[:alnum:]_][^[:alnum:]_]*::
+ t check
+ d
+' $OUTFILE)
+
+# The entries in the following list are not warned.
+# Please do not add a new entry. This list is only for existing ones.
+# The list will be reduced gradually, and deleted eventually. (hopefully)
+#
+# The format is <file-name>:<CONFIG-option> in each line.
+config_leak_ignores="
+arch/alpha/include/uapi/asm/setup.h:CONFIG_ALPHA_LEGACY_START_ADDRESS
+arch/arc/include/uapi/asm/page.h:CONFIG_ARC_PAGE_SIZE_16K
+arch/arc/include/uapi/asm/page.h:CONFIG_ARC_PAGE_SIZE_4K
+arch/arc/include/uapi/asm/swab.h:CONFIG_ARC_HAS_SWAPE
+arch/arm/include/uapi/asm/ptrace.h:CONFIG_CPU_ENDIAN_BE8
+arch/hexagon/include/uapi/asm/ptrace.h:CONFIG_HEXAGON_ARCH_VERSION
+arch/hexagon/include/uapi/asm/user.h:CONFIG_HEXAGON_ARCH_VERSION
+arch/ia64/include/uapi/asm/cmpxchg.h:CONFIG_IA64_DEBUG_CMPXCHG
+arch/m68k/include/uapi/asm/ptrace.h:CONFIG_COLDFIRE
+arch/nios2/include/uapi/asm/swab.h:CONFIG_NIOS2_CI_SWAB_NO
+arch/nios2/include/uapi/asm/swab.h:CONFIG_NIOS2_CI_SWAB_SUPPORT
+arch/sh/include/uapi/asm/ptrace.h:CONFIG_CPU_SH5
+arch/sh/include/uapi/asm/sigcontext.h:CONFIG_CPU_SH5
+arch/sh/include/uapi/asm/stat.h:CONFIG_CPU_SH5
+arch/x86/include/uapi/asm/auxvec.h:CONFIG_IA32_EMULATION
+arch/x86/include/uapi/asm/auxvec.h:CONFIG_X86_64
+arch/x86/include/uapi/asm/mman.h:CONFIG_X86_INTEL_MEMORY_PROTECTION_KEYS
+include/uapi/asm-generic/fcntl.h:CONFIG_64BIT
+include/uapi/linux/atmdev.h:CONFIG_COMPAT
+include/uapi/linux/elfcore.h:CONFIG_BINFMT_ELF_FDPIC
+include/uapi/linux/eventpoll.h:CONFIG_PM_SLEEP
+include/uapi/linux/hw_breakpoint.h:CONFIG_HAVE_MIXED_BREAKPOINTS_REGS
+include/uapi/linux/pktcdvd.h:CONFIG_CDROM_PKTCDVD_WCACHE
+include/uapi/linux/raw.h:CONFIG_MAX_RAW_DEVS
+"
+
+for c in $configs
do
- FILE="$(basename "$i")"
- sed -E \
- -e 's/([[:space:](])(__user|__force|__iomem)[[:space:]]/\1/g' \
- -e 's/__attribute_const__([[:space:]]|$)/\1/g' \
- -e 's@^#include <linux/compiler(|_types).h>@@' \
- -e 's/(^|[^a-zA-Z0-9])__packed([^a-zA-Z0-9_]|$)/\1__attribute__((packed))\2/g' \
- -e 's/(^|[[:space:](])(inline|asm|volatile)([[:space:](]|$)/\1__\2__\3/g' \
- -e 's@#(ifndef|define|endif[[:space:]]*/[*])[[:space:]]*_UAPI@#\1 @' \
- "$SRCDIR/$i" > "$OUTDIR/$FILE.sed" || exit 1
- scripts/unifdef -U__KERNEL__ -D__EXPORTED_HEADERS__ "$OUTDIR/$FILE.sed" \
- > "$OUTDIR/$FILE"
- [ $? -gt 1 ] && exit 1
- rm -f "$OUTDIR/$FILE.sed"
+ warn=1
+
+ for ignore in $config_leak_ignores
+ do
+ if echo "$INFILE:$c" | grep -q "$ignore$"; then
+ warn=
+ break
+ fi
+ done
+
+ if [ "$warn" = 1 ]; then
+ echo "warning: $INFILE: leak $c to user-space" >&2
+ fi
done
+
+rm -f $TMPFILE
trap - EXIT
diff --git a/scripts/kallsyms.c b/scripts/kallsyms.c
index a9186a9..ae6504d 100644
--- a/scripts/kallsyms.c
+++ b/scripts/kallsyms.c
@@ -48,8 +48,6 @@
static struct addr_range text_ranges[] = {
{ "_stext", "_etext" },
{ "_sinittext", "_einittext" },
- { "_stext_l1", "_etext_l1" }, /* Blackfin on-chip L1 inst SRAM */
- { "_stext_l2", "_etext_l2" }, /* Blackfin on-chip L2 SRAM */
};
#define text_range_text (&text_ranges[0])
#define text_range_inittext (&text_ranges[1])
@@ -64,11 +62,11 @@
static int absolute_percpu = 0;
static int base_relative = 0;
-int token_profit[0x10000];
+static int token_profit[0x10000];
/* the table that holds the result of the compression */
-unsigned char best_table[256][2];
-unsigned char best_table_len[256];
+static unsigned char best_table[256][2];
+static unsigned char best_table_len[256];
static void usage(void)
@@ -82,7 +80,7 @@
* This ignores the intensely annoying "mapping symbols" found
* in ARM ELF files: $a, $t and $d.
*/
-static inline int is_arm_mapping_symbol(const char *str)
+static int is_arm_mapping_symbol(const char *str)
{
return str[0] == '$' && strchr("axtd", str[1])
&& (str[2] == '\0' || str[2] == '.');
@@ -120,8 +118,8 @@
fprintf(stderr, "Read error or end of file.\n");
return -1;
}
- if (strlen(sym) > KSYM_NAME_LEN) {
- fprintf(stderr, "Symbol %s too long for kallsyms (%zu vs %d).\n"
+ if (strlen(sym) >= 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;
@@ -152,6 +150,9 @@
/* exclude debugging symbols */
else if (stype == 'N' || stype == 'n')
return -1;
+ /* exclude s390 kasan local symbols */
+ else if (!strncmp(sym, ".LASANPC", 8))
+ return -1;
/* include the type field in the symbol name, so that it gets
* compressed together */
@@ -333,13 +334,13 @@
unsigned int *markers;
char buf[KSYM_NAME_LEN];
- printf("#include <asm/types.h>\n");
+ printf("#include <asm/bitsperlong.h>\n");
printf("#if BITS_PER_LONG == 64\n");
printf("#define PTR .quad\n");
- printf("#define ALGN .align 8\n");
+ printf("#define ALGN .balign 8\n");
printf("#else\n");
printf("#define PTR .long\n");
- printf("#define ALGN .align 4\n");
+ printf("#define ALGN .balign 4\n");
printf("#endif\n");
printf("\t.section .rodata, \"a\"\n");
@@ -405,7 +406,7 @@
}
output_label("kallsyms_num_syms");
- printf("\tPTR\t%u\n", table_cnt);
+ printf("\t.long\t%u\n", table_cnt);
printf("\n");
/* table of offset markers, that give the offset in the compressed stream
@@ -434,7 +435,7 @@
output_label("kallsyms_markers");
for (i = 0; i < ((table_cnt + 255) >> 8); i++)
- printf("\tPTR\t%d\n", markers[i]);
+ printf("\t.long\t%u\n", markers[i]);
printf("\n");
free(markers);
@@ -598,9 +599,6 @@
{
unsigned int i, j, c;
- memset(best_table, 0, sizeof(best_table));
- memset(best_table_len, 0, sizeof(best_table_len));
-
for (i = 0; i < table_cnt; i++) {
for (j = 0; j < table[i].len; j++) {
c = table[i].sym[j];
diff --git a/scripts/kconfig/.gitignore b/scripts/kconfig/.gitignore
index 0aabc1d..b5bf92f 100644
--- a/scripts/kconfig/.gitignore
+++ b/scripts/kconfig/.gitignore
@@ -2,6 +2,7 @@
# Generated files
#
*.moc
+*conf-cfg
#
# configuration programs
diff --git a/scripts/kconfig/Makefile b/scripts/kconfig/Makefile
index 67ed9f6..ef2f233 100644
--- a/scripts/kconfig/Makefile
+++ b/scripts/kconfig/Makefile
@@ -12,6 +12,10 @@
Kconfig := Kconfig
endif
+ifndef KBUILD_DEFCONFIG
+KBUILD_DEFCONFIG := defconfig
+endif
+
ifeq ($(quiet),silent_)
silent := -s
endif
@@ -68,29 +72,12 @@
$(simple-targets): $(obj)/conf
$< $(silent) --$@ $(Kconfig)
-PHONY += oldnoconfig silentoldconfig savedefconfig defconfig
-
-# oldnoconfig is an alias of olddefconfig, because people already are dependent
-# on its behavior (sets new symbols to their default value but not 'n') with the
-# counter-intuitive name.
-oldnoconfig: olddefconfig
- @echo " WARNING: \"oldnoconfig\" target will be removed after Linux 4.19"
- @echo " Please use \"olddefconfig\" instead, which is an alias."
-
-# We do not expect manual invokcation of "silentoldcofig" (or "syncconfig").
-silentoldconfig: syncconfig
- @echo " WARNING: \"silentoldconfig\" has been renamed to \"syncconfig\""
- @echo " and is now an internal implementation detail."
- @echo " What you want is probably \"oldconfig\"."
- @echo " \"silentoldconfig\" will be removed after Linux 4.19"
+PHONY += savedefconfig defconfig
savedefconfig: $(obj)/conf
$< $(silent) --$@=defconfig $(Kconfig)
defconfig: $(obj)/conf
-ifeq ($(KBUILD_DEFCONFIG),)
- $< $(silent) --defconfig $(Kconfig)
-else
ifneq ($(wildcard $(srctree)/arch/$(SRCARCH)/configs/$(KBUILD_DEFCONFIG)),)
@$(kecho) "*** Default configuration is based on '$(KBUILD_DEFCONFIG)'"
$(Q)$< $(silent) --defconfig=arch/$(SRCARCH)/configs/$(KBUILD_DEFCONFIG) $(Kconfig)
@@ -98,7 +85,6 @@
@$(kecho) "*** Default configuration is based on target '$(KBUILD_DEFCONFIG)'"
$(Q)$(MAKE) -f $(srctree)/Makefile $(KBUILD_DEFCONFIG)
endif
-endif
%_defconfig: $(obj)/conf
$(Q)$< $(silent) --defconfig=arch/$(SRCARCH)/configs/$@ $(Kconfig)
@@ -108,7 +94,7 @@
%.config: $(obj)/conf
$(if $(call configfiles),, $(error No configuration exists for this target on this architecture))
$(Q)$(CONFIG_SHELL) $(srctree)/scripts/kconfig/merge_config.sh -m .config $(configfiles)
- +$(Q)yes "" | $(MAKE) -f $(srctree)/Makefile oldconfig
+ $(Q)$(MAKE) -f $(srctree)/Makefile olddefconfig
PHONY += kvmconfig
kvmconfig: kvm_guest.config
@@ -128,7 +114,7 @@
$(PYTHON3) -B -m pytest $(srctree)/$(src)/tests \
-o cache_dir=$(abspath $(obj)/tests/.cache) \
$(if $(findstring 1,$(KBUILD_VERBOSE)),--capture=no)
-clean-dirs += tests/.cache
+clean-files += tests/.cache
# Help text used by make help
help:
@@ -156,75 +142,69 @@
@echo ' testconfig - Run Kconfig unit tests (requires python3 and pytest)'
# ===========================================================================
-# Shared Makefile for the various kconfig executables:
-# conf: Used for defconfig, oldconfig and related targets
# object files used by all kconfig flavours
+common-objs := confdata.o expr.o lexer.lex.o parser.tab.o preprocess.o \
+ symbol.o
-conf-objs := conf.o zconf.tab.o
+$(obj)/lexer.lex.o: $(obj)/parser.tab.h
+HOSTCFLAGS_lexer.lex.o := -I $(srctree)/$(src)
+HOSTCFLAGS_parser.tab.o := -I $(srctree)/$(src)
-hostprogs-y := conf
-
-targets += zconf.lex.c
-
-# generated files seem to need this to find local include files
-HOSTCFLAGS_zconf.lex.o := -I$(src)
-HOSTCFLAGS_zconf.tab.o := -I$(src)
+# conf: Used for defconfig, oldconfig and related targets
+hostprogs-y += conf
+conf-objs := conf.o $(common-objs)
# nconf: Used for the nconfig target based on ncurses
hostprogs-y += nconf
-nconf-objs := nconf.o zconf.tab.o nconf.gui.o
+nconf-objs := nconf.o nconf.gui.o $(common-objs)
-HOSTLDLIBS_nconf = $(shell . $(obj)/.nconf-cfg && echo $$libs)
-HOSTCFLAGS_nconf.o = $(shell . $(obj)/.nconf-cfg && echo $$cflags)
-HOSTCFLAGS_nconf.gui.o = $(shell . $(obj)/.nconf-cfg && echo $$cflags)
+HOSTLDLIBS_nconf = $(shell . $(obj)/nconf-cfg && echo $$libs)
+HOSTCFLAGS_nconf.o = $(shell . $(obj)/nconf-cfg && echo $$cflags)
+HOSTCFLAGS_nconf.gui.o = $(shell . $(obj)/nconf-cfg && echo $$cflags)
-$(obj)/nconf.o $(obj)/nconf.gui.o: $(obj)/.nconf-cfg
+$(obj)/nconf.o $(obj)/nconf.gui.o: $(obj)/nconf-cfg
# mconf: Used for the menuconfig target based on lxdialog
hostprogs-y += mconf
-lxdialog := checklist.o inputbox.o menubox.o textbox.o util.o yesno.o
-mconf-objs := mconf.o zconf.tab.o $(addprefix lxdialog/, $(lxdialog))
+lxdialog := $(addprefix lxdialog/, \
+ checklist.o inputbox.o menubox.o textbox.o util.o yesno.o)
+mconf-objs := mconf.o $(lxdialog) $(common-objs)
-HOSTLDLIBS_mconf = $(shell . $(obj)/.mconf-cfg && echo $$libs)
+HOSTLDLIBS_mconf = $(shell . $(obj)/mconf-cfg && echo $$libs)
$(foreach f, mconf.o $(lxdialog), \
- $(eval HOSTCFLAGS_$f = $$(shell . $(obj)/.mconf-cfg && echo $$$$cflags)))
+ $(eval HOSTCFLAGS_$f = $$(shell . $(obj)/mconf-cfg && echo $$$$cflags)))
-$(obj)/mconf.o: $(obj)/.mconf-cfg
-$(addprefix $(obj)/lxdialog/, $(lxdialog)): $(obj)/.mconf-cfg
+$(addprefix $(obj)/, mconf.o $(lxdialog)): $(obj)/mconf-cfg
# qconf: Used for the xconfig target based on Qt
hostprogs-y += qconf
qconf-cxxobjs := qconf.o
-qconf-objs := zconf.tab.o
+qconf-objs := images.o $(common-objs)
-HOSTLDLIBS_qconf = $(shell . $(obj)/.qconf-cfg && echo $$libs)
-HOSTCXXFLAGS_qconf.o = $(shell . $(obj)/.qconf-cfg && echo $$cflags)
+HOSTLDLIBS_qconf = $(shell . $(obj)/qconf-cfg && echo $$libs)
+HOSTCXXFLAGS_qconf.o = $(shell . $(obj)/qconf-cfg && echo $$cflags)
-$(obj)/qconf.o: $(obj)/.qconf-cfg $(obj)/qconf.moc
+$(obj)/qconf.o: $(obj)/qconf-cfg $(obj)/qconf.moc
quiet_cmd_moc = MOC $@
- cmd_moc = $(shell . $(obj)/.qconf-cfg && echo $$moc) -i $< -o $@
+ cmd_moc = $(shell . $(obj)/qconf-cfg && echo $$moc) -i $< -o $@
-$(obj)/%.moc: $(src)/%.h $(obj)/.qconf-cfg
+$(obj)/%.moc: $(src)/%.h $(obj)/qconf-cfg
$(call cmd,moc)
# gconf: Used for the gconfig target based on GTK+
hostprogs-y += gconf
-gconf-objs := gconf.o zconf.tab.o
+gconf-objs := gconf.o images.o $(common-objs)
-HOSTLDLIBS_gconf = $(shell . $(obj)/.gconf-cfg && echo $$libs)
-HOSTCFLAGS_gconf.o = $(shell . $(obj)/.gconf-cfg && echo $$cflags)
+HOSTLDLIBS_gconf = $(shell . $(obj)/gconf-cfg && echo $$libs)
+HOSTCFLAGS_gconf.o = $(shell . $(obj)/gconf-cfg && echo $$cflags)
-$(obj)/gconf.o: $(obj)/.gconf-cfg
-
-$(obj)/zconf.tab.o: $(obj)/zconf.lex.c
+$(obj)/gconf.o: $(obj)/gconf-cfg
# check if necessary packages are available, and configure build flags
-define filechk_conf_cfg
- $(CONFIG_SHELL) $<
-endef
+filechk_conf_cfg = $(CONFIG_SHELL) $<
-$(obj)/.%conf-cfg: $(src)/%conf-cfg.sh FORCE
+$(obj)/%conf-cfg: $(src)/%conf-cfg.sh FORCE
$(call filechk,conf_cfg)
-clean-files += .*conf-cfg
+clean-files += *conf-cfg
diff --git a/scripts/kconfig/conf.c b/scripts/kconfig/conf.c
index 7b2b372..40e16e8 100644
--- a/scripts/kconfig/conf.c
+++ b/scripts/kconfig/conf.c
@@ -1,6 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
- * Released under the terms of the GNU GPL v2.0.
*/
#include <ctype.h>
@@ -90,7 +90,7 @@
line[0] = '\n';
line[1] = 0;
- if (!sym_is_changable(sym)) {
+ if (!sym_is_changeable(sym)) {
printf("%s\n", def);
line[0] = '\n';
line[1] = 0;
@@ -234,7 +234,7 @@
sym = menu->sym;
is_new = !sym_has_value(sym);
- if (sym_is_changable(sym)) {
+ if (sym_is_changeable(sym)) {
conf_sym(menu);
sym_calc_value(sym);
switch (sym_get_tristate_value(sym)) {
@@ -418,7 +418,7 @@
sym = menu->sym;
if (sym && !sym_has_value(sym)) {
- if (sym_is_changable(sym) ||
+ if (sym_is_changeable(sym) ||
(sym_is_choice(sym) && sym_get_tristate_value(sym) == yes)) {
if (input_mode == listnewconfig) {
if (sym->name) {
@@ -451,7 +451,7 @@
{"oldaskconfig", no_argument, NULL, oldaskconfig},
{"oldconfig", no_argument, NULL, oldconfig},
{"syncconfig", no_argument, NULL, syncconfig},
- {"defconfig", optional_argument, NULL, defconfig},
+ {"defconfig", required_argument, NULL, defconfig},
{"savedefconfig", required_argument, NULL, savedefconfig},
{"allnoconfig", no_argument, NULL, allnoconfig},
{"allyesconfig", no_argument, NULL, allyesconfig},
@@ -460,12 +460,6 @@
{"randconfig", no_argument, NULL, randconfig},
{"listnewconfig", no_argument, NULL, listnewconfig},
{"olddefconfig", no_argument, NULL, olddefconfig},
- /*
- * oldnoconfig is an alias of olddefconfig, because people already
- * are dependent on its behavior(sets new symbols to their default
- * value but not 'n') with the counter-intuitive name.
- */
- {"oldnoconfig", no_argument, NULL, olddefconfig},
{NULL, 0, NULL, 0}
};
@@ -480,7 +474,6 @@
printf(" --syncconfig Similar to oldconfig but generates configuration in\n"
" include/{generated/,config/}\n");
printf(" --olddefconfig Same as oldconfig but sets new symbols to their default value\n");
- printf(" --oldnoconfig An alias of olddefconfig\n");
printf(" --defconfig <file> New config with default defined in <file>\n");
printf(" --savedefconfig <file> Save the minimal current configuration to <file>\n");
printf(" --allnoconfig New config where all options are answered with no\n");
@@ -495,7 +488,6 @@
const char *progname = av[0];
int opt;
const char *name, *defconfig_file = NULL /* gcc uninit */;
- struct stat tmpstat;
int no_conf_write = 0;
tty_stdio = isatty(0) && isatty(1);
@@ -567,23 +559,9 @@
name = av[optind];
conf_parse(name);
//zconfdump(stdout);
- if (sync_kconfig) {
- name = conf_get_configname();
- if (stat(name, &tmpstat)) {
- fprintf(stderr, "***\n"
- "*** Configuration file \"%s\" not found!\n"
- "***\n"
- "*** Please run some configurator (e.g. \"make oldconfig\" or\n"
- "*** \"make menuconfig\" or \"make xconfig\").\n"
- "***\n", name);
- exit(1);
- }
- }
switch (input_mode) {
case defconfig:
- if (!defconfig_file)
- defconfig_file = conf_get_default_confname();
if (conf_read(defconfig_file)) {
fprintf(stderr,
"***\n"
diff --git a/scripts/kconfig/confdata.c b/scripts/kconfig/confdata.c
index 91d0a5c..3569d2d 100644
--- a/scripts/kconfig/confdata.c
+++ b/scripts/kconfig/confdata.c
@@ -1,12 +1,14 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
- * Released under the terms of the GNU GPL v2.0.
*/
+#include <sys/mman.h>
#include <sys/stat.h>
#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
+#include <limits.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
@@ -35,6 +37,52 @@
return S_ISDIR(st.st_mode);
}
+/* return true if the given two files are the same, false otherwise */
+static bool is_same(const char *file1, const char *file2)
+{
+ int fd1, fd2;
+ struct stat st1, st2;
+ void *map1, *map2;
+ bool ret = false;
+
+ fd1 = open(file1, O_RDONLY);
+ if (fd1 < 0)
+ return ret;
+
+ fd2 = open(file2, O_RDONLY);
+ if (fd2 < 0)
+ goto close1;
+
+ ret = fstat(fd1, &st1);
+ if (ret)
+ goto close2;
+ ret = fstat(fd2, &st2);
+ if (ret)
+ goto close2;
+
+ if (st1.st_size != st2.st_size)
+ goto close2;
+
+ map1 = mmap(NULL, st1.st_size, PROT_READ, MAP_PRIVATE, fd1, 0);
+ if (map1 == MAP_FAILED)
+ goto close2;
+
+ map2 = mmap(NULL, st2.st_size, PROT_READ, MAP_PRIVATE, fd2, 0);
+ if (map2 == MAP_FAILED)
+ goto close2;
+
+ if (bcmp(map1, map2, st1.st_size))
+ goto close2;
+
+ ret = true;
+close2:
+ close(fd2);
+close1:
+ close(fd1);
+
+ return ret;
+}
+
/*
* Create the parent directory of the given path.
*
@@ -74,6 +122,47 @@
return 0;
}
+static char depfile_path[PATH_MAX];
+static size_t depfile_prefix_len;
+
+/* touch depfile for symbol 'name' */
+static int conf_touch_dep(const char *name)
+{
+ int fd, ret;
+ const char *s;
+ char *d, c;
+
+ /* check overflow: prefix + name + ".h" + '\0' must fit in buffer. */
+ if (depfile_prefix_len + strlen(name) + 3 > sizeof(depfile_path))
+ return -1;
+
+ d = depfile_path + depfile_prefix_len;
+ s = name;
+
+ while ((c = *s++))
+ *d++ = (c == '_') ? '/' : tolower(c);
+ strcpy(d, ".h");
+
+ /* Assume directory path already exists. */
+ fd = open(depfile_path, O_WRONLY | O_CREAT | O_TRUNC, 0644);
+ if (fd == -1) {
+ if (errno != ENOENT)
+ return -1;
+
+ ret = make_parent_dir(depfile_path);
+ if (ret)
+ return ret;
+
+ /* Try it again. */
+ fd = open(depfile_path, O_WRONLY | O_CREAT | O_TRUNC, 0644);
+ if (fd == -1)
+ return -1;
+ }
+ close(fd);
+
+ return 0;
+}
+
struct conf_printer {
void (*print_symbol)(FILE *, struct symbol *, const char *, void *);
void (*print_comment)(FILE *, const char *, void *);
@@ -88,8 +177,6 @@
static const char *conf_filename;
static int conf_lineno, conf_warnings;
-const char conf_defname[] = "arch/$(ARCH)/defconfig";
-
static void conf_warning(const char *fmt, ...)
{
va_list ap;
@@ -137,28 +224,13 @@
return name ? name : ".config";
}
-const char *conf_get_autoconfig_name(void)
+static const char *conf_get_autoconfig_name(void)
{
char *name = getenv("KCONFIG_AUTOCONFIG");
return name ? name : "include/config/auto.conf";
}
-char *conf_get_default_confname(void)
-{
- static char fullname[PATH_MAX+1];
- char *env, *name;
-
- name = expand_string(conf_defname);
- env = getenv(SRCTREE);
- if (env) {
- sprintf(fullname, "%s/%s", env, name);
- if (is_present(fullname))
- return fullname;
- }
- return name;
-}
-
static int conf_set_sym_val(struct symbol *sym, int def, int def_flags, char *p)
{
char *p2;
@@ -186,14 +258,6 @@
conf_warning("symbol value '%s' invalid for %s",
p, sym->name);
return 1;
- case S_OTHER:
- if (*p != '"') {
- for (p2 = p; *p2 && !isspace(*p2); p2++)
- ;
- sym->type = S_STRING;
- goto done;
- }
- /* fall through */
case S_STRING:
if (*p++ != '"')
break;
@@ -212,7 +276,6 @@
/* fall through */
case S_INT:
case S_HEX:
- done:
if (sym_string_valid(sym, p)) {
sym->def[def].val = xstrdup(p);
sym->flags |= def_flags;
@@ -363,7 +426,7 @@
sym = sym_find(line + 2 + strlen(CONFIG_));
if (!sym) {
sym_add_change_count(1);
- goto setsym;
+ continue;
}
} else {
sym = sym_lookup(line + 2 + strlen(CONFIG_), 0);
@@ -393,17 +456,22 @@
if (*p2 == '\r')
*p2 = 0;
}
- if (def == S_DEF_USER) {
- sym = sym_find(line + strlen(CONFIG_));
- if (!sym) {
+
+ sym = sym_find(line + strlen(CONFIG_));
+ if (!sym) {
+ if (def == S_DEF_AUTO)
+ /*
+ * Reading from include/config/auto.conf
+ * If CONFIG_FOO previously existed in
+ * auto.conf but it is missing now,
+ * include/config/foo.h must be touched.
+ */
+ conf_touch_dep(line + strlen(CONFIG_));
+ else
sym_add_change_count(1);
- goto setsym;
- }
- } else {
- sym = sym_lookup(line + strlen(CONFIG_), 0);
- if (sym->type == S_UNKNOWN)
- sym->type = S_OTHER;
+ continue;
}
+
if (sym->flags & def_flags) {
conf_warning("override: reassigning to symbol %s", sym->name);
}
@@ -416,7 +484,7 @@
continue;
}
-setsym:
+
if (sym && sym_is_choice_value(sym)) {
struct symbol *cs = prop_get_symbol(sym_get_choice_prop(sym));
switch (sym->def[def].tri) {
@@ -466,11 +534,9 @@
switch (sym->type) {
case S_BOOLEAN:
case S_TRISTATE:
- if (sym->def[S_DEF_USER].tri != sym_get_tristate_value(sym))
- break;
- if (!sym_is_choice(sym))
+ if (sym->def[S_DEF_USER].tri == sym_get_tristate_value(sym))
continue;
- /* fall through */
+ break;
default:
if (!strcmp(sym->curr.val, sym->def[S_DEF_USER].val))
continue;
@@ -669,7 +735,6 @@
const char *str;
switch (sym->type) {
- case S_OTHER:
case S_UNKNOWN:
break;
case S_STRING:
@@ -729,7 +794,7 @@
goto next_menu;
sym->flags &= ~SYMBOL_WRITE;
/* If we cannot change the symbol - skip */
- if (!sym_is_changable(sym))
+ if (!sym_is_changeable(sym))
goto next_menu;
/* If symbol equals to default value - skip */
if (strcmp(sym_get_string_value(sym), sym_get_string_default(sym)) == 0)
@@ -780,40 +845,36 @@
FILE *out;
struct symbol *sym;
struct menu *menu;
- const char *basename;
const char *str;
- char dirname[PATH_MAX+1], tmpname[PATH_MAX+22], newname[PATH_MAX+8];
+ char tmpname[PATH_MAX + 1], oldname[PATH_MAX + 1];
char *env;
+ int i;
+ bool need_newline = false;
- dirname[0] = 0;
- if (name && name[0]) {
- char *slash;
+ if (!name)
+ name = conf_get_configname();
- if (is_dir(name)) {
- strcpy(dirname, name);
- strcat(dirname, "/");
- basename = conf_get_configname();
- } else if ((slash = strrchr(name, '/'))) {
- int size = slash - name + 1;
- memcpy(dirname, name, size);
- dirname[size] = 0;
- if (slash[1])
- basename = slash + 1;
- else
- basename = conf_get_configname();
- } else
- basename = name;
- } else
- basename = conf_get_configname();
+ if (!*name) {
+ fprintf(stderr, "config name is empty\n");
+ return -1;
+ }
- sprintf(newname, "%s%s", dirname, basename);
+ if (is_dir(name)) {
+ fprintf(stderr, "%s: Is a directory\n", name);
+ return -1;
+ }
+
+ if (make_parent_dir(name))
+ return -1;
+
env = getenv("KCONFIG_OVERWRITECONFIG");
- if (!env || !*env) {
- sprintf(tmpname, "%s.tmpconfig.%d", dirname, (int)getpid());
- out = fopen(tmpname, "w");
- } else {
+ if (env && *env) {
*tmpname = 0;
- out = fopen(newname, "w");
+ out = fopen(name, "w");
+ } else {
+ snprintf(tmpname, sizeof(tmpname), "%s.%d.tmp",
+ name, (int)getpid());
+ out = fopen(tmpname, "w");
}
if (!out)
return 1;
@@ -834,12 +895,17 @@
"#\n"
"# %s\n"
"#\n", str);
- } else if (!(sym->flags & SYMBOL_CHOICE)) {
+ need_newline = false;
+ } else if (!(sym->flags & SYMBOL_CHOICE) &&
+ !(sym->flags & SYMBOL_WRITTEN)) {
sym_calc_value(sym);
if (!(sym->flags & SYMBOL_WRITE))
goto next;
- sym->flags &= ~SYMBOL_WRITE;
-
+ if (need_newline) {
+ fprintf(out, "\n");
+ need_newline = false;
+ }
+ sym->flags |= SYMBOL_WRITTEN;
conf_write_symbol(out, sym, &kconfig_printer_cb, NULL);
}
@@ -851,6 +917,12 @@
if (menu->next)
menu = menu->next;
else while ((menu = menu->parent)) {
+ if (!menu->sym && menu_is_visible(menu) &&
+ menu != &rootmenu) {
+ str = menu_get_prompt(menu);
+ fprintf(out, "# end of %s\n", str);
+ need_newline = true;
+ }
if (menu->next) {
menu = menu->next;
break;
@@ -859,15 +931,24 @@
}
fclose(out);
+ for_all_symbols(i, sym)
+ sym->flags &= ~SYMBOL_WRITTEN;
+
if (*tmpname) {
- strcat(dirname, basename);
- strcat(dirname, ".old");
- rename(newname, dirname);
- if (rename(tmpname, newname))
+ if (is_same(name, tmpname)) {
+ conf_message("No change to %s", name);
+ unlink(tmpname);
+ sym_set_change_count(0);
+ return 0;
+ }
+
+ snprintf(oldname, sizeof(oldname), "%s.old", name);
+ rename(name, oldname);
+ if (rename(tmpname, name))
return 1;
}
- conf_message("configuration written to %s", newname);
+ conf_message("configuration written to %s", name);
sym_set_change_count(0);
@@ -880,8 +961,6 @@
struct file *file;
FILE *out;
- if (!name)
- name = ".kconfig.d";
out = fopen("..config.tmp", "w");
if (!out)
return 1;
@@ -906,24 +985,19 @@
return 0;
}
-static int conf_split_config(void)
+static int conf_touch_deps(void)
{
const char *name;
- char path[PATH_MAX+1];
- char *s, *d, c;
struct symbol *sym;
- int res, i, fd;
+ int res, i;
+
+ strcpy(depfile_path, "include/config/");
+ depfile_prefix_len = strlen(depfile_path);
name = conf_get_autoconfig_name();
conf_read_simple(name, S_DEF_AUTO);
sym_calc_value(modules_sym);
- if (make_parent_dir("include/config/foo.h"))
- return 1;
- if (chdir("include/config"))
- return 1;
-
- res = 0;
for_all_symbols(i, sym) {
sym_calc_value(sym);
if ((sym->flags & SYMBOL_NO_WRITE) || !sym->name)
@@ -975,42 +1049,12 @@
* different from 'no').
*/
- /* Replace all '_' and append ".h" */
- s = sym->name;
- d = path;
- while ((c = *s++)) {
- c = tolower(c);
- *d++ = (c == '_') ? '/' : c;
- }
- strcpy(d, ".h");
-
- /* Assume directory path already exists. */
- fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0644);
- if (fd == -1) {
- if (errno != ENOENT) {
- res = 1;
- break;
- }
-
- if (make_parent_dir(path)) {
- res = 1;
- goto out;
- }
-
- /* Try it again. */
- fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0644);
- if (fd == -1) {
- res = 1;
- break;
- }
- }
- close(fd);
+ res = conf_touch_dep(sym->name);
+ if (res)
+ return res;
}
-out:
- if (chdir("../.."))
- return 1;
- return res;
+ return 0;
}
int conf_write_autoconf(int overwrite)
@@ -1024,11 +1068,9 @@
if (!overwrite && is_present(autoconf_name))
return 0;
- sym_clear_all_valid();
-
conf_write_dep("include/config/auto.conf.cmd");
- if (conf_split_config())
+ if (conf_touch_deps())
return 1;
out = fopen(".tmpconfig", "w");
diff --git a/scripts/kconfig/expr.c b/scripts/kconfig/expr.c
index e1a39e9..77ffff3 100644
--- a/scripts/kconfig/expr.c
+++ b/scripts/kconfig/expr.c
@@ -1,8 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
- * Released under the terms of the GNU GPL v2.0.
*/
+#include <ctype.h>
+#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -980,7 +982,6 @@
k_string,
k_signed,
k_unsigned,
- k_invalid
};
union string_value {
@@ -1011,13 +1012,10 @@
val->u = strtoull(str, &tail, 16);
kind = k_unsigned;
break;
- case S_STRING:
- case S_UNKNOWN:
+ default:
val->s = strtoll(str, &tail, 0);
kind = k_signed;
break;
- default:
- return k_invalid;
}
return !errno && !*tail && tail > str && isxdigit(tail[-1])
? kind : k_string;
@@ -1073,13 +1071,7 @@
if (k1 == k_string || k2 == k_string)
res = strcmp(str1, str2);
- else if (k1 == k_invalid || k2 == k_invalid) {
- if (e->type != E_EQUAL && e->type != E_UNEQUAL) {
- printf("Cannot compare \"%s\" and \"%s\"\n", str1, str2);
- return no;
- }
- res = strcmp(str1, str2);
- } else if (k1 == k_unsigned || k2 == k_unsigned)
+ else if (k1 == k_unsigned || k2 == k_unsigned)
res = (lval.u > rval.u) - (lval.u < rval.u);
else /* if (k1 == k_signed && k2 == k_signed) */
res = (lval.s > rval.s) - (lval.s < rval.s);
diff --git a/scripts/kconfig/expr.h b/scripts/kconfig/expr.h
index 7c329e1..017843c 100644
--- a/scripts/kconfig/expr.h
+++ b/scripts/kconfig/expr.h
@@ -1,6 +1,6 @@
+/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
- * Released under the terms of the GNU GPL v2.0.
*/
#ifndef EXPR_H
@@ -62,7 +62,7 @@
};
enum symbol_type {
- S_UNKNOWN, S_BOOLEAN, S_TRISTATE, S_INT, S_HEX, S_STRING, S_OTHER
+ S_UNKNOWN, S_BOOLEAN, S_TRISTATE, S_INT, S_HEX, S_STRING
};
/* enum values are used as index to symbol.def[] */
@@ -131,7 +131,7 @@
struct expr_value implied;
};
-#define for_all_symbols(i, sym) for (i = 0; i < SYMBOL_HASHSIZE; i++) for (sym = symbol_hash[i]; sym; sym = sym->next) if (sym->type != S_OTHER)
+#define for_all_symbols(i, sym) for (i = 0; i < SYMBOL_HASHSIZE; i++) for (sym = symbol_hash[i]; sym; sym = sym->next)
#define SYMBOL_CONST 0x0001 /* symbol is const */
#define SYMBOL_CHECK 0x0008 /* used during dependency checking */
@@ -141,6 +141,7 @@
#define SYMBOL_OPTIONAL 0x0100 /* choice is optional - values can be 'n' */
#define SYMBOL_WRITE 0x0200 /* write symbol to file (KCONFIG_CONFIG) */
#define SYMBOL_CHANGED 0x0400 /* ? */
+#define SYMBOL_WRITTEN 0x0800 /* track info to avoid double-write to .config */
#define SYMBOL_NO_WRITE 0x1000 /* Symbol for internal use only; it will not be written */
#define SYMBOL_CHECKED 0x2000 /* used during dependency checking */
#define SYMBOL_WARNED 0x8000 /* warning has been issued */
@@ -172,7 +173,7 @@
* int "BAZ Value"
* range 1..255
*
- * Please, also check zconf.y:print_symbol() when modifying the
+ * Please, also check parser.y:print_symbol() when modifying the
* list of property types!
*/
enum prop_type {
diff --git a/scripts/kconfig/gconf.c b/scripts/kconfig/gconf.c
index 36f5784..e36b342 100644
--- a/scripts/kconfig/gconf.c
+++ b/scripts/kconfig/gconf.c
@@ -1,9 +1,6 @@
-/* Hey EMACS -*- linux-c -*- */
+// SPDX-License-Identifier: GPL-2.0
/*
- *
* Copyright (C) 2002-2003 Romain Lievin <roms@tilp.info>
- * Released under the terms of the GNU GPL v2.0.
- *
*/
#ifdef HAVE_CONFIG_H
@@ -12,7 +9,7 @@
#include <stdlib.h>
#include "lkc.h"
-#include "images.c"
+#include "images.h"
#include <glade/glade.h>
#include <gtk/gtk.h>
@@ -78,8 +75,8 @@
static void conf_changed(void);
/* Helping/Debugging Functions */
-
-const char *dbg_sym_flags(int val)
+#ifdef DEBUG
+static const char *dbg_sym_flags(int val)
{
static char buf[256];
@@ -108,9 +105,10 @@
return buf;
}
+#endif
-void replace_button_icon(GladeXML * xml, GdkDrawable * window,
- GtkStyle * style, gchar * btn_name, gchar ** xpm)
+static void replace_button_icon(GladeXML *xml, GdkDrawable *window,
+ GtkStyle *style, gchar *btn_name, gchar **xpm)
{
GdkPixmap *pixmap;
GdkBitmap *mask;
@@ -128,7 +126,7 @@
}
/* Main Window Initialization */
-void init_main_window(const gchar * glade_file)
+static void init_main_window(const gchar *glade_file)
{
GladeXML *xml;
GtkWidget *widget;
@@ -190,7 +188,7 @@
gtk_widget_show(main_wnd);
}
-void init_tree_model(void)
+static void init_tree_model(void)
{
gint i;
@@ -220,7 +218,7 @@
model1 = GTK_TREE_MODEL(tree1);
}
-void init_left_tree(void)
+static void init_left_tree(void)
{
GtkTreeView *view = GTK_TREE_VIEW(tree1_w);
GtkCellRenderer *renderer;
@@ -262,7 +260,7 @@
const gchar * path_string,
const gchar * new_text, gpointer user_data);
-void init_right_tree(void)
+static void init_right_tree(void)
{
GtkTreeView *view = GTK_TREE_VIEW(tree2_w);
GtkCellRenderer *renderer;
@@ -640,7 +638,7 @@
void on_introduction1_activate(GtkMenuItem * menuitem, gpointer user_data)
{
GtkWidget *dialog;
- const gchar *intro_text =
+ const gchar *intro_text =
"Welcome to gkc, the GTK+ graphical configuration tool\n"
"For each option, a blank box indicates the feature is disabled, a\n"
"check indicates it is enabled, and a dot indicates that it is to\n"
@@ -1212,8 +1210,8 @@
/*
* Find a menu in the GtkTree starting at parent.
*/
-GtkTreeIter *gtktree_iter_find_node(GtkTreeIter * parent,
- struct menu *tofind)
+static GtkTreeIter *gtktree_iter_find_node(GtkTreeIter *parent,
+ struct menu *tofind)
{
GtkTreeIter iter;
GtkTreeIter *child = &iter;
@@ -1424,7 +1422,7 @@
tree = tree2;
}
-void fixup_rootmenu(struct menu *menu)
+static void fixup_rootmenu(struct menu *menu)
{
struct menu *child;
static int menu_cnt = 0;
diff --git a/scripts/kconfig/images.c b/scripts/kconfig/images.c
index d4f84bd..b4fa0e4 100644
--- a/scripts/kconfig/images.c
+++ b/scripts/kconfig/images.c
@@ -1,9 +1,11 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
- * Released under the terms of the GNU GPL v2.0.
*/
-static const char *xpm_load[] = {
+#include "images.h"
+
+const char *xpm_load[] = {
"22 22 5 1",
". c None",
"# c #000000",
@@ -33,7 +35,7 @@
"###############.......",
"......................"};
-static const char *xpm_save[] = {
+const char *xpm_save[] = {
"22 22 5 1",
". c None",
"# c #000000",
@@ -63,7 +65,7 @@
"..##################..",
"......................"};
-static const char *xpm_back[] = {
+const char *xpm_back[] = {
"22 22 3 1",
". c None",
"# c #000083",
@@ -91,7 +93,7 @@
"......................",
"......................"};
-static const char *xpm_tree_view[] = {
+const char *xpm_tree_view[] = {
"22 22 2 1",
". c None",
"# c #000000",
@@ -118,7 +120,7 @@
"......................",
"......................"};
-static const char *xpm_single_view[] = {
+const char *xpm_single_view[] = {
"22 22 2 1",
". c None",
"# c #000000",
@@ -145,7 +147,7 @@
"......................",
"......................"};
-static const char *xpm_split_view[] = {
+const char *xpm_split_view[] = {
"22 22 2 1",
". c None",
"# c #000000",
@@ -172,7 +174,7 @@
"......................",
"......................"};
-static const char *xpm_symbol_no[] = {
+const char *xpm_symbol_no[] = {
"12 12 2 1",
" c white",
". c black",
@@ -189,7 +191,7 @@
" .......... ",
" "};
-static const char *xpm_symbol_mod[] = {
+const char *xpm_symbol_mod[] = {
"12 12 2 1",
" c white",
". c black",
@@ -206,7 +208,7 @@
" .......... ",
" "};
-static const char *xpm_symbol_yes[] = {
+const char *xpm_symbol_yes[] = {
"12 12 2 1",
" c white",
". c black",
@@ -223,7 +225,7 @@
" .......... ",
" "};
-static const char *xpm_choice_no[] = {
+const char *xpm_choice_no[] = {
"12 12 2 1",
" c white",
". c black",
@@ -240,7 +242,7 @@
" .... ",
" "};
-static const char *xpm_choice_yes[] = {
+const char *xpm_choice_yes[] = {
"12 12 2 1",
" c white",
". c black",
@@ -257,7 +259,7 @@
" .... ",
" "};
-static const char *xpm_menu[] = {
+const char *xpm_menu[] = {
"12 12 2 1",
" c white",
". c black",
@@ -274,7 +276,7 @@
" .......... ",
" "};
-static const char *xpm_menu_inv[] = {
+const char *xpm_menu_inv[] = {
"12 12 2 1",
" c white",
". c black",
@@ -291,7 +293,7 @@
" .......... ",
" "};
-static const char *xpm_menuback[] = {
+const char *xpm_menuback[] = {
"12 12 2 1",
" c white",
". c black",
@@ -308,7 +310,7 @@
" .......... ",
" "};
-static const char *xpm_void[] = {
+const char *xpm_void[] = {
"12 12 2 1",
" c white",
". c black",
diff --git a/scripts/kconfig/images.h b/scripts/kconfig/images.h
new file mode 100644
index 0000000..d8ff614
--- /dev/null
+++ b/scripts/kconfig/images.h
@@ -0,0 +1,33 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
+ */
+
+#ifndef IMAGES_H
+#define IMAGES_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern const char *xpm_load[];
+extern const char *xpm_save[];
+extern const char *xpm_back[];
+extern const char *xpm_tree_view[];
+extern const char *xpm_single_view[];
+extern const char *xpm_split_view[];
+extern const char *xpm_symbol_no[];
+extern const char *xpm_symbol_mod[];
+extern const char *xpm_symbol_yes[];
+extern const char *xpm_choice_no[];
+extern const char *xpm_choice_yes[];
+extern const char *xpm_menu[];
+extern const char *xpm_menu_inv[];
+extern const char *xpm_menuback[];
+extern const char *xpm_void[];
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* IMAGES_H */
diff --git a/scripts/kconfig/kconf_id.c b/scripts/kconfig/kconf_id.c
deleted file mode 100644
index b3e0ea0..0000000
--- a/scripts/kconfig/kconf_id.c
+++ /dev/null
@@ -1,52 +0,0 @@
-
-static struct kconf_id kconf_id_array[] = {
- { "mainmenu", T_MAINMENU, TF_COMMAND },
- { "menu", T_MENU, TF_COMMAND },
- { "endmenu", T_ENDMENU, TF_COMMAND },
- { "source", T_SOURCE, TF_COMMAND },
- { "choice", T_CHOICE, TF_COMMAND },
- { "endchoice", T_ENDCHOICE, TF_COMMAND },
- { "comment", T_COMMENT, TF_COMMAND },
- { "config", T_CONFIG, TF_COMMAND },
- { "menuconfig", T_MENUCONFIG, TF_COMMAND },
- { "help", T_HELP, TF_COMMAND },
- { "---help---", T_HELP, TF_COMMAND },
- { "if", T_IF, TF_COMMAND|TF_PARAM },
- { "endif", T_ENDIF, TF_COMMAND },
- { "depends", T_DEPENDS, TF_COMMAND },
- { "optional", T_OPTIONAL, TF_COMMAND },
- { "default", T_DEFAULT, TF_COMMAND, S_UNKNOWN },
- { "prompt", T_PROMPT, TF_COMMAND },
- { "tristate", T_TYPE, TF_COMMAND, S_TRISTATE },
- { "def_tristate", T_DEFAULT, TF_COMMAND, S_TRISTATE },
- { "bool", T_TYPE, TF_COMMAND, S_BOOLEAN },
- { "def_bool", T_DEFAULT, TF_COMMAND, S_BOOLEAN },
- { "int", T_TYPE, TF_COMMAND, S_INT },
- { "hex", T_TYPE, TF_COMMAND, S_HEX },
- { "string", T_TYPE, TF_COMMAND, S_STRING },
- { "select", T_SELECT, TF_COMMAND },
- { "imply", T_IMPLY, TF_COMMAND },
- { "range", T_RANGE, TF_COMMAND },
- { "visible", T_VISIBLE, TF_COMMAND },
- { "option", T_OPTION, TF_COMMAND },
- { "on", T_ON, TF_PARAM },
- { "modules", T_OPT_MODULES, TF_OPTION },
- { "defconfig_list", T_OPT_DEFCONFIG_LIST, TF_OPTION },
- { "allnoconfig_y", T_OPT_ALLNOCONFIG_Y, TF_OPTION },
-};
-
-#define KCONF_ID_ARRAY_SIZE (sizeof(kconf_id_array)/sizeof(struct kconf_id))
-
-static const struct kconf_id *kconf_id_lookup(register const char *str, register unsigned int len)
-{
- int i;
-
- for (i = 0; i < KCONF_ID_ARRAY_SIZE; i++) {
- struct kconf_id *id = kconf_id_array+i;
- int l = strlen(id->name);
-
- if (len == l && !memcmp(str, id->name, len))
- return id;
- }
- return NULL;
-}
diff --git a/scripts/kconfig/zconf.l b/scripts/kconfig/lexer.l
similarity index 67%
rename from scripts/kconfig/zconf.l
rename to scripts/kconfig/lexer.l
index 25bd2b8..6354c90 100644
--- a/scripts/kconfig/zconf.l
+++ b/scripts/kconfig/lexer.l
@@ -1,11 +1,11 @@
-%option nostdinit noyywrap never-interactive full ecs
-%option 8bit nodefault yylineno
-%x COMMAND HELP STRING PARAM ASSIGN_VAL
-%{
+/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
- * Released under the terms of the GNU GPL v2.0.
*/
+%option nostdinit noyywrap never-interactive full ecs
+%option 8bit nodefault yylineno
+%x ASSIGN_VAL HELP STRING
+%{
#include <assert.h>
#include <limits.h>
@@ -15,6 +15,9 @@
#include <unistd.h>
#include "lkc.h"
+#include "parser.tab.h"
+
+#define YY_DECL static int yylex1(void)
#define START_STRSIZE 16
@@ -23,6 +26,8 @@
int lineno;
} current_pos;
+static int prev_prev_token = T_EOL;
+static int prev_token = T_EOL;
static char *text;
static int text_size, text_asize;
@@ -73,7 +78,7 @@
{
fprintf(stderr,
"%s:%d:warning: ignoring unsupported character '%c'\n",
- zconf_curname(), zconf_lineno(), chr);
+ current_file->name, yylineno, chr);
}
%}
@@ -83,54 +88,73 @@
int str = 0;
int ts, i;
-[ \t]*#.*\n |
-[ \t]*\n {
- return T_EOL;
-}
-[ \t]*#.*
-
-
-[ \t]+ {
- BEGIN(COMMAND);
-}
-
-. {
- unput(yytext[0]);
- BEGIN(COMMAND);
-}
-
-
-<COMMAND>{
- {n}+ {
- const struct kconf_id *id = kconf_id_lookup(yytext, yyleng);
- current_pos.file = current_file;
- current_pos.lineno = yylineno;
- if (id && id->flags & TF_COMMAND) {
- BEGIN(PARAM);
- yylval.id = id;
- return id->token;
- }
- alloc_string(yytext, yyleng);
- yylval.string = text;
- return T_VARIABLE;
- }
- ({n}|$)+ {
- /* this token includes at least one '$' */
- yylval.string = expand_token(yytext, yyleng);
- if (strlen(yylval.string))
- return T_VARIABLE;
- free(yylval.string);
- }
- "=" { BEGIN(ASSIGN_VAL); yylval.flavor = VAR_RECURSIVE; return T_ASSIGN; }
- ":=" { BEGIN(ASSIGN_VAL); yylval.flavor = VAR_SIMPLE; return T_ASSIGN; }
- "+=" { BEGIN(ASSIGN_VAL); yylval.flavor = VAR_APPEND; return T_ASSIGN; }
- [[:blank:]]+
- . warn_ignored_character(*yytext);
- \n {
- BEGIN(INITIAL);
- return T_EOL;
- }
-}
+#.* /* ignore comment */
+[ \t]* /* whitespaces */
+\\\n /* escaped new line */
+\n return T_EOL;
+"allnoconfig_y" return T_ALLNOCONFIG_Y;
+"bool" return T_BOOL;
+"choice" return T_CHOICE;
+"comment" return T_COMMENT;
+"config" return T_CONFIG;
+"def_bool" return T_DEF_BOOL;
+"def_tristate" return T_DEF_TRISTATE;
+"default" return T_DEFAULT;
+"defconfig_list" return T_DEFCONFIG_LIST;
+"depends" return T_DEPENDS;
+"endchoice" return T_ENDCHOICE;
+"endif" return T_ENDIF;
+"endmenu" return T_ENDMENU;
+"help"|"---help---" return T_HELP;
+"hex" return T_HEX;
+"if" return T_IF;
+"imply" return T_IMPLY;
+"int" return T_INT;
+"mainmenu" return T_MAINMENU;
+"menu" return T_MENU;
+"menuconfig" return T_MENUCONFIG;
+"modules" return T_MODULES;
+"on" return T_ON;
+"option" return T_OPTION;
+"optional" return T_OPTIONAL;
+"prompt" return T_PROMPT;
+"range" return T_RANGE;
+"select" return T_SELECT;
+"source" return T_SOURCE;
+"string" return T_STRING;
+"tristate" return T_TRISTATE;
+"visible" return T_VISIBLE;
+"||" return T_OR;
+"&&" return T_AND;
+"=" return T_EQUAL;
+"!=" return T_UNEQUAL;
+"<" return T_LESS;
+"<=" return T_LESS_EQUAL;
+">" return T_GREATER;
+">=" return T_GREATER_EQUAL;
+"!" return T_NOT;
+"(" return T_OPEN_PAREN;
+")" return T_CLOSE_PAREN;
+":=" return T_COLON_EQUAL;
+"+=" return T_PLUS_EQUAL;
+\"|\' {
+ str = yytext[0];
+ new_string();
+ BEGIN(STRING);
+ }
+{n}+ {
+ alloc_string(yytext, yyleng);
+ yylval.string = text;
+ return T_WORD;
+ }
+({n}|$)+ {
+ /* this token includes at least one '$' */
+ yylval.string = expand_token(yytext, yyleng);
+ if (strlen(yylval.string))
+ return T_WORD;
+ free(yylval.string);
+ }
+. warn_ignored_character(*yytext);
<ASSIGN_VAL>{
[^[:blank:]\n]+.* {
@@ -142,71 +166,17 @@
.
}
-<PARAM>{
- "&&" return T_AND;
- "||" return T_OR;
- "(" return T_OPEN_PAREN;
- ")" return T_CLOSE_PAREN;
- "!" return T_NOT;
- "=" return T_EQUAL;
- "!=" return T_UNEQUAL;
- "<=" return T_LESS_EQUAL;
- ">=" return T_GREATER_EQUAL;
- "<" return T_LESS;
- ">" return T_GREATER;
- \"|\' {
- str = yytext[0];
- new_string();
- BEGIN(STRING);
- }
- \n BEGIN(INITIAL); return T_EOL;
- ({n}|[/.])+ {
- const struct kconf_id *id = kconf_id_lookup(yytext, yyleng);
- if (id && id->flags & TF_PARAM) {
- yylval.id = id;
- return id->token;
- }
- alloc_string(yytext, yyleng);
- yylval.string = text;
- return T_WORD;
- }
- ({n}|[/.$])+ {
- /* this token includes at least one '$' */
- yylval.string = expand_token(yytext, yyleng);
- if (strlen(yylval.string))
- return T_WORD;
- free(yylval.string);
- }
- #.* /* comment */
- \\\n ;
- [[:blank:]]+
- . warn_ignored_character(*yytext);
- <<EOF>> {
- BEGIN(INITIAL);
- }
-}
-
<STRING>{
"$".* append_expanded_string(yytext);
- [^$'"\\\n]+/\n {
- append_string(yytext, yyleng);
- yylval.string = text;
- return T_WORD_QUOTE;
- }
[^$'"\\\n]+ {
append_string(yytext, yyleng);
}
- \\.?/\n {
- append_string(yytext + 1, yyleng - 1);
- yylval.string = text;
- return T_WORD_QUOTE;
- }
\\.? {
append_string(yytext + 1, yyleng - 1);
}
\'|\" {
if (str == yytext[0]) {
- BEGIN(PARAM);
+ BEGIN(INITIAL);
yylval.string = text;
return T_WORD_QUOTE;
} else
@@ -216,11 +186,15 @@
fprintf(stderr,
"%s:%d:warning: multi-line strings not supported\n",
zconf_curname(), zconf_lineno());
+ unput('\n');
BEGIN(INITIAL);
- return T_EOL;
+ yylval.string = text;
+ return T_WORD_QUOTE;
}
<<EOF>> {
BEGIN(INITIAL);
+ yylval.string = text;
+ return T_WORD_QUOTE;
}
}
@@ -271,6 +245,12 @@
}
<<EOF>> {
+ BEGIN(INITIAL);
+
+ if (prev_token != T_EOL && prev_token != T_HELPTEXT)
+ fprintf(stderr, "%s:%d:warning: no new line at end of file\n",
+ current_file->name, yylineno);
+
if (current_file) {
zconf_endfile();
return T_EOL;
@@ -280,6 +260,41 @@
}
%%
+
+/* second stage lexer */
+int yylex(void)
+{
+ int token;
+
+repeat:
+ token = yylex1();
+
+ if (prev_token == T_EOL || prev_token == T_HELPTEXT) {
+ if (token == T_EOL) {
+ /* Do not pass unneeded T_EOL to the parser. */
+ goto repeat;
+ } else {
+ /*
+ * For the parser, update file/lineno at the first token
+ * of each statement. Generally, \n is a statement
+ * terminator in Kconfig, but it is not always true
+ * because \n could be escaped by a backslash.
+ */
+ current_pos.file = current_file;
+ current_pos.lineno = yylineno;
+ }
+ }
+
+ if (prev_prev_token == T_EOL && prev_token == T_WORD &&
+ (token == T_EQUAL || token == T_COLON_EQUAL || token == T_PLUS_EQUAL))
+ BEGIN(ASSIGN_VAL);
+
+ prev_prev_token = prev_token;
+ prev_token = token;
+
+ return token;
+}
+
static char *expand_token(const char *in, size_t n)
{
char *out;
@@ -363,7 +378,8 @@
if (!f && name != NULL && name[0] != '/') {
env = getenv(SRCTREE);
if (env) {
- sprintf(fullname, "%s/%s", env, name);
+ snprintf(fullname, sizeof(fullname),
+ "%s/%s", env, name);
f = fopen(fullname, "r");
}
}
diff --git a/scripts/kconfig/lkc.h b/scripts/kconfig/lkc.h
index 9eb7c83..4fb16f3 100644
--- a/scripts/kconfig/lkc.h
+++ b/scripts/kconfig/lkc.h
@@ -1,6 +1,6 @@
+/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
- * Released under the terms of the GNU GPL v2.0.
*/
#ifndef LKC_H
@@ -30,10 +30,6 @@
#undef CONFIG_
#define CONFIG_ CONFIG_prefix()
-#define TF_COMMAND 0x0001
-#define TF_PARAM 0x0002
-#define TF_OPTION 0x0004
-
enum conf_def_mode {
def_default,
def_yes,
@@ -42,17 +38,6 @@
def_random
};
-#define T_OPT_MODULES 1
-#define T_OPT_DEFCONFIG_LIST 2
-#define T_OPT_ALLNOCONFIG_Y 4
-
-struct kconf_id {
- const char *name;
- int token;
- unsigned int flags;
- enum symbol_type stype;
-};
-
extern int yylineno;
void zconfdump(FILE *out);
void zconf_starthelp(void);
@@ -64,8 +49,6 @@
/* confdata.c */
const char *conf_get_configname(void);
-const char *conf_get_autoconfig_name(void);
-char *conf_get_default_confname(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);
@@ -91,7 +74,9 @@
struct property *menu_add_prompt(enum prop_type type, char *prompt, struct expr *dep);
void menu_add_expr(enum prop_type type, struct expr *expr, struct expr *dep);
void menu_add_symbol(enum prop_type type, struct symbol *sym, struct expr *dep);
-void menu_add_option(int token, char *arg);
+void menu_add_option_modules(void);
+void menu_add_option_defconfig_list(void);
+void menu_add_option_allnoconfig_y(void);
void menu_finalize(struct menu *parent);
void menu_set_type(int type);
@@ -103,6 +88,9 @@
char *xstrdup(const char *s);
char *xstrndup(const char *s, size_t n);
+/* lexer.l */
+int yylex(void);
+
struct gstr {
size_t len;
char *s;
@@ -121,6 +109,7 @@
/* symbol.c */
void sym_clear_all_valid(void);
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);
diff --git a/scripts/kconfig/lkc_proto.h b/scripts/kconfig/lkc_proto.h
index 86c2675..f9ab982 100644
--- a/scripts/kconfig/lkc_proto.h
+++ b/scripts/kconfig/lkc_proto.h
@@ -42,7 +42,7 @@
bool sym_string_valid(struct symbol *sym, const char *newval);
bool sym_string_within_range(struct symbol *sym, const char *str);
bool sym_set_string_value(struct symbol *sym, const char *newval);
-bool sym_is_changable(struct symbol *sym);
+bool sym_is_changeable(struct symbol *sym);
struct property * sym_get_choice_prop(struct symbol *sym);
const char * sym_get_string_value(struct symbol *sym);
@@ -58,7 +58,6 @@
void variable_add(const char *name, const char *value,
enum variable_flavor flavor);
void variable_all_del(void);
-char *expand_string(const char *in);
char *expand_dollar(const char **str);
char *expand_one_token(const char **str);
diff --git a/scripts/kconfig/lxdialog/.gitignore b/scripts/kconfig/lxdialog/.gitignore
deleted file mode 100644
index 90b08ff..0000000
--- a/scripts/kconfig/lxdialog/.gitignore
+++ /dev/null
@@ -1,4 +0,0 @@
-#
-# Generated files
-#
-lxdialog
diff --git a/scripts/kconfig/lxdialog/BIG.FAT.WARNING b/scripts/kconfig/lxdialog/BIG.FAT.WARNING
index a8999d8..7cb5a7e 100644
--- a/scripts/kconfig/lxdialog/BIG.FAT.WARNING
+++ b/scripts/kconfig/lxdialog/BIG.FAT.WARNING
@@ -1,4 +1,4 @@
This is NOT the official version of dialog. This version has been
significantly modified from the original. It is for use by the Linux
-kernel configuration script. Please do not bother Savio Lam with
+kernel configuration script. Please do not bother Savio Lam with
questions about this program.
diff --git a/scripts/kconfig/lxdialog/checklist.c b/scripts/kconfig/lxdialog/checklist.c
index 2e96323..fd161cf 100644
--- a/scripts/kconfig/lxdialog/checklist.c
+++ b/scripts/kconfig/lxdialog/checklist.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* checklist.c -- implements the checklist box
*
@@ -5,20 +6,6 @@
* Stuart Herbert - S.Herbert@sheffield.ac.uk: radiolist extension
* Alessandro Rubini - rubini@ipvvis.unipv.it: merged the two
* MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com)
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "dialog.h"
diff --git a/scripts/kconfig/lxdialog/dialog.h b/scripts/kconfig/lxdialog/dialog.h
index 0b00be5..68b565e 100644
--- a/scripts/kconfig/lxdialog/dialog.h
+++ b/scripts/kconfig/lxdialog/dialog.h
@@ -1,21 +1,8 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
/*
* dialog.h -- common declarations for all dialog modules
*
* AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <sys/types.h>
diff --git a/scripts/kconfig/lxdialog/inputbox.c b/scripts/kconfig/lxdialog/inputbox.c
index fe82ff6..1dcfb28 100644
--- a/scripts/kconfig/lxdialog/inputbox.c
+++ b/scripts/kconfig/lxdialog/inputbox.c
@@ -1,22 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* inputbox.c -- implements the input box
*
* ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
* MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com)
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "dialog.h"
@@ -126,7 +113,8 @@
case KEY_DOWN:
break;
case KEY_BACKSPACE:
- case 127:
+ case 8: /* ^H */
+ case 127: /* ^? */
if (pos) {
wattrset(dialog, dlg.inputbox.atr);
if (input_x == 0) {
diff --git a/scripts/kconfig/lxdialog/menubox.c b/scripts/kconfig/lxdialog/menubox.c
index d70cab3..58c2f8a 100644
--- a/scripts/kconfig/lxdialog/menubox.c
+++ b/scripts/kconfig/lxdialog/menubox.c
@@ -1,22 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* menubox.c -- implements the menu box
*
* ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
* MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcapw@cfw.com)
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*
diff --git a/scripts/kconfig/lxdialog/textbox.c b/scripts/kconfig/lxdialog/textbox.c
index 88d2818..4e339b1 100644
--- a/scripts/kconfig/lxdialog/textbox.c
+++ b/scripts/kconfig/lxdialog/textbox.c
@@ -1,22 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* textbox.c -- implements the text box
*
* ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
* MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com)
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "dialog.h"
diff --git a/scripts/kconfig/lxdialog/util.c b/scripts/kconfig/lxdialog/util.c
index f7abdeb..1b490d4 100644
--- a/scripts/kconfig/lxdialog/util.c
+++ b/scripts/kconfig/lxdialog/util.c
@@ -1,22 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* util.c
*
* ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
* MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com)
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <stdarg.h>
diff --git a/scripts/kconfig/lxdialog/yesno.c b/scripts/kconfig/lxdialog/yesno.c
index cd1223c..bcaac9b 100644
--- a/scripts/kconfig/lxdialog/yesno.c
+++ b/scripts/kconfig/lxdialog/yesno.c
@@ -1,22 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* yesno.c -- implements the yes/no box
*
* ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
* MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com)
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "dialog.h"
diff --git a/scripts/kconfig/mconf.c b/scripts/kconfig/mconf.c
index 143c05f..49c26ea 100644
--- a/scripts/kconfig/mconf.c
+++ b/scripts/kconfig/mconf.c
@@ -1,6 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
- * Released under the terms of the GNU GPL v2.0.
*
* Introduced single menu mode (show all sub-menus in one large tree).
* 2002-11-06 Petr Baudis <pasky@ucw.cz>
@@ -536,7 +536,7 @@
}
val = sym_get_tristate_value(sym);
- if (sym_is_changable(sym)) {
+ if (sym_is_changeable(sym)) {
switch (type) {
case S_BOOLEAN:
item_make("[%c]", val == no ? ' ' : '*');
@@ -587,7 +587,7 @@
} else {
switch (type) {
case S_BOOLEAN:
- if (sym_is_changable(sym))
+ if (sym_is_changeable(sym))
item_make("[%c]", val == no ? ' ' : '*');
else
item_make("-%c-", val == no ? ' ' : '*');
@@ -600,7 +600,7 @@
case mod: ch = 'M'; break;
default: ch = ' '; break;
}
- if (sym_is_changable(sym)) {
+ if (sym_is_changeable(sym)) {
if (sym->rev_dep.tri == mod)
item_make("{%c}", ch);
else
@@ -617,7 +617,7 @@
if (tmp < 0)
tmp = 0;
item_add_str("%*c%s%s", tmp, ' ', menu_get_prompt(menu),
- (sym_has_value(sym) || !sym_is_changable(sym)) ?
+ (sym_has_value(sym) || !sym_is_changeable(sym)) ?
"" : " (NEW)");
item_set_tag('s');
item_set_data(menu);
@@ -625,7 +625,7 @@
}
}
item_add_str("%*c%s%s", indent + 1, ' ', menu_get_prompt(menu),
- (sym_has_value(sym) || !sym_is_changable(sym)) ?
+ (sym_has_value(sym) || !sym_is_changeable(sym)) ?
"" : " (NEW)");
if (menu->prompt->type == P_MENU) {
item_add_str(" %s", menu_is_empty(menu) ? "----" : "--->");
@@ -936,7 +936,7 @@
set_config_filename(dialog_input_result);
return;
}
- show_textbox(NULL, "Can't create file! Probably a nonexistent directory.", 5, 60);
+ show_textbox(NULL, "Can't create file!", 5, 60);
break;
case 1:
show_helptext("Save Alternate Configuration", save_config_help);
diff --git a/scripts/kconfig/menu.c b/scripts/kconfig/menu.c
index 4cf15d4..d9d1646 100644
--- a/scripts/kconfig/menu.c
+++ b/scripts/kconfig/menu.c
@@ -1,6 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
- * Released under the terms of the GNU GPL v2.0.
*/
#include <ctype.h>
@@ -195,29 +195,26 @@
menu_add_prop(type, NULL, expr_alloc_symbol(sym), dep);
}
-void menu_add_option(int token, char *arg)
+void menu_add_option_modules(void)
{
- switch (token) {
- case T_OPT_MODULES:
- if (modules_sym)
- zconf_error("symbol '%s' redefines option 'modules'"
- " already defined by symbol '%s'",
- current_entry->sym->name,
- modules_sym->name
- );
- modules_sym = current_entry->sym;
- break;
- case T_OPT_DEFCONFIG_LIST:
- if (!sym_defconfig_list)
- sym_defconfig_list = current_entry->sym;
- else if (sym_defconfig_list != current_entry->sym)
- zconf_error("trying to redefine defconfig symbol");
- sym_defconfig_list->flags |= SYMBOL_NO_WRITE;
- break;
- case T_OPT_ALLNOCONFIG_Y:
- current_entry->sym->flags |= SYMBOL_ALLNOCONFIG_Y;
- break;
- }
+ if (modules_sym)
+ zconf_error("symbol '%s' redefines option 'modules' already defined by symbol '%s'",
+ current_entry->sym->name, modules_sym->name);
+ modules_sym = current_entry->sym;
+}
+
+void menu_add_option_defconfig_list(void)
+{
+ if (!sym_defconfig_list)
+ sym_defconfig_list = current_entry->sym;
+ else if (sym_defconfig_list != current_entry->sym)
+ zconf_error("trying to redefine defconfig symbol");
+ sym_defconfig_list->flags |= SYMBOL_NO_WRITE;
+}
+
+void menu_add_option_allnoconfig_y(void)
+{
+ current_entry->sym->flags |= SYMBOL_ALLNOCONFIG_Y;
}
static int menu_validate_number(struct symbol *sym, struct symbol *sym2)
diff --git a/scripts/kconfig/merge_config.sh b/scripts/kconfig/merge_config.sh
index 67d1314..63c8565 100755
--- a/scripts/kconfig/merge_config.sh
+++ b/scripts/kconfig/merge_config.sh
@@ -1,4 +1,6 @@
#!/bin/sh
+# SPDX-License-Identifier: GPL-2.0
+#
# merge_config.sh - Takes a list of config fragment values, and merges
# them one by one. Provides warnings on overridden values, and specified
# values that did not make it to the resulting .config file (due to missed
@@ -10,21 +12,13 @@
#
# Copyright (c) 2009-2010 Wind River Systems, Inc.
# Copyright 2011 Linaro
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License version 2 as
-# published by the Free Software Foundation.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-# See the GNU General Public License for more details.
+
+set -e
clean_up() {
rm -f $TMP_FILE
- exit
+ rm -f $MERGE_FILE
}
-trap clean_up HUP INT TERM
usage() {
echo "Usage: $0 [OPTIONS] [CONFIG [...]]"
@@ -32,13 +26,18 @@
echo " -m only merge the fragments, do not execute the make command"
echo " -n use allnoconfig instead of alldefconfig"
echo " -r list redundant entries when merging fragments"
+ echo " -y make builtin have precedence over modules"
echo " -O dir to put generated output files. Consider setting \$KCONFIG_CONFIG instead."
+ echo
+ echo "Used prefix: '$CONFIG_PREFIX'. You can redefine it with \$CONFIG_ environment variable."
}
RUNMAKE=true
ALLTARGET=alldefconfig
WARNREDUN=false
+BUILTIN=false
OUTPUT=.
+CONFIG_PREFIX=${CONFIG_-CONFIG_}
while true; do
case $1 in
@@ -61,6 +60,11 @@
shift
continue
;;
+ "-y")
+ BUILTIN=true
+ shift
+ continue
+ ;;
"-O")
if [ -d $2 ];then
OUTPUT=$(echo $2 | sed 's/\/*$//')
@@ -99,34 +103,52 @@
fi
MERGE_LIST=$*
-SED_CONFIG_EXP="s/^\(# \)\{0,1\}\(CONFIG_[a-zA-Z0-9_]*\)[= ].*/\2/p"
+SED_CONFIG_EXP1="s/^\(${CONFIG_PREFIX}[a-zA-Z0-9_]*\)=.*/\1/p"
+SED_CONFIG_EXP2="s/^# \(${CONFIG_PREFIX}[a-zA-Z0-9_]*\) is not set$/\1/p"
+
TMP_FILE=$(mktemp ./.tmp.config.XXXXXXXXXX)
+MERGE_FILE=$(mktemp ./.merge_tmp.config.XXXXXXXXXX)
echo "Using $INITFILE as base"
+
+trap clean_up EXIT
+
cat $INITFILE > $TMP_FILE
# Merge files, printing warnings on overridden values
-for MERGE_FILE in $MERGE_LIST ; do
- echo "Merging $MERGE_FILE"
- if [ ! -r "$MERGE_FILE" ]; then
- echo "The merge file '$MERGE_FILE' does not exist. Exit." >&2
+for ORIG_MERGE_FILE in $MERGE_LIST ; do
+ echo "Merging $ORIG_MERGE_FILE"
+ if [ ! -r "$ORIG_MERGE_FILE" ]; then
+ echo "The merge file '$ORIG_MERGE_FILE' does not exist. Exit." >&2
exit 1
fi
- CFG_LIST=$(sed -n "$SED_CONFIG_EXP" $MERGE_FILE)
+ cat $ORIG_MERGE_FILE > $MERGE_FILE
+ CFG_LIST=$(sed -n -e "$SED_CONFIG_EXP1" -e "$SED_CONFIG_EXP2" $MERGE_FILE)
for CFG in $CFG_LIST ; do
grep -q -w $CFG $TMP_FILE || continue
PREV_VAL=$(grep -w $CFG $TMP_FILE)
NEW_VAL=$(grep -w $CFG $MERGE_FILE)
- if [ "x$PREV_VAL" != "x$NEW_VAL" ] ; then
- echo Value of $CFG is redefined by fragment $MERGE_FILE:
+ BUILTIN_FLAG=false
+ if [ "$BUILTIN" = "true" ] && [ "${NEW_VAL#CONFIG_*=}" = "m" ] && [ "${PREV_VAL#CONFIG_*=}" = "y" ]; then
+ echo Previous value: $PREV_VAL
+ echo New value: $NEW_VAL
+ echo -y passed, will not demote y to m
+ echo
+ BUILTIN_FLAG=true
+ elif [ "x$PREV_VAL" != "x$NEW_VAL" ] ; then
+ echo Value of $CFG is redefined by fragment $ORIG_MERGE_FILE:
echo Previous value: $PREV_VAL
echo New value: $NEW_VAL
echo
elif [ "$WARNREDUN" = "true" ]; then
- echo Value of $CFG is redundant by fragment $MERGE_FILE:
+ echo Value of $CFG is redundant by fragment $ORIG_MERGE_FILE:
fi
- sed -i "/$CFG[ =]/d" $TMP_FILE
+ if [ "$BUILTIN_FLAG" = "false" ]; then
+ sed -i "/$CFG[ =]/d" $TMP_FILE
+ else
+ sed -i "/$CFG[ =]/d" $MERGE_FILE
+ fi
done
cat $MERGE_FILE >> $TMP_FILE
done
@@ -136,7 +158,6 @@
echo "#"
echo "# merged configuration written to $KCONFIG_CONFIG (needs make)"
echo "#"
- clean_up
exit
fi
@@ -155,10 +176,10 @@
# Check all specified config values took (might have missed-dependency issues)
-for CFG in $(sed -n "$SED_CONFIG_EXP" $TMP_FILE); do
+for CFG in $(sed -n -e "$SED_CONFIG_EXP1" -e "$SED_CONFIG_EXP2" $TMP_FILE); do
REQUESTED_VAL=$(grep -w -e "$CFG" $TMP_FILE)
- ACTUAL_VAL=$(grep -w -e "$CFG" "$KCONFIG_CONFIG")
+ ACTUAL_VAL=$(grep -w -e "$CFG" "$KCONFIG_CONFIG" || true)
if [ "x$REQUESTED_VAL" != "x$ACTUAL_VAL" ] ; then
echo "Value requested for $CFG not in final .config"
echo "Requested value: $REQUESTED_VAL"
@@ -166,5 +187,3 @@
echo ""
fi
done
-
-clean_up
diff --git a/scripts/kconfig/nconf-cfg.sh b/scripts/kconfig/nconf-cfg.sh
old mode 100644
new mode 100755
diff --git a/scripts/kconfig/nconf.c b/scripts/kconfig/nconf.c
index 1ef232a..b7c1ef7 100644
--- a/scripts/kconfig/nconf.c
+++ b/scripts/kconfig/nconf.c
@@ -1,9 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
/*
- * Copyright (C) 2008 Nir Tzachar <nir.tzachar@gmail.com?
- * Released under the terms of the GNU GPL v2.0.
+ * Copyright (C) 2008 Nir Tzachar <nir.tzachar@gmail.com>
*
* Derived from menuconfig.
- *
*/
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
@@ -804,7 +803,7 @@
}
val = sym_get_tristate_value(sym);
- if (sym_is_changable(sym)) {
+ if (sym_is_changeable(sym)) {
switch (type) {
case S_BOOLEAN:
item_make(menu, 't', "[%c]",
@@ -858,7 +857,7 @@
} else {
switch (type) {
case S_BOOLEAN:
- if (sym_is_changable(sym))
+ if (sym_is_changeable(sym))
item_make(menu, 't', "[%c]",
val == no ? ' ' : '*');
else
@@ -877,7 +876,7 @@
ch = ' ';
break;
}
- if (sym_is_changable(sym)) {
+ if (sym_is_changeable(sym)) {
if (sym->rev_dep.tri == mod)
item_make(menu,
't', "{%c}", ch);
@@ -897,14 +896,14 @@
item_add_str("%*c%s%s", tmp, ' ',
menu_get_prompt(menu),
(sym_has_value(sym) ||
- !sym_is_changable(sym)) ? "" :
+ !sym_is_changeable(sym)) ? "" :
" (NEW)");
goto conf_childs;
}
}
item_add_str("%*c%s%s", indent + 1, ' ',
menu_get_prompt(menu),
- (sym_has_value(sym) || !sym_is_changable(sym)) ?
+ (sym_has_value(sym) || !sym_is_changeable(sym)) ?
"" : " (NEW)");
if (menu->prompt && menu->prompt->type == P_MENU) {
item_add_str(" %s", menu_is_empty(menu) ? "----" : "--->");
@@ -1049,7 +1048,7 @@
state->match_direction = FIND_NEXT_MATCH_UP;
*ans = get_mext_match(state->pattern,
state->match_direction);
- } else if (key == KEY_BACKSPACE || key == 127) {
+ } else if (key == KEY_BACKSPACE || key == 8 || key == 127) {
state->pattern[strlen(state->pattern)-1] = '\0';
adj_match_dir(&state->match_direction);
} else
@@ -1439,8 +1438,7 @@
set_config_filename(dialog_input_result);
return;
}
- btn_dialog(main_window, "Can't create file! "
- "Probably a nonexistent directory.",
+ btn_dialog(main_window, "Can't create file!",
1, "<OK>");
break;
case 1:
diff --git a/scripts/kconfig/nconf.gui.c b/scripts/kconfig/nconf.gui.c
index 88874ac..77f525a 100644
--- a/scripts/kconfig/nconf.gui.c
+++ b/scripts/kconfig/nconf.gui.c
@@ -1,9 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
/*
- * Copyright (C) 2008 Nir Tzachar <nir.tzachar@gmail.com?
- * Released under the terms of the GNU GPL v2.0.
+ * Copyright (C) 2008 Nir Tzachar <nir.tzachar@gmail.com>
*
* Derived from menuconfig.
- *
*/
#include "nconf.h"
#include "lkc.h"
@@ -440,7 +439,8 @@
case KEY_F(F_EXIT):
case KEY_F(F_BACK):
break;
- case 127:
+ case 8: /* ^H */
+ case 127: /* ^? */
case KEY_BACKSPACE:
if (cursor_position > 0) {
memmove(&result[cursor_position-1],
diff --git a/scripts/kconfig/nconf.h b/scripts/kconfig/nconf.h
index 2b9e19f..fa5245e 100644
--- a/scripts/kconfig/nconf.h
+++ b/scripts/kconfig/nconf.h
@@ -1,9 +1,8 @@
+/* SPDX-License-Identifier: GPL-2.0 */
/*
- * Copyright (C) 2008 Nir Tzachar <nir.tzachar@gmail.com?
- * Released under the terms of the GNU GPL v2.0.
+ * Copyright (C) 2008 Nir Tzachar <nir.tzachar@gmail.com>
*
* Derived from menuconfig.
- *
*/
#include <ctype.h>
diff --git a/scripts/kconfig/zconf.y b/scripts/kconfig/parser.y
similarity index 74%
rename from scripts/kconfig/zconf.y
rename to scripts/kconfig/parser.y
index 22fceb2..60936c7 100644
--- a/scripts/kconfig/zconf.y
+++ b/scripts/kconfig/parser.y
@@ -1,8 +1,8 @@
-%{
+/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
- * Released under the terms of the GNU GPL v2.0.
*/
+%{
#include <ctype.h>
#include <stdarg.h>
@@ -20,66 +20,68 @@
int cdebug = PRINTD;
-int yylex(void);
static void yyerror(const char *err);
static void zconfprint(const char *err, ...);
static void zconf_error(const char *err, ...);
-static bool zconf_endtoken(const struct kconf_id *id, int starttoken, int endtoken);
+static bool zconf_endtoken(const char *tokenname,
+ const char *expected_tokenname);
struct symbol *symbol_hash[SYMBOL_HASHSIZE];
static struct menu *current_menu, *current_entry;
%}
-%expect 30
%union
{
char *string;
- struct file *file;
struct symbol *symbol;
struct expr *expr;
struct menu *menu;
- const struct kconf_id *id;
+ enum symbol_type type;
enum variable_flavor flavor;
}
-%token <id>T_MAINMENU
-%token <id>T_MENU
-%token <id>T_ENDMENU
-%token <id>T_SOURCE
-%token <id>T_CHOICE
-%token <id>T_ENDCHOICE
-%token <id>T_COMMENT
-%token <id>T_CONFIG
-%token <id>T_MENUCONFIG
-%token <id>T_HELP
%token <string> T_HELPTEXT
-%token <id>T_IF
-%token <id>T_ENDIF
-%token <id>T_DEPENDS
-%token <id>T_OPTIONAL
-%token <id>T_PROMPT
-%token <id>T_TYPE
-%token <id>T_DEFAULT
-%token <id>T_SELECT
-%token <id>T_IMPLY
-%token <id>T_RANGE
-%token <id>T_VISIBLE
-%token <id>T_OPTION
-%token <id>T_ON
%token <string> T_WORD
%token <string> T_WORD_QUOTE
-%token T_UNEQUAL
-%token T_LESS
-%token T_LESS_EQUAL
-%token T_GREATER
-%token T_GREATER_EQUAL
+%token T_ALLNOCONFIG_Y
+%token T_BOOL
+%token T_CHOICE
%token T_CLOSE_PAREN
+%token T_COLON_EQUAL
+%token T_COMMENT
+%token T_CONFIG
+%token T_DEFAULT
+%token T_DEFCONFIG_LIST
+%token T_DEF_BOOL
+%token T_DEF_TRISTATE
+%token T_DEPENDS
+%token T_ENDCHOICE
+%token T_ENDIF
+%token T_ENDMENU
+%token T_HELP
+%token T_HEX
+%token T_IF
+%token T_IMPLY
+%token T_INT
+%token T_MAINMENU
+%token T_MENU
+%token T_MENUCONFIG
+%token T_MODULES
+%token T_ON
%token T_OPEN_PAREN
+%token T_OPTION
+%token T_OPTIONAL
+%token T_PLUS_EQUAL
+%token T_PROMPT
+%token T_RANGE
+%token T_SELECT
+%token T_SOURCE
+%token T_STRING
+%token T_TRISTATE
+%token T_VISIBLE
%token T_EOL
-%token <string> T_VARIABLE
-%token <flavor> T_ASSIGN
%token <string> T_ASSIGN_VAL
%left T_OR
@@ -91,12 +93,13 @@
%type <string> prompt
%type <symbol> nonconst_symbol
%type <symbol> symbol
+%type <type> type logic_type default
%type <expr> expr
%type <expr> if_expr
-%type <id> end
-%type <id> option_name
+%type <string> end
%type <menu> if_entry menu_entry choice_entry
-%type <string> symbol_option_arg word_opt assign_val
+%type <string> word_opt assign_val
+%type <flavor> assign_op
%destructor {
fprintf(stderr, "%s:%d: missing end statement for this entry\n",
@@ -105,15 +108,8 @@
menu_end_menu();
} if_entry menu_entry choice_entry
-%{
-/* Include kconf_id.c here so it can see the token constants. */
-#include "kconf_id.c"
-%}
-
%%
-input: nl start | start;
-
-start: mainmenu_stmt stmt_list | stmt_list;
+input: mainmenu_stmt stmt_list | stmt_list;
/* mainmenu entry */
@@ -127,22 +123,12 @@
| stmt_list common_stmt
| stmt_list choice_stmt
| stmt_list menu_stmt
- | stmt_list end { zconf_error("unexpected end statement"); }
| stmt_list T_WORD error T_EOL { zconf_error("unknown statement \"%s\"", $2); }
- | stmt_list option_name error T_EOL
-{
- zconf_error("unexpected option \"%s\"", $2->name);
-}
| stmt_list error T_EOL { zconf_error("invalid statement"); }
;
-option_name:
- T_DEPENDS | T_PROMPT | T_TYPE | T_SELECT | T_IMPLY | T_OPTIONAL | T_RANGE | T_DEFAULT | T_VISIBLE
-;
-
common_stmt:
- T_EOL
- | if_stmt
+ if_stmt
| comment_stmt
| config_stmt
| menuconfig_stmt
@@ -150,12 +136,6 @@
| assignment_stmt
;
-option_error:
- T_WORD error T_EOL { zconf_error("unknown option \"%s\"", $1); }
- | error T_EOL { zconf_error("invalid option"); }
-;
-
-
/* config/menuconfig entry */
config_entry_start: T_CONFIG nonconst_symbol T_EOL
@@ -189,19 +169,16 @@
config_option_list:
/* empty */
| config_option_list config_option
- | config_option_list symbol_option
| config_option_list depends
| config_option_list help
- | config_option_list option_error
- | config_option_list T_EOL
;
-config_option: T_TYPE prompt_stmt_opt T_EOL
+config_option: type prompt_stmt_opt T_EOL
{
- menu_set_type($1->stype);
+ menu_set_type($1);
printd(DEBUG_PARSE, "%s:%d:type(%u)\n",
zconf_curname(), zconf_lineno(),
- $1->stype);
+ $1);
};
config_option: T_PROMPT prompt if_expr T_EOL
@@ -210,14 +187,14 @@
printd(DEBUG_PARSE, "%s:%d:prompt\n", zconf_curname(), zconf_lineno());
};
-config_option: T_DEFAULT expr if_expr T_EOL
+config_option: default expr if_expr T_EOL
{
menu_add_expr(P_DEFAULT, $2, $3);
- if ($1->stype != S_UNKNOWN)
- menu_set_type($1->stype);
+ if ($1 != S_UNKNOWN)
+ menu_set_type($1);
printd(DEBUG_PARSE, "%s:%d:default(%u)\n",
zconf_curname(), zconf_lineno(),
- $1->stype);
+ $1);
};
config_option: T_SELECT nonconst_symbol if_expr T_EOL
@@ -238,27 +215,20 @@
printd(DEBUG_PARSE, "%s:%d:range\n", zconf_curname(), zconf_lineno());
};
-symbol_option: T_OPTION symbol_option_list T_EOL
-;
-
-symbol_option_list:
- /* empty */
- | symbol_option_list T_WORD symbol_option_arg
+config_option: T_OPTION T_MODULES T_EOL
{
- const struct kconf_id *id = kconf_id_lookup($2, strlen($2));
- if (id && id->flags & TF_OPTION) {
- menu_add_option(id->token, $3);
- free($3);
- }
- else
- zconfprint("warning: ignoring unknown option %s", $2);
- free($2);
+ menu_add_option_modules();
};
-symbol_option_arg:
- /* empty */ { $$ = NULL; }
- | T_EQUAL prompt { $$ = $2; }
-;
+config_option: T_OPTION T_DEFCONFIG_LIST T_EOL
+{
+ menu_add_option_defconfig_list();
+};
+
+config_option: T_OPTION T_ALLNOCONFIG_Y T_EOL
+{
+ menu_add_option_allnoconfig_y();
+};
/* choice entry */
@@ -279,7 +249,7 @@
choice_end: end
{
- if (zconf_endtoken($1, T_CHOICE, T_ENDCHOICE)) {
+ if (zconf_endtoken($1, "choice")) {
menu_end_menu();
printd(DEBUG_PARSE, "%s:%d:endchoice\n", zconf_curname(), zconf_lineno());
}
@@ -293,8 +263,6 @@
| choice_option_list choice_option
| choice_option_list depends
| choice_option_list help
- | choice_option_list T_EOL
- | choice_option_list option_error
;
choice_option: T_PROMPT prompt if_expr T_EOL
@@ -303,15 +271,11 @@
printd(DEBUG_PARSE, "%s:%d:prompt\n", zconf_curname(), zconf_lineno());
};
-choice_option: T_TYPE prompt_stmt_opt T_EOL
+choice_option: logic_type prompt_stmt_opt T_EOL
{
- if ($1->stype == S_BOOLEAN || $1->stype == S_TRISTATE) {
- menu_set_type($1->stype);
- printd(DEBUG_PARSE, "%s:%d:type(%u)\n",
- zconf_curname(), zconf_lineno(),
- $1->stype);
- } else
- YYERROR;
+ menu_set_type($1);
+ printd(DEBUG_PARSE, "%s:%d:type(%u)\n",
+ zconf_curname(), zconf_lineno(), $1);
};
choice_option: T_OPTIONAL T_EOL
@@ -322,14 +286,26 @@
choice_option: T_DEFAULT nonconst_symbol if_expr T_EOL
{
- if ($1->stype == S_UNKNOWN) {
- menu_add_symbol(P_DEFAULT, $2, $3);
- printd(DEBUG_PARSE, "%s:%d:default\n",
- zconf_curname(), zconf_lineno());
- } else
- YYERROR;
+ menu_add_symbol(P_DEFAULT, $2, $3);
+ printd(DEBUG_PARSE, "%s:%d:default\n",
+ zconf_curname(), zconf_lineno());
};
+type:
+ logic_type
+ | T_INT { $$ = S_INT; }
+ | T_HEX { $$ = S_HEX; }
+ | T_STRING { $$ = S_STRING; }
+
+logic_type:
+ T_BOOL { $$ = S_BOOLEAN; }
+ | T_TRISTATE { $$ = S_TRISTATE; }
+
+default:
+ T_DEFAULT { $$ = S_UNKNOWN; }
+ | T_DEF_BOOL { $$ = S_BOOLEAN; }
+ | T_DEF_TRISTATE { $$ = S_TRISTATE; }
+
choice_block:
/* empty */
| choice_block common_stmt
@@ -347,20 +323,13 @@
if_end: end
{
- if (zconf_endtoken($1, T_IF, T_ENDIF)) {
+ if (zconf_endtoken($1, "if")) {
menu_end_menu();
printd(DEBUG_PARSE, "%s:%d:endif\n", zconf_curname(), zconf_lineno());
}
};
-if_stmt: if_entry if_block if_end
-;
-
-if_block:
- /* empty */
- | if_block common_stmt
- | if_block menu_stmt
- | if_block choice_stmt
+if_stmt: if_entry stmt_list if_end
;
/* menu entry */
@@ -372,27 +341,26 @@
printd(DEBUG_PARSE, "%s:%d:menu\n", zconf_curname(), zconf_lineno());
};
-menu_entry: menu visibility_list depends_list
+menu_entry: menu menu_option_list
{
$$ = menu_add_menu();
};
menu_end: end
{
- if (zconf_endtoken($1, T_MENU, T_ENDMENU)) {
+ if (zconf_endtoken($1, "menu")) {
menu_end_menu();
printd(DEBUG_PARSE, "%s:%d:endmenu\n", zconf_curname(), zconf_lineno());
}
};
-menu_stmt: menu_entry menu_block menu_end
+menu_stmt: menu_entry stmt_list menu_end
;
-menu_block:
+menu_option_list:
/* empty */
- | menu_block common_stmt
- | menu_block menu_stmt
- | menu_block choice_stmt
+ | menu_option_list visible
+ | menu_option_list depends
;
source_stmt: T_SOURCE prompt T_EOL
@@ -411,7 +379,12 @@
printd(DEBUG_PARSE, "%s:%d:comment\n", zconf_curname(), zconf_lineno());
};
-comment_stmt: comment depends_list
+comment_stmt: comment comment_option_list
+;
+
+comment_option_list:
+ /* empty */
+ | comment_option_list depends
;
/* help option */
@@ -440,13 +413,6 @@
/* depends option */
-depends_list:
- /* empty */
- | depends_list depends
- | depends_list T_EOL
- | depends_list option_error
-;
-
depends: T_DEPENDS T_ON expr T_EOL
{
menu_add_dep($3);
@@ -454,14 +420,7 @@
};
/* visibility option */
-
-visibility_list:
- /* empty */
- | visibility_list visible
- | visibility_list T_EOL
-;
-
-visible: T_VISIBLE if_expr
+visible: T_VISIBLE if_expr T_EOL
{
menu_add_visibility($2);
};
@@ -479,14 +438,9 @@
| T_WORD_QUOTE
;
-end: T_ENDMENU T_EOL { $$ = $1; }
- | T_ENDCHOICE T_EOL { $$ = $1; }
- | T_ENDIF T_EOL { $$ = $1; }
-;
-
-nl:
- T_EOL
- | nl T_EOL
+end: T_ENDMENU T_EOL { $$ = "menu"; }
+ | T_ENDCHOICE T_EOL { $$ = "choice"; }
+ | T_ENDIF T_EOL { $$ = "if"; }
;
if_expr: /* empty */ { $$ = NULL; }
@@ -518,7 +472,13 @@
/* assignment statement */
-assignment_stmt: T_VARIABLE T_ASSIGN assign_val T_EOL { variable_add($1, $3, $2); free($1); free($3); }
+assignment_stmt: T_WORD assign_op assign_val T_EOL { variable_add($1, $3, $2); free($1); free($3); }
+
+assign_op:
+ T_EQUAL { $$ = VAR_RECURSIVE; }
+ | T_COLON_EQUAL { $$ = VAR_SIMPLE; }
+ | T_PLUS_EQUAL { $$ = VAR_APPEND; }
+;
assign_val:
/* empty */ { $$ = xstrdup(""); };
@@ -563,35 +523,21 @@
sym_set_change_count(1);
}
-static const char *zconf_tokenname(int token)
+static bool zconf_endtoken(const char *tokenname,
+ const char *expected_tokenname)
{
- switch (token) {
- case T_MENU: return "menu";
- case T_ENDMENU: return "endmenu";
- case T_CHOICE: return "choice";
- case T_ENDCHOICE: return "endchoice";
- case T_IF: return "if";
- case T_ENDIF: return "endif";
- case T_DEPENDS: return "depends";
- case T_VISIBLE: return "visible";
- }
- return "<token>";
-}
-
-static bool zconf_endtoken(const struct kconf_id *id, int starttoken, int endtoken)
-{
- if (id->token != endtoken) {
+ if (strcmp(tokenname, expected_tokenname)) {
zconf_error("unexpected '%s' within %s block",
- id->name, zconf_tokenname(starttoken));
+ tokenname, expected_tokenname);
yynerrs++;
return false;
}
if (current_menu->file != current_file) {
zconf_error("'%s' in different file than '%s'",
- id->name, zconf_tokenname(starttoken));
+ tokenname, expected_tokenname);
fprintf(stderr, "%s:%d: location of the '%s'\n",
current_menu->file->name, current_menu->lineno,
- zconf_tokenname(starttoken));
+ expected_tokenname);
yynerrs++;
return false;
}
@@ -781,10 +727,5 @@
}
}
-#include "zconf.lex.c"
#include "util.c"
-#include "confdata.c"
-#include "expr.c"
-#include "symbol.c"
#include "menu.c"
-#include "preprocess.c"
diff --git a/scripts/kconfig/preprocess.c b/scripts/kconfig/preprocess.c
index 5ca2df7..0243086 100644
--- a/scripts/kconfig/preprocess.c
+++ b/scripts/kconfig/preprocess.c
@@ -2,6 +2,7 @@
//
// Copyright (C) 2018 Masahiro Yamada <yamada.masahiro@socionext.com>
+#include <ctype.h>
#include <stdarg.h>
#include <stdbool.h>
#include <stdio.h>
@@ -9,10 +10,12 @@
#include <string.h>
#include "list.h"
+#include "lkc.h"
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
static char *expand_string_with_args(const char *in, int argc, char *argv[]);
+static char *expand_string(const char *in);
static void __attribute__((noreturn)) pperror(const char *format, ...)
{
@@ -548,15 +551,14 @@
return __expand_string(&in, is_end_of_str, argc, argv);
}
-char *expand_string(const char *in)
+static char *expand_string(const char *in)
{
return expand_string_with_args(in, 0, NULL);
}
static bool is_end_of_token(char c)
{
- /* Why are '.' and '/' valid characters for symbols? */
- return !(isalnum(c) || c == '_' || c == '-' || c == '.' || c == '/');
+ return !(isalnum(c) || c == '_' || c == '-');
}
/*
diff --git a/scripts/kconfig/qconf.cc b/scripts/kconfig/qconf.cc
index ef4310f..82773cc 100644
--- a/scripts/kconfig/qconf.cc
+++ b/scripts/kconfig/qconf.cc
@@ -1,7 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
* Copyright (C) 2015 Boris Barbulovski <bbarbulovski@gmail.com>
- * Released under the terms of the GNU GPL v2.0.
*/
#include <qglobal.h>
@@ -32,7 +32,7 @@
#include "qconf.h"
#include "qconf.moc"
-#include "images.c"
+#include "images.h"
static QApplication *configApp;
@@ -152,7 +152,7 @@
case S_TRISTATE:
char ch;
- if (!sym_is_changable(sym) && list->optMode == normalOpt) {
+ if (!sym_is_changeable(sym) && list->optMode == normalOpt) {
setPixmap(promptColIdx, QIcon());
setText(noColIdx, QString::null);
setText(modColIdx, QString::null);
@@ -1392,6 +1392,8 @@
conf_set_changed_callback(conf_changed);
// Set saveAction's initial state
conf_changed();
+ configname = xstrdup(conf_get_configname());
+
QAction *saveAsAction = new QAction("Save &As...", this);
connect(saveAsAction, SIGNAL(triggered(bool)), SLOT(saveConfigAs()));
QAction *searchAction = new QAction("&Find", this);
@@ -1520,17 +1522,29 @@
void ConfigMainWindow::loadConfig(void)
{
- QString s = QFileDialog::getOpenFileName(this, "", conf_get_configname());
- if (s.isNull())
+ QString str;
+ QByteArray ba;
+ const char *name;
+
+ str = QFileDialog::getOpenFileName(this, "", configname);
+ if (str.isNull())
return;
- if (conf_read(QFile::encodeName(s)))
+
+ ba = str.toLocal8Bit();
+ name = ba.data();
+
+ if (conf_read(name))
QMessageBox::information(this, "qconf", "Unable to load configuration!");
+
+ free(configname);
+ configname = xstrdup(name);
+
ConfigView::updateListAll();
}
bool ConfigMainWindow::saveConfig(void)
{
- if (conf_write(NULL)) {
+ if (conf_write(configname)) {
QMessageBox::information(this, "qconf", "Unable to save configuration!");
return false;
}
@@ -1541,10 +1555,24 @@
void ConfigMainWindow::saveConfigAs(void)
{
- QString s = QFileDialog::getSaveFileName(this, "", conf_get_configname());
- if (s.isNull())
+ QString str;
+ QByteArray ba;
+ const char *name;
+
+ str = QFileDialog::getSaveFileName(this, "", configname);
+ if (str.isNull())
return;
- saveConfig();
+
+ ba = str.toLocal8Bit();
+ name = ba.data();
+
+ if (conf_write(name)) {
+ QMessageBox::information(this, "qconf", "Unable to save configuration!");
+ }
+ conf_write_autoconf(0);
+
+ free(configname);
+ configname = xstrdup(name);
}
void ConfigMainWindow::searchConfig(void)
diff --git a/scripts/kconfig/qconf.h b/scripts/kconfig/qconf.h
index a40036d..45bfe9b 100644
--- a/scripts/kconfig/qconf.h
+++ b/scripts/kconfig/qconf.h
@@ -1,6 +1,6 @@
+/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
- * Released under the terms of the GNU GPL v2.0.
*/
#include <QTextBrowser>
@@ -291,6 +291,7 @@
class ConfigMainWindow : public QMainWindow {
Q_OBJECT
+ char *configname;
static QAction *saveAction;
static void conf_changed(void);
public:
diff --git a/scripts/kconfig/streamline_config.pl b/scripts/kconfig/streamline_config.pl
index 4686531..08d76d7 100755
--- a/scripts/kconfig/streamline_config.pl
+++ b/scripts/kconfig/streamline_config.pl
@@ -1,7 +1,7 @@
#!/usr/bin/env perl
+# SPDX-License-Identifier: GPL-2.0
#
# Copyright 2005-2009 - Steven Rostedt
-# Licensed under the terms of the GNU GPL License version 2
#
# It's simple enough to figure out how this works.
# If not, then you can ask me at stripconfig@goodmis.org
diff --git a/scripts/kconfig/symbol.c b/scripts/kconfig/symbol.c
index 703b9b8..f56eec5 100644
--- a/scripts/kconfig/symbol.c
+++ b/scripts/kconfig/symbol.c
@@ -1,6 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
- * Released under the terms of the GNU GPL v2.0.
*/
#include <ctype.h>
@@ -61,8 +61,6 @@
return "string";
case S_UNKNOWN:
return "unknown";
- case S_OTHER:
- break;
}
return "???";
}
@@ -88,7 +86,7 @@
return NULL;
}
-static struct property *sym_get_range_prop(struct symbol *sym)
+struct property *sym_get_range_prop(struct symbol *sym)
{
struct property *prop;
@@ -757,7 +755,6 @@
return str;
case S_STRING:
return str;
- case S_OTHER:
case S_UNKNOWN:
break;
}
@@ -788,7 +785,7 @@
return (const char *)sym->curr.val;
}
-bool sym_is_changable(struct symbol *sym)
+bool sym_is_changeable(struct symbol *sym)
{
return sym->visible > sym->rev_dep.tri;
}
@@ -1117,7 +1114,7 @@
}
fprintf(stderr,
- "For a resolution refer to Documentation/kbuild/kconfig-language.txt\n"
+ "For a resolution refer to Documentation/kbuild/kconfig-language.rst\n"
"subsection \"Kconfig recursive dependency limitations\"\n"
"\n");
diff --git a/scripts/kconfig/tests/auto_submenu/Kconfig b/scripts/kconfig/tests/auto_submenu/Kconfig
index c17bf2c..b20761e 100644
--- a/scripts/kconfig/tests/auto_submenu/Kconfig
+++ b/scripts/kconfig/tests/auto_submenu/Kconfig
@@ -1,3 +1,5 @@
+# SPDX-License-Identifier: GPL-2.0
+
config A
bool "A"
default y
diff --git a/scripts/kconfig/tests/auto_submenu/__init__.py b/scripts/kconfig/tests/auto_submenu/__init__.py
index 32e79b8..25abd92 100644
--- a/scripts/kconfig/tests/auto_submenu/__init__.py
+++ b/scripts/kconfig/tests/auto_submenu/__init__.py
@@ -1,3 +1,4 @@
+# SPDX-License-Identifier: GPL-2.0
"""
Create submenu for symbols that depend on the preceding one.
diff --git a/scripts/kconfig/tests/choice/Kconfig b/scripts/kconfig/tests/choice/Kconfig
index cc60e9c..a412205 100644
--- a/scripts/kconfig/tests/choice/Kconfig
+++ b/scripts/kconfig/tests/choice/Kconfig
@@ -1,3 +1,5 @@
+# SPDX-License-Identifier: GPL-2.0
+
config MODULES
bool "Enable loadable module support"
option modules
diff --git a/scripts/kconfig/tests/choice/__init__.py b/scripts/kconfig/tests/choice/__init__.py
index 9edcc52..4318fce 100644
--- a/scripts/kconfig/tests/choice/__init__.py
+++ b/scripts/kconfig/tests/choice/__init__.py
@@ -1,3 +1,4 @@
+# SPDX-License-Identifier: GPL-2.0
"""
Basic choice tests.
diff --git a/scripts/kconfig/tests/choice_value_with_m_dep/Kconfig b/scripts/kconfig/tests/choice_value_with_m_dep/Kconfig
index 11ac25c..7106c26 100644
--- a/scripts/kconfig/tests/choice_value_with_m_dep/Kconfig
+++ b/scripts/kconfig/tests/choice_value_with_m_dep/Kconfig
@@ -1,3 +1,5 @@
+# SPDX-License-Identifier: GPL-2.0
+
config MODULES
def_bool y
option modules
diff --git a/scripts/kconfig/tests/choice_value_with_m_dep/__init__.py b/scripts/kconfig/tests/choice_value_with_m_dep/__init__.py
index f8d728c..075b4e0 100644
--- a/scripts/kconfig/tests/choice_value_with_m_dep/__init__.py
+++ b/scripts/kconfig/tests/choice_value_with_m_dep/__init__.py
@@ -1,3 +1,4 @@
+# SPDX-License-Identifier: GPL-2.0
"""
Hide tristate choice values with mod dependency in y choice.
diff --git a/scripts/kconfig/tests/err_recursive_dep/expected_stderr b/scripts/kconfig/tests/err_recursive_dep/expected_stderr
index 84679b1..c9f4abf 100644
--- a/scripts/kconfig/tests/err_recursive_dep/expected_stderr
+++ b/scripts/kconfig/tests/err_recursive_dep/expected_stderr
@@ -1,38 +1,38 @@
Kconfig:11:error: recursive dependency detected!
Kconfig:11: symbol B is selected by B
-For a resolution refer to Documentation/kbuild/kconfig-language.txt
+For a resolution refer to Documentation/kbuild/kconfig-language.rst
subsection "Kconfig recursive dependency limitations"
Kconfig:5:error: recursive dependency detected!
Kconfig:5: symbol A depends on A
-For a resolution refer to Documentation/kbuild/kconfig-language.txt
+For a resolution refer to Documentation/kbuild/kconfig-language.rst
subsection "Kconfig recursive dependency limitations"
Kconfig:17:error: recursive dependency detected!
Kconfig:17: symbol C1 depends on C2
Kconfig:21: symbol C2 depends on C1
-For a resolution refer to Documentation/kbuild/kconfig-language.txt
+For a resolution refer to Documentation/kbuild/kconfig-language.rst
subsection "Kconfig recursive dependency limitations"
Kconfig:32:error: recursive dependency detected!
Kconfig:32: symbol D2 is selected by D1
Kconfig:27: symbol D1 depends on D2
-For a resolution refer to Documentation/kbuild/kconfig-language.txt
+For a resolution refer to Documentation/kbuild/kconfig-language.rst
subsection "Kconfig recursive dependency limitations"
Kconfig:37:error: recursive dependency detected!
Kconfig:37: symbol E1 depends on E2
Kconfig:42: symbol E2 is implied by E1
-For a resolution refer to Documentation/kbuild/kconfig-language.txt
+For a resolution refer to Documentation/kbuild/kconfig-language.rst
subsection "Kconfig recursive dependency limitations"
Kconfig:60:error: recursive dependency detected!
Kconfig:60: symbol G depends on G
-For a resolution refer to Documentation/kbuild/kconfig-language.txt
+For a resolution refer to Documentation/kbuild/kconfig-language.rst
subsection "Kconfig recursive dependency limitations"
Kconfig:51:error: recursive dependency detected!
Kconfig:51: symbol F2 depends on F1
Kconfig:49: symbol F1 default value contains F2
-For a resolution refer to Documentation/kbuild/kconfig-language.txt
+For a resolution refer to Documentation/kbuild/kconfig-language.rst
subsection "Kconfig recursive dependency limitations"
diff --git a/scripts/kconfig/tests/err_recursive_inc/Kconfig b/scripts/kconfig/tests/err_recursive_inc/Kconfig
index 0e4c875..c6f4ade 100644
--- a/scripts/kconfig/tests/err_recursive_inc/Kconfig
+++ b/scripts/kconfig/tests/err_recursive_inc/Kconfig
@@ -1 +1,2 @@
+# SPDX-License-Identifier: GPL-2.0-only
source "Kconfig.inc1"
diff --git a/scripts/kconfig/tests/err_recursive_inc/Kconfig.inc1 b/scripts/kconfig/tests/err_recursive_inc/Kconfig.inc1
index 00e408d..01cbf0d 100644
--- a/scripts/kconfig/tests/err_recursive_inc/Kconfig.inc1
+++ b/scripts/kconfig/tests/err_recursive_inc/Kconfig.inc1
@@ -1,3 +1,4 @@
+# SPDX-License-Identifier: GPL-2.0-only
diff --git a/scripts/kconfig/tests/err_recursive_inc/Kconfig.inc2 b/scripts/kconfig/tests/err_recursive_inc/Kconfig.inc2
index 349ea2d..8235107 100644
--- a/scripts/kconfig/tests/err_recursive_inc/Kconfig.inc2
+++ b/scripts/kconfig/tests/err_recursive_inc/Kconfig.inc2
@@ -1,3 +1,4 @@
+# SPDX-License-Identifier: GPL-2.0-only
source "Kconfig.inc3"
diff --git a/scripts/kconfig/tests/err_recursive_inc/Kconfig.inc3 b/scripts/kconfig/tests/err_recursive_inc/Kconfig.inc3
index 0e4c875..c6f4ade 100644
--- a/scripts/kconfig/tests/err_recursive_inc/Kconfig.inc3
+++ b/scripts/kconfig/tests/err_recursive_inc/Kconfig.inc3
@@ -1 +1,2 @@
+# SPDX-License-Identifier: GPL-2.0-only
source "Kconfig.inc1"
diff --git a/scripts/kconfig/tests/err_recursive_inc/__init__.py b/scripts/kconfig/tests/err_recursive_inc/__init__.py
index 0e4c839..27aa189 100644
--- a/scripts/kconfig/tests/err_recursive_inc/__init__.py
+++ b/scripts/kconfig/tests/err_recursive_inc/__init__.py
@@ -1,3 +1,4 @@
+# SPDX-License-Identifier: GPL-2.0
"""
Detect recursive inclusion error.
diff --git a/scripts/kconfig/tests/err_recursive_inc/expected_stderr b/scripts/kconfig/tests/err_recursive_inc/expected_stderr
index 6b582ee..b070a31 100644
--- a/scripts/kconfig/tests/err_recursive_inc/expected_stderr
+++ b/scripts/kconfig/tests/err_recursive_inc/expected_stderr
@@ -1,6 +1,6 @@
Recursive inclusion detected.
Inclusion path:
current file : Kconfig.inc1
- included from: Kconfig.inc3:1
- included from: Kconfig.inc2:3
- included from: Kconfig.inc1:4
+ included from: Kconfig.inc3:2
+ included from: Kconfig.inc2:4
+ included from: Kconfig.inc1:5
diff --git a/scripts/kconfig/tests/inter_choice/Kconfig b/scripts/kconfig/tests/inter_choice/Kconfig
index e44449f..5698a40 100644
--- a/scripts/kconfig/tests/inter_choice/Kconfig
+++ b/scripts/kconfig/tests/inter_choice/Kconfig
@@ -1,3 +1,5 @@
+# SPDX-License-Identifier: GPL-2.0
+
config MODULES
def_bool y
option modules
diff --git a/scripts/kconfig/tests/inter_choice/__init__.py b/scripts/kconfig/tests/inter_choice/__init__.py
index 5c7fc36..ffea6b1 100644
--- a/scripts/kconfig/tests/inter_choice/__init__.py
+++ b/scripts/kconfig/tests/inter_choice/__init__.py
@@ -1,3 +1,4 @@
+# SPDX-License-Identifier: GPL-2.0
"""
Do not affect user-assigned choice value by another choice.
diff --git a/scripts/kconfig/tests/new_choice_with_dep/Kconfig b/scripts/kconfig/tests/new_choice_with_dep/Kconfig
index 53ef1b8..127731c 100644
--- a/scripts/kconfig/tests/new_choice_with_dep/Kconfig
+++ b/scripts/kconfig/tests/new_choice_with_dep/Kconfig
@@ -1,3 +1,5 @@
+# SPDX-License-Identifier: GPL-2.0
+
config A
bool "A"
help
diff --git a/scripts/kconfig/tests/new_choice_with_dep/__init__.py b/scripts/kconfig/tests/new_choice_with_dep/__init__.py
index f0e0ead..fe9d322 100644
--- a/scripts/kconfig/tests/new_choice_with_dep/__init__.py
+++ b/scripts/kconfig/tests/new_choice_with_dep/__init__.py
@@ -1,3 +1,4 @@
+# SPDX-License-Identifier: GPL-2.0
"""
Ask new choice values when they become visible.
diff --git a/scripts/kconfig/tests/no_write_if_dep_unmet/Kconfig b/scripts/kconfig/tests/no_write_if_dep_unmet/Kconfig
index c00b8fe..4767aab 100644
--- a/scripts/kconfig/tests/no_write_if_dep_unmet/Kconfig
+++ b/scripts/kconfig/tests/no_write_if_dep_unmet/Kconfig
@@ -1,3 +1,5 @@
+# SPDX-License-Identifier: GPL-2.0
+
config A
bool "A"
diff --git a/scripts/kconfig/tests/no_write_if_dep_unmet/__init__.py b/scripts/kconfig/tests/no_write_if_dep_unmet/__init__.py
index 207261b..ffd469d 100644
--- a/scripts/kconfig/tests/no_write_if_dep_unmet/__init__.py
+++ b/scripts/kconfig/tests/no_write_if_dep_unmet/__init__.py
@@ -1,3 +1,4 @@
+# SPDX-License-Identifier: GPL-2.0
"""
Do not write choice values to .config if the dependency is unmet.
diff --git a/scripts/kconfig/tests/rand_nested_choice/Kconfig b/scripts/kconfig/tests/rand_nested_choice/Kconfig
index c591d51..8350de7 100644
--- a/scripts/kconfig/tests/rand_nested_choice/Kconfig
+++ b/scripts/kconfig/tests/rand_nested_choice/Kconfig
@@ -1,3 +1,5 @@
+# SPDX-License-Identifier: GPL-2.0
+
choice
prompt "choice"
diff --git a/scripts/kconfig/tests/rand_nested_choice/__init__.py b/scripts/kconfig/tests/rand_nested_choice/__init__.py
index e729a4e..9e4b2db 100644
--- a/scripts/kconfig/tests/rand_nested_choice/__init__.py
+++ b/scripts/kconfig/tests/rand_nested_choice/__init__.py
@@ -1,3 +1,4 @@
+# SPDX-License-Identifier: GPL-2.0
"""
Set random values recursively in nested choices.
diff --git a/scripts/kconfig/util.c b/scripts/kconfig/util.c
index d999683..2958539 100644
--- a/scripts/kconfig/util.c
+++ b/scripts/kconfig/util.c
@@ -1,8 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) 2002-2005 Roman Zippel <zippel@linux-m68k.org>
* Copyright (C) 2002-2005 Sam Ravnborg <sam@ravnborg.org>
- *
- * Released under the terms of the GNU GPL v2.0.
*/
#include <stdarg.h>
diff --git a/scripts/kernel-doc b/scripts/kernel-doc
index 8f0f508..81dc917 100755
--- a/scripts/kernel-doc
+++ b/scripts/kernel-doc
@@ -212,7 +212,7 @@
my $type_constant = '\b``([^\`]+)``\b';
my $type_constant2 = '\%([-_\w]+)';
my $type_func = '(\w+)\(\)';
-my $type_param = '\@(\w*(\.\w+)*(\.\.\.)?)';
+my $type_param = '\@(\w*((\.\w+)|(->\w+))*(\.\.\.)?)';
my $type_fp_param = '\@(\w+)\(\)'; # Special RST handling for func ptr params
my $type_env = '(\$\w+)';
my $type_enum = '\&(enum\s*([_\w]+))';
@@ -249,7 +249,7 @@
[$type_member_func, "\\:c\\:type\\:`\$1\$2\$3\\\\(\\\\) <\$1>`"],
[$type_member, "\\:c\\:type\\:`\$1\$2\$3 <\$1>`"],
[$type_fp_param, "**\$1\\\\(\\\\)**"],
- [$type_func, "\\:c\\:func\\:`\$1()`"],
+ [$type_func, "\$1()"],
[$type_enum, "\\:c\\:type\\:`\$1 <\$2>`"],
[$type_struct, "\\:c\\:type\\:`\$1 <\$2>`"],
[$type_typedef, "\\:c\\:type\\:`\$1 <\$2>`"],
@@ -285,7 +285,7 @@
OUTPUT_INTERNAL => 4, # output non-exported symbols
};
my $output_selection = OUTPUT_ALL;
-my $show_not_found = 0;
+my $show_not_found = 0; # No longer used
my @export_file_list;
@@ -361,7 +361,7 @@
my $doc_com_body = '\s*\* ?';
my $doc_decl = $doc_com . '(\w+)';
# @params and a strictly limited set of supported section names
-my $doc_sect = $doc_com .
+my $doc_sect = $doc_com .
'\s*(\@[.\w]+|\@\.\.\.|description|context|returns?|notes?|examples?)\s*:(.*)';
my $doc_content = $doc_com_body . '(.*)';
my $doc_block = $doc_com . 'DOC:\s*(.*)?';
@@ -435,7 +435,7 @@
} elsif ($cmd eq 'enable-lineno') {
$enable_lineno = 1;
} elsif ($cmd eq 'show-not-found') {
- $show_not_found = 1;
+ $show_not_found = 1; # A no-op but don't fail
} else {
# Unknown argument
usage();
@@ -751,7 +751,7 @@
#
# Apply the RST highlights to a sub-block of text.
-#
+#
sub highlight_block($) {
# The dohighlight kludge requires the text be called $contents
my $contents = shift;
@@ -1062,7 +1062,7 @@
my $x = shift;
my $file = shift;
- if ($x =~ /(struct|union)\s+(\w+)\s*\{(.*)\}/) {
+ if ($x =~ /(struct|union)\s+(\w+)\s*\{(.*)\}(\s*(__packed|__aligned|__attribute__\s*\(\([a-z0-9,_\s\(\)]*\)\)))*/) {
my $decl_type = $1;
$declaration_name = $2;
my $members = $3;
@@ -1073,8 +1073,9 @@
# strip comments:
$members =~ s/\/\*.*?\*\///gos;
# strip attributes
- $members =~ s/__attribute__\s*\(\([a-z,_\*\s\(\)]*\)\)//i;
- $members =~ s/__aligned\s*\([^;]*\)//gos;
+ $members =~ s/\s*__attribute__\s*\(\([a-z0-9,_\*\s\(\)]*\)\)//gi;
+ $members =~ s/\s*__aligned\s*\([^;]*\)//gos;
+ $members =~ s/\s*__packed\s*//gos;
$members =~ s/\s*CRYPTO_MINALIGN_ATTR//gos;
# replace DECLARE_BITMAP
$members =~ s/DECLARE_BITMAP\s*\(([^,)]+),\s*([^,)]+)\)/unsigned long $1\[BITS_TO_LONGS($2)\]/gos;
@@ -1244,7 +1245,7 @@
# strip #define macros inside enums
$x =~ s@#\s*((define|ifdef)\s+|endif)[^;]*;@@gos;
- if ($x =~ /enum\s+(\w+)\s*\{(.*)\}/) {
+ if ($x =~ /enum\s+(\w*)\s*\{(.*)\}/) {
$declaration_name = $1;
my $members = $2;
my %_members;
@@ -1473,7 +1474,7 @@
if (!defined $parameterdescs{$param} && $param !~ /^#/) {
$parameterdescs{$param} = $undescribed;
- if (show_warnings($type, $declaration_name)) {
+ if (show_warnings($type, $declaration_name) && $param !~ /\./) {
print STDERR
"${file}:$.: warning: Function parameter or member '$param' not described in '$declaration_name'\n";
++$warnings;
@@ -1579,6 +1580,7 @@
$prototype =~ s/__must_check +//;
$prototype =~ s/__weak +//;
$prototype =~ s/__sched +//;
+ $prototype =~ s/__printf\s*\(\s*\d*\s*,\s*\d*\s*\) +//;
my $define = $prototype =~ s/^#\s*define\s+//; #ak added
$prototype =~ s/__attribute__\s*\(\(
(?:
@@ -1904,13 +1906,13 @@
++$warnings;
}
- if ($identifier =~ m/^struct/) {
+ if ($identifier =~ m/^struct\b/) {
$decl_type = 'struct';
- } elsif ($identifier =~ m/^union/) {
+ } elsif ($identifier =~ m/^union\b/) {
$decl_type = 'union';
- } elsif ($identifier =~ m/^enum/) {
+ } elsif ($identifier =~ m/^enum\b/) {
$decl_type = 'enum';
- } elsif ($identifier =~ m/^typedef/) {
+ } elsif ($identifier =~ m/^typedef\b/) {
$decl_type = 'typedef';
} else {
$decl_type = 'function';
@@ -2162,12 +2164,14 @@
}
# Make sure we got something interesting.
- if ($initial_section_counter == $section_counter) {
- if ($output_mode ne "none") {
- print STDERR "${file}:1: warning: no structured comments found\n";
+ if ($initial_section_counter == $section_counter && $
+ output_mode ne "none") {
+ if ($output_selection == OUTPUT_INCLUDE) {
+ print STDERR "${file}:1: warning: '$_' not found\n"
+ for keys %function_table;
}
- if (($output_selection == OUTPUT_INCLUDE) && ($show_not_found == 1)) {
- print STDERR " Was looking for '$_'.\n" for keys %function_table;
+ else {
+ print STDERR "${file}:1: warning: no structured comments found\n";
}
}
}
diff --git a/scripts/leaking_addresses.pl b/scripts/leaking_addresses.pl
index 6a89778..b2d8b8a 100755
--- a/scripts/leaking_addresses.pl
+++ b/scripts/leaking_addresses.pl
@@ -1,7 +1,7 @@
#!/usr/bin/env perl
+# SPDX-License-Identifier: GPL-2.0-only
#
# (c) 2017 Tobin C. Harding <me@tobin.cc>
-# Licensed under the terms of the GNU GPL License version 2
#
# leaking_addresses.pl: Scan the kernel for potential leaking addresses.
# - Scans dmesg output.
@@ -97,7 +97,7 @@
--32-bit Scan 32-bit kernel.
--page-offset-32-bit=o Page offset (for 32-bit kernel 0xABCD1234).
-d, --debug Display debugging output.
- -h, --help, --version Display this help and exit.
+ -h, --help Display this help and exit.
Scans the running kernel for potential leaking addresses.
@@ -108,7 +108,6 @@
GetOptions(
'd|debug' => \$debug,
'h|help' => \$help,
- 'version' => \$help,
'o|output-raw=s' => \$output_raw,
'i|input-raw=s' => \$input_raw,
'suppress-dmesg' => \$suppress_dmesg,
@@ -231,7 +230,7 @@
my $tmp_file = "/tmp/tmpkconf";
if (system("gunzip < /proc/config.gz > $tmp_file")) {
- dprint "$0: system(gunzip < /proc/config.gz) failed\n";
+ dprint("system(gunzip < /proc/config.gz) failed\n");
return "";
} else {
@config_files = ($tmp_file);
@@ -243,7 +242,7 @@
}
foreach my $file (@config_files) {
- dprint("parsing config file: %s\n", $file);
+ dprint("parsing config file: $file\n");
$value = option_from_file($option, $file);
if ($value ne "") {
last;
@@ -502,7 +501,7 @@
next;
}
- dprint "parsing: $path\n";
+ dprint("parsing: $path\n");
timed_parse_file($path);
}
}
diff --git a/scripts/link-vmlinux.sh b/scripts/link-vmlinux.sh
index c8cf453..0649537 100755
--- a/scripts/link-vmlinux.sh
+++ b/scripts/link-vmlinux.sh
@@ -3,22 +3,17 @@
#
# link vmlinux
#
-# vmlinux is linked from the objects selected by $(KBUILD_VMLINUX_INIT) and
-# $(KBUILD_VMLINUX_MAIN) and $(KBUILD_VMLINUX_LIBS). Most are built-in.a files
-# from top-level directories in the kernel tree, others are specified in
-# arch/$(ARCH)/Makefile. Ordering when linking is important, and
-# $(KBUILD_VMLINUX_INIT) must be first. $(KBUILD_VMLINUX_LIBS) are archives
-# which are linked conditionally (not within --whole-archive), and do not
-# require symbol indexes added.
+# vmlinux is linked from the objects selected by $(KBUILD_VMLINUX_OBJS) and
+# $(KBUILD_VMLINUX_LIBS). Most are built-in.a files from top-level directories
+# in the kernel tree, others are specified in arch/$(ARCH)/Makefile.
+# $(KBUILD_VMLINUX_LIBS) are archives which are linked conditionally
+# (not within --whole-archive), and do not require symbol indexes added.
#
# vmlinux
# ^
# |
-# +-< $(KBUILD_VMLINUX_INIT)
-# | +--< init/version.o + more
-# |
-# +--< $(KBUILD_VMLINUX_MAIN)
-# | +--< drivers/built-in.a mm/built-in.a + more
+# +--< $(KBUILD_VMLINUX_OBJS)
+# | +--< init/built-in.a drivers/built-in.a mm/built-in.a + more
# |
# +--< $(KBUILD_VMLINUX_LIBS)
# | +--< lib/lib.a + more
@@ -40,28 +35,10 @@
info()
{
if [ "${quiet}" != "silent_" ]; then
- printf " %-7s %s\n" ${1} ${2}
+ printf " %-7s %s\n" "${1}" "${2}"
fi
}
-# Thin archive build here makes a final archive with symbol table and indexes
-# from vmlinux objects INIT and MAIN, which can be used as input to linker.
-# KBUILD_VMLINUX_LIBS archives should already have symbol table and indexes
-# added.
-#
-# Traditional incremental style of link does not require this step
-#
-# built-in.a output file
-#
-archive_builtin()
-{
- info AR built-in.a
- rm -f built-in.a;
- ${AR} rcsTP${KBUILD_ARFLAGS} built-in.a \
- ${KBUILD_VMLINUX_INIT} \
- ${KBUILD_VMLINUX_MAIN}
-}
-
# Link of vmlinux.o used for section mismatch analysis
# ${1} output file
modpost_link()
@@ -69,7 +46,7 @@
local objects
objects="--whole-archive \
- built-in.a \
+ ${KBUILD_VMLINUX_OBJS} \
--no-whole-archive \
--start-group \
${KBUILD_VMLINUX_LIBS} \
@@ -79,34 +56,42 @@
}
# Link of vmlinux
-# ${1} - optional extra .o files
-# ${2} - output file
+# ${1} - output file
+# ${2}, ${3}, ... - optional extra .o files
vmlinux_link()
{
local lds="${objtree}/${KBUILD_LDS}"
+ local output=${1}
local objects
+ info LD ${output}
+
+ # skip output file argument
+ shift
+
if [ "${SRCARCH}" != "um" ]; then
objects="--whole-archive \
- built-in.a \
+ ${KBUILD_VMLINUX_OBJS} \
--no-whole-archive \
--start-group \
${KBUILD_VMLINUX_LIBS} \
--end-group \
- ${1}"
+ ${@}"
- ${LD} ${KBUILD_LDFLAGS} ${LDFLAGS_vmlinux} -o ${2} \
+ ${LD} ${KBUILD_LDFLAGS} ${LDFLAGS_vmlinux} \
+ -o ${output} \
-T ${lds} ${objects}
else
objects="-Wl,--whole-archive \
- built-in.a \
+ ${KBUILD_VMLINUX_OBJS} \
-Wl,--no-whole-archive \
-Wl,--start-group \
${KBUILD_VMLINUX_LIBS} \
-Wl,--end-group \
- ${1}"
+ ${@}"
- ${CC} ${CFLAGS_vmlinux} -o ${2} \
+ ${CC} ${CFLAGS_vmlinux} \
+ -o ${output} \
-Wl,-T,${lds} \
${objects} \
-lutil -lrt -lpthread
@@ -114,6 +99,38 @@
fi
}
+# generate .BTF typeinfo from DWARF debuginfo
+# ${1} - vmlinux image
+# ${2} - file to dump raw BTF data into
+gen_btf()
+{
+ local pahole_ver
+ local bin_arch
+
+ if ! [ -x "$(command -v ${PAHOLE})" ]; then
+ info "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"
+ return 1
+ fi
+
+ info "BTF" ${2}
+ vmlinux_link ${1}
+ LLVM_OBJCOPY=${OBJCOPY} ${PAHOLE} -J ${1}
+
+ # dump .BTF section into raw binary file to link with final vmlinux
+ bin_arch=$(LANG=C ${OBJDUMP} -f ${1} | grep architecture | \
+ cut -d, -f1 | cut -d' ' -f2)
+ bin_format=$(LANG=C ${OBJDUMP} -f ${1} | grep 'file format' | \
+ awk '{print $4}')
+ ${OBJCOPY} --dump-section .BTF=.btf.vmlinux.bin ${1} 2>/dev/null
+ ${OBJCOPY} -I binary -O ${bin_format} -B ${bin_arch} \
+ --rename-section .data=.BTF .btf.vmlinux.bin ${2}
+}
# Create ${2} .o file with all symbols from the ${1} object file
kallsyms()
@@ -142,6 +159,18 @@
${CC} ${aflags} -c -o ${2} ${afile}
}
+# Perform one step in kallsyms generation, including temporary linking of
+# vmlinux.
+kallsyms_step()
+{
+ kallsymso_prev=${kallsymso}
+ kallsymso=.tmp_kallsyms${1}.o
+ kallsyms_vmlinux=.tmp_vmlinux${1}
+
+ vmlinux_link ${kallsyms_vmlinux} "${kallsymso_prev}" ${btf_vmlinux_bin_o}
+ kallsyms ${kallsyms_vmlinux} ${kallsymso}
+}
+
# Create map file with all symbols from ${1}
# See mksymap for additional details
mksysmap()
@@ -157,10 +186,10 @@
# Delete output files in case of error
cleanup()
{
+ rm -f .btf.*
rm -f .tmp_System.map
rm -f .tmp_kallsyms*
rm -f .tmp_vmlinux*
- rm -f built-in.a
rm -f System.map
rm -f vmlinux
rm -f vmlinux.o
@@ -195,14 +224,7 @@
fi
# We need access to CONFIG_ symbols
-case "${KCONFIG_CONFIG}" in
-*/*)
- . "${KCONFIG_CONFIG}"
- ;;
-*)
- # Force using a file from the current directory
- . "./${KCONFIG_CONFIG}"
-esac
+. include/config/auto.conf
# Update version
info GEN .version
@@ -217,16 +239,25 @@
# final build of init/
${MAKE} -f "${srctree}/scripts/Makefile.build" obj=init
-archive_builtin
-
#link vmlinux.o
info LD vmlinux.o
modpost_link vmlinux.o
# modpost vmlinux.o to check for section mismatches
-${MAKE} -f "${srctree}/scripts/Makefile.modpost" vmlinux.o
+${MAKE} -f "${srctree}/scripts/Makefile.modpost" MODPOST_VMLINUX=1
+
+info MODINFO modules.builtin.modinfo
+${OBJCOPY} -j .modinfo -O binary vmlinux.o modules.builtin.modinfo
+
+btf_vmlinux_bin_o=""
+if [ -n "${CONFIG_DEBUG_INFO_BTF}" ]; then
+ if gen_btf .tmp_vmlinux.btf .btf.vmlinux.bin.o ; then
+ btf_vmlinux_bin_o=.btf.vmlinux.bin.o
+ fi
+fi
kallsymso=""
+kallsymso_prev=""
kallsyms_vmlinux=""
if [ -n "${CONFIG_KALLSYMS}" ]; then
@@ -253,33 +284,19 @@
# a) Verify that the System.map from vmlinux matches the map from
# ${kallsymso}.
- kallsymso=.tmp_kallsyms2.o
- kallsyms_vmlinux=.tmp_vmlinux2
-
- # step 1
- vmlinux_link "" .tmp_vmlinux1
- kallsyms .tmp_vmlinux1 .tmp_kallsyms1.o
-
- # step 2
- vmlinux_link .tmp_kallsyms1.o .tmp_vmlinux2
- kallsyms .tmp_vmlinux2 .tmp_kallsyms2.o
+ kallsyms_step 1
+ kallsyms_step 2
# step 3
- size1=$(${CONFIG_SHELL} "${srctree}/scripts/file-size.sh" .tmp_kallsyms1.o)
- size2=$(${CONFIG_SHELL} "${srctree}/scripts/file-size.sh" .tmp_kallsyms2.o)
+ size1=$(${CONFIG_SHELL} "${srctree}/scripts/file-size.sh" ${kallsymso_prev})
+ size2=$(${CONFIG_SHELL} "${srctree}/scripts/file-size.sh" ${kallsymso})
if [ $size1 -ne $size2 ] || [ -n "${KALLSYMS_EXTRA_PASS}" ]; then
- kallsymso=.tmp_kallsyms3.o
- kallsyms_vmlinux=.tmp_vmlinux3
-
- vmlinux_link .tmp_kallsyms2.o .tmp_vmlinux3
-
- kallsyms .tmp_vmlinux3 .tmp_kallsyms3.o
+ kallsyms_step 3
fi
fi
-info LD vmlinux
-vmlinux_link "${kallsymso}" vmlinux
+vmlinux_link vmlinux "${kallsymso}" ${btf_vmlinux_bin_o}
if [ -n "${CONFIG_BUILDTIME_EXTABLE_SORT}" ]; then
info SORTEX vmlinux
diff --git a/scripts/markup_oops.pl b/scripts/markup_oops.pl
index 70dcfb6..e476caf 100755
--- a/scripts/markup_oops.pl
+++ b/scripts/markup_oops.pl
@@ -1,4 +1,5 @@
#!/usr/bin/env perl
+# SPDX-License-Identifier: GPL-2.0-only
use File::Basename;
use Math::BigInt;
@@ -8,10 +9,6 @@
#
# This file is part of the Linux kernel
#
-# This program file is free software; you can redistribute it and/or modify it
-# under the terms of the GNU General Public License as published by the
-# Free Software Foundation; version 2 of the License.
-#
# Authors:
# Arjan van de Ven <arjan@linux.intel.com>
diff --git a/scripts/mkcompile_h b/scripts/mkcompile_h
index 87f1fc9..d1d757c 100755
--- a/scripts/mkcompile_h
+++ b/scripts/mkcompile_h
@@ -5,7 +5,8 @@
ARCH=$2
SMP=$3
PREEMPT=$4
-CC=$5
+PREEMPT_RT=$5
+CC=$6
vecho() { [ "${quiet}" = "silent_" ] || echo "$@" ; }
@@ -53,6 +54,7 @@
CONFIG_FLAGS=""
if [ -n "$SMP" ] ; then CONFIG_FLAGS="SMP"; fi
if [ -n "$PREEMPT" ] ; then CONFIG_FLAGS="$CONFIG_FLAGS PREEMPT"; fi
+if [ -n "$PREEMPT_RT" ] ; then CONFIG_FLAGS="$CONFIG_FLAGS PREEMPT_RT"; fi
UTS_VERSION="$UTS_VERSION $CONFIG_FLAGS $TIMESTAMP"
# Truncate to maximum length
@@ -62,7 +64,7 @@
# Generate a temporary compile.h
-( echo /\* This file is auto generated, version $VERSION \*/
+{ echo /\* This file is auto generated, version $VERSION \*/
if [ -n "$CONFIG_FLAGS" ] ; then echo "/* $CONFIG_FLAGS */"; fi
echo \#define UTS_MACHINE \"$ARCH\"
@@ -73,7 +75,7 @@
echo \#define LINUX_COMPILE_HOST \"`echo $LINUX_COMPILE_HOST | $UTS_TRUNCATE`\"
echo \#define LINUX_COMPILER \"`$CC -v 2>&1 | grep ' version ' | sed 's/[[:space:]]*$//'`\"
-) > .tmpcompile
+} > .tmpcompile
# Only replace the real compile.h if the new one is different,
# in order to preserve the timestamp and avoid unnecessary
diff --git a/scripts/mkmakefile b/scripts/mkmakefile
index e19d656..1cb1747 100755
--- a/scripts/mkmakefile
+++ b/scripts/mkmakefile
@@ -6,48 +6,12 @@
# Usage
# $1 - Kernel src directory
-# $2 - Output directory
-# $3 - version
-# $4 - patchlevel
-
-test ! -r $2/Makefile -o -O $2/Makefile || exit 0
-# Only overwrite automatically generated Makefiles
-# (so we do not overwrite kernel Makefile)
-if test -e $2/Makefile && ! grep -q Automatically $2/Makefile
-then
- exit 0
-fi
if [ "${quiet}" != "silent_" ]; then
- echo " GEN $2/Makefile"
+ echo " GEN Makefile"
fi
-cat << EOF > $2/Makefile
+cat << EOF > Makefile
# Automatically generated by $0: don't edit
-
-VERSION = $3
-PATCHLEVEL = $4
-
-lastword = \$(word \$(words \$(1)),\$(1))
-makedir := \$(dir \$(call lastword,\$(MAKEFILE_LIST)))
-
-ifeq ("\$(origin V)", "command line")
-VERBOSE := \$(V)
-endif
-ifneq (\$(VERBOSE),1)
-Q := @
-endif
-
-MAKEARGS := -C $1
-MAKEARGS += O=\$(if \$(patsubst /%,,\$(makedir)),\$(CURDIR)/)\$(patsubst %/,%,\$(makedir))
-
-MAKEFLAGS += --no-print-directory
-
-.PHONY: __sub-make \$(MAKECMDGOALS)
-
-__sub-make:
- \$(Q)\$(MAKE) \$(MAKEARGS) \$(MAKECMDGOALS)
-
-\$(filter-out __sub-make, \$(MAKECMDGOALS)): __sub-make
- @:
+include $1/Makefile
EOF
diff --git a/scripts/mod/devicetable-offsets.c b/scripts/mod/devicetable-offsets.c
index 2930044..054405b 100644
--- a/scripts/mod/devicetable-offsets.c
+++ b/scripts/mod/devicetable-offsets.c
@@ -225,5 +225,11 @@
DEVID_FIELD(typec_device_id, svid);
DEVID_FIELD(typec_device_id, mode);
+ DEVID(tee_client_device_id);
+ DEVID_FIELD(tee_client_device_id, uuid);
+
+ DEVID(wmi_device_id);
+ DEVID_FIELD(wmi_device_id, guid_string);
+
return 0;
}
diff --git a/scripts/mod/file2alias.c b/scripts/mod/file2alias.c
index 7be4369..c91eba7 100644
--- a/scripts/mod/file2alias.c
+++ b/scripts/mod/file2alias.c
@@ -36,7 +36,16 @@
typedef unsigned char __u8;
typedef struct {
__u8 b[16];
+} guid_t;
+
+/* backwards compatibility, don't use in new code */
+typedef struct {
+ __u8 b[16];
} uuid_le;
+typedef struct {
+ __u8 b[16];
+} uuid_t;
+#define UUID_STRING_LEN 36
/* Big exception to the "don't include kernel headers into userspace, which
* even potentially has different endianness and word sizes, since
@@ -47,70 +56,31 @@
struct devtable {
const char *device_id; /* name of table, __mod_<name>__*_device_table. */
unsigned long id_size;
- void *function;
+ int (*do_entry)(const char *filename, void *symval, char *alias);
};
-#define ___cat(a,b) a ## b
-#define __cat(a,b) ___cat(a,b)
-
-/* we need some special handling for this host tool running eventually on
- * Darwin. The Mach-O section handling is a bit different than ELF section
- * handling. The differnces in detail are:
- * a) we have segments which have sections
- * b) we need a API call to get the respective section symbols */
-#if defined(__MACH__)
-#include <mach-o/getsect.h>
-
-#define INIT_SECTION(name) do { \
- unsigned long name ## _len; \
- char *__cat(pstart_,name) = getsectdata("__TEXT", \
- #name, &__cat(name,_len)); \
- char *__cat(pstop_,name) = __cat(pstart_,name) + \
- __cat(name, _len); \
- __cat(__start_,name) = (void *)__cat(pstart_,name); \
- __cat(__stop_,name) = (void *)__cat(pstop_,name); \
- } while (0)
-#define SECTION(name) __attribute__((section("__TEXT, " #name)))
-
-struct devtable **__start___devtable, **__stop___devtable;
-#else
-#define INIT_SECTION(name) /* no-op for ELF */
-#define SECTION(name) __attribute__((section(#name)))
-
-/* We construct a table of pointers in an ELF section (pointers generally
- * go unpadded by gcc). ld creates boundary syms for us. */
-extern struct devtable *__start___devtable[], *__stop___devtable[];
-#endif /* __MACH__ */
-
-#if !defined(__used)
-# if __GNUC__ == 3 && __GNUC_MINOR__ < 3
-# define __used __attribute__((__unused__))
-# else
-# define __used __attribute__((__used__))
-# endif
-#endif
+/* Size of alias provided to do_entry functions */
+#define ALIAS_SIZE 500
/* Define a variable f that holds the value of field f of struct devid
* based at address m.
*/
#define DEF_FIELD(m, devid, f) \
typeof(((struct devid *)0)->f) f = TO_NATIVE(*(typeof(f) *)((m) + OFF_##devid##_##f))
+
+/* Define a variable v that holds the address of field f of struct devid
+ * based at address m. Due to the way typeof works, for a field of type
+ * T[N] the variable has type T(*)[N], _not_ T*.
+ */
+#define DEF_FIELD_ADDR_VAR(m, devid, f, v) \
+ typeof(((struct devid *)0)->f) *v = ((m) + OFF_##devid##_##f)
+
/* Define a variable f that holds the address of field f of struct devid
* based at address m. Due to the way typeof works, for a field of type
* T[N] the variable has type T(*)[N], _not_ T*.
*/
#define DEF_FIELD_ADDR(m, devid, f) \
- typeof(((struct devid *)0)->f) *f = ((m) + OFF_##devid##_##f)
-
-/* Add a table entry. We test function type matches while we're here. */
-#define ADD_TO_DEVTABLE(device_id, type, function) \
- static struct devtable __cat(devtable,__LINE__) = { \
- device_id + 0*sizeof((function)((const char *)NULL, \
- (void *)NULL, \
- (char *)NULL)), \
- SIZE_##type, (function) }; \
- static struct devtable *SECTION(__devtable) __used \
- __cat(devtable_ptr,__LINE__) = &__cat(devtable,__LINE__)
+ DEF_FIELD_ADDR_VAR(m, devid, f, f)
#define ADD(str, sep, cond, field) \
do { \
@@ -431,7 +401,6 @@
return 1;
}
-ADD_TO_DEVTABLE("hid", hid_device_id, do_hid_entry);
/* Looks like: ieee1394:venNmoNspNverN */
static int do_ieee1394_entry(const char *filename,
@@ -456,7 +425,6 @@
add_wildcard(alias);
return 1;
}
-ADD_TO_DEVTABLE("ieee1394", ieee1394_device_id, do_ieee1394_entry);
/* Looks like: pci:vNdNsvNsdNbcNscNiN. */
static int do_pci_entry(const char *filename,
@@ -500,7 +468,6 @@
add_wildcard(alias);
return 1;
}
-ADD_TO_DEVTABLE("pci", pci_device_id, do_pci_entry);
/* looks like: "ccw:tNmNdtNdmN" */
static int do_ccw_entry(const char *filename,
@@ -524,7 +491,6 @@
add_wildcard(alias);
return 1;
}
-ADD_TO_DEVTABLE("ccw", ccw_device_id, do_ccw_entry);
/* looks like: "ap:tN" */
static int do_ap_entry(const char *filename,
@@ -535,7 +501,6 @@
sprintf(alias, "ap:t%02X*", dev_type);
return 1;
}
-ADD_TO_DEVTABLE("ap", ap_device_id, do_ap_entry);
/* looks like: "css:tN" */
static int do_css_entry(const char *filename,
@@ -546,7 +511,6 @@
sprintf(alias, "css:t%01X", type);
return 1;
}
-ADD_TO_DEVTABLE("css", css_device_id, do_css_entry);
/* Looks like: "serio:tyNprNidNexN" */
static int do_serio_entry(const char *filename,
@@ -566,7 +530,6 @@
add_wildcard(alias);
return 1;
}
-ADD_TO_DEVTABLE("serio", serio_device_id, do_serio_entry);
/* looks like: "acpi:ACPI0003" or "acpi:PNP0C0B" or "acpi:LNXVIDEO" or
* "acpi:bbsspp" (bb=base-class, ss=sub-class, pp=prog-if)
@@ -604,7 +567,6 @@
}
return 1;
}
-ADD_TO_DEVTABLE("acpi", acpi_device_id, do_acpi_entry);
/* looks like: "pnp:dD" */
static void do_pnp_device_entry(void *symval, unsigned long size,
@@ -644,7 +606,7 @@
for (i = 0; i < count; i++) {
unsigned int j;
- DEF_FIELD_ADDR(symval + i*id_size, pnp_card_device_id, devs);
+ DEF_FIELD_ADDR(symval + i * id_size, pnp_card_device_id, devs);
for (j = 0; j < PNP_MAX_DEVICES; j++) {
const char *id = (char *)(*devs)[j].id;
@@ -656,10 +618,13 @@
/* find duplicate, already added value */
for (i2 = 0; i2 < i && !dup; i2++) {
- DEF_FIELD_ADDR(symval + i2*id_size, pnp_card_device_id, devs);
+ DEF_FIELD_ADDR_VAR(symval + i2 * id_size,
+ pnp_card_device_id,
+ devs, devs_dup);
for (j2 = 0; j2 < PNP_MAX_DEVICES; j2++) {
- const char *id2 = (char *)(*devs)[j2].id;
+ const char *id2 =
+ (char *)(*devs_dup)[j2].id;
if (!id2[0])
break;
@@ -725,7 +690,6 @@
add_wildcard(alias);
return 1;
}
-ADD_TO_DEVTABLE("pcmcia", pcmcia_device_id, do_pcmcia_entry);
static int do_vio_entry(const char *filename, void *symval,
char *alias)
@@ -745,7 +709,6 @@
add_wildcard(alias);
return 1;
}
-ADD_TO_DEVTABLE("vio", vio_device_id, do_vio_entry);
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
@@ -818,7 +781,6 @@
do_input(alias, *swbit, 0, INPUT_DEVICE_ID_SW_MAX);
return 1;
}
-ADD_TO_DEVTABLE("input", input_device_id, do_input_entry);
static int do_eisa_entry(const char *filename, void *symval,
char *alias)
@@ -830,7 +792,6 @@
strcat(alias, "*");
return 1;
}
-ADD_TO_DEVTABLE("eisa", eisa_device_id, do_eisa_entry);
/* Looks like: parisc:tNhvNrevNsvN */
static int do_parisc_entry(const char *filename, void *symval,
@@ -850,7 +811,6 @@
add_wildcard(alias);
return 1;
}
-ADD_TO_DEVTABLE("parisc", parisc_device_id, do_parisc_entry);
/* Looks like: sdio:cNvNdN. */
static int do_sdio_entry(const char *filename,
@@ -867,7 +827,6 @@
add_wildcard(alias);
return 1;
}
-ADD_TO_DEVTABLE("sdio", sdio_device_id, do_sdio_entry);
/* Looks like: ssb:vNidNrevN. */
static int do_ssb_entry(const char *filename,
@@ -884,7 +843,6 @@
add_wildcard(alias);
return 1;
}
-ADD_TO_DEVTABLE("ssb", ssb_device_id, do_ssb_entry);
/* Looks like: bcma:mNidNrevNclN. */
static int do_bcma_entry(const char *filename,
@@ -903,7 +861,6 @@
add_wildcard(alias);
return 1;
}
-ADD_TO_DEVTABLE("bcma", bcma_device_id, do_bcma_entry);
/* Looks like: virtio:dNvN */
static int do_virtio_entry(const char *filename, void *symval,
@@ -919,7 +876,6 @@
add_wildcard(alias);
return 1;
}
-ADD_TO_DEVTABLE("virtio", virtio_device_id, do_virtio_entry);
/*
* Looks like: vmbus:guid
@@ -942,7 +898,6 @@
return 1;
}
-ADD_TO_DEVTABLE("vmbus", hv_vmbus_device_id, do_vmbus_entry);
/* Looks like: rpmsg:S */
static int do_rpmsg_entry(const char *filename, void *symval,
@@ -953,7 +908,6 @@
return 1;
}
-ADD_TO_DEVTABLE("rpmsg", rpmsg_device_id, do_rpmsg_entry);
/* Looks like: i2c:S */
static int do_i2c_entry(const char *filename, void *symval,
@@ -964,7 +918,6 @@
return 1;
}
-ADD_TO_DEVTABLE("i2c", i2c_device_id, do_i2c_entry);
/* Looks like: spi:S */
static int do_spi_entry(const char *filename, void *symval,
@@ -975,7 +928,6 @@
return 1;
}
-ADD_TO_DEVTABLE("spi", spi_device_id, do_spi_entry);
static const struct dmifield {
const char *prefix;
@@ -1030,7 +982,6 @@
strcat(alias, ":");
return 1;
}
-ADD_TO_DEVTABLE("dmi", dmi_system_id, do_dmi_entry);
static int do_platform_entry(const char *filename,
void *symval, char *alias)
@@ -1039,7 +990,6 @@
sprintf(alias, PLATFORM_MODULE_PREFIX "%s", *name);
return 1;
}
-ADD_TO_DEVTABLE("platform", platform_device_id, do_platform_entry);
static int do_mdio_entry(const char *filename,
void *symval, char *alias)
@@ -1064,7 +1014,6 @@
return 1;
}
-ADD_TO_DEVTABLE("mdio", mdio_device_id, do_mdio_entry);
/* Looks like: zorro:iN. */
static int do_zorro_entry(const char *filename, void *symval,
@@ -1075,7 +1024,6 @@
ADD(alias, "i", id != ZORRO_WILDCARD, id);
return 1;
}
-ADD_TO_DEVTABLE("zorro", zorro_device_id, do_zorro_entry);
/* looks like: "pnp:dD" */
static int do_isapnp_entry(const char *filename,
@@ -1091,7 +1039,6 @@
(function >> 12) & 0x0f, (function >> 8) & 0x0f);
return 1;
}
-ADD_TO_DEVTABLE("isapnp", isapnp_device_id, do_isapnp_entry);
/* Looks like: "ipack:fNvNdN". */
static int do_ipack_entry(const char *filename,
@@ -1107,7 +1054,6 @@
add_wildcard(alias);
return 1;
}
-ADD_TO_DEVTABLE("ipack", ipack_device_id, do_ipack_entry);
/*
* Append a match expression for a single masked hex digit.
@@ -1178,7 +1124,6 @@
return 1;
}
-ADD_TO_DEVTABLE("amba", amba_id, do_amba_entry);
/*
* looks like: "mipscdmm:tN"
@@ -1194,7 +1139,6 @@
sprintf(alias, "mipscdmm:t%02X*", type);
return 1;
}
-ADD_TO_DEVTABLE("mipscdmm", mips_cdmm_device_id, do_mips_cdmm_entry);
/* LOOKS like cpu:type:x86,venVVVVfamFFFFmodMMMM:feature:*,FEAT,*
* All fields are numbers. It would be nicer to use strings for vendor
@@ -1219,7 +1163,6 @@
sprintf(alias + strlen(alias), "%04X*", feature);
return 1;
}
-ADD_TO_DEVTABLE("x86cpu", x86_cpu_id, do_x86cpu_entry);
/* LOOKS like cpu:type:*:feature:*FEAT* */
static int do_cpu_entry(const char *filename, void *symval, char *alias)
@@ -1229,7 +1172,6 @@
sprintf(alias, "cpu:type:*:feature:*%04X*", feature);
return 1;
}
-ADD_TO_DEVTABLE("cpu", cpu_feature, do_cpu_entry);
/* Looks like: mei:S:uuid:N:* */
static int do_mei_entry(const char *filename, void *symval,
@@ -1248,7 +1190,6 @@
return 1;
}
-ADD_TO_DEVTABLE("mei", mei_cl_device_id, do_mei_entry);
/* Looks like: rapidio:vNdNavNadN */
static int do_rio_entry(const char *filename,
@@ -1268,7 +1209,6 @@
add_wildcard(alias);
return 1;
}
-ADD_TO_DEVTABLE("rapidio", rio_device_id, do_rio_entry);
/* Looks like: ulpi:vNpN */
static int do_ulpi_entry(const char *filename, void *symval,
@@ -1281,7 +1221,6 @@
return 1;
}
-ADD_TO_DEVTABLE("ulpi", ulpi_device_id, do_ulpi_entry);
/* Looks like: hdaudio:vNrNaN */
static int do_hda_entry(const char *filename, void *symval, char *alias)
@@ -1298,7 +1237,6 @@
add_wildcard(alias);
return 1;
}
-ADD_TO_DEVTABLE("hdaudio", hda_device_id, do_hda_entry);
/* Looks like: sdw:mNpN */
static int do_sdw_entry(const char *filename, void *symval, char *alias)
@@ -1313,7 +1251,6 @@
add_wildcard(alias);
return 1;
}
-ADD_TO_DEVTABLE("sdw", sdw_device_id, do_sdw_entry);
/* Looks like: fsl-mc:vNdN */
static int do_fsl_mc_entry(const char *filename, void *symval,
@@ -1325,7 +1262,6 @@
sprintf(alias, "fsl-mc:v%08Xd%s", vendor, *obj_type);
return 1;
}
-ADD_TO_DEVTABLE("fslmc", fsl_mc_device_id, do_fsl_mc_entry);
/* Looks like: tbsvc:kSpNvNrN */
static int do_tbsvc_entry(const char *filename, void *symval, char *alias)
@@ -1350,7 +1286,6 @@
add_wildcard(alias);
return 1;
}
-ADD_TO_DEVTABLE("tbsvc", tb_service_id, do_tbsvc_entry);
/* Looks like: typec:idNmN */
static int do_typec_entry(const char *filename, void *symval, char *alias)
@@ -1363,7 +1298,42 @@
return 1;
}
-ADD_TO_DEVTABLE("typec", typec_device_id, do_typec_entry);
+
+/* Looks like: tee:uuid */
+static int do_tee_entry(const char *filename, void *symval, char *alias)
+{
+ DEF_FIELD(symval, tee_client_device_id, uuid);
+
+ sprintf(alias, "tee:%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
+ uuid.b[0], uuid.b[1], uuid.b[2], uuid.b[3], uuid.b[4],
+ uuid.b[5], uuid.b[6], uuid.b[7], uuid.b[8], uuid.b[9],
+ uuid.b[10], uuid.b[11], uuid.b[12], uuid.b[13], uuid.b[14],
+ uuid.b[15]);
+
+ add_wildcard(alias);
+ return 1;
+}
+
+/* Looks like: wmi:guid */
+static int do_wmi_entry(const char *filename, void *symval, char *alias)
+{
+ int len;
+ DEF_FIELD_ADDR(symval, wmi_device_id, guid_string);
+
+ if (strlen(*guid_string) != UUID_STRING_LEN) {
+ warn("Invalid WMI device id 'wmi:%s' in '%s'\n",
+ *guid_string, filename);
+ return 0;
+ }
+
+ len = snprintf(alias, ALIAS_SIZE, WMI_MODULE_PREFIX "%s", *guid_string);
+ if (len < 0 || len >= ALIAS_SIZE) {
+ warn("Could not generate all MODULE_ALIAS's in '%s'\n",
+ filename);
+ return 0;
+ }
+ return 1;
+}
/* Does namelen bytes of name exactly match the symbol? */
static bool sym_is(const char *name, unsigned namelen, const char *symbol)
@@ -1377,12 +1347,11 @@
static void do_table(void *symval, unsigned long size,
unsigned long id_size,
const char *device_id,
- void *function,
+ int (*do_entry)(const char *filename, void *symval, char *alias),
struct module *mod)
{
unsigned int i;
- char alias[500];
- int (*do_entry)(const char *, void *entry, char *alias) = function;
+ char alias[ALIAS_SIZE];
device_id_check(mod->name, device_id, size, id_size, symval);
/* Leave last one: it's the terminator. */
@@ -1396,6 +1365,50 @@
}
}
+static const struct devtable devtable[] = {
+ {"hid", SIZE_hid_device_id, do_hid_entry},
+ {"ieee1394", SIZE_ieee1394_device_id, do_ieee1394_entry},
+ {"pci", SIZE_pci_device_id, do_pci_entry},
+ {"ccw", SIZE_ccw_device_id, do_ccw_entry},
+ {"ap", SIZE_ap_device_id, do_ap_entry},
+ {"css", SIZE_css_device_id, do_css_entry},
+ {"serio", SIZE_serio_device_id, do_serio_entry},
+ {"acpi", SIZE_acpi_device_id, do_acpi_entry},
+ {"pcmcia", SIZE_pcmcia_device_id, do_pcmcia_entry},
+ {"vio", SIZE_vio_device_id, do_vio_entry},
+ {"input", SIZE_input_device_id, do_input_entry},
+ {"eisa", SIZE_eisa_device_id, do_eisa_entry},
+ {"parisc", SIZE_parisc_device_id, do_parisc_entry},
+ {"sdio", SIZE_sdio_device_id, do_sdio_entry},
+ {"ssb", SIZE_ssb_device_id, do_ssb_entry},
+ {"bcma", SIZE_bcma_device_id, do_bcma_entry},
+ {"virtio", SIZE_virtio_device_id, do_virtio_entry},
+ {"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},
+ {"spi", SIZE_spi_device_id, do_spi_entry},
+ {"dmi", SIZE_dmi_system_id, do_dmi_entry},
+ {"platform", SIZE_platform_device_id, do_platform_entry},
+ {"mdio", SIZE_mdio_device_id, do_mdio_entry},
+ {"zorro", SIZE_zorro_device_id, do_zorro_entry},
+ {"isapnp", SIZE_isapnp_device_id, do_isapnp_entry},
+ {"ipack", SIZE_ipack_device_id, do_ipack_entry},
+ {"amba", SIZE_amba_id, do_amba_entry},
+ {"mipscdmm", SIZE_mips_cdmm_device_id, do_mips_cdmm_entry},
+ {"x86cpu", SIZE_x86_cpu_id, do_x86cpu_entry},
+ {"cpu", SIZE_cpu_feature, do_cpu_entry},
+ {"mei", SIZE_mei_cl_device_id, do_mei_entry},
+ {"rapidio", SIZE_rio_device_id, do_rio_entry},
+ {"ulpi", SIZE_ulpi_device_id, do_ulpi_entry},
+ {"hdaudio", SIZE_hda_device_id, do_hda_entry},
+ {"sdw", SIZE_sdw_device_id, do_sdw_entry},
+ {"fslmc", SIZE_fsl_mc_device_id, do_fsl_mc_entry},
+ {"tbsvc", SIZE_tb_service_id, do_tbsvc_entry},
+ {"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},
+};
+
/* Create MODULE_ALIAS() statements.
* At this time, we cannot write the actual output C source yet,
* so we write into the mod->dev_table_buf buffer. */
@@ -1415,11 +1428,10 @@
if (ELF_ST_TYPE(sym->st_info) != STT_OBJECT)
return;
- /* All our symbols are of form <prefix>__mod_<name>__<identifier>_device_table. */
- name = strstr(symname, "__mod_");
- if (!name)
+ /* All our symbols are of form __mod_<name>__<identifier>_device_table. */
+ if (strncmp(symname, "__mod_", strlen("__mod_")))
return;
- name += strlen("__mod_");
+ name = symname + strlen("__mod_");
namelen = strlen(name);
if (namelen < strlen("_device_table"))
return;
@@ -1450,13 +1462,14 @@
else if (sym_is(name, namelen, "pnp_card"))
do_pnp_card_entries(symval, sym->st_size, mod);
else {
- struct devtable **p;
- INIT_SECTION(__devtable);
+ int i;
- for (p = __start___devtable; p < __stop___devtable; p++) {
- if (sym_is(name, namelen, (*p)->device_id)) {
- do_table(symval, sym->st_size, (*p)->id_size,
- (*p)->device_id, (*p)->function, mod);
+ for (i = 0; i < ARRAY_SIZE(devtable); i++) {
+ const struct devtable *p = &devtable[i];
+
+ if (sym_is(name, namelen, p->device_id)) {
+ do_table(symval, sym->st_size, p->id_size,
+ p->device_id, p->do_entry, mod);
break;
}
}
diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c
index 0d998c5..d2a30a7 100644
--- a/scripts/mod/modpost.c
+++ b/scripts/mod/modpost.c
@@ -35,10 +35,11 @@
static int warn_unresolved = 0;
/* How a symbol is exported */
static int sec_mismatch_count = 0;
-static int sec_mismatch_verbose = 1;
static int sec_mismatch_fatal = 0;
/* ignore missing files */
static int ignore_missing_files;
+/* write namespace dependencies */
+static int write_namespace_deps;
enum export {
export_plain, export_unused, export_gpl,
@@ -165,11 +166,13 @@
struct module *module;
unsigned int crc;
int crc_valid;
+ char *namespace;
unsigned int weak:1;
unsigned int vmlinux:1; /* 1 if symbol is defined in vmlinux */
unsigned int kernel:1; /* 1 if symbol is from kernel
* (only for external modules) **/
unsigned int preloaded:1; /* 1 if symbol from Module.symvers, or crc */
+ unsigned int is_static:1; /* 1 if symbol is not global */
enum export export; /* Type of export */
char name[0];
};
@@ -202,6 +205,7 @@
strcpy(s->name, name);
s->weak = weak;
s->next = next;
+ s->is_static = 1;
return s;
}
@@ -234,6 +238,37 @@
return NULL;
}
+static bool contains_namespace(struct namespace_list *list,
+ const char *namespace)
+{
+ struct namespace_list *ns_entry;
+
+ for (ns_entry = list; ns_entry != NULL; ns_entry = ns_entry->next)
+ if (strcmp(ns_entry->namespace, namespace) == 0)
+ return true;
+
+ return false;
+}
+
+static void add_namespace(struct namespace_list **list, const char *namespace)
+{
+ struct namespace_list *ns_entry;
+
+ if (!contains_namespace(*list, namespace)) {
+ ns_entry = NOFAIL(malloc(sizeof(struct namespace_list) +
+ strlen(namespace) + 1));
+ strcpy(ns_entry->namespace, namespace);
+ ns_entry->next = *list;
+ *list = ns_entry;
+ }
+}
+
+static bool module_imports_namespace(struct module *module,
+ const char *namespace)
+{
+ return contains_namespace(module->imported_namespaces, namespace);
+}
+
static const struct {
const char *str;
enum export export;
@@ -313,6 +348,32 @@
return export_unknown;
}
+static const char *namespace_from_kstrtabns(struct elf_info *info,
+ Elf_Sym *kstrtabns)
+{
+ char *value = info->ksymtab_strings + kstrtabns->st_value;
+ return value[0] ? value : NULL;
+}
+
+static void sym_update_namespace(const char *symname, const char *namespace)
+{
+ struct symbol *s = find_symbol(symname);
+
+ /*
+ * That symbol should have been created earlier and thus this is
+ * actually an assertion.
+ */
+ if (!s) {
+ merror("Could not update namespace(%s) for symbol %s\n",
+ namespace, symname);
+ return;
+ }
+
+ free(s->namespace);
+ s->namespace =
+ namespace && namespace[0] ? NOFAIL(strdup(namespace)) : NULL;
+}
+
/**
* Add an exported symbol - it may have already been added without a
* CRC, in this case just update the CRC
@@ -326,10 +387,9 @@
s = new_symbol(name, mod, export);
} else {
if (!s->preloaded) {
- warn("%s: '%s' exported twice. Previous export "
- "was in %s%s\n", mod->name, name,
- s->module->name,
- is_vmlinux(s->module->name) ?"":".ko");
+ warn("%s: '%s' exported twice. Previous export was in %s%s\n",
+ mod->name, name, s->module->name,
+ is_vmlinux(s->module->name) ? "" : ".ko");
} else {
/* In case Module.symvers was out of date */
s->module = mod;
@@ -533,6 +593,10 @@
info->export_unused_gpl_sec = i;
else if (strcmp(secname, "__ksymtab_gpl_future") == 0)
info->export_gpl_future_sec = i;
+ else if (strcmp(secname, "__ksymtab_strings") == 0)
+ info->ksymtab_strings = (void *)hdr +
+ sechdrs[i].sh_offset -
+ sechdrs[i].sh_addr;
if (sechdrs[i].sh_type == SHT_SYMTAB) {
unsigned int sh_link_idx;
@@ -621,6 +685,7 @@
unsigned int crc;
enum export export;
bool is_crc = false;
+ const char *name;
if ((!is_vmlinux(mod->name) || mod->is_dot_o) &&
strstarts(symname, "__ksymtab"))
@@ -640,7 +705,7 @@
info->sechdrs[sym->st_shndx].sh_offset -
(info->hdr->e_type != ET_REL ?
info->sechdrs[sym->st_shndx].sh_addr : 0);
- crc = *crcp;
+ crc = TO_NATIVE(*crcp);
}
sym_update_crc(symname + strlen("__crc_"), mod, crc,
export);
@@ -692,8 +757,8 @@
default:
/* All exported symbols */
if (strstarts(symname, "__ksymtab_")) {
- sym_add_exported(symname + strlen("__ksymtab_"), mod,
- export);
+ name = symname + strlen("__ksymtab_");
+ sym_add_exported(name, mod, export);
}
if (strcmp(symname, "init_module") == 0)
mod->has_init = 1;
@@ -796,9 +861,9 @@
/* "*foo*" */
if (*p == '*' && *endp == '*') {
- char *here, *bare = strndup(p + 1, strlen(p) - 2);
+ char *bare = NOFAIL(strndup(p + 1, strlen(p) - 2));
+ char *here = strstr(sym, bare);
- here = strstr(sym, bare);
free(bare);
if (here != NULL)
return 1;
@@ -1163,6 +1228,14 @@
* fromsec = text section
* refsymname = *.constprop.*
*
+ * Pattern 6:
+ * Hide section mismatch warnings for ELF local symbols. The goal
+ * is to eliminate false positive modpost warnings caused by
+ * compiler-generated ELF local symbol names such as ".LANCHOR1".
+ * Autogenerated symbol names bypass modpost's "Pattern 2"
+ * whitelisting, which relies on pattern-matching against symbol
+ * names to work. (One situation where gcc can autogenerate ELF
+ * local symbols is when "-fsection-anchors" is used.)
**/
static int secref_whitelist(const struct sectioncheck *mismatch,
const char *fromsec, const char *fromsym,
@@ -1201,9 +1274,37 @@
match(fromsym, optim_symbols))
return 0;
+ /* Check for pattern 6 */
+ if (strstarts(fromsym, ".L"))
+ return 0;
+
return 1;
}
+static inline int is_arm_mapping_symbol(const char *str)
+{
+ return str[0] == '$' && strchr("axtd", str[1])
+ && (str[2] == '\0' || str[2] == '.');
+}
+
+/*
+ * If there's no name there, ignore it; likewise, ignore it if it's
+ * one of the magic symbols emitted used by current ARM tools.
+ *
+ * Otherwise if find_symbols_between() returns those symbols, they'll
+ * fail the whitelist tests and cause lots of false alarms ... fixable
+ * only by merging __exit and __init sections into __text, bloating
+ * the kernel (which is especially evil on embedded platforms).
+ */
+static inline int is_valid_name(struct elf_info *elf, Elf_Sym *sym)
+{
+ const char *name = elf->strtab + sym->st_name;
+
+ if (!name || !strlen(name))
+ return 0;
+ return !is_arm_mapping_symbol(name);
+}
+
/**
* Find symbol based on relocation record info.
* In some cases the symbol supplied is a valid symbol so
@@ -1229,6 +1330,8 @@
continue;
if (ELF_ST_TYPE(sym->st_info) == STT_SECTION)
continue;
+ if (!is_valid_name(elf, sym))
+ continue;
if (sym->st_value == addr)
return sym;
/* Find a symbol nearby - addr are maybe negative */
@@ -1247,30 +1350,6 @@
return NULL;
}
-static inline int is_arm_mapping_symbol(const char *str)
-{
- return str[0] == '$' && strchr("axtd", str[1])
- && (str[2] == '\0' || str[2] == '.');
-}
-
-/*
- * If there's no name there, ignore it; likewise, ignore it if it's
- * one of the magic symbols emitted used by current ARM tools.
- *
- * Otherwise if find_symbols_between() returns those symbols, they'll
- * fail the whitelist tests and cause lots of false alarms ... fixable
- * only by merging __exit and __init sections into __text, bloating
- * the kernel (which is especially evil on embedded platforms).
- */
-static inline int is_valid_name(struct elf_info *elf, Elf_Sym *sym)
-{
- const char *name = elf->strtab + sym->st_name;
-
- if (!name || !strlen(name))
- return 0;
- return !is_arm_mapping_symbol(name);
-}
-
/*
* Find symbols before or equal addr and after addr - in the section sec.
* If we find two symbols with equal offset prefer one with a valid name.
@@ -1392,8 +1471,6 @@
char *prl_to;
sec_mismatch_count++;
- if (!sec_mismatch_verbose)
- return;
get_pretty_name(from_is_func, &from, &from_p);
get_pretty_name(to_is_func, &to, &to_p);
@@ -1641,9 +1718,7 @@
sec_mismatch_count++;
- if (sec_mismatch_verbose)
- report_extable_warnings(modname, elf, mismatch, r, sym,
- fromsec, tosec);
+ report_extable_warnings(modname, elf, mismatch, r, sym, fromsec, tosec);
if (match(tosec, mismatch->bad_tosec))
fatal("The relocation at %s+0x%lx references\n"
@@ -1934,6 +2009,7 @@
const char *symname;
char *version;
char *license;
+ char *namespace;
struct module *mod;
struct elf_info info = { };
Elf_Sym *sym;
@@ -1965,12 +2041,43 @@
license = get_next_modinfo(&info, "license", license);
}
+ namespace = get_modinfo(&info, "import_ns");
+ while (namespace) {
+ add_namespace(&mod->imported_namespaces, namespace);
+ namespace = get_next_modinfo(&info, "import_ns", namespace);
+ }
+
for (sym = info.symtab_start; sym < info.symtab_stop; sym++) {
symname = remove_dot(info.strtab + sym->st_name);
handle_modversions(mod, &info, sym, symname);
handle_moddevtable(mod, &info, sym, symname);
}
+
+ /* Apply symbol namespaces from __kstrtabns_<symbol> entries. */
+ for (sym = info.symtab_start; sym < info.symtab_stop; sym++) {
+ symname = remove_dot(info.strtab + sym->st_name);
+
+ if (strstarts(symname, "__kstrtabns_"))
+ sym_update_namespace(symname + strlen("__kstrtabns_"),
+ namespace_from_kstrtabns(&info,
+ sym));
+ }
+
+ // check for static EXPORT_SYMBOL_* functions && global vars
+ for (sym = info.symtab_start; sym < info.symtab_stop; sym++) {
+ unsigned char bind = ELF_ST_BIND(sym->st_info);
+
+ if (bind == STB_GLOBAL || bind == STB_WEAK) {
+ struct symbol *s =
+ find_symbol(remove_dot(info.strtab +
+ sym->st_name));
+
+ if (s)
+ s->is_static = 0;
+ }
+ }
+
if (!is_vmlinux(modname) || vmlinux_section_warnings)
check_sec_ref(mod, modname, &info);
@@ -2083,24 +2190,50 @@
}
}
-static void check_exports(struct module *mod)
+static int check_exports(struct module *mod)
{
struct symbol *s, *exp;
+ int err = 0;
for (s = mod->unres; s; s = s->next) {
const char *basename;
exp = find_symbol(s->name);
- if (!exp || exp->module == mod)
+ if (!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);
+ err = 1;
+ }
+ }
continue;
+ }
basename = strrchr(mod->name, '/');
if (basename)
basename++;
else
basename = mod->name;
+
+ if (exp->namespace) {
+ add_namespace(&mod->required_namespaces,
+ exp->namespace);
+
+ if (!write_namespace_deps &&
+ !module_imports_namespace(mod, exp->namespace)) {
+ warn("module %s uses symbol %s from namespace %s, but does not import it.\n",
+ basename, exp->name, exp->namespace);
+ }
+ }
+
if (!mod->gpl_compatible)
check_for_gpl_usage(exp->export, basename, exp->name);
check_for_unused(exp->export, basename, exp->name);
}
+
+ return err;
}
static int check_modname_len(struct module *mod)
@@ -2136,7 +2269,7 @@
buf_printf(b, "MODULE_INFO(name, KBUILD_MODNAME);\n");
buf_printf(b, "\n");
buf_printf(b, "__visible struct module __this_module\n");
- buf_printf(b, "__attribute__((section(\".gnu.linkonce.this_module\"))) = {\n");
+ buf_printf(b, "__section(.gnu.linkonce.this_module) = {\n");
buf_printf(b, "\t.name = KBUILD_MODNAME,\n");
if (mod->has_init)
buf_printf(b, "\t.init = init_module,\n");
@@ -2157,7 +2290,7 @@
/* Cannot check for assembler */
static void add_retpoline(struct buffer *b)
{
- buf_printf(b, "\n#ifdef RETPOLINE\n");
+ buf_printf(b, "\n#ifdef CONFIG_RETPOLINE\n");
buf_printf(b, "MODULE_INFO(retpoline, \"Y\");\n");
buf_printf(b, "#endif\n");
}
@@ -2178,19 +2311,8 @@
for (s = mod->unres; s; s = s->next) {
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);
- err = 1;
- }
- }
+ if (!exp || exp->module == mod)
continue;
- }
s->module = exp->module;
s->crc_valid = exp->crc_valid;
s->crc = exp->crc;
@@ -2201,8 +2323,7 @@
buf_printf(b, "\n");
buf_printf(b, "static const struct modversion_info ____versions[]\n");
- buf_printf(b, "__used\n");
- buf_printf(b, "__attribute__((section(\"__versions\"))) = {\n");
+ buf_printf(b, "__used __section(__versions) = {\n");
for (s = mod->unres; s; s = s->next) {
if (!s->module)
@@ -2227,21 +2348,18 @@
return err;
}
-static void add_depends(struct buffer *b, struct module *mod,
- struct module *modules)
+static void add_depends(struct buffer *b, struct module *mod)
{
struct symbol *s;
- struct module *m;
int first = 1;
- for (m = modules; m; m = m->next)
- m->seen = is_vmlinux(m->name);
+ /* Clear ->seen flag of modules that own symbols needed by this. */
+ for (s = mod->unres; s; s = s->next)
+ if (s->module)
+ s->module->seen = is_vmlinux(s->module->name);
buf_printf(b, "\n");
- buf_printf(b, "static const char __module_depends[]\n");
- buf_printf(b, "__used\n");
- buf_printf(b, "__attribute__((section(\".modinfo\"))) =\n");
- buf_printf(b, "\"depends=");
+ buf_printf(b, "MODULE_INFO(depends, \"");
for (s = mod->unres; s; s = s->next) {
const char *p;
if (!s->module)
@@ -2259,7 +2377,7 @@
buf_printf(b, "%s%s", first ? "" : ",", p);
first = 0;
}
- buf_printf(b, "\";\n");
+ buf_printf(b, "\");\n");
}
static void add_srcversion(struct buffer *b, struct module *mod)
@@ -2329,7 +2447,7 @@
return;
while ((line = get_next_line(&pos, file, size))) {
- char *symname, *modname, *d, *export, *end;
+ char *symname, *namespace, *modname, *d, *export, *end;
unsigned int crc;
struct module *mod;
struct symbol *s;
@@ -2337,7 +2455,10 @@
if (!(symname = strchr(line, '\t')))
goto fail;
*symname++ = '\0';
- if (!(modname = strchr(symname, '\t')))
+ if (!(namespace = strchr(symname, '\t')))
+ goto fail;
+ *namespace++ = '\0';
+ if (!(modname = strchr(namespace, '\t')))
goto fail;
*modname++ = '\0';
if ((export = strchr(modname, '\t')) != NULL)
@@ -2357,7 +2478,9 @@
s = sym_add_exported(symname, mod, export_no(export));
s->kernel = kernel;
s->preloaded = 1;
+ s->is_static = 0;
sym_update_crc(symname, mod, crc, export_no(export));
+ sym_update_namespace(symname, namespace);
}
release_file(file, size);
return;
@@ -2383,16 +2506,20 @@
{
struct buffer buf = { };
struct symbol *symbol;
+ const char *namespace;
int n;
for (n = 0; n < SYMBOL_HASH_SIZE ; n++) {
symbol = symbolhash[n];
while (symbol) {
- if (dump_sym(symbol))
- buf_printf(&buf, "0x%08x\t%s\t%s\t%s\n",
- symbol->crc, symbol->name,
- symbol->module->name,
- export_str(symbol->export));
+ if (dump_sym(symbol)) {
+ namespace = symbol->namespace;
+ buf_printf(&buf, "0x%08x\t%s\t%s\t%s\t%s\n",
+ symbol->crc, symbol->name,
+ namespace ? namespace : "",
+ symbol->module->name,
+ export_str(symbol->export));
+ }
symbol = symbol->next;
}
}
@@ -2400,6 +2527,31 @@
free(buf.p);
}
+static void write_namespace_deps_files(void)
+{
+ struct module *mod;
+ struct namespace_list *ns;
+ struct buffer ns_deps_buf = {};
+
+ for (mod = modules; mod; mod = mod->next) {
+ char fname[PATH_MAX];
+
+ if (mod->skip)
+ continue;
+
+ ns_deps_buf.pos = 0;
+
+ for (ns = mod->required_namespaces; ns; ns = ns->next)
+ buf_printf(&ns_deps_buf, "%s\n", ns->namespace);
+
+ if (ns_deps_buf.pos == 0)
+ continue;
+
+ sprintf(fname, "%s.ns_deps", mod->name);
+ write_if_changed(&ns_deps_buf, fname);
+ }
+}
+
struct ext_sym_list {
struct ext_sym_list *next;
const char *file;
@@ -2413,10 +2565,11 @@
char *dump_write = NULL, *files_source = NULL;
int opt;
int err;
+ int n;
struct ext_sym_list *extsym_iter;
struct ext_sym_list *extsym_start = NULL;
- while ((opt = getopt(argc, argv, "i:I:e:mnsST:o:awM:K:E")) != -1) {
+ while ((opt = getopt(argc, argv, "i:I:e:mnsT:o:awEd")) != -1) {
switch (opt) {
case 'i':
kernel_read = optarg;
@@ -2448,9 +2601,6 @@
case 's':
vmlinux_section_warnings = 0;
break;
- case 'S':
- sec_mismatch_verbose = 0;
- break;
case 'T':
files_source = optarg;
break;
@@ -2460,6 +2610,9 @@
case 'E':
sec_mismatch_fatal = 1;
break;
+ case 'd':
+ write_namespace_deps = 1;
+ break;
default:
exit(1);
}
@@ -2482,12 +2635,6 @@
if (files_source)
read_symbols_from_files(files_source);
- for (mod = modules; mod; mod = mod->next) {
- if (mod->skip)
- continue;
- check_exports(mod);
- }
-
err = 0;
for (mod = modules; mod; mod = mod->next) {
@@ -2499,32 +2646,51 @@
buf.pos = 0;
err |= check_modname_len(mod);
+ err |= check_exports(mod);
+ if (write_namespace_deps)
+ continue;
+
add_header(&buf, mod);
add_intree_flag(&buf, !external_module);
add_retpoline(&buf);
add_staging_flag(&buf, mod->name);
err |= add_versions(&buf, mod);
- add_depends(&buf, mod, modules);
+ add_depends(&buf, mod);
add_moddevtable(&buf, mod);
add_srcversion(&buf, mod);
sprintf(fname, "%s.mod.c", mod->name);
write_if_changed(&buf, fname);
}
+
+ if (write_namespace_deps) {
+ write_namespace_deps_files();
+ return 0;
+ }
+
if (dump_write)
write_dump(dump_write);
- if (sec_mismatch_count) {
- if (!sec_mismatch_verbose) {
- warn("modpost: Found %d section mismatch(es).\n"
- "To see full details build your kernel with:\n"
- "'make CONFIG_DEBUG_SECTION_MISMATCH=y'\n",
- sec_mismatch_count);
- }
- if (sec_mismatch_fatal) {
- fatal("modpost: Section mismatches detected.\n"
- "Set CONFIG_SECTION_MISMATCH_WARN_ONLY=y to allow them.\n");
+ if (sec_mismatch_count && sec_mismatch_fatal)
+ fatal("modpost: Section mismatches detected.\n"
+ "Set CONFIG_SECTION_MISMATCH_WARN_ONLY=y to allow them.\n");
+ for (n = 0; n < SYMBOL_HASH_SIZE; n++) {
+ struct symbol *s;
+
+ for (s = symbolhash[n]; s; s = s->next) {
+ /*
+ * Do not check "vmlinux". This avoids the same warnings
+ * shown twice, and false-positives for ARCH=um.
+ */
+ if (is_vmlinux(s->module->name) && !s->module->is_dot_o)
+ continue;
+
+ if (s->is_static)
+ warn("\"%s\" [%s] is a static %s\n",
+ s->name, s->module->name,
+ export_str(s->export));
}
}
+
free(buf.p);
return err;
diff --git a/scripts/mod/modpost.h b/scripts/mod/modpost.h
index 8453d6a..ad271bc 100644
--- a/scripts/mod/modpost.h
+++ b/scripts/mod/modpost.h
@@ -109,6 +109,11 @@
void
buf_write(struct buffer *buf, const char *s, int len);
+struct namespace_list {
+ struct namespace_list *next;
+ char namespace[0];
+};
+
struct module {
struct module *next;
const char *name;
@@ -121,6 +126,10 @@
struct buffer dev_table_buf;
char srcversion[25];
int is_dot_o;
+ // Required namespace dependencies
+ struct namespace_list *required_namespaces;
+ // Actual imported namespaces
+ struct namespace_list *imported_namespaces;
};
struct elf_info {
@@ -134,6 +143,7 @@
Elf_Section export_gpl_sec;
Elf_Section export_unused_gpl_sec;
Elf_Section export_gpl_future_sec;
+ char *ksymtab_strings;
char *strtab;
char *modinfo;
unsigned int modinfo_len;
diff --git a/scripts/mod/sumversion.c b/scripts/mod/sumversion.c
index 0f6dcb4..6306202 100644
--- a/scripts/mod/sumversion.c
+++ b/scripts/mod/sumversion.c
@@ -396,34 +396,19 @@
unsigned long len;
struct md4_ctx md;
char *sources, *end, *fname;
- const char *basename;
char filelist[PATH_MAX + 1];
- char *modverdir = getenv("MODVERDIR");
- if (!modverdir)
- modverdir = ".";
-
- /* Source files for module are in .tmp_versions/modname.mod,
- after the first line. */
- if (strrchr(modname, '/'))
- basename = strrchr(modname, '/') + 1;
- else
- basename = modname;
- snprintf(filelist, sizeof(filelist), "%s/%.*s.mod", modverdir,
- (int) strlen(basename) - 2, basename);
+ /* objects for a module are listed in the first line of *.mod file. */
+ snprintf(filelist, sizeof(filelist), "%.*smod",
+ (int)strlen(modname) - 1, modname);
file = grab_file(filelist, &len);
if (!file)
/* not a module or .mod file missing - ignore */
return;
- sources = strchr(file, '\n');
- if (!sources) {
- warn("malformed versions file for %s\n", modname);
- goto release;
- }
+ sources = file;
- sources++;
end = strchr(sources, '\n');
if (!end) {
warn("bad ending versions file for %s\n", modname);
diff --git a/scripts/modules-check.sh b/scripts/modules-check.sh
new file mode 100755
index 0000000..f51f446
--- /dev/null
+++ b/scripts/modules-check.sh
@@ -0,0 +1,16 @@
+#!/bin/sh
+# SPDX-License-Identifier: GPL-2.0
+
+set -e
+
+# Check uniqueness of module names
+check_same_name_modules()
+{
+ for m in $(sed 's:.*/::' modules.order | sort | uniq -d)
+ do
+ echo "warning: same module names found:" >&2
+ sed -n "/\/$m/s:^: :p" modules.order >&2
+ done
+}
+
+check_same_name_modules
diff --git a/scripts/namespace.pl b/scripts/namespace.pl
index 6135574..1da7bca 100755
--- a/scripts/namespace.pl
+++ b/scripts/namespace.pl
@@ -65,13 +65,14 @@
use warnings;
use strict;
use File::Find;
+use File::Spec;
my $nm = ($ENV{'NM'} || "nm") . " -p";
my $objdump = ($ENV{'OBJDUMP'} || "objdump") . " -s -j .comment";
-my $srctree = "";
-my $objtree = "";
-$srctree = "$ENV{'srctree'}/" if (exists($ENV{'srctree'}));
-$objtree = "$ENV{'objtree'}/" if (exists($ENV{'objtree'}));
+my $srctree = File::Spec->curdir();
+my $objtree = File::Spec->curdir();
+$srctree = File::Spec->rel2abs($ENV{'srctree'}) if (exists($ENV{'srctree'}));
+$objtree = File::Spec->rel2abs($ENV{'objtree'}) if (exists($ENV{'objtree'}));
if ($#ARGV != -1) {
print STDERR "usage: $0 takes no parameters\n";
@@ -231,9 +232,9 @@
}
($source = $basename) =~ s/\.o$//;
if (-e "$source.c" || -e "$source.S") {
- $source = "$objtree$File::Find::dir/$source";
+ $source = File::Spec->catfile($objtree, $File::Find::dir, $source)
} else {
- $source = "$srctree$File::Find::dir/$source";
+ $source = File::Spec->catfile($srctree, $File::Find::dir, $source)
}
if (! -e "$source.c" && ! -e "$source.S") {
# No obvious source, exclude the object if it is conglomerate
diff --git a/scripts/nsdeps b/scripts/nsdeps
new file mode 100644
index 0000000..04cea09
--- /dev/null
+++ b/scripts/nsdeps
@@ -0,0 +1,58 @@
+#!/bin/sh
+# SPDX-License-Identifier: GPL-2.0
+# Linux kernel symbol namespace import generator
+#
+# This script requires a minimum spatch version.
+SPATCH_REQ_VERSION="1.0.4"
+
+DIR="$(dirname $(readlink -f $0))/.."
+SPATCH="`which ${SPATCH:=spatch}`"
+if [ ! -x "$SPATCH" ]; then
+ echo 'spatch is part of the Coccinelle project and is available at http://coccinelle.lip6.fr/'
+ exit 1
+fi
+
+SPATCH_REQ_VERSION_NUM=$(echo $SPATCH_REQ_VERSION | ${DIR}/scripts/ld-version.sh)
+SPATCH_VERSION=$($SPATCH --version | head -1 | awk '{print $3}')
+SPATCH_VERSION_NUM=$(echo $SPATCH_VERSION | ${DIR}/scripts/ld-version.sh)
+
+if [ "$SPATCH_VERSION_NUM" -lt "$SPATCH_REQ_VERSION_NUM" ] ; then
+ echo "spatch needs to be version $SPATCH_REQ_VERSION or higher"
+ exit 1
+fi
+
+generate_deps_for_ns() {
+ $SPATCH --very-quiet --in-place --sp-file \
+ $srctree/scripts/coccinelle/misc/add_namespace.cocci -D ns=$1 $2
+}
+
+generate_deps() {
+ local mod_name=`basename $@ .ko`
+ local mod_file=`echo $@ | sed -e 's/\.ko/\.mod/'`
+ local ns_deps_file=`echo $@ | sed -e 's/\.ko/\.ns_deps/'`
+ if [ ! -f "$ns_deps_file" ]; then return; fi
+ local mod_source_files="`cat $mod_file | sed -n 1p \
+ | sed -e 's/\.o/\.c/g' \
+ | sed "s|[^ ]* *|${srctree}/&|g"`"
+ for ns in `cat $ns_deps_file`; do
+ echo "Adding namespace $ns to module $mod_name (if needed)."
+ generate_deps_for_ns $ns "$mod_source_files"
+ # sort the imports
+ for source_file in $mod_source_files; do
+ sed '/MODULE_IMPORT_NS/Q' $source_file > ${source_file}.tmp
+ offset=$(wc -l ${source_file}.tmp | awk '{print $1;}')
+ cat $source_file | grep MODULE_IMPORT_NS | LANG=C sort -u >> ${source_file}.tmp
+ tail -n +$((offset +1)) ${source_file} | grep -v MODULE_IMPORT_NS >> ${source_file}.tmp
+ if ! diff -q ${source_file} ${source_file}.tmp; then
+ mv ${source_file}.tmp ${source_file}
+ else
+ rm ${source_file}.tmp
+ fi
+ done
+ done
+}
+
+for f in `cat $objtree/modules.order`; do
+ generate_deps $f
+done
+
diff --git a/scripts/objdiff b/scripts/objdiff
index 4fb5d67..72b0b63 100755
--- a/scripts/objdiff
+++ b/scripts/objdiff
@@ -1,11 +1,11 @@
#!/bin/bash
+# SPDX-License-Identifier: GPL-2.0-only
# objdiff - a small script for validating that a commit or series of commits
# didn't change object code.
#
# Copyright 2014, Jason Cooper <jason@lakedaemon.net>
#
-# Licensed under the terms of the GNU GPL version 2
# usage example:
#
diff --git a/scripts/package/builddeb b/scripts/package/builddeb
index 90c9a8a..c4c580f 100755
--- a/scripts/package/builddeb
+++ b/scripts/package/builddeb
@@ -12,6 +12,18 @@
set -e
+is_enabled() {
+ grep -q "^$1=y" include/config/auto.conf
+}
+
+if_enabled_echo() {
+ if is_enabled "$1"; then
+ echo -n "$2"
+ elif [ $# -ge 3 ]; then
+ echo -n "$3"
+ fi
+}
+
create_package() {
local pname="$1" pdir="$2"
@@ -62,7 +74,7 @@
installed_image_path="boot/vmlinuz-$version"
esac
-BUILD_DEBUG="$(grep -s '^CONFIG_DEBUG_INFO=y' $KCONFIG_CONFIG || true)"
+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
@@ -81,17 +93,17 @@
cp System.map "$tmpdir/boot/System.map-$version"
cp $KCONFIG_CONFIG "$tmpdir/boot/config-$version"
fi
-cp "$($MAKE -s image_name)" "$tmpdir/$installed_image_path"
+cp "$($MAKE -s -f $srctree/Makefile image_name)" "$tmpdir/$installed_image_path"
-if grep -q "^CONFIG_OF=y" $KCONFIG_CONFIG ; then
+if is_enabled CONFIG_OF_EARLY_FLATTREE; then
# Only some architectures with OF support have this target
- if grep -q dtbs_install "${srctree}/arch/$SRCARCH/Makefile"; then
- $MAKE KBUILD_SRC= INSTALL_DTBS_PATH="$tmpdir/usr/lib/$packagename" dtbs_install
+ if [ -d "${srctree}/arch/$SRCARCH/boot/dts" ]; then
+ $MAKE -f $srctree/Makefile INSTALL_DTBS_PATH="$tmpdir/usr/lib/$packagename" dtbs_install
fi
fi
-if grep -q '^CONFIG_MODULES=y' $KCONFIG_CONFIG ; then
- INSTALL_MOD_PATH="$tmpdir" $MAKE KBUILD_SRC= modules_install
+if is_enabled CONFIG_MODULES; then
+ INSTALL_MOD_PATH="$tmpdir" $MAKE -f $srctree/Makefile modules_install
rm -f "$tmpdir/lib/modules/$version/build"
rm -f "$tmpdir/lib/modules/$version/source"
if [ "$ARCH" = "um" ] ; then
@@ -111,16 +123,20 @@
done
# resign stripped modules
- MODULE_SIG_ALL="$(grep -s '^CONFIG_MODULE_SIG_ALL=y' $KCONFIG_CONFIG || true)"
- if [ -n "$MODULE_SIG_ALL" ]; then
- INSTALL_MOD_PATH="$tmpdir" $MAKE KBUILD_SRC= modules_sign
+ if is_enabled CONFIG_MODULE_SIG_ALL; then
+ INSTALL_MOD_PATH="$tmpdir" $MAKE -f $srctree/Makefile modules_sign
fi
fi
fi
if [ "$ARCH" != "um" ]; then
- $MAKE headers_check KBUILD_SRC=
- $MAKE headers_install KBUILD_SRC= INSTALL_HDR_PATH="$libc_headers_dir/usr"
+ $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
@@ -129,11 +145,6 @@
# make-kpkg sets $INITRD to indicate whether an initramfs is wanted, and
# so do we; recent versions of dracut and initramfs-tools will obey this.
debhookdir=${KDEB_HOOKDIR:-/etc/kernel}
-if grep -q '^CONFIG_BLK_DEV_INITRD=y' $KCONFIG_CONFIG; then
- want_initrd=Yes
-else
- want_initrd=No
-fi
for script in postinst postrm preinst prerm ; do
mkdir -p "$tmpdir$debhookdir/$script.d"
cat <<EOF > "$tmpdir/DEBIAN/$script"
@@ -145,7 +156,7 @@
export DEB_MAINT_PARAMS="\$*"
# Tell initramfs builder whether it's wanted
-export INITRD=$want_initrd
+export INITRD=$(if_enabled_echo CONFIG_BLK_DEV_INITRD Yes No)
test -d $debhookdir/$script.d && run-parts --arg="$version" --arg="/$installed_image_path" $debhookdir/$script.d
exit 0
@@ -158,11 +169,11 @@
(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 grep -q '^CONFIG_STACK_VALIDATION=y' $KCONFIG_CONFIG ; then
+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 grep -q '^CONFIG_GCC_PLUGINS=y' $KCONFIG_CONFIG ; then
+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
diff --git a/scripts/package/buildtar b/scripts/package/buildtar
index d624a07..2f66c81 100755
--- a/scripts/package/buildtar
+++ b/scripts/package/buildtar
@@ -56,8 +56,8 @@
#
# Try to install modules
#
-if grep -q '^CONFIG_MODULES=y' "${KCONFIG_CONFIG}"; then
- make ARCH="${ARCH}" O="${objtree}" KBUILD_SRC= INSTALL_MOD_PATH="${tmpdir}" modules_install
+if grep -q '^CONFIG_MODULES=y' include/config/auto.conf; then
+ make ARCH="${ARCH}" -f ${srctree}/Makefile INSTALL_MOD_PATH="${tmpdir}" modules_install
dirs="$dirs lib"
fi
diff --git a/scripts/package/mkdebian b/scripts/package/mkdebian
index edcad61..e0750b7 100755
--- a/scripts/package/mkdebian
+++ b/scripts/package/mkdebian
@@ -7,7 +7,7 @@
set -e
is_enabled() {
- grep -q "^CONFIG_$1=y" $KCONFIG_CONFIG
+ grep -q "^$1=y" include/config/auto.conf
}
if_enabled_echo() {
@@ -31,23 +31,23 @@
x86_64)
debarch=amd64 ;;
sparc*)
- debarch=sparc$(if_enabled_echo 64BIT 64) ;;
+ debarch=sparc$(if_enabled_echo CONFIG_64BIT 64) ;;
s390*)
debarch=s390x ;;
ppc*)
- if is_enabled 64BIT; then
- debarch=ppc64$(if_enabled_echo CPU_LITTLE_ENDIAN el)
+ if is_enabled CONFIG_64BIT; then
+ debarch=ppc64$(if_enabled_echo CONFIG_CPU_LITTLE_ENDIAN el)
else
- debarch=powerpc$(if_enabled_echo SPE spe)
+ debarch=powerpc$(if_enabled_echo CONFIG_SPE spe)
fi
;;
parisc*)
debarch=hppa ;;
mips*)
- if is_enabled CPU_LITTLE_ENDIAN; then
- debarch=mips$(if_enabled_echo 64BIT 64)$(if_enabled_echo CPU_MIPSR6 r6)el
- elif is_enabled CPU_MIPSR6; then
- debarch=mips$(if_enabled_echo 64BIT 64)r6
+ if is_enabled CONFIG_CPU_LITTLE_ENDIAN; then
+ debarch=mips$(if_enabled_echo CONFIG_64BIT 64)$(if_enabled_echo CONFIG_CPU_MIPSR6 r6)el
+ elif is_enabled CONFIG_CPU_MIPSR6; then
+ debarch=mips$(if_enabled_echo CONFIG_64BIT 64)r6
else
debarch=mips
fi
@@ -55,8 +55,8 @@
aarch64|arm64)
debarch=arm64 ;;
arm*)
- if is_enabled AEABI; then
- debarch=arm$(if_enabled_echo VFP hf el)
+ if is_enabled CONFIG_AEABI; then
+ debarch=arm$(if_enabled_echo CONFIG_VFP hf el)
else
debarch=arm
fi
@@ -64,10 +64,10 @@
openrisc)
debarch=or1k ;;
sh)
- if is_enabled CPU_SH3; then
- debarch=sh3$(if_enabled_echo CPU_BIG_ENDIAN eb)
- elif is_enabled CPU_SH4; then
- debarch=sh4$(if_enabled_echo CPU_BIG_ENDIAN eb)
+ if is_enabled CONFIG_CPU_SH3; then
+ debarch=sh3$(if_enabled_echo CONFIG_CPU_BIG_ENDIAN eb)
+ elif is_enabled CONFIG_CPU_SH4; then
+ debarch=sh4$(if_enabled_echo CONFIG_CPU_BIG_ENDIAN eb)
fi
;;
esac
@@ -132,8 +132,12 @@
echo >&2 "Install lsb-release or set \$KDEB_CHANGELOG_DIST explicitly"
fi
-mkdir -p debian/
+mkdir -p debian/source/
+echo "1.0" > debian/source/format
+
echo $debarch > debian/arch
+extra_build_depends=", $(if_enabled_echo CONFIG_UNWINDER_ORC libelf-dev)"
+extra_build_depends="$extra_build_depends, $(if_enabled_echo CONFIG_SYSTEM_TRUSTED_KEYRING libssl-dev:native)"
# Generate a simple changelog template
cat <<EOF > debian/changelog
@@ -170,7 +174,7 @@
Section: kernel
Priority: optional
Maintainer: $maintainer
-Build-Depends: bc, kmod, cpio
+Build-Depends: bc, kmod, cpio, bison, flex | flex:native $extra_build_depends
Homepage: http://www.kernel.org/
Package: $packagename
@@ -193,6 +197,7 @@
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
Package: $dbg_packagename
Section: debug
@@ -205,13 +210,15 @@
cat <<EOF > debian/rules
#!$(command -v $MAKE) -f
+srctree ?= .
+
build:
\$(MAKE) KERNELRELEASE=${version} ARCH=${ARCH} \
- KBUILD_BUILD_VERSION=${revision} KBUILD_SRC=
+ KBUILD_BUILD_VERSION=${revision} -f \$(srctree)/Makefile
binary-arch:
\$(MAKE) KERNELRELEASE=${version} ARCH=${ARCH} \
- KBUILD_BUILD_VERSION=${revision} KBUILD_SRC= intdeb-pkg
+ KBUILD_BUILD_VERSION=${revision} -f \$(srctree)/Makefile intdeb-pkg
clean:
rm -rf debian/*tmp debian/files
@@ -219,5 +226,6 @@
binary: binary-arch
EOF
+chmod +x debian/rules
exit 0
diff --git a/scripts/package/mkspec b/scripts/package/mkspec
index e05646d..8640c27 100755
--- a/scripts/package/mkspec
+++ b/scripts/package/mkspec
@@ -12,6 +12,7 @@
# how we were called determines which rpms we build and how we build them
if [ "$1" = prebuilt ]; then
S=DEL
+ MAKE="$MAKE -f $srctree/Makefile"
else
S=
fi
@@ -28,9 +29,9 @@
PROVIDES="$PROVIDES kernel-$KERNELRELEASE"
__KERNELRELEASE=$(echo $KERNELRELEASE | sed -e "s/-/_/g")
-EXCLUDES="$RCS_TAR_IGNORE --exclude=.tmp_versions --exclude=*vmlinux* \
+EXCLUDES="$RCS_TAR_IGNORE --exclude=*vmlinux* --exclude=*.mod \
--exclude=*.o --exclude=*.ko --exclude=*.cmd --exclude=Documentation \
---exclude=.config.old --exclude=.missing-syscalls.d"
+--exclude=.config.old --exclude=.missing-syscalls.d --exclude=*.s"
# We can label the here-doc lines for conditional output to the spec file
#
@@ -78,19 +79,19 @@
$S %setup -q
$S
$S %build
-$S make %{?_smp_mflags} KBUILD_BUILD_VERSION=%{release}
+$S $MAKE %{?_smp_mflags} KBUILD_BUILD_VERSION=%{release}
$S
%install
mkdir -p %{buildroot}/boot
%ifarch ia64
mkdir -p %{buildroot}/boot/efi
- cp \$(make image_name) %{buildroot}/boot/efi/vmlinuz-$KERNELRELEASE
+ cp \$($MAKE image_name) %{buildroot}/boot/efi/vmlinuz-$KERNELRELEASE
ln -s efi/vmlinuz-$KERNELRELEASE %{buildroot}/boot/
%else
- cp \$(make image_name) %{buildroot}/boot/vmlinuz-$KERNELRELEASE
+ cp \$($MAKE image_name) %{buildroot}/boot/vmlinuz-$KERNELRELEASE
%endif
-$M make %{?_smp_mflags} INSTALL_MOD_PATH=%{buildroot} KBUILD_SRC= modules_install
- make %{?_smp_mflags} INSTALL_HDR_PATH=%{buildroot}/usr KBUILD_SRC= headers_install
+$M $MAKE %{?_smp_mflags} INSTALL_MOD_PATH=%{buildroot} modules_install
+ $MAKE %{?_smp_mflags} INSTALL_HDR_PATH=%{buildroot}/usr headers_install
cp System.map %{buildroot}/boot/System.map-$KERNELRELEASE
cp .config %{buildroot}/boot/config-$KERNELRELEASE
bzip2 -9 --keep vmlinux
diff --git a/scripts/recordmcount.c b/scripts/recordmcount.c
index 895c40e..612268e 100644
--- a/scripts/recordmcount.c
+++ b/scripts/recordmcount.c
@@ -1,8 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0-only
/*
* recordmcount.c: construct a table of the locations of calls to 'mcount'
* so that ftrace can find them quickly.
* Copyright 2009 John F. Reiser <jreiser@BitWagon.com>. All rights reserved.
- * Licensed under the GNU General Public License, version 2 (GPLv2).
*
* Restructured to fit Linux format, as well as other updates:
* Copyright 2010 Steven Rostedt <srostedt@redhat.com>, Red Hat Inc.
@@ -27,7 +27,6 @@
#include <getopt.h>
#include <elf.h>
#include <fcntl.h>
-#include <setjmp.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -43,56 +42,37 @@
static int mmap_failed; /* Boolean flag. */
static char gpfx; /* prefix for global symbol name (sometimes '_') */
static struct stat sb; /* Remember .st_size, etc. */
-static jmp_buf jmpenv; /* setjmp/longjmp per-file error escape */
static const char *altmcount; /* alternate mcount symbol name */
static int warn_on_notrace_sect; /* warn when section has mcount not being recorded */
static void *file_map; /* pointer of the mapped file */
static void *file_end; /* pointer to the end of the mapped file */
static int file_updated; /* flag to state file was changed */
static void *file_ptr; /* current file pointer location */
+
static void *file_append; /* added to the end of the file */
static size_t file_append_size; /* how much is added to end of file */
-/* setjmp() return values */
-enum {
- SJ_SETJMP = 0, /* hardwired first return */
- SJ_FAIL,
- SJ_SUCCEED
-};
-
/* Per-file resource cleanup when multiple files. */
-static void
-cleanup(void)
+static void file_append_cleanup(void)
{
- if (!mmap_failed)
- munmap(file_map, sb.st_size);
- else
- free(file_map);
- file_map = NULL;
free(file_append);
file_append = NULL;
file_append_size = 0;
file_updated = 0;
}
-static void __attribute__((noreturn))
-fail_file(void)
+static void mmap_cleanup(void)
{
- cleanup();
- longjmp(jmpenv, SJ_FAIL);
+ if (!mmap_failed)
+ munmap(file_map, sb.st_size);
+ else
+ free(file_map);
+ file_map = NULL;
}
-static void __attribute__((noreturn))
-succeed_file(void)
-{
- cleanup();
- longjmp(jmpenv, SJ_SUCCEED);
-}
+/* ulseek, uwrite, ...: Check return value for errors. */
-/* ulseek, uread, ...: Check return value for errors. */
-
-static off_t
-ulseek(int const fd, off_t const offset, int const whence)
+static off_t ulseek(off_t const offset, int const whence)
{
switch (whence) {
case SEEK_SET:
@@ -107,24 +87,12 @@
}
if (file_ptr < file_map) {
fprintf(stderr, "lseek: seek before file\n");
- fail_file();
+ return -1;
}
return file_ptr - file_map;
}
-static size_t
-uread(int const fd, void *const buf, size_t const count)
-{
- size_t const n = read(fd, buf, count);
- if (n != count) {
- perror("read");
- fail_file();
- }
- return n;
-}
-
-static size_t
-uwrite(int const fd, void const *const buf, size_t const count)
+static ssize_t uwrite(void const *const buf, size_t const count)
{
size_t cnt = count;
off_t idx = 0;
@@ -140,7 +108,9 @@
}
if (!file_append) {
perror("write");
- fail_file();
+ file_append_cleanup();
+ mmap_cleanup();
+ return -1;
}
if (file_ptr < file_end) {
cnt = file_end - file_ptr;
@@ -160,17 +130,81 @@
return count;
}
-static void *
-umalloc(size_t size)
+static void * umalloc(size_t size)
{
void *const addr = malloc(size);
if (addr == 0) {
fprintf(stderr, "malloc failed: %zu bytes\n", size);
- fail_file();
+ file_append_cleanup();
+ mmap_cleanup();
+ return NULL;
}
return addr;
}
+/*
+ * Get the whole file as a programming convenience in order to avoid
+ * malloc+lseek+read+free of many pieces. If successful, then mmap
+ * avoids copying unused pieces; else just read the whole file.
+ * Open for both read and write; new info will be appended to the file.
+ * Use MAP_PRIVATE so that a few changes to the in-memory ElfXX_Ehdr
+ * do not propagate to the file until an explicit overwrite at the last.
+ * This preserves most aspects of consistency (all except .st_size)
+ * for simultaneous readers of the file while we are appending to it.
+ * However, multiple writers still are bad. We choose not to use
+ * locking because it is expensive and the use case of kernel build
+ * makes multiple writers unlikely.
+ */
+static void *mmap_file(char const *fname)
+{
+ /* Avoid problems if early cleanup() */
+ fd_map = -1;
+ mmap_failed = 1;
+ file_map = NULL;
+ file_ptr = NULL;
+ file_updated = 0;
+ sb.st_size = 0;
+
+ fd_map = open(fname, O_RDONLY);
+ if (fd_map < 0) {
+ perror(fname);
+ return NULL;
+ }
+ if (fstat(fd_map, &sb) < 0) {
+ perror(fname);
+ goto out;
+ }
+ if (!S_ISREG(sb.st_mode)) {
+ fprintf(stderr, "not a regular file: %s\n", fname);
+ goto out;
+ }
+ file_map = mmap(0, sb.st_size, PROT_READ|PROT_WRITE, MAP_PRIVATE,
+ fd_map, 0);
+ if (file_map == MAP_FAILED) {
+ mmap_failed = 1;
+ file_map = umalloc(sb.st_size);
+ if (!file_map) {
+ perror(fname);
+ goto out;
+ }
+ if (read(fd_map, file_map, sb.st_size) != sb.st_size) {
+ perror(fname);
+ free(file_map);
+ file_map = NULL;
+ goto out;
+ }
+ } else
+ mmap_failed = 0;
+out:
+ close(fd_map);
+ fd_map = -1;
+
+ file_end = file_map + sb.st_size;
+
+ return file_map;
+}
+
+
static unsigned char ideal_nop5_x86_64[5] = { 0x0f, 0x1f, 0x44, 0x00, 0x00 };
static unsigned char ideal_nop5_x86_32[5] = { 0x3e, 0x8d, 0x74, 0x26, 0x00 };
static unsigned char *ideal_nop;
@@ -194,8 +228,10 @@
return -1;
/* convert to nop */
- ulseek(fd_map, offset - 1, SEEK_SET);
- uwrite(fd_map, ideal_nop, 5);
+ if (ulseek(offset - 1, SEEK_SET) < 0)
+ return -1;
+ if (uwrite(ideal_nop, 5) < 0)
+ return -1;
return 0;
}
@@ -243,10 +279,12 @@
return -1;
/* Convert to nop */
- ulseek(fd_map, off, SEEK_SET);
+ if (ulseek(off, SEEK_SET) < 0)
+ return -1;
do {
- uwrite(fd_map, ideal_nop, nop_size);
+ if (uwrite(ideal_nop, nop_size) < 0)
+ return -1;
} while (--cnt > 0);
return 0;
@@ -263,57 +301,20 @@
return -1;
/* Convert to nop */
- ulseek(fd_map, offset, SEEK_SET);
- uwrite(fd_map, ideal_nop, 4);
+ if (ulseek(offset, SEEK_SET) < 0)
+ return -1;
+ if (uwrite(ideal_nop, 4) < 0)
+ return -1;
return 0;
}
-/*
- * Get the whole file as a programming convenience in order to avoid
- * malloc+lseek+read+free of many pieces. If successful, then mmap
- * avoids copying unused pieces; else just read the whole file.
- * Open for both read and write; new info will be appended to the file.
- * Use MAP_PRIVATE so that a few changes to the in-memory ElfXX_Ehdr
- * do not propagate to the file until an explicit overwrite at the last.
- * This preserves most aspects of consistency (all except .st_size)
- * for simultaneous readers of the file while we are appending to it.
- * However, multiple writers still are bad. We choose not to use
- * locking because it is expensive and the use case of kernel build
- * makes multiple writers unlikely.
- */
-static void *mmap_file(char const *fname)
-{
- fd_map = open(fname, O_RDONLY);
- if (fd_map < 0 || fstat(fd_map, &sb) < 0) {
- perror(fname);
- fail_file();
- }
- if (!S_ISREG(sb.st_mode)) {
- fprintf(stderr, "not a regular file: %s\n", fname);
- fail_file();
- }
- file_map = mmap(0, sb.st_size, PROT_READ|PROT_WRITE, MAP_PRIVATE,
- fd_map, 0);
- mmap_failed = 0;
- if (file_map == MAP_FAILED) {
- mmap_failed = 1;
- file_map = umalloc(sb.st_size);
- uread(fd_map, file_map, sb.st_size);
- }
- close(fd_map);
-
- file_end = file_map + sb.st_size;
-
- return file_map;
-}
-
-static void write_file(const char *fname)
+static int write_file(const char *fname)
{
char tmp_file[strlen(fname) + 4];
size_t n;
if (!file_updated)
- return;
+ return 0;
sprintf(tmp_file, "%s.rc", fname);
@@ -325,25 +326,28 @@
fd_map = open(tmp_file, O_WRONLY | O_TRUNC | O_CREAT, sb.st_mode);
if (fd_map < 0) {
perror(fname);
- fail_file();
+ return -1;
}
n = write(fd_map, file_map, sb.st_size);
if (n != sb.st_size) {
perror("write");
- fail_file();
+ close(fd_map);
+ return -1;
}
if (file_append_size) {
n = write(fd_map, file_append, file_append_size);
if (n != file_append_size) {
perror("write");
- fail_file();
+ close(fd_map);
+ return -1;
}
}
close(fd_map);
if (rename(tmp_file, fname) < 0) {
perror(fname);
- fail_file();
+ return -1;
}
+ return 0;
}
/* w8rev, w8nat, ...: Handle endianness. */
@@ -394,10 +398,9 @@
static uint32_t (*w2)(uint16_t);
/* Names of the sections that could contain calls to mcount. */
-static int
-is_mcounted_section_name(char const *const txtname)
+static int is_mcounted_section_name(char const *const txtname)
{
- return strcmp(".text", txtname) == 0 ||
+ return strncmp(".text", txtname, 5) == 0 ||
strcmp(".init.text", txtname) == 0 ||
strcmp(".ref.text", txtname) == 0 ||
strcmp(".sched.text", txtname) == 0 ||
@@ -405,10 +408,11 @@
strcmp(".irqentry.text", txtname) == 0 ||
strcmp(".softirqentry.text", txtname) == 0 ||
strcmp(".kprobes.text", txtname) == 0 ||
- strcmp(".cpuidle.text", txtname) == 0 ||
- strcmp(".text.unlikely", txtname) == 0;
+ strcmp(".cpuidle.text", txtname) == 0;
}
+static char const *already_has_rel_mcount = "success"; /* our work here is done! */
+
/* 32 bit and 64 bit are very similar */
#include "recordmcount.h"
#define RECORD_MCOUNT_64
@@ -447,11 +451,15 @@
}).r_info;
}
-static void
-do_file(char const *const fname)
+static int do_file(char const *const fname)
{
- Elf32_Ehdr *const ehdr = mmap_file(fname);
unsigned int reltype = 0;
+ Elf32_Ehdr *ehdr;
+ int rc = -1;
+
+ ehdr = mmap_file(fname);
+ if (!ehdr)
+ goto out;
w = w4nat;
w2 = w2nat;
@@ -461,8 +469,7 @@
default:
fprintf(stderr, "unrecognized ELF data encoding %d: %s\n",
ehdr->e_ident[EI_DATA], fname);
- fail_file();
- break;
+ goto out;
case ELFDATA2LSB:
if (*(unsigned char const *)&endian != 1) {
/* main() is big endian, file.o is little endian. */
@@ -490,52 +497,54 @@
push_bl_mcount_thumb = push_bl_mcount_thumb_be;
break;
} /* end switch */
- if (memcmp(ELFMAG, ehdr->e_ident, SELFMAG) != 0
- || w2(ehdr->e_type) != ET_REL
- || ehdr->e_ident[EI_VERSION] != EV_CURRENT) {
+ if (memcmp(ELFMAG, ehdr->e_ident, SELFMAG) != 0 ||
+ w2(ehdr->e_type) != ET_REL ||
+ ehdr->e_ident[EI_VERSION] != EV_CURRENT) {
fprintf(stderr, "unrecognized ET_REL file %s\n", fname);
- fail_file();
+ goto out;
}
- gpfx = 0;
+ gpfx = '_';
switch (w2(ehdr->e_machine)) {
default:
fprintf(stderr, "unrecognized e_machine %u %s\n",
w2(ehdr->e_machine), fname);
- fail_file();
- break;
+ goto out;
case EM_386:
reltype = R_386_32;
rel_type_nop = R_386_NONE;
make_nop = make_nop_x86;
ideal_nop = ideal_nop5_x86_32;
mcount_adjust_32 = -1;
+ gpfx = 0;
break;
- case EM_ARM: reltype = R_ARM_ABS32;
- altmcount = "__gnu_mcount_nc";
- make_nop = make_nop_arm;
- rel_type_nop = R_ARM_NONE;
- break;
+ case EM_ARM:
+ reltype = R_ARM_ABS32;
+ altmcount = "__gnu_mcount_nc";
+ make_nop = make_nop_arm;
+ rel_type_nop = R_ARM_NONE;
+ gpfx = 0;
+ break;
case EM_AARCH64:
- reltype = R_AARCH64_ABS64;
- make_nop = make_nop_arm64;
- rel_type_nop = R_AARCH64_NONE;
- ideal_nop = ideal_nop4_arm64;
- gpfx = '_';
- break;
- case EM_IA_64: reltype = R_IA64_IMM64; gpfx = '_'; break;
- case EM_MIPS: /* reltype: e_class */ gpfx = '_'; break;
- case EM_PPC: reltype = R_PPC_ADDR32; gpfx = '_'; break;
- case EM_PPC64: reltype = R_PPC64_ADDR64; gpfx = '_'; break;
- case EM_S390: /* reltype: e_class */ gpfx = '_'; break;
- case EM_SH: reltype = R_SH_DIR32; break;
- case EM_SPARCV9: reltype = R_SPARC_64; gpfx = '_'; break;
+ reltype = R_AARCH64_ABS64;
+ make_nop = make_nop_arm64;
+ rel_type_nop = R_AARCH64_NONE;
+ ideal_nop = ideal_nop4_arm64;
+ break;
+ case EM_IA_64: reltype = R_IA64_IMM64; break;
+ case EM_MIPS: /* reltype: e_class */ break;
+ case EM_PPC: reltype = R_PPC_ADDR32; break;
+ case EM_PPC64: reltype = R_PPC64_ADDR64; break;
+ case EM_S390: /* reltype: e_class */ break;
+ case EM_SH: reltype = R_SH_DIR32; gpfx = 0; break;
+ case EM_SPARCV9: reltype = R_SPARC_64; break;
case EM_X86_64:
make_nop = make_nop_x86;
ideal_nop = ideal_nop5_x86_64;
reltype = R_X86_64_64;
rel_type_nop = R_X86_64_NONE;
mcount_adjust_64 = -1;
+ gpfx = 0;
break;
} /* end switch */
@@ -543,20 +552,20 @@
default:
fprintf(stderr, "unrecognized ELF class %d %s\n",
ehdr->e_ident[EI_CLASS], fname);
- fail_file();
- break;
+ goto out;
case ELFCLASS32:
if (w2(ehdr->e_ehsize) != sizeof(Elf32_Ehdr)
|| w2(ehdr->e_shentsize) != sizeof(Elf32_Shdr)) {
fprintf(stderr,
"unrecognized ET_REL file: %s\n", fname);
- fail_file();
+ goto out;
}
if (w2(ehdr->e_machine) == EM_MIPS) {
reltype = R_MIPS_32;
is_fake_mcount32 = MIPS32_is_fake_mcount;
}
- do32(ehdr, fname, reltype);
+ if (do32(ehdr, fname, reltype) < 0)
+ goto out;
break;
case ELFCLASS64: {
Elf64_Ehdr *const ghdr = (Elf64_Ehdr *)ehdr;
@@ -564,7 +573,7 @@
|| w2(ghdr->e_shentsize) != sizeof(Elf64_Shdr)) {
fprintf(stderr,
"unrecognized ET_REL file: %s\n", fname);
- fail_file();
+ goto out;
}
if (w2(ghdr->e_machine) == EM_S390) {
reltype = R_390_64;
@@ -576,17 +585,20 @@
Elf64_r_info = MIPS64_r_info;
is_fake_mcount64 = MIPS64_is_fake_mcount;
}
- do64(ghdr, fname, reltype);
+ if (do64(ghdr, fname, reltype) < 0)
+ goto out;
break;
}
} /* end switch */
- write_file(fname);
- cleanup();
+ rc = write_file(fname);
+out:
+ file_append_cleanup();
+ mmap_cleanup();
+ return rc;
}
-int
-main(int argc, char *argv[])
+int main(int argc, char *argv[])
{
const char ftrace[] = "/ftrace.o";
int ftrace_size = sizeof(ftrace) - 1;
@@ -613,7 +625,6 @@
/* Process each file in turn, allowing deep failure. */
for (i = optind; i < argc; i++) {
char *file = argv[i];
- int const sjval = setjmp(jmpenv);
int len;
/*
@@ -626,28 +637,10 @@
strcmp(file + (len - ftrace_size), ftrace) == 0)
continue;
- switch (sjval) {
- default:
- fprintf(stderr, "internal error: %s\n", file);
- exit(1);
- break;
- case SJ_SETJMP: /* normal sequence */
- /* Avoid problems if early cleanup() */
- fd_map = -1;
- mmap_failed = 1;
- file_map = NULL;
- file_ptr = NULL;
- file_updated = 0;
- do_file(file);
- break;
- case SJ_FAIL: /* error in do_file or below */
+ if (do_file(file)) {
fprintf(stderr, "%s: failed\n", file);
++n_error;
- break;
- case SJ_SUCCEED: /* premature success */
- /* do nothing */
- break;
- } /* end switch */
+ }
}
return !!n_error;
}
diff --git a/scripts/recordmcount.h b/scripts/recordmcount.h
index 2e77937..74eab03 100644
--- a/scripts/recordmcount.h
+++ b/scripts/recordmcount.h
@@ -1,3 +1,4 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
/*
* recordmcount.h
*
@@ -15,8 +16,6 @@
*
* This conversion to macros was done by:
* Copyright 2010 Steven Rostedt <srostedt@redhat.com>, Red Hat Inc.
- *
- * Licensed under the GNU General Public License, version 2 (GPLv2).
*/
#undef append_func
#undef is_fake_mcount
@@ -175,7 +174,7 @@
}
/* Append the new shstrtab, Elf_Shdr[], __mcount_loc and its relocations. */
-static void append_func(Elf_Ehdr *const ehdr,
+static int append_func(Elf_Ehdr *const ehdr,
Elf_Shdr *const shstr,
uint_t const *const mloc0,
uint_t const *const mlocp,
@@ -203,15 +202,20 @@
new_e_shoff = t;
/* body for new shstrtab */
- ulseek(fd_map, sb.st_size, SEEK_SET);
- uwrite(fd_map, old_shstr_sh_offset + (void *)ehdr, old_shstr_sh_size);
- uwrite(fd_map, mc_name, 1 + strlen(mc_name));
+ if (ulseek(sb.st_size, SEEK_SET) < 0)
+ return -1;
+ if (uwrite(old_shstr_sh_offset + (void *)ehdr, old_shstr_sh_size) < 0)
+ return -1;
+ if (uwrite(mc_name, 1 + strlen(mc_name)) < 0)
+ return -1;
/* old(modified) Elf_Shdr table, word-byte aligned */
- ulseek(fd_map, t, SEEK_SET);
+ if (ulseek(t, SEEK_SET) < 0)
+ return -1;
t += sizeof(Elf_Shdr) * old_shnum;
- uwrite(fd_map, old_shoff + (void *)ehdr,
- sizeof(Elf_Shdr) * old_shnum);
+ if (uwrite(old_shoff + (void *)ehdr,
+ sizeof(Elf_Shdr) * old_shnum) < 0)
+ return -1;
/* new sections __mcount_loc and .rel__mcount_loc */
t += 2*sizeof(mcsec);
@@ -226,7 +230,8 @@
mcsec.sh_info = 0;
mcsec.sh_addralign = _w(_size);
mcsec.sh_entsize = _w(_size);
- uwrite(fd_map, &mcsec, sizeof(mcsec));
+ if (uwrite(&mcsec, sizeof(mcsec)) < 0)
+ return -1;
mcsec.sh_name = w(old_shstr_sh_size);
mcsec.sh_type = (sizeof(Elf_Rela) == rel_entsize)
@@ -240,15 +245,22 @@
mcsec.sh_info = w(old_shnum);
mcsec.sh_addralign = _w(_size);
mcsec.sh_entsize = _w(rel_entsize);
- uwrite(fd_map, &mcsec, sizeof(mcsec));
- uwrite(fd_map, mloc0, (void *)mlocp - (void *)mloc0);
- uwrite(fd_map, mrel0, (void *)mrelp - (void *)mrel0);
+ if (uwrite(&mcsec, sizeof(mcsec)) < 0)
+ return -1;
+
+ if (uwrite(mloc0, (void *)mlocp - (void *)mloc0) < 0)
+ return -1;
+ if (uwrite(mrel0, (void *)mrelp - (void *)mrel0) < 0)
+ return -1;
ehdr->e_shoff = _w(new_e_shoff);
ehdr->e_shnum = w2(2 + w2(ehdr->e_shnum)); /* {.rel,}__mcount_loc */
- ulseek(fd_map, 0, SEEK_SET);
- uwrite(fd_map, ehdr, sizeof(*ehdr));
+ if (ulseek(0, SEEK_SET) < 0)
+ return -1;
+ if (uwrite(ehdr, sizeof(*ehdr)) < 0)
+ return -1;
+ return 0;
}
static unsigned get_mcountsym(Elf_Sym const *const sym0,
@@ -326,7 +338,8 @@
if (!mcountsym)
mcountsym = get_mcountsym(sym0, relp, str0);
- if (mcountsym == Elf_r_sym(relp) && !is_fake_mcount(relp)) {
+ if (mcountsym && mcountsym == Elf_r_sym(relp) &&
+ !is_fake_mcount(relp)) {
uint_t const addend =
_w(_w(relp->r_offset) - recval + mcount_adjust);
mrelp->r_offset = _w(offbase
@@ -351,9 +364,9 @@
* that are not going to be traced. The mcount calls here will be converted
* into nops.
*/
-static void nop_mcount(Elf_Shdr const *const relhdr,
- Elf_Ehdr const *const ehdr,
- const char *const txtname)
+static int nop_mcount(Elf_Shdr const *const relhdr,
+ Elf_Ehdr const *const ehdr,
+ const char *const txtname)
{
Elf_Shdr *const shdr0 = (Elf_Shdr *)(_w(ehdr->e_shoff)
+ (void *)ehdr);
@@ -384,7 +397,7 @@
once = 1;
/* just warn? */
if (!make_nop)
- return;
+ return 0;
}
}
@@ -396,14 +409,16 @@
Elf_Rel rel;
rel = *(Elf_Rel *)relp;
Elf_r_info(&rel, Elf_r_sym(relp), rel_type_nop);
- ulseek(fd_map, (void *)relp - (void *)ehdr, SEEK_SET);
- uwrite(fd_map, &rel, sizeof(rel));
+ if (ulseek((void *)relp - (void *)ehdr, SEEK_SET) < 0)
+ return -1;
+ if (uwrite(&rel, sizeof(rel)) < 0)
+ return -1;
}
relp = (Elf_Rel const *)(rel_entsize + (void *)relp);
}
+ return 0;
}
-
/*
* Find a symbol in the given section, to be used as the base for relocating
* the table of offsets of calls to mcount. A local or global symbol suffices,
@@ -414,9 +429,10 @@
* Num: Value Size Type Bind Vis Ndx Name
* 2: 00000000 0 SECTION LOCAL DEFAULT 1
*/
-static unsigned find_secsym_ndx(unsigned const txtndx,
+static int find_secsym_ndx(unsigned const txtndx,
char const *const txtname,
uint_t *const recvalp,
+ unsigned int *sym_index,
Elf_Shdr const *const symhdr,
Elf_Ehdr const *const ehdr)
{
@@ -438,21 +454,20 @@
continue;
*recvalp = _w(symp->st_value);
- return symp - sym0;
+ *sym_index = symp - sym0;
+ return 0;
}
}
fprintf(stderr, "Cannot find symbol for section %u: %s.\n",
txtndx, txtname);
- fail_file();
+ return -1;
}
-
/* Evade ISO C restriction: no declaration after statement in has_rel_mcount. */
-static char const *
-__has_rel_mcount(Elf_Shdr const *const relhdr, /* is SHT_REL or SHT_RELA */
- Elf_Shdr const *const shdr0,
- char const *const shstrtab,
- char const *const fname)
+static char const * __has_rel_mcount(Elf_Shdr const *const relhdr, /* reltype */
+ Elf_Shdr const *const shdr0,
+ char const *const shstrtab,
+ char const *const fname)
{
/* .sh_info depends on .sh_type == SHT_REL[,A] */
Elf_Shdr const *const txthdr = &shdr0[w(relhdr->sh_info)];
@@ -461,7 +476,7 @@
if (strcmp("__mcount_loc", txtname) == 0) {
fprintf(stderr, "warning: __mcount_loc already exists: %s\n",
fname);
- succeed_file();
+ return already_has_rel_mcount;
}
if (w(txthdr->sh_type) != SHT_PROGBITS ||
!(_w(txthdr->sh_flags) & SHF_EXECINSTR))
@@ -491,6 +506,10 @@
for (; nhdr; --nhdr, ++shdrp) {
txtname = has_rel_mcount(shdrp, shdr0, shstrtab, fname);
+ if (txtname == already_has_rel_mcount) {
+ totrelsz = 0;
+ break;
+ }
if (txtname && is_mcounted_section_name(txtname))
totrelsz += _w(shdrp->sh_size);
}
@@ -499,8 +518,8 @@
/* Overall supervision for Elf32 ET_REL file. */
-static void
-do_func(Elf_Ehdr *const ehdr, char const *const fname, unsigned const reltype)
+static int do_func(Elf_Ehdr *const ehdr, char const *const fname,
+ unsigned const reltype)
{
Elf_Shdr *const shdr0 = (Elf_Shdr *)(_w(ehdr->e_shoff)
+ (void *)ehdr);
@@ -513,26 +532,54 @@
unsigned k;
/* Upper bound on space: assume all relevant relocs are for mcount. */
- unsigned const totrelsz = tot_relsize(shdr0, nhdr, shstrtab, fname);
- Elf_Rel *const mrel0 = umalloc(totrelsz);
- Elf_Rel * mrelp = mrel0;
+ unsigned totrelsz;
- /* 2*sizeof(address) <= sizeof(Elf_Rel) */
- uint_t *const mloc0 = umalloc(totrelsz>>1);
- uint_t * mlocp = mloc0;
+ Elf_Rel * mrel0;
+ Elf_Rel * mrelp;
+
+ uint_t * mloc0;
+ uint_t * mlocp;
unsigned rel_entsize = 0;
unsigned symsec_sh_link = 0;
+ int result = 0;
+
+ totrelsz = tot_relsize(shdr0, nhdr, shstrtab, fname);
+ if (totrelsz == 0)
+ return 0;
+ mrel0 = umalloc(totrelsz);
+ mrelp = mrel0;
+ if (!mrel0)
+ return -1;
+
+ /* 2*sizeof(address) <= sizeof(Elf_Rel) */
+ mloc0 = umalloc(totrelsz>>1);
+ mlocp = mloc0;
+ if (!mloc0) {
+ free(mrel0);
+ return -1;
+ }
+
for (relhdr = shdr0, k = nhdr; k; --k, ++relhdr) {
char const *const txtname = has_rel_mcount(relhdr, shdr0,
shstrtab, fname);
+ if (txtname == already_has_rel_mcount) {
+ result = 0;
+ file_updated = 0;
+ goto out; /* Nothing to be done; don't append! */
+ }
if (txtname && is_mcounted_section_name(txtname)) {
+ unsigned int recsym;
uint_t recval = 0;
- unsigned const recsym = find_secsym_ndx(
- w(relhdr->sh_info), txtname, &recval,
- &shdr0[symsec_sh_link = w(relhdr->sh_link)],
- ehdr);
+
+ symsec_sh_link = w(relhdr->sh_link);
+ result = find_secsym_ndx(w(relhdr->sh_info), txtname,
+ &recval, &recsym,
+ &shdr0[symsec_sh_link],
+ ehdr);
+ if (result)
+ goto out;
rel_entsize = _w(relhdr->sh_entsize);
mlocp = sift_rel_mcount(mlocp,
@@ -543,13 +590,17 @@
* This section is ignored by ftrace, but still
* has mcount calls. Convert them to nops now.
*/
- nop_mcount(relhdr, ehdr, txtname);
+ if (nop_mcount(relhdr, ehdr, txtname) < 0) {
+ result = -1;
+ goto out;
+ }
}
}
- if (mloc0 != mlocp) {
- append_func(ehdr, shstr, mloc0, mlocp, mrel0, mrelp,
- rel_entsize, symsec_sh_link);
- }
+ if (!result && mloc0 != mlocp)
+ result = append_func(ehdr, shstr, mloc0, mlocp, mrel0, mrelp,
+ rel_entsize, symsec_sh_link);
+out:
free(mrel0);
free(mloc0);
+ return result;
}
diff --git a/scripts/recordmcount.pl b/scripts/recordmcount.pl
index f599031..3f77a5d 100755
--- a/scripts/recordmcount.pl
+++ b/scripts/recordmcount.pl
@@ -1,6 +1,6 @@
#!/usr/bin/env perl
+# SPDX-License-Identifier: GPL-2.0-only
# (c) 2008, Steven Rostedt <srostedt@redhat.com>
-# Licensed under the terms of the GNU GPL License version 2
#
# recordmcount.pl - makes a section called __mcount_loc that holds
# all the offsets to the calls to mcount.
@@ -142,6 +142,11 @@
".text.unlikely" => 1,
);
+# Acceptable section-prefixes to record.
+my %text_section_prefixes = (
+ ".text." => 1,
+);
+
# Note: we are nice to C-programmers here, thus we skip the '||='-idiom.
$objdump = 'objdump' if (!$objdump);
$objcopy = 'objcopy' if (!$objcopy);
@@ -392,6 +397,9 @@
} elsif ($arch eq "nds32") {
$mcount_regex = "^\\s*([0-9a-fA-F]+):\\s*R_NDS32_HI20_RELA\\s+_mcount\$";
$alignment = 2;
+} elsif ($arch eq "csky") {
+ $mcount_regex = "^\\s*([0-9a-fA-F]+):\\s*R_CKCORE_PCREL_JSR_IMM26BY2\\s+_mcount\$";
+ $alignment = 2;
} else {
die "Arch $arch is not supported with CONFIG_FTRACE_MCOUNT_RECORD";
}
@@ -488,7 +496,7 @@
#
# Step 2: find the sections and mcount call sites
#
-open(IN, "$objdump -hdr $inputfile|") || die "error running $objdump";
+open(IN, "LANG=C $objdump -hdr $inputfile|") || die "error running $objdump";
my $text;
@@ -519,6 +527,14 @@
# Only record text sections that we know are safe
$read_function = defined($text_sections{$1});
+ if (!$read_function) {
+ foreach my $prefix (keys %text_section_prefixes) {
+ if (substr($1, 0, length $prefix) eq $prefix) {
+ $read_function = 1;
+ last;
+ }
+ }
+ }
# print out any recorded offsets
update_funcs();
diff --git a/scripts/selinux/Makefile b/scripts/selinux/Makefile
index b3048b8..59494e1 100644
--- a/scripts/selinux/Makefile
+++ b/scripts/selinux/Makefile
@@ -1 +1,2 @@
+# SPDX-License-Identifier: GPL-2.0-only
subdir-y := mdp genheaders
diff --git a/scripts/selinux/genheaders/genheaders.c b/scripts/selinux/genheaders/genheaders.c
index fa48fab..544ca12 100644
--- a/scripts/selinux/genheaders/genheaders.c
+++ b/scripts/selinux/genheaders/genheaders.c
@@ -9,7 +9,6 @@
#include <string.h>
#include <errno.h>
#include <ctype.h>
-#include <sys/socket.h>
struct security_class_mapping {
const char *name;
@@ -19,8 +18,6 @@
#include "classmap.h"
#include "initial_sid_to_string.h"
-#define max(x, y) (((int)(x) > (int)(y)) ? x : y)
-
const char *progname;
static void usage(void)
@@ -46,11 +43,9 @@
int main(int argc, char *argv[])
{
- int i, j, k;
+ int i, j;
int isids_len;
FILE *fout;
- const char *needle = "SOCKET";
- char *substr;
progname = argv[0];
@@ -80,20 +75,14 @@
for (i = 0; secclass_map[i].name; i++) {
struct security_class_mapping *map = &secclass_map[i];
- fprintf(fout, "#define SECCLASS_%s", map->name);
- for (j = 0; j < max(1, 40 - strlen(map->name)); j++)
- fprintf(fout, " ");
- fprintf(fout, "%2d\n", i+1);
+ fprintf(fout, "#define SECCLASS_%-39s %2d\n", map->name, i+1);
}
fprintf(fout, "\n");
for (i = 1; i < isids_len; i++) {
const char *s = initial_sid_to_string[i];
- fprintf(fout, "#define SECINITSID_%s", s);
- for (j = 0; j < max(1, 40 - strlen(s)); j++)
- fprintf(fout, " ");
- fprintf(fout, "%2d\n", i);
+ 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");
@@ -101,9 +90,10 @@
fprintf(fout, "\tbool sock = false;\n\n");
fprintf(fout, "\tswitch (kern_tclass) {\n");
for (i = 0; secclass_map[i].name; i++) {
+ static char s[] = "SOCKET";
struct security_class_mapping *map = &secclass_map[i];
- substr = strstr(map->name, needle);
- if (substr && strcmp(substr, needle) == 0)
+ int len = strlen(map->name), l = sizeof(s) - 1;
+ if (len >= l && memcmp(map->name + len - l, s, l) == 0)
fprintf(fout, "\tcase SECCLASS_%s:\n", map->name);
}
fprintf(fout, "\t\tsock = true;\n");
@@ -129,17 +119,15 @@
for (i = 0; secclass_map[i].name; i++) {
struct security_class_mapping *map = &secclass_map[i];
+ int len = strlen(map->name);
for (j = 0; map->perms[j]; j++) {
if (j >= 32) {
fprintf(stderr, "Too many permissions to fit into an access vector at (%s, %s).\n",
map->name, map->perms[j]);
exit(5);
}
- fprintf(fout, "#define %s__%s", map->name,
- map->perms[j]);
- for (k = 0; k < max(1, 40 - strlen(map->name) - strlen(map->perms[j])); k++)
- fprintf(fout, " ");
- fprintf(fout, "0x%08xU\n", (1<<j));
+ fprintf(fout, "#define %s__%-*s 0x%08xU\n", map->name,
+ 39-len, map->perms[j], 1U<<j);
}
}
diff --git a/scripts/selinux/install_policy.sh b/scripts/selinux/install_policy.sh
index 0b86c47..2dccf14 100755
--- a/scripts/selinux/install_policy.sh
+++ b/scripts/selinux/install_policy.sh
@@ -1,30 +1,61 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
+set -e
if [ `id -u` -ne 0 ]; then
echo "$0: must be root to install the selinux policy"
exit 1
fi
+
SF=`which setfiles`
if [ $? -eq 1 ]; then
- if [ -f /sbin/setfiles ]; then
- SF="/usr/setfiles"
- else
- echo "no selinux tools installed: setfiles"
- exit 1
- fi
+ echo "Could not find setfiles"
+ echo "Do you have policycoreutils installed?"
+ exit 1
+fi
+
+CP=`which checkpolicy`
+if [ $? -eq 1 ]; then
+ echo "Could not find checkpolicy"
+ echo "Do you have checkpolicy installed?"
+ exit 1
+fi
+VERS=`$CP -V | awk '{print $1}'`
+
+ENABLED=`which selinuxenabled`
+if [ $? -eq 1 ]; then
+ echo "Could not find selinuxenabled"
+ echo "Do you have libselinux-utils installed?"
+ exit 1
+fi
+
+if selinuxenabled; then
+ echo "SELinux is already enabled"
+ echo "This prevents safely relabeling all files."
+ echo "Boot with selinux=0 on the kernel command-line or"
+ echo "SELINUX=disabled in /etc/selinux/config."
+ exit 1
fi
cd mdp
-
-CP=`which checkpolicy`
-VERS=`$CP -V | awk '{print $1}'`
-
-./mdp policy.conf file_contexts
-$CP -o policy.$VERS policy.conf
+./mdp -m policy.conf file_contexts
+$CP -U allow -M -o policy.$VERS policy.conf
mkdir -p /etc/selinux/dummy/policy
mkdir -p /etc/selinux/dummy/contexts/files
+echo "__default__:user_u:s0" > /etc/selinux/dummy/seusers
+echo "base_r:base_t:s0" > /etc/selinux/dummy/contexts/failsafe_context
+echo "base_r:base_t:s0 base_r:base_t:s0" > /etc/selinux/dummy/default_contexts
+cat > /etc/selinux/dummy/contexts/x_contexts <<EOF
+client * user_u:base_r:base_t:s0
+property * user_u:object_r:base_t:s0
+extension * user_u:object_r:base_t:s0
+selection * user_u:object_r:base_t:s0
+event * user_u:object_r:base_t:s0
+EOF
+touch /etc/selinux/dummy/contexts/virtual_domain_context
+touch /etc/selinux/dummy/contexts/virtual_image_context
+
cp file_contexts /etc/selinux/dummy/contexts/files
cp dbus_contexts /etc/selinux/dummy/contexts
cp policy.$VERS /etc/selinux/dummy/policy
@@ -33,37 +64,22 @@
if [ ! -d /etc/selinux ]; then
mkdir -p /etc/selinux
fi
-if [ ! -f /etc/selinux/config ]; then
- cat > /etc/selinux/config << EOF
-SELINUX=enforcing
+if [ -f /etc/selinux/config ]; then
+ echo "/etc/selinux/config exists, moving to /etc/selinux/config.bak."
+ mv /etc/selinux/config /etc/selinux/config.bak
+fi
+echo "Creating new /etc/selinux/config for dummy policy."
+cat > /etc/selinux/config << EOF
+SELINUX=permissive
SELINUXTYPE=dummy
EOF
-else
- TYPE=`cat /etc/selinux/config | grep "^SELINUXTYPE" | tail -1 | awk -F= '{ print $2 '}`
- if [ "eq$TYPE" != "eqdummy" ]; then
- selinuxenabled
- if [ $? -eq 0 ]; then
- echo "SELinux already enabled with a non-dummy policy."
- echo "Exiting. Please install policy by hand if that"
- echo "is what you REALLY want."
- exit 1
- fi
- mv /etc/selinux/config /etc/selinux/config.mdpbak
- grep -v "^SELINUXTYPE" /etc/selinux/config.mdpbak >> /etc/selinux/config
- echo "SELINUXTYPE=dummy" >> /etc/selinux/config
- fi
-fi
cd /etc/selinux/dummy/contexts/files
-$SF file_contexts /
+$SF -F file_contexts /
-mounts=`cat /proc/$$/mounts | egrep "ext2|ext3|xfs|jfs|ext4|ext4dev|gfs2" | awk '{ print $2 '}`
-$SF file_contexts $mounts
+mounts=`cat /proc/$$/mounts | \
+ egrep "ext[234]|jfs|xfs|reiserfs|jffs2|gfs2|btrfs|f2fs|ocfs2" | \
+ awk '{ print $2 '}`
+$SF -F file_contexts $mounts
-
-dodev=`cat /proc/$$/mounts | grep "/dev "`
-if [ "eq$dodev" != "eq" ]; then
- mount --move /dev /mnt
- $SF file_contexts /dev
- mount --move /mnt /dev
-fi
+echo "-F" > /.autorelabel
diff --git a/scripts/selinux/mdp/Makefile b/scripts/selinux/mdp/Makefile
index e9c92db..8a1269a 100644
--- a/scripts/selinux/mdp/Makefile
+++ b/scripts/selinux/mdp/Makefile
@@ -2,7 +2,7 @@
hostprogs-y := mdp
HOST_EXTRACFLAGS += \
-I$(srctree)/include/uapi -I$(srctree)/include \
- -I$(srctree)/security/selinux/include
+ -I$(srctree)/security/selinux/include -I$(objtree)/include
always := $(hostprogs-y)
clean-files := policy.* file_contexts
diff --git a/scripts/selinux/mdp/mdp.c b/scripts/selinux/mdp/mdp.c
index 073fe75..576d11a 100644
--- a/scripts/selinux/mdp/mdp.c
+++ b/scripts/selinux/mdp/mdp.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
/*
*
* mdp - make dummy policy
@@ -5,20 +6,6 @@
* When pointed at a kernel tree, builds a dummy policy for that kernel
* with exactly one type with full rights to itself.
*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- *
* Copyright (C) IBM Corporation, 2006
*
* Authors: Serge E. Hallyn <serue@us.ibm.com>
@@ -32,7 +19,7 @@
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
-#include <sys/socket.h>
+#include <linux/kconfig.h>
static void usage(char *name)
{
@@ -95,10 +82,31 @@
}
fprintf(fout, "\n");
- /* NOW PRINT OUT MLS STUFF */
+ /* print out mls declarations and constraints */
if (mls) {
- printf("MLS not yet implemented\n");
- exit(1);
+ fprintf(fout, "sensitivity s0;\n");
+ fprintf(fout, "sensitivity s1;\n");
+ fprintf(fout, "dominance { s0 s1 }\n");
+ fprintf(fout, "category c0;\n");
+ fprintf(fout, "category c1;\n");
+ fprintf(fout, "level s0:c0.c1;\n");
+ fprintf(fout, "level s1:c0.c1;\n");
+#define SYSTEMLOW "s0"
+#define SYSTEMHIGH "s1:c0.c1"
+ for (i = 0; secclass_map[i].name; i++) {
+ struct security_class_mapping *map = &secclass_map[i];
+
+ fprintf(fout, "mlsconstrain %s {\n", map->name);
+ for (j = 0; map->perms[j]; j++)
+ fprintf(fout, "\t%s\n", map->perms[j]);
+ /*
+ * This requires all subjects and objects to be
+ * single-level (l2 eq h2), and that the subject
+ * level dominate the object level (h1 dom h2)
+ * in order to have any permissions to it.
+ */
+ fprintf(fout, "} (l2 eq h2 and h1 dom h2);\n\n");
+ }
}
/* types, roles, and allows */
@@ -108,34 +116,127 @@
for (i = 0; secclass_map[i].name; i++)
fprintf(fout, "allow base_t base_t:%s *;\n",
secclass_map[i].name);
- fprintf(fout, "user user_u roles { base_r };\n");
- fprintf(fout, "\n");
+ fprintf(fout, "user user_u roles { base_r }");
+ if (mls)
+ fprintf(fout, " level %s range %s - %s", SYSTEMLOW,
+ SYSTEMLOW, SYSTEMHIGH);
+ fprintf(fout, ";\n");
+
+#define SUBJUSERROLETYPE "user_u:base_r:base_t"
+#define OBJUSERROLETYPE "user_u:object_r:base_t"
/* default sids */
for (i = 1; i < initial_sid_to_string_len; i++)
- fprintf(fout, "sid %s user_u:base_r:base_t\n", initial_sid_to_string[i]);
+ fprintf(fout, "sid %s " SUBJUSERROLETYPE "%s\n",
+ initial_sid_to_string[i], mls ? ":" SYSTEMLOW : "");
fprintf(fout, "\n");
- fprintf(fout, "fs_use_xattr ext2 user_u:base_r:base_t;\n");
- fprintf(fout, "fs_use_xattr ext3 user_u:base_r:base_t;\n");
- fprintf(fout, "fs_use_xattr ext4 user_u:base_r:base_t;\n");
- fprintf(fout, "fs_use_xattr jfs user_u:base_r:base_t;\n");
- fprintf(fout, "fs_use_xattr xfs user_u:base_r:base_t;\n");
- fprintf(fout, "fs_use_xattr reiserfs user_u:base_r:base_t;\n");
- fprintf(fout, "fs_use_xattr jffs2 user_u:base_r:base_t;\n");
- fprintf(fout, "fs_use_xattr gfs2 user_u:base_r:base_t;\n");
+#define FS_USE(behavior, fstype) \
+ fprintf(fout, "fs_use_%s %s " OBJUSERROLETYPE "%s;\n", \
+ behavior, fstype, mls ? ":" SYSTEMLOW : "")
- fprintf(fout, "fs_use_task eventpollfs user_u:base_r:base_t;\n");
- fprintf(fout, "fs_use_task pipefs user_u:base_r:base_t;\n");
- fprintf(fout, "fs_use_task sockfs user_u:base_r:base_t;\n");
+ /*
+ * Filesystems whose inode labels can be fetched via getxattr.
+ */
+#ifdef CONFIG_EXT2_FS_SECURITY
+ FS_USE("xattr", "ext2");
+#endif
+#ifdef CONFIG_EXT4_FS_SECURITY
+#ifdef CONFIG_EXT4_USE_FOR_EXT2
+ FS_USE("xattr", "ext2");
+#endif
+ FS_USE("xattr", "ext3");
+ FS_USE("xattr", "ext4");
+#endif
+#ifdef CONFIG_JFS_SECURITY
+ FS_USE("xattr", "jfs");
+#endif
+#ifdef CONFIG_REISERFS_FS_SECURITY
+ FS_USE("xattr", "reiserfs");
+#endif
+#ifdef CONFIG_JFFS2_FS_SECURITY
+ FS_USE("xattr", "jffs2");
+#endif
+#ifdef CONFIG_XFS_FS
+ FS_USE("xattr", "xfs");
+#endif
+#ifdef CONFIG_GFS2_FS
+ FS_USE("xattr", "gfs2");
+#endif
+#ifdef CONFIG_BTRFS_FS
+ FS_USE("xattr", "btrfs");
+#endif
+#ifdef CONFIG_F2FS_FS_SECURITY
+ FS_USE("xattr", "f2fs");
+#endif
+#ifdef CONFIG_OCFS2_FS
+ FS_USE("xattr", "ocsfs2");
+#endif
+#ifdef CONFIG_OVERLAY_FS
+ FS_USE("xattr", "overlay");
+#endif
+#ifdef CONFIG_SQUASHFS_XATTR
+ FS_USE("xattr", "squashfs");
+#endif
- fprintf(fout, "fs_use_trans mqueue user_u:base_r:base_t;\n");
- fprintf(fout, "fs_use_trans devpts user_u:base_r:base_t;\n");
- fprintf(fout, "fs_use_trans hugetlbfs user_u:base_r:base_t;\n");
- fprintf(fout, "fs_use_trans tmpfs user_u:base_r:base_t;\n");
- fprintf(fout, "fs_use_trans shm user_u:base_r:base_t;\n");
+ /*
+ * Filesystems whose inodes are labeled from allocating task.
+ */
+ FS_USE("task", "pipefs");
+ FS_USE("task", "sockfs");
- fprintf(fout, "genfscon proc / user_u:base_r:base_t\n");
+ /*
+ * Filesystems whose inode labels are computed from both
+ * the allocating task and the superblock label.
+ */
+#ifdef CONFIG_UNIX98_PTYS
+ FS_USE("trans", "devpts");
+#endif
+#ifdef CONFIG_HUGETLBFS
+ FS_USE("trans", "hugetlbfs");
+#endif
+#ifdef CONFIG_TMPFS
+ FS_USE("trans", "tmpfs");
+#endif
+#ifdef CONFIG_DEVTMPFS
+ FS_USE("trans", "devtmpfs");
+#endif
+#ifdef CONFIG_POSIX_MQUEUE
+ FS_USE("trans", "mqueue");
+#endif
+
+#define GENFSCON(fstype, prefix) \
+ fprintf(fout, "genfscon %s %s " OBJUSERROLETYPE "%s\n", \
+ fstype, prefix, mls ? ":" SYSTEMLOW : "")
+
+ /*
+ * Filesystems whose inodes are labeled from path prefix match
+ * relative to the filesystem root. Depending on the filesystem,
+ * only a single label for all inodes may be supported. Here
+ * we list the filesystem types for which per-file labeling is
+ * supported using genfscon; any other filesystem type can also
+ * be added by only with a single entry for all of its inodes.
+ */
+#ifdef CONFIG_PROC_FS
+ GENFSCON("proc", "/");
+#endif
+#ifdef CONFIG_SECURITY_SELINUX
+ GENFSCON("selinuxfs", "/");
+#endif
+#ifdef CONFIG_SYSFS
+ GENFSCON("sysfs", "/");
+#endif
+#ifdef CONFIG_DEBUG_FS
+ GENFSCON("debugfs", "/");
+#endif
+#ifdef CONFIG_TRACING
+ GENFSCON("tracefs", "/");
+#endif
+#ifdef CONFIG_PSTORE
+ GENFSCON("pstore", "/");
+#endif
+ GENFSCON("cgroup", "/");
+ GENFSCON("cgroup2", "/");
fclose(fout);
@@ -144,8 +245,8 @@
printf("Wrote policy, but cannot open %s for writing\n", ctxout);
usage(argv[0]);
}
- fprintf(fout, "/ user_u:base_r:base_t\n");
- fprintf(fout, "/.* user_u:base_r:base_t\n");
+ fprintf(fout, "/ " OBJUSERROLETYPE "%s\n", mls ? ":" SYSTEMLOW : "");
+ fprintf(fout, "/.* " OBJUSERROLETYPE "%s\n", mls ? ":" SYSTEMLOW : "");
fclose(fout);
return 0;
diff --git a/scripts/setlocalversion b/scripts/setlocalversion
index 71f3941..a2998b1 100755
--- a/scripts/setlocalversion
+++ b/scripts/setlocalversion
@@ -73,8 +73,16 @@
printf -- '-svn%s' "`git svn find-rev $head`"
fi
- # Check for uncommitted changes
- if git diff-index --name-only HEAD | grep -qv "^scripts/package"; then
+ # Check for uncommitted changes.
+ # First, with git-status, but --no-optional-locks is only
+ # supported in git >= 2.14, so fall back to git-diff-index if
+ # it fails. Note that git-diff-index does not refresh the
+ # index, so it may give misleading results. See
+ # git-update-index(1), git-diff-index(1), and git-status(1).
+ if {
+ git --no-optional-locks status -uno --porcelain 2>/dev/null ||
+ git diff-index --name-only HEAD
+ } | grep -qvE '^(.. )?scripts/package'; then
printf '%s' -dirty
fi
@@ -85,7 +93,7 @@
# Check for mercurial and a mercurial repo.
if test -d .hg && hgid=`hg id 2>/dev/null`; then
# Do we have an tagged version? If so, latesttagdistance == 1
- if [ "`hg log -r . --template '{latesttagdistance}'`" == "1" ]; then
+ if [ "`hg log -r . --template '{latesttagdistance}'`" = "1" ]; then
id=`hg log -r . --template '{latesttag}'`
printf '%s%s' -hg "$id"
else
@@ -118,7 +126,7 @@
collect_files()
{
- local file res
+ local file res=
for file; do
case "$file" in
diff --git a/scripts/show_delta b/scripts/show_delta
index 5b36500..2643993 100755
--- a/scripts/show_delta
+++ b/scripts/show_delta
@@ -1,4 +1,5 @@
#!/usr/bin/python
+# SPDX-License-Identifier: GPL-2.0-only
#
# show_deltas: Read list of printk messages instrumented with
# time data, and format with time deltas.
@@ -7,7 +8,6 @@
#
# Copyright 2003 Sony Corporation
#
-# GPL 2.0 applies.
import sys
import string
diff --git a/scripts/sortextable.c b/scripts/sortextable.c
index 365a907..5576865 100644
--- a/scripts/sortextable.c
+++ b/scripts/sortextable.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0-only
/*
* sortextable.c: Sort the kernel's exception table
*
@@ -6,7 +7,6 @@
* Based on code taken from recortmcount.c which is:
*
* Copyright 2009 John F. Reiser <jreiser@BitWagon.com>. All rights reserved.
- * Licensed under the GNU General Public License, version 2 (GPLv2).
*
* Restructured to fit Linux format, as well as other updates:
* Copyright 2010 Steven Rostedt <srostedt@redhat.com>, Red Hat Inc.
diff --git a/scripts/sortextable.h b/scripts/sortextable.h
index ba87004..d4b3f6c 100644
--- a/scripts/sortextable.h
+++ b/scripts/sortextable.h
@@ -1,3 +1,4 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
/*
* sortextable.h
*
@@ -7,9 +8,6 @@
*
* Copyright 2009 John F. Reiser <jreiser@BitWagon.com>. All rights reserved.
* Copyright 2010 Steven Rostedt <srostedt@redhat.com>, Red Hat Inc.
- *
- *
- * Licensed under the GNU General Public License, version 2 (GPLv2).
*/
#undef extable_ent_size
diff --git a/scripts/spdxcheck-test.sh b/scripts/spdxcheck-test.sh
new file mode 100644
index 0000000..cfea6a0
--- /dev/null
+++ b/scripts/spdxcheck-test.sh
@@ -0,0 +1,12 @@
+#!/bin/sh
+
+for PYTHON in python2 python3; do
+ # run check on a text and a binary file
+ for FILE in Makefile Documentation/logo.gif; do
+ $PYTHON scripts/spdxcheck.py $FILE
+ $PYTHON scripts/spdxcheck.py - < $FILE
+ done
+
+ # run check on complete tree to catch any other issues
+ $PYTHON scripts/spdxcheck.py > /dev/null
+done
diff --git a/scripts/spdxcheck.py b/scripts/spdxcheck.py
index e559c62..6374e07 100755
--- a/scripts/spdxcheck.py
+++ b/scripts/spdxcheck.py
@@ -32,7 +32,8 @@
def read_spdxdata(repo):
# The subdirectories of LICENSES in the kernel source
- license_dirs = [ "preferred", "other", "exceptions" ]
+ # Note: exceptions needs to be parsed as last directory.
+ license_dirs = [ "preferred", "dual", "deprecated", "exceptions" ]
lictree = repo.head.commit.tree['LICENSES']
spdx = SPDXdata()
@@ -58,13 +59,13 @@
elif l.startswith('SPDX-Licenses:'):
for lic in l.split(':')[1].upper().strip().replace(' ', '').replace('\t', '').split(','):
if not lic in spdx.licenses:
- raise SPDXException(None, 'Exception %s missing license %s' %(ex, lic))
+ raise SPDXException(None, 'Exception %s missing license %s' %(exception, lic))
spdx.exceptions[exception].append(lic)
elif l.startswith("License-Text:"):
if exception:
if not len(spdx.exceptions[exception]):
- raise SPDXException(el, 'Exception %s is missing SPDX-Licenses' %excid)
+ raise SPDXException(el, 'Exception %s is missing SPDX-Licenses' %exception)
spdx.exception_files += 1
else:
spdx.license_files += 1
@@ -175,7 +176,13 @@
self.lines_checked += 1
if line.find("SPDX-License-Identifier:") < 0:
continue
- expr = line.split(':')[1].replace('*/', '').strip()
+ expr = line.split(':')[1].strip()
+ # Remove trailing comment closure
+ if line.strip().endswith('*/'):
+ expr = expr.rstrip('*/').strip()
+ # Special case for SH magic boot code files
+ if line.startswith('LIST \"'):
+ expr = expr.rstrip('\"').strip()
self.parse(expr)
self.spdx_valid += 1
#
diff --git a/scripts/spelling.txt b/scripts/spelling.txt
index 517d0c3..de75b9f 100644
--- a/scripts/spelling.txt
+++ b/scripts/spelling.txt
@@ -10,6 +10,8 @@
abandonning||abandoning
abigious||ambiguous
abitrate||arbitrate
+abnornally||abnormally
+abnrormal||abnormal
abord||abort
aboslute||absolute
abov||above
@@ -39,6 +41,7 @@
accross||across
acessable||accessible
acess||access
+acessing||accessing
achitecture||architecture
acient||ancient
acitions||actions
@@ -52,6 +55,7 @@
actived||activated
actualy||actually
acumulating||accumulating
+acumulative||accumulative
acumulator||accumulator
adapater||adapter
addional||additional
@@ -101,12 +105,14 @@
alot||a lot
alow||allow
alows||allows
+alredy||already
altough||although
alue||value
ambigious||ambiguous
amoung||among
amout||amount
amplifer||amplifier
+amplifyer||amplifier
an union||a union
an user||a user
an userspace||a userspace
@@ -145,6 +151,7 @@
asign||assign
asser||assert
assertation||assertion
+assertting||asserting
assiged||assigned
assigment||assignment
assigments||assignments
@@ -168,6 +175,8 @@
attched||attached
attemps||attempts
attemping||attempting
+attepmpt||attempt
+attnetion||attention
attruibutes||attributes
authentification||authentication
automaticaly||automatically
@@ -217,6 +226,8 @@
borad||board
boundry||boundary
brievely||briefly
+brigde||bridge
+broadcase||broadcast
broadcat||broadcast
bufufer||buffer
cacluated||calculated
@@ -232,8 +243,10 @@
cancelation||cancellation
cancle||cancel
capabilites||capabilities
+capabilties||capabilities
capabilty||capability
capabitilies||capabilities
+capablity||capability
capatibilities||capabilities
capapbilities||capabilities
caputure||capture
@@ -274,6 +287,7 @@
closeing||closing
clustred||clustered
coexistance||coexistence
+colescing||coalescing
collapsable||collapsible
colorfull||colorful
comand||command
@@ -290,6 +304,7 @@
comsuming||consuming
compability||compatibility
compaibility||compatibility
+comparsion||comparison
compatability||compatibility
compatable||compatible
compatibiliy||compatibility
@@ -303,6 +318,7 @@
complient||compliant
componnents||components
compoment||component
+comppatible||compatible
compres||compress
compresion||compression
comression||compression
@@ -314,6 +330,7 @@
connecetd||connected
configuartion||configuration
configuation||configuration
+configued||configured
configuratoin||configuration
configuraton||configuration
configuretion||configuration
@@ -368,6 +385,8 @@
decription||description
dectected||detected
defailt||default
+deferal||deferral
+deffered||deferred
defferred||deferred
definate||definite
definately||definitely
@@ -394,12 +413,14 @@
desactivate||deactivate
desciptor||descriptor
desciptors||descriptors
+descripto||descriptor
descripton||description
descrition||description
descritptor||descriptor
desctiptor||descriptor
desriptor||descriptor
desriptors||descriptors
+desination||destination
destionation||destination
destoried||destroyed
destory||destroy
@@ -418,6 +439,7 @@
devided||divided
deviece||device
diable||disable
+dicline||decline
dictionnary||dictionary
didnt||didn't
diferent||different
@@ -426,7 +448,9 @@
differenciate||differentiate
diffrentiate||differentiate
difinition||definition
+dimention||dimension
dimesions||dimensions
+dispalying||displaying
diplay||display
directon||direction
direectly||directly
@@ -442,8 +466,10 @@
disconnet||disconnect
discontinous||discontinuous
disharge||discharge
+disnabled||disabled
dispertion||dispersion
dissapears||disappears
+dissconect||disconnect
distiction||distinction
divisable||divisible
divsiors||divisors
@@ -452,10 +478,14 @@
documentaion||documentation
documment||document
doesnt||doesn't
+donwload||download
+donwloading||downloading
dorp||drop
dosen||doesn
downlad||download
downlads||downloads
+droped||dropped
+droput||dropout
druing||during
dynmaic||dynamic
eanable||enable
@@ -464,6 +494,7 @@
edditable||editable
editting||editing
efective||effective
+effectivness||effectiveness
efficently||efficiently
ehther||ether
eigth||eight
@@ -471,6 +502,7 @@
eletronic||electronic
embeded||embedded
enabledi||enabled
+enble||enable
enchanced||enhanced
encorporating||incorporating
encrupted||encrypted
@@ -479,6 +511,9 @@
endianess||endianness
enhaced||enhanced
enlightnment||enlightenment
+enqueing||enqueuing
+entires||entries
+entites||entities
entrys||entries
enocded||encoded
enterily||entirely
@@ -498,6 +533,8 @@
excecutable||executable
exceded||exceeded
excellant||excellent
+execeeded||exceeded
+execeeds||exceeds
exeed||exceed
existance||existence
existant||existent
@@ -506,6 +543,7 @@
exlcusive||exclusive
exmaple||example
expecially||especially
+experies||expires
explicite||explicit
explicitely||explicitly
explict||explicit
@@ -518,9 +556,11 @@
extention||extension
extenstion||extension
extracter||extractor
+faied||failed
faield||failed
falied||failed
faild||failed
+failded||failed
failer||failure
faill||fail
failied||failed
@@ -540,6 +580,8 @@
fetaures||features
fileystem||filesystem
fimware||firmware
+firmare||firmware
+firmaware||firmware
firware||firmware
finanize||finalize
findn||find
@@ -574,6 +616,9 @@
furthur||further
futhermore||furthermore
futrue||future
+gatable||gateable
+gateing||gating
+gauage||gauge
gaurenteed||guaranteed
generiously||generously
genereate||generate
@@ -613,9 +658,11 @@
imblance||imbalance
immeadiately||immediately
immedaite||immediate
+immedate||immediate
immediatelly||immediately
immediatly||immediately
immidiate||immediate
+immutible||immutable
impelentation||implementation
impementated||implemented
implemantation||implementation
@@ -633,10 +680,12 @@
incomming||incoming
incompatabilities||incompatibilities
incompatable||incompatible
+incompatble||incompatible
inconsistant||inconsistent
increas||increase
incremeted||incremented
incrment||increment
+inculde||include
indendation||indentation
indended||intended
independant||independent
@@ -645,6 +694,7 @@
indiate||indicate
indicat||indicate
inexpect||inexpected
+inferface||interface
infomation||information
informatiom||information
informations||information
@@ -662,14 +712,17 @@
initializiation||initialization
initialze||initialize
initialzed||initialized
+initialzing||initializing
initilization||initialization
initilize||initialize
inofficial||unofficial
inrerface||interface
insititute||institute
+instace||instance
instal||install
instanciate||instantiate
instanciated||instantiated
+insufficent||insufficient
inteface||interface
integreated||integrated
integrety||integrity
@@ -684,6 +737,8 @@
internel||internal
interoprability||interoperability
interuupt||interrupt
+interupt||interrupt
+interupts||interrupts
interrface||interface
interrrupt||interrupt
interrup||interrupt
@@ -699,11 +754,14 @@
intialized||initialized
intialize||initialize
intregral||integral
+intrerrupt||interrupt
intrrupt||interrupt
intterrupt||interrupt
intuative||intuitive
inavlid||invalid
invaid||invalid
+invaild||invalid
+invailid||invalid
invald||invalid
invalde||invalid
invalide||invalid
@@ -712,6 +770,7 @@
invididual||individual
invokation||invocation
invokations||invocations
+ireelevant||irrelevant
irrelevent||irrelevant
isnt||isn't
isssue||issue
@@ -740,6 +799,7 @@
librairies||libraries
libraris||libraries
licenceing||licencing
+logaritmic||logarithmic
loggging||logging
loggin||login
logile||logfile
@@ -747,6 +807,7 @@
loosing||losing
losted||lost
machinary||machinery
+maibox||mailbox
maintainance||maintenance
maintainence||maintenance
maintan||maintain
@@ -758,14 +819,19 @@
managment||management
mangement||management
manoeuvering||maneuvering
+manufaucturing||manufacturing
mappping||mapping
matchs||matches
mathimatical||mathematical
mathimatic||mathematic
mathimatics||mathematics
+maximium||maximum
maxium||maximum
mechamism||mechanism
meetign||meeting
+memeory||memory
+memmber||member
+memoery||memory
ment||meant
mergable||mergeable
mesage||message
@@ -779,6 +845,7 @@
milliseonds||milliseconds
minium||minimum
minimam||minimum
+miniumum||minimum
minumum||minimum
misalinged||misaligned
miscelleneous||miscellaneous
@@ -787,6 +854,7 @@
mispelt||misspelt
mising||missing
mismactch||mismatch
+missign||missing
missmanaged||mismanaged
missmatch||mismatch
miximum||maximum
@@ -803,6 +871,7 @@
mroe||more
mulitplied||multiplied
multidimensionnal||multidimensional
+multipe||multiple
multple||multiple
mumber||number
muticast||multicast
@@ -825,7 +894,9 @@
nessessary||necessary
noticable||noticeable
notications||notifications
+notifcations||notifications
notifed||notified
+notity||notify
numebr||number
numner||number
obtaion||obtain
@@ -839,8 +910,10 @@
occure||occurred
occured||occurred
occuring||occurring
+offser||offset
offet||offset
offloded||offloaded
+offseting||offsetting
omited||omitted
omiting||omitting
omitt||omit
@@ -855,6 +928,7 @@
orientatied||orientated
orientied||oriented
orignal||original
+originial||original
otherise||otherwise
ouput||output
oustanding||outstanding
@@ -874,6 +948,7 @@
packge||package
packtes||packets
pakage||package
+paket||packet
pallette||palette
paln||plan
paramameters||parameters
@@ -886,6 +961,8 @@
parmaters||parameters
particuarly||particularly
particularily||particularly
+partion||partition
+partions||partitions
partiton||partition
pased||passed
passin||passing
@@ -897,10 +974,12 @@
pendantic||pedantic
peprocessor||preprocessor
perfoming||performing
+peripherial||peripheral
permissons||permissions
peroid||period
persistance||persistence
persistant||persistent
+phoneticly||phonetically
plalform||platform
platfoem||platform
platfrom||platform
@@ -915,6 +994,7 @@
positon||position
possibilites||possibilities
powerfull||powerful
+pramater||parameter
preamle||preamble
preample||preamble
preapre||prepare
@@ -956,6 +1036,8 @@
programm||program
programms||programs
progresss||progress
+prohibitted||prohibited
+prohibitting||prohibiting
promiscous||promiscuous
promps||prompts
pronnounced||pronounced
@@ -970,12 +1052,14 @@
protable||portable
protcol||protocol
protecion||protection
+protedcted||protected
protocoll||protocol
promixity||proximity
psudo||pseudo
psuedo||pseudo
psychadelic||psychedelic
pwoer||power
+queing||queuing
quering||querying
randomally||randomly
raoming||roaming
@@ -983,6 +1067,7 @@
reasearchers||researchers
reasearch||research
recepient||recipient
+recevied||received
receving||receiving
recieved||received
recieve||receive
@@ -1004,6 +1089,7 @@
refernces||references
refernnce||reference
refrence||reference
+registed||registered
registerd||registered
registeration||registration
registeresd||registered
@@ -1018,6 +1104,7 @@
reigstration||registration
releated||related
relevent||relevant
+reloade||reload
remoote||remote
remore||remote
removeable||removable
@@ -1036,20 +1123,25 @@
requst||request
reregisteration||reregistration
reseting||resetting
+reseved||reserved
reseverd||reserved
resizeable||resizable
resouce||resource
resouces||resources
resoures||resources
responce||response
+resrouce||resource
ressizes||resizes
ressource||resource
ressources||resources
restesting||retesting
+resumbmitting||resubmitting
retransmited||retransmitted
retreived||retrieved
retreive||retrieve
+retreiving||retrieving
retrive||retrieve
+retrived||retrieved
retuned||returned
reudce||reduce
reuest||request
@@ -1085,7 +1177,6 @@
sentivite||sensitive
separatly||separately
sepcify||specify
-sepc||spec
seperated||separated
seperately||separately
seperate||separate
@@ -1117,9 +1208,11 @@
singal||signal
singed||signed
sleeped||slept
+sliped||slipped
softwares||software
speach||speech
specfic||specific
+specfield||specified
speciefied||specified
specifc||specific
specifed||specified
@@ -1142,7 +1235,10 @@
standardss||standards
standartization||standardization
standart||standard
+standy||standby
+stardard||standard
staticly||statically
+statuss||status
stoped||stopped
stoping||stopping
stoppped||stopped
@@ -1219,6 +1315,7 @@
threshhold||threshold
thresold||threshold
throught||through
+trackling||tracking
troughput||throughput
thses||these
tiggers||triggers
@@ -1227,12 +1324,14 @@
timeing||timing
timout||timeout
tmis||this
+toogle||toggle
torerable||tolerable
traking||tracking
tramsmitted||transmitted
tramsmit||transmit
tranasction||transaction
tranfer||transfer
+transcevier||transceiver
transciever||transceiver
transferd||transferred
transfered||transferred
@@ -1267,6 +1366,7 @@
unifiy||unify
uniterrupted||uninterrupted
unintialized||uninitialized
+unitialized||uninitialized
unkmown||unknown
unknonw||unknown
unknow||unknown
@@ -1291,7 +1391,9 @@
unsuported||unsupported
untill||until
unuseful||useless
+unvalid||invalid
upate||update
+upsupported||unsupported
usefule||useful
usefull||useful
usege||usage
@@ -1340,5 +1442,6 @@
workarould||workaround
writeing||writing
writting||writing
+wtih||with
zombe||zombie
zomebie||zombie
diff --git a/scripts/sphinx-pre-install b/scripts/sphinx-pre-install
index 0674597..3b638c0 100755
--- a/scripts/sphinx-pre-install
+++ b/scripts/sphinx-pre-install
@@ -1,20 +1,16 @@
#!/usr/bin/perl
+# SPDX-License-Identifier: GPL-2.0-or-later
use strict;
-# Copyright (c) 2017 Mauro Carvalho Chehab <mchehab@kernel.org>
+# Copyright (c) 2017-2019 Mauro Carvalho Chehab <mchehab@kernel.org>
#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-my $virtenv_dir = "sphinx_1.4";
-my $requirement_file = "Documentation/sphinx/requirements.txt";
+my $prefix = "./";
+$prefix = "$ENV{'srctree'}/" if ($ENV{'srctree'});
+
+my $conf = $prefix . "Documentation/conf.py";
+my $requirement_file = $prefix . "Documentation/sphinx/requirements.txt";
+my $virtenv_prefix = "sphinx_";
#
# Static vars
@@ -26,7 +22,10 @@
my $optional = 0;
my $need_symlink = 0;
my $need_sphinx = 0;
+my $rec_sphinx_upgrade = 0;
my $install = "";
+my $virtenv_dir = "";
+my $min_version;
#
# Command line arguments
@@ -34,6 +33,7 @@
my $pdf = 1;
my $virtualenv = 1;
+my $version_check = 0;
#
# List of required texlive packages on Fedora and OpenSuse
@@ -83,6 +83,17 @@
foreach my $prog (sort keys %missing) {
my $is_optional = $missing{$prog};
+ # At least on some LTS distros like CentOS 7, texlive doesn't
+ # provide all packages we need. When such distros are
+ # detected, we have to disable PDF output.
+ #
+ # So, we need to ignore the packages that distros would
+ # need for LaTeX to work
+ if ($is_optional == 2 && !$pdf) {
+ $optional--;
+ next;
+ }
+
if ($is_optional) {
print "Warning: better to also install \"$prog\".\n";
} else {
@@ -201,13 +212,15 @@
}
}
-sub check_sphinx()
+sub get_sphinx_fname()
{
- return if findprog("sphinx-build");
+ my $fname = "sphinx-build";
+ return $fname if findprog($fname);
- if (findprog("sphinx-build-3")) {
+ $fname = "sphinx-build-3";
+ if (findprog($fname)) {
$need_symlink = 1;
- return;
+ return $fname;
}
if ($virtualenv) {
@@ -219,6 +232,74 @@
} else {
add_package("python-sphinx", 0);
}
+
+ return "";
+}
+
+sub check_sphinx()
+{
+ my $rec_version;
+ my $cur_version;
+
+ open IN, $conf or die "Can't open $conf";
+ while (<IN>) {
+ if (m/^\s*needs_sphinx\s*=\s*[\'\"]([\d\.]+)[\'\"]/) {
+ $min_version=$1;
+ last;
+ }
+ }
+ close IN;
+
+ die "Can't get needs_sphinx version from $conf" if (!$min_version);
+
+ open IN, $requirement_file or die "Can't open $requirement_file";
+ while (<IN>) {
+ if (m/^\s*Sphinx\s*==\s*([\d\.]+)$/) {
+ $rec_version=$1;
+ last;
+ }
+ }
+ close IN;
+
+ die "Can't get recommended sphinx version from $requirement_file" if (!$min_version);
+
+ $virtenv_dir = $virtenv_prefix . $rec_version;
+
+ my $sphinx = get_sphinx_fname();
+ return if ($sphinx eq "");
+
+ open IN, "$sphinx --version 2>&1 |" or die "$sphinx returned an error";
+ while (<IN>) {
+ if (m/^\s*sphinx-build\s+([\d\.]+)$/) {
+ $cur_version=$1;
+ last;
+ }
+ # Sphinx 1.2.x uses a different format
+ if (m/^\s*Sphinx.*\s+([\d\.]+)$/) {
+ $cur_version=$1;
+ last;
+ }
+ }
+ close IN;
+
+ die "$sphinx didn't return its version" if (!$cur_version);
+
+ if ($cur_version lt $min_version) {
+ printf "ERROR: Sphinx version is %s. It should be >= %s (recommended >= %s)\n",
+ $cur_version, $min_version, $rec_version;;
+ $need_sphinx = 1;
+ return;
+ }
+
+ if ($cur_version lt $rec_version) {
+ printf "Sphinx version %s\n", $cur_version;
+ print "Warning: It is recommended at least Sphinx version $rec_version.\n";
+ $rec_sphinx_upgrade = 1;
+ return;
+ }
+
+ # On version check mode, just assume Sphinx has all mandatory deps
+ exit (0) if ($version_check);
}
#
@@ -263,10 +344,13 @@
if ($pdf) {
check_missing_file("/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf",
- "fonts-dejavu", 1);
+ "fonts-dejavu", 2);
+
+ check_missing_file("/usr/share/fonts/noto-cjk/NotoSansCJK-Regular.ttc",
+ "fonts-noto-cjk", 2);
}
- check_program("dvipng", 1) if ($pdf);
+ check_program("dvipng", 2) if ($pdf);
check_missing(\%map);
return if (!$need && !$optional);
@@ -293,6 +377,7 @@
my @fedora_tex_pkgs = (
"texlive-collection-fontsrecommended",
"texlive-collection-latex",
+ "texlive-xecjk",
"dejavu-sans-fonts",
"dejavu-serif-fonts",
"dejavu-sans-mono-fonts",
@@ -301,22 +386,45 @@
#
# Checks valid for RHEL/CentOS version 7.x.
#
- if (! $system_release =~ /Fedora/) {
+ my $old = 0;
+ my $rel;
+ $rel = $1 if ($system_release =~ /release\s+(\d+)/);
+
+ if (!($system_release =~ /Fedora/)) {
$map{"virtualenv"} = "python-virtualenv";
+
+ if ($rel && $rel < 8) {
+ $old = 1;
+ $pdf = 0;
+
+ printf("Note: texlive packages on RHEL/CENTOS <= 7 are incomplete. Can't support PDF output\n");
+ printf("If you want to build PDF, please read:\n");
+ printf("\thttps://www.systutorials.com/241660/how-to-install-tex-live-on-centos-7-linux/\n");
+ }
+ } else {
+ if ($rel && $rel < 26) {
+ $old = 1;
+ }
+ }
+ if (!$rel) {
+ printf("Couldn't identify release number\n");
+ $old = 1;
+ $pdf = 0;
}
- my $release;
+ if ($pdf) {
+ check_missing_file("/usr/share/fonts/google-noto-cjk/NotoSansCJK-Regular.ttc",
+ "google-noto-sans-cjk-ttc-fonts", 2);
+ }
- $release = $1 if ($system_release =~ /Fedora\s+release\s+(\d+)/);
-
- check_rpm_missing(\@fedora26_opt_pkgs, 1) if ($pdf && $release >= 26);
- check_rpm_missing(\@fedora_tex_pkgs, 1) if ($pdf);
- check_missing_tex(1) if ($pdf);
+ check_rpm_missing(\@fedora26_opt_pkgs, 2) if ($pdf && !$old);
+ check_rpm_missing(\@fedora_tex_pkgs, 2) if ($pdf);
+ check_missing_tex(2) if ($pdf);
check_missing(\%map);
return if (!$need && !$optional);
- if ($release >= 18) {
+ if (!$old) {
# dnf, for Fedora 18+
printf("You should run:\n\n\tsudo dnf install -y $install\n");
} else {
@@ -355,8 +463,15 @@
"texlive-zapfding",
);
- check_rpm_missing(\@suse_tex_pkgs, 1) if ($pdf);
- check_missing_tex(1) if ($pdf);
+ $map{"latexmk"} = "texlive-latexmk-bin";
+
+ # FIXME: add support for installing CJK fonts
+ #
+ # I tried hard, but was unable to find a way to install
+ # "Noto Sans CJK SC" on openSUSE
+
+ check_rpm_missing(\@suse_tex_pkgs, 2) if ($pdf);
+ check_missing_tex(2) if ($pdf);
check_missing(\%map);
return if (!$need && !$optional);
@@ -380,7 +495,14 @@
"texlive-fontsextra",
);
- check_rpm_missing(\@tex_pkgs, 1) if ($pdf);
+ $map{"latexmk"} = "texlive-collection-basic";
+
+ if ($pdf) {
+ check_missing_file("/usr/share/fonts/google-noto-cjk/NotoSansCJK-Regular.ttc",
+ "google-noto-sans-cjk-ttc-fonts", 2);
+ }
+
+ check_rpm_missing(\@tex_pkgs, 2) if ($pdf);
check_missing(\%map);
return if (!$need && !$optional);
@@ -403,7 +525,13 @@
"texlive-latexextra",
"ttf-dejavu",
);
- check_pacman_missing(\@archlinux_tex_pkgs, 1) if ($pdf);
+ check_pacman_missing(\@archlinux_tex_pkgs, 2) if ($pdf);
+
+ if ($pdf) {
+ check_missing_file("/usr/share/fonts/noto-cjk/NotoSansCJK-Regular.ttc",
+ "noto-fonts-cjk", 2);
+ }
+
check_missing(\%map);
return if (!$need && !$optional);
@@ -422,15 +550,31 @@
);
check_missing_file("/usr/share/fonts/dejavu/DejaVuSans.ttf",
- "media-fonts/dejavu", 1) if ($pdf);
+ "media-fonts/dejavu", 2) if ($pdf);
+
+ if ($pdf) {
+ check_missing_file("/usr/share/fonts/noto-cjk/NotoSansCJKsc-Regular.otf",
+ "media-fonts/noto-cjk", 2);
+ }
check_missing(\%map);
return if (!$need && !$optional);
printf("You should run:\n\n");
- printf("\tsudo su -c 'echo \"media-gfx/imagemagick svg png\" > /etc/portage/package.use/imagemagick'\n");
- printf("\tsudo su -c 'echo \"media-gfx/graphviz cairo pdf\" > /etc/portage/package.use/graphviz'\n");
+
+ my $imagemagick = "media-gfx/imagemagick svg png";
+ my $cairo = "media-gfx/graphviz cairo pdf";
+ my $portage_imagemagick = "/etc/portage/package.use/imagemagick";
+ my $portage_cairo = "/etc/portage/package.use/graphviz";
+
+ if (qx(cat $portage_imagemagick) ne "$imagemagick\n") {
+ printf("\tsudo su -c 'echo \"$imagemagick\" > $portage_imagemagick'\n")
+ }
+ if (qx(cat $portage_cairo) ne "$cairo\n") {
+ printf("\tsudo su -c 'echo \"$cairo\" > $portage_cairo'\n");
+ }
+
printf("\tsudo emerge --ask $install\n");
}
@@ -490,7 +634,7 @@
my %map = (
"sphinx-build" => "sphinx"
);
- check_missing_tex(1) if ($pdf);
+ check_missing_tex(2) if ($pdf);
check_missing(\%map);
print "I don't know distro $system_release.\n";
print "So, I can't provide you a hint with the install procedure.\n";
@@ -503,35 +647,29 @@
sub check_needs()
{
- if ($system_release) {
- print "Detected OS: $system_release.\n";
- } else {
- print "Unknown OS\n";
- }
-
- # RHEL 7.x and clones have Sphinx version 1.1.x and incomplete texlive
- if (($system_release =~ /Red Hat Enterprise Linux/) ||
- ($system_release =~ /CentOS/) ||
- ($system_release =~ /Scientific Linux/) ||
- ($system_release =~ /Oracle Linux Server/)) {
- $virtualenv = 1;
- $pdf = 0;
-
- printf("NOTE: On this distro, Sphinx and TexLive shipped versions are incompatible\n");
- printf("with doc build. So, use Sphinx via a Python virtual environment.\n\n");
- printf("This script can't install a TexLive version that would provide PDF.\n");
- }
-
# Check for needed programs/tools
check_sphinx();
+
+ if ($system_release) {
+ print "Detected OS: $system_release.\n\n";
+ } else {
+ print "Unknown OS\n\n";
+ }
+
+ print "To upgrade Sphinx, use:\n\n" if ($rec_sphinx_upgrade);
+
+ # Check for needed programs/tools
check_perl_module("Pod::Usage", 0);
check_program("make", 0);
check_program("gcc", 0);
check_python_module("sphinx_rtd_theme", 1) if (!$virtualenv);
- check_program("xelatex", 1) if ($pdf);
check_program("dot", 1);
check_program("convert", 1);
- check_program("rsvg-convert", 1) if ($pdf);
+
+ # Extra PDF files - should use 2 for is_optional
+ check_program("xelatex", 2) if ($pdf);
+ check_program("rsvg-convert", 2) if ($pdf);
+ check_program("latexmk", 2) if ($pdf);
check_distros();
@@ -539,26 +677,33 @@
printf "\tsudo ln -sf %s /usr/bin/sphinx-build\n\n",
which("sphinx-build-3");
}
- if ($need_sphinx) {
- my $activate = "$virtenv_dir/bin/activate";
- if (-e "$ENV{'PWD'}/$activate") {
- printf "\nNeed to activate virtualenv with:\n";
- printf "\t. $activate\n";
+ if ($need_sphinx || $rec_sphinx_upgrade) {
+ my $min_activate = "$ENV{'PWD'}/${virtenv_prefix}${min_version}/bin/activate";
+ my @activates = glob "$ENV{'PWD'}/${virtenv_prefix}*/bin/activate";
+
+ @activates = sort {$b cmp $a} @activates;
+
+ if ($need_sphinx && scalar @activates > 0 && $activates[0] ge $min_activate) {
+ printf "\nNeed to activate a compatible Sphinx version on virtualenv with:\n";
+ printf "\t. $activates[0]\n";
+ exit (1);
} else {
+ my $rec_activate = "$virtenv_dir/bin/activate";
my $virtualenv = findprog("virtualenv-3");
$virtualenv = findprog("virtualenv-3.5") if (!$virtualenv);
$virtualenv = findprog("virtualenv") if (!$virtualenv);
$virtualenv = "virtualenv" if (!$virtualenv);
printf "\t$virtualenv $virtenv_dir\n";
- printf "\t. $activate\n";
+ printf "\t. $rec_activate\n";
printf "\tpip install -r $requirement_file\n";
- $need++;
+
+ $need++ if (!$rec_sphinx_upgrade);
}
}
printf "\n";
- print "All optional dependenties are met.\n" if (!$optional);
+ print "All optional dependencies are met.\n" if (!$optional);
if ($need == 1) {
die "Can't build as $need mandatory dependency is missing";
@@ -580,8 +725,14 @@
$virtualenv = 0;
} elsif ($arg eq "--no-pdf"){
$pdf = 0;
+ } elsif ($arg eq "--version-check"){
+ $version_check = 1;
} else {
- print "Usage:\n\t$0 <--no-virtualenv> <--no-pdf>\n\n";
+ print "Usage:\n\t$0 <--no-virtualenv> <--no-pdf> <--version-check>\n\n";
+ print "Where:\n";
+ print "\t--no-virtualenv\t- Recommend installing Sphinx instead of using a virtualenv\n";
+ print "\t--version-check\t- if version is compatible, don't check for missing dependencies\n";
+ print "\t--no-pdf\t- don't check for dependencies required to build PDF docs\n\n";
exit -1;
}
}
diff --git a/scripts/tags.sh b/scripts/tags.sh
index 26de7d5..4e18ae5 100755
--- a/scripts/tags.sh
+++ b/scripts/tags.sh
@@ -1,11 +1,12 @@
#!/bin/bash
+# SPDX-License-Identifier: GPL-2.0-only
# Generate tags or cscope files
# Usage tags.sh <mode>
#
# mode may be any of: tags, TAGS, cscope
#
# Uses the following environment variables:
-# ARCH, SUBARCH, SRCARCH, srctree, src, obj
+# SUBARCH, SRCARCH, srctree
if [ "$KBUILD_VERBOSE" = "1" ]; then
set -x
@@ -16,10 +17,9 @@
# tags and cscope files should also ignore MODVERSION *.mod.c files
ignore="$ignore ( -name *.mod.c ) -prune -o"
-# Do not use full path if we do not use O=.. builds
-# Use make O=. {tags|cscope}
+# Use make KBUILD_ABS_SRCTREE=1 {tags|cscope}
# to force full paths for a non-O= build
-if [ "${KBUILD_SRC}" = "" ]; then
+if [ "${srctree}" = "." -o -z "${srctree}" ]; then
tree=
else
tree=${srctree}/
@@ -35,21 +35,19 @@
ALLSOURCE_ARCHS=$(find ${tree}arch/ -mindepth 1 -maxdepth 1 -type d -printf '%f ')
fi
-# find sources in arch/$ARCH
+# find sources in arch/$1
find_arch_sources()
{
for i in $archincludedir; do
prune="$prune -wholename $i -prune -o"
done
- find ${tree}arch/$1 $ignore $subarchprune $prune -name "$2" \
- -not -type l -print;
+ find ${tree}arch/$1 $ignore $prune -name "$2" -not -type l -print;
}
# find sources in arch/$1/include
find_arch_include_sources()
{
- include=$(find ${tree}arch/$1/ $subarchprune \
- -name include -type d -print);
+ include=$(find ${tree}arch/$1/ -name include -type d -print);
if [ -n "$include" ]; then
archincludedir="$archincludedir $include"
find $include $ignore -name "$2" -not -type l -print;
@@ -191,7 +189,7 @@
'/^DEF_PCI_AC_\(\|NO\)RET(\([[:alnum:]_]*\).*/\2/'
'/^PCI_OP_READ(\(\w*\).*[1-4])/pci_bus_read_config_\1/'
'/^PCI_OP_WRITE(\(\w*\).*[1-4])/pci_bus_write_config_\1/'
- '/\<DEFINE_\(MUTEX\|SEMAPHORE\|SPINLOCK\)(\([[:alnum:]_]*\)/\2/v/'
+ '/\<DEFINE_\(RT_MUTEX\|MUTEX\|SEMAPHORE\|SPINLOCK\)(\([[:alnum:]_]*\)/\2/v/'
'/\<DEFINE_\(RAW_SPINLOCK\|RWLOCK\|SEQLOCK\)(\([[:alnum:]_]*\)/\2/v/'
'/\<DECLARE_\(RWSEM\|COMPLETION\)(\([[:alnum:]_]\+\)/\2/v/'
'/\<DECLARE_BITMAP(\([[:alnum:]_]*\)/\1/v/'
@@ -203,7 +201,16 @@
'/\<DECLARE_\(TASKLET\|WORK\|DELAYED_WORK\)(\([[:alnum:]_]*\)/\2/v/'
'/\(^\s\)OFFSET(\([[:alnum:]_]*\)/\2/v/'
'/\(^\s\)DEFINE(\([[:alnum:]_]*\)/\2/v/'
- '/\<DEFINE_HASHTABLE(\([[:alnum:]_]*\)/\1/v/'
+ '/\<\(DEFINE\|DECLARE\)_HASHTABLE(\([[:alnum:]_]*\)/\2/v/'
+ '/\<DEFINE_ID\(R\|A\)(\([[:alnum:]_]\+\)/\2/'
+ '/\<DEFINE_WD_CLASS(\([[:alnum:]_]\+\)/\1/'
+ '/\<ATOMIC_NOTIFIER_HEAD(\([[:alnum:]_]\+\)/\1/'
+ '/\<RAW_NOTIFIER_HEAD(\([[:alnum:]_]\+\)/\1/'
+ '/\<DECLARE_FAULT_ATTR(\([[:alnum:]_]\+\)/\1/'
+ '/\<BLOCKING_NOTIFIER_HEAD(\([[:alnum:]_]\+\)/\1/'
+ '/\<DEVICE_ATTR_\(RW\|RO\|WO\)(\([[:alnum:]_]\+\)/dev_attr_\2/'
+ '/\<DRIVER_ATTR_\(RW\|RO\|WO\)(\([[:alnum:]_]\+\)/driver_attr_\2/'
+ '/\<\(DEFINE\|DECLARE\)_STATIC_KEY_\(TRUE\|FALSE\)\(\|_RO\)(\([[:alnum:]_]\+\)/\4/'
)
regex_kconfig=(
'/^[[:blank:]]*\(menu\|\)config[[:blank:]]\+\([[:alnum:]_]\+\)/\2/'
@@ -249,7 +256,7 @@
-I __initdata,__exitdata,__initconst,__ro_after_init \
-I __initdata_memblock \
-I __refdata,__attribute,__maybe_unused,__always_unused \
- -I __acquires,__releases,__deprecated \
+ -I __acquires,__releases,__deprecated,__always_inline \
-I __read_mostly,__aligned,____cacheline_aligned \
-I ____cacheline_aligned_in_smp \
-I __cacheline_aligned,__cacheline_aligned_in_smp \
@@ -296,36 +303,6 @@
else
archinclude=${SUBARCH}
fi
-elif [ "${SRCARCH}" = "arm" -a "${SUBARCH}" != "" ]; then
- subarchdir=$(find ${tree}arch/$SRCARCH/ -name "mach-*" -type d -o \
- -name "plat-*" -type d);
- mach_suffix=$SUBARCH
- plat_suffix=$SUBARCH
-
- # Special cases when $plat_suffix != $mach_suffix
- case $mach_suffix in
- "omap1" | "omap2")
- plat_suffix="omap"
- ;;
- esac
-
- if [ ! -d ${tree}arch/$SRCARCH/mach-$mach_suffix ]; then
- echo "Warning: arch/arm/mach-$mach_suffix/ not found." >&2
- echo " Fix your \$SUBARCH appropriately" >&2
- fi
-
- for i in $subarchdir; do
- case "$i" in
- *"mach-"${mach_suffix})
- ;;
- *"plat-"${plat_suffix})
- ;;
- *)
- subarchprune="$subarchprune \
- -wholename $i -prune -o"
- ;;
- esac
- done
fi
remove_structs=
diff --git a/scripts/tools-support-relr.sh b/scripts/tools-support-relr.sh
new file mode 100755
index 0000000..45e8aa3
--- /dev/null
+++ b/scripts/tools-support-relr.sh
@@ -0,0 +1,16 @@
+#!/bin/sh -eu
+# SPDX-License-Identifier: GPL-2.0
+
+tmp_file=$(mktemp)
+trap "rm -f $tmp_file.o $tmp_file $tmp_file.bin" EXIT
+
+cat << "END" | $CC -c -x c - -o $tmp_file.o >/dev/null 2>&1
+void *p = &p;
+END
+$LD $tmp_file.o -shared -Bsymbolic --pack-dyn-relocs=relr -o $tmp_file
+
+# Despite printing an error message, GNU nm still exits with exit code 0 if it
+# sees a relr section. So we need to check that nothing is printed to stderr.
+test -z "$($NM $tmp_file 2>&1 >/dev/null)"
+
+$OBJCOPY -O binary $tmp_file $tmp_file.bin
diff --git a/scripts/tracing/draw_functrace.py b/scripts/tracing/draw_functrace.py
index 9b6dd4f..b657357 100755
--- a/scripts/tracing/draw_functrace.py
+++ b/scripts/tracing/draw_functrace.py
@@ -1,8 +1,8 @@
#!/usr/bin/python
+# SPDX-License-Identifier: GPL-2.0-only
"""
Copyright 2008 (c) Frederic Weisbecker <fweisbec@gmail.com>
-Licensed under the terms of the GNU GPL License version 2
This script parses a trace provided by the function tracer in
kernel/trace/trace_functions.c
diff --git a/scripts/ver_linux b/scripts/ver_linux
index a6c728d..810e608 100755
--- a/scripts/ver_linux
+++ b/scripts/ver_linux
@@ -13,6 +13,8 @@
system("uname -a")
printf("\n")
+ vernum = "[0-9]+([.]?[0-9]+)+"
+
printversion("GNU C", version("gcc -dumpversion"))
printversion("GNU Make", version("make --version"))
printversion("Binutils", version("ld -v"))
@@ -34,7 +36,7 @@
while (getline <"/proc/self/maps" > 0) {
if (/libc.*\.so$/) {
n = split($0, procmaps, "/")
- if (match(procmaps[n], /[0-9]+([.]?[0-9]+)+/)) {
+ if (match(procmaps[n], vernum)) {
ver = substr(procmaps[n], RSTART, RLENGTH)
printversion("Linux C Library", ver)
break
@@ -70,7 +72,7 @@
function version(cmd, ver) {
cmd = cmd " 2>&1"
while (cmd | getline > 0) {
- if (match($0, /[0-9]+([.]?[0-9]+)+/)) {
+ if (match($0, vernum)) {
ver = substr($0, RSTART, RLENGTH)
break
}