//===-- Debug.h -------------------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef liblldb_Debug_h_
#define liblldb_Debug_h_
#include <vector>
#include "lldb/lldb-private.h"
namespace lldb_private {
//------------------------------------------------------------------
// Tells a thread what it needs to do when the process is resumed.
//------------------------------------------------------------------
struct ResumeAction
{
lldb::tid_t tid; // The thread ID that this action applies to, LLDB_INVALID_THREAD_ID for the default thread action
lldb::StateType state; // Valid values are eStateStopped/eStateSuspended, eStateRunning, and eStateStepping.
int signal; // When resuming this thread, resume it with this signal if this value is > 0
};
//------------------------------------------------------------------
// A class that contains instructions for all threads for
// NativeProcessProtocol::Resume(). Each thread can either run, stay
// suspended, or step when the process is resumed. We optionally
// have the ability to also send a signal to the thread when the
// action is run or step.
//------------------------------------------------------------------
class ResumeActionList
{
public:
ResumeActionList () :
m_actions (),
m_signal_handled ()
{
}
ResumeActionList (lldb::StateType default_action, int signal) :
m_actions(),
m_signal_handled ()
{
SetDefaultThreadActionIfNeeded (default_action, signal);
}
ResumeActionList (const ResumeAction *actions, size_t num_actions) :
m_actions (),
m_signal_handled ()
{
if (actions && num_actions)
{
m_actions.assign (actions, actions + num_actions);
m_signal_handled.assign (num_actions, false);
}
}
~ResumeActionList()
{
}
bool
IsEmpty() const
{
return m_actions.empty();
}
void
Append (const ResumeAction &action)
{
m_actions.push_back (action);
m_signal_handled.push_back (false);
}
void
AppendAction (lldb::tid_t tid,
lldb::StateType state,
int signal = 0)
{
ResumeAction action = { tid, state, signal };
Append (action);
}
void
AppendResumeAll ()
{
AppendAction (LLDB_INVALID_THREAD_ID, lldb::eStateRunning);
}
void
AppendSuspendAll ()
{
AppendAction (LLDB_INVALID_THREAD_ID, lldb::eStateStopped);
}
void
AppendStepAll ()
{
AppendAction (LLDB_INVALID_THREAD_ID, lldb::eStateStepping);
}
const ResumeAction *
GetActionForThread (lldb::tid_t tid, bool default_ok) const
{
const size_t num_actions = m_actions.size();
for (size_t i=0; i<num_actions; ++i)
{
if (m_actions[i].tid == tid)
return &m_actions[i];
}
if (default_ok && tid != LLDB_INVALID_THREAD_ID)
return GetActionForThread (LLDB_INVALID_THREAD_ID, false);
return NULL;
}
size_t
NumActionsWithState (lldb::StateType state) const
{
size_t count = 0;
const size_t num_actions = m_actions.size();
for (size_t i=0; i<num_actions; ++i)
{
if (m_actions[i].state == state)
++count;
}
return count;
}
bool
SetDefaultThreadActionIfNeeded (lldb::StateType action, int signal)
{
if (GetActionForThread (LLDB_INVALID_THREAD_ID, true) == NULL)
{
// There isn't a default action so we do need to set it.
ResumeAction default_action = {LLDB_INVALID_THREAD_ID, action, signal };
m_actions.push_back (default_action);
m_signal_handled.push_back (false);
return true; // Return true as we did add the default action
}
return false;
}
void
SetSignalHandledForThread (lldb::tid_t tid) const
{
if (tid != LLDB_INVALID_THREAD_ID)
{
const size_t num_actions = m_actions.size();
for (size_t i=0; i<num_actions; ++i)
{
if (m_actions[i].tid == tid)
m_signal_handled[i] = true;
}
}
}
const ResumeAction *
GetFirst() const
{
return m_actions.data();
}
size_t
GetSize () const
{
return m_actions.size();
}
void
Clear()
{
m_actions.clear();
m_signal_handled.clear();
}
protected:
std::vector<ResumeAction> m_actions;
mutable std::vector<bool> m_signal_handled;
};
struct ThreadStopInfo
{
lldb::StopReason reason;
union
{
// eStopReasonSignal
struct
{
uint32_t signo;
} signal;
// eStopReasonException
struct
{
uint64_t type;
uint32_t data_count;
lldb::addr_t data[2];
} exception;
} details;
};
}
#endif // #ifndef liblldb_Debug_h_