Add TRACE calls to debugger code.
Added a new trace flag and added TRACE calls to all functions in files living directly in the hphp/runtime/eval/debugger directory
Esse commit está contido em:
@@ -27,7 +27,10 @@
|
||||
namespace HPHP { namespace Eval {
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static const Trace::Module TRACEMOD = Trace::debugger;
|
||||
|
||||
int InterruptSite::getFileLen() const {
|
||||
TRACE(2, "InterruptSite::getFileLen\n");
|
||||
if (m_file.empty()) {
|
||||
getFile();
|
||||
}
|
||||
@@ -35,6 +38,7 @@ int InterruptSite::getFileLen() const {
|
||||
}
|
||||
|
||||
std::string InterruptSite::desc() const {
|
||||
TRACE(2, "InterruptSite::desc\n");
|
||||
string ret;
|
||||
if (m_exception.isNull()) {
|
||||
ret = "Break";
|
||||
@@ -75,6 +79,7 @@ std::string InterruptSite::desc() const {
|
||||
InterruptSiteVM::InterruptSiteVM(bool hardBreakPoint /* = false */,
|
||||
CVarRef e /* = null_variant */)
|
||||
: InterruptSite(e), m_unit(nullptr), m_valid(false), m_funcEntry(false) {
|
||||
TRACE(2, "InterruptSite::InterruptSiteVM\n");
|
||||
VM::Transl::VMRegAnchor _;
|
||||
#define bail_on(c) if (c) { return; }
|
||||
VMExecutionContext* context = g_vmContext;
|
||||
@@ -133,10 +138,12 @@ InterruptSiteVM::InterruptSiteVM(bool hardBreakPoint /* = false */,
|
||||
}
|
||||
|
||||
const char *InterruptSiteVM::getFile() const {
|
||||
TRACE(2, "InterruptSiteVM::getFile\n");
|
||||
return m_file.data();
|
||||
}
|
||||
|
||||
const char *InterruptSiteVM::getClass() const {
|
||||
TRACE(2, "InterruptSiteVM::getClass\n");
|
||||
if (m_class) {
|
||||
return m_class;
|
||||
}
|
||||
@@ -144,6 +151,7 @@ const char *InterruptSiteVM::getClass() const {
|
||||
}
|
||||
|
||||
const char *InterruptSiteVM::getFunction() const {
|
||||
TRACE(2, "InterruptSiteVM::getFunction\n");
|
||||
if (m_function) {
|
||||
return m_function;
|
||||
}
|
||||
@@ -155,6 +163,7 @@ const char *InterruptSiteVM::getFunction() const {
|
||||
const char *BreakPointInfo::ErrorClassName = "@";
|
||||
|
||||
const char *BreakPointInfo::GetInterruptName(InterruptType interrupt) {
|
||||
TRACE(2, "BreakPointInfo::GetInterruptName\n");
|
||||
switch (interrupt) {
|
||||
case RequestStarted: return "start of request";
|
||||
case RequestEnded: return "end of request or start of psp";
|
||||
@@ -172,6 +181,7 @@ BreakPointInfo::BreakPointInfo(bool regex, State state,
|
||||
m_interrupt(BreakPointReached),
|
||||
m_file(file), m_line1(line), m_line2(line),
|
||||
m_regex(regex), m_check(false) {
|
||||
TRACE(2, "BreakPointInfo::BreakPointInfo..const std::string &file, int)\n");
|
||||
createIndex();
|
||||
}
|
||||
|
||||
@@ -181,6 +191,7 @@ BreakPointInfo::BreakPointInfo(bool regex, State state,
|
||||
: m_index(0), m_state(state), m_valid(true), m_interrupt(interrupt),
|
||||
m_line1(0), m_line2(0), m_url(url),
|
||||
m_regex(regex), m_check(false) {
|
||||
TRACE(2, "BreakPointInfo::BreakPointInfo..const std::string &url)\n");
|
||||
createIndex();
|
||||
}
|
||||
|
||||
@@ -191,6 +202,7 @@ BreakPointInfo::BreakPointInfo(bool regex, State state,
|
||||
: m_index(0), m_state(state), m_valid(true), m_interrupt(interrupt),
|
||||
m_line1(0), m_line2(0),
|
||||
m_regex(regex), m_check(false) {
|
||||
TRACE(2, "BreakPointInfo::BreakPointInfo..const std::string &file)\n");
|
||||
if (m_interrupt == ExceptionThrown) {
|
||||
parseExceptionThrown(exp);
|
||||
if (!m_file.empty() || m_line1 || m_line2 || !m_funcs.empty()) {
|
||||
@@ -204,16 +216,19 @@ BreakPointInfo::BreakPointInfo(bool regex, State state,
|
||||
|
||||
static int s_max_breakpoint_index = 0;
|
||||
void BreakPointInfo::createIndex() {
|
||||
TRACE(2, "BreakPointInfo::createIndex\n");
|
||||
m_index = ++s_max_breakpoint_index;
|
||||
}
|
||||
|
||||
BreakPointInfo::~BreakPointInfo() {
|
||||
TRACE(2, "BreakPointInfo::~BreakPointInfo\n");
|
||||
if (m_index && m_index == s_max_breakpoint_index) {
|
||||
--s_max_breakpoint_index;
|
||||
}
|
||||
}
|
||||
|
||||
void BreakPointInfo::sendImpl(DebuggerThriftBuffer &thrift) {
|
||||
TRACE(2, "BreakPointInfo::sendImpl\n");
|
||||
thrift.write(m_state);
|
||||
thrift.write(m_interrupt);
|
||||
thrift.write(m_file);
|
||||
@@ -232,6 +247,7 @@ void BreakPointInfo::sendImpl(DebuggerThriftBuffer &thrift) {
|
||||
}
|
||||
|
||||
void BreakPointInfo::recvImpl(DebuggerThriftBuffer &thrift) {
|
||||
TRACE(2, "BreakPointInfo::recvImpl\n");
|
||||
thrift.read(m_state);
|
||||
thrift.read(m_interrupt);
|
||||
thrift.read(m_file);
|
||||
@@ -250,11 +266,13 @@ void BreakPointInfo::recvImpl(DebuggerThriftBuffer &thrift) {
|
||||
}
|
||||
|
||||
void BreakPointInfo::setClause(const std::string &clause, bool check) {
|
||||
TRACE(2, "BreakPointInfo::setClause\n");
|
||||
m_clause = clause;
|
||||
m_check = check;
|
||||
}
|
||||
|
||||
void BreakPointInfo::changeBreakPointDepth(int stackDepth) {
|
||||
TRACE(2, "BreakPointInfo::changeBreakPointDepth\n");
|
||||
// if the breakpoint is equal or lower than the stack depth
|
||||
// delete it
|
||||
breakDepthStack.remove_if(
|
||||
@@ -263,16 +281,19 @@ void BreakPointInfo::changeBreakPointDepth(int stackDepth) {
|
||||
}
|
||||
|
||||
void BreakPointInfo::unsetBreakable(int stackDepth) {
|
||||
TRACE(2, "BreakPointInfo::unsetBreakable\n");
|
||||
breakDepthStack.push_back(stackDepth);
|
||||
}
|
||||
|
||||
void BreakPointInfo::setBreakable(int stackDepth) {
|
||||
TRACE(2, "BreakPointInfo::setBreakable\n");
|
||||
if (!breakDepthStack.empty() && breakDepthStack.back() == stackDepth) {
|
||||
breakDepthStack.pop_back();
|
||||
}
|
||||
}
|
||||
|
||||
bool BreakPointInfo::breakable(int stackDepth) const {
|
||||
TRACE(2, "BreakPointInfo::breakable\n");
|
||||
if (!breakDepthStack.empty() && breakDepthStack.back() == stackDepth) {
|
||||
return false;
|
||||
} else {
|
||||
@@ -281,6 +302,7 @@ bool BreakPointInfo::breakable(int stackDepth) const {
|
||||
}
|
||||
|
||||
void BreakPointInfo::toggle() {
|
||||
TRACE(2, "BreakPointInfo::toggle\n");
|
||||
switch (m_state) {
|
||||
case Always: setState(Once); break;
|
||||
case Once: setState(Disabled); break;
|
||||
@@ -292,6 +314,7 @@ void BreakPointInfo::toggle() {
|
||||
}
|
||||
|
||||
bool BreakPointInfo::valid() {
|
||||
TRACE(2, "BreakPointInfo::valid\n");
|
||||
if (m_valid) {
|
||||
switch (m_interrupt) {
|
||||
case BreakPointReached:
|
||||
@@ -320,10 +343,12 @@ bool BreakPointInfo::valid() {
|
||||
}
|
||||
|
||||
bool BreakPointInfo::same(BreakPointInfoPtr bpi) {
|
||||
TRACE(2, "BreakPointInfo::same\n");
|
||||
return desc() == bpi->desc();
|
||||
}
|
||||
|
||||
bool BreakPointInfo::match(InterruptType interrupt, InterruptSite &site) {
|
||||
TRACE(2, "BreakPointInfo::match\n");
|
||||
if (m_interrupt == interrupt) {
|
||||
switch (interrupt) {
|
||||
case RequestStarted:
|
||||
@@ -357,6 +382,7 @@ bool BreakPointInfo::match(InterruptType interrupt, InterruptSite &site) {
|
||||
}
|
||||
|
||||
std::string BreakPointInfo::state(bool padding) const {
|
||||
TRACE(2, "BreakPointInfo::state\n");
|
||||
switch (m_state) {
|
||||
case Always: return padding ? "ALWAYS " : "ALWAYS" ;
|
||||
case Once: return padding ? "ONCE " : "ONCE" ;
|
||||
@@ -369,6 +395,7 @@ std::string BreakPointInfo::state(bool padding) const {
|
||||
}
|
||||
|
||||
std::string BreakPointInfo::regex(const std::string &name) const {
|
||||
TRACE(2, "BreakPointInfo::regex\n");
|
||||
if (m_regex) {
|
||||
return "regex{" + name + "}";
|
||||
}
|
||||
@@ -376,6 +403,7 @@ std::string BreakPointInfo::regex(const std::string &name) const {
|
||||
}
|
||||
|
||||
std::string BreakPointInfo::getNamespace() const {
|
||||
TRACE(2, "BreakPointInfo::getNamespace\n");
|
||||
if (!m_funcs.empty()) {
|
||||
return m_funcs[0]->m_namespace;
|
||||
}
|
||||
@@ -383,6 +411,7 @@ std::string BreakPointInfo::getNamespace() const {
|
||||
}
|
||||
|
||||
std::string BreakPointInfo::getClass() const {
|
||||
TRACE(2, "BreakPointInfo::getClass\n");
|
||||
if (!m_funcs.empty()) {
|
||||
return m_funcs[0]->m_class;
|
||||
}
|
||||
@@ -390,6 +419,7 @@ std::string BreakPointInfo::getClass() const {
|
||||
}
|
||||
|
||||
std::string BreakPointInfo::getFunction() const {
|
||||
TRACE(2, "BreakPointInfo::getFunction\n");
|
||||
if (!m_funcs.empty()) {
|
||||
return m_funcs[0]->m_function;
|
||||
}
|
||||
@@ -397,6 +427,7 @@ std::string BreakPointInfo::getFunction() const {
|
||||
}
|
||||
|
||||
std::string BreakPointInfo::getFuncName() const {
|
||||
TRACE(2, "BreakPointInfo::getFuncName\n");
|
||||
if (!m_funcs.empty()) {
|
||||
return m_funcs[0]->getName();
|
||||
}
|
||||
@@ -404,6 +435,7 @@ std::string BreakPointInfo::getFuncName() const {
|
||||
}
|
||||
|
||||
std::string BreakPointInfo::site() const {
|
||||
TRACE(2, "BreakPointInfo::site\n");
|
||||
string ret;
|
||||
|
||||
string preposition = "at ";
|
||||
@@ -436,6 +468,7 @@ std::string BreakPointInfo::site() const {
|
||||
}
|
||||
|
||||
std::string BreakPointInfo::descBreakPointReached() const {
|
||||
TRACE(2, "BreakPointInfo::descBreakPointReached\n");
|
||||
string ret;
|
||||
for (unsigned int i = 0; i < m_funcs.size(); i++) {
|
||||
ret += (i == 0 ? "upon entering " : " called by ");
|
||||
@@ -468,6 +501,7 @@ std::string BreakPointInfo::descBreakPointReached() const {
|
||||
}
|
||||
|
||||
std::string BreakPointInfo::descExceptionThrown() const {
|
||||
TRACE(2, "BreakPointInfo::descExceptionThrown\n");
|
||||
string ret;
|
||||
if (!m_namespace.empty() || !m_class.empty()) {
|
||||
if (m_class == ErrorClassName) {
|
||||
@@ -488,6 +522,7 @@ std::string BreakPointInfo::descExceptionThrown() const {
|
||||
}
|
||||
|
||||
std::string BreakPointInfo::desc() const {
|
||||
TRACE(2, "BreakPointInfo::desc\n");
|
||||
string ret;
|
||||
switch (m_interrupt) {
|
||||
case BreakPointReached:
|
||||
@@ -517,6 +552,7 @@ std::string BreakPointInfo::desc() const {
|
||||
}
|
||||
|
||||
bool BreakPointInfo::parseLines(const std::string &token) {
|
||||
TRACE(2, "BreakPointInfo::parseLines\n");
|
||||
if (token.empty()) return false;
|
||||
|
||||
for (unsigned int i = 0; i < token.size(); i++) {
|
||||
@@ -573,6 +609,7 @@ bool BreakPointInfo::parseLines(const std::string &token) {
|
||||
|
||||
void BreakPointInfo::parseBreakPointReached(const std::string &exp,
|
||||
const std::string &file) {
|
||||
TRACE(2, "BreakPointInfo::parseBreakPointReached\n");
|
||||
string input = exp;
|
||||
|
||||
// everything after @ is URL
|
||||
@@ -660,6 +697,7 @@ void BreakPointInfo::parseBreakPointReached(const std::string &exp,
|
||||
}
|
||||
|
||||
void BreakPointInfo::parseExceptionThrown(const std::string &exp) {
|
||||
TRACE(2, "BreakPointInfo::parseExceptionThrown\n");
|
||||
string input = exp;
|
||||
|
||||
// everything after @ is URL
|
||||
@@ -685,6 +723,7 @@ void BreakPointInfo::parseExceptionThrown(const std::string &exp) {
|
||||
|
||||
bool BreakPointInfo::MatchFile(const char *haystack, int haystack_len,
|
||||
const std::string &needle) {
|
||||
TRACE(2, "BreakPointInfo::MatchFile(const char *haystack\n");
|
||||
int pos = haystack_len - needle.size();
|
||||
if ((pos == 0 || haystack[pos - 1] == '/') &&
|
||||
strcasecmp(haystack + pos, needle.c_str()) == 0) {
|
||||
@@ -700,6 +739,7 @@ bool BreakPointInfo::MatchFile(const char *haystack, int haystack_len,
|
||||
bool BreakPointInfo::MatchFile(const std::string& file,
|
||||
const std::string& fullPath,
|
||||
const std::string& relPath) {
|
||||
TRACE(2, "BreakPointInfo::MatchFile(const std::string&\n");
|
||||
if (file == fullPath || file == relPath) {
|
||||
return true;
|
||||
}
|
||||
@@ -717,6 +757,7 @@ bool BreakPointInfo::MatchFile(const std::string& file,
|
||||
|
||||
bool BreakPointInfo::MatchClass(const char *fcls, const std::string &bcls,
|
||||
bool regex, const char *func) {
|
||||
TRACE(2, "BreakPointInfo::MatchClass\n");
|
||||
if (bcls.empty()) return true;
|
||||
if (!fcls || !*fcls) return false;
|
||||
if (regex || !func || !*func) {
|
||||
@@ -737,6 +778,7 @@ bool BreakPointInfo::MatchClass(const char *fcls, const std::string &bcls,
|
||||
|
||||
bool BreakPointInfo::Match(const char *haystack, int haystack_len,
|
||||
const std::string &needle, bool regex, bool exact) {
|
||||
TRACE(2, "BreakPointInfo::Match\n");
|
||||
if (needle.empty()) {
|
||||
return true;
|
||||
}
|
||||
@@ -760,6 +802,7 @@ bool BreakPointInfo::Match(const char *haystack, int haystack_len,
|
||||
}
|
||||
|
||||
bool BreakPointInfo::checkException(CVarRef e) {
|
||||
TRACE(2, "BreakPointInfo::checkException\n");
|
||||
assert(!e.isNull());
|
||||
if (e.isObject()) {
|
||||
if (m_regex) {
|
||||
@@ -773,6 +816,7 @@ bool BreakPointInfo::checkException(CVarRef e) {
|
||||
}
|
||||
|
||||
bool BreakPointInfo::checkUrl(std::string &url) {
|
||||
TRACE(2, "BreakPointInfo::checkUrl\n");
|
||||
if (!m_url.empty()) {
|
||||
if (url.empty()) {
|
||||
url = "/";
|
||||
@@ -787,6 +831,7 @@ bool BreakPointInfo::checkUrl(std::string &url) {
|
||||
}
|
||||
|
||||
bool BreakPointInfo::checkLines(int line) {
|
||||
TRACE(2, "BreakPointInfo::checkLines\n");
|
||||
if (m_line1) {
|
||||
assert(m_line2 == -1 || m_line2 >= m_line1);
|
||||
return line >= m_line1 && (m_line2 == -1 || line <= m_line2);
|
||||
@@ -795,6 +840,7 @@ bool BreakPointInfo::checkLines(int line) {
|
||||
}
|
||||
|
||||
bool BreakPointInfo::checkStack(InterruptSite &site) {
|
||||
TRACE(2, "BreakPointInfo::checkStack\n");
|
||||
if (m_funcs.empty()) return true;
|
||||
|
||||
if (!Match(site.getNamespace(), 0, m_funcs[0]->m_namespace, m_regex, true) ||
|
||||
@@ -808,6 +854,7 @@ bool BreakPointInfo::checkStack(InterruptSite &site) {
|
||||
}
|
||||
|
||||
bool BreakPointInfo::checkClause() {
|
||||
TRACE(2, "BreakPointInfo::checkClause\n");
|
||||
if (!m_clause.empty()) {
|
||||
if (m_php.empty()) {
|
||||
if (m_check) {
|
||||
@@ -834,6 +881,7 @@ bool BreakPointInfo::checkClause() {
|
||||
|
||||
void BreakPointInfo::SendImpl(const BreakPointInfoPtrVec &bps,
|
||||
DebuggerThriftBuffer &thrift) {
|
||||
TRACE(2, "BreakPointInfo::SendImpl\n");
|
||||
int16_t size = bps.size();
|
||||
thrift.write(size);
|
||||
for (int i = 0; i < size; i++) {
|
||||
@@ -843,6 +891,7 @@ void BreakPointInfo::SendImpl(const BreakPointInfoPtrVec &bps,
|
||||
|
||||
void BreakPointInfo::RecvImpl(BreakPointInfoPtrVec &bps,
|
||||
DebuggerThriftBuffer &thrift) {
|
||||
TRACE(2, "BreakPointInfo::RecvImpl\n");
|
||||
int16_t size;
|
||||
thrift.read(size);
|
||||
bps.resize(size);
|
||||
|
||||
@@ -28,14 +28,18 @@
|
||||
namespace HPHP { namespace Eval {
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static const Trace::Module TRACEMOD = Trace::debugger;
|
||||
|
||||
Debugger Debugger::s_debugger;
|
||||
bool Debugger::s_clientStarted = false;
|
||||
|
||||
bool Debugger::StartServer() {
|
||||
TRACE(2, "Debugger::StartServer\n");
|
||||
return DebuggerServer::Start();
|
||||
}
|
||||
|
||||
DebuggerProxyPtr Debugger::StartClient(const DebuggerClientOptions &options) {
|
||||
TRACE(2, "Debugger::StartClient\n");
|
||||
SmartPtr<Socket> localProxy = DebuggerClient::Start(options);
|
||||
if (localProxy.get()) {
|
||||
s_clientStarted = true;
|
||||
@@ -45,6 +49,7 @@ DebuggerProxyPtr Debugger::StartClient(const DebuggerClientOptions &options) {
|
||||
}
|
||||
|
||||
void Debugger::Stop() {
|
||||
TRACE(2, "Debugger::Stop\n");
|
||||
s_debugger.m_proxyMap.clear();
|
||||
DebuggerServer::Stop();
|
||||
if (s_clientStarted) {
|
||||
@@ -55,30 +60,37 @@ void Debugger::Stop() {
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void Debugger::RegisterSandbox(const DSandboxInfo &sandbox) {
|
||||
TRACE(2, "Debugger::RegisterSandbox\n");
|
||||
s_debugger.registerSandbox(sandbox);
|
||||
}
|
||||
|
||||
void Debugger::UnregisterSandbox(CStrRef id) {
|
||||
TRACE(2, "Debugger::UnregisterSandbox\n");
|
||||
s_debugger.unregisterSandbox(id.get());
|
||||
}
|
||||
|
||||
void Debugger::RegisterThread() {
|
||||
TRACE(2, "Debugger::RegisterThread\n");
|
||||
s_debugger.registerThread();
|
||||
}
|
||||
|
||||
DebuggerProxyPtr Debugger::CreateProxy(SmartPtr<Socket> socket, bool local) {
|
||||
TRACE(2, "Debugger::CreateProxy\n");
|
||||
return s_debugger.createProxy(socket, local);
|
||||
}
|
||||
|
||||
void Debugger::RemoveProxy(DebuggerProxyPtr proxy) {
|
||||
TRACE(2, "Debugger::RemoveProxy\n");
|
||||
s_debugger.removeProxy(proxy);
|
||||
}
|
||||
|
||||
int Debugger::CountConnectedProxy() {
|
||||
TRACE(2, "Debugger::CountConnectedProxy\n");
|
||||
return s_debugger.countConnectedProxy();
|
||||
}
|
||||
|
||||
DebuggerProxyPtr Debugger::GetProxy() {
|
||||
TRACE(2, "Debugger::GetProxy\n");
|
||||
CStrRef sandboxId = g_context->getSandboxId();
|
||||
return s_debugger.findProxy(sandboxId.get());
|
||||
}
|
||||
@@ -86,31 +98,38 @@ DebuggerProxyPtr Debugger::GetProxy() {
|
||||
bool Debugger::SwitchSandbox(DebuggerProxyPtr proxy,
|
||||
const std::string &newId,
|
||||
bool force) {
|
||||
TRACE(2, "Debugger::SwitchSandbox\n");
|
||||
return s_debugger.switchSandbox(proxy, newId, force);
|
||||
}
|
||||
|
||||
void Debugger::GetRegisteredSandboxes(DSandboxInfoPtrVec &sandboxes) {
|
||||
TRACE(2, "Debugger::GetRegisteredSandboxes\n");
|
||||
s_debugger.getSandboxes(sandboxes);
|
||||
}
|
||||
|
||||
bool Debugger::IsThreadDebugging(int64_t id) {
|
||||
TRACE(2, "Debugger::IsThreadDebugging\n");
|
||||
return s_debugger.isThreadDebugging(id);
|
||||
}
|
||||
|
||||
void Debugger::RequestInterrupt(DebuggerProxyPtr proxy) {
|
||||
TRACE(2, "Debugger::RequestInterrupt\n");
|
||||
s_debugger.requestInterrupt(proxy);
|
||||
}
|
||||
|
||||
void Debugger::RetireDummySandboxThread(DummySandbox* toRetire) {
|
||||
TRACE(2, "Debugger::RetireDummySandboxThread\n");
|
||||
s_debugger.retireDummySandboxThread(toRetire);
|
||||
}
|
||||
|
||||
void Debugger::CleanupDummySandboxThreads() {
|
||||
TRACE(2, "Debugger::CleanupDummySandboxThreads\n");
|
||||
s_debugger.cleanupDummySandboxThreads();
|
||||
}
|
||||
|
||||
void Debugger::DebuggerSession(const DebuggerClientOptions& options,
|
||||
const std::string& file, bool restart) {
|
||||
TRACE(2, "Debugger::DebuggerSession: restart=%d\n", restart);
|
||||
if (options.extension.empty()) {
|
||||
// even if it's empty, still need to call for warmup
|
||||
hphp_invoke_simple("", true); // not to run the 1st file if compiled
|
||||
@@ -134,21 +153,25 @@ void Debugger::DebuggerSession(const DebuggerClientOptions& options,
|
||||
|
||||
void Debugger::InterruptSessionStarted(const char *file,
|
||||
const char *error /* = NULL */) {
|
||||
TRACE(2, "Debugger::InterruptSessionStarted\n");
|
||||
ThreadInfo::s_threadInfo->m_reqInjectionData.debugger = true;
|
||||
Interrupt(SessionStarted, file, nullptr, error);
|
||||
}
|
||||
|
||||
void Debugger::InterruptSessionEnded(const char *file) {
|
||||
TRACE(2, "Debugger::InterruptSessionEnded\n");
|
||||
Interrupt(SessionEnded, file);
|
||||
}
|
||||
|
||||
void Debugger::InterruptRequestStarted(const char *url) {
|
||||
TRACE(2, "Debugger::InterruptRequestStarted\n");
|
||||
if (ThreadInfo::s_threadInfo->m_reqInjectionData.debugger) {
|
||||
Interrupt(RequestStarted, url);
|
||||
}
|
||||
}
|
||||
|
||||
void Debugger::InterruptRequestEnded(const char *url) {
|
||||
TRACE(2, "Debugger::InterruptRequestEnded: url=%s\n", url);
|
||||
if (ThreadInfo::s_threadInfo->m_reqInjectionData.debugger) {
|
||||
Interrupt(RequestEnded, url);
|
||||
}
|
||||
@@ -157,6 +180,7 @@ void Debugger::InterruptRequestEnded(const char *url) {
|
||||
}
|
||||
|
||||
void Debugger::InterruptPSPEnded(const char *url) {
|
||||
TRACE(2, "Debugger::InterruptPSPEnded\n");
|
||||
if (ThreadInfo::s_threadInfo->m_reqInjectionData.debugger) {
|
||||
Interrupt(PSPEnded, url);
|
||||
}
|
||||
@@ -166,6 +190,7 @@ void Debugger::InterruptPSPEnded(const char *url) {
|
||||
// failed to handle an exeption. NB: this is quite distinct from the hook called
|
||||
// from iopThrow named phpDebuggerExceptionHook().
|
||||
bool Debugger::InterruptException(CVarRef e) {
|
||||
TRACE(2, "Debugger::InterruptException\n");
|
||||
if (RuntimeOption::EnableDebugger) {
|
||||
ThreadInfo *ti = ThreadInfo::s_threadInfo.getNoCheck();
|
||||
if (ti->m_reqInjectionData.debugger) {
|
||||
@@ -186,9 +211,11 @@ void Debugger::Interrupt(int type, const char *program,
|
||||
InterruptSite *site /* = NULL */,
|
||||
const char *error /* = NULL */) {
|
||||
assert(RuntimeOption::EnableDebugger);
|
||||
TRACE(2, "Debugger::Interrupt\n");
|
||||
|
||||
DebuggerProxyPtr proxy = GetProxy();
|
||||
if (proxy) {
|
||||
TRACE(3, "proxy != null\n");
|
||||
RequestInjectionData &rjdata = ThreadInfo::s_threadInfo->m_reqInjectionData;
|
||||
// The proxy will only service an interrupt if we've previously setup some
|
||||
// form of flow control command (steps, breakpoints, etc.) or if it's
|
||||
@@ -207,6 +234,7 @@ void Debugger::Interrupt(int type, const char *program,
|
||||
// interpreter so phpDebuggerOpcodeHook has a chance to work.
|
||||
rjdata.debuggerIntr = proxy->needInterruptForNonBreak();
|
||||
} else {
|
||||
TRACE(3, "proxy == null\n");
|
||||
// Debugger clients are disconnected abnormally, or this sandbox is not
|
||||
// being debugged.
|
||||
if (type == SessionStarted || type == SessionEnded) {
|
||||
@@ -229,6 +257,7 @@ void Debugger::Interrupt(int type, const char *program,
|
||||
// debugger.
|
||||
void Debugger::InterruptVMHook(int type /* = BreakPointReached */,
|
||||
CVarRef e /* = null_variant */) {
|
||||
TRACE(2, "Debugger::InterruptVMHook\n");
|
||||
// Computing the interrupt site here pulls in more data from the Unit to
|
||||
// describe the current execution point.
|
||||
InterruptSiteVM site(type == HardBreakPoint, e);
|
||||
@@ -243,11 +272,13 @@ void Debugger::InterruptVMHook(int type /* = BreakPointReached */,
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void Debugger::SetTextColors() {
|
||||
TRACE(2, "Debugger::SetTextColors\n");
|
||||
s_stdout_color = ANSI_COLOR_CYAN;
|
||||
s_stderr_color = ANSI_COLOR_RED;
|
||||
}
|
||||
|
||||
String Debugger::ColorStdout(CStrRef s) {
|
||||
TRACE(2, "Debugger::ColorStdout\n");
|
||||
if (s_stdout_color) {
|
||||
return String(s_stdout_color) + s + String(ANSI_COLOR_END);
|
||||
}
|
||||
@@ -255,6 +286,7 @@ String Debugger::ColorStdout(CStrRef s) {
|
||||
}
|
||||
|
||||
String Debugger::ColorStderr(CStrRef s) {
|
||||
TRACE(2, "Debugger::ColorStderr\n");
|
||||
if (s_stderr_color) {
|
||||
return String(s_stderr_color) + s + String(ANSI_COLOR_END);
|
||||
}
|
||||
@@ -264,6 +296,7 @@ String Debugger::ColorStderr(CStrRef s) {
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool Debugger::isThreadDebugging(int64_t tid) {
|
||||
TRACE(2, "Debugger::isThreadDebugging\n");
|
||||
ThreadInfoMap::const_accessor acc;
|
||||
if (m_threadInfos.find(acc, tid)) {
|
||||
ThreadInfo* ti = acc->second;
|
||||
@@ -273,6 +306,7 @@ bool Debugger::isThreadDebugging(int64_t tid) {
|
||||
}
|
||||
|
||||
void Debugger::registerThread() {
|
||||
TRACE(2, "Debugger::registerThread\n");
|
||||
ThreadInfo* ti = ThreadInfo::s_threadInfo.getNoCheck();
|
||||
int64_t tid = (int64_t)Process::GetThreadId();
|
||||
ThreadInfoMap::accessor acc;
|
||||
@@ -281,6 +315,7 @@ void Debugger::registerThread() {
|
||||
}
|
||||
|
||||
void Debugger::updateSandbox(const DSandboxInfo &sandbox) {
|
||||
TRACE(2, "Debugger::updateSandbox\n");
|
||||
const StringData* sd = StringData::GetStaticString(sandbox.id());
|
||||
SandboxMap::accessor acc;
|
||||
if (m_sandboxMap.insert(acc, sd)) {
|
||||
@@ -293,6 +328,7 @@ void Debugger::updateSandbox(const DSandboxInfo &sandbox) {
|
||||
}
|
||||
|
||||
void Debugger::getSandboxes(DSandboxInfoPtrVec &sandboxes) {
|
||||
TRACE(2, "Debugger::getSandboxes\n");
|
||||
sandboxes.reserve(m_sandboxMap.size());
|
||||
for (SandboxMap::const_iterator iter =
|
||||
m_sandboxMap.begin(); iter != m_sandboxMap.end(); ++iter) {
|
||||
@@ -305,6 +341,7 @@ void Debugger::getSandboxes(DSandboxInfoPtrVec &sandboxes) {
|
||||
}
|
||||
|
||||
void Debugger::registerSandbox(const DSandboxInfo &sandbox) {
|
||||
TRACE(2, "Debugger::registerSandbox\n");
|
||||
// update sandbox first
|
||||
updateSandbox(sandbox);
|
||||
|
||||
@@ -328,6 +365,7 @@ void Debugger::registerSandbox(const DSandboxInfo &sandbox) {
|
||||
}
|
||||
|
||||
void Debugger::unregisterSandbox(const StringData* sandboxId) {
|
||||
TRACE(2, "Debugger::unregisterSandbox\n");
|
||||
ThreadInfo *ti = ThreadInfo::s_threadInfo.getNoCheck();
|
||||
SandboxThreadInfoMap::accessor acc;
|
||||
if (m_sandboxThreadInfoMap.find(acc, sandboxId)) {
|
||||
@@ -352,6 +390,7 @@ void Debugger::unregisterSandbox(const StringData* sandboxId) {
|
||||
// force them all to start interpreting all of their code in an effort to gain
|
||||
// control in phpDebuggerOpcodeHook().
|
||||
void Debugger::requestInterrupt(DebuggerProxyPtr proxy) {
|
||||
TRACE(2, "Debugger::requestInterrupt\n");
|
||||
const StringData* sid = StringData::GetStaticString(proxy->getSandboxId());
|
||||
FOREACH_SANDBOX_THREAD_BEGIN(sid, ti)
|
||||
ti->m_reqInjectionData.debuggerIntr = true;
|
||||
@@ -364,6 +403,7 @@ void Debugger::requestInterrupt(DebuggerProxyPtr proxy) {
|
||||
}
|
||||
|
||||
void Debugger::setDebuggerFlag(const StringData* sandboxId, bool flag) {
|
||||
TRACE(2, "Debugger::setDebuggerFlag\n");
|
||||
FOREACH_SANDBOX_THREAD_BEGIN(sandboxId, ti)
|
||||
ti->m_reqInjectionData.debugger = flag;
|
||||
FOREACH_SANDBOX_THREAD_END()
|
||||
@@ -373,6 +413,7 @@ void Debugger::setDebuggerFlag(const StringData* sandboxId, bool flag) {
|
||||
#undef FOREACH_SANDBOX_THREAD_END
|
||||
|
||||
DebuggerProxyPtr Debugger::createProxy(SmartPtr<Socket> socket, bool local) {
|
||||
TRACE(2, "Debugger::createProxy\n");
|
||||
// Creates a proxy and threads needed to handle it. At this point, there is
|
||||
// not enough information to attach a sandbox.
|
||||
DebuggerProxyPtr proxy(new DebuggerProxyVM(socket, local));
|
||||
@@ -392,10 +433,12 @@ DebuggerProxyPtr Debugger::createProxy(SmartPtr<Socket> socket, bool local) {
|
||||
}
|
||||
|
||||
void Debugger::retireDummySandboxThread(DummySandbox* toRetire) {
|
||||
TRACE(2, "Debugger::retireDummySandboxThread\n");
|
||||
m_cleanupDummySandboxQ.push(toRetire);
|
||||
}
|
||||
|
||||
void Debugger::cleanupDummySandboxThreads() {
|
||||
TRACE(2, "Debugger::cleanupDummySandboxThreads\n");
|
||||
DummySandbox* ptr = nullptr;
|
||||
while (m_cleanupDummySandboxQ.try_pop(ptr)) {
|
||||
ptr->notify();
|
||||
@@ -413,6 +456,7 @@ void Debugger::cleanupDummySandboxThreads() {
|
||||
}
|
||||
|
||||
void Debugger::removeProxy(DebuggerProxyPtr proxy) {
|
||||
TRACE(2, "Debugger::removeProxy\n");
|
||||
if (proxy->getSandbox().valid()) {
|
||||
const StringData* sid = StringData::GetStaticString(proxy->getSandboxId());
|
||||
setDebuggerFlag(sid, false);
|
||||
@@ -428,6 +472,7 @@ void Debugger::removeProxy(DebuggerProxyPtr proxy) {
|
||||
}
|
||||
|
||||
DebuggerProxyPtr Debugger::findProxy(const StringData* sandboxId) {
|
||||
TRACE(2, "Debugger::findProxy\n");
|
||||
ProxyMap::const_accessor acc;
|
||||
if (m_proxyMap.find(acc, sandboxId)) {
|
||||
return acc->second;
|
||||
@@ -438,6 +483,7 @@ DebuggerProxyPtr Debugger::findProxy(const StringData* sandboxId) {
|
||||
bool Debugger::switchSandbox(DebuggerProxyPtr proxy,
|
||||
const std::string &newId,
|
||||
bool force) {
|
||||
TRACE(2, "Debugger::switchSandbox\n");
|
||||
const StringData* newSid = StringData::GetStaticString(newId);
|
||||
// Lock the proxy during the switch
|
||||
Lock l(proxy.get());
|
||||
@@ -455,6 +501,7 @@ bool Debugger::switchSandbox(DebuggerProxyPtr proxy,
|
||||
bool Debugger::switchSandboxImpl(DebuggerProxyPtr proxy,
|
||||
const StringData* newSid,
|
||||
bool force) {
|
||||
TRACE(2, "Debugger::switchSandboxImpln");
|
||||
// Take the new sandbox
|
||||
DebuggerProxyPtr dpp;
|
||||
{
|
||||
@@ -492,6 +539,7 @@ bool Debugger::switchSandboxImpl(DebuggerProxyPtr proxy,
|
||||
|
||||
void Debugger::updateProxySandbox(DebuggerProxyPtr proxy,
|
||||
const StringData* sandboxId) {
|
||||
TRACE(2, "Debugger::updateProxySandbox\n");
|
||||
// update proxy's sandbox info from what is on file
|
||||
SandboxMap::const_accessor acc;
|
||||
if (m_sandboxMap.find(acc, sandboxId)) {
|
||||
@@ -506,19 +554,23 @@ void Debugger::updateProxySandbox(DebuggerProxyPtr proxy,
|
||||
}
|
||||
|
||||
DebuggerDummyEnv::DebuggerDummyEnv() {
|
||||
TRACE(2, "DebuggerDummyEnv::DebuggerDummyEnv\n");
|
||||
g_vmContext->enterDebuggerDummyEnv();
|
||||
}
|
||||
|
||||
DebuggerDummyEnv::~DebuggerDummyEnv() {
|
||||
TRACE(2, "DebuggerDummyEnv::~DebuggerDummyEnv\n");
|
||||
g_vmContext->exitDebuggerDummyEnv();
|
||||
}
|
||||
|
||||
EvalBreakControl::EvalBreakControl(bool noBreak) {
|
||||
TRACE(2, "EvalBreakControl::EvalBreakControl\n");
|
||||
m_noBreakSave = g_vmContext->m_dbgNoBreak;
|
||||
g_vmContext->m_dbgNoBreak = noBreak;
|
||||
}
|
||||
|
||||
EvalBreakControl::~EvalBreakControl() {
|
||||
TRACE(2, "EvalBreakControl::~EvalBreakControl\n");
|
||||
g_vmContext->m_dbgNoBreak = m_noBreakSave;
|
||||
}
|
||||
|
||||
|
||||
@@ -23,7 +23,10 @@
|
||||
namespace HPHP { namespace Eval {
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static const Trace::Module TRACEMOD = Trace::debugger;
|
||||
|
||||
const std::string &DSandboxInfo::id() const {
|
||||
TRACE(2, "DSandboxInfo::id\n");
|
||||
if (m_cached_id.empty() && !m_user.empty()) {
|
||||
m_cached_id = m_user + "\t" + m_name;
|
||||
}
|
||||
@@ -31,6 +34,7 @@ const std::string &DSandboxInfo::id() const {
|
||||
}
|
||||
|
||||
const std::string DSandboxInfo::desc() const {
|
||||
TRACE(2, "DSandboxInfo::desc\n");
|
||||
string ret = m_user + "'s " + m_name + " sandbox";
|
||||
if (!m_path.empty()) {
|
||||
ret += " at " + m_path;
|
||||
@@ -39,12 +43,14 @@ const std::string DSandboxInfo::desc() const {
|
||||
}
|
||||
|
||||
DSandboxInfo DSandboxInfo::CreateDummyInfo(uint64_t unique) {
|
||||
TRACE(2, "DSandboxInfo::CreateDummyInfo\n");
|
||||
char buf[64];
|
||||
snprintf(buf, 64, "dummy\t0x%" PRIu64, unique);
|
||||
return DSandboxInfo(std::string(buf));
|
||||
}
|
||||
|
||||
void DSandboxInfo::set(const std::string &id) {
|
||||
TRACE(2, "DSandboxInfo::set\n");
|
||||
m_cached_id.clear();
|
||||
m_user.clear();
|
||||
m_name.clear();
|
||||
@@ -60,18 +66,21 @@ void DSandboxInfo::set(const std::string &id) {
|
||||
}
|
||||
|
||||
void DSandboxInfo::update(const DSandboxInfo &src) {
|
||||
TRACE(2, "DSandboxInfo::update\n");
|
||||
if (!src.m_path.empty() && m_path.empty()) {
|
||||
m_path = src.m_path;
|
||||
}
|
||||
}
|
||||
|
||||
void DSandboxInfo::sendImpl(ThriftBuffer &thrift) {
|
||||
TRACE(2, "DSandboxInfo::sendImpl\n");
|
||||
thrift.write(m_user);
|
||||
thrift.write(m_name);
|
||||
thrift.write(m_path);
|
||||
}
|
||||
|
||||
void DSandboxInfo::recvImpl(ThriftBuffer &thrift) {
|
||||
TRACE(2, "DSandboxInfo::recvImpl\n");
|
||||
thrift.read(m_user);
|
||||
thrift.read(m_name);
|
||||
thrift.read(m_path);
|
||||
@@ -80,6 +89,7 @@ void DSandboxInfo::recvImpl(ThriftBuffer &thrift) {
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void DThreadInfo::sendImpl(ThriftBuffer &thrift) {
|
||||
TRACE(2, "DThreadInfo::sendImpl\n");
|
||||
thrift.write(m_id);
|
||||
thrift.write(m_desc);
|
||||
thrift.write(m_type);
|
||||
@@ -87,6 +97,7 @@ void DThreadInfo::sendImpl(ThriftBuffer &thrift) {
|
||||
}
|
||||
|
||||
void DThreadInfo::recvImpl(ThriftBuffer &thrift) {
|
||||
TRACE(2, "DThreadInfo::recvImpl\n");
|
||||
thrift.read(m_id);
|
||||
thrift.read(m_desc);
|
||||
thrift.read(m_type);
|
||||
@@ -96,18 +107,21 @@ void DThreadInfo::recvImpl(ThriftBuffer &thrift) {
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void DFunctionInfo::sendImpl(ThriftBuffer &thrift) {
|
||||
TRACE(2, "DFunctionInfo::sendImpl\n");
|
||||
thrift.write(m_namespace);
|
||||
thrift.write(m_class);
|
||||
thrift.write(m_function);
|
||||
}
|
||||
|
||||
void DFunctionInfo::recvImpl(ThriftBuffer &thrift) {
|
||||
TRACE(2, "DFunctionInfo::recvImpl\n");
|
||||
thrift.read(m_namespace);
|
||||
thrift.read(m_class);
|
||||
thrift.read(m_function);
|
||||
}
|
||||
|
||||
std::string DFunctionInfo::getName() const {
|
||||
TRACE(2, "DFunctionInfo::getName\n");
|
||||
if (m_function.empty() || m_class.empty()) {
|
||||
return m_function;
|
||||
} else {
|
||||
@@ -116,6 +130,7 @@ std::string DFunctionInfo::getName() const {
|
||||
}
|
||||
|
||||
std::string DFunctionInfo::site(std::string &preposition) const {
|
||||
TRACE(2, "DFunctionInfo::site\n");
|
||||
string ret;
|
||||
preposition = "at ";
|
||||
if (!m_class.empty()) {
|
||||
@@ -144,6 +159,7 @@ std::string DFunctionInfo::site(std::string &preposition) const {
|
||||
}
|
||||
|
||||
std::string DFunctionInfo::desc(const BreakPointInfo *bpi) const {
|
||||
TRACE(2, "DFunctionInfo::desc\n");
|
||||
string ret;
|
||||
if (!m_class.empty()) {
|
||||
string cls;
|
||||
@@ -172,6 +188,7 @@ std::string DFunctionInfo::desc(const BreakPointInfo *bpi) const {
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
std::string Macro::desc(const char *indent) {
|
||||
TRACE(2, "Macro::desc\n");
|
||||
string ret;
|
||||
for (unsigned int i = 0; i < m_cmds.size(); i++) {
|
||||
if (indent) ret += indent;
|
||||
@@ -182,11 +199,13 @@ std::string Macro::desc(const char *indent) {
|
||||
}
|
||||
|
||||
void Macro::load(Hdf node) {
|
||||
TRACE(2, "Macro::load\n");
|
||||
m_name = node["name"].getString();
|
||||
node["cmds"].get(m_cmds);
|
||||
}
|
||||
|
||||
void Macro::save(Hdf node) {
|
||||
TRACE(2, "Macro::save\n");
|
||||
node["name"] = m_name;
|
||||
for (unsigned int i = 0; i < m_cmds.size(); i++) {
|
||||
node["cmds"][i] = m_cmds[i];
|
||||
@@ -274,6 +293,7 @@ static void get_color(int tokid, int prev, int next,
|
||||
const char **palette =
|
||||
DebuggerClient::DefaultCodeColors) {
|
||||
|
||||
TRACE(2, "debugger_base:get_color\n");
|
||||
#undef YYTOKENTYPE
|
||||
#ifdef YYTOKEN_MAP
|
||||
#undef YYTOKEN_MAP
|
||||
@@ -366,6 +386,7 @@ static void get_color(int tokid, int prev, int next,
|
||||
|
||||
static void color_line_no(StringBuffer &sb, int line, int lineFocus0,
|
||||
int lineFocus1, const char *color) {
|
||||
TRACE(2, "debugger_base:color_line_no\n");
|
||||
if (((line == lineFocus0 && lineFocus1 == 0) ||
|
||||
(line >= lineFocus0 && line <= lineFocus1)) &&
|
||||
DebuggerClient::HighlightBgColor) {
|
||||
@@ -381,6 +402,7 @@ static void append_line_no(StringBuffer &sb, const char *text,
|
||||
int lineFocus0, int charFocus0, int lineFocus1,
|
||||
int charFocus1, const char **palette =
|
||||
DebuggerClient::DefaultCodeColors) {
|
||||
TRACE(2, "debugger_base:append_line_no\n");
|
||||
const char *colorLineNo = palette[CodeColorLineNo * 2];
|
||||
const char *endLineNo = palette[CodeColorLineNo * 2 + 1];
|
||||
|
||||
@@ -435,6 +457,7 @@ static void append_line_no(StringBuffer &sb, const char *text,
|
||||
String highlight_code(CStrRef source, int line /* = 0 */,
|
||||
int lineFocus0 /* = 0 */, int charFocus0 /* = 0 */,
|
||||
int lineFocus1 /* = 0 */, int charFocus1 /* = 0 */) {
|
||||
TRACE(2, "debugger_base:highlight_code\n");
|
||||
String prepended = "<?php\n";
|
||||
prepended += source;
|
||||
String highlighted = highlight_php(prepended, line, lineFocus0, charFocus0,
|
||||
@@ -446,6 +469,7 @@ String highlight_code(CStrRef source, int line /* = 0 */,
|
||||
string check_char_highlight(int lineFocus0, int charFocus0,
|
||||
int lineFocus1, int charFocus1,
|
||||
Location &loc) {
|
||||
TRACE(2, "debugger_base:check_char_highlight\n");
|
||||
if (DebuggerClient::HighlightBgColor &&
|
||||
lineFocus0 && charFocus0 && lineFocus1 && charFocus1 &&
|
||||
loc.line0 * 1000 + loc.char0 >= lineFocus0 * 1000 + charFocus0 &&
|
||||
@@ -459,6 +483,7 @@ string check_char_highlight(int lineFocus0, int charFocus0,
|
||||
String highlight_php(CStrRef source, int line /* = 0 */,
|
||||
int lineFocus0 /* = 0 */, int charFocus0 /* = 0 */,
|
||||
int lineFocus1 /* = 0 */, int charFocus1 /* = 0 */) {
|
||||
TRACE(2, "debugger_base:highlight_php\n");
|
||||
StringBuffer res;
|
||||
Scanner scanner(source.data(), source.size(),
|
||||
Scanner::AllowShortTags | Scanner::ReturnAllTokens);
|
||||
|
||||
@@ -43,9 +43,12 @@ using namespace HPHP::Util::TextArt;
|
||||
namespace HPHP { namespace Eval {
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static const Trace::Module TRACEMOD = Trace::debugger;
|
||||
|
||||
static boost::scoped_ptr<DebuggerClient> debugger_client;
|
||||
|
||||
static DebuggerClient& getStaticDebuggerClient() {
|
||||
TRACE(2, "DebuggerClient::getStaticDebuggerClient\n");
|
||||
/*
|
||||
* DebuggerClient acquires global mutexes in its constructor, so we
|
||||
* allocate s_debugger_client lazily to ensure that all of the
|
||||
@@ -63,6 +66,7 @@ static DebuggerClient& getStaticDebuggerClient() {
|
||||
}
|
||||
|
||||
void shutdown_hphpd() {
|
||||
TRACE(2, "DebuggerClient::shutdown_hphpd\n");
|
||||
if (debugger_client) {
|
||||
debugger_client->resetSmartAllocatedMembers();
|
||||
debugger_client.reset();
|
||||
@@ -73,10 +77,12 @@ void shutdown_hphpd() {
|
||||
// readline setups
|
||||
|
||||
static char* debugger_generator(const char* text, int state) {
|
||||
TRACE(2, "DebuggerClient::debugger_generator\n");
|
||||
return getStaticDebuggerClient().getCompletion(text, state);
|
||||
}
|
||||
|
||||
static char **debugger_completion(const char *text, int start, int end) {
|
||||
TRACE(2, "DebuggerClient::debugger_completion\n");
|
||||
if (getStaticDebuggerClient().setCompletion(text, start, end)) {
|
||||
return rl_completion_matches((char*)text, &debugger_generator);
|
||||
}
|
||||
@@ -84,10 +90,12 @@ static char **debugger_completion(const char *text, int start, int end) {
|
||||
}
|
||||
|
||||
static void debugger_signal_handler(int sig) {
|
||||
TRACE(2, "DebuggerClient::debugger_signal_handler\n");
|
||||
getStaticDebuggerClient().onSignal(sig);
|
||||
}
|
||||
|
||||
void DebuggerClient::onSignal(int sig) {
|
||||
TRACE(2, "DebuggerClient::onSignal\n");
|
||||
if (m_inputState == TakingInterrupt) {
|
||||
time_t now = time(0);
|
||||
|
||||
@@ -114,6 +122,7 @@ void DebuggerClient::onSignal(int sig) {
|
||||
}
|
||||
|
||||
int DebuggerClient::pollSignal() {
|
||||
TRACE(2, "DebuggerClient::pollSignal\n");
|
||||
int ret = m_signum;
|
||||
m_signum = CmdSignal::SignalNone;
|
||||
return ret;
|
||||
@@ -127,6 +136,7 @@ int DebuggerClient::pollSignal() {
|
||||
class ReadlineApp {
|
||||
public:
|
||||
ReadlineApp() {
|
||||
TRACE(2, "ReadlineApp::ReadlineApp\n");
|
||||
DebuggerClient::AdjustScreenMetrics();
|
||||
|
||||
rl_attempted_completion_function = debugger_completion;
|
||||
@@ -135,11 +145,14 @@ public:
|
||||
rl_catch_signals = 0;
|
||||
signal(SIGINT, debugger_signal_handler);
|
||||
|
||||
TRACE(3, "ReadlineApp::ReadlineApp, about to call read_history\n");
|
||||
read_history((Process::GetHomeDirectory() +
|
||||
DebuggerClient::HistoryFileName).c_str());
|
||||
TRACE(3, "ReadlineApp::ReadlineApp, done calling read_history\n");
|
||||
}
|
||||
|
||||
~ReadlineApp() {
|
||||
TRACE(2, "ReadlineApp::~ReadlineApp\n");
|
||||
write_history((Process::GetHomeDirectory() +
|
||||
DebuggerClient::HistoryFileName).c_str());
|
||||
}
|
||||
@@ -152,15 +165,18 @@ class ReadlineWaitCursor {
|
||||
public:
|
||||
ReadlineWaitCursor()
|
||||
: m_thread(this, &ReadlineWaitCursor::animate), m_waiting(true) {
|
||||
TRACE(2, "ReadlineWaitCursor::ReadlineWaitCursor\n");
|
||||
m_thread.start();
|
||||
}
|
||||
|
||||
~ReadlineWaitCursor() {
|
||||
TRACE(2, "ReadlineWaitCursor::~ReadlineWaitCursor\n");
|
||||
m_waiting = false;
|
||||
m_thread.waitForEnd();
|
||||
}
|
||||
|
||||
void animate() {
|
||||
TRACE(2, "ReadlineWaitCursor::animate\n");
|
||||
m_line = rl_line_buffer;
|
||||
while (m_waiting) {
|
||||
frame('|'); frame('/'); frame('-'); frame('\\');
|
||||
@@ -175,6 +191,7 @@ private:
|
||||
string m_line;
|
||||
|
||||
void frame(char ch) {
|
||||
TRACE(2, "ReadlineWaitCursor::getStaticDebuggerClient\n");
|
||||
string line = m_line + ch;
|
||||
rl_replace_line(line.c_str(), 1);
|
||||
rl_redisplay();
|
||||
@@ -218,6 +235,7 @@ const char *DebuggerClient::DefaultCodeColors[] = {
|
||||
};
|
||||
|
||||
void DebuggerClient::LoadColors(Hdf hdf) {
|
||||
TRACE(2, "DebuggerClient::LoadColors\n");
|
||||
HelpColor = LoadColor(hdf["Help"], "BROWN");
|
||||
InfoColor = LoadColor(hdf["Info"], "GREEN");
|
||||
OutputColor = LoadColor(hdf["Output"], "CYAN");
|
||||
@@ -240,6 +258,7 @@ void DebuggerClient::LoadColors(Hdf hdf) {
|
||||
}
|
||||
|
||||
const char *DebuggerClient::LoadColor(Hdf hdf, const char *defaultName) {
|
||||
TRACE(2, "DebuggerClient::LoadColor\n");
|
||||
const char *name = hdf.get(defaultName);
|
||||
hdf = name; // for starter
|
||||
const char *color = get_color_by_name(name);
|
||||
@@ -251,6 +270,7 @@ const char *DebuggerClient::LoadColor(Hdf hdf, const char *defaultName) {
|
||||
}
|
||||
|
||||
const char *DebuggerClient::LoadBgColor(Hdf hdf, const char *defaultName) {
|
||||
TRACE(2, "DebuggerClient::LoadBgColor\n");
|
||||
const char *name = hdf.get(defaultName);
|
||||
hdf = name; // for starter
|
||||
const char *color = get_bgcolor_by_name(name);
|
||||
@@ -263,12 +283,14 @@ const char *DebuggerClient::LoadBgColor(Hdf hdf, const char *defaultName) {
|
||||
|
||||
void DebuggerClient::LoadCodeColor(CodeColor index, Hdf hdf,
|
||||
const char *defaultName) {
|
||||
TRACE(2, "DebuggerClient::LoadCodeColor\n");
|
||||
const char *color = LoadColor(hdf, defaultName);
|
||||
DefaultCodeColors[index * 2] = color;
|
||||
DefaultCodeColors[index * 2 + 1] = color ? ANSI_COLOR_END : nullptr;
|
||||
}
|
||||
|
||||
SmartPtr<Socket> DebuggerClient::Start(const DebuggerClientOptions &options) {
|
||||
TRACE(2, "DebuggerClient::Start\n");
|
||||
Debugger::SetTextColors();
|
||||
SmartPtr<Socket> ret = getStaticDebuggerClient().connectLocal();
|
||||
getStaticDebuggerClient().start(options);
|
||||
@@ -276,19 +298,23 @@ SmartPtr<Socket> DebuggerClient::Start(const DebuggerClientOptions &options) {
|
||||
}
|
||||
|
||||
void DebuggerClient::Stop() {
|
||||
TRACE(2, "DebuggerClient::Stop\n");
|
||||
getStaticDebuggerClient().stop();
|
||||
}
|
||||
|
||||
void DebuggerClient::AdjustScreenMetrics() {
|
||||
TRACE(2, "entered: DebuggerClient::AdjustScreenMetrics\n");
|
||||
int rows = 0; int cols = 0;
|
||||
rl_get_screen_size(&rows, &cols);
|
||||
if (rows > 0 && cols > 0) {
|
||||
LineWidth = cols - 4;
|
||||
ScrollBlockSize = CodeBlockSize = rows - (rows >> 2);
|
||||
}
|
||||
TRACE(2, "leaving: DebuggerClient::AdjustScreenMetrics\n");
|
||||
}
|
||||
|
||||
bool DebuggerClient::IsValidNumber(const std::string &arg) {
|
||||
TRACE(2, "DebuggerClient::IsValidNumber\n");
|
||||
if (arg.empty()) return false;
|
||||
for (unsigned int i = 0; i < arg.size(); i++) {
|
||||
if (!isdigit(arg[i])) {
|
||||
@@ -300,6 +326,7 @@ bool DebuggerClient::IsValidNumber(const std::string &arg) {
|
||||
|
||||
String DebuggerClient::FormatVariable(CVarRef v, int maxlen /* = 80 */,
|
||||
bool vardump /* = false */) {
|
||||
TRACE(2, "DebuggerClient::FormatVariable\n");
|
||||
String value;
|
||||
if (maxlen <= 0) {
|
||||
try {
|
||||
@@ -331,6 +358,7 @@ String DebuggerClient::FormatVariable(CVarRef v, int maxlen /* = 80 */,
|
||||
|
||||
String DebuggerClient::FormatInfoVec(const IDebuggable::InfoVec &info,
|
||||
int *nameLen /* = NULL */) {
|
||||
TRACE(2, "DebuggerClient::FormatInfoVec\n");
|
||||
// vertical align names
|
||||
int maxlen = 0;
|
||||
for (unsigned int i = 0; i < info.size(); i++) {
|
||||
@@ -356,6 +384,7 @@ String DebuggerClient::FormatInfoVec(const IDebuggable::InfoVec &info,
|
||||
}
|
||||
|
||||
String DebuggerClient::FormatTitle(const char *title) {
|
||||
TRACE(2, "DebuggerClient::FormatTitle\n");
|
||||
String dash = StringUtil::Repeat(BOX_H, (LineWidth - strlen(title)) / 2 - 4);
|
||||
|
||||
StringBuffer sb;
|
||||
@@ -381,10 +410,12 @@ DebuggerClient::DebuggerClient(std::string name /* = "" */)
|
||||
m_threadId(0), m_listLine(0), m_listLineFocus(0), m_frame(0),
|
||||
m_clientState(StateUninit), m_inApiUse(false),
|
||||
m_nameForApi(name), m_usageLogFP(nullptr) {
|
||||
TRACE(2, "DebuggerClient::DebuggerClient\n");
|
||||
initUsageLogging();
|
||||
}
|
||||
|
||||
DebuggerClient::~DebuggerClient() {
|
||||
TRACE(2, "DebuggerClient::~DebuggerClient\n");
|
||||
m_stopped = true;
|
||||
m_mainThread.waitForEnd();
|
||||
FILE *f = getLogFileHandler();
|
||||
@@ -396,6 +427,7 @@ DebuggerClient::~DebuggerClient() {
|
||||
}
|
||||
|
||||
void DebuggerClient::reset() {
|
||||
TRACE(2, "DebuggerClient::reset\n");
|
||||
for (unsigned int i = 0; i < m_machines.size(); i++) {
|
||||
m_machines[i]->m_thrift.close();
|
||||
}
|
||||
@@ -408,10 +440,12 @@ void DebuggerClient::reset() {
|
||||
}
|
||||
|
||||
bool DebuggerClient::isLocal() {
|
||||
TRACE(2, "DebuggerClient::isLocal\n");
|
||||
return !isApiMode() && m_machines[0] == m_machine;
|
||||
}
|
||||
|
||||
bool DebuggerClient::connect(const std::string &host, int port) {
|
||||
TRACE(2, "DebuggerClient::connect\n");
|
||||
assert(isApiMode() ||
|
||||
(!m_machines.empty() && m_machines[0]->m_name == LocalPrompt));
|
||||
for (unsigned int i = 1; i < m_machines.size(); i++) {
|
||||
@@ -425,6 +459,7 @@ bool DebuggerClient::connect(const std::string &host, int port) {
|
||||
}
|
||||
|
||||
bool DebuggerClient::connectRPC(const std::string &host, int port) {
|
||||
TRACE(2, "DebuggerClient::connectRPC\n");
|
||||
assert(!m_machines.empty());
|
||||
DMachineInfoPtr local = m_machines[0];
|
||||
assert(local->m_name == LocalPrompt);
|
||||
@@ -436,6 +471,7 @@ bool DebuggerClient::connectRPC(const std::string &host, int port) {
|
||||
}
|
||||
|
||||
bool DebuggerClient::disconnect() {
|
||||
TRACE(2, "DebuggerClient::disconnect\n");
|
||||
assert(!m_machines.empty());
|
||||
DMachineInfoPtr local = m_machines[0];
|
||||
assert(local->m_name == LocalPrompt);
|
||||
@@ -446,6 +482,7 @@ bool DebuggerClient::disconnect() {
|
||||
}
|
||||
|
||||
void DebuggerClient::switchMachine(DMachineInfoPtr machine) {
|
||||
TRACE(2, "DebuggerClient::switchMachine\n");
|
||||
m_rpcHost.clear();
|
||||
machine->m_initialized = false; // even if m_machine == machine
|
||||
|
||||
@@ -465,6 +502,7 @@ void DebuggerClient::switchMachine(DMachineInfoPtr machine) {
|
||||
}
|
||||
|
||||
SmartPtr<Socket> DebuggerClient::connectLocal() {
|
||||
TRACE(2, "DebuggerClient::connectLocal\n");
|
||||
int fds[2];
|
||||
if (socketpair(AF_UNIX, SOCK_STREAM, 0, fds) != 0) {
|
||||
throw Exception("unable to create socket pair for local debugging");
|
||||
@@ -485,6 +523,7 @@ SmartPtr<Socket> DebuggerClient::connectLocal() {
|
||||
}
|
||||
|
||||
bool DebuggerClient::connectRemote(const std::string &host, int port) {
|
||||
TRACE(2, "DebuggerClient::connectRemote\n");
|
||||
if (port <= 0) {
|
||||
port = RuntimeOption::DebuggerServerPort;
|
||||
}
|
||||
@@ -510,6 +549,7 @@ bool DebuggerClient::connectRemote(const std::string &host, int port) {
|
||||
}
|
||||
|
||||
bool DebuggerClient::reconnect() {
|
||||
TRACE(2, "DebuggerClient::reconnect\n");
|
||||
assert(m_machine);
|
||||
string &host = m_machine->m_name;
|
||||
int port = m_machine->m_port;
|
||||
@@ -539,6 +579,7 @@ bool DebuggerClient::reconnect() {
|
||||
}
|
||||
|
||||
std::string DebuggerClient::getPrompt() {
|
||||
TRACE(2, "DebuggerClient::getPrompt\n");
|
||||
if (NoPrompt) {
|
||||
return "";
|
||||
}
|
||||
@@ -558,6 +599,7 @@ std::string DebuggerClient::getPrompt() {
|
||||
}
|
||||
|
||||
void DebuggerClient::init(const DebuggerClientOptions &options) {
|
||||
TRACE(2, "DebuggerClient::init\n");
|
||||
m_options = options;
|
||||
|
||||
if (isApiMode()) {
|
||||
@@ -603,20 +645,24 @@ void DebuggerClient::init(const DebuggerClientOptions &options) {
|
||||
}
|
||||
|
||||
void DebuggerClient::start(const DebuggerClientOptions &options) {
|
||||
TRACE(2, "DebuggerClient::start\n");
|
||||
init(options);
|
||||
m_mainThread.start();
|
||||
}
|
||||
|
||||
void DebuggerClient::stop() {
|
||||
TRACE(2, "DebuggerClient::stop\n");
|
||||
m_stopped = true;
|
||||
m_mainThread.waitForEnd();
|
||||
}
|
||||
|
||||
void DebuggerClient::run() {
|
||||
TRACE(2, "DebuggerClient::run\n");
|
||||
// Make sure we don't run the interface thread for API mode
|
||||
assert(!isApiMode());
|
||||
|
||||
ReadlineApp app;
|
||||
TRACE(3, "DebuggerClient::run, about to call playMacro\n");
|
||||
playMacro("startup");
|
||||
|
||||
if (!m_options.cmds.empty()) {
|
||||
@@ -660,12 +706,14 @@ void DebuggerClient::run() {
|
||||
// auto-complete
|
||||
|
||||
void DebuggerClient::updateLiveLists() {
|
||||
TRACE(2, "DebuggerClient::updateLiveLists\n");
|
||||
ReadlineWaitCursor waitCursor;
|
||||
CmdInfo::UpdateLiveLists(this);
|
||||
m_acLiveListsDirty = false;
|
||||
}
|
||||
|
||||
void DebuggerClient::promptFunctionPrototype() {
|
||||
TRACE(2, "DebuggerClient::promptFunctionPrototype\n");
|
||||
if (m_acProtoTypePrompted) return;
|
||||
m_acProtoTypePrompted = true;
|
||||
|
||||
@@ -698,6 +746,7 @@ void DebuggerClient::promptFunctionPrototype() {
|
||||
}
|
||||
|
||||
bool DebuggerClient::setCompletion(const char *text, int start, int end) {
|
||||
TRACE(2, "DebuggerClient::setCompletion\n");
|
||||
if (m_inputState == TakingCommand) {
|
||||
parseCommand(rl_line_buffer);
|
||||
if (*text) {
|
||||
@@ -712,6 +761,7 @@ bool DebuggerClient::setCompletion(const char *text, int start, int end) {
|
||||
}
|
||||
|
||||
void DebuggerClient::addCompletion(AutoComplete type) {
|
||||
TRACE(2, "DebuggerClient::addCompletion(AutoComplete type)\n");
|
||||
if (type < 0 || type >= AutoCompleteCount) {
|
||||
Logger::Error("Invalid auto completion enum: %d", type);
|
||||
return;
|
||||
@@ -739,19 +789,23 @@ void DebuggerClient::addCompletion(AutoComplete type) {
|
||||
}
|
||||
|
||||
void DebuggerClient::addCompletion(const char **list) {
|
||||
TRACE(2, "DebuggerClient::addCompletion(const char **list)\n");
|
||||
m_acLists.push_back(list);
|
||||
}
|
||||
|
||||
void DebuggerClient::addCompletion(const char *name) {
|
||||
TRACE(2, "DebuggerClient::addCompletion(const char *name)\n");
|
||||
m_acStrings.push_back(name);
|
||||
}
|
||||
|
||||
void DebuggerClient::addCompletion(const std::vector<std::string> &items) {
|
||||
TRACE(2, "DebuggerClient::addCompletion(const std::vector<std::string>)\n");
|
||||
m_acItems.insert(m_acItems.end(), items.begin(), items.end());
|
||||
}
|
||||
|
||||
char *DebuggerClient::getCompletion(const std::vector<std::string> &items,
|
||||
const char *text) {
|
||||
TRACE(2, "DebuggerClient::getCompletion(const std::vector<std::string>\n");
|
||||
while (++m_acPos < (int)items.size()) {
|
||||
const char *p = items[m_acPos].c_str();
|
||||
if (m_acLen == 0 || strncasecmp(p, text, m_acLen) == 0) {
|
||||
@@ -764,6 +818,7 @@ char *DebuggerClient::getCompletion(const std::vector<std::string> &items,
|
||||
|
||||
std::vector<std::string> DebuggerClient::getAllCompletions(
|
||||
std::string const &text) {
|
||||
TRACE(2, "DebuggerClient::getAllCompletions\n");
|
||||
std::vector<std::string> res;
|
||||
|
||||
if (m_acLiveListsDirty) {
|
||||
@@ -784,6 +839,7 @@ std::vector<std::string> DebuggerClient::getAllCompletions(
|
||||
|
||||
char *DebuggerClient::getCompletion(const std::vector<const char *> &items,
|
||||
const char *text) {
|
||||
TRACE(2, "DebuggerClient::getCompletion(const std::vector<const char *>\n");
|
||||
while (++m_acPos < (int)items.size()) {
|
||||
const char *p = items[m_acPos];
|
||||
if (m_acLen == 0 || strncasecmp(p, text, m_acLen) == 0) {
|
||||
@@ -795,11 +851,13 @@ char *DebuggerClient::getCompletion(const std::vector<const char *> &items,
|
||||
}
|
||||
|
||||
static char first_non_whitespace(const char *s) {
|
||||
TRACE(2, "DebuggerClient::first_non_whitespace\n");
|
||||
while (*s && isspace(*s)) s++;
|
||||
return *s;
|
||||
}
|
||||
|
||||
char *DebuggerClient::getCompletion(const char *text, int state) {
|
||||
TRACE(2, "DebuggerClient::getCompletion\n");
|
||||
if (state == 0) {
|
||||
m_acLen = strlen(text);
|
||||
m_acIndex = 0;
|
||||
@@ -881,6 +939,7 @@ char *DebuggerClient::getCompletion(const char *text, int state) {
|
||||
// main
|
||||
|
||||
bool DebuggerClient::initializeMachine() {
|
||||
TRACE(2, "DebuggerClient::initializeMachine\n");
|
||||
if (!m_machine->m_initialized) {
|
||||
// set/clear intercept for RPC thread
|
||||
if (!m_machines.empty() && m_machine == m_machines[0]) {
|
||||
@@ -916,6 +975,7 @@ bool DebuggerClient::initializeMachine() {
|
||||
}
|
||||
|
||||
DebuggerCommandPtr DebuggerClient::waitForNextInterrupt() {
|
||||
TRACE(2, "DebuggerClient::waitForNextInterrupt\n");
|
||||
const char *func = "DebuggerClient::waitForNextInterrupt()";
|
||||
while (!m_stopped) {
|
||||
DebuggerCommandPtr cmd;
|
||||
@@ -955,6 +1015,7 @@ DebuggerCommandPtr DebuggerClient::waitForNextInterrupt() {
|
||||
}
|
||||
|
||||
void DebuggerClient::runImpl() {
|
||||
TRACE(2, "DebuggerClient::runImpl\n");
|
||||
const char *func = "DebuggerClient::runImpl()";
|
||||
|
||||
try {
|
||||
@@ -1007,6 +1068,7 @@ void DebuggerClient::runImpl() {
|
||||
}
|
||||
|
||||
bool DebuggerClient::console() {
|
||||
TRACE(2, "DebuggerClient::console\n");
|
||||
while (true) {
|
||||
const char *line = nullptr;
|
||||
|
||||
@@ -1088,12 +1150,14 @@ bool DebuggerClient::console() {
|
||||
// output functions
|
||||
|
||||
String DebuggerClient::getPrintString() {
|
||||
TRACE(2, "DebuggerClient::getPrintString\n");
|
||||
String s(m_outputBuf); // makes a copy;
|
||||
m_outputBuf.clear();
|
||||
return s;
|
||||
}
|
||||
|
||||
Array DebuggerClient::getOutputArray() {
|
||||
TRACE(2, "DebuggerClient::getOutputArray\n");
|
||||
Array ret;
|
||||
switch (m_outputType) {
|
||||
case OTCodeLoc:
|
||||
@@ -1127,6 +1191,7 @@ Array DebuggerClient::getOutputArray() {
|
||||
// spew showing the code around the breakpoint.
|
||||
//
|
||||
void DebuggerClient::shortCode(BreakPointInfoPtr bp) {
|
||||
TRACE(2, "DebuggerClient::shortCode\n");
|
||||
if (bp && !bp->m_file.empty() && bp->m_line1) {
|
||||
Variant source = CmdList::GetSourceFile(this, bp->m_file);
|
||||
if (source.isString()) {
|
||||
@@ -1172,6 +1237,7 @@ void DebuggerClient::shortCode(BreakPointInfoPtr bp) {
|
||||
bool DebuggerClient::code(CStrRef source, int lineFocus, int line1 /* = 0 */,
|
||||
int line2 /* = 0 */, int charFocus0 /* = 0 */,
|
||||
int lineFocus1 /* = 0 */, int charFocus1 /* = 0 */) {
|
||||
TRACE(2, "DebuggerClient::code\n");
|
||||
if (line1 == 0 && line2 == 0) {
|
||||
String highlighted;
|
||||
if (isApiMode()) {
|
||||
@@ -1214,6 +1280,7 @@ bool DebuggerClient::code(CStrRef source, int lineFocus, int line1 /* = 0 */,
|
||||
}
|
||||
|
||||
char DebuggerClient::ask(const char *fmt, ...) {
|
||||
TRACE(2, "DebuggerClient::ask\n");
|
||||
assert(!isApiMode());
|
||||
string msg;
|
||||
va_list ap;
|
||||
@@ -1230,12 +1297,12 @@ char DebuggerClient::ask(const char *fmt, ...) {
|
||||
#define FWRITE(ptr, size, nmemb, stream) \
|
||||
do { \
|
||||
if (isApiMode()) { \
|
||||
m_outputBuf.append(ptr, size * nmemb); \
|
||||
m_outputBuf.append(ptr, size * nmemb); \
|
||||
} \
|
||||
\
|
||||
/* LogFile debugger setting */ \
|
||||
FILE *f = getLogFileHandler(); \
|
||||
if (f != nullptr) { \
|
||||
if (f != nullptr) { \
|
||||
fwrite(ptr, size, nmemb, f); \
|
||||
} \
|
||||
\
|
||||
@@ -1244,6 +1311,7 @@ do { \
|
||||
} while (0) \
|
||||
|
||||
void DebuggerClient::print(const char *fmt, ...) {
|
||||
TRACE(2, "DebuggerClient::print(const char *fmt, ...)\n");
|
||||
string msg;
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
@@ -1252,12 +1320,14 @@ void DebuggerClient::print(const char *fmt, ...) {
|
||||
}
|
||||
|
||||
void DebuggerClient::print(const std::string &s) {
|
||||
TRACE(2, "DebuggerClient::print(const std::string &s)\n");
|
||||
FWRITE(s.data(), 1, s.length(), stdout);
|
||||
FWRITE("\n", 1, 1, stdout);
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
void DebuggerClient::print(CStrRef msg) {
|
||||
TRACE(2, "DebuggerClient::print(CStrRef msg)\n");
|
||||
FWRITE(msg.data(), 1, msg.length(), stdout);
|
||||
FWRITE("\n", 1, 1, stdout);
|
||||
fflush(stdout);
|
||||
@@ -1295,16 +1365,19 @@ IMPLEMENT_COLOR_OUTPUT(error, stderr, ErrorColor);
|
||||
#undef IMPLEMENT_COLOR_OUTPUT
|
||||
|
||||
string DebuggerClient::wrap(const std::string &s) {
|
||||
TRACE(2, "DebuggerClient::wrap\n");
|
||||
String ret = StringUtil::WordWrap(String(s.c_str(), s.size(), AttachLiteral),
|
||||
LineWidth - 4, "\n", true);
|
||||
return string(ret.data(), ret.size());
|
||||
}
|
||||
|
||||
void DebuggerClient::helpTitle(const char *title) {
|
||||
TRACE(2, "DebuggerClient::helpTitle\n");
|
||||
help(FormatTitle(title));
|
||||
}
|
||||
|
||||
void DebuggerClient::helpCmds(const char *cmd, const char *desc, ...) {
|
||||
TRACE(2, "DebuggerClient::helpCmds(const char *cmd, const char *desc,...)\n");
|
||||
std::vector<const char *> cmds;
|
||||
cmds.push_back(cmd);
|
||||
cmds.push_back(desc);
|
||||
@@ -1322,6 +1395,7 @@ void DebuggerClient::helpCmds(const char *cmd, const char *desc, ...) {
|
||||
}
|
||||
|
||||
void DebuggerClient::helpCmds(const std::vector<const char *> &cmds) {
|
||||
TRACE(2, "DebuggerClient::helpCmds(const std::vector<const char *> &cmds)\n");
|
||||
int left = 0; int right = 0;
|
||||
for (unsigned int i = 0; i < cmds.size(); i++) {
|
||||
int &width = (i % 2 ? right : left);
|
||||
@@ -1373,16 +1447,19 @@ void DebuggerClient::helpCmds(const std::vector<const char *> &cmds) {
|
||||
}
|
||||
|
||||
void DebuggerClient::helpBody(const std::string &s) {
|
||||
TRACE(2, "DebuggerClient::helpBody\n");
|
||||
help("");
|
||||
help(wrap(s));
|
||||
help("");
|
||||
}
|
||||
|
||||
void DebuggerClient::helpSection(const std::string &s) {
|
||||
TRACE(2, "DebuggerClient::helpSection\n");
|
||||
help(wrap(s));
|
||||
}
|
||||
|
||||
void DebuggerClient::tutorial(const char *text) {
|
||||
TRACE(2, "DebuggerClient::tutorial\n");
|
||||
if (m_tutorial < 0) return;
|
||||
|
||||
String ret = String(text).replace("\t", " ");
|
||||
@@ -1426,6 +1503,7 @@ void DebuggerClient::tutorial(const char *text) {
|
||||
}
|
||||
|
||||
void DebuggerClient::setTutorial(int mode) {
|
||||
TRACE(2, "DebuggerClient::setTutorial\n");
|
||||
if (m_tutorial != mode) {
|
||||
m_tutorial = mode;
|
||||
m_tutorialVisited.clear();
|
||||
@@ -1450,6 +1528,7 @@ const char **DebuggerClient::GetCommands() {
|
||||
}
|
||||
|
||||
void DebuggerClient::shiftCommand() {
|
||||
TRACE(2, "DebuggerClient::shiftCommand\n");
|
||||
if (m_command.size() > 1) {
|
||||
m_args.insert(m_args.begin(), m_command.substr(1));
|
||||
m_argIdx.insert(m_argIdx.begin(), 1);
|
||||
@@ -1458,13 +1537,14 @@ void DebuggerClient::shiftCommand() {
|
||||
}
|
||||
|
||||
DebuggerCommand *DebuggerClient::createCommand() {
|
||||
TRACE(2, "DebuggerClient::createCommand\n");
|
||||
#define MATCH_CMD(name, cmd) \
|
||||
do { \
|
||||
if (match(name)) { \
|
||||
m_commandCanonical = name; \
|
||||
return new cmd(); \
|
||||
} \
|
||||
return nullptr; \
|
||||
return nullptr; \
|
||||
} while(0) \
|
||||
|
||||
#define NEW_CMD_NAME(name, cmd) \
|
||||
@@ -1517,6 +1597,7 @@ do { \
|
||||
}
|
||||
|
||||
bool DebuggerClient::process() {
|
||||
TRACE(2, "DebuggerClient::process\n");
|
||||
clearCachedLocal();
|
||||
if (isApiMode()) {
|
||||
// construct m_line based on m_command and m_args
|
||||
@@ -1566,6 +1647,7 @@ bool DebuggerClient::process() {
|
||||
// helpers
|
||||
|
||||
void DebuggerClient::addToken(std::string &token, int idx) {
|
||||
TRACE(2, "DebuggerClient::addToken\n");
|
||||
m_argIdx.push_back(idx);
|
||||
if (m_command.empty()) {
|
||||
m_command = token;
|
||||
@@ -1576,6 +1658,7 @@ void DebuggerClient::addToken(std::string &token, int idx) {
|
||||
}
|
||||
|
||||
void DebuggerClient::parseCommand(const char *line) {
|
||||
TRACE(2, "DebuggerClient::parseCommand\n");
|
||||
m_command.clear();
|
||||
m_args.clear();
|
||||
|
||||
@@ -1632,6 +1715,7 @@ void DebuggerClient::parseCommand(const char *line) {
|
||||
}
|
||||
|
||||
bool DebuggerClient::parse(const char *line) {
|
||||
TRACE(2, "DebuggerClient::parse\n");
|
||||
if (m_inputState != TakingCode) {
|
||||
while (isspace(*line)) line++;
|
||||
}
|
||||
@@ -1663,15 +1747,18 @@ bool DebuggerClient::parse(const char *line) {
|
||||
}
|
||||
|
||||
bool DebuggerClient::match(const char *cmd) {
|
||||
TRACE(2, "DebuggerClient::match\n");
|
||||
assert(cmd && *cmd);
|
||||
return !strncasecmp(m_command.c_str(), cmd, m_command.size());
|
||||
}
|
||||
|
||||
bool DebuggerClient::Match(const char *input, const char *cmd) {
|
||||
TRACE(2, "DebuggerClient::Match\n");
|
||||
return !strncasecmp(input, cmd, strlen(input));
|
||||
}
|
||||
|
||||
bool DebuggerClient::arg(int index, const char *s) {
|
||||
TRACE(2, "DebuggerClient::arg\n");
|
||||
assert(s && *s);
|
||||
assert(index > 0);
|
||||
--index;
|
||||
@@ -1680,6 +1767,7 @@ bool DebuggerClient::arg(int index, const char *s) {
|
||||
}
|
||||
|
||||
std::string DebuggerClient::argValue(int index) {
|
||||
TRACE(2, "DebuggerClient::argValue\n");
|
||||
assert(index > 0);
|
||||
--index;
|
||||
if (index >= 0 && index < (int)m_args.size()) {
|
||||
@@ -1689,6 +1777,7 @@ std::string DebuggerClient::argValue(int index) {
|
||||
}
|
||||
|
||||
std::string DebuggerClient::lineRest(int index) {
|
||||
TRACE(2, "DebuggerClient::lineRest\n");
|
||||
assert(index > 0);
|
||||
return m_line.substr(m_argIdx[index - 1] + 1);
|
||||
}
|
||||
@@ -1697,17 +1786,20 @@ std::string DebuggerClient::lineRest(int index) {
|
||||
// comunication with DebuggerProxy
|
||||
|
||||
DebuggerCommandPtr DebuggerClient::xend(DebuggerCommand *cmd) {
|
||||
TRACE(2, "DebuggerClient::xend\n");
|
||||
send(cmd);
|
||||
return recv(cmd->getType());
|
||||
}
|
||||
|
||||
void DebuggerClient::send(DebuggerCommand *cmd) {
|
||||
TRACE(2, "DebuggerClient::send\n");
|
||||
if (!cmd->send(m_machine->m_thrift)) {
|
||||
throw DebuggerProtocolException();
|
||||
}
|
||||
}
|
||||
|
||||
DebuggerCommandPtr DebuggerClient::recv(int expected) {
|
||||
TRACE(2, "DebuggerClient::recv\n");
|
||||
const char *func = "DebuggerClient::recv()";
|
||||
|
||||
DebuggerCommandPtr res;
|
||||
@@ -1766,6 +1858,7 @@ DebuggerCommandPtr DebuggerClient::recv(int expected) {
|
||||
// helpers
|
||||
|
||||
int DebuggerClient::checkEvalEnd() {
|
||||
TRACE(2, "DebuggerClient::checkEvalEnd\n");
|
||||
size_t pos = m_line.rfind("?>");
|
||||
if (pos == string::npos) {
|
||||
return -1;
|
||||
@@ -1781,6 +1874,7 @@ int DebuggerClient::checkEvalEnd() {
|
||||
}
|
||||
|
||||
bool DebuggerClient::processTakeCode() {
|
||||
TRACE(2, "DebuggerClient::processTakeCode\n");
|
||||
assert(m_inputState == TakingCommand);
|
||||
|
||||
char first = m_line[0];
|
||||
@@ -1818,6 +1912,7 @@ bool DebuggerClient::processTakeCode() {
|
||||
}
|
||||
|
||||
bool DebuggerClient::processEval() {
|
||||
TRACE(2, "DebuggerClient::processEval\n");
|
||||
m_runState = Running;
|
||||
m_inputState = TakingCommand;
|
||||
m_acLiveListsDirty = true;
|
||||
@@ -1826,12 +1921,14 @@ bool DebuggerClient::processEval() {
|
||||
}
|
||||
|
||||
void DebuggerClient::swapHelp() {
|
||||
TRACE(2, "DebuggerClient::swapHelp\n");
|
||||
assert(m_args.size() > 0);
|
||||
m_command = m_args[0];
|
||||
m_args[0] = "help";
|
||||
}
|
||||
|
||||
void DebuggerClient::quit() {
|
||||
TRACE(2, "DebuggerClient::quit\n");
|
||||
m_quitting = true;
|
||||
for (unsigned int i = 0; i < m_machines.size(); i++) {
|
||||
m_machines[i]->m_thrift.close();
|
||||
@@ -1840,6 +1937,7 @@ void DebuggerClient::quit() {
|
||||
}
|
||||
|
||||
DSandboxInfoPtr DebuggerClient::getSandbox(int index) const {
|
||||
TRACE(2, "DebuggerClient::getSandbox\n");
|
||||
if (index > 0) {
|
||||
--index;
|
||||
if (index >= 0 && index < (int)m_sandboxes.size()) {
|
||||
@@ -1850,6 +1948,7 @@ DSandboxInfoPtr DebuggerClient::getSandbox(int index) const {
|
||||
}
|
||||
|
||||
void DebuggerClient::updateThreads(DThreadInfoPtrVec threads) {
|
||||
TRACE(2, "DebuggerClient::updateThreads\n");
|
||||
m_threads = threads;
|
||||
for (unsigned int i = 0; i < m_threads.size(); i++) {
|
||||
DThreadInfoPtr thread = m_threads[i];
|
||||
@@ -1866,6 +1965,7 @@ void DebuggerClient::updateThreads(DThreadInfoPtrVec threads) {
|
||||
}
|
||||
|
||||
DThreadInfoPtr DebuggerClient::getThread(int index) const {
|
||||
TRACE(2, "DebuggerClient::getThread\n");
|
||||
for (unsigned int i = 0; i < m_threads.size(); i++) {
|
||||
if (m_threads[i]->m_index == index) {
|
||||
return m_threads[i];
|
||||
@@ -1877,6 +1977,7 @@ DThreadInfoPtr DebuggerClient::getThread(int index) const {
|
||||
void DebuggerClient::getListLocation(std::string &file, int &line,
|
||||
int &lineFocus0, int &charFocus0,
|
||||
int &lineFocus1, int &charFocus1) {
|
||||
TRACE(2, "DebuggerClient::getListLocation\n");
|
||||
lineFocus0 = charFocus0 = lineFocus1 = charFocus1 = 0;
|
||||
if (m_listFile.empty() && m_breakpoint) {
|
||||
setListLocation(m_breakpoint->m_file, m_breakpoint->m_line1, true);
|
||||
@@ -1893,6 +1994,7 @@ void DebuggerClient::getListLocation(std::string &file, int &line,
|
||||
|
||||
void DebuggerClient::setListLocation(const std::string &file, int line,
|
||||
bool center) {
|
||||
TRACE(2, "DebuggerClient::setListLocation\n");
|
||||
m_listFile = file;
|
||||
if (!m_listFile.empty() && m_listFile[0] != '/' && !m_sourceRoot.empty()) {
|
||||
if (m_sourceRoot[m_sourceRoot.size() - 1] != '/') {
|
||||
@@ -1912,6 +2014,7 @@ void DebuggerClient::setListLocation(const std::string &file, int line,
|
||||
}
|
||||
|
||||
void DebuggerClient::setSourceRoot(const std::string &sourceRoot) {
|
||||
TRACE(2, "DebuggerClient::setSourceRoot\n");
|
||||
m_config["SourceRoot"] = m_sourceRoot = sourceRoot;
|
||||
saveConfig();
|
||||
|
||||
@@ -1920,11 +2023,13 @@ void DebuggerClient::setSourceRoot(const std::string &sourceRoot) {
|
||||
}
|
||||
|
||||
void DebuggerClient::setMatchedBreakPoints(BreakPointInfoPtrVec breakpoints) {
|
||||
TRACE(2, "DebuggerClient::setMatchedBreakPoints\n");
|
||||
m_matched = breakpoints;
|
||||
}
|
||||
|
||||
void DebuggerClient::setCurrentLocation(int64_t threadId,
|
||||
BreakPointInfoPtr breakpoint) {
|
||||
TRACE(2, "DebuggerClient::setCurrentLocation\n");
|
||||
m_threadId = threadId;
|
||||
m_breakpoint = breakpoint;
|
||||
m_stacktrace.reset();
|
||||
@@ -1935,6 +2040,7 @@ void DebuggerClient::setCurrentLocation(int64_t threadId,
|
||||
}
|
||||
|
||||
void DebuggerClient::addWatch(const char *fmt, const std::string &php) {
|
||||
TRACE(2, "DebuggerClient::addWatch\n");
|
||||
WatchPtr watch(new Watch());
|
||||
watch->first = fmt;
|
||||
watch->second = php;
|
||||
@@ -1942,10 +2048,12 @@ void DebuggerClient::addWatch(const char *fmt, const std::string &php) {
|
||||
}
|
||||
|
||||
void DebuggerClient::setStackTrace(CArrRef stacktrace) {
|
||||
TRACE(2, "DebuggerClient::setStackTrace\n");
|
||||
m_stacktrace = stacktrace;
|
||||
}
|
||||
|
||||
void DebuggerClient::moveToFrame(int index, bool display /* = true */) {
|
||||
TRACE(2, "DebuggerClient::moveToFrame\n");
|
||||
m_frame = index;
|
||||
if (m_frame >= m_stacktrace.size()) {
|
||||
m_frame = m_stacktrace.size() - 1;
|
||||
@@ -1973,6 +2081,7 @@ void DebuggerClient::moveToFrame(int index, bool display /* = true */) {
|
||||
}
|
||||
|
||||
void DebuggerClient::printFrame(int index, CArrRef frame) {
|
||||
TRACE(2, "DebuggerClient::printFrame\n");
|
||||
StringBuffer args;
|
||||
for (ArrayIter iter(frame["args"]); iter; ++iter) {
|
||||
if (!args.empty()) args.append(", ");
|
||||
@@ -2002,6 +2111,7 @@ void DebuggerClient::printFrame(int index, CArrRef frame) {
|
||||
}
|
||||
|
||||
void DebuggerClient::startMacro(std::string name) {
|
||||
TRACE(2, "DebuggerClient::startMacro\n");
|
||||
if (m_macroRecording &&
|
||||
ask("We are recording a macro. Do you want to save? [Y/n]") != 'n') {
|
||||
endMacro();
|
||||
@@ -2024,6 +2134,7 @@ void DebuggerClient::startMacro(std::string name) {
|
||||
}
|
||||
|
||||
void DebuggerClient::endMacro() {
|
||||
TRACE(2, "DebuggerClient::endMacro\n");
|
||||
if (!m_macroRecording) {
|
||||
error("There is no ongoing recording.");
|
||||
tutorial("Use '& [s]tart {name}' or '& [s]tart' command to start "
|
||||
@@ -2047,6 +2158,7 @@ void DebuggerClient::endMacro() {
|
||||
}
|
||||
|
||||
bool DebuggerClient::playMacro(std::string name) {
|
||||
TRACE(2, "DebuggerClient::playMacro\n");
|
||||
if (name.empty()) {
|
||||
name = "default";
|
||||
}
|
||||
@@ -2061,6 +2173,7 @@ bool DebuggerClient::playMacro(std::string name) {
|
||||
}
|
||||
|
||||
bool DebuggerClient::deleteMacro(int index) {
|
||||
TRACE(2, "DebuggerClient::deleteMacro\n");
|
||||
--index;
|
||||
if (index >= 0 && index < (int)m_macros.size()) {
|
||||
if (ask("Are you sure you want to delete the macro? [y/N]") != 'y') {
|
||||
@@ -2074,6 +2187,7 @@ bool DebuggerClient::deleteMacro(int index) {
|
||||
}
|
||||
|
||||
void DebuggerClient::record(const char *line) {
|
||||
TRACE(2, "DebuggerClient::record\n");
|
||||
assert(line);
|
||||
if (m_macroRecording && line[0] != '&') {
|
||||
m_macroRecording->m_cmds.push_back(line);
|
||||
@@ -2084,6 +2198,7 @@ void DebuggerClient::record(const char *line) {
|
||||
// helpers for server API
|
||||
|
||||
bool DebuggerClient::apiGrab() {
|
||||
TRACE(2, "DebuggerClient::apiGrab\n");
|
||||
Lock l(m_inApiUseLck);
|
||||
if (m_inApiUse) {
|
||||
return false;
|
||||
@@ -2093,11 +2208,13 @@ bool DebuggerClient::apiGrab() {
|
||||
}
|
||||
|
||||
void DebuggerClient::apiFree() {
|
||||
TRACE(2, "DebuggerClient::apiFree\n");
|
||||
Lock l(m_inApiUseLck);
|
||||
m_inApiUse = false;
|
||||
}
|
||||
|
||||
void DebuggerClient::resetSmartAllocatedMembers() {
|
||||
TRACE(2, "DebuggerClient::resetSmartAllocatedMembers\n");
|
||||
// Essentially sets these to null: so it's safe to run their
|
||||
// destructors at sweep time or after the SmartAllocators are torn
|
||||
// down.
|
||||
@@ -2109,6 +2226,7 @@ void DebuggerClient::resetSmartAllocatedMembers() {
|
||||
// helpers for usage logging
|
||||
|
||||
void DebuggerClient::initUsageLogging() {
|
||||
TRACE(2, "DebuggerClient::initUsageLogging\n");
|
||||
// Usage log file is a runtime option instead of debugger config because
|
||||
// it is for internal monitoring and we don't want users to modify this.
|
||||
if (RuntimeOption::DebuggerUsageLogFile.empty()) {
|
||||
@@ -2124,6 +2242,7 @@ void DebuggerClient::initUsageLogging() {
|
||||
}
|
||||
|
||||
void DebuggerClient::finiUsageLogging() {
|
||||
TRACE(2, "DebuggerClient::finiUsageLogging\n");
|
||||
if (m_usageLogFP) {
|
||||
fclose(m_usageLogFP);
|
||||
m_usageLogFP = nullptr;
|
||||
@@ -2131,6 +2250,7 @@ void DebuggerClient::finiUsageLogging() {
|
||||
}
|
||||
|
||||
void DebuggerClient::usageLog(const std::string& cmd, const std::string& line) {
|
||||
TRACE(2, "DebuggerClient::usageLog\n");
|
||||
if (!m_usageLogFP) {
|
||||
return;
|
||||
}
|
||||
@@ -2159,6 +2279,7 @@ void DebuggerClient::usageLog(const std::string& cmd, const std::string& line) {
|
||||
}
|
||||
|
||||
void DebuggerClient::usageLogInterrupt(DebuggerCommandPtr cmd) {
|
||||
TRACE(2, "DebuggerClient::usageLogInterrupt\n");
|
||||
CmdInterruptPtr intr = dynamic_pointer_cast<CmdInterrupt>(cmd);
|
||||
if (!intr) {
|
||||
return;
|
||||
@@ -2181,6 +2302,7 @@ void DebuggerClient::usageLogInterrupt(DebuggerCommandPtr cmd) {
|
||||
// configuration
|
||||
|
||||
void DebuggerClient::loadConfig() {
|
||||
TRACE(2, "DebuggerClient::loadConfig\n");
|
||||
if (m_configFileName.empty()) {
|
||||
m_configFileName = Process::GetHomeDirectory() + ConfigFileName;
|
||||
}
|
||||
@@ -2245,6 +2367,7 @@ void DebuggerClient::loadConfig() {
|
||||
}
|
||||
|
||||
void DebuggerClient::saveConfig() {
|
||||
TRACE(2, "DebuggerClient::saveConfig\n");
|
||||
if (m_configFileName.empty()) {
|
||||
// we are not touching a file that was not successfully loaded earlier
|
||||
return;
|
||||
@@ -2268,6 +2391,7 @@ void DebuggerClient::saveConfig() {
|
||||
}
|
||||
|
||||
void DebuggerClient::defineColors() {
|
||||
TRACE(2, "DebuggerClient::defineColors\n");
|
||||
vector<string> names;
|
||||
get_supported_colors(names);
|
||||
Hdf support = m_config["Color"]["SupportedNames"];
|
||||
|
||||
@@ -23,9 +23,11 @@
|
||||
|
||||
namespace HPHP { namespace Eval {
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// send/recv
|
||||
static const Trace::Module TRACEMOD = Trace::debugger;
|
||||
|
||||
// send/recv
|
||||
bool DebuggerCommand::send(DebuggerThriftBuffer &thrift) {
|
||||
TRACE(2, "DebuggerCommand::send\n");
|
||||
try {
|
||||
thrift.reset(false);
|
||||
sendImpl(thrift);
|
||||
@@ -39,6 +41,7 @@ bool DebuggerCommand::send(DebuggerThriftBuffer &thrift) {
|
||||
}
|
||||
|
||||
bool DebuggerCommand::recv(DebuggerThriftBuffer &thrift) {
|
||||
TRACE(2, "DebuggerCommand::recv\n");
|
||||
try {
|
||||
recvImpl(thrift);
|
||||
} catch (...) {
|
||||
@@ -50,6 +53,7 @@ bool DebuggerCommand::recv(DebuggerThriftBuffer &thrift) {
|
||||
}
|
||||
|
||||
void DebuggerCommand::sendImpl(DebuggerThriftBuffer &thrift) {
|
||||
TRACE(2, "DebuggerCommand::sendImpl\n");
|
||||
thrift.write((int32_t)m_type);
|
||||
thrift.write(m_class);
|
||||
thrift.write(m_body);
|
||||
@@ -57,12 +61,14 @@ void DebuggerCommand::sendImpl(DebuggerThriftBuffer &thrift) {
|
||||
}
|
||||
|
||||
void DebuggerCommand::recvImpl(DebuggerThriftBuffer &thrift) {
|
||||
TRACE(2, "DebuggerCommand::recvImpl\n");
|
||||
thrift.read(m_body);
|
||||
thrift.read(m_version);
|
||||
}
|
||||
|
||||
bool DebuggerCommand::Receive(DebuggerThriftBuffer &thrift,
|
||||
DebuggerCommandPtr &cmd, const char *caller) {
|
||||
TRACE(2, "DebuggerCommand::Receive\n");
|
||||
cmd.reset();
|
||||
|
||||
struct pollfd fds[1];
|
||||
@@ -141,14 +147,17 @@ bool DebuggerCommand::Receive(DebuggerThriftBuffer &thrift,
|
||||
// default handlers
|
||||
|
||||
void DebuggerCommand::list(DebuggerClient *client) {
|
||||
TRACE(2, "DebuggerCommand::list\n");
|
||||
}
|
||||
|
||||
bool DebuggerCommand::help(DebuggerClient *client) {
|
||||
TRACE(2, "DebuggerCommand::help\n");
|
||||
assert(false);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DebuggerCommand::onClient(DebuggerClient *client) {
|
||||
TRACE(2, "DebuggerCommand::onClient\n");
|
||||
if (client->arg(1, "help") || client->arg(1, "?")) {
|
||||
return help(client);
|
||||
}
|
||||
@@ -156,11 +165,13 @@ bool DebuggerCommand::onClient(DebuggerClient *client) {
|
||||
}
|
||||
|
||||
void DebuggerCommand::setClientOutput(DebuggerClient *client) {
|
||||
TRACE(2, "DebuggerCommand::setClientOutput\n");
|
||||
// Just default to text
|
||||
client->setOutputType(DebuggerClient::OTText);
|
||||
}
|
||||
|
||||
bool DebuggerCommand::onClientD(DebuggerClient *client) {
|
||||
TRACE(2, "DebuggerCommand::onClientD\n");
|
||||
bool ret = onClientVM(client);
|
||||
if (client->isApiMode() && !m_incomplete) {
|
||||
setClientOutput(client);
|
||||
@@ -169,6 +180,7 @@ bool DebuggerCommand::onClientD(DebuggerClient *client) {
|
||||
}
|
||||
|
||||
bool DebuggerCommand::onServer(DebuggerProxy *proxy) {
|
||||
TRACE(2, "DebuggerCommand::onServer\n");
|
||||
assert(false);
|
||||
Logger::Error("DebuggerCommand::onServer(): bad cmd type: %d", m_type);
|
||||
return false;
|
||||
|
||||
@@ -28,16 +28,20 @@
|
||||
namespace HPHP { namespace Eval {
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static const Trace::Module TRACEMOD = Trace::debugger;
|
||||
|
||||
DebuggerProxy::DebuggerProxy(SmartPtr<Socket> socket, bool local)
|
||||
: m_stopped(false), m_local(local), m_dummySandbox(nullptr),
|
||||
m_hasBreakPoints(false), m_threadMode(Normal), m_thread(0),
|
||||
m_signalThread(this, &DebuggerProxy::pollSignal),
|
||||
m_signum(CmdSignal::SignalNone) {
|
||||
TRACE(2, "DebuggerProxy::DebuggerProxy\n");
|
||||
m_thrift.create(socket);
|
||||
m_dummyInfo = DSandboxInfo::CreateDummyInfo((int64_t)this);
|
||||
}
|
||||
|
||||
DebuggerProxy::~DebuggerProxy() {
|
||||
TRACE(2, "DebuggerProxy::~DebuggerProxy\n");
|
||||
m_stopped = true;
|
||||
m_signalThread.waitForEnd();
|
||||
|
||||
@@ -47,20 +51,24 @@ DebuggerProxy::~DebuggerProxy() {
|
||||
}
|
||||
|
||||
const char *DebuggerProxy::getThreadType() const {
|
||||
TRACE(2, "DebuggerProxy::getThreadType\n");
|
||||
return isLocal() ? "Command Line Script" : "Dummy Sandbox";
|
||||
}
|
||||
|
||||
DSandboxInfo DebuggerProxy::getSandbox() const {
|
||||
TRACE(2, "DebuggerProxy::getSandbox\n");
|
||||
Lock lock(m_mutex);
|
||||
return m_sandbox;
|
||||
}
|
||||
|
||||
std::string DebuggerProxy::getSandboxId() const {
|
||||
TRACE(2, "DebuggerProxy::getSandboxId\n");
|
||||
Lock lock(m_mutex);
|
||||
return m_sandbox.id();
|
||||
}
|
||||
|
||||
void DebuggerProxy::getThreads(DThreadInfoPtrVec &threads) {
|
||||
TRACE(2, "DebuggerProxy::getThreads\n");
|
||||
Lock lock(this);
|
||||
std::stack<void *> &interrupts =
|
||||
ThreadInfo::s_threadInfo->m_reqInjectionData.interrupts;
|
||||
@@ -81,10 +89,12 @@ void DebuggerProxy::getThreads(DThreadInfoPtrVec &threads) {
|
||||
}
|
||||
|
||||
bool DebuggerProxy::switchSandbox(const std::string &newId, bool force) {
|
||||
TRACE(2, "DebuggerProxy::switchSandbox\n");
|
||||
return Debugger::SwitchSandbox(shared_from_this(), newId, force);
|
||||
}
|
||||
|
||||
void DebuggerProxy::updateSandbox(DSandboxInfoPtr sandbox) {
|
||||
TRACE(2, "DebuggerProxy::updateSandbox\n");
|
||||
Lock lock(m_mutex);
|
||||
if (sandbox) {
|
||||
if (m_sandbox.id() != sandbox->id()) {
|
||||
@@ -96,6 +106,7 @@ void DebuggerProxy::updateSandbox(DSandboxInfoPtr sandbox) {
|
||||
}
|
||||
|
||||
bool DebuggerProxy::switchThread(DThreadInfoPtr thread) {
|
||||
TRACE(2, "DebuggerProxy::switchThread\n");
|
||||
Lock lock(this);
|
||||
if (m_threads.find(thread->m_id) != m_threads.end()) {
|
||||
m_newThread = thread;
|
||||
@@ -106,6 +117,7 @@ bool DebuggerProxy::switchThread(DThreadInfoPtr thread) {
|
||||
|
||||
void DebuggerProxy::switchThreadMode(ThreadMode mode,
|
||||
int64_t threadId /* = 0 */) {
|
||||
TRACE(2, "DebuggerProxy::switchThreadMode\n");
|
||||
Lock lock(this);
|
||||
m_threadMode = mode;
|
||||
if (threadId) {
|
||||
@@ -125,6 +137,7 @@ void DebuggerProxy::switchThreadMode(ThreadMode mode,
|
||||
}
|
||||
|
||||
void DebuggerProxy::startDummySandbox() {
|
||||
TRACE(2, "DebuggerProxy::startDummySandbox\n");
|
||||
m_dummySandbox =
|
||||
new DummySandbox(this, RuntimeOption::DebuggerDefaultSandboxPath,
|
||||
RuntimeOption::DebuggerStartupDocument);
|
||||
@@ -132,12 +145,14 @@ void DebuggerProxy::startDummySandbox() {
|
||||
}
|
||||
|
||||
void DebuggerProxy::notifyDummySandbox() {
|
||||
TRACE(2, "DebuggerProxy::notifyDummySandbox\n");
|
||||
m_dummySandbox->notifySignal(CmdSignal::SignalBreak);
|
||||
}
|
||||
|
||||
// Hold the entire set of breakpoints, and sift breakpoints by function and
|
||||
// class name into separate containers for later.
|
||||
void DebuggerProxy::setBreakPoints(BreakPointInfoPtrVec &breakpoints) {
|
||||
TRACE(2, "DebuggerProxy::setBreakPoints\n");
|
||||
WriteLock lock(m_breakMutex);
|
||||
m_breakpoints = breakpoints;
|
||||
m_hasBreakPoints = !m_breakpoints.empty();
|
||||
@@ -164,17 +179,20 @@ void DebuggerProxy::setBreakPoints(BreakPointInfoPtrVec &breakpoints) {
|
||||
}
|
||||
|
||||
void DebuggerProxy::getBreakPoints(BreakPointInfoPtrVec &breakpoints) {
|
||||
TRACE(2, "DebuggerProxy::getBreakPoints\n");
|
||||
ReadLock lock(m_breakMutex);
|
||||
breakpoints = m_breakpoints;
|
||||
}
|
||||
|
||||
bool DebuggerProxy::couldBreakEnterClsMethod(const StringData* className) {
|
||||
TRACE(2, "DebuggerProxy::couldBreakEnterClsMethod\n");
|
||||
ReadLock lock(m_breakMutex);
|
||||
StringDataMap::const_accessor acc;
|
||||
return m_breaksEnterClsMethod.find(acc, className);
|
||||
}
|
||||
|
||||
bool DebuggerProxy::couldBreakEnterFunc(const StringData* funcFullName) {
|
||||
TRACE(2, "DebuggerProxy::couldBreakEnterFunc\n");
|
||||
ReadLock lock(m_breakMutex);
|
||||
StringDataMap::const_accessor acc;
|
||||
return m_breaksEnterFunc.find(acc, funcFullName);
|
||||
@@ -182,6 +200,7 @@ bool DebuggerProxy::couldBreakEnterFunc(const StringData* funcFullName) {
|
||||
|
||||
void DebuggerProxy::getBreakClsMethods(
|
||||
std::vector<const StringData*>& classNames) {
|
||||
TRACE(2, "DebuggerProxy::getBreakClsMethods\n");
|
||||
classNames.clear();
|
||||
WriteLock lock(m_breakMutex); // Write lock in case iteration causes a re-hash
|
||||
for (StringDataMap::const_iterator iter = m_breaksEnterClsMethod.begin();
|
||||
@@ -192,6 +211,7 @@ void DebuggerProxy::getBreakClsMethods(
|
||||
|
||||
void DebuggerProxy::getBreakFuncs(
|
||||
std::vector<const StringData*>& funcFullNames) {
|
||||
TRACE(2, "DebuggerProxy::getBreakFuncs\n");
|
||||
funcFullNames.clear();
|
||||
WriteLock lock(m_breakMutex); // Write lock in case iteration causes a re-hash
|
||||
for (StringDataMap::const_iterator iter = m_breaksEnterFunc.begin();
|
||||
@@ -201,17 +221,20 @@ void DebuggerProxy::getBreakFuncs(
|
||||
}
|
||||
|
||||
bool DebuggerProxy::needInterrupt() {
|
||||
TRACE(2, "DebuggerProxy::needInterrupt\n");
|
||||
return m_hasBreakPoints || m_flow ||
|
||||
m_signum != CmdSignal::SignalNone;
|
||||
}
|
||||
|
||||
bool DebuggerProxy::needInterruptForNonBreak() {
|
||||
TRACE(2, "DebuggerProxy::needInterruptForNonBreak\n");
|
||||
return m_flow || m_signum != CmdSignal::SignalNone;
|
||||
}
|
||||
|
||||
// Handle an interrupt from the VM. Note: some work for breakpoints has already
|
||||
// occured in DebuggerProxyVM::interrupt().
|
||||
void DebuggerProxy::interrupt(CmdInterrupt &cmd) {
|
||||
TRACE(2, "DebuggerProxy::interrupt\n");
|
||||
// Wait until this thread is the thread this proxy wants to debug.
|
||||
// NB: breakpoints and control flow checks happen here, too, and return false
|
||||
// if we're not done with the flow, or not at a breakpoint, etc.
|
||||
@@ -255,10 +278,12 @@ void DebuggerProxy::interrupt(CmdInterrupt &cmd) {
|
||||
}
|
||||
|
||||
bool DebuggerProxy::send(DebuggerCommand *cmd) {
|
||||
TRACE(2, "DebuggerProxy::send\n");
|
||||
return cmd->send(m_thrift);
|
||||
}
|
||||
|
||||
void DebuggerProxy::startSignalThread() {
|
||||
TRACE(2, "DebuggerProxy::startSignalThread\n");
|
||||
m_signalThread.start();
|
||||
}
|
||||
|
||||
@@ -270,6 +295,7 @@ void DebuggerProxy::startSignalThread() {
|
||||
// If another thread in the sandbox fails to stop and consume the signal then
|
||||
// it will be passed to the dummy sandbox instead.
|
||||
void DebuggerProxy::pollSignal() {
|
||||
TRACE(2, "DebuggerProxy::pollSignal\n");
|
||||
while (!m_stopped) {
|
||||
sleep(1);
|
||||
|
||||
@@ -311,6 +337,7 @@ void DebuggerProxy::pollSignal() {
|
||||
}
|
||||
|
||||
void DebuggerProxy::forceQuit() {
|
||||
TRACE(2, "DebuggerProxy::forceQuit\n");
|
||||
DSandboxInfo invalid;
|
||||
Lock l(this);
|
||||
m_sandbox = invalid;
|
||||
@@ -322,14 +349,17 @@ void DebuggerProxy::forceQuit() {
|
||||
// helpers
|
||||
|
||||
std::string DebuggerProxy::MakePHP(const std::string &php) {
|
||||
TRACE(2, "DebuggerProxy::MakePHP\n");
|
||||
return "<?php " + php + ";";
|
||||
}
|
||||
|
||||
std::string DebuggerProxy::MakePHPReturn(const std::string &php) {
|
||||
TRACE(2, "DebuggerProxy::MakePHPReturn\n");
|
||||
return "<?php return " + php + ";";
|
||||
}
|
||||
|
||||
static void append_stdout(const char *s, int len, void *data) {
|
||||
TRACE(2, "DebuggerProxy::append_stdout\n");
|
||||
StringBuffer *sb = (StringBuffer*)data;
|
||||
if (s_stdout_color) {
|
||||
sb->append(s_stdout_color);
|
||||
@@ -342,6 +372,7 @@ static void append_stdout(const char *s, int len, void *data) {
|
||||
|
||||
static void append_stderr(const char *header, const char *msg,
|
||||
const char *ending, void *data) {
|
||||
TRACE(2, "DebuggerProxy::append_stderr\n");
|
||||
StringBuffer *sb = (StringBuffer*)data;
|
||||
if (s_stderr_color) {
|
||||
sb->append(s_stderr_color);
|
||||
@@ -355,6 +386,7 @@ static void append_stderr(const char *header, const char *msg,
|
||||
|
||||
Variant DebuggerProxy::ExecutePHP(const std::string &php, String &output,
|
||||
bool log, int frame) {
|
||||
TRACE(2, "DebuggerProxy::ExecutePHP\n");
|
||||
Variant ret;
|
||||
StringBuffer sb;
|
||||
StringBuffer *save = g_context->swapOutputBuffer(nullptr);
|
||||
@@ -373,6 +405,7 @@ Variant DebuggerProxy::ExecutePHP(const std::string &php, String &output,
|
||||
}
|
||||
|
||||
DThreadInfoPtr DebuggerProxy::createThreadInfo(const std::string &desc) {
|
||||
TRACE(2, "DebuggerProxy::createThreadInfo\n");
|
||||
DThreadInfoPtr info(new DThreadInfo());
|
||||
info->m_id = (int64_t)Process::GetThreadId();
|
||||
info->m_desc = desc;
|
||||
@@ -392,6 +425,7 @@ DThreadInfoPtr DebuggerProxy::createThreadInfo(const std::string &desc) {
|
||||
// of the stepping logic is handled below here and this will return false if
|
||||
// the stepping operation has not completed.
|
||||
bool DebuggerProxy::blockUntilOwn(CmdInterrupt &cmd, bool check) {
|
||||
TRACE(2, "DebuggerProxy::blockUntilOwn\n");
|
||||
int64_t self = cmd.getThreadId();
|
||||
|
||||
Lock lock(this);
|
||||
@@ -433,12 +467,14 @@ bool DebuggerProxy::blockUntilOwn(CmdInterrupt &cmd, bool check) {
|
||||
// Checks whether the cmd has any breakpoints that match the current Site.
|
||||
// Also returns true for cmds that have should always break.
|
||||
bool DebuggerProxy::checkBreakPoints(CmdInterrupt &cmd) {
|
||||
TRACE(2, "DebuggerProxy::checkBreakPoints\n");
|
||||
ReadLock lock(m_breakMutex);
|
||||
return cmd.shouldBreak(m_breakpoints);
|
||||
}
|
||||
|
||||
// Check if we should stop due to flow control, breakpoints, and signals.
|
||||
bool DebuggerProxy::checkJumpFlowBreak(CmdInterrupt &cmd) {
|
||||
TRACE(2, "DebuggerProxy::checkJumpFlowBreak\n");
|
||||
// If there is an outstanding Ctrl-C from the client, go ahead and break now.
|
||||
// Note: this stops any flow control command we might have in-flight.
|
||||
if (m_signum == CmdSignal::SignalBreak) {
|
||||
@@ -487,6 +523,7 @@ bool DebuggerProxy::checkJumpFlowBreak(CmdInterrupt &cmd) {
|
||||
}
|
||||
|
||||
bool DebuggerProxy::processJumpFlowBreak(CmdInterrupt &cmd) {
|
||||
TRACE(2, "DebuggerProxy::processJumpFlowBreak\n");
|
||||
if (m_jump) {
|
||||
switch (cmd.getInterruptType()) {
|
||||
case SessionEnded:
|
||||
@@ -510,6 +547,7 @@ bool DebuggerProxy::processJumpFlowBreak(CmdInterrupt &cmd) {
|
||||
}
|
||||
|
||||
void DebuggerProxy::checkStop() {
|
||||
TRACE(2, "DebuggerProxy::checkStop\n");
|
||||
if (m_stopped) {
|
||||
Debugger::RemoveProxy(shared_from_this());
|
||||
m_thrift.close();
|
||||
@@ -518,6 +556,7 @@ void DebuggerProxy::checkStop() {
|
||||
}
|
||||
|
||||
void DebuggerProxy::processInterrupt(CmdInterrupt &cmd) {
|
||||
TRACE(2, "DebuggerProxy::processInterrupt\n");
|
||||
// Do the server-side work for this cmd.
|
||||
if (!cmd.onServerD(this)) {
|
||||
Debugger::RemoveProxy(shared_from_this()); // on socket error
|
||||
@@ -582,10 +621,12 @@ void DebuggerProxy::processInterrupt(CmdInterrupt &cmd) {
|
||||
}
|
||||
|
||||
void DebuggerProxy::processFlowControl(CmdInterrupt &cmd) {
|
||||
TRACE(2, "DebuggerProxy::processFlowControl\n");
|
||||
const_assert(false);
|
||||
}
|
||||
|
||||
bool DebuggerProxy::breakByFlowControl(CmdInterrupt &cmd) {
|
||||
TRACE(2, "DebuggerProxy::breakByFlowControl\n");
|
||||
const_assert(false);
|
||||
}
|
||||
|
||||
@@ -594,6 +635,7 @@ bool DebuggerProxy::breakByFlowControl(CmdInterrupt &cmd) {
|
||||
|
||||
Variant DebuggerProxyVM::ExecutePHP(const std::string &php, String &output,
|
||||
bool log, int frame) {
|
||||
TRACE(2, "DebuggerProxyVM::ExecutePHP\n");
|
||||
Variant ret;
|
||||
StringBuffer sb;
|
||||
StringBuffer *save = g_context->swapOutputBuffer(nullptr);
|
||||
@@ -633,6 +675,7 @@ Variant DebuggerProxyVM::ExecutePHP(const std::string &php, String &output,
|
||||
// There could be multiple breakpoints at one place but we can manage this
|
||||
// with only one breakpoint.
|
||||
BreakPointInfoPtr DebuggerProxyVM::getBreakPointAtCmd(CmdInterrupt& cmd) {
|
||||
TRACE(2, "DebuggerProxyVM::getBreakPointAtCmd\n");
|
||||
for (unsigned int i = 0; i < m_breakpoints.size(); ++i) {
|
||||
BreakPointInfoPtr bp = m_breakpoints[i];
|
||||
if (bp->m_state != BreakPointInfo::Disabled &&
|
||||
@@ -645,6 +688,7 @@ BreakPointInfoPtr DebuggerProxyVM::getBreakPointAtCmd(CmdInterrupt& cmd) {
|
||||
|
||||
// Handle an interrupt from the VM.
|
||||
void DebuggerProxyVM::interrupt(CmdInterrupt &cmd) {
|
||||
TRACE(2, "DebuggerProxyVM::interrupt\n");
|
||||
changeBreakPointDepth(cmd);
|
||||
|
||||
if (cmd.getInterruptType() == BreakPointReached) {
|
||||
@@ -688,11 +732,13 @@ void DebuggerProxyVM::interrupt(CmdInterrupt &cmd) {
|
||||
}
|
||||
|
||||
void DebuggerProxyVM::setBreakPoints(BreakPointInfoPtrVec& breakpoints) {
|
||||
TRACE(2, "DebuggerProxyVM::setBreakPoints\n");
|
||||
DebuggerProxy::setBreakPoints(breakpoints); // Hold bp's in the proxy.
|
||||
VM::phpSetBreakPointsInAllFiles(this); // Apply breakpoints to the code.
|
||||
}
|
||||
|
||||
void DebuggerProxyVM::readInjTablesFromThread() {
|
||||
TRACE(2, "DebuggerProxyVM::readInjTablesFromThread\n");
|
||||
ThreadInfo* ti = ThreadInfo::s_threadInfo.getNoCheck();
|
||||
if (ti->m_reqInjectionData.dummySandbox) {
|
||||
return;
|
||||
@@ -708,6 +754,7 @@ void DebuggerProxyVM::readInjTablesFromThread() {
|
||||
}
|
||||
|
||||
void DebuggerProxyVM::writeInjTablesToThread() {
|
||||
TRACE(2, "DebuggerProxyVM::writeInjTablesToThread\n");
|
||||
if (g_vmContext->m_injTables) {
|
||||
delete g_vmContext->m_injTables;
|
||||
g_vmContext->m_injTables = nullptr;
|
||||
@@ -719,6 +766,7 @@ void DebuggerProxyVM::writeInjTablesToThread() {
|
||||
}
|
||||
|
||||
int DebuggerProxyVM::getRealStackDepth() {
|
||||
TRACE(2, "DebuggerProxyVM::getRealStackDepth\n");
|
||||
int depth = 0;
|
||||
VMExecutionContext* context = g_vmContext;
|
||||
HPHP::VM::ActRec *fp = context->getFP();
|
||||
@@ -732,6 +780,7 @@ int DebuggerProxyVM::getRealStackDepth() {
|
||||
}
|
||||
|
||||
int DebuggerProxyVM::getStackDepth() {
|
||||
TRACE(2, "DebuggerProxyVM::getStackDepth\n");
|
||||
int depth = 0;
|
||||
VMExecutionContext* context = g_vmContext;
|
||||
HPHP::VM::ActRec *fp = context->getFP();
|
||||
@@ -747,6 +796,7 @@ int DebuggerProxyVM::getStackDepth() {
|
||||
|
||||
// Handle a continue cmd, or setup stepping.
|
||||
void DebuggerProxyVM::processFlowControl(CmdInterrupt &cmd) {
|
||||
TRACE(2, "DebuggerProxyVM::processFlowControl\n");
|
||||
switch (m_flow->getType()) {
|
||||
case DebuggerCommand::KindOfContinue:
|
||||
if (!m_flow->decCount()) {
|
||||
@@ -782,6 +832,7 @@ void DebuggerProxyVM::processFlowControl(CmdInterrupt &cmd) {
|
||||
*/
|
||||
|
||||
void DebuggerProxyVM::changeBreakPointDepth(CmdInterrupt& cmd) {
|
||||
TRACE(2, "DebuggerProxyVM::changeBreakPointDepth\n");
|
||||
for (unsigned int i = 0; i < m_breakpoints.size(); ++i) {
|
||||
// if the site changes, then update the breakpoint depth
|
||||
BreakPointInfoPtr bp = m_breakpoints[i];
|
||||
@@ -795,6 +846,7 @@ void DebuggerProxyVM::changeBreakPointDepth(CmdInterrupt& cmd) {
|
||||
// Determine if an outstanding flow control cmd has run it's course and we
|
||||
// should stop execution.
|
||||
bool DebuggerProxyVM::breakByFlowControl(CmdInterrupt &cmd) {
|
||||
TRACE(2, "DebuggerProxyVM::breakByFlowControl\n");
|
||||
switch (m_flow->getType()) {
|
||||
case DebuggerCommand::KindOfStep: {
|
||||
if (!m_flow->decCount()) {
|
||||
|
||||
@@ -25,10 +25,12 @@
|
||||
|
||||
namespace HPHP { namespace Eval {
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
static const Trace::Module TRACEMOD = Trace::debugger;
|
||||
|
||||
DebuggerServer DebuggerServer::s_debugger_server;
|
||||
|
||||
bool DebuggerServer::Start() {
|
||||
TRACE(2, "DebuggerServer::Start\n");
|
||||
if (RuntimeOption::EnableDebuggerServer) {
|
||||
Debugger::SetTextColors();
|
||||
|
||||
@@ -43,6 +45,7 @@ bool DebuggerServer::Start() {
|
||||
}
|
||||
|
||||
void DebuggerServer::Stop() {
|
||||
TRACE(2, "DebuggerServer::Stop\n");
|
||||
if (RuntimeOption::EnableDebuggerServer) {
|
||||
s_debugger_server.stop();
|
||||
}
|
||||
@@ -52,14 +55,17 @@ void DebuggerServer::Stop() {
|
||||
|
||||
DebuggerServer::DebuggerServer()
|
||||
: m_serverThread(this, &DebuggerServer::accept), m_stopped(false) {
|
||||
TRACE(2, "DebuggerServer::DebuggerServer\n");
|
||||
}
|
||||
|
||||
DebuggerServer::~DebuggerServer() {
|
||||
TRACE(2, "DebuggerServer::~DebuggerServery\n");
|
||||
m_stopped = true;
|
||||
m_serverThread.waitForEnd();
|
||||
}
|
||||
|
||||
bool DebuggerServer::start() {
|
||||
TRACE(2, "DebuggerServer::start\n");
|
||||
int port = RuntimeOption::DebuggerServerPort;
|
||||
int backlog = 128;
|
||||
|
||||
@@ -97,11 +103,13 @@ bool DebuggerServer::start() {
|
||||
}
|
||||
|
||||
void DebuggerServer::stop() {
|
||||
TRACE(2, "DebuggerServer::stop\n");
|
||||
m_stopped = true;
|
||||
m_serverThread.waitForEnd();
|
||||
}
|
||||
|
||||
void DebuggerServer::accept() {
|
||||
TRACE(2, "DebuggerServer::accept\n");
|
||||
// server loop
|
||||
while (!m_stopped) {
|
||||
struct pollfd fds[1];
|
||||
|
||||
@@ -20,8 +20,10 @@
|
||||
|
||||
namespace HPHP {
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
static const Trace::Module TRACEMOD = Trace::debugger;
|
||||
|
||||
String DebuggerThriftBuffer::readImpl() {
|
||||
TRACE(2, "DebuggerThriftBuffer::readImpl\n");
|
||||
assert(m_size <= BUFFER_SIZE);
|
||||
int nread = m_socket->readImpl(m_buffer, m_size);
|
||||
m_buffer[nread] = '\0';
|
||||
@@ -29,10 +31,12 @@ String DebuggerThriftBuffer::readImpl() {
|
||||
}
|
||||
|
||||
void DebuggerThriftBuffer::flushImpl(CStrRef data) {
|
||||
TRACE(2, "DebuggerThriftBuffer::flushImpl\n");
|
||||
m_socket->write(data);
|
||||
}
|
||||
|
||||
void DebuggerThriftBuffer::throwError(const char *msg, int code) {
|
||||
TRACE(2, "DebuggerThriftBuffer::throwError\n");
|
||||
throw Exception("Protocol Error (%d): %s", code, msg);
|
||||
}
|
||||
|
||||
@@ -44,6 +48,7 @@ static StaticString s_type_mismatch(LITSTR_INIT("Type mismatch"));
|
||||
|
||||
template<typename T>
|
||||
static inline int serializeImpl(T data, String& sdata) {
|
||||
TRACE(2, "DebuggerWireHelpers::serializeImpl\n");
|
||||
VariableSerializer vs(VariableSerializer::DebuggerSerialize);
|
||||
try {
|
||||
sdata = vs.serialize(data, true);
|
||||
@@ -58,6 +63,7 @@ static inline int serializeImpl(T data, String& sdata) {
|
||||
}
|
||||
|
||||
static inline int unserializeImpl(CStrRef sdata, Variant& data) {
|
||||
TRACE(2, "DebuggerWireHelpers::unserializeImpl(CStrRef sdata,\n");
|
||||
if (sdata.same(s_hit_limit)) {
|
||||
return DebuggerWireHelpers::HitLimit;
|
||||
}
|
||||
@@ -76,18 +82,22 @@ static inline int unserializeImpl(CStrRef sdata, Variant& data) {
|
||||
}
|
||||
|
||||
int DebuggerWireHelpers::WireSerialize(CArrRef data, String& sdata) {
|
||||
TRACE(2, "DebuggerWireHelpers::WireSerialize(CArrRef data,\n");
|
||||
return serializeImpl(data, sdata);
|
||||
}
|
||||
|
||||
int DebuggerWireHelpers::WireSerialize(CObjRef data, String& sdata) {
|
||||
TRACE(2, "DebuggerWireHelpers::WireSerialize(CObjRef data,\n");
|
||||
return serializeImpl(data, sdata);
|
||||
}
|
||||
|
||||
int DebuggerWireHelpers::WireSerialize(CVarRef data, String& sdata) {
|
||||
TRACE(2, "DebuggerWireHelpers::WireSerialize(CVarRef data,\n");
|
||||
return serializeImpl(data, sdata);
|
||||
}
|
||||
|
||||
int DebuggerWireHelpers::WireUnserialize(String& sdata, Array& data) {
|
||||
TRACE(2, "DebuggerWireHelpers::WireUnserialize, Array& data)\n");
|
||||
Variant v;
|
||||
int ret = unserializeImpl(sdata, v);
|
||||
if (ret != NoError) {
|
||||
@@ -102,6 +112,7 @@ int DebuggerWireHelpers::WireUnserialize(String& sdata, Array& data) {
|
||||
}
|
||||
|
||||
int DebuggerWireHelpers::WireUnserialize(String& sdata, Object& data) {
|
||||
TRACE(2, "DebuggerWireHelpers::WireUnserialize, Object& data\n");
|
||||
Variant v;
|
||||
int ret = unserializeImpl(sdata, v);
|
||||
if (ret != NoError) {
|
||||
@@ -116,6 +127,7 @@ int DebuggerWireHelpers::WireUnserialize(String& sdata, Object& data) {
|
||||
}
|
||||
|
||||
int DebuggerWireHelpers::WireUnserialize(String& sdata, Variant& data) {
|
||||
TRACE(2, "DebuggerWireHelpers::WireUnserialize\n");
|
||||
return unserializeImpl(sdata, data);
|
||||
}
|
||||
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
|
||||
namespace HPHP { namespace Eval {
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
static const Trace::Module TRACEMOD = Trace::debugger;
|
||||
|
||||
DummySandbox::DummySandbox(DebuggerProxy *proxy,
|
||||
const std::string &defaultPath,
|
||||
@@ -35,10 +36,12 @@ DummySandbox::DummySandbox(DebuggerProxy *proxy,
|
||||
: m_proxy(proxy), m_defaultPath(defaultPath), m_startupFile(startupFile),
|
||||
m_stopped(false),
|
||||
m_signum(CmdSignal::SignalNone) {
|
||||
TRACE(2, "DummySandbox::DummySandbox\n");
|
||||
m_thread = new AsyncFunc<DummySandbox>(this, &DummySandbox::run);
|
||||
}
|
||||
|
||||
bool DummySandbox::waitForEnd(int seconds) {
|
||||
TRACE(2, "DummySandbox::waitForEnd\n");
|
||||
bool ret = m_thread->waitForEnd(seconds);
|
||||
if (ret) {
|
||||
delete m_thread;
|
||||
@@ -47,10 +50,12 @@ bool DummySandbox::waitForEnd(int seconds) {
|
||||
}
|
||||
|
||||
void DummySandbox::start() {
|
||||
TRACE(2, "DummySandbox::start\n");
|
||||
m_thread->start();
|
||||
}
|
||||
|
||||
void DummySandbox::stop() {
|
||||
TRACE(2, "DummySandbox::stop\n");
|
||||
m_stopped = true;
|
||||
ThreadInfo *ti = ThreadInfo::s_threadInfo.getNoCheck();
|
||||
if (ti->m_reqInjectionData.dummySandbox) {
|
||||
@@ -69,10 +74,12 @@ namespace {
|
||||
|
||||
struct CLISession : boost::noncopyable {
|
||||
CLISession() {
|
||||
TRACE(2, "CLISession::CLISession\n");
|
||||
char *argv[] = {"", nullptr};
|
||||
execute_command_line_begin(1, argv, 0);
|
||||
}
|
||||
~CLISession() {
|
||||
TRACE(2, "CLISession::~CLISession\n");
|
||||
Debugger::UnregisterSandbox(g_context->getSandboxId());
|
||||
ThreadInfo::s_threadInfo.getNoCheck()->
|
||||
m_reqInjectionData.debugger = false;
|
||||
@@ -83,6 +90,7 @@ struct CLISession : boost::noncopyable {
|
||||
}
|
||||
|
||||
void DummySandbox::run() {
|
||||
TRACE(2, "DummySandbox::run\n");
|
||||
ThreadInfo *ti = ThreadInfo::s_threadInfo.getNoCheck();
|
||||
Debugger::RegisterThread();
|
||||
ti->m_reqInjectionData.dummySandbox = true;
|
||||
@@ -155,12 +163,14 @@ void DummySandbox::run() {
|
||||
}
|
||||
|
||||
void DummySandbox::notifySignal(int signum) {
|
||||
TRACE(2, "DummySandbox::notifySignal\n");
|
||||
Lock lock(this);
|
||||
m_signum = signum;
|
||||
notify();
|
||||
}
|
||||
|
||||
std::string DummySandbox::getStartupDoc(const DSandboxInfo &sandbox) {
|
||||
TRACE(2, "DummySandbox::getStartupDoc\n");
|
||||
string path;
|
||||
if (!m_startupFile.empty()) {
|
||||
// if relative path, prepend directory
|
||||
|
||||
@@ -21,8 +21,10 @@
|
||||
|
||||
namespace HPHP { namespace Eval {
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
static const Trace::Module TRACEMOD = Trace::debugger;
|
||||
|
||||
const uchar* InstPointInfo::lookupPC() {
|
||||
TRACE(2, "InstPointInfo::lookupPC\n");
|
||||
VMExecutionContext* context = g_vmContext;
|
||||
if (m_locType == LocHere) {
|
||||
// Instrument to current location
|
||||
@@ -44,21 +46,25 @@ const uchar* InstPointInfo::lookupPC() {
|
||||
}
|
||||
|
||||
void InstPointInfo::setLocHere() {
|
||||
TRACE(2, "InstPointInfo::setLocHere\n");
|
||||
m_locType = LocHere;
|
||||
}
|
||||
|
||||
void InstPointInfo::setLocFileLine(const std::string& file, int line) {
|
||||
TRACE(2, "InstPointInfo::setLocFileLine\n");
|
||||
m_locType = LocFileLine;
|
||||
m_file = file;
|
||||
m_line = line;
|
||||
}
|
||||
|
||||
void InstPointInfo::setLocFuncEntry(const std::string& func) {
|
||||
TRACE(2, "InstPointInfo::setLocFuncEntry\n");
|
||||
m_locType = LocFuncEntry;
|
||||
m_func = func;
|
||||
}
|
||||
|
||||
void InstPointInfo::sendImpl(DebuggerThriftBuffer &thrift) {
|
||||
TRACE(2, "InstPointInfo::sendImpl\n");
|
||||
thrift.write(m_locType);
|
||||
thrift.write(m_valid);
|
||||
thrift.write(m_file);
|
||||
@@ -69,6 +75,7 @@ void InstPointInfo::sendImpl(DebuggerThriftBuffer &thrift) {
|
||||
}
|
||||
|
||||
void InstPointInfo::recvImpl(DebuggerThriftBuffer &thrift) {
|
||||
TRACE(2, "InstPointInfo::recvImpl\n");
|
||||
thrift.read(m_locType);
|
||||
thrift.read(m_valid);
|
||||
thrift.read(m_file);
|
||||
@@ -80,6 +87,7 @@ void InstPointInfo::recvImpl(DebuggerThriftBuffer &thrift) {
|
||||
|
||||
void InstPointInfo::SendImpl(const InstPointInfoPtrVec& ips,
|
||||
DebuggerThriftBuffer &thrift) {
|
||||
TRACE(2, "InstPointInfo::SendImpl\n");
|
||||
int16_t size = ips.size();
|
||||
thrift.write(size);
|
||||
for (int i = 0; i < size; i++) {
|
||||
@@ -89,6 +97,7 @@ void InstPointInfo::SendImpl(const InstPointInfoPtrVec& ips,
|
||||
|
||||
void InstPointInfo::RecvImpl(InstPointInfoPtrVec& ips,
|
||||
DebuggerThriftBuffer &thrift) {
|
||||
TRACE(2, "InstPointInfo::RecvImpl\n");
|
||||
int16_t size;
|
||||
thrift.read(size);
|
||||
ips.resize(size);
|
||||
|
||||
@@ -75,6 +75,7 @@ namespace Trace {
|
||||
TM(refcount) \
|
||||
TM(asmx64) \
|
||||
TM(runtime) \
|
||||
TM(debugger) \
|
||||
TM(debuginfo) \
|
||||
TM(stats) \
|
||||
TM(emitter) \
|
||||
|
||||
Referência em uma Nova Issue
Bloquear um usuário