diff --git a/include/linux/export.h b/include/linux/export.h index b962df3c5dd3..3bbba0e476df 100644 --- a/include/linux/export.h +++ b/include/linux/export.h @@ -63,12 +63,39 @@ struct kernel_symbol { int namespace_offset; }; #else +#ifdef CONFIG_CFI_CLANG +#include +/* + * With -fno-sanitize-cfi-canonical-jump-tables, the compiler replaces + * references to functions with jump table addresses. Use inline assembly + * to emit ksymtab entries that point to the actual function instead. + */ +#define ___KSYMTAB_ENTRY(sym, sec, size) \ + __ADDRESSABLE(sym) \ + asm(" .section \"___ksymtab" sec "+" #sym "\", \"a\" \n" \ + " .balign " #size " \n" \ + "__ksymtab_" #sym ": \n" \ + " ." #size "byte " #sym " \n" \ + " ." #size "byte __kstrtab_" #sym " \n" \ + " ." #size "byte __kstrtabns_" #sym " \n" \ + " .previous \n") + +#ifdef CONFIG_64BIT +#define __KSYMTAB_ENTRY(sym, sec) ___KSYMTAB_ENTRY(sym, sec, 8) +#else +#define __KSYMTAB_ENTRY(sym, sec) ___KSYMTAB_ENTRY(sym, sec, 4) +#endif + +#else /* !CONFIG_CFI_CLANG */ + #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 } +#endif + struct kernel_symbol { unsigned long value; const char *name;