mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 02:30:34 +02:00 
			
		
		
		
	kbuild: generate KSYMTAB entries by modpost
Commit7b4537199a("kbuild: link symbol CRCs at final link, removing CONFIG_MODULE_REL_CRCS") made modpost output CRCs in the same way whether the EXPORT_SYMBOL() is placed in *.c or *.S. For further cleanups, this commit applies a similar approach to the entire data structure of EXPORT_SYMBOL(). The EXPORT_SYMBOL() compilation is split into two stages. When a source file is compiled, EXPORT_SYMBOL() will be converted into a dummy symbol in the .export_symbol section. For example, EXPORT_SYMBOL(foo); EXPORT_SYMBOL_NS_GPL(bar, BAR_NAMESPACE); will be encoded into the following assembly code: .section ".export_symbol","a" __export_symbol_foo: .asciz "" /* license */ .asciz "" /* name space */ .balign 8 .quad foo /* symbol reference */ .previous .section ".export_symbol","a" __export_symbol_bar: .asciz "GPL" /* license */ .asciz "BAR_NAMESPACE" /* name space */ .balign 8 .quad bar /* symbol reference */ .previous They are mere markers to tell modpost the name, license, and namespace of the symbols. They will be dropped from the final vmlinux and modules because the *(.export_symbol) will go into /DISCARD/ in the linker script. Then, modpost extracts all the information about EXPORT_SYMBOL() from the .export_symbol section, and generates the final C code: KSYMTAB_FUNC(foo, "", ""); KSYMTAB_FUNC(bar, "_gpl", "BAR_NAMESPACE"); KSYMTAB_FUNC() (or KSYMTAB_DATA() if it is data) is expanded to struct kernel_symbol that will be linked to the vmlinux or a module. With this change, EXPORT_SYMBOL() works in the same way for *.c and *.S files, providing the following benefits. [1] Deprecate EXPORT_DATA_SYMBOL() In the old days, EXPORT_SYMBOL() was only available in C files. To export a symbol in *.S, EXPORT_SYMBOL() was placed in a separate *.c file. arch/arm/kernel/armksyms.c is one example written in the classic manner. Commit22823ab419("EXPORT_SYMBOL() for asm") removed this limitation. Since then, EXPORT_SYMBOL() can be placed close to the symbol definition in *.S files. It was a nice improvement. However, as that commit mentioned, you need to use EXPORT_DATA_SYMBOL() for data objects on some architectures. In the new approach, modpost checks symbol's type (STT_FUNC or not), and outputs KSYMTAB_FUNC() or KSYMTAB_DATA() accordingly. There are only two users of EXPORT_DATA_SYMBOL: EXPORT_DATA_SYMBOL_GPL(empty_zero_page) (arch/ia64/kernel/head.S) EXPORT_DATA_SYMBOL(ia64_ivt) (arch/ia64/kernel/ivt.S) They are transformed as follows and output into .vmlinux.export.c KSYMTAB_DATA(empty_zero_page, "_gpl", ""); KSYMTAB_DATA(ia64_ivt, "", ""); The other EXPORT_SYMBOL users in ia64 assembly are output as KSYMTAB_FUNC(). EXPORT_DATA_SYMBOL() is now deprecated. [2] merge <linux/export.h> and <asm-generic/export.h> There are two similar header implementations: include/linux/export.h for .c files include/asm-generic/export.h for .S files Ideally, the functionality should be consistent between them, but they tend to diverge. Commit8651ec01da("module: add support for symbol namespaces.") did not support the namespace for *.S files. This commit shifts the essential implementation part to C, which supports EXPORT_SYMBOL_NS() for *.S files. <asm/export.h> and <asm-generic/export.h> will remain as a wrapper of <linux/export.h> for a while. They will be removed after #include <asm/export.h> directives are all replaced with #include <linux/export.h>. [3] Implement CONFIG_TRIM_UNUSED_KSYMS in one-pass algorithm (by a later commit) When CONFIG_TRIM_UNUSED_KSYMS is enabled, Kbuild recursively traverses the directory tree to determine which EXPORT_SYMBOL to trim. If an EXPORT_SYMBOL turns out to be unused by anyone, Kbuild begins the second traverse, where some source files are recompiled with their EXPORT_SYMBOL() tuned into a no-op. We can do this better now; modpost can selectively emit KSYMTAB entries that are really used by modules. Signed-off-by: Masahiro Yamada <masahiroy@kernel.org> Reviewed-by: Nick Desaulniers <ndesaulniers@google.com>
This commit is contained in:
		
							parent
							
								
									94d6cb6812
								
							
						
					
					
						commit
						ddb5cdbafa
					
				
					 12 changed files with 190 additions and 184 deletions
				
			
		| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,3 +0,0 @@
 | 
			
		|||
/* EXPORT_DATA_SYMBOL != EXPORT_SYMBOL here */
 | 
			
		||||
#define KSYM_FUNC(name) @fptr(name)
 | 
			
		||||
#include <asm-generic/export.h>
 | 
			
		||||
| 
						 | 
				
			
			@ -3,86 +3,12 @@
 | 
			
		|||
#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.
 | 
			
		||||
 */
 | 
			
		||||
#include <linux/export.h>
 | 
			
		||||
 | 
			
		||||
#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)
 | 
			
		||||
#define EXPORT_DATA_SYMBOL(name)	EXPORT_SYMBOL(name)
 | 
			
		||||
#define EXPORT_DATA_SYMBOL_GPL(name)	EXPORT_SYMBOL_GPL(name)
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1006,6 +1006,7 @@
 | 
			
		|||
	PATCHABLE_DISCARDS						\
 | 
			
		||||
	*(.discard)							\
 | 
			
		||||
	*(.discard.*)							\
 | 
			
		||||
	*(.export_symbol)						\
 | 
			
		||||
	*(.modinfo)							\
 | 
			
		||||
	/* ld.bfd warns about .gnu.version* even when not emitted */	\
 | 
			
		||||
	*(.gnu.version*)						\
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -10,6 +10,55 @@
 | 
			
		|||
#include <linux/compiler.h>
 | 
			
		||||
#include <linux/types.h>
 | 
			
		||||
 | 
			
		||||
#if defined(CONFIG_HAVE_ARCH_PREL32_RELOCATIONS)
 | 
			
		||||
/*
 | 
			
		||||
 * relative reference: this reduces the size by half on 64-bit architectures,
 | 
			
		||||
 * and eliminates the need for absolute relocations that require runtime
 | 
			
		||||
 * processing on relocatable kernels.
 | 
			
		||||
 */
 | 
			
		||||
#define __KSYM_REF(sym)		".long " #sym "- ."
 | 
			
		||||
#elif defined(CONFIG_64BIT)
 | 
			
		||||
#define __KSYM_REF(sym)		".quad " #sym
 | 
			
		||||
#else
 | 
			
		||||
#define __KSYM_REF(sym)		".long " #sym
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * For every exported symbol, do the following:
 | 
			
		||||
 *
 | 
			
		||||
 * - Put the name of the symbol and namespace (empty string "" for none) in
 | 
			
		||||
 *   __ksymtab_strings.
 | 
			
		||||
 * - Place a struct kernel_symbol entry in the __ksymtab section.
 | 
			
		||||
 *
 | 
			
		||||
 * Note on .section use: we specify progbits since usage of the "M" (SHF_MERGE)
 | 
			
		||||
 * section flag requires it. Use '%progbits' instead of '@progbits' since the
 | 
			
		||||
 * former apparently works on all arches according to the binutils source.
 | 
			
		||||
 */
 | 
			
		||||
#define __KSYMTAB(name, sym, sec, ns)						\
 | 
			
		||||
	asm("	.section \"__ksymtab_strings\",\"aMS\",%progbits,1"	"\n"	\
 | 
			
		||||
	    "__kstrtab_" #name ":"					"\n"	\
 | 
			
		||||
	    "	.asciz \"" #name "\""					"\n"	\
 | 
			
		||||
	    "__kstrtabns_" #name ":"					"\n"	\
 | 
			
		||||
	    "	.asciz \"" ns "\""					"\n"	\
 | 
			
		||||
	    "	.previous"						"\n"	\
 | 
			
		||||
	    "	.section \"___ksymtab" sec "+" #name "\", \"a\""	"\n"	\
 | 
			
		||||
	    "	.balign	4"						"\n"	\
 | 
			
		||||
	    "__ksymtab_" #name ":"					"\n"	\
 | 
			
		||||
		__KSYM_REF(sym)						"\n"	\
 | 
			
		||||
		__KSYM_REF(__kstrtab_ ##name)				"\n"	\
 | 
			
		||||
		__KSYM_REF(__kstrtabns_ ##name)				"\n"	\
 | 
			
		||||
	    "	.previous"						"\n"	\
 | 
			
		||||
	)
 | 
			
		||||
 | 
			
		||||
#ifdef CONFIG_IA64
 | 
			
		||||
#define KSYM_FUNC(name)		@fptr(name)
 | 
			
		||||
#else
 | 
			
		||||
#define KSYM_FUNC(name)		name
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#define KSYMTAB_FUNC(name, sec, ns)	__KSYMTAB(name, KSYM_FUNC(name), sec, ns)
 | 
			
		||||
#define KSYMTAB_DATA(name, sec, ns)	__KSYMTAB(name, name, sec, ns)
 | 
			
		||||
 | 
			
		||||
#define SYMBOL_CRC(sym, crc, sec)   \
 | 
			
		||||
	asm(".section \"___kcrctab" sec "+" #sym "\",\"a\""	"\n" \
 | 
			
		||||
	    "__crc_" #sym ":"					"\n" \
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2,6 +2,8 @@
 | 
			
		|||
#ifndef _LINUX_EXPORT_H
 | 
			
		||||
#define _LINUX_EXPORT_H
 | 
			
		||||
 | 
			
		||||
#include <linux/compiler.h>
 | 
			
		||||
#include <linux/linkage.h>
 | 
			
		||||
#include <linux/stringify.h>
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
| 
						 | 
				
			
			@ -28,72 +30,41 @@ 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
 | 
			
		||||
 | 
			
		||||
#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
 | 
			
		||||
 | 
			
		||||
#ifdef __GENKSYMS__
 | 
			
		||||
 | 
			
		||||
#define ___EXPORT_SYMBOL(sym, sec, ns)	__GENKSYMS_EXPORT_SYMBOL(sym)
 | 
			
		||||
 | 
			
		||||
#elif defined(__ASSEMBLY__)
 | 
			
		||||
 | 
			
		||||
#define ___EXPORT_SYMBOL(sym, license, ns) \
 | 
			
		||||
	____EXPORT_SYMBOL(sym, license, ns)
 | 
			
		||||
 | 
			
		||||
#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)
 | 
			
		||||
#define ___EXPORT_SYMBOL(sym, license, ns)			\
 | 
			
		||||
	extern typeof(sym) sym;					\
 | 
			
		||||
	__ADDRESSABLE(sym)					\
 | 
			
		||||
	asm(__stringify(____EXPORT_SYMBOL(sym, license, ns)))
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -117,9 +88,21 @@ struct kernel_symbol {
 | 
			
		|||
 * from the $(NM) output (see scripts/gen_ksymdeps.sh). These symbols are
 | 
			
		||||
 * discarded in the final link stage.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifdef __ASSEMBLY__
 | 
			
		||||
 | 
			
		||||
#define __ksym_marker(sym)					\
 | 
			
		||||
	.section ".discard.ksym","a" ;				\
 | 
			
		||||
__ksym_marker_##sym: ;						\
 | 
			
		||||
	.previous
 | 
			
		||||
 | 
			
		||||
#else
 | 
			
		||||
 | 
			
		||||
#define __ksym_marker(sym)	\
 | 
			
		||||
	static int __ksym_marker_##sym[0] __section(".discard.ksym") __used
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#define __EXPORT_SYMBOL(sym, sec, ns)					\
 | 
			
		||||
	__ksym_marker(sym);						\
 | 
			
		||||
	__cond_export_sym(sym, sec, ns, __is_defined(__KSYM_##sym))
 | 
			
		||||
| 
						 | 
				
			
			@ -148,10 +131,8 @@ struct kernel_symbol {
 | 
			
		|||
#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 */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -389,9 +389,9 @@ const struct dev_pm_ops name = { \
 | 
			
		|||
#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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -32,6 +32,18 @@
 | 
			
		|||
/* Maximum number of characters written by module_flags() */
 | 
			
		||||
#define MODULE_FLAGS_BUF_SIZE (TAINT_FLAGS_COUNT + 4)
 | 
			
		||||
 | 
			
		||||
struct kernel_symbol {
 | 
			
		||||
#ifdef CONFIG_HAVE_ARCH_PREL32_RELOCATIONS
 | 
			
		||||
	int value_offset;
 | 
			
		||||
	int name_offset;
 | 
			
		||||
	int namespace_offset;
 | 
			
		||||
#else
 | 
			
		||||
	unsigned long value;
 | 
			
		||||
	const char *name;
 | 
			
		||||
	const char *namespace;
 | 
			
		||||
#endif
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
extern struct mutex module_mutex;
 | 
			
		||||
extern struct list_head modules;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -163,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.
 | 
			
		||||
| 
						 | 
				
			
			@ -171,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
 | 
			
		||||
| 
						 | 
				
			
			@ -342,9 +342,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) $@
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -46,9 +46,9 @@ BEGIN {
 | 
			
		|||
{ symbol_types[$3]=$2 }
 | 
			
		||||
 | 
			
		||||
# append the exported symbol to the array
 | 
			
		||||
($3 ~ /^__ksymtab_/) {
 | 
			
		||||
($3 ~ /^__export_symbol_.*/) {
 | 
			
		||||
	export_symbols[i] = $3
 | 
			
		||||
	sub(/^__ksymtab_/, "", export_symbols[i])
 | 
			
		||||
	sub(/^__export_symbol_/, "", export_symbols[i])
 | 
			
		||||
	i++
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -217,6 +217,7 @@ struct symbol {
 | 
			
		|||
	unsigned int crc;
 | 
			
		||||
	bool crc_valid;
 | 
			
		||||
	bool weak;
 | 
			
		||||
	bool is_func;
 | 
			
		||||
	bool is_gpl_only;	/* exported by EXPORT_SYMBOL_GPL */
 | 
			
		||||
	char name[];
 | 
			
		||||
};
 | 
			
		||||
| 
						 | 
				
			
			@ -533,6 +534,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) {
 | 
			
		||||
| 
						 | 
				
			
			@ -655,18 +658,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)
 | 
			
		||||
| 
						 | 
				
			
			@ -848,7 +839,6 @@ enum mismatch {
 | 
			
		|||
	XXXEXIT_TO_SOME_EXIT,
 | 
			
		||||
	ANY_INIT_TO_ANY_EXIT,
 | 
			
		||||
	ANY_EXIT_TO_ANY_INIT,
 | 
			
		||||
	EXPORT_TO_INIT_EXIT,
 | 
			
		||||
	EXTABLE_TO_NON_TEXT,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -920,12 +910,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
 | 
			
		||||
| 
						 | 
				
			
			@ -1180,10 +1164,6 @@ static void default_mismatch_handler(const char *modname, struct elf_info *elf,
 | 
			
		|||
		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:
 | 
			
		||||
		warn("%s(%s+0x%lx): Section mismatch in reference to the %s:%s\n",
 | 
			
		||||
		     modname, fromsec, (long)faddr, tosec, tosym);
 | 
			
		||||
| 
						 | 
				
			
			@ -1211,14 +1191,75 @@ static void default_mismatch_handler(const char *modname, struct elf_info *elf,
 | 
			
		|||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void check_export_symbol(struct module *mod, struct elf_info *elf,
 | 
			
		||||
				Elf_Addr faddr, const char *secname,
 | 
			
		||||
				Elf_Sym *sym)
 | 
			
		||||
{
 | 
			
		||||
	static const char *prefix = "__export_symbol_";
 | 
			
		||||
	const char *label_name, *name, *data;
 | 
			
		||||
	Elf_Sym *label;
 | 
			
		||||
	struct symbol *s;
 | 
			
		||||
	bool is_gpl;
 | 
			
		||||
 | 
			
		||||
	label = find_fromsym(elf, faddr, elf->export_symbol_secndx);
 | 
			
		||||
	label_name = sym_name(elf, label);
 | 
			
		||||
 | 
			
		||||
	if (!strstarts(label_name, prefix)) {
 | 
			
		||||
		error("%s: .export_symbol section contains strange symbol '%s'\n",
 | 
			
		||||
		      mod->name, label_name);
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	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;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	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);
 | 
			
		||||
	sym_update_namespace(name, 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(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 (elf->export_symbol_secndx == fsecndx) {
 | 
			
		||||
		check_export_symbol(mod, elf, faddr, tosec, sym);
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	mismatch = section_mismatch(fromsec, tosec);
 | 
			
		||||
	if (!mismatch)
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1698,15 +1739,6 @@ 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(mod, &info);
 | 
			
		||||
 | 
			
		||||
	if (!mod->is_vmlinux) {
 | 
			
		||||
| 
						 | 
				
			
			@ -1890,6 +1922,14 @@ 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)
 | 
			
		||||
		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;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue