Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Merged
merged 10 commits into from May 7, 2024
9 changes: 0 additions & 9 deletions Meta/CMake/utils.cmake
Expand Up @@ -9,15 +9,6 @@ function(serenity_set_implicit_links target_name)
# slightly outdated stub in the sysroot, but have not yet installed the freshly
# built LibC.
target_link_libraries(${target_name} PRIVATE LibC)

# Same goes for -lssp_nonshared, which is required during build time but is not
# yet installed in the sysroot. However, we just want to add the link directory
# and a dependency here, since actually linking the library is decided on by
# passing one of the -fstack-protector options.
# -lssp is contained inside LibC, so that case is handled by the above and a linker
# script.
target_link_directories(${target_name} PRIVATE "$<TARGET_FILE_DIR:ssp_nonshared>")
add_dependencies(${target_name} ssp_nonshared)
endfunction()

function(serenity_install_headers target_name)
Expand Down
Expand Up @@ -87,7 +87,7 @@ new file mode 100644
index 0000000000000000000000000000000000000000..10c6f16fbe13eab36bab8f6896f8e2a6ae48df02
--- /dev/null
+++ b/gcc/config/serenity.h
@@ -0,0 +1,48 @@
@@ -0,0 +1,50 @@
+/* Useful if you wish to make target-specific GCC changes. */
+#undef TARGET_SERENITY
+#define TARGET_SERENITY 1
Expand All @@ -110,6 +110,8 @@ index 0000000000000000000000000000000000000000..10c6f16fbe13eab36bab8f6896f8e2a6
+#undef ENDFILE_SPEC
+#define ENDFILE_SPEC "%{shared|static-pie|!no-pie:crtendS.o%s; :crtend.o%s} crtn.o%s"
+
+#define TARGET_LIBC_PROVIDES_SSP
DanShaders marked this conversation as resolved.
Show resolved Hide resolved
+
+#undef LINK_SPEC
+#define LINK_SPEC "%{shared:-shared} %{static:-static} %{!static: %{rdynamic:-export-dynamic} -dynamic-linker /usr/lib/Loader.so}"
+
Expand Down
59 changes: 8 additions & 51 deletions Userland/DynamicLoader/CMakeLists.txt
@@ -1,64 +1,21 @@
set(LOADER_SOURCES
set(SOURCES
main.cpp
misc.cpp
)

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")
add_executable(Loader.so ${SOURCES})

target_link_libraries(Loader.so PRIVATE DynamicLoader_CompileOptions DynamicLoader_LibELF)
if (ENABLE_UNDEFINED_SANITIZER)
set(LOADER_SOURCES ${LOADER_SOURCES} ../Libraries/LibSanitizer/UBSanitizer.cpp)
target_link_libraries(Loader.so PRIVATE DynamicLoader_LibUBSanitizer)
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")
set_source_files_properties(../Libraries/LibC/ssp_nonshared.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()

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_options(Loader.so PRIVATE LINKER:--no-dynamic-linker)
# Don't confuse the coverage results by instrumenting Loader
target_link_libraries(Loader.so PRIVATE NoCoverage)
Expand Down
2 changes: 1 addition & 1 deletion Userland/DynamicLoader/main.cpp
Expand Up @@ -108,7 +108,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) {
Expand Down