blob: 6d4733afcb264cbbc1c73ddb26bba27ebe266c52 [file] [log] [blame]
//===-- 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;
}