d834db9f2c
Config MODULE_SCMVERSION introduces a new module attribute -- `scmversion` -- which can be used to identify a given module's SCM version. This is very useful for developers that update their kernel independently from their kernel modules or vice-versa since the SCM version provided by UTS_RELEASE (`uname -r`) will now differ from the module's vermagic attribute. For example, we have a CI setup that tests new kernel changes on the hikey960 and db845c devices without updating their kernel modules. When these tests fail, we need to be able to identify the exact device configuration the test was using. By including MODULE_SCMVERSION, we can identify the exact kernel and modules' SCM versions for debugging the failures. Additionally, by exposing the SCM version via the sysfs node /sys/module/MODULENAME/scmversion, one can also verify the SCM versions of the modules loaded from the initramfs. Currently, modinfo can only retrieve module attributes from the module's ko on disk and not from the actual module that is loaded in RAM. You can retrieve the SCM version in two ways, 1) By using modinfo: > modinfo -F scmversion MODULENAME 2) By module sysfs node: > cat /sys/module/MODULENAME/scmversion Bug: 180027765 Link: https://lore.kernel.org/all/20210121213641.3477522-1-willmcvicker@google.com/ Signed-off-by: Will McVicker <willmcvicker@google.com> Change-Id: Ib7c72c72f95c4545adb7cd4e842729557039ce3a
197 lines
6.6 KiB
Makefile
197 lines
6.6 KiB
Makefile
# SPDX-License-Identifier: GPL-2.0
|
|
# ===========================================================================
|
|
# Module versions
|
|
# ===========================================================================
|
|
#
|
|
# Stage one of module building created the following:
|
|
# a) The individual .o files used for the module
|
|
# b) A <module>.o file which is the .o files above linked together
|
|
# c) A <module>.mod file, listing the name of the preliminary <module>.o file,
|
|
# plus all .o files
|
|
# d) modules.order, which lists all the modules
|
|
|
|
# Stage 2 is handled by this file and does the following
|
|
# 1) Find all modules listed in modules.order
|
|
# 2) modpost is then used to
|
|
# 3) create one <module>.mod.c file per module
|
|
# 4) create one Module.symvers file with CRC for all exported symbols
|
|
|
|
# Step 3 is used to place certain information in the module's ELF
|
|
# section, including information such as:
|
|
# Version magic (see include/linux/vermagic.h for full details)
|
|
# - Kernel release
|
|
# - SMP is CONFIG_SMP
|
|
# - PREEMPT is CONFIG_PREEMPT[_RT]
|
|
# - GCC Version
|
|
# Module info
|
|
# - Module version (MODULE_VERSION)
|
|
# - Module alias'es (MODULE_ALIAS)
|
|
# - Module license (MODULE_LICENSE)
|
|
# - See include/linux/module.h for more details
|
|
|
|
# Step 4 is solely used to allow module versioning in external modules,
|
|
# where the CRC of each module is retrieved from the Module.symvers file.
|
|
|
|
PHONY := __modpost
|
|
__modpost:
|
|
|
|
include include/config/auto.conf
|
|
include $(srctree)/scripts/Kbuild.include
|
|
|
|
mixed-build-prefix = $(if $(KBUILD_MIXED_TREE),$(KBUILD_MIXED_TREE)/)
|
|
|
|
modpost-args = \
|
|
$(if $(CONFIG_MODVERSIONS),-m) \
|
|
$(if $(CONFIG_MODULE_SRCVERSION_ALL),-a) \
|
|
$(if $(CONFIG_SECTION_MISMATCH_WARN_ONLY),,-E) \
|
|
$(if $(KBUILD_NSDEPS),-d $(MODULES_NSDEPS)) \
|
|
$(if $(CONFIG_MODULE_ALLOW_MISSING_NAMESPACE_IMPORTS)$(KBUILD_NSDEPS),-N) \
|
|
-o $@
|
|
|
|
# 'make -i -k' ignores compile errors, and builds as many modules as possible.
|
|
ifneq ($(findstring i,$(filter-out --%,$(MAKEFLAGS))),)
|
|
modpost-args += -n
|
|
endif
|
|
|
|
ifeq ($(CONFIG_MODULE_SCMVERSION),y)
|
|
ifeq ($(KBUILD_EXTMOD),)
|
|
module_srcpath := $(srctree)
|
|
else
|
|
# Get the external module's source path. KBUILD_EXTMOD could either be an
|
|
# absolute path or relative path from $(srctree). This makes sure that we
|
|
# aren't using a relative path from a separate working directory (O= or
|
|
# KBUILD_OUTPUT) since that may not be the actual module's SCM project path. So
|
|
# check the path relative to $(srctree) first.
|
|
ifneq ($(realpath $(srctree)/$(KBUILD_EXTMOD) 2>/dev/null),)
|
|
module_srcpath := $(srctree)/$(KBUILD_EXTMOD)
|
|
else
|
|
module_srcpath := $(KBUILD_EXTMOD)
|
|
endif
|
|
endif
|
|
|
|
# Get the SCM version of the module. Sed verifies setlocalversion returns
|
|
# a proper revision based on the SCM type, e.g. git, mercurial, or svn.
|
|
# Note: relative M= paths are not supported when building the kernel out of the
|
|
# srctree since setlocalversion won't be able to find the module srctree.
|
|
module_scmversion := $(shell $(srctree)/scripts/setlocalversion $(module_srcpath) | \
|
|
sed -n 's/.*-\(\(g\|hg\)[a-fA-F0-9]\+\(-dirty\)\?\|svn[0-9]\+\).*/\1/p')
|
|
ifneq ($(module_scmversion),)
|
|
modpost-args += -v $(module_scmversion)
|
|
endif
|
|
endif
|
|
|
|
ifeq ($(KBUILD_EXTMOD),)
|
|
|
|
# Generate the list of in-tree objects in vmlinux
|
|
# ---------------------------------------------------------------------------
|
|
|
|
# This is used to retrieve symbol versions generated by genksyms.
|
|
ifdef CONFIG_MODVERSIONS
|
|
ifndef KBUILD_MIXED_TREE
|
|
vmlinux.symvers Module.symvers: .vmlinux.objs
|
|
endif
|
|
endif
|
|
|
|
# Ignore libgcc.a
|
|
# Some architectures do '$(CC) --print-libgcc-file-name' to borrow libgcc.a
|
|
# from the toolchain, but there is no EXPORT_SYMBOL in it.
|
|
|
|
quiet_cmd_vmlinux_objs = GEN $@
|
|
cmd_vmlinux_objs = \
|
|
for f in $(real-prereqs); do \
|
|
case $${f} in \
|
|
*libgcc.a) ;; \
|
|
*) $(AR) t $${f} ;; \
|
|
esac \
|
|
done > $@
|
|
|
|
quiet_cmd_vmlinux_symvers = GEN $@
|
|
cmd_vmlinux_symvers = grep "\<vmlinux\s\+EXPORT" $< > $@
|
|
|
|
quiet_cmd_cat_symvers = GEN $@
|
|
cmd_cat_symvers = cat $(real-prereqs) > $@
|
|
|
|
ifndef KBUILD_MIXED_TREE
|
|
targets += .vmlinux.objs
|
|
.vmlinux.objs: vmlinux.a $(KBUILD_VMLINUX_LIBS) FORCE
|
|
$(call if_changed,vmlinux_objs)
|
|
endif
|
|
|
|
vmlinux.o-if-present := $(wildcard vmlinux.o)
|
|
output-symdump := vmlinux.symvers
|
|
|
|
ifdef KBUILD_MODULES
|
|
output-symdump := $(if $(vmlinux.o-if-present), Module.symvers, modules-only.symvers)
|
|
missing-input := $(filter-out $(vmlinux.o-if-present),vmlinux.o)
|
|
|
|
targets += vmlinux.symvers
|
|
vmlinux.symvers: Module.symvers FORCE
|
|
$(call if_changed,vmlinux_symvers)
|
|
|
|
__modpost: $(if $(vmlinux.o-if-present),vmlinux.symvers,)
|
|
endif
|
|
|
|
# Overwrite values for mixed building (overwritting makes merges easier)
|
|
ifdef KBUILD_MIXED_TREE
|
|
targets += Module.symvers
|
|
Module.symvers: $(mixed-build-prefix)vmlinux.symvers modules-only.symvers FORCE
|
|
$(call if_changed,cat_symvers)
|
|
|
|
__modpost: Module.symvers
|
|
|
|
vmlinux.o-if-present :=
|
|
vmlinux.symvers-if-present := $(wildcard $(mixed-build-prefix)vmlinux.symvers)
|
|
modpost-args += $(addprefix -i ,$(vmlinux.symvers-if-present))
|
|
output-symdump := modules-only.symvers
|
|
missing-input := $(filter-out $(vmlinux.symvers-if-present),$(mixed-build-prefix)vmlinux.symvers)
|
|
endif
|
|
|
|
else
|
|
|
|
# set src + obj - they may be used in the modules's Makefile
|
|
obj := $(KBUILD_EXTMOD)
|
|
src := $(obj)
|
|
|
|
# Include the module's Makefile to find KBUILD_EXTRA_SYMBOLS
|
|
include $(or $(wildcard $(src)/Kbuild), $(src)/Makefile)
|
|
|
|
module.symvers-if-present := $(wildcard Module.symvers)
|
|
output-symdump := $(KBUILD_EXTMOD)/Module.symvers
|
|
missing-input := $(filter-out $(module.symvers-if-present), Module.symvers)
|
|
|
|
modpost-args += -e $(addprefix -i ,$(module.symvers-if-present) $(KBUILD_EXTRA_SYMBOLS))
|
|
|
|
endif # ($(KBUILD_EXTMOD),)
|
|
|
|
ifneq ($(KBUILD_MODPOST_WARN)$(missing-input),)
|
|
modpost-args += -w
|
|
endif
|
|
|
|
modorder-if-needed := $(if $(KBUILD_MODULES), $(MODORDER))
|
|
|
|
MODPOST = scripts/mod/modpost
|
|
|
|
# Read out modules.order to pass in modpost.
|
|
# Otherwise, allmodconfig would fail with "Argument list too long".
|
|
quiet_cmd_modpost = MODPOST $@
|
|
cmd_modpost = \
|
|
$(if $(missing-input), \
|
|
echo >&2 "WARNING: $(missing-input) is missing."; \
|
|
echo >&2 " Modules may not have dependencies or modversions."; \
|
|
echo >&2 " You may get many unresolved symbol warnings.";) \
|
|
sed 's/ko$$/o/' $(or $(modorder-if-needed), /dev/null) | $(MODPOST) $(modpost-args) -T - $(vmlinux.o-if-present)
|
|
|
|
targets += $(output-symdump)
|
|
$(output-symdump): $(modorder-if-needed) $(vmlinux.o-if-present) $(module.symvers-if-present) $(MODPOST) FORCE
|
|
$(call if_changed,modpost)
|
|
|
|
__modpost: $(output-symdump)
|
|
PHONY += FORCE
|
|
FORCE:
|
|
|
|
existing-targets := $(wildcard $(sort $(targets)))
|
|
|
|
-include $(foreach f,$(existing-targets),$(dir $(f)).$(notdir $(f)).cmd)
|
|
|
|
.PHONY: $(PHONY)
|