예제 #1
0
// 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);
}
예제 #2
0
void phpDebuggerStepIn() {
    // If this is called in the middle of a flow command we short-circuit the
    // other commands
    auto& req_data = RID();
    req_data.setDebuggerStepIn(true);
    req_data.setDebuggerStepOut(StepOutState::NONE);
    req_data.setDebuggerNext(false);

    // Ensure the flow filter is fresh
    auto flow_filter = getFlowFilter();
    flow_filter->clear();

    // Check if the site is valid.
    VMRegAnchor _;
    ActRec* fp = vmfp();
    PC pc = vmpc();
    if (fp == nullptr || pc == nullptr) {
        TRACE(5, "Could not grab stack or program counter\n");
        return;
    }

    // Try to get needed context info. Bail if we can't
    const Func* func = fp->func();
    const Unit* unit = func != nullptr ? func->unit() : nullptr;
    if (func == nullptr || func == nullptr) {
        TRACE(5, "Could not grab the current unit or function\n");
        return;
    }

    // We use line1 here because it works better than line0 in our
    // bytecode-source mapping.
    int line;
    SourceLoc source_loc;
    if (unit->getSourceLoc(unit->offsetOf(pc), source_loc)) {
        line = source_loc.line1;
    } else {
        TRACE(5, "Could not grab the current line number\n");
        return;
    }

    TRACE(3, "Prepare location filter for %s:%d, unit %p:\n",
          unit->filepath()->data(), line, unit);

    // Get offset ranges for the whole line.
    OffsetRangeVec ranges;
    if (!unit->getOffsetRanges(line, ranges)) {
        ranges.clear();
    }

    flow_filter->addRanges(unit, ranges);
}