Esempio n. 1
0
bool EventHook::RunInterceptHandler(ActRec* ar) {
  const Func* func = ar->m_func;
  if (LIKELY(func->maybeIntercepted() == 0)) return true;

  // Intercept only original generator / async function calls, not resumption.
  if (ar->inGenerator()) return true;

  Variant *h = get_intercept_handler(func->fullNameRef(),
                                     &func->maybeIntercepted());
  if (!h) return true;

  JIT::VMRegAnchor _;

  PC savePc = g_context->m_pc;

  Variant doneFlag = true;
  Variant called_on;

  if (ar->hasThis()) {
    called_on = Variant(ar->getThis());
  } else if (ar->hasClass()) {
    // For static methods, give handler the name of called class
    called_on = Variant(const_cast<StringData*>(ar->getClass()->name()));
  }
  Variant intArgs =
    PackedArrayInit(5)
      .append(ar->m_func->fullNameRef())
      .append(called_on)
      .append(get_frame_args_with_ref(ar))
      .append(h->asCArrRef()[1])
      .appendRef(doneFlag)
      .toArray();

  Variant ret = vm_call_user_func(h->asCArrRef()[0], intArgs);
  if (doneFlag.toBoolean()) {
    Offset pcOff;
    ActRec* outer = g_context->getPrevVMState(ar, &pcOff);

    frame_free_locals_inl_no_hook<true>(ar, ar->m_func->numLocals());
    Stack& stack = g_context->getStack();
    stack.top() = (Cell*)(ar + 1);
    cellDup(*ret.asCell(), *stack.allocTV());

    g_context->m_fp = outer;
    g_context->m_pc = outer ? outer->m_func->unit()->at(pcOff) : nullptr;

    return false;
  }
  g_context->m_fp = ar;
  g_context->m_pc = savePc;

  return true;
}
Esempio n. 2
0
bool EventHook::RunInterceptHandler(ActRec* ar) {
  const Func* func = ar->m_func;
  if (LIKELY(func->maybeIntercepted() == 0)) return true;

  Variant *h = get_intercept_handler(func->fullNameRef(),
                                     &func->maybeIntercepted());
  if (!h) return true;

  Transl::VMRegAnchor _;

  PC savePc = g_vmContext->m_pc;

  Variant doneFlag = true;
  Variant called_on;

  if (ar->hasThis()) {
    called_on = Variant(ar->getThis());
  } else if (ar->hasClass()) {
    // For static methods, give handler the name of called class
    called_on = Variant(const_cast<StringData*>(ar->getClass()->name()));
  }
  Array intArgs =
    CREATE_VECTOR5(ar->m_func->fullNameRef(),
                   called_on,
                   get_frame_args_with_ref(ar),
                   h->asCArrRef()[1],
                   ref(doneFlag));

  Variant ret = vm_call_user_func(h->asCArrRef()[0], intArgs);
  if (doneFlag.toBoolean()) {
    Offset pcOff;
    ActRec* outer = g_vmContext->getPrevVMState(ar, &pcOff);
    assert(outer);

    frame_free_locals_inl_no_hook<true>(ar, ar->m_func->numLocals());
    Stack& stack = g_vmContext->getStack();
    stack.top() = (Cell*)(ar + 1);
    tvDup(ret.asTypedValue(), stack.allocTV());

    g_vmContext->m_fp = outer;
    g_vmContext->m_pc = outer->m_func->unit()->at(pcOff);

    return false;
  }
  g_vmContext->m_fp = ar;
  g_vmContext->m_pc = savePc;

  return true;
}
Esempio n. 3
0
bool EventHook::RunInterceptHandler(ActRec* ar) {
  const Func* func = ar->m_func;
  if (LIKELY(func->maybeIntercepted() == 0)) return true;

  Variant *h = get_intercept_handler(func->fullNameRef(),
                                     &func->maybeIntercepted());
  if (!h) return true;

  Transl::VMRegAnchor _;

  PC savePc = g_vmContext->m_pc;

  Offset pcOff;
  ActRec* outer = g_vmContext->getPrevVMState(ar, &pcOff);
  assert(outer);
  g_vmContext->m_fp = outer;
  g_vmContext->m_pc = outer->m_func->unit()->at(pcOff);

  try {
    Variant doneFlag = true;
    Variant obj = ar->hasThis() ?
      Variant(Object(ar->getThis())) : uninit_null();
    Array intArgs =
      CREATE_VECTOR5(ar->m_func->fullNameRef(),
                     obj,
                     get_frame_args_with_ref(ar),
                     h->asCArrRef()[1],
                     ref(doneFlag));

    Variant ret = vm_call_user_func(h->asCArrRef()[0], intArgs);
    if (doneFlag.toBoolean()) {
      frame_free_locals_inl_no_hook(ar, ar->m_func->numLocals());
      Stack& stack = g_vmContext->getStack();
      stack.top() = (Cell*)(ar + 1);
      tvDup(ret.asTypedValue(), stack.allocTV());
      return false;
    }
    g_vmContext->m_fp = ar;
    g_vmContext->m_pc = savePc;
  } catch (...) {
    g_vmContext->m_fp = ar;
    g_vmContext->m_pc = savePc;
    g_vmContext->m_stack.top() = Stack::frameStackBase(ar);
    throw;
  }

  return true;
}
Esempio n. 4
0
bool EventHook::RunInterceptHandler(ActRec* ar) {
  const Func* func = ar->func();
  if (LIKELY(func->maybeIntercepted() == 0)) return true;

  // Intercept only original generator / async function calls, not resumption.
  if (ar->resumed()) return true;

  Variant* h = get_intercept_handler(func->fullNameStr(),
                                     &func->maybeIntercepted());
  if (!h) return true;

  /*
   * In production mode, only functions that we have assumed can be
   * intercepted during static analysis should actually be
   * intercepted.
   */
  if (RuntimeOption::RepoAuthoritative &&
      !RuntimeOption::EvalJitEnableRenameFunction) {
    if (!(func->attrs() & AttrInterceptable)) {
      raise_error("fb_intercept was used on a non-interceptable function (%s) "
                  "in RepoAuthoritative mode", func->fullName()->data());
    }
  }

  VMRegAnchor _;

  PC savePc = vmpc();

  Variant doneFlag = true;
  Variant called_on;

  if (ar->hasThis()) {
    called_on = Variant(ar->getThis());
  } else if (ar->hasClass()) {
    // For static methods, give handler the name of called class
    called_on = Variant(const_cast<StringData*>(ar->getClass()->name()));
  }
  Variant intArgs =
    PackedArrayInit(5)
      .append(VarNR(ar->func()->fullName()))
      .append(called_on)
      .append(get_frame_args_with_ref(ar))
      .append(h->asCArrRef()[1])
      .appendRef(doneFlag)
      .toArray();

  Variant ret = vm_call_user_func(h->asCArrRef()[0], intArgs);
  if (doneFlag.toBoolean()) {
    Offset pcOff;
    ActRec* outer = g_context->getPrevVMState(ar, &pcOff);

    frame_free_locals_inl_no_hook<true>(ar, ar->func()->numLocals());
    Stack& stack = vmStack();
    stack.top() = (Cell*)(ar + 1);
    cellDup(*ret.asCell(), *stack.allocTV());

    vmfp() = outer;
    vmpc() = outer ? outer->func()->unit()->at(pcOff) : nullptr;

    return false;
  }
  vmfp() = ar;
  vmpc() = savePc;

  return true;
}