forked from OSchip/llvm-project
				
			
		
			
				
	
	
		
			207 lines
		
	
	
		
			7.1 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			207 lines
		
	
	
		
			7.1 KiB
		
	
	
	
		
			C++
		
	
	
	
//===-- ThreadPlanPython.cpp ------------------------------------*- C++ -*-===//
 | 
						|
//
 | 
						|
//                     The LLVM Compiler Infrastructure
 | 
						|
//
 | 
						|
// This file is distributed under the University of Illinois Open Source
 | 
						|
// License. See LICENSE.TXT for details.
 | 
						|
//
 | 
						|
//===----------------------------------------------------------------------===//
 | 
						|
 | 
						|
#include "lldb/Target/ThreadPlan.h"
 | 
						|
 | 
						|
// C Includes
 | 
						|
// C++ Includes
 | 
						|
// Other libraries and framework includes
 | 
						|
// Project includes
 | 
						|
#include "lldb/Core/Debugger.h"
 | 
						|
#include "lldb/Core/State.h"
 | 
						|
#include "lldb/Interpreter/CommandInterpreter.h"
 | 
						|
#include "lldb/Interpreter/ScriptInterpreter.h"
 | 
						|
#include "lldb/Target/Process.h"
 | 
						|
#include "lldb/Target/RegisterContext.h"
 | 
						|
#include "lldb/Target/Target.h"
 | 
						|
#include "lldb/Target/Thread.h"
 | 
						|
#include "lldb/Target/ThreadPlan.h"
 | 
						|
#include "lldb/Target/ThreadPlanPython.h"
 | 
						|
#include "lldb/Utility/Log.h"
 | 
						|
 | 
						|
using namespace lldb;
 | 
						|
using namespace lldb_private;
 | 
						|
 | 
						|
//----------------------------------------------------------------------
 | 
						|
// ThreadPlanPython
 | 
						|
//----------------------------------------------------------------------
 | 
						|
 | 
						|
ThreadPlanPython::ThreadPlanPython(Thread &thread, const char *class_name)
 | 
						|
    : ThreadPlan(ThreadPlan::eKindPython, "Python based Thread Plan", thread,
 | 
						|
                 eVoteNoOpinion, eVoteNoOpinion),
 | 
						|
      m_class_name(class_name) {
 | 
						|
  SetIsMasterPlan(true);
 | 
						|
  SetOkayToDiscard(true);
 | 
						|
  SetPrivate(false);
 | 
						|
}
 | 
						|
 | 
						|
ThreadPlanPython::~ThreadPlanPython() {
 | 
						|
  // FIXME, do I need to decrement the ref count on this implementation object
 | 
						|
  // to make it go away?
 | 
						|
}
 | 
						|
 | 
						|
bool ThreadPlanPython::ValidatePlan(Stream *error) {
 | 
						|
  // I have to postpone setting up the implementation till after the constructor
 | 
						|
  // because I need to call
 | 
						|
  // shared_from_this, which you can't do in the constructor.  So I'll do it
 | 
						|
  // here.
 | 
						|
  if (m_implementation_sp)
 | 
						|
    return true;
 | 
						|
  else
 | 
						|
    return false;
 | 
						|
}
 | 
						|
 | 
						|
void ThreadPlanPython::DidPush() {
 | 
						|
  // We set up the script side in DidPush, so that it can push other plans in
 | 
						|
  // the constructor,
 | 
						|
  // and doesn't have to care about the details of DidPush.
 | 
						|
 | 
						|
  if (!m_class_name.empty()) {
 | 
						|
    ScriptInterpreter *script_interp = m_thread.GetProcess()
 | 
						|
                                           ->GetTarget()
 | 
						|
                                           .GetDebugger()
 | 
						|
                                           .GetCommandInterpreter()
 | 
						|
                                           .GetScriptInterpreter();
 | 
						|
    if (script_interp) {
 | 
						|
      m_implementation_sp = script_interp->CreateScriptedThreadPlan(
 | 
						|
          m_class_name.c_str(), this->shared_from_this());
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
bool ThreadPlanPython::ShouldStop(Event *event_ptr) {
 | 
						|
  Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD));
 | 
						|
  if (log)
 | 
						|
    log->Printf("%s called on Python Thread Plan: %s )", LLVM_PRETTY_FUNCTION,
 | 
						|
                m_class_name.c_str());
 | 
						|
 | 
						|
  bool should_stop = true;
 | 
						|
  if (m_implementation_sp) {
 | 
						|
    ScriptInterpreter *script_interp = m_thread.GetProcess()
 | 
						|
                                           ->GetTarget()
 | 
						|
                                           .GetDebugger()
 | 
						|
                                           .GetCommandInterpreter()
 | 
						|
                                           .GetScriptInterpreter();
 | 
						|
    if (script_interp) {
 | 
						|
      bool script_error;
 | 
						|
      should_stop = script_interp->ScriptedThreadPlanShouldStop(
 | 
						|
          m_implementation_sp, event_ptr, script_error);
 | 
						|
      if (script_error)
 | 
						|
        SetPlanComplete(false);
 | 
						|
    }
 | 
						|
  }
 | 
						|
  return should_stop;
 | 
						|
}
 | 
						|
 | 
						|
bool ThreadPlanPython::IsPlanStale() {
 | 
						|
  Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD));
 | 
						|
  if (log)
 | 
						|
    log->Printf("%s called on Python Thread Plan: %s )", LLVM_PRETTY_FUNCTION,
 | 
						|
                m_class_name.c_str());
 | 
						|
 | 
						|
  bool is_stale = true;
 | 
						|
  if (m_implementation_sp) {
 | 
						|
    ScriptInterpreter *script_interp = m_thread.GetProcess()
 | 
						|
                                           ->GetTarget()
 | 
						|
                                           .GetDebugger()
 | 
						|
                                           .GetCommandInterpreter()
 | 
						|
                                           .GetScriptInterpreter();
 | 
						|
    if (script_interp) {
 | 
						|
      bool script_error;
 | 
						|
      is_stale = script_interp->ScriptedThreadPlanIsStale(m_implementation_sp,
 | 
						|
                                                          script_error);
 | 
						|
      if (script_error)
 | 
						|
        SetPlanComplete(false);
 | 
						|
    }
 | 
						|
  }
 | 
						|
  return is_stale;
 | 
						|
}
 | 
						|
 | 
						|
bool ThreadPlanPython::DoPlanExplainsStop(Event *event_ptr) {
 | 
						|
  Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD));
 | 
						|
  if (log)
 | 
						|
    log->Printf("%s called on Python Thread Plan: %s )", LLVM_PRETTY_FUNCTION,
 | 
						|
                m_class_name.c_str());
 | 
						|
 | 
						|
  bool explains_stop = true;
 | 
						|
  if (m_implementation_sp) {
 | 
						|
    ScriptInterpreter *script_interp = m_thread.GetProcess()
 | 
						|
                                           ->GetTarget()
 | 
						|
                                           .GetDebugger()
 | 
						|
                                           .GetCommandInterpreter()
 | 
						|
                                           .GetScriptInterpreter();
 | 
						|
    if (script_interp) {
 | 
						|
      bool script_error;
 | 
						|
      explains_stop = script_interp->ScriptedThreadPlanExplainsStop(
 | 
						|
          m_implementation_sp, event_ptr, script_error);
 | 
						|
      if (script_error)
 | 
						|
        SetPlanComplete(false);
 | 
						|
    }
 | 
						|
  }
 | 
						|
  return explains_stop;
 | 
						|
}
 | 
						|
 | 
						|
bool ThreadPlanPython::MischiefManaged() {
 | 
						|
  Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD));
 | 
						|
  if (log)
 | 
						|
    log->Printf("%s called on Python Thread Plan: %s )", LLVM_PRETTY_FUNCTION,
 | 
						|
                m_class_name.c_str());
 | 
						|
  bool mischief_managed = true;
 | 
						|
  if (m_implementation_sp) {
 | 
						|
    // I don't really need mischief_managed, since it's simpler to just call
 | 
						|
    // SetPlanComplete in should_stop.
 | 
						|
    mischief_managed = IsPlanComplete();
 | 
						|
    if (mischief_managed)
 | 
						|
      m_implementation_sp.reset();
 | 
						|
  }
 | 
						|
  return mischief_managed;
 | 
						|
}
 | 
						|
 | 
						|
lldb::StateType ThreadPlanPython::GetPlanRunState() {
 | 
						|
  Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD));
 | 
						|
  if (log)
 | 
						|
    log->Printf("%s called on Python Thread Plan: %s )", LLVM_PRETTY_FUNCTION,
 | 
						|
                m_class_name.c_str());
 | 
						|
  lldb::StateType run_state = eStateRunning;
 | 
						|
  if (m_implementation_sp) {
 | 
						|
    ScriptInterpreter *script_interp = m_thread.GetProcess()
 | 
						|
                                           ->GetTarget()
 | 
						|
                                           .GetDebugger()
 | 
						|
                                           .GetCommandInterpreter()
 | 
						|
                                           .GetScriptInterpreter();
 | 
						|
    if (script_interp) {
 | 
						|
      bool script_error;
 | 
						|
      run_state = script_interp->ScriptedThreadPlanGetRunState(
 | 
						|
          m_implementation_sp, script_error);
 | 
						|
    }
 | 
						|
  }
 | 
						|
  return run_state;
 | 
						|
}
 | 
						|
 | 
						|
// The ones below are not currently exported to Python.
 | 
						|
 | 
						|
bool ThreadPlanPython::StopOthers() {
 | 
						|
  // For now Python plans run all threads, but we should add some controls for
 | 
						|
  // this.
 | 
						|
  return false;
 | 
						|
}
 | 
						|
 | 
						|
void ThreadPlanPython::GetDescription(Stream *s, lldb::DescriptionLevel level) {
 | 
						|
  s->Printf("Python thread plan implemented by class %s.",
 | 
						|
            m_class_name.c_str());
 | 
						|
}
 | 
						|
 | 
						|
bool ThreadPlanPython::WillStop() {
 | 
						|
  Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD));
 | 
						|
  if (log)
 | 
						|
    log->Printf("%s called on Python Thread Plan: %s )", LLVM_PRETTY_FUNCTION,
 | 
						|
                m_class_name.c_str());
 | 
						|
  return true;
 | 
						|
}
 |