bool UnitRepoProxy::GetSourceLocPastOffsetsStmt ::get(int64 unitSn, int line, OffsetRangeVec& ranges) { try { RepoTxn txn(m_repo); if (!prepared()) { std::stringstream ssSelect; ssSelect << "SELECT pastOffset FROM " << m_repo.table(m_repoId, "UnitSourceLoc") << " WHERE unitSn == @unitSn AND line0 <= @line" " AND line1 >= @line;"; txn.prepare(*this, ssSelect.str()); } RepoTxnQuery query(txn, *this); query.bindInt64("@unitSn", unitSn); query.bindInt("@line", line); do { query.step(); if (query.row()) { Offset pastOffset; /**/ query.getOffset(0, pastOffset); ranges.push_back(OffsetRange(pastOffset, pastOffset)); } } while (!query.done()); txn.commit(); } catch (RepoExc& re) { return true; } return false; }
// Setup the last location filter on the VM context for all offsets covered by // the current source line. This will short-circuit the work done in // phpDebuggerOpcodeHook() and ensure we don't interrupt on this source line. // We exclude continuation opcodes which transfer control out of the function, // which allows cmds to get a chance to alter their behavior when those opcodes // are encountered. void CmdFlowControl::installLocationFilterForLine(InterruptSite *site) { // We may be stopped at a place with no source info. if (!site || !site->valid()) return; if (g_context->m_lastLocFilter) { g_context->m_lastLocFilter->clear(); } else { g_context->m_lastLocFilter = new PCFilter(); } TRACE(3, "Prepare location filter for %s:%d, unit %p:\n", site->getFile(), site->getLine0(), site->getUnit()); OffsetRangeVec ranges; const auto unit = site->getUnit(); if (m_smallStep) { // Get offset range for the pc only. OffsetRange range; if (unit->getOffsetRange(site->getCurOffset(), range)) { ranges.push_back(range); } } else { // Get offset ranges for the whole line. // We use line1 here because it seems to be working better than line0 // in a handful of cases for our bytecode-source mapping. if (!unit->getOffsetRanges(site->getLine1(), ranges)) { ranges.clear(); } } auto excludeContinuationReturns = [] (Op op) { return (op != OpContSuspend) && (op != OpContSuspendK) && (op != OpAsyncESuspend) && (op != OpContRetC); }; g_context->m_lastLocFilter->addRanges(unit, ranges, excludeContinuationReturns); }
// Ensure we interpret an entire function when the debugger is attached. static void blacklistFuncInJit(const Func* f) { Unit* unit = f->unit(); OffsetRangeVec ranges; ranges.push_back(OffsetRange(f->base(), f->past())); blacklistRangesInJit(unit, ranges); }