// 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"); // Hold the break mutex while we update the proxy's state. There's no need // to hold it over the longer operation to set breakpoints in each file later. { WriteLock lock(m_breakMutex); m_breakpoints = breakpoints; m_hasBreakPoints = !m_breakpoints.empty(); m_breaksEnterFunc.clear(); m_breaksEnterClsMethod.clear(); for (unsigned int i = 0; i < m_breakpoints.size(); i++) { BreakPointInfoPtr bp = m_breakpoints[i]; std::string funcFullName = bp->getFuncName(); if (funcFullName.empty()) { continue; } { StringDataMap::accessor acc; const StringData* sd = StringData::GetStaticString(funcFullName); m_breaksEnterFunc.insert(acc, sd); } std::string clsName = bp->getClass(); if (!clsName.empty()) { StringDataMap::accessor acc; const StringData* sd = StringData::GetStaticString(clsName); m_breaksEnterClsMethod.insert(acc, sd); } } } VM::phpSetBreakPointsInAllFiles(this); // Apply breakpoints to the code. }
void HphpdHook::onDefFunc(const Func* f) { // Make sure we have a proxy DebuggerProxyPtr proxy = Debugger::GetProxy(); if (proxy == nullptr) return; // If the proxy has an enabled breakpoint that matches entry into the given // function, arrange for the VM to stop execution and notify the debugger // whenever execution enters the given function. std::vector<BreakPointInfoPtr> bps; proxy->getBreakPoints(bps); for (unsigned int i = 0; i < bps.size(); i++) { BreakPointInfoPtr bp = bps[i]; if (bp->m_state == BreakPointInfo::Disabled) continue; if (!matchFunctionName(bp->getFuncName(), f)) continue; bp->m_bindState = BreakPointInfo::KnownToBeValid; phpAddBreakPointFuncEntry(f); return; } }
void proxySetBreakPoints(DebuggerProxy* proxy) { std::vector<BreakPointInfoPtr> bps; proxy->getBreakPoints(bps); for (unsigned int i = 0; i < bps.size(); i++) { BreakPointInfoPtr bp = bps[i]; bp->m_bindState = BreakPointInfo::Unknown; auto className = bp->getClass(); if (!className.empty()) { auto clsName = makeStaticString(className); auto cls = Unit::lookupClass(clsName); if (cls == nullptr) continue; bp->m_bindState = BreakPointInfo::KnownToBeInvalid; size_t numFuncs = cls->numMethods(); if (numFuncs == 0) continue; auto methodName = bp->getFunction(); for (size_t i = 0; i < numFuncs; ++i) { auto f = cls->getMethod(i); if (!matchFunctionName(methodName, f)) continue; bp->m_bindState = BreakPointInfo::KnownToBeValid; phpAddBreakPointFuncEntry(f); break; } // TODO(#2527229): what about superclass methods accessed via the derived // class? continue; } auto funcName = bp->getFuncName(); if (!funcName.empty()) { auto fName = makeStaticString(funcName); Func* f = Unit::lookupFunc(fName); if (f == nullptr) continue; bp->m_bindState = BreakPointInfo::KnownToBeValid; phpAddBreakPointFuncEntry(f); continue; } auto fileName = bp->m_file; if (!fileName.empty()) { for (auto& kv : g_context->m_evaledFiles) { auto const unit = kv.second; if (!BreakPointInfo::MatchFile(fileName, unit->filepath()->toCppString())) { continue; } addBreakPointInUnit(bp, unit); break; } continue; } auto exceptionClassName = bp->getExceptionClass(); if (exceptionClassName == "@") { bp->m_bindState = BreakPointInfo::KnownToBeValid; continue; } else if (!exceptionClassName.empty()) { auto expClsName = makeStaticString(exceptionClassName); auto cls = Unit::lookupClass(expClsName); if (cls != nullptr) { auto baseClsName = makeStaticString("Exception"); auto baseCls = Unit::lookupClass(baseClsName); if (baseCls != nullptr) { if (cls->classof(baseCls)) { bp->m_bindState = BreakPointInfo::KnownToBeValid; } else { bp->m_bindState = BreakPointInfo::KnownToBeInvalid; } } } continue; } else { continue; } // If we get here, the break point is of a type that does // not need to be explicitly enabled in the VM. For example // a break point that get's triggered when the server starts // to process a page request. bp->m_bindState = BreakPointInfo::KnownToBeValid; } }