Commit ad288597 authored by Linus Torvalds's avatar Linus Torvalds

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

Pull Kbuild updates from Masahiro Yamada:

 - Remove the deprecated rule to build *.dtbo from *.dts

 - Refactor section mismatch detection in modpost

 - Fix bogus ARM section mismatch detections

 - Fix error of 'make gtags' with O= option

 - Add Clang's target triple to KBUILD_CPPFLAGS to fix a build error
   with the latest LLVM version

 - Rebuild the built-in initrd when KBUILD_BUILD_TIMESTAMP is changed

 - Ignore more compiler-generated symbols for kallsyms

 - Fix 'make local*config' to handle the ${CONFIG_FOO} form in Makefiles

 - Enable more kernel-doc warnings with W=2

 - Refactor <linux/export.h> by generating KSYMTAB data by modpost

 - Deprecate <asm/export.h> and <asm-generic/export.h>

 - Remove the EXPORT_DATA_SYMBOL macro

 - Move the check for static EXPORT_SYMBOL back to modpost, which makes
   the build faster

 - Re-implement CONFIG_TRIM_UNUSED_KSYMS with one-pass algorithm

 - Warn missing MODULE_DESCRIPTION when building modules with W=1

 - Make 'make clean' robust against too long argument error

 - Exclude more objects from GCOV to fix CFI failures with GCOV

 - Allow 'make modules_install' to install modules.builtin and
   modules.builtin.modinfo even when CONFIG_MODULES is disabled

 - Include modules.builtin and modules.builtin.modinfo in the
   linux-image Debian package even when CONFIG_MODULES is disabled

 - Revive "Entering directory" logging for the latest Make version

* tag 'kbuild-v6.5' of git://git.kernel.org/pub/scm/linux/kernel/git/masahiroy/linux-kbuild: (72 commits)
  modpost: define more R_ARM_* for old distributions
  kbuild: revive "Entering directory" for Make >= 4.4.1
  kbuild: set correct abs_srctree and abs_objtree for package builds
  scripts/mksysmap: Ignore prefixed KCFI symbols
  kbuild: deb-pkg: remove the CONFIG_MODULES check in buildeb
  kbuild: builddeb: always make modules_install, to install modules.builtin*
  modpost: continue even with unknown relocation type
  modpost: factor out Elf_Sym pointer calculation to section_rel()
  modpost: factor out inst location calculation to section_rel()
  kbuild: Disable GCOV for *.mod.o
  kbuild: Fix CFI failures with GCOV
  kbuild: make clean rule robust against too long argument error
  script: modpost: emit a warning when the description is missing
  kbuild: make modules_install copy modules.builtin(.modinfo)
  linux/export.h: rename 'sec' argument to 'license'
  modpost: show offset from symbol for section mismatch warnings
  modpost: merge two similar section mismatch warnings
  kbuild: implement CONFIG_TRIM_UNUSED_KSYMS without recursion
  modpost: use null string instead of NULL pointer for default namespace
  modpost: squash sym_update_namespace() into sym_add_exported()
  ...
parents e3c2b10d f5983dab
......@@ -51,7 +51,6 @@
*.symversions
*.tab.[ch]
*.tar
*.usyms
*.xz
*.zst
Module.symvers
......@@ -112,7 +111,6 @@ modules.order
#
/include/config/
/include/generated/
/include/ksym/
/arch/*/include/generated/
# stgit generated dirs
......
......@@ -150,6 +150,12 @@ the UTS_MACHINE variable, and on some architectures also the kernel config.
The value of KBUILD_DEBARCH is assumed (not checked) to be a valid Debian
architecture.
KDOCFLAGS
---------
Specify extra (warning/error) flags for kernel-doc checks during the build,
see scripts/kernel-doc for which flags are supported. Note that this doesn't
(currently) apply to documentation builds.
ARCH
----
Set ARCH to the architecture to be built.
......
......@@ -60,6 +60,8 @@ openssl & libcrypto 1.0.0 openssl version
bc 1.06.95 bc --version
Sphinx\ [#f1]_ 1.7 sphinx-build --version
cpio any cpio --version
GNU tar 1.28 tar --version
gtags (optional) 6.6.5 gtags --version
====================== =============== ========================================
.. [#f1] Sphinx is needed only to build the Kernel documentation
......@@ -174,6 +176,18 @@ You will need openssl to build kernels 3.7 and higher if module signing is
enabled. You will also need openssl development packages to build kernels 4.3
and higher.
Tar
---
GNU tar is needed if you want to enable access to the kernel headers via sysfs
(CONFIG_IKHEADERS).
gtags / GNU GLOBAL (optional)
-----------------------------
The kernel build requires GNU GLOBAL version 6.6.5 or later to generate
tag files through ``make gtags``. This is due to its use of the gtags
``-C (--directory)`` flag.
System utilities
****************
......
......@@ -38,6 +38,10 @@ __all:
# descending is started. They are now explicitly listed as the
# prepare rule.
this-makefile := $(lastword $(MAKEFILE_LIST))
export abs_srctree := $(realpath $(dir $(this-makefile)))
export abs_objtree := $(CURDIR)
ifneq ($(sub_make_done),1)
# Do not use make's built-in rules and variables
......@@ -185,20 +189,8 @@ $(if $(abs_objtree),, \
# $(realpath ...) resolves symlinks
abs_objtree := $(realpath $(abs_objtree))
else
abs_objtree := $(CURDIR)
endif # ifneq ($(KBUILD_OUTPUT),)
ifeq ($(abs_objtree),$(CURDIR))
# Suppress "Entering directory ..." unless we are changing the work directory.
MAKEFLAGS += --no-print-directory
else
need-sub-make := 1
endif
this-makefile := $(lastword $(MAKEFILE_LIST))
abs_srctree := $(realpath $(dir $(this-makefile)))
ifneq ($(words $(subst :, ,$(abs_srctree))), 1)
$(error source directory cannot contain spaces or colons)
endif
......@@ -211,9 +203,25 @@ need-sub-make := 1
$(this-makefile): ;
endif
export abs_srctree abs_objtree
export sub_make_done := 1
endif # sub_make_done
ifeq ($(abs_objtree),$(CURDIR))
# Suppress "Entering directory ..." if we are at the final work directory.
no-print-directory := --no-print-directory
else
# Recursion to show "Entering directory ..."
need-sub-make := 1
endif
ifeq ($(filter --no-print-directory, $(MAKEFLAGS)),)
# If --no-print-directory is unset, recurse once again to set it.
# You may end up recursing into __sub-make twice. This is needed due to the
# behavior change in GNU Make 4.4.1.
need-sub-make := 1
endif
ifeq ($(need-sub-make),1)
PHONY += $(MAKECMDGOALS) __sub-make
......@@ -223,18 +231,12 @@ $(filter-out $(this-makefile), $(MAKECMDGOALS)) __all: __sub-make
# Invoke a second make in the output directory, passing relevant variables
__sub-make:
$(Q)$(MAKE) -C $(abs_objtree) -f $(abs_srctree)/Makefile $(MAKECMDGOALS)
$(Q)$(MAKE) $(no-print-directory) -C $(abs_objtree) \
-f $(abs_srctree)/Makefile $(MAKECMDGOALS)
endif # need-sub-make
endif # sub_make_done
else # need-sub-make
# We process the rest of the Makefile if this is the final invocation of make
ifeq ($(need-sub-make),)
# Do not print "Entering directory ...",
# but we want to display it when entering to the output directory
# so that IDEs/editors are able to understand relative filenames.
MAKEFLAGS += --no-print-directory
ifeq ($(abs_srctree),$(abs_objtree))
# building in the source tree
......@@ -1199,28 +1201,12 @@ endif
export KBUILD_VMLINUX_LIBS
export KBUILD_LDS := arch/$(SRCARCH)/kernel/vmlinux.lds
# Recurse until adjust_autoksyms.sh is satisfied
PHONY += autoksyms_recursive
ifdef CONFIG_TRIM_UNUSED_KSYMS
# For the kernel to actually contain only the needed exported symbols,
# we have to build modules as well to determine what those symbols are.
# (this can be evaluated only once include/config/auto.conf has been included)
KBUILD_MODULES := 1
autoksyms_recursive: $(build-dir) modules.order
$(Q)$(CONFIG_SHELL) $(srctree)/scripts/adjust_autoksyms.sh \
"$(MAKE) -f $(srctree)/Makefile autoksyms_recursive"
endif
autoksyms_h := $(if $(CONFIG_TRIM_UNUSED_KSYMS), include/generated/autoksyms.h)
quiet_cmd_autoksyms_h = GEN $@
cmd_autoksyms_h = mkdir -p $(dir $@); \
$(CONFIG_SHELL) $(srctree)/scripts/gen_autoksyms.sh $@
$(autoksyms_h):
$(call cmd,autoksyms_h)
# '$(AR) mPi' needs 'T' to workaround the bug of llvm-ar <= 14
quiet_cmd_ar_vmlinux.a = AR $@
cmd_ar_vmlinux.a = \
......@@ -1229,7 +1215,7 @@ quiet_cmd_ar_vmlinux.a = AR $@
$(AR) mPiT $$($(AR) t $@ | sed -n 1p) $@ $$($(AR) t $@ | grep -F -f $(srctree)/scripts/head-object-list.txt)
targets += vmlinux.a
vmlinux.a: $(KBUILD_VMLINUX_OBJS) scripts/head-object-list.txt autoksyms_recursive FORCE
vmlinux.a: $(KBUILD_VMLINUX_OBJS) scripts/head-object-list.txt FORCE
$(call if_changed,ar_vmlinux.a)
PHONY += vmlinux_o
......@@ -1285,7 +1271,7 @@ scripts: scripts_basic scripts_dtc
PHONY += prepare archprepare
archprepare: outputmakefile archheaders archscripts scripts include/config/kernel.release \
asm-generic $(version_h) $(autoksyms_h) include/generated/utsrelease.h \
asm-generic $(version_h) include/generated/utsrelease.h \
include/generated/compile.h include/generated/autoconf.h remove-stale-files
prepare0: archprepare
......@@ -1567,6 +1553,8 @@ modules_sign_only := y
endif
endif
endif # CONFIG_MODULES
modinst_pre :=
ifneq ($(filter modules_install,$(MAKECMDGOALS)),)
modinst_pre := __modinst_pre
......@@ -1577,18 +1565,18 @@ PHONY += __modinst_pre
__modinst_pre:
@rm -rf $(MODLIB)/kernel
@rm -f $(MODLIB)/source
@mkdir -p $(MODLIB)/kernel
@mkdir -p $(MODLIB)
ifdef CONFIG_MODULES
@ln -s $(abspath $(srctree)) $(MODLIB)/source
@if [ ! $(objtree) -ef $(MODLIB)/build ]; then \
rm -f $(MODLIB)/build ; \
ln -s $(CURDIR) $(MODLIB)/build ; \
fi
@sed 's:^\(.*\)\.o$$:kernel/\1.ko:' modules.order > $(MODLIB)/modules.order
endif
@cp -f modules.builtin $(MODLIB)/
@cp -f $(objtree)/modules.builtin.modinfo $(MODLIB)/
endif # CONFIG_MODULES
###
# Cleaning is done on three levels.
# make clean Delete most generated files
......@@ -1930,6 +1918,13 @@ help:
@echo ' clean - remove generated files in module directory only'
@echo ''
__external_modules_error:
@echo >&2 '***'
@echo >&2 '*** The present kernel disabled CONFIG_MODULES.'
@echo >&2 '*** You cannot build or install external modules.'
@echo >&2 '***'
@false
endif # KBUILD_EXTMOD
# ---------------------------------------------------------------------------
......@@ -1966,13 +1961,10 @@ else # CONFIG_MODULES
# Modules not configured
# ---------------------------------------------------------------------------
modules modules_install:
@echo >&2 '***'
@echo >&2 '*** The present kernel configuration has modules disabled.'
@echo >&2 '*** To use the module feature, please run "make menuconfig" etc.'
@echo >&2 '*** to enable CONFIG_MODULES.'
@echo >&2 '***'
@exit 1
PHONY += __external_modules_error
modules modules_install: __external_modules_error
@:
KBUILD_MODULES :=
......@@ -2045,7 +2037,7 @@ clean: $(clean-dirs)
-o -name '*.dtb.S' -o -name '*.dtbo.S' \
-o -name '*.dt.yaml' \
-o -name '*.dwo' -o -name '*.lst' \
-o -name '*.su' -o -name '*.mod' -o -name '*.usyms' \
-o -name '*.su' -o -name '*.mod' \
-o -name '.*.d' -o -name '.*.tmp' -o -name '*.mod.c' \
-o -name '*.lex.c' -o -name '*.tab.[ch]' \
-o -name '*.asn1.[ch]' \
......
......@@ -8,6 +8,10 @@
#include <asm/dwarf.h>
#define ASM_NL ` /* use '`' to mark new line in macro */
#define __ALIGN .align 4
#define __ALIGN_STR __stringify(__ALIGN)
#ifdef __ASSEMBLY__
.macro ST2 e, o, off
......@@ -28,10 +32,6 @@
#endif
.endm
#define ASM_NL ` /* use '`' to mark new line in macro */
#define __ALIGN .align 4
#define __ALIGN_STR __stringify(__ALIGN)
/* annotation for data we want in DCCM - if enabled in .config */
.macro ARCFP_DATA nm
#ifdef CONFIG_ARC_HAS_DCCM
......
# SPDX-License-Identifier: GPL-2.0
generated-y += syscall_table.h
generic-y += agp.h
generic-y += export.h
generic-y += kvm_para.h
generic-y += mcs_spinlock.h
generic-y += vtime.h
/* EXPORT_DATA_SYMBOL != EXPORT_SYMBOL here */
#define KSYM_FUNC(name) @fptr(name)
#include <asm-generic/export.h>
......@@ -170,7 +170,7 @@ RestRR: \
__PAGE_ALIGNED_DATA
.global empty_zero_page
EXPORT_DATA_SYMBOL_GPL(empty_zero_page)
EXPORT_SYMBOL_GPL(empty_zero_page)
empty_zero_page:
.skip PAGE_SIZE
......
......@@ -87,7 +87,7 @@
.align 32768 // align on 32KB boundary
.global ia64_ivt
EXPORT_DATA_SYMBOL(ia64_ivt)
EXPORT_SYMBOL(ia64_ivt)
ia64_ivt:
/////////////////////////////////////////////////////////////////////////////////////////
// 0x0000 Entry 0 (size 64 bundles) VHPT Translation (8,20,47)
......
......@@ -346,7 +346,7 @@ KBUILD_CFLAGS += -fno-asynchronous-unwind-tables
KBUILD_LDFLAGS += -m $(ld-emul)
ifdef CONFIG_MIPS
CHECKFLAGS += $(shell $(CC) $(KBUILD_CFLAGS) -dM -E -x c /dev/null | \
CHECKFLAGS += $(shell $(CC) $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS) -dM -E -x c /dev/null | \
grep -E -vw '__GNUC_(MINOR_|PATCHLEVEL_)?_' | \
sed -e "s/^\#define /-D'/" -e "s/ /'='/" -e "s/$$/'/" -e 's/\$$/&&/g')
endif
......
......@@ -54,7 +54,7 @@ KASAN_SANITIZE := n
KCSAN_SANITIZE := n
ccflags-y := -fno-common -fno-builtin
ldflags-y := -Wl,--hash-style=both -nostdlib -shared -z noexecstack
ldflags-y := -Wl,--hash-style=both -nostdlib -shared -z noexecstack $(CLANG_FLAGS)
ldflags-$(CONFIG_LD_IS_LLD) += $(call cc-option,--ld-path=$(LD),-fuse-ld=lld)
ldflags-$(CONFIG_LD_ORPHAN_WARN) += -Wl,--orphan-handling=$(CONFIG_LD_ORPHAN_WARN_LEVEL)
......
......@@ -37,13 +37,6 @@ EXPORT_SYMBOL(vsyscall_ehdr);
EXPORT_SYMBOL(vsyscall_end);
#endif
/* Export symbols used by GCC for the stack protector. */
extern void __stack_smash_handler(void *) __attribute__((weak));
EXPORT_SYMBOL(__stack_smash_handler);
extern long __guard __attribute__((weak));
EXPORT_SYMBOL(__guard);
#ifdef _FORTIFY_SOURCE
extern int __sprintf_chk(char *str, int flag, size_t len, const char *format);
EXPORT_SYMBOL(__sprintf_chk);
......
......@@ -3,86 +3,9 @@
#define __ASM_GENERIC_EXPORT_H
/*
* This comment block is used by fixdep. Please do not remove.
*
* When CONFIG_MODVERSIONS is changed from n to y, all source files having
* EXPORT_SYMBOL variants must be re-compiled because genksyms is run as a
* side effect of the *.o build rule.
* <asm/export.h> and <asm-generic/export.h> are deprecated.
* Please include <linux/export.h> directly.
*/
#ifndef KSYM_FUNC
#define KSYM_FUNC(x) x
#endif
#ifdef CONFIG_HAVE_ARCH_PREL32_RELOCATIONS
#define KSYM_ALIGN 4
#elif defined(CONFIG_64BIT)
#define KSYM_ALIGN 8
#else
#define KSYM_ALIGN 4
#endif
.macro __put, val, name
#ifdef CONFIG_HAVE_ARCH_PREL32_RELOCATIONS
.long \val - ., \name - ., 0
#elif defined(CONFIG_64BIT)
.quad \val, \name, 0
#else
.long \val, \name, 0
#endif
.endm
/*
* note on .section use: we specify progbits since usage of the "M" (SHF_MERGE)
* section flag requires it. Use '%progbits' instead of '@progbits' since the
* former apparently works on all arches according to the binutils source.
*/
.macro ___EXPORT_SYMBOL name,val,sec
#if defined(CONFIG_MODULES) && !defined(__DISABLE_EXPORTS)
.section ___ksymtab\sec+\name,"a"
.balign KSYM_ALIGN
__ksymtab_\name:
__put \val, __kstrtab_\name
.previous
.section __ksymtab_strings,"aMS",%progbits,1
__kstrtab_\name:
.asciz "\name"
.previous
#endif
.endm
#if defined(CONFIG_TRIM_UNUSED_KSYMS)
#include <linux/kconfig.h>
#include <generated/autoksyms.h>
.macro __ksym_marker sym
.section ".discard.ksym","a"
__ksym_marker_\sym:
.previous
.endm
#define __EXPORT_SYMBOL(sym, val, sec) \
__ksym_marker sym; \
__cond_export_sym(sym, val, sec, __is_defined(__KSYM_##sym))
#define __cond_export_sym(sym, val, sec, conf) \
___cond_export_sym(sym, val, sec, conf)
#define ___cond_export_sym(sym, val, sec, enabled) \
__cond_export_sym_##enabled(sym, val, sec)
#define __cond_export_sym_1(sym, val, sec) ___EXPORT_SYMBOL sym, val, sec
#define __cond_export_sym_0(sym, val, sec) /* nothing */
#else
#define __EXPORT_SYMBOL(sym, val, sec) ___EXPORT_SYMBOL sym, val, sec
#endif
#define EXPORT_SYMBOL(name) \
__EXPORT_SYMBOL(name, KSYM_FUNC(name),)
#define EXPORT_SYMBOL_GPL(name) \
__EXPORT_SYMBOL(name, KSYM_FUNC(name), _gpl)
#define EXPORT_DATA_SYMBOL(name) \
__EXPORT_SYMBOL(name, name,)
#define EXPORT_DATA_SYMBOL_GPL(name) \
__EXPORT_SYMBOL(name, name,_gpl)
#include <linux/export.h>
#endif
......@@ -1016,6 +1016,7 @@
PATCHABLE_DISCARDS \
*(.discard) \
*(.discard.*) \
*(.export_symbol) \
*(.modinfo) \
/* ld.bfd warns about .gnu.version* even when not emitted */ \
*(.gnu.version*) \
......
......@@ -10,6 +10,55 @@
#include <linux/compiler.h>
#include <linux/types.h>
#if defined(CONFIG_HAVE_ARCH_PREL32_RELOCATIONS)
/*
* relative reference: this reduces the size by half on 64-bit architectures,
* and eliminates the need for absolute relocations that require runtime
* processing on relocatable kernels.
*/
#define __KSYM_REF(sym) ".long " #sym "- ."
#elif defined(CONFIG_64BIT)
#define __KSYM_REF(sym) ".quad " #sym
#else
#define __KSYM_REF(sym) ".long " #sym
#endif
/*
* For every exported symbol, do the following:
*
* - Put the name of the symbol and namespace (empty string "" for none) in
* __ksymtab_strings.
* - Place a struct kernel_symbol entry in the __ksymtab section.
*
* Note on .section use: we specify progbits since usage of the "M" (SHF_MERGE)
* section flag requires it. Use '%progbits' instead of '@progbits' since the
* former apparently works on all arches according to the binutils source.
*/
#define __KSYMTAB(name, sym, sec, ns) \
asm(" .section \"__ksymtab_strings\",\"aMS\",%progbits,1" "\n" \
"__kstrtab_" #name ":" "\n" \
" .asciz \"" #name "\"" "\n" \
"__kstrtabns_" #name ":" "\n" \
" .asciz \"" ns "\"" "\n" \
" .previous" "\n" \
" .section \"___ksymtab" sec "+" #name "\", \"a\"" "\n" \
" .balign 4" "\n" \
"__ksymtab_" #name ":" "\n" \
__KSYM_REF(sym) "\n" \
__KSYM_REF(__kstrtab_ ##name) "\n" \
__KSYM_REF(__kstrtabns_ ##name) "\n" \
" .previous" "\n" \
)
#ifdef CONFIG_IA64
#define KSYM_FUNC(name) @fptr(name)
#else
#define KSYM_FUNC(name) name
#endif
#define KSYMTAB_FUNC(name, sec, ns) __KSYMTAB(name, KSYM_FUNC(name), sec, ns)
#define KSYMTAB_DATA(name, sec, ns) __KSYMTAB(name, name, sec, ns)
#define SYMBOL_CRC(sym, crc, sec) \
asm(".section \"___kcrctab" sec "+" #sym "\",\"a\"" "\n" \
"__crc_" #sym ":" "\n" \
......
......@@ -2,6 +2,8 @@
#ifndef _LINUX_EXPORT_H
#define _LINUX_EXPORT_H
#include <linux/compiler.h>
#include <linux/linkage.h>
#include <linux/stringify.h>
/*
......@@ -28,74 +30,25 @@ extern struct module __this_module;
#else
#define THIS_MODULE ((struct module *)0)
#endif
#endif /* __ASSEMBLY__ */
#ifdef CONFIG_HAVE_ARCH_PREL32_RELOCATIONS
#include <linux/compiler.h>
/*
* Emit the ksymtab entry as a pair of relative references: this reduces
* the size by half on 64-bit architectures, and eliminates the need for
* absolute relocations that require runtime processing on relocatable
* kernels.
*/
#define __KSYMTAB_ENTRY(sym, sec) \
__ADDRESSABLE(sym) \
asm(" .section \"___ksymtab" sec "+" #sym "\", \"a\" \n" \
" .balign 4 \n" \
"__ksymtab_" #sym ": \n" \
" .long " #sym "- . \n" \
" .long __kstrtab_" #sym "- . \n" \
" .long __kstrtabns_" #sym "- . \n" \
" .previous \n")
struct kernel_symbol {
int value_offset;
int name_offset;
int namespace_offset;
};
#ifdef CONFIG_64BIT
#define __EXPORT_SYMBOL_REF(sym) \
.balign 8 ASM_NL \
.quad sym
#else
#define __KSYMTAB_ENTRY(sym, sec) \
static const struct kernel_symbol __ksymtab_##sym \
__attribute__((section("___ksymtab" sec "+" #sym), used)) \
__aligned(sizeof(void *)) \
= { (unsigned long)&sym, __kstrtab_##sym, __kstrtabns_##sym }
struct kernel_symbol {
unsigned long value;
const char *name;
const char *namespace;
};
#define __EXPORT_SYMBOL_REF(sym) \
.balign 4 ASM_NL \
.long sym
#endif
#ifdef __GENKSYMS__
#define ___EXPORT_SYMBOL(sym, sec, ns) __GENKSYMS_EXPORT_SYMBOL(sym)
#else
/*
* For every exported symbol, do the following:
*
* - Put the name of the symbol and namespace (empty string "" for none) in
* __ksymtab_strings.
* - Place a struct kernel_symbol entry in the __ksymtab section.
*
* note on .section use: we specify progbits since usage of the "M" (SHF_MERGE)
* section flag requires it. Use '%progbits' instead of '@progbits' since the
* former apparently works on all arches according to the binutils source.
*/
#define ___EXPORT_SYMBOL(sym, sec, ns) \
extern typeof(sym) sym; \
extern const char __kstrtab_##sym[]; \
extern const char __kstrtabns_##sym[]; \
asm(" .section \"__ksymtab_strings\",\"aMS\",%progbits,1 \n" \
"__kstrtab_" #sym ": \n" \
" .asciz \"" #sym "\" \n" \
"__kstrtabns_" #sym ": \n" \
" .asciz \"" ns "\" \n" \
" .previous \n"); \
__KSYMTAB_ENTRY(sym, sec)
#endif
#define ___EXPORT_SYMBOL(sym, license, ns) \
.section ".export_symbol","a" ASM_NL \
__export_symbol_##sym: ASM_NL \
.asciz license ASM_NL \
.asciz ns ASM_NL \
__EXPORT_SYMBOL_REF(sym) ASM_NL \
.previous
#if !defined(CONFIG_MODULES) || defined(__DISABLE_EXPORTS)
......@@ -104,54 +57,35 @@ struct kernel_symbol {
* be reused in other execution contexts such as the UEFI stub or the
* decompressor.
*/
#define __EXPORT_SYMBOL(sym, sec, ns)
#define __EXPORT_SYMBOL(sym, license, ns)
#elif defined(CONFIG_TRIM_UNUSED_KSYMS)
#elif defined(__GENKSYMS__)
#include <generated/autoksyms.h>
#define __EXPORT_SYMBOL(sym, license, ns) __GENKSYMS_EXPORT_SYMBOL(sym)
/*
* For fine grained build dependencies, we want to tell the build system
* about each possible exported symbol even if they're not actually exported.
* We use a symbol pattern __ksym_marker_<symbol> that the build system filters
* from the $(NM) output (see scripts/gen_ksymdeps.sh). These symbols are
* discarded in the final link stage.
*/
#define __ksym_marker(sym) \
static int __ksym_marker_##sym[0] __section(".discard.ksym") __used
#define __EXPORT_SYMBOL(sym, sec, ns) \
__ksym_marker(sym); \
__cond_export_sym(sym, sec, ns, __is_defined(__KSYM_##sym))
#define __cond_export_sym(sym, sec, ns, conf) \
___cond_export_sym(sym, sec, ns, conf)
#define ___cond_export_sym(sym, sec, ns, enabled) \
__cond_export_sym_##enabled(sym, sec, ns)
#define __cond_export_sym_1(sym, sec, ns) ___EXPORT_SYMBOL(sym, sec, ns)
#ifdef __GENKSYMS__
#define __cond_export_sym_0(sym, sec, ns) __GENKSYMS_EXPORT_SYMBOL(sym)
#else
#define __cond_export_sym_0(sym, sec, ns) /* nothing */
#endif
#elif defined(__ASSEMBLY__)
#define __EXPORT_SYMBOL(sym, license, ns) \
___EXPORT_SYMBOL(sym, license, ns)
#else
#define __EXPORT_SYMBOL(sym, sec, ns) ___EXPORT_SYMBOL(sym, sec, ns)
#define __EXPORT_SYMBOL(sym, license, ns) \
extern typeof(sym) sym; \
__ADDRESSABLE(sym) \
asm(__stringify(___EXPORT_SYMBOL(sym, license, ns)))
#endif /* CONFIG_MODULES */
#ifdef DEFAULT_SYMBOL_NAMESPACE
#define _EXPORT_SYMBOL(sym, sec) __EXPORT_SYMBOL(sym, sec, __stringify(DEFAULT_SYMBOL_NAMESPACE))
#define _EXPORT_SYMBOL(sym, license) __EXPORT_SYMBOL(sym, license, __stringify(DEFAULT_SYMBOL_NAMESPACE))
#else
#define _EXPORT_SYMBOL(sym, sec) __EXPORT_SYMBOL(sym, sec, "")
#define _EXPORT_SYMBOL(sym, license) __EXPORT_SYMBOL(sym, license, "")
#endif
#define EXPORT_SYMBOL(sym) _EXPORT_SYMBOL(sym, "")
#define EXPORT_SYMBOL_GPL(sym) _EXPORT_SYMBOL(sym, "_gpl")
#define EXPORT_SYMBOL_GPL(sym) _EXPORT_SYMBOL(sym, "GPL")
#define EXPORT_SYMBOL_NS(sym, ns) __EXPORT_SYMBOL(sym, "", __stringify(ns))
#define EXPORT_SYMBOL_NS_GPL(sym, ns) __EXPORT_SYMBOL(sym, "_gpl", __stringify(ns))
#endif /* !__ASSEMBLY__ */
#define EXPORT_SYMBOL_NS_GPL(sym, ns) __EXPORT_SYMBOL(sym, "GPL", __stringify(ns))
#endif /* _LINUX_EXPORT_H */
......@@ -375,23 +375,23 @@ const struct dev_pm_ops name = { \
}
#ifdef CONFIG_PM
#define _EXPORT_DEV_PM_OPS(name, sec, ns) \
#define _EXPORT_DEV_PM_OPS(name, license, ns) \
const struct dev_pm_ops name; \
__EXPORT_SYMBOL(name, sec, ns); \
__EXPORT_SYMBOL(name, license, ns); \
const struct dev_pm_ops name
#define EXPORT_PM_FN_GPL(name) EXPORT_SYMBOL_GPL(name)
#define EXPORT_PM_FN_NS_GPL(name, ns) EXPORT_SYMBOL_NS_GPL(name, ns)
#else
#define _EXPORT_DEV_PM_OPS(name, sec, ns) \
#define _EXPORT_DEV_PM_OPS(name, license, ns) \
static __maybe_unused const struct dev_pm_ops __static_##name
#define EXPORT_PM_FN_GPL(name)
#define EXPORT_PM_FN_NS_GPL(name, ns)
#endif
#define EXPORT_DEV_PM_OPS(name) _EXPORT_DEV_PM_OPS(name, "", "")
#define EXPORT_GPL_DEV_PM_OPS(name) _EXPORT_DEV_PM_OPS(name, "_gpl", "")
#define EXPORT_GPL_DEV_PM_OPS(name) _EXPORT_DEV_PM_OPS(name, "GPL", "")
#define EXPORT_NS_DEV_PM_OPS(name, ns) _EXPORT_DEV_PM_OPS(name, "", #ns)
#define EXPORT_NS_GPL_DEV_PM_OPS(name, ns) _EXPORT_DEV_PM_OPS(name, "_gpl", #ns)
#define EXPORT_NS_GPL_DEV_PM_OPS(name, ns) _EXPORT_DEV_PM_OPS(name, "GPL", #ns)
/*
* Use this if you want to use the same suspend and resume callbacks for suspend
......
......@@ -60,3 +60,4 @@ include/generated/utsversion.h: FORCE
$(obj)/version-timestamp.o: include/generated/utsversion.h
CFLAGS_version-timestamp.o := -include include/generated/utsversion.h
KASAN_SANITIZE_version-timestamp.o := n
GCOV_PROFILE_version-timestamp.o := n
......@@ -83,12 +83,9 @@ find $cpio_dir -type f -print0 |
xargs -0 -P8 -n1 perl -pi -e 'BEGIN {undef $/;}; s/\/\*((?!SPDX).)*?\*\///smg;'
# Create archive and try to normalize metadata for reproducibility.
# For compatibility with older versions of tar, files are fed to tar
# pre-sorted, as --sort=name might not be available.
find $cpio_dir -printf "./%P\n" | LC_ALL=C sort | \
tar "${KBUILD_BUILD_TIMESTAMP:+--mtime=$KBUILD_BUILD_TIMESTAMP}" \
--owner=0 --group=0 --numeric-owner --no-recursion \
-I $XZ -cf $tarfile -C $cpio_dir/ -T - > /dev/null
tar "${KBUILD_BUILD_TIMESTAMP:+--mtime=$KBUILD_BUILD_TIMESTAMP}" \
--owner=0 --group=0 --sort=name --numeric-owner \
-I $XZ -cf $tarfile -C $cpio_dir/ . > /dev/null
echo $headers_md5 > kernel/kheaders.md5
echo "$this_file_md5" >> kernel/kheaders.md5
......
......@@ -32,6 +32,18 @@
/* Maximum number of characters written by module_flags() */
#define MODULE_FLAGS_BUF_SIZE (TAINT_FLAGS_COUNT + 4)
struct kernel_symbol {
#ifdef CONFIG_HAVE_ARCH_PREL32_RELOCATIONS
int value_offset;
int name_offset;
int namespace_offset;
#else
unsigned long value;
const char *name;
const char *namespace;
#endif
};
extern struct mutex module_mutex;
extern struct list_head modules;
......
......@@ -82,7 +82,7 @@ ifdef need-builtin
targets-for-builtin += $(obj)/built-in.a
endif
targets-for-modules := $(foreach x, o mod $(if $(CONFIG_TRIM_UNUSED_KSYMS), usyms), \
targets-for-modules := $(foreach x, o mod, \
$(patsubst %.o, %.$x, $(filter %.o, $(obj-m))))
ifdef need-modorder
......@@ -101,7 +101,9 @@ else ifeq ($(KBUILD_CHECKSRC),2)
endif
ifneq ($(KBUILD_EXTRA_WARN),)
cmd_checkdoc = $(srctree)/scripts/kernel-doc -none $<
cmd_checkdoc = $(srctree)/scripts/kernel-doc -none $(KDOCFLAGS) \
$(if $(findstring 2, $(KBUILD_EXTRA_WARN)), -Wall) \
$<
endif
# Compile C sources (.c)
......@@ -161,7 +163,7 @@ quiet_cmd_cc_o_c = CC $(quiet_modtag) $@
ifdef CONFIG_MODVERSIONS
# When module versioning is enabled the following steps are executed:
# o compile a <file>.o from <file>.c
# o if <file>.o doesn't contain a __ksymtab version, i.e. does
# o if <file>.o doesn't contain a __export_symbol_*, i.e. does
# not export symbols, it's done.
# o otherwise, we calculate symbol versions using the good old
# genksyms on the preprocessed source and dump them into the .cmd file.
......@@ -169,7 +171,7 @@ ifdef CONFIG_MODVERSIONS
# be compiled and linked to the kernel and/or modules.
gen_symversions = \
if $(NM) $@ 2>/dev/null | grep -q __ksymtab; then \
if $(NM) $@ 2>/dev/null | grep -q ' __export_symbol_'; then \
$(call cmd_gensymtypes_$(1),$(KBUILD_SYMTYPES),$(@:.o=.symtypes)) \
>> $(dot-target).cmd; \
fi
......@@ -215,21 +217,12 @@ is-standard-object = $(if $(filter-out y%, $(OBJECT_FILES_NON_STANDARD_$(basetar
$(obj)/%.o: objtool-enabled = $(if $(is-standard-object),$(if $(delay-objtool),$(is-single-obj-m),y))
ifdef CONFIG_TRIM_UNUSED_KSYMS
cmd_gen_ksymdeps = \
$(CONFIG_SHELL) $(srctree)/scripts/gen_ksymdeps.sh $@ >> $(dot-target).cmd
endif
cmd_check_local_export = $(srctree)/scripts/check-local-export $@
ifneq ($(findstring 1, $(KBUILD_EXTRA_WARN)),)
cmd_warn_shared_object = $(if $(word 2, $(modname-multi)),$(warning $(kbuild-file): $*.o is added to multiple modules: $(modname-multi)))
endif
define rule_cc_o_c
$(call cmd_and_fixdep,cc_o_c)
$(call cmd,gen_ksymdeps)
$(call cmd,check_local_export)
$(call cmd,checksrc)
$(call cmd,checkdoc)
$(call cmd,gen_objtooldep)
......@@ -240,8 +233,6 @@ endef
define rule_as_o_S
$(call cmd_and_fixdep,as_o_S)
$(call cmd,gen_ksymdeps)
$(call cmd,check_local_export)
$(call cmd,gen_objtooldep)
$(call cmd,gen_symversions_S)
$(call cmd,warn_shared_object)
......@@ -260,12 +251,6 @@ cmd_mod = printf '%s\n' $(call real-search, $*.o, .o, -objs -y -m) | \
$(obj)/%.mod: FORCE
$(call if_changed,mod)
# List module undefined symbols
cmd_undefined_syms = $(NM) $< | sed -n 's/^ *U //p' > $@
$(obj)/%.usyms: $(obj)/%.o FORCE
$(call if_changed,undefined_syms)
quiet_cmd_cc_lst_c = MKLST $@
cmd_cc_lst_c = $(CC) $(c_flags) -g -c -o $*.o $< && \
$(CONFIG_SHELL) $(srctree)/scripts/makelst $*.o \
......@@ -340,9 +325,7 @@ $(obj)/%.ll: $(src)/%.rs FORCE
cmd_gensymtypes_S = \
{ echo "\#include <linux/kernel.h>" ; \
echo "\#include <asm/asm-prototypes.h>" ; \
$(CPP) $(a_flags) $< | \
grep "\<___EXPORT_SYMBOL\>" | \
sed 's/.*___EXPORT_SYMBOL[[:space:]]*\([a-zA-Z0-9_]*\)[[:space:]]*,.*/EXPORT_SYMBOL(\1);/' ; } | \
$(NM) $@ | sed -n 's/.* __export_symbol_\(.*\)/EXPORT_SYMBOL(\1);/p' ; } | \
$(CPP) -D__GENKSYMS__ $(c_flags) -xc - | $(genksyms)
quiet_cmd_cc_symtypes_S = SYM $(quiet_modtag) $@
......
......@@ -35,6 +35,5 @@ CLANG_FLAGS += -Werror=unknown-warning-option
CLANG_FLAGS += -Werror=ignored-optimization-argument
CLANG_FLAGS += -Werror=option-ignored
CLANG_FLAGS += -Werror=unused-command-line-argument
KBUILD_CFLAGS += $(CLANG_FLAGS)
KBUILD_AFLAGS += $(CLANG_FLAGS)
KBUILD_CPPFLAGS += $(CLANG_FLAGS)
export CLANG_FLAGS
......@@ -37,8 +37,10 @@ __clean-files := $(wildcard $(addprefix $(obj)/, $(__clean-files)))
# ==========================================================================
# To make this rule robust against "Argument list too long" error,
# remove $(obj)/ prefix, and restore it by a shell command.
quiet_cmd_clean = CLEAN $(obj)
cmd_clean = rm -rf $(__clean-files)
cmd_clean = printf '$(obj)/%s ' $(patsubst $(obj)/%,%,$(__clean-files)) | xargs rm -rf
__clean: $(subdir-ymn)
ifneq ($(strip $(__clean-files)),)
......
......@@ -32,13 +32,13 @@ try-run = $(shell set -e; \
# Usage: aflags-y += $(call as-option,-Wa$(comma)-isa=foo,)
as-option = $(call try-run,\
$(CC) -Werror $(KBUILD_AFLAGS) $(1) -c -x assembler-with-cpp /dev/null -o "$$TMP",$(1),$(2))
$(CC) -Werror $(KBUILD_CPPFLAGS) $(KBUILD_AFLAGS) $(1) -c -x assembler-with-cpp /dev/null -o "$$TMP",$(1),$(2))
# as-instr
# Usage: aflags-y += $(call as-instr,instr,option1,option2)
as-instr = $(call try-run,\
printf "%b\n" "$(1)" | $(CC) -Werror $(KBUILD_AFLAGS) -c -x assembler-with-cpp -o "$$TMP" -,$(2),$(3))
printf "%b\n" "$(1)" | $(CC) -Werror $(CLANG_FLAGS) $(KBUILD_AFLAGS) -c -x assembler-with-cpp -o "$$TMP" -,$(2),$(3))
# __cc-option
# Usage: MY_CFLAGS += $(call __cc-option,$(CC),$(MY_CFLAGS),-march=winchip-c6,-march=i586)
......
......@@ -418,9 +418,6 @@ endif
$(obj)/%.dtb: $(src)/%.dts $(DTC) $(DT_TMP_SCHEMA) FORCE
$(call if_changed_dep,dtb)
$(obj)/%.dtbo: $(src)/%.dts $(DTC) FORCE
$(call if_changed_dep,dtc)
$(obj)/%.dtbo: $(src)/%.dtso $(DTC) FORCE
$(call if_changed_dep,dtc)
......
......@@ -23,7 +23,7 @@ modname = $(notdir $(@:.mod.o=))
part-of-module = y
quiet_cmd_cc_o_c = CC [M] $@
cmd_cc_o_c = $(CC) $(filter-out $(CC_FLAGS_CFI), $(c_flags)) -c -o $@ $<
cmd_cc_o_c = $(CC) $(filter-out $(CC_FLAGS_CFI) $(CFLAGS_GCOV), $(c_flags)) -c -o $@ $<
%.mod.o: %.mod.c FORCE
$(call if_changed_dep,cc_o_c)
......
......@@ -47,6 +47,7 @@ modpost-args = \
$(if $(KBUILD_MODPOST_WARN),-w) \
$(if $(KBUILD_NSDEPS),-d $(MODULES_NSDEPS)) \
$(if $(CONFIG_MODULE_ALLOW_MISSING_NAMESPACE_IMPORTS)$(KBUILD_NSDEPS),-N) \
$(if $(findstring 1, $(KBUILD_EXTRA_WARN)),-W) \
-o $@
modpost-deps := $(MODPOST)
......@@ -90,6 +91,13 @@ targets += .vmlinux.objs
.vmlinux.objs: vmlinux.a $(KBUILD_VMLINUX_LIBS) FORCE
$(call if_changed,vmlinux_objs)
ifdef CONFIG_TRIM_UNUSED_KSYMS
ksym-wl := $(CONFIG_UNUSED_KSYMS_WHITELIST)
ksym-wl := $(if $(filter-out /%, $(ksym-wl)),$(srctree)/)$(ksym-wl)
modpost-args += -t $(addprefix -u , $(ksym-wl))
modpost-deps += $(ksym-wl)
endif
ifeq ($(wildcard vmlinux.o),)
missing-input := vmlinux.o
output-symdump := modules-only.symvers
......
......@@ -19,6 +19,7 @@ quiet_cmd_cc_o_c = CC $@
ifdef CONFIG_MODULES
KASAN_SANITIZE_.vmlinux.export.o := n
GCOV_PROFILE_.vmlinux.export.o := n
targets += .vmlinux.export.o
vmlinux: .vmlinux.export.o
endif
......
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0-only
# Script to update include/generated/autoksyms.h and dependency files
#
# Copyright: (C) 2016 Linaro Limited
# Created by: Nicolas Pitre, January 2016
#
# Update the include/generated/autoksyms.h file.
#
# For each symbol being added or removed, the corresponding dependency
# file's timestamp is updated to force a rebuild of the affected source
# file. All arguments passed to this script are assumed to be a command
# to be exec'd to trigger a rebuild of those files.
set -e
cur_ksyms_file="include/generated/autoksyms.h"
new_ksyms_file="include/generated/autoksyms.h.tmpnew"
info() {
if [ "$quiet" != "silent_" ]; then
printf " %-7s %s\n" "$1" "$2"
fi
}
info "CHK" "$cur_ksyms_file"
# Use "make V=1" to debug this script.
case "$KBUILD_VERBOSE" in
*1*)
set -x
;;
esac
# Generate a new symbol list file
$CONFIG_SHELL $srctree/scripts/gen_autoksyms.sh --modorder "$new_ksyms_file"
# Extract changes between old and new list and touch corresponding
# dependency files.
changed=$(
count=0
sort "$cur_ksyms_file" "$new_ksyms_file" | uniq -u |
sed -n 's/^#define __KSYM_\(.*\) 1/\1/p' |
while read sympath; do
if [ -z "$sympath" ]; then continue; fi
depfile="include/ksym/${sympath}"
mkdir -p "$(dirname "$depfile")"
touch "$depfile"
# Filesystems with coarse time precision may create timestamps
# equal to the one from a file that was very recently built and that
# needs to be rebuild. Let's guard against that by making sure our
# dep files are always newer than the first file we created here.
while [ ! "$depfile" -nt "$new_ksyms_file" ]; do
touch "$depfile"
done
echo $((count += 1))
done | tail -1 )
changed=${changed:-0}
if [ $changed -gt 0 ]; then
# Replace the old list with tne new one
old=$(grep -c "^#define __KSYM_" "$cur_ksyms_file" || true)
new=$(grep -c "^#define __KSYM_" "$new_ksyms_file" || true)
info "KSYMS" "symbols: before=$old, after=$new, changed=$changed"
info "UPD" "$cur_ksyms_file"
mv -f "$new_ksyms_file" "$cur_ksyms_file"
# Then trigger a rebuild of affected source files
exec $@
else
rm -f "$new_ksyms_file"
fi
......@@ -246,8 +246,7 @@ static void *read_file(const char *filename)
/* Ignore certain dependencies */
static int is_ignored_file(const char *s, int len)
{
return str_ends_with(s, len, "include/generated/autoconf.h") ||
str_ends_with(s, len, "include/generated/autoksyms.h");
return str_ends_with(s, len, "include/generated/autoconf.h");
}
/* Do not parse these files */
......
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0-only
#
# Copyright (C) 2022 Masahiro Yamada <masahiroy@kernel.org>
# Copyright (C) 2022 Owen Rafferty <owen@owenrafferty.com>
#
# Exit with error if a local exported symbol is found.
# EXPORT_SYMBOL should be used for global symbols.
set -e
pid=$$
# If there is no symbol in the object, ${NM} (both GNU nm and llvm-nm) shows
# 'no symbols' diagnostic (but exits with 0). It is harmless and hidden by
# '2>/dev/null'. However, it suppresses real error messages as well. Add a
# hand-crafted error message here.
#
# TODO:
# Use --quiet instead of 2>/dev/null when we upgrade the minimum version of
# binutils to 2.37, llvm to 13.0.0.
# Then, the following line will be simpler:
# { ${NM} --quiet ${1} || kill 0; } |
{ ${NM} ${1} 2>/dev/null || { echo "${0}: ${NM} failed" >&2; kill $pid; } } |
${AWK} -v "file=${1}" '
BEGIN {
i = 0
}
# Skip the line if the number of fields is less than 3.
#
# case 1)
# For undefined symbols, the first field (value) is empty.
# The outout looks like this:
# " U _printk"
# It is unneeded to record undefined symbols.
#
# case 2)
# For Clang LTO, llvm-nm outputs a line with type t but empty name:
# "---------------- t"
!length($3) {
next
}
# save (name, type) in the associative array
{ symbol_types[$3]=$2 }
# append the exported symbol to the array
($3 ~ /^__ksymtab_/) {
export_symbols[i] = $3
sub(/^__ksymtab_/, "", export_symbols[i])
i++
}
END {
exit_code = 0
for (j = 0; j < i; ++j) {
name = export_symbols[j]
# nm(3) says "If lowercase, the symbol is usually local"
if (symbol_types[name] ~ /[a-z]/) {
printf "%s: error: local symbol %s was exported\n",
file, name | "cat 1>&2"
exit_code = 1
}
}
exit exit_code
}'
exit $?
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0-only
# Create an autoksyms.h header file from the list of all module's needed symbols
# as recorded in *.usyms files and the user-provided symbol whitelist.
set -e
# Use "make V=1" to debug this script.
case "$KBUILD_VERBOSE" in
*1*)
set -x
;;
esac
read_modorder=
if [ "$1" = --modorder ]; then
shift
read_modorder=1
fi
output_file="$1"
needed_symbols=
# Special case for modversions (see modpost.c)
if grep -q "^CONFIG_MODVERSIONS=y$" include/config/auto.conf; then
needed_symbols="$needed_symbols module_layout"
fi
ksym_wl=$(sed -n 's/^CONFIG_UNUSED_KSYMS_WHITELIST=\(.*\)$/\1/p' include/config/auto.conf)
if [ -n "$ksym_wl" ]; then
[ "${ksym_wl}" != "${ksym_wl#/}" ] || ksym_wl="$abs_srctree/$ksym_wl"
if [ ! -f "$ksym_wl" ] || [ ! -r "$ksym_wl" ]; then
echo "ERROR: '$ksym_wl' whitelist file not found" >&2
exit 1
fi
fi
# Generate a new ksym list file with symbols needed by the current
# set of modules.
cat > "$output_file" << EOT
/*
* Automatically generated file; DO NOT EDIT.
*/
EOT
{
[ -n "${read_modorder}" ] && sed 's/o$/usyms/' modules.order | xargs cat
echo "$needed_symbols"
[ -n "$ksym_wl" ] && cat "$ksym_wl"
} | sed -e 's/ /\n/g' | sed -n -e '/^$/!p' |
# Remove the dot prefix for ppc64; symbol names with a dot (.) hold entry
# point addresses.
sed -e 's/^\.//' |
sort -u |
# Ignore __this_module. It's not an exported symbol, and will be resolved
# when the final .ko's are linked.
grep -v '^__this_module$' |
sed -e 's/\(.*\)/#define __KSYM_\1 1/' >> "$output_file"
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
set -e
# List of exported symbols
#
# If the object has no symbol, $NM warns 'no symbols'.
# Suppress the stderr.
# TODO:
# Use -q instead of 2>/dev/null when we upgrade the minimum version of
# binutils to 2.37, llvm to 13.0.0.
ksyms=$($NM $1 2>/dev/null | sed -n 's/.*__ksym_marker_\(.*\)/\1/p')
if [ -z "$ksyms" ]; then
exit 0
fi
echo
echo "ksymdeps_$1 := \\"
for s in $ksyms
do
printf ' $(wildcard include/ksym/%s) \\\n' "$s"
done
echo
echo "$1: \$(ksymdeps_$1)"
echo
echo "\$(ksymdeps_$1):"
......@@ -19,6 +19,7 @@
*
*/
#include <errno.h>
#include <getopt.h>
#include <stdbool.h>
#include <stdio.h>
......@@ -29,24 +30,8 @@
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof(arr[0]))
#define _stringify_1(x) #x
#define _stringify(x) _stringify_1(x)
#define KSYM_NAME_LEN 512
/*
* A substantially bigger size than the current maximum.
*
* It cannot be defined as an expression because it gets stringified
* for the fscanf() format string. Therefore, a _Static_assert() is
* used instead to maintain the relationship with KSYM_NAME_LEN.
*/
#define KSYM_NAME_LEN_BUFFER 2048
_Static_assert(
KSYM_NAME_LEN_BUFFER == KSYM_NAME_LEN * 4,
"Please keep KSYM_NAME_LEN_BUFFER in sync with KSYM_NAME_LEN"
);
struct sym_entry {
unsigned long long addr;
unsigned int len;
......@@ -136,24 +121,40 @@ static void check_symbol_range(const char *sym, unsigned long long addr,
}
}
static struct sym_entry *read_symbol(FILE *in)
static struct sym_entry *read_symbol(FILE *in, char **buf, size_t *buf_len)
{
char name[KSYM_NAME_LEN_BUFFER+1], type;
char *name, type, *p;
unsigned long long addr;
unsigned int len;
size_t len;
ssize_t readlen;
struct sym_entry *sym;
int rc;
rc = fscanf(in, "%llx %c %" _stringify(KSYM_NAME_LEN_BUFFER) "s\n", &addr, &type, name);
if (rc != 3) {
if (rc != EOF && fgets(name, ARRAY_SIZE(name), in) == NULL)
fprintf(stderr, "Read error or end of file.\n");
readlen = getline(buf, buf_len, in);
if (readlen < 0) {
if (errno) {
perror("read_symbol");
exit(EXIT_FAILURE);
}
return NULL;
}
if (strlen(name) >= KSYM_NAME_LEN) {
if ((*buf)[readlen - 1] == '\n')
(*buf)[readlen - 1] = 0;
addr = strtoull(*buf, &p, 16);
if (*buf == p || *p++ != ' ' || !isascii((type = *p++)) || *p++ != ' ') {
fprintf(stderr, "line format error\n");
exit(EXIT_FAILURE);
}
name = p;
len = strlen(name);
if (len >= KSYM_NAME_LEN) {
fprintf(stderr, "Symbol %s too long for kallsyms (%zu >= %d).\n"
"Please increase KSYM_NAME_LEN both in kernel and kallsyms.c\n",
name, strlen(name), KSYM_NAME_LEN);
name, len, KSYM_NAME_LEN);
return NULL;
}
......@@ -169,8 +170,7 @@ static struct sym_entry *read_symbol(FILE *in)
/* include the type field in the symbol name, so that it gets
* compressed together */
len = strlen(name) + 1;
len++;
sym = malloc(sizeof(*sym) + len + 1);
if (!sym) {
......@@ -257,6 +257,8 @@ static void read_map(const char *in)
{
FILE *fp;
struct sym_entry *sym;
char *buf = NULL;
size_t buflen = 0;
fp = fopen(in, "r");
if (!fp) {
......@@ -265,7 +267,7 @@ static void read_map(const char *in)
}
while (!feof(fp)) {
sym = read_symbol(fp);
sym = read_symbol(fp, &buf, &buflen);
if (!sym)
continue;
......@@ -284,6 +286,7 @@ static void read_map(const char *in)
table[table_cnt++] = sym;
}
free(buf);
fclose(fp);
}
......@@ -806,7 +809,7 @@ static void record_relative_base(void)
int main(int argc, char **argv)
{
while (1) {
static struct option long_options[] = {
static const struct option long_options[] = {
{"all-symbols", no_argument, &all_symbols, 1},
{"absolute-percpu", no_argument, &absolute_percpu, 1},
{"base-relative", no_argument, &base_relative, 1},
......
......@@ -317,7 +317,7 @@ foreach my $makefile (@makefiles) {
$_ = convert_vars($_, %make_vars);
# collect objects after obj-$(CONFIG_FOO_BAR)
if (/obj-\$\((CONFIG_[^\)]*)\)\s*[+:]?=\s*(.*)/) {
if (/obj-\$[({](CONFIG_[^})]*)[)}]\s*[+:]?=\s*(.*)/) {
$var = $1;
$objs = $2;
......
......@@ -23,7 +23,7 @@ kernel-doc - Print formatted kernel documentation to stdout
=head1 SYNOPSIS
kernel-doc [-h] [-v] [-Werror]
kernel-doc [-h] [-v] [-Werror] [-Wall] [-Wreturn] [-Wshort-description] [-Wcontents-before-sections]
[ -man |
-rst [-sphinx-version VERSION] [-enable-lineno] |
-none
......@@ -133,6 +133,9 @@ my $dohighlight = "";
my $verbose = 0;
my $Werror = 0;
my $Wreturn = 0;
my $Wshort_desc = 0;
my $Wcontents_before_sections = 0;
my $output_mode = "rst";
my $output_preformatted = 0;
my $no_doc_sections = 0;
......@@ -187,9 +190,14 @@ if (defined($ENV{'KCFLAGS'})) {
}
}
# reading this variable is for backwards compat just in case
# someone was calling it with the variable from outside the
# kernel's build system
if (defined($ENV{'KDOC_WERROR'})) {
$Werror = "$ENV{'KDOC_WERROR'}";
}
# other environment variables are converted to command-line
# arguments in cmd_checkdoc in the build system
# Generated docbook code is inserted in a template at a point where
# docbook v3.1 requires a non-zero sequence of RefEntry's; see:
......@@ -318,6 +326,16 @@ while ($ARGV[0] =~ m/^--?(.*)/) {
$verbose = 1;
} elsif ($cmd eq "Werror") {
$Werror = 1;
} elsif ($cmd eq "Wreturn") {
$Wreturn = 1;
} elsif ($cmd eq "Wshort-desc") {
$Wshort_desc = 1;
} elsif ($cmd eq "Wcontents-before-sections") {
$Wcontents_before_sections = 1;
} elsif ($cmd eq "Wall") {
$Wreturn = 1;
$Wshort_desc = 1;
$Wcontents_before_sections = 1;
} elsif (($cmd eq "h") || ($cmd eq "help")) {
pod2usage(-exitval => 0, -verbose => 2);
} elsif ($cmd eq 'no-doc-sections') {
......@@ -1748,9 +1766,9 @@ sub dump_function($$) {
# This check emits a lot of warnings at the moment, because many
# functions don't have a 'Return' doc section. So until the number
# of warnings goes sufficiently down, the check is only performed in
# verbose mode.
# -Wreturn mode.
# TODO: always perform the check.
if ($verbose && !$noret) {
if ($Wreturn && !$noret) {
check_return_section($file, $declaration_name, $return_type);
}
......@@ -2054,7 +2072,7 @@ sub process_name($$) {
$state = STATE_NORMAL;
}
if (($declaration_purpose eq "") && $verbose) {
if (($declaration_purpose eq "") && $Wshort_desc) {
emit_warning("${file}:$.", "missing initial short description on line:\n$_");
}
......@@ -2103,7 +2121,7 @@ sub process_body($$) {
}
if (($contents ne "") && ($contents ne "\n")) {
if (!$in_doc_sect && $verbose) {
if (!$in_doc_sect && $Wcontents_before_sections) {
emit_warning("${file}:$.", "contents before sections\n");
}
dump_section($file, $section, $contents);
......
......@@ -32,7 +32,7 @@ ${NM} -n ${1} | sed >${2} -e "
# (do not forget a space before each pattern)
# local symbols for ARM, MIPS, etc.
/ \$/d
/ \\$/d
# local labels, .LBB, .Ltmpxxx, .L__unnamed_xx, .LASANPC, etc.
/ \.L/d
......@@ -40,8 +40,12 @@ ${NM} -n ${1} | sed >${2} -e "
# arm64 EFI stub namespace
/ __efistub_/d
# arm64 local symbols in PIE namespace
/ __pi_\\$/d
/ __pi_\.L/d
# arm64 local symbols in non-VHE KVM namespace
/ __kvm_nvhe_\$/d
/ __kvm_nvhe_\\$/d
/ __kvm_nvhe_\.L/d
# arm64 lld
......@@ -58,6 +62,8 @@ ${NM} -n ${1} | sed >${2} -e "
# CFI type identifiers
/ __kcfi_typeid_/d
/ __kvm_nvhe___kcfi_typeid_/d
/ __pi___kcfi_typeid_/d
# CRC from modversions
/ __crc_/d
......
......@@ -35,6 +35,9 @@ static bool warn_unresolved;
static int sec_mismatch_count;
static bool sec_mismatch_warn_only = true;
/* Trim EXPORT_SYMBOLs that are unused by in-tree modules */
static bool trim_unused_exports;
/* ignore missing files */
static bool ignore_missing_files;
/* If set to 1, only warn (instead of error) about missing ns imports */
......@@ -42,6 +45,8 @@ static bool allow_missing_ns_imports;
static bool error_occurred;
static bool extra_warn;
/*
* Cut off the warnings when there are too many. This typically occurs when
* vmlinux is missing. ('make modules' without building vmlinux.)
......@@ -215,7 +220,9 @@ struct symbol {
unsigned int crc;
bool crc_valid;
bool weak;
bool is_func;
bool is_gpl_only; /* exported by EXPORT_SYMBOL_GPL */
bool used; /* there exists a user of this symbol */
char name[];
};
......@@ -297,6 +304,13 @@ static bool contains_namespace(struct list_head *head, const char *namespace)
{
struct namespace_list *list;
/*
* The default namespace is null string "", which is always implicitly
* contained.
*/
if (!namespace[0])
return true;
list_for_each_entry(list, head, list) {
if (!strcmp(list->namespace, namespace))
return true;
......@@ -352,26 +366,8 @@ static const char *sec_name(const struct elf_info *info, unsigned int secindex)
#define strstarts(str, prefix) (strncmp(str, prefix, strlen(prefix)) == 0)
static void sym_update_namespace(const char *symname, const char *namespace)
{
struct symbol *s = find_symbol(symname);
/*
* That symbol should have been created earlier and thus this is
* actually an assertion.
*/
if (!s) {
error("Could not update namespace(%s) for symbol %s\n",
namespace, symname);
return;
}
free(s->namespace);
s->namespace = namespace[0] ? NOFAIL(strdup(namespace)) : NULL;
}
static struct symbol *sym_add_exported(const char *name, struct module *mod,
bool gpl_only)
bool gpl_only, const char *namespace)
{
struct symbol *s = find_symbol(name);
......@@ -384,6 +380,7 @@ static struct symbol *sym_add_exported(const char *name, struct module *mod,
s = alloc_symbol(name);
s->module = mod;
s->is_gpl_only = gpl_only;
s->namespace = NOFAIL(strdup(namespace));
list_add_tail(&s->list, &mod->exported_symbols);
hash_add_symbol(s);
......@@ -531,6 +528,8 @@ static int parse_elf(struct elf_info *info, const char *filename)
fatal("%s has NOBITS .modinfo\n", filename);
info->modinfo = (void *)hdr + sechdrs[i].sh_offset;
info->modinfo_len = sechdrs[i].sh_size;
} else if (!strcmp(secname, ".export_symbol")) {
info->export_symbol_secndx = i;
}
if (sechdrs[i].sh_type == SHT_SYMTAB) {
......@@ -653,18 +652,6 @@ static void handle_symbol(struct module *mod, struct elf_info *info,
ELF_ST_BIND(sym->st_info) == STB_WEAK);
break;
default:
/* All exported symbols */
if (strstarts(symname, "__ksymtab_")) {
const char *name, *secname;
name = symname + strlen("__ksymtab_");
secname = sec_name(info, get_secindex(info, sym));
if (strstarts(secname, "___ksymtab_gpl+"))
sym_add_exported(name, mod, true);
else if (strstarts(secname, "___ksymtab+"))
sym_add_exported(name, mod, false);
}
if (strcmp(symname, "init_module") == 0)
mod->has_init = true;
if (strcmp(symname, "cleanup_module") == 0)
......@@ -838,34 +825,14 @@ static void check_section(const char *modname, struct elf_info *elf,
#define ALL_TEXT_SECTIONS ALL_INIT_TEXT_SECTIONS, ALL_EXIT_TEXT_SECTIONS, \
TEXT_SECTIONS, OTHER_TEXT_SECTIONS
/* init data sections */
static const char *const init_data_sections[] =
{ ALL_INIT_DATA_SECTIONS, NULL };
/* all init sections */
static const char *const init_sections[] = { ALL_INIT_SECTIONS, NULL };
/* all text sections */
static const char *const text_sections[] = { ALL_TEXT_SECTIONS, NULL };
/* data section */
static const char *const data_sections[] = { DATA_SECTIONS, NULL };
static const char *const head_sections[] = { ".head.text*", NULL };
static const char *const linker_symbols[] =
{ "__init_begin", "_sinittext", "_einittext", NULL };
static const char *const optim_symbols[] = { "*.constprop.*", NULL };
enum mismatch {
TEXT_TO_ANY_INIT,
DATA_TO_ANY_INIT,
TEXT_TO_ANY_EXIT,
DATA_TO_ANY_EXIT,
TEXTDATA_TO_ANY_EXIT,
XXXINIT_TO_SOME_INIT,
XXXEXIT_TO_SOME_EXIT,
ANY_INIT_TO_ANY_EXIT,
ANY_EXIT_TO_ANY_INIT,
EXPORT_TO_INIT_EXIT,
EXTABLE_TO_NON_TEXT,
};
......@@ -881,27 +848,14 @@ enum mismatch {
* targeting sections in this array (white-list). Can be empty.
*
* @mismatch: Type of mismatch.
*
* @handler: Specific handler to call when a match is found. If NULL,
* default_mismatch_handler() will be called.
*
*/
struct sectioncheck {
const char *fromsec[20];
const char *bad_tosec[20];
const char *good_tosec[20];
enum mismatch mismatch;
void (*handler)(const char *modname, struct elf_info *elf,
const struct sectioncheck* const mismatch,
Elf_Rela *r, Elf_Sym *sym, const char *fromsec);
};
static void extable_mismatch_handler(const char *modname, struct elf_info *elf,
const struct sectioncheck* const mismatch,
Elf_Rela *r, Elf_Sym *sym,
const char *fromsec);
static const struct sectioncheck sectioncheck[] = {
/* Do not reference init/exit code/data from
* normal code and data
......@@ -913,23 +867,13 @@ static const struct sectioncheck sectioncheck[] = {
},
{
.fromsec = { DATA_SECTIONS, NULL },
.bad_tosec = { ALL_XXXINIT_SECTIONS, NULL },
.mismatch = DATA_TO_ANY_INIT,
},
{
.fromsec = { DATA_SECTIONS, NULL },
.bad_tosec = { INIT_SECTIONS, NULL },
.bad_tosec = { ALL_XXXINIT_SECTIONS, INIT_SECTIONS, NULL },
.mismatch = DATA_TO_ANY_INIT,
},
{
.fromsec = { TEXT_SECTIONS, NULL },
.bad_tosec = { ALL_EXIT_SECTIONS, NULL },
.mismatch = TEXT_TO_ANY_EXIT,
},
{
.fromsec = { DATA_SECTIONS, NULL },
.fromsec = { TEXT_SECTIONS, DATA_SECTIONS, NULL },
.bad_tosec = { ALL_EXIT_SECTIONS, NULL },
.mismatch = DATA_TO_ANY_EXIT,
.mismatch = TEXTDATA_TO_ANY_EXIT,
},
/* Do not reference init code/data from meminit code/data */
{
......@@ -960,12 +904,6 @@ static const struct sectioncheck sectioncheck[] = {
.bad_tosec = { INIT_SECTIONS, NULL },
.mismatch = ANY_INIT_TO_ANY_EXIT,
},
/* Do not export init/exit functions or data */
{
.fromsec = { "___ksymtab*", NULL },
.bad_tosec = { INIT_SECTIONS, EXIT_SECTIONS, NULL },
.mismatch = EXPORT_TO_INIT_EXIT,
},
{
.fromsec = { "__ex_table", NULL },
/* If you're adding any new black-listed sections in here, consider
......@@ -974,7 +912,6 @@ static const struct sectioncheck sectioncheck[] = {
.bad_tosec = { ".altinstr_replacement", NULL },
.good_tosec = {ALL_TEXT_SECTIONS , NULL},
.mismatch = EXTABLE_TO_NON_TEXT,
.handler = extable_mismatch_handler,
}
};
......@@ -1048,28 +985,19 @@ static const struct sectioncheck *section_mismatch(
* fromsec = text section
* refsymname = *.constprop.*
*
* Pattern 6:
* Hide section mismatch warnings for ELF local symbols. The goal
* is to eliminate false positive modpost warnings caused by
* compiler-generated ELF local symbol names such as ".LANCHOR1".
* Autogenerated symbol names bypass modpost's "Pattern 2"
* whitelisting, which relies on pattern-matching against symbol
* names to work. (One situation where gcc can autogenerate ELF
* local symbols is when "-fsection-anchors" is used.)
**/
static int secref_whitelist(const struct sectioncheck *mismatch,
const char *fromsec, const char *fromsym,
static int secref_whitelist(const char *fromsec, const char *fromsym,
const char *tosec, const char *tosym)
{
/* Check for pattern 1 */
if (match(tosec, init_data_sections) &&
match(fromsec, data_sections) &&
if (match(tosec, PATTERNS(ALL_INIT_DATA_SECTIONS)) &&
match(fromsec, PATTERNS(DATA_SECTIONS)) &&
strstarts(fromsym, "__param"))
return 0;
/* Check for pattern 1a */
if (strcmp(tosec, ".init.text") == 0 &&
match(fromsec, data_sections) &&
match(fromsec, PATTERNS(DATA_SECTIONS)) &&
strstarts(fromsym, "__param_ops_"))
return 0;
......@@ -1092,22 +1020,18 @@ static int secref_whitelist(const struct sectioncheck *mismatch,
return 0;
/* Check for pattern 3 */
if (match(fromsec, head_sections) &&
match(tosec, init_sections))
if (strstarts(fromsec, ".head.text") &&
match(tosec, PATTERNS(ALL_INIT_SECTIONS)))
return 0;
/* Check for pattern 4 */
if (match(tosym, linker_symbols))
if (match(tosym, PATTERNS("__init_begin", "_sinittext", "_einittext")))
return 0;
/* Check for pattern 5 */
if (match(fromsec, text_sections) &&
match(tosec, init_sections) &&
match(fromsym, optim_symbols))
return 0;
/* Check for pattern 6 */
if (strstarts(fromsym, ".L"))
if (match(fromsec, PATTERNS(ALL_TEXT_SECTIONS)) &&
match(tosec, PATTERNS(ALL_INIT_SECTIONS)) &&
match(fromsym, PATTERNS("*.constprop.*")))
return 0;
return 1;
......@@ -1131,303 +1055,210 @@ static inline int is_valid_name(struct elf_info *elf, Elf_Sym *sym)
return !is_mapping_symbol(name);
}
/**
* Find symbol based on relocation record info.
* In some cases the symbol supplied is a valid symbol so
* return refsym. If st_name != 0 we assume this is a valid symbol.
* In other cases the symbol needs to be looked up in the symbol table
* based on section and address.
* **/
static Elf_Sym *find_elf_symbol(struct elf_info *elf, Elf64_Sword addr,
Elf_Sym *relsym)
/* Look up the nearest symbol based on the section and the address */
static Elf_Sym *find_nearest_sym(struct elf_info *elf, Elf_Addr addr,
unsigned int secndx, bool allow_negative,
Elf_Addr min_distance)
{
Elf_Sym *sym;
Elf_Sym *near = NULL;
Elf64_Sword distance = 20;
Elf64_Sword d;
unsigned int relsym_secindex;
if (relsym->st_name != 0)
return relsym;
Elf_Addr sym_addr, distance;
bool is_arm = (elf->hdr->e_machine == EM_ARM);
relsym_secindex = get_secindex(elf, relsym);
for (sym = elf->symtab_start; sym < elf->symtab_stop; sym++) {
if (get_secindex(elf, sym) != relsym_secindex)
continue;
if (ELF_ST_TYPE(sym->st_info) == STT_SECTION)
if (get_secindex(elf, sym) != secndx)
continue;
if (!is_valid_name(elf, sym))
continue;
if (sym->st_value == addr)
return sym;
/* Find a symbol nearby - addr are maybe negative */
d = sym->st_value - addr;
if (d < 0)
d = addr - sym->st_value;
if (d < distance) {
distance = d;
near = sym;
}
}
/* We need a close match */
if (distance < 20)
return near;
else
return NULL;
}
/*
* Find symbols before or equal addr and after addr - in the section sec.
* If we find two symbols with equal offset prefer one with a valid name.
* The ELF format may have a better way to detect what type of symbol
* it is, but this works for now.
**/
static Elf_Sym *find_elf_symbol2(struct elf_info *elf, Elf_Addr addr,
const char *sec)
{
Elf_Sym *sym;
Elf_Sym *near = NULL;
Elf_Addr distance = ~0;
sym_addr = sym->st_value;
for (sym = elf->symtab_start; sym < elf->symtab_stop; sym++) {
const char *symsec;
/*
* For ARM Thumb instruction, the bit 0 of st_value is set
* if the symbol is STT_FUNC type. Mask it to get the address.
*/
if (is_arm && ELF_ST_TYPE(sym->st_info) == STT_FUNC)
sym_addr &= ~1;
if (is_shndx_special(sym->st_shndx))
continue;
symsec = sec_name(elf, get_secindex(elf, sym));
if (strcmp(symsec, sec) != 0)
continue;
if (!is_valid_name(elf, sym))
if (addr >= sym_addr)
distance = addr - sym_addr;
else if (allow_negative)
distance = sym_addr - addr;
else
continue;
if (sym->st_value <= addr && addr - sym->st_value <= distance) {
distance = addr - sym->st_value;
if (distance <= min_distance) {
min_distance = distance;
near = sym;
}
if (min_distance == 0)
break;
}
return near;
}
static int is_function(Elf_Sym *sym)
static Elf_Sym *find_fromsym(struct elf_info *elf, Elf_Addr addr,
unsigned int secndx)
{
if (sym)
return ELF_ST_TYPE(sym->st_info) == STT_FUNC;
else
return -1;
return find_nearest_sym(elf, addr, secndx, false, ~0);
}
static inline void get_pretty_name(int is_func, const char** name, const char** name_p)
static Elf_Sym *find_tosym(struct elf_info *elf, Elf_Addr addr, Elf_Sym *sym)
{
switch (is_func) {
case 0: *name = "variable"; *name_p = ""; break;
case 1: *name = "function"; *name_p = "()"; break;
default: *name = "(unknown reference)"; *name_p = ""; break;
}
/* If the supplied symbol has a valid name, return it */
if (is_valid_name(elf, sym))
return sym;
/*
* Strive to find a better symbol name, but the resulting name may not
* match the symbol referenced in the original code.
*/
return find_nearest_sym(elf, addr, get_secindex(elf, sym), true, 20);
}
/*
* Print a warning about a section mismatch.
* Try to find symbols near it so user can find it.
* Check whitelist before warning - it may be a false positive.
*/
static void report_sec_mismatch(const char *modname,
const struct sectioncheck *mismatch,
const char *fromsec,
const char *fromsym,
const char *tosec, const char *tosym)
static bool is_executable_section(struct elf_info *elf, unsigned int secndx)
{
sec_mismatch_count++;
if (secndx >= elf->num_sections)
return false;
switch (mismatch->mismatch) {
case TEXT_TO_ANY_INIT:
case DATA_TO_ANY_INIT:
case TEXT_TO_ANY_EXIT:
case DATA_TO_ANY_EXIT:
case XXXINIT_TO_SOME_INIT:
case XXXEXIT_TO_SOME_EXIT:
case ANY_INIT_TO_ANY_EXIT:
case ANY_EXIT_TO_ANY_INIT:
warn("%s: section mismatch in reference: %s (section: %s) -> %s (section: %s)\n",
modname, fromsym, fromsec, tosym, tosec);
break;
case EXPORT_TO_INIT_EXIT:
warn("%s: EXPORT_SYMBOL used for init/exit symbol: %s (section: %s)\n",
modname, tosym, tosec);
break;
case EXTABLE_TO_NON_TEXT:
fatal("There's a special handler for this mismatch type, we should never get here.\n");
break;
}
return (elf->sechdrs[secndx].sh_flags & SHF_EXECINSTR) != 0;
}
static void default_mismatch_handler(const char *modname, struct elf_info *elf,
const struct sectioncheck* const mismatch,
Elf_Rela *r, Elf_Sym *sym, const char *fromsec)
Elf_Sym *tsym,
unsigned int fsecndx, const char *fromsec, Elf_Addr faddr,
const char *tosec, Elf_Addr taddr)
{
const char *tosec;
Elf_Sym *to;
Elf_Sym *from;
const char *tosym;
const char *fromsym;
from = find_elf_symbol2(elf, r->r_offset, fromsec);
from = find_fromsym(elf, faddr, fsecndx);
fromsym = sym_name(elf, from);
tosec = sec_name(elf, get_secindex(elf, sym));
to = find_elf_symbol(elf, r->r_addend, sym);
tosym = sym_name(elf, to);
tsym = find_tosym(elf, taddr, tsym);
tosym = sym_name(elf, tsym);
/* check whitelist - we may ignore it */
if (secref_whitelist(mismatch,
fromsec, fromsym, tosec, tosym)) {
report_sec_mismatch(modname, mismatch,
fromsec, fromsym, tosec, tosym);
if (!secref_whitelist(fromsec, fromsym, tosec, tosym))
return;
sec_mismatch_count++;
warn("%s: section mismatch in reference: %s+0x%x (section: %s) -> %s (section: %s)\n",
modname, fromsym, (unsigned int)(faddr - from->st_value), fromsec, tosym, tosec);
if (mismatch->mismatch == EXTABLE_TO_NON_TEXT) {
if (match(tosec, mismatch->bad_tosec))
fatal("The relocation at %s+0x%lx references\n"
"section \"%s\" which is black-listed.\n"
"Something is seriously wrong and should be fixed.\n"
"You might get more information about where this is\n"
"coming from by using scripts/check_extable.sh %s\n",
fromsec, (long)faddr, tosec, modname);
else if (is_executable_section(elf, get_secindex(elf, tsym)))
warn("The relocation at %s+0x%lx references\n"
"section \"%s\" which is not in the list of\n"
"authorized sections. If you're adding a new section\n"
"and/or if this reference is valid, add \"%s\" to the\n"
"list of authorized sections to jump to on fault.\n"
"This can be achieved by adding \"%s\" to\n"
"OTHER_TEXT_SECTIONS in scripts/mod/modpost.c.\n",
fromsec, (long)faddr, tosec, tosec, tosec);
else
error("%s+0x%lx references non-executable section '%s'\n",
fromsec, (long)faddr, tosec);
}
}
static int is_executable_section(struct elf_info* elf, unsigned int section_index)
static void check_export_symbol(struct module *mod, struct elf_info *elf,
Elf_Addr faddr, const char *secname,
Elf_Sym *sym)
{
if (section_index > elf->num_sections)
fatal("section_index is outside elf->num_sections!\n");
static const char *prefix = "__export_symbol_";
const char *label_name, *name, *data;
Elf_Sym *label;
struct symbol *s;
bool is_gpl;
return ((elf->sechdrs[section_index].sh_flags & SHF_EXECINSTR) == SHF_EXECINSTR);
}
label = find_fromsym(elf, faddr, elf->export_symbol_secndx);
label_name = sym_name(elf, label);
/*
* We rely on a gross hack in section_rel[a]() calling find_extable_entry_size()
* to know the sizeof(struct exception_table_entry) for the target architecture.
*/
static unsigned int extable_entry_size = 0;
static void find_extable_entry_size(const char* const sec, const Elf_Rela* r)
{
/*
* If we're currently checking the second relocation within __ex_table,
* that relocation offset tells us the offsetof(struct
* exception_table_entry, fixup) which is equal to sizeof(struct
* exception_table_entry) divided by two. We use that to our advantage
* since there's no portable way to get that size as every architecture
* seems to go with different sized types. Not pretty but better than
* hard-coding the size for every architecture..
*/
if (!extable_entry_size)
extable_entry_size = r->r_offset * 2;
}
if (!strstarts(label_name, prefix)) {
error("%s: .export_symbol section contains strange symbol '%s'\n",
mod->name, label_name);
return;
}
static inline bool is_extable_fault_address(Elf_Rela *r)
{
/*
* extable_entry_size is only discovered after we've handled the
* _second_ relocation in __ex_table, so only abort when we're not
* handling the first reloc and extable_entry_size is zero.
*/
if (r->r_offset && extable_entry_size == 0)
fatal("extable_entry size hasn't been discovered!\n");
return ((r->r_offset == 0) ||
(r->r_offset % extable_entry_size == 0));
}
#define is_second_extable_reloc(Start, Cur, Sec) \
(((Cur) == (Start) + 1) && (strcmp("__ex_table", (Sec)) == 0))
static void report_extable_warnings(const char* modname, struct elf_info* elf,
const struct sectioncheck* const mismatch,
Elf_Rela* r, Elf_Sym* sym,
const char* fromsec, const char* tosec)
{
Elf_Sym* fromsym = find_elf_symbol2(elf, r->r_offset, fromsec);
const char* fromsym_name = sym_name(elf, fromsym);
Elf_Sym* tosym = find_elf_symbol(elf, r->r_addend, sym);
const char* tosym_name = sym_name(elf, tosym);
const char* from_pretty_name;
const char* from_pretty_name_p;
const char* to_pretty_name;
const char* to_pretty_name_p;
get_pretty_name(is_function(fromsym),
&from_pretty_name, &from_pretty_name_p);
get_pretty_name(is_function(tosym),
&to_pretty_name, &to_pretty_name_p);
warn("%s(%s+0x%lx): Section mismatch in reference from the %s %s%s to the %s %s:%s%s\n",
modname, fromsec, (long)r->r_offset, from_pretty_name,
fromsym_name, from_pretty_name_p,
to_pretty_name, tosec, tosym_name, to_pretty_name_p);
if (!match(tosec, mismatch->bad_tosec) &&
is_executable_section(elf, get_secindex(elf, sym)))
fprintf(stderr,
"The relocation at %s+0x%lx references\n"
"section \"%s\" which is not in the list of\n"
"authorized sections. If you're adding a new section\n"
"and/or if this reference is valid, add \"%s\" to the\n"
"list of authorized sections to jump to on fault.\n"
"This can be achieved by adding \"%s\" to \n"
"OTHER_TEXT_SECTIONS in scripts/mod/modpost.c.\n",
fromsec, (long)r->r_offset, tosec, tosec, tosec);
}
static void extable_mismatch_handler(const char* modname, struct elf_info *elf,
const struct sectioncheck* const mismatch,
Elf_Rela* r, Elf_Sym* sym,
const char *fromsec)
{
const char* tosec = sec_name(elf, get_secindex(elf, sym));
if (ELF_ST_BIND(sym->st_info) != STB_GLOBAL &&
ELF_ST_BIND(sym->st_info) != STB_WEAK) {
error("%s: local symbol '%s' was exported\n", mod->name,
label_name + strlen(prefix));
return;
}
sec_mismatch_count++;
name = sym_name(elf, sym);
if (strcmp(label_name + strlen(prefix), name)) {
error("%s: .export_symbol section references '%s', but it does not seem to be an export symbol\n",
mod->name, name);
return;
}
report_extable_warnings(modname, elf, mismatch, r, sym, fromsec, tosec);
if (match(tosec, mismatch->bad_tosec))
fatal("The relocation at %s+0x%lx references\n"
"section \"%s\" which is black-listed.\n"
"Something is seriously wrong and should be fixed.\n"
"You might get more information about where this is\n"
"coming from by using scripts/check_extable.sh %s\n",
fromsec, (long)r->r_offset, tosec, modname);
else if (!is_executable_section(elf, get_secindex(elf, sym))) {
if (is_extable_fault_address(r))
fatal("The relocation at %s+0x%lx references\n"
"section \"%s\" which is not executable, IOW\n"
"it is not possible for the kernel to fault\n"
"at that address. Something is seriously wrong\n"
"and should be fixed.\n",
fromsec, (long)r->r_offset, tosec);
else
fatal("The relocation at %s+0x%lx references\n"
"section \"%s\" which is not executable, IOW\n"
"the kernel will fault if it ever tries to\n"
"jump to it. Something is seriously wrong\n"
"and should be fixed.\n",
fromsec, (long)r->r_offset, tosec);
data = sym_get_data(elf, label); /* license */
if (!strcmp(data, "GPL")) {
is_gpl = true;
} else if (!strcmp(data, "")) {
is_gpl = false;
} else {
error("%s: unknown license '%s' was specified for '%s'\n",
mod->name, data, name);
return;
}
data += strlen(data) + 1; /* namespace */
s = sym_add_exported(name, mod, is_gpl, data);
/*
* We need to be aware whether we are exporting a function or
* a data on some architectures.
*/
s->is_func = (ELF_ST_TYPE(sym->st_info) == STT_FUNC);
if (match(secname, PATTERNS(INIT_SECTIONS)))
warn("%s: %s: EXPORT_SYMBOL used for init symbol. Remove __init or EXPORT_SYMBOL.\n",
mod->name, name);
else if (match(secname, PATTERNS(EXIT_SECTIONS)))
warn("%s: %s: EXPORT_SYMBOL used for exit symbol. Remove __exit or EXPORT_SYMBOL.\n",
mod->name, name);
}
static void check_section_mismatch(const char *modname, struct elf_info *elf,
Elf_Rela *r, Elf_Sym *sym, const char *fromsec)
static void check_section_mismatch(struct module *mod, struct elf_info *elf,
Elf_Sym *sym,
unsigned int fsecndx, const char *fromsec,
Elf_Addr faddr, Elf_Addr taddr)
{
const char *tosec = sec_name(elf, get_secindex(elf, sym));
const struct sectioncheck *mismatch = section_mismatch(fromsec, tosec);
const struct sectioncheck *mismatch;
if (mismatch) {
if (mismatch->handler)
mismatch->handler(modname, elf, mismatch,
r, sym, fromsec);
else
default_mismatch_handler(modname, elf, mismatch,
r, sym, fromsec);
if (elf->export_symbol_secndx == fsecndx) {
check_export_symbol(mod, elf, faddr, tosec, sym);
return;
}
}
static unsigned int *reloc_location(struct elf_info *elf,
Elf_Shdr *sechdr, Elf_Rela *r)
{
return sym_get_data_by_offset(elf, sechdr->sh_info, r->r_offset);
mismatch = section_mismatch(fromsec, tosec);
if (!mismatch)
return;
default_mismatch_handler(mod->name, elf, mismatch, sym,
fsecndx, fromsec, faddr,
tosec, taddr);
}
static int addend_386_rel(struct elf_info *elf, Elf_Shdr *sechdr, Elf_Rela *r)
static int addend_386_rel(uint32_t *location, Elf_Rela *r)
{
unsigned int r_typ = ELF_R_TYPE(r->r_info);
unsigned int *location = reloc_location(elf, sechdr, r);
switch (r_typ) {
case R_386_32:
......@@ -1436,6 +1267,8 @@ static int addend_386_rel(struct elf_info *elf, Elf_Shdr *sechdr, Elf_Rela *r)
case R_386_PC32:
r->r_addend = TO_NATIVE(*location) + 4;
break;
default:
r->r_addend = (Elf_Addr)(-1);
}
return 0;
}
......@@ -1453,45 +1286,131 @@ static int addend_386_rel(struct elf_info *elf, Elf_Shdr *sechdr, Elf_Rela *r)
#ifndef R_ARM_THM_JUMP24
#define R_ARM_THM_JUMP24 30
#endif
#ifndef R_ARM_MOVW_ABS_NC
#define R_ARM_MOVW_ABS_NC 43
#endif
#ifndef R_ARM_MOVT_ABS
#define R_ARM_MOVT_ABS 44
#endif
#ifndef R_ARM_THM_MOVW_ABS_NC
#define R_ARM_THM_MOVW_ABS_NC 47
#endif
#ifndef R_ARM_THM_MOVT_ABS
#define R_ARM_THM_MOVT_ABS 48
#endif
#ifndef R_ARM_THM_JUMP19
#define R_ARM_THM_JUMP19 51
#endif
static int addend_arm_rel(struct elf_info *elf, Elf_Shdr *sechdr, Elf_Rela *r)
static int32_t sign_extend32(int32_t value, int index)
{
uint8_t shift = 31 - index;
return (int32_t)(value << shift) >> shift;
}
static int addend_arm_rel(void *loc, Elf_Sym *sym, Elf_Rela *r)
{
unsigned int r_typ = ELF_R_TYPE(r->r_info);
uint32_t inst, upper, lower, sign, j1, j2;
int32_t offset;
switch (r_typ) {
case R_ARM_ABS32:
/* From ARM ABI: (S + A) | T */
r->r_addend = (int)(long)
(elf->symtab_start + ELF_R_SYM(r->r_info));
case R_ARM_REL32:
inst = TO_NATIVE(*(uint32_t *)loc);
r->r_addend = inst + sym->st_value;
break;
case R_ARM_MOVW_ABS_NC:
case R_ARM_MOVT_ABS:
inst = TO_NATIVE(*(uint32_t *)loc);
offset = sign_extend32(((inst & 0xf0000) >> 4) | (inst & 0xfff),
15);
r->r_addend = offset + sym->st_value;
break;
case R_ARM_PC24:
case R_ARM_CALL:
case R_ARM_JUMP24:
inst = TO_NATIVE(*(uint32_t *)loc);
offset = sign_extend32((inst & 0x00ffffff) << 2, 25);
r->r_addend = offset + sym->st_value + 8;
break;
case R_ARM_THM_MOVW_ABS_NC:
case R_ARM_THM_MOVT_ABS:
upper = TO_NATIVE(*(uint16_t *)loc);
lower = TO_NATIVE(*((uint16_t *)loc + 1));
offset = sign_extend32(((upper & 0x000f) << 12) |
((upper & 0x0400) << 1) |
((lower & 0x7000) >> 4) |
(lower & 0x00ff),
15);
r->r_addend = offset + sym->st_value;
break;
case R_ARM_THM_JUMP19:
/*
* Encoding T3:
* S = upper[10]
* imm6 = upper[5:0]
* J1 = lower[13]
* J2 = lower[11]
* imm11 = lower[10:0]
* imm32 = SignExtend(S:J2:J1:imm6:imm11:'0')
*/
upper = TO_NATIVE(*(uint16_t *)loc);
lower = TO_NATIVE(*((uint16_t *)loc + 1));
sign = (upper >> 10) & 1;
j1 = (lower >> 13) & 1;
j2 = (lower >> 11) & 1;
offset = sign_extend32((sign << 20) | (j2 << 19) | (j1 << 18) |
((upper & 0x03f) << 12) |
((lower & 0x07ff) << 1),
20);
r->r_addend = offset + sym->st_value + 4;
break;
case R_ARM_THM_CALL:
case R_ARM_THM_JUMP24:
case R_ARM_THM_JUMP19:
/* From ARM ABI: ((S + A) | T) - P */
r->r_addend = (int)(long)(elf->hdr +
sechdr->sh_offset +
(r->r_offset - sechdr->sh_addr));
/*
* Encoding T4:
* S = upper[10]
* imm10 = upper[9:0]
* J1 = lower[13]
* J2 = lower[11]
* imm11 = lower[10:0]
* I1 = NOT(J1 XOR S)
* I2 = NOT(J2 XOR S)
* imm32 = SignExtend(S:I1:I2:imm10:imm11:'0')
*/
upper = TO_NATIVE(*(uint16_t *)loc);
lower = TO_NATIVE(*((uint16_t *)loc + 1));
sign = (upper >> 10) & 1;
j1 = (lower >> 13) & 1;
j2 = (lower >> 11) & 1;
offset = sign_extend32((sign << 24) |
((~(j1 ^ sign) & 1) << 23) |
((~(j2 ^ sign) & 1) << 22) |
((upper & 0x03ff) << 12) |
((lower & 0x07ff) << 1),
24);
r->r_addend = offset + sym->st_value + 4;
break;
default:
return 1;
r->r_addend = (Elf_Addr)(-1);
}
return 0;
}
static int addend_mips_rel(struct elf_info *elf, Elf_Shdr *sechdr, Elf_Rela *r)
static int addend_mips_rel(uint32_t *location, Elf_Rela *r)
{
unsigned int r_typ = ELF_R_TYPE(r->r_info);
unsigned int *location = reloc_location(elf, sechdr, r);
unsigned int inst;
uint32_t inst;
if (r_typ == R_MIPS_HI16)
return 1; /* skip this */
inst = TO_NATIVE(*location);
switch (r_typ) {
case R_MIPS_LO16:
......@@ -1503,6 +1422,8 @@ static int addend_mips_rel(struct elf_info *elf, Elf_Shdr *sechdr, Elf_Rela *r)
case R_MIPS_32:
r->r_addend = inst;
break;
default:
r->r_addend = (Elf_Addr)(-1);
}
return 0;
}
......@@ -1523,19 +1444,17 @@ static int addend_mips_rel(struct elf_info *elf, Elf_Shdr *sechdr, Elf_Rela *r)
#define R_LARCH_SUB32 55
#endif
static void section_rela(const char *modname, struct elf_info *elf,
static void section_rela(struct module *mod, struct elf_info *elf,
Elf_Shdr *sechdr)
{
Elf_Sym *sym;
Elf_Rela *rela;
Elf_Rela r;
unsigned int r_sym;
const char *fromsec;
unsigned int fsecndx = sechdr->sh_info;
const char *fromsec = sec_name(elf, fsecndx);
Elf_Rela *start = (void *)elf->hdr + sechdr->sh_offset;
Elf_Rela *stop = (void *)start + sechdr->sh_size;
fromsec = sec_name(elf, sechdr->sh_info);
/* if from section (name) is know good then skip it */
if (match(fromsec, section_white_list))
return;
......@@ -1570,34 +1489,31 @@ static void section_rela(const char *modname, struct elf_info *elf,
continue;
break;
}
sym = elf->symtab_start + r_sym;
/* Skip special sections */
if (is_shndx_special(sym->st_shndx))
continue;
if (is_second_extable_reloc(start, rela, fromsec))
find_extable_entry_size(fromsec, &r);
check_section_mismatch(modname, elf, &r, sym, fromsec);
check_section_mismatch(mod, elf, elf->symtab_start + r_sym,
fsecndx, fromsec, r.r_offset, r.r_addend);
}
}
static void section_rel(const char *modname, struct elf_info *elf,
static void section_rel(struct module *mod, struct elf_info *elf,
Elf_Shdr *sechdr)
{
Elf_Sym *sym;
Elf_Rel *rel;
Elf_Rela r;
unsigned int r_sym;
const char *fromsec;
unsigned int fsecndx = sechdr->sh_info;
const char *fromsec = sec_name(elf, fsecndx);
Elf_Rel *start = (void *)elf->hdr + sechdr->sh_offset;
Elf_Rel *stop = (void *)start + sechdr->sh_size;
fromsec = sec_name(elf, sechdr->sh_info);
/* if from section (name) is know good then skip it */
if (match(fromsec, section_white_list))
return;
for (rel = start; rel < stop; rel++) {
Elf_Sym *tsym;
void *loc;
r.r_offset = TO_NATIVE(rel->r_offset);
#if KERNEL_ELFCLASS == ELFCLASS64
if (elf->hdr->e_machine == EM_MIPS) {
......@@ -1615,27 +1531,26 @@ static void section_rel(const char *modname, struct elf_info *elf,
r_sym = ELF_R_SYM(r.r_info);
#endif
r.r_addend = 0;
loc = sym_get_data_by_offset(elf, fsecndx, r.r_offset);
tsym = elf->symtab_start + r_sym;
switch (elf->hdr->e_machine) {
case EM_386:
if (addend_386_rel(elf, sechdr, &r))
continue;
addend_386_rel(loc, &r);
break;
case EM_ARM:
if (addend_arm_rel(elf, sechdr, &r))
continue;
addend_arm_rel(loc, tsym, &r);
break;
case EM_MIPS:
if (addend_mips_rel(elf, sechdr, &r))
continue;
addend_mips_rel(loc, &r);
break;
default:
fatal("Please add code to calculate addend for this architecture\n");
}
sym = elf->symtab_start + r_sym;
/* Skip special sections */
if (is_shndx_special(sym->st_shndx))
continue;
if (is_second_extable_reloc(start, rel, fromsec))
find_extable_entry_size(fromsec, &r);
check_section_mismatch(modname, elf, &r, sym, fromsec);
check_section_mismatch(mod, elf, tsym,
fsecndx, fromsec, r.r_offset, r.r_addend);
}
}
......@@ -1651,19 +1566,19 @@ static void section_rel(const char *modname, struct elf_info *elf,
* to find all references to a section that reference a section that will
* be discarded and warns about it.
**/
static void check_sec_ref(const char *modname, struct elf_info *elf)
static void check_sec_ref(struct module *mod, struct elf_info *elf)
{
int i;
Elf_Shdr *sechdrs = elf->sechdrs;
/* Walk through all sections */
for (i = 0; i < elf->num_sections; i++) {
check_section(modname, elf, &elf->sechdrs[i]);
check_section(mod->name, elf, &elf->sechdrs[i]);
/* We want to process only relocation sections and not .init */
if (sechdrs[i].sh_type == SHT_RELA)
section_rela(modname, elf, &elf->sechdrs[i]);
section_rela(mod, elf, &elf->sechdrs[i]);
else if (sechdrs[i].sh_type == SHT_REL)
section_rel(modname, elf, &elf->sechdrs[i]);
section_rel(mod, elf, &elf->sechdrs[i]);
}
}
......@@ -1818,6 +1733,8 @@ static void read_symbols(const char *modname)
}
}
if (extra_warn && !get_modinfo(&info, "description"))
warn("missing MODULE_DESCRIPTION() in %s\n", modname);
for (sym = info.symtab_start; sym < info.symtab_stop; sym++) {
symname = remove_dot(info.strtab + sym->st_name);
......@@ -1825,16 +1742,7 @@ static void read_symbols(const char *modname)
handle_moddevtable(mod, &info, sym, symname);
}
for (sym = info.symtab_start; sym < info.symtab_stop; sym++) {
symname = remove_dot(info.strtab + sym->st_name);
/* Apply symbol namespaces from __kstrtabns_<symbol> entries. */
if (strstarts(symname, "__kstrtabns_"))
sym_update_namespace(symname + strlen("__kstrtabns_"),
sym_get_data(&info, sym));
}
check_sec_ref(modname, &info);
check_sec_ref(mod, &info);
if (!mod->is_vmlinux) {
version = get_modinfo(&info, "version");
......@@ -1925,6 +1833,7 @@ static void check_exports(struct module *mod)
continue;
}
exp->used = true;
s->module = exp->module;
s->crc_valid = exp->crc_valid;
s->crc = exp->crc;
......@@ -1935,8 +1844,7 @@ static void check_exports(struct module *mod)
else
basename = mod->name;
if (exp->namespace &&
!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,
"module %s uses symbol %s from namespace %s, but does not import it.\n",
basename, exp->name, exp->namespace);
......@@ -1949,6 +1857,23 @@ static void check_exports(struct module *mod)
}
}
static void handle_white_list_exports(const char *white_list)
{
char *buf, *p, *name;
buf = read_text_file(white_list);
p = buf;
while ((name = strsep(&p, "\n"))) {
struct symbol *sym = find_symbol(name);
if (sym)
sym->used = true;
}
free(buf);
}
static void check_modname_len(struct module *mod)
{
const char *mod_name;
......@@ -2022,12 +1947,26 @@ static void add_exported_symbols(struct buffer *buf, struct module *mod)
{
struct symbol *sym;
/* generate struct for exported symbols */
buf_printf(buf, "\n");
list_for_each_entry(sym, &mod->exported_symbols, list) {
if (trim_unused_exports && !sym->used)
continue;
buf_printf(buf, "KSYMTAB_%s(%s, \"%s\", \"%s\");\n",
sym->is_func ? "FUNC" : "DATA", sym->name,
sym->is_gpl_only ? "_gpl" : "", sym->namespace);
}
if (!modversions)
return;
/* record CRCs for exported symbols */
buf_printf(buf, "\n");
list_for_each_entry(sym, &mod->exported_symbols, list) {
if (trim_unused_exports && !sym->used)
continue;
if (!sym->crc_valid)
warn("EXPORT symbol \"%s\" [%s%s] version generation failed, symbol will not be versioned.\n"
"Is \"%s\" prototyped in <asm/asm-prototypes.h>?\n",
......@@ -2191,9 +2130,6 @@ static void write_mod_c_file(struct module *mod)
char fname[PATH_MAX];
int ret;
check_modname_len(mod);
check_exports(mod);
add_header(&buf, mod);
add_exported_symbols(&buf, mod);
add_versions(&buf, mod);
......@@ -2265,9 +2201,8 @@ static void read_dump(const char *fname)
mod = new_module(modname, strlen(modname));
mod->from_dump = true;
}
s = sym_add_exported(symname, mod, gpl_only);
s = sym_add_exported(symname, mod, gpl_only, namespace);
sym_set_crc(s, crc);
sym_update_namespace(symname, namespace);
}
free(buf);
return;
......@@ -2286,10 +2221,13 @@ static void write_dump(const char *fname)
if (mod->from_dump)
continue;
list_for_each_entry(sym, &mod->exported_symbols, list) {
if (trim_unused_exports && !sym->used)
continue;
buf_printf(&buf, "0x%08x\t%s\t%s\tEXPORT_SYMBOL%s\t%s\n",
sym->crc, sym->name, mod->name,
sym->is_gpl_only ? "_GPL" : "",
sym->namespace ?: "");
sym->namespace);
}
}
write_buf(&buf, fname);
......@@ -2328,12 +2266,13 @@ int main(int argc, char **argv)
{
struct module *mod;
char *missing_namespace_deps = NULL;
char *unused_exports_white_list = NULL;
char *dump_write = NULL, *files_source = NULL;
int opt;
LIST_HEAD(dump_lists);
struct dump_list *dl, *dl2;
while ((opt = getopt(argc, argv, "ei:mnT:o:awENd:")) != -1) {
while ((opt = getopt(argc, argv, "ei:mnT:to:au:WwENd:")) != -1) {
switch (opt) {
case 'e':
external_module = true;
......@@ -2358,6 +2297,15 @@ int main(int argc, char **argv)
case 'T':
files_source = optarg;
break;
case 't':
trim_unused_exports = true;
break;
case 'u':
unused_exports_white_list = optarg;
break;
case 'W':
extra_warn = true;
break;
case 'w':
warn_unresolved = true;
break;
......@@ -2387,6 +2335,17 @@ int main(int argc, char **argv)
if (files_source)
read_symbols_from_files(files_source);
list_for_each_entry(mod, &modules, list) {
if (mod->from_dump || mod->is_vmlinux)
continue;
check_modname_len(mod);
check_exports(mod);
}
if (unused_exports_white_list)
handle_white_list_exports(unused_exports_white_list);
list_for_each_entry(mod, &modules, list) {
if (mod->from_dump)
continue;
......
......@@ -137,6 +137,7 @@ struct elf_info {
Elf_Shdr *sechdrs;
Elf_Sym *symtab_start;
Elf_Sym *symtab_stop;
unsigned int export_symbol_secndx; /* .export_symbol section */
char *strtab;
char *modinfo;
unsigned int modinfo_len;
......@@ -151,11 +152,6 @@ struct elf_info {
Elf32_Word *symtab_shndx_stop;
};
static inline int is_shndx_special(unsigned int i)
{
return i != SHN_XINDEX && i >= SHN_LORESERVE && i <= SHN_HIRESERVE;
}
/* Accessor for sym->st_shndx, hides ugliness of "64k sections" */
static inline unsigned int get_secindex(const struct elf_info *info,
const Elf_Sym *sym)
......
......@@ -62,18 +62,14 @@ install_linux_image () {
${MAKE} -f ${srctree}/Makefile INSTALL_DTBS_PATH="${pdir}/usr/lib/linux-image-${KERNELRELEASE}" dtbs_install
fi
if is_enabled CONFIG_MODULES; then
${MAKE} -f ${srctree}/Makefile INSTALL_MOD_PATH="${pdir}" modules_install
rm -f "${pdir}/lib/modules/${KERNELRELEASE}/build"
rm -f "${pdir}/lib/modules/${KERNELRELEASE}/source"
if [ "${SRCARCH}" = um ] ; then
mkdir -p "${pdir}/usr/lib/uml/modules"
mv "${pdir}/lib/modules/${KERNELRELEASE}" "${pdir}/usr/lib/uml/modules/${KERNELRELEASE}"
fi
fi
${MAKE} -f ${srctree}/Makefile INSTALL_MOD_PATH="${pdir}" modules_install
rm -f "${pdir}/lib/modules/${KERNELRELEASE}/build"
rm -f "${pdir}/lib/modules/${KERNELRELEASE}/source"
# Install the kernel
if [ "${ARCH}" = um ] ; then
mkdir -p "${pdir}/usr/lib/uml/modules"
mv "${pdir}/lib/modules/${KERNELRELEASE}" "${pdir}/usr/lib/uml/modules/${KERNELRELEASE}"
mkdir -p "${pdir}/usr/bin" "${pdir}/usr/share/doc/${pname}"
cp System.map "${pdir}/usr/lib/uml/modules/${KERNELRELEASE}/System.map"
cp ${KCONFIG_CONFIG} "${pdir}/usr/share/doc/${pname}/config"
......
......@@ -33,3 +33,7 @@ rm -f rust/target.json
rm -f scripts/bin2c
rm -f .scmversion
rm -rf include/ksym
find . -name '*.usyms' | xargs rm -f
......@@ -32,6 +32,13 @@ else
tree=${srctree}/
fi
# gtags(1) refuses to index any file outside of its current working dir.
# If gtags indexing is requested and the build output directory is not
# the kernel source tree, index all files in absolute-path form.
if [[ "$1" == "gtags" && -n "${tree}" ]]; then
tree=$(realpath "$tree")/
fi
# Detect if ALLSOURCE_ARCHS is set. If not, we assume SRCARCH
if [ "${ALLSOURCE_ARCHS}" = "" ]; then
ALLSOURCE_ARCHS=${SRCARCH}
......@@ -131,7 +138,7 @@ docscope()
dogtags()
{
all_target_sources | gtags -i -f -
all_target_sources | gtags -i -C "${tree:-.}" -f - "$PWD"
}
# Basic regular expressions with an optional /kind-spec/ for ctags and
......
......@@ -64,6 +64,7 @@ quiet_cmd_initfs = GEN $@
$(CONFIG_SHELL) $< -o $@ -l $(obj)/.initramfs_data.cpio.d \
$(if $(CONFIG_INITRAMFS_ROOT_UID), -u $(CONFIG_INITRAMFS_ROOT_UID)) \
$(if $(CONFIG_INITRAMFS_ROOT_GID), -g $(CONFIG_INITRAMFS_ROOT_GID)) \
$(if $(KBUILD_BUILD_TIMESTAMP), -d "$(KBUILD_BUILD_TIMESTAMP)") \
$(ramfs-input)
# We rebuild initramfs_data.cpio if:
......
......@@ -23,6 +23,7 @@ $0 [-o <file>] [-l <dep_list>] [-u <uid>] [-g <gid>] {-d | <cpio_source>} ...
-g <gid> Group ID to map to group ID 0 (root).
<gid> is only meaningful if <cpio_source> is a
directory. "squash" forces all files to gid 0.
-d <date> Use date for all file mtime values
<cpio_source> File list or directory for cpio archive.
If <cpio_source> is a .cpio file it will be used
as direct input to initramfs.
......@@ -190,6 +191,7 @@ prog=$0
root_uid=0
root_gid=0
dep_list=
timestamp=
cpio_list=$(mktemp ${TMPDIR:-/tmp}/cpiolist.XXXXXX)
output="/dev/stdout"
......@@ -218,6 +220,13 @@ while [ $# -gt 0 ]; do
[ "$root_gid" = "-1" ] && root_gid=$(id -g || echo 0)
shift
;;
"-d") # date for file mtimes
timestamp="$(date -d"$1" +%s || :)"
if test -n "$timestamp"; then
timestamp="-t $timestamp"
fi
shift
;;
"-h")
usage
exit 0
......@@ -237,11 +246,4 @@ done
# If output_file is set we will generate cpio archive
# we are careful to delete tmp files
timestamp=
if test -n "$KBUILD_BUILD_TIMESTAMP"; then
timestamp="$(date -d"$KBUILD_BUILD_TIMESTAMP" +%s || :)"
if test -n "$timestamp"; then
timestamp="-t $timestamp"
fi
fi
usr/gen_init_cpio $timestamp $cpio_list > $output
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