diff --git a/Kernel/CMakeLists.txt b/Kernel/CMakeLists.txt index 5964dbc48a..f37e4cb3e9 100644 --- a/Kernel/CMakeLists.txt +++ b/Kernel/CMakeLists.txt @@ -489,6 +489,7 @@ set_target_properties(Kernel PROPERTIES LINK_DEPENDS "${CMAKE_CURRENT_BINARY_DIR if (ENABLE_KERNEL_LTO) include(CheckIPOSupported) check_ipo_supported() + add_definitions(-DENABLE_KERNEL_LTO) set_property(TARGET Kernel PROPERTY INTERPROCEDURAL_OPTIMIZATION TRUE) endif() diff --git a/Kernel/StdLib.cpp b/Kernel/StdLib.cpp index aebd148070..145f03d1b7 100644 --- a/Kernel/StdLib.cpp +++ b/Kernel/StdLib.cpp @@ -207,6 +207,18 @@ KResult memset_user(void* dest_ptr, int c, size_t n) return KSuccess; } +#if defined(__clang__) && defined(ENABLE_KERNEL_LTO) +// Due to a chicken-and-egg situation, certain linker-defined symbols that are added on-demand (like the GOT) +// need to be present before LTO bitcode files are compiled. And since we don't link to any native object files, +// the linker does not know that _GLOBAL_OFFSET_TABLE_ is needed, so it doesn't define it, so linking as a PIE fails. +// See https://bugs.llvm.org/show_bug.cgi?id=39634 +FlatPtr missing_got_workaround() +{ + extern volatile FlatPtr _GLOBAL_OFFSET_TABLE_; + return _GLOBAL_OFFSET_TABLE_; +} +#endif + extern "C" { const void* memmem(const void* haystack, size_t haystack_length, const void* needle, size_t needle_length)