DynamicLoader+LibC: Link LibC into DynamicLoader --as-sane-people

In particular, define a static LibC library *in LibC's CMakeLists* and
use it in DynamicLoader. This is similar to the way LibELF is included
in DynamicLoader.

Additionally, compile DynamicLoader with -ffunction-sections,
-fdata-sections, and -Wl,--gc-sections. This brings the loader size from
~2Mb to ~1Mb with debug symbols and from ~500Kb to ~150Kb without. Also,
this makes linking DynamicLoader with LibTimeZone unnecessary.
This commit is contained in:
Dan Klishch 2024-04-26 23:22:31 -04:00 committed by Andrew Kaster
parent 0b6c08c9a2
commit 61cf20582c
6 changed files with 23 additions and 47 deletions

View file

@ -4,60 +4,21 @@ set(LOADER_SOURCES
)
add_library(DynamicLoader_CompileOptions INTERFACE)
target_compile_options(DynamicLoader_CompileOptions INTERFACE -fno-rtti -fpie)
target_link_options(DynamicLoader_CompileOptions INTERFACE -nostdlib -fpie)
target_compile_definitions(DynamicLoader_CompileOptions INTERFACE NO_TLS)
target_compile_definitions(DynamicLoader_CompileOptions INTERFACE NO_TLS _DYNAMIC_LOADER)
target_compile_options(DynamicLoader_CompileOptions INTERFACE -fno-rtti -fpie -ffunction-sections -fdata-sections)
target_link_options(DynamicLoader_CompileOptions INTERFACE -nolibc -nostdlib++ -nostartfiles -static-libgcc -fpie -Wl,--gc-sections)
target_link_options(DynamicLoader_CompileOptions INTERFACE -fno-sanitize=undefined) # Sanitizer runtime is linked in manually
add_dependencies(DynamicLoader_CompileOptions install_libc_headers)
file(GLOB LIBC_SOURCES1 "../Libraries/LibC/*.cpp")
file(GLOB LIBC_SOURCES2 "../Libraries/LibC/*/*.cpp")
set(ARCH_FOLDER "${SERENITY_ARCH}")
file(GLOB LIBC_SOURCES3 "../Libraries/LibC/arch/${ARCH_FOLDER}/*.S")
set(LIBC_SOURCES3 ${LIBC_SOURCES3} "../Libraries/LibC/arch/${ARCH_FOLDER}/fenv.cpp")
if ("${SERENITY_ARCH}" STREQUAL "x86_64")
set(LIBC_SOURCES3 ${LIBC_SOURCES3} "../Libraries/LibC/arch/x86_64/memset.cpp")
endif()
file(GLOB LIBSYSTEM_SOURCES "../Libraries/LibSystem/*.cpp")
if (ENABLE_UNDEFINED_SANITIZER)
set(LOADER_SOURCES ${LOADER_SOURCES} ../Libraries/LibSanitizer/UBSanitizer.cpp)
endif()
# pthread requires thread local storage, which DynamicLoader does not have.
list(FILTER LIBC_SOURCES1 EXCLUDE REGEX ".*/LibC/(pthread|semaphore)\\.cpp")
add_definitions(-D_DYNAMIC_LOADER)
set(SOURCES ${LOADER_SOURCES} ${AK_SOURCES} ${LIBC_SOURCES1} ${LIBC_SOURCES2} ${LIBC_SOURCES3} ${LIBSYSTEM_SOURCES})
if (("${SERENITY_ARCH}" STREQUAL "aarch64") OR ("${SERENITY_ARCH}" STREQUAL "riscv64"))
# On aarch64 and riscv64 the stack protector would be accessed before the Loader can relocate itself.
set_source_files_properties(main.cpp PROPERTIES COMPILE_FLAGS "-fno-stack-protector")
endif()
set_source_files_properties(../Libraries/LibC/ssp.cpp PROPERTIES COMPILE_FLAGS "-fno-stack-protector")
# Prevent GCC from removing null checks by marking the `FILE*` argument non-null
set_source_files_properties(../Libraries/LibC/stdio.cpp PROPERTIES COMPILE_FLAGS "-fno-builtin-fputc -fno-builtin-fputs -fno-builtin-fwrite")
# Prevent naively implemented string functions (like strlen) from being "optimized" into a call to themselves.
if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
set_source_files_properties(../Libraries/LibC/string.cpp ../Libraries/LibC/wchar.cpp
PROPERTIES COMPILE_FLAGS "-fno-tree-loop-distribution -fno-tree-loop-distribute-patterns")
endif()
set(SOURCES ${LOADER_SOURCES})
add_executable(Loader.so ${SOURCES})
add_dependencies(Loader.so install_libc_headers)
if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
target_link_libraries(Loader.so PRIVATE gcc)
elseif (CMAKE_CXX_COMPILER_ID MATCHES "Clang$")
target_link_libraries(Loader.so PRIVATE clang_rt.builtins)
endif ()
target_link_libraries(Loader.so PRIVATE DynamicLoader_CompileOptions DynamicLoader_LibELF LibTimeZone)
target_link_libraries(Loader.so PRIVATE DynamicLoader_CompileOptions DynamicLoader_LibELF)
target_link_options(Loader.so PRIVATE LINKER:--no-dynamic-linker)
# Don't confuse the coverage results by instrumenting Loader
target_link_libraries(Loader.so PRIVATE NoCoverage)

View file

@ -91,7 +91,7 @@ ALWAYS_INLINE static void optimizer_fence()
asm("" ::: "memory");
}
void _entry(int argc, char** argv, char** envp)
[[gnu::no_stack_protector]] void _entry(int argc, char** argv, char** envp)
{
char** env;
for (env = envp; *env; ++env) {

View file

@ -291,6 +291,13 @@ file(WRITE "${CMAKE_STAGING_PREFIX}/${CMAKE_INSTALL_LIBDIR}/libdl.so" "INPUT(lib
file(WRITE "${CMAKE_STAGING_PREFIX}/${CMAKE_INSTALL_LIBDIR}/libm.so" "INPUT(libc.so)")
file(WRITE "${CMAKE_STAGING_PREFIX}/${CMAKE_INSTALL_LIBDIR}/libssp.so" "INPUT(libc.so)")
# ===== LibC for DynamicLoader =====
add_library(DynamicLoader_LibC STATIC ${SOURCES})
target_link_libraries(DynamicLoader_LibC
PUBLIC DynamicLoader_CompileOptions
PRIVATE DynamicLoader_LibSystem
)
# ===== Compatibility with the GCC toolchain without TARGET_LIBC_PROVIDES_SSP =====
# FIXME: Remove this on the next GCC toolchain version bump
if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")

View file

@ -161,6 +161,7 @@ void pthread_exit(void* value_ptr)
pthread_exit_without_cleanup_handlers(value_ptr);
}
#ifndef _DYNAMIC_LOADER
void __pthread_maybe_cancel()
{
// Check if we have cancellations enabled.
@ -175,6 +176,7 @@ void __pthread_maybe_cancel()
// return value and calling the cleanup handlers for us.
pthread_exit(PTHREAD_CANCELED);
}
#endif
// https://pubs.opengroup.org/onlinepubs/009695399/functions/pthread_cleanup_push.html
void pthread_cleanup_push(void (*routine)(void*), void* arg)

View file

@ -25,7 +25,10 @@ if (SERENITYOS)
endif()
add_library(DynamicLoader_LibELF STATIC ${SOURCES})
target_link_libraries(DynamicLoader_LibELF PUBLIC DynamicLoader_CompileOptions)
target_link_libraries(DynamicLoader_LibELF
PUBLIC DynamicLoader_CompileOptions
PRIVATE DynamicLoader_LibC
)
endif()
serenity_lib(LibELF elf ${SOURCES})

View file

@ -5,3 +5,6 @@ set(SOURCES
serenity_libc(LibSystem system)
add_dependencies(LibSystem install_libc_headers)
target_link_options(LibSystem PRIVATE -nostdlib)
add_library(DynamicLoader_LibSystem STATIC ${SOURCES})
target_link_libraries(DynamicLoader_LibSystem PUBLIC DynamicLoader_CompileOptions)