mirror of
https://github.com/RGBCube/serenity
synced 2025-07-27 05:47:35 +00:00
Tests/LibELF: Test loading libraries with dynamic TLS
The setup is a bit peculiar: both the definition and the use site of these TLS variables have to be in a shared library, otherwise the linker might relax the global-dynamic access mode to something that doesn't require a `__tls_get_addr` call.
This commit is contained in:
parent
ad9e674fa0
commit
c63fe0e1f1
4 changed files with 106 additions and 6 deletions
|
@ -1,15 +1,21 @@
|
||||||
set(CMAKE_SKIP_RPATH FALSE)
|
set(CMAKE_SKIP_RPATH FALSE)
|
||||||
macro(add_dlopen_lib NAME FUNCTION)
|
|
||||||
add_library(${NAME} SHARED Dynlib.cpp)
|
macro(add_test_lib NAME FILE)
|
||||||
target_compile_definitions(${NAME} PRIVATE -DFUNCTION=${FUNCTION})
|
add_library(${NAME} SHARED ${FILE})
|
||||||
# LibLine is not special, just an "external" dependency
|
|
||||||
target_link_libraries(${NAME} PRIVATE LibLine)
|
|
||||||
serenity_set_implicit_links(${NAME})
|
serenity_set_implicit_links(${NAME})
|
||||||
# Avoid execution by the test runner
|
# Avoid execution by the test runner
|
||||||
install(TARGETS ${NAME}
|
install(TARGETS ${NAME}
|
||||||
DESTINATION usr/Tests/LibELF
|
DESTINATION usr/Tests/LibELF
|
||||||
PERMISSIONS OWNER_READ GROUP_READ WORLD_READ OWNER_WRITE GROUP_WRITE)
|
PERMISSIONS OWNER_READ GROUP_READ WORLD_READ OWNER_WRITE GROUP_WRITE)
|
||||||
endmacro()
|
endmacro()
|
||||||
|
|
||||||
|
macro(add_dlopen_lib NAME FUNCTION)
|
||||||
|
add_test_lib(${NAME} Dynlib.cpp)
|
||||||
|
target_compile_definitions(${NAME} PRIVATE -DFUNCTION=${FUNCTION})
|
||||||
|
# LibLine is not special, just an "external" dependency
|
||||||
|
target_link_libraries(${NAME} PRIVATE LibLine)
|
||||||
|
endmacro()
|
||||||
|
|
||||||
add_dlopen_lib(DynlibA dynliba_function)
|
add_dlopen_lib(DynlibA dynliba_function)
|
||||||
add_dlopen_lib(DynlibB dynlibb_function)
|
add_dlopen_lib(DynlibB dynlibb_function)
|
||||||
|
|
||||||
|
@ -22,8 +28,17 @@ unset(CMAKE_INSTALL_RPATH)
|
||||||
set(TEST_SOURCES
|
set(TEST_SOURCES
|
||||||
test-elf.cpp
|
test-elf.cpp
|
||||||
TestDlOpen.cpp
|
TestDlOpen.cpp
|
||||||
|
TestTLS.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
foreach(source IN LISTS TEST_SOURCES)
|
foreach(source IN LISTS TEST_SOURCES)
|
||||||
serenity_test("${source}" LibELF)
|
serenity_test("${source}" LibELF)
|
||||||
endforeach()
|
endforeach()
|
||||||
|
|
||||||
|
add_test_lib(TLSDef TLSDef.cpp)
|
||||||
|
add_test_lib(TLSUse TLSUse.cpp)
|
||||||
|
target_compile_options(TLSUse PRIVATE -ftls-model=global-dynamic)
|
||||||
|
target_link_libraries(TLSUse PRIVATE LibCore LibTest LibThreading TLSDef)
|
||||||
|
set_target_properties(TLSUse PROPERTIES INSTALL_RPATH "$ORIGIN")
|
||||||
|
target_link_libraries(TestTLS PRIVATE TLSUse)
|
||||||
|
set_target_properties(TestTLS PROPERTIES INSTALL_RPATH "$ORIGIN")
|
||||||
|
|
21
Tests/LibELF/TLSDef.cpp
Normal file
21
Tests/LibELF/TLSDef.cpp
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2023, Daniel Bertalan <dani@danielbertalan.dev>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <LibTest/Macros.h>
|
||||||
|
|
||||||
|
__thread int one = 1;
|
||||||
|
__thread int two = 2;
|
||||||
|
[[gnu::tls_model("initial-exec")]] __thread int three = 3;
|
||||||
|
[[gnu::tls_model("initial-exec")]] __thread int four = 4;
|
||||||
|
|
||||||
|
void check_increment_worked();
|
||||||
|
void check_increment_worked()
|
||||||
|
{
|
||||||
|
EXPECT_EQ(one, 2);
|
||||||
|
EXPECT_EQ(two, 3);
|
||||||
|
EXPECT_EQ(three, 4);
|
||||||
|
EXPECT_EQ(four, 5);
|
||||||
|
}
|
48
Tests/LibELF/TLSUse.cpp
Normal file
48
Tests/LibELF/TLSUse.cpp
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2023, Daniel Bertalan <dani@danielbertalan.dev>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <LibTest/Macros.h>
|
||||||
|
#include <LibThreading/Thread.h>
|
||||||
|
|
||||||
|
// Defined in TLSDef.cpp
|
||||||
|
extern __thread int one;
|
||||||
|
extern __thread int two;
|
||||||
|
extern __thread int three;
|
||||||
|
[[gnu::tls_model("initial-exec")]] extern __thread int four;
|
||||||
|
extern void check_increment_worked();
|
||||||
|
|
||||||
|
static void check_initial()
|
||||||
|
{
|
||||||
|
EXPECT_EQ(one, 1);
|
||||||
|
EXPECT_EQ(two, 2);
|
||||||
|
EXPECT_EQ(three, 3);
|
||||||
|
EXPECT_EQ(four, 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
// This checks the basic functionality of thread-local variables:
|
||||||
|
// - TLS variables with a static initializer have the correct value on program startup
|
||||||
|
// - TLS variables are set to their initial values in a new thread
|
||||||
|
// - relocations refer to the correct variables
|
||||||
|
// - accessing an initial-exec variable from a DSO works even if
|
||||||
|
// it's not declared as initial-exec at the use site
|
||||||
|
// FIXME: Test C++11 thread_local variables with dynamic initializers
|
||||||
|
void run_test();
|
||||||
|
void run_test()
|
||||||
|
{
|
||||||
|
check_initial();
|
||||||
|
++one;
|
||||||
|
++two;
|
||||||
|
++three;
|
||||||
|
++four;
|
||||||
|
check_increment_worked();
|
||||||
|
|
||||||
|
auto second_thread = Threading::Thread::construct([] {
|
||||||
|
check_initial();
|
||||||
|
return 0;
|
||||||
|
});
|
||||||
|
second_thread->start();
|
||||||
|
(void)second_thread->join();
|
||||||
|
}
|
16
Tests/LibELF/TestTLS.cpp
Normal file
16
Tests/LibELF/TestTLS.cpp
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2023, Daniel Bertalan <dani@danielbertalan.dev>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <LibTest/TestCase.h>
|
||||||
|
|
||||||
|
// When linking an executable, TLS relaxations might be relaxed to different
|
||||||
|
// access modes than intended. Hence, the actual logic has been moved to a
|
||||||
|
// shared library, and this executable just calls it.
|
||||||
|
extern void run_test();
|
||||||
|
TEST_CASE(basic)
|
||||||
|
{
|
||||||
|
run_test();
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue