1 //===-- ThreadElfCore.cpp --------------------------------------*- C++ -*-===// 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 "lldb/Target/RegisterContext.h" 10 #include "lldb/Target/StopInfo.h" 11 #include "lldb/Target/Target.h" 12 #include "lldb/Target/Unwind.h" 13 #include "lldb/Utility/DataExtractor.h" 14 #include "lldb/Utility/Log.h" 15 16 #include "Plugins/Process/Utility/RegisterContextFreeBSD_i386.h" 17 #include "Plugins/Process/Utility/RegisterContextFreeBSD_mips64.h" 18 #include "Plugins/Process/Utility/RegisterContextFreeBSD_powerpc.h" 19 #include "Plugins/Process/Utility/RegisterContextFreeBSD_x86_64.h" 20 #include "Plugins/Process/Utility/RegisterContextLinux_i386.h" 21 #include "Plugins/Process/Utility/RegisterContextLinux_mips.h" 22 #include "Plugins/Process/Utility/RegisterContextLinux_mips64.h" 23 #include "Plugins/Process/Utility/RegisterContextLinux_s390x.h" 24 #include "Plugins/Process/Utility/RegisterContextLinux_x86_64.h" 25 #include "Plugins/Process/Utility/RegisterContextNetBSD_x86_64.h" 26 #include "Plugins/Process/Utility/RegisterContextOpenBSD_i386.h" 27 #include "Plugins/Process/Utility/RegisterContextOpenBSD_x86_64.h" 28 #include "Plugins/Process/Utility/RegisterInfoPOSIX_arm.h" 29 #include "Plugins/Process/Utility/RegisterInfoPOSIX_arm64.h" 30 #include "Plugins/Process/Utility/RegisterInfoPOSIX_ppc64le.h" 31 #include "ProcessElfCore.h" 32 #include "RegisterContextPOSIXCore_arm.h" 33 #include "RegisterContextPOSIXCore_arm64.h" 34 #include "RegisterContextPOSIXCore_mips64.h" 35 #include "RegisterContextPOSIXCore_powerpc.h" 36 #include "RegisterContextPOSIXCore_ppc64le.h" 37 #include "RegisterContextPOSIXCore_s390x.h" 38 #include "RegisterContextPOSIXCore_x86_64.h" 39 #include "ThreadElfCore.h" 40 41 #include <memory> 42 43 using namespace lldb; 44 using namespace lldb_private; 45 46 //---------------------------------------------------------------------- 47 // Construct a Thread object with given data 48 //---------------------------------------------------------------------- 49 ThreadElfCore::ThreadElfCore(Process &process, const ThreadData &td) 50 : Thread(process, td.tid), m_thread_name(td.name), m_thread_reg_ctx_sp(), 51 m_signo(td.signo), m_gpregset_data(td.gpregset), m_notes(td.notes) {} 52 53 ThreadElfCore::~ThreadElfCore() { DestroyThread(); } 54 55 void ThreadElfCore::RefreshStateAfterStop() { 56 GetRegisterContext()->InvalidateIfNeeded(false); 57 } 58 59 RegisterContextSP ThreadElfCore::GetRegisterContext() { 60 if (!m_reg_context_sp) { 61 m_reg_context_sp = CreateRegisterContextForFrame(nullptr); 62 } 63 return m_reg_context_sp; 64 } 65 66 RegisterContextSP 67 ThreadElfCore::CreateRegisterContextForFrame(StackFrame *frame) { 68 RegisterContextSP reg_ctx_sp; 69 uint32_t concrete_frame_idx = 0; 70 Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD)); 71 72 if (frame) 73 concrete_frame_idx = frame->GetConcreteFrameIndex(); 74 75 if (concrete_frame_idx == 0) { 76 if (m_thread_reg_ctx_sp) 77 return m_thread_reg_ctx_sp; 78 79 ProcessElfCore *process = static_cast<ProcessElfCore *>(GetProcess().get()); 80 ArchSpec arch = process->GetArchitecture(); 81 RegisterInfoInterface *reg_interface = nullptr; 82 83 switch (arch.GetTriple().getOS()) { 84 case llvm::Triple::FreeBSD: { 85 switch (arch.GetMachine()) { 86 case llvm::Triple::aarch64: 87 reg_interface = new RegisterInfoPOSIX_arm64(arch); 88 break; 89 case llvm::Triple::arm: 90 reg_interface = new RegisterInfoPOSIX_arm(arch); 91 break; 92 case llvm::Triple::ppc: 93 reg_interface = new RegisterContextFreeBSD_powerpc32(arch); 94 break; 95 case llvm::Triple::ppc64: 96 reg_interface = new RegisterContextFreeBSD_powerpc64(arch); 97 break; 98 case llvm::Triple::mips64: 99 reg_interface = new RegisterContextFreeBSD_mips64(arch); 100 break; 101 case llvm::Triple::x86: 102 reg_interface = new RegisterContextFreeBSD_i386(arch); 103 break; 104 case llvm::Triple::x86_64: 105 reg_interface = new RegisterContextFreeBSD_x86_64(arch); 106 break; 107 default: 108 break; 109 } 110 break; 111 } 112 113 case llvm::Triple::NetBSD: { 114 switch (arch.GetMachine()) { 115 case llvm::Triple::x86_64: 116 reg_interface = new RegisterContextNetBSD_x86_64(arch); 117 break; 118 default: 119 break; 120 } 121 break; 122 } 123 124 case llvm::Triple::Linux: { 125 switch (arch.GetMachine()) { 126 case llvm::Triple::arm: 127 reg_interface = new RegisterInfoPOSIX_arm(arch); 128 break; 129 case llvm::Triple::aarch64: 130 reg_interface = new RegisterInfoPOSIX_arm64(arch); 131 break; 132 case llvm::Triple::mipsel: 133 case llvm::Triple::mips: 134 reg_interface = new RegisterContextLinux_mips(arch); 135 break; 136 case llvm::Triple::mips64el: 137 case llvm::Triple::mips64: 138 reg_interface = new RegisterContextLinux_mips64(arch); 139 break; 140 case llvm::Triple::ppc64le: 141 reg_interface = new RegisterInfoPOSIX_ppc64le(arch); 142 break; 143 case llvm::Triple::systemz: 144 reg_interface = new RegisterContextLinux_s390x(arch); 145 break; 146 case llvm::Triple::x86: 147 reg_interface = new RegisterContextLinux_i386(arch); 148 break; 149 case llvm::Triple::x86_64: 150 reg_interface = new RegisterContextLinux_x86_64(arch); 151 break; 152 default: 153 break; 154 } 155 break; 156 } 157 158 case llvm::Triple::OpenBSD: { 159 switch (arch.GetMachine()) { 160 case llvm::Triple::aarch64: 161 reg_interface = new RegisterInfoPOSIX_arm64(arch); 162 break; 163 case llvm::Triple::arm: 164 reg_interface = new RegisterInfoPOSIX_arm(arch); 165 break; 166 case llvm::Triple::x86: 167 reg_interface = new RegisterContextOpenBSD_i386(arch); 168 break; 169 case llvm::Triple::x86_64: 170 reg_interface = new RegisterContextOpenBSD_x86_64(arch); 171 break; 172 default: 173 break; 174 } 175 break; 176 } 177 178 default: 179 break; 180 } 181 182 if (!reg_interface) { 183 if (log) 184 log->Printf("elf-core::%s:: Architecture(%d) or OS(%d) not supported", 185 __FUNCTION__, arch.GetMachine(), arch.GetTriple().getOS()); 186 assert(false && "Architecture or OS not supported"); 187 } 188 189 switch (arch.GetMachine()) { 190 case llvm::Triple::aarch64: 191 m_thread_reg_ctx_sp = std::make_shared<RegisterContextCorePOSIX_arm64>( 192 *this, reg_interface, m_gpregset_data, m_notes); 193 break; 194 case llvm::Triple::arm: 195 m_thread_reg_ctx_sp = std::make_shared<RegisterContextCorePOSIX_arm>( 196 *this, reg_interface, m_gpregset_data, m_notes); 197 break; 198 case llvm::Triple::mipsel: 199 case llvm::Triple::mips: 200 m_thread_reg_ctx_sp = std::make_shared<RegisterContextCorePOSIX_mips64>( 201 *this, reg_interface, m_gpregset_data, m_notes); 202 break; 203 case llvm::Triple::mips64: 204 case llvm::Triple::mips64el: 205 m_thread_reg_ctx_sp = std::make_shared<RegisterContextCorePOSIX_mips64>( 206 *this, reg_interface, m_gpregset_data, m_notes); 207 break; 208 case llvm::Triple::ppc: 209 case llvm::Triple::ppc64: 210 m_thread_reg_ctx_sp = std::make_shared<RegisterContextCorePOSIX_powerpc>( 211 *this, reg_interface, m_gpregset_data, m_notes); 212 break; 213 case llvm::Triple::ppc64le: 214 m_thread_reg_ctx_sp = std::make_shared<RegisterContextCorePOSIX_ppc64le>( 215 *this, reg_interface, m_gpregset_data, m_notes); 216 break; 217 case llvm::Triple::systemz: 218 m_thread_reg_ctx_sp = std::make_shared<RegisterContextCorePOSIX_s390x>( 219 *this, reg_interface, m_gpregset_data, m_notes); 220 break; 221 case llvm::Triple::x86: 222 case llvm::Triple::x86_64: 223 m_thread_reg_ctx_sp = std::make_shared<RegisterContextCorePOSIX_x86_64>( 224 *this, reg_interface, m_gpregset_data, m_notes); 225 break; 226 default: 227 break; 228 } 229 230 reg_ctx_sp = m_thread_reg_ctx_sp; 231 } else { 232 Unwind *unwinder = GetUnwinder(); 233 if (unwinder != nullptr) 234 reg_ctx_sp = unwinder->CreateRegisterContextForFrame(frame); 235 } 236 return reg_ctx_sp; 237 } 238 239 bool ThreadElfCore::CalculateStopInfo() { 240 ProcessSP process_sp(GetProcess()); 241 if (process_sp) { 242 SetStopInfo(StopInfo::CreateStopReasonWithSignal(*this, m_signo)); 243 return true; 244 } 245 return false; 246 } 247 248 //---------------------------------------------------------------- 249 // Parse PRSTATUS from NOTE entry 250 //---------------------------------------------------------------- 251 ELFLinuxPrStatus::ELFLinuxPrStatus() { 252 memset(this, 0, sizeof(ELFLinuxPrStatus)); 253 } 254 255 size_t ELFLinuxPrStatus::GetSize(const lldb_private::ArchSpec &arch) { 256 constexpr size_t mips_linux_pr_status_size_o32 = 96; 257 constexpr size_t mips_linux_pr_status_size_n32 = 72; 258 if (arch.IsMIPS()) { 259 std::string abi = arch.GetTargetABI(); 260 assert(!abi.empty() && "ABI is not set"); 261 if (!abi.compare("n64")) 262 return sizeof(ELFLinuxPrStatus); 263 else if (!abi.compare("o32")) 264 return mips_linux_pr_status_size_o32; 265 // N32 ABI 266 return mips_linux_pr_status_size_n32; 267 } 268 switch (arch.GetCore()) { 269 case lldb_private::ArchSpec::eCore_s390x_generic: 270 case lldb_private::ArchSpec::eCore_x86_64_x86_64: 271 case lldb_private::ArchSpec::eCore_ppc64le_generic: 272 return sizeof(ELFLinuxPrStatus); 273 case lldb_private::ArchSpec::eCore_x86_32_i386: 274 case lldb_private::ArchSpec::eCore_x86_32_i486: 275 return 72; 276 default: 277 return 0; 278 } 279 } 280 281 Status ELFLinuxPrStatus::Parse(const DataExtractor &data, 282 const ArchSpec &arch) { 283 Status error; 284 if (GetSize(arch) > data.GetByteSize()) { 285 error.SetErrorStringWithFormat( 286 "NT_PRSTATUS size should be %zu, but the remaining bytes are: %" PRIu64, 287 GetSize(arch), data.GetByteSize()); 288 return error; 289 } 290 291 // Read field by field to correctly account for endianess of both the core 292 // dump and the platform running lldb. 293 offset_t offset = 0; 294 si_signo = data.GetU32(&offset); 295 si_code = data.GetU32(&offset); 296 si_errno = data.GetU32(&offset); 297 298 pr_cursig = data.GetU16(&offset); 299 offset += 2; // pad 300 301 pr_sigpend = data.GetPointer(&offset); 302 pr_sighold = data.GetPointer(&offset); 303 304 pr_pid = data.GetU32(&offset); 305 pr_ppid = data.GetU32(&offset); 306 pr_pgrp = data.GetU32(&offset); 307 pr_sid = data.GetU32(&offset); 308 309 pr_utime.tv_sec = data.GetPointer(&offset); 310 pr_utime.tv_usec = data.GetPointer(&offset); 311 312 pr_stime.tv_sec = data.GetPointer(&offset); 313 pr_stime.tv_usec = data.GetPointer(&offset); 314 315 pr_cutime.tv_sec = data.GetPointer(&offset); 316 pr_cutime.tv_usec = data.GetPointer(&offset); 317 318 pr_cstime.tv_sec = data.GetPointer(&offset); 319 pr_cstime.tv_usec = data.GetPointer(&offset); 320 321 return error; 322 } 323 324 //---------------------------------------------------------------- 325 // Parse PRPSINFO from NOTE entry 326 //---------------------------------------------------------------- 327 ELFLinuxPrPsInfo::ELFLinuxPrPsInfo() { 328 memset(this, 0, sizeof(ELFLinuxPrPsInfo)); 329 } 330 331 size_t ELFLinuxPrPsInfo::GetSize(const lldb_private::ArchSpec &arch) { 332 constexpr size_t mips_linux_pr_psinfo_size_o32_n32 = 128; 333 if (arch.IsMIPS()) { 334 uint8_t address_byte_size = arch.GetAddressByteSize(); 335 if (address_byte_size == 8) 336 return sizeof(ELFLinuxPrPsInfo); 337 return mips_linux_pr_psinfo_size_o32_n32; 338 } 339 340 switch (arch.GetCore()) { 341 case lldb_private::ArchSpec::eCore_s390x_generic: 342 case lldb_private::ArchSpec::eCore_x86_64_x86_64: 343 return sizeof(ELFLinuxPrPsInfo); 344 case lldb_private::ArchSpec::eCore_x86_32_i386: 345 case lldb_private::ArchSpec::eCore_x86_32_i486: 346 return 124; 347 default: 348 return 0; 349 } 350 } 351 352 Status ELFLinuxPrPsInfo::Parse(const DataExtractor &data, 353 const ArchSpec &arch) { 354 Status error; 355 ByteOrder byteorder = data.GetByteOrder(); 356 if (GetSize(arch) > data.GetByteSize()) { 357 error.SetErrorStringWithFormat( 358 "NT_PRPSINFO size should be %zu, but the remaining bytes are: %" PRIu64, 359 GetSize(arch), data.GetByteSize()); 360 return error; 361 } 362 size_t size = 0; 363 offset_t offset = 0; 364 365 pr_state = data.GetU8(&offset); 366 pr_sname = data.GetU8(&offset); 367 pr_zomb = data.GetU8(&offset); 368 pr_nice = data.GetU8(&offset); 369 if (data.GetAddressByteSize() == 8) { 370 // Word align the next field on 64 bit. 371 offset += 4; 372 } 373 374 pr_flag = data.GetPointer(&offset); 375 376 if (arch.IsMIPS()) { 377 // The pr_uid and pr_gid is always 32 bit irrespective of platforms 378 pr_uid = data.GetU32(&offset); 379 pr_gid = data.GetU32(&offset); 380 } else { 381 // 16 bit on 32 bit platforms, 32 bit on 64 bit platforms 382 pr_uid = data.GetMaxU64(&offset, data.GetAddressByteSize() >> 1); 383 pr_gid = data.GetMaxU64(&offset, data.GetAddressByteSize() >> 1); 384 } 385 386 pr_pid = data.GetU32(&offset); 387 pr_ppid = data.GetU32(&offset); 388 pr_pgrp = data.GetU32(&offset); 389 pr_sid = data.GetU32(&offset); 390 391 size = 16; 392 data.ExtractBytes(offset, size, byteorder, pr_fname); 393 offset += size; 394 395 size = 80; 396 data.ExtractBytes(offset, size, byteorder, pr_psargs); 397 offset += size; 398 399 return error; 400 } 401 402 //---------------------------------------------------------------- 403 // Parse SIGINFO from NOTE entry 404 //---------------------------------------------------------------- 405 ELFLinuxSigInfo::ELFLinuxSigInfo() { memset(this, 0, sizeof(ELFLinuxSigInfo)); } 406 407 size_t ELFLinuxSigInfo::GetSize(const lldb_private::ArchSpec &arch) { 408 if (arch.IsMIPS()) 409 return sizeof(ELFLinuxSigInfo); 410 switch (arch.GetCore()) { 411 case lldb_private::ArchSpec::eCore_x86_64_x86_64: 412 return sizeof(ELFLinuxSigInfo); 413 case lldb_private::ArchSpec::eCore_s390x_generic: 414 case lldb_private::ArchSpec::eCore_x86_32_i386: 415 case lldb_private::ArchSpec::eCore_x86_32_i486: 416 return 12; 417 default: 418 return 0; 419 } 420 } 421 422 Status ELFLinuxSigInfo::Parse(const DataExtractor &data, const ArchSpec &arch) { 423 Status error; 424 if (GetSize(arch) > data.GetByteSize()) { 425 error.SetErrorStringWithFormat( 426 "NT_SIGINFO size should be %zu, but the remaining bytes are: %" PRIu64, 427 GetSize(arch), data.GetByteSize()); 428 return error; 429 } 430 431 // Parsing from a 32 bit ELF core file, and populating/reusing the structure 432 // properly, because the struct is for the 64 bit version 433 offset_t offset = 0; 434 si_signo = data.GetU32(&offset); 435 si_code = data.GetU32(&offset); 436 si_errno = data.GetU32(&offset); 437 438 return error; 439 } 440