| //===-- LinuxThread.cpp -----------------------------------------*- C++ -*-===// |
| // |
| // The LLVM Compiler Infrastructure |
| // |
| // This file is distributed under the University of Illinois Open Source |
| // License. See LICENSE.TXT for details. |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #include <errno.h> |
| |
| // C Includes |
| // C++ Includes |
| // Other libraries and framework includes |
| #include "lldb/Target/Process.h" |
| #include "lldb/Target/Target.h" |
| |
| #include "LinuxThread.h" |
| #include "ProcessLinux.h" |
| #include "ProcessMonitor.h" |
| #include "RegisterContextLinux_x86_64.h" |
| |
| using namespace lldb_private; |
| |
| LinuxThread::LinuxThread(Process &process, lldb::tid_t tid) |
| : Thread(process, tid), |
| m_frame_ap(0), |
| m_register_ap(0), |
| m_note(eNone) |
| { |
| ArchSpec arch = process.GetTarget().GetArchitecture(); |
| |
| switch (arch.GetGenericCPUType()) |
| { |
| default: |
| assert(false && "CPU type not supported!"); |
| break; |
| |
| case ArchSpec::eCPU_x86_64: |
| m_register_ap.reset(new RegisterContextLinux_x86_64(*this, NULL)); |
| break; |
| } |
| } |
| |
| ProcessMonitor & |
| LinuxThread::GetMonitor() |
| { |
| ProcessLinux *process = static_cast<ProcessLinux*>(CalculateProcess()); |
| return process->GetMonitor(); |
| } |
| |
| void |
| LinuxThread::RefreshStateAfterStop() |
| { |
| } |
| |
| const char * |
| LinuxThread::GetInfo() |
| { |
| return NULL; |
| } |
| |
| uint32_t |
| LinuxThread::GetStackFrameCount() |
| { |
| return 0; |
| } |
| |
| lldb::StackFrameSP |
| LinuxThread::GetStackFrameAtIndex(uint32_t idx) |
| { |
| if (idx == 0) |
| { |
| RegisterContextLinux *regs = GetRegisterContext(); |
| StackFrame *frame = new StackFrame( |
| idx, *this, regs->GetFP(), regs->GetPC()); |
| return lldb::StackFrameSP(frame); |
| } |
| else |
| return lldb::StackFrameSP(); |
| } |
| |
| RegisterContextLinux * |
| LinuxThread::GetRegisterContext() |
| { |
| return m_register_ap.get(); |
| } |
| |
| bool |
| LinuxThread::SaveFrameZeroState(RegisterCheckpoint &checkpoint) |
| { |
| return false; |
| } |
| |
| bool |
| LinuxThread::RestoreSaveFrameZero(const RegisterCheckpoint &checkpoint) |
| { |
| return false; |
| } |
| |
| RegisterContextLinux * |
| LinuxThread::CreateRegisterContextForFrame(lldb_private::StackFrame *frame) |
| { |
| return new RegisterContextLinux_x86_64(*this, frame); |
| } |
| |
| bool |
| LinuxThread::GetRawStopReason(StopInfo *stop_info) |
| { |
| stop_info->Clear(); |
| |
| switch (m_note) |
| { |
| default: |
| stop_info->SetStopReasonToNone(); |
| break; |
| |
| case eBreak: |
| stop_info->SetStopReasonWithBreakpointSiteID(m_breakpoint->GetID()); |
| break; |
| |
| case eTrace: |
| stop_info->SetStopReasonToTrace(); |
| } |
| |
| return true; |
| } |
| |
| bool |
| LinuxThread::WillResume(lldb::StateType resume_state) |
| { |
| SetResumeState(resume_state); |
| return Thread::WillResume(resume_state); |
| } |
| |
| bool |
| LinuxThread::Resume() |
| { |
| lldb::StateType resume_state = GetResumeState(); |
| ProcessMonitor &monitor = GetMonitor(); |
| bool status; |
| |
| switch (GetResumeState()) |
| { |
| default: |
| assert(false && "Unexpected state for resume!"); |
| status = false; |
| break; |
| |
| case lldb::eStateSuspended: |
| // FIXME: Implement process suspension. |
| status = false; |
| |
| case lldb::eStateRunning: |
| SetState(resume_state); |
| status = monitor.Resume(GetID()); |
| break; |
| |
| case lldb::eStateStepping: |
| SetState(resume_state); |
| status = GetRegisterContext()->HardwareSingleStep(true); |
| break; |
| } |
| |
| m_note = eNone; |
| return status; |
| } |
| |
| void |
| LinuxThread::BreakNotify() |
| { |
| bool status; |
| |
| status = GetRegisterContext()->UpdateAfterBreakpoint(); |
| assert(status && "Breakpoint update failed!"); |
| |
| // With our register state restored, resolve the breakpoint object |
| // corresponding to our current PC. |
| lldb::addr_t pc = GetRegisterContext()->GetPC(); |
| lldb::BreakpointSiteSP bp_site = |
| GetProcess().GetBreakpointSiteList().FindByAddress(pc); |
| assert(bp_site && bp_site->ValidForThisThread(this)); |
| |
| m_note = eBreak; |
| m_breakpoint = bp_site; |
| } |
| |
| void |
| LinuxThread::TraceNotify() |
| { |
| m_note = eTrace; |
| } |
| |
| void |
| LinuxThread::ExitNotify() |
| { |
| m_note = eExit; |
| } |