/* +----------------------------------------------------------------------+ | HipHop for PHP | +----------------------------------------------------------------------+ | Copyright (c) 2010- Facebook, Inc. (http://www.facebook.com) | +----------------------------------------------------------------------+ | This source file is subject to version 3.01 of the PHP license, | | that is bundled with this package in the file LICENSE, and is | | available through the world-wide-web at the following url: | | http://www.php.net/license/3_01.txt | | If you did not receive a copy of the PHP license and are unable to | | obtain it through the world-wide-web, please send a note to | | license@php.net so we can mail you a copy immediately. | +----------------------------------------------------------------------+ */ #ifndef __HPHP_EVAL_DEBUGGER_PROXY_H__ #define __HPHP_EVAL_DEBUGGER_PROXY_H__ #include #include #include #include #include #include namespace HPHP { namespace Eval { /////////////////////////////////////////////////////////////////////////////// class CmdInterrupt; DECLARE_BOOST_TYPES(DebuggerProxy); DECLARE_BOOST_TYPES(DebuggerCommand); DECLARE_BOOST_TYPES(CmdFlowControl); DECLARE_BOOST_TYPES(CmdJump); class DebuggerProxy : public Synchronizable, public boost::enable_shared_from_this { public: enum ThreadMode { Normal, Sticky, Exclusive }; static std::string MakePHP(const std::string &php); static std::string MakePHPReturn(const std::string &php); static Variant ExecutePHP(const std::string &php, String &output, bool log, int frame); public: DebuggerProxy(SmartPtr socket, bool local); virtual ~DebuggerProxy(); bool isLocal() const { return m_local;} const char *getThreadType() const; DSandboxInfo getSandbox() const; std::string getSandboxId() const; const DSandboxInfo& getDummyInfo() const { return m_dummyInfo; } void getThreads(DThreadInfoPtrVec &threads); bool switchSandbox(const std::string &newId, bool force); void updateSandbox(DSandboxInfoPtr sandbox); bool switchThread(DThreadInfoPtr thread); void switchThreadMode(ThreadMode mode, int64_t threadId = 0); void startDummySandbox(); void notifyDummySandbox(); virtual void setBreakPoints(BreakPointInfoPtrVec &breakpoints); void getBreakPoints(BreakPointInfoPtrVec &breakpoints); bool couldBreakEnterClsMethod(const StringData* className); bool couldBreakEnterFunc(const StringData* funcFullName); void getBreakClsMethods(std::vector& classNames); void getBreakFuncs(std::vector& funcFullNames); bool needInterrupt(); bool needInterruptForNonBreak(); virtual void interrupt(CmdInterrupt &cmd); bool send(DebuggerCommand *cmd); void startSignalThread(); void pollSignal(); // for signal polling thread void checkStop(); void forceQuit(); protected: bool m_stopped; bool m_local; DebuggerThriftBuffer m_thrift; DummySandbox* m_dummySandbox; mutable Mutex m_mutex; ReadWriteMutex m_breakMutex; bool m_hasBreakPoints; BreakPointInfoPtrVec m_breakpoints; DSandboxInfo m_sandbox; DSandboxInfo m_dummyInfo; ThreadMode m_threadMode; int64_t m_thread; DThreadInfoPtr m_newThread; std::map m_threads; typedef tbb::concurrent_hash_map StringDataMap; StringDataMap m_breaksEnterClsMethod; StringDataMap m_breaksEnterFunc; CmdFlowControlPtr m_flow; // c, s, n, o commands that can skip breakpoints CmdJumpPtr m_jump; Mutex m_signalMutex; // who can talk to client AsyncFunc m_signalThread; // polling signals from client Mutex m_signumMutex; int m_signum; // helpers bool blockUntilOwn(CmdInterrupt &cmd, bool check); virtual bool checkBreakPoints(CmdInterrupt &cmd); bool checkJumpFlowBreak(CmdInterrupt &cmd); virtual bool processJumpFlowBreak(CmdInterrupt &cmd); void processInterrupt(CmdInterrupt &cmd); virtual void processFlowControl(CmdInterrupt &cmd); virtual bool breakByFlowControl(CmdInterrupt &cmd); DThreadInfoPtr createThreadInfo(const std::string &desc); }; class DebuggerProxyVM : public DebuggerProxy { public: static Variant ExecutePHP(const std::string &php, String &output, bool log, int frame); public: DebuggerProxyVM(SmartPtr socket, bool local) : DebuggerProxy(socket, local), m_injTables(nullptr) { } virtual ~DebuggerProxyVM() { delete m_injTables; } virtual void interrupt(CmdInterrupt &cmd); virtual void setBreakPoints(BreakPointInfoPtrVec &breakpoints); // For instrumentation HPHP::VM::InjectionTables* getInjTables() const { return m_injTables; } void setInjTables(HPHP::VM::InjectionTables* tables) { m_injTables = tables;} void readInjTablesFromThread(); void writeInjTablesToThread(); void changeBreakPointDepth(CmdInterrupt& cmd); BreakPointInfoPtr getBreakPointAtCmd(CmdInterrupt& cmd); private: int getStackDepth(); int getRealStackDepth(); virtual void processFlowControl(CmdInterrupt &cmd); virtual bool breakByFlowControl(CmdInterrupt &cmd); // For instrumentation HPHP::VM::InjectionTables* m_injTables; }; /////////////////////////////////////////////////////////////////////////////// }} #endif // __HPHP_EVAL_DEBUGGER_PROXY_H__