LinuxThread.cpp revision 708b4470d260c6fa72eb78bdc694e7c96f5f13a9
1//===-- LinuxThread.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// C Includes 11#include <errno.h> 12 13// C++ Includes 14// Other libraries and framework includes 15#include "lldb/Host/Host.h" 16#include "lldb/Target/Process.h" 17#include "lldb/Target/StopInfo.h" 18#include "lldb/Target/Target.h" 19 20#include "LinuxThread.h" 21#include "ProcessLinux.h" 22#include "ProcessMonitor.h" 23#include "RegisterContextLinux_i386.h" 24#include "RegisterContextLinux_x86_64.h" 25#include "UnwindLLDB.h" 26 27using namespace lldb_private; 28 29LinuxThread::LinuxThread(Process &process, lldb::tid_t tid) 30 : Thread(process, tid), 31 m_frame_ap(0), 32 m_stop_info_id(0), 33 m_note(eNone) 34{ 35} 36 37LinuxThread::~LinuxThread() 38{ 39 DestroyThread(); 40} 41 42ProcessMonitor & 43LinuxThread::GetMonitor() 44{ 45 ProcessLinux &process = static_cast<ProcessLinux&>(GetProcess()); 46 return process.GetMonitor(); 47} 48 49void 50LinuxThread::RefreshStateAfterStop() 51{ 52 RefreshPrivateStopReason(); 53} 54 55const char * 56LinuxThread::GetInfo() 57{ 58 return NULL; 59} 60 61lldb::RegisterContextSP 62LinuxThread::GetRegisterContext() 63{ 64 if (!m_reg_context_sp) 65 { 66 ArchSpec arch = Host::GetArchitecture(); 67 68 switch (arch.GetCore()) 69 { 70 default: 71 assert(false && "CPU type not supported!"); 72 break; 73 74 case ArchSpec::eCore_x86_32_i386: 75 case ArchSpec::eCore_x86_32_i486: 76 case ArchSpec::eCore_x86_32_i486sx: 77 m_reg_context_sp.reset(new RegisterContextLinux_i386(*this, 0)); 78 break; 79 80 case ArchSpec::eCore_x86_64_x86_64: 81 m_reg_context_sp.reset(new RegisterContextLinux_x86_64(*this, 0)); 82 break; 83 } 84 } 85 return m_reg_context_sp; 86} 87 88bool 89LinuxThread::SaveFrameZeroState(RegisterCheckpoint &checkpoint) 90{ 91 return false; 92} 93 94bool 95LinuxThread::RestoreSaveFrameZero(const RegisterCheckpoint &checkpoint) 96{ 97 return false; 98} 99 100lldb::RegisterContextSP 101LinuxThread::CreateRegisterContextForFrame(lldb_private::StackFrame *frame) 102{ 103 lldb::RegisterContextSP reg_ctx_sp; 104 uint32_t concrete_frame_idx = 0; 105 106 if (frame) 107 concrete_frame_idx = frame->GetConcreteFrameIndex(); 108 109 if (concrete_frame_idx == 0) 110 reg_ctx_sp = GetRegisterContext(); 111 else 112 reg_ctx_sp = GetUnwinder()->CreateRegisterContextForFrame(frame); 113 114 return reg_ctx_sp; 115} 116 117lldb::StopInfoSP 118LinuxThread::GetPrivateStopReason() 119{ 120 const uint32_t process_stop_id = GetProcess().GetStopID(); 121 122 if (m_stop_info_id != process_stop_id || !m_stop_info || !m_stop_info->IsValid()) 123 RefreshPrivateStopReason(); 124 return m_stop_info; 125} 126 127Unwind * 128LinuxThread::GetUnwinder() 129{ 130 if (m_unwinder_ap.get() == NULL) 131 m_unwinder_ap.reset(new UnwindLLDB(*this)); 132 133 return m_unwinder_ap.get(); 134} 135 136bool 137LinuxThread::WillResume(lldb::StateType resume_state) 138{ 139 SetResumeState(resume_state); 140 141 ClearStackFrames(); 142 if (m_unwinder_ap.get()) 143 m_unwinder_ap->Clear(); 144 145 return Thread::WillResume(resume_state); 146} 147 148bool 149LinuxThread::Resume() 150{ 151 lldb::StateType resume_state = GetResumeState(); 152 ProcessMonitor &monitor = GetMonitor(); 153 bool status; 154 155 switch (GetResumeState()) 156 { 157 default: 158 assert(false && "Unexpected state for resume!"); 159 status = false; 160 break; 161 162 case lldb::eStateSuspended: 163 // FIXME: Implement process suspension. 164 status = false; 165 166 case lldb::eStateRunning: 167 SetState(resume_state); 168 status = monitor.Resume(GetID()); 169 break; 170 171 case lldb::eStateStepping: 172 SetState(resume_state); 173 status = monitor.SingleStep(GetID()); 174 break; 175 } 176 177 m_note = eNone; 178 return status; 179} 180 181void 182LinuxThread::BreakNotify() 183{ 184 bool status; 185 186 status = GetRegisterContextLinux()->UpdateAfterBreakpoint(); 187 assert(status && "Breakpoint update failed!"); 188 189 // With our register state restored, resolve the breakpoint object 190 // corresponding to our current PC. 191 lldb::addr_t pc = GetRegisterContext()->GetPC(); 192 lldb::BreakpointSiteSP bp_site(GetProcess().GetBreakpointSiteList().FindByAddress(pc)); 193 assert(bp_site && bp_site->ValidForThisThread(this)); 194 195 m_note = eBreak; 196 m_breakpoint = bp_site; 197} 198 199void 200LinuxThread::TraceNotify() 201{ 202 m_note = eTrace; 203} 204 205void 206LinuxThread::ExitNotify() 207{ 208 m_note = eExit; 209} 210 211void 212LinuxThread::RefreshPrivateStopReason() 213{ 214 m_stop_info_id = GetProcess().GetStopID(); 215 216 switch (m_note) { 217 218 default: 219 case eNone: 220 m_stop_info.reset(); 221 break; 222 223 case eBreak: 224 m_stop_info = StopInfo::CreateStopReasonWithBreakpointSiteID( 225 *this, m_breakpoint->GetID()); 226 break; 227 228 case eTrace: 229 m_stop_info = StopInfo::CreateStopReasonToTrace(*this); 230 break; 231 232 case eExit: 233 m_stop_info = StopInfo::CreateStopReasonWithSignal(*this, SIGCHLD); 234 break; 235 } 236} 237