269 lines
6.0 KiB
C++
269 lines
6.0 KiB
C++
//===-- LinuxThread.cpp -----------------------------------------*- C++ -*-===//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// C Includes
|
|
#include <errno.h>
|
|
|
|
// C++ Includes
|
|
// Other libraries and framework includes
|
|
// Project includes
|
|
#include "lldb/Host/Host.h"
|
|
#include "lldb/Target/Process.h"
|
|
#include "lldb/Target/StopInfo.h"
|
|
#include "lldb/Target/Target.h"
|
|
|
|
#include "LinuxStopInfo.h"
|
|
#include "LinuxThread.h"
|
|
#include "ProcessLinux.h"
|
|
#include "ProcessMonitor.h"
|
|
#include "RegisterContextLinux_i386.h"
|
|
#include "RegisterContextLinux_x86_64.h"
|
|
#include "UnwindLLDB.h"
|
|
|
|
using namespace lldb_private;
|
|
|
|
|
|
LinuxThread::LinuxThread(Process &process, lldb::tid_t tid)
|
|
: Thread(process, tid),
|
|
m_frame_ap(0)
|
|
{
|
|
}
|
|
|
|
LinuxThread::~LinuxThread()
|
|
{
|
|
DestroyThread();
|
|
}
|
|
|
|
ProcessMonitor &
|
|
LinuxThread::GetMonitor()
|
|
{
|
|
ProcessLinux &process = static_cast<ProcessLinux&>(GetProcess());
|
|
return process.GetMonitor();
|
|
}
|
|
|
|
void
|
|
LinuxThread::RefreshStateAfterStop()
|
|
{
|
|
}
|
|
|
|
const char *
|
|
LinuxThread::GetInfo()
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
lldb::RegisterContextSP
|
|
LinuxThread::GetRegisterContext()
|
|
{
|
|
if (!m_reg_context_sp)
|
|
{
|
|
ArchSpec arch = Host::GetArchitecture();
|
|
|
|
switch (arch.GetCore())
|
|
{
|
|
default:
|
|
assert(false && "CPU type not supported!");
|
|
break;
|
|
|
|
case ArchSpec::eCore_x86_32_i386:
|
|
case ArchSpec::eCore_x86_32_i486:
|
|
case ArchSpec::eCore_x86_32_i486sx:
|
|
m_reg_context_sp.reset(new RegisterContextLinux_i386(*this, 0));
|
|
break;
|
|
|
|
case ArchSpec::eCore_x86_64_x86_64:
|
|
m_reg_context_sp.reset(new RegisterContextLinux_x86_64(*this, 0));
|
|
break;
|
|
}
|
|
}
|
|
return m_reg_context_sp;
|
|
}
|
|
|
|
bool
|
|
LinuxThread::SaveFrameZeroState(RegisterCheckpoint &checkpoint)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
bool
|
|
LinuxThread::RestoreSaveFrameZero(const RegisterCheckpoint &checkpoint)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
lldb::RegisterContextSP
|
|
LinuxThread::CreateRegisterContextForFrame(lldb_private::StackFrame *frame)
|
|
{
|
|
lldb::RegisterContextSP reg_ctx_sp;
|
|
uint32_t concrete_frame_idx = 0;
|
|
|
|
if (frame)
|
|
concrete_frame_idx = frame->GetConcreteFrameIndex();
|
|
|
|
if (concrete_frame_idx == 0)
|
|
reg_ctx_sp = GetRegisterContext();
|
|
else
|
|
reg_ctx_sp = GetUnwinder()->CreateRegisterContextForFrame(frame);
|
|
|
|
return reg_ctx_sp;
|
|
}
|
|
|
|
lldb::StopInfoSP
|
|
LinuxThread::GetPrivateStopReason()
|
|
{
|
|
return m_stop_info;
|
|
}
|
|
|
|
Unwind *
|
|
LinuxThread::GetUnwinder()
|
|
{
|
|
if (m_unwinder_ap.get() == NULL)
|
|
m_unwinder_ap.reset(new UnwindLLDB(*this));
|
|
|
|
return m_unwinder_ap.get();
|
|
}
|
|
|
|
bool
|
|
LinuxThread::WillResume(lldb::StateType resume_state)
|
|
{
|
|
SetResumeState(resume_state);
|
|
|
|
ClearStackFrames();
|
|
if (m_unwinder_ap.get())
|
|
m_unwinder_ap->Clear();
|
|
|
|
return Thread::WillResume(resume_state);
|
|
}
|
|
|
|
bool
|
|
LinuxThread::Resume()
|
|
{
|
|
lldb::StateType resume_state = GetResumeState();
|
|
ProcessMonitor &monitor = GetMonitor();
|
|
bool status;
|
|
|
|
switch (resume_state)
|
|
{
|
|
default:
|
|
assert(false && "Unexpected state for resume!");
|
|
status = false;
|
|
break;
|
|
|
|
case lldb::eStateRunning:
|
|
SetState(resume_state);
|
|
status = monitor.Resume(GetID(), GetResumeSignal());
|
|
break;
|
|
|
|
case lldb::eStateStepping:
|
|
SetState(resume_state);
|
|
status = monitor.SingleStep(GetID(), GetResumeSignal());
|
|
break;
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
void
|
|
LinuxThread::Notify(const ProcessMessage &message)
|
|
{
|
|
switch (message.GetKind())
|
|
{
|
|
default:
|
|
assert(false && "Unexpected message kind!");
|
|
break;
|
|
|
|
case ProcessMessage::eLimboMessage:
|
|
LimboNotify(message);
|
|
break;
|
|
|
|
case ProcessMessage::eSignalMessage:
|
|
SignalNotify(message);
|
|
break;
|
|
|
|
case ProcessMessage::eSignalDeliveredMessage:
|
|
SignalDeliveredNotify(message);
|
|
break;
|
|
|
|
case ProcessMessage::eTraceMessage:
|
|
TraceNotify(message);
|
|
break;
|
|
|
|
case ProcessMessage::eBreakpointMessage:
|
|
BreakNotify(message);
|
|
break;
|
|
|
|
case ProcessMessage::eCrashMessage:
|
|
CrashNotify(message);
|
|
break;
|
|
}
|
|
}
|
|
|
|
void
|
|
LinuxThread::BreakNotify(const ProcessMessage &message)
|
|
{
|
|
bool status;
|
|
|
|
status = GetRegisterContextLinux()->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));
|
|
lldb::break_id_t bp_id = bp_site->GetID();
|
|
assert(bp_site && bp_site->ValidForThisThread(this));
|
|
|
|
|
|
m_breakpoint = bp_site;
|
|
m_stop_info = StopInfo::CreateStopReasonWithBreakpointSiteID(*this, bp_id);
|
|
}
|
|
|
|
void
|
|
LinuxThread::TraceNotify(const ProcessMessage &message)
|
|
{
|
|
m_stop_info = StopInfo::CreateStopReasonToTrace(*this);
|
|
}
|
|
|
|
void
|
|
LinuxThread::LimboNotify(const ProcessMessage &message)
|
|
{
|
|
m_stop_info = lldb::StopInfoSP(new LinuxLimboStopInfo(*this));
|
|
}
|
|
|
|
void
|
|
LinuxThread::SignalNotify(const ProcessMessage &message)
|
|
{
|
|
int signo = message.GetSignal();
|
|
|
|
m_stop_info = StopInfo::CreateStopReasonWithSignal(*this, signo);
|
|
SetResumeSignal(signo);
|
|
}
|
|
|
|
void
|
|
LinuxThread::SignalDeliveredNotify(const ProcessMessage &message)
|
|
{
|
|
int signo = message.GetSignal();
|
|
|
|
// Just treat debugger generated signal events like breakpoints for now.
|
|
m_stop_info = StopInfo::CreateStopReasonToTrace(*this);
|
|
SetResumeSignal(signo);
|
|
}
|
|
|
|
void
|
|
LinuxThread::CrashNotify(const ProcessMessage &message)
|
|
{
|
|
int signo = message.GetSignal();
|
|
|
|
assert(message.GetKind() == ProcessMessage::eCrashMessage);
|
|
|
|
m_stop_info = lldb::StopInfoSP(new LinuxCrashStopInfo(
|
|
*this, signo, message.GetCrashReason()));
|
|
SetResumeSignal(signo);
|
|
}
|