Merge tag 'kbuild-v6.5' of git://git.kernel.org/pub/scm/linux/kernel/git/masahiroy...
authorLinus Torvalds <torvalds@linux-foundation.org>
Sat, 1 Jul 2023 16:24:31 +0000 (09:24 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sat, 1 Jul 2023 16:24:31 +0000 (09:24 -0700)
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()
  ...

44 files changed:
.gitignore
Documentation/kbuild/kbuild.rst
Documentation/process/changes.rst
Makefile
arch/arc/include/asm/linkage.h
arch/ia64/include/asm/Kbuild
arch/ia64/include/asm/export.h [deleted file]
arch/ia64/kernel/head.S
arch/ia64/kernel/ivt.S
arch/mips/Makefile
arch/powerpc/kernel/vdso/Makefile
arch/um/os-Linux/user_syms.c
include/asm-generic/export.h
include/asm-generic/vmlinux.lds.h
include/linux/export-internal.h
include/linux/export.h
include/linux/pm.h
init/Makefile
kernel/gen_kheaders.sh
kernel/module/internal.h
scripts/Makefile.build
scripts/Makefile.clang
scripts/Makefile.clean
scripts/Makefile.compiler
scripts/Makefile.lib
scripts/Makefile.modfinal
scripts/Makefile.modpost
scripts/Makefile.vmlinux
scripts/adjust_autoksyms.sh [deleted file]
scripts/basic/fixdep.c
scripts/check-local-export [deleted file]
scripts/gen_autoksyms.sh [deleted file]
scripts/gen_ksymdeps.sh [deleted file]
scripts/kallsyms.c
scripts/kconfig/streamline_config.pl
scripts/kernel-doc
scripts/mksysmap
scripts/mod/modpost.c
scripts/mod/modpost.h
scripts/package/builddeb
scripts/remove-stale-files
scripts/tags.sh
usr/Makefile
usr/gen_initramfs.sh

index 7f86e08..c3ce78c 100644 (file)
@@ -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
index 2a22ddb..bd90640 100644 (file)
@@ -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.
index 5cf6a5f..5561dae 100644 (file)
@@ -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
 ****************
index 48a044b..7a5a175 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -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]' \
index c9434ff..8a3fb71 100644 (file)
@@ -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
 #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
index aefae2e..3373324 100644 (file)
@@ -1,6 +1,7 @@
 # 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
diff --git a/arch/ia64/include/asm/export.h b/arch/ia64/include/asm/export.h
deleted file mode 100644 (file)
index ad18c65..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-/* EXPORT_DATA_SYMBOL != EXPORT_SYMBOL here */
-#define KSYM_FUNC(name) @fptr(name)
-#include <asm-generic/export.h>
index f22469f..c096500 100644 (file)
@@ -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
 
index d6d4229..7a418e3 100644 (file)
@@ -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)
index a7a4ee6..ef7b05a 100644 (file)
@@ -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
index 23ee961..0c7d82c 100644 (file)
@@ -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)
 
index 9b62a9d..a310ae2 100644 (file)
@@ -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);
index 5e4b1f2..570cd4d 100644 (file)
@@ -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
index da9e562..45401f7 100644 (file)
        PATCHABLE_DISCARDS                                              \
        *(.discard)                                                     \
        *(.discard.*)                                                   \
+       *(.export_symbol)                                               \
        *(.modinfo)                                                     \
        /* ld.bfd warns about .gnu.version* even when not emitted */    \
        *(.gnu.version*)                                                \
index fe7e6ba..1c849db 100644 (file)
 #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" \
index 3f31ced..beed838 100644 (file)
@@ -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 */
index 035d964..badad7d 100644 (file)
@@ -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
index 26de459..ec557ad 100644 (file)
@@ -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
index 1ef9a87..6d443ea 100755 (executable)
@@ -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
index dc7b016..c8b7b4d 100644 (file)
 /* 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;
 
index 7817523..6413342 100644 (file)
@@ -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) $@
index 9a0aebf..6c23c6a 100644 (file)
@@ -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
index 3649900..f2cb4d7 100644 (file)
@@ -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)),)
index 1279c5f..8fcb427 100644 (file)
@@ -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)
index 100a386..68d0134 100644 (file)
@@ -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)
 
index 4703f65..fc19f67 100644 (file)
@@ -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)
index 0980c58..39472e8 100644 (file)
@@ -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
index 10176de..3cd6ca1 100644 (file)
@@ -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
diff --git a/scripts/adjust_autoksyms.sh b/scripts/adjust_autoksyms.sh
deleted file mode 100755 (executable)
index f1b5ac8..0000000
+++ /dev/null
@@ -1,73 +0,0 @@
-#!/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
index fa56280..84b6efa 100644 (file)
@@ -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 */
diff --git a/scripts/check-local-export b/scripts/check-local-export
deleted file mode 100755 (executable)
index f90b5a9..0000000
+++ /dev/null
@@ -1,70 +0,0 @@
-#!/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 $?
diff --git a/scripts/gen_autoksyms.sh b/scripts/gen_autoksyms.sh
deleted file mode 100755 (executable)
index 12bcfae..0000000
+++ /dev/null
@@ -1,62 +0,0 @@
-#!/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"
diff --git a/scripts/gen_ksymdeps.sh b/scripts/gen_ksymdeps.sh
deleted file mode 100755 (executable)
index 8ee533f..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-#!/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):"
index 0d2db41..d387c93 100644 (file)
@@ -19,6 +19,7 @@
  *
  */
 
+#include <errno.h>
 #include <getopt.h>
 #include <stdbool.h>
 #include <stdio.h>
 
 #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},
index 3387ad7..d51cd7a 100755 (executable)
@@ -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;
 
index eb70c1f..8c392fb 100755 (executable)
@@ -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);
index cb3b1ff..9ba1c9d 100755 (executable)
@@ -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
index c12150f..b29b297 100644 (file)
@@ -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;
@@ -2388,6 +2336,17 @@ int main(int argc, char **argv)
                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;
 
index 1178f40..dfdb948 100644 (file)
@@ -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)
index 252faaa..032774e 100755 (executable)
@@ -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"
index 7f43290..f3659ea 100755 (executable)
@@ -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
index ea31640..f6b3c7c 100755 (executable)
@@ -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
index 59d9e8b..f8e1ad1 100644 (file)
@@ -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:
index 63476bb..14b5782 100755 (executable)
@@ -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