mirror of
https://github.com/Gericom/teak-llvm.git
synced 2025-06-19 11:35:51 -04:00

Summary: This patch fixes two problems with the crtbegin.c as written: 1. In do_init, register_frame_info is not guarded by a #define, but in do_fini, deregister_frame_info is guarded by #ifndef CRT_HAS_INITFINI_ARRAY. Thus when CRT_HAS_INITFINI_ARRAY is not defined, frames are registered but then never deregistered. The frame registry mechanism builds a linked-list from the .so's static variable do_init.object, and when the .so is unloaded, this memory becomes invalid and should be deregistered. Further, libgcc's crtbegin treats the frame registry as independent from the initfini array mechanism. This patch fixes this by adding a new #define, "EH_USE_FRAME_INFO_REGISTRY", which is set by the cmake option COMPILER_RT_CRT_USE_EH_FRAME_REGISTRY Currently, do_init calls register_frame_info, and then calls the binary's constructors. This allows constructors to safely use libunwind. However, do_fini calls deregister_frame_info and then calls the binary's destructors. This prevents destructors from safely using libunwind. This patch also switches that ordering, so that destructors can safely use libunwind. As it happens, this is a fairly common scenario for thread sanitizer.
95 lines
3.3 KiB
CMake
95 lines
3.3 KiB
CMake
add_compiler_rt_component(crt)
|
|
|
|
function(check_cxx_section_exists section output)
|
|
cmake_parse_arguments(ARG "" "" "SOURCE;FLAGS" ${ARGN})
|
|
if(NOT ARG_SOURCE)
|
|
set(ARG_SOURCE "int main() { return 0; }\n")
|
|
endif()
|
|
|
|
string(RANDOM TARGET_NAME)
|
|
set(TARGET_NAME "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/cmTC_${TARGET_NAME}.dir")
|
|
file(MAKE_DIRECTORY ${TARGET_NAME})
|
|
|
|
file(WRITE "${TARGET_NAME}/CheckSectionExists.c" "${ARG_SOURCE}\n")
|
|
|
|
string(REGEX MATCHALL "<[A-Za-z0-9_]*>" substitutions
|
|
${CMAKE_C_COMPILE_OBJECT})
|
|
|
|
set(try_compile_flags "${ARG_FLAGS}")
|
|
if(CMAKE_C_COMPILER_ID MATCHES Clang AND CMAKE_C_COMPILER_TARGET)
|
|
list(APPEND try_compile_flags "-target ${CMAKE_C_COMPILER_TARGET}")
|
|
endif()
|
|
append_list_if(COMPILER_RT_HAS_FNO_LTO_FLAG -fno-lto try_compile_flags)
|
|
|
|
string(REPLACE ";" " " extra_flags "${try_compile_flags}")
|
|
|
|
set(test_compile_command "${CMAKE_C_COMPILE_OBJECT}")
|
|
foreach(substitution ${substitutions})
|
|
if(substitution STREQUAL "<CMAKE_C_COMPILER>")
|
|
string(REPLACE "<CMAKE_C_COMPILER>" "${CMAKE_C_COMPILER} ${CMAKE_C_COMPILER_ARG1}"
|
|
test_compile_command ${test_compile_command})
|
|
elseif(substitution STREQUAL "<OBJECT>")
|
|
string(REPLACE "<OBJECT>" "${TARGET_NAME}/CheckSectionExists.o"
|
|
test_compile_command ${test_compile_command})
|
|
elseif(substitution STREQUAL "<SOURCE>")
|
|
string(REPLACE "<SOURCE>" "${TARGET_NAME}/CheckSectionExists.c"
|
|
test_compile_command ${test_compile_command})
|
|
elseif(substitution STREQUAL "<FLAGS>")
|
|
string(REPLACE "<FLAGS>" "${CMAKE_C_FLAGS} ${extra_flags}"
|
|
test_compile_command ${test_compile_command})
|
|
else()
|
|
string(REPLACE "${substitution}" "" test_compile_command
|
|
${test_compile_command})
|
|
endif()
|
|
endforeach()
|
|
|
|
string(REPLACE " " ";" test_compile_command "${test_compile_command}")
|
|
|
|
execute_process(
|
|
COMMAND ${test_compile_command}
|
|
RESULT_VARIABLE TEST_RESULT
|
|
OUTPUT_VARIABLE TEST_OUTPUT
|
|
ERROR_VARIABLE TEST_ERROR
|
|
)
|
|
|
|
execute_process(
|
|
COMMAND ${CMAKE_OBJDUMP} -h "${TARGET_NAME}/CheckSectionExists.o"
|
|
RESULT_VARIABLE CHECK_RESULT
|
|
OUTPUT_VARIABLE CHECK_OUTPUT
|
|
ERROR_VARIABLE CHECK_ERROR
|
|
)
|
|
string(FIND "${CHECK_OUTPUT}" "${section}" SECTION_FOUND)
|
|
|
|
if(NOT SECTION_FOUND EQUAL -1)
|
|
set(${output} TRUE PARENT_SCOPE)
|
|
else()
|
|
set(${output} FALSE PARENT_SCOPE)
|
|
endif()
|
|
|
|
file(REMOVE_RECURSE ${TARGET_NAME})
|
|
endfunction()
|
|
|
|
check_cxx_section_exists(".init_array" COMPILER_RT_HAS_INITFINI_ARRAY
|
|
SOURCE "volatile int x;\n__attribute__((constructor)) void f() {x = 0;}\nint main() { return 0; }\n")
|
|
|
|
append_list_if(COMPILER_RT_HAS_STD_C11_FLAG -std=c11 CRT_CFLAGS)
|
|
append_list_if(COMPILER_RT_HAS_INITFINI_ARRAY -DCRT_HAS_INITFINI_ARRAY CRT_CFLAGS)
|
|
append_list_if(COMPILER_RT_CRT_USE_EH_FRAME_REGISTRY -DEH_USE_FRAME_REGISTRY CRT_CFLAGS)
|
|
append_list_if(COMPILER_RT_HAS_FPIC_FLAG -fPIC CRT_CFLAGS)
|
|
append_list_if(COMPILER_RT_HAS_WNO_PEDANTIC -Wno-pedantic CRT_CFLAGS)
|
|
|
|
foreach(arch ${CRT_SUPPORTED_ARCH})
|
|
add_compiler_rt_runtime(clang_rt.crtbegin
|
|
OBJECT
|
|
ARCHS ${arch}
|
|
SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/crtbegin.c
|
|
CFLAGS ${CRT_CFLAGS}
|
|
PARENT_TARGET crt)
|
|
add_compiler_rt_runtime(clang_rt.crtend
|
|
OBJECT
|
|
ARCHS ${arch}
|
|
SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/crtend.c
|
|
CFLAGS ${CRT_CFLAGS}
|
|
PARENT_TARGET crt)
|
|
endforeach()
|