summaryrefslogtreecommitdiff
path: root/scripts
diff options
context:
space:
mode:
Diffstat (limited to 'scripts')
-rw-r--r--scripts/Kbuild.include6
-rw-r--r--scripts/Kconfig.include2
-rw-r--r--scripts/Makefile11
-rw-r--r--scripts/Makefile.btf19
-rw-r--r--scripts/Makefile.build37
-rw-r--r--scripts/Makefile.compiler2
-rw-r--r--scripts/Makefile.defconf8
-rw-r--r--scripts/Makefile.dtbinst32
-rw-r--r--scripts/Makefile.extrawarn28
-rw-r--r--scripts/Makefile.host4
-rw-r--r--scripts/Makefile.lib46
-rw-r--r--scripts/Makefile.modfinal7
-rw-r--r--scripts/Makefile.package38
-rw-r--r--scripts/Makefile.ubsan5
-rw-r--r--scripts/Makefile.userprogs6
-rw-r--r--scripts/Makefile.vdsoinst45
-rw-r--r--scripts/Makefile.vmlinux1
-rw-r--r--scripts/Makefile.vmlinux_o3
-rwxr-xr-xscripts/atomic/gen-atomic-fallback.sh33
-rwxr-xr-xscripts/atomic/gen-atomic-instrumented.sh3
-rw-r--r--scripts/atomic/kerneldoc/add_unless1
-rw-r--r--scripts/atomic/kerneldoc/cmpxchg1
-rw-r--r--scripts/atomic/kerneldoc/dec_if_positive1
-rw-r--r--scripts/atomic/kerneldoc/dec_unless_positive1
-rw-r--r--scripts/atomic/kerneldoc/inc_not_zero1
-rw-r--r--scripts/atomic/kerneldoc/inc_unless_negative1
-rw-r--r--scripts/atomic/kerneldoc/try_cmpxchg3
-rwxr-xr-xscripts/bpf_doc.py8
-rwxr-xr-xscripts/check-sysctl-docs65
-rwxr-xr-xscripts/check-uapi.sh573
-rwxr-xr-xscripts/checkpatch.pl31
-rwxr-xr-xscripts/checkstack.pl56
-rwxr-xr-xscripts/clang-tools/gen_compile_commands.py16
-rwxr-xr-xscripts/clang-tools/run-clang-tools.py32
-rw-r--r--scripts/coccinelle/api/device_attr_show.cocci17
-rw-r--r--scripts/coccinelle/api/string_choices.cocci41
-rw-r--r--scripts/coccinelle/misc/struct_size.cocci74
-rw-r--r--scripts/const_structs.checkpatch3
-rwxr-xr-xscripts/decode_stacktrace.sh22
-rwxr-xr-xscripts/decodecode5
-rwxr-xr-xscripts/dtc/dt-extract-compatibles86
-rwxr-xr-xscripts/dummy-tools/gcc10
-rwxr-xr-xscripts/faddr2line24
-rw-r--r--scripts/gcc-plugins/latent_entropy_plugin.c4
-rw-r--r--scripts/gcc-plugins/randomize_layout_plugin.c24
-rw-r--r--scripts/gcc-plugins/stackleak_plugin.c2
-rw-r--r--scripts/gdb/linux/constants.py.in18
-rw-r--r--scripts/gdb/linux/cpus.py15
-rw-r--r--scripts/gdb/linux/device.py16
-rw-r--r--scripts/gdb/linux/interrupts.py2
-rw-r--r--scripts/gdb/linux/mm.py2
-rw-r--r--scripts/gdb/linux/page_owner.py58
-rw-r--r--scripts/gdb/linux/slab.py3
-rw-r--r--scripts/gdb/linux/stackdepot.py6
-rw-r--r--scripts/gdb/linux/symbols.py2
-rw-r--r--scripts/gdb/linux/tasks.py33
-rw-r--r--scripts/gdb/linux/vmalloc.py64
-rw-r--r--scripts/generate_rust_target.rs13
-rw-r--r--scripts/genksyms/genksyms.c22
-rwxr-xr-xscripts/get_abi.pl3
-rwxr-xr-xscripts/get_maintainer.pl86
-rw-r--r--scripts/git.orderFile42
-rw-r--r--scripts/head-object-list.txt1
-rwxr-xr-xscripts/headers_install.sh2
-rw-r--r--scripts/kconfig/Makefile14
-rw-r--r--scripts/kconfig/array_size.h11
-rw-r--r--scripts/kconfig/conf.c23
-rw-r--r--scripts/kconfig/confdata.c233
-rw-r--r--scripts/kconfig/expr.c1
-rw-r--r--scripts/kconfig/expr.h29
-rw-r--r--scripts/kconfig/hashtable.h48
-rw-r--r--scripts/kconfig/internal.h12
-rw-r--r--scripts/kconfig/lexer.l130
-rw-r--r--scripts/kconfig/list.h254
-rw-r--r--scripts/kconfig/list_types.h17
-rw-r--r--scripts/kconfig/lkc.h10
-rw-r--r--scripts/kconfig/lkc_proto.h22
-rw-r--r--scripts/kconfig/lxdialog/checklist.c7
-rw-r--r--scripts/kconfig/lxdialog/dialog.h16
-rw-r--r--scripts/kconfig/lxdialog/inputbox.c2
-rw-r--r--scripts/kconfig/lxdialog/menubox.c2
-rw-r--r--scripts/kconfig/lxdialog/textbox.c2
-rw-r--r--scripts/kconfig/lxdialog/util.c22
-rw-r--r--scripts/kconfig/lxdialog/yesno.c2
-rw-r--r--scripts/kconfig/mconf.c61
-rw-r--r--scripts/kconfig/menu.c87
-rw-r--r--scripts/kconfig/mnconf-common.c53
-rw-r--r--scripts/kconfig/mnconf-common.h18
-rw-r--r--scripts/kconfig/nconf.c56
-rw-r--r--scripts/kconfig/parser.y127
-rw-r--r--scripts/kconfig/preprocess.c23
-rw-r--r--scripts/kconfig/preprocess.h19
-rw-r--r--scripts/kconfig/qconf.cc2
-rw-r--r--scripts/kconfig/symbol.c104
-rw-r--r--scripts/kconfig/tests/choice_randomize/Kconfig22
-rw-r--r--scripts/kconfig/tests/choice_randomize/__init__.py34
-rw-r--r--scripts/kconfig/tests/choice_randomize/expected_config06
-rw-r--r--scripts/kconfig/tests/choice_randomize/expected_config18
-rw-r--r--scripts/kconfig/tests/choice_randomize/expected_config28
-rw-r--r--scripts/kconfig/tests/choice_randomize2/Kconfig32
-rw-r--r--scripts/kconfig/tests/choice_randomize2/__init__.py18
-rw-r--r--scripts/kconfig/tests/choice_randomize2/expected_config08
-rw-r--r--scripts/kconfig/tests/choice_randomize2/expected_config17
-rw-r--r--scripts/kconfig/tests/choice_randomize2/expected_config26
-rw-r--r--scripts/kconfig/tests/conftest.py16
-rw-r--r--scripts/kconfig/tests/err_recursive_dep/expected_stderr22
-rw-r--r--scripts/kconfig/util.c50
-rwxr-xr-xscripts/kernel-doc2523
-rwxr-xr-xscripts/leaking_addresses.pl90
-rwxr-xr-xscripts/link-vmlinux.sh9
-rwxr-xr-xscripts/min-tool-version.sh6
-rwxr-xr-xscripts/mksysmap13
-rw-r--r--scripts/mod/Makefile4
-rw-r--r--scripts/mod/devicetable-offsets.c10
-rw-r--r--scripts/mod/file2alias.c41
-rw-r--r--scripts/mod/modpost.c261
-rw-r--r--scripts/mod/modpost.h56
-rw-r--r--scripts/mod/sumversion.c7
-rw-r--r--scripts/mod/symsearch.c199
-rwxr-xr-xscripts/package/builddeb130
-rwxr-xr-xscripts/package/buildtar8
-rwxr-xr-xscripts/package/deb-build-option14
-rw-r--r--scripts/package/debian/copyright16
-rwxr-xr-xscripts/package/debian/rules82
-rwxr-xr-xscripts/package/install-extmod-build2
-rw-r--r--scripts/package/kernel.spec76
-rwxr-xr-xscripts/package/mkdebian28
-rwxr-xr-xscripts/package/mkspec6
-rw-r--r--scripts/package/snapcraft.template2
-rwxr-xr-xscripts/pahole-flags.sh30
-rw-r--r--scripts/recordmcount.c1
-rwxr-xr-xscripts/recordmcount.pl9
-rwxr-xr-xscripts/remove-stale-files2
-rwxr-xr-xscripts/show_delta3
-rw-r--r--scripts/sign-file.c12
-rw-r--r--scripts/spelling.txt14
-rwxr-xr-xscripts/sphinx-pre-install42
-rwxr-xr-xscripts/tags.sh17
-rwxr-xr-xscripts/xz_wrap.sh1
139 files changed, 4304 insertions, 2880 deletions
diff --git a/scripts/Kbuild.include b/scripts/Kbuild.include
index 7778cc97a4e0..2f331879816b 100644
--- a/scripts/Kbuild.include
+++ b/scripts/Kbuild.include
@@ -114,12 +114,6 @@ endef
build := -f $(srctree)/scripts/Makefile.build obj
###
-# Shorthand for $(Q)$(MAKE) -f scripts/Makefile.dtbinst obj=
-# Usage:
-# $(Q)$(MAKE) $(dtbinst)=dir
-dtbinst := -f $(srctree)/scripts/Makefile.dtbinst obj
-
-###
# Shorthand for $(Q)$(MAKE) -f scripts/Makefile.clean obj=
# Usage:
# $(Q)$(MAKE) $(clean)=dir
diff --git a/scripts/Kconfig.include b/scripts/Kconfig.include
index 5a84b6443875..3ee8ecfb8c04 100644
--- a/scripts/Kconfig.include
+++ b/scripts/Kconfig.include
@@ -33,7 +33,7 @@ ld-option = $(success,$(LD) -v $(1))
# $(as-instr,<instr>)
# Return y if the assembler supports <instr>, n otherwise
-as-instr = $(success,printf "%b\n" "$(1)" | $(CC) $(CLANG_FLAGS) -c -x assembler-with-cpp -o /dev/null -)
+as-instr = $(success,printf "%b\n" "$(1)" | $(CC) $(CLANG_FLAGS) -Wa$(comma)--fatal-warnings -c -x assembler-with-cpp -o /dev/null -)
# check if $(CC) and $(LD) exist
$(error-if,$(failure,command -v $(CC)),C compiler '$(CC)' not found)
diff --git a/scripts/Makefile b/scripts/Makefile
index 576cf64be667..bc90520a5426 100644
--- a/scripts/Makefile
+++ b/scripts/Makefile
@@ -11,12 +11,14 @@ hostprogs-always-$(CONFIG_MODULE_SIG_FORMAT) += sign-file
hostprogs-always-$(CONFIG_SYSTEM_EXTRA_CERTIFICATE) += insert-sys-cert
hostprogs-always-$(CONFIG_RUST_KERNEL_DOCTESTS) += rustdoc_test_builder
hostprogs-always-$(CONFIG_RUST_KERNEL_DOCTESTS) += rustdoc_test_gen
-always-$(CONFIG_RUST) += target.json
+ifneq ($(or $(CONFIG_X86_64),$(CONFIG_LOONGARCH)),)
+always-$(CONFIG_RUST) += target.json
filechk_rust_target = $< < include/config/auto.conf
$(obj)/target.json: scripts/generate_rust_target include/config/auto.conf FORCE
$(call filechk,rust_target)
+endif
hostprogs += generate_rust_target
generate_rust_target-rust := y
@@ -31,9 +33,12 @@ HOSTLDLIBS_sign-file = $(shell $(HOSTPKG_CONFIG) --libs libcrypto 2> /dev/null |
ifdef CONFIG_UNWINDER_ORC
ifeq ($(ARCH),x86_64)
-ARCH := x86
+SRCARCH := x86
+endif
+ifeq ($(ARCH),loongarch)
+SRCARCH := loongarch
endif
-HOSTCFLAGS_sorttable.o += -I$(srctree)/tools/arch/x86/include
+HOSTCFLAGS_sorttable.o += -I$(srctree)/tools/arch/$(SRCARCH)/include
HOSTCFLAGS_sorttable.o += -DUNWINDER_ORC_ENABLED
endif
diff --git a/scripts/Makefile.btf b/scripts/Makefile.btf
new file mode 100644
index 000000000000..82377e470aed
--- /dev/null
+++ b/scripts/Makefile.btf
@@ -0,0 +1,19 @@
+# SPDX-License-Identifier: GPL-2.0
+
+pahole-ver := $(CONFIG_PAHOLE_VERSION)
+pahole-flags-y :=
+
+# pahole 1.18 through 1.21 can't handle zero-sized per-CPU vars
+ifeq ($(call test-le, $(pahole-ver), 121),y)
+pahole-flags-$(call test-ge, $(pahole-ver), 118) += --skip_encoding_btf_vars
+endif
+
+pahole-flags-$(call test-ge, $(pahole-ver), 121) += --btf_gen_floats
+
+pahole-flags-$(call test-ge, $(pahole-ver), 122) += -j
+
+pahole-flags-$(CONFIG_PAHOLE_HAS_LANG_EXCLUDE) += --lang_exclude=rust
+
+pahole-flags-$(call test-ge, $(pahole-ver), 125) += --skip_encoding_btf_inconsistent_proto --btf_gen_optimized
+
+export PAHOLE_FLAGS := $(pahole-flags-y)
diff --git a/scripts/Makefile.build b/scripts/Makefile.build
index 82e3fb19fdaf..533a7799fdfe 100644
--- a/scripts/Makefile.build
+++ b/scripts/Makefile.build
@@ -71,6 +71,7 @@ endif
# subdir-builtin and subdir-modorder may contain duplications. Use $(sort ...)
subdir-builtin := $(sort $(filter %/built-in.a, $(real-obj-y)))
subdir-modorder := $(sort $(filter %/modules.order, $(obj-m)))
+subdir-dtbslist := $(sort $(filter %/dtbs-list, $(dtb-y)))
targets-for-builtin := $(extra-y)
@@ -213,7 +214,7 @@ endif # CONFIG_FTRACE_MCOUNT_USE_RECORDMCOUNT
# 'OBJECT_FILES_NON_STANDARD_foo.o := 'y': skip objtool checking for a file
# 'OBJECT_FILES_NON_STANDARD_foo.o := 'n': override directory skip for a file
-is-standard-object = $(if $(filter-out y%, $(OBJECT_FILES_NON_STANDARD_$(basetarget).o)$(OBJECT_FILES_NON_STANDARD)n),y)
+is-standard-object = $(if $(filter-out y%, $(OBJECT_FILES_NON_STANDARD_$(target-stem).o)$(OBJECT_FILES_NON_STANDARD)n),y)
$(obj)/%.o: objtool-enabled = $(if $(is-standard-object),$(if $(delay-objtool),$(is-single-obj-m),y))
@@ -262,7 +263,7 @@ $(obj)/%.lst: $(src)/%.c FORCE
# Compile Rust sources (.rs)
# ---------------------------------------------------------------------------
-rust_allowed_features := new_uninit
+rust_allowed_features := new_uninit,offset_of
# `--out-dir` is required to avoid temporaries being created by `rustc` in the
# current working directory, which may be not accessible in the out-of-tree
@@ -272,9 +273,10 @@ rust_common_cmd = \
-Zallow-features=$(rust_allowed_features) \
-Zcrate-attr=no_std \
-Zcrate-attr='feature($(rust_allowed_features))' \
- --extern alloc --extern kernel \
+ -Zunstable-options --extern force:alloc --extern kernel \
--crate-type rlib -L $(objtree)/rust/ \
--crate-name $(basename $(notdir $@)) \
+ --sysroot=/dev/null \
--out-dir $(dir $@) --emit=dep-info=$(depfile)
# `--emit=obj`, `--emit=asm` and `--emit=llvm-ir` imply a single codegen unit
@@ -289,7 +291,7 @@ quiet_cmd_rustc_o_rs = $(RUSTC_OR_CLIPPY_QUIET) $(quiet_modtag) $@
cmd_rustc_o_rs = $(rust_common_cmd) --emit=obj=$@ $<
$(obj)/%.o: $(src)/%.rs FORCE
- $(call if_changed_dep,rustc_o_rs)
+ +$(call if_changed_dep,rustc_o_rs)
quiet_cmd_rustc_rsi_rs = $(RUSTC_OR_CLIPPY_QUIET) $(quiet_modtag) $@
cmd_rustc_rsi_rs = \
@@ -297,19 +299,19 @@ quiet_cmd_rustc_rsi_rs = $(RUSTC_OR_CLIPPY_QUIET) $(quiet_modtag) $@
command -v $(RUSTFMT) >/dev/null && $(RUSTFMT) $@
$(obj)/%.rsi: $(src)/%.rs FORCE
- $(call if_changed_dep,rustc_rsi_rs)
+ +$(call if_changed_dep,rustc_rsi_rs)
quiet_cmd_rustc_s_rs = $(RUSTC_OR_CLIPPY_QUIET) $(quiet_modtag) $@
cmd_rustc_s_rs = $(rust_common_cmd) --emit=asm=$@ $<
$(obj)/%.s: $(src)/%.rs FORCE
- $(call if_changed_dep,rustc_s_rs)
+ +$(call if_changed_dep,rustc_s_rs)
quiet_cmd_rustc_ll_rs = $(RUSTC_OR_CLIPPY_QUIET) $(quiet_modtag) $@
cmd_rustc_ll_rs = $(rust_common_cmd) --emit=llvm-ir=$@ $<
$(obj)/%.ll: $(src)/%.rs FORCE
- $(call if_changed_dep,rustc_ll_rs)
+ +$(call if_changed_dep,rustc_ll_rs)
# Compile assembler sources (.S)
# ---------------------------------------------------------------------------
@@ -387,6 +389,7 @@ $(obj)/%.asn1.c $(obj)/%.asn1.h: $(src)/%.asn1 $(objtree)/scripts/asn1_compiler
# To build objects in subdirs, we need to descend into the directories
$(subdir-builtin): $(obj)/%/built-in.a: $(obj)/% ;
$(subdir-modorder): $(obj)/%/modules.order: $(obj)/% ;
+$(subdir-dtbslist): $(obj)/%/dtbs-list: $(obj)/% ;
#
# Rule to compile a set of .o files into one .a file (without symbol table)
@@ -403,19 +406,21 @@ $(obj)/built-in.a: $(real-obj-y) FORCE
$(call if_changed,ar_builtin)
#
-# Rule to create modules.order file
+# Rule to create modules.order and dtbs-list
#
-# Create commands to either record .ko file or cat modules.order from
-# a subdirectory
-# Add $(obj-m) as the prerequisite to avoid updating the timestamp of
-# modules.order unless contained modules are updated.
+# This is a list of build artifacts (module or dtb) from the current Makefile
+# and its sub-directories. The timestamp should be updated when any of the
+# member files.
-cmd_modules_order = { $(foreach m, $(real-prereqs), \
- $(if $(filter %/modules.order, $m), cat $m, echo $m);) :; } \
+cmd_gen_order = { $(foreach m, $(real-prereqs), \
+ $(if $(filter %/$(notdir $@), $m), cat $m, echo $m);) :; } \
> $@
$(obj)/modules.order: $(obj-m) FORCE
- $(call if_changed,modules_order)
+ $(call if_changed,gen_order)
+
+$(obj)/dtbs-list: $(dtb-y) FORCE
+ $(call if_changed,gen_order)
#
# Rule to compile a set of .o files into one .a file (with symbol table)
@@ -425,7 +430,7 @@ $(obj)/lib.a: $(lib-y) FORCE
$(call if_changed,ar)
quiet_cmd_ld_multi_m = LD [M] $@
- cmd_ld_multi_m = $(LD) $(ld_flags) -r -o $@ @$(patsubst %.o,%.mod,$@) $(cmd_objtool)
+ cmd_ld_multi_m = $(LD) $(ld_flags) -r -o $@ @$< $(cmd_objtool)
define rule_ld_multi_m
$(call cmd_and_savecmd,ld_multi_m)
diff --git a/scripts/Makefile.compiler b/scripts/Makefile.compiler
index 8fcb427405a6..92be0c9a13ee 100644
--- a/scripts/Makefile.compiler
+++ b/scripts/Makefile.compiler
@@ -38,7 +38,7 @@ as-option = $(call try-run,\
# Usage: aflags-y += $(call as-instr,instr,option1,option2)
as-instr = $(call try-run,\
- printf "%b\n" "$(1)" | $(CC) -Werror $(CLANG_FLAGS) $(KBUILD_AFLAGS) -c -x assembler-with-cpp -o "$$TMP" -,$(2),$(3))
+ printf "%b\n" "$(1)" | $(CC) -Werror $(CLANG_FLAGS) $(KBUILD_AFLAGS) -Wa$(comma)--fatal-warnings -c -x assembler-with-cpp -o "$$TMP" -,$(2),$(3))
# __cc-option
# Usage: MY_CFLAGS += $(call __cc-option,$(CC),$(MY_CFLAGS),-march=winchip-c6,-march=i586)
diff --git a/scripts/Makefile.defconf b/scripts/Makefile.defconf
index ab271b2051a2..226ea3df3b4b 100644
--- a/scripts/Makefile.defconf
+++ b/scripts/Makefile.defconf
@@ -9,8 +9,8 @@
# Input config fragments without '.config' suffix
define merge_into_defconfig
$(Q)$(CONFIG_SHELL) $(srctree)/scripts/kconfig/merge_config.sh \
- -m -O $(objtree) $(srctree)/arch/$(ARCH)/configs/$(1) \
- $(foreach config,$(2),$(srctree)/arch/$(ARCH)/configs/$(config).config)
+ -m -O $(objtree) $(srctree)/arch/$(SRCARCH)/configs/$(1) \
+ $(foreach config,$(2),$(srctree)/arch/$(SRCARCH)/configs/$(config).config)
+$(Q)$(MAKE) -f $(srctree)/Makefile olddefconfig
endef
@@ -23,7 +23,7 @@ endef
# Input config fragments without '.config' suffix
define merge_into_defconfig_override
$(Q)$(CONFIG_SHELL) $(srctree)/scripts/kconfig/merge_config.sh \
- -Q -m -O $(objtree) $(srctree)/arch/$(ARCH)/configs/$(1) \
- $(foreach config,$(2),$(srctree)/arch/$(ARCH)/configs/$(config).config)
+ -Q -m -O $(objtree) $(srctree)/arch/$(SRCARCH)/configs/$(1) \
+ $(foreach config,$(2),$(srctree)/arch/$(SRCARCH)/configs/$(config).config)
+$(Q)$(MAKE) -f $(srctree)/Makefile olddefconfig
endef
diff --git a/scripts/Makefile.dtbinst b/scripts/Makefile.dtbinst
index 4405d5b67578..67956f6496a5 100644
--- a/scripts/Makefile.dtbinst
+++ b/scripts/Makefile.dtbinst
@@ -8,32 +8,36 @@
# $INSTALL_PATH/dtbs/$KERNELRELEASE
# ==========================================================================
-src := $(obj)
-
PHONY := __dtbs_install
__dtbs_install:
include include/config/auto.conf
include $(srctree)/scripts/Kbuild.include
-include $(kbuild-file)
-
-dtbs := $(addprefix $(dst)/, $(dtb-y) $(if $(CONFIG_OF_ALL_DTBS),$(dtb-)))
-subdirs := $(addprefix $(obj)/, $(subdir-y) $(subdir-m))
-__dtbs_install: $(dtbs) $(subdirs)
- @:
+dst := $(INSTALL_DTBS_PATH)
quiet_cmd_dtb_install = INSTALL $@
cmd_dtb_install = install -D $< $@
-$(dst)/%.dtb: $(obj)/%.dtb
+$(dst)/%: $(obj)/%
$(call cmd,dtb_install)
-$(dst)/%.dtbo: $(obj)/%.dtbo
- $(call cmd,dtb_install)
+dtbs := $(patsubst $(obj)/%,%,$(call read-file, $(obj)/dtbs-list))
+
+ifdef CONFIG_ARCH_WANT_FLAT_DTB_INSTALL
-PHONY += $(subdirs)
-$(subdirs):
- $(Q)$(MAKE) $(dtbinst)=$@ dst=$(if $(CONFIG_ARCH_WANT_FLAT_DTB_INSTALL),$(dst),$(patsubst $(obj)/%,$(dst)/%,$@))
+define gen_install_rules
+$(dst)/%: $(obj)/$(1)%
+ $$(call cmd,dtb_install)
+endef
+
+$(foreach d, $(sort $(dir $(dtbs))), $(eval $(call gen_install_rules,$(d))))
+
+dtbs := $(notdir $(dtbs))
+
+endif # CONFIG_ARCH_WANT_FLAT_DTB_INSTALL
+
+__dtbs_install: $(addprefix $(dst)/, $(dtbs))
+ @:
.PHONY: $(PHONY)
diff --git a/scripts/Makefile.extrawarn b/scripts/Makefile.extrawarn
index 2fe6f2828d37..c5af566e911a 100644
--- a/scripts/Makefile.extrawarn
+++ b/scripts/Makefile.extrawarn
@@ -17,6 +17,8 @@ KBUILD_CFLAGS += -Wno-format-security
KBUILD_CFLAGS += -Wno-trigraphs
KBUILD_CFLAGS += $(call cc-disable-warning,frame-address,)
KBUILD_CFLAGS += $(call cc-disable-warning, address-of-packed-member)
+KBUILD_CFLAGS += -Wmissing-declarations
+KBUILD_CFLAGS += -Wmissing-prototypes
ifneq ($(CONFIG_FRAME_WARN),0)
KBUILD_CFLAGS += -Wframe-larger-than=$(CONFIG_FRAME_WARN)
@@ -80,25 +82,14 @@ KBUILD_CFLAGS += $(call cc-option,-Werror=designated-init)
# Warn if there is an enum types mismatch
KBUILD_CFLAGS += $(call cc-option,-Wenum-conversion)
-# backward compatibility
-KBUILD_EXTRA_WARN ?= $(KBUILD_ENABLE_EXTRA_GCC_CHECKS)
-
-ifeq ("$(origin W)", "command line")
- KBUILD_EXTRA_WARN := $(W)
-endif
-
-export KBUILD_EXTRA_WARN
-
#
# W=1 - warnings which may be relevant and do not occur too often
#
ifneq ($(findstring 1, $(KBUILD_EXTRA_WARN)),)
KBUILD_CFLAGS += -Wextra -Wunused -Wno-unused-parameter
-KBUILD_CFLAGS += -Wmissing-declarations
KBUILD_CFLAGS += $(call cc-option, -Wrestrict)
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)
@@ -106,7 +97,6 @@ KBUILD_CFLAGS += $(call cc-option, -Wunused-const-variable)
KBUILD_CFLAGS += $(call cc-option, -Wpacked-not-aligned)
KBUILD_CFLAGS += $(call cc-option, -Wformat-overflow)
KBUILD_CFLAGS += $(call cc-option, -Wformat-truncation)
-KBUILD_CFLAGS += $(call cc-option, -Wstringop-overflow)
KBUILD_CFLAGS += $(call cc-option, -Wstringop-truncation)
KBUILD_CPPFLAGS += -Wundef
@@ -122,9 +112,10 @@ KBUILD_CFLAGS += $(call cc-disable-warning, restrict)
KBUILD_CFLAGS += $(call cc-disable-warning, packed-not-aligned)
KBUILD_CFLAGS += $(call cc-disable-warning, format-overflow)
KBUILD_CFLAGS += $(call cc-disable-warning, format-truncation)
-KBUILD_CFLAGS += $(call cc-disable-warning, stringop-overflow)
KBUILD_CFLAGS += $(call cc-disable-warning, stringop-truncation)
+KBUILD_CFLAGS += -Wno-override-init # alias for -Wno-initializer-overrides in clang
+
ifdef CONFIG_CC_IS_CLANG
# Clang before clang-16 would warn on default argument promotions.
ifneq ($(call clang-min-version, 160000),y)
@@ -143,6 +134,8 @@ KBUILD_CFLAGS += $(call cc-disable-warning, pointer-to-enum-cast)
KBUILD_CFLAGS += -Wno-tautological-constant-out-of-range-compare
KBUILD_CFLAGS += $(call cc-disable-warning, unaligned-access)
KBUILD_CFLAGS += $(call cc-disable-warning, cast-function-type-strict)
+KBUILD_CFLAGS += -Wno-enum-compare-conditional
+KBUILD_CFLAGS += -Wno-enum-enum-conversion
endif
endif
@@ -160,10 +153,6 @@ KBUILD_CFLAGS += -Wtype-limits
KBUILD_CFLAGS += $(call cc-option, -Wmaybe-uninitialized)
KBUILD_CFLAGS += $(call cc-option, -Wunused-macros)
-ifdef CONFIG_CC_IS_CLANG
-KBUILD_CFLAGS += -Winitializer-overrides
-endif
-
KBUILD_CPPFLAGS += -DKBUILD_EXTRA_WARN2
else
@@ -173,9 +162,7 @@ KBUILD_CFLAGS += -Wno-missing-field-initializers
KBUILD_CFLAGS += -Wno-type-limits
KBUILD_CFLAGS += -Wno-shift-negative-value
-ifdef CONFIG_CC_IS_CLANG
-KBUILD_CFLAGS += -Wno-initializer-overrides
-else
+ifdef CONFIG_CC_IS_GCC
KBUILD_CFLAGS += -Wno-maybe-uninitialized
endif
@@ -196,7 +183,6 @@ KBUILD_CFLAGS += -Wpointer-arith
KBUILD_CFLAGS += -Wredundant-decls
KBUILD_CFLAGS += -Wsign-compare
KBUILD_CFLAGS += -Wswitch-default
-KBUILD_CFLAGS += $(call cc-option, -Wpacked-bitfield-compat)
KBUILD_CPPFLAGS += -DKBUILD_EXTRA_WARN3
diff --git a/scripts/Makefile.host b/scripts/Makefile.host
index 8f7f842b54f9..3c17e6ba421c 100644
--- a/scripts/Makefile.host
+++ b/scripts/Makefile.host
@@ -91,6 +91,8 @@ hostcxx_flags = -Wp,-MMD,$(depfile) \
# current working directory, which may be not accessible in the out-of-tree
# modules case.
hostrust_flags = --out-dir $(dir $@) --emit=dep-info=$(depfile) \
+ -Clinker-flavor=gcc -Clinker=$(HOSTCC) \
+ -Clink-args='$(call escsq,$(KBUILD_HOSTLDFLAGS))' \
$(KBUILD_HOSTRUSTFLAGS) $(HOST_EXTRARUSTFLAGS) \
$(HOSTRUSTFLAGS_$(target-stem))
@@ -154,7 +156,7 @@ quiet_cmd_host-rust = HOSTRUSTC $@
cmd_host-rust = \
$(HOSTRUSTC) $(hostrust_flags) --emit=link=$@ $<
$(host-rust): $(obj)/%: $(src)/%.rs FORCE
- $(call if_changed_dep,host-rust)
+ +$(call if_changed_dep,host-rust)
targets += $(host-csingle) $(host-cmulti) $(host-cobjs) \
$(host-cxxmulti) $(host-cxxobjs) $(host-rust)
diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib
index 68d0134bdbf9..3179747cbd2c 100644
--- a/scripts/Makefile.lib
+++ b/scripts/Makefile.lib
@@ -45,6 +45,11 @@ else
obj-y := $(filter-out %/, $(obj-y))
endif
+ifdef need-dtbslist
+dtb-y += $(addsuffix /dtbs-list, $(subdir-ym))
+always-y += dtbs-list
+endif
+
# Expand $(foo-objs) $(foo-y) etc. by replacing their individuals
suffix-search = $(strip $(foreach s, $3, $($(1:%$(strip $2)=%$s))))
# List composite targets that are constructed by combining other targets
@@ -83,8 +88,8 @@ dtb-$(CONFIG_OF_ALL_DTBS) += $(dtb-)
multi-dtb-y := $(call multi-search, $(dtb-y), .dtb, -dtbs)
# Primitive DTB compiled from *.dts
real-dtb-y := $(call real-search, $(dtb-y), .dtb, -dtbs)
-# Base DTB that overlay is applied onto (each first word of $(*-dtbs) expansion)
-base-dtb-y := $(foreach m, $(multi-dtb-y), $(firstword $(call suffix-search, $m, .dtb, -dtbs)))
+# Base DTB that overlay is applied onto
+base-dtb-y := $(filter %.dtb, $(call real-search, $(multi-dtb-y), .dtb, -dtbs))
always-y += $(dtb-y)
@@ -99,6 +104,7 @@ lib-y := $(addprefix $(obj)/,$(lib-y))
real-obj-y := $(addprefix $(obj)/,$(real-obj-y))
real-obj-m := $(addprefix $(obj)/,$(real-obj-m))
multi-obj-m := $(addprefix $(obj)/, $(multi-obj-m))
+dtb-y := $(addprefix $(obj)/, $(dtb-y))
multi-dtb-y := $(addprefix $(obj)/, $(multi-dtb-y))
real-dtb-y := $(addprefix $(obj)/, $(real-dtb-y))
subdir-ym := $(addprefix $(obj)/,$(subdir-ym))
@@ -148,7 +154,7 @@ _cpp_flags = $(KBUILD_CPPFLAGS) $(cppflags-y) $(CPPFLAGS_$(target-stem).lds)
#
ifeq ($(CONFIG_GCOV_KERNEL),y)
_c_flags += $(if $(patsubst n%,, \
- $(GCOV_PROFILE_$(basetarget).o)$(GCOV_PROFILE)$(CONFIG_GCOV_PROFILE_ALL)), \
+ $(GCOV_PROFILE_$(target-stem).o)$(GCOV_PROFILE)$(CONFIG_GCOV_PROFILE_ALL)), \
$(CFLAGS_GCOV))
endif
@@ -159,29 +165,32 @@ endif
ifeq ($(CONFIG_KASAN),y)
ifneq ($(CONFIG_KASAN_HW_TAGS),y)
_c_flags += $(if $(patsubst n%,, \
- $(KASAN_SANITIZE_$(basetarget).o)$(KASAN_SANITIZE)y), \
+ $(KASAN_SANITIZE_$(target-stem).o)$(KASAN_SANITIZE)y), \
$(CFLAGS_KASAN), $(CFLAGS_KASAN_NOSANITIZE))
endif
endif
ifeq ($(CONFIG_KMSAN),y)
_c_flags += $(if $(patsubst n%,, \
- $(KMSAN_SANITIZE_$(basetarget).o)$(KMSAN_SANITIZE)y), \
+ $(KMSAN_SANITIZE_$(target-stem).o)$(KMSAN_SANITIZE)y), \
$(CFLAGS_KMSAN))
_c_flags += $(if $(patsubst n%,, \
- $(KMSAN_ENABLE_CHECKS_$(basetarget).o)$(KMSAN_ENABLE_CHECKS)y), \
+ $(KMSAN_ENABLE_CHECKS_$(target-stem).o)$(KMSAN_ENABLE_CHECKS)y), \
, -mllvm -msan-disable-checks=1)
endif
ifeq ($(CONFIG_UBSAN),y)
_c_flags += $(if $(patsubst n%,, \
- $(UBSAN_SANITIZE_$(basetarget).o)$(UBSAN_SANITIZE)$(CONFIG_UBSAN_SANITIZE_ALL)), \
+ $(UBSAN_SANITIZE_$(target-stem).o)$(UBSAN_SANITIZE)y), \
$(CFLAGS_UBSAN))
+_c_flags += $(if $(patsubst n%,, \
+ $(UBSAN_SIGNED_WRAP_$(target-stem).o)$(UBSAN_SANITIZE_$(target-stem).o)$(UBSAN_SIGNED_WRAP)$(UBSAN_SANITIZE)y), \
+ $(CFLAGS_UBSAN_SIGNED_WRAP))
endif
ifeq ($(CONFIG_KCOV),y)
_c_flags += $(if $(patsubst n%,, \
- $(KCOV_INSTRUMENT_$(basetarget).o)$(KCOV_INSTRUMENT)$(CONFIG_KCOV_INSTRUMENT_ALL)), \
+ $(KCOV_INSTRUMENT_$(target-stem).o)$(KCOV_INSTRUMENT)$(CONFIG_KCOV_INSTRUMENT_ALL)), \
$(CFLAGS_KCOV))
endif
@@ -191,12 +200,12 @@ endif
#
ifeq ($(CONFIG_KCSAN),y)
_c_flags += $(if $(patsubst n%,, \
- $(KCSAN_SANITIZE_$(basetarget).o)$(KCSAN_SANITIZE)y), \
+ $(KCSAN_SANITIZE_$(target-stem).o)$(KCSAN_SANITIZE)y), \
$(CFLAGS_KCSAN))
# Some uninstrumented files provide implied barriers required to avoid false
# positives: set KCSAN_INSTRUMENT_BARRIERS for barrier instrumentation only.
_c_flags += $(if $(patsubst n%,, \
- $(KCSAN_INSTRUMENT_BARRIERS_$(basetarget).o)$(KCSAN_INSTRUMENT_BARRIERS)n), \
+ $(KCSAN_INSTRUMENT_BARRIERS_$(target-stem).o)$(KCSAN_INSTRUMENT_BARRIERS)n), \
-D__KCSAN_INSTRUMENT_BARRIERS__)
endif
@@ -254,7 +263,7 @@ objtool := $(objtree)/tools/objtool/objtool
objtool-args-$(CONFIG_HAVE_JUMP_LABEL_HACK) += --hacks=jump_label
objtool-args-$(CONFIG_HAVE_NOINSTR_HACK) += --hacks=noinstr
-objtool-args-$(CONFIG_CALL_DEPTH_TRACKING) += --hacks=skylake
+objtool-args-$(CONFIG_MITIGATION_CALL_DEPTH_TRACKING) += --hacks=skylake
objtool-args-$(CONFIG_X86_KERNEL_IBT) += --ibt
objtool-args-$(CONFIG_FINEIBT) += --cfi
objtool-args-$(CONFIG_FTRACE_MCOUNT_USE_OBJTOOL) += --mcount
@@ -262,9 +271,9 @@ ifdef CONFIG_FTRACE_MCOUNT_USE_OBJTOOL
objtool-args-$(CONFIG_HAVE_OBJTOOL_NOP_MCOUNT) += --mnop
endif
objtool-args-$(CONFIG_UNWINDER_ORC) += --orc
-objtool-args-$(CONFIG_RETPOLINE) += --retpoline
-objtool-args-$(CONFIG_RETHUNK) += --rethunk
-objtool-args-$(CONFIG_SLS) += --sls
+objtool-args-$(CONFIG_MITIGATION_RETPOLINE) += --retpoline
+objtool-args-$(CONFIG_MITIGATION_RETHUNK) += --rethunk
+objtool-args-$(CONFIG_MITIGATION_SLS) += --sls
objtool-args-$(CONFIG_STACK_VALIDATION) += --stackval
objtool-args-$(CONFIG_HAVE_STATIC_CALL_INLINE) += --static-call
objtool-args-$(CONFIG_HAVE_UACCESS_VALIDATION) += --uaccess
@@ -340,7 +349,7 @@ quiet_cmd_gzip = GZIP $@
# DTC
# ---------------------------------------------------------------------------
DTC ?= $(objtree)/scripts/dtc/dtc
-DTC_FLAGS += -Wno-interrupt_provider \
+DTC_FLAGS += \
-Wno-unique_unit_address
# Disable noisy checks by default
@@ -358,11 +367,10 @@ endif
ifneq ($(findstring 2,$(KBUILD_EXTRA_WARN)),)
DTC_FLAGS += -Wnode_name_chars_strict \
-Wproperty_name_chars_strict \
- -Winterrupt_provider \
-Wunique_unit_address
endif
-DTC_FLAGS += $(DTC_FLAGS_$(basetarget))
+DTC_FLAGS += $(DTC_FLAGS_$(target-stem))
# Set -@ if the target is a base DTB that overlay is applied onto
DTC_FLAGS += $(if $(filter $(patsubst $(obj)/%,%,$@), $(base-dtb-y)), -@)
@@ -487,14 +495,14 @@ UIMAGE_OPTS-y ?=
UIMAGE_TYPE ?= kernel
UIMAGE_LOADADDR ?= arch_must_set_this
UIMAGE_ENTRYADDR ?= $(UIMAGE_LOADADDR)
-UIMAGE_NAME ?= 'Linux-$(KERNELRELEASE)'
+UIMAGE_NAME ?= Linux-$(KERNELRELEASE)
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 $< $@
+ -n '$(UIMAGE_NAME)' -d $< $@
# XZ
# ---------------------------------------------------------------------------
diff --git a/scripts/Makefile.modfinal b/scripts/Makefile.modfinal
index b3a6aa8fbe8c..79fcf2731686 100644
--- a/scripts/Makefile.modfinal
+++ b/scripts/Makefile.modfinal
@@ -23,19 +23,16 @@ modname = $(notdir $(@:.mod.o=))
part-of-module = y
quiet_cmd_cc_o_c = CC [M] $@
- cmd_cc_o_c = $(CC) $(filter-out $(CC_FLAGS_CFI) $(CFLAGS_GCOV), $(c_flags)) -c -o $@ $<
+ cmd_cc_o_c = $(CC) $(filter-out $(CC_FLAGS_CFI) $(CFLAGS_GCOV) $(CFLAGS_KCSAN), $(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) \
- -T scripts/module.lds -o $@ $(filter %.o, $^); \
- $(if $(ARCH_POSTLINK), $(MAKE) -f $(ARCH_POSTLINK) $@, true)
+ -T scripts/module.lds -o $@ $(filter %.o, $^)
quiet_cmd_btf_ko = BTF [M] $@
cmd_btf_ko = \
diff --git a/scripts/Makefile.package b/scripts/Makefile.package
index 2bcab02da965..38653f3e8108 100644
--- a/scripts/Makefile.package
+++ b/scripts/Makefile.package
@@ -4,27 +4,6 @@
include $(srctree)/scripts/Kbuild.include
include $(srctree)/scripts/Makefile.lib
-KERNELPATH := kernel-$(subst -,_,$(KERNELRELEASE))
-# Include only those top-level files that are needed by make, plus the GPL copy
-TAR_CONTENT := Documentation LICENSES arch block certs crypto drivers fs \
- include init io_uring ipc kernel lib mm net rust \
- samples scripts security sound tools usr virt \
- .config Makefile \
- Kbuild Kconfig COPYING $(wildcard localversion*)
-
-quiet_cmd_src_tar = TAR $(2).tar.gz
- cmd_src_tar = \
-if test "$(objtree)" != "$(srctree)"; then \
- echo >&2; \
- echo >&2 " ERROR:"; \
- echo >&2 " Building source tarball is not possible outside the"; \
- echo >&2 " kernel source tree. Don't set KBUILD_OUTPUT"; \
- echo >&2; \
- false; \
-fi ; \
-tar -I $(KGZIP) -c $(RCS_TAR_IGNORE) -f $(2).tar.gz \
- --transform 's:^:$(2)/:S' $(TAR_CONTENT) $(3)
-
# Git
# ---------------------------------------------------------------------------
@@ -69,9 +48,9 @@ $(linux-tarballs): .tmp_HEAD FORCE
# ---------------------------------------------------------------------------
quiet_cmd_mkspec = GEN $@
- cmd_mkspec = $(srctree)/scripts/package/mkspec > $@
+ cmd_mkspec = $(srctree)/scripts/package/mkspec $@
-kernel.spec: FORCE
+rpmbuild/SPECS/kernel.spec: FORCE
$(call cmd,mkspec)
PHONY += rpm-sources
@@ -88,14 +67,12 @@ srcrpm-pkg: private build-type := s
binrpm-pkg: private build-type := b
rpm-pkg srcrpm-pkg: rpm-sources
-rpm-pkg srcrpm-pkg binrpm-pkg: kernel.spec
- +$(strip rpmbuild -b$(build-type) kernel.spec \
+rpm-pkg srcrpm-pkg binrpm-pkg: rpmbuild/SPECS/kernel.spec
+ +$(strip rpmbuild -b$(build-type) rpmbuild/SPECS/kernel.spec \
--define='_topdir $(abspath rpmbuild)' \
$(if $(filter a b, $(build-type)), \
--target $(UTS_MACHINE)-linux --build-in-place --noprep --define='_smp_mflags %{nil}' \
$$(rpm -q rpm >/dev/null 2>&1 || echo --nodeps)) \
- $(if $(filter b, $(build-type)), \
- --without devel) \
$(RPMOPTS))
# deb-pkg srcdeb-pkg bindeb-pkg
@@ -132,8 +109,6 @@ debian-orig: linux.tar$(debian-orig-suffix) debian
cp $< ../$(orig-name); \
fi
-KBUILD_PKG_ROOTCMD ?= 'fakeroot -u'
-
PHONY += deb-pkg srcdeb-pkg bindeb-pkg
deb-pkg: private build-type := source,binary
@@ -148,7 +123,7 @@ deb-pkg srcdeb-pkg bindeb-pkg:
$(if $(findstring source, $(build-type)), \
--unsigned-source --compression=$(KDEB_SOURCE_COMPRESS)) \
$(if $(findstring binary, $(build-type)), \
- --rules-file='$(MAKE) -f debian/rules' --jobs=1 -r$(KBUILD_PKG_ROOTCMD) -a$$(cat debian/arch), \
+ -R'$(MAKE) -f debian/rules' -j1 -a$$(cat debian/arch), \
--no-check-builddeps) \
$(DPKG_FLAGS))
@@ -159,9 +134,8 @@ snap-pkg:
rm -rf $(objtree)/snap
mkdir $(objtree)/snap
$(MAKE) clean
- $(call cmd,src_tar,$(KERNELPATH))
sed "s@KERNELRELEASE@$(KERNELRELEASE)@; \
- s@SRCTREE@$(shell realpath $(KERNELPATH).tar.gz)@" \
+ s@SRCTREE@$(realpath $(srctree))@" \
$(srctree)/scripts/package/snapcraft.template > \
$(objtree)/snap/snapcraft.yaml
cd $(objtree)/snap && \
diff --git a/scripts/Makefile.ubsan b/scripts/Makefile.ubsan
index 4749865c1b2c..b2d3b273b802 100644
--- a/scripts/Makefile.ubsan
+++ b/scripts/Makefile.ubsan
@@ -10,6 +10,9 @@ ubsan-cflags-$(CONFIG_UBSAN_DIV_ZERO) += -fsanitize=integer-divide-by-zero
ubsan-cflags-$(CONFIG_UBSAN_UNREACHABLE) += -fsanitize=unreachable
ubsan-cflags-$(CONFIG_UBSAN_BOOL) += -fsanitize=bool
ubsan-cflags-$(CONFIG_UBSAN_ENUM) += -fsanitize=enum
-ubsan-cflags-$(CONFIG_UBSAN_TRAP) += -fsanitize-undefined-trap-on-error
+ubsan-cflags-$(CONFIG_UBSAN_TRAP) += $(call cc-option,-fsanitize-trap=undefined,-fsanitize-undefined-trap-on-error)
export CFLAGS_UBSAN := $(ubsan-cflags-y)
+
+ubsan-signed-wrap-cflags-$(CONFIG_UBSAN_SIGNED_WRAP) += -fsanitize=signed-integer-overflow
+export CFLAGS_UBSAN_SIGNED_WRAP := $(ubsan-signed-wrap-cflags-y)
diff --git a/scripts/Makefile.userprogs b/scripts/Makefile.userprogs
index fb415297337a..f3a7e1ef3753 100644
--- a/scripts/Makefile.userprogs
+++ b/scripts/Makefile.userprogs
@@ -19,19 +19,19 @@ user-cobjs := $(addprefix $(obj)/, $(user-cobjs))
user_ccflags = -Wp,-MMD,$(depfile) $(KBUILD_USERCFLAGS) $(userccflags) \
$($(target-stem)-userccflags)
user_ldflags = $(KBUILD_USERLDFLAGS) $(userldflags) $($(target-stem)-userldflags)
+user_ldlibs = $(userldlibs) $($(target-stem)-userldlibs)
# Create an executable from a single .c file
quiet_cmd_user_cc_c = CC [U] $@
cmd_user_cc_c = $(CC) $(user_ccflags) $(user_ldflags) -o $@ $< \
- $($(target-stem)-userldlibs)
+ $(user_ldlibs)
$(user-csingle): $(obj)/%: $(src)/%.c FORCE
$(call if_changed_dep,user_cc_c)
# Link an executable based on list of .o files
quiet_cmd_user_ld = LD [U] $@
cmd_user_ld = $(CC) $(user_ldflags) -o $@ \
- $(addprefix $(obj)/, $($(target-stem)-objs)) \
- $($(target-stem)-userldlibs)
+ $(addprefix $(obj)/, $($(target-stem)-objs)) $(user_ldlibs)
$(user-cmulti): FORCE
$(call if_changed,user_ld)
$(call multi_depend, $(user-cmulti), , -objs)
diff --git a/scripts/Makefile.vdsoinst b/scripts/Makefile.vdsoinst
new file mode 100644
index 000000000000..c477d17b0aa5
--- /dev/null
+++ b/scripts/Makefile.vdsoinst
@@ -0,0 +1,45 @@
+# SPDX-License-Identifier: GPL-2.0-only
+# ==========================================================================
+# Install unstripped copies of vDSO
+# ==========================================================================
+
+PHONY := __default
+__default:
+ @:
+
+include $(srctree)/scripts/Kbuild.include
+
+install-dir := $(MODLIB)/vdso
+
+define gen_install_rules
+
+src := $$(firstword $$(subst :,$(space),$(1)))
+dest := $(install-dir)/$$(or $$(word 2,$$(subst :,$(space),$(1))),$$(patsubst %.dbg,%,$$(notdir $(1))))
+
+__default: $$(dest)
+$$(dest): $$(src) FORCE
+ $$(call cmd,install)
+
+# Some architectures create .build-id symlinks
+ifneq ($(filter arm sparc x86, $(SRCARCH)),)
+link := $(install-dir)/.build-id/$$(shell $(READELF) -n $$(src) | sed -n 's@^.*Build ID: \(..\)\(.*\)@\1/\2@p').debug
+
+__default: $$(link)
+$$(link): $$(dest) FORCE
+ $$(call cmd,symlink)
+endif
+
+endef
+
+$(foreach x, $(sort $(INSTALL_FILES)), $(eval $(call gen_install_rules,$(x))))
+
+quiet_cmd_install = INSTALL $@
+ cmd_install = mkdir -p $(dir $@); cp $< $@
+
+quiet_cmd_symlink = SYMLINK $@
+ cmd_symlink = mkdir -p $(dir $@); ln -sf --relative $< $@
+
+PHONY += FORCE
+FORCE:
+
+.PHONY: $(PHONY)
diff --git a/scripts/Makefile.vmlinux b/scripts/Makefile.vmlinux
index 3cd6ca15f390..c9f3e03124d7 100644
--- a/scripts/Makefile.vmlinux
+++ b/scripts/Makefile.vmlinux
@@ -19,6 +19,7 @@ quiet_cmd_cc_o_c = CC $@
ifdef CONFIG_MODULES
KASAN_SANITIZE_.vmlinux.export.o := n
+KCSAN_SANITIZE_.vmlinux.export.o := n
GCOV_PROFILE_.vmlinux.export.o := n
targets += .vmlinux.export.o
vmlinux: .vmlinux.export.o
diff --git a/scripts/Makefile.vmlinux_o b/scripts/Makefile.vmlinux_o
index 0edfdb40364b..6de297916ce6 100644
--- a/scripts/Makefile.vmlinux_o
+++ b/scripts/Makefile.vmlinux_o
@@ -37,7 +37,8 @@ objtool-enabled := $(or $(delay-objtool),$(CONFIG_NOINSTR_VALIDATION))
vmlinux-objtool-args-$(delay-objtool) += $(objtool-args-y)
vmlinux-objtool-args-$(CONFIG_GCOV_KERNEL) += --no-unreachable
-vmlinux-objtool-args-$(CONFIG_NOINSTR_VALIDATION) += --noinstr $(if $(CONFIG_CPU_UNRET_ENTRY), --unret)
+vmlinux-objtool-args-$(CONFIG_NOINSTR_VALIDATION) += --noinstr \
+ $(if $(or $(CONFIG_MITIGATION_UNRET_ENTRY),$(CONFIG_MITIGATION_SRSO)), --unret)
objtool-args = $(vmlinux-objtool-args-y) --link
diff --git a/scripts/atomic/gen-atomic-fallback.sh b/scripts/atomic/gen-atomic-fallback.sh
index a45154cefa48..f80d69cfeb1f 100755
--- a/scripts/atomic/gen-atomic-fallback.sh
+++ b/scripts/atomic/gen-atomic-fallback.sh
@@ -223,14 +223,15 @@ gen_xchg_fallbacks()
gen_try_cmpxchg_fallback()
{
+ local prefix="$1"; shift
local cmpxchg="$1"; shift;
- local order="$1"; shift;
+ local suffix="$1"; shift;
cat <<EOF
-#define raw_try_${cmpxchg}${order}(_ptr, _oldp, _new) \\
+#define raw_${prefix}try_${cmpxchg}${suffix}(_ptr, _oldp, _new) \\
({ \\
typeof(*(_ptr)) *___op = (_oldp), ___o = *___op, ___r; \\
- ___r = raw_${cmpxchg}${order}((_ptr), ___o, (_new)); \\
+ ___r = raw_${prefix}${cmpxchg}${suffix}((_ptr), ___o, (_new)); \\
if (unlikely(___r != ___o)) \\
*___op = ___r; \\
likely(___r == ___o); \\
@@ -259,11 +260,11 @@ gen_try_cmpxchg_order_fallback()
fi
printf "#else\n"
- gen_try_cmpxchg_fallback "${cmpxchg}" "${order}"
+ gen_try_cmpxchg_fallback "" "${cmpxchg}" "${order}"
printf "#endif\n\n"
}
-gen_try_cmpxchg_fallbacks()
+gen_try_cmpxchg_order_fallbacks()
{
local cmpxchg="$1"; shift;
@@ -272,15 +273,17 @@ gen_try_cmpxchg_fallbacks()
done
}
-gen_cmpxchg_local_fallbacks()
+gen_def_and_try_cmpxchg_fallback()
{
+ local prefix="$1"; shift
local cmpxchg="$1"; shift
+ local suffix="$1"; shift
- printf "#define raw_${cmpxchg} arch_${cmpxchg}\n\n"
- printf "#ifdef arch_try_${cmpxchg}\n"
- printf "#define raw_try_${cmpxchg} arch_try_${cmpxchg}\n"
+ printf "#define raw_${prefix}${cmpxchg}${suffix} arch_${prefix}${cmpxchg}${suffix}\n\n"
+ printf "#ifdef arch_${prefix}try_${cmpxchg}${suffix}\n"
+ printf "#define raw_${prefix}try_${cmpxchg}${suffix} arch_${prefix}try_${cmpxchg}${suffix}\n"
printf "#else\n"
- gen_try_cmpxchg_fallback "${cmpxchg}" ""
+ gen_try_cmpxchg_fallback "${prefix}" "${cmpxchg}" "${suffix}"
printf "#endif\n\n"
}
@@ -302,15 +305,15 @@ for xchg in "xchg" "cmpxchg" "cmpxchg64" "cmpxchg128"; do
done
for cmpxchg in "cmpxchg" "cmpxchg64" "cmpxchg128"; do
- gen_try_cmpxchg_fallbacks "${cmpxchg}"
+ gen_try_cmpxchg_order_fallbacks "${cmpxchg}"
done
-for cmpxchg in "cmpxchg_local" "cmpxchg64_local" "cmpxchg128_local"; do
- gen_cmpxchg_local_fallbacks "${cmpxchg}" ""
+for cmpxchg in "cmpxchg" "cmpxchg64" "cmpxchg128"; do
+ gen_def_and_try_cmpxchg_fallback "" "${cmpxchg}" "_local"
done
-for cmpxchg in "sync_cmpxchg"; do
- printf "#define raw_${cmpxchg} arch_${cmpxchg}\n\n"
+for cmpxchg in "cmpxchg"; do
+ gen_def_and_try_cmpxchg_fallback "sync_" "${cmpxchg}" ""
done
grep '^[a-z]' "$1" | while read name meta args; do
diff --git a/scripts/atomic/gen-atomic-instrumented.sh b/scripts/atomic/gen-atomic-instrumented.sh
index 8f8f8e3b20f9..592f3ec89b5f 100755
--- a/scripts/atomic/gen-atomic-instrumented.sh
+++ b/scripts/atomic/gen-atomic-instrumented.sh
@@ -169,7 +169,8 @@ for xchg in "xchg" "cmpxchg" "cmpxchg64" "cmpxchg128" "try_cmpxchg" "try_cmpxchg
done
done
-for xchg in "cmpxchg_local" "cmpxchg64_local" "cmpxchg128_local" "sync_cmpxchg" "try_cmpxchg_local" "try_cmpxchg64_local" "try_cmpxchg128_local"; do
+for xchg in "cmpxchg_local" "cmpxchg64_local" "cmpxchg128_local" "sync_cmpxchg" \
+ "try_cmpxchg_local" "try_cmpxchg64_local" "try_cmpxchg128_local" "sync_try_cmpxchg"; do
gen_xchg "${xchg}" ""
printf "\n"
done
diff --git a/scripts/atomic/kerneldoc/add_unless b/scripts/atomic/kerneldoc/add_unless
index f828e5f6750c..fbc2fadfbdc4 100644
--- a/scripts/atomic/kerneldoc/add_unless
+++ b/scripts/atomic/kerneldoc/add_unless
@@ -10,6 +10,7 @@ cat <<EOF
* @u: ${int} value to compare with
*
* If (@v != @u), atomically updates @v to (@v + @a) with ${desc_order} ordering.
+ * Otherwise, @v is not modified and relaxed ordering is provided.
*
* ${desc_noinstr}
*
diff --git a/scripts/atomic/kerneldoc/cmpxchg b/scripts/atomic/kerneldoc/cmpxchg
index 3bce328f50cf..02b24ee9d8a4 100644
--- a/scripts/atomic/kerneldoc/cmpxchg
+++ b/scripts/atomic/kerneldoc/cmpxchg
@@ -6,6 +6,7 @@ cat <<EOF
* @new: ${int} value to assign
*
* If (@v == @old), atomically updates @v to @new with ${desc_order} ordering.
+ * Otherwise, @v is not modified and relaxed ordering is provided.
*
* ${desc_noinstr}
*
diff --git a/scripts/atomic/kerneldoc/dec_if_positive b/scripts/atomic/kerneldoc/dec_if_positive
index 04f1aed3cf83..9468b4a69603 100644
--- a/scripts/atomic/kerneldoc/dec_if_positive
+++ b/scripts/atomic/kerneldoc/dec_if_positive
@@ -4,6 +4,7 @@ cat <<EOF
* @v: pointer to ${atomic}_t
*
* If (@v > 0), atomically updates @v to (@v - 1) with ${desc_order} ordering.
+ * Otherwise, @v is not modified and relaxed ordering is provided.
*
* ${desc_noinstr}
*
diff --git a/scripts/atomic/kerneldoc/dec_unless_positive b/scripts/atomic/kerneldoc/dec_unless_positive
index ee73612f0354..06a678678f71 100644
--- a/scripts/atomic/kerneldoc/dec_unless_positive
+++ b/scripts/atomic/kerneldoc/dec_unless_positive
@@ -4,6 +4,7 @@ cat <<EOF
* @v: pointer to ${atomic}_t
*
* If (@v <= 0), atomically updates @v to (@v - 1) with ${desc_order} ordering.
+ * Otherwise, @v is not modified and relaxed ordering is provided.
*
* ${desc_noinstr}
*
diff --git a/scripts/atomic/kerneldoc/inc_not_zero b/scripts/atomic/kerneldoc/inc_not_zero
index 618be08e653e..c1a30fc66ee9 100644
--- a/scripts/atomic/kerneldoc/inc_not_zero
+++ b/scripts/atomic/kerneldoc/inc_not_zero
@@ -4,6 +4,7 @@ cat <<EOF
* @v: pointer to ${atomic}_t
*
* If (@v != 0), atomically updates @v to (@v + 1) with ${desc_order} ordering.
+ * Otherwise, @v is not modified and relaxed ordering is provided.
*
* ${desc_noinstr}
*
diff --git a/scripts/atomic/kerneldoc/inc_unless_negative b/scripts/atomic/kerneldoc/inc_unless_negative
index 597f23d4dc8d..ece0d2c7b38f 100644
--- a/scripts/atomic/kerneldoc/inc_unless_negative
+++ b/scripts/atomic/kerneldoc/inc_unless_negative
@@ -4,6 +4,7 @@ cat <<EOF
* @v: pointer to ${atomic}_t
*
* If (@v >= 0), atomically updates @v to (@v + 1) with ${desc_order} ordering.
+ * Otherwise, @v is not modified and relaxed ordering is provided.
*
* ${desc_noinstr}
*
diff --git a/scripts/atomic/kerneldoc/try_cmpxchg b/scripts/atomic/kerneldoc/try_cmpxchg
index 296553206c06..3ccff29538f5 100644
--- a/scripts/atomic/kerneldoc/try_cmpxchg
+++ b/scripts/atomic/kerneldoc/try_cmpxchg
@@ -6,7 +6,8 @@ cat <<EOF
* @new: ${int} value to assign
*
* If (@v == @old), atomically updates @v to @new with ${desc_order} ordering.
- * Otherwise, updates @old to the current value of @v.
+ * Otherwise, @v is not modified, @old is updated to the current value of @v,
+ * and relaxed ordering is provided.
*
* ${desc_noinstr}
*
diff --git a/scripts/bpf_doc.py b/scripts/bpf_doc.py
index 61b7dddedc46..c55878bddfdd 100755
--- a/scripts/bpf_doc.py
+++ b/scripts/bpf_doc.py
@@ -414,8 +414,8 @@ class PrinterRST(Printer):
version = version.stdout.decode().rstrip()
except:
try:
- version = subprocess.run(['make', 'kernelversion'], cwd=linuxRoot,
- capture_output=True, check=True)
+ version = subprocess.run(['make', '-s', '--no-print-directory', 'kernelversion'],
+ cwd=linuxRoot, capture_output=True, check=True)
version = version.stdout.decode().rstrip()
except:
return 'Linux'
@@ -513,7 +513,7 @@ eBPF programs can have an associated license, passed along with the bytecode
instructions to the kernel when the programs are loaded. The format for that
string is identical to the one in use for kernel modules (Dual licenses, such
as "Dual BSD/GPL", may be used). Some helper functions are only accessible to
-programs that are compatible with the GNU Privacy License (GPL).
+programs that are compatible with the GNU General Public License (GNU GPL).
In order to use such helpers, the eBPF program must be loaded with the correct
license string passed (via **attr**) to the **bpf**\\ () system call, and this
@@ -827,7 +827,7 @@ class PrinterHelpers(Printer):
print(' *{}{}'.format(' \t' if line else '', line))
print(' */')
- print('static %s %s(*%s)(' % (self.map_type(proto['ret_type']),
+ print('static %s %s(* const %s)(' % (self.map_type(proto['ret_type']),
proto['ret_star'], proto['name']), end='')
comma = ''
for i, a in enumerate(proto['args']):
diff --git a/scripts/check-sysctl-docs b/scripts/check-sysctl-docs
index 4f163e0bf6a4..20274c63e745 100755
--- a/scripts/check-sysctl-docs
+++ b/scripts/check-sysctl-docs
@@ -8,7 +8,7 @@
# Example invocation:
# scripts/check-sysctl-docs -vtable="kernel" \
# Documentation/admin-guide/sysctl/kernel.rst \
-# $(git grep -l register_sysctl_)
+# $(git grep -l register_sysctl)
#
# Specify -vdebug=1 to see debugging information
@@ -20,14 +20,10 @@ BEGIN {
}
# The following globals are used:
-# children: maps ctl_table names and procnames to child ctl_table names
# documented: maps documented entries (each key is an entry)
# entries: maps ctl_table names and procnames to counts (so
# enumerating the subkeys for a given ctl_table lists its
# procnames)
-# files: maps procnames to source file names
-# paths: maps ctl_path names to paths
-# curpath: the name of the current ctl_path struct
# curtable: the name of the current ctl_table struct
# curentry: the name of the current proc entry (procname when parsing
# a ctl_table, constructed path when parsing a ctl_path)
@@ -94,42 +90,23 @@ FNR == NR {
# Stage 2: process each file and find all sysctl tables
BEGINFILE {
- delete children
delete entries
- delete paths
- curpath = ""
curtable = ""
curentry = ""
+ delete vars
if (debug) print "Processing file " FILENAME
}
-/^static struct ctl_path/ {
- match($0, /static struct ctl_path ([^][]+)/, tables)
- curpath = tables[1]
- if (debug) print "Processing path " curpath
-}
-
-/^static struct ctl_table/ {
- match($0, /static struct ctl_table ([^][]+)/, tables)
- curtable = tables[1]
+/^static( const)? struct ctl_table/ {
+ match($0, /static( const)? struct ctl_table ([^][]+)/, tables)
+ curtable = tables[2]
if (debug) print "Processing table " curtable
}
/^};$/ {
- curpath = ""
curtable = ""
curentry = ""
-}
-
-curpath && /\.procname[\t ]*=[\t ]*".+"/ {
- match($0, /.procname[\t ]*=[\t ]*"([^"]+)"/, names)
- if (curentry) {
- curentry = curentry "/" names[1]
- } else {
- curentry = names[1]
- }
- if (debug) print "Setting path " curpath " to " curentry
- paths[curpath] = curentry
+ delete vars
}
curtable && /\.procname[\t ]*=[\t ]*".+"/ {
@@ -140,10 +117,32 @@ curtable && /\.procname[\t ]*=[\t ]*".+"/ {
file[curentry] = FILENAME
}
-/\.child[\t ]*=/ {
- child = trimpunct($NF)
- if (debug) print "Linking child " child " to table " curtable " entry " curentry
- children[curtable][curentry] = child
+/register_sysctl.*/ {
+ match($0, /register_sysctl(|_init|_sz)\("([^"]+)" *, *([^,)]+)/, tables)
+ if (debug) print "Registering table " tables[3] " at " tables[2]
+ if (tables[2] == table) {
+ for (entry in entries[tables[3]]) {
+ printentry(entry)
+ }
+ }
+}
+
+/kmemdup.*/ {
+ match($0, /([^ \t]+) *= *kmemdup\(([^,]+) *,/, names)
+ if (debug) print "Found variable " names[1] " for table " names[2]
+ if (names[2] in entries) {
+ vars[names[1]] = names[2]
+ }
+}
+
+/__register_sysctl_table.*/ {
+ match($0, /__register_sysctl_table\([^,]+, *"([^"]+)" *, *([^,]+)/, tables)
+ if (debug) print "Registering variable table " tables[2] " at " tables[1]
+ if (tables[1] == table && tables[2] in vars) {
+ for (entry in entries[vars[tables[2]]]) {
+ printentry(entry)
+ }
+ }
}
END {
diff --git a/scripts/check-uapi.sh b/scripts/check-uapi.sh
new file mode 100755
index 000000000000..955581735cb3
--- /dev/null
+++ b/scripts/check-uapi.sh
@@ -0,0 +1,573 @@
+#!/bin/bash
+# SPDX-License-Identifier: GPL-2.0-only
+# Script to check commits for UAPI backwards compatibility
+
+set -o errexit
+set -o pipefail
+
+print_usage() {
+ name=$(basename "$0")
+ cat << EOF
+$name - check for UAPI header stability across Git commits
+
+By default, the script will check to make sure the latest commit (or current
+dirty changes) did not introduce ABI changes when compared to HEAD^1. You can
+check against additional commit ranges with the -b and -p options.
+
+The script will not check UAPI headers for architectures other than the one
+defined in ARCH.
+
+Usage: $name [-b BASE_REF] [-p PAST_REF] [-j N] [-l ERROR_LOG] [-i] [-q] [-v]
+
+Options:
+ -b BASE_REF Base git reference to use for comparison. If unspecified or empty,
+ will use any dirty changes in tree to UAPI files. If there are no
+ dirty changes, HEAD will be used.
+ -p PAST_REF Compare BASE_REF to PAST_REF (e.g. -p v6.1). If unspecified or empty,
+ will use BASE_REF^1. Must be an ancestor of BASE_REF. Only headers
+ that exist on PAST_REF will be checked for compatibility.
+ -j JOBS Number of checks to run in parallel (default: number of CPU cores).
+ -l ERROR_LOG Write error log to file (default: no error log is generated).
+ -i Ignore ambiguous changes that may or may not break UAPI compatibility.
+ -q Quiet operation.
+ -v Verbose operation (print more information about each header being checked).
+
+Environmental args:
+ ABIDIFF Custom path to abidiff binary
+ CC C compiler (default is "gcc")
+ ARCH Target architecture for the UAPI check (default is host arch)
+
+Exit codes:
+ $SUCCESS) Success
+ $FAIL_ABI) ABI difference detected
+ $FAIL_PREREQ) Prerequisite not met
+EOF
+}
+
+readonly SUCCESS=0
+readonly FAIL_ABI=1
+readonly FAIL_PREREQ=2
+
+# Print to stderr
+eprintf() {
+ # shellcheck disable=SC2059
+ printf "$@" >&2
+}
+
+# Expand an array with a specific character (similar to Python string.join())
+join() {
+ local IFS="$1"
+ shift
+ printf "%s" "$*"
+}
+
+# Create abidiff suppressions
+gen_suppressions() {
+ # Common enum variant names which we don't want to worry about
+ # being shifted when new variants are added.
+ local -a enum_regex=(
+ ".*_AFTER_LAST$"
+ ".*_CNT$"
+ ".*_COUNT$"
+ ".*_END$"
+ ".*_LAST$"
+ ".*_MASK$"
+ ".*_MAX$"
+ ".*_MAX_BIT$"
+ ".*_MAX_BPF_ATTACH_TYPE$"
+ ".*_MAX_ID$"
+ ".*_MAX_SHIFT$"
+ ".*_NBITS$"
+ ".*_NETDEV_NUMHOOKS$"
+ ".*_NFT_META_IIFTYPE$"
+ ".*_NL80211_ATTR$"
+ ".*_NLDEV_NUM_OPS$"
+ ".*_NUM$"
+ ".*_NUM_ELEMS$"
+ ".*_NUM_IRQS$"
+ ".*_SIZE$"
+ ".*_TLSMAX$"
+ "^MAX_.*"
+ "^NUM_.*"
+ )
+
+ # Common padding field names which can be expanded into
+ # without worrying about users.
+ local -a padding_regex=(
+ ".*end$"
+ ".*pad$"
+ ".*pad[0-9]?$"
+ ".*pad_[0-9]?$"
+ ".*padding$"
+ ".*padding[0-9]?$"
+ ".*padding_[0-9]?$"
+ ".*res$"
+ ".*resv$"
+ ".*resv[0-9]?$"
+ ".*resv_[0-9]?$"
+ ".*reserved$"
+ ".*reserved[0-9]?$"
+ ".*reserved_[0-9]?$"
+ ".*rsvd[0-9]?$"
+ ".*unused$"
+ )
+
+ cat << EOF
+[suppress_type]
+ type_kind = enum
+ changed_enumerators_regexp = $(join , "${enum_regex[@]}")
+EOF
+
+ for p in "${padding_regex[@]}"; do
+ cat << EOF
+[suppress_type]
+ type_kind = struct
+ has_data_member_inserted_at = offset_of_first_data_member_regexp(${p})
+EOF
+ done
+
+if [ "$IGNORE_AMBIGUOUS_CHANGES" = "true" ]; then
+ cat << EOF
+[suppress_type]
+ type_kind = struct
+ has_data_member_inserted_at = end
+ has_size_change = yes
+EOF
+fi
+}
+
+# Check if git tree is dirty
+tree_is_dirty() {
+ ! git diff --quiet
+}
+
+# Get list of files installed in $ref
+get_file_list() {
+ local -r ref="$1"
+ local -r tree="$(get_header_tree "$ref")"
+
+ # Print all installed headers, filtering out ones that can't be compiled
+ find "$tree" -type f -name '*.h' -printf '%P\n' | grep -v -f "$INCOMPAT_LIST"
+}
+
+# Add to the list of incompatible headers
+add_to_incompat_list() {
+ local -r ref="$1"
+
+ # Start with the usr/include/Makefile to get a list of the headers
+ # that don't compile using this method.
+ if [ ! -f usr/include/Makefile ]; then
+ eprintf "error - no usr/include/Makefile present at %s\n" "$ref"
+ eprintf "Note: usr/include/Makefile was added in the v5.3 kernel release\n"
+ exit "$FAIL_PREREQ"
+ fi
+ {
+ # shellcheck disable=SC2016
+ printf 'all: ; @echo $(no-header-test)\n'
+ cat usr/include/Makefile
+ } | SRCARCH="$ARCH" make --always-make -f - | tr " " "\n" \
+ | grep -v "asm-generic" >> "$INCOMPAT_LIST"
+
+ # The makefile also skips all asm-generic files, but prints "asm-generic/%"
+ # which won't work for our grep match. Instead, print something grep will match.
+ printf "asm-generic/.*\.h\n" >> "$INCOMPAT_LIST"
+}
+
+# Compile the simple test app
+do_compile() {
+ local -r inc_dir="$1"
+ local -r header="$2"
+ local -r out="$3"
+ printf "int main(void) { return 0; }\n" | \
+ "$CC" -c \
+ -o "$out" \
+ -x c \
+ -O0 \
+ -std=c90 \
+ -fno-eliminate-unused-debug-types \
+ -g \
+ "-I${inc_dir}" \
+ -include "$header" \
+ -
+}
+
+# Run make headers_install
+run_make_headers_install() {
+ local -r ref="$1"
+ local -r install_dir="$(get_header_tree "$ref")"
+ make -j "$MAX_THREADS" ARCH="$ARCH" INSTALL_HDR_PATH="$install_dir" \
+ headers_install > /dev/null
+}
+
+# Install headers for both git refs
+install_headers() {
+ local -r base_ref="$1"
+ local -r past_ref="$2"
+
+ for ref in "$base_ref" "$past_ref"; do
+ printf "Installing user-facing UAPI headers from %s... " "${ref:-dirty tree}"
+ if [ -n "$ref" ]; then
+ git archive --format=tar --prefix="${ref}-archive/" "$ref" \
+ | (cd "$TMP_DIR" && tar xf -)
+ (
+ cd "${TMP_DIR}/${ref}-archive"
+ run_make_headers_install "$ref"
+ add_to_incompat_list "$ref" "$INCOMPAT_LIST"
+ )
+ else
+ run_make_headers_install "$ref"
+ add_to_incompat_list "$ref" "$INCOMPAT_LIST"
+ fi
+ printf "OK\n"
+ done
+ sort -u -o "$INCOMPAT_LIST" "$INCOMPAT_LIST"
+ sed -i -e '/^$/d' "$INCOMPAT_LIST"
+}
+
+# Print the path to the headers_install tree for a given ref
+get_header_tree() {
+ local -r ref="$1"
+ printf "%s" "${TMP_DIR}/${ref}/usr"
+}
+
+# Check file list for UAPI compatibility
+check_uapi_files() {
+ local -r base_ref="$1"
+ local -r past_ref="$2"
+ local -r abi_error_log="$3"
+
+ local passed=0;
+ local failed=0;
+ local -a threads=()
+ set -o errexit
+
+ printf "Checking changes to UAPI headers between %s and %s...\n" "$past_ref" "${base_ref:-dirty tree}"
+ # Loop over all UAPI headers that were installed by $past_ref (if they only exist on $base_ref,
+ # there's no way they're broken and no way to compare anyway)
+ while read -r file; do
+ if [ "${#threads[@]}" -ge "$MAX_THREADS" ]; then
+ if wait "${threads[0]}"; then
+ passed=$((passed + 1))
+ else
+ failed=$((failed + 1))
+ fi
+ threads=("${threads[@]:1}")
+ fi
+
+ check_individual_file "$base_ref" "$past_ref" "$file" &
+ threads+=("$!")
+ done < <(get_file_list "$past_ref")
+
+ for t in "${threads[@]}"; do
+ if wait "$t"; then
+ passed=$((passed + 1))
+ else
+ failed=$((failed + 1))
+ fi
+ done
+
+ if [ -n "$abi_error_log" ]; then
+ printf 'Generated by "%s %s" from git ref %s\n\n' \
+ "$0" "$*" "$(git rev-parse HEAD)" > "$abi_error_log"
+ fi
+
+ while read -r error_file; do
+ {
+ cat "$error_file"
+ printf "\n\n"
+ } | tee -a "${abi_error_log:-/dev/null}" >&2
+ done < <(find "$TMP_DIR" -type f -name '*.error' | sort)
+
+ total="$((passed + failed))"
+ if [ "$failed" -gt 0 ]; then
+ eprintf "error - %d/%d UAPI headers compatible with %s appear _not_ to be backwards compatible\n" \
+ "$failed" "$total" "$ARCH"
+ if [ -n "$abi_error_log" ]; then
+ eprintf "Failure summary saved to %s\n" "$abi_error_log"
+ fi
+ else
+ printf "All %d UAPI headers compatible with %s appear to be backwards compatible\n" \
+ "$total" "$ARCH"
+ fi
+
+ return "$failed"
+}
+
+# Check an individual file for UAPI compatibility
+check_individual_file() {
+ local -r base_ref="$1"
+ local -r past_ref="$2"
+ local -r file="$3"
+
+ local -r base_header="$(get_header_tree "$base_ref")/${file}"
+ local -r past_header="$(get_header_tree "$past_ref")/${file}"
+
+ if [ ! -f "$base_header" ]; then
+ mkdir -p "$(dirname "$base_header")"
+ printf "==== UAPI header %s was removed between %s and %s ====" \
+ "$file" "$past_ref" "$base_ref" \
+ > "${base_header}.error"
+ return 1
+ fi
+
+ compare_abi "$file" "$base_header" "$past_header" "$base_ref" "$past_ref"
+}
+
+# Perform the A/B compilation and compare output ABI
+compare_abi() {
+ local -r file="$1"
+ local -r base_header="$2"
+ local -r past_header="$3"
+ local -r base_ref="$4"
+ local -r past_ref="$5"
+ local -r log="${TMP_DIR}/log/${file}.log"
+ local -r error_log="${TMP_DIR}/log/${file}.error"
+
+ mkdir -p "$(dirname "$log")"
+
+ if ! do_compile "$(get_header_tree "$base_ref")/include" "$base_header" "${base_header}.bin" 2> "$log"; then
+ {
+ warn_str=$(printf "==== Could not compile version of UAPI header %s at %s ====\n" \
+ "$file" "$base_ref")
+ printf "%s\n" "$warn_str"
+ cat "$log"
+ printf -- "=%.0s" $(seq 0 ${#warn_str})
+ } > "$error_log"
+ return 1
+ fi
+
+ if ! do_compile "$(get_header_tree "$past_ref")/include" "$past_header" "${past_header}.bin" 2> "$log"; then
+ {
+ warn_str=$(printf "==== Could not compile version of UAPI header %s at %s ====\n" \
+ "$file" "$past_ref")
+ printf "%s\n" "$warn_str"
+ cat "$log"
+ printf -- "=%.0s" $(seq 0 ${#warn_str})
+ } > "$error_log"
+ return 1
+ fi
+
+ local ret=0
+ "$ABIDIFF" --non-reachable-types \
+ --suppressions "$SUPPRESSIONS" \
+ "${past_header}.bin" "${base_header}.bin" > "$log" || ret="$?"
+ if [ "$ret" -eq 0 ]; then
+ if [ "$VERBOSE" = "true" ]; then
+ printf "No ABI differences detected in %s from %s -> %s\n" \
+ "$file" "$past_ref" "$base_ref"
+ fi
+ else
+ # Bits in abidiff's return code can be used to determine the type of error
+ if [ $((ret & 0x2)) -gt 0 ]; then
+ eprintf "error - abidiff did not run properly\n"
+ exit 1
+ fi
+
+ if [ "$IGNORE_AMBIGUOUS_CHANGES" = "true" ] && [ "$ret" -eq 4 ]; then
+ return 0
+ fi
+
+ # If the only changes were additions (not modifications to existing APIs), then
+ # there's no problem. Ignore these diffs.
+ if grep "Unreachable types summary" "$log" | grep -q "0 removed" &&
+ grep "Unreachable types summary" "$log" | grep -q "0 changed"; then
+ return 0
+ fi
+
+ {
+ warn_str=$(printf "==== ABI differences detected in %s from %s -> %s ====" \
+ "$file" "$past_ref" "$base_ref")
+ printf "%s\n" "$warn_str"
+ sed -e '/summary:/d' -e '/changed type/d' -e '/^$/d' -e 's/^/ /g' "$log"
+ printf -- "=%.0s" $(seq 0 ${#warn_str})
+ if cmp "$past_header" "$base_header" > /dev/null 2>&1; then
+ printf "\n%s did not change between %s and %s...\n" "$file" "$past_ref" "${base_ref:-dirty tree}"
+ printf "It's possible a change to one of the headers it includes caused this error:\n"
+ grep '^#include' "$base_header"
+ printf "\n"
+ fi
+ } > "$error_log"
+
+ return 1
+ fi
+}
+
+# Check that a minimum software version number is satisfied
+min_version_is_satisfied() {
+ local -r min_version="$1"
+ local -r version_installed="$2"
+
+ printf "%s\n%s\n" "$min_version" "$version_installed" \
+ | sort -Vc > /dev/null 2>&1
+}
+
+# Make sure we have the tools we need and the arguments make sense
+check_deps() {
+ ABIDIFF="${ABIDIFF:-abidiff}"
+ CC="${CC:-gcc}"
+ ARCH="${ARCH:-$(uname -m)}"
+ if [ "$ARCH" = "x86_64" ]; then
+ ARCH="x86"
+ fi
+
+ local -r abidiff_min_version="2.4"
+ local -r libdw_min_version_if_clang="0.171"
+
+ if ! command -v "$ABIDIFF" > /dev/null 2>&1; then
+ eprintf "error - abidiff not found!\n"
+ eprintf "Please install abigail-tools version %s or greater\n" "$abidiff_min_version"
+ eprintf "See: https://sourceware.org/libabigail/manual/libabigail-overview.html\n"
+ return 1
+ fi
+
+ local -r abidiff_version="$("$ABIDIFF" --version | cut -d ' ' -f 2)"
+ if ! min_version_is_satisfied "$abidiff_min_version" "$abidiff_version"; then
+ eprintf "error - abidiff version too old: %s\n" "$abidiff_version"
+ eprintf "Please install abigail-tools version %s or greater\n" "$abidiff_min_version"
+ eprintf "See: https://sourceware.org/libabigail/manual/libabigail-overview.html\n"
+ return 1
+ fi
+
+ if ! command -v "$CC" > /dev/null 2>&1; then
+ eprintf 'error - %s not found\n' "$CC"
+ return 1
+ fi
+
+ if "$CC" --version | grep -q clang; then
+ local -r libdw_version="$(ldconfig -v 2>/dev/null | grep -v SKIPPED | grep -m 1 -o 'libdw-[0-9]\+.[0-9]\+' | cut -c 7-)"
+ if ! min_version_is_satisfied "$libdw_min_version_if_clang" "$libdw_version"; then
+ eprintf "error - libdw version too old for use with clang: %s\n" "$libdw_version"
+ eprintf "Please install libdw from elfutils version %s or greater\n" "$libdw_min_version_if_clang"
+ eprintf "See: https://sourceware.org/elfutils/\n"
+ return 1
+ fi
+ fi
+
+ if [ ! -d "arch/${ARCH}" ]; then
+ eprintf 'error - ARCH "%s" is not a subdirectory under arch/\n' "$ARCH"
+ eprintf "Please set ARCH to one of:\n%s\n" "$(find arch -maxdepth 1 -mindepth 1 -type d -printf '%f ' | fmt)"
+ return 1
+ fi
+
+ if ! git rev-parse --is-inside-work-tree > /dev/null 2>&1; then
+ eprintf "error - this script requires the kernel tree to be initialized with Git\n"
+ return 1
+ fi
+
+ if ! git rev-parse --verify "$past_ref" > /dev/null 2>&1; then
+ printf 'error - invalid git reference "%s"\n' "$past_ref"
+ return 1
+ fi
+
+ if [ -n "$base_ref" ]; then
+ if ! git merge-base --is-ancestor "$past_ref" "$base_ref" > /dev/null 2>&1; then
+ printf 'error - "%s" is not an ancestor of base ref "%s"\n' "$past_ref" "$base_ref"
+ return 1
+ fi
+ if [ "$(git rev-parse "$base_ref")" = "$(git rev-parse "$past_ref")" ]; then
+ printf 'error - "%s" and "%s" are the same reference\n' "$past_ref" "$base_ref"
+ return 1
+ fi
+ fi
+}
+
+run() {
+ local base_ref="$1"
+ local past_ref="$2"
+ local abi_error_log="$3"
+ shift 3
+
+ if [ -z "$KERNEL_SRC" ]; then
+ KERNEL_SRC="$(realpath "$(dirname "$0")"/..)"
+ fi
+
+ cd "$KERNEL_SRC"
+
+ if [ -z "$base_ref" ] && ! tree_is_dirty; then
+ base_ref=HEAD
+ fi
+
+ if [ -z "$past_ref" ]; then
+ if [ -n "$base_ref" ]; then
+ past_ref="${base_ref}^1"
+ else
+ past_ref=HEAD
+ fi
+ fi
+
+ if ! check_deps; then
+ exit "$FAIL_PREREQ"
+ fi
+
+ TMP_DIR=$(mktemp -d)
+ readonly TMP_DIR
+ trap 'rm -rf "$TMP_DIR"' EXIT
+
+ readonly INCOMPAT_LIST="${TMP_DIR}/incompat_list.txt"
+ touch "$INCOMPAT_LIST"
+
+ readonly SUPPRESSIONS="${TMP_DIR}/suppressions.txt"
+ gen_suppressions > "$SUPPRESSIONS"
+
+ # Run make install_headers for both refs
+ install_headers "$base_ref" "$past_ref"
+
+ # Check for any differences in the installed header trees
+ if diff -r -q "$(get_header_tree "$base_ref")" "$(get_header_tree "$past_ref")" > /dev/null 2>&1; then
+ printf "No changes to UAPI headers were applied between %s and %s\n" "$past_ref" "${base_ref:-dirty tree}"
+ exit "$SUCCESS"
+ fi
+
+ if ! check_uapi_files "$base_ref" "$past_ref" "$abi_error_log"; then
+ exit "$FAIL_ABI"
+ fi
+}
+
+main() {
+ MAX_THREADS=$(nproc)
+ VERBOSE="false"
+ IGNORE_AMBIGUOUS_CHANGES="false"
+ quiet="false"
+ local base_ref=""
+ while getopts "hb:p:j:l:iqv" opt; do
+ case $opt in
+ h)
+ print_usage
+ exit "$SUCCESS"
+ ;;
+ b)
+ base_ref="$OPTARG"
+ ;;
+ p)
+ past_ref="$OPTARG"
+ ;;
+ j)
+ MAX_THREADS="$OPTARG"
+ ;;
+ l)
+ abi_error_log="$OPTARG"
+ ;;
+ i)
+ IGNORE_AMBIGUOUS_CHANGES="true"
+ ;;
+ q)
+ quiet="true"
+ VERBOSE="false"
+ ;;
+ v)
+ VERBOSE="true"
+ quiet="false"
+ ;;
+ *)
+ exit "$FAIL_PREREQ"
+ esac
+ done
+
+ if [ "$quiet" = "true" ]; then
+ exec > /dev/null 2>&1
+ fi
+
+ run "$base_ref" "$past_ref" "$abi_error_log" "$@"
+}
+
+main "$@"
diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl
index 7d16f863edf1..9c4c4a61bc83 100755
--- a/scripts/checkpatch.pl
+++ b/scripts/checkpatch.pl
@@ -512,6 +512,7 @@ our $Attribute = qr{
__ro_after_init|
__kprobes|
$InitAttribute|
+ __aligned\s*\(.*\)|
____cacheline_aligned|
____cacheline_aligned_in_smp|
____cacheline_internodealigned_in_smp|
@@ -4054,7 +4055,7 @@ sub process {
if ($prevline =~ /^[\+ ]};?\s*$/ &&
$line =~ /^\+/ &&
!($line =~ /^\+\s*$/ ||
- $line =~ /^\+\s*(?:EXPORT_SYMBOL|early_param)/ ||
+ $line =~ /^\+\s*(?:EXPORT_SYMBOL|early_param|ALLOW_ERROR_INJECTION)/ ||
$line =~ /^\+\s*MODULE_/i ||
$line =~ /^\+\s*\#\s*(?:end|elif|else)/ ||
$line =~ /^\+[a-z_]*init/ ||
@@ -6427,15 +6428,6 @@ sub process {
}
}
-# check for soon-to-be-deprecated single-argument k[v]free_rcu() API
- if ($line =~ /\bk[v]?free_rcu\s*\([^(]+\)/) {
- if ($line =~ /\bk[v]?free_rcu\s*\([^,]+\)/) {
- ERROR("DEPRECATED_API",
- "Single-argument k[v]free_rcu() API is deprecated, please pass rcu_head object or call k[v]free_rcu_mightsleep()." . $herecurr);
- }
- }
-
-
# check for unnecessary "Out of Memory" messages
if ($line =~ /^\+.*\b$logFunctions\s*\(/ &&
$prevline =~ /^[ \+]\s*if\s*\(\s*(\!\s*|NULL\s*==\s*)?($Lval)(\s*==\s*NULL\s*)?\s*\)/ &&
@@ -7020,6 +7012,25 @@ sub process {
"Prefer strscpy, strscpy_pad, or __nonstring over strncpy - see: https://github.com/KSPP/linux/issues/90\n" . $herecurr);
}
+# ethtool_sprintf uses that should likely be ethtool_puts
+ if ($line =~ /\bethtool_sprintf\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*\)/) {
+ if (WARN("PREFER_ETHTOOL_PUTS",
+ "Prefer ethtool_puts over ethtool_sprintf with only two arguments\n" . $herecurr) &&
+ $fix) {
+ $fixed[$fixlinenr] =~ s/\bethtool_sprintf\s*\(\s*($FuncArg)\s*,\s*($FuncArg)/ethtool_puts($1, $7)/;
+ }
+ }
+
+ # use $rawline because $line loses %s via sanitization and thus we can't match against it.
+ if ($rawline =~ /\bethtool_sprintf\s*\(\s*$FuncArg\s*,\s*\"\%s\"\s*,\s*$FuncArg\s*\)/) {
+ if (WARN("PREFER_ETHTOOL_PUTS",
+ "Prefer ethtool_puts over ethtool_sprintf with standalone \"%s\" specifier\n" . $herecurr) &&
+ $fix) {
+ $fixed[$fixlinenr] =~ s/\bethtool_sprintf\s*\(\s*($FuncArg)\s*,\s*"\%s"\s*,\s*($FuncArg)/ethtool_puts($1, $7)/;
+ }
+ }
+
+
# typecasts on min/max could be min_t/max_t
if ($perl_version_ok &&
defined $stat &&
diff --git a/scripts/checkstack.pl b/scripts/checkstack.pl
index 84f5fb7f1cec..14ce31f732ee 100755
--- a/scripts/checkstack.pl
+++ b/scripts/checkstack.pl
@@ -8,7 +8,6 @@
# Original idea maybe from Keith Owens
# s390 port and big speedup by Arnd Bergmann <arnd@bergmann-dalldorf.de>
# Mips port by Juan Quintela <quintela@mandrakesoft.com>
-# IA64 port via Andreas Dilger
# Arm port by Holger Schurig
# Random bits by Matt Mackall <mpm@selenic.com>
# M68k port by Geert Uytterhoeven and Andreas Schwab
@@ -16,9 +15,10 @@
# sparc port by Martin Habets <errandir_news@mph.eclipse.co.uk>
# ppc64le port by Breno Leitao <leitao@debian.org>
# riscv port by Wadim Mueller <wafgo01@gmail.com>
+# loongarch port by Youling Tang <tangyouling@kylinos.cn>
#
# Usage:
-# objdump -d vmlinux | scripts/checkstack.pl [arch]
+# objdump -d vmlinux | scripts/checkstack.pl [arch] [min_stack]
#
# TODO : Port to all architectures (one regex per arch)
@@ -47,7 +47,7 @@ my (@stack, $re, $dre, $sub, $x, $xs, $funcre, $min_stack);
$min_stack = shift;
if ($min_stack eq "" || $min_stack !~ /^\d+$/) {
- $min_stack = 100;
+ $min_stack = 512;
}
$x = "[0-9a-f]"; # hex character
@@ -56,7 +56,7 @@ my (@stack, $re, $dre, $sub, $x, $xs, $funcre, $min_stack);
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;
+ $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
@@ -68,25 +68,22 @@ my (@stack, $re, $dre, $sub, $x, $xs, $funcre, $min_stack);
# 2f60: 48 81 ec e8 05 00 00 sub $0x5e8,%rsp
$re = qr/^.*[as][du][db] \$(0x$x{1,8}),\%(e|r)sp$/o;
$dre = qr/^.*[as][du][db] (%.*),\%(e|r)sp$/o;
- } elsif ($arch eq 'ia64') {
- #e0000000044011fc: 01 0f fc 8c adds r12=-384,r12
- $re = qr/.*adds.*r12=-(([0-9]{2}|[3-9])[0-9]{2}),r12/o;
} elsif ($arch eq 'm68k') {
# 2b6c: 4e56 fb70 linkw %fp,#-1168
# 1df770: defc ffe4 addaw #-28,%sp
$re = qr/.*(?:linkw %fp,|addaw )#-([0-9]{1,4})(?:,%sp)?$/o;
} elsif ($arch eq 'mips64') {
#8800402c: 67bdfff0 daddiu sp,sp,-16
- $re = qr/.*daddiu.*sp,sp,-(([0-9]{2}|[3-9])[0-9]{2})/o;
+ $re = qr/.*daddiu.*sp,sp,-([0-9]{1,8})/o;
} elsif ($arch eq 'mips') {
#88003254: 27bdffe0 addiu sp,sp,-32
- $re = qr/.*addiu.*sp,sp,-(([0-9]{2}|[3-9])[0-9]{2})/o;
+ $re = qr/.*addiu.*sp,sp,-([0-9]{1,8})/o;
} elsif ($arch eq 'nios2') {
#25a8: defffb04 addi sp,sp,-20
- $re = qr/.*addi.*sp,sp,-(([0-9]{2}|[3-9])[0-9]{2})/o;
+ $re = qr/.*addi.*sp,sp,-([0-9]{1,8})/o;
} elsif ($arch eq 'openrisc') {
# c000043c: 9c 21 fe f0 l.addi r1,r1,-272
- $re = qr/.*l\.addi.*r1,r1,-(([0-9]{2}|[3-9])[0-9]{2})/o;
+ $re = qr/.*l\.addi.*r1,r1,-([0-9]{1,8})/o;
} elsif ($arch eq 'parisc' || $arch eq 'parisc64') {
$re = qr/.*ldo ($x{1,8})\(sp\),sp/o;
} elsif ($arch eq 'powerpc' || $arch =~ /^ppc(64)?(le)?$/ ) {
@@ -97,14 +94,16 @@ my (@stack, $re, $dre, $sub, $x, $xs, $funcre, $min_stack);
# 11160: a7 fb ff 60 aghi %r15,-160
# or
# 100092: e3 f0 ff c8 ff 71 lay %r15,-56(%r15)
- $re = qr/.*(?:lay|ag?hi).*\%r15,-(([0-9]{2}|[3-9])[0-9]{2})
- (?:\(\%r15\))?$/ox;
+ $re = qr/.*(?:lay|ag?hi).*\%r15,-([0-9]+)(?:\(\%r15\))?$/o;
} elsif ($arch eq 'sparc' || $arch eq 'sparc64') {
# f0019d10: 9d e3 bf 90 save %sp, -112, %sp
- $re = qr/.*save.*%sp, -(([0-9]{2}|[3-9])[0-9]{2}), %sp/o;
+ $re = qr/.*save.*%sp, -([0-9]{1,8}), %sp/o;
} elsif ($arch =~ /^riscv(64)?$/) {
#ffffffff8036e868: c2010113 addi sp,sp,-992
- $re = qr/.*addi.*sp,sp,-(([0-9]{2}|[3-9])[0-9]{2})/o;
+ $re = qr/.*addi.*sp,sp,-([0-9]{1,8})/o;
+ } elsif ($arch =~ /^loongarch(32|64)?$/) {
+ #9000000000224708: 02ff4063 addi.d $sp, $sp, -48(0xfd0)
+ $re = qr/.*addi\..*sp, .*sp, -([0-9]{1,8}).*/o;
} else {
print("wrong or unknown architecture \"$arch\"\n");
exit
@@ -139,15 +138,11 @@ $total_size = 0;
while (my $line = <STDIN>) {
if ($line =~ m/$funcre/) {
$func = $1;
- next if $line !~ m/^($xs*)/;
+ next if $line !~ m/^($x*)/;
if ($total_size > $min_stack) {
push @stack, "$intro$total_size\n";
}
-
- $addr = $1;
- $addr =~ s/ /0/g;
- $addr = "0x$addr";
-
+ $addr = "0x$1";
$intro = "$addr $func [$file]:";
my $padlen = 56 - length($intro);
while ($padlen > 0) {
@@ -194,5 +189,20 @@ if ($total_size > $min_stack) {
push @stack, "$intro$total_size\n";
}
-# Sort output by size (last field)
-print sort { ($b =~ /:\t*(\d+)$/)[0] <=> ($a =~ /:\t*(\d+)$/)[0] } @stack;
+# Sort output by size (last field) and function name if size is the same
+sub sort_lines {
+ my ($a, $b) = @_;
+
+ my $num_a = $1 if $a =~ /:\t*(\d+)$/;
+ my $num_b = $1 if $b =~ /:\t*(\d+)$/;
+ my $func_a = $1 if $a =~ / (.*):/;
+ my $func_b = $1 if $b =~ / (.*):/;
+
+ if ($num_a != $num_b) {
+ return $num_b <=> $num_a;
+ } else {
+ return $func_a cmp $func_b;
+ }
+}
+
+print sort { sort_lines($a, $b) } @stack;
diff --git a/scripts/clang-tools/gen_compile_commands.py b/scripts/clang-tools/gen_compile_commands.py
index a84cc5737c2c..e4fb686dfaa9 100755
--- a/scripts/clang-tools/gen_compile_commands.py
+++ b/scripts/clang-tools/gen_compile_commands.py
@@ -19,7 +19,7 @@ _DEFAULT_OUTPUT = 'compile_commands.json'
_DEFAULT_LOG_LEVEL = 'WARNING'
_FILENAME_PATTERN = r'^\..*\.cmd$'
-_LINE_PATTERN = r'^savedcmd_[^ ]*\.o := (.* )([^ ]*\.[cS]) *(;|$)'
+_LINE_PATTERN = r'^(saved)?cmd_[^ ]*\.o := (?P<command_prefix>.* )(?P<file_path>[^ ]*\.[cS]) *(;|$)'
_VALID_LOG_LEVELS = ['DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL']
# The tools/ directory adopts a different build system, and produces .cmd
# files in a different format. Do not support it.
@@ -64,7 +64,7 @@ def parse_arguments():
args = parser.parse_args()
return (args.log_level,
- os.path.abspath(args.directory),
+ os.path.realpath(args.directory),
args.output,
args.ar,
args.paths if len(args.paths) > 0 else [args.directory])
@@ -170,10 +170,10 @@ def process_line(root_directory, command_prefix, file_path):
# 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)', '#')
+ prefix = command_prefix.replace(r'\#', '#').replace('$(pound)', '#')
- # Use os.path.abspath() to normalize the path resolving '.' and '..' .
- abs_path = os.path.abspath(os.path.join(root_directory, file_path))
+ # Return the canonical path, eliminating any symbolic links encountered in the path.
+ abs_path = os.path.realpath(os.path.join(root_directory, file_path))
if not os.path.exists(abs_path):
raise ValueError('File %s not found' % abs_path)
return {
@@ -213,15 +213,15 @@ def main():
result = line_matcher.match(f.readline())
if result:
try:
- entry = process_line(directory, result.group(1),
- result.group(2))
+ entry = process_line(directory, result.group('command_prefix'),
+ result.group('file_path'))
compile_commands.append(entry)
except ValueError as err:
logging.info('Could not add line from %s: %s',
cmdfile, err)
with open(output, 'wt') as f:
- json.dump(compile_commands, f, indent=2, sort_keys=True)
+ json.dump(sorted(compile_commands, key=lambda x: x["file"]), f, indent=2, sort_keys=True)
if __name__ == '__main__':
diff --git a/scripts/clang-tools/run-clang-tools.py b/scripts/clang-tools/run-clang-tools.py
index 3266708a8658..f31ffd09e1ea 100755
--- a/scripts/clang-tools/run-clang-tools.py
+++ b/scripts/clang-tools/run-clang-tools.py
@@ -33,6 +33,11 @@ def parse_arguments():
path_help = "Path to the compilation database to parse"
parser.add_argument("path", type=str, help=path_help)
+ checks_help = "Checks to pass to the analysis"
+ parser.add_argument("-checks", type=str, default=None, help=checks_help)
+ header_filter_help = "Pass the -header-filter value to the tool"
+ parser.add_argument("-header-filter", type=str, default=None, help=header_filter_help)
+
return parser.parse_args()
@@ -45,14 +50,27 @@ def init(l, a):
def run_analysis(entry):
# Disable all checks, then re-enable the ones we want
- checks = []
- checks.append("-checks=-*")
- if args.type == "clang-tidy":
- checks.append("linuxkernel-*")
+ global args
+ checks = None
+ if args.checks:
+ checks = args.checks.split(',')
else:
- checks.append("clang-analyzer-*")
- checks.append("-clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling")
- p = subprocess.run(["clang-tidy", "-p", args.path, ",".join(checks), entry["file"]],
+ checks = ["-*"]
+ if args.type == "clang-tidy":
+ checks.append("linuxkernel-*")
+ else:
+ checks.append("clang-analyzer-*")
+ checks.append("-clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling")
+ file = entry["file"]
+ if not file.endswith(".c") and not file.endswith(".cpp"):
+ with lock:
+ print(f"Skipping non-C file: '{file}'", file=sys.stderr)
+ return
+ pargs = ["clang-tidy", "-p", args.path, "-checks=" + ",".join(checks)]
+ if args.header_filter:
+ pargs.append("-header-filter=" + args.header_filter)
+ pargs.append(file)
+ p = subprocess.run(pargs,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
cwd=entry["directory"])
diff --git a/scripts/coccinelle/api/device_attr_show.cocci b/scripts/coccinelle/api/device_attr_show.cocci
index a28dc061653a..dfcf9304195f 100644
--- a/scripts/coccinelle/api/device_attr_show.cocci
+++ b/scripts/coccinelle/api/device_attr_show.cocci
@@ -1,10 +1,8 @@
// SPDX-License-Identifier: GPL-2.0-only
///
/// From Documentation/filesystems/sysfs.rst:
-/// show() must not use snprintf() when formatting the value to be
-/// returned to user space. If you can guarantee that an overflow
-/// will never happen you can use sprintf() otherwise you must use
-/// scnprintf().
+/// show() should only use sysfs_emit() or sysfs_emit_at() when formatting
+/// the value to be returned to user space.
///
// Confidence: High
// Copyright: (C) 2020 Denis Efremov ISPRAS
@@ -30,15 +28,16 @@ ssize_t show(struct device *dev, struct device_attribute *attr, char *buf)
@rp depends on patch@
identifier show, dev, attr, buf;
+expression BUF, SZ, FORMAT;
@@
ssize_t show(struct device *dev, struct device_attribute *attr, char *buf)
{
<...
return
-- snprintf
-+ scnprintf
- (...);
+- snprintf(BUF, SZ, FORMAT
++ sysfs_emit(BUF, FORMAT
+ ,...);
...>
}
@@ -46,10 +45,10 @@ ssize_t show(struct device *dev, struct device_attribute *attr, char *buf)
p << r.p;
@@
-coccilib.report.print_report(p[0], "WARNING: use scnprintf or sprintf")
+coccilib.report.print_report(p[0], "WARNING: please use sysfs_emit or sysfs_emit_at")
@script: python depends on org@
p << r.p;
@@
-coccilib.org.print_todo(p[0], "WARNING: use scnprintf or sprintf")
+coccilib.org.print_todo(p[0], "WARNING: please use sysfs_emit or sysfs_emit_at")
diff --git a/scripts/coccinelle/api/string_choices.cocci b/scripts/coccinelle/api/string_choices.cocci
new file mode 100644
index 000000000000..a71966c0494e
--- /dev/null
+++ b/scripts/coccinelle/api/string_choices.cocci
@@ -0,0 +1,41 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/// Find places to use string_choices.h's various helpers.
+//
+// Confidence: Medium
+// Options: --no-includes --include-headers
+virtual patch
+virtual context
+virtual report
+
+@str_plural depends on patch@
+expression E;
+@@
+(
+- ((E == 1) ? "" : "s")
++ str_plural(E)
+|
+- ((E != 1) ? "s" : "")
++ str_plural(E)
+|
+- ((E > 1) ? "s" : "")
++ str_plural(E)
+)
+
+@str_plural_r depends on !patch exists@
+expression E;
+position P;
+@@
+(
+* ((E@P == 1) ? "" : "s")
+|
+* ((E@P != 1) ? "s" : "")
+|
+* ((E@P > 1) ? "s" : "")
+)
+
+@script:python depends on report@
+p << str_plural_r.P;
+e << str_plural_r.E;
+@@
+
+coccilib.report.print_report(p[0], "opportunity for str_plural(%s)" % e)
diff --git a/scripts/coccinelle/misc/struct_size.cocci b/scripts/coccinelle/misc/struct_size.cocci
new file mode 100644
index 000000000000..9b02c37438e4
--- /dev/null
+++ b/scripts/coccinelle/misc/struct_size.cocci
@@ -0,0 +1,74 @@
+// SPDX-License-Identifier: GPL-2.0-only
+///
+/// Check for code that could use struct_size().
+///
+// Confidence: Medium
+// Author: Jacob Keller <jacob.e.keller@intel.com>
+// Copyright: (C) 2023 Intel Corporation
+// Options: --no-includes --include-headers
+
+virtual patch
+virtual context
+virtual org
+virtual report
+
+// the overflow Kunit tests have some code which intentionally does not use
+// the macros, so we want to ignore this code when reporting potential
+// issues.
+@overflow_tests@
+identifier f = overflow_size_helpers_test;
+@@
+
+f
+
+//----------------------------------------------------------
+// For context mode
+//----------------------------------------------------------
+
+@depends on !overflow_tests && context@
+expression E1, E2;
+identifier m;
+@@
+(
+* (sizeof(*E1) + (E2 * sizeof(*E1->m)))
+)
+
+//----------------------------------------------------------
+// For patch mode
+//----------------------------------------------------------
+
+@depends on !overflow_tests && patch@
+expression E1, E2;
+identifier m;
+@@
+(
+- (sizeof(*E1) + (E2 * sizeof(*E1->m)))
++ struct_size(E1, m, E2)
+)
+
+//----------------------------------------------------------
+// For org and report mode
+//----------------------------------------------------------
+
+@r depends on !overflow_tests && (org || report)@
+expression E1, E2;
+identifier m;
+position p;
+@@
+(
+ (sizeof(*E1)@p + (E2 * sizeof(*E1->m)))
+)
+
+@script:python depends on org@
+p << r.p;
+@@
+
+coccilib.org.print_todo(p[0], "WARNING should use struct_size")
+
+@script:python depends on report@
+p << r.p;
+@@
+
+msg="WARNING: Use struct_size"
+coccilib.report.print_report(p[0], msg)
+
diff --git a/scripts/const_structs.checkpatch b/scripts/const_structs.checkpatch
index dc39d938ea77..fa96cfd16e99 100644
--- a/scripts/const_structs.checkpatch
+++ b/scripts/const_structs.checkpatch
@@ -2,11 +2,13 @@ acpi_dock_ops
address_space_operations
backlight_ops
block_device_operations
+bus_type
clk_ops
comedi_lrange
component_ops
dentry_operations
dev_pm_ops
+device_type
dma_map_ops
driver_info
drm_connector_funcs
@@ -94,3 +96,4 @@ vm_operations_struct
wacom_features
watchdog_ops
wd_ops
+xattr_handler
diff --git a/scripts/decode_stacktrace.sh b/scripts/decode_stacktrace.sh
index 564c5632e1a2..fa5be6f57b00 100755
--- a/scripts/decode_stacktrace.sh
+++ b/scripts/decode_stacktrace.sh
@@ -16,6 +16,21 @@ elif type c++filt >/dev/null 2>&1 ; then
cppfilt_opts=-i
fi
+UTIL_SUFFIX=
+if [[ -z ${LLVM:-} ]]; then
+ UTIL_PREFIX=${CROSS_COMPILE:-}
+else
+ UTIL_PREFIX=llvm-
+ if [[ ${LLVM} == */ ]]; then
+ UTIL_PREFIX=${LLVM}${UTIL_PREFIX}
+ elif [[ ${LLVM} == -* ]]; then
+ UTIL_SUFFIX=${LLVM}
+ fi
+fi
+
+READELF=${UTIL_PREFIX}readelf${UTIL_SUFFIX}
+ADDR2LINE=${UTIL_PREFIX}addr2line${UTIL_SUFFIX}
+
if [[ $1 == "-r" ]] ; then
vmlinux=""
basepath="auto"
@@ -75,7 +90,7 @@ find_module() {
if [[ "$modpath" != "" ]] ; then
for fn in $(find "$modpath" -name "${module//_/[-_]}.ko*") ; do
- if readelf -WS "$fn" | grep -qwF .debug_line ; then
+ if ${READELF} -WS "$fn" | grep -qwF .debug_line ; then
echo $fn
return
fi
@@ -169,7 +184,7 @@ parse_symbol() {
if [[ $aarray_support == true && "${cache[$module,$address]+isset}" == "isset" ]]; then
local code=${cache[$module,$address]}
else
- local code=$(${CROSS_COMPILE}addr2line -i -e "$objfile" "$address" 2>/dev/null)
+ local code=$(${ADDR2LINE} -i -e "$objfile" "$address" 2>/dev/null)
if [[ $aarray_support == true ]]; then
cache[$module,$address]=$code
fi
@@ -291,6 +306,9 @@ handle_line() {
}
while read line; do
+ # Strip unexpected carriage return at end of line
+ line=${line%$'\r'}
+
# Let's see if we have an address in the line
if [[ $line =~ \[\<([^]]+)\>\] ]] ||
[[ $line =~ [^+\ ]+\+0x[0-9a-f]+/0x[0-9a-f]+ ]]; then
diff --git a/scripts/decodecode b/scripts/decodecode
index 8fe71c292381..6364218b2178 100755
--- a/scripts/decodecode
+++ b/scripts/decodecode
@@ -67,6 +67,7 @@ if [ -z "$ARCH" ]; then
case `uname -m` in
aarch64*) ARCH=arm64 ;;
arm*) ARCH=arm ;;
+ loongarch*) ARCH=loongarch ;;
esac
fi
@@ -98,6 +99,10 @@ disas() {
${CROSS_COMPILE}strip $t.o
fi
+ if [ "$ARCH" = "loongarch" ]; then
+ ${CROSS_COMPILE}strip $t.o
+ fi
+
if [ $pc_sub -ne 0 ]; then
if [ $PC ]; then
adj_vma=$(( $PC - $pc_sub ))
diff --git a/scripts/dtc/dt-extract-compatibles b/scripts/dtc/dt-extract-compatibles
index 9df9f1face83..5ffb2364409b 100755
--- a/scripts/dtc/dt-extract-compatibles
+++ b/scripts/dtc/dt-extract-compatibles
@@ -1,17 +1,21 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: GPL-2.0-only
+import fnmatch
import os
-import glob
import re
import argparse
-def parse_of_declare_macros(data):
+def parse_of_declare_macros(data, include_driver_macros=True):
""" Find all compatible strings in OF_DECLARE() style macros """
compat_list = []
# CPU_METHOD_OF_DECLARE does not have a compatible string
- for m in re.finditer(r'(?<!CPU_METHOD_)(IRQCHIP|OF)_(DECLARE|MATCH)(_DRIVER)?\(.*?\)', data):
+ if include_driver_macros:
+ re_macros = r'(?<!CPU_METHOD_)(IRQCHIP|OF)_(DECLARE|MATCH)(_DRIVER)?\(.*?\)'
+ else:
+ re_macros = r'(?<!CPU_METHOD_)(IRQCHIP|OF)_(DECLARE|MATCH)\(.*?\)'
+ for m in re.finditer(re_macros, data):
try:
compat = re.search(r'"(.*?)"', m[0])[1]
except:
@@ -22,24 +26,52 @@ def parse_of_declare_macros(data):
return compat_list
-def parse_of_device_id(data):
+def parse_of_device_id(data, match_table_list=None):
""" Find all compatible strings in of_device_id structs """
compat_list = []
- for m in re.finditer(r'of_device_id(\s+\S+)?\s+\S+\[\](\s+\S+)?\s*=\s*({.*?);', data):
- compat_list += re.findall(r'\.compatible\s+=\s+"(\S+)"', m[3])
+ for m in re.finditer(r'of_device_id(\s+\S+)?\s+(\S+)\[\](\s+\S+)?\s*=\s*({.*?);', data):
+ if match_table_list is not None and m[2] not in match_table_list:
+ continue
+ compat_list += re.findall(r'\.compatible\s+=\s+"(\S+)"', m[4])
return compat_list
-def parse_compatibles(file):
+def parse_of_match_table(data):
+ """ Find all driver's of_match_table """
+ match_table_list = []
+ for m in re.finditer(r'\.of_match_table\s+=\s+(of_match_ptr\()?([a-zA-Z0-9_-]+)', data):
+ match_table_list.append(m[2])
+
+ return match_table_list
+
+
+def parse_compatibles(file, compat_ignore_list):
with open(file, 'r', encoding='utf-8') as f:
data = f.read().replace('\n', '')
- compat_list = parse_of_declare_macros(data)
- compat_list += parse_of_device_id(data)
+ if compat_ignore_list is not None:
+ # For a compatible in the DT to be matched to a driver it needs to show
+ # up in a driver's of_match_table
+ match_table_list = parse_of_match_table(data)
+ compat_list = parse_of_device_id(data, match_table_list)
+
+ compat_list = [compat for compat in compat_list if compat not in compat_ignore_list]
+ else:
+ compat_list = parse_of_declare_macros(data)
+ compat_list += parse_of_device_id(data)
return compat_list
+def parse_compatibles_to_ignore(file):
+ with open(file, 'r', encoding='utf-8') as f:
+ data = f.read().replace('\n', '')
+
+ # Compatibles that show up in OF_DECLARE macros can't be expected to
+ # match a driver, except for the _DRIVER ones.
+ return parse_of_declare_macros(data, include_driver_macros=False)
+
+
def print_compat(filename, compatibles):
if not compatibles:
return
@@ -49,21 +81,41 @@ def print_compat(filename, compatibles):
else:
print(*compatibles, sep='\n')
+def glob_without_symlinks(root, glob):
+ for path, dirs, files in os.walk(root):
+ # Ignore hidden directories
+ for d in dirs:
+ if fnmatch.fnmatch(d, ".*"):
+ dirs.remove(d)
+ for f in files:
+ if fnmatch.fnmatch(f, glob):
+ yield os.path.join(path, f)
+
+def files_to_parse(path_args):
+ for f in path_args:
+ if os.path.isdir(f):
+ for filename in glob_without_symlinks(f, "*.c"):
+ yield filename
+ else:
+ yield f
+
show_filename = False
if __name__ == "__main__":
ap = argparse.ArgumentParser()
ap.add_argument("cfile", type=str, nargs='*', help="C source files or directories to parse")
ap.add_argument('-H', '--with-filename', help="Print filename with compatibles", action="store_true")
+ ap.add_argument('-d', '--driver-match', help="Only print compatibles that should match to a driver", action="store_true")
args = ap.parse_args()
show_filename = args.with_filename
+ compat_ignore_list = None
- for f in args.cfile:
- if os.path.isdir(f):
- for filename in glob.iglob(f + "/**/*.c", recursive=True):
- compat_list = parse_compatibles(filename)
- print_compat(filename, compat_list)
- else:
- compat_list = parse_compatibles(f)
- print_compat(f, compat_list)
+ if args.driver_match:
+ compat_ignore_list = []
+ for f in files_to_parse(args.cfile):
+ compat_ignore_list.extend(parse_compatibles_to_ignore(f))
+
+ for f in files_to_parse(args.cfile):
+ compat_list = parse_compatibles(f, compat_ignore_list)
+ print_compat(f, compat_list)
diff --git a/scripts/dummy-tools/gcc b/scripts/dummy-tools/gcc
index 07f6dc4c5cf6..e6c41427c02f 100755
--- a/scripts/dummy-tools/gcc
+++ b/scripts/dummy-tools/gcc
@@ -91,6 +91,16 @@ if arg_contain -S "$@"; then
fi
exit 0
fi
+
+ # For arch/powerpc/tools/gcc-check-fpatchable-function-entry.sh
+ if arg_contain -m64 "$@" && arg_contain -fpatchable-function-entry=2 "$@"; then
+ echo "func:"
+ echo ".section __patchable_function_entries"
+ echo ".localentry"
+ echo " nop"
+ echo " nop"
+ exit 0
+ fi
fi
# To set GCC_PLUGINS
diff --git a/scripts/faddr2line b/scripts/faddr2line
index 0e73aca4f908..587415a52b6f 100755
--- a/scripts/faddr2line
+++ b/scripts/faddr2line
@@ -58,8 +58,21 @@ die() {
exit 1
}
-READELF="${CROSS_COMPILE:-}readelf"
-ADDR2LINE="${CROSS_COMPILE:-}addr2line"
+UTIL_SUFFIX=""
+if [[ "${LLVM:-}" == "" ]]; then
+ UTIL_PREFIX=${CROSS_COMPILE:-}
+else
+ UTIL_PREFIX=llvm-
+
+ if [[ "${LLVM}" == *"/" ]]; then
+ UTIL_PREFIX=${LLVM}${UTIL_PREFIX}
+ elif [[ "${LLVM}" == "-"* ]]; then
+ UTIL_SUFFIX=${LLVM}
+ fi
+fi
+
+READELF="${UTIL_PREFIX}readelf${UTIL_SUFFIX}"
+ADDR2LINE="${UTIL_PREFIX}addr2line${UTIL_SUFFIX}"
AWK="awk"
GREP="grep"
@@ -166,6 +179,11 @@ __faddr2line() {
local cur_sym_elf_size=${fields[2]}
local cur_sym_name=${fields[7]:-}
+ # is_mapping_symbol(cur_sym_name)
+ if [[ ${cur_sym_name} =~ ^(\.L|L0|\$) ]]; then
+ continue
+ fi
+
if [[ $cur_sym_addr = $sym_addr ]] &&
[[ $cur_sym_elf_size = $sym_elf_size ]] &&
[[ $cur_sym_name = $sym_name ]]; then
@@ -260,7 +278,7 @@ __faddr2line() {
DONE=1
- done < <(${READELF} --symbols --wide $objfile | sed 's/\[.*\]//' | ${AWK} -v fn=$sym_name '$4 == "FUNC" && $8 == fn')
+ done < <(${READELF} --symbols --wide $objfile | sed 's/\[.*\]//' | ${AWK} -v fn=$sym_name '$8 == fn')
}
[[ $# -lt 2 ]] && usage
diff --git a/scripts/gcc-plugins/latent_entropy_plugin.c b/scripts/gcc-plugins/latent_entropy_plugin.c
index 39e86be60dd2..ff0b192be91f 100644
--- a/scripts/gcc-plugins/latent_entropy_plugin.c
+++ b/scripts/gcc-plugins/latent_entropy_plugin.c
@@ -17,7 +17,7 @@
* if (argc <= 1)
* printf("%s: no command arguments :(\n", *argv);
* else
- * printf("%s: %d command arguments!\n", *argv, args - 1);
+ * printf("%s: %d command arguments!\n", *argv, argc - 1);
* }
*
* after:
@@ -47,7 +47,7 @@
* // perturb_local_entropy()
* } else {
* local_entropy ^= 3896280633962944730;
- * printf("%s: %d command arguments!\n", *argv, args - 1);
+ * printf("%s: %d command arguments!\n", *argv, argc - 1);
* }
*
* // latent_entropy_execute() 4.
diff --git a/scripts/gcc-plugins/randomize_layout_plugin.c b/scripts/gcc-plugins/randomize_layout_plugin.c
index 951b74ba1b24..746ff2d272f2 100644
--- a/scripts/gcc-plugins/randomize_layout_plugin.c
+++ b/scripts/gcc-plugins/randomize_layout_plugin.c
@@ -191,12 +191,14 @@ static void partition_struct(tree *fields, unsigned long length, struct partitio
static void performance_shuffle(tree *newtree, unsigned long length, ranctx *prng_state)
{
- unsigned long i, x;
+ unsigned long i, x, index;
struct partition_group size_group[length];
unsigned long num_groups = 0;
unsigned long randnum;
partition_struct(newtree, length, (struct partition_group *)&size_group, &num_groups);
+
+ /* FIXME: this group shuffle is currently a no-op. */
for (i = num_groups - 1; i > 0; i--) {
struct partition_group tmp;
randnum = ranval(prng_state) % (i + 1);
@@ -206,11 +208,14 @@ static void performance_shuffle(tree *newtree, unsigned long length, ranctx *prn
}
for (x = 0; x < num_groups; x++) {
- for (i = size_group[x].start + size_group[x].length - 1; i > size_group[x].start; i--) {
+ for (index = size_group[x].length - 1; index > 0; index--) {
tree tmp;
+
+ i = size_group[x].start + index;
if (DECL_BIT_FIELD_TYPE(newtree[i]))
continue;
- randnum = ranval(prng_state) % (i + 1);
+ randnum = ranval(prng_state) % (index + 1);
+ randnum += size_group[x].start;
// we could handle this case differently if desired
if (DECL_BIT_FIELD_TYPE(newtree[randnum]))
continue;
@@ -273,8 +278,6 @@ static bool is_flexible_array(const_tree field)
{
const_tree fieldtype;
const_tree typesize;
- const_tree elemtype;
- const_tree elemsize;
fieldtype = TREE_TYPE(field);
typesize = TYPE_SIZE(fieldtype);
@@ -282,20 +285,12 @@ static bool is_flexible_array(const_tree field)
if (TREE_CODE(fieldtype) != ARRAY_TYPE)
return false;
- elemtype = TREE_TYPE(fieldtype);
- elemsize = TYPE_SIZE(elemtype);
-
/* size of type is represented in bits */
if (typesize == NULL_TREE && TYPE_DOMAIN(fieldtype) != NULL_TREE &&
TYPE_MAX_VALUE(TYPE_DOMAIN(fieldtype)) == NULL_TREE)
return true;
- if (typesize != NULL_TREE &&
- (TREE_CONSTANT(typesize) && (!tree_to_uhwi(typesize) ||
- tree_to_uhwi(typesize) == tree_to_uhwi(elemsize))))
- return true;
-
return false;
}
@@ -344,8 +339,7 @@ static int relayout_struct(tree type)
/*
* enforce that we don't randomize the layout of the last
- * element of a struct if it's a 0 or 1-length array
- * or a proper flexible array
+ * element of a struct if it's a proper flexible array
*/
if (is_flexible_array(newtree[num_fields - 1])) {
has_flexarray = true;
diff --git a/scripts/gcc-plugins/stackleak_plugin.c b/scripts/gcc-plugins/stackleak_plugin.c
index c5c2ce113c92..d20c47d21ad8 100644
--- a/scripts/gcc-plugins/stackleak_plugin.c
+++ b/scripts/gcc-plugins/stackleak_plugin.c
@@ -467,6 +467,8 @@ static bool stackleak_gate(void)
return false;
if (STRING_EQUAL(section, ".entry.text"))
return false;
+ if (STRING_EQUAL(section, ".head.text"))
+ return false;
}
return track_frame_size >= 0;
diff --git a/scripts/gdb/linux/constants.py.in b/scripts/gdb/linux/constants.py.in
index e3517d4ab8ec..fd6bd69c5096 100644
--- a/scripts/gdb/linux/constants.py.in
+++ b/scripts/gdb/linux/constants.py.in
@@ -66,10 +66,11 @@ LX_GDBPARSED(IRQD_LEVEL)
LX_GDBPARSED(IRQ_HIDDEN)
/* linux/module.h */
-LX_GDBPARSED(MOD_TEXT)
-LX_GDBPARSED(MOD_DATA)
-LX_GDBPARSED(MOD_RODATA)
-LX_GDBPARSED(MOD_RO_AFTER_INIT)
+if IS_BUILTIN(CONFIG_MODULES):
+ LX_GDBPARSED(MOD_TEXT)
+ LX_GDBPARSED(MOD_DATA)
+ LX_GDBPARSED(MOD_RODATA)
+ LX_GDBPARSED(MOD_RO_AFTER_INIT)
/* linux/mount.h */
LX_VALUE(MNT_NOSUID)
@@ -129,7 +130,11 @@ LX_CONFIG(CONFIG_X86_MCE_THRESHOLD)
LX_CONFIG(CONFIG_X86_MCE_AMD)
LX_CONFIG(CONFIG_X86_MCE)
LX_CONFIG(CONFIG_X86_IO_APIC)
-LX_CONFIG(CONFIG_HAVE_KVM)
+/*
+ * CONFIG_KVM can be "m" but it affects common code too. Use CONFIG_KVM_COMMON
+ * as a proxy for IS_ENABLED(CONFIG_KVM).
+ */
+LX_CONFIG_KVM = IS_BUILTIN(CONFIG_KVM_COMMON)
LX_CONFIG(CONFIG_NUMA)
LX_CONFIG(CONFIG_ARM64)
LX_CONFIG(CONFIG_ARM64_4K_PAGES)
@@ -138,7 +143,7 @@ LX_CONFIG(CONFIG_ARM64_64K_PAGES)
if IS_BUILTIN(CONFIG_ARM64):
LX_VALUE(CONFIG_ARM64_PA_BITS)
LX_VALUE(CONFIG_ARM64_VA_BITS)
- LX_VALUE(CONFIG_ARM64_PAGE_SHIFT)
+ LX_VALUE(CONFIG_PAGE_SHIFT)
LX_VALUE(CONFIG_ARCH_FORCE_MAX_ORDER)
LX_CONFIG(CONFIG_SPARSEMEM)
LX_CONFIG(CONFIG_SPARSEMEM_EXTREME)
@@ -157,3 +162,4 @@ LX_CONFIG(CONFIG_STACKDEPOT)
LX_CONFIG(CONFIG_PAGE_OWNER)
LX_CONFIG(CONFIG_SLUB_DEBUG)
LX_CONFIG(CONFIG_SLAB_FREELIST_HARDENED)
+LX_CONFIG(CONFIG_MMU)
diff --git a/scripts/gdb/linux/cpus.py b/scripts/gdb/linux/cpus.py
index 255dc18cb9da..cba589e5b57d 100644
--- a/scripts/gdb/linux/cpus.py
+++ b/scripts/gdb/linux/cpus.py
@@ -179,6 +179,21 @@ def get_current_task(cpu):
else:
raise gdb.GdbError("Sorry, obtaining the current task is not allowed "
"while running in userspace(EL0)")
+ elif utils.is_target_arch("riscv"):
+ current_tp = gdb.parse_and_eval("$tp")
+ scratch_reg = gdb.parse_and_eval("$sscratch")
+
+ # by default tp points to current task
+ current_task = current_tp.cast(task_ptr_type)
+
+ # scratch register is set 0 in trap handler after entering kernel.
+ # When hart is in user mode, scratch register is pointing to task_struct.
+ # and tp is used by user mode. So when scratch register holds larger value
+ # (negative address as ulong is larger value) than tp, then use scratch register.
+ if (scratch_reg.cast(utils.get_ulong_type()) > current_tp.cast(utils.get_ulong_type())):
+ current_task = scratch_reg.cast(task_ptr_type)
+
+ return current_task.dereference()
else:
raise gdb.GdbError("Sorry, obtaining the current task is not yet "
"supported with this arch")
diff --git a/scripts/gdb/linux/device.py b/scripts/gdb/linux/device.py
index 16376c5cfec6..0eabc5f4f8ca 100644
--- a/scripts/gdb/linux/device.py
+++ b/scripts/gdb/linux/device.py
@@ -36,26 +36,26 @@ 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']
+ yield subsys_priv
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']
+ yield subsys_priv
def get_bus_by_name(name):
for item in for_each_bus():
- if item['name'].string() == name:
+ if item['bus']['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:
+ if item['class']['name'].string() == name:
return item
raise gdb.GdbError("Can't find device class {!r}".format(name))
@@ -70,13 +70,13 @@ def klist_for_each(klist):
def bus_for_each_device(bus):
- for kn in klist_for_each(bus['p']['klist_devices']):
+ for kn in klist_for_each(bus['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']):
+ for kn in klist_for_each(cls['klist_devices']):
dp = container_of(kn, device_private_type.get_type().pointer(), 'knode_class')
yield dp['device']
@@ -103,7 +103,7 @@ class LxDeviceListBus(gdb.Command):
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))
+ gdb.write('bus {}:\t{}\n'.format(bus['bus']['name'].string(), bus))
for dev in bus_for_each_device(bus):
_show_device(dev, level=1)
else:
@@ -123,7 +123,7 @@ class LxDeviceListClass(gdb.Command):
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))
+ gdb.write("class {}:\t{}\n".format(cls['class']['name'].string(), cls))
for dev in class_for_each_device(cls):
_show_device(dev, level=1)
else:
diff --git a/scripts/gdb/linux/interrupts.py b/scripts/gdb/linux/interrupts.py
index ef478e273791..66ae5c7690cf 100644
--- a/scripts/gdb/linux/interrupts.py
+++ b/scripts/gdb/linux/interrupts.py
@@ -151,7 +151,7 @@ def x86_show_interupts(prec):
if cnt is not None:
text += "%*s: %10u\n" % (prec, "MIS", cnt['counter'])
- if constants.LX_CONFIG_HAVE_KVM:
+ if constants.LX_CONFIG_KVM:
text += x86_show_irqstat(prec, "PIN", 'kvm_posted_intr_ipis', 'Posted-interrupt notification event')
text += x86_show_irqstat(prec, "NPI", 'kvm_posted_intr_nested_ipis', 'Nested posted-interrupt event')
text += x86_show_irqstat(prec, "PIW", 'kvm_posted_intr_wakeup_ipis', 'Posted-interrupt wakeup event')
diff --git a/scripts/gdb/linux/mm.py b/scripts/gdb/linux/mm.py
index ad5641dcb068..515730fd4c9d 100644
--- a/scripts/gdb/linux/mm.py
+++ b/scripts/gdb/linux/mm.py
@@ -41,7 +41,7 @@ class aarch64_page_ops():
self.SECTION_SIZE_BITS = 27
self.MAX_PHYSMEM_BITS = constants.LX_CONFIG_ARM64_VA_BITS
- self.PAGE_SHIFT = constants.LX_CONFIG_ARM64_PAGE_SHIFT
+ self.PAGE_SHIFT = constants.LX_CONFIG_PAGE_SHIFT
self.PAGE_SIZE = 1 << self.PAGE_SHIFT
self.PAGE_MASK = (~(self.PAGE_SIZE - 1)) & ((1 << 64) - 1)
diff --git a/scripts/gdb/linux/page_owner.py b/scripts/gdb/linux/page_owner.py
index 844fd5d0c912..8e713a09cfe7 100644
--- a/scripts/gdb/linux/page_owner.py
+++ b/scripts/gdb/linux/page_owner.py
@@ -122,27 +122,24 @@ class DumpPageOwner(gdb.Command):
if not (page_ext['flags'] & (1 << PAGE_EXT_OWNER_ALLOCATED)):
gdb.write("page_owner is not allocated\n")
- try:
- page_owner = self.get_page_owner(page_ext)
- gdb.write("Page last allocated via order %d, gfp_mask: 0x%x, pid: %d, tgid: %d (%s), ts %u ns, free_ts %u ns\n" %\
- (page_owner["order"], page_owner["gfp_mask"],\
- page_owner["pid"], page_owner["tgid"], page_owner["comm"],\
- page_owner["ts_nsec"], page_owner["free_ts_nsec"]))
- gdb.write("PFN: %d, Flags: 0x%x\n" % (pfn, page['flags']))
- if page_owner["handle"] == 0:
- gdb.write('page_owner allocation stack trace missing\n')
- else:
- stackdepot.stack_depot_print(page_owner["handle"])
+ page_owner = self.get_page_owner(page_ext)
+ gdb.write("Page last allocated via order %d, gfp_mask: 0x%x, pid: %d, tgid: %d (%s), ts %u ns, free_ts %u ns\n" %\
+ (page_owner["order"], page_owner["gfp_mask"],\
+ page_owner["pid"], page_owner["tgid"], page_owner["comm"].string(),\
+ page_owner["ts_nsec"], page_owner["free_ts_nsec"]))
+ gdb.write("PFN: %d, Flags: 0x%x\n" % (pfn, page['flags']))
+ if page_owner["handle"] == 0:
+ gdb.write('page_owner allocation stack trace missing\n')
+ else:
+ stackdepot.stack_depot_print(page_owner["handle"])
- if page_owner["free_handle"] == 0:
- gdb.write('page_owner free stack trace missing\n')
- else:
- gdb.write('page last free stack trace:\n')
- stackdepot.stack_depot_print(page_owner["free_handle"])
- if page_owner['last_migrate_reason'] != -1:
- gdb.write('page has been migrated, last migrate reason: %s\n' % self.migrate_reason_names[page_owner['last_migrate_reason']])
- except:
- gdb.write("\n")
+ if page_owner["free_handle"] == 0:
+ gdb.write('page_owner free stack trace missing\n')
+ else:
+ gdb.write('page last free stack trace:\n')
+ stackdepot.stack_depot_print(page_owner["free_handle"])
+ if page_owner['last_migrate_reason'] != -1:
+ gdb.write('page has been migrated, last migrate reason: %s\n' % self.migrate_reason_names[page_owner['last_migrate_reason']])
def read_page_owner(self):
pfn = self.min_pfn
@@ -173,18 +170,13 @@ class DumpPageOwner(gdb.Command):
pfn += 1
continue
- try:
- page_owner = self.get_page_owner(page_ext)
- gdb.write("Page allocated via order %d, gfp_mask: 0x%x, pid: %d, tgid: %d (%s), ts %u ns, free_ts %u ns\n" %\
- (page_owner["order"], page_owner["gfp_mask"],\
- page_owner["pid"], page_owner["tgid"], page_owner["comm"],\
- page_owner["ts_nsec"], page_owner["free_ts_nsec"]))
- gdb.write("PFN: %d, Flags: 0x%x\n" % (pfn, page['flags']))
- stackdepot.stack_depot_print(page_owner["handle"])
- pfn += (1 << page_owner["order"])
- continue
- except:
- gdb.write("\n")
- pfn += 1
+ page_owner = self.get_page_owner(page_ext)
+ gdb.write("Page allocated via order %d, gfp_mask: 0x%x, pid: %d, tgid: %d (%s), ts %u ns, free_ts %u ns\n" %\
+ (page_owner["order"], page_owner["gfp_mask"],\
+ page_owner["pid"], page_owner["tgid"], page_owner["comm"].string(),\
+ page_owner["ts_nsec"], page_owner["free_ts_nsec"]))
+ gdb.write("PFN: %d, Flags: 0x%x\n" % (pfn, page['flags']))
+ stackdepot.stack_depot_print(page_owner["handle"])
+ pfn += (1 << page_owner["order"])
DumpPageOwner()
diff --git a/scripts/gdb/linux/slab.py b/scripts/gdb/linux/slab.py
index f012ba38c7d9..0e2d93867fe2 100644
--- a/scripts/gdb/linux/slab.py
+++ b/scripts/gdb/linux/slab.py
@@ -228,8 +228,7 @@ def slabtrace(alloc, cache_name):
nr_cpu = gdb.parse_and_eval('__num_online_cpus')['counter']
if nr_cpu > 1:
gdb.write(" cpus=")
- for i in loc['cpus']:
- gdb.write("%d," % i)
+ gdb.write(','.join(str(cpu) for cpu in loc['cpus']))
gdb.write("\n")
if constants.LX_CONFIG_STACKDEPOT:
if loc['handle']:
diff --git a/scripts/gdb/linux/stackdepot.py b/scripts/gdb/linux/stackdepot.py
index 047d329a6a12..0281d9de4b7c 100644
--- a/scripts/gdb/linux/stackdepot.py
+++ b/scripts/gdb/linux/stackdepot.py
@@ -25,10 +25,10 @@ def stack_depot_fetch(handle):
handle_parts_t = gdb.lookup_type("union handle_parts")
parts = handle.cast(handle_parts_t)
offset = parts['offset'] << DEPOT_STACK_ALIGN
- pool_index_cached = gdb.parse_and_eval('pool_index')
+ pools_num = gdb.parse_and_eval('pools_num')
- if parts['pool_index'] > pool_index_cached:
- gdb.write("pool index %d out of bounds (%d) for stack id 0x%08x\n" % (parts['pool_index'], pool_index_cached, handle))
+ if parts['pool_index'] > pools_num:
+ gdb.write("pool index %d out of bounds (%d) for stack id 0x%08x\n" % (parts['pool_index'], pools_num, handle))
return gdb.Value(0), 0
stack_pools = gdb.parse_and_eval('stack_pools')
diff --git a/scripts/gdb/linux/symbols.py b/scripts/gdb/linux/symbols.py
index c8047f4441e6..e8316beb17a7 100644
--- a/scripts/gdb/linux/symbols.py
+++ b/scripts/gdb/linux/symbols.py
@@ -82,7 +82,7 @@ lx-symbols command."""
self.module_files_updated = True
def _get_module_file(self, module_name):
- module_pattern = ".*/{0}\.ko(?:.debug)?$".format(
+ module_pattern = r".*/{0}\.ko(?:.debug)?$".format(
module_name.replace("_", r"[_\-]"))
for name in self.module_files:
if re.match(module_pattern, name) and os.path.exists(name):
diff --git a/scripts/gdb/linux/tasks.py b/scripts/gdb/linux/tasks.py
index 17ec19e9b5bf..6793d6e86e77 100644
--- a/scripts/gdb/linux/tasks.py
+++ b/scripts/gdb/linux/tasks.py
@@ -13,7 +13,7 @@
import gdb
-from linux import utils
+from linux import utils, lists
task_type = utils.CachedType("struct task_struct")
@@ -22,19 +22,15 @@ task_type = utils.CachedType("struct task_struct")
def task_lists():
task_ptr_type = task_type.get_type().pointer()
init_task = gdb.parse_and_eval("init_task").address
- t = g = init_task
+ t = init_task
while True:
- while True:
- yield t
+ thread_head = t['signal']['thread_head']
+ for thread in lists.list_for_each_entry(thread_head, task_ptr_type, 'thread_node'):
+ yield thread
- t = utils.container_of(t['thread_group']['next'],
- task_ptr_type, "thread_group")
- if t == g:
- break
-
- t = g = utils.container_of(g['tasks']['next'],
- task_ptr_type, "tasks")
+ t = utils.container_of(t['tasks']['next'],
+ task_ptr_type, "tasks")
if t == init_task:
return
@@ -86,21 +82,12 @@ LxPs()
thread_info_type = utils.CachedType("struct thread_info")
-ia64_task_size = None
-
def get_thread_info(task):
thread_info_ptr_type = thread_info_type.get_type().pointer()
- if utils.is_target_arch("ia64"):
- global ia64_task_size
- if ia64_task_size is None:
- ia64_task_size = gdb.parse_and_eval("sizeof(struct task_struct)")
- thread_info_addr = task.address + ia64_task_size
- thread_info = thread_info_addr.cast(thread_info_ptr_type)
- else:
- if task.type.fields()[0].type == thread_info_type.get_type():
- return task['thread_info']
- thread_info = task['stack'].cast(thread_info_ptr_type)
+ if task.type.fields()[0].type == thread_info_type.get_type():
+ return task['thread_info']
+ thread_info = task['stack'].cast(thread_info_ptr_type)
return thread_info.dereference()
diff --git a/scripts/gdb/linux/vmalloc.py b/scripts/gdb/linux/vmalloc.py
index 48e4a4fae7bb..803f17371052 100644
--- a/scripts/gdb/linux/vmalloc.py
+++ b/scripts/gdb/linux/vmalloc.py
@@ -10,8 +10,9 @@ import gdb
import re
from linux import lists, utils, stackdepot, constants, mm
-vmap_area_type = utils.CachedType('struct vmap_area')
-vmap_area_ptr_type = vmap_area_type.get_type().pointer()
+if constants.LX_CONFIG_MMU:
+ vmap_area_type = utils.CachedType('struct vmap_area')
+ vmap_area_ptr_type = vmap_area_type.get_type().pointer()
def is_vmalloc_addr(x):
pg_ops = mm.page_ops().ops
@@ -25,32 +26,37 @@ class LxVmallocInfo(gdb.Command):
super(LxVmallocInfo, self).__init__("lx-vmallocinfo", gdb.COMMAND_DATA)
def invoke(self, arg, from_tty):
- vmap_area_list = gdb.parse_and_eval('vmap_area_list')
- for vmap_area in lists.list_for_each_entry(vmap_area_list, vmap_area_ptr_type, "list"):
- if not vmap_area['vm']:
- gdb.write("0x%x-0x%x %10d vm_map_ram\n" % (vmap_area['va_start'], vmap_area['va_end'],
- vmap_area['va_end'] - vmap_area['va_start']))
- continue
- v = vmap_area['vm']
- gdb.write("0x%x-0x%x %10d" % (v['addr'], v['addr'] + v['size'], v['size']))
- if v['caller']:
- gdb.write(" %s" % str(v['caller']).split(' ')[-1])
- if v['nr_pages']:
- gdb.write(" pages=%d" % v['nr_pages'])
- if v['phys_addr']:
- gdb.write(" phys=0x%x" % v['phys_addr'])
- if v['flags'] & constants.LX_VM_IOREMAP:
- gdb.write(" ioremap")
- if v['flags'] & constants.LX_VM_ALLOC:
- gdb.write(" vmalloc")
- if v['flags'] & constants.LX_VM_MAP:
- gdb.write(" vmap")
- if v['flags'] & constants.LX_VM_USERMAP:
- gdb.write(" user")
- if v['flags'] & constants.LX_VM_DMA_COHERENT:
- gdb.write(" dma-coherent")
- if is_vmalloc_addr(v['pages']):
- gdb.write(" vpages")
- gdb.write("\n")
+ if not constants.LX_CONFIG_MMU:
+ raise gdb.GdbError("Requires MMU support")
+
+ nr_vmap_nodes = gdb.parse_and_eval('nr_vmap_nodes')
+ for i in range(0, nr_vmap_nodes):
+ vn = gdb.parse_and_eval('&vmap_nodes[%d]' % i)
+ for vmap_area in lists.list_for_each_entry(vn['busy']['head'], vmap_area_ptr_type, "list"):
+ if not vmap_area['vm']:
+ gdb.write("0x%x-0x%x %10d vm_map_ram\n" % (vmap_area['va_start'], vmap_area['va_end'],
+ vmap_area['va_end'] - vmap_area['va_start']))
+ continue
+ v = vmap_area['vm']
+ gdb.write("0x%x-0x%x %10d" % (v['addr'], v['addr'] + v['size'], v['size']))
+ if v['caller']:
+ gdb.write(" %s" % str(v['caller']).split(' ')[-1])
+ if v['nr_pages']:
+ gdb.write(" pages=%d" % v['nr_pages'])
+ if v['phys_addr']:
+ gdb.write(" phys=0x%x" % v['phys_addr'])
+ if v['flags'] & constants.LX_VM_IOREMAP:
+ gdb.write(" ioremap")
+ if v['flags'] & constants.LX_VM_ALLOC:
+ gdb.write(" vmalloc")
+ if v['flags'] & constants.LX_VM_MAP:
+ gdb.write(" vmap")
+ if v['flags'] & constants.LX_VM_USERMAP:
+ gdb.write(" user")
+ if v['flags'] & constants.LX_VM_DMA_COHERENT:
+ gdb.write(" dma-coherent")
+ if is_vmalloc_addr(v['pages']):
+ gdb.write(" vpages")
+ gdb.write("\n")
LxVmallocInfo()
diff --git a/scripts/generate_rust_target.rs b/scripts/generate_rust_target.rs
index 3c6cbe2b278d..54919cf48621 100644
--- a/scripts/generate_rust_target.rs
+++ b/scripts/generate_rust_target.rs
@@ -148,19 +148,28 @@ fn main() {
let mut ts = TargetSpec::new();
// `llvm-target`s are taken from `scripts/Makefile.clang`.
- if cfg.has("X86_64") {
+ if cfg.has("ARM64") {
+ panic!("arm64 uses the builtin rustc aarch64-unknown-none target");
+ } else if cfg.has("X86_64") {
ts.push("arch", "x86_64");
ts.push(
"data-layout",
"e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128",
);
let mut features = "-3dnow,-3dnowa,-mmx,+soft-float".to_string();
- if cfg.has("RETPOLINE") {
+ if cfg.has("MITIGATION_RETPOLINE") {
features += ",+retpoline-external-thunk";
}
ts.push("features", features);
ts.push("llvm-target", "x86_64-linux-gnu");
ts.push("target-pointer-width", "64");
+ } else if cfg.has("LOONGARCH") {
+ ts.push("arch", "loongarch64");
+ ts.push("data-layout", "e-m:e-p:64:64-i64:64-i128:128-n64-S128");
+ ts.push("features", "-f,-d");
+ ts.push("llvm-target", "loongarch64-linux-gnusf");
+ ts.push("llvm-abiname", "lp64s");
+ ts.push("target-pointer-width", "64");
} else {
panic!("Unsupported architecture");
}
diff --git a/scripts/genksyms/genksyms.c b/scripts/genksyms/genksyms.c
index f5dfdb9d80e9..f3901c55df23 100644
--- a/scripts/genksyms/genksyms.c
+++ b/scripts/genksyms/genksyms.c
@@ -16,9 +16,7 @@
#include <unistd.h>
#include <assert.h>
#include <stdarg.h>
-#ifdef __GNU_LIBRARY__
#include <getopt.h>
-#endif /* __GNU_LIBRARY__ */
#include "genksyms.h"
/*----------------------------------------------------------------------*/
@@ -718,8 +716,6 @@ void error_with_pos(const char *fmt, ...)
static void genksyms_usage(void)
{
fputs("Usage:\n" "genksyms [-adDTwqhVR] > /path/to/.tmp_obj.ver\n" "\n"
-#ifdef __GNU_LIBRARY__
- " -s, --symbol-prefix Select symbol prefix\n"
" -d, --debug Increment the debug level (repeatable)\n"
" -D, --dump Dump expanded symbol defs (for debugging only)\n"
" -r, --reference file Read reference symbols from a file\n"
@@ -729,18 +725,6 @@ static void genksyms_usage(void)
" -q, --quiet Disable warnings (default)\n"
" -h, --help Print this message\n"
" -V, --version Print the release version\n"
-#else /* __GNU_LIBRARY__ */
- " -s Select symbol prefix\n"
- " -d Increment the debug level (repeatable)\n"
- " -D Dump expanded symbol defs (for debugging only)\n"
- " -r file Read reference symbols from a file\n"
- " -T file Dump expanded types into file\n"
- " -p Preserve reference modversions or fail\n"
- " -w Enable warnings\n"
- " -q Disable warnings (default)\n"
- " -h Print this message\n"
- " -V Print the release version\n"
-#endif /* __GNU_LIBRARY__ */
, stderr);
}
@@ -749,7 +733,6 @@ int main(int argc, char **argv)
FILE *dumpfile = NULL, *ref_file = NULL;
int o;
-#ifdef __GNU_LIBRARY__
struct option long_opts[] = {
{"debug", 0, 0, 'd'},
{"warnings", 0, 0, 'w'},
@@ -763,11 +746,8 @@ int main(int argc, char **argv)
{0, 0, 0, 0}
};
- while ((o = getopt_long(argc, argv, "s:dwqVDr:T:ph",
+ while ((o = getopt_long(argc, argv, "dwqVDr:T:ph",
&long_opts[0], NULL)) != EOF)
-#else /* __GNU_LIBRARY__ */
- while ((o = getopt(argc, argv, "s:dwqVDr:T:ph")) != EOF)
-#endif /* __GNU_LIBRARY__ */
switch (o) {
case 'd':
flag_debug++;
diff --git a/scripts/get_abi.pl b/scripts/get_abi.pl
index 0ffd5531242a..de1c0354b50c 100755
--- a/scripts/get_abi.pl
+++ b/scripts/get_abi.pl
@@ -93,12 +93,13 @@ sub parse_abi {
return if ($mode & S_IFDIR);
return if ($file =~ m,/README,);
return if ($file =~ m,/\.,);
+ return if ($file =~ m,\.(rej|org|orig|bak)$,);
my $name = $file;
$name =~ s,.*/,,;
my $fn = $file;
- $fn =~ s,Documentation/ABI/,,;
+ $fn =~ s,.*Documentation/ABI/,,;
my $nametag = "File $fn";
$data{$nametag}->{what} = "File $name";
diff --git a/scripts/get_maintainer.pl b/scripts/get_maintainer.pl
index ab123b498fd9..ee1aed7e090c 100755
--- a/scripts/get_maintainer.pl
+++ b/scripts/get_maintainer.pl
@@ -20,6 +20,7 @@ use Getopt::Long qw(:config no_auto_abbrev);
use Cwd;
use File::Find;
use File::Spec::Functions;
+use open qw(:std :encoding(UTF-8));
my $cur_path = fastgetcwd() . '/';
my $lk_path = "./";
@@ -57,6 +58,7 @@ my $subsystem = 0;
my $status = 0;
my $letters = "";
my $keywords = 1;
+my $keywords_in_file = 0;
my $sections = 0;
my $email_file_emails = 0;
my $from_filename = 0;
@@ -272,6 +274,7 @@ if (!GetOptions(
'letters=s' => \$letters,
'pattern-depth=i' => \$pattern_depth,
'k|keywords!' => \$keywords,
+ 'kf|keywords-in-file!' => \$keywords_in_file,
'sections!' => \$sections,
'fe|file-emails!' => \$email_file_emails,
'f|file' => \$from_filename,
@@ -318,6 +321,7 @@ if ($sections || $letters ne "") {
$subsystem = 0;
$web = 0;
$keywords = 0;
+ $keywords_in_file = 0;
$interactive = 0;
} else {
my $selections = $email + $scm + $status + $subsystem + $web;
@@ -442,7 +446,7 @@ sub maintainers_in_file {
my $text = do { local($/) ; <$f> };
close($f);
- my @poss_addr = $text =~ m$[A-Za-zÀ-ÿ\"\' \,\.\+-]*\s*[\,]*\s*[\(\<\{]{0,1}[A-Za-z0-9_\.\+-]+\@[A-Za-z0-9\.-]+\.[A-Za-z0-9]+[\)\>\}]{0,1}$g;
+ my @poss_addr = $text =~ m$[\p{L}\"\' \,\.\+-]*\s*[\,]*\s*[\(\<\{]{0,1}[A-Za-z0-9_\.\+-]+\@[A-Za-z0-9\.-]+\.[A-Za-z0-9]+[\)\>\}]{0,1}$g;
push(@file_emails, clean_file_emails(@poss_addr));
}
}
@@ -548,16 +552,14 @@ foreach my $file (@ARGV) {
$file =~ s/^\Q${cur_path}\E//; #strip any absolute path
$file =~ s/^\Q${lk_path}\E//; #or the path to the lk tree
push(@files, $file);
- if ($file ne "MAINTAINERS" && -f $file && $keywords) {
+ if ($file ne "MAINTAINERS" && -f $file && $keywords && $keywords_in_file) {
open(my $f, '<', $file)
or die "$P: Can't open $file: $!\n";
my $text = do { local($/) ; <$f> };
close($f);
- if ($keywords) {
- foreach my $line (keys %keyword_hash) {
- if ($text =~ m/$keyword_hash{$line}/x) {
- push(@keyword_tvi, $line);
- }
+ foreach my $line (keys %keyword_hash) {
+ if ($text =~ m/$keyword_hash{$line}/x) {
+ push(@keyword_tvi, $line);
}
}
}
@@ -919,7 +921,7 @@ sub get_maintainers {
}
foreach my $line (sort {$hash{$b} <=> $hash{$a}} keys %hash) {
- add_categories($line);
+ add_categories($line, "");
if ($sections) {
my $i;
my $start = find_starting_index($line);
@@ -947,7 +949,7 @@ sub get_maintainers {
if ($keywords) {
@keyword_tvi = sort_and_uniq(@keyword_tvi);
foreach my $line (@keyword_tvi) {
- add_categories($line);
+ add_categories($line, ":Keyword:$keyword_hash{$line}");
}
}
@@ -1076,6 +1078,7 @@ Output type options:
Other options:
--pattern-depth => Number of pattern directory traversals (default: 0 (all))
--keywords => scan patch for keywords (default: $keywords)
+ --keywords-in-file => scan file for keywords (default: $keywords_in_file)
--sections => print all of the subsystem sections with pattern matches
--letters => print all matching 'letter' types from all matching sections
--mailmap => use .mailmap file (default: $email_use_mailmap)
@@ -1086,7 +1089,7 @@ Other options:
Default options:
[--email --tree --nogit --git-fallback --m --r --n --l --multiline
- --pattern-depth=0 --remove-duplicates --rolestats]
+ --pattern-depth=0 --remove-duplicates --rolestats --keywords]
Notes:
Using "-f directory" may give unexpected results:
@@ -1150,6 +1153,17 @@ sub top_of_kernel_tree {
return 0;
}
+sub escape_name {
+ my ($name) = @_;
+
+ if ($name =~ /[^\w \-]/ai) { ##has "must quote" chars
+ $name =~ s/(?<!\\)"/\\"/g; ##escape quotes
+ $name = "\"$name\"";
+ }
+
+ return $name;
+}
+
sub parse_email {
my ($formatted_email) = @_;
@@ -1167,13 +1181,9 @@ sub parse_email {
$name =~ s/^\s+|\s+$//g;
$name =~ s/^\"|\"$//g;
+ $name = escape_name($name);
$address =~ s/^\s+|\s+$//g;
- if ($name =~ /[^\w \-]/i) { ##has "must quote" chars
- $name =~ s/(?<!\\)"/\\"/g; ##escape quotes
- $name = "\"$name\"";
- }
-
return ($name, $address);
}
@@ -1184,13 +1194,9 @@ sub format_email {
$name =~ s/^\s+|\s+$//g;
$name =~ s/^\"|\"$//g;
+ $name = escape_name($name);
$address =~ s/^\s+|\s+$//g;
- if ($name =~ /[^\w \-]/i) { ##has "must quote" chars
- $name =~ s/(?<!\\)"/\\"/g; ##escape quotes
- $name = "\"$name\"";
- }
-
if ($usename) {
if ("$name" eq "") {
$formatted_email = "$address";
@@ -1312,7 +1318,7 @@ sub get_list_role {
}
sub add_categories {
- my ($index) = @_;
+ my ($index, $suffix) = @_;
my $i;
my $start = find_starting_index($index);
@@ -1342,7 +1348,7 @@ sub add_categories {
if (!$hash_list_to{lc($list_address)}) {
$hash_list_to{lc($list_address)} = 1;
push(@list_to, [$list_address,
- "subscriber list${list_role}"]);
+ "subscriber list${list_role}" . $suffix]);
}
}
} else {
@@ -1352,12 +1358,12 @@ sub add_categories {
if ($email_moderated_list) {
$hash_list_to{lc($list_address)} = 1;
push(@list_to, [$list_address,
- "moderated list${list_role}"]);
+ "moderated list${list_role}" . $suffix]);
}
} else {
$hash_list_to{lc($list_address)} = 1;
push(@list_to, [$list_address,
- "open list${list_role}"]);
+ "open list${list_role}" . $suffix]);
}
}
}
@@ -1365,19 +1371,19 @@ sub add_categories {
} elsif ($ptype eq "M") {
if ($email_maintainer) {
my $role = get_maintainer_role($i);
- push_email_addresses($pvalue, $role);
+ push_email_addresses($pvalue, $role . $suffix);
}
} elsif ($ptype eq "R") {
if ($email_reviewer) {
my $subsystem = get_subsystem_name($i);
- push_email_addresses($pvalue, "reviewer:$subsystem");
+ push_email_addresses($pvalue, "reviewer:$subsystem" . $suffix);
}
} elsif ($ptype eq "T") {
- push(@scm, $pvalue);
+ push(@scm, $pvalue . $suffix);
} elsif ($ptype eq "W") {
- push(@web, $pvalue);
+ push(@web, $pvalue . $suffix);
} elsif ($ptype eq "S") {
- push(@status, $pvalue);
+ push(@status, $pvalue . $suffix);
}
}
}
@@ -2456,17 +2462,23 @@ sub clean_file_emails {
foreach my $email (@file_emails) {
$email =~ s/[\(\<\{]{0,1}([A-Za-z0-9_\.\+-]+\@[A-Za-z0-9\.-]+)[\)\>\}]{0,1}/\<$1\>/g;
my ($name, $address) = parse_email($email);
- if ($name eq '"[,\.]"') {
- $name = "";
- }
- my @nw = split(/[^A-Za-zÀ-ÿ\'\,\.\+-]/, $name);
+ # Strip quotes for easier processing, format_email will add them back
+ $name =~ s/^"(.*)"$/$1/;
+
+ # Split into name-like parts and remove stray punctuation particles
+ my @nw = split(/[^\p{L}\'\,\.\+-]/, $name);
+ @nw = grep(!/^[\'\,\.\+-]$/, @nw);
+
+ # Make a best effort to extract the name, and only the name, by taking
+ # only the last two names, or in the case of obvious initials, the last
+ # three names.
if (@nw > 2) {
my $first = $nw[@nw - 3];
my $middle = $nw[@nw - 2];
my $last = $nw[@nw - 1];
- if (((length($first) == 1 && $first =~ m/[A-Za-z]/) ||
+ if (((length($first) == 1 && $first =~ m/\p{L}/) ||
(length($first) == 2 && substr($first, -1) eq ".")) ||
(length($middle) == 1 ||
(length($middle) == 2 && substr($middle, -1) eq "."))) {
@@ -2474,18 +2486,16 @@ sub clean_file_emails {
} else {
$name = "$middle $last";
}
+ } else {
+ $name = "@nw";
}
if (substr($name, -1) =~ /[,\.]/) {
$name = substr($name, 0, length($name) - 1);
- } elsif (substr($name, -2) =~ /[,\.]"/) {
- $name = substr($name, 0, length($name) - 2) . '"';
}
if (substr($name, 0, 1) =~ /[,\.]/) {
$name = substr($name, 1, length($name) - 1);
- } elsif (substr($name, 0, 2) =~ /"[,\.]/) {
- $name = '"' . substr($name, 2, length($name) - 2);
}
my $fmt_email = format_email($name, $address, $email_usename);
diff --git a/scripts/git.orderFile b/scripts/git.orderFile
new file mode 100644
index 000000000000..5102ba73357f
--- /dev/null
+++ b/scripts/git.orderFile
@@ -0,0 +1,42 @@
+# SPDX-License-Identifier: GPL-2.0
+
+# order file for git, to produce patches which are easier to review
+# by diffing the important stuff like header changes first.
+#
+# one-off usage:
+# git diff -O scripts/git.orderFile ...
+#
+# add to git config:
+# git config diff.orderFile scripts/git.orderFile
+#
+
+MAINTAINERS
+
+# Documentation
+Documentation/*
+*.rst
+
+# git-specific
+.gitignore
+scripts/git.orderFile
+
+# build system
+Kconfig*
+*/Kconfig*
+Kbuild*
+*/Kbuild*
+Makefile*
+*/Makefile*
+*.mak
+*.mk
+scripts/*
+
+# semantic patches
+*.cocci
+
+# headers
+*types.h
+*.h
+
+# code
+*.c
diff --git a/scripts/head-object-list.txt b/scripts/head-object-list.txt
index 26359968744e..890f69005bab 100644
--- a/scripts/head-object-list.txt
+++ b/scripts/head-object-list.txt
@@ -17,7 +17,6 @@ arch/arm/kernel/head-nommu.o
arch/arm/kernel/head.o
arch/csky/kernel/head.o
arch/hexagon/kernel/head.o
-arch/ia64/kernel/head.o
arch/loongarch/kernel/head.o
arch/m68k/68000/head.o
arch/m68k/coldfire/head.o
diff --git a/scripts/headers_install.sh b/scripts/headers_install.sh
index 56d3c338d91d..f7d9b114de8f 100755
--- a/scripts/headers_install.sh
+++ b/scripts/headers_install.sh
@@ -74,8 +74,6 @@ 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/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
diff --git a/scripts/kconfig/Makefile b/scripts/kconfig/Makefile
index 4eee155121a8..ea1bf3b3dbde 100644
--- a/scripts/kconfig/Makefile
+++ b/scripts/kconfig/Makefile
@@ -27,6 +27,14 @@ KCONFIG_DEFCONFIG_LIST += \
endif
KCONFIG_DEFCONFIG_LIST += arch/$(SRCARCH)/configs/$(KBUILD_DEFCONFIG)
+ifneq ($(findstring c, $(KBUILD_EXTRA_WARN)),)
+export KCONFIG_WARN_UNKNOWN_SYMBOLS=1
+endif
+
+ifneq ($(findstring e, $(KBUILD_EXTRA_WARN)),)
+export KCONFIG_WERROR=1
+endif
+
# We need this, in case the user has it in its environment
unexport CONFIG_
@@ -99,7 +107,7 @@ config-fragments = $(call configfiles,$@)
%.config: $(obj)/conf
$(if $(config-fragments),, $(error $@ fragment does not exists on this architecture))
- $(Q)$(CONFIG_SHELL) $(srctree)/scripts/kconfig/merge_config.sh -m .config $(config-fragments)
+ $(Q)$(CONFIG_SHELL) $(srctree)/scripts/kconfig/merge_config.sh -m $(KCONFIG_CONFIG) $(config-fragments)
$(Q)$(MAKE) -f $(srctree)/Makefile olddefconfig
PHONY += tinyconfig
@@ -166,7 +174,7 @@ conf-objs := conf.o $(common-objs)
# nconf: Used for the nconfig target based on ncurses
hostprogs += nconf
-nconf-objs := nconf.o nconf.gui.o $(common-objs)
+nconf-objs := nconf.o nconf.gui.o mnconf-common.o $(common-objs)
HOSTLDLIBS_nconf = $(call read-file, $(obj)/nconf-libs)
HOSTCFLAGS_nconf.o = $(call read-file, $(obj)/nconf-cflags)
@@ -179,7 +187,7 @@ $(obj)/nconf.o $(obj)/nconf.gui.o: | $(obj)/nconf-cflags
hostprogs += mconf
lxdialog := $(addprefix lxdialog/, \
checklist.o inputbox.o menubox.o textbox.o util.o yesno.o)
-mconf-objs := mconf.o $(lxdialog) $(common-objs)
+mconf-objs := mconf.o $(lxdialog) mnconf-common.o $(common-objs)
HOSTLDLIBS_mconf = $(call read-file, $(obj)/mconf-libs)
$(foreach f, mconf.o $(lxdialog), \
diff --git a/scripts/kconfig/array_size.h b/scripts/kconfig/array_size.h
new file mode 100644
index 000000000000..26ba78d867d1
--- /dev/null
+++ b/scripts/kconfig/array_size.h
@@ -0,0 +1,11 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef ARRAY_SIZE_H
+#define ARRAY_SIZE_H
+
+/**
+ * ARRAY_SIZE - get the number of elements in array @arr
+ * @arr: array to be sized
+ */
+#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
+
+#endif /* ARRAY_SIZE_H */
diff --git a/scripts/kconfig/conf.c b/scripts/kconfig/conf.c
index 33d19e419908..965bb40c50e5 100644
--- a/scripts/kconfig/conf.c
+++ b/scripts/kconfig/conf.c
@@ -14,6 +14,7 @@
#include <sys/time.h>
#include <errno.h>
+#include "internal.h"
#include "lkc.h"
static void conf(struct menu *menu);
@@ -171,7 +172,7 @@ enum conf_def_mode {
static bool conf_set_all_new_symbols(enum conf_def_mode mode)
{
struct symbol *sym, *csym;
- int i, cnt;
+ int cnt;
/*
* can't go as the default in switch-case below, otherwise gcc whines
* about -Wmaybe-uninitialized
@@ -226,7 +227,7 @@ static bool conf_set_all_new_symbols(enum conf_def_mode mode)
}
}
- for_all_symbols(i, sym) {
+ for_all_symbols(sym) {
if (sym_has_value(sym) || sym->flags & SYMBOL_VALID)
continue;
switch (sym_get_type(sym)) {
@@ -278,14 +279,14 @@ static bool conf_set_all_new_symbols(enum conf_def_mode mode)
* and the rest to no.
*/
if (mode != def_random) {
- for_all_symbols(i, csym) {
+ for_all_symbols(csym) {
if ((sym_is_choice(csym) && !sym_has_value(csym)) ||
sym_is_choice_value(csym))
csym->flags |= SYMBOL_NEED_SET_CHOICE_VALUES;
}
}
- for_all_symbols(i, csym) {
+ for_all_symbols(csym) {
if (sym_has_value(csym) || !sym_is_choice(csym))
continue;
@@ -304,9 +305,8 @@ static bool conf_set_all_new_symbols(enum conf_def_mode mode)
static void conf_rewrite_tristates(tristate old_val, tristate new_val)
{
struct symbol *sym;
- int i;
- for_all_symbols(i, sym) {
+ for_all_symbols(sym) {
if (sym_get_type(sym) == S_TRISTATE &&
sym->def[S_DEF_USER].tri == old_val)
sym->def[S_DEF_USER].tri = new_val;
@@ -552,11 +552,6 @@ static int conf_choice(struct menu *menu)
continue;
}
sym_set_tristate_value(child->sym, yes);
- for (child = child->list; child; child = child->next) {
- indent += 2;
- conf(child);
- indent -= 2;
- }
return 1;
}
}
@@ -827,6 +822,9 @@ int main(int ac, char **av)
break;
}
+ if (conf_errors())
+ exit(1);
+
if (sync_kconfig) {
name = getenv("KCONFIG_NOSILENTUPDATE");
if (name && *name) {
@@ -890,6 +888,9 @@ int main(int ac, char **av)
break;
}
+ if (sym_dep_errors())
+ exit(1);
+
if (input_mode == savedefconfig) {
if (conf_write_defconfig(defconfig_file)) {
fprintf(stderr, "n*** Error while saving defconfig to: %s\n\n",
diff --git a/scripts/kconfig/confdata.c b/scripts/kconfig/confdata.c
index 4a6811d77d18..0e35c4819cf1 100644
--- a/scripts/kconfig/confdata.c
+++ b/scripts/kconfig/confdata.c
@@ -18,8 +18,11 @@
#include <time.h>
#include <unistd.h>
+#include "internal.h"
#include "lkc.h"
+struct gstr autoconf_cmd;
+
/* return true if 'path' exists, false otherwise */
static bool is_present(const char *path)
{
@@ -155,6 +158,13 @@ static void conf_message(const char *fmt, ...)
static const char *conf_filename;
static int conf_lineno, conf_warnings;
+bool conf_errors(void)
+{
+ if (conf_warnings)
+ return getenv("KCONFIG_WERROR");
+ return false;
+}
+
static void conf_warning(const char *fmt, ...)
{
va_list ap;
@@ -286,59 +296,24 @@ static int conf_set_sym_val(struct symbol *sym, int def, int def_flags, char *p)
return 0;
}
-#define LINE_GROWTH 16
-static int add_byte(int c, char **lineptr, size_t slen, size_t *n)
+/* like getline(), but the newline character is stripped away */
+static ssize_t getline_stripped(char **lineptr, size_t *n, FILE *stream)
{
- char *nline;
- size_t new_size = slen + 1;
- if (new_size > *n) {
- new_size += LINE_GROWTH - 1;
- new_size *= 2;
- nline = xrealloc(*lineptr, new_size);
- if (!nline)
- return -1;
-
- *lineptr = nline;
- *n = new_size;
- }
+ ssize_t len;
- (*lineptr)[slen] = c;
+ len = getline(lineptr, n, stream);
- return 0;
-}
-
-static ssize_t compat_getline(char **lineptr, size_t *n, FILE *stream)
-{
- char *line = *lineptr;
- size_t slen = 0;
+ if (len > 0 && (*lineptr)[len - 1] == '\n') {
+ len--;
+ (*lineptr)[len] = '\0';
- for (;;) {
- int c = getc(stream);
-
- switch (c) {
- case '\n':
- if (add_byte(c, &line, slen, n) < 0)
- goto e_out;
- slen++;
- /* fall through */
- case EOF:
- if (add_byte('\0', &line, slen, n) < 0)
- goto e_out;
- *lineptr = line;
- if (slen == 0)
- return -1;
- return slen;
- default:
- if (add_byte(c, &line, slen, n) < 0)
- goto e_out;
- slen++;
+ if (len > 0 && (*lineptr)[len - 1] == '\r') {
+ len--;
+ (*lineptr)[len] = '\0';
}
}
-e_out:
- line[slen-1] = '\0';
- *lineptr = line;
- return -1;
+ return len;
}
int conf_read_simple(const char *name, int def)
@@ -346,14 +321,12 @@ int conf_read_simple(const char *name, int def)
FILE *in = NULL;
char *line = NULL;
size_t line_asize = 0;
- char *p, *p2;
+ char *p, *val;
struct symbol *sym;
- int i, def_flags;
- const char *warn_unknown;
- const char *werror;
+ int def_flags;
+ const char *warn_unknown, *sym_name;
warn_unknown = getenv("KCONFIG_WARN_UNKNOWN_SYMBOLS");
- werror = getenv("KCONFIG_WERROR");
if (name) {
in = zconf_fopen(name);
} else {
@@ -408,7 +381,7 @@ load:
conf_warnings = 0;
def_flags = SYMBOL_DEF << def;
- for_all_symbols(i, sym) {
+ for_all_symbols(sym) {
sym->flags |= SYMBOL_CHANGED;
sym->flags &= ~(def_flags|SYMBOL_VALID);
if (sym_is_choice(sym))
@@ -417,8 +390,7 @@ load:
case S_INT:
case S_HEX:
case S_STRING:
- if (sym->def[def].val)
- free(sym->def[def].val);
+ free(sym->def[def].val);
/* fall through */
default:
sym->def[def].val = NULL;
@@ -426,90 +398,68 @@ load:
}
}
- while (compat_getline(&line, &line_asize, in) != -1) {
+ while (getline_stripped(&line, &line_asize, in) != -1) {
conf_lineno++;
- sym = NULL;
+
+ if (!line[0]) /* blank line */
+ continue;
+
if (line[0] == '#') {
- if (memcmp(line + 2, CONFIG_, strlen(CONFIG_)))
+ if (line[1] != ' ')
+ continue;
+ p = line + 2;
+ if (memcmp(p, CONFIG_, strlen(CONFIG_)))
continue;
- p = strchr(line + 2 + strlen(CONFIG_), ' ');
+ sym_name = p + strlen(CONFIG_);
+ p = strchr(sym_name, ' ');
if (!p)
continue;
*p++ = 0;
- if (strncmp(p, "is not set", 10))
+ if (strcmp(p, "is not set"))
continue;
- if (def == S_DEF_USER) {
- sym = sym_find(line + 2 + strlen(CONFIG_));
- if (!sym) {
- if (warn_unknown)
- conf_warning("unknown symbol: %s",
- line + 2 + strlen(CONFIG_));
-
- conf_set_changed(true);
- continue;
- }
- } else {
- sym = sym_lookup(line + 2 + strlen(CONFIG_), 0);
- if (sym->type == S_UNKNOWN)
- sym->type = S_BOOLEAN;
- }
- if (sym->flags & def_flags) {
- conf_warning("override: reassigning to symbol %s", sym->name);
- }
- switch (sym->type) {
- case S_BOOLEAN:
- case S_TRISTATE:
- sym->def[def].tri = no;
- sym->flags |= def_flags;
- break;
- default:
- ;
- }
- } else if (memcmp(line, CONFIG_, strlen(CONFIG_)) == 0) {
- p = strchr(line + strlen(CONFIG_), '=');
- if (!p)
+
+ val = "n";
+ } else {
+ if (memcmp(line, CONFIG_, strlen(CONFIG_))) {
+ conf_warning("unexpected data: %s", line);
continue;
- *p++ = 0;
- p2 = strchr(p, '\n');
- if (p2) {
- *p2-- = 0;
- if (*p2 == '\r')
- *p2 = 0;
}
- 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 must be touched.
- */
- conf_touch_dep(line + strlen(CONFIG_));
- } else {
- if (warn_unknown)
- conf_warning("unknown symbol: %s",
- line + strlen(CONFIG_));
-
- conf_set_changed(true);
- }
+ sym_name = line + strlen(CONFIG_);
+ p = strchr(sym_name, '=');
+ if (!p) {
+ conf_warning("unexpected data: %s", line);
continue;
}
+ *p = 0;
+ val = p + 1;
+ }
- if (sym->flags & def_flags) {
- conf_warning("override: reassigning to symbol %s", sym->name);
- }
- if (conf_set_sym_val(sym, def, def_flags, p))
- continue;
- } else {
- if (line[0] != '\r' && line[0] != '\n')
- conf_warning("unexpected data: %.*s",
- (int)strcspn(line, "\r\n"), line);
+ sym = sym_find(sym_name);
+ 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
+ * must be touched.
+ */
+ conf_touch_dep(sym_name);
+ } else {
+ if (warn_unknown)
+ conf_warning("unknown symbol: %s", sym_name);
+ conf_set_changed(true);
+ }
continue;
}
+ if (sym->flags & def_flags)
+ conf_warning("override: reassigning to symbol %s", sym->name);
+
+ if (conf_set_sym_val(sym, def, def_flags, val))
+ continue;
+
if (sym && sym_is_choice_value(sym)) {
struct symbol *cs = prop_get_symbol(sym_get_choice_prop(sym));
switch (sym->def[def].tri) {
@@ -533,9 +483,6 @@ load:
free(line);
fclose(in);
- if (conf_warnings && werror)
- exit(1);
-
return 0;
}
@@ -543,7 +490,6 @@ int conf_read(const char *name)
{
struct symbol *sym;
int conf_unsaved = 0;
- int i;
conf_set_changed(false);
@@ -554,7 +500,7 @@ int conf_read(const char *name)
sym_calc_value(modules_sym);
- for_all_symbols(i, sym) {
+ for_all_symbols(sym) {
sym_calc_value(sym);
if (sym_is_choice(sym) || (sym->flags & SYMBOL_NO_WRITE))
continue;
@@ -578,7 +524,7 @@ int conf_read(const char *name)
/* maybe print value in verbose mode... */
}
- for_all_symbols(i, sym) {
+ for_all_symbols(sym) {
if (sym_has_value(sym) && !sym_is_choice_value(sym)) {
/* Reset values of generates values, so they'll appear
* as new, if they should become visible, but that
@@ -594,7 +540,7 @@ int conf_read(const char *name)
/* Reset a string value if it's out of range */
if (sym_string_within_range(sym, sym->def[S_DEF_USER].val))
break;
- sym->flags &= ~(SYMBOL_VALID|SYMBOL_DEF_USER);
+ sym->flags &= ~SYMBOL_VALID;
conf_unsaved++;
break;
default:
@@ -853,10 +799,7 @@ int conf_write_defconfig(const char *filename)
while (menu != NULL)
{
sym = menu->sym;
- if (sym == NULL) {
- if (!menu_is_visible(menu))
- goto next_menu;
- } else if (!sym_is_choice(sym)) {
+ if (sym && !sym_is_choice(sym)) {
sym_calc_value(sym);
if (!(sym->flags & SYMBOL_WRITE))
goto next_menu;
@@ -916,7 +859,6 @@ int conf_write(const char *name)
const char *str;
char tmpname[PATH_MAX + 1], oldname[PATH_MAX + 1];
char *env;
- int i;
bool need_newline = false;
if (!name)
@@ -1000,7 +942,7 @@ end_check:
}
fclose(out);
- for_all_symbols(i, sym)
+ for_all_symbols(sym)
sym->flags &= ~SYMBOL_WRITTEN;
if (*tmpname) {
@@ -1028,7 +970,6 @@ end_check:
static int conf_write_autoconf_cmd(const char *autoconf_name)
{
char name[PATH_MAX], tmp[PATH_MAX];
- struct file *file;
FILE *out;
int ret;
@@ -1049,15 +990,9 @@ static int conf_write_autoconf_cmd(const char *autoconf_name)
return -1;
}
- fprintf(out, "deps_config := \\\n");
- for (file = file_list; file; file = file->next)
- fprintf(out, "\t%s \\\n", file->name);
-
- fprintf(out, "\n%s: $(deps_config)\n\n", autoconf_name);
+ fprintf(out, "autoconfig := %s\n", autoconf_name);
- env_write_dep(out, autoconf_name);
-
- fprintf(out, "\n$(deps_config): ;\n");
+ fputs(str_get(&autoconf_cmd), out);
fflush(out);
ret = ferror(out); /* error check for all fprintf() calls */
@@ -1077,7 +1012,7 @@ static int conf_touch_deps(void)
{
const char *name, *tmp;
struct symbol *sym;
- int res, i;
+ int res;
name = conf_get_autoconfig_name();
tmp = strrchr(name, '/');
@@ -1091,7 +1026,7 @@ static int conf_touch_deps(void)
conf_read_simple(name, S_DEF_AUTO);
sym_calc_value(modules_sym);
- for_all_symbols(i, sym) {
+ for_all_symbols(sym) {
sym_calc_value(sym);
if ((sym->flags & SYMBOL_NO_WRITE) || !sym->name)
continue;
@@ -1157,7 +1092,7 @@ static int __conf_write_autoconf(const char *filename,
char tmp[PATH_MAX];
FILE *file;
struct symbol *sym;
- int ret, i;
+ int ret;
if (make_parent_dir(filename))
return -1;
@@ -1174,7 +1109,7 @@ static int __conf_write_autoconf(const char *filename,
conf_write_heading(file, comment_style);
- for_all_symbols(i, sym)
+ for_all_symbols(sym)
if ((sym->flags & SYMBOL_WRITE) && sym->name)
print_symbol(file, sym);
@@ -1197,7 +1132,7 @@ int conf_write_autoconf(int overwrite)
{
struct symbol *sym;
const char *autoconf_name = conf_get_autoconfig_name();
- int ret, i;
+ int ret;
if (!overwrite && is_present(autoconf_name))
return 0;
@@ -1209,7 +1144,7 @@ int conf_write_autoconf(int overwrite)
if (conf_touch_deps())
return 1;
- for_all_symbols(i, sym)
+ for_all_symbols(sym)
sym_calc_value(sym);
ret = __conf_write_autoconf(conf_get_autoheader_name(),
diff --git a/scripts/kconfig/expr.c b/scripts/kconfig/expr.c
index 81ebf8108ca7..a290de36307b 100644
--- a/scripts/kconfig/expr.c
+++ b/scripts/kconfig/expr.c
@@ -1131,7 +1131,6 @@ static int expr_compare_type(enum expr_type t1, enum expr_type t2)
default:
return -1;
}
- printf("[%dgt%d?]", t1, t2);
return 0;
}
diff --git a/scripts/kconfig/expr.h b/scripts/kconfig/expr.h
index 4a9a23b1b7e1..0158f5eac454 100644
--- a/scripts/kconfig/expr.h
+++ b/scripts/kconfig/expr.h
@@ -12,17 +12,12 @@ extern "C" {
#include <assert.h>
#include <stdio.h>
-#include "list.h"
+#include "list_types.h"
#ifndef __cplusplus
#include <stdbool.h>
#endif
-struct file {
- struct file *next;
- struct file *parent;
- const char *name;
- int lineno;
-};
+#include "list_types.h"
typedef enum tristate {
no, mod, yes
@@ -81,8 +76,8 @@ enum {
* SYMBOL_CHOICE bit set in 'flags'.
*/
struct symbol {
- /* The next symbol in the same bucket in the symbol hash table */
- struct symbol *next;
+ /* link node for the hash table */
+ struct hlist_node node;
/* The name of the symbol, e.g. "FOO" for 'config FOO' */
char *name;
@@ -113,6 +108,9 @@ struct symbol {
*/
tristate visible;
+ /* config entries associated with this symbol */
+ struct list_head menus;
+
/* SYMBOL_* flags */
int flags;
@@ -131,8 +129,6 @@ struct symbol {
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)
-
#define SYMBOL_CONST 0x0001 /* symbol is const */
#define SYMBOL_CHECK 0x0008 /* used during dependency checking */
#define SYMBOL_CHOICE 0x0010 /* start of a choice block (null name) */
@@ -157,7 +153,6 @@ struct symbol {
#define SYMBOL_NEED_SET_CHOICE_VALUES 0x100000
#define SYMBOL_MAXLENGTH 256
-#define SYMBOL_HASHSIZE 9973
/* A property represent the config options that can be associated
* with a config "symbol".
@@ -195,7 +190,7 @@ struct property {
struct menu *menu; /* the menu the property are associated with
* valid for: P_SELECT, P_RANGE, P_CHOICE,
* P_PROMPT, P_DEFAULT, P_MENU, P_COMMENT */
- struct file *file; /* what file was this property defined */
+ const char *filename; /* what file was this property defined */
int lineno; /* what lineno was this property defined */
};
@@ -230,6 +225,8 @@ struct menu {
*/
struct symbol *sym;
+ struct list_head link; /* link to symbol::menus */
+
/*
* The prompt associated with the node. This holds the prompt for a
* symbol as well as the text for a menu or comment, along with the
@@ -256,7 +253,7 @@ struct menu {
char *help;
/* The location where the menu node appears in the Kconfig files */
- struct file *file;
+ const char *filename;
int lineno;
/* For use by front ends that need to store auxiliary data */
@@ -277,10 +274,6 @@ struct jump_key {
struct menu *target;
};
-extern struct file *file_list;
-extern struct file *current_file;
-struct file *lookup_file(const char *name);
-
extern struct symbol symbol_yes, symbol_no, symbol_mod;
extern struct symbol *modules_sym;
extern int cdebug;
diff --git a/scripts/kconfig/hashtable.h b/scripts/kconfig/hashtable.h
new file mode 100644
index 000000000000..a0a2c8f5f639
--- /dev/null
+++ b/scripts/kconfig/hashtable.h
@@ -0,0 +1,48 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+#ifndef HASHTABLE_H
+#define HASHTABLE_H
+
+#include "array_size.h"
+#include "list.h"
+
+#define HASH_SIZE(name) (ARRAY_SIZE(name))
+
+#define HASHTABLE_DECLARE(name, size) struct hlist_head name[size]
+
+#define HASHTABLE_DEFINE(name, size) \
+ HASHTABLE_DECLARE(name, size) = \
+ { [0 ... ((size) - 1)] = HLIST_HEAD_INIT }
+
+#define hash_head(table, key) (&(table)[(key) % HASH_SIZE(table)])
+
+/**
+ * hash_add - add an object to a hashtable
+ * @table: hashtable to add to
+ * @node: the &struct hlist_node of the object to be added
+ * @key: the key of the object to be added
+ */
+#define hash_add(table, node, key) \
+ hlist_add_head(node, hash_head(table, key))
+
+/**
+ * hash_for_each - iterate over a hashtable
+ * @table: hashtable to iterate
+ * @obj: the type * to use as a loop cursor for each entry
+ * @member: the name of the hlist_node within the struct
+ */
+#define hash_for_each(table, obj, member) \
+ for (int _bkt = 0; _bkt < HASH_SIZE(table); _bkt++) \
+ hlist_for_each_entry(obj, &table[_bkt], member)
+
+/**
+ * hash_for_each_possible - iterate over all possible objects hashing to the
+ * same bucket
+ * @table: hashtable to iterate
+ * @obj: the type * to use as a loop cursor for each entry
+ * @member: the name of the hlist_node within the struct
+ * @key: the key of the objects to iterate over
+ */
+#define hash_for_each_possible(table, obj, member, key) \
+ hlist_for_each_entry(obj, hash_head(table, key), member)
+
+#endif /* HASHTABLE_H */
diff --git a/scripts/kconfig/internal.h b/scripts/kconfig/internal.h
index 2f7298c21b64..6c721c4cfd72 100644
--- a/scripts/kconfig/internal.h
+++ b/scripts/kconfig/internal.h
@@ -2,8 +2,20 @@
#ifndef INTERNAL_H
#define INTERNAL_H
+#include "hashtable.h"
+
+#define SYMBOL_HASHSIZE (1U << 14)
+
+extern HASHTABLE_DECLARE(sym_hashtable, SYMBOL_HASHSIZE);
+
+#define for_all_symbols(sym) \
+ hash_for_each(sym_hashtable, sym, node)
+
struct menu;
extern struct menu *current_menu, *current_entry;
+extern const char *cur_filename;
+extern int cur_lineno;
+
#endif /* INTERNAL_H */
diff --git a/scripts/kconfig/lexer.l b/scripts/kconfig/lexer.l
index cc386e443683..89544c3a1a29 100644
--- a/scripts/kconfig/lexer.l
+++ b/scripts/kconfig/lexer.l
@@ -14,16 +14,22 @@
#include <string.h>
#include "lkc.h"
+#include "preprocess.h"
+
#include "parser.tab.h"
#define YY_DECL static int yylex1(void)
#define START_STRSIZE 16
-static struct {
- struct file *file;
- int lineno;
-} current_pos;
+/* The Kconfig file currently being parsed. */
+const char *cur_filename;
+
+/*
+ * The line number of the current statement. This does not match yylineno.
+ * yylineno is used by the lexer, while cur_lineno is used by the parser.
+ */
+int cur_lineno;
static int prev_prev_token = T_EOL;
static int prev_token = T_EOL;
@@ -33,6 +39,9 @@ static int text_size, text_asize;
struct buffer {
struct buffer *parent;
YY_BUFFER_STATE state;
+ int yylineno;
+ const char *filename;
+ int source_lineno;
};
static struct buffer *current_buf;
@@ -77,7 +86,7 @@ static void warn_ignored_character(char chr)
{
fprintf(stderr,
"%s:%d:warning: ignoring unsupported character '%c'\n",
- current_file->name, yylineno, chr);
+ cur_filename, yylineno, chr);
}
%}
@@ -180,7 +189,7 @@ n [A-Za-z0-9_-]
\n {
fprintf(stderr,
"%s:%d:warning: multi-line strings not supported\n",
- zconf_curname(), zconf_lineno());
+ cur_filename, cur_lineno);
unput('\n');
BEGIN(INITIAL);
yylval.string = text;
@@ -246,9 +255,9 @@ n [A-Za-z0-9_-]
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);
+ cur_filename, yylineno);
- if (current_file) {
+ if (current_buf) {
zconf_endfile();
return T_EOL;
}
@@ -267,19 +276,17 @@ repeat:
token = yylex1();
if (prev_token == T_EOL || prev_token == T_HELPTEXT) {
- if (token == T_EOL) {
+ if (token == T_EOL)
/* Do not pass unneeded T_EOL to the parser. */
goto repeat;
- } else {
+ else
/*
- * For the parser, update file/lineno at the first token
+ * For the parser, update 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;
- }
+ cur_lineno = yylineno;
}
if (prev_prev_token == T_EOL && prev_token == T_WORD &&
@@ -302,8 +309,11 @@ static char *expand_token(const char *in, size_t n)
new_string();
append_string(in, n);
- /* get the whole line because we do not know the end of token. */
- while ((c = input()) != EOF) {
+ /*
+ * get the whole line because we do not know the end of token.
+ * input() returns 0 (not EOF!) when it reachs the end of file.
+ */
+ while ((c = input()) != 0) {
if (c == '\n') {
unput(c);
break;
@@ -391,78 +401,60 @@ void zconf_initscan(const char *name)
exit(1);
}
- current_buf = xmalloc(sizeof(*current_buf));
- memset(current_buf, 0, sizeof(*current_buf));
-
- current_file = file_lookup(name);
+ cur_filename = file_lookup(name);
yylineno = 1;
}
void zconf_nextfile(const char *name)
{
- struct file *iter;
- struct file *file = file_lookup(name);
struct buffer *buf = xmalloc(sizeof(*buf));
- memset(buf, 0, sizeof(*buf));
+ bool recur_include = false;
- current_buf->state = YY_CURRENT_BUFFER;
- yyin = zconf_fopen(file->name);
+ buf->state = YY_CURRENT_BUFFER;
+ buf->yylineno = yylineno;
+ buf->filename = cur_filename;
+ buf->source_lineno = cur_lineno;
+ buf->parent = current_buf;
+ current_buf = buf;
+ yyin = zconf_fopen(name);
if (!yyin) {
fprintf(stderr, "%s:%d: can't open file \"%s\"\n",
- zconf_curname(), zconf_lineno(), file->name);
+ cur_filename, cur_lineno, name);
exit(1);
}
yy_switch_to_buffer(yy_create_buffer(yyin, YY_BUF_SIZE));
- buf->parent = current_buf;
- current_buf = buf;
- current_file->lineno = yylineno;
- file->parent = current_file;
-
- for (iter = current_file; iter; iter = iter->parent) {
- if (!strcmp(iter->name, file->name)) {
- fprintf(stderr,
- "Recursive inclusion detected.\n"
- "Inclusion path:\n"
- " current file : %s\n", file->name);
- iter = file;
- do {
- iter = iter->parent;
- fprintf(stderr, " included from: %s:%d\n",
- iter->name, iter->lineno - 1);
- } while (strcmp(iter->name, file->name));
- exit(1);
- }
+ for (buf = current_buf; buf; buf = buf->parent) {
+ if (!strcmp(buf->filename, name))
+ recur_include = true;
}
- yylineno = 1;
- current_file = file;
-}
-
-static void zconf_endfile(void)
-{
- struct buffer *parent;
-
- current_file = current_file->parent;
- if (current_file)
- yylineno = current_file->lineno;
+ if (recur_include) {
+ fprintf(stderr,
+ "Recursive inclusion detected.\n"
+ "Inclusion path:\n"
+ " current file : %s\n", name);
- parent = current_buf->parent;
- if (parent) {
- fclose(yyin);
- yy_delete_buffer(YY_CURRENT_BUFFER);
- yy_switch_to_buffer(parent->state);
+ for (buf = current_buf; buf; buf = buf->parent)
+ fprintf(stderr, " included from: %s:%d\n",
+ buf->filename, buf->source_lineno);
+ exit(1);
}
- free(current_buf);
- current_buf = parent;
-}
-int zconf_lineno(void)
-{
- return current_pos.lineno;
+ yylineno = 1;
+ cur_filename = file_lookup(name);
}
-const char *zconf_curname(void)
+static void zconf_endfile(void)
{
- return current_pos.file ? current_pos.file->name : "<none>";
+ struct buffer *tmp;
+
+ fclose(yyin);
+ yy_delete_buffer(YY_CURRENT_BUFFER);
+ yy_switch_to_buffer(current_buf->state);
+ yylineno = current_buf->yylineno;
+ cur_filename = current_buf->filename;
+ tmp = current_buf;
+ current_buf = current_buf->parent;
+ free(tmp);
}
diff --git a/scripts/kconfig/list.h b/scripts/kconfig/list.h
index 45cb237ab7ef..882859ddf9f4 100644
--- a/scripts/kconfig/list.h
+++ b/scripts/kconfig/list.h
@@ -2,29 +2,39 @@
#ifndef LIST_H
#define LIST_H
-/*
- * Copied from include/linux/...
- */
+#include <stddef.h>
-#undef offsetof
-#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
+#include "list_types.h"
+
+/* Are two types/vars the same type (ignoring qualifiers)? */
+#define __same_type(a, b) __builtin_types_compatible_p(typeof(a), typeof(b))
/**
* container_of - cast a member of a structure out to the containing structure
- * @ptr: the pointer to the member.
- * @type: the type of the container struct this is embedded in.
- * @member: the name of the member within the struct.
+ * @ptr: the pointer to the member.
+ * @type: the type of the container struct this is embedded in.
+ * @member: the name of the member within the struct.
*
*/
-#define container_of(ptr, type, member) ({ \
- const typeof( ((type *)0)->member ) *__mptr = (ptr); \
- (type *)( (char *)__mptr - offsetof(type,member) );})
-
+#define container_of(ptr, type, member) ({ \
+ void *__mptr = (void *)(ptr); \
+ _Static_assert(__same_type(*(ptr), ((type *)0)->member) || \
+ __same_type(*(ptr), void), \
+ "pointer type mismatch in container_of()"); \
+ ((type *)(__mptr - offsetof(type, member))); })
-struct list_head {
- struct list_head *next, *prev;
-};
+#define LIST_POISON1 ((void *) 0x100)
+#define LIST_POISON2 ((void *) 0x122)
+/*
+ * Circular doubly linked list implementation.
+ *
+ * Some of the internal functions ("__xxx") are useful when
+ * manipulating whole lists rather than single entries, as
+ * sometimes we already know the next/prev entries and we can
+ * generate better code by using them directly rather than
+ * using the generic single-entry routines.
+ */
#define LIST_HEAD_INIT(name) { &(name), &(name) }
@@ -32,45 +42,16 @@ struct list_head {
struct list_head name = LIST_HEAD_INIT(name)
/**
- * list_entry - get the struct for this entry
- * @ptr: the &struct list_head pointer.
- * @type: the type of the struct this is embedded in.
- * @member: the name of the list_head within the struct.
- */
-#define list_entry(ptr, type, member) \
- container_of(ptr, type, member)
-
-/**
- * list_for_each_entry - iterate over list of given type
- * @pos: the type * to use as a loop cursor.
- * @head: the head for your list.
- * @member: the name of the list_head within the struct.
- */
-#define list_for_each_entry(pos, head, member) \
- for (pos = list_entry((head)->next, typeof(*pos), member); \
- &pos->member != (head); \
- pos = list_entry(pos->member.next, typeof(*pos), member))
-
-/**
- * list_for_each_entry_safe - iterate over list of given type safe against removal of list entry
- * @pos: the type * to use as a loop cursor.
- * @n: another type * to use as temporary storage
- * @head: the head for your list.
- * @member: the name of the list_head within the struct.
- */
-#define list_for_each_entry_safe(pos, n, head, member) \
- for (pos = list_entry((head)->next, typeof(*pos), member), \
- n = list_entry(pos->member.next, typeof(*pos), member); \
- &pos->member != (head); \
- pos = n, n = list_entry(n->member.next, typeof(*n), member))
-
-/**
- * list_empty - tests whether a list is empty
- * @head: the list to test.
+ * INIT_LIST_HEAD - Initialize a list_head structure
+ * @list: list_head structure to be initialized.
+ *
+ * Initializes the list_head to point to itself. If it is a list header,
+ * the result is an empty list.
*/
-static inline int list_empty(const struct list_head *head)
+static inline void INIT_LIST_HEAD(struct list_head *list)
{
- return head->next == head;
+ list->next = list;
+ list->prev = list;
}
/*
@@ -79,14 +60,27 @@ static inline int list_empty(const struct list_head *head)
* This is only for internal list manipulation where we know
* the prev/next entries already!
*/
-static inline void __list_add(struct list_head *_new,
+static inline void __list_add(struct list_head *new,
struct list_head *prev,
struct list_head *next)
{
- next->prev = _new;
- _new->next = next;
- _new->prev = prev;
- prev->next = _new;
+ next->prev = new;
+ new->next = next;
+ new->prev = prev;
+ prev->next = new;
+}
+
+/**
+ * list_add - add a new entry
+ * @new: new entry to be added
+ * @head: list head to add it after
+ *
+ * Insert a new entry after the specified head.
+ * This is good for implementing stacks.
+ */
+static inline void list_add(struct list_head *new, struct list_head *head)
+{
+ __list_add(new, head, head->next);
}
/**
@@ -97,9 +91,9 @@ static inline void __list_add(struct list_head *_new,
* Insert a new entry before the specified head.
* This is useful for implementing queues.
*/
-static inline void list_add_tail(struct list_head *_new, struct list_head *head)
+static inline void list_add_tail(struct list_head *new, struct list_head *head)
{
- __list_add(_new, head->prev, head);
+ __list_add(new, head->prev, head);
}
/*
@@ -115,8 +109,11 @@ static inline void __list_del(struct list_head *prev, struct list_head *next)
prev->next = next;
}
-#define LIST_POISON1 ((void *) 0x00100100)
-#define LIST_POISON2 ((void *) 0x00200200)
+static inline void __list_del_entry(struct list_head *entry)
+{
+ __list_del(entry->prev, entry->next);
+}
+
/**
* list_del - deletes entry from list.
* @entry: the element to delete from the list.
@@ -125,8 +122,135 @@ static inline void __list_del(struct list_head *prev, struct list_head *next)
*/
static inline void list_del(struct list_head *entry)
{
- __list_del(entry->prev, entry->next);
- entry->next = (struct list_head*)LIST_POISON1;
- entry->prev = (struct list_head*)LIST_POISON2;
+ __list_del_entry(entry);
+ entry->next = LIST_POISON1;
+ entry->prev = LIST_POISON2;
+}
+
+/**
+ * list_is_head - tests whether @list is the list @head
+ * @list: the entry to test
+ * @head: the head of the list
+ */
+static inline int list_is_head(const struct list_head *list, const struct list_head *head)
+{
+ return list == head;
+}
+
+/**
+ * list_empty - tests whether a list is empty
+ * @head: the list to test.
+ */
+static inline int list_empty(const struct list_head *head)
+{
+ return head->next == head;
+}
+
+/**
+ * list_entry - get the struct for this entry
+ * @ptr: the &struct list_head pointer.
+ * @type: the type of the struct this is embedded in.
+ * @member: the name of the list_head within the struct.
+ */
+#define list_entry(ptr, type, member) \
+ container_of(ptr, type, member)
+
+/**
+ * list_first_entry - get the first element from a list
+ * @ptr: the list head to take the element from.
+ * @type: the type of the struct this is embedded in.
+ * @member: the name of the list_head within the struct.
+ *
+ * Note, that list is expected to be not empty.
+ */
+#define list_first_entry(ptr, type, member) \
+ list_entry((ptr)->next, type, member)
+
+/**
+ * list_next_entry - get the next element in list
+ * @pos: the type * to cursor
+ * @member: the name of the list_head within the struct.
+ */
+#define list_next_entry(pos, member) \
+ list_entry((pos)->member.next, typeof(*(pos)), member)
+
+/**
+ * list_entry_is_head - test if the entry points to the head of the list
+ * @pos: the type * to cursor
+ * @head: the head for your list.
+ * @member: the name of the list_head within the struct.
+ */
+#define list_entry_is_head(pos, head, member) \
+ (&pos->member == (head))
+
+/**
+ * list_for_each_entry - iterate over list of given type
+ * @pos: the type * to use as a loop cursor.
+ * @head: the head for your list.
+ * @member: the name of the list_head within the struct.
+ */
+#define list_for_each_entry(pos, head, member) \
+ for (pos = list_first_entry(head, typeof(*pos), member); \
+ !list_entry_is_head(pos, head, member); \
+ pos = list_next_entry(pos, member))
+
+/**
+ * list_for_each_entry_safe - iterate over list of given type. Safe against removal of list entry
+ * @pos: the type * to use as a loop cursor.
+ * @n: another type * to use as temporary storage
+ * @head: the head for your list.
+ * @member: the name of the list_head within the struct.
+ */
+#define list_for_each_entry_safe(pos, n, head, member) \
+ for (pos = list_first_entry(head, typeof(*pos), member), \
+ n = list_next_entry(pos, member); \
+ !list_entry_is_head(pos, head, member); \
+ pos = n, n = list_next_entry(n, member))
+
+/*
+ * Double linked lists with a single pointer list head.
+ * Mostly useful for hash tables where the two pointer list head is
+ * too wasteful.
+ * You lose the ability to access the tail in O(1).
+ */
+
+#define HLIST_HEAD_INIT { .first = NULL }
+
+/**
+ * hlist_add_head - add a new entry at the beginning of the hlist
+ * @n: new entry to be added
+ * @h: hlist head to add it after
+ *
+ * Insert a new entry after the specified head.
+ * This is good for implementing stacks.
+ */
+static inline void hlist_add_head(struct hlist_node *n, struct hlist_head *h)
+{
+ struct hlist_node *first = h->first;
+
+ n->next = first;
+ if (first)
+ first->pprev = &n->next;
+ h->first = n;
+ n->pprev = &h->first;
}
-#endif
+
+#define hlist_entry(ptr, type, member) container_of(ptr, type, member)
+
+#define hlist_entry_safe(ptr, type, member) \
+ ({ typeof(ptr) ____ptr = (ptr); \
+ ____ptr ? hlist_entry(____ptr, type, member) : NULL; \
+ })
+
+/**
+ * hlist_for_each_entry - iterate over list of given type
+ * @pos: the type * to use as a loop cursor.
+ * @head: the head for your list.
+ * @member: the name of the hlist_node within the struct.
+ */
+#define hlist_for_each_entry(pos, head, member) \
+ for (pos = hlist_entry_safe((head)->first, typeof(*(pos)), member);\
+ pos; \
+ pos = hlist_entry_safe((pos)->member.next, typeof(*(pos)), member))
+
+#endif /* LIST_H */
diff --git a/scripts/kconfig/list_types.h b/scripts/kconfig/list_types.h
new file mode 100644
index 000000000000..d935b7c5aa81
--- /dev/null
+++ b/scripts/kconfig/list_types.h
@@ -0,0 +1,17 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef LIST_TYPES_H
+#define LIST_TYPES_H
+
+struct list_head {
+ struct list_head *next, *prev;
+};
+
+struct hlist_head {
+ struct hlist_node *first;
+};
+
+struct hlist_node {
+ struct hlist_node *next, **pprev;
+};
+
+#endif /* LIST_TYPES_H */
diff --git a/scripts/kconfig/lkc.h b/scripts/kconfig/lkc.h
index 471a59acecec..e7cc9e985c4f 100644
--- a/scripts/kconfig/lkc.h
+++ b/scripts/kconfig/lkc.h
@@ -36,10 +36,9 @@ void zconf_starthelp(void);
FILE *zconf_fopen(const char *name);
void zconf_initscan(const char *name);
void zconf_nextfile(const char *name);
-int zconf_lineno(void);
-const char *zconf_curname(void);
/* confdata.c */
+extern struct gstr autoconf_cmd;
const char *conf_get_configname(void);
void set_all_choice_values(struct symbol *csym);
@@ -53,7 +52,8 @@ static inline void xfwrite(const void *str, size_t len, size_t count, FILE *out)
}
/* util.c */
-struct file *file_lookup(const char *name);
+unsigned int strhash(const char *s);
+const char *file_lookup(const char *name);
void *xmalloc(size_t size);
void *xcalloc(size_t nmemb, size_t size);
void *xrealloc(void *p, size_t size);
@@ -89,7 +89,7 @@ void menu_add_visibility(struct expr *dep);
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_finalize(struct menu *parent);
+void menu_finalize(void);
void menu_set_type(int type);
extern struct menu rootmenu;
@@ -99,8 +99,6 @@ bool menu_is_visible(struct menu *menu);
bool menu_has_prompt(struct menu *menu);
const char *menu_get_prompt(struct menu *menu);
struct menu *menu_get_parent_menu(struct menu *menu);
-bool menu_has_help(struct menu *menu);
-const char *menu_get_help(struct menu *menu);
int get_jump_key_char(void);
struct gstr get_relations_str(struct symbol **sym_arr, struct list_head *head);
void menu_get_ext_help(struct menu *menu, struct gstr *help);
diff --git a/scripts/kconfig/lkc_proto.h b/scripts/kconfig/lkc_proto.h
index edd1e617b25c..2807fa584c2b 100644
--- a/scripts/kconfig/lkc_proto.h
+++ b/scripts/kconfig/lkc_proto.h
@@ -1,4 +1,7 @@
/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef LKC_PROTO_H
+#define LKC_PROTO_H
+
#include <stdarg.h>
/* confdata.c */
@@ -12,16 +15,16 @@ void conf_set_changed(bool val);
bool conf_get_changed(void);
void conf_set_changed_callback(void (*fn)(void));
void conf_set_message_callback(void (*fn)(const char *s));
+bool conf_errors(void);
/* symbol.c */
-extern struct symbol * symbol_hash[SYMBOL_HASHSIZE];
-
struct symbol * sym_lookup(const char *name, int flags);
struct symbol * sym_find(const char *name);
void print_symbol_for_listconfig(struct symbol *sym);
struct symbol ** sym_re_search(const char *pattern);
const char * sym_type_name(enum symbol_type type);
void sym_calc_value(struct symbol *sym);
+bool sym_dep_errors(void);
enum symbol_type sym_get_type(struct symbol *sym);
bool sym_tristate_within_range(struct symbol *sym,tristate tri);
bool sym_set_tristate_value(struct symbol *sym,tristate tri);
@@ -35,18 +38,7 @@ const char * sym_get_string_value(struct symbol *sym);
const char * prop_get_type_name(enum prop_type type);
-/* preprocess.c */
-enum variable_flavor {
- VAR_SIMPLE,
- VAR_RECURSIVE,
- VAR_APPEND,
-};
-void env_write_dep(FILE *f, const char *auto_conf_name);
-void variable_add(const char *name, const char *value,
- enum variable_flavor flavor);
-void variable_all_del(void);
-char *expand_dollar(const char **str);
-char *expand_one_token(const char **str);
-
/* expr.c */
void expr_print(struct expr *e, void (*fn)(void *, struct symbol *, const char *), void *data, int prevtoken);
+
+#endif /* LKC_PROTO_H */
diff --git a/scripts/kconfig/lxdialog/checklist.c b/scripts/kconfig/lxdialog/checklist.c
index fd161cfff121..75493302fb85 100644
--- a/scripts/kconfig/lxdialog/checklist.c
+++ b/scripts/kconfig/lxdialog/checklist.c
@@ -119,7 +119,7 @@ int dialog_checklist(const char *title, const char *prompt, int height,
}
do_resize:
- if (getmaxy(stdscr) < (height + CHECKLIST_HEIGTH_MIN))
+ if (getmaxy(stdscr) < (height + CHECKLIST_HEIGHT_MIN))
return -ERRDISPLAYTOOSMALL;
if (getmaxx(stdscr) < (width + CHECKLIST_WIDTH_MIN))
return -ERRDISPLAYTOOSMALL;
@@ -188,9 +188,8 @@ do_resize:
print_buttons(dialog, height, width, 0);
- wnoutrefresh(dialog);
- wnoutrefresh(list);
- doupdate();
+ wmove(list, choice, check_x + 1);
+ wrefresh(list);
while (key != KEY_ESC) {
key = wgetch(dialog);
diff --git a/scripts/kconfig/lxdialog/dialog.h b/scripts/kconfig/lxdialog/dialog.h
index a501abf9fa31..f6c2ebe6d1f9 100644
--- a/scripts/kconfig/lxdialog/dialog.h
+++ b/scripts/kconfig/lxdialog/dialog.h
@@ -91,10 +91,6 @@ struct dialog_info {
struct dialog_color button_label_active;
struct dialog_color button_label_inactive;
struct dialog_color inputbox;
- struct dialog_color inputbox_border;
- struct dialog_color searchbox;
- struct dialog_color searchbox_title;
- struct dialog_color searchbox_border;
struct dialog_color position_indicator;
struct dialog_color menubox;
struct dialog_color menubox_border;
@@ -166,17 +162,17 @@ int on_key_esc(WINDOW *win);
int on_key_resize(void);
/* minimum (re)size values */
-#define CHECKLIST_HEIGTH_MIN 6 /* For dialog_checklist() */
+#define CHECKLIST_HEIGHT_MIN 6 /* For dialog_checklist() */
#define CHECKLIST_WIDTH_MIN 6
-#define INPUTBOX_HEIGTH_MIN 2 /* For dialog_inputbox() */
+#define INPUTBOX_HEIGHT_MIN 2 /* For dialog_inputbox() */
#define INPUTBOX_WIDTH_MIN 2
-#define MENUBOX_HEIGTH_MIN 15 /* For dialog_menu() */
+#define MENUBOX_HEIGHT_MIN 15 /* For dialog_menu() */
#define MENUBOX_WIDTH_MIN 65
-#define TEXTBOX_HEIGTH_MIN 8 /* For dialog_textbox() */
+#define TEXTBOX_HEIGHT_MIN 8 /* For dialog_textbox() */
#define TEXTBOX_WIDTH_MIN 8
-#define YESNO_HEIGTH_MIN 4 /* For dialog_yesno() */
+#define YESNO_HEIGHT_MIN 4 /* For dialog_yesno() */
#define YESNO_WIDTH_MIN 4
-#define WINDOW_HEIGTH_MIN 19 /* For init_dialog() */
+#define WINDOW_HEIGHT_MIN 19 /* For init_dialog() */
#define WINDOW_WIDTH_MIN 80
int init_dialog(const char *backtitle);
diff --git a/scripts/kconfig/lxdialog/inputbox.c b/scripts/kconfig/lxdialog/inputbox.c
index 1dcfb288ee63..3c6e24b20f5b 100644
--- a/scripts/kconfig/lxdialog/inputbox.c
+++ b/scripts/kconfig/lxdialog/inputbox.c
@@ -43,7 +43,7 @@ int dialog_inputbox(const char *title, const char *prompt, int height, int width
strcpy(instr, init);
do_resize:
- if (getmaxy(stdscr) <= (height - INPUTBOX_HEIGTH_MIN))
+ if (getmaxy(stdscr) <= (height - INPUTBOX_HEIGHT_MIN))
return -ERRDISPLAYTOOSMALL;
if (getmaxx(stdscr) <= (width - INPUTBOX_WIDTH_MIN))
return -ERRDISPLAYTOOSMALL;
diff --git a/scripts/kconfig/lxdialog/menubox.c b/scripts/kconfig/lxdialog/menubox.c
index 0e333284e947..6e6244df0c56 100644
--- a/scripts/kconfig/lxdialog/menubox.c
+++ b/scripts/kconfig/lxdialog/menubox.c
@@ -172,7 +172,7 @@ int dialog_menu(const char *title, const char *prompt,
do_resize:
height = getmaxy(stdscr);
width = getmaxx(stdscr);
- if (height < MENUBOX_HEIGTH_MIN || width < MENUBOX_WIDTH_MIN)
+ if (height < MENUBOX_HEIGHT_MIN || width < MENUBOX_WIDTH_MIN)
return -ERRDISPLAYTOOSMALL;
height -= 4;
diff --git a/scripts/kconfig/lxdialog/textbox.c b/scripts/kconfig/lxdialog/textbox.c
index 058ed0e5bbd5..0abaf635978f 100644
--- a/scripts/kconfig/lxdialog/textbox.c
+++ b/scripts/kconfig/lxdialog/textbox.c
@@ -175,7 +175,7 @@ int dialog_textbox(const char *title, const char *tbuf, int initial_height,
do_resize:
getmaxyx(stdscr, height, width);
- if (height < TEXTBOX_HEIGTH_MIN || width < TEXTBOX_WIDTH_MIN)
+ if (height < TEXTBOX_HEIGHT_MIN || width < TEXTBOX_WIDTH_MIN)
return -ERRDISPLAYTOOSMALL;
if (initial_height != 0)
height = initial_height;
diff --git a/scripts/kconfig/lxdialog/util.c b/scripts/kconfig/lxdialog/util.c
index 3f78fb265136..f18e2a89f613 100644
--- a/scripts/kconfig/lxdialog/util.c
+++ b/scripts/kconfig/lxdialog/util.c
@@ -29,10 +29,6 @@ static void set_mono_theme(void)
dlg.button_label_active.atr = A_REVERSE;
dlg.button_label_inactive.atr = A_NORMAL;
dlg.inputbox.atr = A_NORMAL;
- dlg.inputbox_border.atr = A_NORMAL;
- dlg.searchbox.atr = A_NORMAL;
- dlg.searchbox_title.atr = A_BOLD;
- dlg.searchbox_border.atr = A_NORMAL;
dlg.position_indicator.atr = A_BOLD;
dlg.menubox.atr = A_NORMAL;
dlg.menubox_border.atr = A_NORMAL;
@@ -69,10 +65,6 @@ static void set_classic_theme(void)
DLG_COLOR(button_label_active, COLOR_YELLOW, COLOR_BLUE, true);
DLG_COLOR(button_label_inactive, COLOR_BLACK, COLOR_WHITE, true);
DLG_COLOR(inputbox, COLOR_BLACK, COLOR_WHITE, false);
- DLG_COLOR(inputbox_border, COLOR_BLACK, COLOR_WHITE, false);
- DLG_COLOR(searchbox, COLOR_BLACK, COLOR_WHITE, false);
- DLG_COLOR(searchbox_title, COLOR_YELLOW, COLOR_WHITE, true);
- DLG_COLOR(searchbox_border, COLOR_WHITE, COLOR_WHITE, true);
DLG_COLOR(position_indicator, COLOR_YELLOW, COLOR_WHITE, true);
DLG_COLOR(menubox, COLOR_BLACK, COLOR_WHITE, false);
DLG_COLOR(menubox_border, COLOR_WHITE, COLOR_WHITE, true);
@@ -101,14 +93,9 @@ static void set_blackbg_theme(void)
DLG_COLOR(button_key_active, COLOR_YELLOW, COLOR_RED, true);
DLG_COLOR(button_key_inactive, COLOR_RED, COLOR_BLACK, false);
DLG_COLOR(button_label_active, COLOR_WHITE, COLOR_RED, false);
- DLG_COLOR(button_label_inactive, COLOR_BLACK, COLOR_BLACK, true);
+ DLG_COLOR(button_label_inactive, COLOR_WHITE, COLOR_BLACK, false);
DLG_COLOR(inputbox, COLOR_YELLOW, COLOR_BLACK, false);
- DLG_COLOR(inputbox_border, COLOR_YELLOW, COLOR_BLACK, false);
-
- DLG_COLOR(searchbox, COLOR_YELLOW, COLOR_BLACK, false);
- DLG_COLOR(searchbox_title, COLOR_YELLOW, COLOR_BLACK, true);
- DLG_COLOR(searchbox_border, COLOR_BLACK, COLOR_BLACK, true);
DLG_COLOR(position_indicator, COLOR_RED, COLOR_BLACK, false);
@@ -136,7 +123,6 @@ static void set_bluetitle_theme(void)
DLG_COLOR(title, COLOR_BLUE, COLOR_WHITE, true);
DLG_COLOR(button_key_active, COLOR_YELLOW, COLOR_BLUE, true);
DLG_COLOR(button_label_active, COLOR_WHITE, COLOR_BLUE, true);
- DLG_COLOR(searchbox_title, COLOR_BLUE, COLOR_WHITE, true);
DLG_COLOR(position_indicator, COLOR_BLUE, COLOR_WHITE, true);
DLG_COLOR(tag, COLOR_BLUE, COLOR_WHITE, true);
DLG_COLOR(tag_key, COLOR_BLUE, COLOR_WHITE, true);
@@ -189,10 +175,6 @@ static void init_dialog_colors(void)
init_one_color(&dlg.button_label_active);
init_one_color(&dlg.button_label_inactive);
init_one_color(&dlg.inputbox);
- init_one_color(&dlg.inputbox_border);
- init_one_color(&dlg.searchbox);
- init_one_color(&dlg.searchbox_title);
- init_one_color(&dlg.searchbox_border);
init_one_color(&dlg.position_indicator);
init_one_color(&dlg.menubox);
init_one_color(&dlg.menubox_border);
@@ -309,7 +291,7 @@ int init_dialog(const char *backtitle)
getyx(stdscr, saved_y, saved_x);
getmaxyx(stdscr, height, width);
- if (height < WINDOW_HEIGTH_MIN || width < WINDOW_WIDTH_MIN) {
+ if (height < WINDOW_HEIGHT_MIN || width < WINDOW_WIDTH_MIN) {
endwin();
return -ERRDISPLAYTOOSMALL;
}
diff --git a/scripts/kconfig/lxdialog/yesno.c b/scripts/kconfig/lxdialog/yesno.c
index bcaac9b7bab2..b57d25e1549f 100644
--- a/scripts/kconfig/lxdialog/yesno.c
+++ b/scripts/kconfig/lxdialog/yesno.c
@@ -32,7 +32,7 @@ int dialog_yesno(const char *title, const char *prompt, int height, int width)
WINDOW *dialog;
do_resize:
- if (getmaxy(stdscr) < (height + YESNO_HEIGTH_MIN))
+ if (getmaxy(stdscr) < (height + YESNO_HEIGHT_MIN))
return -ERRDISPLAYTOOSMALL;
if (getmaxx(stdscr) < (width + YESNO_WIDTH_MIN))
return -ERRDISPLAYTOOSMALL;
diff --git a/scripts/kconfig/mconf.c b/scripts/kconfig/mconf.c
index eccc87a441e7..c0969097447d 100644
--- a/scripts/kconfig/mconf.c
+++ b/scripts/kconfig/mconf.c
@@ -19,8 +19,10 @@
#include <signal.h>
#include <unistd.h>
+#include "list.h"
#include "lkc.h"
#include "lxdialog/dialog.h"
+#include "mnconf-common.h"
static const char mconf_readme[] =
"Overview\n"
@@ -247,7 +249,7 @@ search_help[] =
" -> PCI support (PCI [=y])\n"
"(1) -> PCI access mode (<choice> [=y])\n"
" Defined at drivers/pci/Kconfig:47\n"
- " Depends on: X86_LOCAL_APIC && X86_IO_APIC || IA64\n"
+ " Depends on: X86_LOCAL_APIC && X86_IO_APIC\n"
" Selects: LIBCRC32\n"
" Selected by: BAR [=n]\n"
"-----------------------------------------------------------------\n"
@@ -286,7 +288,6 @@ static int single_menu_mode;
static int show_all_options;
static int save_and_exit;
static int silent;
-static int jump_key_char;
static void conf(struct menu *menu, struct menu *active_menu);
@@ -378,58 +379,6 @@ static void show_help(struct menu *menu)
str_free(&help);
}
-struct search_data {
- struct list_head *head;
- struct menu *target;
-};
-
-static int next_jump_key(int key)
-{
- if (key < '1' || key > '9')
- return '1';
-
- key++;
-
- if (key > '9')
- key = '1';
-
- return key;
-}
-
-static int handle_search_keys(int key, size_t start, size_t end, void *_data)
-{
- struct search_data *data = _data;
- struct jump_key *pos;
- int index = 0;
-
- if (key < '1' || key > '9')
- return 0;
-
- list_for_each_entry(pos, data->head, entries) {
- index = next_jump_key(index);
-
- if (pos->offset < start)
- continue;
-
- if (pos->offset >= end)
- break;
-
- if (key == index) {
- data->target = pos->target;
- return 1;
- }
- }
-
- return 0;
-}
-
-int get_jump_key_char(void)
-{
- jump_key_char = next_jump_key(jump_key_char);
-
- return jump_key_char;
-}
-
static void search_conf(void)
{
struct symbol **sym_arr;
@@ -710,9 +659,9 @@ static void conf_choice(struct menu *menu)
dialog_clear();
res = dialog_checklist(prompt ? prompt : "Main Menu",
radiolist_instructions,
- MENUBOX_HEIGTH_MIN,
+ MENUBOX_HEIGHT_MIN,
MENUBOX_WIDTH_MIN,
- CHECKLIST_HEIGTH_MIN);
+ CHECKLIST_HEIGHT_MIN);
selected = item_activate_selected();
switch (res) {
case 0:
diff --git a/scripts/kconfig/menu.c b/scripts/kconfig/menu.c
index 61c442d84aef..3b822cd110f4 100644
--- a/scripts/kconfig/menu.c
+++ b/scripts/kconfig/menu.c
@@ -10,20 +10,18 @@
#include "lkc.h"
#include "internal.h"
+#include "list.h"
static const char nohelp_text[] = "There is no help available for this option.";
struct menu rootmenu;
static struct menu **last_entry_ptr;
-struct file *file_list;
-struct file *current_file;
-
void menu_warn(struct menu *menu, const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
- fprintf(stderr, "%s:%d:warning: ", menu->file->name, menu->lineno);
+ fprintf(stderr, "%s:%d:warning: ", menu->filename, menu->lineno);
vfprintf(stderr, fmt, ap);
fprintf(stderr, "\n");
va_end(ap);
@@ -33,7 +31,7 @@ static void prop_warn(struct property *prop, const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
- fprintf(stderr, "%s:%d:warning: ", prop->file->name, prop->lineno);
+ fprintf(stderr, "%s:%d:warning: ", prop->filename, prop->lineno);
vfprintf(stderr, fmt, ap);
fprintf(stderr, "\n");
va_end(ap);
@@ -53,14 +51,16 @@ void menu_add_entry(struct symbol *sym)
memset(menu, 0, sizeof(*menu));
menu->sym = sym;
menu->parent = current_menu;
- menu->file = current_file;
- menu->lineno = zconf_lineno();
+ menu->filename = cur_filename;
+ menu->lineno = cur_lineno;
*last_entry_ptr = menu;
last_entry_ptr = &menu->next;
current_entry = menu;
- if (sym)
+ if (sym) {
menu_add_symbol(P_SYMBOL, sym, NULL);
+ list_add_tail(&menu->link, &sym->menus);
+ }
}
struct menu *menu_add_menu(void)
@@ -134,8 +134,8 @@ static struct property *menu_add_prop(enum prop_type type, struct expr *expr,
prop = xmalloc(sizeof(*prop));
memset(prop, 0, sizeof(*prop));
prop->type = type;
- prop->file = current_file;
- prop->lineno = zconf_lineno();
+ prop->filename = cur_filename;
+ prop->lineno = cur_lineno;
prop->menu = current_entry;
prop->expr = expr;
prop->visible.expr = dep;
@@ -282,7 +282,7 @@ static void sym_check_prop(struct symbol *sym)
}
}
-void menu_finalize(struct menu *parent)
+static void _menu_finalize(struct menu *parent, bool inside_choice)
{
struct menu *menu, *last_menu;
struct symbol *sym;
@@ -296,7 +296,12 @@ void menu_finalize(struct menu *parent)
* and propagate parent dependencies before moving on.
*/
- if (sym && sym_is_choice(sym)) {
+ bool is_choice = false;
+
+ if (sym && sym_is_choice(sym))
+ is_choice = true;
+
+ if (is_choice) {
if (sym->type == S_UNKNOWN) {
/* find the first choice value to find out choice type */
current_entry = parent;
@@ -307,12 +312,6 @@ void menu_finalize(struct menu *parent)
}
}
}
- /* set the type of the remaining choice values */
- for (menu = parent->list; menu; menu = menu->next) {
- current_entry = menu;
- if (menu->sym && menu->sym->type == S_UNKNOWN)
- menu_set_type(sym->type);
- }
/*
* Use the choice itself as the parent dependency of
@@ -400,7 +399,7 @@ void menu_finalize(struct menu *parent)
}
}
- if (sym && sym_is_choice(sym))
+ if (is_choice)
expr_free(parentdep);
/*
@@ -408,8 +407,8 @@ void menu_finalize(struct menu *parent)
* moving on
*/
for (menu = parent->list; menu; menu = menu->next)
- menu_finalize(menu);
- } else if (sym) {
+ _menu_finalize(menu, is_choice);
+ } else if (!inside_choice && sym) {
/*
* Automatic submenu creation. If sym is a symbol and A, B, C,
* ... are consecutive items (symbols, menus, ifs, etc.) that
@@ -469,7 +468,7 @@ void menu_finalize(struct menu *parent)
/* Superset, put in submenu */
expr_free(dep2);
next:
- menu_finalize(menu);
+ _menu_finalize(menu, false);
menu->parent = parent;
last_menu = menu;
}
@@ -567,9 +566,6 @@ void menu_finalize(struct menu *parent)
if (sym->type == S_UNKNOWN)
menu_warn(parent, "config symbol defined without type");
- if (sym_is_choice(sym) && !parent->prompt)
- menu_warn(parent, "choice must have a prompt");
-
/* Check properties connected to this symbol */
sym_check_prop(sym);
sym->flags |= SYMBOL_WARNED;
@@ -591,6 +587,11 @@ void menu_finalize(struct menu *parent)
}
}
+void menu_finalize(void)
+{
+ _menu_finalize(&rootmenu, false);
+}
+
bool menu_has_prompt(struct menu *menu)
{
if (!menu->prompt)
@@ -673,23 +674,10 @@ struct menu *menu_get_parent_menu(struct menu *menu)
return menu;
}
-bool menu_has_help(struct menu *menu)
-{
- return menu->help != NULL;
-}
-
-const char *menu_get_help(struct menu *menu)
-{
- if (menu->help)
- return menu->help;
- else
- return "";
-}
-
static void get_def_str(struct gstr *r, struct menu *menu)
{
str_printf(r, "Defined at %s:%d\n",
- menu->file->name, menu->lineno);
+ menu->filename, menu->lineno);
}
static void get_dep_str(struct gstr *r, struct expr *expr, const char *prefix)
@@ -790,6 +778,7 @@ static void get_symbol_str(struct gstr *r, struct symbol *sym,
struct list_head *head)
{
struct property *prop;
+ struct menu *menu;
if (sym && sym->name) {
str_printf(r, "Symbol: %s [=%s]\n", sym->name,
@@ -806,17 +795,17 @@ static void get_symbol_str(struct gstr *r, struct symbol *sym,
}
/* Print the definitions with prompts before the ones without */
- for_all_properties(sym, prop, P_SYMBOL) {
- if (prop->menu->prompt) {
- get_def_str(r, prop->menu);
- get_prompt_str(r, prop->menu->prompt, head);
+ list_for_each_entry(menu, &sym->menus, link) {
+ if (menu->prompt) {
+ get_def_str(r, menu);
+ get_prompt_str(r, menu->prompt, head);
}
}
- for_all_properties(sym, prop, P_SYMBOL) {
- if (!prop->menu->prompt) {
- get_def_str(r, prop->menu);
- get_dep_str(r, prop->menu->dep, " Depends on: ");
+ list_for_each_entry(menu, &sym->menus, link) {
+ if (!menu->prompt) {
+ get_def_str(r, menu);
+ get_dep_str(r, menu->dep, " Depends on: ");
}
}
@@ -856,10 +845,10 @@ void menu_get_ext_help(struct menu *menu, struct gstr *help)
struct symbol *sym = menu->sym;
const char *help_text = nohelp_text;
- if (menu_has_help(menu)) {
+ if (menu->help) {
if (sym->name)
str_printf(help, "%s%s:\n\n", CONFIG_, sym->name);
- help_text = menu_get_help(menu);
+ help_text = menu->help;
}
str_printf(help, "%s\n", help_text);
if (sym)
diff --git a/scripts/kconfig/mnconf-common.c b/scripts/kconfig/mnconf-common.c
new file mode 100644
index 000000000000..18cb9a6c5aaa
--- /dev/null
+++ b/scripts/kconfig/mnconf-common.c
@@ -0,0 +1,53 @@
+// SPDX-License-Identifier: GPL-2.0-only
+#include "expr.h"
+#include "list.h"
+#include "mnconf-common.h"
+
+int jump_key_char;
+
+int next_jump_key(int key)
+{
+ if (key < '1' || key > '9')
+ return '1';
+
+ key++;
+
+ if (key > '9')
+ key = '1';
+
+ return key;
+}
+
+int handle_search_keys(int key, size_t start, size_t end, void *_data)
+{
+ struct search_data *data = _data;
+ struct jump_key *pos;
+ int index = 0;
+
+ if (key < '1' || key > '9')
+ return 0;
+
+ list_for_each_entry(pos, data->head, entries) {
+ index = next_jump_key(index);
+
+ if (pos->offset < start)
+ continue;
+
+ if (pos->offset >= end)
+ break;
+
+ if (key == index) {
+ data->target = pos->target;
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+int get_jump_key_char(void)
+{
+ jump_key_char = next_jump_key(jump_key_char);
+
+ return jump_key_char;
+}
diff --git a/scripts/kconfig/mnconf-common.h b/scripts/kconfig/mnconf-common.h
new file mode 100644
index 000000000000..ab6292cc4bf2
--- /dev/null
+++ b/scripts/kconfig/mnconf-common.h
@@ -0,0 +1,18 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+#ifndef MNCONF_COMMON_H
+#define MNCONF_COMMON_H
+
+#include <stddef.h>
+
+struct search_data {
+ struct list_head *head;
+ struct menu *target;
+};
+
+extern int jump_key_char;
+
+int next_jump_key(int key);
+int handle_search_keys(int key, size_t start, size_t end, void *_data);
+int get_jump_key_char(void);
+
+#endif /* MNCONF_COMMON_H */
diff --git a/scripts/kconfig/nconf.c b/scripts/kconfig/nconf.c
index 143a2c351d57..9d22b0f3197b 100644
--- a/scripts/kconfig/nconf.c
+++ b/scripts/kconfig/nconf.c
@@ -11,7 +11,9 @@
#include <strings.h>
#include <stdlib.h>
+#include "list.h"
#include "lkc.h"
+#include "mnconf-common.h"
#include "nconf.h"
#include <ctype.h>
@@ -216,7 +218,7 @@ search_help[] =
"Symbol: FOO [ = m]\n"
"Prompt: Foo bus is used to drive the bar HW\n"
"Defined at drivers/pci/Kconfig:47\n"
-"Depends on: X86_LOCAL_APIC && X86_IO_APIC || IA64\n"
+"Depends on: X86_LOCAL_APIC && X86_IO_APIC\n"
"Location:\n"
" -> Bus options (PCI, PCMCIA, EISA, ISA)\n"
" -> PCI support (PCI [ = y])\n"
@@ -279,7 +281,6 @@ static const char *current_instructions = menu_instructions;
static char *dialog_input_result;
static int dialog_input_result_len;
-static int jump_key_char;
static void selected_conf(struct menu *menu, struct menu *active_menu);
static void conf(struct menu *menu);
@@ -691,57 +692,6 @@ static int do_exit(void)
return 0;
}
-struct search_data {
- struct list_head *head;
- struct menu *target;
-};
-
-static int next_jump_key(int key)
-{
- if (key < '1' || key > '9')
- return '1';
-
- key++;
-
- if (key > '9')
- key = '1';
-
- return key;
-}
-
-static int handle_search_keys(int key, size_t start, size_t end, void *_data)
-{
- struct search_data *data = _data;
- struct jump_key *pos;
- int index = 0;
-
- if (key < '1' || key > '9')
- return 0;
-
- list_for_each_entry(pos, data->head, entries) {
- index = next_jump_key(index);
-
- if (pos->offset < start)
- continue;
-
- if (pos->offset >= end)
- break;
-
- if (key == index) {
- data->target = pos->target;
- return 1;
- }
- }
-
- return 0;
-}
-
-int get_jump_key_char(void)
-{
- jump_key_char = next_jump_key(jump_key_char);
-
- return jump_key_char;
-}
static void search_conf(void)
{
diff --git a/scripts/kconfig/parser.y b/scripts/kconfig/parser.y
index 2af7ce4e1531..7fb996612c96 100644
--- a/scripts/kconfig/parser.y
+++ b/scripts/kconfig/parser.y
@@ -13,6 +13,7 @@
#include "lkc.h"
#include "internal.h"
+#include "preprocess.h"
#define printd(mask, fmt...) if (cdebug & (mask)) printf(fmt)
@@ -27,8 +28,6 @@ static void zconf_error(const char *err, ...);
static bool zconf_endtoken(const char *tokenname,
const char *expected_tokenname);
-struct symbol *symbol_hash[SYMBOL_HASHSIZE];
-
struct menu *current_menu, *current_entry;
%}
@@ -95,12 +94,12 @@ struct menu *current_menu, *current_entry;
%type <expr> if_expr
%type <string> end
%type <menu> if_entry menu_entry choice_entry
-%type <string> word_opt assign_val
+%type <string> assign_val
%type <flavor> assign_op
%destructor {
fprintf(stderr, "%s:%d: missing end statement for this entry\n",
- $$->file->name, $$->lineno);
+ $$->filename, $$->lineno);
if (current_menu == $$)
menu_end_menu();
} if_entry menu_entry choice_entry
@@ -143,19 +142,19 @@ config_entry_start: T_CONFIG nonconst_symbol T_EOL
{
$2->flags |= SYMBOL_OPTIONAL;
menu_add_entry($2);
- printd(DEBUG_PARSE, "%s:%d:config %s\n", zconf_curname(), zconf_lineno(), $2->name);
+ printd(DEBUG_PARSE, "%s:%d:config %s\n", cur_filename, cur_lineno, $2->name);
};
config_stmt: config_entry_start config_option_list
{
- printd(DEBUG_PARSE, "%s:%d:endconfig\n", zconf_curname(), zconf_lineno());
+ printd(DEBUG_PARSE, "%s:%d:endconfig\n", cur_filename, cur_lineno);
};
menuconfig_entry_start: T_MENUCONFIG nonconst_symbol T_EOL
{
$2->flags |= SYMBOL_OPTIONAL;
menu_add_entry($2);
- printd(DEBUG_PARSE, "%s:%d:menuconfig %s\n", zconf_curname(), zconf_lineno(), $2->name);
+ printd(DEBUG_PARSE, "%s:%d:menuconfig %s\n", cur_filename, cur_lineno, $2->name);
};
menuconfig_stmt: menuconfig_entry_start config_option_list
@@ -164,7 +163,7 @@ menuconfig_stmt: menuconfig_entry_start config_option_list
current_entry->prompt->type = P_MENU;
else
zconfprint("warning: menuconfig statement without prompt");
- printd(DEBUG_PARSE, "%s:%d:endconfig\n", zconf_curname(), zconf_lineno());
+ printd(DEBUG_PARSE, "%s:%d:endconfig\n", cur_filename, cur_lineno);
};
config_option_list:
@@ -177,15 +176,13 @@ config_option_list:
config_option: type prompt_stmt_opt T_EOL
{
menu_set_type($1);
- printd(DEBUG_PARSE, "%s:%d:type(%u)\n",
- zconf_curname(), zconf_lineno(),
- $1);
+ printd(DEBUG_PARSE, "%s:%d:type(%u)\n", cur_filename, cur_lineno, $1);
};
config_option: T_PROMPT T_WORD_QUOTE if_expr T_EOL
{
menu_add_prompt(P_PROMPT, $2, $3);
- printd(DEBUG_PARSE, "%s:%d:prompt\n", zconf_curname(), zconf_lineno());
+ printd(DEBUG_PARSE, "%s:%d:prompt\n", cur_filename, cur_lineno);
};
config_option: default expr if_expr T_EOL
@@ -193,27 +190,26 @@ config_option: default expr if_expr T_EOL
menu_add_expr(P_DEFAULT, $2, $3);
if ($1 != S_UNKNOWN)
menu_set_type($1);
- printd(DEBUG_PARSE, "%s:%d:default(%u)\n",
- zconf_curname(), zconf_lineno(),
+ printd(DEBUG_PARSE, "%s:%d:default(%u)\n", cur_filename, cur_lineno,
$1);
};
config_option: T_SELECT nonconst_symbol if_expr T_EOL
{
menu_add_symbol(P_SELECT, $2, $3);
- printd(DEBUG_PARSE, "%s:%d:select\n", zconf_curname(), zconf_lineno());
+ printd(DEBUG_PARSE, "%s:%d:select\n", cur_filename, cur_lineno);
};
config_option: T_IMPLY nonconst_symbol if_expr T_EOL
{
menu_add_symbol(P_IMPLY, $2, $3);
- printd(DEBUG_PARSE, "%s:%d:imply\n", zconf_curname(), zconf_lineno());
+ printd(DEBUG_PARSE, "%s:%d:imply\n", cur_filename, cur_lineno);
};
config_option: T_RANGE symbol symbol if_expr T_EOL
{
menu_add_expr(P_RANGE, expr_alloc_comp(E_RANGE,$2, $3), $4);
- printd(DEBUG_PARSE, "%s:%d:range\n", zconf_curname(), zconf_lineno());
+ printd(DEBUG_PARSE, "%s:%d:range\n", cur_filename, cur_lineno);
};
config_option: T_MODULES T_EOL
@@ -226,18 +222,23 @@ config_option: T_MODULES T_EOL
/* choice entry */
-choice: T_CHOICE word_opt T_EOL
+choice: T_CHOICE T_EOL
{
- struct symbol *sym = sym_lookup($2, SYMBOL_CHOICE);
+ struct symbol *sym = sym_lookup(NULL, SYMBOL_CHOICE);
sym->flags |= SYMBOL_NO_WRITE;
menu_add_entry(sym);
menu_add_expr(P_CHOICE, NULL, NULL);
- free($2);
- printd(DEBUG_PARSE, "%s:%d:choice\n", zconf_curname(), zconf_lineno());
+ printd(DEBUG_PARSE, "%s:%d:choice\n", cur_filename, cur_lineno);
};
choice_entry: choice choice_option_list
{
+ if (!current_entry->prompt) {
+ fprintf(stderr, "%s:%d: error: choice must have a prompt\n",
+ current_entry->filename, current_entry->lineno);
+ yynerrs++;
+ }
+
$$ = menu_add_menu();
};
@@ -245,7 +246,7 @@ choice_end: end
{
if (zconf_endtoken($1, "choice")) {
menu_end_menu();
- printd(DEBUG_PARSE, "%s:%d:endchoice\n", zconf_curname(), zconf_lineno());
+ printd(DEBUG_PARSE, "%s:%d:endchoice\n", cur_filename, cur_lineno);
}
};
@@ -262,27 +263,25 @@ choice_option_list:
choice_option: T_PROMPT T_WORD_QUOTE if_expr T_EOL
{
menu_add_prompt(P_PROMPT, $2, $3);
- printd(DEBUG_PARSE, "%s:%d:prompt\n", zconf_curname(), zconf_lineno());
+ printd(DEBUG_PARSE, "%s:%d:prompt\n", cur_filename, cur_lineno);
};
choice_option: logic_type prompt_stmt_opt T_EOL
{
menu_set_type($1);
- printd(DEBUG_PARSE, "%s:%d:type(%u)\n",
- zconf_curname(), zconf_lineno(), $1);
+ printd(DEBUG_PARSE, "%s:%d:type(%u)\n", cur_filename, cur_lineno, $1);
};
choice_option: T_OPTIONAL T_EOL
{
current_entry->sym->flags |= SYMBOL_OPTIONAL;
- printd(DEBUG_PARSE, "%s:%d:optional\n", zconf_curname(), zconf_lineno());
+ printd(DEBUG_PARSE, "%s:%d:optional\n", cur_filename, cur_lineno);
};
choice_option: T_DEFAULT nonconst_symbol if_expr T_EOL
{
menu_add_symbol(P_DEFAULT, $2, $3);
- printd(DEBUG_PARSE, "%s:%d:default\n",
- zconf_curname(), zconf_lineno());
+ printd(DEBUG_PARSE, "%s:%d:default\n", cur_filename, cur_lineno);
};
type:
@@ -304,7 +303,7 @@ default:
if_entry: T_IF expr T_EOL
{
- printd(DEBUG_PARSE, "%s:%d:if\n", zconf_curname(), zconf_lineno());
+ printd(DEBUG_PARSE, "%s:%d:if\n", cur_filename, cur_lineno);
menu_add_entry(NULL);
menu_add_dep($2);
$$ = menu_add_menu();
@@ -314,7 +313,7 @@ if_end: end
{
if (zconf_endtoken($1, "if")) {
menu_end_menu();
- printd(DEBUG_PARSE, "%s:%d:endif\n", zconf_curname(), zconf_lineno());
+ printd(DEBUG_PARSE, "%s:%d:endif\n", cur_filename, cur_lineno);
}
};
@@ -330,7 +329,7 @@ menu: T_MENU T_WORD_QUOTE T_EOL
{
menu_add_entry(NULL);
menu_add_prompt(P_MENU, $2, NULL);
- printd(DEBUG_PARSE, "%s:%d:menu\n", zconf_curname(), zconf_lineno());
+ printd(DEBUG_PARSE, "%s:%d:menu\n", cur_filename, cur_lineno);
};
menu_entry: menu menu_option_list
@@ -342,7 +341,7 @@ menu_end: end
{
if (zconf_endtoken($1, "menu")) {
menu_end_menu();
- printd(DEBUG_PARSE, "%s:%d:endmenu\n", zconf_curname(), zconf_lineno());
+ printd(DEBUG_PARSE, "%s:%d:endmenu\n", cur_filename, cur_lineno);
}
};
@@ -357,7 +356,7 @@ menu_option_list:
source_stmt: T_SOURCE T_WORD_QUOTE T_EOL
{
- printd(DEBUG_PARSE, "%s:%d:source %s\n", zconf_curname(), zconf_lineno(), $2);
+ printd(DEBUG_PARSE, "%s:%d:source %s\n", cur_filename, cur_lineno, $2);
zconf_nextfile($2);
free($2);
};
@@ -368,7 +367,7 @@ comment: T_COMMENT T_WORD_QUOTE T_EOL
{
menu_add_entry(NULL);
menu_add_prompt(P_COMMENT, $2, NULL);
- printd(DEBUG_PARSE, "%s:%d:comment\n", zconf_curname(), zconf_lineno());
+ printd(DEBUG_PARSE, "%s:%d:comment\n", cur_filename, cur_lineno);
};
comment_stmt: comment comment_option_list
@@ -383,7 +382,7 @@ comment_option_list:
help_start: T_HELP T_EOL
{
- printd(DEBUG_PARSE, "%s:%d:help\n", zconf_curname(), zconf_lineno());
+ printd(DEBUG_PARSE, "%s:%d:help\n", cur_filename, cur_lineno);
zconf_starthelp();
};
@@ -408,7 +407,7 @@ help: help_start T_HELPTEXT
depends: T_DEPENDS T_ON expr T_EOL
{
menu_add_dep($3);
- printd(DEBUG_PARSE, "%s:%d:depends on\n", zconf_curname(), zconf_lineno());
+ printd(DEBUG_PARSE, "%s:%d:depends on\n", cur_filename, cur_lineno);
};
/* visibility option */
@@ -455,9 +454,6 @@ symbol: nonconst_symbol
| T_WORD_QUOTE { $$ = sym_lookup($1, SYMBOL_CONST); free($1); }
;
-word_opt: /* empty */ { $$ = NULL; }
- | T_WORD
-
/* assignment statement */
assignment_stmt: T_WORD assign_op assign_val T_EOL { variable_add($1, $3, $2); free($1); free($3); }
@@ -477,8 +473,11 @@ assign_val:
void conf_parse(const char *name)
{
- struct symbol *sym;
- int i;
+ struct menu *menu;
+
+ autoconf_cmd = str_new();
+
+ str_printf(&autoconf_cmd, "\ndeps_config := \\\n");
zconf_initscan(name);
@@ -488,24 +487,52 @@ void conf_parse(const char *name)
yydebug = 1;
yyparse();
+ /*
+ * FIXME:
+ * cur_filename and cur_lineno are used even after yyparse();
+ * menu_finalize() calls menu_add_symbol(). This should be fixed.
+ */
+ cur_filename = "<none>";
+ cur_lineno = 0;
+
+ str_printf(&autoconf_cmd,
+ "\n"
+ "$(autoconfig): $(deps_config)\n"
+ "$(deps_config): ;\n");
+
+ env_write_dep(&autoconf_cmd);
+
/* Variables are expanded in the parse phase. We can free them here. */
variable_all_del();
if (yynerrs)
exit(1);
if (!modules_sym)
- modules_sym = sym_find( "n" );
+ modules_sym = &symbol_no;
if (!menu_has_prompt(&rootmenu)) {
current_entry = &rootmenu;
menu_add_prompt(P_MENU, "Main menu", NULL);
}
- menu_finalize(&rootmenu);
- for_all_symbols(i, sym) {
- if (sym_check_deps(sym))
+ menu_finalize();
+
+ menu = &rootmenu;
+ while (menu) {
+ if (menu->sym && sym_check_deps(menu->sym))
yynerrs++;
+
+ if (menu->list) {
+ menu = menu->list;
+ continue;
+ }
+
+ while (!menu->next && menu->parent)
+ menu = menu->parent;
+
+ menu = menu->next;
}
+
if (yynerrs)
exit(1);
conf_set_changed(true);
@@ -520,11 +547,11 @@ static bool zconf_endtoken(const char *tokenname,
yynerrs++;
return false;
}
- if (current_menu->file != current_file) {
+ if (strcmp(current_menu->filename, cur_filename)) {
zconf_error("'%s' in different file than '%s'",
tokenname, expected_tokenname);
fprintf(stderr, "%s:%d: location of the '%s'\n",
- current_menu->file->name, current_menu->lineno,
+ current_menu->filename, current_menu->lineno,
expected_tokenname);
yynerrs++;
return false;
@@ -536,7 +563,7 @@ static void zconfprint(const char *err, ...)
{
va_list ap;
- fprintf(stderr, "%s:%d: ", zconf_curname(), zconf_lineno());
+ fprintf(stderr, "%s:%d: ", cur_filename, cur_lineno);
va_start(ap, err);
vfprintf(stderr, err, ap);
va_end(ap);
@@ -548,7 +575,7 @@ static void zconf_error(const char *err, ...)
va_list ap;
yynerrs++;
- fprintf(stderr, "%s:%d: ", zconf_curname(), zconf_lineno());
+ fprintf(stderr, "%s:%d: ", cur_filename, cur_lineno);
va_start(ap, err);
vfprintf(stderr, err, ap);
va_end(ap);
@@ -557,7 +584,7 @@ static void zconf_error(const char *err, ...)
static void yyerror(const char *err)
{
- fprintf(stderr, "%s:%d: %s\n", zconf_curname(), zconf_lineno() + 1, err);
+ fprintf(stderr, "%s:%d: %s\n", cur_filename, cur_lineno, err);
}
static void print_quoted_string(FILE *out, const char *str)
diff --git a/scripts/kconfig/preprocess.c b/scripts/kconfig/preprocess.c
index d1f5bcff4b62..f0a4a218c4a5 100644
--- a/scripts/kconfig/preprocess.c
+++ b/scripts/kconfig/preprocess.c
@@ -9,10 +9,11 @@
#include <stdlib.h>
#include <string.h>
+#include "array_size.h"
+#include "internal.h"
#include "list.h"
#include "lkc.h"
-
-#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
+#include "preprocess.h"
static char *expand_string_with_args(const char *in, int argc, char *argv[]);
static char *expand_string(const char *in);
@@ -21,7 +22,7 @@ static void __attribute__((noreturn)) pperror(const char *format, ...)
{
va_list ap;
- fprintf(stderr, "%s:%d: ", current_file->name, yylineno);
+ fprintf(stderr, "%s:%d: ", cur_filename, yylineno);
va_start(ap, format);
vfprintf(stderr, format, ap);
va_end(ap);
@@ -87,14 +88,17 @@ static char *env_expand(const char *name)
return xstrdup(value);
}
-void env_write_dep(FILE *f, const char *autoconfig_name)
+void env_write_dep(struct gstr *s)
{
struct env *e, *tmp;
list_for_each_entry_safe(e, tmp, &env_list, node) {
- fprintf(f, "ifneq \"$(%s)\" \"%s\"\n", e->name, e->value);
- fprintf(f, "%s: FORCE\n", autoconfig_name);
- fprintf(f, "endif\n");
+ str_printf(s,
+ "\n"
+ "ifneq \"$(%s)\" \"%s\"\n"
+ "$(autoconfig): FORCE\n"
+ "endif\n",
+ e->name, e->value);
env_del(e);
}
}
@@ -119,7 +123,7 @@ static char *do_error_if(int argc, char *argv[])
static char *do_filename(int argc, char *argv[])
{
- return xstrdup(current_file->name);
+ return xstrdup(cur_filename);
}
static char *do_info(int argc, char *argv[])
@@ -181,8 +185,7 @@ static char *do_shell(int argc, char *argv[])
static char *do_warning_if(int argc, char *argv[])
{
if (!strcmp(argv[0], "y"))
- fprintf(stderr, "%s:%d: %s\n",
- current_file->name, yylineno, argv[1]);
+ fprintf(stderr, "%s:%d: %s\n", cur_filename, yylineno, argv[1]);
return xstrdup("");
}
diff --git a/scripts/kconfig/preprocess.h b/scripts/kconfig/preprocess.h
new file mode 100644
index 000000000000..a7e4a550638c
--- /dev/null
+++ b/scripts/kconfig/preprocess.h
@@ -0,0 +1,19 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+#ifndef PREPROCESS_H
+#define PREPROCESS_H
+
+enum variable_flavor {
+ VAR_SIMPLE,
+ VAR_RECURSIVE,
+ VAR_APPEND,
+};
+
+struct gstr;
+void env_write_dep(struct gstr *gs);
+void variable_add(const char *name, const char *value,
+ enum variable_flavor flavor);
+void variable_all_del(void);
+char *expand_dollar(const char **str);
+char *expand_one_token(const char **str);
+
+#endif /* PREPROCESS_H */
diff --git a/scripts/kconfig/qconf.cc b/scripts/kconfig/qconf.cc
index 620a3527c767..c6c42c0f4e5d 100644
--- a/scripts/kconfig/qconf.cc
+++ b/scripts/kconfig/qconf.cc
@@ -1058,7 +1058,7 @@ void ConfigInfoView::menuInfo(void)
stream << "<br><br>";
}
- stream << "defined at " << _menu->file->name << ":"
+ stream << "defined at " << _menu->filename << ":"
<< _menu->lineno << "<br><br>";
}
}
diff --git a/scripts/kconfig/symbol.c b/scripts/kconfig/symbol.c
index 0572330bf8a7..81fe1884ef8a 100644
--- a/scripts/kconfig/symbol.c
+++ b/scripts/kconfig/symbol.c
@@ -9,34 +9,33 @@
#include <string.h>
#include <regex.h>
+#include "internal.h"
#include "lkc.h"
struct symbol symbol_yes = {
.name = "y",
.curr = { "y", yes },
+ .menus = LIST_HEAD_INIT(symbol_yes.menus),
.flags = SYMBOL_CONST|SYMBOL_VALID,
};
struct symbol symbol_mod = {
.name = "m",
.curr = { "m", mod },
+ .menus = LIST_HEAD_INIT(symbol_mod.menus),
.flags = SYMBOL_CONST|SYMBOL_VALID,
};
struct symbol symbol_no = {
.name = "n",
.curr = { "n", no },
+ .menus = LIST_HEAD_INIT(symbol_no.menus),
.flags = SYMBOL_CONST|SYMBOL_VALID,
};
-static struct symbol symbol_empty = {
- .name = "",
- .curr = { "", no },
- .flags = SYMBOL_VALID,
-};
-
struct symbol *modules_sym;
static tristate modules_val;
+static int sym_warnings;
enum symbol_type sym_get_type(struct symbol *sym)
{
@@ -122,9 +121,9 @@ static long long sym_get_range_val(struct symbol *sym, int base)
static void sym_validate_range(struct symbol *sym)
{
struct property *prop;
+ struct symbol *range_sym;
int base;
long long val, val2;
- char str[64];
switch (sym->type) {
case S_INT:
@@ -140,17 +139,15 @@ static void sym_validate_range(struct symbol *sym)
if (!prop)
return;
val = strtoll(sym->curr.val, NULL, base);
- val2 = sym_get_range_val(prop->expr->left.sym, base);
+ range_sym = prop->expr->left.sym;
+ val2 = sym_get_range_val(range_sym, base);
if (val >= val2) {
- val2 = sym_get_range_val(prop->expr->right.sym, base);
+ range_sym = prop->expr->right.sym;
+ val2 = sym_get_range_val(range_sym, base);
if (val <= val2)
return;
}
- if (sym->type == S_INT)
- sprintf(str, "%lld", val2);
- else
- sprintf(str, "0x%llx", val2);
- sym->curr.val = xstrdup(str);
+ sym->curr.val = range_sym->curr.val;
}
static void sym_set_changed(struct symbol *sym)
@@ -167,9 +164,8 @@ static void sym_set_changed(struct symbol *sym)
static void sym_set_all_changed(void)
{
struct symbol *sym;
- int i;
- for_all_symbols(i, sym)
+ for_all_symbols(sym)
sym_set_changed(sym);
}
@@ -319,6 +315,14 @@ static void sym_warn_unmet_dep(struct symbol *sym)
" Selected by [m]:\n");
fputs(str_get(&gs), stderr);
+ sym_warnings++;
+}
+
+bool sym_dep_errors(void)
+{
+ if (sym_warnings)
+ return getenv("KCONFIG_WERROR");
+ return false;
}
void sym_calc_value(struct symbol *sym)
@@ -344,15 +348,21 @@ void sym_calc_value(struct symbol *sym)
oldval = sym->curr;
+ newval.tri = no;
+
switch (sym->type) {
case S_INT:
+ newval.val = "0";
+ break;
case S_HEX:
+ newval.val = "0x0";
+ break;
case S_STRING:
- newval = symbol_empty.curr;
+ newval.val = "";
break;
case S_BOOLEAN:
case S_TRISTATE:
- newval = symbol_no.curr;
+ newval.val = "n";
break;
default:
sym->curr.val = sym->name;
@@ -468,9 +478,8 @@ void sym_calc_value(struct symbol *sym)
void sym_clear_all_valid(void)
{
struct symbol *sym;
- int i;
- for_all_symbols(i, sym)
+ for_all_symbols(sym)
sym->flags &= ~SYMBOL_VALID;
conf_set_changed(true);
sym_calc_value(modules_sym);
@@ -699,13 +708,12 @@ const char *sym_get_string_default(struct symbol *sym)
{
struct property *prop;
struct symbol *ds;
- const char *str;
+ const char *str = "";
tristate val;
sym_calc_visibility(sym);
sym_calc_value(modules_sym);
val = symbol_no.curr.tri;
- str = symbol_empty.curr.val;
/* If symbol has a default value look it up */
prop = sym_get_default_prop(sym);
@@ -755,14 +763,17 @@ const char *sym_get_string_default(struct symbol *sym)
case yes: return "y";
}
case S_INT:
+ if (!str[0])
+ str = "0";
+ break;
case S_HEX:
- return str;
- case S_STRING:
- return str;
- case S_UNKNOWN:
+ if (!str[0])
+ str = "0x0";
+ break;
+ default:
break;
}
- return "";
+ return str;
}
const char *sym_get_string_value(struct symbol *sym)
@@ -794,14 +805,7 @@ bool sym_is_changeable(struct symbol *sym)
return sym->visible > sym->rev_dep.tri;
}
-static unsigned strhash(const char *s)
-{
- /* fnv32 hash */
- unsigned hash = 2166136261U;
- for (; *s; s++)
- hash = (hash ^ *s) * 0x01000193;
- return hash;
-}
+HASHTABLE_DEFINE(sym_hashtable, SYMBOL_HASHSIZE);
struct symbol *sym_lookup(const char *name, int flags)
{
@@ -817,9 +821,9 @@ struct symbol *sym_lookup(const char *name, int flags)
case 'n': return &symbol_no;
}
}
- hash = strhash(name) % SYMBOL_HASHSIZE;
+ hash = strhash(name);
- for (symbol = symbol_hash[hash]; symbol; symbol = symbol->next) {
+ hash_for_each_possible(sym_hashtable, symbol, node, hash) {
if (symbol->name &&
!strcmp(symbol->name, name) &&
(flags ? symbol->flags & flags
@@ -837,9 +841,9 @@ struct symbol *sym_lookup(const char *name, int flags)
symbol->name = new_name;
symbol->type = S_UNKNOWN;
symbol->flags = flags;
+ INIT_LIST_HEAD(&symbol->menus);
- symbol->next = symbol_hash[hash];
- symbol_hash[hash] = symbol;
+ hash_add(sym_hashtable, &symbol->node, hash);
return symbol;
}
@@ -859,9 +863,9 @@ struct symbol *sym_find(const char *name)
case 'n': return &symbol_no;
}
}
- hash = strhash(name) % SYMBOL_HASHSIZE;
+ hash = strhash(name);
- for (symbol = symbol_hash[hash]; symbol; symbol = symbol->next) {
+ hash_for_each_possible(sym_hashtable, symbol, node, hash) {
if (symbol->name &&
!strcmp(symbol->name, name) &&
!(symbol->flags & SYMBOL_CONST))
@@ -921,7 +925,7 @@ struct symbol **sym_re_search(const char *pattern)
if (regcomp(&re, pattern, REG_EXTENDED|REG_ICASE))
return NULL;
- for_all_symbols(i, sym) {
+ for_all_symbols(sym) {
if (sym->flags & SYMBOL_CONST || !sym->name)
continue;
if (regexec(&re, sym->name, 1, match, 0))
@@ -1032,42 +1036,42 @@ static void sym_check_print_recursive(struct symbol *last_sym)
}
if (stack->sym == last_sym)
fprintf(stderr, "%s:%d:error: recursive dependency detected!\n",
- prop->file->name, prop->lineno);
+ prop->filename, prop->lineno);
if (sym_is_choice(sym)) {
fprintf(stderr, "%s:%d:\tchoice %s contains symbol %s\n",
- menu->file->name, menu->lineno,
+ menu->filename, menu->lineno,
sym->name ? sym->name : "<choice>",
next_sym->name ? next_sym->name : "<choice>");
} else if (sym_is_choice_value(sym)) {
fprintf(stderr, "%s:%d:\tsymbol %s is part of choice %s\n",
- menu->file->name, menu->lineno,
+ menu->filename, menu->lineno,
sym->name ? sym->name : "<choice>",
next_sym->name ? next_sym->name : "<choice>");
} else if (stack->expr == &sym->dir_dep.expr) {
fprintf(stderr, "%s:%d:\tsymbol %s depends on %s\n",
- prop->file->name, prop->lineno,
+ prop->filename, prop->lineno,
sym->name ? sym->name : "<choice>",
next_sym->name ? next_sym->name : "<choice>");
} else if (stack->expr == &sym->rev_dep.expr) {
fprintf(stderr, "%s:%d:\tsymbol %s is selected by %s\n",
- prop->file->name, prop->lineno,
+ prop->filename, prop->lineno,
sym->name ? sym->name : "<choice>",
next_sym->name ? next_sym->name : "<choice>");
} else if (stack->expr == &sym->implied.expr) {
fprintf(stderr, "%s:%d:\tsymbol %s is implied by %s\n",
- prop->file->name, prop->lineno,
+ prop->filename, prop->lineno,
sym->name ? sym->name : "<choice>",
next_sym->name ? next_sym->name : "<choice>");
} else if (stack->expr) {
fprintf(stderr, "%s:%d:\tsymbol %s %s value contains %s\n",
- prop->file->name, prop->lineno,
+ prop->filename, prop->lineno,
sym->name ? sym->name : "<choice>",
prop_get_type_name(prop->type),
next_sym->name ? next_sym->name : "<choice>");
} else {
fprintf(stderr, "%s:%d:\tsymbol %s %s is visible depending on %s\n",
- prop->file->name, prop->lineno,
+ prop->filename, prop->lineno,
sym->name ? sym->name : "<choice>",
prop_get_type_name(prop->type),
next_sym->name ? next_sym->name : "<choice>");
diff --git a/scripts/kconfig/tests/choice_randomize/Kconfig b/scripts/kconfig/tests/choice_randomize/Kconfig
new file mode 100644
index 000000000000..93a1699ce3cb
--- /dev/null
+++ b/scripts/kconfig/tests/choice_randomize/Kconfig
@@ -0,0 +1,22 @@
+choice
+ prompt "choose A or B"
+
+config A
+ bool "A"
+
+config B
+ bool "B"
+
+endchoice
+
+choice
+ prompt "choose X or Y"
+ depends on B
+
+config X
+ bool "X"
+
+config Y
+ bool "Y"
+
+endchoice
diff --git a/scripts/kconfig/tests/choice_randomize/__init__.py b/scripts/kconfig/tests/choice_randomize/__init__.py
new file mode 100644
index 000000000000..d380045be79c
--- /dev/null
+++ b/scripts/kconfig/tests/choice_randomize/__init__.py
@@ -0,0 +1,34 @@
+# SPDX-License-Identifier: GPL-2.0-only
+"""
+Randomize all dependent choices
+
+This is a somewhat tricky case for randconfig; the visibility of one choice is
+determined by a member of another choice. Randconfig should be able to generate
+all possible patterns.
+"""
+
+
+def test(conf):
+
+ expected0 = False
+ expected1 = False
+ expected2 = False
+
+ for i in range(100):
+ assert conf.randconfig(seed=i) == 0
+
+ if conf.config_matches('expected_config0'):
+ expected0 = True
+ elif conf.config_matches('expected_config1'):
+ expected1 = True
+ elif conf.config_matches('expected_config2'):
+ expected2 = True
+ else:
+ assert False
+
+ if expected0 and expected1 and expected2:
+ break
+
+ assert expected0
+ assert expected1
+ assert expected2
diff --git a/scripts/kconfig/tests/choice_randomize/expected_config0 b/scripts/kconfig/tests/choice_randomize/expected_config0
new file mode 100644
index 000000000000..f69227323759
--- /dev/null
+++ b/scripts/kconfig/tests/choice_randomize/expected_config0
@@ -0,0 +1,6 @@
+#
+# Automatically generated file; DO NOT EDIT.
+# Main menu
+#
+CONFIG_A=y
+# CONFIG_B is not set
diff --git a/scripts/kconfig/tests/choice_randomize/expected_config1 b/scripts/kconfig/tests/choice_randomize/expected_config1
new file mode 100644
index 000000000000..bf83784c9b2a
--- /dev/null
+++ b/scripts/kconfig/tests/choice_randomize/expected_config1
@@ -0,0 +1,8 @@
+#
+# Automatically generated file; DO NOT EDIT.
+# Main menu
+#
+# CONFIG_A is not set
+CONFIG_B=y
+CONFIG_X=y
+# CONFIG_Y is not set
diff --git a/scripts/kconfig/tests/choice_randomize/expected_config2 b/scripts/kconfig/tests/choice_randomize/expected_config2
new file mode 100644
index 000000000000..38f93a8f37bd
--- /dev/null
+++ b/scripts/kconfig/tests/choice_randomize/expected_config2
@@ -0,0 +1,8 @@
+#
+# Automatically generated file; DO NOT EDIT.
+# Main menu
+#
+# CONFIG_A is not set
+CONFIG_B=y
+# CONFIG_X is not set
+CONFIG_Y=y
diff --git a/scripts/kconfig/tests/choice_randomize2/Kconfig b/scripts/kconfig/tests/choice_randomize2/Kconfig
new file mode 100644
index 000000000000..530cf2ef7f47
--- /dev/null
+++ b/scripts/kconfig/tests/choice_randomize2/Kconfig
@@ -0,0 +1,32 @@
+choice
+ prompt "This is always invisible"
+ depends on n
+
+config DUMMY
+ bool "DUMMY"
+
+endchoice
+
+choice
+ prompt "Choose A or B"
+
+config A
+ bool "A"
+
+config B
+ bool "B"
+
+endchoice
+
+config FOO
+ bool "FOO"
+ depends on A
+
+choice
+ prompt "Choose X"
+ depends on FOO
+
+config X
+ bool "X"
+
+endchoice
diff --git a/scripts/kconfig/tests/choice_randomize2/__init__.py b/scripts/kconfig/tests/choice_randomize2/__init__.py
new file mode 100644
index 000000000000..2066757b80b9
--- /dev/null
+++ b/scripts/kconfig/tests/choice_randomize2/__init__.py
@@ -0,0 +1,18 @@
+# SPDX-License-Identifier: GPL-2.0-only
+"""
+Randomize choices with correct dependencies
+
+When shuffling a choice may potentially disrupt certain dependencies, symbol
+values must be recalculated.
+
+Related Linux commits:
+ - c8fb7d7e48d11520ad24808cfce7afb7b9c9f798
+"""
+
+
+def test(conf):
+ for i in range(20):
+ assert conf.randconfig(seed=i) == 0
+ assert (conf.config_matches('expected_config0') or
+ conf.config_matches('expected_config1') or
+ conf.config_matches('expected_config2'))
diff --git a/scripts/kconfig/tests/choice_randomize2/expected_config0 b/scripts/kconfig/tests/choice_randomize2/expected_config0
new file mode 100644
index 000000000000..5c9e1c172c15
--- /dev/null
+++ b/scripts/kconfig/tests/choice_randomize2/expected_config0
@@ -0,0 +1,8 @@
+#
+# Automatically generated file; DO NOT EDIT.
+# Main menu
+#
+CONFIG_A=y
+# CONFIG_B is not set
+CONFIG_FOO=y
+CONFIG_X=y
diff --git a/scripts/kconfig/tests/choice_randomize2/expected_config1 b/scripts/kconfig/tests/choice_randomize2/expected_config1
new file mode 100644
index 000000000000..5b975d91bef1
--- /dev/null
+++ b/scripts/kconfig/tests/choice_randomize2/expected_config1
@@ -0,0 +1,7 @@
+#
+# Automatically generated file; DO NOT EDIT.
+# Main menu
+#
+CONFIG_A=y
+# CONFIG_B is not set
+# CONFIG_FOO is not set
diff --git a/scripts/kconfig/tests/choice_randomize2/expected_config2 b/scripts/kconfig/tests/choice_randomize2/expected_config2
new file mode 100644
index 000000000000..5a5ebb90d1d7
--- /dev/null
+++ b/scripts/kconfig/tests/choice_randomize2/expected_config2
@@ -0,0 +1,6 @@
+#
+# Automatically generated file; DO NOT EDIT.
+# Main menu
+#
+# CONFIG_A is not set
+CONFIG_B=y
diff --git a/scripts/kconfig/tests/conftest.py b/scripts/kconfig/tests/conftest.py
index af8774a5697c..2a2a7e2da060 100644
--- a/scripts/kconfig/tests/conftest.py
+++ b/scripts/kconfig/tests/conftest.py
@@ -154,12 +154,10 @@ class Conf:
defconfig_path = os.path.join(self._test_dir, defconfig)
return self._run_conf('--defconfig={}'.format(defconfig_path))
- def _allconfig(self, mode, all_config):
+ def _allconfig(self, mode, all_config, extra_env={}):
if all_config:
all_config_path = os.path.join(self._test_dir, all_config)
- extra_env = {'KCONFIG_ALLCONFIG': all_config_path}
- else:
- extra_env = {}
+ extra_env['KCONFIG_ALLCONFIG'] = all_config_path
return self._run_conf('--{}config'.format(mode), extra_env=extra_env)
@@ -195,13 +193,19 @@ class Conf:
"""
return self._allconfig('alldef', all_config)
- def randconfig(self, all_config=None):
+ def randconfig(self, all_config=None, seed=None):
"""Run randconfig.
all_config: fragment config file for KCONFIG_ALLCONFIG (optional)
+ seed: the seed for randconfig (optional)
returncode: exit status of the Kconfig executable
"""
- return self._allconfig('rand', all_config)
+ if seed is not None:
+ extra_env = {'KCONFIG_SEED': hex(seed)}
+ else:
+ extra_env = {}
+
+ return self._allconfig('rand', all_config, extra_env=extra_env)
def savedefconfig(self, dot_config):
"""Run savedefconfig.
diff --git a/scripts/kconfig/tests/err_recursive_dep/expected_stderr b/scripts/kconfig/tests/err_recursive_dep/expected_stderr
index c9f4abf9a791..05d4ced70320 100644
--- a/scripts/kconfig/tests/err_recursive_dep/expected_stderr
+++ b/scripts/kconfig/tests/err_recursive_dep/expected_stderr
@@ -1,10 +1,10 @@
-Kconfig:11:error: recursive dependency detected!
-Kconfig:11: symbol B is selected by B
+Kconfig:5:error: recursive dependency detected!
+Kconfig:5: symbol A depends on A
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
+Kconfig:11:error: recursive dependency detected!
+Kconfig:11: symbol B is selected by B
For a resolution refer to Documentation/kbuild/kconfig-language.rst
subsection "Kconfig recursive dependency limitations"
@@ -14,9 +14,9 @@ Kconfig:21: symbol C2 depends on C1
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:error: recursive dependency detected!
Kconfig:27: symbol D1 depends on D2
+Kconfig:32: symbol D2 is selected by D1
For a resolution refer to Documentation/kbuild/kconfig-language.rst
subsection "Kconfig recursive dependency limitations"
@@ -26,13 +26,13 @@ Kconfig:42: symbol E2 is implied by E1
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
+Kconfig:49:error: recursive dependency detected!
+Kconfig:49: symbol F1 default value contains F2
+Kconfig:51: symbol F2 depends on F1
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
+Kconfig:60:error: recursive dependency detected!
+Kconfig:60: symbol G depends on G
For a resolution refer to Documentation/kbuild/kconfig-language.rst
subsection "Kconfig recursive dependency limitations"
diff --git a/scripts/kconfig/util.c b/scripts/kconfig/util.c
index b78f114ad48c..439c131b424e 100644
--- a/scripts/kconfig/util.c
+++ b/scripts/kconfig/util.c
@@ -7,25 +7,50 @@
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
+
+#include "hashtable.h"
#include "lkc.h"
+unsigned int strhash(const char *s)
+{
+ /* fnv32 hash */
+ unsigned int hash = 2166136261U;
+
+ for (; *s; s++)
+ hash = (hash ^ *s) * 0x01000193;
+ return hash;
+}
+
+/* hash table of all parsed Kconfig files */
+static HASHTABLE_DEFINE(file_hashtable, 1U << 11);
+
+struct file {
+ struct hlist_node node;
+ char name[];
+};
+
/* file already present in list? If not add it */
-struct file *file_lookup(const char *name)
+const char *file_lookup(const char *name)
{
struct file *file;
+ size_t len;
+ int hash = strhash(name);
- for (file = file_list; file; file = file->next) {
- if (!strcmp(name, file->name)) {
- return file;
- }
- }
+ hash_for_each_possible(file_hashtable, file, node, hash)
+ if (!strcmp(name, file->name))
+ return file->name;
- file = xmalloc(sizeof(*file));
+ len = strlen(name);
+ file = xmalloc(sizeof(*file) + len + 1);
memset(file, 0, sizeof(*file));
- file->name = xstrdup(name);
- file->next = file_list;
- file_list = file;
- return file;
+ memcpy(file->name, name, len);
+ file->name[len] = '\0';
+
+ hash_add(file_hashtable, &file->node, hash);
+
+ str_printf(&autoconf_cmd, "\t%s \\\n", name);
+
+ return file->name;
}
/* Allocate initial growable string */
@@ -42,8 +67,7 @@ struct gstr str_new(void)
/* Free storage for growable string */
void str_free(struct gstr *gs)
{
- if (gs->s)
- free(gs->s);
+ free(gs->s);
gs->s = NULL;
gs->len = 0;
}
diff --git a/scripts/kernel-doc b/scripts/kernel-doc
index 6e199a745ccb..cb1be22afc65 100755
--- a/scripts/kernel-doc
+++ b/scripts/kernel-doc
@@ -1,5 +1,6 @@
#!/usr/bin/env perl
# SPDX-License-Identifier: GPL-2.0
+# vim: softtabstop=4
use warnings;
use strict;
@@ -23,7 +24,7 @@ kernel-doc - Print formatted kernel documentation to stdout
=head1 SYNOPSIS
- kernel-doc [-h] [-v] [-Werror] [-Wall] [-Wreturn] [-Wshort-description] [-Wcontents-before-sections]
+ kernel-doc [-h] [-v] [-Werror] [-Wall] [-Wreturn] [-Wshort-desc[ription]] [-Wcontents-before-sections]
[ -man |
-rst [-sphinx-version VERSION] [-enable-lineno] |
-none
@@ -64,7 +65,7 @@ my $type_constant = '\b``([^\`]+)``\b';
my $type_constant2 = '\%([-_\w]+)';
my $type_func = '(\w+)\(\)';
my $type_param = '\@(\w*((\.\w+)|(->\w+))*(\.\.\.)?)';
-my $type_param_ref = '([\!~]?)\@(\w*((\.\w+)|(->\w+))*(\.\.\.)?)';
+my $type_param_ref = '([\!~\*]?)\@(\w*((\.\w+)|(->\w+))*(\.\.\.)?)';
my $type_fp_param = '\@(\w+)\(\)'; # Special RST handling for func ptr params
my $type_fp_param2 = '\@(\w+->\S+)\(\)'; # Special RST handling for structs with func ptr params
my $type_env = '(\$\w+)';
@@ -81,49 +82,51 @@ my $type_member_func = $type_member . '\(\)';
# these are pretty rough
my @highlights_man = (
- [$type_constant, "\$1"],
- [$type_constant2, "\$1"],
- [$type_func, "\\\\fB\$1\\\\fP"],
- [$type_enum, "\\\\fI\$1\\\\fP"],
- [$type_struct, "\\\\fI\$1\\\\fP"],
- [$type_typedef, "\\\\fI\$1\\\\fP"],
- [$type_union, "\\\\fI\$1\\\\fP"],
- [$type_param, "\\\\fI\$1\\\\fP"],
- [$type_param_ref, "\\\\fI\$1\$2\\\\fP"],
- [$type_member, "\\\\fI\$1\$2\$3\\\\fP"],
- [$type_fallback, "\\\\fI\$1\\\\fP"]
- );
+ [$type_constant, "\$1"],
+ [$type_constant2, "\$1"],
+ [$type_func, "\\\\fB\$1\\\\fP"],
+ [$type_enum, "\\\\fI\$1\\\\fP"],
+ [$type_struct, "\\\\fI\$1\\\\fP"],
+ [$type_typedef, "\\\\fI\$1\\\\fP"],
+ [$type_union, "\\\\fI\$1\\\\fP"],
+ [$type_param, "\\\\fI\$1\\\\fP"],
+ [$type_param_ref, "\\\\fI\$1\$2\\\\fP"],
+ [$type_member, "\\\\fI\$1\$2\$3\\\\fP"],
+ [$type_fallback, "\\\\fI\$1\\\\fP"]
+ );
my $blankline_man = "";
# rst-mode
my @highlights_rst = (
- [$type_constant, "``\$1``"],
- [$type_constant2, "``\$1``"],
- # Note: need to escape () to avoid func matching later
- [$type_member_func, "\\:c\\:type\\:`\$1\$2\$3\\\\(\\\\) <\$1>`"],
- [$type_member, "\\:c\\:type\\:`\$1\$2\$3 <\$1>`"],
- [$type_fp_param, "**\$1\\\\(\\\\)**"],
- [$type_fp_param2, "**\$1\\\\(\\\\)**"],
- [$type_func, "\$1()"],
- [$type_enum, "\\:c\\:type\\:`\$1 <\$2>`"],
- [$type_struct, "\\:c\\:type\\:`\$1 <\$2>`"],
- [$type_typedef, "\\:c\\:type\\:`\$1 <\$2>`"],
- [$type_union, "\\:c\\:type\\:`\$1 <\$2>`"],
- # in rst this can refer to any type
- [$type_fallback, "\\:c\\:type\\:`\$1`"],
- [$type_param_ref, "**\$1\$2**"]
- );
+ [$type_constant, "``\$1``"],
+ [$type_constant2, "``\$1``"],
+
+ # Note: need to escape () to avoid func matching later
+ [$type_member_func, "\\:c\\:type\\:`\$1\$2\$3\\\\(\\\\) <\$1>`"],
+ [$type_member, "\\:c\\:type\\:`\$1\$2\$3 <\$1>`"],
+ [$type_fp_param, "**\$1\\\\(\\\\)**"],
+ [$type_fp_param2, "**\$1\\\\(\\\\)**"],
+ [$type_func, "\$1()"],
+ [$type_enum, "\\:c\\:type\\:`\$1 <\$2>`"],
+ [$type_struct, "\\:c\\:type\\:`\$1 <\$2>`"],
+ [$type_typedef, "\\:c\\:type\\:`\$1 <\$2>`"],
+ [$type_union, "\\:c\\:type\\:`\$1 <\$2>`"],
+
+ # in rst this can refer to any type
+ [$type_fallback, "\\:c\\:type\\:`\$1`"],
+ [$type_param_ref, "**\$1\$2**"]
+ );
my $blankline_rst = "\n";
# read arguments
if ($#ARGV == -1) {
- pod2usage(
- -message => "No arguments!\n",
- -exitval => 1,
- -verbose => 99,
- -sections => 'SYNOPSIS',
- -output => \*STDERR,
- );
+ pod2usage(
+ -message => "No arguments!\n",
+ -exitval => 1,
+ -verbose => 99,
+ -sections => 'SYNOPSIS',
+ -output => \*STDERR,
+ );
}
my $kernelversion;
@@ -164,9 +167,9 @@ if (defined($ENV{'KBUILD_BUILD_TIMESTAMP'}) &&
}
my $man_date = ('January', 'February', 'March', 'April', 'May', 'June',
- 'July', 'August', 'September', 'October',
- 'November', 'December')[$build_time[4]] .
- " " . ($build_time[5]+1900);
+ 'July', 'August', 'September', 'October',
+ 'November', 'December')[$build_time[4]] .
+ " " . ($build_time[5]+1900);
# Essentially these are globals.
# They probably want to be tidied up, made more localised or something.
@@ -179,22 +182,22 @@ my ($type, $declaration_name, $return_type);
my ($newsection, $newcontents, $prototype, $brcount, %source_map);
if (defined($ENV{'KBUILD_VERBOSE'}) && $ENV{'KBUILD_VERBOSE'} =~ '1') {
- $verbose = 1;
+ $verbose = 1;
}
if (defined($ENV{'KCFLAGS'})) {
- my $kcflags = "$ENV{'KCFLAGS'}";
+ my $kcflags = "$ENV{'KCFLAGS'}";
- if ($kcflags =~ /Werror/) {
- $Werror = 1;
- }
+ if ($kcflags =~ /(\s|^)-Werror(\s|$)/) {
+ $Werror = 1;
+ }
}
# reading this variable is for backwards compat just in case
# someone was calling it with the variable from outside the
# kernel's build system
if (defined($ENV{'KDOC_WERROR'})) {
- $Werror = "$ENV{'KDOC_WERROR'}";
+ $Werror = "$ENV{'KDOC_WERROR'}";
}
# other environment variables are converted to command-line
# arguments in cmd_checkdoc in the build system
@@ -295,90 +298,90 @@ while ($ARGV[0] =~ m/^--?(.*)/) {
my $cmd = $1;
shift @ARGV;
if ($cmd eq "man") {
- $output_mode = "man";
- @highlights = @highlights_man;
- $blankline = $blankline_man;
+ $output_mode = "man";
+ @highlights = @highlights_man;
+ $blankline = $blankline_man;
} elsif ($cmd eq "rst") {
- $output_mode = "rst";
- @highlights = @highlights_rst;
- $blankline = $blankline_rst;
+ $output_mode = "rst";
+ @highlights = @highlights_rst;
+ $blankline = $blankline_rst;
} elsif ($cmd eq "none") {
- $output_mode = "none";
+ $output_mode = "none";
} elsif ($cmd eq "module") { # not needed for XML, inherits from calling document
- $modulename = shift @ARGV;
+ $modulename = shift @ARGV;
} elsif ($cmd eq "function") { # to only output specific functions
- $output_selection = OUTPUT_INCLUDE;
- $function = shift @ARGV;
- $function_table{$function} = 1;
+ $output_selection = OUTPUT_INCLUDE;
+ $function = shift @ARGV;
+ $function_table{$function} = 1;
} elsif ($cmd eq "nosymbol") { # Exclude specific symbols
- my $symbol = shift @ARGV;
- $nosymbol_table{$symbol} = 1;
+ my $symbol = shift @ARGV;
+ $nosymbol_table{$symbol} = 1;
} elsif ($cmd eq "export") { # only exported symbols
- $output_selection = OUTPUT_EXPORTED;
- %function_table = ();
+ $output_selection = OUTPUT_EXPORTED;
+ %function_table = ();
} elsif ($cmd eq "internal") { # only non-exported symbols
- $output_selection = OUTPUT_INTERNAL;
- %function_table = ();
+ $output_selection = OUTPUT_INTERNAL;
+ %function_table = ();
} elsif ($cmd eq "export-file") {
- my $file = shift @ARGV;
- push(@export_file_list, $file);
+ my $file = shift @ARGV;
+ push(@export_file_list, $file);
} elsif ($cmd eq "v") {
- $verbose = 1;
+ $verbose = 1;
} elsif ($cmd eq "Werror") {
- $Werror = 1;
+ $Werror = 1;
} elsif ($cmd eq "Wreturn") {
- $Wreturn = 1;
- } elsif ($cmd eq "Wshort-desc") {
- $Wshort_desc = 1;
+ $Wreturn = 1;
+ } elsif ($cmd eq "Wshort-desc" or $cmd eq "Wshort-description") {
+ $Wshort_desc = 1;
} elsif ($cmd eq "Wcontents-before-sections") {
- $Wcontents_before_sections = 1;
+ $Wcontents_before_sections = 1;
} elsif ($cmd eq "Wall") {
$Wreturn = 1;
$Wshort_desc = 1;
$Wcontents_before_sections = 1;
} elsif (($cmd eq "h") || ($cmd eq "help")) {
- pod2usage(-exitval => 0, -verbose => 2);
+ pod2usage(-exitval => 0, -verbose => 2);
} elsif ($cmd eq 'no-doc-sections') {
- $no_doc_sections = 1;
+ $no_doc_sections = 1;
} elsif ($cmd eq 'enable-lineno') {
- $enable_lineno = 1;
+ $enable_lineno = 1;
} elsif ($cmd eq 'show-not-found') {
- $show_not_found = 1; # A no-op but don't fail
+ $show_not_found = 1; # A no-op but don't fail
} elsif ($cmd eq "sphinx-version") {
- my $ver_string = shift @ARGV;
- if ($ver_string =~ m/^(\d+)(\.\d+)?(\.\d+)?/) {
- $sphinx_major = $1;
- if (defined($2)) {
- $sphinx_minor = substr($2,1);
- } else {
- $sphinx_minor = 0;
- }
- if (defined($3)) {
- $sphinx_patch = substr($3,1)
- } else {
- $sphinx_patch = 0;
- }
- } else {
- die "Sphinx version should either major.minor or major.minor.patch format\n";
- }
+ my $ver_string = shift @ARGV;
+ if ($ver_string =~ m/^(\d+)(\.\d+)?(\.\d+)?/) {
+ $sphinx_major = $1;
+ if (defined($2)) {
+ $sphinx_minor = substr($2,1);
+ } else {
+ $sphinx_minor = 0;
+ }
+ if (defined($3)) {
+ $sphinx_patch = substr($3,1)
+ } else {
+ $sphinx_patch = 0;
+ }
+ } else {
+ die "Sphinx version should either major.minor or major.minor.patch format\n";
+ }
} else {
- # Unknown argument
- pod2usage(
- -message => "Argument unknown!\n",
- -exitval => 1,
- -verbose => 99,
- -sections => 'SYNOPSIS',
- -output => \*STDERR,
- );
+ # Unknown argument
+ pod2usage(
+ -message => "Argument unknown!\n",
+ -exitval => 1,
+ -verbose => 99,
+ -sections => 'SYNOPSIS',
+ -output => \*STDERR,
+ );
}
if ($#ARGV < 0){
- pod2usage(
- -message => "FILE argument missing\n",
- -exitval => 1,
- -verbose => 99,
- -sections => 'SYNOPSIS',
- -output => \*STDERR,
- );
+ pod2usage(
+ -message => "FILE argument missing\n",
+ -exitval => 1,
+ -verbose => 99,
+ -sections => 'SYNOPSIS',
+ -output => \*STDERR,
+ );
}
}
@@ -388,45 +391,45 @@ while ($ARGV[0] =~ m/^--?(.*)/) {
# version in order to produce the right tags.
sub findprog($)
{
- foreach(split(/:/, $ENV{PATH})) {
- return "$_/$_[0]" if(-x "$_/$_[0]");
- }
+ foreach(split(/:/, $ENV{PATH})) {
+ return "$_/$_[0]" if(-x "$_/$_[0]");
+ }
}
sub get_sphinx_version()
{
- my $ver;
-
- my $cmd = "sphinx-build";
- if (!findprog($cmd)) {
- my $cmd = "sphinx-build3";
- if (!findprog($cmd)) {
- $sphinx_major = 1;
- $sphinx_minor = 2;
- $sphinx_patch = 0;
- printf STDERR "Warning: Sphinx version not found. Using default (Sphinx version %d.%d.%d)\n",
- $sphinx_major, $sphinx_minor, $sphinx_patch;
- return;
- }
- }
-
- open IN, "$cmd --version 2>&1 |";
- while (<IN>) {
- if (m/^\s*sphinx-build\s+([\d]+)\.([\d\.]+)(\+\/[\da-f]+)?$/) {
- $sphinx_major = $1;
- $sphinx_minor = $2;
- $sphinx_patch = $3;
- last;
- }
- # Sphinx 1.2.x uses a different format
- if (m/^\s*Sphinx.*\s+([\d]+)\.([\d\.]+)$/) {
- $sphinx_major = $1;
- $sphinx_minor = $2;
- $sphinx_patch = $3;
- last;
- }
- }
- close IN;
+ my $ver;
+
+ my $cmd = "sphinx-build";
+ if (!findprog($cmd)) {
+ my $cmd = "sphinx-build3";
+ if (!findprog($cmd)) {
+ $sphinx_major = 1;
+ $sphinx_minor = 2;
+ $sphinx_patch = 0;
+ printf STDERR "Warning: Sphinx version not found. Using default (Sphinx version %d.%d.%d)\n",
+ $sphinx_major, $sphinx_minor, $sphinx_patch;
+ return;
+ }
+ }
+
+ open IN, "$cmd --version 2>&1 |";
+ while (<IN>) {
+ if (m/^\s*sphinx-build\s+([\d]+)\.([\d\.]+)(\+\/[\da-f]+)?$/) {
+ $sphinx_major = $1;
+ $sphinx_minor = $2;
+ $sphinx_patch = $3;
+ last;
+ }
+ # Sphinx 1.2.x uses a different format
+ if (m/^\s*Sphinx.*\s+([\d]+)\.([\d\.]+)$/) {
+ $sphinx_major = $1;
+ $sphinx_minor = $2;
+ $sphinx_patch = $3;
+ last;
+ }
+ }
+ close IN;
}
# get kernel version from env
@@ -434,7 +437,7 @@ sub get_kernel_version() {
my $version = 'unknown kernel version';
if (defined($ENV{'KERNELVERSION'})) {
- $version = $ENV{'KERNELVERSION'};
+ $version = $ENV{'KERNELVERSION'};
}
return $version;
}
@@ -462,30 +465,30 @@ sub dump_section {
my $contents = join "\n", @_;
if ($name =~ m/$type_param/) {
- $name = $1;
- $parameterdescs{$name} = $contents;
- $sectcheck = $sectcheck . $name . " ";
+ $name = $1;
+ $parameterdescs{$name} = $contents;
+ $sectcheck = $sectcheck . $name . " ";
$parameterdesc_start_lines{$name} = $new_start_line;
$new_start_line = 0;
} elsif ($name eq "@\.\.\.") {
- $name = "...";
- $parameterdescs{$name} = $contents;
- $sectcheck = $sectcheck . $name . " ";
+ $name = "...";
+ $parameterdescs{$name} = $contents;
+ $sectcheck = $sectcheck . $name . " ";
$parameterdesc_start_lines{$name} = $new_start_line;
$new_start_line = 0;
} else {
- if (defined($sections{$name}) && ($sections{$name} ne "")) {
- # Only warn on user specified duplicate section names.
- if ($name ne $section_default) {
- emit_warning("${file}:$.", "duplicate section name '$name'\n");
- }
- $sections{$name} .= $contents;
- } else {
- $sections{$name} = $contents;
- push @sectionlist, $name;
+ if (defined($sections{$name}) && ($sections{$name} ne "")) {
+ # Only warn on user specified duplicate section names.
+ if ($name ne $section_default) {
+ emit_warning("${file}:$.", "duplicate section name '$name'\n");
+ }
+ $sections{$name} .= $contents;
+ } else {
+ $sections{$name} = $contents;
+ push @sectionlist, $name;
$section_start_lines{$name} = $new_start_line;
$new_start_line = 0;
- }
+ }
}
}
@@ -504,14 +507,14 @@ sub dump_doc_section {
return if (defined($nosymbol_table{$name}));
if (($output_selection == OUTPUT_ALL) ||
- (($output_selection == OUTPUT_INCLUDE) &&
- defined($function_table{$name})))
+ (($output_selection == OUTPUT_INCLUDE) &&
+ defined($function_table{$name})))
{
- dump_section($file, $name, $contents);
- output_blockhead({'sectionlist' => \@sectionlist,
- 'sections' => \%sections,
- 'module' => $modulename,
- 'content-only' => ($output_selection != OUTPUT_ALL), });
+ dump_section($file, $name, $contents);
+ output_blockhead({'sectionlist' => \@sectionlist,
+ 'sections' => \%sections,
+ 'module' => $modulename,
+ 'content-only' => ($output_selection != OUTPUT_ALL), });
}
}
@@ -542,21 +545,21 @@ sub output_highlight {
# print STDERR "contents af:$contents\n";
foreach $line (split "\n", $contents) {
- if (! $output_preformatted) {
- $line =~ s/^\s*//;
- }
- if ($line eq ""){
- if (! $output_preformatted) {
- print $lineprefix, $blankline;
- }
- } else {
- if ($output_mode eq "man" && substr($line, 0, 1) eq ".") {
- print "\\&$line";
- } else {
- print $lineprefix, $line;
- }
- }
- print "\n";
+ if (! $output_preformatted) {
+ $line =~ s/^\s*//;
+ }
+ if ($line eq ""){
+ if (! $output_preformatted) {
+ print $lineprefix, $blankline;
+ }
+ } else {
+ if ($output_mode eq "man" && substr($line, 0, 1) eq ".") {
+ print "\\&$line";
+ } else {
+ print $lineprefix, $line;
+ }
+ }
+ print "\n";
}
}
@@ -574,40 +577,40 @@ sub output_function_man(%) {
print ".SH SYNOPSIS\n";
if ($args{'functiontype'} ne "") {
- print ".B \"" . $args{'functiontype'} . "\" " . $args{'function'} . "\n";
+ print ".B \"" . $args{'functiontype'} . "\" " . $args{'function'} . "\n";
} else {
- print ".B \"" . $args{'function'} . "\n";
+ print ".B \"" . $args{'function'} . "\n";
}
$count = 0;
my $parenth = "(";
my $post = ",";
foreach my $parameter (@{$args{'parameterlist'}}) {
- if ($count == $#{$args{'parameterlist'}}) {
- $post = ");";
- }
- $type = $args{'parametertypes'}{$parameter};
- if ($type =~ m/$function_pointer/) {
- # pointer-to-function
- print ".BI \"" . $parenth . $1 . "\" " . " \") (" . $2 . ")" . $post . "\"\n";
- } else {
- $type =~ s/([^\*])$/$1 /;
- print ".BI \"" . $parenth . $type . "\" " . " \"" . $post . "\"\n";
- }
- $count++;
- $parenth = "";
+ if ($count == $#{$args{'parameterlist'}}) {
+ $post = ");";
+ }
+ $type = $args{'parametertypes'}{$parameter};
+ if ($type =~ m/$function_pointer/) {
+ # pointer-to-function
+ print ".BI \"" . $parenth . $1 . "\" " . " \") (" . $2 . ")" . $post . "\"\n";
+ } else {
+ $type =~ s/([^\*])$/$1 /;
+ print ".BI \"" . $parenth . $type . "\" " . " \"" . $post . "\"\n";
+ }
+ $count++;
+ $parenth = "";
}
print ".SH ARGUMENTS\n";
foreach $parameter (@{$args{'parameterlist'}}) {
- my $parameter_name = $parameter;
- $parameter_name =~ s/\[.*//;
+ my $parameter_name = $parameter;
+ $parameter_name =~ s/\[.*//;
- print ".IP \"" . $parameter . "\" 12\n";
- output_highlight($args{'parameterdescs'}{$parameter_name});
+ print ".IP \"" . $parameter . "\" 12\n";
+ output_highlight($args{'parameterdescs'}{$parameter_name});
}
foreach $section (@{$args{'sectionlist'}}) {
- print ".SH \"", uc $section, "\"\n";
- output_highlight($args{'sections'}{$section});
+ print ".SH \"", uc $section, "\"\n";
+ output_highlight($args{'sections'}{$section});
}
}
@@ -627,28 +630,27 @@ sub output_enum_man(%) {
print "enum " . $args{'enum'} . " {\n";
$count = 0;
foreach my $parameter (@{$args{'parameterlist'}}) {
- print ".br\n.BI \" $parameter\"\n";
- if ($count == $#{$args{'parameterlist'}}) {
- print "\n};\n";
- last;
- }
- else {
- print ", \n.br\n";
- }
- $count++;
+ print ".br\n.BI \" $parameter\"\n";
+ if ($count == $#{$args{'parameterlist'}}) {
+ print "\n};\n";
+ last;
+ } else {
+ print ", \n.br\n";
+ }
+ $count++;
}
print ".SH Constants\n";
foreach $parameter (@{$args{'parameterlist'}}) {
- my $parameter_name = $parameter;
- $parameter_name =~ s/\[.*//;
+ my $parameter_name = $parameter;
+ $parameter_name =~ s/\[.*//;
- print ".IP \"" . $parameter . "\" 12\n";
- output_highlight($args{'parameterdescs'}{$parameter_name});
+ print ".IP \"" . $parameter . "\" 12\n";
+ output_highlight($args{'parameterdescs'}{$parameter_name});
}
foreach $section (@{$args{'sectionlist'}}) {
- print ".SH \"$section\"\n";
- output_highlight($args{'sections'}{$section});
+ print ".SH \"$section\"\n";
+ output_highlight($args{'sections'}{$section});
}
}
@@ -672,18 +674,18 @@ sub output_struct_man(%) {
print ".SH Members\n";
foreach $parameter (@{$args{'parameterlist'}}) {
- ($parameter =~ /^#/) && next;
+ ($parameter =~ /^#/) && next;
- my $parameter_name = $parameter;
- $parameter_name =~ s/\[.*//;
+ my $parameter_name = $parameter;
+ $parameter_name =~ s/\[.*//;
- ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next;
- print ".IP \"" . $parameter . "\" 12\n";
- output_highlight($args{'parameterdescs'}{$parameter_name});
+ ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next;
+ print ".IP \"" . $parameter . "\" 12\n";
+ output_highlight($args{'parameterdescs'}{$parameter_name});
}
foreach $section (@{$args{'sectionlist'}}) {
- print ".SH \"$section\"\n";
- output_highlight($args{'sections'}{$section});
+ print ".SH \"$section\"\n";
+ output_highlight($args{'sections'}{$section});
}
}
@@ -699,8 +701,8 @@ sub output_typedef_man(%) {
print "typedef " . $args{'typedef'} . " \\- " . $args{'purpose'} . "\n";
foreach $section (@{$args{'sectionlist'}}) {
- print ".SH \"$section\"\n";
- output_highlight($args{'sections'}{$section});
+ print ".SH \"$section\"\n";
+ output_highlight($args{'sections'}{$section});
}
}
@@ -712,8 +714,8 @@ sub output_blockhead_man(%) {
print ".TH \"$args{'module'}\" 9 \"$args{'module'}\" \"$man_date\" \"API Manual\" LINUX\n";
foreach $section (@{$args{'sectionlist'}}) {
- print ".SH \"$section\"\n";
- output_highlight($args{'sections'}{$section});
+ print ".SH \"$section\"\n";
+ output_highlight($args{'sections'}{$section});
}
}
@@ -731,15 +733,15 @@ sub output_blockhead_rst(%) {
my ($parameter, $section);
foreach $section (@{$args{'sectionlist'}}) {
- next if (defined($nosymbol_table{$section}));
+ next if (defined($nosymbol_table{$section}));
- if ($output_selection != OUTPUT_INCLUDE) {
- print ".. _$section:\n\n";
- print "**$section**\n\n";
- }
+ if ($output_selection != OUTPUT_INCLUDE) {
+ print ".. _$section:\n\n";
+ print "**$section**\n\n";
+ }
print_lineno($section_start_lines{$section});
- output_highlight_rst($args{'sections'}{$section});
- print "\n";
+ output_highlight_rst($args{'sections'}{$section});
+ print "\n";
}
}
@@ -769,48 +771,48 @@ sub output_highlight_rst {
my $block = "";
foreach $line (split "\n",$input) {
- #
- # If we're in a literal block, see if we should drop out
- # of it. Otherwise pass the line straight through unmunged.
- #
- if ($in_literal) {
- if (! ($line =~ /^\s*$/)) {
- #
- # If this is the first non-blank line in a literal
- # block we need to figure out what the proper indent is.
- #
- if ($litprefix eq "") {
- $line =~ /^(\s*)/;
- $litprefix = '^' . $1;
- $output .= $line . "\n";
- } elsif (! ($line =~ /$litprefix/)) {
- $in_literal = 0;
- } else {
- $output .= $line . "\n";
- }
- } else {
- $output .= $line . "\n";
- }
- }
- #
- # Not in a literal block (or just dropped out)
- #
- if (! $in_literal) {
- $block .= $line . "\n";
- if (($line =~ /$sphinx_literal/) || ($line =~ /$sphinx_cblock/)) {
- $in_literal = 1;
- $litprefix = "";
- $output .= highlight_block($block);
- $block = ""
- }
- }
+ #
+ # If we're in a literal block, see if we should drop out
+ # of it. Otherwise pass the line straight through unmunged.
+ #
+ if ($in_literal) {
+ if (! ($line =~ /^\s*$/)) {
+ #
+ # If this is the first non-blank line in a literal
+ # block we need to figure out what the proper indent is.
+ #
+ if ($litprefix eq "") {
+ $line =~ /^(\s*)/;
+ $litprefix = '^' . $1;
+ $output .= $line . "\n";
+ } elsif (! ($line =~ /$litprefix/)) {
+ $in_literal = 0;
+ } else {
+ $output .= $line . "\n";
+ }
+ } else {
+ $output .= $line . "\n";
+ }
+ }
+ #
+ # Not in a literal block (or just dropped out)
+ #
+ if (! $in_literal) {
+ $block .= $line . "\n";
+ if (($line =~ /$sphinx_literal/) || ($line =~ /$sphinx_cblock/)) {
+ $in_literal = 1;
+ $litprefix = "";
+ $output .= highlight_block($block);
+ $block = ""
+ }
+ }
}
if ($block) {
- $output .= highlight_block($block);
+ $output .= highlight_block($block);
}
foreach $line (split "\n", $output) {
- print $lineprefix . $line . "\n";
+ print $lineprefix . $line . "\n";
}
}
@@ -818,71 +820,68 @@ sub output_function_rst(%) {
my %args = %{$_[0]};
my ($parameter, $section);
my $oldprefix = $lineprefix;
- my $start = "";
- my $is_macro = 0;
- if ($sphinx_major < 3) {
- if ($args{'typedef'}) {
- print ".. c:type:: ". $args{'function'} . "\n\n";
- print_lineno($declaration_start_line);
- print " **Typedef**: ";
- $lineprefix = "";
- output_highlight_rst($args{'purpose'});
- $start = "\n\n**Syntax**\n\n ``";
- $is_macro = 1;
- } else {
- print ".. c:function:: ";
- }
- } else {
- if ($args{'typedef'} || $args{'functiontype'} eq "") {
- $is_macro = 1;
- print ".. c:macro:: ". $args{'function'} . "\n\n";
- } else {
- print ".. c:function:: ";
- }
-
- if ($args{'typedef'}) {
- print_lineno($declaration_start_line);
- print " **Typedef**: ";
- $lineprefix = "";
- output_highlight_rst($args{'purpose'});
- $start = "\n\n**Syntax**\n\n ``";
- } else {
- print "``" if ($is_macro);
- }
- }
+ my $signature = "";
if ($args{'functiontype'} ne "") {
- $start .= $args{'functiontype'} . " " . $args{'function'} . " (";
+ $signature = $args{'functiontype'} . " " . $args{'function'} . " (";
} else {
- $start .= $args{'function'} . " (";
+ $signature = $args{'function'} . " (";
}
- print $start;
my $count = 0;
foreach my $parameter (@{$args{'parameterlist'}}) {
- if ($count ne 0) {
- print ", ";
- }
- $count++;
- $type = $args{'parametertypes'}{$parameter};
-
- if ($type =~ m/$function_pointer/) {
- # pointer-to-function
- print $1 . $parameter . ") (" . $2 . ")";
- } else {
- print $type;
- }
- }
- if ($is_macro) {
- print ")``\n\n";
+ if ($count ne 0) {
+ $signature .= ", ";
+ }
+ $count++;
+ $type = $args{'parametertypes'}{$parameter};
+
+ if ($type =~ m/$function_pointer/) {
+ # pointer-to-function
+ $signature .= $1 . $parameter . ") (" . $2 . ")";
+ } else {
+ $signature .= $type;
+ }
+ }
+
+ $signature .= ")";
+
+ if ($sphinx_major < 3) {
+ if ($args{'typedef'}) {
+ print ".. c:type:: ". $args{'function'} . "\n\n";
+ print_lineno($declaration_start_line);
+ print " **Typedef**: ";
+ $lineprefix = "";
+ output_highlight_rst($args{'purpose'});
+ print "\n\n**Syntax**\n\n";
+ print " ``$signature``\n\n";
+ } else {
+ print ".. c:function:: $signature\n\n";
+ }
} else {
- print ")\n\n";
+ if ($args{'typedef'} || $args{'functiontype'} eq "") {
+ print ".. c:macro:: ". $args{'function'} . "\n\n";
+
+ if ($args{'typedef'}) {
+ print_lineno($declaration_start_line);
+ print " **Typedef**: ";
+ $lineprefix = "";
+ output_highlight_rst($args{'purpose'});
+ print "\n\n**Syntax**\n\n";
+ print " ``$signature``\n\n";
+ } else {
+ print "``$signature``\n\n";
+ }
+ } else {
+ print ".. c:function:: $signature\n\n";
+ }
}
+
if (!$args{'typedef'}) {
- print_lineno($declaration_start_line);
- $lineprefix = " ";
- output_highlight_rst($args{'purpose'});
- print "\n";
+ print_lineno($declaration_start_line);
+ $lineprefix = " ";
+ output_highlight_rst($args{'purpose'});
+ print "\n";
}
#
@@ -893,27 +892,27 @@ sub output_function_rst(%) {
$lineprefix = " ";
print $lineprefix . "**Parameters**\n\n";
foreach $parameter (@{$args{'parameterlist'}}) {
- my $parameter_name = $parameter;
- $parameter_name =~ s/\[.*//;
- $type = $args{'parametertypes'}{$parameter};
-
- if ($type ne "") {
- print $lineprefix . "``$type``\n";
- } else {
- print $lineprefix . "``$parameter``\n";
- }
+ my $parameter_name = $parameter;
+ $parameter_name =~ s/\[.*//;
+ $type = $args{'parametertypes'}{$parameter};
+
+ if ($type ne "") {
+ print $lineprefix . "``$type``\n";
+ } else {
+ print $lineprefix . "``$parameter``\n";
+ }
print_lineno($parameterdesc_start_lines{$parameter_name});
- $lineprefix = " ";
- if (defined($args{'parameterdescs'}{$parameter_name}) &&
- $args{'parameterdescs'}{$parameter_name} ne $undescribed) {
- output_highlight_rst($args{'parameterdescs'}{$parameter_name});
- } else {
- print $lineprefix . "*undescribed*\n";
- }
- $lineprefix = " ";
- print "\n";
+ $lineprefix = " ";
+ if (defined($args{'parameterdescs'}{$parameter_name}) &&
+ $args{'parameterdescs'}{$parameter_name} ne $undescribed) {
+ output_highlight_rst($args{'parameterdescs'}{$parameter_name});
+ } else {
+ print $lineprefix . "*undescribed*\n";
+ }
+ $lineprefix = " ";
+ print "\n";
}
output_section_rst(@_);
@@ -926,10 +925,10 @@ sub output_section_rst(%) {
my $oldprefix = $lineprefix;
foreach $section (@{$args{'sectionlist'}}) {
- print $lineprefix . "**$section**\n\n";
+ print $lineprefix . "**$section**\n\n";
print_lineno($section_start_lines{$section});
- output_highlight_rst($args{'sections'}{$section});
- print "\n";
+ output_highlight_rst($args{'sections'}{$section});
+ print "\n";
}
print "\n";
}
@@ -942,11 +941,11 @@ sub output_enum_rst(%) {
my $outer;
if ($sphinx_major < 3) {
- my $name = "enum " . $args{'enum'};
- print "\n\n.. c:type:: " . $name . "\n\n";
+ my $name = "enum " . $args{'enum'};
+ print "\n\n.. c:type:: " . $name . "\n\n";
} else {
- my $name = $args{'enum'};
- print "\n\n.. c:enum:: " . $name . "\n\n";
+ my $name = $args{'enum'};
+ print "\n\n.. c:enum:: " . $name . "\n\n";
}
print_lineno($declaration_start_line);
$lineprefix = " ";
@@ -958,14 +957,14 @@ sub output_enum_rst(%) {
$lineprefix = $outer . " ";
print $outer . "**Constants**\n\n";
foreach $parameter (@{$args{'parameterlist'}}) {
- print $outer . "``$parameter``\n";
+ print $outer . "``$parameter``\n";
- if ($args{'parameterdescs'}{$parameter} ne $undescribed) {
- output_highlight_rst($args{'parameterdescs'}{$parameter});
- } else {
- print $lineprefix . "*undescribed*\n";
- }
- print "\n";
+ if ($args{'parameterdescs'}{$parameter} ne $undescribed) {
+ output_highlight_rst($args{'parameterdescs'}{$parameter});
+ } else {
+ print $lineprefix . "*undescribed*\n";
+ }
+ print "\n";
}
print "\n";
$lineprefix = $oldprefix;
@@ -979,9 +978,9 @@ sub output_typedef_rst(%) {
my $name;
if ($sphinx_major < 3) {
- $name = "typedef " . $args{'typedef'};
+ $name = "typedef " . $args{'typedef'};
} else {
- $name = $args{'typedef'};
+ $name = $args{'typedef'};
}
print "\n\n.. c:type:: " . $name . "\n\n";
print_lineno($declaration_start_line);
@@ -999,15 +998,15 @@ sub output_struct_rst(%) {
my $oldprefix = $lineprefix;
if ($sphinx_major < 3) {
- my $name = $args{'type'} . " " . $args{'struct'};
- print "\n\n.. c:type:: " . $name . "\n\n";
+ my $name = $args{'type'} . " " . $args{'struct'};
+ print "\n\n.. c:type:: " . $name . "\n\n";
} else {
- my $name = $args{'struct'};
- if ($args{'type'} eq 'union') {
- print "\n\n.. c:union:: " . $name . "\n\n";
- } else {
- print "\n\n.. c:struct:: " . $name . "\n\n";
- }
+ my $name = $args{'struct'};
+ if ($args{'type'} eq 'union') {
+ print "\n\n.. c:union:: " . $name . "\n\n";
+ } else {
+ print "\n\n.. c:struct:: " . $name . "\n\n";
+ }
}
print_lineno($declaration_start_line);
$lineprefix = " ";
@@ -1024,19 +1023,19 @@ sub output_struct_rst(%) {
$lineprefix = " ";
print $lineprefix . "**Members**\n\n";
foreach $parameter (@{$args{'parameterlist'}}) {
- ($parameter =~ /^#/) && next;
+ ($parameter =~ /^#/) && next;
- my $parameter_name = $parameter;
- $parameter_name =~ s/\[.*//;
+ my $parameter_name = $parameter;
+ $parameter_name =~ s/\[.*//;
- ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next;
- $type = $args{'parametertypes'}{$parameter};
+ ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next;
+ $type = $args{'parametertypes'}{$parameter};
print_lineno($parameterdesc_start_lines{$parameter_name});
- print $lineprefix . "``" . $parameter . "``\n";
- $lineprefix = " ";
- output_highlight_rst($args{'parameterdescs'}{$parameter_name});
- $lineprefix = " ";
- print "\n";
+ print $lineprefix . "``" . $parameter . "``\n";
+ $lineprefix = " ";
+ output_highlight_rst($args{'parameterdescs'}{$parameter_name});
+ $lineprefix = " ";
+ print "\n";
}
print "\n";
@@ -1074,14 +1073,14 @@ sub output_declaration {
return if (defined($nosymbol_table{$name}));
if (($output_selection == OUTPUT_ALL) ||
- (($output_selection == OUTPUT_INCLUDE ||
- $output_selection == OUTPUT_EXPORTED) &&
- defined($function_table{$name})) ||
- ($output_selection == OUTPUT_INTERNAL &&
- !($functype eq "function" && defined($function_table{$name}))))
+ (($output_selection == OUTPUT_INCLUDE ||
+ $output_selection == OUTPUT_EXPORTED) &&
+ defined($function_table{$name})) ||
+ ($output_selection == OUTPUT_INTERNAL &&
+ !($functype eq "function" && defined($function_table{$name}))))
{
- &$func(@_);
- $section_counter++;
+ &$func(@_);
+ $section_counter++;
}
}
@@ -1120,202 +1119,202 @@ sub dump_struct($$) {
my $struct_members = qr{($type)([^\{\};]+)\{([^\{\}]*)\}([^\{\}\;]*)\;};
if ($x =~ /($type)\s+(\w+)\s*$definition_body/) {
- $decl_type = $1;
- $declaration_name = $2;
- $members = $3;
+ $decl_type = $1;
+ $declaration_name = $2;
+ $members = $3;
} elsif ($x =~ /typedef\s+($type)\s*$definition_body\s*(\w+)\s*;/) {
- $decl_type = $1;
- $declaration_name = $3;
- $members = $2;
+ $decl_type = $1;
+ $declaration_name = $3;
+ $members = $2;
}
if ($members) {
- if ($identifier ne $declaration_name) {
- emit_warning("${file}:$.", "expecting prototype for $decl_type $identifier. Prototype was for $decl_type $declaration_name instead\n");
- return;
- }
-
- # ignore members marked private:
- $members =~ s/\/\*\s*private:.*?\/\*\s*public:.*?\*\///gosi;
- $members =~ s/\/\*\s*private:.*//gosi;
- # strip comments:
- $members =~ s/\/\*.*?\*\///gos;
- # strip attributes
- $members =~ s/\s*$attribute/ /gi;
- $members =~ s/\s*__aligned\s*\([^;]*\)/ /gos;
- $members =~ s/\s*__packed\s*/ /gos;
- $members =~ s/\s*CRYPTO_MINALIGN_ATTR/ /gos;
- $members =~ s/\s*____cacheline_aligned_in_smp/ /gos;
- $members =~ s/\s*____cacheline_aligned/ /gos;
- # unwrap struct_group():
- # - first eat non-declaration parameters and rewrite for final match
- # - then remove macro, outer parens, and trailing semicolon
- $members =~ s/\bstruct_group\s*\(([^,]*,)/STRUCT_GROUP(/gos;
- $members =~ s/\bstruct_group_(attr|tagged)\s*\(([^,]*,){2}/STRUCT_GROUP(/gos;
- $members =~ s/\b__struct_group\s*\(([^,]*,){3}/STRUCT_GROUP(/gos;
- $members =~ s/\bSTRUCT_GROUP(\(((?:(?>[^)(]+)|(?1))*)\))[^;]*;/$2/gos;
-
- my $args = qr{([^,)]+)};
- # replace DECLARE_BITMAP
- $members =~ s/__ETHTOOL_DECLARE_LINK_MODE_MASK\s*\(([^\)]+)\)/DECLARE_BITMAP($1, __ETHTOOL_LINK_MODE_MASK_NBITS)/gos;
- $members =~ s/DECLARE_PHY_INTERFACE_MASK\s*\(([^\)]+)\)/DECLARE_BITMAP($1, PHY_INTERFACE_MODE_MAX)/gos;
- $members =~ s/DECLARE_BITMAP\s*\($args,\s*$args\)/unsigned long $1\[BITS_TO_LONGS($2)\]/gos;
- # replace DECLARE_HASHTABLE
- $members =~ s/DECLARE_HASHTABLE\s*\($args,\s*$args\)/unsigned long $1\[1 << (($2) - 1)\]/gos;
- # replace DECLARE_KFIFO
- $members =~ s/DECLARE_KFIFO\s*\($args,\s*$args,\s*$args\)/$2 \*$1/gos;
- # replace DECLARE_KFIFO_PTR
- $members =~ s/DECLARE_KFIFO_PTR\s*\($args,\s*$args\)/$2 \*$1/gos;
- # replace DECLARE_FLEX_ARRAY
- $members =~ s/(?:__)?DECLARE_FLEX_ARRAY\s*\($args,\s*$args\)/$1 $2\[\]/gos;
- #replace DEFINE_DMA_UNMAP_ADDR
- $members =~ s/DEFINE_DMA_UNMAP_ADDR\s*\($args\)/dma_addr_t $1/gos;
- #replace DEFINE_DMA_UNMAP_LEN
- $members =~ s/DEFINE_DMA_UNMAP_LEN\s*\($args\)/__u32 $1/gos;
- my $declaration = $members;
-
- # Split nested struct/union elements as newer ones
- while ($members =~ m/$struct_members/) {
- my $newmember;
- my $maintype = $1;
- my $ids = $4;
- my $content = $3;
- foreach my $id(split /,/, $ids) {
- $newmember .= "$maintype $id; ";
-
- $id =~ s/[:\[].*//;
- $id =~ s/^\s*\**(\S+)\s*/$1/;
- foreach my $arg (split /;/, $content) {
- next if ($arg =~ m/^\s*$/);
- if ($arg =~ m/^([^\(]+\(\*?\s*)([\w\.]*)(\s*\).*)/) {
- # pointer-to-function
- my $type = $1;
- my $name = $2;
- my $extra = $3;
- next if (!$name);
- if ($id =~ m/^\s*$/) {
- # anonymous struct/union
- $newmember .= "$type$name$extra; ";
- } else {
- $newmember .= "$type$id.$name$extra; ";
- }
- } else {
- my $type;
- my $names;
- $arg =~ s/^\s+//;
- $arg =~ s/\s+$//;
- # Handle bitmaps
- $arg =~ s/:\s*\d+\s*//g;
- # Handle arrays
- $arg =~ s/\[.*\]//g;
- # The type may have multiple words,
- # and multiple IDs can be defined, like:
- # const struct foo, *bar, foobar
- # So, we remove spaces when parsing the
- # names, in order to match just names
- # and commas for the names
- $arg =~ s/\s*,\s*/,/g;
- if ($arg =~ m/(.*)\s+([\S+,]+)/) {
- $type = $1;
- $names = $2;
- } else {
- $newmember .= "$arg; ";
- next;
- }
- foreach my $name (split /,/, $names) {
- $name =~ s/^\s*\**(\S+)\s*/$1/;
- next if (($name =~ m/^\s*$/));
- if ($id =~ m/^\s*$/) {
- # anonymous struct/union
- $newmember .= "$type $name; ";
- } else {
- $newmember .= "$type $id.$name; ";
- }
- }
- }
- }
- }
- $members =~ s/$struct_members/$newmember/;
- }
-
- # Ignore other nested elements, like enums
- $members =~ s/(\{[^\{\}]*\})//g;
-
- create_parameterlist($members, ';', $file, $declaration_name);
- check_sections($file, $declaration_name, $decl_type, $sectcheck, $struct_actual);
-
- # Adjust declaration for better display
- $declaration =~ s/([\{;])/$1\n/g;
- $declaration =~ s/\}\s+;/};/g;
- # Better handle inlined enums
- do {} while ($declaration =~ s/(enum\s+\{[^\}]+),([^\n])/$1,\n$2/);
-
- my @def_args = split /\n/, $declaration;
- my $level = 1;
- $declaration = "";
- foreach my $clause (@def_args) {
- $clause =~ s/^\s+//;
- $clause =~ s/\s+$//;
- $clause =~ s/\s+/ /;
- next if (!$clause);
- $level-- if ($clause =~ m/(\})/ && $level > 1);
- if (!($clause =~ m/^\s*#/)) {
- $declaration .= "\t" x $level;
- }
- $declaration .= "\t" . $clause . "\n";
- $level++ if ($clause =~ m/(\{)/ && !($clause =~m/\}/));
- }
- output_declaration($declaration_name,
- 'struct',
- {'struct' => $declaration_name,
- 'module' => $modulename,
- 'definition' => $declaration,
- 'parameterlist' => \@parameterlist,
- 'parameterdescs' => \%parameterdescs,
- 'parametertypes' => \%parametertypes,
- 'sectionlist' => \@sectionlist,
- 'sections' => \%sections,
- 'purpose' => $declaration_purpose,
- 'type' => $decl_type
- });
- }
- else {
- print STDERR "${file}:$.: error: Cannot parse struct or union!\n";
- ++$errors;
+ if ($identifier ne $declaration_name) {
+ emit_warning("${file}:$.", "expecting prototype for $decl_type $identifier. Prototype was for $decl_type $declaration_name instead\n");
+ return;
+ }
+
+ # ignore members marked private:
+ $members =~ s/\/\*\s*private:.*?\/\*\s*public:.*?\*\///gosi;
+ $members =~ s/\/\*\s*private:.*//gosi;
+ # strip comments:
+ $members =~ s/\/\*.*?\*\///gos;
+ # strip attributes
+ $members =~ s/\s*$attribute/ /gi;
+ $members =~ s/\s*__aligned\s*\([^;]*\)/ /gos;
+ $members =~ s/\s*__counted_by\s*\([^;]*\)/ /gos;
+ $members =~ s/\s*__packed\s*/ /gos;
+ $members =~ s/\s*CRYPTO_MINALIGN_ATTR/ /gos;
+ $members =~ s/\s*____cacheline_aligned_in_smp/ /gos;
+ $members =~ s/\s*____cacheline_aligned/ /gos;
+ # unwrap struct_group():
+ # - first eat non-declaration parameters and rewrite for final match
+ # - then remove macro, outer parens, and trailing semicolon
+ $members =~ s/\bstruct_group\s*\(([^,]*,)/STRUCT_GROUP(/gos;
+ $members =~ s/\bstruct_group_(attr|tagged)\s*\(([^,]*,){2}/STRUCT_GROUP(/gos;
+ $members =~ s/\b__struct_group\s*\(([^,]*,){3}/STRUCT_GROUP(/gos;
+ $members =~ s/\bSTRUCT_GROUP(\(((?:(?>[^)(]+)|(?1))*)\))[^;]*;/$2/gos;
+
+ my $args = qr{([^,)]+)};
+ # replace DECLARE_BITMAP
+ $members =~ s/__ETHTOOL_DECLARE_LINK_MODE_MASK\s*\(([^\)]+)\)/DECLARE_BITMAP($1, __ETHTOOL_LINK_MODE_MASK_NBITS)/gos;
+ $members =~ s/DECLARE_PHY_INTERFACE_MASK\s*\(([^\)]+)\)/DECLARE_BITMAP($1, PHY_INTERFACE_MODE_MAX)/gos;
+ $members =~ s/DECLARE_BITMAP\s*\($args,\s*$args\)/unsigned long $1\[BITS_TO_LONGS($2)\]/gos;
+ # replace DECLARE_HASHTABLE
+ $members =~ s/DECLARE_HASHTABLE\s*\($args,\s*$args\)/unsigned long $1\[1 << (($2) - 1)\]/gos;
+ # replace DECLARE_KFIFO
+ $members =~ s/DECLARE_KFIFO\s*\($args,\s*$args,\s*$args\)/$2 \*$1/gos;
+ # replace DECLARE_KFIFO_PTR
+ $members =~ s/DECLARE_KFIFO_PTR\s*\($args,\s*$args\)/$2 \*$1/gos;
+ # replace DECLARE_FLEX_ARRAY
+ $members =~ s/(?:__)?DECLARE_FLEX_ARRAY\s*\($args,\s*$args\)/$1 $2\[\]/gos;
+ #replace DEFINE_DMA_UNMAP_ADDR
+ $members =~ s/DEFINE_DMA_UNMAP_ADDR\s*\($args\)/dma_addr_t $1/gos;
+ #replace DEFINE_DMA_UNMAP_LEN
+ $members =~ s/DEFINE_DMA_UNMAP_LEN\s*\($args\)/__u32 $1/gos;
+ my $declaration = $members;
+
+ # Split nested struct/union elements as newer ones
+ while ($members =~ m/$struct_members/) {
+ my $newmember;
+ my $maintype = $1;
+ my $ids = $4;
+ my $content = $3;
+ foreach my $id(split /,/, $ids) {
+ $newmember .= "$maintype $id; ";
+
+ $id =~ s/[:\[].*//;
+ $id =~ s/^\s*\**(\S+)\s*/$1/;
+ foreach my $arg (split /;/, $content) {
+ next if ($arg =~ m/^\s*$/);
+ if ($arg =~ m/^([^\(]+\(\*?\s*)([\w\.]*)(\s*\).*)/) {
+ # pointer-to-function
+ my $type = $1;
+ my $name = $2;
+ my $extra = $3;
+ next if (!$name);
+ if ($id =~ m/^\s*$/) {
+ # anonymous struct/union
+ $newmember .= "$type$name$extra; ";
+ } else {
+ $newmember .= "$type$id.$name$extra; ";
+ }
+ } else {
+ my $type;
+ my $names;
+ $arg =~ s/^\s+//;
+ $arg =~ s/\s+$//;
+ # Handle bitmaps
+ $arg =~ s/:\s*\d+\s*//g;
+ # Handle arrays
+ $arg =~ s/\[.*\]//g;
+ # The type may have multiple words,
+ # and multiple IDs can be defined, like:
+ # const struct foo, *bar, foobar
+ # So, we remove spaces when parsing the
+ # names, in order to match just names
+ # and commas for the names
+ $arg =~ s/\s*,\s*/,/g;
+ if ($arg =~ m/(.*)\s+([\S+,]+)/) {
+ $type = $1;
+ $names = $2;
+ } else {
+ $newmember .= "$arg; ";
+ next;
+ }
+ foreach my $name (split /,/, $names) {
+ $name =~ s/^\s*\**(\S+)\s*/$1/;
+ next if (($name =~ m/^\s*$/));
+ if ($id =~ m/^\s*$/) {
+ # anonymous struct/union
+ $newmember .= "$type $name; ";
+ } else {
+ $newmember .= "$type $id.$name; ";
+ }
+ }
+ }
+ }
+ }
+ $members =~ s/$struct_members/$newmember/;
+ }
+
+ # Ignore other nested elements, like enums
+ $members =~ s/(\{[^\{\}]*\})//g;
+
+ create_parameterlist($members, ';', $file, $declaration_name);
+ check_sections($file, $declaration_name, $decl_type, $sectcheck, $struct_actual);
+
+ # Adjust declaration for better display
+ $declaration =~ s/([\{;])/$1\n/g;
+ $declaration =~ s/\}\s+;/};/g;
+ # Better handle inlined enums
+ do {} while ($declaration =~ s/(enum\s+\{[^\}]+),([^\n])/$1,\n$2/);
+
+ my @def_args = split /\n/, $declaration;
+ my $level = 1;
+ $declaration = "";
+ foreach my $clause (@def_args) {
+ $clause =~ s/^\s+//;
+ $clause =~ s/\s+$//;
+ $clause =~ s/\s+/ /;
+ next if (!$clause);
+ $level-- if ($clause =~ m/(\})/ && $level > 1);
+ if (!($clause =~ m/^\s*#/)) {
+ $declaration .= "\t" x $level;
+ }
+ $declaration .= "\t" . $clause . "\n";
+ $level++ if ($clause =~ m/(\{)/ && !($clause =~m/\}/));
+ }
+ output_declaration($declaration_name,
+ 'struct',
+ {'struct' => $declaration_name,
+ 'module' => $modulename,
+ 'definition' => $declaration,
+ 'parameterlist' => \@parameterlist,
+ 'parameterdescs' => \%parameterdescs,
+ 'parametertypes' => \%parametertypes,
+ 'sectionlist' => \@sectionlist,
+ 'sections' => \%sections,
+ 'purpose' => $declaration_purpose,
+ 'type' => $decl_type
+ });
+ } else {
+ print STDERR "${file}:$.: error: Cannot parse struct or union!\n";
+ ++$errors;
}
}
sub show_warnings($$) {
- my $functype = shift;
- my $name = shift;
-
- return 0 if (defined($nosymbol_table{$name}));
-
- return 1 if ($output_selection == OUTPUT_ALL);
-
- if ($output_selection == OUTPUT_EXPORTED) {
- if (defined($function_table{$name})) {
- return 1;
- } else {
- return 0;
- }
- }
- if ($output_selection == OUTPUT_INTERNAL) {
- if (!($functype eq "function" && defined($function_table{$name}))) {
- return 1;
- } else {
- return 0;
- }
- }
- if ($output_selection == OUTPUT_INCLUDE) {
- if (defined($function_table{$name})) {
- return 1;
- } else {
- return 0;
- }
- }
- die("Please add the new output type at show_warnings()");
+ my $functype = shift;
+ my $name = shift;
+
+ return 0 if (defined($nosymbol_table{$name}));
+
+ return 1 if ($output_selection == OUTPUT_ALL);
+
+ if ($output_selection == OUTPUT_EXPORTED) {
+ if (defined($function_table{$name})) {
+ return 1;
+ } else {
+ return 0;
+ }
+ }
+ if ($output_selection == OUTPUT_INTERNAL) {
+ if (!($functype eq "function" && defined($function_table{$name}))) {
+ return 1;
+ } else {
+ return 0;
+ }
+ }
+ if ($output_selection == OUTPUT_INCLUDE) {
+ if (defined($function_table{$name})) {
+ return 1;
+ } else {
+ return 0;
+ }
+ }
+ die("Please add the new output type at show_warnings()");
}
sub dump_enum($$) {
@@ -1329,65 +1328,65 @@ sub dump_enum($$) {
$x =~ s@/\*.*?\*/@@gos; # strip comments.
# strip #define macros inside enums
- $x =~ s@#\s*((define|ifdef)\s+|endif)[^;]*;@@gos;
+ $x =~ s@#\s*((define|ifdef|if)\s+|endif)[^;]*;@@gos;
if ($x =~ /typedef\s+enum\s*\{(.*)\}\s*(\w*)\s*;/) {
- $declaration_name = $2;
- $members = $1;
+ $declaration_name = $2;
+ $members = $1;
} elsif ($x =~ /enum\s+(\w*)\s*\{(.*)\}/) {
- $declaration_name = $1;
- $members = $2;
+ $declaration_name = $1;
+ $members = $2;
}
if ($members) {
- if ($identifier ne $declaration_name) {
- if ($identifier eq "") {
- emit_warning("${file}:$.", "wrong kernel-doc identifier on line:\n");
- } else {
- emit_warning("${file}:$.", "expecting prototype for enum $identifier. Prototype was for enum $declaration_name instead\n");
- }
- return;
- }
- $declaration_name = "(anonymous)" if ($declaration_name eq "");
-
- my %_members;
-
- $members =~ s/\s+$//;
- $members =~ s/\([^;]*?[\)]//g;
-
- foreach my $arg (split ',', $members) {
- $arg =~ s/^\s*(\w+).*/$1/;
- push @parameterlist, $arg;
- if (!$parameterdescs{$arg}) {
- $parameterdescs{$arg} = $undescribed;
- if (show_warnings("enum", $declaration_name)) {
- emit_warning("${file}:$.", "Enum value '$arg' not described in enum '$declaration_name'\n");
- }
- }
- $_members{$arg} = 1;
- }
-
- while (my ($k, $v) = each %parameterdescs) {
- if (!exists($_members{$k})) {
- if (show_warnings("enum", $declaration_name)) {
- emit_warning("${file}:$.", "Excess enum value '$k' description in '$declaration_name'\n");
- }
- }
- }
-
- output_declaration($declaration_name,
- 'enum',
- {'enum' => $declaration_name,
- 'module' => $modulename,
- 'parameterlist' => \@parameterlist,
- 'parameterdescs' => \%parameterdescs,
- 'sectionlist' => \@sectionlist,
- 'sections' => \%sections,
- 'purpose' => $declaration_purpose
- });
+ if ($identifier ne $declaration_name) {
+ if ($identifier eq "") {
+ emit_warning("${file}:$.", "wrong kernel-doc identifier on line:\n");
+ } else {
+ emit_warning("${file}:$.", "expecting prototype for enum $identifier. Prototype was for enum $declaration_name instead\n");
+ }
+ return;
+ }
+ $declaration_name = "(anonymous)" if ($declaration_name eq "");
+
+ my %_members;
+
+ $members =~ s/\s+$//;
+ $members =~ s/\([^;]*?[\)]//g;
+
+ foreach my $arg (split ',', $members) {
+ $arg =~ s/^\s*(\w+).*/$1/;
+ push @parameterlist, $arg;
+ if (!$parameterdescs{$arg}) {
+ $parameterdescs{$arg} = $undescribed;
+ if (show_warnings("enum", $declaration_name)) {
+ emit_warning("${file}:$.", "Enum value '$arg' not described in enum '$declaration_name'\n");
+ }
+ }
+ $_members{$arg} = 1;
+ }
+
+ while (my ($k, $v) = each %parameterdescs) {
+ if (!exists($_members{$k})) {
+ if (show_warnings("enum", $declaration_name)) {
+ emit_warning("${file}:$.", "Excess enum value '$k' description in '$declaration_name'\n");
+ }
+ }
+ }
+
+ output_declaration($declaration_name,
+ 'enum',
+ {'enum' => $declaration_name,
+ 'module' => $modulename,
+ 'parameterlist' => \@parameterlist,
+ 'parameterdescs' => \%parameterdescs,
+ 'sectionlist' => \@sectionlist,
+ 'sections' => \%sections,
+ 'purpose' => $declaration_purpose
+ });
} else {
- print STDERR "${file}:$.: error: Cannot parse enum!\n";
- ++$errors;
+ print STDERR "${file}:$.: error: Cannot parse enum!\n";
+ ++$errors;
}
}
@@ -1406,59 +1405,58 @@ sub dump_typedef($$) {
# Parse function typedef prototypes
if ($x =~ $typedef1 || $x =~ $typedef2) {
- $return_type = $1;
- $declaration_name = $2;
- my $args = $3;
- $return_type =~ s/^\s+//;
-
- if ($identifier ne $declaration_name) {
- emit_warning("${file}:$.", "expecting prototype for typedef $identifier. Prototype was for typedef $declaration_name instead\n");
- return;
- }
-
- create_parameterlist($args, ',', $file, $declaration_name);
-
- output_declaration($declaration_name,
- 'function',
- {'function' => $declaration_name,
- 'typedef' => 1,
- 'module' => $modulename,
- 'functiontype' => $return_type,
- 'parameterlist' => \@parameterlist,
- 'parameterdescs' => \%parameterdescs,
- 'parametertypes' => \%parametertypes,
- 'sectionlist' => \@sectionlist,
- 'sections' => \%sections,
- 'purpose' => $declaration_purpose
- });
- return;
+ $return_type = $1;
+ $declaration_name = $2;
+ my $args = $3;
+ $return_type =~ s/^\s+//;
+
+ if ($identifier ne $declaration_name) {
+ emit_warning("${file}:$.", "expecting prototype for typedef $identifier. Prototype was for typedef $declaration_name instead\n");
+ return;
+ }
+
+ create_parameterlist($args, ',', $file, $declaration_name);
+
+ output_declaration($declaration_name,
+ 'function',
+ {'function' => $declaration_name,
+ 'typedef' => 1,
+ 'module' => $modulename,
+ 'functiontype' => $return_type,
+ 'parameterlist' => \@parameterlist,
+ 'parameterdescs' => \%parameterdescs,
+ 'parametertypes' => \%parametertypes,
+ 'sectionlist' => \@sectionlist,
+ 'sections' => \%sections,
+ 'purpose' => $declaration_purpose
+ });
+ return;
}
while (($x =~ /\(*.\)\s*;$/) || ($x =~ /\[*.\]\s*;$/)) {
- $x =~ s/\(*.\)\s*;$/;/;
- $x =~ s/\[*.\]\s*;$/;/;
+ $x =~ s/\(*.\)\s*;$/;/;
+ $x =~ s/\[*.\]\s*;$/;/;
}
if ($x =~ /typedef.*\s+(\w+)\s*;/) {
- $declaration_name = $1;
+ $declaration_name = $1;
- if ($identifier ne $declaration_name) {
- emit_warning("${file}:$.", "expecting prototype for typedef $identifier. Prototype was for typedef $declaration_name instead\n");
- return;
- }
+ if ($identifier ne $declaration_name) {
+ emit_warning("${file}:$.", "expecting prototype for typedef $identifier. Prototype was for typedef $declaration_name instead\n");
+ return;
+ }
- output_declaration($declaration_name,
- 'typedef',
- {'typedef' => $declaration_name,
- 'module' => $modulename,
- 'sectionlist' => \@sectionlist,
- 'sections' => \%sections,
- 'purpose' => $declaration_purpose
- });
- }
- else {
- print STDERR "${file}:$.: error: Cannot parse typedef!\n";
- ++$errors;
+ output_declaration($declaration_name,
+ 'typedef',
+ {'typedef' => $declaration_name,
+ 'module' => $modulename,
+ 'sectionlist' => \@sectionlist,
+ 'sections' => \%sections,
+ 'purpose' => $declaration_purpose
+ });
+ } else {
+ print STDERR "${file}:$.: error: Cannot parse typedef!\n";
+ ++$errors;
}
}
@@ -1481,202 +1479,220 @@ sub create_parameterlist($$$$) {
# temporarily replace commas inside function pointer definition
my $arg_expr = qr{\([^\),]+};
while ($args =~ /$arg_expr,/) {
- $args =~ s/($arg_expr),/$1#/g;
+ $args =~ s/($arg_expr),/$1#/g;
}
foreach my $arg (split($splitter, $args)) {
- # strip comments
- $arg =~ s/\/\*.*\*\///;
- # ignore argument attributes
- $arg =~ s/\sPOS0?\s/ /;
- # strip leading/trailing spaces
- $arg =~ s/^\s*//;
- $arg =~ s/\s*$//;
- $arg =~ s/\s+/ /;
-
- if ($arg =~ /^#/) {
- # Treat preprocessor directive as a typeless variable just to fill
- # corresponding data structures "correctly". Catch it later in
- # output_* subs.
- push_parameter($arg, "", "", $file);
- } elsif ($arg =~ m/\(.+\)\s*\(/) {
- # pointer-to-function
- $arg =~ tr/#/,/;
- $arg =~ m/[^\(]+\(\*?\s*([\w\[\]\.]*)\s*\)/;
- $param = $1;
- $type = $arg;
- $type =~ s/([^\(]+\(\*?)\s*$param/$1/;
- save_struct_actual($param);
- push_parameter($param, $type, $arg, $file, $declaration_name);
- } elsif ($arg) {
- $arg =~ s/\s*:\s*/:/g;
- $arg =~ s/\s*\[/\[/g;
-
- my @args = split('\s*,\s*', $arg);
- if ($args[0] =~ m/\*/) {
- $args[0] =~ s/(\*+)\s*/ $1/;
- }
-
- my @first_arg;
- if ($args[0] =~ /^(.*\s+)(.*?\[.*\].*)$/) {
- shift @args;
- push(@first_arg, split('\s+', $1));
- push(@first_arg, $2);
- } else {
- @first_arg = split('\s+', shift @args);
- }
-
- unshift(@args, pop @first_arg);
- $type = join " ", @first_arg;
-
- foreach $param (@args) {
- if ($param =~ m/^(\*+)\s*(.*)/) {
- save_struct_actual($2);
-
- push_parameter($2, "$type $1", $arg, $file, $declaration_name);
- }
- elsif ($param =~ m/(.*?):(\d+)/) {
- if ($type ne "") { # skip unnamed bit-fields
- save_struct_actual($1);
- push_parameter($1, "$type:$2", $arg, $file, $declaration_name)
- }
- }
- else {
- save_struct_actual($param);
- push_parameter($param, $type, $arg, $file, $declaration_name);
- }
- }
- }
+ # strip comments
+ $arg =~ s/\/\*.*\*\///;
+ # ignore argument attributes
+ $arg =~ s/\sPOS0?\s/ /;
+ # strip leading/trailing spaces
+ $arg =~ s/^\s*//;
+ $arg =~ s/\s*$//;
+ $arg =~ s/\s+/ /;
+
+ if ($arg =~ /^#/) {
+ # Treat preprocessor directive as a typeless variable just to fill
+ # corresponding data structures "correctly". Catch it later in
+ # output_* subs.
+ push_parameter($arg, "", "", $file);
+ } elsif ($arg =~ m/\(.+\)\s*\(/) {
+ # pointer-to-function
+ $arg =~ tr/#/,/;
+ $arg =~ m/[^\(]+\(\*?\s*([\w\[\]\.]*)\s*\)/;
+ $param = $1;
+ $type = $arg;
+ $type =~ s/([^\(]+\(\*?)\s*$param/$1/;
+ save_struct_actual($param);
+ push_parameter($param, $type, $arg, $file, $declaration_name);
+ } elsif ($arg =~ m/\(.+\)\s*\[/) {
+ # array-of-pointers
+ $arg =~ tr/#/,/;
+ $arg =~ m/[^\(]+\(\s*\*\s*([\w\[\]\.]*?)\s*(\s*\[\s*[\w]+\s*\]\s*)*\)/;
+ $param = $1;
+ $type = $arg;
+ $type =~ s/([^\(]+\(\*?)\s*$param/$1/;
+ save_struct_actual($param);
+ push_parameter($param, $type, $arg, $file, $declaration_name);
+ } elsif ($arg) {
+ $arg =~ s/\s*:\s*/:/g;
+ $arg =~ s/\s*\[/\[/g;
+
+ my @args = split('\s*,\s*', $arg);
+ if ($args[0] =~ m/\*/) {
+ $args[0] =~ s/(\*+)\s*/ $1/;
+ }
+
+ my @first_arg;
+ if ($args[0] =~ /^(.*\s+)(.*?\[.*\].*)$/) {
+ shift @args;
+ push(@first_arg, split('\s+', $1));
+ push(@first_arg, $2);
+ } else {
+ @first_arg = split('\s+', shift @args);
+ }
+
+ unshift(@args, pop @first_arg);
+ $type = join " ", @first_arg;
+
+ foreach $param (@args) {
+ if ($param =~ m/^(\*+)\s*(.*)/) {
+ save_struct_actual($2);
+
+ push_parameter($2, "$type $1", $arg, $file, $declaration_name);
+ } elsif ($param =~ m/(.*?):(\w+)/) {
+ if ($type ne "") { # skip unnamed bit-fields
+ save_struct_actual($1);
+ push_parameter($1, "$type:$2", $arg, $file, $declaration_name)
+ }
+ } else {
+ save_struct_actual($param);
+ push_parameter($param, $type, $arg, $file, $declaration_name);
+ }
+ }
+ }
}
}
sub push_parameter($$$$$) {
- my $param = shift;
- my $type = shift;
- my $org_arg = shift;
- my $file = shift;
- my $declaration_name = shift;
-
- if (($anon_struct_union == 1) && ($type eq "") &&
- ($param eq "}")) {
- return; # ignore the ending }; from anon. struct/union
- }
-
- $anon_struct_union = 0;
- $param =~ s/[\[\)].*//;
-
- if ($type eq "" && $param =~ /\.\.\.$/)
- {
- if (!$param =~ /\w\.\.\.$/) {
- # handles unnamed variable parameters
- $param = "...";
- }
- elsif ($param =~ /\w\.\.\.$/) {
- # for named variable parameters of the form `x...`, remove the dots
- $param =~ s/\.\.\.$//;
- }
- if (!defined $parameterdescs{$param} || $parameterdescs{$param} eq "") {
- $parameterdescs{$param} = "variable arguments";
- }
- }
- elsif ($type eq "" && ($param eq "" or $param eq "void"))
- {
- $param="void";
- $parameterdescs{void} = "no arguments";
- }
- elsif ($type eq "" && ($param eq "struct" or $param eq "union"))
- # handle unnamed (anonymous) union or struct:
- {
- $type = $param;
- $param = "{unnamed_" . $param . "}";
- $parameterdescs{$param} = "anonymous\n";
- $anon_struct_union = 1;
- }
-
- # warn if parameter has no description
- # (but ignore ones starting with # as these are not parameters
- # but inline preprocessor statements);
- # Note: It will also ignore void params and unnamed structs/unions
- if (!defined $parameterdescs{$param} && $param !~ /^#/) {
- $parameterdescs{$param} = $undescribed;
-
- if (show_warnings($type, $declaration_name) && $param !~ /\./) {
- emit_warning("${file}:$.", "Function parameter or member '$param' not described in '$declaration_name'\n");
- }
- }
-
- # strip spaces from $param so that it is one continuous string
- # on @parameterlist;
- # this fixes a problem where check_sections() cannot find
- # a parameter like "addr[6 + 2]" because it actually appears
- # as "addr[6", "+", "2]" on the parameter list;
- # but it's better to maintain the param string unchanged for output,
- # so just weaken the string compare in check_sections() to ignore
- # "[blah" in a parameter string;
- ###$param =~ s/\s*//g;
- push @parameterlist, $param;
- $org_arg =~ s/\s\s+/ /g;
- $parametertypes{$param} = $org_arg;
+ my $param = shift;
+ my $type = shift;
+ my $org_arg = shift;
+ my $file = shift;
+ my $declaration_name = shift;
+
+ if (($anon_struct_union == 1) && ($type eq "") &&
+ ($param eq "}")) {
+ return; # ignore the ending }; from anon. struct/union
+ }
+
+ $anon_struct_union = 0;
+ $param =~ s/[\[\)].*//;
+
+ if ($type eq "" && $param =~ /\.\.\.$/)
+ {
+ if (!$param =~ /\w\.\.\.$/) {
+ # handles unnamed variable parameters
+ $param = "...";
+ } elsif ($param =~ /\w\.\.\.$/) {
+ # for named variable parameters of the form `x...`, remove the dots
+ $param =~ s/\.\.\.$//;
+ }
+ if (!defined $parameterdescs{$param} || $parameterdescs{$param} eq "") {
+ $parameterdescs{$param} = "variable arguments";
+ }
+ }
+ elsif ($type eq "" && ($param eq "" or $param eq "void"))
+ {
+ $param="void";
+ $parameterdescs{void} = "no arguments";
+ }
+ elsif ($type eq "" && ($param eq "struct" or $param eq "union"))
+ # handle unnamed (anonymous) union or struct:
+ {
+ $type = $param;
+ $param = "{unnamed_" . $param . "}";
+ $parameterdescs{$param} = "anonymous\n";
+ $anon_struct_union = 1;
+ }
+ elsif ($param =~ "__cacheline_group" )
+ # handle cache group enforcing variables: they do not need be described in header files
+ {
+ return; # ignore __cacheline_group_begin and __cacheline_group_end
+ }
+
+ # warn if parameter has no description
+ # (but ignore ones starting with # as these are not parameters
+ # but inline preprocessor statements);
+ # Note: It will also ignore void params and unnamed structs/unions
+ if (!defined $parameterdescs{$param} && $param !~ /^#/) {
+ $parameterdescs{$param} = $undescribed;
+
+ if (show_warnings($type, $declaration_name) && $param !~ /\./) {
+ emit_warning("${file}:$.", "Function parameter or struct member '$param' not described in '$declaration_name'\n");
+ }
+ }
+
+ # strip spaces from $param so that it is one continuous string
+ # on @parameterlist;
+ # this fixes a problem where check_sections() cannot find
+ # a parameter like "addr[6 + 2]" because it actually appears
+ # as "addr[6", "+", "2]" on the parameter list;
+ # but it's better to maintain the param string unchanged for output,
+ # so just weaken the string compare in check_sections() to ignore
+ # "[blah" in a parameter string;
+ ###$param =~ s/\s*//g;
+ push @parameterlist, $param;
+ $org_arg =~ s/\s\s+/ /g;
+ $parametertypes{$param} = $org_arg;
}
sub check_sections($$$$$) {
- my ($file, $decl_name, $decl_type, $sectcheck, $prmscheck) = @_;
- my @sects = split ' ', $sectcheck;
- my @prms = split ' ', $prmscheck;
- my $err;
- my ($px, $sx);
- my $prm_clean; # strip trailing "[array size]" and/or beginning "*"
-
- foreach $sx (0 .. $#sects) {
- $err = 1;
- foreach $px (0 .. $#prms) {
- $prm_clean = $prms[$px];
- $prm_clean =~ s/\[.*\]//;
- $prm_clean =~ s/$attribute//i;
- # ignore array size in a parameter string;
- # however, the original param string may contain
- # spaces, e.g.: addr[6 + 2]
- # and this appears in @prms as "addr[6" since the
- # parameter list is split at spaces;
- # hence just ignore "[..." for the sections check;
- $prm_clean =~ s/\[.*//;
-
- ##$prm_clean =~ s/^\**//;
- if ($prm_clean eq $sects[$sx]) {
- $err = 0;
- last;
- }
- }
- if ($err) {
- if ($decl_type eq "function") {
- emit_warning("${file}:$.",
- "Excess function parameter " .
- "'$sects[$sx]' " .
- "description in '$decl_name'\n");
- }
- }
- }
+ my ($file, $decl_name, $decl_type, $sectcheck, $prmscheck) = @_;
+ my @sects = split ' ', $sectcheck;
+ my @prms = split ' ', $prmscheck;
+ my $err;
+ my ($px, $sx);
+ my $prm_clean; # strip trailing "[array size]" and/or beginning "*"
+
+ foreach $sx (0 .. $#sects) {
+ $err = 1;
+ foreach $px (0 .. $#prms) {
+ $prm_clean = $prms[$px];
+ $prm_clean =~ s/\[.*\]//;
+ $prm_clean =~ s/$attribute//i;
+ # ignore array size in a parameter string;
+ # however, the original param string may contain
+ # spaces, e.g.: addr[6 + 2]
+ # and this appears in @prms as "addr[6" since the
+ # parameter list is split at spaces;
+ # hence just ignore "[..." for the sections check;
+ $prm_clean =~ s/\[.*//;
+
+ ##$prm_clean =~ s/^\**//;
+ if ($prm_clean eq $sects[$sx]) {
+ $err = 0;
+ last;
+ }
+ }
+ if ($err) {
+ if ($decl_type eq "function") {
+ emit_warning("${file}:$.",
+ "Excess function parameter " .
+ "'$sects[$sx]' " .
+ "description in '$decl_name'\n");
+ } elsif (($decl_type eq "struct") or
+ ($decl_type eq "union")) {
+ emit_warning("${file}:$.",
+ "Excess $decl_type member " .
+ "'$sects[$sx]' " .
+ "description in '$decl_name'\n");
+ }
+ }
+ }
}
##
# Checks the section describing the return value of a function.
sub check_return_section {
- my $file = shift;
- my $declaration_name = shift;
- my $return_type = shift;
+ my $file = shift;
+ my $declaration_name = shift;
+ my $return_type = shift;
- # Ignore an empty return type (It's a macro)
- # Ignore functions with a "void" return type. (But don't ignore "void *")
- if (($return_type eq "") || ($return_type =~ /void\s*\w*\s*$/)) {
- return;
- }
+ # Ignore an empty return type (It's a macro)
+ # Ignore functions with a "void" return type. (But don't ignore "void *")
+ if (($return_type eq "") || ($return_type =~ /void\s*\w*\s*$/)) {
+ return;
+ }
- if (!defined($sections{$section_return}) ||
- $sections{$section_return} eq "") {
- emit_warning("${file}:$.",
- "No description found for return value of " .
- "'$declaration_name'\n");
- }
+ if (!defined($sections{$section_return}) ||
+ $sections{$section_return} eq "")
+ {
+ emit_warning("${file}:$.",
+ "No description found for return value of " .
+ "'$declaration_name'\n");
+ }
}
##
@@ -1751,21 +1767,21 @@ sub dump_function($$) {
$declaration_name = $2;
$noret = 1;
} elsif ($prototype =~ m/^()($name)\s*$prototype_end/ ||
- $prototype =~ m/^($type1)\s+($name)\s*$prototype_end/ ||
- $prototype =~ m/^($type2+)\s*($name)\s*$prototype_end/) {
- $return_type = $1;
- $declaration_name = $2;
- my $args = $3;
+ $prototype =~ m/^($type1)\s+($name)\s*$prototype_end/ ||
+ $prototype =~ m/^($type2+)\s*($name)\s*$prototype_end/) {
+ $return_type = $1;
+ $declaration_name = $2;
+ my $args = $3;
- create_parameterlist($args, ',', $file, $declaration_name);
+ create_parameterlist($args, ',', $file, $declaration_name);
} else {
- emit_warning("${file}:$.", "cannot understand function prototype: '$prototype'\n");
- return;
+ emit_warning("${file}:$.", "cannot understand function prototype: '$prototype'\n");
+ return;
}
if ($identifier ne $declaration_name) {
- emit_warning("${file}:$.", "expecting prototype for $identifier(). Prototype was for $declaration_name() instead\n");
- return;
+ emit_warning("${file}:$.", "expecting prototype for $identifier(). Prototype was for $declaration_name() instead\n");
+ return;
}
my $prms = join " ", @parameterlist;
@@ -1777,38 +1793,38 @@ sub dump_function($$) {
# -Wreturn mode.
# TODO: always perform the check.
if ($Wreturn && !$noret) {
- check_return_section($file, $declaration_name, $return_type);
+ check_return_section($file, $declaration_name, $return_type);
}
# The function parser can be called with a typedef parameter.
# Handle it.
if ($return_type =~ /typedef/) {
- output_declaration($declaration_name,
- 'function',
- {'function' => $declaration_name,
- 'typedef' => 1,
- 'module' => $modulename,
- 'functiontype' => $return_type,
- 'parameterlist' => \@parameterlist,
- 'parameterdescs' => \%parameterdescs,
- 'parametertypes' => \%parametertypes,
- 'sectionlist' => \@sectionlist,
- 'sections' => \%sections,
- 'purpose' => $declaration_purpose
- });
+ output_declaration($declaration_name,
+ 'function',
+ {'function' => $declaration_name,
+ 'typedef' => 1,
+ 'module' => $modulename,
+ 'functiontype' => $return_type,
+ 'parameterlist' => \@parameterlist,
+ 'parameterdescs' => \%parameterdescs,
+ 'parametertypes' => \%parametertypes,
+ 'sectionlist' => \@sectionlist,
+ 'sections' => \%sections,
+ 'purpose' => $declaration_purpose
+ });
} else {
- output_declaration($declaration_name,
- 'function',
- {'function' => $declaration_name,
- 'module' => $modulename,
- 'functiontype' => $return_type,
- 'parameterlist' => \@parameterlist,
- 'parameterdescs' => \%parameterdescs,
- 'parametertypes' => \%parametertypes,
- 'sectionlist' => \@sectionlist,
- 'sections' => \%sections,
- 'purpose' => $declaration_purpose
- });
+ output_declaration($declaration_name,
+ 'function',
+ {'function' => $declaration_name,
+ 'module' => $modulename,
+ 'functiontype' => $return_type,
+ 'parameterlist' => \@parameterlist,
+ 'parameterdescs' => \%parameterdescs,
+ 'parametertypes' => \%parametertypes,
+ 'sectionlist' => \@sectionlist,
+ 'sections' => \%sections,
+ 'purpose' => $declaration_purpose
+ });
}
}
@@ -1828,64 +1844,64 @@ sub reset_state {
}
sub tracepoint_munge($) {
- my $file = shift;
- my $tracepointname = 0;
- my $tracepointargs = 0;
-
- if ($prototype =~ m/TRACE_EVENT\((.*?),/) {
- $tracepointname = $1;
- }
- if ($prototype =~ m/DEFINE_SINGLE_EVENT\((.*?),/) {
- $tracepointname = $1;
- }
- if ($prototype =~ m/DEFINE_EVENT\((.*?),(.*?),/) {
- $tracepointname = $2;
- }
- $tracepointname =~ s/^\s+//; #strip leading whitespace
- if ($prototype =~ m/TP_PROTO\((.*?)\)/) {
- $tracepointargs = $1;
- }
- if (($tracepointname eq 0) || ($tracepointargs eq 0)) {
- emit_warning("${file}:$.", "Unrecognized tracepoint format: \n".
- "$prototype\n");
- } else {
- $prototype = "static inline void trace_$tracepointname($tracepointargs)";
- $identifier = "trace_$identifier";
- }
+ my $file = shift;
+ my $tracepointname = 0;
+ my $tracepointargs = 0;
+
+ if ($prototype =~ m/TRACE_EVENT\((.*?),/) {
+ $tracepointname = $1;
+ }
+ if ($prototype =~ m/DEFINE_SINGLE_EVENT\((.*?),/) {
+ $tracepointname = $1;
+ }
+ if ($prototype =~ m/DEFINE_EVENT\((.*?),(.*?),/) {
+ $tracepointname = $2;
+ }
+ $tracepointname =~ s/^\s+//; #strip leading whitespace
+ if ($prototype =~ m/TP_PROTO\((.*?)\)/) {
+ $tracepointargs = $1;
+ }
+ if (($tracepointname eq 0) || ($tracepointargs eq 0)) {
+ emit_warning("${file}:$.", "Unrecognized tracepoint format: \n".
+ "$prototype\n");
+ } else {
+ $prototype = "static inline void trace_$tracepointname($tracepointargs)";
+ $identifier = "trace_$identifier";
+ }
}
sub syscall_munge() {
- my $void = 0;
-
- $prototype =~ s@[\r\n]+@ @gos; # strip newlines/CR's
-## if ($prototype =~ m/SYSCALL_DEFINE0\s*\(\s*(a-zA-Z0-9_)*\s*\)/) {
- if ($prototype =~ m/SYSCALL_DEFINE0/) {
- $void = 1;
-## $prototype = "long sys_$1(void)";
- }
-
- $prototype =~ s/SYSCALL_DEFINE.*\(/long sys_/; # fix return type & func name
- if ($prototype =~ m/long (sys_.*?),/) {
- $prototype =~ s/,/\(/;
- } elsif ($void) {
- $prototype =~ s/\)/\(void\)/;
- }
-
- # now delete all of the odd-number commas in $prototype
- # so that arg types & arg names don't have a comma between them
- my $count = 0;
- my $len = length($prototype);
- if ($void) {
- $len = 0; # skip the for-loop
- }
- for (my $ix = 0; $ix < $len; $ix++) {
- if (substr($prototype, $ix, 1) eq ',') {
- $count++;
- if ($count % 2 == 1) {
- substr($prototype, $ix, 1) = ' ';
- }
- }
- }
+ my $void = 0;
+
+ $prototype =~ s@[\r\n]+@ @gos; # strip newlines/CR's
+## if ($prototype =~ m/SYSCALL_DEFINE0\s*\(\s*(a-zA-Z0-9_)*\s*\)/) {
+ if ($prototype =~ m/SYSCALL_DEFINE0/) {
+ $void = 1;
+## $prototype = "long sys_$1(void)";
+ }
+
+ $prototype =~ s/SYSCALL_DEFINE.*\(/long sys_/; # fix return type & func name
+ if ($prototype =~ m/long (sys_.*?),/) {
+ $prototype =~ s/,/\(/;
+ } elsif ($void) {
+ $prototype =~ s/\)/\(void\)/;
+ }
+
+ # now delete all of the odd-number commas in $prototype
+ # so that arg types & arg names don't have a comma between them
+ my $count = 0;
+ my $len = length($prototype);
+ if ($void) {
+ $len = 0; # skip the for-loop
+ }
+ for (my $ix = 0; $ix < $len; $ix++) {
+ if (substr($prototype, $ix, 1) eq ',') {
+ $count++;
+ if ($count % 2 == 1) {
+ substr($prototype, $ix, 1) = ' ';
+ }
+ }
+ }
}
sub process_proto_function($$) {
@@ -1894,32 +1910,31 @@ sub process_proto_function($$) {
$x =~ s@\/\/.*$@@gos; # strip C99-style comments to end of line
- if ($x =~ m#\s*/\*\s+MACDOC\s*#io || ($x =~ /^#/ && $x !~ /^#\s*define/)) {
- # do nothing
- }
- elsif ($x =~ /([^\{]*)/) {
- $prototype .= $1;
+ if ($x =~ /^#/ && $x !~ /^#\s*define/) {
+ # do nothing
+ } elsif ($x =~ /([^\{]*)/) {
+ $prototype .= $1;
}
if (($x =~ /\{/) || ($x =~ /\#\s*define/) || ($x =~ /;/)) {
- $prototype =~ s@/\*.*?\*/@@gos; # strip comments.
- $prototype =~ s@[\r\n]+@ @gos; # strip newlines/cr's.
- $prototype =~ s@^\s+@@gos; # strip leading spaces
+ $prototype =~ s@/\*.*?\*/@@gos; # strip comments.
+ $prototype =~ s@[\r\n]+@ @gos; # strip newlines/cr's.
+ $prototype =~ s@^\s+@@gos; # strip leading spaces
- # Handle prototypes for function pointers like:
- # int (*pcs_config)(struct foo)
- $prototype =~ s@^(\S+\s+)\(\s*\*(\S+)\)@$1$2@gos;
+ # Handle prototypes for function pointers like:
+ # int (*pcs_config)(struct foo)
+ $prototype =~ s@^(\S+\s+)\(\s*\*(\S+)\)@$1$2@gos;
- if ($prototype =~ /SYSCALL_DEFINE/) {
- syscall_munge();
- }
- if ($prototype =~ /TRACE_EVENT/ || $prototype =~ /DEFINE_EVENT/ ||
- $prototype =~ /DEFINE_SINGLE_EVENT/)
- {
- tracepoint_munge($file);
- }
- dump_function($prototype, $file);
- reset_state();
+ if ($prototype =~ /SYSCALL_DEFINE/) {
+ syscall_munge();
+ }
+ if ($prototype =~ /TRACE_EVENT/ || $prototype =~ /DEFINE_EVENT/ ||
+ $prototype =~ /DEFINE_SINGLE_EVENT/)
+ {
+ tracepoint_munge($file);
+ }
+ dump_function($prototype, $file);
+ reset_state();
}
}
@@ -1933,28 +1948,28 @@ sub process_proto_type($$) {
$x =~ s@\/\/.*$@@gos; # strip C99-style comments to end of line
if ($x =~ /^#/) {
- # To distinguish preprocessor directive from regular declaration later.
- $x .= ";";
+ # To distinguish preprocessor directive from regular declaration later.
+ $x .= ";";
}
while (1) {
- if ( $x =~ /([^\{\};]*)([\{\};])(.*)/ ) {
+ if ( $x =~ /([^\{\};]*)([\{\};])(.*)/ ) {
if( length $prototype ) {
$prototype .= " "
}
- $prototype .= $1 . $2;
- ($2 eq '{') && $brcount++;
- ($2 eq '}') && $brcount--;
- if (($2 eq ';') && ($brcount == 0)) {
- dump_declaration($prototype, $file);
- reset_state();
- last;
- }
- $x = $3;
- } else {
- $prototype .= $x;
- last;
- }
+ $prototype .= $1 . $2;
+ ($2 eq '{') && $brcount++;
+ ($2 eq '}') && $brcount--;
+ if (($2 eq ';') && ($brcount == 0)) {
+ dump_declaration($prototype, $file);
+ reset_state();
+ last;
+ }
+ $x = $3;
+ } else {
+ $prototype .= $x;
+ last;
+ }
}
}
@@ -1964,13 +1979,13 @@ sub map_filename($) {
my ($orig_file) = @_;
if (defined($ENV{'SRCTREE'})) {
- $file = "$ENV{'SRCTREE'}" . "/" . $orig_file;
+ $file = "$ENV{'SRCTREE'}" . "/" . $orig_file;
} else {
- $file = $orig_file;
+ $file = $orig_file;
}
if (defined($source_map{$file})) {
- $file = $source_map{$file};
+ $file = $source_map{$file};
}
return $file;
@@ -1981,20 +1996,20 @@ sub process_export_file($) {
my $file = map_filename($orig_file);
if (!open(IN,"<$file")) {
- print STDERR "Error: Cannot open file $file\n";
- ++$errors;
- return;
+ print STDERR "Error: Cannot open file $file\n";
+ ++$errors;
+ return;
}
while (<IN>) {
- if (/$export_symbol/) {
- next if (defined($nosymbol_table{$2}));
- $function_table{$2} = 1;
- }
- if (/$export_symbol_ns/) {
- next if (defined($nosymbol_table{$2}));
- $function_table{$2} = 1;
- }
+ if (/$export_symbol/) {
+ next if (defined($nosymbol_table{$2}));
+ $function_table{$2} = 1;
+ }
+ if (/$export_symbol_ns/) {
+ next if (defined($nosymbol_table{$2}));
+ $function_table{$2} = 1;
+ }
}
close(IN);
@@ -2007,9 +2022,9 @@ sub process_export_file($) {
#
sub process_normal() {
if (/$doc_start/o) {
- $state = STATE_NAME; # next line is always the function name
- $in_doc_sect = 0;
- $declaration_start_line = $. + 1;
+ $state = STATE_NAME; # next line is always the function name
+ $in_doc_sect = 0;
+ $declaration_start_line = $. + 1;
}
}
@@ -2021,80 +2036,80 @@ sub process_name($$) {
my $descr;
if (/$doc_block/o) {
- $state = STATE_DOCBLOCK;
- $contents = "";
- $new_start_line = $.;
-
- if ( $1 eq "" ) {
- $section = $section_intro;
- } else {
- $section = $1;
- }
+ $state = STATE_DOCBLOCK;
+ $contents = "";
+ $new_start_line = $.;
+
+ if ( $1 eq "" ) {
+ $section = $section_intro;
+ } else {
+ $section = $1;
+ }
} elsif (/$doc_decl/o) {
- $identifier = $1;
- my $is_kernel_comment = 0;
- my $decl_start = qr{$doc_com};
- # test for pointer declaration type, foo * bar() - desc
- my $fn_type = qr{\w+\s*\*\s*};
- my $parenthesis = qr{\(\w*\)};
- my $decl_end = qr{[-:].*};
- if (/^$decl_start([\w\s]+?)$parenthesis?\s*$decl_end?$/) {
- $identifier = $1;
- }
- if ($identifier =~ m/^(struct|union|enum|typedef)\b\s*(\S*)/) {
- $decl_type = $1;
- $identifier = $2;
- $is_kernel_comment = 1;
- }
- # Look for foo() or static void foo() - description; or misspelt
- # identifier
- elsif (/^$decl_start$fn_type?(\w+)\s*$parenthesis?\s*$decl_end?$/ ||
- /^$decl_start$fn_type?(\w+.*)$parenthesis?\s*$decl_end$/) {
- $identifier = $1;
- $decl_type = 'function';
- $identifier =~ s/^define\s+//;
- $is_kernel_comment = 1;
- }
- $identifier =~ s/\s+$//;
-
- $state = STATE_BODY;
- # if there's no @param blocks need to set up default section
- # here
- $contents = "";
- $section = $section_default;
- $new_start_line = $. + 1;
- if (/[-:](.*)/) {
- # strip leading/trailing/multiple spaces
- $descr= $1;
- $descr =~ s/^\s*//;
- $descr =~ s/\s*$//;
- $descr =~ s/\s+/ /g;
- $declaration_purpose = $descr;
- $state = STATE_BODY_MAYBE;
- } else {
- $declaration_purpose = "";
- }
-
- if (!$is_kernel_comment) {
- emit_warning("${file}:$.", "This comment starts with '/**', but isn't a kernel-doc comment. Refer Documentation/doc-guide/kernel-doc.rst\n$_");
- $state = STATE_NORMAL;
- }
-
- if (($declaration_purpose eq "") && $Wshort_desc) {
- emit_warning("${file}:$.", "missing initial short description on line:\n$_");
- }
-
- if ($identifier eq "" && $decl_type ne "enum") {
- emit_warning("${file}:$.", "wrong kernel-doc identifier on line:\n$_");
- $state = STATE_NORMAL;
- }
-
- if ($verbose) {
- print STDERR "${file}:$.: info: Scanning doc for $decl_type $identifier\n";
- }
+ $identifier = $1;
+ my $is_kernel_comment = 0;
+ my $decl_start = qr{$doc_com};
+ # test for pointer declaration type, foo * bar() - desc
+ my $fn_type = qr{\w+\s*\*\s*};
+ my $parenthesis = qr{\(\w*\)};
+ my $decl_end = qr{[-:].*};
+ if (/^$decl_start([\w\s]+?)$parenthesis?\s*$decl_end?$/) {
+ $identifier = $1;
+ }
+ if ($identifier =~ m/^(struct|union|enum|typedef)\b\s*(\S*)/) {
+ $decl_type = $1;
+ $identifier = $2;
+ $is_kernel_comment = 1;
+ }
+ # Look for foo() or static void foo() - description; or misspelt
+ # identifier
+ elsif (/^$decl_start$fn_type?(\w+)\s*$parenthesis?\s*$decl_end?$/ ||
+ /^$decl_start$fn_type?(\w+.*)$parenthesis?\s*$decl_end$/) {
+ $identifier = $1;
+ $decl_type = 'function';
+ $identifier =~ s/^define\s+//;
+ $is_kernel_comment = 1;
+ }
+ $identifier =~ s/\s+$//;
+
+ $state = STATE_BODY;
+ # if there's no @param blocks need to set up default section
+ # here
+ $contents = "";
+ $section = $section_default;
+ $new_start_line = $. + 1;
+ if (/[-:](.*)/) {
+ # strip leading/trailing/multiple spaces
+ $descr= $1;
+ $descr =~ s/^\s*//;
+ $descr =~ s/\s*$//;
+ $descr =~ s/\s+/ /g;
+ $declaration_purpose = $descr;
+ $state = STATE_BODY_MAYBE;
+ } else {
+ $declaration_purpose = "";
+ }
+
+ if (!$is_kernel_comment) {
+ emit_warning("${file}:$.", "This comment starts with '/**', but isn't a kernel-doc comment. Refer Documentation/doc-guide/kernel-doc.rst\n$_");
+ $state = STATE_NORMAL;
+ }
+
+ if (($declaration_purpose eq "") && $Wshort_desc) {
+ emit_warning("${file}:$.", "missing initial short description on line:\n$_");
+ }
+
+ if ($identifier eq "" && $decl_type ne "enum") {
+ emit_warning("${file}:$.", "wrong kernel-doc identifier on line:\n$_");
+ $state = STATE_NORMAL;
+ }
+
+ if ($verbose) {
+ print STDERR "${file}:$.: info: Scanning doc for $decl_type $identifier\n";
+ }
} else {
- emit_warning("${file}:$.", "Cannot understand $_ on line $. - I thought it was a doc line\n");
- $state = STATE_NORMAL;
+ emit_warning("${file}:$.", "Cannot understand $_ on line $. - I thought it was a doc line\n");
+ $state = STATE_NORMAL;
}
}
@@ -2106,101 +2121,102 @@ sub process_body($$) {
my $file = shift;
if ($state == STATE_BODY_WITH_BLANK_LINE && /^\s*\*\s?\S/) {
- dump_section($file, $section, $contents);
- $section = $section_default;
- $new_start_line = $.;
- $contents = "";
+ dump_section($file, $section, $contents);
+ $section = $section_default;
+ $new_start_line = $.;
+ $contents = "";
}
if (/$doc_sect/i) { # case insensitive for supported section names
- $newsection = $1;
- $newcontents = $2;
-
- # map the supported section names to the canonical names
- if ($newsection =~ m/^description$/i) {
- $newsection = $section_default;
- } elsif ($newsection =~ m/^context$/i) {
- $newsection = $section_context;
- } elsif ($newsection =~ m/^returns?$/i) {
- $newsection = $section_return;
- } elsif ($newsection =~ m/^\@return$/) {
- # special: @return is a section, not a param description
- $newsection = $section_return;
- }
-
- if (($contents ne "") && ($contents ne "\n")) {
- if (!$in_doc_sect && $Wcontents_before_sections) {
- emit_warning("${file}:$.", "contents before sections\n");
- }
- dump_section($file, $section, $contents);
- $section = $section_default;
- }
-
- $in_doc_sect = 1;
- $state = STATE_BODY;
- $contents = $newcontents;
- $new_start_line = $.;
- while (substr($contents, 0, 1) eq " ") {
- $contents = substr($contents, 1);
- }
- if ($contents ne "") {
- $contents .= "\n";
- }
- $section = $newsection;
- $leading_space = undef;
+ $in_doc_sect = 1;
+ $newsection = $1;
+ $newcontents = $2;
+
+ # map the supported section names to the canonical names
+ if ($newsection =~ m/^description$/i) {
+ $newsection = $section_default;
+ } elsif ($newsection =~ m/^context$/i) {
+ $newsection = $section_context;
+ } elsif ($newsection =~ m/^returns?$/i) {
+ $newsection = $section_return;
+ } elsif ($newsection =~ m/^\@return$/) {
+ # special: @return is a section, not a param description
+ $newsection = $section_return;
+ }
+
+ if (($contents ne "") && ($contents ne "\n")) {
+ if (!$in_doc_sect && $Wcontents_before_sections) {
+ emit_warning("${file}:$.", "contents before sections\n");
+ }
+ dump_section($file, $section, $contents);
+ $section = $section_default;
+ }
+
+ $in_doc_sect = 1;
+ $state = STATE_BODY;
+ $contents = $newcontents;
+ $new_start_line = $.;
+ while (substr($contents, 0, 1) eq " ") {
+ $contents = substr($contents, 1);
+ }
+ if ($contents ne "") {
+ $contents .= "\n";
+ }
+ $section = $newsection;
+ $leading_space = undef;
} elsif (/$doc_end/) {
- if (($contents ne "") && ($contents ne "\n")) {
- dump_section($file, $section, $contents);
- $section = $section_default;
- $contents = "";
- }
- # look for doc_com + <text> + doc_end:
- if ($_ =~ m'\s*\*\s*[a-zA-Z_0-9:\.]+\*/') {
- emit_warning("${file}:$.", "suspicious ending line: $_");
- }
-
- $prototype = "";
- $state = STATE_PROTO;
- $brcount = 0;
+ if (($contents ne "") && ($contents ne "\n")) {
+ dump_section($file, $section, $contents);
+ $section = $section_default;
+ $contents = "";
+ }
+ # look for doc_com + <text> + doc_end:
+ if ($_ =~ m'\s*\*\s*[a-zA-Z_0-9:\.]+\*/') {
+ emit_warning("${file}:$.", "suspicious ending line: $_");
+ }
+
+ $prototype = "";
+ $state = STATE_PROTO;
+ $brcount = 0;
$new_start_line = $. + 1;
} elsif (/$doc_content/) {
- if ($1 eq "") {
- if ($section eq $section_context) {
- dump_section($file, $section, $contents);
- $section = $section_default;
- $contents = "";
- $new_start_line = $.;
- $state = STATE_BODY;
- } else {
- if ($section ne $section_default) {
- $state = STATE_BODY_WITH_BLANK_LINE;
- } else {
- $state = STATE_BODY;
- }
- $contents .= "\n";
- }
- } elsif ($state == STATE_BODY_MAYBE) {
- # Continued declaration purpose
- chomp($declaration_purpose);
- $declaration_purpose .= " " . $1;
- $declaration_purpose =~ s/\s+/ /g;
- } else {
- my $cont = $1;
- if ($section =~ m/^@/ || $section eq $section_context) {
- if (!defined $leading_space) {
- if ($cont =~ m/^(\s+)/) {
- $leading_space = $1;
- } else {
- $leading_space = "";
- }
- }
- $cont =~ s/^$leading_space//;
- }
- $contents .= $cont . "\n";
- }
+ if ($1 eq "") {
+ if ($section eq $section_context) {
+ dump_section($file, $section, $contents);
+ $section = $section_default;
+ $contents = "";
+ $new_start_line = $.;
+ $state = STATE_BODY;
+ } else {
+ if ($section ne $section_default) {
+ $state = STATE_BODY_WITH_BLANK_LINE;
+ } else {
+ $state = STATE_BODY;
+ }
+ $contents .= "\n";
+ }
+ } elsif ($state == STATE_BODY_MAYBE) {
+ # Continued declaration purpose
+ chomp($declaration_purpose);
+ $declaration_purpose .= " " . $1;
+ $declaration_purpose =~ s/\s+/ /g;
+ } else {
+ my $cont = $1;
+ if ($section =~ m/^@/ || $section eq $section_context) {
+ if (!defined $leading_space) {
+ if ($cont =~ m/^(\s+)/) {
+ $leading_space = $1;
+ } else {
+ $leading_space = "";
+ }
+ }
+ $cont =~ s/^$leading_space//;
+ }
+ $contents .= $cont . "\n";
+ }
} else {
- # i dont know - bad line? ignore.
- emit_warning("${file}:$.", "bad line: $_");
+ # i dont know - bad line? ignore.
+ emit_warning("${file}:$.", "bad line: $_");
}
}
@@ -2212,21 +2228,21 @@ sub process_proto($$) {
my $file = shift;
if (/$doc_inline_oneline/) {
- $section = $1;
- $contents = $2;
- if ($contents ne "") {
- $contents .= "\n";
- dump_section($file, $section, $contents);
- $section = $section_default;
- $contents = "";
- }
+ $section = $1;
+ $contents = $2;
+ if ($contents ne "") {
+ $contents .= "\n";
+ dump_section($file, $section, $contents);
+ $section = $section_default;
+ $contents = "";
+ }
} elsif (/$doc_inline_start/) {
- $state = STATE_INLINE;
- $inline_doc_state = STATE_INLINE_NAME;
+ $state = STATE_INLINE;
+ $inline_doc_state = STATE_INLINE_NAME;
} elsif ($decl_type eq 'function') {
- process_proto_function($_, $file);
+ process_proto_function($_, $file);
} else {
- process_proto_type($_, $file);
+ process_proto_type($_, $file);
}
}
@@ -2237,23 +2253,23 @@ sub process_docblock($$) {
my $file = shift;
if (/$doc_end/) {
- dump_doc_section($file, $section, $contents);
- $section = $section_default;
- $contents = "";
- $function = "";
- %parameterdescs = ();
- %parametertypes = ();
- @parameterlist = ();
- %sections = ();
- @sectionlist = ();
- $prototype = "";
- $state = STATE_NORMAL;
+ dump_doc_section($file, $section, $contents);
+ $section = $section_default;
+ $contents = "";
+ $function = "";
+ %parameterdescs = ();
+ %parametertypes = ();
+ @parameterlist = ();
+ %sections = ();
+ @sectionlist = ();
+ $prototype = "";
+ $state = STATE_NORMAL;
} elsif (/$doc_content/) {
- if ( $1 eq "" ) {
- $contents .= $blankline;
- } else {
- $contents .= $1 . "\n";
- }
+ if ( $1 eq "" ) {
+ $contents .= $blankline;
+ } else {
+ $contents .= $1 . "\n";
+ }
}
}
@@ -2265,37 +2281,37 @@ sub process_inline($$) {
# First line (state 1) needs to be a @parameter
if ($inline_doc_state == STATE_INLINE_NAME && /$doc_inline_sect/o) {
- $section = $1;
- $contents = $2;
- $new_start_line = $.;
- if ($contents ne "") {
- while (substr($contents, 0, 1) eq " ") {
- $contents = substr($contents, 1);
- }
- $contents .= "\n";
- }
- $inline_doc_state = STATE_INLINE_TEXT;
- # Documentation block end */
+ $section = $1;
+ $contents = $2;
+ $new_start_line = $.;
+ if ($contents ne "") {
+ while (substr($contents, 0, 1) eq " ") {
+ $contents = substr($contents, 1);
+ }
+ $contents .= "\n";
+ }
+ $inline_doc_state = STATE_INLINE_TEXT;
+ # Documentation block end */
} elsif (/$doc_inline_end/) {
- if (($contents ne "") && ($contents ne "\n")) {
- dump_section($file, $section, $contents);
- $section = $section_default;
- $contents = "";
- }
- $state = STATE_PROTO;
- $inline_doc_state = STATE_INLINE_NA;
- # Regular text
+ if (($contents ne "") && ($contents ne "\n")) {
+ dump_section($file, $section, $contents);
+ $section = $section_default;
+ $contents = "";
+ }
+ $state = STATE_PROTO;
+ $inline_doc_state = STATE_INLINE_NA;
+ # Regular text
} elsif (/$doc_content/) {
- if ($inline_doc_state == STATE_INLINE_TEXT) {
- $contents .= $1 . "\n";
- # nuke leading blank lines
- if ($contents =~ /^\s*$/) {
- $contents = "";
- }
- } elsif ($inline_doc_state == STATE_INLINE_NAME) {
- $inline_doc_state = STATE_INLINE_ERROR;
- emit_warning("${file}:$.", "Incorrect use of kernel-doc format: $_");
- }
+ if ($inline_doc_state == STATE_INLINE_TEXT) {
+ $contents .= $1 . "\n";
+ # nuke leading blank lines
+ if ($contents =~ /^\s*$/) {
+ $contents = "";
+ }
+ } elsif ($inline_doc_state == STATE_INLINE_NAME) {
+ $inline_doc_state = STATE_INLINE_ERROR;
+ emit_warning("${file}:$.", "Incorrect use of kernel-doc format: $_");
+ }
}
}
@@ -2308,54 +2324,53 @@ sub process_file($) {
$file = map_filename($orig_file);
if (!open(IN_FILE,"<$file")) {
- print STDERR "Error: Cannot open file $file\n";
- ++$errors;
- return;
+ print STDERR "Error: Cannot open file $file\n";
+ ++$errors;
+ return;
}
$. = 1;
$section_counter = 0;
while (<IN_FILE>) {
- while (s/\\\s*$//) {
- $_ .= <IN_FILE>;
- }
- # Replace tabs by spaces
+ while (!/^ \*/ && s/\\\s*$//) {
+ $_ .= <IN_FILE>;
+ }
+ # Replace tabs by spaces
while ($_ =~ s/\t+/' ' x (length($&) * 8 - length($`) % 8)/e) {};
- # Hand this line to the appropriate state handler
- if ($state == STATE_NORMAL) {
- process_normal();
- } elsif ($state == STATE_NAME) {
- process_name($file, $_);
- } elsif ($state == STATE_BODY || $state == STATE_BODY_MAYBE ||
- $state == STATE_BODY_WITH_BLANK_LINE) {
- process_body($file, $_);
- } elsif ($state == STATE_INLINE) { # scanning for inline parameters
- process_inline($file, $_);
- } elsif ($state == STATE_PROTO) {
- process_proto($file, $_);
- } elsif ($state == STATE_DOCBLOCK) {
- process_docblock($file, $_);
- }
+ # Hand this line to the appropriate state handler
+ if ($state == STATE_NORMAL) {
+ process_normal();
+ } elsif ($state == STATE_NAME) {
+ process_name($file, $_);
+ } elsif ($state == STATE_BODY || $state == STATE_BODY_MAYBE ||
+ $state == STATE_BODY_WITH_BLANK_LINE) {
+ process_body($file, $_);
+ } elsif ($state == STATE_INLINE) { # scanning for inline parameters
+ process_inline($file, $_);
+ } elsif ($state == STATE_PROTO) {
+ process_proto($file, $_);
+ } elsif ($state == STATE_DOCBLOCK) {
+ process_docblock($file, $_);
+ }
}
# Make sure we got something interesting.
if ($initial_section_counter == $section_counter && $
- output_mode ne "none") {
- if ($output_selection == OUTPUT_INCLUDE) {
- emit_warning("${file}:1", "'$_' not found\n")
- for keys %function_table;
- }
- else {
- emit_warning("${file}:1", "no structured comments found\n");
- }
+ output_mode ne "none") {
+ if ($output_selection == OUTPUT_INCLUDE) {
+ emit_warning("${file}:1", "'$_' not found\n")
+ for keys %function_table;
+ } else {
+ emit_warning("${file}:1", "no structured comments found\n");
+ }
}
close IN_FILE;
}
if ($output_mode eq "rst") {
- get_sphinx_version() if (!$sphinx_major);
+ get_sphinx_version() if (!$sphinx_major);
}
$kernelversion = get_kernel_version();
@@ -2372,14 +2387,14 @@ for (my $k = 0; $k < @highlights; $k++) {
# Read the file that maps relative names to absolute names for
# separate source and object directories and for shadow trees.
if (open(SOURCE_MAP, "<.tmp_filelist.txt")) {
- my ($relname, $absname);
- while(<SOURCE_MAP>) {
- chop();
- ($relname, $absname) = (split())[0..1];
- $relname =~ s:^/+::;
- $source_map{$relname} = $absname;
- }
- close(SOURCE_MAP);
+ my ($relname, $absname);
+ while(<SOURCE_MAP>) {
+ chop();
+ ($relname, $absname) = (split())[0..1];
+ $relname =~ s:^/+::;
+ $source_map{$relname} = $absname;
+ }
+ close(SOURCE_MAP);
}
if ($output_selection == OUTPUT_EXPORTED ||
@@ -2388,8 +2403,8 @@ if ($output_selection == OUTPUT_EXPORTED ||
push(@export_file_list, @ARGV);
foreach (@export_file_list) {
- chomp;
- process_export_file($_);
+ chomp;
+ process_export_file($_);
}
}
@@ -2398,10 +2413,10 @@ foreach (@ARGV) {
process_file($_);
}
if ($verbose && $errors) {
- print STDERR "$errors errors\n";
+ print STDERR "$errors errors\n";
}
if ($verbose && $warnings) {
- print STDERR "$warnings warnings\n";
+ print STDERR "$warnings warnings\n";
}
if ($Werror && $warnings) {
diff --git a/scripts/leaking_addresses.pl b/scripts/leaking_addresses.pl
index e695634d153d..8e992b18bcd9 100755
--- a/scripts/leaking_addresses.pl
+++ b/scripts/leaking_addresses.pl
@@ -23,6 +23,7 @@ use strict;
use POSIX;
use File::Basename;
use File::Spec;
+use File::Temp qw/tempfile/;
use Cwd 'abs_path';
use Term::ANSIColor qw(:constants);
use Getopt::Long qw(:config no_auto_abbrev);
@@ -51,10 +52,13 @@ my $input_raw = ""; # Read raw results from file instead of scanning.
my $suppress_dmesg = 0; # Don't show dmesg in output.
my $squash_by_path = 0; # Summary report grouped by absolute path.
my $squash_by_filename = 0; # Summary report grouped by filename.
+my $kallsyms_file = ""; # Kernel symbols file.
my $kernel_config_file = ""; # Kernel configuration file.
my $opt_32bit = 0; # Scan 32-bit kernel.
my $page_offset_32bit = 0; # Page offset for 32-bit kernel.
+my @kallsyms = ();
+
# Skip these absolute paths.
my @skip_abs = (
'/proc/kmsg',
@@ -95,6 +99,8 @@ Options:
--squash-by-path Show one result per unique path.
--squash-by-filename Show one result per unique filename.
--kernel-config-file=<file> Kernel configuration file (e.g /boot/config)
+ --kallsyms=<file> Read kernel symbol addresses from file (for
+ scanning binary files).
--32-bit Scan 32-bit kernel.
--page-offset-32-bit=o Page offset (for 32-bit kernel 0xABCD1234).
-d, --debug Display debugging output.
@@ -115,6 +121,7 @@ GetOptions(
'squash-by-path' => \$squash_by_path,
'squash-by-filename' => \$squash_by_filename,
'raw' => \$raw,
+ 'kallsyms=s' => \$kallsyms_file,
'kernel-config-file=s' => \$kernel_config_file,
'32-bit' => \$opt_32bit,
'page-offset-32-bit=o' => \$page_offset_32bit,
@@ -155,6 +162,25 @@ if ($output_raw) {
select $fh;
}
+if ($kallsyms_file) {
+ open my $fh, '<', $kallsyms_file or die "$0: $kallsyms_file: $!\n";
+ while (<$fh>) {
+ chomp;
+ my @entry = split / /, $_;
+ my $addr_text = $entry[0];
+ if ($addr_text !~ /^0/) {
+ # TODO: Why is hex() so impossibly slow?
+ my $addr = hex($addr_text);
+ my $symbol = $entry[2];
+ # Only keep kernel text addresses.
+ my $long = pack("J", $addr);
+ my $entry = [$long, $symbol];
+ push @kallsyms, $entry;
+ }
+ }
+ close $fh;
+}
+
parse_dmesg();
walk(@DIRS);
@@ -221,6 +247,7 @@ sub get_kernel_config_option
{
my ($option) = @_;
my $value = "";
+ my $tmp_fh;
my $tmp_file = "";
my @config_files;
@@ -228,7 +255,8 @@ sub get_kernel_config_option
if ($kernel_config_file ne "") {
@config_files = ($kernel_config_file);
} elsif (-R "/proc/config.gz") {
- my $tmp_file = "/tmp/tmpkconf";
+ ($tmp_fh, $tmp_file) = tempfile("config.gz-XXXXXX",
+ UNLINK => 1);
if (system("gunzip < /proc/config.gz > $tmp_file")) {
dprint("system(gunzip < /proc/config.gz) failed\n");
@@ -250,10 +278,6 @@ sub get_kernel_config_option
}
}
- if ($tmp_file ne "") {
- system("rm -f $tmp_file");
- }
-
return $value;
}
@@ -285,9 +309,10 @@ sub is_false_positive
return is_false_positive_32bit($match);
}
- # 64 bit false positives.
-
- if ($match =~ '\b(0x)?(f|F){16}\b' or
+ # Ignore 64 bit false positives:
+ # 0xfffffffffffffff[0-f]
+ # 0x0000000000000000
+ if ($match =~ '\b(0x)?(f|F){15}[0-9a-f]\b' or
$match =~ '\b(0x)?0{16}\b') {
return 1;
}
@@ -304,7 +329,7 @@ sub is_false_positive_32bit
my ($match) = @_;
state $page_offset = get_page_offset();
- if ($match =~ '\b(0x)?(f|F){8}\b') {
+ if ($match =~ '\b(0x)?(f|F){7}[0-9a-f]\b') {
return 1;
}
@@ -347,18 +372,23 @@ sub is_in_vsyscall_memory_region
# True if argument potentially contains a kernel address.
sub may_leak_address
{
- my ($line) = @_;
+ my ($path, $line) = @_;
my $address_re;
- # Signal masks.
+ # Ignore Signal masks.
if ($line =~ '^SigBlk:' or
$line =~ '^SigIgn:' or
$line =~ '^SigCgt:') {
return 0;
}
- if ($line =~ '\bKEY=[[:xdigit:]]{14} [[:xdigit:]]{16} [[:xdigit:]]{16}\b' or
- $line =~ '\b[[:xdigit:]]{14} [[:xdigit:]]{16} [[:xdigit:]]{16}\b') {
+ # Ignore input device reporting.
+ # /proc/bus/input/devices: B: KEY=402000000 3803078f800d001 feffffdfffefffff fffffffffffffffe
+ # /sys/devices/platform/i8042/serio0/input/input1/uevent: KEY=402000000 3803078f800d001 feffffdfffefffff fffffffffffffffe
+ # /sys/devices/platform/i8042/serio0/input/input1/capabilities/key: 402000000 3803078f800d001 feffffdfffefffff fffffffffffffffe
+ if ($line =~ '\bKEY=[[:xdigit:]]{9,14} [[:xdigit:]]{16} [[:xdigit:]]{16}\b' or
+ ($path =~ '\bkey$' and
+ $line =~ '\b[[:xdigit:]]{9,14} [[:xdigit:]]{16} [[:xdigit:]]{16}\b')) {
return 0;
}
@@ -401,7 +431,7 @@ sub parse_dmesg
{
open my $cmd, '-|', 'dmesg';
while (<$cmd>) {
- if (may_leak_address($_)) {
+ if (may_leak_address("dmesg", $_)) {
print 'dmesg: ' . $_;
}
}
@@ -442,6 +472,25 @@ sub timed_parse_file
}
}
+sub parse_binary
+{
+ my ($file) = @_;
+
+ open my $fh, "<:raw", $file or return;
+ local $/ = undef;
+ my $bytes = <$fh>;
+ close $fh;
+
+ foreach my $entry (@kallsyms) {
+ my $addr = $entry->[0];
+ my $symbol = $entry->[1];
+ my $offset = index($bytes, $addr);
+ if ($offset != -1) {
+ printf("$file: $symbol @ $offset\n");
+ }
+ }
+}
+
sub parse_file
{
my ($file) = @_;
@@ -451,13 +500,22 @@ sub parse_file
}
if (! -T $file) {
+ if ($file =~ m|^/sys/kernel/btf/| or
+ $file =~ m|^/sys/devices/pci| or
+ $file =~ m|^/sys/firmware/efi/efivars/| or
+ $file =~ m|^/proc/bus/pci/|) {
+ return;
+ }
+ if (scalar @kallsyms > 0) {
+ parse_binary($file);
+ }
return;
}
open my $fh, "<", $file or return;
while ( <$fh> ) {
chomp;
- if (may_leak_address($_)) {
+ if (may_leak_address($file, $_)) {
printf("$file: $_\n");
}
}
@@ -469,7 +527,7 @@ sub check_path_for_leaks
{
my ($path) = @_;
- if (may_leak_address($path)) {
+ if (may_leak_address($path, $path)) {
printf("Path name may contain address: $path\n");
}
}
diff --git a/scripts/link-vmlinux.sh b/scripts/link-vmlinux.sh
index a432b171be82..7862a8101747 100755
--- a/scripts/link-vmlinux.sh
+++ b/scripts/link-vmlinux.sh
@@ -135,8 +135,13 @@ gen_btf()
${OBJCOPY} --only-section=.BTF --set-section-flags .BTF=alloc,readonly \
--strip-all ${1} ${2} 2>/dev/null
# Change e_type to ET_REL so that it can be used to link final vmlinux.
- # Unlike GNU ld, lld does not allow an ET_EXEC input.
- printf '\1' | dd of=${2} conv=notrunc bs=1 seek=16 status=none
+ # GNU ld 2.35+ and lld do not allow an ET_EXEC input.
+ if is_enabled CONFIG_CPU_BIG_ENDIAN; then
+ et_rel='\0\1'
+ else
+ et_rel='\1\0'
+ fi
+ printf "${et_rel}" | dd of=${2} conv=notrunc bs=1 seek=16 status=none
}
# Create ${2} .S file with all symbols from the ${1} object file
diff --git a/scripts/min-tool-version.sh b/scripts/min-tool-version.sh
index d65ab8bfeaf4..5927cc6b7de3 100755
--- a/scripts/min-tool-version.sh
+++ b/scripts/min-tool-version.sh
@@ -26,12 +26,14 @@ gcc)
llvm)
if [ "$SRCARCH" = s390 ]; then
echo 15.0.0
+ elif [ "$SRCARCH" = loongarch ]; then
+ echo 18.0.0
else
- echo 11.0.0
+ echo 13.0.1
fi
;;
rustc)
- echo 1.71.1
+ echo 1.76.0
;;
bindgen)
echo 0.65.1
diff --git a/scripts/mksysmap b/scripts/mksysmap
index 9ba1c9da0a40..57ff5656d566 100755
--- a/scripts/mksysmap
+++ b/scripts/mksysmap
@@ -48,17 +48,8 @@ ${NM} -n ${1} | sed >${2} -e "
/ __kvm_nvhe_\\$/d
/ __kvm_nvhe_\.L/d
-# arm64 lld
-/ __AArch64ADRPThunk_/d
-
-# arm lld
-/ __ARMV5PILongThunk_/d
-/ __ARMV7PILongThunk_/d
-/ __ThumbV7PILongThunk_/d
-
-# mips lld
-/ __LA25Thunk_/d
-/ __microLA25Thunk_/d
+# lld arm/aarch64/mips thunks
+/ __[[:alnum:]]*Thunk_/d
# CFI type identifiers
/ __kcfi_typeid_/d
diff --git a/scripts/mod/Makefile b/scripts/mod/Makefile
index c9e38ad937fd..3c54125eb373 100644
--- a/scripts/mod/Makefile
+++ b/scripts/mod/Makefile
@@ -5,7 +5,7 @@ CFLAGS_REMOVE_empty.o += $(CC_FLAGS_LTO)
hostprogs-always-y += modpost mk_elfconfig
always-y += empty.o
-modpost-objs := modpost.o file2alias.o sumversion.o
+modpost-objs := modpost.o file2alias.o sumversion.o symsearch.o
devicetable-offsets-file := devicetable-offsets.h
@@ -16,7 +16,7 @@ targets += $(devicetable-offsets-file) devicetable-offsets.s
# dependencies on generated files need to be listed explicitly
-$(obj)/modpost.o $(obj)/file2alias.o $(obj)/sumversion.o: $(obj)/elfconfig.h
+$(obj)/modpost.o $(obj)/file2alias.o $(obj)/sumversion.o $(obj)/symsearch.o: $(obj)/elfconfig.h
$(obj)/file2alias.o: $(obj)/$(devicetable-offsets-file)
quiet_cmd_elfconfig = MKELF $@
diff --git a/scripts/mod/devicetable-offsets.c b/scripts/mod/devicetable-offsets.c
index abe65f8968dd..518200813d4e 100644
--- a/scripts/mod/devicetable-offsets.c
+++ b/scripts/mod/devicetable-offsets.c
@@ -265,7 +265,17 @@ int main(void)
DEVID(cdx_device_id);
DEVID_FIELD(cdx_device_id, vendor);
DEVID_FIELD(cdx_device_id, device);
+ DEVID_FIELD(cdx_device_id, subvendor);
+ DEVID_FIELD(cdx_device_id, subdevice);
+ DEVID_FIELD(cdx_device_id, class);
+ DEVID_FIELD(cdx_device_id, class_mask);
DEVID_FIELD(cdx_device_id, override_only);
+ DEVID(vchiq_device_id);
+ DEVID_FIELD(vchiq_device_id, name);
+
+ DEVID(coreboot_device_id);
+ DEVID_FIELD(coreboot_device_id, tag);
+
return 0;
}
diff --git a/scripts/mod/file2alias.c b/scripts/mod/file2alias.c
index 7056751c29b1..5d1c61fa5a55 100644
--- a/scripts/mod/file2alias.c
+++ b/scripts/mod/file2alias.c
@@ -1348,13 +1348,13 @@ static int do_typec_entry(const char *filename, void *symval, char *alias)
/* Looks like: tee:uuid */
static int do_tee_entry(const char *filename, void *symval, char *alias)
{
- DEF_FIELD(symval, tee_client_device_id, uuid);
+ DEF_FIELD_ADDR(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]);
+ 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;
@@ -1401,10 +1401,10 @@ static int do_mhi_ep_entry(const char *filename, void *symval, char *alias)
/* Looks like: ishtp:{guid} */
static int do_ishtp_entry(const char *filename, void *symval, char *alias)
{
- DEF_FIELD(symval, ishtp_device_id, guid);
+ DEF_FIELD_ADDR(symval, ishtp_device_id, guid);
strcpy(alias, ISHTP_MODULE_PREFIX "{");
- add_guid(alias, guid);
+ add_guid(alias, *guid);
strcat(alias, "}");
return 1;
@@ -1458,6 +1458,10 @@ static int do_cdx_entry(const char *filename, void *symval,
{
DEF_FIELD(symval, cdx_device_id, vendor);
DEF_FIELD(symval, cdx_device_id, device);
+ DEF_FIELD(symval, cdx_device_id, subvendor);
+ DEF_FIELD(symval, cdx_device_id, subdevice);
+ DEF_FIELD(symval, cdx_device_id, class);
+ DEF_FIELD(symval, cdx_device_id, class_mask);
DEF_FIELD(symval, cdx_device_id, override_only);
switch (override_only) {
@@ -1475,6 +1479,27 @@ static int do_cdx_entry(const char *filename, void *symval,
ADD(alias, "v", vendor != CDX_ANY_ID, vendor);
ADD(alias, "d", device != CDX_ANY_ID, device);
+ ADD(alias, "sv", subvendor != CDX_ANY_ID, subvendor);
+ ADD(alias, "sd", subdevice != CDX_ANY_ID, subdevice);
+ ADD(alias, "c", class_mask == 0xFFFFFF, class);
+
+ return 1;
+}
+
+static int do_vchiq_entry(const char *filename, void *symval, char *alias)
+{
+ DEF_FIELD_ADDR(symval, vchiq_device_id, name);
+ sprintf(alias, "vchiq:%s", *name);
+
+ return 1;
+}
+
+/* Looks like: coreboot:tN */
+static int do_coreboot_entry(const char *filename, void *symval, char *alias)
+{
+ DEF_FIELD(symval, coreboot_device_id, tag);
+ sprintf(alias, "coreboot:t%08X", tag);
+
return 1;
}
@@ -1558,6 +1583,8 @@ static const struct devtable devtable[] = {
{"dfl", SIZE_dfl_device_id, do_dfl_entry},
{"ishtp", SIZE_ishtp_device_id, do_ishtp_entry},
{"cdx", SIZE_cdx_device_id, do_cdx_entry},
+ {"vchiq", SIZE_vchiq_device_id, do_vchiq_entry},
+ {"coreboot", SIZE_coreboot_device_id, do_coreboot_entry},
};
/* Create MODULE_ALIAS() statements.
diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c
index b3dee80497cb..2f5b91da5afa 100644
--- a/scripts/mod/modpost.c
+++ b/scripts/mod/modpost.c
@@ -22,7 +22,6 @@
#include <errno.h>
#include "modpost.h"
#include "../../include/linux/license.h"
-#include "../../include/linux/module_symbol.h"
static bool module_enabled;
/* Are we using CONFIG_MODVERSIONS? */
@@ -61,8 +60,7 @@ static unsigned int nr_unresolved;
#define MODULE_NAME_LEN (64 - sizeof(Elf_Addr))
-void __attribute__((format(printf, 2, 3)))
-modpost_log(enum loglevel loglevel, const char *fmt, ...)
+void modpost_log(enum loglevel loglevel, const char *fmt, ...)
{
va_list arglist;
@@ -72,9 +70,7 @@ modpost_log(enum loglevel loglevel, const char *fmt, ...)
break;
case LOG_ERROR:
fprintf(stderr, "ERROR: ");
- break;
- case LOG_FATAL:
- fprintf(stderr, "FATAL: ");
+ error_occurred = true;
break;
default: /* invalid loglevel, ignore */
break;
@@ -85,11 +81,6 @@ modpost_log(enum loglevel loglevel, const char *fmt, ...)
va_start(arglist, fmt);
vfprintf(stderr, fmt, arglist);
va_end(arglist);
-
- if (loglevel == LOG_FATAL)
- exit(1);
- if (loglevel == LOG_ERROR)
- error_occurred = true;
}
static inline bool strends(const char *str, const char *postfix)
@@ -475,11 +466,9 @@ static int parse_elf(struct elf_info *info, const char *filename)
fatal("%s: not relocatable object.", filename);
/* Check if file offset is correct */
- if (hdr->e_shoff > info->size) {
+ if (hdr->e_shoff > info->size)
fatal("section header offset=%lu in file '%s' is bigger than filesize=%zu\n",
(unsigned long)hdr->e_shoff, filename, info->size);
- return 0;
- }
if (hdr->e_shnum == SHN_UNDEF) {
/*
@@ -517,12 +506,11 @@ static int parse_elf(struct elf_info *info, const char *filename)
const char *secname;
int nobits = sechdrs[i].sh_type == SHT_NOBITS;
- if (!nobits && sechdrs[i].sh_offset > info->size) {
+ if (!nobits && sechdrs[i].sh_offset > info->size)
fatal("%s is truncated. sechdrs[i].sh_offset=%lu > sizeof(*hrd)=%zu\n",
filename, (unsigned long)sechdrs[i].sh_offset,
sizeof(*hdr));
- return 0;
- }
+
secname = secstrings + sechdrs[i].sh_name;
if (strcmp(secname, ".modinfo") == 0) {
if (nobits)
@@ -577,11 +565,14 @@ static int parse_elf(struct elf_info *info, const char *filename)
*p = TO_NATIVE(*p);
}
+ symsearch_init(info);
+
return 1;
}
static void parse_elf_finish(struct elf_info *info)
{
+ symsearch_finish(info);
release_file(info->hdr, info->size);
}
@@ -792,47 +783,33 @@ static void check_section(const char *modname, struct elf_info *elf,
#define ALL_INIT_DATA_SECTIONS \
".init.setup", ".init.rodata", ".meminit.rodata", \
".init.data", ".meminit.data"
-#define ALL_EXIT_DATA_SECTIONS \
- ".exit.data", ".memexit.data"
-
-#define ALL_INIT_TEXT_SECTIONS \
- ".init.text", ".meminit.text"
-#define ALL_EXIT_TEXT_SECTIONS \
- ".exit.text", ".memexit.text"
#define ALL_PCI_INIT_SECTIONS \
".pci_fixup_early", ".pci_fixup_header", ".pci_fixup_final", \
".pci_fixup_enable", ".pci_fixup_resume", \
".pci_fixup_resume_early", ".pci_fixup_suspend"
-#define ALL_XXXINIT_SECTIONS MEM_INIT_SECTIONS
-#define ALL_XXXEXIT_SECTIONS MEM_EXIT_SECTIONS
+#define ALL_XXXINIT_SECTIONS ".meminit.*"
#define ALL_INIT_SECTIONS INIT_SECTIONS, ALL_XXXINIT_SECTIONS
-#define ALL_EXIT_SECTIONS EXIT_SECTIONS, ALL_XXXEXIT_SECTIONS
+#define ALL_EXIT_SECTIONS ".exit.*"
#define DATA_SECTIONS ".data", ".data.rel"
#define TEXT_SECTIONS ".text", ".text.*", ".sched.text", \
- ".kprobes.text", ".cpuidle.text", ".noinstr.text"
+ ".kprobes.text", ".cpuidle.text", ".noinstr.text", \
+ ".ltext", ".ltext.*"
#define OTHER_TEXT_SECTIONS ".ref.text", ".head.text", ".spinlock.text", \
".fixup", ".entry.text", ".exception.text", \
".coldtext", ".softirqentry.text"
#define INIT_SECTIONS ".init.*"
-#define MEM_INIT_SECTIONS ".meminit.*"
-
-#define EXIT_SECTIONS ".exit.*"
-#define MEM_EXIT_SECTIONS ".memexit.*"
-#define ALL_TEXT_SECTIONS ALL_INIT_TEXT_SECTIONS, ALL_EXIT_TEXT_SECTIONS, \
+#define ALL_TEXT_SECTIONS ".init.text", ".meminit.text", ".exit.text", \
TEXT_SECTIONS, OTHER_TEXT_SECTIONS
enum mismatch {
- TEXT_TO_ANY_INIT,
- DATA_TO_ANY_INIT,
- TEXTDATA_TO_ANY_EXIT,
+ TEXTDATA_TO_ANY_INIT_EXIT,
XXXINIT_TO_SOME_INIT,
- XXXEXIT_TO_SOME_EXIT,
ANY_INIT_TO_ANY_EXIT,
ANY_EXIT_TO_ANY_INIT,
EXTABLE_TO_NON_TEXT,
@@ -863,19 +840,9 @@ static const struct sectioncheck sectioncheck[] = {
* normal code and data
*/
{
- .fromsec = { TEXT_SECTIONS, NULL },
- .bad_tosec = { ALL_INIT_SECTIONS, NULL },
- .mismatch = TEXT_TO_ANY_INIT,
-},
-{
- .fromsec = { DATA_SECTIONS, NULL },
- .bad_tosec = { ALL_XXXINIT_SECTIONS, INIT_SECTIONS, NULL },
- .mismatch = DATA_TO_ANY_INIT,
-},
-{
.fromsec = { TEXT_SECTIONS, DATA_SECTIONS, NULL },
- .bad_tosec = { ALL_EXIT_SECTIONS, NULL },
- .mismatch = TEXTDATA_TO_ANY_EXIT,
+ .bad_tosec = { ALL_INIT_SECTIONS, ALL_EXIT_SECTIONS, NULL },
+ .mismatch = TEXTDATA_TO_ANY_INIT_EXIT,
},
/* Do not reference init code/data from meminit code/data */
{
@@ -883,12 +850,6 @@ static const struct sectioncheck sectioncheck[] = {
.bad_tosec = { INIT_SECTIONS, NULL },
.mismatch = XXXINIT_TO_SOME_INIT,
},
-/* Do not reference exit code/data from memexit code/data */
-{
- .fromsec = { ALL_XXXEXIT_SECTIONS, NULL },
- .bad_tosec = { EXIT_SECTIONS, NULL },
- .mismatch = XXXEXIT_TO_SOME_EXIT,
-},
/* Do not use exit code/data from init code */
{
.fromsec = { ALL_INIT_SECTIONS, NULL },
@@ -1006,19 +967,7 @@ static int secref_whitelist(const char *fromsec, const char *fromsym,
/* symbols in data sections that may refer to any init/exit sections */
if (match(fromsec, PATTERNS(DATA_SECTIONS)) &&
match(tosec, PATTERNS(ALL_INIT_SECTIONS, ALL_EXIT_SECTIONS)) &&
- match(fromsym, PATTERNS("*_template", // scsi uses *_template a lot
- "*_timer", // arm uses ops structures named _timer a lot
- "*_sht", // scsi also used *_sht to some extent
- "*_ops",
- "*_probe",
- "*_probe_one",
- "*_console")))
- return 0;
-
- /* symbols in data sections that may refer to meminit sections */
- if (match(fromsec, PATTERNS(DATA_SECTIONS)) &&
- match(tosec, PATTERNS(ALL_XXXINIT_SECTIONS, ALL_XXXEXIT_SECTIONS)) &&
- match(fromsym, PATTERNS("*driver")))
+ match(fromsym, PATTERNS("*_ops", "*_probe", "*_console")))
return 0;
/*
@@ -1028,7 +977,7 @@ static int secref_whitelist(const char *fromsec, const char *fromsym,
*/
if (!extra_warn &&
match(fromsec, PATTERNS(DATA_SECTIONS)) &&
- match(tosec, PATTERNS(EXIT_SECTIONS)) &&
+ match(tosec, PATTERNS(ALL_EXIT_SECTIONS)) &&
match(fromsym, PATTERNS("*driver")))
return 0;
@@ -1050,75 +999,16 @@ static int secref_whitelist(const char *fromsec, const char *fromsym,
return 1;
}
-/*
- * If there's no name there, ignore it; likewise, ignore it if it's
- * one of the magic symbols emitted used by current 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_mapping_symbol(name);
-}
-
-/* Look up the nearest symbol based on the section and the address */
-static Elf_Sym *find_nearest_sym(struct elf_info *elf, Elf_Addr addr,
- unsigned int secndx, bool allow_negative,
- Elf_Addr min_distance)
-{
- Elf_Sym *sym;
- Elf_Sym *near = NULL;
- Elf_Addr sym_addr, distance;
- bool is_arm = (elf->hdr->e_machine == EM_ARM);
-
- for (sym = elf->symtab_start; sym < elf->symtab_stop; sym++) {
- if (get_secindex(elf, sym) != secndx)
- continue;
- if (!is_valid_name(elf, sym))
- continue;
-
- sym_addr = sym->st_value;
-
- /*
- * For ARM Thumb instruction, the bit 0 of st_value is set
- * if the symbol is STT_FUNC type. Mask it to get the address.
- */
- if (is_arm && ELF_ST_TYPE(sym->st_info) == STT_FUNC)
- sym_addr &= ~1;
-
- if (addr >= sym_addr)
- distance = addr - sym_addr;
- else if (allow_negative)
- distance = sym_addr - addr;
- else
- continue;
-
- if (distance <= min_distance) {
- min_distance = distance;
- near = sym;
- }
-
- if (min_distance == 0)
- break;
- }
- return near;
-}
-
static Elf_Sym *find_fromsym(struct elf_info *elf, Elf_Addr addr,
unsigned int secndx)
{
- return find_nearest_sym(elf, addr, secndx, false, ~0);
+ return symsearch_find_nearest(elf, addr, secndx, false, ~0);
}
static Elf_Sym *find_tosym(struct elf_info *elf, Elf_Addr addr, Elf_Sym *sym)
{
+ Elf_Sym *new_sym;
+
/* If the supplied symbol has a valid name, return it */
if (is_valid_name(elf, sym))
return sym;
@@ -1127,7 +1017,9 @@ static Elf_Sym *find_tosym(struct elf_info *elf, Elf_Addr addr, Elf_Sym *sym)
* Strive to find a better symbol name, but the resulting name may not
* match the symbol referenced in the original code.
*/
- return find_nearest_sym(elf, addr, get_secindex(elf, sym), true, 20);
+ new_sym = symsearch_find_nearest(elf, addr, get_secindex(elf, sym),
+ true, 20);
+ return new_sym ? new_sym : sym;
}
static bool is_executable_section(struct elf_info *elf, unsigned int secndx)
@@ -1161,7 +1053,9 @@ static void default_mismatch_handler(const char *modname, struct elf_info *elf,
sec_mismatch_count++;
warn("%s: section mismatch in reference: %s+0x%x (section: %s) -> %s (section: %s)\n",
- modname, fromsym, (unsigned int)(faddr - from->st_value), fromsec, tosym, tosec);
+ modname, fromsym,
+ (unsigned int)(faddr - (from ? from->st_value : 0)),
+ fromsec, tosym, tosec);
if (mismatch->mismatch == EXTABLE_TO_NON_TEXT) {
if (match(tosec, mismatch->bad_tosec))
@@ -1248,10 +1142,10 @@ static void check_export_symbol(struct module *mod, struct elf_info *elf,
ELF_ST_TYPE(sym->st_info) == STT_LOPROC)
s->is_func = true;
- if (match(secname, PATTERNS(INIT_SECTIONS)))
+ if (match(secname, PATTERNS(ALL_INIT_SECTIONS)))
warn("%s: %s: EXPORT_SYMBOL used for init symbol. Remove __init or EXPORT_SYMBOL.\n",
mod->name, name);
- else if (match(secname, PATTERNS(EXIT_SECTIONS)))
+ else if (match(secname, PATTERNS(ALL_EXIT_SECTIONS)))
warn("%s: %s: EXPORT_SYMBOL used for exit symbol. Remove __exit or EXPORT_SYMBOL.\n",
mod->name, name);
}
@@ -1447,6 +1341,14 @@ static Elf_Addr addend_mips_rel(uint32_t *location, unsigned int r_type)
#define R_LARCH_SUB32 55
#endif
+#ifndef R_LARCH_RELAX
+#define R_LARCH_RELAX 100
+#endif
+
+#ifndef R_LARCH_ALIGN
+#define R_LARCH_ALIGN 102
+#endif
+
static void get_rel_type_and_sym(struct elf_info *elf, uint64_t r_info,
unsigned int *r_type, unsigned int *r_sym)
{
@@ -1468,41 +1370,31 @@ static void get_rel_type_and_sym(struct elf_info *elf, uint64_t r_info,
return;
}
- if (is_64bit) {
- Elf64_Xword r_info64 = r_info;
-
- r_info = TO_NATIVE(r_info64);
- } else {
- Elf32_Word r_info32 = r_info;
-
- r_info = TO_NATIVE(r_info32);
- }
+ if (is_64bit)
+ r_info = TO_NATIVE((Elf64_Xword)r_info);
+ else
+ r_info = TO_NATIVE((Elf32_Word)r_info);
*r_type = ELF_R_TYPE(r_info);
*r_sym = ELF_R_SYM(r_info);
}
static void section_rela(struct module *mod, struct elf_info *elf,
- Elf_Shdr *sechdr)
+ unsigned int fsecndx, const char *fromsec,
+ const Elf_Rela *start, const Elf_Rela *stop)
{
- Elf_Rela *rela;
- unsigned int fsecndx = sechdr->sh_info;
- const char *fromsec = sec_name(elf, fsecndx);
- Elf_Rela *start = (void *)elf->hdr + sechdr->sh_offset;
- Elf_Rela *stop = (void *)start + sechdr->sh_size;
-
- /* if from section (name) is know good then skip it */
- if (match(fromsec, section_white_list))
- return;
+ const Elf_Rela *rela;
for (rela = start; rela < stop; rela++) {
+ Elf_Sym *tsym;
Elf_Addr taddr, r_offset;
unsigned int r_type, r_sym;
r_offset = TO_NATIVE(rela->r_offset);
get_rel_type_and_sym(elf, rela->r_info, &r_type, &r_sym);
- taddr = TO_NATIVE(rela->r_addend);
+ tsym = elf->symtab_start + r_sym;
+ taddr = tsym->st_value + TO_NATIVE(rela->r_addend);
switch (elf->hdr->e_machine) {
case EM_RISCV:
@@ -1511,33 +1403,33 @@ static void section_rela(struct module *mod, struct elf_info *elf,
continue;
break;
case EM_LOONGARCH:
- if (!strcmp("__ex_table", fromsec) &&
- r_type == R_LARCH_SUB32)
+ switch (r_type) {
+ case R_LARCH_SUB32:
+ if (!strcmp("__ex_table", fromsec))
+ continue;
+ break;
+ case R_LARCH_RELAX:
+ case R_LARCH_ALIGN:
+ /* These relocs do not refer to symbols */
continue;
+ }
break;
}
- check_section_mismatch(mod, elf, elf->symtab_start + r_sym,
+ check_section_mismatch(mod, elf, tsym,
fsecndx, fromsec, r_offset, taddr);
}
}
static void section_rel(struct module *mod, struct elf_info *elf,
- Elf_Shdr *sechdr)
+ unsigned int fsecndx, const char *fromsec,
+ const Elf_Rel *start, const Elf_Rel *stop)
{
- Elf_Rel *rel;
- unsigned int fsecndx = sechdr->sh_info;
- const char *fromsec = sec_name(elf, fsecndx);
- Elf_Rel *start = (void *)elf->hdr + sechdr->sh_offset;
- Elf_Rel *stop = (void *)start + sechdr->sh_size;
-
- /* if from section (name) is know good then skip it */
- if (match(fromsec, section_white_list))
- return;
+ const Elf_Rel *rel;
for (rel = start; rel < stop; rel++) {
Elf_Sym *tsym;
- Elf_Addr taddr = 0, r_offset;
+ Elf_Addr taddr, r_offset;
unsigned int r_type, r_sym;
void *loc;
@@ -1581,16 +1473,33 @@ static void section_rel(struct module *mod, struct elf_info *elf,
static void check_sec_ref(struct module *mod, struct elf_info *elf)
{
int i;
- Elf_Shdr *sechdrs = elf->sechdrs;
/* Walk through all sections */
for (i = 0; i < elf->num_sections; i++) {
- check_section(mod->name, elf, &elf->sechdrs[i]);
+ Elf_Shdr *sechdr = &elf->sechdrs[i];
+
+ check_section(mod->name, elf, sechdr);
/* We want to process only relocation sections and not .init */
- if (sechdrs[i].sh_type == SHT_RELA)
- section_rela(mod, elf, &elf->sechdrs[i]);
- else if (sechdrs[i].sh_type == SHT_REL)
- section_rel(mod, elf, &elf->sechdrs[i]);
+ if (sechdr->sh_type == SHT_REL || sechdr->sh_type == SHT_RELA) {
+ /* section to which the relocation applies */
+ unsigned int secndx = sechdr->sh_info;
+ const char *secname = sec_name(elf, secndx);
+ const void *start, *stop;
+
+ /* If the section is known good, skip it */
+ if (match(secname, section_white_list))
+ continue;
+
+ start = sym_get_data_by_offset(elf, i, 0);
+ stop = start + sechdr->sh_size;
+
+ if (sechdr->sh_type == SHT_RELA)
+ section_rela(mod, elf, secndx, secname,
+ start, stop);
+ else
+ section_rel(mod, elf, secndx, secname,
+ start, stop);
+ }
}
}
@@ -1944,7 +1853,7 @@ static void add_header(struct buffer *b, struct module *mod)
buf_printf(b,
"\n"
- "#ifdef CONFIG_RETPOLINE\n"
+ "#ifdef CONFIG_MITIGATION_RETPOLINE\n"
"MODULE_INFO(retpoline, \"Y\");\n"
"#endif\n");
diff --git a/scripts/mod/modpost.h b/scripts/mod/modpost.h
index 5f94c2c9f2d9..ee43c7950636 100644
--- a/scripts/mod/modpost.h
+++ b/scripts/mod/modpost.h
@@ -1,4 +1,5 @@
/* SPDX-License-Identifier: GPL-2.0 */
+#include <byteswap.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
@@ -10,6 +11,7 @@
#include <fcntl.h>
#include <unistd.h>
#include <elf.h>
+#include "../../include/linux/module_symbol.h"
#include "list.h"
#include "elfconfig.h"
@@ -50,21 +52,19 @@
#define ELF_R_TYPE ELF64_R_TYPE
#endif
-#if KERNEL_ELFDATA != HOST_ELFDATA
+#define bswap(x) \
+({ \
+ _Static_assert(sizeof(x) == 1 || sizeof(x) == 2 || \
+ sizeof(x) == 4 || sizeof(x) == 8, "bug"); \
+ (typeof(x))(sizeof(x) == 2 ? bswap_16(x) : \
+ sizeof(x) == 4 ? bswap_32(x) : \
+ sizeof(x) == 8 ? bswap_64(x) : \
+ x); \
+})
-static inline void __endian(const void *src, void *dest, unsigned int size)
-{
- unsigned int i;
- for (i = 0; i < size; i++)
- ((unsigned char*)dest)[i] = ((unsigned char*)src)[size - i-1];
-}
+#if KERNEL_ELFDATA != HOST_ELFDATA
-#define TO_NATIVE(x) \
-({ \
- typeof(x) __x; \
- __endian(&(x), &(__x), sizeof(__x)); \
- __x; \
-})
+#define TO_NATIVE(x) (bswap(x))
#else /* endianness matches */
@@ -128,6 +128,8 @@ struct elf_info {
* take shndx from symtab_shndx_start[N] instead */
Elf32_Word *symtab_shndx_start;
Elf32_Word *symtab_shndx_stop;
+
+ struct symsearch *symsearch;
};
/* Accessor for sym->st_shndx, hides ugliness of "64k sections" */
@@ -154,6 +156,28 @@ static inline unsigned int get_secindex(const struct elf_info *info,
return index;
}
+/*
+ * If there's no name there, ignore it; likewise, ignore it if it's
+ * one of the magic symbols emitted used by current tools.
+ *
+ * Internal symbols created by tools should be ignored by modpost.
+ */
+static inline bool is_valid_name(struct elf_info *elf, Elf_Sym *sym)
+{
+ const char *name = elf->strtab + sym->st_name;
+
+ if (!name || !strlen(name))
+ return false;
+ return !is_mapping_symbol(name);
+}
+
+/* symsearch.c */
+void symsearch_init(struct elf_info *elf);
+void symsearch_finish(struct elf_info *elf);
+Elf_Sym *symsearch_find_nearest(struct elf_info *elf, Elf_Addr addr,
+ unsigned int secndx, bool allow_negative,
+ Elf_Addr min_distance);
+
/* file2alias.c */
void handle_moddevtable(struct module *mod, struct elf_info *info,
Elf_Sym *sym, const char *symname);
@@ -170,10 +194,10 @@ void *sym_get_data(const struct elf_info *info, const Elf_Sym *sym);
enum loglevel {
LOG_WARN,
LOG_ERROR,
- LOG_FATAL
};
-void modpost_log(enum loglevel loglevel, const char *fmt, ...);
+void __attribute__((format(printf, 2, 3)))
+modpost_log(enum loglevel loglevel, const char *fmt, ...);
/*
* warn - show the given message, then let modpost continue running, still
@@ -190,4 +214,4 @@ void modpost_log(enum loglevel loglevel, const char *fmt, ...);
*/
#define warn(fmt, args...) modpost_log(LOG_WARN, fmt, ##args)
#define error(fmt, args...) modpost_log(LOG_ERROR, fmt, ##args)
-#define fatal(fmt, args...) modpost_log(LOG_FATAL, fmt, ##args)
+#define fatal(fmt, args...) do { error(fmt, ##args); exit(1); } while (1)
diff --git a/scripts/mod/sumversion.c b/scripts/mod/sumversion.c
index 31066bfdba04..dc4878502276 100644
--- a/scripts/mod/sumversion.c
+++ b/scripts/mod/sumversion.c
@@ -326,7 +326,12 @@ static int parse_source_files(const char *objfile, struct md4_ctx *md)
/* Sum all files in the same dir or subdirs. */
while ((line = get_line(&pos))) {
- char* p = line;
+ char* p;
+
+ /* trim the leading spaces away */
+ while (isspace(*line))
+ line++;
+ p = line;
if (strncmp(line, "source_", sizeof("source_")-1) == 0) {
p = strrchr(line, ' ');
diff --git a/scripts/mod/symsearch.c b/scripts/mod/symsearch.c
new file mode 100644
index 000000000000..aa4ed51f9960
--- /dev/null
+++ b/scripts/mod/symsearch.c
@@ -0,0 +1,199 @@
+// SPDX-License-Identifier: GPL-2.0
+
+/*
+ * Helper functions for finding the symbol in an ELF which is "nearest"
+ * to a given address.
+ */
+
+#include "modpost.h"
+
+struct syminfo {
+ unsigned int symbol_index;
+ unsigned int section_index;
+ Elf_Addr addr;
+};
+
+/*
+ * Container used to hold an entire binary search table.
+ * Entries in table are ascending, sorted first by section_index,
+ * then by addr, and last by symbol_index. The sorting by
+ * symbol_index is used to ensure predictable behavior when
+ * multiple symbols are present with the same address; all
+ * symbols past the first are effectively ignored, by eliding
+ * them in symsearch_fixup().
+ */
+struct symsearch {
+ unsigned int table_size;
+ struct syminfo table[];
+};
+
+static int syminfo_compare(const void *s1, const void *s2)
+{
+ const struct syminfo *sym1 = s1;
+ const struct syminfo *sym2 = s2;
+
+ if (sym1->section_index > sym2->section_index)
+ return 1;
+ if (sym1->section_index < sym2->section_index)
+ return -1;
+ if (sym1->addr > sym2->addr)
+ return 1;
+ if (sym1->addr < sym2->addr)
+ return -1;
+ if (sym1->symbol_index > sym2->symbol_index)
+ return 1;
+ if (sym1->symbol_index < sym2->symbol_index)
+ return -1;
+ return 0;
+}
+
+static unsigned int symbol_count(struct elf_info *elf)
+{
+ unsigned int result = 0;
+
+ for (Elf_Sym *sym = elf->symtab_start; sym < elf->symtab_stop; sym++) {
+ if (is_valid_name(elf, sym))
+ result++;
+ }
+ return result;
+}
+
+/*
+ * Populate the search array that we just allocated.
+ * Be slightly paranoid here. The ELF file is mmap'd and could
+ * conceivably change between symbol_count() and symsearch_populate().
+ * If we notice any difference, bail out rather than potentially
+ * propagating errors or crashing.
+ */
+static void symsearch_populate(struct elf_info *elf,
+ struct syminfo *table,
+ unsigned int table_size)
+{
+ bool is_arm = (elf->hdr->e_machine == EM_ARM);
+
+ for (Elf_Sym *sym = elf->symtab_start; sym < elf->symtab_stop; sym++) {
+ if (is_valid_name(elf, sym)) {
+ if (table_size-- == 0)
+ fatal("%s: size mismatch\n", __func__);
+ table->symbol_index = sym - elf->symtab_start;
+ table->section_index = get_secindex(elf, sym);
+ table->addr = sym->st_value;
+
+ /*
+ * For ARM Thumb instruction, the bit 0 of st_value is
+ * set if the symbol is STT_FUNC type. Mask it to get
+ * the address.
+ */
+ if (is_arm && ELF_ST_TYPE(sym->st_info) == STT_FUNC)
+ table->addr &= ~1;
+
+ table++;
+ }
+ }
+
+ if (table_size != 0)
+ fatal("%s: size mismatch\n", __func__);
+}
+
+/*
+ * Do any fixups on the table after sorting.
+ * For now, this just finds adjacent entries which have
+ * the same section_index and addr, and it propagates
+ * the first symbol_index over the subsequent entries,
+ * so that only one symbol_index is seen for any given
+ * section_index and addr. This ensures that whether
+ * we're looking at an address from "above" or "below"
+ * that we see the same symbol_index.
+ * This does leave some duplicate entries in the table;
+ * in practice, these are a small fraction of the
+ * total number of entries, and they are harmless to
+ * the binary search algorithm other than a few occasional
+ * unnecessary comparisons.
+ */
+static void symsearch_fixup(struct syminfo *table, unsigned int table_size)
+{
+ /* Don't look at index 0, it will never change. */
+ for (unsigned int i = 1; i < table_size; i++) {
+ if (table[i].addr == table[i - 1].addr &&
+ table[i].section_index == table[i - 1].section_index) {
+ table[i].symbol_index = table[i - 1].symbol_index;
+ }
+ }
+}
+
+void symsearch_init(struct elf_info *elf)
+{
+ unsigned int table_size = symbol_count(elf);
+
+ elf->symsearch = NOFAIL(malloc(sizeof(struct symsearch) +
+ sizeof(struct syminfo) * table_size));
+ elf->symsearch->table_size = table_size;
+
+ symsearch_populate(elf, elf->symsearch->table, table_size);
+ qsort(elf->symsearch->table, table_size,
+ sizeof(struct syminfo), syminfo_compare);
+
+ symsearch_fixup(elf->symsearch->table, table_size);
+}
+
+void symsearch_finish(struct elf_info *elf)
+{
+ free(elf->symsearch);
+ elf->symsearch = NULL;
+}
+
+/*
+ * Find the syminfo which is in secndx and "nearest" to addr.
+ * allow_negative: allow returning a symbol whose address is > addr.
+ * min_distance: ignore symbols which are further away than this.
+ *
+ * Returns a pointer into the symbol table for success.
+ * Returns NULL if no legal symbol is found within the requested range.
+ */
+Elf_Sym *symsearch_find_nearest(struct elf_info *elf, Elf_Addr addr,
+ unsigned int secndx, bool allow_negative,
+ Elf_Addr min_distance)
+{
+ unsigned int hi = elf->symsearch->table_size;
+ unsigned int lo = 0;
+ struct syminfo *table = elf->symsearch->table;
+ struct syminfo target;
+
+ target.addr = addr;
+ target.section_index = secndx;
+ target.symbol_index = ~0; /* compares greater than any actual index */
+ while (hi > lo) {
+ unsigned int mid = lo + (hi - lo) / 2; /* Avoids overflow */
+
+ if (syminfo_compare(&table[mid], &target) > 0)
+ hi = mid;
+ else
+ lo = mid + 1;
+ }
+
+ /*
+ * table[hi], if it exists, is the first entry in the array which
+ * lies beyond target. table[hi - 1], if it exists, is the last
+ * entry in the array which comes before target, including the
+ * case where it perfectly matches the section and the address.
+ *
+ * Note -- if the address we're looking up falls perfectly
+ * in the middle of two symbols, this is written to always
+ * prefer the symbol with the lower address.
+ */
+ Elf_Sym *result = NULL;
+
+ if (allow_negative &&
+ hi < elf->symsearch->table_size &&
+ table[hi].section_index == secndx &&
+ table[hi].addr - addr <= min_distance) {
+ min_distance = table[hi].addr - addr;
+ result = &elf->symtab_start[table[hi].symbol_index];
+ }
+ if (hi > 0 &&
+ table[hi - 1].section_index == secndx &&
+ addr - table[hi - 1].addr <= min_distance) {
+ result = &elf->symtab_start[table[hi - 1].symbol_index];
+ }
+ return result;
+}
diff --git a/scripts/package/builddeb b/scripts/package/builddeb
index d7dd0d04c70c..e797ad360f7a 100755
--- a/scripts/package/builddeb
+++ b/scripts/package/builddeb
@@ -24,45 +24,16 @@ if_enabled_echo() {
fi
}
-create_package() {
- local pname="$1" pdir="$2"
- local dpkg_deb_opts
-
- mkdir -m 755 -p "$pdir/DEBIAN"
- mkdir -p "$pdir/usr/share/doc/$pname"
- cp debian/copyright "$pdir/usr/share/doc/$pname/"
- cp debian/changelog "$pdir/usr/share/doc/$pname/changelog.Debian"
- gzip -n -9 "$pdir/usr/share/doc/$pname/changelog.Debian"
- sh -c "cd '$pdir'; find . -type f ! -path './DEBIAN/*' -printf '%P\0' \
- | xargs -r0 md5sum > DEBIAN/md5sums"
-
- # Fix ownership and permissions
- if [ "$DEB_RULES_REQUIRES_ROOT" = "no" ]; then
- dpkg_deb_opts="--root-owner-group"
- else
- chown -R root:root "$pdir"
- fi
- # a+rX in case we are in a restrictive umask environment like 0077
- # ug-s in case we build in a setuid/setgid directory
- chmod -R go-w,a+rX,ug-s "$pdir"
-
- # Create the package
- dpkg-gencontrol -p$pname -P"$pdir"
- dpkg-deb $dpkg_deb_opts ${KDEB_COMPRESS:+-Z$KDEB_COMPRESS} --build "$pdir" ..
-}
-
install_linux_image () {
- pdir=$1
- pname=$2
-
- rm -rf ${pdir}
+ pname=$1
+ pdir=debian/$1
# Only some architectures with OF support have this target
if is_enabled CONFIG_OF_EARLY_FLATTREE && [ -d "${srctree}/arch/${SRCARCH}/boot/dts" ]; then
${MAKE} -f ${srctree}/Makefile INSTALL_DTBS_PATH="${pdir}/usr/lib/linux-image-${KERNELRELEASE}" dtbs_install
fi
- ${MAKE} -f ${srctree}/Makefile INSTALL_MOD_PATH="${pdir}" modules_install
+ ${MAKE} -f ${srctree}/Makefile INSTALL_MOD_PATH="${pdir}" INSTALL_MOD_STRIP=1 modules_install
rm -f "${pdir}/lib/modules/${KERNELRELEASE}/build"
# Install the kernel
@@ -122,26 +93,20 @@ install_linux_image () {
}
install_linux_image_dbg () {
- pdir=$1
- image_pdir=$2
-
- rm -rf ${pdir}
-
- for module in $(find ${image_pdir}/lib/modules/ -name *.ko -printf '%P\n'); do
- module=lib/modules/${module}
- mkdir -p $(dirname ${pdir}/usr/lib/debug/${module})
- # only keep debug symbols in the debug file
- ${OBJCOPY} --only-keep-debug ${image_pdir}/${module} ${pdir}/usr/lib/debug/${module}
- # strip original module from debug symbols
- ${OBJCOPY} --strip-debug ${image_pdir}/${module}
- # then add a link to those
- ${OBJCOPY} --add-gnu-debuglink=${pdir}/usr/lib/debug/${module} ${image_pdir}/${module}
- done
+ pdir=debian/$1
- # re-sign stripped modules
- if is_enabled CONFIG_MODULE_SIG_ALL; then
- ${MAKE} -f ${srctree}/Makefile INSTALL_MOD_PATH="${image_pdir}" modules_sign
- fi
+ # Parse modules.order directly because 'make modules_install' may sign,
+ # compress modules, and then run unneeded depmod.
+ while read -r mod; do
+ mod="${mod%.o}.ko"
+ dbg="${pdir}/usr/lib/debug/lib/modules/${KERNELRELEASE}/kernel/${mod}"
+ buildid=$("${READELF}" -n "${mod}" | sed -n 's@^.*Build ID: \(..\)\(.*\)@\1/\2@p')
+ link="${pdir}/usr/lib/debug/.build-id/${buildid}.debug"
+
+ mkdir -p "${dbg%/*}" "${link%/*}"
+ "${OBJCOPY}" --only-keep-debug "${mod}" "${dbg}"
+ ln -sf --relative "${dbg}" "${link}"
+ done < modules.order
# Build debug package
# Different tools want the image in different locations
@@ -156,10 +121,8 @@ install_linux_image_dbg () {
}
install_kernel_headers () {
- pdir=$1
- version=$2
-
- rm -rf $pdir
+ pdir=debian/$1
+ version=${1#linux-headers-}
"${srctree}/scripts/package/install-extmod-build" "${pdir}/usr/src/linux-headers-${version}"
@@ -168,52 +131,25 @@ install_kernel_headers () {
}
install_libc_headers () {
- pdir=$1
-
- rm -rf $pdir
+ pdir=debian/$1
- $MAKE -f $srctree/Makefile headers
$MAKE -f $srctree/Makefile headers_install INSTALL_HDR_PATH=$pdir/usr
# move asm headers to /usr/include/<libc-machine>/asm to match the structure
# used by Debian-based distros (to support multi-arch)
- host_arch=$(dpkg-architecture -a$DEB_HOST_ARCH -qDEB_HOST_MULTIARCH)
- mkdir $pdir/usr/include/$host_arch
- mv $pdir/usr/include/asm $pdir/usr/include/$host_arch/
+ mkdir "$pdir/usr/include/${DEB_HOST_MULTIARCH}"
+ mv "$pdir/usr/include/asm" "$pdir/usr/include/${DEB_HOST_MULTIARCH}"
}
-rm -f debian/files
-
-packages_enabled=$(dh_listpackages)
-
-for package in ${packages_enabled}
-do
- case ${package} in
- *-dbg)
- # This must be done after linux-image, that is, we expect the
- # debug package appears after linux-image in debian/control.
- install_linux_image_dbg debian/linux-image-dbg debian/linux-image;;
- linux-image-*|user-mode-linux-*)
- install_linux_image debian/linux-image ${package};;
- linux-libc-dev)
- install_libc_headers debian/linux-libc-dev;;
- linux-headers-*)
- install_kernel_headers debian/linux-headers ${package#linux-headers-};;
- esac
-done
-
-for package in ${packages_enabled}
-do
- case ${package} in
- *-dbg)
- create_package ${package} debian/linux-image-dbg;;
- linux-image-*|user-mode-linux-*)
- create_package ${package} debian/linux-image;;
- linux-libc-dev)
- create_package ${package} debian/linux-libc-dev;;
- linux-headers-*)
- create_package ${package} debian/linux-headers;;
- esac
-done
-
-exit 0
+package=$1
+
+case "${package}" in
+*-dbg)
+ install_linux_image_dbg "${package}";;
+linux-image-*|user-mode-linux-*)
+ install_linux_image "${package}";;
+linux-libc-dev)
+ install_libc_headers "${package}";;
+linux-headers-*)
+ install_kernel_headers "${package}";;
+esac
diff --git a/scripts/package/buildtar b/scripts/package/buildtar
index 65b4ea502962..72c91a1b832f 100755
--- a/scripts/package/buildtar
+++ b/scripts/package/buildtar
@@ -23,7 +23,6 @@ tmpdir=$1
#
rm -rf -- "${tmpdir}"
mkdir -p -- "${tmpdir}/boot"
-dirs=boot
#
@@ -38,12 +37,9 @@ fi
#
-# Try to install modules
+# Install modules
#
-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
+make ARCH="${ARCH}" -f ${srctree}/Makefile INSTALL_MOD_PATH="${tmpdir}" modules_install
#
diff --git a/scripts/package/deb-build-option b/scripts/package/deb-build-option
deleted file mode 100755
index 7950eff01781..000000000000
--- a/scripts/package/deb-build-option
+++ /dev/null
@@ -1,14 +0,0 @@
-#!/bin/sh
-# SPDX-License-Identifier: GPL-2.0-only
-
-# Set up CROSS_COMPILE if not defined yet
-if [ "${CROSS_COMPILE+set}" != "set" -a "${DEB_HOST_ARCH}" != "${DEB_BUILD_ARCH}" ]; then
- echo CROSS_COMPILE=${DEB_HOST_GNU_TYPE}-
-fi
-
-version=$(dpkg-parsechangelog -S Version)
-debian_revision="${version##*-}"
-
-if [ "${version}" != "${debian_revision}" ]; then
- echo KBUILD_BUILD_VERSION=${debian_revision}
-fi
diff --git a/scripts/package/debian/copyright b/scripts/package/debian/copyright
new file mode 100644
index 000000000000..4f1f06221f09
--- /dev/null
+++ b/scripts/package/debian/copyright
@@ -0,0 +1,16 @@
+This is a packaged upstream version of the Linux kernel.
+
+The sources may be found at most Linux archive sites, including:
+https://www.kernel.org/pub/linux/kernel
+
+Copyright: 1991 - 2023 Linus Torvalds and others.
+
+The git repository for mainline kernel development is at:
+git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
+
+ 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 dated June, 1991.
+
+On Debian GNU/Linux systems, the complete text of the GNU General Public
+License version 2 can be found in `/usr/share/common-licenses/GPL-2'.
diff --git a/scripts/package/debian/rules b/scripts/package/debian/rules
index 3dafa9496c63..ca07243bd5cd 100755
--- a/scripts/package/debian/rules
+++ b/scripts/package/debian/rules
@@ -1,33 +1,91 @@
#!/usr/bin/make -f
# SPDX-License-Identifier: GPL-2.0-only
-include debian/rules.vars
+# in case debian/rules is executed directly
+export DEB_RULES_REQUIRES_ROOT := no
-srctree ?= .
+include debian/rules.vars
ifneq (,$(filter-out parallel=1,$(filter parallel=%,$(DEB_BUILD_OPTIONS))))
NUMJOBS = $(patsubst parallel=%,%,$(filter parallel=%,$(DEB_BUILD_OPTIONS)))
MAKEFLAGS += -j$(NUMJOBS)
endif
+# When KBUILD_VERBOSE is undefined (presumably you are directly working with
+# the debianized tree), show verbose logs unless DEB_BUILD_OPTION=terse is set.
+ifeq ($(origin KBUILD_VERBOSE),undefined)
+ ifeq (,$(filter terse,$(DEB_BUILD_OPTIONS)))
+ export KBUILD_VERBOSE := 1
+ else
+ Q := @
+ endif
+endif
+
+revision = $(lastword $(subst -, ,$(shell dpkg-parsechangelog -S Version)))
+CROSS_COMPILE ?= $(filter-out $(DEB_BUILD_GNU_TYPE)-, $(DEB_HOST_GNU_TYPE)-)
+make-opts = ARCH=$(ARCH) KERNELRELEASE=$(KERNELRELEASE) KBUILD_BUILD_VERSION=$(revision) $(addprefix CROSS_COMPILE=,$(CROSS_COMPILE))
+
+binary-targets := $(addprefix binary-, image image-dbg headers libc-dev)
+
+all-packages = $(shell dh_listpackages)
+image-package = $(filter linux-image-% user-%, $(filter-out %-dbg, $(all-packages)))
+image-dbg-package = $(filter %-dbg, $(all-packages))
+libc-dev-package = $(filter linux-libc-dev, $(all-packages))
+headers-package = $(filter linux-headers-%, $(all-packages))
+
+mk-files = $(patsubst binary-%,debian/%.files,$1)
+package = $($(@:binary-%=%-package))
+
+# DH_OPTION is an environment variable common for all debhelper commands.
+# We could 'export' it, but here it is passed from the command line to clarify
+# which package is being processed in the build log.
+DH_OPTIONS = -p$(package)
+
+define binary
+ $(Q)dh_testdir $(DH_OPTIONS)
+ $(Q)dh_testroot $(DH_OPTIONS)
+ $(Q)dh_prep $(DH_OPTIONS)
+ $(Q)+$(MAKE) $(make-opts) run-command KBUILD_RUN_COMMAND='+$$(srctree)/scripts/package/builddeb $(package)'
+ $(Q)dh_installdocs $(DH_OPTIONS)
+ $(Q)dh_installchangelogs $(DH_OPTIONS)
+ $(Q)dh_compress $(DH_OPTIONS)
+ $(Q)dh_fixperms $(DH_OPTIONS)
+ $(Q)dh_gencontrol $(DH_OPTIONS) -- -f$(call mk-files,$@)
+ $(Q)dh_md5sums $(DH_OPTIONS)
+ $(Q)dh_builddeb $(DH_OPTIONS) -- $(addprefix -Z,$(KDEB_COMPRESS))
+endef
+
+.PHONY: $(binary-targets)
+$(binary-targets): build-arch
+ $(Q)truncate -s0 $(call mk-files,$@)
+ $(if $(package),$(binary))
+
.PHONY: binary binary-indep binary-arch
binary: binary-arch binary-indep
binary-indep: build-indep
-binary-arch: build-arch
- $(MAKE) -f $(srctree)/Makefile ARCH=$(ARCH) \
- KERNELRELEASE=$(KERNELRELEASE) \
- run-command KBUILD_RUN_COMMAND=+$(srctree)/scripts/package/builddeb
+binary-arch: $(binary-targets)
+ $(Q)cat $(call mk-files,$^) > debian/files
.PHONY: build build-indep build-arch
build: build-arch build-indep
build-indep:
build-arch:
- $(MAKE) -f $(srctree)/Makefile ARCH=$(ARCH) \
- KERNELRELEASE=$(KERNELRELEASE) \
- $(shell $(srctree)/scripts/package/deb-build-option) \
- olddefconfig all
+ $(Q)$(MAKE) $(make-opts) olddefconfig
+ $(Q)$(MAKE) $(make-opts) $(if $(filter um,$(ARCH)),,headers) all
.PHONY: clean
clean:
- rm -rf debian/files debian/linux-*
- $(MAKE) -f $(srctree)/Makefile ARCH=$(ARCH) clean
+ $(Q)dh_clean
+ $(Q)rm -rf debian/deb-env.vars* debian/*.files
+ $(Q)$(MAKE) ARCH=$(ARCH) clean
+
+# If DEB_HOST_ARCH is empty, it is likely that debian/rules was executed
+# directly. Run 'dpkg-architecture --print-set --print-format=make' to
+# generate a makefile construct that exports all DEB_* variables.
+ifndef DEB_HOST_ARCH
+include debian/deb-env.vars
+
+debian/deb-env.vars:
+ $(Q)dpkg-architecture -a$$(cat debian/arch) --print-set --print-format=make > $@.tmp
+ $(Q)mv $@.tmp $@
+endif
diff --git a/scripts/package/install-extmod-build b/scripts/package/install-extmod-build
index 8a7051fad087..76e0765dfcd6 100755
--- a/scripts/package/install-extmod-build
+++ b/scripts/package/install-extmod-build
@@ -20,7 +20,7 @@ mkdir -p "${destdir}"
find "arch/${SRCARCH}" -maxdepth 1 -name 'Makefile*'
find include scripts -type f -o -type l
find "arch/${SRCARCH}" -name Kbuild.platforms -o -name Platform
- find "arch/${SRCARCH}" -name include -o -name scripts -type d
+ find "arch/${SRCARCH}" -name include -type d
) | tar -c -f - -C "${srctree}" -T - | tar -xf - -C "${destdir}"
{
diff --git a/scripts/package/kernel.spec b/scripts/package/kernel.spec
index 3eee0143e0c5..e095eb1e290e 100644
--- a/scripts/package/kernel.spec
+++ b/scripts/package/kernel.spec
@@ -55,52 +55,72 @@ patch -p1 < %{SOURCE2}
%{make} %{makeflags} KERNELRELEASE=%{KERNELRELEASE} KBUILD_BUILD_VERSION=%{release}
%install
-mkdir -p %{buildroot}/boot
-%ifarch ia64
-mkdir -p %{buildroot}/boot/efi
-cp $(%{make} %{makeflags} -s image_name) %{buildroot}/boot/efi/vmlinuz-%{KERNELRELEASE}
-ln -s efi/vmlinuz-%{KERNELRELEASE} %{buildroot}/boot/
-%else
-cp $(%{make} %{makeflags} -s image_name) %{buildroot}/boot/vmlinuz-%{KERNELRELEASE}
-%endif
+mkdir -p %{buildroot}/lib/modules/%{KERNELRELEASE}
+cp $(%{make} %{makeflags} -s image_name) %{buildroot}/lib/modules/%{KERNELRELEASE}/vmlinuz
%{make} %{makeflags} INSTALL_MOD_PATH=%{buildroot} modules_install
%{make} %{makeflags} INSTALL_HDR_PATH=%{buildroot}/usr headers_install
-cp System.map %{buildroot}/boot/System.map-%{KERNELRELEASE}
-cp .config %{buildroot}/boot/config-%{KERNELRELEASE}
+cp System.map %{buildroot}/lib/modules/%{KERNELRELEASE}
+cp .config %{buildroot}/lib/modules/%{KERNELRELEASE}/config
+if %{make} %{makeflags} run-command KBUILD_RUN_COMMAND='test -d ${srctree}/arch/${SRCARCH}/boot/dts' 2>/dev/null; then
+ %{make} %{makeflags} INSTALL_DTBS_PATH=%{buildroot}/lib/modules/%{KERNELRELEASE}/dtb dtbs_install
+fi
ln -fns /usr/src/kernels/%{KERNELRELEASE} %{buildroot}/lib/modules/%{KERNELRELEASE}/build
%if %{with_devel}
%{make} %{makeflags} run-command KBUILD_RUN_COMMAND='${srctree}/scripts/package/install-extmod-build %{buildroot}/usr/src/kernels/%{KERNELRELEASE}'
%endif
+{
+ for x in System.map config kernel modules.builtin \
+ modules.builtin.modinfo modules.order vmlinuz; do
+ echo "/lib/modules/%{KERNELRELEASE}/${x}"
+ done
+
+ for x in alias alias.bin builtin.alias.bin builtin.bin dep dep.bin \
+ devname softdep symbols symbols.bin; do
+ echo "%ghost /lib/modules/%{KERNELRELEASE}/modules.${x}"
+ done
+
+ for x in System.map config vmlinuz; do
+ echo "%ghost /boot/${x}-%{KERNELRELEASE}"
+ done
+
+ if [ -d "%{buildroot}/lib/modules/%{KERNELRELEASE}/dtb" ];then
+ echo "/lib/modules/%{KERNELRELEASE}/dtb"
+ find "%{buildroot}/lib/modules/%{KERNELRELEASE}/dtb" -printf "%%%ghost /boot/dtb-%{KERNELRELEASE}/%%P\n"
+ fi
+
+ echo "%exclude /lib/modules/%{KERNELRELEASE}/build"
+} > %{buildroot}/kernel.list
+
%clean
rm -rf %{buildroot}
%post
-if [ -x /sbin/installkernel -a -r /boot/vmlinuz-%{KERNELRELEASE} -a -r /boot/System.map-%{KERNELRELEASE} ]; then
-cp /boot/vmlinuz-%{KERNELRELEASE} /boot/.vmlinuz-%{KERNELRELEASE}-rpm
-cp /boot/System.map-%{KERNELRELEASE} /boot/.System.map-%{KERNELRELEASE}-rpm
-rm -f /boot/vmlinuz-%{KERNELRELEASE} /boot/System.map-%{KERNELRELEASE}
-/sbin/installkernel %{KERNELRELEASE} /boot/.vmlinuz-%{KERNELRELEASE}-rpm /boot/.System.map-%{KERNELRELEASE}-rpm
-rm -f /boot/.vmlinuz-%{KERNELRELEASE}-rpm /boot/.System.map-%{KERNELRELEASE}-rpm
+if [ -x /usr/bin/kernel-install ]; then
+ /usr/bin/kernel-install add %{KERNELRELEASE} /lib/modules/%{KERNELRELEASE}/vmlinuz
+fi
+for file in vmlinuz System.map config; do
+ if ! cmp --silent "/lib/modules/%{KERNELRELEASE}/${file}" "/boot/${file}-%{KERNELRELEASE}"; then
+ cp "/lib/modules/%{KERNELRELEASE}/${file}" "/boot/${file}-%{KERNELRELEASE}"
+ fi
+done
+if [ -d "/lib/modules/%{KERNELRELEASE}/dtb" ] && \
+ ! diff -rq "/lib/modules/%{KERNELRELEASE}/dtb" "/boot/dtb-%{KERNELRELEASE}" >/dev/null 2>&1; then
+ rm -rf "/boot/dtb-%{KERNELRELEASE}"
+ cp -r "/lib/modules/%{KERNELRELEASE}/dtb" "/boot/dtb-%{KERNELRELEASE}"
+fi
+if [ ! -e "/lib/modules/%{KERNELRELEASE}/modules.dep" ]; then
+ /usr/sbin/depmod %{KERNELRELEASE}
fi
%preun
-if [ -x /sbin/new-kernel-pkg ]; then
-new-kernel-pkg --remove %{KERNELRELEASE} --rminitrd --initrdfile=/boot/initramfs-%{KERNELRELEASE}.img
-elif [ -x /usr/bin/kernel-install ]; then
+if [ -x /usr/bin/kernel-install ]; then
kernel-install remove %{KERNELRELEASE}
fi
-%postun
-if [ -x /sbin/update-bootloader ]; then
-/sbin/update-bootloader --remove %{KERNELRELEASE}
-fi
-
-%files
+%files -f %{buildroot}/kernel.list
%defattr (-, root, root)
-/lib/modules/%{KERNELRELEASE}
-%exclude /lib/modules/%{KERNELRELEASE}/build
-/boot/*
+%exclude /kernel.list
%files headers
%defattr (-, root, root)
diff --git a/scripts/package/mkdebian b/scripts/package/mkdebian
index 5044224cf671..070149c985fe 100755
--- a/scripts/package/mkdebian
+++ b/scripts/package/mkdebian
@@ -26,7 +26,7 @@ set_debarch() {
# Attempt to find the correct Debian architecture
case "$UTS_MACHINE" in
- i386|ia64|alpha|m68k|riscv*)
+ i386|alpha|m68k|riscv*)
debarch="$UTS_MACHINE" ;;
x86_64)
debarch=amd64 ;;
@@ -176,8 +176,6 @@ else
fi
echo $debarch > debian/arch
-extra_build_depends=", $(if_enabled_echo CONFIG_UNWINDER_ORC libelf-dev:native)"
-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
@@ -188,26 +186,6 @@ $sourcename ($packageversion) $distribution; urgency=low
-- $maintainer $(date -R)
EOF
-# Generate copyright file
-cat <<EOF > debian/copyright
-This is a packaged upstream version of the Linux kernel.
-
-The sources may be found at most Linux archive sites, including:
-https://www.kernel.org/pub/linux/kernel
-
-Copyright: 1991 - 2018 Linus Torvalds and others.
-
-The git repository for mainline kernel development is at:
-git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
-
- 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 dated June, 1991.
-
-On Debian GNU/Linux systems, the complete text of the GNU General Public
-License version 2 can be found in \`/usr/share/common-licenses/GPL-2'.
-EOF
-
# Generate a control file
cat <<EOF > debian/control
Source: $sourcename
@@ -215,7 +193,8 @@ Section: kernel
Priority: optional
Maintainer: $maintainer
Rules-Requires-Root: no
-Build-Depends: bc, debhelper, rsync, kmod, cpio, bison, flex $extra_build_depends
+Build-Depends: debhelper-compat (= 12)
+Build-Depends-Arch: bc, bison, cpio, flex, kmod, libelf-dev:native, libssl-dev:native, rsync
Homepage: https://www.kernel.org/
Package: $packagename-$version
@@ -268,6 +247,7 @@ ARCH := ${ARCH}
KERNELRELEASE := ${KERNELRELEASE}
EOF
+cp "${srctree}/scripts/package/debian/copyright" debian/
cp "${srctree}/scripts/package/debian/rules" debian/
exit 0
diff --git a/scripts/package/mkspec b/scripts/package/mkspec
index d41608efb747..ce201bfa8377 100755
--- a/scripts/package/mkspec
+++ b/scripts/package/mkspec
@@ -9,6 +9,12 @@
# Patched for non-x86 by Opencon (L) 2002 <opencon@rio.skydome.net>
#
+output=$1
+
+mkdir -p "$(dirname "${output}")"
+
+exec >"${output}"
+
if grep -q CONFIG_MODULES=y include/config/auto.conf; then
echo '%define with_devel %{?_without_devel: 0} %{?!_without_devel: 1}'
else
diff --git a/scripts/package/snapcraft.template b/scripts/package/snapcraft.template
index 626d278e4a5a..85d5e07d1b40 100644
--- a/scripts/package/snapcraft.template
+++ b/scripts/package/snapcraft.template
@@ -10,5 +10,5 @@ parts:
kernel:
plugin: kernel
source: SRCTREE
- source-type: tar
+ source-type: local
kernel-with-firmware: false
diff --git a/scripts/pahole-flags.sh b/scripts/pahole-flags.sh
deleted file mode 100755
index 728d55190d97..000000000000
--- a/scripts/pahole-flags.sh
+++ /dev/null
@@ -1,30 +0,0 @@
-#!/bin/sh
-# SPDX-License-Identifier: GPL-2.0
-
-extra_paholeopt=
-
-if ! [ -x "$(command -v ${PAHOLE})" ]; then
- exit 0
-fi
-
-pahole_ver=$($(dirname $0)/pahole-version.sh ${PAHOLE})
-
-if [ "${pahole_ver}" -ge "118" ] && [ "${pahole_ver}" -le "121" ]; then
- # pahole 1.18 through 1.21 can't handle zero-sized per-CPU vars
- extra_paholeopt="${extra_paholeopt} --skip_encoding_btf_vars"
-fi
-if [ "${pahole_ver}" -ge "121" ]; then
- extra_paholeopt="${extra_paholeopt} --btf_gen_floats"
-fi
-if [ "${pahole_ver}" -ge "122" ]; then
- extra_paholeopt="${extra_paholeopt} -j"
-fi
-if [ "${pahole_ver}" -ge "124" ]; then
- # see PAHOLE_HAS_LANG_EXCLUDE
- extra_paholeopt="${extra_paholeopt} --lang_exclude=rust"
-fi
-if [ "${pahole_ver}" -ge "125" ]; then
- extra_paholeopt="${extra_paholeopt} --skip_encoding_btf_inconsistent_proto --btf_gen_optimized"
-fi
-
-echo ${extra_paholeopt}
diff --git a/scripts/recordmcount.c b/scripts/recordmcount.c
index 40ae6b2c7a6d..3e4f54799cc0 100644
--- a/scripts/recordmcount.c
+++ b/scripts/recordmcount.c
@@ -590,7 +590,6 @@ static int do_file(char const *const fname)
ideal_nop = ideal_nop4_arm64;
is_fake_mcount64 = arm64_is_fake_mcount;
break;
- case EM_IA_64: reltype = R_IA64_IMM64; break;
case EM_MIPS: /* reltype: e_class */ break;
case EM_LOONGARCH: /* reltype: e_class */ break;
case EM_PPC: reltype = R_PPC_ADDR32; break;
diff --git a/scripts/recordmcount.pl b/scripts/recordmcount.pl
index 6a4645a57976..0871b2e92584 100755
--- a/scripts/recordmcount.pl
+++ b/scripts/recordmcount.pl
@@ -275,13 +275,6 @@ if ($arch eq "x86_64") {
$section_type = '%progbits';
$mcount_regex = "^\\s*([0-9a-fA-F]+):\\s*R_AARCH64_CALL26\\s+_mcount\$";
$type = ".quad";
-} elsif ($arch eq "ia64") {
- $mcount_regex = "^\\s*([0-9a-fA-F]+):.*\\s_mcount\$";
- $type = "data8";
-
- if ($is_module eq "0") {
- $cc .= " -mconstant-gp";
- }
} elsif ($arch eq "sparc64") {
# In the objdump output there are giblets like:
# 0000000000000000 <igmp_net_exit-0x18>:
@@ -359,7 +352,7 @@ if ($arch eq "x86_64") {
$mcount_regex = "^\\s*([0-9a-fA-F]+):.*\\s_mcount\$";
} elsif ($arch eq "riscv") {
$function_regex = "^([0-9a-fA-F]+)\\s+<([^.0-9][0-9a-zA-Z_\\.]+)>:";
- $mcount_regex = "^\\s*([0-9a-fA-F]+):\\sR_RISCV_CALL(_PLT)?\\s_?mcount\$";
+ $mcount_regex = "^\\s*([0-9a-fA-F]+):\\sR_RISCV_CALL(_PLT)?\\s_mcount\$";
$type = ".quad";
$alignment = 2;
} elsif ($arch eq "csky") {
diff --git a/scripts/remove-stale-files b/scripts/remove-stale-files
index 8b1a636f8543..385610fe3936 100755
--- a/scripts/remove-stale-files
+++ b/scripts/remove-stale-files
@@ -38,4 +38,4 @@ rm -rf include/ksym
find . -name '*.usyms' | xargs rm -f
-rm -f binkernel.spec
+rm -f *.spec
diff --git a/scripts/show_delta b/scripts/show_delta
index 28e67e178194..291ad65e3089 100755
--- a/scripts/show_delta
+++ b/scripts/show_delta
@@ -125,4 +125,5 @@ def main():
for line in lines:
print (convert_line(line, base_time),)
-main()
+if __name__ == "__main__":
+ main()
diff --git a/scripts/sign-file.c b/scripts/sign-file.c
index 598ef5465f82..3edb156ae52c 100644
--- a/scripts/sign-file.c
+++ b/scripts/sign-file.c
@@ -322,7 +322,7 @@ int main(int argc, char **argv)
CMS_NOSMIMECAP | use_keyid |
use_signed_attrs),
"CMS_add1_signer");
- ERR(CMS_final(cms, bm, NULL, CMS_NOCERTS | CMS_BINARY) < 0,
+ ERR(CMS_final(cms, bm, NULL, CMS_NOCERTS | CMS_BINARY) != 1,
"CMS_final");
#else
@@ -341,10 +341,10 @@ int main(int argc, char **argv)
b = BIO_new_file(sig_file_name, "wb");
ERR(!b, "%s", sig_file_name);
#ifndef USE_PKCS7
- ERR(i2d_CMS_bio_stream(b, cms, NULL, 0) < 0,
+ ERR(i2d_CMS_bio_stream(b, cms, NULL, 0) != 1,
"%s", sig_file_name);
#else
- ERR(i2d_PKCS7_bio(b, pkcs7) < 0,
+ ERR(i2d_PKCS7_bio(b, pkcs7) != 1,
"%s", sig_file_name);
#endif
BIO_free(b);
@@ -374,9 +374,9 @@ int main(int argc, char **argv)
if (!raw_sig) {
#ifndef USE_PKCS7
- ERR(i2d_CMS_bio_stream(bd, cms, NULL, 0) < 0, "%s", dest_name);
+ ERR(i2d_CMS_bio_stream(bd, cms, NULL, 0) != 1, "%s", dest_name);
#else
- ERR(i2d_PKCS7_bio(bd, pkcs7) < 0, "%s", dest_name);
+ ERR(i2d_PKCS7_bio(bd, pkcs7) != 1, "%s", dest_name);
#endif
} else {
BIO *b;
@@ -396,7 +396,7 @@ int main(int argc, char **argv)
ERR(BIO_write(bd, &sig_info, sizeof(sig_info)) < 0, "%s", dest_name);
ERR(BIO_write(bd, magic_number, sizeof(magic_number) - 1) < 0, "%s", dest_name);
- ERR(BIO_free(bd) < 0, "%s", dest_name);
+ ERR(BIO_free(bd) != 1, "%s", dest_name);
/* Finally, if we're signing in place, replace the original. */
if (replace_orig)
diff --git a/scripts/spelling.txt b/scripts/spelling.txt
index 855c4863124b..edec60d39bbf 100644
--- a/scripts/spelling.txt
+++ b/scripts/spelling.txt
@@ -26,6 +26,7 @@ accelaration||acceleration
accelearion||acceleration
acceleratoin||acceleration
accelleration||acceleration
+accelrometer||accelerometer
accesing||accessing
accesnt||accent
accessable||accessible
@@ -137,6 +138,7 @@ anniversery||anniversary
annoucement||announcement
anomolies||anomalies
anomoly||anomaly
+anonynous||anonymous
anway||anyway
aplication||application
appearence||appearance
@@ -267,6 +269,7 @@ cadidate||candidate
cahces||caches
calender||calendar
calescing||coalescing
+calibraiton||calibration
calle||called
callibration||calibration
callled||called
@@ -288,6 +291,7 @@ capabitilies||capabilities
capablity||capability
capatibilities||capabilities
capapbilities||capabilities
+captuer||capture
caputure||capture
carefuly||carefully
cariage||carriage
@@ -340,6 +344,7 @@ comminucation||communication
commited||committed
commiting||committing
committ||commit
+commmand||command
commnunication||communication
commoditiy||commodity
comsume||consume
@@ -406,6 +411,7 @@ continious||continuous
continous||continuous
continously||continuously
continueing||continuing
+contiuous||continuous
contraints||constraints
contruct||construct
contol||control
@@ -757,6 +763,7 @@ hardward||hardware
havind||having
heirarchically||hierarchically
heirarchy||hierarchy
+heirachy||hierarchy
helpfull||helpful
hearbeat||heartbeat
heterogenous||heterogeneous
@@ -1199,6 +1206,7 @@ priting||printing
privilaged||privileged
privilage||privilege
priviledge||privilege
+priviledged||privileged
priviledges||privileges
privleges||privileges
probaly||probably
@@ -1251,6 +1259,7 @@ purgable||purgeable
pwoer||power
queing||queuing
quering||querying
+querrying||querying
queus||queues
randomally||randomly
raoming||roaming
@@ -1324,6 +1333,7 @@ reseting||resetting
reseved||reserved
reseverd||reserved
resizeable||resizable
+resonable||reasonable
resotre||restore
resouce||resource
resouces||resources
@@ -1427,6 +1437,7 @@ sliped||slipped
softwade||software
softwares||software
soley||solely
+soluation||solution
souce||source
speach||speech
specfic||specific
@@ -1458,6 +1469,7 @@ standart||standard
standy||standby
stardard||standard
staticly||statically
+statisitcs||statistics
statuss||status
stoped||stopped
stoping||stopping
@@ -1548,6 +1560,7 @@ threds||threads
threee||three
threshhold||threshold
thresold||threshold
+throtting||throttling
throught||through
tansition||transition
trackling||tracking
@@ -1571,6 +1584,7 @@ tranasction||transaction
tranceiver||transceiver
tranfer||transfer
tranmission||transmission
+tranport||transport
transcevier||transceiver
transciever||transceiver
transferd||transferred
diff --git a/scripts/sphinx-pre-install b/scripts/sphinx-pre-install
index 1fb88fdceec3..4c781617ffe6 100755
--- a/scripts/sphinx-pre-install
+++ b/scripts/sphinx-pre-install
@@ -32,8 +32,7 @@ my $python_cmd = "";
my $activate_cmd;
my $min_version;
my $cur_version;
-my $rec_version = "1.7.9"; # PDF won't build here
-my $min_pdf_version = "2.4.4"; # Min version where pdf builds
+my $rec_version = "3.4.3";
my $latest_avail_ver;
#
@@ -281,8 +280,6 @@ sub get_sphinx_version($)
sub check_sphinx()
{
- my $default_version;
-
open IN, $conf or die "Can't open $conf";
while (<IN>) {
if (m/^\s*needs_sphinx\s*=\s*[\'\"]([\d\.]+)[\'\"]/) {
@@ -294,18 +291,7 @@ sub check_sphinx()
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\.]+)$/) {
- $default_version=$1;
- last;
- }
- }
- close IN;
-
- die "Can't get default sphinx version from $requirement_file" if (!$default_version);
-
- $virtenv_dir = $virtenv_prefix . $default_version;
+ $virtenv_dir = $virtenv_prefix . "latest";
my $sphinx = get_sphinx_fname();
if ($sphinx eq "") {
@@ -319,8 +305,8 @@ sub check_sphinx()
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, $default_version;
+ printf "ERROR: Sphinx version is %s. It should be >= %s\n",
+ $cur_version, $min_version;
$need_sphinx = 1;
return;
}
@@ -362,6 +348,7 @@ sub give_debian_hints()
{
my %map = (
"python-sphinx" => "python3-sphinx",
+ "yaml" => "python3-yaml",
"ensurepip" => "python3-venv",
"virtualenv" => "virtualenv",
"dot" => "graphviz",
@@ -396,6 +383,7 @@ sub give_redhat_hints()
{
my %map = (
"python-sphinx" => "python3-sphinx",
+ "yaml" => "python3-pyyaml",
"virtualenv" => "python3-virtualenv",
"dot" => "graphviz",
"convert" => "ImageMagick",
@@ -422,6 +410,7 @@ sub give_redhat_hints()
#
my $old = 0;
my $rel;
+ my $noto_sans_redhat = "google-noto-sans-cjk-ttc-fonts";
$rel = $1 if ($system_release =~ /release\s+(\d+)/);
if (!($system_release =~ /Fedora/)) {
@@ -439,6 +428,9 @@ sub give_redhat_hints()
if ($rel && $rel < 26) {
$old = 1;
}
+ if ($rel && $rel >= 38) {
+ $noto_sans_redhat = "google-noto-sans-cjk-fonts";
+ }
}
if (!$rel) {
printf("Couldn't identify release number\n");
@@ -447,8 +439,9 @@ sub give_redhat_hints()
}
if ($pdf) {
- check_missing_file(["/usr/share/fonts/google-noto-cjk/NotoSansCJK-Regular.ttc"],
- "google-noto-sans-cjk-ttc-fonts", 2);
+ check_missing_file(["/usr/share/fonts/google-noto-cjk/NotoSansCJK-Regular.ttc",
+ "/usr/share/fonts/google-noto-sans-cjk-fonts/NotoSansCJK-Regular.ttc"],
+ $noto_sans_redhat, 2);
}
check_rpm_missing(\@fedora26_opt_pkgs, 2) if ($pdf && !$old);
@@ -473,6 +466,7 @@ sub give_opensuse_hints()
{
my %map = (
"python-sphinx" => "python3-sphinx",
+ "yaml" => "python3-pyyaml",
"virtualenv" => "python3-virtualenv",
"dot" => "graphviz",
"convert" => "ImageMagick",
@@ -791,9 +785,6 @@ sub recommend_sphinx_version($)
# Version is OK. Nothing to do.
if ($cur_version && ($cur_version ge $rec_version)) {
- if ($cur_version lt $min_pdf_version) {
- print "note: If you want pdf, you need at least Sphinx $min_pdf_version.\n";
- }
return;
};
@@ -842,10 +833,6 @@ sub recommend_sphinx_version($)
printf "\t. $activate_cmd\n";
deactivate_help();
- if ($latest_avail_ver lt $min_pdf_version) {
- print "note: If you want pdf, you need at least Sphinx $min_pdf_version.\n";
- }
-
return;
}
@@ -959,6 +946,7 @@ sub check_needs()
# Check for needed programs/tools
check_perl_module("Pod::Usage", 0);
+ check_python_module("yaml", 0);
check_program("make", 0);
check_program("gcc", 0);
check_program("dot", 1);
diff --git a/scripts/tags.sh b/scripts/tags.sh
index a70d43723146..191e0461d6d5 100755
--- a/scripts/tags.sh
+++ b/scripts/tags.sh
@@ -3,7 +3,7 @@
# Generate tags or cscope files
# Usage tags.sh <mode>
#
-# mode may be any of: tags, TAGS, cscope
+# mode may be any of: tags, gtags, TAGS, cscope
#
# Uses the following environment variables:
# SUBARCH, SRCARCH, srctree
@@ -50,7 +50,7 @@ fi
find_arch_sources()
{
for i in $archincludedir; do
- prune="$prune -wholename $i -prune -o"
+ local prune="$prune ( -path $i ) -prune -o"
done
find ${tree}arch/$1 $ignore $prune -name "$2" -not -type l -print;
}
@@ -58,7 +58,7 @@ find_arch_sources()
# find sources in arch/$1/include
find_arch_include_sources()
{
- include=$(find ${tree}arch/$1/ -name include -type d -print);
+ local 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;
@@ -81,21 +81,16 @@ find_other_sources()
-name "$1" -not -type l -print;
}
-find_sources()
-{
- find_arch_sources $1 "$2"
-}
-
all_sources()
{
find_arch_include_sources ${SRCARCH} '*.[chS]'
- if [ ! -z "$archinclude" ]; then
+ if [ -n "$archinclude" ]; then
find_arch_include_sources $archinclude '*.[chS]'
fi
find_include_sources '*.[chS]'
for arch in $ALLSOURCE_ARCHS
do
- find_sources $arch '*.[chS]'
+ find_arch_sources $arch '*.[chS]'
done
find_other_sources '*.[chS]'
}
@@ -125,7 +120,7 @@ all_kconfigs()
find ${tree}arch/ -maxdepth 1 $ignore \
-name "Kconfig*" -not -type l -print;
for arch in $ALLSOURCE_ARCHS; do
- find_sources $arch 'Kconfig*'
+ find_arch_sources $arch 'Kconfig*'
done
find_other_sources 'Kconfig*'
}
diff --git a/scripts/xz_wrap.sh b/scripts/xz_wrap.sh
index 76e9cbcfbeab..d06baf626abe 100755
--- a/scripts/xz_wrap.sh
+++ b/scripts/xz_wrap.sh
@@ -15,7 +15,6 @@ LZMA2OPTS=
case $SRCARCH in
x86) BCJ=--x86 ;;
powerpc) BCJ=--powerpc ;;
- ia64) BCJ=--ia64; LZMA2OPTS=pb=4 ;;
arm) BCJ=--arm ;;
sparc) BCJ=--sparc ;;
esac