ThreadElfCore.cpp revision 314564
1//===-- ThreadElfCore.cpp --------------------------------------*- C++ -*-===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9 10#include "lldb/Core/DataExtractor.h" 11#include "lldb/Core/Log.h" 12#include "lldb/Target/RegisterContext.h" 13#include "lldb/Target/StopInfo.h" 14#include "lldb/Target/Target.h" 15#include "lldb/Target/Unwind.h" 16 17#include "Plugins/Process/Utility/RegisterContextFreeBSD_arm.h" 18#include "Plugins/Process/Utility/RegisterContextFreeBSD_i386.h" 19#include "Plugins/Process/Utility/RegisterContextFreeBSD_mips64.h" 20#include "Plugins/Process/Utility/RegisterContextFreeBSD_powerpc.h" 21#include "Plugins/Process/Utility/RegisterContextFreeBSD_x86_64.h" 22#include "Plugins/Process/Utility/RegisterContextLinux_arm.h" 23#include "Plugins/Process/Utility/RegisterContextLinux_i386.h" 24//#include "Plugins/Process/Utility/RegisterContextLinux_s390x.h" 25#include "Plugins/Process/Utility/RegisterContextLinux_x86_64.h" 26#include "Plugins/Process/Utility/RegisterInfoPOSIX_arm64.h" 27#include "ProcessElfCore.h" 28#include "RegisterContextPOSIXCore_arm.h" 29#include "RegisterContextPOSIXCore_arm64.h" 30#include "RegisterContextPOSIXCore_mips64.h" 31#include "RegisterContextPOSIXCore_powerpc.h" 32//#include "RegisterContextPOSIXCore_s390x.h" 33#include "RegisterContextPOSIXCore_x86_64.h" 34#include "ThreadElfCore.h" 35 36using namespace lldb; 37using namespace lldb_private; 38 39//---------------------------------------------------------------------- 40// Construct a Thread object with given data 41//---------------------------------------------------------------------- 42ThreadElfCore::ThreadElfCore(Process &process, const ThreadData &td) 43 : Thread(process, td.tid), m_thread_name(td.name), m_thread_reg_ctx_sp(), 44 m_signo(td.signo), m_gpregset_data(td.gpregset), 45 m_fpregset_data(td.fpregset), m_vregset_data(td.vregset) {} 46 47ThreadElfCore::~ThreadElfCore() { DestroyThread(); } 48 49void ThreadElfCore::RefreshStateAfterStop() { 50 GetRegisterContext()->InvalidateIfNeeded(false); 51} 52 53void ThreadElfCore::ClearStackFrames() { 54 Unwind *unwinder = GetUnwinder(); 55 if (unwinder) 56 unwinder->Clear(); 57 Thread::ClearStackFrames(); 58} 59 60RegisterContextSP ThreadElfCore::GetRegisterContext() { 61 if (m_reg_context_sp.get() == NULL) { 62 m_reg_context_sp = CreateRegisterContextForFrame(NULL); 63 } 64 return m_reg_context_sp; 65} 66 67RegisterContextSP 68ThreadElfCore::CreateRegisterContextForFrame(StackFrame *frame) { 69 RegisterContextSP reg_ctx_sp; 70 uint32_t concrete_frame_idx = 0; 71 Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD)); 72 73 if (frame) 74 concrete_frame_idx = frame->GetConcreteFrameIndex(); 75 76 if (concrete_frame_idx == 0) { 77 if (m_thread_reg_ctx_sp) 78 return m_thread_reg_ctx_sp; 79 80 ProcessElfCore *process = static_cast<ProcessElfCore *>(GetProcess().get()); 81 ArchSpec arch = process->GetArchitecture(); 82 RegisterInfoInterface *reg_interface = NULL; 83 84 switch (arch.GetTriple().getOS()) { 85 case llvm::Triple::FreeBSD: { 86 switch (arch.GetMachine()) { 87 case llvm::Triple::aarch64: 88 reg_interface = new RegisterInfoPOSIX_arm64(arch); 89 break; 90 case llvm::Triple::arm: 91 reg_interface = new RegisterContextFreeBSD_arm(arch); 92 break; 93 case llvm::Triple::ppc: 94 reg_interface = new RegisterContextFreeBSD_powerpc32(arch); 95 break; 96 case llvm::Triple::ppc64: 97 reg_interface = new RegisterContextFreeBSD_powerpc64(arch); 98 break; 99 case llvm::Triple::mips64: 100 reg_interface = new RegisterContextFreeBSD_mips64(arch); 101 break; 102 case llvm::Triple::x86: 103 reg_interface = new RegisterContextFreeBSD_i386(arch); 104 break; 105 case llvm::Triple::x86_64: 106 reg_interface = new RegisterContextFreeBSD_x86_64(arch); 107 break; 108 default: 109 break; 110 } 111 break; 112 } 113 114 case llvm::Triple::Linux: { 115 switch (arch.GetMachine()) { 116 case llvm::Triple::arm: 117 reg_interface = new RegisterContextLinux_arm(arch); 118 break; 119 case llvm::Triple::aarch64: 120 reg_interface = new RegisterInfoPOSIX_arm64(arch); 121 break; 122// case llvm::Triple::systemz: 123// reg_interface = new RegisterContextLinux_s390x(arch); 124// break; 125 case llvm::Triple::x86: 126 reg_interface = new RegisterContextLinux_i386(arch); 127 break; 128 case llvm::Triple::x86_64: 129 reg_interface = new RegisterContextLinux_x86_64(arch); 130 break; 131 default: 132 break; 133 } 134 break; 135 } 136 137 default: 138 break; 139 } 140 141 if (!reg_interface) { 142 if (log) 143 log->Printf("elf-core::%s:: Architecture(%d) or OS(%d) not supported", 144 __FUNCTION__, arch.GetMachine(), arch.GetTriple().getOS()); 145 assert(false && "Architecture or OS not supported"); 146 } 147 148 switch (arch.GetMachine()) { 149 case llvm::Triple::aarch64: 150 m_thread_reg_ctx_sp.reset(new RegisterContextCorePOSIX_arm64( 151 *this, reg_interface, m_gpregset_data, m_fpregset_data)); 152 break; 153 case llvm::Triple::arm: 154 m_thread_reg_ctx_sp.reset(new RegisterContextCorePOSIX_arm( 155 *this, reg_interface, m_gpregset_data, m_fpregset_data)); 156 break; 157 case llvm::Triple::mips64: 158 m_thread_reg_ctx_sp.reset(new RegisterContextCorePOSIX_mips64( 159 *this, reg_interface, m_gpregset_data, m_fpregset_data)); 160 break; 161 case llvm::Triple::ppc: 162 case llvm::Triple::ppc64: 163 m_thread_reg_ctx_sp.reset(new RegisterContextCorePOSIX_powerpc( 164 *this, reg_interface, m_gpregset_data, m_fpregset_data, 165 m_vregset_data)); 166 break; 167// case llvm::Triple::systemz: 168// m_thread_reg_ctx_sp.reset(new RegisterContextCorePOSIX_s390x( 169// *this, reg_interface, m_gpregset_data, m_fpregset_data)); 170// break; 171 case llvm::Triple::x86: 172 case llvm::Triple::x86_64: 173 m_thread_reg_ctx_sp.reset(new RegisterContextCorePOSIX_x86_64( 174 *this, reg_interface, m_gpregset_data, m_fpregset_data)); 175 break; 176 default: 177 break; 178 } 179 180 reg_ctx_sp = m_thread_reg_ctx_sp; 181 } else if (m_unwinder_ap.get()) { 182 reg_ctx_sp = m_unwinder_ap->CreateRegisterContextForFrame(frame); 183 } 184 return reg_ctx_sp; 185} 186 187bool ThreadElfCore::CalculateStopInfo() { 188 ProcessSP process_sp(GetProcess()); 189 if (process_sp) { 190 SetStopInfo(StopInfo::CreateStopReasonWithSignal(*this, m_signo)); 191 return true; 192 } 193 return false; 194} 195 196//---------------------------------------------------------------- 197// Parse PRSTATUS from NOTE entry 198//---------------------------------------------------------------- 199ELFLinuxPrStatus::ELFLinuxPrStatus() { 200 memset(this, 0, sizeof(ELFLinuxPrStatus)); 201} 202 203Error ELFLinuxPrStatus::Parse(DataExtractor &data, ArchSpec &arch) { 204 Error error; 205 if (GetSize(arch) > data.GetByteSize()) { 206 error.SetErrorStringWithFormat( 207 "NT_PRSTATUS size should be %zu, but the remaining bytes are: %" PRIu64, 208 GetSize(arch), data.GetByteSize()); 209 return error; 210 } 211 212 // Read field by field to correctly account for endianess 213 // of both the core dump and the platform running lldb. 214 offset_t offset = 0; 215 si_signo = data.GetU32(&offset); 216 si_code = data.GetU32(&offset); 217 si_errno = data.GetU32(&offset); 218 219 pr_cursig = data.GetU16(&offset); 220 offset += 2; // pad 221 222 pr_sigpend = data.GetPointer(&offset); 223 pr_sighold = data.GetPointer(&offset); 224 225 pr_pid = data.GetU32(&offset); 226 pr_ppid = data.GetU32(&offset); 227 pr_pgrp = data.GetU32(&offset); 228 pr_sid = data.GetU32(&offset); 229 230 pr_utime.tv_sec = data.GetPointer(&offset); 231 pr_utime.tv_usec = data.GetPointer(&offset); 232 233 pr_stime.tv_sec = data.GetPointer(&offset); 234 pr_stime.tv_usec = data.GetPointer(&offset); 235 236 pr_cutime.tv_sec = data.GetPointer(&offset); 237 pr_cutime.tv_usec = data.GetPointer(&offset); 238 239 pr_cstime.tv_sec = data.GetPointer(&offset); 240 pr_cstime.tv_usec = data.GetPointer(&offset); 241 242 243 return error; 244} 245 246//---------------------------------------------------------------- 247// Parse PRPSINFO from NOTE entry 248//---------------------------------------------------------------- 249ELFLinuxPrPsInfo::ELFLinuxPrPsInfo() { 250 memset(this, 0, sizeof(ELFLinuxPrPsInfo)); 251} 252 253Error ELFLinuxPrPsInfo::Parse(DataExtractor &data, ArchSpec &arch) { 254 Error error; 255 ByteOrder byteorder = data.GetByteOrder(); 256 if (GetSize(arch) > data.GetByteSize()) { 257 error.SetErrorStringWithFormat( 258 "NT_PRPSINFO size should be %zu, but the remaining bytes are: %" PRIu64, 259 GetSize(arch), data.GetByteSize()); 260 return error; 261 } 262 size_t size = 0; 263 offset_t offset = 0; 264 265 pr_state = data.GetU8(&offset); 266 pr_sname = data.GetU8(&offset); 267 pr_zomb = data.GetU8(&offset); 268 pr_nice = data.GetU8(&offset); 269 if (data.GetAddressByteSize() == 8) { 270 // Word align the next field on 64 bit. 271 offset += 4; 272 } 273 274 pr_flag = data.GetPointer(&offset); 275 276 // 16 bit on 32 bit platforms, 32 bit on 64 bit platforms 277 pr_uid = data.GetMaxU64(&offset, data.GetAddressByteSize() >> 1); 278 pr_gid = data.GetMaxU64(&offset, data.GetAddressByteSize() >> 1); 279 280 pr_pid = data.GetU32(&offset); 281 pr_ppid = data.GetU32(&offset); 282 pr_pgrp = data.GetU32(&offset); 283 pr_sid = data.GetU32(&offset); 284 285 size = 16; 286 data.ExtractBytes(offset, size, byteorder, pr_fname); 287 offset += size; 288 289 size = 80; 290 data.ExtractBytes(offset, size, byteorder, pr_psargs); 291 offset += size; 292 293 return error; 294} 295 296//---------------------------------------------------------------- 297// Parse SIGINFO from NOTE entry 298//---------------------------------------------------------------- 299ELFLinuxSigInfo::ELFLinuxSigInfo() { 300 memset(this, 0, sizeof(ELFLinuxSigInfo)); 301} 302 303Error ELFLinuxSigInfo::Parse(DataExtractor &data, const ArchSpec &arch) { 304 Error error; 305 if (GetSize(arch) > data.GetByteSize()) { 306 error.SetErrorStringWithFormat( 307 "NT_SIGINFO size should be %zu, but the remaining bytes are: %" PRIu64, 308 GetSize(arch), data.GetByteSize()); 309 return error; 310 } 311 312 // Parsing from a 32 bit ELF core file, and populating/reusing the structure 313 // properly, because the struct is for the 64 bit version 314 offset_t offset = 0; 315 si_signo = data.GetU32(&offset); 316 si_code = data.GetU32(&offset); 317 si_errno = data.GetU32(&offset); 318 319 return error; 320} 321