aboutsummaryrefslogtreecommitdiff
path: root/lldb/source/Interpreter/CommandObject.cpp
diff options
context:
space:
mode:
authorGreg Clayton <gclayton@apple.com>2013-01-09 19:44:40 +0000
committerGreg Clayton <gclayton@apple.com>2013-01-09 19:44:40 +0000
commitf9fc609fe7e246f98ba72818af1827a269cf71ee (patch)
tree676a461898bf2f4feef048d3254f326973b68064 /lldb/source/Interpreter/CommandObject.cpp
parenteb9ae768647ee4280e4f25d58180067e1ed3c5ab (diff)
downloadllvm-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.cpp101
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;
}