Пример #1
0
// Helper used when looping through the unmatched breakpoints. Checks if the
// given function breakpoint matches the given function. If it does, it is
// removed from the unmatched set using the given iterator. The passed iterator
// reference is then modified to be the correct "next" iterator. Returns true
// if there was a match, false otherwise.
bool check_func_match(XDebugBreakpoint& bp,
                      const Func* func,
                      hphp_hash_set<int>::iterator& iter) {
  if (func->fullName()->equal(bp.fullFuncName.get())) {
    add_func_breakpoint(*iter, bp, func);
    iter = UNMATCHED.erase(iter);
    return true;
  }
  return false;
}
Пример #2
0
// Adding a breakpoint. Returns a unique id for the breakpoint.
int XDebugThreadBreakpoints::addBreakpoint(XDebugBreakpoint& bp) {
  auto const id = s_xdebug_breakpoints->m_nextBreakpointId;

  // php5 xdebug only accepts multiple breakpoints of the same type for
  // line breakpoints. A useful addition might be to allow multiple of all
  // types, but for now, multiple function or exception breakpoints results
  // in the most recent silently being used (matching php5 xdebug).
  switch (bp.type) {
    case BreakType::EXCEPTION: {
      // Remove duplicates then insert the name
      auto exceptionName = bp.exceptionName.toCppString();
      auto iter = EXCEPTION_MAP.find(exceptionName);
      if (iter != EXCEPTION_MAP.end()) {
        XDEBUG_REMOVE_BREAKPOINT(iter->second);
      }
      EXCEPTION_MAP[exceptionName] = id;
      break;
    }
    // Attempt to find the unit/line combo
    case BreakType::LINE: {
      const Unit* unit = find_unit(bp.fileName);
      if (unit == nullptr) {
        UNMATCHED.insert(id);
        break;
      }

      // If the file/line combo is invalid, throw an error
      if (!phpAddBreakPointLine(unit, bp.line)) {
        throw XDebugServer::ERROR_BREAKPOINT_INVALID;
      }
      add_line_breakpoint(id, bp, unit);
      break;
    }
    // Try to find the breakpoint's function
    case BreakType::CALL:
    case BreakType::RETURN: {
      const Class* cls = nullptr;
      const Func* func = nullptr;
      if (bp.className.isNull()) {
        func = Unit::lookupFunc(bp.funcName.get());
      } else {
        cls = Unit::lookupClass(bp.className.toString().get());
        if (cls != nullptr) {
          func = cls->lookupMethod(bp.funcName.get());
        }
      }

      // Either add the breakpoint or store it as unmatched. If the class
      // exists, we can verify that the method is valid.
      if (func != nullptr) {
        add_func_breakpoint(id, bp, func);
      } else if (!bp.className.isNull() && cls != nullptr) {
        throw XDebugServer::ERROR_BREAKPOINT_INVALID;
      } else {
        UNMATCHED.insert(id);
      }
      break;
    }
  }

  // Success, store the breakpoint and increment the id.
  BREAKPOINT_MAP[id] = bp;
  s_xdebug_breakpoints->m_nextBreakpointId++;
  return id;
}