19
19
#include " src/signal/raise.h"
20
20
#include " src/signal/sigaction.h"
21
21
#include " test/UnitTest/ErrnoSetterMatcher.h"
22
- #include " test/UnitTest/LibcTest.h" vdso_test
22
+ #include " test/UnitTest/LibcTest.h"
23
23
#include " test/UnitTest/Test.h"
24
24
#include < linux/time_types.h>
25
25
#include < sys/syscall.h>
26
26
27
+ struct riscv_hwprobe {
28
+ int64_t key;
29
+ uint64_t value;
30
+ };
31
+
27
32
namespace LIBC_NAMESPACE {
28
33
// For x86_64, we explicitly test some traditional vdso symbols are indeed
29
34
// available.
30
35
31
36
TEST (LlvmLibcOSUtilVDSOTest, GetTimeOfDay) {
32
- using FuncTy = int (*)(timeval *, struct timezone *);
33
- vdso::Symbol symbol{vdso::VDSOSym::GetTimeOfDay};
34
- auto func = symbol.get <FuncTy>();
37
+ vdso::TypedSymbol<vdso::VDSOSym::GetTimeOfDay> symbol;
38
+
35
39
#ifdef LIBC_TARGET_ARCH_IS_X86
36
- ASSERT_NE (func, static_cast <FuncTy>( nullptr ) );
40
+ ASSERT_TRUE (symbol != nullptr );
37
41
#else
38
- if (func == nullptr )
42
+ if (!symbol )
39
43
return ;
40
44
#endif
41
45
timeval tv;
42
- EXPECT_EQ (func (&tv, nullptr ), 0 );
46
+ EXPECT_EQ (symbol (&tv, nullptr ), 0 );
43
47
// hopefully people are not building time machines using our libc.
44
48
EXPECT_GT (tv.tv_sec , static_cast <decltype (tv.tv_sec )>(0 ));
45
49
}
46
50
47
51
TEST (LlvmLibcOSUtilVDSOTest, Time) {
48
- using FuncTy = time_t (*)(time_t *);
49
- vdso::Symbol symbol{vdso::VDSOSym::Time};
50
- auto func = symbol.get <FuncTy>();
52
+ vdso::TypedSymbol<vdso::VDSOSym::Time> symbol;
51
53
#ifdef LIBC_TARGET_ARCH_IS_X86
52
- ASSERT_NE (func, static_cast <FuncTy>( nullptr ) );
54
+ ASSERT_TRUE (symbol != nullptr );
53
55
#else
54
- if (func == nullptr )
56
+ if (!symbol )
55
57
return ;
56
58
#endif
57
59
time_t a, b;
58
- EXPECT_GT (func (&a), static_cast <time_t >(0 ));
59
- EXPECT_GT (func (&b), static_cast <time_t >(0 ));
60
+ EXPECT_GT (symbol (&a), static_cast <time_t >(0 ));
61
+ EXPECT_GT (symbol (&b), static_cast <time_t >(0 ));
60
62
EXPECT_GE (b, a);
61
63
}
62
64
63
65
TEST (LlvmLibcOSUtilVDSOTest, ClockGetTime) {
64
- using FuncTy = int (*)(clockid_t , timespec *);
65
- vdso::Symbol symbol{vdso::VDSOSym::ClockGetTime};
66
- auto func = symbol.get <FuncTy>();
66
+ vdso::TypedSymbol<vdso::VDSOSym::ClockGetTime> symbol;
67
67
#ifdef LIBC_TARGET_ARCH_IS_X86
68
- ASSERT_NE (func, static_cast <FuncTy>( nullptr ) );
68
+ ASSERT_TRUE (symbol != nullptr );
69
69
#else
70
- if (func == nullptr )
70
+ if (!symbol )
71
71
return ;
72
72
#endif
73
73
timespec a, b;
74
- EXPECT_EQ (func (CLOCK_MONOTONIC, &a), 0 );
75
- EXPECT_EQ (func (CLOCK_MONOTONIC, &b), 0 );
74
+ EXPECT_EQ (symbol (CLOCK_MONOTONIC, &a), 0 );
75
+ EXPECT_EQ (symbol (CLOCK_MONOTONIC, &b), 0 );
76
76
if (a.tv_sec == b.tv_sec ) {
77
77
EXPECT_LT (a.tv_nsec , b.tv_nsec );
78
78
} else {
@@ -81,16 +81,14 @@ TEST(LlvmLibcOSUtilVDSOTest, ClockGetTime) {
81
81
}
82
82
83
83
TEST (LlvmLibcOSUtilVDSOTest, ClockGetTime64) {
84
- using FuncTy = int (*)(clockid_t , __kernel_timespec *);
85
- vdso::Symbol symbol{vdso::VDSOSym::ClockGetTime64};
86
- auto func = symbol.get <FuncTy>();
87
- if (func == nullptr )
84
+ vdso::TypedSymbol<vdso::VDSOSym::ClockGetTime64> symbol;
85
+ if (!symbol)
88
86
return ;
89
87
// See kernel API at
90
88
// https://elixir.bootlin.com/linux/latest/source/tools/testing/selftests/vDSO/vdso_test_correctness.c#L155
91
89
__kernel_timespec a, b;
92
- EXPECT_EQ (func (CLOCK_MONOTONIC, &a), 0 );
93
- EXPECT_EQ (func (CLOCK_MONOTONIC, &b), 0 );
90
+ EXPECT_EQ (symbol (CLOCK_MONOTONIC, &a), 0 );
91
+ EXPECT_EQ (symbol (CLOCK_MONOTONIC, &b), 0 );
94
92
if (a.tv_sec == b.tv_sec ) {
95
93
EXPECT_LT (a.tv_nsec , b.tv_nsec );
96
94
} else {
@@ -99,28 +97,24 @@ TEST(LlvmLibcOSUtilVDSOTest, ClockGetTime64) {
99
97
}
100
98
101
99
TEST (LlvmLibcOSUtilVDSOTest, ClockGetRes) {
102
- using FuncTy = int (*)(clockid_t , timespec *);
103
- vdso::Symbol symbol{vdso::VDSOSym::ClockGetRes};
104
- auto func = symbol.get <FuncTy>();
105
- if (func == nullptr )
100
+ vdso::TypedSymbol<vdso::VDSOSym::ClockGetRes> symbol;
101
+ if (!symbol)
106
102
return ;
107
103
timespec res{};
108
- EXPECT_EQ (func (CLOCK_MONOTONIC, &res), 0 );
104
+ EXPECT_EQ (symbol (CLOCK_MONOTONIC, &res), 0 );
109
105
EXPECT_TRUE (res.tv_sec > 0 || res.tv_nsec > 0 );
110
106
}
111
107
112
108
TEST (LlvmLibcOSUtilVDSOTest, GetCpu) {
113
109
// The kernel system call has a third argument, which should be passed as
114
110
// nullptr.
115
- using FuncTy = int (*)(int *, int *, void *);
116
- vdso::Symbol symbol{vdso::VDSOSym::GetCpu};
117
- auto func = symbol.get <FuncTy>();
118
- if (func == nullptr )
111
+ vdso::TypedSymbol<vdso::VDSOSym::GetCpu> symbol;
112
+ if (!symbol)
119
113
return ;
120
- int cpu = - 1 , node = - 1 ;
121
- EXPECT_EQ (func (&cpu, &node, nullptr ), 0 );
122
- EXPECT_GE (cpu, 0 );
123
- EXPECT_GE (node, 0 );
114
+ unsigned cpu = static_cast < unsigned >(- 1 ) , node = static_cast < unsigned >(- 1 ) ;
115
+ EXPECT_EQ (symbol (&cpu, &node, nullptr ), 0 );
116
+ EXPECT_GE (cpu, 0u );
117
+ EXPECT_GE (node, 0u );
124
118
}
125
119
126
120
static bool flag = false ;
@@ -134,11 +128,10 @@ TEST(LlvmLibcOSUtilVDSOTest, RtSigReturn) {
134
128
struct sigaction old_sa {};
135
129
sa.sa_handler = sigprof_handler;
136
130
sa.sa_flags = SA_RESTORER;
137
- vdso::Symbol symbol{vdso::VDSOSym::RTSigReturn};
138
- auto func = symbol.get <decltype (sa.sa_restorer )>();
139
- if (func == nullptr )
131
+ vdso::TypedSymbol<vdso::VDSOSym::RTSigReturn> symbol;
132
+ if (!symbol)
140
133
return ;
141
- sa.sa_restorer = func ;
134
+ sa.sa_restorer = symbol ;
142
135
ASSERT_THAT (LIBC_NAMESPACE::sigaction (SIGPROF, &sa, &old_sa), Succeeds ());
143
136
raise (SIGPROF);
144
137
ASSERT_TRUE (flag);
@@ -147,40 +140,31 @@ TEST(LlvmLibcOSUtilVDSOTest, RtSigReturn) {
147
140
}
148
141
149
142
TEST (LlvmLibcOSUtilVDSOTest, FlushICache) {
150
- using FuncTy = void (*)(void *, void *, unsigned long );
151
- vdso::Symbol symbol{vdso::VDSOSym::FlushICache};
152
- auto func = symbol.get <FuncTy>();
153
- if (func == nullptr )
143
+ vdso::TypedSymbol<vdso::VDSOSym::FlushICache> symbol;
144
+ if (!symbol)
154
145
return ;
155
146
char buf[512 ];
156
147
// we just check that the flush will not panic the program.
157
148
// the flags part only take 0/1 as up to kernel 6.10, which is used to
158
149
// indicate whether the flush is local to the core or global.
159
- func (buf, buf + sizeof (buf), 0 );
160
- func (buf, buf + sizeof (buf), 1 );
150
+ symbol (buf, buf + sizeof (buf), 0 );
151
+ symbol (buf, buf + sizeof (buf), 1 );
161
152
}
162
153
163
154
// https://docs.kernel.org/6.5/riscv/hwprobe.html
164
155
TEST (LlvmLibcOSUtilVDSOTest, RiscvHwProbe) {
165
156
using namespace testing ::ErrnoSetterMatcher;
166
- struct riscv_hwprobe {
167
- int64_t key;
168
- uint64_t value;
169
- };
170
- using FuncTy =
171
- long (*)(riscv_hwprobe *, size_t , size_t , struct cpu_set_t *, unsigned );
172
- vdso::Symbol symbol{vdso::VDSOSym::RiscvHwProbe};
173
- auto func = symbol.get <FuncTy>();
174
- if (func == nullptr )
157
+ vdso::TypedSymbol<vdso::VDSOSym::RiscvHwProbe> symbol;
158
+ if (!symbol)
175
159
return ;
176
160
// If a key is unknown to the kernel, its key field will be cleared to -1, and
177
161
// its value set to 0. We expect probes.value are all 0.
178
162
// Usermode can supply NULL for cpus and 0 for cpu_count as a shortcut for all
179
163
// online CPUs
180
164
riscv_hwprobe probes[2 ] = {{-1 , 1 }, {-1 , 1 }};
181
- ASSERT_THAT (func (/* pairs=*/ probes, /* count=*/ 2 , /* cpusetsize=*/ 0 ,
182
- /* cpuset=*/ nullptr ,
183
- /* flags=*/ 0 ),
165
+ ASSERT_THAT (symbol (/* pairs=*/ probes, /* count=*/ 2 , /* cpusetsize=*/ 0 ,
166
+ /* cpuset=*/ nullptr ,
167
+ /* flags=*/ 0 ),
184
168
Succeeds ());
185
169
for (auto &probe : probes) {
186
170
EXPECT_EQ (probe.key , static_cast <decltype (probe.key )>(-1 ));
0 commit comments