diff options
author | Greg Clayton <gclayton@apple.com> | 2013-01-09 19:44:40 +0000 |
---|---|---|
committer | Greg Clayton <gclayton@apple.com> | 2013-01-09 19:44:40 +0000 |
commit | f9fc609fe7e246f98ba72818af1827a269cf71ee (patch) | |
tree | 676a461898bf2f4feef048d3254f326973b68064 /lldb/source/Interpreter/CommandObject.cpp | |
parent | eb9ae768647ee4280e4f25d58180067e1ed3c5ab (diff) | |
download | llvm-f9fc609fe7e246f98ba72818af1827a269cf71ee.zip llvm-f9fc609fe7e246f98ba72818af1827a269cf71ee.tar.gz llvm-f9fc609fe7e246f98ba72818af1827a269cf71ee.tar.bz2 |
Expanded the flags that can be set for a command object in lldb_private::CommandObject. This list of available flags are:
enum
{
//----------------------------------------------------------------------
// eFlagRequiresTarget
//
// Ensures a valid target is contained in m_exe_ctx prior to executing
// the command. If a target doesn't exist or is invalid, the command
// will fail and CommandObject::GetInvalidTargetDescription() will be
// returned as the error. CommandObject subclasses can override the
// virtual function for GetInvalidTargetDescription() to provide custom
// strings when needed.
//----------------------------------------------------------------------
eFlagRequiresTarget = (1u << 0),
//----------------------------------------------------------------------
// eFlagRequiresProcess
//
// Ensures a valid process is contained in m_exe_ctx prior to executing
// the command. If a process doesn't exist or is invalid, the command
// will fail and CommandObject::GetInvalidProcessDescription() will be
// returned as the error. CommandObject subclasses can override the
// virtual function for GetInvalidProcessDescription() to provide custom
// strings when needed.
//----------------------------------------------------------------------
eFlagRequiresProcess = (1u << 1),
//----------------------------------------------------------------------
// eFlagRequiresThread
//
// Ensures a valid thread is contained in m_exe_ctx prior to executing
// the command. If a thread doesn't exist or is invalid, the command
// will fail and CommandObject::GetInvalidThreadDescription() will be
// returned as the error. CommandObject subclasses can override the
// virtual function for GetInvalidThreadDescription() to provide custom
// strings when needed.
//----------------------------------------------------------------------
eFlagRequiresThread = (1u << 2),
//----------------------------------------------------------------------
// eFlagRequiresFrame
//
// Ensures a valid frame is contained in m_exe_ctx prior to executing
// the command. If a frame doesn't exist or is invalid, the command
// will fail and CommandObject::GetInvalidFrameDescription() will be
// returned as the error. CommandObject subclasses can override the
// virtual function for GetInvalidFrameDescription() to provide custom
// strings when needed.
//----------------------------------------------------------------------
eFlagRequiresFrame = (1u << 3),
//----------------------------------------------------------------------
// eFlagRequiresRegContext
//
// Ensures a valid register context (from the selected frame if there
// is a frame in m_exe_ctx, or from the selected thread from m_exe_ctx)
// is availble from m_exe_ctx prior to executing the command. If a
// target doesn't exist or is invalid, the command will fail and
// CommandObject::GetInvalidRegContextDescription() will be returned as
// the error. CommandObject subclasses can override the virtual function
// for GetInvalidRegContextDescription() to provide custom strings when
// needed.
//----------------------------------------------------------------------
eFlagRequiresRegContext = (1u << 4),
//----------------------------------------------------------------------
// eFlagTryTargetAPILock
//
// Attempts to acquire the target lock if a target is selected in the
// command interpreter. If the command object fails to acquire the API
// lock, the command will fail with an appropriate error message.
//----------------------------------------------------------------------
eFlagTryTargetAPILock = (1u << 5),
//----------------------------------------------------------------------
// eFlagProcessMustBeLaunched
//
// Verifies that there is a launched process in m_exe_ctx, if there
// isn't, the command will fail with an appropriate error message.
//----------------------------------------------------------------------
eFlagProcessMustBeLaunched = (1u << 6),
//----------------------------------------------------------------------
// eFlagProcessMustBePaused
//
// Verifies that there is a paused process in m_exe_ctx, if there
// isn't, the command will fail with an appropriate error message.
//----------------------------------------------------------------------
eFlagProcessMustBePaused = (1u << 7)
};
Now each command object contains a "ExecutionContext m_exe_ctx;" member variable that gets initialized prior to running the command. The validity of the target objects in m_exe_ctx are checked to ensure that any target/process/thread/frame/reg context that are required are valid prior to executing the command. Each command object also contains a Mutex::Locker m_api_locker which gets used if eFlagTryTargetAPILock is set. This centralizes a lot of checking code that was previously and inconsistently implemented across many commands.
llvm-svn: 171990
Diffstat (limited to 'lldb/source/Interpreter/CommandObject.cpp')
-rw-r--r-- | lldb/source/Interpreter/CommandObject.cpp | 101 |
1 files changed, 90 insertions, 11 deletions
diff --git a/lldb/source/Interpreter/CommandObject.cpp b/lldb/source/Interpreter/CommandObject.cpp index e90ae8f..784187f 100644 --- a/lldb/source/Interpreter/CommandObject.cpp +++ b/lldb/source/Interpreter/CommandObject.cpp @@ -208,8 +208,77 @@ CommandObject::ParseOptions bool -CommandObject::CheckFlags (CommandReturnObject &result) +CommandObject::CheckRequirements (CommandReturnObject &result) { +#ifdef LLDB_CONFIGURATION_DEBUG + // Nothing should be stored in m_exe_ctx between running commands as m_exe_ctx + // has shared pointers to the target, process, thread and frame and we don't + // want any CommandObject instances to keep any of these objects around + // longer than for a single command. Every command should call + // CommandObject::Cleanup() after it has completed + assert (m_exe_ctx.GetTargetPtr() == NULL); + assert (m_exe_ctx.GetProcessPtr() == NULL); + assert (m_exe_ctx.GetThreadPtr() == NULL); + assert (m_exe_ctx.GetFramePtr() == NULL); +#endif + + // Lock down the interpreter's execution context prior to running the + // command so we guarantee the selected target, process, thread and frame + // can't go away during the execution + m_exe_ctx = m_interpreter.GetExecutionContext(); + + const uint32_t flags = GetFlags().Get(); + if (flags & (eFlagRequiresTarget | + eFlagRequiresProcess | + eFlagRequiresThread | + eFlagRequiresFrame | + eFlagTryTargetAPILock )) + { + + if ((flags & eFlagRequiresTarget) && !m_exe_ctx.HasTargetScope()) + { + result.AppendError (GetInvalidTargetDescription()); + return false; + } + + if ((flags & eFlagRequiresProcess) && !m_exe_ctx.HasProcessScope()) + { + result.AppendError (GetInvalidProcessDescription()); + return false; + } + + if ((flags & eFlagRequiresThread) && !m_exe_ctx.HasThreadScope()) + { + result.AppendError (GetInvalidThreadDescription()); + return false; + } + + if ((flags & eFlagRequiresFrame) && !m_exe_ctx.HasFrameScope()) + { + result.AppendError (GetInvalidFrameDescription()); + return false; + } + + if ((flags & eFlagRequiresRegContext) && (m_exe_ctx.GetRegisterContext() == NULL)) + { + result.AppendError (GetInvalidRegContextDescription()); + return false; + } + + if (flags & eFlagTryTargetAPILock) + { + Target *target = m_exe_ctx.GetTargetPtr(); + if (target) + { + if (m_api_locker.TryLock (target->GetAPIMutex(), NULL) == false) + { + result.AppendError ("failed to get API lock"); + return false; + } + } + } + } + if (GetFlags().AnySet (CommandObject::eFlagProcessMustBeLaunched | CommandObject::eFlagProcessMustBePaused)) { Process *process = m_interpreter.GetExecutionContext().GetProcessPtr(); @@ -263,6 +332,14 @@ CommandObject::CheckFlags (CommandReturnObject &result) return true; } +void +CommandObject::Cleanup () +{ + m_exe_ctx.Clear(); + m_api_locker.Unlock(); +} + + class CommandDictCommandPartialMatch { public: @@ -888,14 +965,16 @@ CommandObjectParsed::Execute (const char *args_string, CommandReturnObject &resu cmd_args.ReplaceArgumentAtIndex (i, m_interpreter.ProcessEmbeddedScriptCommands (tmp_str)); } - if (!CheckFlags(result)) - return false; - - if (!ParseOptions (cmd_args, result)) - return false; + if (CheckRequirements(result)) + { + if (ParseOptions (cmd_args, result)) + { + // Call the command-specific version of 'Execute', passing it the already processed arguments. + handled = DoExecute (cmd_args, result); + } + } - // Call the command-specific version of 'Execute', passing it the already processed arguments. - handled = DoExecute (cmd_args, result); + Cleanup(); } return handled; } @@ -916,10 +995,10 @@ CommandObjectRaw::Execute (const char *args_string, CommandReturnObject &result) } if (!handled) { - if (!CheckFlags(result)) - return false; - else + if (CheckRequirements(result)) handled = DoExecute (args_string, result); + + Cleanup(); } return handled; } |