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