Commit 7b453719 authored by Masahiro Yamada's avatar Masahiro Yamada

kbuild: link symbol CRCs at final link, removing CONFIG_MODULE_REL_CRCS

include/{linux,asm-generic}/export.h defines a weak symbol, __crc_*
as a placeholder.

Genksyms writes the version CRCs into the linker script, which will be
used for filling the __crc_* symbols. The linker script format depends
on CONFIG_MODULE_REL_CRCS. If it is enabled, __crc_* holds the offset
to the reference of CRC.

It is time to get rid of this complexity.

Now that modpost parses text files (.*.cmd) to collect all the CRCs,
it can generate C code that will be linked to the vmlinux or modules.

Generate a new C file, .vmlinux.export.c, which contains the CRCs of
symbols exported by vmlinux. It is compiled and linked to vmlinux in
scripts/link-vmlinux.sh.

Put the CRCs of symbols exported by modules into the existing *.mod.c
files. No additional build step is needed for modules. As before,
*.mod.c are compiled and linked to *.ko in scripts/Makefile.modfinal.

No linker magic is used here. The new C implementation works in the
same way, whether CONFIG_RELOCATABLE is enabled or not.
CONFIG_MODULE_REL_CRCS is no longer needed.

Previously, Kbuild invoked additional $(LD) to update the CRCs in
objects, but this step is unneeded too.
Signed-off-by: default avatarMasahiro Yamada <masahiroy@kernel.org>
Tested-by: default avatarNathan Chancellor <nathan@kernel.org>
Tested-by: default avatarNicolas Schier <nicolas@fjasle.eu>
Reviewed-by: default avatarNicolas Schier <nicolas@fjasle.eu>
Tested-by: Sedat Dilek <sedat.dilek@gmail.com> # LLVM-14 (x86-64)
parent f292d875
# SPDX-License-Identifier: GPL-2.0 # SPDX-License-Identifier: GPL-2.0
generated-y += syscall_table.h generated-y += syscall_table.h
generic-y += export.h
generic-y += extable.h generic-y += extable.h
generic-y += kvm_para.h generic-y += kvm_para.h
generic-y += mcs_spinlock.h generic-y += mcs_spinlock.h
......
#define KCRC_ALIGN 2
#include <asm-generic/export.h>
...@@ -566,7 +566,6 @@ config RELOCATABLE ...@@ -566,7 +566,6 @@ config RELOCATABLE
bool "Build a relocatable kernel" bool "Build a relocatable kernel"
depends on PPC64 || (FLATMEM && (44x || FSL_BOOKE)) depends on PPC64 || (FLATMEM && (44x || FSL_BOOKE))
select NONSTATIC_KERNEL select NONSTATIC_KERNEL
select MODULE_REL_CRCS if MODVERSIONS
help help
This builds a kernel image that is capable of running at the This builds a kernel image that is capable of running at the
location the kernel is loaded at. For ppc32, there is no any location the kernel is loaded at. For ppc32, there is no any
......
...@@ -567,7 +567,6 @@ endchoice ...@@ -567,7 +567,6 @@ endchoice
config RELOCATABLE config RELOCATABLE
bool "Build a relocatable kernel" bool "Build a relocatable kernel"
select MODULE_REL_CRCS if MODVERSIONS
default y default y
help help
This builds a kernel image that retains relocation information This builds a kernel image that retains relocation information
......
...@@ -106,7 +106,6 @@ config LD_SCRIPT_DYN ...@@ -106,7 +106,6 @@ config LD_SCRIPT_DYN
bool bool
default y default y
depends on !LD_SCRIPT_STATIC depends on !LD_SCRIPT_STATIC
select MODULE_REL_CRCS if MODVERSIONS
config LD_SCRIPT_DYN_RPATH config LD_SCRIPT_DYN_RPATH
bool "set rpath in the binary" if EXPERT bool "set rpath in the binary" if EXPERT
......
...@@ -2,6 +2,14 @@ ...@@ -2,6 +2,14 @@
#ifndef __ASM_GENERIC_EXPORT_H #ifndef __ASM_GENERIC_EXPORT_H
#define __ASM_GENERIC_EXPORT_H #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.
*/
#ifndef KSYM_FUNC #ifndef KSYM_FUNC
#define KSYM_FUNC(x) x #define KSYM_FUNC(x) x
#endif #endif
...@@ -12,9 +20,6 @@ ...@@ -12,9 +20,6 @@
#else #else
#define KSYM_ALIGN 4 #define KSYM_ALIGN 4
#endif #endif
#ifndef KCRC_ALIGN
#define KCRC_ALIGN 4
#endif
.macro __put, val, name .macro __put, val, name
#ifdef CONFIG_HAVE_ARCH_PREL32_RELOCATIONS #ifdef CONFIG_HAVE_ARCH_PREL32_RELOCATIONS
...@@ -43,17 +48,6 @@ __ksymtab_\name: ...@@ -43,17 +48,6 @@ __ksymtab_\name:
__kstrtab_\name: __kstrtab_\name:
.asciz "\name" .asciz "\name"
.previous .previous
#ifdef CONFIG_MODVERSIONS
.section ___kcrctab\sec+\name,"a"
.balign KCRC_ALIGN
#if defined(CONFIG_MODULE_REL_CRCS)
.long __crc_\name - .
#else
.long __crc_\name
#endif
.weak __crc_\name
.previous
#endif
#endif #endif
.endm .endm
......
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Please do not include this explicitly.
* This is used by C files generated by modpost.
*/
#ifndef __LINUX_EXPORT_INTERNAL_H__
#define __LINUX_EXPORT_INTERNAL_H__
#include <linux/compiler.h>
#include <linux/types.h>
/* __used is needed to keep __crc_* for LTO */
#define SYMBOL_CRC(sym, crc, sec) \
u32 __section("___kcrctab" sec "+" #sym) __used __crc_##sym = crc
#endif /* __LINUX_EXPORT_INTERNAL_H__ */
...@@ -11,6 +11,14 @@ ...@@ -11,6 +11,14 @@
* hackers place grumpy comments in header files. * hackers place grumpy comments in header files.
*/ */
/*
* 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.
*/
#ifndef __ASSEMBLY__ #ifndef __ASSEMBLY__
#ifdef MODULE #ifdef MODULE
extern struct module __this_module; extern struct module __this_module;
...@@ -19,26 +27,6 @@ extern struct module __this_module; ...@@ -19,26 +27,6 @@ extern struct module __this_module;
#define THIS_MODULE ((struct module *)0) #define THIS_MODULE ((struct module *)0)
#endif #endif
#ifdef CONFIG_MODVERSIONS
/* Mark the CRC weak since genksyms apparently decides not to
* generate a checksums for some symbols */
#if defined(CONFIG_MODULE_REL_CRCS)
#define __CRC_SYMBOL(sym, sec) \
asm(" .section \"___kcrctab" sec "+" #sym "\", \"a\" \n" \
" .weak __crc_" #sym " \n" \
" .long __crc_" #sym " - . \n" \
" .previous \n")
#else
#define __CRC_SYMBOL(sym, sec) \
asm(" .section \"___kcrctab" sec "+" #sym "\", \"a\" \n" \
" .weak __crc_" #sym " \n" \
" .long __crc_" #sym " \n" \
" .previous \n")
#endif
#else
#define __CRC_SYMBOL(sym, sec)
#endif
#ifdef CONFIG_HAVE_ARCH_PREL32_RELOCATIONS #ifdef CONFIG_HAVE_ARCH_PREL32_RELOCATIONS
#include <linux/compiler.h> #include <linux/compiler.h>
/* /*
...@@ -85,7 +73,6 @@ struct kernel_symbol { ...@@ -85,7 +73,6 @@ struct kernel_symbol {
/* /*
* For every exported symbol, do the following: * For every exported symbol, do the following:
* *
* - If applicable, place a CRC entry in the __kcrctab section.
* - Put the name of the symbol and namespace (empty string "" for none) in * - Put the name of the symbol and namespace (empty string "" for none) in
* __ksymtab_strings. * __ksymtab_strings.
* - Place a struct kernel_symbol entry in the __ksymtab section. * - Place a struct kernel_symbol entry in the __ksymtab section.
...@@ -98,7 +85,6 @@ struct kernel_symbol { ...@@ -98,7 +85,6 @@ struct kernel_symbol {
extern typeof(sym) sym; \ extern typeof(sym) sym; \
extern const char __kstrtab_##sym[]; \ extern const char __kstrtab_##sym[]; \
extern const char __kstrtabns_##sym[]; \ extern const char __kstrtabns_##sym[]; \
__CRC_SYMBOL(sym, sec); \
asm(" .section \"__ksymtab_strings\",\"aMS\",%progbits,1 \n" \ asm(" .section \"__ksymtab_strings\",\"aMS\",%progbits,1 \n" \
"__kstrtab_" #sym ": \n" \ "__kstrtab_" #sym ": \n" \
" .asciz \"" #sym "\" \n" \ " .asciz \"" #sym "\" \n" \
......
...@@ -2136,10 +2136,6 @@ config ASM_MODVERSIONS ...@@ -2136,10 +2136,6 @@ config ASM_MODVERSIONS
assembly. This can be enabled only when the target architecture assembly. This can be enabled only when the target architecture
supports it. supports it.
config MODULE_REL_CRCS
bool
depends on MODVERSIONS
config MODULE_SRCVERSION_ALL config MODULE_SRCVERSION_ALL
bool "Source checksum for all modules" bool "Source checksum for all modules"
help help
......
...@@ -1231,11 +1231,6 @@ static int try_to_force_load(struct module *mod, const char *reason) ...@@ -1231,11 +1231,6 @@ static int try_to_force_load(struct module *mod, const char *reason)
#ifdef CONFIG_MODVERSIONS #ifdef CONFIG_MODVERSIONS
static u32 resolve_rel_crc(const s32 *crc)
{
return *(u32 *)((void *)crc + *crc);
}
static int check_version(const struct load_info *info, static int check_version(const struct load_info *info,
const char *symname, const char *symname,
struct module *mod, struct module *mod,
...@@ -1264,10 +1259,7 @@ static int check_version(const struct load_info *info, ...@@ -1264,10 +1259,7 @@ static int check_version(const struct load_info *info,
if (strcmp(versions[i].name, symname) != 0) if (strcmp(versions[i].name, symname) != 0)
continue; continue;
if (IS_ENABLED(CONFIG_MODULE_REL_CRCS)) crcval = *crc;
crcval = resolve_rel_crc(crc);
else
crcval = *crc;
if (versions[i].crc == crcval) if (versions[i].crc == crcval)
return 1; return 1;
pr_debug("Found checksum %X vs module %lX\n", pr_debug("Found checksum %X vs module %lX\n",
......
...@@ -128,7 +128,6 @@ $(obj)/%.i: $(src)/%.c FORCE ...@@ -128,7 +128,6 @@ $(obj)/%.i: $(src)/%.c FORCE
genksyms = scripts/genksyms/genksyms \ genksyms = scripts/genksyms/genksyms \
$(if $(1), -T $(2)) \ $(if $(1), -T $(2)) \
$(if $(CONFIG_MODULE_REL_CRCS), -R) \
$(if $(KBUILD_PRESERVE), -p) \ $(if $(KBUILD_PRESERVE), -p) \
-r $(or $(wildcard $(2:.symtypes=.symref)), /dev/null) -r $(or $(wildcard $(2:.symtypes=.symref)), /dev/null)
...@@ -162,19 +161,11 @@ ifdef CONFIG_MODVERSIONS ...@@ -162,19 +161,11 @@ ifdef CONFIG_MODVERSIONS
# o if <file>.o doesn't contain a __ksymtab version, i.e. does # o if <file>.o doesn't contain a __ksymtab version, i.e. does
# not export symbols, it's done. # not export symbols, it's done.
# o otherwise, we calculate symbol versions using the good old # o otherwise, we calculate symbol versions using the good old
# genksyms on the preprocessed source and postprocess them in a way # genksyms on the preprocessed source and dump them into the .cmd file.
# that they are usable as a linker script # o modpost will extract versions from that file and create *.c files that will
# o generate .tmp_<file>.o from <file>.o using the linker to # be compiled and linked to the kernel and/or modules.
# replace the unresolved symbols __crc_exported_symbol with
# the actual value of the checksum generated by genksyms
# o remove .tmp_<file>.o to <file>.o
# Generate .o.symversions files for each .o with exported symbols, and link these genksyms_format := __crc_\(.*\) = \(.*\);
# to the kernel and/or modules at the end.
genksyms_format_rel_crc := [^_]*__crc_\([^ ]*\) = \.; LONG(\([^)]*\)).*
genksyms_format_normal := __crc_\(.*\) = \(.*\);
genksyms_format := $(if $(CONFIG_MODULE_REL_CRCS),$(genksyms_format_rel_crc),$(genksyms_format_normal))
gen_symversions = \ gen_symversions = \
if $(NM) $@ 2>/dev/null | grep -q __ksymtab; then \ if $(NM) $@ 2>/dev/null | grep -q __ksymtab; then \
...@@ -188,12 +179,6 @@ gen_symversions = \ ...@@ -188,12 +179,6 @@ gen_symversions = \
cmd_gen_symversions_c = $(call gen_symversions,c) cmd_gen_symversions_c = $(call gen_symversions,c)
cmd_modversions = \
if [ -r $@.symversions ]; then \
$(LD) $(KBUILD_LDFLAGS) -r -o $(@D)/.tmp_$(@F) $@ \
-T $@.symversions; \
mv -f $(@D)/.tmp_$(@F) $@; \
fi
endif endif
ifdef CONFIG_FTRACE_MCOUNT_USE_RECORDMCOUNT ifdef CONFIG_FTRACE_MCOUNT_USE_RECORDMCOUNT
...@@ -273,7 +258,6 @@ define rule_cc_o_c ...@@ -273,7 +258,6 @@ define rule_cc_o_c
$(call cmd,checkdoc) $(call cmd,checkdoc)
$(call cmd,gen_objtooldep) $(call cmd,gen_objtooldep)
$(call cmd,gen_symversions_c) $(call cmd,gen_symversions_c)
$(if $(CONFIG_LTO_CLANG),,$(call cmd,modversions))
$(call cmd,record_mcount) $(call cmd,record_mcount)
endef endef
...@@ -282,7 +266,6 @@ define rule_as_o_S ...@@ -282,7 +266,6 @@ define rule_as_o_S
$(call cmd,gen_ksymdeps) $(call cmd,gen_ksymdeps)
$(call cmd,gen_objtooldep) $(call cmd,gen_objtooldep)
$(call cmd,gen_symversions_S) $(call cmd,gen_symversions_S)
$(call cmd,modversions)
endef endef
# Built-in and composite module parts # Built-in and composite module parts
...@@ -296,8 +279,6 @@ ifneq ($(CONFIG_LTO_CLANG)$(CONFIG_X86_KERNEL_IBT),) ...@@ -296,8 +279,6 @@ ifneq ($(CONFIG_LTO_CLANG)$(CONFIG_X86_KERNEL_IBT),)
quiet_cmd_cc_prelink_modules = LD [M] $@ quiet_cmd_cc_prelink_modules = LD [M] $@
cmd_cc_prelink_modules = \ cmd_cc_prelink_modules = \
$(LD) $(ld_flags) -r -o $@ \ $(LD) $(ld_flags) -r -o $@ \
$(shell [ -s $(@:.prelink.o=.o.symversions) ] && \
echo -T $(@:.prelink.o=.o.symversions)) \
--whole-archive $(filter-out FORCE,$^) \ --whole-archive $(filter-out FORCE,$^) \
$(cmd_objtool) $(cmd_objtool)
......
# SPDX-License-Identifier: GPL-2.0-only
include include/config/auto.conf
include $(srctree)/scripts/Kbuild.include
# for c_flags
include $(srctree)/scripts/Makefile.lib
quiet_cmd_cc_o_c = CC $@
cmd_cc_o_c = $(CC) $(c_flags) -c -o $@ $<
%.o: %.c FORCE
$(call if_changed_dep,cc_o_c)
targets := $(MAKECMDGOALS)
# Add FORCE to the prequisites of a target to force it to be always rebuilt.
# ---------------------------------------------------------------------------
PHONY += FORCE
FORCE:
# Read all saved command lines and dependencies for the $(targets) we
# may be building above, using $(if_changed{,_dep}). As an
# optimization, we don't need to read them if the target does not
# exist, we will rebuild anyway in that case.
existing-targets := $(wildcard $(sort $(targets)))
-include $(foreach f,$(existing-targets),$(dir $(f)).$(notdir $(f)).cmd)
.PHONY: $(PHONY)
...@@ -33,7 +33,7 @@ char *cur_filename; ...@@ -33,7 +33,7 @@ char *cur_filename;
int in_source_file; int in_source_file;
static int flag_debug, flag_dump_defs, flag_reference, flag_dump_types, static int flag_debug, flag_dump_defs, flag_reference, flag_dump_types,
flag_preserve, flag_warnings, flag_rel_crcs; flag_preserve, flag_warnings;
static int errors; static int errors;
static int nsyms; static int nsyms;
...@@ -680,11 +680,7 @@ void export_symbol(const char *name) ...@@ -680,11 +680,7 @@ void export_symbol(const char *name)
if (flag_dump_defs) if (flag_dump_defs)
fputs(">\n", debugfile); fputs(">\n", debugfile);
/* Used as a linker script. */ printf("__crc_%s = 0x%08lx;\n", name, crc);
printf(!flag_rel_crcs ? "__crc_%s = 0x%08lx;\n" :
"SECTIONS { .rodata : ALIGN(4) { "
"__crc_%s = .; LONG(0x%08lx); } }\n",
name, crc);
} }
} }
...@@ -733,7 +729,6 @@ static void genksyms_usage(void) ...@@ -733,7 +729,6 @@ static void genksyms_usage(void)
" -q, --quiet Disable warnings (default)\n" " -q, --quiet Disable warnings (default)\n"
" -h, --help Print this message\n" " -h, --help Print this message\n"
" -V, --version Print the release version\n" " -V, --version Print the release version\n"
" -R, --relative-crc Emit section relative symbol CRCs\n"
#else /* __GNU_LIBRARY__ */ #else /* __GNU_LIBRARY__ */
" -s Select symbol prefix\n" " -s Select symbol prefix\n"
" -d Increment the debug level (repeatable)\n" " -d Increment the debug level (repeatable)\n"
...@@ -745,7 +740,6 @@ static void genksyms_usage(void) ...@@ -745,7 +740,6 @@ static void genksyms_usage(void)
" -q Disable warnings (default)\n" " -q Disable warnings (default)\n"
" -h Print this message\n" " -h Print this message\n"
" -V Print the release version\n" " -V Print the release version\n"
" -R Emit section relative symbol CRCs\n"
#endif /* __GNU_LIBRARY__ */ #endif /* __GNU_LIBRARY__ */
, stderr); , stderr);
} }
...@@ -766,14 +760,13 @@ int main(int argc, char **argv) ...@@ -766,14 +760,13 @@ int main(int argc, char **argv)
{"preserve", 0, 0, 'p'}, {"preserve", 0, 0, 'p'},
{"version", 0, 0, 'V'}, {"version", 0, 0, 'V'},
{"help", 0, 0, 'h'}, {"help", 0, 0, 'h'},
{"relative-crc", 0, 0, 'R'},
{0, 0, 0, 0} {0, 0, 0, 0}
}; };
while ((o = getopt_long(argc, argv, "s:dwqVDr:T:phR", while ((o = getopt_long(argc, argv, "s:dwqVDr:T:ph",
&long_opts[0], NULL)) != EOF) &long_opts[0], NULL)) != EOF)
#else /* __GNU_LIBRARY__ */ #else /* __GNU_LIBRARY__ */
while ((o = getopt(argc, argv, "s:dwqVDr:T:phR")) != EOF) while ((o = getopt(argc, argv, "s:dwqVDr:T:ph")) != EOF)
#endif /* __GNU_LIBRARY__ */ #endif /* __GNU_LIBRARY__ */
switch (o) { switch (o) {
case 'd': case 'd':
...@@ -813,9 +806,6 @@ int main(int argc, char **argv) ...@@ -813,9 +806,6 @@ int main(int argc, char **argv)
case 'h': case 'h':
genksyms_usage(); genksyms_usage();
return 0; return 0;
case 'R':
flag_rel_crcs = 1;
break;
default: default:
genksyms_usage(); genksyms_usage();
return 1; return 1;
......
...@@ -90,7 +90,6 @@ modpost_link() ...@@ -90,7 +90,6 @@ modpost_link()
if is_enabled CONFIG_MODVERSIONS; then if is_enabled CONFIG_MODVERSIONS; then
gen_symversions gen_symversions
lds="${lds} -T .tmp_symversions.lds"
fi fi
# This might take a while, so indicate that we're doing # This might take a while, so indicate that we're doing
...@@ -183,6 +182,10 @@ vmlinux_link() ...@@ -183,6 +182,10 @@ vmlinux_link()
libs="${KBUILD_VMLINUX_LIBS}" libs="${KBUILD_VMLINUX_LIBS}"
fi fi
if is_enabled CONFIG_MODULES; then
objs="${objs} .vmlinux.export.o"
fi
if [ "${SRCARCH}" = "um" ]; then if [ "${SRCARCH}" = "um" ]; then
wl=-Wl, wl=-Wl,
ld="${CC}" ld="${CC}"
...@@ -312,6 +315,7 @@ cleanup() ...@@ -312,6 +315,7 @@ cleanup()
rm -f vmlinux.o rm -f vmlinux.o
rm -f .vmlinux.d rm -f .vmlinux.d
rm -f .vmlinux.objs rm -f .vmlinux.objs
rm -f .vmlinux.export.c
} }
# Use "make V=1" to debug this script # Use "make V=1" to debug this script
...@@ -363,6 +367,10 @@ info GEN modules.builtin ...@@ -363,6 +367,10 @@ info GEN modules.builtin
tr '\0' '\n' < modules.builtin.modinfo | sed -n 's/^[[:alnum:]:_]*\.file=//p' | tr '\0' '\n' < modules.builtin.modinfo | sed -n 's/^[[:alnum:]:_]*\.file=//p' |
tr ' ' '\n' | uniq | sed -e 's:^:kernel/:' -e 's/$/.ko/' > modules.builtin tr ' ' '\n' | uniq | sed -e 's:^:kernel/:' -e 's/$/.ko/' > modules.builtin
if is_enabled CONFIG_MODULES; then
${MAKE} -f "${srctree}/scripts/Makefile.vmlinux" .vmlinux.export.o
fi
btf_vmlinux_bin_o="" btf_vmlinux_bin_o=""
if is_enabled CONFIG_DEBUG_INFO_BTF; then if is_enabled CONFIG_DEBUG_INFO_BTF; then
btf_vmlinux_bin_o=.btf.vmlinux.bin.o btf_vmlinux_bin_o=.btf.vmlinux.bin.o
......
...@@ -2234,6 +2234,7 @@ static void add_header(struct buffer *b, struct module *mod) ...@@ -2234,6 +2234,7 @@ static void add_header(struct buffer *b, struct module *mod)
buf_printf(b, "#define INCLUDE_VERMAGIC\n"); buf_printf(b, "#define INCLUDE_VERMAGIC\n");
buf_printf(b, "#include <linux/build-salt.h>\n"); buf_printf(b, "#include <linux/build-salt.h>\n");
buf_printf(b, "#include <linux/elfnote-lto.h>\n"); buf_printf(b, "#include <linux/elfnote-lto.h>\n");
buf_printf(b, "#include <linux/export-internal.h>\n");
buf_printf(b, "#include <linux/vermagic.h>\n"); buf_printf(b, "#include <linux/vermagic.h>\n");
buf_printf(b, "#include <linux/compiler.h>\n"); buf_printf(b, "#include <linux/compiler.h>\n");
buf_printf(b, "\n"); buf_printf(b, "\n");
...@@ -2268,20 +2269,26 @@ static void add_header(struct buffer *b, struct module *mod) ...@@ -2268,20 +2269,26 @@ static void add_header(struct buffer *b, struct module *mod)
buf_printf(b, "\nMODULE_INFO(staging, \"Y\");\n"); buf_printf(b, "\nMODULE_INFO(staging, \"Y\");\n");
} }
static void check_symversions(struct module *mod) static void add_exported_symbols(struct buffer *buf, struct module *mod)
{ {
struct symbol *sym; struct symbol *sym;
if (!modversions) if (!modversions)
return; return;
/* record CRCs for exported symbols */
buf_printf(buf, "\n");
list_for_each_entry(sym, &mod->exported_symbols, list) { list_for_each_entry(sym, &mod->exported_symbols, list) {
if (!sym->crc_valid) { if (!sym->crc_valid) {
warn("EXPORT symbol \"%s\" [%s%s] version generation failed, symbol will not be versioned.\n" warn("EXPORT symbol \"%s\" [%s%s] version generation failed, symbol will not be versioned.\n"
"Is \"%s\" prototyped in <asm/asm-prototypes.h>?\n", "Is \"%s\" prototyped in <asm/asm-prototypes.h>?\n",
sym->name, mod->name, mod->is_vmlinux ? "" : ".ko", sym->name, mod->name, mod->is_vmlinux ? "" : ".ko",
sym->name); sym->name);
continue;
} }
buf_printf(buf, "SYMBOL_CRC(%s, 0x%08x, \"%s\");\n",
sym->name, sym->crc, sym->is_gpl_only ? "_gpl" : "");
} }
} }
...@@ -2418,6 +2425,18 @@ static void write_if_changed(struct buffer *b, const char *fname) ...@@ -2418,6 +2425,18 @@ static void write_if_changed(struct buffer *b, const char *fname)
write_buf(b, fname); write_buf(b, fname);
} }
static void write_vmlinux_export_c_file(struct module *mod)
{
struct buffer buf = { };
buf_printf(&buf,
"#include <linux/export-internal.h>\n");
add_exported_symbols(&buf, mod);
write_if_changed(&buf, ".vmlinux.export.c");
free(buf.p);
}
/* do sanity checks, and generate *.mod.c file */ /* do sanity checks, and generate *.mod.c file */
static void write_mod_c_file(struct module *mod) static void write_mod_c_file(struct module *mod)
{ {
...@@ -2429,6 +2448,7 @@ static void write_mod_c_file(struct module *mod) ...@@ -2429,6 +2448,7 @@ static void write_mod_c_file(struct module *mod)
check_exports(mod); check_exports(mod);
add_header(&buf, mod); add_header(&buf, mod);
add_exported_symbols(&buf, mod);
add_versions(&buf, mod); add_versions(&buf, mod);
add_depends(&buf, mod); add_depends(&buf, mod);
add_moddevtable(&buf, mod); add_moddevtable(&buf, mod);
...@@ -2626,9 +2646,9 @@ int main(int argc, char **argv) ...@@ -2626,9 +2646,9 @@ int main(int argc, char **argv)
if (mod->from_dump) if (mod->from_dump)
continue; continue;
check_symversions(mod); if (mod->is_vmlinux)
write_vmlinux_export_c_file(mod);
if (!mod->is_vmlinux) else
write_mod_c_file(mod); write_mod_c_file(mod);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment