Commit 68e5c7d4 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'kbuild-v6.12' of git://git.kernel.org/pub/scm/linux/kernel/git/masahiroy/linux-kbuild

Pull Kbuild updates from Masahiro Yamada:

 - Support cross-compiling linux-headers Debian package and kernel-devel
   RPM package

 - Add support for the linux-debug Pacman package

 - Improve module rebuilding speed by factoring out the common code to
   scripts/module-common.c

 - Separate device tree build rules into scripts/Makefile.dtbs

 - Add a new script to generate modules.builtin.ranges, which is useful
   for tracing tools to find symbols in built-in modules

 - Refactor Kconfig and misc tools

 - Update Kbuild and Kconfig documentation

* tag 'kbuild-v6.12' of git://git.kernel.org/pub/scm/linux/kernel/git/masahiroy/linux-kbuild: (51 commits)
  kbuild: doc: replace "gcc" in external module description
  kbuild: doc: describe the -C option precisely for external module builds
  kbuild: doc: remove the description about shipped files
  kbuild: doc: drop section numbering, use references in modules.rst
  kbuild: doc: throw out the local table of contents in modules.rst
  kbuild: doc: remove outdated description of the limitation on -I usage
  kbuild: doc: remove description about grepping CONFIG options
  kbuild: doc: update the description about Kbuild/Makefile split
  kbuild: remove unnecessary export of RUST_LIB_SRC
  kbuild: remove append operation on cmd_ld_ko_o
  kconfig: cache expression values
  kconfig: use hash table to reuse expressions
  kconfig: refactor expr_eliminate_dups()
  kconfig: add comments to expression transformations
  kconfig: change some expr_*() functions to bool
  scripts: move hash function from scripts/kconfig/ to scripts/include/
  kallsyms: change overflow variable to bool type
  kallsyms: squash output_address()
  kbuild: add install target for modules.builtin.ranges
  scripts: add verifier script for builtin module range data
  ...
parents 7f8de2bf fa911d1f
...@@ -47,7 +47,6 @@ ...@@ -47,7 +47,6 @@
*.so.dbg *.so.dbg
*.su *.su
*.symtypes *.symtypes
*.symversions
*.tab.[ch] *.tab.[ch]
*.tar *.tar
*.xz *.xz
...@@ -71,6 +70,7 @@ modules.order ...@@ -71,6 +70,7 @@ modules.order
/Module.markers /Module.markers
/modules.builtin /modules.builtin
/modules.builtin.modinfo /modules.builtin.modinfo
/modules.builtin.ranges
/modules.nsdeps /modules.nsdeps
# #
...@@ -143,7 +143,6 @@ GTAGS ...@@ -143,7 +143,6 @@ GTAGS
# id-utils files # id-utils files
ID ID
*.orig
*~ *~
\#*# \#*#
......
...@@ -180,6 +180,7 @@ modpost ...@@ -180,6 +180,7 @@ modpost
modules-only.symvers modules-only.symvers
modules.builtin modules.builtin
modules.builtin.modinfo modules.builtin.modinfo
modules.builtin.ranges
modules.nsdeps modules.nsdeps
modules.order modules.order
modversions.h* modversions.h*
......
...@@ -22,6 +22,11 @@ modules.builtin.modinfo ...@@ -22,6 +22,11 @@ modules.builtin.modinfo
This file contains modinfo from all modules that are built into the kernel. This file contains modinfo from all modules that are built into the kernel.
Unlike modinfo of a separate module, all fields are prefixed with module name. Unlike modinfo of a separate module, all fields are prefixed with module name.
modules.builtin.ranges
----------------------
This file contains address offset ranges (per ELF section) for all modules
that are built into the kernel. Together with System.map, it can be used
to associate module names with symbols.
Environment variables Environment variables
===================== =====================
...@@ -129,6 +134,11 @@ KBUILD_OUTPUT ...@@ -129,6 +134,11 @@ KBUILD_OUTPUT
------------- -------------
Specify the output directory when building the kernel. Specify the output directory when building the kernel.
This variable can also be used to point to the kernel output directory when
building external modules against a pre-built kernel in a separate build
directory. Please note that this does NOT specify the output directory for the
external modules themselves.
The output directory can also be specified using "O=...". The output directory can also be specified using "O=...".
Setting "O=..." takes precedence over KBUILD_OUTPUT. Setting "O=..." takes precedence over KBUILD_OUTPUT.
......
...@@ -70,7 +70,11 @@ applicable everywhere (see syntax). ...@@ -70,7 +70,11 @@ applicable everywhere (see syntax).
Every menu entry can have at most one prompt, which is used to display Every menu entry can have at most one prompt, which is used to display
to the user. Optionally dependencies only for this prompt can be added to the user. Optionally dependencies only for this prompt can be added
with "if". with "if". If a prompt is not present, the config option is a non-visible
symbol, meaning its value cannot be directly changed by the user (such as
altering the value in ``.config``) and the option will not appear in any
config menus. Its value can only be set via "default" and "select" (see
below).
- default value: "default" <expr> ["if" <expr>] - default value: "default" <expr> ["if" <expr>]
......
...@@ -1665,6 +1665,5 @@ Credits ...@@ -1665,6 +1665,5 @@ Credits
TODO TODO
==== ====
- Describe how kbuild supports shipped files with _shipped.
- Generating offset header files. - Generating offset header files.
- Add more variables to chapters 7 or 9? - Add more variables to chapters 7 or 9?
This diff is collapsed.
...@@ -64,6 +64,7 @@ GNU tar 1.28 tar --version ...@@ -64,6 +64,7 @@ GNU tar 1.28 tar --version
gtags (optional) 6.6.5 gtags --version gtags (optional) 6.6.5 gtags --version
mkimage (optional) 2017.01 mkimage --version mkimage (optional) 2017.01 mkimage --version
Python (optional) 3.5.x python3 --version Python (optional) 3.5.x python3 --version
GNU AWK (optional) 5.1.0 gawk --version
====================== =============== ======================================== ====================== =============== ========================================
.. [#f1] Sphinx is needed only to build the Kernel documentation .. [#f1] Sphinx is needed only to build the Kernel documentation
...@@ -192,6 +193,12 @@ platforms. The tool is available via the ``u-boot-tools`` package or can be ...@@ -192,6 +193,12 @@ platforms. The tool is available via the ``u-boot-tools`` package or can be
built from the U-Boot source code. See the instructions at built from the U-Boot source code. See the instructions at
https://docs.u-boot.org/en/latest/build/tools.html#building-tools-for-linux https://docs.u-boot.org/en/latest/build/tools.html#building-tools-for-linux
GNU AWK
-------
GNU AWK is needed if you want kernel builds to generate address range data for
builtin modules (CONFIG_BUILTIN_MODULE_RANGES).
System utilities System utilities
**************** ****************
......
...@@ -579,10 +579,6 @@ else ...@@ -579,10 +579,6 @@ else
RUSTC_OR_CLIPPY = $(RUSTC) RUSTC_OR_CLIPPY = $(RUSTC)
endif endif
ifdef RUST_LIB_SRC
export RUST_LIB_SRC
endif
# Allows the usage of unstable features in stable compilers. # Allows the usage of unstable features in stable compilers.
export RUSTC_BOOTSTRAP := 1 export RUSTC_BOOTSTRAP := 1
...@@ -1483,6 +1479,7 @@ endif # CONFIG_MODULES ...@@ -1483,6 +1479,7 @@ endif # CONFIG_MODULES
# Directories & files removed with 'make clean' # Directories & files removed with 'make clean'
CLEAN_FILES += vmlinux.symvers modules-only.symvers \ CLEAN_FILES += vmlinux.symvers modules-only.symvers \
modules.builtin modules.builtin.modinfo modules.nsdeps \ modules.builtin modules.builtin.modinfo modules.nsdeps \
modules.builtin.ranges vmlinux.o.map \
compile_commands.json rust/test \ compile_commands.json rust/test \
rust-project.json .vmlinux.objs .vmlinux.export.c rust-project.json .vmlinux.objs .vmlinux.export.c
...@@ -1947,7 +1944,7 @@ clean: $(clean-dirs) ...@@ -1947,7 +1944,7 @@ clean: $(clean-dirs)
-o -name '*.c.[012]*.*' \ -o -name '*.c.[012]*.*' \
-o -name '*.ll' \ -o -name '*.ll' \
-o -name '*.gcno' \ -o -name '*.gcno' \
-o -name '*.*.symversions' \) -type f -print \ \) -type f -print \
-o -name '.tmp_*' -print \ -o -name '.tmp_*' -print \
| xargs rm -rf | xargs rm -rf
......
...@@ -554,7 +554,7 @@ config ARC_BUILTIN_DTB_NAME ...@@ -554,7 +554,7 @@ config ARC_BUILTIN_DTB_NAME
string "Built in DTB" string "Built in DTB"
help help
Set the name of the DTB to embed in the vmlinux binary Set the name of the DTB to embed in the vmlinux binary
Leaving it blank selects the minimal "skeleton" dtb Leaving it blank selects the "nsim_700" dtb.
endmenu # "ARC Architecture Configuration" endmenu # "ARC Architecture Configuration"
......
CONFIG_NOHIGHMEM=y CONFIG_NOHIGHMEM=y
# CONFIG_HIGHMEM4G is not set
# CONFIG_HIGHMEM64G is not set
# CONFIG_UNWINDER_ORC is not set
CONFIG_UNWINDER_GUESS=y CONFIG_UNWINDER_GUESS=y
# CONFIG_UNWINDER_FRAME_POINTER is not set
...@@ -34,7 +34,7 @@ ...@@ -34,7 +34,7 @@
/* /*
* __dtb_empty_root_begin[] and __dtb_empty_root_end[] magically created by * __dtb_empty_root_begin[] and __dtb_empty_root_end[] magically created by
* cmd_dt_S_dtb in scripts/Makefile.lib * cmd_wrap_S_dtb in scripts/Makefile.dtbs
*/ */
extern uint8_t __dtb_empty_root_begin[]; extern uint8_t __dtb_empty_root_begin[];
extern uint8_t __dtb_empty_root_end[]; extern uint8_t __dtb_empty_root_end[];
......
...@@ -1861,7 +1861,7 @@ static int __init unittest_data_add(void) ...@@ -1861,7 +1861,7 @@ static int __init unittest_data_add(void)
struct device_node *unittest_data_node = NULL, *np; struct device_node *unittest_data_node = NULL, *np;
/* /*
* __dtbo_testcases_begin[] and __dtbo_testcases_end[] are magically * __dtbo_testcases_begin[] and __dtbo_testcases_end[] are magically
* created by cmd_dt_S_dtbo in scripts/Makefile.lib * created by cmd_wrap_S_dtbo in scripts/Makefile.dtbs
*/ */
extern uint8_t __dtbo_testcases_begin[]; extern uint8_t __dtbo_testcases_begin[];
extern uint8_t __dtbo_testcases_end[]; extern uint8_t __dtbo_testcases_end[];
...@@ -3525,7 +3525,7 @@ static void __init of_unittest_lifecycle(void) ...@@ -3525,7 +3525,7 @@ static void __init of_unittest_lifecycle(void)
/* /*
* __dtbo_##overlay_name##_begin[] and __dtbo_##overlay_name##_end[] are * __dtbo_##overlay_name##_begin[] and __dtbo_##overlay_name##_end[] are
* created by cmd_dt_S_dtbo in scripts/Makefile.lib * created by cmd_wrap_S_dtbo in scripts/Makefile.dtbs
*/ */
#define OVERLAY_INFO_EXTERN(overlay_name) \ #define OVERLAY_INFO_EXTERN(overlay_name) \
......
# CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE is not set
CONFIG_CC_OPTIMIZE_FOR_SIZE=y CONFIG_CC_OPTIMIZE_FOR_SIZE=y
# CONFIG_KERNEL_GZIP is not set
# CONFIG_KERNEL_BZIP2 is not set
# CONFIG_KERNEL_LZMA is not set
CONFIG_KERNEL_XZ=y CONFIG_KERNEL_XZ=y
# CONFIG_KERNEL_LZO is not set
# CONFIG_KERNEL_LZ4 is not set
CONFIG_SLUB=y CONFIG_SLUB=y
CONFIG_SLUB_TINY=y CONFIG_SLUB_TINY=y
...@@ -573,6 +573,21 @@ config VMLINUX_MAP ...@@ -573,6 +573,21 @@ config VMLINUX_MAP
pieces of code get eliminated with pieces of code get eliminated with
CONFIG_LD_DEAD_CODE_DATA_ELIMINATION. CONFIG_LD_DEAD_CODE_DATA_ELIMINATION.
config BUILTIN_MODULE_RANGES
bool "Generate address range information for builtin modules"
depends on !LTO
depends on VMLINUX_MAP
help
When modules are built into the kernel, there will be no module name
associated with its symbols in /proc/kallsyms. Tracers may want to
identify symbols by module name and symbol name regardless of whether
the module is configured as loadable or not.
This option generates modules.builtin.ranges in the build tree with
offset ranges (per ELF section) for the module(s) they belong to.
It also records an anchor symbol to determine the load address of the
section.
config DEBUG_FORCE_WEAK_PER_CPU config DEBUG_FORCE_WEAK_PER_CPU
bool "Force weak per-cpu definitions" bool "Force weak per-cpu definitions"
depends on DEBUG_KERNEL depends on DEBUG_KERNEL
......
...@@ -41,20 +41,6 @@ include $(srctree)/scripts/Makefile.compiler ...@@ -41,20 +41,6 @@ include $(srctree)/scripts/Makefile.compiler
include $(kbuild-file) include $(kbuild-file)
include $(srctree)/scripts/Makefile.lib include $(srctree)/scripts/Makefile.lib
# Do not include hostprogs rules unless needed.
# $(sort ...) is used here to remove duplicated words and excessive spaces.
hostprogs := $(sort $(hostprogs))
ifneq ($(hostprogs),)
include $(srctree)/scripts/Makefile.host
endif
# Do not include userprogs rules unless needed.
# $(sort ...) is used here to remove duplicated words and excessive spaces.
userprogs := $(sort $(userprogs))
ifneq ($(userprogs),)
include $(srctree)/scripts/Makefile.userprogs
endif
ifndef obj ifndef obj
$(warning kbuild: Makefile.build is included improperly) $(warning kbuild: Makefile.build is included improperly)
endif endif
...@@ -71,7 +57,6 @@ endif ...@@ -71,7 +57,6 @@ endif
# subdir-builtin and subdir-modorder may contain duplications. Use $(sort ...) # subdir-builtin and subdir-modorder may contain duplications. Use $(sort ...)
subdir-builtin := $(sort $(filter %/built-in.a, $(real-obj-y))) subdir-builtin := $(sort $(filter %/built-in.a, $(real-obj-y)))
subdir-modorder := $(sort $(filter %/modules.order, $(obj-m))) subdir-modorder := $(sort $(filter %/modules.order, $(obj-m)))
subdir-dtbslist := $(sort $(filter %/dtbs-list, $(dtb-y)))
targets-for-builtin := $(extra-y) targets-for-builtin := $(extra-y)
...@@ -363,7 +348,7 @@ $(obj)/%.o: $(obj)/%.S FORCE ...@@ -363,7 +348,7 @@ $(obj)/%.o: $(obj)/%.S FORCE
targets += $(filter-out $(subdir-builtin), $(real-obj-y)) targets += $(filter-out $(subdir-builtin), $(real-obj-y))
targets += $(filter-out $(subdir-modorder), $(real-obj-m)) targets += $(filter-out $(subdir-modorder), $(real-obj-m))
targets += $(real-dtb-y) $(lib-y) $(always-y) targets += $(lib-y) $(always-y)
# Linker scripts preprocessor (.lds.S -> .lds) # Linker scripts preprocessor (.lds.S -> .lds)
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
...@@ -389,7 +374,6 @@ $(obj)/%.asn1.c $(obj)/%.asn1.h: $(src)/%.asn1 $(objtree)/scripts/asn1_compiler ...@@ -389,7 +374,6 @@ $(obj)/%.asn1.c $(obj)/%.asn1.h: $(src)/%.asn1 $(objtree)/scripts/asn1_compiler
# To build objects in subdirs, we need to descend into the directories # To build objects in subdirs, we need to descend into the directories
$(subdir-builtin): $(obj)/%/built-in.a: $(obj)/% ; $(subdir-builtin): $(obj)/%/built-in.a: $(obj)/% ;
$(subdir-modorder): $(obj)/%/modules.order: $(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) # Rule to compile a set of .o files into one .a file (without symbol table)
...@@ -405,12 +389,8 @@ quiet_cmd_ar_builtin = AR $@ ...@@ -405,12 +389,8 @@ quiet_cmd_ar_builtin = AR $@
$(obj)/built-in.a: $(real-obj-y) FORCE $(obj)/built-in.a: $(real-obj-y) FORCE
$(call if_changed,ar_builtin) $(call if_changed,ar_builtin)
# # This is a list of build artifacts from the current Makefile and its
# Rule to create modules.order and dtbs-list # sub-directories. The timestamp should be updated when any of the member files.
#
# 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_gen_order = { $(foreach m, $(real-prereqs), \ cmd_gen_order = { $(foreach m, $(real-prereqs), \
$(if $(filter %/$(notdir $@), $m), cat $m, echo $m);) :; } \ $(if $(filter %/$(notdir $@), $m), cat $m, echo $m);) :; } \
...@@ -419,9 +399,6 @@ cmd_gen_order = { $(foreach m, $(real-prereqs), \ ...@@ -419,9 +399,6 @@ cmd_gen_order = { $(foreach m, $(real-prereqs), \
$(obj)/modules.order: $(obj-m) FORCE $(obj)/modules.order: $(obj-m) FORCE
$(call if_changed,gen_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) # Rule to compile a set of .o files into one .a file (with symbol table)
# #
...@@ -450,15 +427,26 @@ intermediate_targets = $(foreach sfx, $(2), \ ...@@ -450,15 +427,26 @@ intermediate_targets = $(foreach sfx, $(2), \
$(patsubst %$(strip $(1)),%$(sfx), \ $(patsubst %$(strip $(1)),%$(sfx), \
$(filter %$(strip $(1)), $(targets)))) $(filter %$(strip $(1)), $(targets))))
# %.asn1.o <- %.asn1.[ch] <- %.asn1 # %.asn1.o <- %.asn1.[ch] <- %.asn1
# %.dtb.o <- %.dtb.S <- %.dtb <- %.dts targets += $(call intermediate_targets, .asn1.o, .asn1.c .asn1.h)
# %.dtbo.o <- %.dtbo.S <- %.dtbo <- %.dtso
# %.lex.o <- %.lex.c <- %.l # Include additional build rules when necessary
# %.tab.o <- %.tab.[ch] <- %.y # ---------------------------------------------------------------------------
targets += $(call intermediate_targets, .asn1.o, .asn1.c .asn1.h) \
$(call intermediate_targets, .dtb.o, .dtb.S .dtb) \ # $(sort ...) is used here to remove duplicated words and excessive spaces.
$(call intermediate_targets, .dtbo.o, .dtbo.S .dtbo) \ hostprogs := $(sort $(hostprogs))
$(call intermediate_targets, .lex.o, .lex.c) \ ifneq ($(hostprogs),)
$(call intermediate_targets, .tab.o, .tab.c .tab.h) include $(srctree)/scripts/Makefile.host
endif
# $(sort ...) is used here to remove duplicated words and excessive spaces.
userprogs := $(sort $(userprogs))
ifneq ($(userprogs),)
include $(srctree)/scripts/Makefile.userprogs
endif
ifneq ($(need-dtbslist)$(dtb-y)$(dtb-)$(filter %.dtb %.dtb.o %.dtbo.o,$(targets)),)
include $(srctree)/scripts/Makefile.dtbs
endif
# Build # Build
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
......
# SPDX-License-Identifier: GPL-2.0-only
# If CONFIG_OF_ALL_DTBS is enabled, all DT blobs are built
dtb-$(CONFIG_OF_ALL_DTBS) += $(dtb-)
# Composite DTB (i.e. DTB constructed by overlay)
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
base-dtb-y := $(filter %.dtb, $(call real-search, $(multi-dtb-y), .dtb, -dtbs))
dtb-y := $(addprefix $(obj)/, $(dtb-y))
multi-dtb-y := $(addprefix $(obj)/, $(multi-dtb-y))
real-dtb-y := $(addprefix $(obj)/, $(real-dtb-y))
always-y += $(dtb-y)
targets += $(real-dtb-y)
# dtbs-list
# ---------------------------------------------------------------------------
ifdef need-dtbslist
subdir-dtbslist := $(addsuffix /dtbs-list, $(subdir-ym))
dtb-y += $(subdir-dtbslist)
always-y += $(obj)/dtbs-list
endif
$(subdir-dtbslist): $(obj)/%/dtbs-list: $(obj)/% ;
$(obj)/dtbs-list: $(dtb-y) FORCE
$(call if_changed,gen_order)
# Assembly file to wrap dtb(o)
# ---------------------------------------------------------------------------
# Generate an assembly file to wrap the output of the device tree compiler
quiet_cmd_wrap_S_dtb = WRAP $@
cmd_wrap_S_dtb = { \
symbase=__$(patsubst .%,%,$(suffix $<))_$(subst -,_,$(notdir $*)); \
echo '\#include <asm-generic/vmlinux.lds.h>'; \
echo '.section .dtb.init.rodata,"a"'; \
echo '.balign STRUCT_ALIGNMENT'; \
echo ".global $${symbase}_begin"; \
echo "$${symbase}_begin:"; \
echo '.incbin "$<" '; \
echo ".global $${symbase}_end"; \
echo "$${symbase}_end:"; \
echo '.balign STRUCT_ALIGNMENT'; \
} > $@
$(obj)/%.dtb.S: $(obj)/%.dtb FORCE
$(call if_changed,wrap_S_dtb)
$(obj)/%.dtbo.S: $(obj)/%.dtbo FORCE
$(call if_changed,wrap_S_dtb)
# Schema check
# ---------------------------------------------------------------------------
ifneq ($(CHECK_DTBS),)
DT_CHECKER ?= dt-validate
DT_CHECKER_FLAGS ?= $(if $(DT_SCHEMA_FILES),-l $(DT_SCHEMA_FILES),-m)
DT_BINDING_DIR := Documentation/devicetree/bindings
DT_TMP_SCHEMA := $(objtree)/$(DT_BINDING_DIR)/processed-schema.json
dtb-check-enabled = $(if $(filter %.dtb, $@),y)
endif
quiet_dtb_check_tag = $(if $(dtb-check-enabled),[C], )
cmd_dtb_check = $(if $(dtb-check-enabled),; $(DT_CHECKER) $(DT_CHECKER_FLAGS) -u $(srctree)/$(DT_BINDING_DIR) -p $(DT_TMP_SCHEMA) $@ || true)
# Overlay
# ---------------------------------------------------------------------------
# NOTE:
# Do not replace $(filter %.dtb %.dtbo, $^) with $(real-prereqs). When a single
# DTB is turned into a multi-blob DTB, $^ will contain header file dependencies
# recorded in the .*.cmd file.
quiet_cmd_fdtoverlay = OVL $(quiet_dtb_check_tag) $@
cmd_fdtoverlay = $(objtree)/scripts/dtc/fdtoverlay -o $@ -i $(filter %.dtb %.dtbo, $^) $(cmd_dtb_check)
$(multi-dtb-y): $(DT_TMP_SCHEMA) FORCE
$(call if_changed,fdtoverlay)
$(call multi_depend, $(multi-dtb-y), .dtb, -dtbs)
# DTC
# ---------------------------------------------------------------------------
DTC ?= $(objtree)/scripts/dtc/dtc
DTC_FLAGS += -Wno-unique_unit_address
# Disable noisy checks by default
ifeq ($(findstring 1,$(KBUILD_EXTRA_WARN)),)
DTC_FLAGS += -Wno-unit_address_vs_reg \
-Wno-avoid_unnecessary_addr_size \
-Wno-alias_paths \
-Wno-graph_child_address \
-Wno-simple_bus_reg
else
DTC_FLAGS += -Wunique_unit_address_if_enabled
endif
ifneq ($(findstring 2,$(KBUILD_EXTRA_WARN)),)
DTC_FLAGS += -Wnode_name_chars_strict \
-Wproperty_name_chars_strict \
-Wunique_unit_address
endif
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)), -@)
DTC_INCLUDE := $(srctree)/scripts/dtc/include-prefixes
dtc_cpp_flags = -Wp,-MMD,$(depfile).pre.tmp -nostdinc -I $(DTC_INCLUDE) -undef -D__DTS__
dtc-tmp = $(subst $(comma),_,$(dot-target).dts.tmp)
quiet_cmd_dtc = DTC $(quiet_dtb_check_tag) $@
cmd_dtc = \
$(HOSTCC) -E $(dtc_cpp_flags) -x assembler-with-cpp -o $(dtc-tmp) $< ; \
$(DTC) -o $@ -b 0 $(addprefix -i,$(dir $<) $(DTC_INCLUDE)) \
$(DTC_FLAGS) -d $(depfile).dtc.tmp $(dtc-tmp) ; \
cat $(depfile).pre.tmp $(depfile).dtc.tmp > $(depfile) \
$(cmd_dtb_check)
$(obj)/%.dtb: $(obj)/%.dts $(DTC) $(DT_TMP_SCHEMA) FORCE
$(call if_changed_dep,dtc)
$(obj)/%.dtbo: $(src)/%.dtso $(DTC) FORCE
$(call if_changed_dep,dtc)
# targets
# ---------------------------------------------------------------------------
targets += $(always-y)
# %.dtb.o <- %.dtb.S <- %.dtb <- %.dts
# %.dtbo.o <- %.dtbo.S <- %.dtbo <- %.dtso
targets += $(call intermediate_targets, .dtb.o, .dtb.S .dtb) \
$(call intermediate_targets, .dtbo.o, .dtbo.S .dtbo)
...@@ -160,3 +160,8 @@ $(host-rust): $(obj)/%: $(src)/%.rs FORCE ...@@ -160,3 +160,8 @@ $(host-rust): $(obj)/%: $(src)/%.rs FORCE
targets += $(host-csingle) $(host-cmulti) $(host-cobjs) \ targets += $(host-csingle) $(host-cmulti) $(host-cobjs) \
$(host-cxxmulti) $(host-cxxobjs) $(host-rust) $(host-cxxmulti) $(host-cxxobjs) $(host-rust)
# %.lex.o <- %.lex.c <- %.l
# %.tab.o <- %.tab.[ch] <- %.y
targets += $(call intermediate_targets, .lex.o, .lex.c) \
$(call intermediate_targets, .tab.o, .tab.c .tab.h)
...@@ -45,11 +45,6 @@ else ...@@ -45,11 +45,6 @@ else
obj-y := $(filter-out %/, $(obj-y)) obj-y := $(filter-out %/, $(obj-y))
endif 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 # Expand $(foo-objs) $(foo-y) etc. by replacing their individuals
suffix-search = $(strip $(foreach s, $3, $($(1:%$(strip $2)=%$s)))) suffix-search = $(strip $(foreach s, $3, $($(1:%$(strip $2)=%$s))))
# List composite targets that are constructed by combining other targets # List composite targets that are constructed by combining other targets
...@@ -80,19 +75,6 @@ always-y += $(hostprogs-always-y) $(hostprogs-always-m) ...@@ -80,19 +75,6 @@ always-y += $(hostprogs-always-y) $(hostprogs-always-m)
userprogs += $(userprogs-always-y) $(userprogs-always-m) userprogs += $(userprogs-always-y) $(userprogs-always-m)
always-y += $(userprogs-always-y) $(userprogs-always-m) always-y += $(userprogs-always-y) $(userprogs-always-m)
# DTB
# If CONFIG_OF_ALL_DTBS is enabled, all DT blobs are built
dtb-$(CONFIG_OF_ALL_DTBS) += $(dtb-)
# Composite DTB (i.e. DTB constructed by overlay)
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
base-dtb-y := $(filter %.dtb, $(call real-search, $(multi-dtb-y), .dtb, -dtbs))
always-y += $(dtb-y)
# Add subdir path # Add subdir path
ifneq ($(obj),.) ifneq ($(obj),.)
...@@ -104,9 +86,6 @@ lib-y := $(addprefix $(obj)/,$(lib-y)) ...@@ -104,9 +86,6 @@ lib-y := $(addprefix $(obj)/,$(lib-y))
real-obj-y := $(addprefix $(obj)/,$(real-obj-y)) real-obj-y := $(addprefix $(obj)/,$(real-obj-y))
real-obj-m := $(addprefix $(obj)/,$(real-obj-m)) real-obj-m := $(addprefix $(obj)/,$(real-obj-m))
multi-obj-m := $(addprefix $(obj)/, $(multi-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)) subdir-ym := $(addprefix $(obj)/,$(subdir-ym))
endif endif
...@@ -238,7 +217,7 @@ modkern_rustflags = \ ...@@ -238,7 +217,7 @@ modkern_rustflags = \
modkern_aflags = $(if $(part-of-module), \ modkern_aflags = $(if $(part-of-module), \
$(KBUILD_AFLAGS_MODULE) $(AFLAGS_MODULE), \ $(KBUILD_AFLAGS_MODULE) $(AFLAGS_MODULE), \
$(KBUILD_AFLAGS_KERNEL) $(AFLAGS_KERNEL)) $(KBUILD_AFLAGS_KERNEL) $(AFLAGS_KERNEL) $(modfile_flags))
c_flags = -Wp,-MMD,$(depfile) $(NOSTDINC_FLAGS) $(LINUXINCLUDE) \ c_flags = -Wp,-MMD,$(depfile) $(NOSTDINC_FLAGS) $(LINUXINCLUDE) \
-include $(srctree)/include/linux/compiler_types.h \ -include $(srctree)/include/linux/compiler_types.h \
...@@ -248,19 +227,13 @@ c_flags = -Wp,-MMD,$(depfile) $(NOSTDINC_FLAGS) $(LINUXINCLUDE) \ ...@@ -248,19 +227,13 @@ c_flags = -Wp,-MMD,$(depfile) $(NOSTDINC_FLAGS) $(LINUXINCLUDE) \
rust_flags = $(_rust_flags) $(modkern_rustflags) @$(objtree)/include/generated/rustc_cfg rust_flags = $(_rust_flags) $(modkern_rustflags) @$(objtree)/include/generated/rustc_cfg
a_flags = -Wp,-MMD,$(depfile) $(NOSTDINC_FLAGS) $(LINUXINCLUDE) \ a_flags = -Wp,-MMD,$(depfile) $(NOSTDINC_FLAGS) $(LINUXINCLUDE) \
$(_a_flags) $(modkern_aflags) $(_a_flags) $(modkern_aflags) $(modname_flags)
cpp_flags = -Wp,-MMD,$(depfile) $(NOSTDINC_FLAGS) $(LINUXINCLUDE) \ cpp_flags = -Wp,-MMD,$(depfile) $(NOSTDINC_FLAGS) $(LINUXINCLUDE) \
$(_cpp_flags) $(_cpp_flags)
ld_flags = $(KBUILD_LDFLAGS) $(ldflags-y) $(LDFLAGS_$(@F)) ld_flags = $(KBUILD_LDFLAGS) $(ldflags-y) $(LDFLAGS_$(@F))
DTC_INCLUDE := $(srctree)/scripts/dtc/include-prefixes
dtc_cpp_flags = -Wp,-MMD,$(depfile).pre.tmp -nostdinc \
$(addprefix -I,$(DTC_INCLUDE)) \
-undef -D__DTS__
ifdef CONFIG_OBJTOOL ifdef CONFIG_OBJTOOL
objtool := $(objtree)/tools/objtool/objtool objtool := $(objtree)/tools/objtool/objtool
...@@ -350,94 +323,6 @@ cmd_objcopy = $(OBJCOPY) $(OBJCOPYFLAGS) $(OBJCOPYFLAGS_$(@F)) $< $@ ...@@ -350,94 +323,6 @@ cmd_objcopy = $(OBJCOPY) $(OBJCOPYFLAGS) $(OBJCOPYFLAGS_$(@F)) $< $@
quiet_cmd_gzip = GZIP $@ quiet_cmd_gzip = GZIP $@
cmd_gzip = cat $(real-prereqs) | $(KGZIP) -n -f -9 > $@ cmd_gzip = cat $(real-prereqs) | $(KGZIP) -n -f -9 > $@
# DTC
# ---------------------------------------------------------------------------
DTC ?= $(objtree)/scripts/dtc/dtc
DTC_FLAGS += \
-Wno-unique_unit_address
# Disable noisy checks by default
ifeq ($(findstring 1,$(KBUILD_EXTRA_WARN)),)
DTC_FLAGS += -Wno-unit_address_vs_reg \
-Wno-avoid_unnecessary_addr_size \
-Wno-alias_paths \
-Wno-graph_child_address \
-Wno-simple_bus_reg
else
DTC_FLAGS += \
-Wunique_unit_address_if_enabled
endif
ifneq ($(findstring 2,$(KBUILD_EXTRA_WARN)),)
DTC_FLAGS += -Wnode_name_chars_strict \
-Wproperty_name_chars_strict \
-Wunique_unit_address
endif
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)), -@)
# Generate an assembly file to wrap the output of the device tree compiler
quiet_cmd_wrap_S_dtb = WRAP $@
cmd_wrap_S_dtb = { \
symbase=__$(patsubst .%,%,$(suffix $<))_$(subst -,_,$(notdir $*)); \
echo '\#include <asm-generic/vmlinux.lds.h>'; \
echo '.section .dtb.init.rodata,"a"'; \
echo '.balign STRUCT_ALIGNMENT'; \
echo ".global $${symbase}_begin"; \
echo "$${symbase}_begin:"; \
echo '.incbin "$<" '; \
echo ".global $${symbase}_end"; \
echo "$${symbase}_end:"; \
echo '.balign STRUCT_ALIGNMENT'; \
} > $@
$(obj)/%.dtb.S: $(obj)/%.dtb FORCE
$(call if_changed,wrap_S_dtb)
$(obj)/%.dtbo.S: $(obj)/%.dtbo FORCE
$(call if_changed,wrap_S_dtb)
quiet_dtb_check_tag = $(if $(dtb-check-enabled),[C], )
cmd_dtb_check = $(if $(dtb-check-enabled),; $(DT_CHECKER) $(DT_CHECKER_FLAGS) -u $(srctree)/$(DT_BINDING_DIR) -p $(DT_TMP_SCHEMA) $@ || true)
quiet_cmd_dtc = DTC $(quiet_dtb_check_tag) $@
cmd_dtc = $(HOSTCC) -E $(dtc_cpp_flags) -x assembler-with-cpp -o $(dtc-tmp) $< ; \
$(DTC) -o $@ -b 0 \
$(addprefix -i,$(dir $<) $(DTC_INCLUDE)) $(DTC_FLAGS) \
-d $(depfile).dtc.tmp $(dtc-tmp) ; \
cat $(depfile).pre.tmp $(depfile).dtc.tmp > $(depfile) \
$(cmd_dtb_check)
# NOTE:
# Do not replace $(filter %.dtb %.dtbo, $^) with $(real-prereqs). When a single
# DTB is turned into a multi-blob DTB, $^ will contain header file dependencies
# recorded in the .*.cmd file.
quiet_cmd_fdtoverlay = OVL $(quiet_dtb_check_tag) $@
cmd_fdtoverlay = $(objtree)/scripts/dtc/fdtoverlay -o $@ -i $(filter %.dtb %.dtbo, $^) $(cmd_dtb_check)
$(multi-dtb-y): FORCE
$(call if_changed,fdtoverlay)
$(call multi_depend, $(multi-dtb-y), .dtb, -dtbs)
ifneq ($(CHECK_DTBS),)
DT_CHECKER ?= dt-validate
DT_CHECKER_FLAGS ?= $(if $(DT_SCHEMA_FILES),-l $(DT_SCHEMA_FILES),-m)
DT_BINDING_DIR := Documentation/devicetree/bindings
DT_TMP_SCHEMA := $(objtree)/$(DT_BINDING_DIR)/processed-schema.json
dtb-check-enabled = $(if $(filter %.dtb, $@),y)
endif
$(obj)/%.dtb: $(obj)/%.dts $(DTC) $(DT_TMP_SCHEMA) FORCE
$(call if_changed_dep,dtc)
$(obj)/%.dtbo: $(src)/%.dtso $(DTC) FORCE
$(call if_changed_dep,dtc)
dtc-tmp = $(subst $(comma),_,$(dot-target).dts.tmp)
# Bzip2 # Bzip2
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
......
...@@ -30,8 +30,11 @@ quiet_cmd_cc_o_c = CC [M] $@ ...@@ -30,8 +30,11 @@ quiet_cmd_cc_o_c = CC [M] $@
%.mod.o: %.mod.c FORCE %.mod.o: %.mod.c FORCE
$(call if_changed_dep,cc_o_c) $(call if_changed_dep,cc_o_c)
$(extmod_prefix).module-common.o: $(srctree)/scripts/module-common.c FORCE
$(call if_changed_dep,cc_o_c)
quiet_cmd_ld_ko_o = LD [M] $@ quiet_cmd_ld_ko_o = LD [M] $@
cmd_ld_ko_o += \ cmd_ld_ko_o = \
$(LD) -r $(KBUILD_LDFLAGS) \ $(LD) -r $(KBUILD_LDFLAGS) \
$(KBUILD_LDFLAGS_MODULE) $(LDFLAGS_MODULE) \ $(KBUILD_LDFLAGS_MODULE) $(LDFLAGS_MODULE) \
-T scripts/module.lds -o $@ $(filter %.o, $^) -T scripts/module.lds -o $@ $(filter %.o, $^)
...@@ -54,13 +57,13 @@ if_changed_except = $(if $(call newer_prereqs_except,$(2))$(cmd-check), \ ...@@ -54,13 +57,13 @@ if_changed_except = $(if $(call newer_prereqs_except,$(2))$(cmd-check), \
printf '%s\n' 'savedcmd_$@ := $(make-cmd)' > $(dot-target).cmd, @:) printf '%s\n' 'savedcmd_$@ := $(make-cmd)' > $(dot-target).cmd, @:)
# Re-generate module BTFs if either module's .ko or vmlinux changed # Re-generate module BTFs if either module's .ko or vmlinux changed
%.ko: %.o %.mod.o scripts/module.lds $(and $(CONFIG_DEBUG_INFO_BTF_MODULES),$(KBUILD_BUILTIN),vmlinux) FORCE %.ko: %.o %.mod.o $(extmod_prefix).module-common.o scripts/module.lds $(and $(CONFIG_DEBUG_INFO_BTF_MODULES),$(KBUILD_BUILTIN),vmlinux) FORCE
+$(call if_changed_except,ld_ko_o,vmlinux) +$(call if_changed_except,ld_ko_o,vmlinux)
ifdef CONFIG_DEBUG_INFO_BTF_MODULES ifdef CONFIG_DEBUG_INFO_BTF_MODULES
+$(if $(newer-prereqs),$(call cmd,btf_ko)) +$(if $(newer-prereqs),$(call cmd,btf_ko))
endif endif
targets += $(modules:%.o=%.ko) $(modules:%.o=%.mod.o) targets += $(modules:%.o=%.ko) $(modules:%.o=%.mod.o) $(extmod_prefix).module-common.o
# Add FORCE to the prerequisites of a target to force it to be always rebuilt. # Add FORCE to the prerequisites of a target to force it to be always rebuilt.
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
......
...@@ -30,10 +30,12 @@ $(MODLIB)/modules.order: modules.order FORCE ...@@ -30,10 +30,12 @@ $(MODLIB)/modules.order: modules.order FORCE
quiet_cmd_install_modorder = INSTALL $@ quiet_cmd_install_modorder = INSTALL $@
cmd_install_modorder = sed 's:^\(.*\)\.o$$:kernel/\1.ko:' $< > $@ cmd_install_modorder = sed 's:^\(.*\)\.o$$:kernel/\1.ko:' $< > $@
# Install modules.builtin(.modinfo) even when CONFIG_MODULES is disabled. # Install modules.builtin(.modinfo,.ranges) even when CONFIG_MODULES is disabled.
install-y += $(addprefix $(MODLIB)/, modules.builtin modules.builtin.modinfo) install-y += $(addprefix $(MODLIB)/, modules.builtin modules.builtin.modinfo)
$(addprefix $(MODLIB)/, modules.builtin modules.builtin.modinfo): $(MODLIB)/%: % FORCE install-$(CONFIG_BUILTIN_MODULE_RANGES) += $(MODLIB)/modules.builtin.ranges
$(addprefix $(MODLIB)/, modules.builtin modules.builtin.modinfo modules.builtin.ranges): $(MODLIB)/%: % FORCE
$(call cmd,install) $(call cmd,install)
endif endif
...@@ -146,7 +148,7 @@ quiet_cmd_gzip = GZIP $@ ...@@ -146,7 +148,7 @@ quiet_cmd_gzip = GZIP $@
quiet_cmd_xz = XZ $@ quiet_cmd_xz = XZ $@
cmd_xz = $(XZ) --check=crc32 --lzma2=dict=1MiB -f $< cmd_xz = $(XZ) --check=crc32 --lzma2=dict=1MiB -f $<
quiet_cmd_zstd = ZSTD $@ quiet_cmd_zstd = ZSTD $@
cmd_zstd = $(ZSTD) -T0 --rm -f -q $< cmd_zstd = $(ZSTD) --rm -f -q $<
$(dst)/%.ko.gz: $(dst)/%.ko FORCE $(dst)/%.ko.gz: $(dst)/%.ko FORCE
$(call cmd,gzip) $(call cmd,gzip)
......
...@@ -147,8 +147,7 @@ snap-pkg: ...@@ -147,8 +147,7 @@ snap-pkg:
PHONY += pacman-pkg PHONY += pacman-pkg
pacman-pkg: pacman-pkg:
@ln -srf $(srctree)/scripts/package/PKGBUILD $(objtree)/PKGBUILD @ln -srf $(srctree)/scripts/package/PKGBUILD $(objtree)/PKGBUILD
+objtree="$(realpath $(objtree))" \ +BUILDDIR="$(realpath $(objtree))/pacman" \
BUILDDIR="$(realpath $(objtree))/pacman" \
CARCH="$(UTS_MACHINE)" \ CARCH="$(UTS_MACHINE)" \
KBUILD_MAKEFLAGS="$(MAKEFLAGS)" \ KBUILD_MAKEFLAGS="$(MAKEFLAGS)" \
KBUILD_REVISION="$(shell $(srctree)/scripts/build-version)" \ KBUILD_REVISION="$(shell $(srctree)/scripts/build-version)" \
......
...@@ -33,6 +33,24 @@ targets += vmlinux ...@@ -33,6 +33,24 @@ targets += vmlinux
vmlinux: scripts/link-vmlinux.sh vmlinux.o $(KBUILD_LDS) FORCE vmlinux: scripts/link-vmlinux.sh vmlinux.o $(KBUILD_LDS) FORCE
+$(call if_changed_dep,link_vmlinux) +$(call if_changed_dep,link_vmlinux)
# module.builtin.ranges
# ---------------------------------------------------------------------------
ifdef CONFIG_BUILTIN_MODULE_RANGES
__default: modules.builtin.ranges
quiet_cmd_modules_builtin_ranges = GEN $@
cmd_modules_builtin_ranges = gawk -f $(real-prereqs) > $@
targets += modules.builtin.ranges
modules.builtin.ranges: $(srctree)/scripts/generate_builtin_ranges.awk \
modules.builtin vmlinux.map vmlinux.o.map FORCE
$(call if_changed,modules_builtin_ranges)
vmlinux.map: vmlinux
@:
endif
# Add FORCE to the prerequisites of a target to force it to be always rebuilt. # Add FORCE to the prerequisites of a target to force it to be always rebuilt.
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
......
...@@ -45,9 +45,12 @@ objtool-args = $(vmlinux-objtool-args-y) --link ...@@ -45,9 +45,12 @@ objtool-args = $(vmlinux-objtool-args-y) --link
# Link of vmlinux.o used for section mismatch analysis # Link of vmlinux.o used for section mismatch analysis
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
vmlinux-o-ld-args-$(CONFIG_BUILTIN_MODULE_RANGES) += -Map=$@.map
quiet_cmd_ld_vmlinux.o = LD $@ quiet_cmd_ld_vmlinux.o = LD $@
cmd_ld_vmlinux.o = \ cmd_ld_vmlinux.o = \
$(LD) ${KBUILD_LDFLAGS} -r -o $@ \ $(LD) ${KBUILD_LDFLAGS} -r -o $@ \
$(vmlinux-o-ld-args-y) \
$(addprefix -T , $(initcalls-lds)) \ $(addprefix -T , $(initcalls-lds)) \
--whole-archive vmlinux.a --no-whole-archive \ --whole-archive vmlinux.a --no-whole-archive \
--start-group $(KBUILD_VMLINUX_LIBS) --end-group \ --start-group $(KBUILD_VMLINUX_LIBS) --end-group \
......
...@@ -99,6 +99,8 @@ ...@@ -99,6 +99,8 @@
#include <stdio.h> #include <stdio.h>
#include <ctype.h> #include <ctype.h>
#include <xalloc.h>
static void usage(void) static void usage(void)
{ {
fprintf(stderr, "Usage: fixdep <depfile> <target> <cmdline>\n"); fprintf(stderr, "Usage: fixdep <depfile> <target> <cmdline>\n");
...@@ -131,12 +133,9 @@ static unsigned int strhash(const char *str, unsigned int sz) ...@@ -131,12 +133,9 @@ static unsigned int strhash(const char *str, unsigned int sz)
static void add_to_hashtable(const char *name, int len, unsigned int hash, static void add_to_hashtable(const char *name, int len, unsigned int hash,
struct item *hashtab[]) struct item *hashtab[])
{ {
struct item *aux = malloc(sizeof(*aux) + len); struct item *aux;
if (!aux) { aux = xmalloc(sizeof(*aux) + len);
perror("fixdep:malloc");
exit(1);
}
memcpy(aux->name, name, len); memcpy(aux->name, name, len);
aux->len = len; aux->len = len;
aux->hash = hash; aux->hash = hash;
...@@ -228,11 +227,7 @@ static void *read_file(const char *filename) ...@@ -228,11 +227,7 @@ static void *read_file(const char *filename)
perror(filename); perror(filename);
exit(2); exit(2);
} }
buf = malloc(st.st_size + 1); buf = xmalloc(st.st_size + 1);
if (!buf) {
perror("fixdep: malloc");
exit(2);
}
if (read(fd, buf, st.st_size) != st.st_size) { if (read(fd, buf, st.st_size) != st.st_size) {
perror("fixdep: read"); perror("fixdep: read");
exit(2); exit(2);
......
This diff is collapsed.
/* SPDX-License-Identifier: GPL-2.0-only */
#ifndef HASH_H
#define HASH_H
static inline unsigned int hash_str(const char *s)
{
/* fnv32 hash */
unsigned int hash = 2166136261U;
for (; *s; s++)
hash = (hash ^ *s) * 0x01000193;
return hash;
}
/* simplified version of functions from include/linux/hash.h */
#define GOLDEN_RATIO_32 0x61C88647
static inline unsigned int hash_32(unsigned int val)
{
return 0x61C88647 * val;
}
static inline unsigned int hash_ptr(const void *ptr)
{
return hash_32((unsigned int)(unsigned long)ptr);
}
#endif /* HASH_H */
...@@ -15,6 +15,23 @@ ...@@ -15,6 +15,23 @@
#define hash_head(table, key) (&(table)[(key) % HASH_SIZE(table)]) #define hash_head(table, key) (&(table)[(key) % HASH_SIZE(table)])
static inline void __hash_init(struct hlist_head *ht, unsigned int sz)
{
unsigned int i;
for (i = 0; i < sz; i++)
INIT_HLIST_HEAD(&ht[i]);
}
/**
* hash_init - initialize a hash table
* @table: hashtable to be initialized
*
* This has to be a macro since HASH_SIZE() will not work on pointers since
* it calculates the size during preprocessing.
*/
#define hash_init(table) __hash_init(table, HASH_SIZE(table))
/** /**
* hash_add - add an object to a hashtable * hash_add - add an object to a hashtable
* @table: hashtable to add to * @table: hashtable to add to
...@@ -24,6 +41,15 @@ ...@@ -24,6 +41,15 @@
#define hash_add(table, node, key) \ #define hash_add(table, node, key) \
hlist_add_head(node, hash_head(table, key)) hlist_add_head(node, hash_head(table, key))
/**
* hash_del - remove an object from a hashtable
* @node: &struct hlist_node of the object to remove
*/
static inline void hash_del(struct hlist_node *node)
{
hlist_del_init(node);
}
/** /**
* hash_for_each - iterate over a hashtable * hash_for_each - iterate over a hashtable
* @table: hashtable to iterate * @table: hashtable to iterate
...@@ -34,6 +60,18 @@ ...@@ -34,6 +60,18 @@
for (int _bkt = 0; _bkt < HASH_SIZE(table); _bkt++) \ for (int _bkt = 0; _bkt < HASH_SIZE(table); _bkt++) \
hlist_for_each_entry(obj, &table[_bkt], member) hlist_for_each_entry(obj, &table[_bkt], member)
/**
* hash_for_each_safe - iterate over a hashtable safe against removal of
* hash entry
* @table: hashtable to iterate
* @obj: the type * to use as a loop cursor for each entry
* @tmp: a &struct hlist_node used for temporary storage
* @member: the name of the hlist_node within the struct
*/
#define hash_for_each_safe(table, obj, tmp, member) \
for (int _bkt = 0; _bkt < HASH_SIZE(table); _bkt++) \
hlist_for_each_entry_safe(obj, tmp, &table[_bkt], member)
/** /**
* hash_for_each_possible - iterate over all possible objects hashing to the * hash_for_each_possible - iterate over all possible objects hashing to the
* same bucket * same bucket
...@@ -45,4 +83,16 @@ ...@@ -45,4 +83,16 @@
#define hash_for_each_possible(table, obj, member, key) \ #define hash_for_each_possible(table, obj, member, key) \
hlist_for_each_entry(obj, hash_head(table, key), member) hlist_for_each_entry(obj, hash_head(table, key), member)
/**
* hash_for_each_possible_safe - iterate over all possible objects hashing to the
* same bucket safe against removals
* @table: hashtable to iterate
* @obj: the type * to use as a loop cursor for each entry
* @tmp: a &struct hlist_node used for temporary storage
* @member: the name of the hlist_node within the struct
* @key: the key of the objects to iterate over
*/
#define hash_for_each_possible_safe(table, obj, tmp, member, key) \
hlist_for_each_entry_safe(obj, tmp, hash_head(table, key), member)
#endif /* HASHTABLE_H */ #endif /* HASHTABLE_H */
...@@ -268,6 +268,63 @@ static inline int list_empty(const struct list_head *head) ...@@ -268,6 +268,63 @@ static inline int list_empty(const struct list_head *head)
*/ */
#define HLIST_HEAD_INIT { .first = NULL } #define HLIST_HEAD_INIT { .first = NULL }
#define INIT_HLIST_HEAD(ptr) ((ptr)->first = NULL)
static inline void INIT_HLIST_NODE(struct hlist_node *h)
{
h->next = NULL;
h->pprev = NULL;
}
/**
* hlist_unhashed - Has node been removed from list and reinitialized?
* @h: Node to be checked
*
* Not that not all removal functions will leave a node in unhashed
* state. For example, hlist_nulls_del_init_rcu() does leave the
* node in unhashed state, but hlist_nulls_del() does not.
*/
static inline int hlist_unhashed(const struct hlist_node *h)
{
return !h->pprev;
}
static inline void __hlist_del(struct hlist_node *n)
{
struct hlist_node *next = n->next;
struct hlist_node **pprev = n->pprev;
*pprev = next;
if (next)
next->pprev = pprev;
}
/**
* hlist_del - Delete the specified hlist_node from its list
* @n: Node to delete.
*
* Note that this function leaves the node in hashed state. Use
* hlist_del_init() or similar instead to unhash @n.
*/
static inline void hlist_del(struct hlist_node *n)
{
__hlist_del(n);
n->next = LIST_POISON1;
n->pprev = LIST_POISON2;
}
/**
* hlist_del_init - Delete the specified hlist_node from its list and initialize
* @n: Node to delete.
*
* Note that this function leaves the node in unhashed state.
*/
static inline void hlist_del_init(struct hlist_node *n)
{
if (!hlist_unhashed(n)) {
__hlist_del(n);
INIT_HLIST_NODE(n);
}
}
/** /**
* hlist_add_head - add a new entry at the beginning of the hlist * hlist_add_head - add a new entry at the beginning of the hlist
...@@ -306,4 +363,16 @@ static inline void hlist_add_head(struct hlist_node *n, struct hlist_head *h) ...@@ -306,4 +363,16 @@ static inline void hlist_add_head(struct hlist_node *n, struct hlist_head *h)
pos; \ pos; \
pos = hlist_entry_safe((pos)->member.next, typeof(*(pos)), member)) pos = hlist_entry_safe((pos)->member.next, typeof(*(pos)), member))
/**
* hlist_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: a &struct hlist_node to use as temporary storage
* @head: the head for your list.
* @member: the name of the hlist_node within the struct.
*/
#define hlist_for_each_entry_safe(pos, n, head, member) \
for (pos = hlist_entry_safe((head)->first, typeof(*pos), member);\
pos && ({ n = pos->member.next; 1; }); \
pos = hlist_entry_safe(n, typeof(*pos), member))
#endif /* LIST_H */ #endif /* LIST_H */
/* SPDX-License-Identifier: GPL-2.0-only */
#ifndef XALLOC_H
#define XALLOC_H
#include <stdlib.h>
#include <string.h>
static inline void *xmalloc(size_t size)
{
void *p = malloc(size);
if (!p)
exit(1);
return p;
}
static inline void *xcalloc(size_t nmemb, size_t size)
{
void *p = calloc(nmemb, size);
if (!p)
exit(1);
return p;
}
static inline void *xrealloc(void *p, size_t size)
{
p = realloc(p, size);
if (!p)
exit(1);
return p;
}
static inline char *xstrdup(const char *s)
{
char *p = strdup(s);
if (!p)
exit(1);
return p;
}
static inline char *xstrndup(const char *s, size_t n)
{
char *p = strndup(s, n);
if (!p)
exit(1);
return p;
}
#endif /* XALLOC_H */
...@@ -27,6 +27,8 @@ ...@@ -27,6 +27,8 @@
#include <ctype.h> #include <ctype.h>
#include <limits.h> #include <limits.h>
#include <xalloc.h>
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof(arr[0])) #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof(arr[0]))
#define KSYM_NAME_LEN 512 #define KSYM_NAME_LEN 512
...@@ -168,12 +170,7 @@ static struct sym_entry *read_symbol(FILE *in, char **buf, size_t *buf_len) ...@@ -168,12 +170,7 @@ static struct sym_entry *read_symbol(FILE *in, char **buf, size_t *buf_len)
* compressed together */ * compressed together */
len++; len++;
sym = malloc(sizeof(*sym) + len + 1); sym = xmalloc(sizeof(*sym) + len + 1);
if (!sym) {
fprintf(stderr, "kallsyms failure: "
"unable to allocate required amount of memory\n");
exit(EXIT_FAILURE);
}
sym->addr = addr; sym->addr = addr;
sym->len = len; sym->len = len;
sym->sym[0] = type; sym->sym[0] = type;
...@@ -278,12 +275,7 @@ static void read_map(const char *in) ...@@ -278,12 +275,7 @@ static void read_map(const char *in)
if (table_cnt >= table_size) { if (table_cnt >= table_size) {
table_size += 10000; table_size += 10000;
table = realloc(table, sizeof(*table) * table_size); table = xrealloc(table, sizeof(*table) * table_size);
if (!table) {
fprintf(stderr, "out of memory\n");
fclose(fp);
exit (1);
}
} }
table[table_cnt++] = sym; table[table_cnt++] = sym;
...@@ -300,15 +292,6 @@ static void output_label(const char *label) ...@@ -300,15 +292,6 @@ static void output_label(const char *label)
printf("%s:\n", label); printf("%s:\n", label);
} }
/* Provide proper symbols relocatability by their '_text' relativeness. */
static void output_address(unsigned long long addr)
{
if (_text <= addr)
printf("\tPTR\t_text + %#llx\n", addr - _text);
else
printf("\tPTR\t_text - %#llx\n", _text - addr);
}
/* uncompress a compressed symbol. When this function is called, the best table /* uncompress a compressed symbol. When this function is called, the best table
* might still be compressed itself, so the function needs to be recursive */ * might still be compressed itself, so the function needs to be recursive */
static int expand_symbol(const unsigned char *data, int len, char *result) static int expand_symbol(const unsigned char *data, int len, char *result)
...@@ -391,12 +374,7 @@ static void write_src(void) ...@@ -391,12 +374,7 @@ static void write_src(void)
/* table of offset markers, that give the offset in the compressed stream /* table of offset markers, that give the offset in the compressed stream
* every 256 symbols */ * every 256 symbols */
markers_cnt = (table_cnt + 255) / 256; markers_cnt = (table_cnt + 255) / 256;
markers = malloc(sizeof(*markers) * markers_cnt); markers = xmalloc(sizeof(*markers) * markers_cnt);
if (!markers) {
fprintf(stderr, "kallsyms failure: "
"unable to allocate required memory\n");
exit(EXIT_FAILURE);
}
output_label("kallsyms_names"); output_label("kallsyms_names");
off = 0; off = 0;
...@@ -477,17 +455,17 @@ static void write_src(void) ...@@ -477,17 +455,17 @@ static void write_src(void)
*/ */
long long offset; long long offset;
int overflow; bool overflow;
if (!absolute_percpu) { if (!absolute_percpu) {
offset = table[i]->addr - relative_base; offset = table[i]->addr - relative_base;
overflow = (offset < 0 || offset > UINT_MAX); overflow = offset < 0 || offset > UINT_MAX;
} else if (symbol_absolute(table[i])) { } else if (symbol_absolute(table[i])) {
offset = table[i]->addr; offset = table[i]->addr;
overflow = (offset < 0 || offset > INT_MAX); overflow = offset < 0 || offset > INT_MAX;
} else { } else {
offset = relative_base - table[i]->addr - 1; offset = relative_base - table[i]->addr - 1;
overflow = (offset < INT_MIN || offset >= 0); overflow = offset < INT_MIN || offset >= 0;
} }
if (overflow) { if (overflow) {
fprintf(stderr, "kallsyms failure: " fprintf(stderr, "kallsyms failure: "
...@@ -501,7 +479,11 @@ static void write_src(void) ...@@ -501,7 +479,11 @@ static void write_src(void)
printf("\n"); printf("\n");
output_label("kallsyms_relative_base"); output_label("kallsyms_relative_base");
output_address(relative_base); /* Provide proper symbols relocatability by their '_text' relativeness. */
if (_text <= relative_base)
printf("\tPTR\t_text + %#llx\n", relative_base - _text);
else
printf("\tPTR\t_text - %#llx\n", _text - relative_base);
printf("\n"); printf("\n");
sort_symbols_by_name(); sort_symbols_by_name();
......
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#include <time.h> #include <time.h>
#include <unistd.h> #include <unistd.h>
#include <xalloc.h>
#include "internal.h" #include "internal.h"
#include "lkc.h" #include "lkc.h"
...@@ -395,6 +396,8 @@ int conf_read_simple(const char *name, int def) ...@@ -395,6 +396,8 @@ int conf_read_simple(const char *name, int def)
} }
} }
expr_invalidate_all();
while (getline_stripped(&line, &line_asize, in) != -1) { while (getline_stripped(&line, &line_asize, in) != -1) {
struct menu *choice; struct menu *choice;
......
This diff is collapsed.
...@@ -29,12 +29,26 @@ enum expr_type { ...@@ -29,12 +29,26 @@ enum expr_type {
}; };
union expr_data { union expr_data {
struct expr *expr; struct expr * const expr;
struct symbol *sym; struct symbol * const sym;
void *_initdata;
}; };
/**
* struct expr - expression
*
* @node: link node for the hash table
* @type: expressoin type
* @val: calculated tristate value
* @val_is_valid: indicate whether the value is valid
* @left: left node
* @right: right node
*/
struct expr { struct expr {
struct hlist_node node;
enum expr_type type; enum expr_type type;
tristate val;
bool val_is_valid;
union expr_data left, right; union expr_data left, right;
}; };
...@@ -168,7 +182,6 @@ enum prop_type { ...@@ -168,7 +182,6 @@ enum prop_type {
P_SELECT, /* select BAR */ P_SELECT, /* select BAR */
P_IMPLY, /* imply BAR */ P_IMPLY, /* imply BAR */
P_RANGE, /* range 7..100 (for a symbol) */ P_RANGE, /* range 7..100 (for a symbol) */
P_SYMBOL, /* where a symbol is defined */
}; };
struct property { struct property {
...@@ -276,14 +289,12 @@ struct expr *expr_alloc_two(enum expr_type type, struct expr *e1, struct expr *e ...@@ -276,14 +289,12 @@ struct expr *expr_alloc_two(enum expr_type type, struct expr *e1, struct expr *e
struct expr *expr_alloc_comp(enum expr_type type, struct symbol *s1, struct symbol *s2); struct expr *expr_alloc_comp(enum expr_type type, struct symbol *s1, struct symbol *s2);
struct expr *expr_alloc_and(struct expr *e1, struct expr *e2); struct expr *expr_alloc_and(struct expr *e1, struct expr *e2);
struct expr *expr_alloc_or(struct expr *e1, struct expr *e2); struct expr *expr_alloc_or(struct expr *e1, struct expr *e2);
struct expr *expr_copy(const struct expr *org);
void expr_free(struct expr *e);
void expr_eliminate_eq(struct expr **ep1, struct expr **ep2); void expr_eliminate_eq(struct expr **ep1, struct expr **ep2);
int expr_eq(struct expr *e1, struct expr *e2); bool expr_eq(struct expr *e1, struct expr *e2);
tristate expr_calc_value(struct expr *e); tristate expr_calc_value(struct expr *e);
struct expr *expr_eliminate_dups(struct expr *e); struct expr *expr_eliminate_dups(struct expr *e);
struct expr *expr_transform(struct expr *e); struct expr *expr_transform(struct expr *e);
int expr_contains_symbol(struct expr *dep, struct symbol *sym); bool expr_contains_symbol(struct expr *dep, struct symbol *sym);
bool expr_depends_symbol(struct expr *dep, struct symbol *sym); bool expr_depends_symbol(struct expr *dep, struct symbol *sym);
struct expr *expr_trans_compare(struct expr *e, enum expr_type type, struct symbol *sym); struct expr *expr_trans_compare(struct expr *e, enum expr_type type, struct symbol *sym);
...@@ -293,7 +304,7 @@ void expr_gstr_print(const struct expr *e, struct gstr *gs); ...@@ -293,7 +304,7 @@ void expr_gstr_print(const struct expr *e, struct gstr *gs);
void expr_gstr_print_revdep(struct expr *e, struct gstr *gs, void expr_gstr_print_revdep(struct expr *e, struct gstr *gs,
tristate pr_type, const char *title); tristate pr_type, const char *title);
static inline int expr_is_yes(const struct expr *e) static inline bool expr_is_yes(const struct expr *e)
{ {
return !e || (e->type == E_SYMBOL && e->left.sym == &symbol_yes); return !e || (e->type == E_SYMBOL && e->left.sym == &symbol_yes);
} }
......
...@@ -11,6 +11,12 @@ extern HASHTABLE_DECLARE(sym_hashtable, SYMBOL_HASHSIZE); ...@@ -11,6 +11,12 @@ extern HASHTABLE_DECLARE(sym_hashtable, SYMBOL_HASHSIZE);
#define for_all_symbols(sym) \ #define for_all_symbols(sym) \
hash_for_each(sym_hashtable, sym, node) hash_for_each(sym_hashtable, sym, node)
#define EXPR_HASHSIZE (1U << 14)
extern HASHTABLE_DECLARE(expr_hashtable, EXPR_HASHSIZE);
void expr_invalidate_all(void);
struct menu; struct menu;
extern struct menu *current_menu, *current_entry; extern struct menu *current_menu, *current_entry;
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <xalloc.h>
#include "lkc.h" #include "lkc.h"
#include "preprocess.h" #include "preprocess.h"
......
...@@ -51,13 +51,7 @@ static inline void xfwrite(const void *str, size_t len, size_t count, FILE *out) ...@@ -51,13 +51,7 @@ static inline void xfwrite(const void *str, size_t len, size_t count, FILE *out)
} }
/* util.c */ /* util.c */
unsigned int strhash(const char *s);
const char *file_lookup(const char *name); 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);
char *xstrdup(const char *s);
char *xstrndup(const char *s, size_t n);
/* lexer.l */ /* lexer.l */
int yylex(void); int yylex(void);
......
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
#include <unistd.h> #include <unistd.h>
#include <list.h> #include <list.h>
#include <xalloc.h>
#include "lkc.h" #include "lkc.h"
#include "lxdialog/dialog.h" #include "lxdialog/dialog.h"
#include "mnconf-common.h" #include "mnconf-common.h"
......
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
#include <string.h> #include <string.h>
#include <list.h> #include <list.h>
#include <xalloc.h>
#include "lkc.h" #include "lkc.h"
#include "internal.h" #include "internal.h"
...@@ -78,10 +79,8 @@ void menu_add_entry(struct symbol *sym) ...@@ -78,10 +79,8 @@ void menu_add_entry(struct symbol *sym)
*last_entry_ptr = menu; *last_entry_ptr = menu;
last_entry_ptr = &menu->next; last_entry_ptr = &menu->next;
current_entry = menu; current_entry = menu;
if (sym) { if (sym)
menu_add_symbol(P_SYMBOL, sym, NULL);
list_add_tail(&menu->link, &sym->menus); list_add_tail(&menu->link, &sym->menus);
}
} }
struct menu *menu_add_menu(void) struct menu *menu_add_menu(void)
...@@ -108,12 +107,13 @@ static struct expr *rewrite_m(struct expr *e) ...@@ -108,12 +107,13 @@ static struct expr *rewrite_m(struct expr *e)
switch (e->type) { switch (e->type) {
case E_NOT: case E_NOT:
e->left.expr = rewrite_m(e->left.expr); e = expr_alloc_one(E_NOT, rewrite_m(e->left.expr));
break; break;
case E_OR: case E_OR:
case E_AND: case E_AND:
e->left.expr = rewrite_m(e->left.expr); e = expr_alloc_two(e->type,
e->right.expr = rewrite_m(e->right.expr); rewrite_m(e->left.expr),
rewrite_m(e->right.expr));
break; break;
case E_SYMBOL: case E_SYMBOL:
/* change 'm' into 'm' && MODULES */ /* change 'm' into 'm' && MODULES */
...@@ -193,21 +193,11 @@ struct property *menu_add_prompt(enum prop_type type, const char *prompt, ...@@ -193,21 +193,11 @@ struct property *menu_add_prompt(enum prop_type type, const char *prompt,
struct menu *menu = current_entry; struct menu *menu = current_entry;
while ((menu = menu->parent) != NULL) { while ((menu = menu->parent) != NULL) {
struct expr *dup_expr;
if (!menu->visibility) if (!menu->visibility)
continue; continue;
/*
* Do not add a reference to the menu's visibility
* expression but use a copy of it. Otherwise the
* expression reduction functions will modify
* expressions that have multiple references which
* can cause unwanted side effects.
*/
dup_expr = expr_copy(menu->visibility);
prop->visible.expr = expr_alloc_and(prop->visible.expr, prop->visible.expr = expr_alloc_and(prop->visible.expr,
dup_expr); menu->visibility);
} }
} }
...@@ -323,7 +313,7 @@ static void _menu_finalize(struct menu *parent, bool inside_choice) ...@@ -323,7 +313,7 @@ static void _menu_finalize(struct menu *parent, bool inside_choice)
*/ */
basedep = rewrite_m(menu->dep); basedep = rewrite_m(menu->dep);
basedep = expr_transform(basedep); basedep = expr_transform(basedep);
basedep = expr_alloc_and(expr_copy(parent->dep), basedep); basedep = expr_alloc_and(parent->dep, basedep);
basedep = expr_eliminate_dups(basedep); basedep = expr_eliminate_dups(basedep);
menu->dep = basedep; menu->dep = basedep;
...@@ -367,7 +357,7 @@ static void _menu_finalize(struct menu *parent, bool inside_choice) ...@@ -367,7 +357,7 @@ static void _menu_finalize(struct menu *parent, bool inside_choice)
*/ */
dep = rewrite_m(prop->visible.expr); dep = rewrite_m(prop->visible.expr);
dep = expr_transform(dep); dep = expr_transform(dep);
dep = expr_alloc_and(expr_copy(basedep), dep); dep = expr_alloc_and(basedep, dep);
dep = expr_eliminate_dups(dep); dep = expr_eliminate_dups(dep);
prop->visible.expr = dep; prop->visible.expr = dep;
...@@ -378,11 +368,11 @@ static void _menu_finalize(struct menu *parent, bool inside_choice) ...@@ -378,11 +368,11 @@ static void _menu_finalize(struct menu *parent, bool inside_choice)
if (prop->type == P_SELECT) { if (prop->type == P_SELECT) {
struct symbol *es = prop_get_symbol(prop); struct symbol *es = prop_get_symbol(prop);
es->rev_dep.expr = expr_alloc_or(es->rev_dep.expr, es->rev_dep.expr = expr_alloc_or(es->rev_dep.expr,
expr_alloc_and(expr_alloc_symbol(menu->sym), expr_copy(dep))); expr_alloc_and(expr_alloc_symbol(menu->sym), dep));
} else if (prop->type == P_IMPLY) { } else if (prop->type == P_IMPLY) {
struct symbol *es = prop_get_symbol(prop); struct symbol *es = prop_get_symbol(prop);
es->implied.expr = expr_alloc_or(es->implied.expr, es->implied.expr = expr_alloc_or(es->implied.expr,
expr_alloc_and(expr_alloc_symbol(menu->sym), expr_copy(dep))); expr_alloc_and(expr_alloc_symbol(menu->sym), dep));
} }
} }
} }
...@@ -442,22 +432,18 @@ static void _menu_finalize(struct menu *parent, bool inside_choice) ...@@ -442,22 +432,18 @@ static void _menu_finalize(struct menu *parent, bool inside_choice)
*/ */
dep = expr_trans_compare(dep, E_UNEQUAL, &symbol_no); dep = expr_trans_compare(dep, E_UNEQUAL, &symbol_no);
dep = expr_eliminate_dups(expr_transform(dep)); dep = expr_eliminate_dups(expr_transform(dep));
dep2 = expr_copy(basedep); dep2 = basedep;
expr_eliminate_eq(&dep, &dep2); expr_eliminate_eq(&dep, &dep2);
expr_free(dep);
if (!expr_is_yes(dep2)) { if (!expr_is_yes(dep2)) {
/* Not superset, quit */ /* Not superset, quit */
expr_free(dep2);
break; break;
} }
/* Superset, put in submenu */ /* Superset, put in submenu */
expr_free(dep2);
next: next:
_menu_finalize(menu, false); _menu_finalize(menu, false);
menu->parent = parent; menu->parent = parent;
last_menu = menu; last_menu = menu;
} }
expr_free(basedep);
if (last_menu) { if (last_menu) {
parent->list = parent->next; parent->list = parent->next;
parent->next = last_menu->next; parent->next = last_menu->next;
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <list.h> #include <list.h>
#include <xalloc.h>
#include "lkc.h" #include "lkc.h"
#include "mnconf-common.h" #include "mnconf-common.h"
#include "nconf.h" #include "nconf.h"
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
* *
* Derived from menuconfig. * Derived from menuconfig.
*/ */
#include <xalloc.h>
#include "nconf.h" #include "nconf.h"
#include "lkc.h" #include "lkc.h"
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include <string.h> #include <string.h>
#include <stdbool.h> #include <stdbool.h>
#include <xalloc.h>
#include "lkc.h" #include "lkc.h"
#include "internal.h" #include "internal.h"
#include "preprocess.h" #include "preprocess.h"
...@@ -530,14 +531,6 @@ void conf_parse(const char *name) ...@@ -530,14 +531,6 @@ void conf_parse(const char *name)
yydebug = 1; yydebug = 1;
yyparse(); 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, str_printf(&autoconf_cmd,
"\n" "\n"
"$(autoconfig): $(deps_config)\n" "$(autoconfig): $(deps_config)\n"
...@@ -715,10 +708,6 @@ static void print_symbol(FILE *out, const struct menu *menu) ...@@ -715,10 +708,6 @@ static void print_symbol(FILE *out, const struct menu *menu)
print_quoted_string(out, prop->text); print_quoted_string(out, prop->text);
fputc('\n', out); fputc('\n', out);
break; break;
case P_SYMBOL:
fputs( " symbol ", out);
fprintf(out, "%s\n", prop->menu->sym->name);
break;
default: default:
fprintf(out, " unknown prop %d!\n", prop->type); fprintf(out, " unknown prop %d!\n", prop->type);
break; break;
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include <array_size.h> #include <array_size.h>
#include <list.h> #include <list.h>
#include <xalloc.h>
#include "internal.h" #include "internal.h"
#include "lkc.h" #include "lkc.h"
#include "preprocess.h" #include "preprocess.h"
......
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <xalloc.h>
#include "lkc.h" #include "lkc.h"
#include "qconf.h" #include "qconf.h"
...@@ -1094,7 +1095,6 @@ QString ConfigInfoView::debug_info(struct symbol *sym) ...@@ -1094,7 +1095,6 @@ QString ConfigInfoView::debug_info(struct symbol *sym)
case P_RANGE: case P_RANGE:
case P_COMMENT: case P_COMMENT:
case P_IMPLY: case P_IMPLY:
case P_SYMBOL:
stream << prop_get_type_name(prop->type); stream << prop_get_type_name(prop->type);
stream << ": "; stream << ": ";
expr_print(prop->expr, expr_print_help, expr_print(prop->expr, expr_print_help,
......
...@@ -9,6 +9,8 @@ ...@@ -9,6 +9,8 @@
#include <string.h> #include <string.h>
#include <regex.h> #include <regex.h>
#include <hash.h>
#include <xalloc.h>
#include "internal.h" #include "internal.h"
#include "lkc.h" #include "lkc.h"
...@@ -517,6 +519,7 @@ void sym_clear_all_valid(void) ...@@ -517,6 +519,7 @@ void sym_clear_all_valid(void)
for_all_symbols(sym) for_all_symbols(sym)
sym->flags &= ~SYMBOL_VALID; sym->flags &= ~SYMBOL_VALID;
expr_invalidate_all();
conf_set_changed(true); conf_set_changed(true);
sym_calc_value(modules_sym); sym_calc_value(modules_sym);
} }
...@@ -892,7 +895,7 @@ struct symbol *sym_lookup(const char *name, int flags) ...@@ -892,7 +895,7 @@ struct symbol *sym_lookup(const char *name, int flags)
case 'n': return &symbol_no; case 'n': return &symbol_no;
} }
} }
hash = strhash(name); hash = hash_str(name);
hash_for_each_possible(sym_hashtable, symbol, node, hash) { hash_for_each_possible(sym_hashtable, symbol, node, hash) {
if (symbol->name && if (symbol->name &&
...@@ -935,7 +938,7 @@ struct symbol *sym_find(const char *name) ...@@ -935,7 +938,7 @@ struct symbol *sym_find(const char *name)
case 'n': return &symbol_no; case 'n': return &symbol_no;
} }
} }
hash = strhash(name); hash = hash_str(name);
hash_for_each_possible(sym_hashtable, symbol, node, hash) { hash_for_each_possible(sym_hashtable, symbol, node, hash) {
if (symbol->name && if (symbol->name &&
...@@ -1321,8 +1324,6 @@ const char *prop_get_type_name(enum prop_type type) ...@@ -1321,8 +1324,6 @@ const char *prop_get_type_name(enum prop_type type)
return "imply"; return "imply";
case P_RANGE: case P_RANGE:
return "range"; return "range";
case P_SYMBOL:
return "symbol";
case P_UNKNOWN: case P_UNKNOWN:
break; break;
} }
......
...@@ -8,19 +8,11 @@ ...@@ -8,19 +8,11 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <hash.h>
#include <hashtable.h> #include <hashtable.h>
#include <xalloc.h>
#include "lkc.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 */ /* hash table of all parsed Kconfig files */
static HASHTABLE_DEFINE(file_hashtable, 1U << 11); static HASHTABLE_DEFINE(file_hashtable, 1U << 11);
...@@ -34,7 +26,7 @@ const char *file_lookup(const char *name) ...@@ -34,7 +26,7 @@ const char *file_lookup(const char *name)
{ {
struct file *file; struct file *file;
size_t len; size_t len;
int hash = strhash(name); int hash = hash_str(name);
hash_for_each_possible(file_hashtable, file, node, hash) hash_for_each_possible(file_hashtable, file, node, hash)
if (!strcmp(name, file->name)) if (!strcmp(name, file->name))
...@@ -102,52 +94,3 @@ char *str_get(const struct gstr *gs) ...@@ -102,52 +94,3 @@ char *str_get(const struct gstr *gs)
{ {
return gs->s; return gs->s;
} }
void *xmalloc(size_t size)
{
void *p = malloc(size);
if (p)
return p;
fprintf(stderr, "Out of memory.\n");
exit(1);
}
void *xcalloc(size_t nmemb, size_t size)
{
void *p = calloc(nmemb, size);
if (p)
return p;
fprintf(stderr, "Out of memory.\n");
exit(1);
}
void *xrealloc(void *p, size_t size)
{
p = realloc(p, size);
if (p)
return p;
fprintf(stderr, "Out of memory.\n");
exit(1);
}
char *xstrdup(const char *s)
{
char *p;
p = strdup(s);
if (p)
return p;
fprintf(stderr, "Out of memory.\n");
exit(1);
}
char *xstrndup(const char *s, size_t n)
{
char *p;
p = strndup(s, n);
if (p)
return p;
fprintf(stderr, "Out of memory.\n");
exit(1);
}
...@@ -203,7 +203,7 @@ kallsymso= ...@@ -203,7 +203,7 @@ kallsymso=
strip_debug= strip_debug=
if is_enabled CONFIG_KALLSYMS; then if is_enabled CONFIG_KALLSYMS; then
truncate -s0 .tmp_vmlinux.kallsyms0.syms true > .tmp_vmlinux.kallsyms0.syms
kallsyms .tmp_vmlinux.kallsyms0.syms .tmp_vmlinux0.kallsyms kallsyms .tmp_vmlinux.kallsyms0.syms .tmp_vmlinux0.kallsyms
fi fi
......
...@@ -8,7 +8,6 @@ int ...@@ -8,7 +8,6 @@ int
main(int argc, char **argv) main(int argc, char **argv)
{ {
unsigned char ei[EI_NIDENT]; unsigned char ei[EI_NIDENT];
union { short s; char c[2]; } endian_test;
if (fread(ei, 1, EI_NIDENT, stdin) != EI_NIDENT) { if (fread(ei, 1, EI_NIDENT, stdin) != EI_NIDENT) {
fprintf(stderr, "Error: input truncated\n"); fprintf(stderr, "Error: input truncated\n");
...@@ -28,30 +27,6 @@ main(int argc, char **argv) ...@@ -28,30 +27,6 @@ main(int argc, char **argv)
default: default:
exit(1); exit(1);
} }
switch (ei[EI_DATA]) {
case ELFDATA2LSB:
printf("#define KERNEL_ELFDATA ELFDATA2LSB\n");
break;
case ELFDATA2MSB:
printf("#define KERNEL_ELFDATA ELFDATA2MSB\n");
break;
default:
exit(1);
}
if (sizeof(unsigned long) == 4) {
printf("#define HOST_ELFCLASS ELFCLASS32\n");
} else if (sizeof(unsigned long) == 8) {
printf("#define HOST_ELFCLASS ELFCLASS64\n");
}
endian_test.s = 0x0102;
if (memcmp(endian_test.c, "\x01\x02", 2) == 0)
printf("#define HOST_ELFDATA ELFDATA2MSB\n");
else if (memcmp(endian_test.c, "\x02\x01", 2) == 0)
printf("#define HOST_ELFDATA ELFDATA2LSB\n");
else
exit(1);
return 0; return 0;
} }
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
#include <hashtable.h> #include <hashtable.h>
#include <list.h> #include <list.h>
#include <xalloc.h>
#include "modpost.h" #include "modpost.h"
#include "../../include/linux/license.h" #include "../../include/linux/license.h"
...@@ -50,6 +51,9 @@ static bool error_occurred; ...@@ -50,6 +51,9 @@ static bool error_occurred;
static bool extra_warn; static bool extra_warn;
bool target_is_big_endian;
bool host_is_big_endian;
/* /*
* Cut off the warnings when there are too many. This typically occurs when * Cut off the warnings when there are too many. This typically occurs when
* vmlinux is missing. ('make modules' without building vmlinux.) * vmlinux is missing. ('make modules' without building vmlinux.)
...@@ -63,20 +67,15 @@ static unsigned int nr_unresolved; ...@@ -63,20 +67,15 @@ static unsigned int nr_unresolved;
#define MODULE_NAME_LEN (64 - sizeof(Elf_Addr)) #define MODULE_NAME_LEN (64 - sizeof(Elf_Addr))
void modpost_log(enum loglevel loglevel, const char *fmt, ...) void modpost_log(bool is_error, const char *fmt, ...)
{ {
va_list arglist; va_list arglist;
switch (loglevel) { if (is_error) {
case LOG_WARN:
fprintf(stderr, "WARNING: ");
break;
case LOG_ERROR:
fprintf(stderr, "ERROR: "); fprintf(stderr, "ERROR: ");
error_occurred = true; error_occurred = true;
break; } else {
default: /* invalid loglevel, ignore */ fprintf(stderr, "WARNING: ");
break;
} }
fprintf(stderr, "modpost: "); fprintf(stderr, "modpost: ");
...@@ -94,14 +93,6 @@ static inline bool strends(const char *str, const char *postfix) ...@@ -94,14 +93,6 @@ static inline bool strends(const char *str, const char *postfix)
return strcmp(str + strlen(str) - strlen(postfix), postfix) == 0; return strcmp(str + strlen(str) - strlen(postfix), postfix) == 0;
} }
void *do_nofail(void *ptr, const char *expr)
{
if (!ptr)
fatal("Memory allocation failure: %s.\n", expr);
return ptr;
}
char *read_text_file(const char *filename) char *read_text_file(const char *filename)
{ {
struct stat st; struct stat st;
...@@ -120,7 +111,7 @@ char *read_text_file(const char *filename) ...@@ -120,7 +111,7 @@ char *read_text_file(const char *filename)
exit(1); exit(1);
} }
buf = NOFAIL(malloc(st.st_size + 1)); buf = xmalloc(st.st_size + 1);
nbytes = st.st_size; nbytes = st.st_size;
...@@ -178,7 +169,7 @@ static struct module *new_module(const char *name, size_t namelen) ...@@ -178,7 +169,7 @@ static struct module *new_module(const char *name, size_t namelen)
{ {
struct module *mod; struct module *mod;
mod = NOFAIL(malloc(sizeof(*mod) + namelen + 1)); mod = xmalloc(sizeof(*mod) + namelen + 1);
memset(mod, 0, sizeof(*mod)); memset(mod, 0, sizeof(*mod));
INIT_LIST_HEAD(&mod->exported_symbols); INIT_LIST_HEAD(&mod->exported_symbols);
...@@ -237,7 +228,7 @@ static inline unsigned int tdb_hash(const char *name) ...@@ -237,7 +228,7 @@ static inline unsigned int tdb_hash(const char *name)
**/ **/
static struct symbol *alloc_symbol(const char *name) static struct symbol *alloc_symbol(const char *name)
{ {
struct symbol *s = NOFAIL(malloc(sizeof(*s) + strlen(name) + 1)); struct symbol *s = xmalloc(sizeof(*s) + strlen(name) + 1);
memset(s, 0, sizeof(*s)); memset(s, 0, sizeof(*s));
strcpy(s->name, name); strcpy(s->name, name);
...@@ -310,8 +301,7 @@ static void add_namespace(struct list_head *head, const char *namespace) ...@@ -310,8 +301,7 @@ static void add_namespace(struct list_head *head, const char *namespace)
struct namespace_list *ns_entry; struct namespace_list *ns_entry;
if (!contains_namespace(head, namespace)) { if (!contains_namespace(head, namespace)) {
ns_entry = NOFAIL(malloc(sizeof(*ns_entry) + ns_entry = xmalloc(sizeof(*ns_entry) + strlen(namespace) + 1);
strlen(namespace) + 1));
strcpy(ns_entry->namespace, namespace); strcpy(ns_entry->namespace, namespace);
list_add_tail(&ns_entry->list, head); list_add_tail(&ns_entry->list, head);
} }
...@@ -366,7 +356,7 @@ static struct symbol *sym_add_exported(const char *name, struct module *mod, ...@@ -366,7 +356,7 @@ static struct symbol *sym_add_exported(const char *name, struct module *mod,
s = alloc_symbol(name); s = alloc_symbol(name);
s->module = mod; s->module = mod;
s->is_gpl_only = gpl_only; s->is_gpl_only = gpl_only;
s->namespace = NOFAIL(strdup(namespace)); s->namespace = xstrdup(namespace);
list_add_tail(&s->list, &mod->exported_symbols); list_add_tail(&s->list, &mod->exported_symbols);
hash_add_symbol(s); hash_add_symbol(s);
...@@ -438,6 +428,18 @@ static int parse_elf(struct elf_info *info, const char *filename) ...@@ -438,6 +428,18 @@ static int parse_elf(struct elf_info *info, const char *filename)
/* Not an ELF file - silently ignore it */ /* Not an ELF file - silently ignore it */
return 0; return 0;
} }
switch (hdr->e_ident[EI_DATA]) {
case ELFDATA2LSB:
target_is_big_endian = false;
break;
case ELFDATA2MSB:
target_is_big_endian = true;
break;
default:
fatal("target endian is unknown\n");
}
/* Fix endianness in ELF header */ /* Fix endianness in ELF header */
hdr->e_type = TO_NATIVE(hdr->e_type); hdr->e_type = TO_NATIVE(hdr->e_type);
hdr->e_machine = TO_NATIVE(hdr->e_machine); hdr->e_machine = TO_NATIVE(hdr->e_machine);
...@@ -622,7 +624,7 @@ static void handle_symbol(struct module *mod, struct elf_info *info, ...@@ -622,7 +624,7 @@ static void handle_symbol(struct module *mod, struct elf_info *info,
if (ELF_ST_TYPE(sym->st_info) == STT_SPARC_REGISTER) if (ELF_ST_TYPE(sym->st_info) == STT_SPARC_REGISTER)
break; break;
if (symname[0] == '.') { if (symname[0] == '.') {
char *munged = NOFAIL(strdup(symname)); char *munged = xstrdup(symname);
munged[0] = '_'; munged[0] = '_';
munged[1] = toupper(munged[1]); munged[1] = toupper(munged[1]);
symname = munged; symname = munged;
...@@ -690,10 +692,7 @@ static char *get_modinfo(struct elf_info *info, const char *tag) ...@@ -690,10 +692,7 @@ static char *get_modinfo(struct elf_info *info, const char *tag)
static const char *sym_name(struct elf_info *elf, Elf_Sym *sym) static const char *sym_name(struct elf_info *elf, Elf_Sym *sym)
{ {
if (sym) return sym ? elf->strtab + sym->st_name : "";
return elf->strtab + sym->st_name;
else
return "(unknown)";
} }
/* /*
...@@ -1006,6 +1005,7 @@ static void default_mismatch_handler(const char *modname, struct elf_info *elf, ...@@ -1006,6 +1005,7 @@ static void default_mismatch_handler(const char *modname, struct elf_info *elf,
Elf_Sym *from; Elf_Sym *from;
const char *tosym; const char *tosym;
const char *fromsym; const char *fromsym;
char taddr_str[16];
from = find_fromsym(elf, faddr, fsecndx); from = find_fromsym(elf, faddr, fsecndx);
fromsym = sym_name(elf, from); fromsym = sym_name(elf, from);
...@@ -1019,10 +1019,17 @@ static void default_mismatch_handler(const char *modname, struct elf_info *elf, ...@@ -1019,10 +1019,17 @@ static void default_mismatch_handler(const char *modname, struct elf_info *elf,
sec_mismatch_count++; sec_mismatch_count++;
warn("%s: section mismatch in reference: %s+0x%x (section: %s) -> %s (section: %s)\n", if (!tosym[0])
modname, fromsym, snprintf(taddr_str, sizeof(taddr_str), "0x%x", (unsigned int)taddr);
(unsigned int)(faddr - (from ? from->st_value : 0)),
fromsec, tosym, tosec); /*
* The format for the reference source: <symbol_name>+<offset> or <address>
* The format for the reference destination: <symbol_name> or <address>
*/
warn("%s: section mismatch in reference: %s%s0x%x (section: %s) -> %s (section: %s)\n",
modname, fromsym, fromsym[0] ? "+" : "",
(unsigned int)(faddr - (fromsym[0] ? from->st_value : 0)),
fromsec, tosym[0] ? tosym : taddr_str, tosec);
if (mismatch->mismatch == EXTABLE_TO_NON_TEXT) { if (mismatch->mismatch == EXTABLE_TO_NON_TEXT) {
if (match(tosec, mismatch->bad_tosec)) if (match(tosec, mismatch->bad_tosec))
...@@ -1662,7 +1669,7 @@ void buf_write(struct buffer *buf, const char *s, int len) ...@@ -1662,7 +1669,7 @@ void buf_write(struct buffer *buf, const char *s, int len)
{ {
if (buf->size - buf->pos < len) { if (buf->size - buf->pos < len) {
buf->size += len + SZ; buf->size += len + SZ;
buf->p = NOFAIL(realloc(buf->p, buf->size)); buf->p = xrealloc(buf->p, buf->size);
} }
strncpy(buf->p + buf->pos, s, len); strncpy(buf->p + buf->pos, s, len);
buf->pos += len; buf->pos += len;
...@@ -1677,7 +1684,7 @@ static void check_exports(struct module *mod) ...@@ -1677,7 +1684,7 @@ static void check_exports(struct module *mod)
exp = find_symbol(s->name); exp = find_symbol(s->name);
if (!exp) { if (!exp) {
if (!s->weak && nr_unresolved++ < MAX_UNRESOLVED_REPORTS) if (!s->weak && nr_unresolved++ < MAX_UNRESOLVED_REPORTS)
modpost_log(warn_unresolved ? LOG_WARN : LOG_ERROR, modpost_log(!warn_unresolved,
"\"%s\" [%s.ko] undefined!\n", "\"%s\" [%s.ko] undefined!\n",
s->name, mod->name); s->name, mod->name);
continue; continue;
...@@ -1700,7 +1707,7 @@ static void check_exports(struct module *mod) ...@@ -1700,7 +1707,7 @@ static void check_exports(struct module *mod)
basename = mod->name; basename = mod->name;
if (!contains_namespace(&mod->imported_namespaces, exp->namespace)) { if (!contains_namespace(&mod->imported_namespaces, exp->namespace)) {
modpost_log(allow_missing_ns_imports ? LOG_WARN : LOG_ERROR, modpost_log(!allow_missing_ns_imports,
"module %s uses symbol %s from namespace %s, but does not import it.\n", "module %s uses symbol %s from namespace %s, but does not import it.\n",
basename, exp->name, exp->namespace); basename, exp->name, exp->namespace);
add_namespace(&mod->missing_namespaces, exp->namespace); add_namespace(&mod->missing_namespaces, exp->namespace);
...@@ -1748,26 +1755,9 @@ static void check_modname_len(struct module *mod) ...@@ -1748,26 +1755,9 @@ static void check_modname_len(struct module *mod)
static void add_header(struct buffer *b, struct module *mod) static void add_header(struct buffer *b, struct module *mod)
{ {
buf_printf(b, "#include <linux/module.h>\n"); buf_printf(b, "#include <linux/module.h>\n");
/*
* Include build-salt.h after module.h in order to
* inherit the definitions.
*/
buf_printf(b, "#define INCLUDE_VERMAGIC\n");
buf_printf(b, "#include <linux/build-salt.h>\n");
buf_printf(b, "#include <linux/elfnote-lto.h>\n");
buf_printf(b, "#include <linux/export-internal.h>\n"); buf_printf(b, "#include <linux/export-internal.h>\n");
buf_printf(b, "#include <linux/vermagic.h>\n");
buf_printf(b, "#include <linux/compiler.h>\n"); buf_printf(b, "#include <linux/compiler.h>\n");
buf_printf(b, "\n"); buf_printf(b, "\n");
buf_printf(b, "#ifdef CONFIG_UNWINDER_ORC\n");
buf_printf(b, "#include <asm/orc_header.h>\n");
buf_printf(b, "ORC_HEADER;\n");
buf_printf(b, "#endif\n");
buf_printf(b, "\n");
buf_printf(b, "BUILD_SALT;\n");
buf_printf(b, "BUILD_LTO_INFO;\n");
buf_printf(b, "\n");
buf_printf(b, "MODULE_INFO(vermagic, VERMAGIC_STRING);\n");
buf_printf(b, "MODULE_INFO(name, KBUILD_MODNAME);\n"); buf_printf(b, "MODULE_INFO(name, KBUILD_MODNAME);\n");
buf_printf(b, "\n"); buf_printf(b, "\n");
buf_printf(b, "__visible struct module __this_module\n"); buf_printf(b, "__visible struct module __this_module\n");
...@@ -1785,12 +1775,6 @@ static void add_header(struct buffer *b, struct module *mod) ...@@ -1785,12 +1775,6 @@ static void add_header(struct buffer *b, struct module *mod)
if (!external_module) if (!external_module)
buf_printf(b, "\nMODULE_INFO(intree, \"Y\");\n"); buf_printf(b, "\nMODULE_INFO(intree, \"Y\");\n");
buf_printf(b,
"\n"
"#ifdef CONFIG_MITIGATION_RETPOLINE\n"
"MODULE_INFO(retpoline, \"Y\");\n"
"#endif\n");
if (strstarts(mod->name, "drivers/staging")) if (strstarts(mod->name, "drivers/staging"))
buf_printf(b, "\nMODULE_INFO(staging, \"Y\");\n"); buf_printf(b, "\nMODULE_INFO(staging, \"Y\");\n");
...@@ -1947,7 +1931,7 @@ static void write_if_changed(struct buffer *b, const char *fname) ...@@ -1947,7 +1931,7 @@ static void write_if_changed(struct buffer *b, const char *fname)
if (st.st_size != b->pos) if (st.st_size != b->pos)
goto close_write; goto close_write;
tmp = NOFAIL(malloc(b->pos)); tmp = xmalloc(b->pos);
if (fread(tmp, 1, b->pos, file) != b->pos) if (fread(tmp, 1, b->pos, file) != b->pos)
goto free_write; goto free_write;
...@@ -2117,6 +2101,25 @@ struct dump_list { ...@@ -2117,6 +2101,25 @@ struct dump_list {
const char *file; const char *file;
}; };
static void check_host_endian(void)
{
static const union {
short s;
char c[2];
} endian_test = { .c = {0x01, 0x02} };
switch (endian_test.s) {
case 0x0102:
host_is_big_endian = true;
break;
case 0x0201:
host_is_big_endian = false;
break;
default:
fatal("Unknown host endian\n");
}
}
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
struct module *mod; struct module *mod;
...@@ -2133,7 +2136,7 @@ int main(int argc, char **argv) ...@@ -2133,7 +2136,7 @@ int main(int argc, char **argv)
external_module = true; external_module = true;
break; break;
case 'i': case 'i':
dl = NOFAIL(malloc(sizeof(*dl))); dl = xmalloc(sizeof(*dl));
dl->file = optarg; dl->file = optarg;
list_add_tail(&dl->list, &dump_lists); list_add_tail(&dl->list, &dump_lists);
break; break;
...@@ -2181,6 +2184,8 @@ int main(int argc, char **argv) ...@@ -2181,6 +2184,8 @@ int main(int argc, char **argv)
} }
} }
check_host_endian();
list_for_each_entry_safe(dl, dl2, &dump_lists, list) { list_for_each_entry_safe(dl, dl2, &dump_lists, list) {
read_dump(dl->file); read_dump(dl->file);
list_del(&dl->list); list_del(&dl->list);
......
...@@ -62,22 +62,11 @@ ...@@ -62,22 +62,11 @@
x); \ x); \
}) })
#if KERNEL_ELFDATA != HOST_ELFDATA #define TO_NATIVE(x) \
(target_is_big_endian == host_is_big_endian ? x : bswap(x))
#define TO_NATIVE(x) (bswap(x))
#else /* endianness matches */
#define TO_NATIVE(x) (x)
#endif
#define NOFAIL(ptr) do_nofail((ptr), #ptr)
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
void *do_nofail(void *ptr, const char *expr);
struct buffer { struct buffer {
char *p; char *p;
int pos; int pos;
...@@ -187,17 +176,14 @@ void add_moddevtable(struct buffer *buf, struct module *mod); ...@@ -187,17 +176,14 @@ void add_moddevtable(struct buffer *buf, struct module *mod);
void get_src_version(const char *modname, char sum[], unsigned sumlen); void get_src_version(const char *modname, char sum[], unsigned sumlen);
/* from modpost.c */ /* from modpost.c */
extern bool target_is_big_endian;
extern bool host_is_big_endian;
char *read_text_file(const char *filename); char *read_text_file(const char *filename);
char *get_line(char **stringp); char *get_line(char **stringp);
void *sym_get_data(const struct elf_info *info, const Elf_Sym *sym); void *sym_get_data(const struct elf_info *info, const Elf_Sym *sym);
enum loglevel {
LOG_WARN,
LOG_ERROR,
};
void __attribute__((format(printf, 2, 3))) void __attribute__((format(printf, 2, 3)))
modpost_log(enum loglevel loglevel, const char *fmt, ...); modpost_log(bool is_error, const char *fmt, ...);
/* /*
* warn - show the given message, then let modpost continue running, still * warn - show the given message, then let modpost continue running, still
...@@ -212,6 +198,6 @@ modpost_log(enum loglevel loglevel, const char *fmt, ...); ...@@ -212,6 +198,6 @@ modpost_log(enum loglevel loglevel, const char *fmt, ...);
* fatal - show the given message, and bail out immediately. This should be * fatal - show the given message, and bail out immediately. This should be
* used when there is no point to continue running modpost. * used when there is no point to continue running modpost.
*/ */
#define warn(fmt, args...) modpost_log(LOG_WARN, fmt, ##args) #define warn(fmt, args...) modpost_log(false, fmt, ##args)
#define error(fmt, args...) modpost_log(LOG_ERROR, fmt, ##args) #define error(fmt, args...) modpost_log(true, fmt, ##args)
#define fatal(fmt, args...) do { error(fmt, ##args); exit(1); } while (1) #define fatal(fmt, args...) do { error(fmt, ##args); exit(1); } while (1)
...@@ -8,6 +8,8 @@ ...@@ -8,6 +8,8 @@
#include <errno.h> #include <errno.h>
#include <string.h> #include <string.h>
#include <limits.h> #include <limits.h>
#include <xalloc.h>
#include "modpost.h" #include "modpost.h"
/* /*
...@@ -305,7 +307,7 @@ static int parse_source_files(const char *objfile, struct md4_ctx *md) ...@@ -305,7 +307,7 @@ static int parse_source_files(const char *objfile, struct md4_ctx *md)
const char *base; const char *base;
int dirlen, ret = 0, check_files = 0; int dirlen, ret = 0, check_files = 0;
cmd = NOFAIL(malloc(strlen(objfile) + sizeof("..cmd"))); cmd = xmalloc(strlen(objfile) + sizeof("..cmd"));
base = strrchr(objfile, '/'); base = strrchr(objfile, '/');
if (base) { if (base) {
...@@ -316,7 +318,7 @@ static int parse_source_files(const char *objfile, struct md4_ctx *md) ...@@ -316,7 +318,7 @@ static int parse_source_files(const char *objfile, struct md4_ctx *md)
dirlen = 0; dirlen = 0;
sprintf(cmd, ".%s.cmd", objfile); sprintf(cmd, ".%s.cmd", objfile);
} }
dir = NOFAIL(malloc(dirlen + 1)); dir = xmalloc(dirlen + 1);
strncpy(dir, objfile, dirlen); strncpy(dir, objfile, dirlen);
dir[dirlen] = '\0'; dir[dirlen] = '\0';
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
* Helper functions for finding the symbol in an ELF which is "nearest" * Helper functions for finding the symbol in an ELF which is "nearest"
* to a given address. * to a given address.
*/ */
#include <xalloc.h>
#include "modpost.h" #include "modpost.h"
struct syminfo { struct syminfo {
...@@ -125,8 +125,8 @@ void symsearch_init(struct elf_info *elf) ...@@ -125,8 +125,8 @@ void symsearch_init(struct elf_info *elf)
{ {
unsigned int table_size = symbol_count(elf); unsigned int table_size = symbol_count(elf);
elf->symsearch = NOFAIL(malloc(sizeof(struct symsearch) + elf->symsearch = xmalloc(sizeof(struct symsearch) +
sizeof(struct syminfo) * table_size)); sizeof(struct syminfo) * table_size);
elf->symsearch->table_size = table_size; elf->symsearch->table_size = table_size;
symsearch_populate(elf, elf->symsearch->table, table_size); symsearch_populate(elf, elf->symsearch->table, table_size);
......
// SPDX-License-Identifier: GPL-2.0
#include <linux/module.h>
/*
* Include build-salt.h after module.h in order to
* inherit the definitions.
*/
#define INCLUDE_VERMAGIC
#include <linux/build-salt.h>
#include <linux/elfnote-lto.h>
#include <linux/vermagic.h>
#ifdef CONFIG_UNWINDER_ORC
#include <asm/orc_header.h>
ORC_HEADER;
#endif
BUILD_SALT;
BUILD_LTO_INFO;
MODULE_INFO(vermagic, VERMAGIC_STRING);
#ifdef CONFIG_MITIGATION_RETPOLINE
MODULE_INFO(retpoline, "Y");
#endif
...@@ -3,10 +3,13 @@ ...@@ -3,10 +3,13 @@
# Contributor: Jan Alexander Steffens (heftig) <heftig@archlinux.org> # Contributor: Jan Alexander Steffens (heftig) <heftig@archlinux.org>
pkgbase=${PACMAN_PKGBASE:-linux-upstream} pkgbase=${PACMAN_PKGBASE:-linux-upstream}
pkgname=("${pkgbase}" "${pkgbase}-api-headers") pkgname=("${pkgbase}")
if grep -q CONFIG_MODULES=y include/config/auto.conf; then
pkgname+=("${pkgbase}-headers") _extrapackages=${PACMAN_EXTRAPACKAGES-headers api-headers debug}
fi for pkg in $_extrapackages; do
pkgname+=("${pkgbase}-${pkg}")
done
pkgver="${KERNELRELEASE//-/_}" pkgver="${KERNELRELEASE//-/_}"
# The PKGBUILD is evaluated multiple times. # The PKGBUILD is evaluated multiple times.
# Running scripts/build-version from here would introduce inconsistencies. # Running scripts/build-version from here would introduce inconsistencies.
...@@ -33,11 +36,17 @@ makedepends=( ...@@ -33,11 +36,17 @@ makedepends=(
) )
options=(!debug !strip !buildflags !makeflags) options=(!debug !strip !buildflags !makeflags)
build() { _prologue() {
# MAKEFLAGS from makepkg.conf override the ones inherited from kbuild. # MAKEFLAGS from makepkg.conf override the ones inherited from kbuild.
# Bypass this override with a custom variable. # Bypass this override with a custom variable.
export MAKEFLAGS="${KBUILD_MAKEFLAGS}" export MAKEFLAGS="${KBUILD_MAKEFLAGS}"
cd "${objtree}"
# Kbuild works in the output directory, where this PKGBUILD is located.
cd "$(dirname "${BASH_SOURCE[0]}")"
}
build() {
_prologue
${MAKE} KERNELRELEASE="${KERNELRELEASE}" KBUILD_BUILD_VERSION="${pkgrel}" ${MAKE} KERNELRELEASE="${KERNELRELEASE}" KBUILD_BUILD_VERSION="${pkgrel}"
} }
...@@ -45,10 +54,10 @@ build() { ...@@ -45,10 +54,10 @@ build() {
_package() { _package() {
pkgdesc="The ${pkgdesc} kernel and modules" pkgdesc="The ${pkgdesc} kernel and modules"
export MAKEFLAGS="${KBUILD_MAKEFLAGS}"
cd "${objtree}"
local modulesdir="${pkgdir}/usr/${MODLIB}" local modulesdir="${pkgdir}/usr/${MODLIB}"
_prologue
echo "Installing boot image..." echo "Installing boot image..."
# systemd expects to find the kernel here to allow hibernation # systemd expects to find the kernel here to allow hibernation
# https://github.com/systemd/systemd/commit/edda44605f06a41fb86b7ab8128dcf99161d2344 # https://github.com/systemd/systemd/commit/edda44605f06a41fb86b7ab8128dcf99161d2344
...@@ -73,14 +82,17 @@ _package() { ...@@ -73,14 +82,17 @@ _package() {
_package-headers() { _package-headers() {
pkgdesc="Headers and scripts for building modules for the ${pkgdesc} kernel" pkgdesc="Headers and scripts for building modules for the ${pkgdesc} kernel"
export MAKEFLAGS="${KBUILD_MAKEFLAGS}"
cd "${objtree}"
local builddir="${pkgdir}/usr/${MODLIB}/build" local builddir="${pkgdir}/usr/${MODLIB}/build"
_prologue
if grep -q CONFIG_MODULES=y include/config/auto.conf; then
echo "Installing build files..." echo "Installing build files..."
"${srctree}/scripts/package/install-extmod-build" "${builddir}" "${srctree}/scripts/package/install-extmod-build" "${builddir}"
fi
echo "Installing System.map and config..." echo "Installing System.map and config..."
mkdir -p "${builddir}"
cp System.map "${builddir}/System.map" cp System.map "${builddir}/System.map"
cp .config "${builddir}/.config" cp .config "${builddir}/.config"
...@@ -94,12 +106,24 @@ _package-api-headers() { ...@@ -94,12 +106,24 @@ _package-api-headers() {
provides=(linux-api-headers) provides=(linux-api-headers)
conflicts=(linux-api-headers) conflicts=(linux-api-headers)
export MAKEFLAGS="${KBUILD_MAKEFLAGS}" _prologue
cd "${objtree}"
${MAKE} headers_install INSTALL_HDR_PATH="${pkgdir}/usr" ${MAKE} headers_install INSTALL_HDR_PATH="${pkgdir}/usr"
} }
_package-debug(){
pkgdesc="Non-stripped vmlinux file for the ${pkgdesc} kernel"
local debugdir="${pkgdir}/usr/src/debug/${pkgbase}"
local builddir="${pkgdir}/usr/${MODLIB}/build"
_prologue
install -Dt "${debugdir}" -m644 vmlinux
mkdir -p "${builddir}"
ln -sr "${debugdir}/vmlinux" "${builddir}/vmlinux"
}
for _p in "${pkgname[@]}"; do for _p in "${pkgname[@]}"; do
eval "package_$_p() { eval "package_$_p() {
$(declare -f "_package${_p#$pkgbase}") $(declare -f "_package${_p#$pkgbase}")
......
...@@ -9,15 +9,22 @@ is_enabled() { ...@@ -9,15 +9,22 @@ is_enabled() {
grep -q "^$1=y" include/config/auto.conf grep -q "^$1=y" include/config/auto.conf
} }
find_in_scripts() {
find scripts \
\( -name atomic -o -name dtc -o -name kconfig -o -name package \) -prune -o \
! -name unifdef -a ! -name mk_elfconfig -a \( -type f -o -type l \) -print
}
mkdir -p "${destdir}" mkdir -p "${destdir}"
( (
cd "${srctree}" cd "${srctree}"
echo Makefile echo Makefile
find "arch/${SRCARCH}" -maxdepth 1 -name 'Makefile*' find "arch/${SRCARCH}" -maxdepth 1 -name 'Makefile*'
find include scripts -type f -o -type l find "arch/${SRCARCH}" -name generated -prune -o -name include -type d -print
find "arch/${SRCARCH}" -name Kbuild.platforms -o -name Platform find "arch/${SRCARCH}" -name Kbuild.platforms -o -name Platform
find "arch/${SRCARCH}" -name include -type d find include \( -name config -o -name generated \) -prune -o \( -type f -o -type l \) -print
find_in_scripts
) | tar -c -f - -C "${srctree}" -T - | tar -xf - -C "${destdir}" ) | tar -c -f - -C "${srctree}" -T - | tar -xf - -C "${destdir}"
{ {
...@@ -25,12 +32,50 @@ mkdir -p "${destdir}" ...@@ -25,12 +32,50 @@ mkdir -p "${destdir}"
echo tools/objtool/objtool echo tools/objtool/objtool
fi fi
find "arch/${SRCARCH}/include" Module.symvers include scripts -type f echo Module.symvers
echo "arch/${SRCARCH}/include/generated"
echo include/config/auto.conf
echo include/config/kernel.release
echo include/generated
find_in_scripts
if is_enabled CONFIG_GCC_PLUGINS; then if is_enabled CONFIG_GCC_PLUGINS; then
find scripts/gcc-plugins -name '*.so' find scripts/gcc-plugins -name '*.so'
fi fi
} | tar -c -f - -T - | tar -xf - -C "${destdir}" } | tar -c -f - -T - | tar -xf - -C "${destdir}"
# copy .config manually to be where it's expected to be # When ${CC} and ${HOSTCC} differ, we are likely cross-compiling. Rebuild host
cp "${KCONFIG_CONFIG}" "${destdir}/.config" # programs using ${CC}. This assumes CC=${CROSS_COMPILE}gcc, which is usually
# the case for package building. It does not cross-compile when CC=clang.
#
# This caters to host programs that participate in Kbuild. objtool and
# resolve_btfids are out of scope.
if [ "${CC}" != "${HOSTCC}" ] && is_enabled CONFIG_CC_CAN_LINK; then
echo "Rebuilding host programs with ${CC}..."
cat <<-'EOF' > "${destdir}/Kbuild"
subdir-y := scripts
EOF
# HOSTCXX is not overridden. The C++ compiler is used to build:
# - scripts/kconfig/qconf, which is unneeded for external module builds
# - GCC plugins, which will not work on the installed system even after
# being rebuilt.
#
# Use the single-target build to avoid the modpost invocation, which
# would overwrite Module.symvers.
"${MAKE}" HOSTCC="${CC}" KBUILD_EXTMOD="${destdir}" scripts/
cat <<-'EOF' > "${destdir}/scripts/Kbuild"
subdir-y := basic
hostprogs-always-y := mod/modpost
mod/modpost-objs := $(addprefix mod/, modpost.o file2alias.o sumversion.o symsearch.o)
EOF
# Run once again to rebuild scripts/basic/ and scripts/mod/modpost.
"${MAKE}" HOSTCC="${CC}" KBUILD_EXTMOD="${destdir}" scripts/
rm -f "${destdir}/Kbuild" "${destdir}/scripts/Kbuild"
fi
find "${destdir}" \( -name '.*.cmd' -o -name '*.o' \) -delete
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
SUBARCH := $(shell uname -m | sed -e s/i.86/x86/ -e s/x86_64/x86/ \ SUBARCH := $(shell uname -m | sed -e s/i.86/x86/ -e s/x86_64/x86/ \
-e s/sun4u/sparc64/ \ -e s/sun4u/sparc64/ \
-e s/arm.*/arm/ -e s/sa110/arm/ \ -e /^arm64$$/!s/arm.*/arm/ -e s/sa110/arm/ \
-e s/s390x/s390/ \ -e s/s390x/s390/ \
-e s/ppc.*/powerpc/ -e s/mips.*/mips/ \ -e s/ppc.*/powerpc/ -e s/mips.*/mips/ \
-e s/sh[234].*/sh/ -e s/aarch64.*/arm64/ \ -e s/sh[234].*/sh/ -e s/aarch64.*/arm64/ \
......
#!/usr/bin/gawk -f
# SPDX-License-Identifier: GPL-2.0
# verify_builtin_ranges.awk: Verify address range data for builtin modules
# Written by Kris Van Hees <kris.van.hees@oracle.com>
#
# Usage: verify_builtin_ranges.awk modules.builtin.ranges System.map \
# modules.builtin vmlinux.map vmlinux.o.map
#
# Return the module name(s) (if any) associated with the given object.
#
# If we have seen this object before, return information from the cache.
# Otherwise, retrieve it from the corresponding .cmd file.
#
function get_module_info(fn, mod, obj, s) {
if (fn in omod)
return omod[fn];
if (match(fn, /\/[^/]+$/) == 0)
return "";
obj = fn;
mod = "";
fn = substr(fn, 1, RSTART) "." substr(fn, RSTART + 1) ".cmd";
if (getline s <fn == 1) {
if (match(s, /DKBUILD_MODFILE=['"]+[^'"]+/) > 0) {
mod = substr(s, RSTART + 16, RLENGTH - 16);
gsub(/['"]/, "", mod);
} else if (match(s, /RUST_MODFILE=[^ ]+/) > 0)
mod = substr(s, RSTART + 13, RLENGTH - 13);
} else {
print "ERROR: Failed to read: " fn "\n\n" \
" For kernels built with O=<objdir>, cd to <objdir>\n" \
" and execute this script as ./source/scripts/..." \
>"/dev/stderr";
close(fn);
total = 0;
exit(1);
}
close(fn);
# A single module (common case) also reflects objects that are not part
# of a module. Some of those objects have names that are also a module
# name (e.g. core). We check the associated module file name, and if
# they do not match, the object is not part of a module.
if (mod !~ / /) {
if (!(mod in mods))
mod = "";
}
gsub(/([^/ ]*\/)+/, "", mod);
gsub(/-/, "_", mod);
# At this point, mod is a single (valid) module name, or a list of
# module names (that do not need validation).
omod[obj] = mod;
return mod;
}
# Return a representative integer value for a given hexadecimal address.
#
# Since all kernel addresses fall within the same memory region, we can safely
# strip off the first 6 hex digits before performing the hex-to-dec conversion,
# thereby avoiding integer overflows.
#
function addr2val(val) {
sub(/^0x/, "", val);
if (length(val) == 16)
val = substr(val, 5);
return strtonum("0x" val);
}
# Determine the kernel build directory to use (default is .).
#
BEGIN {
if (ARGC < 6) {
print "Syntax: verify_builtin_ranges.awk <ranges-file> <system-map>\n" \
" <builtin-file> <vmlinux-map> <vmlinux-o-map>\n" \
>"/dev/stderr";
total = 0;
exit(1);
}
}
# (1) Load the built-in module address range data.
#
ARGIND == 1 {
ranges[FNR] = $0;
rcnt++;
next;
}
# (2) Annotate System.map symbols with module names.
#
ARGIND == 2 {
addr = addr2val($1);
name = $3;
while (addr >= mod_eaddr) {
if (sect_symb) {
if (sect_symb != name)
next;
sect_base = addr - sect_off;
if (dbg)
printf "[%s] BASE (%s) %016x - %016x = %016x\n", sect_name, sect_symb, addr, sect_off, sect_base >"/dev/stderr";
sect_symb = 0;
}
if (++ridx > rcnt)
break;
$0 = ranges[ridx];
sub(/-/, " ");
if ($4 != "=") {
sub(/-/, " ");
mod_saddr = strtonum("0x" $2) + sect_base;
mod_eaddr = strtonum("0x" $3) + sect_base;
$1 = $2 = $3 = "";
sub(/^ +/, "");
mod_name = $0;
if (dbg)
printf "[%s] %s from %016x to %016x\n", sect_name, mod_name, mod_saddr, mod_eaddr >"/dev/stderr";
} else {
sect_name = $1;
sect_off = strtonum("0x" $2);
sect_symb = $5;
}
}
idx = addr"-"name;
if (addr >= mod_saddr && addr < mod_eaddr)
sym2mod[idx] = mod_name;
next;
}
# Once we are done annotating the System.map, we no longer need the ranges data.
#
FNR == 1 && ARGIND == 3 {
delete ranges;
}
# (3) Build a lookup map of built-in module names.
#
# Lines from modules.builtin will be like:
# kernel/crypto/lzo-rle.ko
# and we record the object name "crypto/lzo-rle".
#
ARGIND == 3 {
sub(/kernel\//, ""); # strip off "kernel/" prefix
sub(/\.ko$/, ""); # strip off .ko suffix
mods[$1] = 1;
next;
}
# (4) Get a list of symbols (per object).
#
# Symbols by object are read from vmlinux.map, with fallback to vmlinux.o.map
# if vmlinux is found to have inked in vmlinux.o.
#
# If we were able to get the data we need from vmlinux.map, there is no need to
# process vmlinux.o.map.
#
FNR == 1 && ARGIND == 5 && total > 0 {
if (dbg)
printf "Note: %s is not needed.\n", FILENAME >"/dev/stderr";
exit;
}
# First determine whether we are dealing with a GNU ld or LLVM lld linker map.
#
ARGIND >= 4 && FNR == 1 && NF == 7 && $1 == "VMA" && $7 == "Symbol" {
map_is_lld = 1;
next;
}
# (LLD) Convert a section record fronm lld format to ld format.
#
ARGIND >= 4 && map_is_lld && NF == 5 && /[0-9] [^ ]+$/ {
$0 = $5 " 0x"$1 " 0x"$3 " load address 0x"$2;
}
# (LLD) Convert an object record from lld format to ld format.
#
ARGIND >= 4 && map_is_lld && NF == 5 && $5 ~ /:\(/ {
if (/\.a\(/ && !/ vmlinux\.a\(/)
next;
gsub(/\)/, "");
sub(/:\(/, " ");
sub(/ vmlinux\.a\(/, " ");
$0 = " "$6 " 0x"$1 " 0x"$3 " " $5;
}
# (LLD) Convert a symbol record from lld format to ld format.
#
ARGIND >= 4 && map_is_lld && NF == 5 && $5 ~ /^[A-Za-z_][A-Za-z0-9_]*$/ {
$0 = " 0x" $1 " " $5;
}
# (LLD) We do not need any other ldd linker map records.
#
ARGIND >= 4 && map_is_lld && /^[0-9a-f]{16} / {
next;
}
# Handle section records with long section names (spilling onto a 2nd line).
#
ARGIND >= 4 && !map_is_lld && NF == 1 && /^[^ ]/ {
s = $0;
getline;
$0 = s " " $0;
}
# Next section - previous one is done.
#
ARGIND >= 4 && /^[^ ]/ {
sect = 0;
}
# Get the (top level) section name.
#
ARGIND >= 4 && /^\./ {
# Explicitly ignore a few sections that are not relevant here.
if ($1 ~ /^\.orc_/ || $1 ~ /_sites$/ || $1 ~ /\.percpu/)
next;
# Sections with a 0-address can be ignored as well (in vmlinux.map).
if (ARGIND == 4 && $2 ~ /^0x0+$/)
next;
sect = $1;
next;
}
# If we are not currently in a section we care about, ignore records.
#
!sect {
next;
}
# Handle object records with long section names (spilling onto a 2nd line).
#
ARGIND >= 4 && /^ [^ \*]/ && NF == 1 {
# If the section name is long, the remainder of the entry is found on
# the next line.
s = $0;
getline;
$0 = s " " $0;
}
# Objects linked in from static libraries are ignored.
# If the object is vmlinux.o, we need to consult vmlinux.o.map for per-object
# symbol information
#
ARGIND == 4 && /^ [^ ]/ && NF == 4 {
if ($4 ~ /\.a\(/)
next;
idx = sect":"$1;
if (!(idx in sect_addend)) {
sect_addend[idx] = addr2val($2);
if (dbg)
printf "ADDEND %s = %016x\n", idx, sect_addend[idx] >"/dev/stderr";
}
if ($4 == "vmlinux.o") {
need_o_map = 1;
next;
}
}
# If data from vmlinux.o.map is needed, we only process section and object
# records from vmlinux.map to determine which section we need to pay attention
# to in vmlinux.o.map. So skip everything else from vmlinux.map.
#
ARGIND == 4 && need_o_map {
next;
}
# Get module information for the current object.
#
ARGIND >= 4 && /^ [^ ]/ && NF == 4 {
msect = $1;
mod_name = get_module_info($4);
mod_eaddr = addr2val($2) + addr2val($3);
next;
}
# Process a symbol record.
#
# Evaluate the module information obtained from vmlinux.map (or vmlinux.o.map)
# as follows:
# - For all symbols in a given object:
# - If the symbol is annotated with the same module name(s) that the object
# belongs to, count it as a match.
# - Otherwise:
# - If the symbol is known to have duplicates of which at least one is
# in a built-in module, disregard it.
# - If the symbol us not annotated with any module name(s) AND the
# object belongs to built-in modules, count it as missing.
# - Otherwise, count it as a mismatch.
#
ARGIND >= 4 && /^ / && NF == 2 && $1 ~ /^0x/ {
idx = sect":"msect;
if (!(idx in sect_addend))
next;
addr = addr2val($1);
# Handle the rare but annoying case where a 0-size symbol is placed at
# the byte *after* the module range. Based on vmlinux.map it will be
# considered part of the current object, but it falls just beyond the
# module address range. Unfortunately, its address could be at the
# start of another built-in module, so the only safe thing to do is to
# ignore it.
if (mod_name && addr == mod_eaddr)
next;
# If we are processing vmlinux.o.map, we need to apply the base address
# of the section to the relative address on the record.
#
if (ARGIND == 5)
addr += sect_addend[idx];
idx = addr"-"$2;
mod = "";
if (idx in sym2mod) {
mod = sym2mod[idx];
if (sym2mod[idx] == mod_name) {
mod_matches++;
matches++;
} else if (mod_name == "") {
print $2 " in " mod " (should NOT be)";
mismatches++;
} else {
print $2 " in " mod " (should be " mod_name ")";
mismatches++;
}
} else if (mod_name != "") {
print $2 " should be in " mod_name;
missing++;
} else
matches++;
total++;
next;
}
# Issue the comparison report.
#
END {
if (total) {
printf "Verification of %s:\n", ARGV[1];
printf " Correct matches: %6d (%d%% of total)\n", matches, 100 * matches / total;
printf " Module matches: %6d (%d%% of matches)\n", mod_matches, 100 * mod_matches / matches;
printf " Mismatches: %6d (%d%% of total)\n", mismatches, 100 * mismatches / total;
printf " Missing: %6d (%d%% of total)\n", missing, 100 * missing / total;
if (mismatches || missing)
exit(1);
}
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment