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