1 | //===-- PlatformSiginfoTest.cpp -------------------------------------------===// |
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | |
9 | #include "gtest/gtest.h" |
10 | |
11 | #include <initializer_list> |
12 | #include <optional> |
13 | #include <tuple> |
14 | |
15 | #include "Plugins/Platform/FreeBSD/PlatformFreeBSD.h" |
16 | #include "Plugins/Platform/Linux/PlatformLinux.h" |
17 | #include "Plugins/Platform/NetBSD/PlatformNetBSD.h" |
18 | #include "Plugins/TypeSystem/Clang/TypeSystemClang.h" |
19 | |
20 | #include "TestingSupport/SubsystemRAII.h" |
21 | #include "lldb/Core/Debugger.h" |
22 | #include "lldb/Host/FileSystem.h" |
23 | #include "lldb/Host/HostInfo.h" |
24 | #include "lldb/Utility/ArchSpec.h" |
25 | |
26 | using namespace lldb; |
27 | using namespace lldb_private; |
28 | using namespace lldb_private::repro; |
29 | |
30 | namespace { |
31 | class PlatformSiginfoTest : public ::testing::Test { |
32 | SubsystemRAII<FileSystem, HostInfo, TypeSystemClang> subsystems; |
33 | PlatformSP platform_sp; |
34 | DebuggerSP debugger_sp; |
35 | TargetSP target_sp; |
36 | |
37 | public: |
38 | CompilerType siginfo_type; |
39 | |
40 | void SetUp() override { |
41 | platform_freebsd::PlatformFreeBSD::Initialize(); |
42 | platform_linux::PlatformLinux::Initialize(); |
43 | platform_netbsd::PlatformNetBSD::Initialize(); |
44 | } |
45 | |
46 | void TearDown() override { |
47 | platform_netbsd::PlatformNetBSD::Terminate(); |
48 | platform_linux::PlatformLinux::Terminate(); |
49 | platform_freebsd::PlatformFreeBSD::Terminate(); |
50 | } |
51 | |
52 | typedef std::tuple<const char *, uint64_t, uint64_t> field_tuple; |
53 | |
54 | void ExpectField(const CompilerType &siginfo_type, field_tuple field) { |
55 | const char *path; |
56 | uint64_t offset, size; |
57 | std::tie(args&: path, args&: offset, args&: size) = field; |
58 | |
59 | SCOPED_TRACE(path); |
60 | CompilerType field_type = siginfo_type; |
61 | uint64_t total_offset = 0; |
62 | for (auto field_name : llvm::split(Str: path, Separator: '.')) { |
63 | uint64_t bit_offset; |
64 | ASSERT_NE(field_type.GetIndexOfFieldWithName(field_name.str().c_str(), |
65 | &field_type, &bit_offset), |
66 | UINT32_MAX); |
67 | total_offset += bit_offset; |
68 | } |
69 | |
70 | EXPECT_EQ(total_offset, offset * 8); |
71 | EXPECT_EQ(field_type.GetByteSize(nullptr), std::optional<uint64_t>(size)); |
72 | } |
73 | |
74 | void ExpectFields(const CompilerType &container, |
75 | std::initializer_list<field_tuple> fields) { |
76 | for (auto x : fields) |
77 | ExpectField(siginfo_type: container, field: x); |
78 | } |
79 | |
80 | void InitializeSiginfo(const std::string &triple) { |
81 | ArchSpec arch(triple); |
82 | |
83 | switch (arch.GetTriple().getOS()) { |
84 | case llvm::Triple::FreeBSD: |
85 | platform_sp = |
86 | platform_freebsd::PlatformFreeBSD::CreateInstance(force: true, arch: &arch); |
87 | break; |
88 | case llvm::Triple::Linux: |
89 | platform_sp = platform_linux::PlatformLinux::CreateInstance(force: true, arch: &arch); |
90 | break; |
91 | case llvm::Triple::NetBSD: |
92 | platform_sp = |
93 | platform_netbsd::PlatformNetBSD::CreateInstance(force: true, arch: &arch); |
94 | break; |
95 | default: |
96 | llvm_unreachable("unknown ostype in triple" ); |
97 | } |
98 | Platform::SetHostPlatform(platform_sp); |
99 | |
100 | debugger_sp = Debugger::CreateInstance(); |
101 | ASSERT_TRUE(debugger_sp); |
102 | |
103 | debugger_sp->GetTargetList().CreateTarget( |
104 | debugger&: *debugger_sp, user_exe_path: "" , arch, get_dependent_modules: eLoadDependentsNo, platform_sp, target_sp); |
105 | ASSERT_TRUE(target_sp); |
106 | |
107 | siginfo_type = platform_sp->GetSiginfoType(triple: arch.GetTriple()); |
108 | } |
109 | }; |
110 | |
111 | } // namespace |
112 | |
113 | TEST_F(PlatformSiginfoTest, TestLinux_64bit) { |
114 | for (std::string arch : {"x86_64" , "aarch64" , "powerpc64le" }) { |
115 | SCOPED_TRACE(arch); |
116 | InitializeSiginfo(triple: arch + "-pc-linux-gnu" ); |
117 | ASSERT_TRUE(siginfo_type); |
118 | |
119 | ExpectFields(container: siginfo_type, |
120 | fields: { |
121 | {"si_signo" , 0, 4}, |
122 | {"si_errno" , 4, 4}, |
123 | {"si_code" , 8, 4}, |
124 | {"_sifields._kill.si_pid" , 16, 4}, |
125 | {"_sifields._kill.si_uid" , 20, 4}, |
126 | {"_sifields._timer.si_tid" , 16, 4}, |
127 | {"_sifields._timer.si_overrun" , 20, 4}, |
128 | {"_sifields._timer.si_sigval" , 24, 8}, |
129 | {"_sifields._rt.si_pid" , 16, 4}, |
130 | {"_sifields._rt.si_uid" , 20, 4}, |
131 | {"_sifields._rt.si_sigval" , 24, 8}, |
132 | {"_sifields._sigchld.si_pid" , 16, 4}, |
133 | {"_sifields._sigchld.si_uid" , 20, 4}, |
134 | {"_sifields._sigchld.si_status" , 24, 4}, |
135 | {"_sifields._sigchld.si_utime" , 32, 8}, |
136 | {"_sifields._sigchld.si_stime" , 40, 8}, |
137 | {"_sifields._sigfault.si_addr" , 16, 8}, |
138 | {"_sifields._sigfault.si_addr_lsb" , 24, 2}, |
139 | {"_sifields._sigfault._bounds._addr_bnd._lower" , 32, 8}, |
140 | {"_sifields._sigfault._bounds._addr_bnd._upper" , 40, 8}, |
141 | {"_sifields._sigfault._bounds._pkey" , 32, 4}, |
142 | {"_sifields._sigpoll.si_band" , 16, 8}, |
143 | {"_sifields._sigpoll.si_fd" , 24, 4}, |
144 | {"_sifields._sigsys._call_addr" , 16, 8}, |
145 | {"_sifields._sigsys._syscall" , 24, 4}, |
146 | {"_sifields._sigsys._arch" , 28, 4}, |
147 | }); |
148 | } |
149 | } |
150 | |
151 | TEST_F(PlatformSiginfoTest, TestLinux_32bit) { |
152 | for (std::string arch : {"i386" , "armv7" }) { |
153 | SCOPED_TRACE(arch); |
154 | InitializeSiginfo(triple: arch + "-pc-linux" ); |
155 | ASSERT_TRUE(siginfo_type); |
156 | |
157 | ExpectFields(container: siginfo_type, |
158 | fields: { |
159 | {"si_signo" , 0, 4}, |
160 | {"si_errno" , 4, 4}, |
161 | {"si_code" , 8, 4}, |
162 | {"_sifields._kill.si_pid" , 12, 4}, |
163 | {"_sifields._kill.si_uid" , 16, 4}, |
164 | {"_sifields._timer.si_tid" , 12, 4}, |
165 | {"_sifields._timer.si_overrun" , 16, 4}, |
166 | {"_sifields._timer.si_sigval" , 20, 4}, |
167 | {"_sifields._rt.si_pid" , 12, 4}, |
168 | {"_sifields._rt.si_uid" , 16, 4}, |
169 | {"_sifields._rt.si_sigval" , 20, 4}, |
170 | {"_sifields._sigchld.si_pid" , 12, 4}, |
171 | {"_sifields._sigchld.si_uid" , 16, 4}, |
172 | {"_sifields._sigchld.si_status" , 20, 4}, |
173 | {"_sifields._sigchld.si_utime" , 24, 4}, |
174 | {"_sifields._sigchld.si_stime" , 28, 4}, |
175 | {"_sifields._sigfault.si_addr" , 12, 4}, |
176 | {"_sifields._sigfault.si_addr_lsb" , 16, 2}, |
177 | {"_sifields._sigfault._bounds._addr_bnd._lower" , 20, 4}, |
178 | {"_sifields._sigfault._bounds._addr_bnd._upper" , 24, 4}, |
179 | {"_sifields._sigfault._bounds._pkey" , 20, 4}, |
180 | {"_sifields._sigpoll.si_band" , 12, 4}, |
181 | {"_sifields._sigpoll.si_fd" , 16, 4}, |
182 | {"_sifields._sigsys._call_addr" , 12, 4}, |
183 | {"_sifields._sigsys._syscall" , 16, 4}, |
184 | {"_sifields._sigsys._arch" , 20, 4}, |
185 | }); |
186 | } |
187 | } |
188 | |
189 | TEST_F(PlatformSiginfoTest, TestFreeBSD_64bit) { |
190 | for (std::string arch : {"x86_64" , "aarch64" }) { |
191 | SCOPED_TRACE(arch); |
192 | InitializeSiginfo(triple: "x86_64-unknown-freebsd13.0" ); |
193 | ASSERT_TRUE(siginfo_type); |
194 | |
195 | ExpectFields(container: siginfo_type, fields: { |
196 | {"si_signo" , 0, 4}, |
197 | {"si_errno" , 4, 4}, |
198 | {"si_code" , 8, 4}, |
199 | {"si_pid" , 12, 4}, |
200 | {"si_uid" , 16, 4}, |
201 | {"si_status" , 20, 4}, |
202 | {"si_addr" , 24, 8}, |
203 | {"si_value" , 32, 8}, |
204 | {"_reason._fault._trapno" , 40, 4}, |
205 | {"_reason._timer._timerid" , 40, 4}, |
206 | {"_reason._timer._overrun" , 44, 4}, |
207 | {"_reason._mesgq._mqd" , 40, 4}, |
208 | {"_reason._poll._band" , 40, 8}, |
209 | }); |
210 | } |
211 | } |
212 | |
213 | TEST_F(PlatformSiginfoTest, TestFreeBSD_32bit) { |
214 | for (std::string arch : {"i386" }) { |
215 | SCOPED_TRACE(arch); |
216 | InitializeSiginfo(triple: arch + "-unknown-freebsd13.0" ); |
217 | ASSERT_TRUE(siginfo_type); |
218 | |
219 | ExpectFields(container: siginfo_type, fields: { |
220 | {"si_signo" , 0, 4}, |
221 | {"si_errno" , 4, 4}, |
222 | {"si_code" , 8, 4}, |
223 | {"si_pid" , 12, 4}, |
224 | {"si_uid" , 16, 4}, |
225 | {"si_status" , 20, 4}, |
226 | {"si_addr" , 24, 4}, |
227 | {"si_value" , 28, 4}, |
228 | {"_reason._fault._trapno" , 32, 4}, |
229 | {"_reason._timer._timerid" , 32, 4}, |
230 | {"_reason._timer._overrun" , 36, 4}, |
231 | {"_reason._mesgq._mqd" , 32, 4}, |
232 | {"_reason._poll._band" , 32, 4}, |
233 | }); |
234 | } |
235 | } |
236 | |
237 | TEST_F(PlatformSiginfoTest, TestNetBSD_64bit) { |
238 | for (std::string arch : {"x86_64" }) { |
239 | SCOPED_TRACE(arch); |
240 | InitializeSiginfo(triple: arch + "-unknown-netbsd9.0" ); |
241 | ASSERT_TRUE(siginfo_type); |
242 | |
243 | ExpectFields( |
244 | container: siginfo_type, |
245 | fields: { |
246 | {"_info._signo" , 0, 4}, |
247 | {"_info._code" , 4, 4}, |
248 | {"_info._errno" , 8, 4}, |
249 | {"_info._reason._rt._pid" , 16, 4}, |
250 | {"_info._reason._rt._uid" , 20, 4}, |
251 | {"_info._reason._rt._value" , 24, 8}, |
252 | {"_info._reason._child._pid" , 16, 4}, |
253 | {"_info._reason._child._uid" , 20, 4}, |
254 | {"_info._reason._child._status" , 24, 4}, |
255 | {"_info._reason._child._utime" , 28, 4}, |
256 | {"_info._reason._child._stime" , 32, 4}, |
257 | {"_info._reason._fault._addr" , 16, 8}, |
258 | {"_info._reason._fault._trap" , 24, 4}, |
259 | {"_info._reason._fault._trap2" , 28, 4}, |
260 | {"_info._reason._fault._trap3" , 32, 4}, |
261 | {"_info._reason._poll._band" , 16, 8}, |
262 | {"_info._reason._poll._fd" , 24, 4}, |
263 | {"_info._reason._syscall._sysnum" , 16, 4}, |
264 | {"_info._reason._syscall._retval" , 20, 8}, |
265 | {"_info._reason._syscall._error" , 28, 4}, |
266 | {"_info._reason._syscall._args" , 32, 64}, |
267 | {"_info._reason._ptrace_state._pe_report_event" , 16, 4}, |
268 | {"_info._reason._ptrace_state._option._pe_other_pid" , 20, 4}, |
269 | {"_info._reason._ptrace_state._option._pe_lwp" , 20, 4}, |
270 | }); |
271 | } |
272 | } |
273 | |
274 | TEST_F(PlatformSiginfoTest, TestNetBSD_32bit) { |
275 | for (std::string arch : {"i386" }) { |
276 | SCOPED_TRACE(arch); |
277 | InitializeSiginfo(triple: arch + "-unknown-netbsd9.0" ); |
278 | ASSERT_TRUE(siginfo_type); |
279 | |
280 | ExpectFields( |
281 | container: siginfo_type, |
282 | fields: { |
283 | {"_info._signo" , 0, 4}, |
284 | {"_info._code" , 4, 4}, |
285 | {"_info._errno" , 8, 4}, |
286 | {"_info._reason._rt._pid" , 12, 4}, |
287 | {"_info._reason._rt._uid" , 16, 4}, |
288 | {"_info._reason._rt._value" , 20, 4}, |
289 | {"_info._reason._child._pid" , 12, 4}, |
290 | {"_info._reason._child._uid" , 16, 4}, |
291 | {"_info._reason._child._status" , 20, 4}, |
292 | {"_info._reason._child._utime" , 24, 4}, |
293 | {"_info._reason._child._stime" , 28, 4}, |
294 | {"_info._reason._fault._addr" , 12, 4}, |
295 | {"_info._reason._fault._trap" , 16, 4}, |
296 | {"_info._reason._fault._trap2" , 20, 4}, |
297 | {"_info._reason._fault._trap3" , 24, 4}, |
298 | {"_info._reason._poll._band" , 12, 4}, |
299 | {"_info._reason._poll._fd" , 16, 4}, |
300 | {"_info._reason._syscall._sysnum" , 12, 4}, |
301 | {"_info._reason._syscall._retval" , 16, 8}, |
302 | {"_info._reason._syscall._error" , 24, 4}, |
303 | {"_info._reason._syscall._args" , 28, 64}, |
304 | {"_info._reason._ptrace_state._pe_report_event" , 12, 4}, |
305 | {"_info._reason._ptrace_state._option._pe_other_pid" , 16, 4}, |
306 | {"_info._reason._ptrace_state._option._pe_lwp" , 16, 4}, |
307 | }); |
308 | } |
309 | } |
310 | |