AnyPS5/core/libs/tests/ThreadLocalDestructors.cmake

39 lines
1.7 KiB
CMake

file(GLOB modules "${MODULES}/*.prx")
if(NOT modules)
message(FATAL_ERROR "no modules in ${MODULES}")
endif()
set(explicit "__cxa_thread_atexit_nid_postfix|__cxa_thread_atexit_impl_nid_postfix|LibcInternalExtCxaThreadAtexit_nid_postfix")
set(failures "")
foreach(module IN LISTS modules)
get_filename_component(name "${module}" NAME)
execute_process(COMMAND "${NM}" --defined-only "${module}" OUTPUT_VARIABLE symbols RESULT_VARIABLE result ERROR_QUIET)
if(NOT result EQUAL 0 OR symbols STREQUAL "")
list(APPEND failures "${name}: no symbol table to inspect")
continue()
endif()
if(NOT symbols MATCHES " T __mingw_cxa_thread_atexit\n")
continue()
endif()
execute_process(COMMAND "${OBJDUMP}" -d --no-show-raw-insn "${module}" OUTPUT_VARIABLE code RESULT_VARIABLE result ERROR_QUIET)
if(NOT result EQUAL 0)
list(APPEND failures "${name}: cannot disassemble")
continue()
endif()
string(REGEX MATCHALL "\n[0-9a-f]+ <[^>\n]+>:|(call|jmp)[^\n]*<__cxa_thread_atexit>" lines "${code}")
set(function "")
foreach(line IN LISTS lines)
if(line MATCHES "^\n[0-9a-f]+ <([^>\n]+)>:$")
set(function "${CMAKE_MATCH_1}")
elseif(NOT function MATCHES "^(${explicit})$")
list(APPEND failures "${name}: ${function} registers a thread_local destructor")
endif()
endforeach()
endforeach()
if(failures)
list(REMOVE_DUPLICATES failures)
list(JOIN failures "\n " text)
message(FATAL_ERROR "On Windows a thread_local destructor in a module runs after emulated TLS freed the object; keep such objects in HostThreadLocal:\n ${text}")
endif()
list(LENGTH modules count)
message(STATUS "${count} modules register no thread_local destructors")