Пример #1
0
bool CmdMachine::onServer(DebuggerProxy &proxy) {
  if (m_body == "rpc") {
    String host = m_rpcConfig[s_host].toString();
    if (host.empty()) {
      register_intercept("", false, uninit_null());
    } else {
      int port = m_rpcConfig[s_port].toInt32();
      LibEventHttpClient::SetCache(host.data(), port, 1);
      register_intercept("", "fb_rpc_intercept_handler", m_rpcConfig);
    }
    return proxy.sendToClient(this);
  }
  if (m_body == "list") {
    Debugger::GetRegisteredSandboxes(m_sandboxes);
    return proxy.sendToClient(this);
  }
  if (m_body == "attach" && !m_sandboxes.empty()) {
    m_succeed = proxy.switchSandbox(m_sandboxes[0]->id(), m_force);
    if (m_succeed) {
      proxy.notifyDummySandbox();
      m_exitInterrupt = true;
    }
    return proxy.sendToClient(this);
  }
  return false;
}
Пример #2
0
bool CmdWhere::onServer(DebuggerProxy &proxy) {
  m_stacktrace = g_vmContext->debugBacktrace(false, true, false);
  if (!m_stackArgs) {
    processStackTrace();
  }
  return proxy.sendToClient(this);
}
Пример #3
0
bool CmdVariable::onServer(DebuggerProxy &proxy) {
  if (m_type == KindOfVariableAsync) {
    //we only do variable inspection on continuation wait handles
    auto frame = getWaitHandleAtAsyncStackPosition(m_frame);

    if (frame != nullptr) {
      auto fp = frame->actRec();
      if (fp != nullptr) {
        m_variables = getVariables(fp);
      }
    }
  }
  else if (m_frame < 0) {
    m_variables = g_context->m_globalVarEnv->getDefinedVariables();
    m_global = true;
  } else {
    m_variables = g_context->getLocalDefinedVariables(m_frame);
    m_global = g_context->getVarEnv(m_frame) == g_context->m_globalVarEnv;
  }

  if (m_global) {
    m_variables.remove(s_GLOBALS);
  }
  if (m_version == 1) {
    // Remove the values before sending to client.
    ArrayInit ret(m_variables->size(), ArrayInit::Map{});
    Variant v;
    for (ArrayIter iter(m_variables); iter; ++iter) {
      ret.add(iter.first().toString(), v);
    }
    m_variables = ret.toArray();
    m_version = 2;
  } else if (m_version == 2) {
    // Remove entries that do not match a non empty m_varName.
    if (!m_varName.empty()) {
      ArrayInit ret(1, ArrayInit::Map{});
      ret.add(m_varName, m_variables[m_varName]);
      m_variables = ret.toArray();
    }
    // Remove entries whose name or contents do not match a non empty m_filter
    if (!m_filter.empty()) {
      ArrayInit ret(m_variables.size(), ArrayInit::Map{});
      for (ArrayIter iter(m_variables); iter; ++iter) {
        String name = iter.first().toString();
        if (name.find(m_filter, 0, false) < 0) {
          String fullvalue = DebuggerClient::FormatVariable(iter.second(), -1);
          if (fullvalue.find(m_filter, 0, false) < 0) {
            continue;
          }
        }
        ret.add(name, iter.second());
      }
      m_variables = ret.toArray();
    }
  }

  return proxy.sendToClient(this);
}
Пример #4
0
bool CmdThread::onServer(DebuggerProxy &proxy) {
  if (m_body == "info") {
    // collect info
    InfoVec info;
    debuggerInfo(info);
    Transport *transport = g_context->getTransport();
    if (transport) {
      transport->debuggerInfo(info);
    } else {
      Add(info, "Thread Type", proxy.getThreadType());
    }
    g_context->debuggerInfo(info);

    m_out = DebuggerClient::FormatInfoVec(info);
    return proxy.sendToClient(this);
  }

  if (m_body == "list") {
    proxy.getThreads(m_threads);
    return proxy.sendToClient(this);
  }
  if (m_body == "switch") {
    if (!m_threads.empty()) {
      proxy.switchThread(m_threads[0]);
      m_exitInterrupt = true;
      return true;
    }
  }

  if (m_body == "normal") {
    proxy.switchThreadMode(DebuggerProxy::Normal);
    return true;
  }
  if (m_body == "sticky") {
    proxy.switchThreadMode(DebuggerProxy::Sticky);
    return true;
  }
  if (m_body == "exclusive") {
    proxy.switchThreadMode(DebuggerProxy::Exclusive);
    return true;
  }

  assert(false);
  return false;
}
Пример #5
0
bool CmdWhere::onServer(DebuggerProxy &proxy) {
  if (m_type == KindOfWhereAsync) {
    m_stacktrace = createAsyncStacktrace();
  } else {
    m_stacktrace = createBacktrace(BacktraceArgs()
                                   .withSelf()
                                   .ignoreArgs(!m_stackArgs));
  }
  return proxy.sendToClient(this);
}
Пример #6
0
bool CmdEval::onServer(DebuggerProxy &proxy) {
  PCFilter* locSave = g_vmContext->m_lastLocFilter;
  g_vmContext->m_lastLocFilter = new PCFilter();
  g_vmContext->setDebuggerBypassCheck(m_bypassAccessCheck);
  DebuggerProxy::ExecutePHP(m_body, m_output, !proxy.isLocal(), m_frame);
  g_vmContext->setDebuggerBypassCheck(false);
  delete g_vmContext->m_lastLocFilter;
  g_vmContext->m_lastLocFilter = locSave;
  return proxy.sendToClient(this);
}
Пример #7
0
bool CmdInstrument::onServer(DebuggerProxy &proxy) {
  m_instPoints = &m_ips;
  m_enabled = true;
  if (m_type == ActionRead) {
    readFromTable(proxy);
  } else if (m_type == ActionWrite) {
    validateAndWriteToTable(proxy);
  }
  return proxy.sendToClient(this);
}
Пример #8
0
bool CmdShell::onServer(DebuggerProxy &proxy) {
  const char **argv =
    (const char **)malloc((m_args.size() + 1) * sizeof(char*));
  for (unsigned int i = 0; i < m_args.size(); i++) {
    argv[i] = (char*)m_args[i].c_str();
  }
  argv[m_args.size()] = nullptr;
  Process::Exec(argv[0], argv, nullptr, m_out, &m_out, true);
  free(argv);
  return proxy.sendToClient(this);
}
Пример #9
0
bool CmdWhere::onServer(DebuggerProxy &proxy) {
  if (m_type == KindOfWhereAsync) {
    m_stacktrace = createAsyncStacktrace();
  } else {
    m_stacktrace = g_vmContext->debugBacktrace(false, true, false);
    if (!m_stackArgs) {
      removeArgs();
    }
  }
  return proxy.sendToClient(this);
}
bool CmdInternalTesting::onServer(DebuggerProxy &proxy) {
  TRACE(2, "CmdInternalTesting::onServer\n");
  if (m_arg == "badcmdtypereceive") {
    m_type = KindOfInternalTestingBad; // Send back a bad cmd.
  } else if (m_arg == "shortcmdreceive") {
    m_arg = "shortcmd"; // Force send to drop a field
  } else if (m_arg == "segfaultServer") {
    int *px = nullptr;
    *px = 42;
  }
  return proxy.sendToClient(this);
}
Пример #11
0
bool CmdGlobal::onServer(DebuggerProxy &proxy) {
  m_globals = CmdVariable::GetGlobalVariables();
  if (m_version == 2) {
    // Remove the values before sending to client.
    ArrayInit ret(m_globals->size(), ArrayInit::Map{});
    Variant v;
    for (ArrayIter iter(m_globals); iter; ++iter) {
      ret.add(iter.first().toString(), v);
    }
    m_globals = ret.toArray();
  }
  return proxy.sendToClient(this);
}
Пример #12
0
// NB: unlike most other commands, the client expects that more interrupts
// can occur while we're doing the server-side work for an eval.
bool CmdEval::onServer(DebuggerProxy &proxy) {
  PCFilter* locSave = g_vmContext->m_lastLocFilter;
  g_vmContext->m_lastLocFilter = new PCFilter();
  g_vmContext->setDebuggerBypassCheck(m_bypassAccessCheck);
  proxy.ExecutePHP(m_body, m_output, m_frame, m_failed,
                   DebuggerProxy::ExecutePHPFlagsAtInterrupt |
                   (!proxy.isLocal() ? DebuggerProxy::ExecutePHPFlagsLog :
                    DebuggerProxy::ExecutePHPFlagsNone));
  g_vmContext->setDebuggerBypassCheck(false);
  delete g_vmContext->m_lastLocFilter;
  g_vmContext->m_lastLocFilter = locSave;
  return proxy.sendToClient(this);
}
Пример #13
0
// NB: unlike most other commands, the client expects that more interrupts
// can occur while we're doing the server-side work for an eval.
bool CmdEval::onServer(DebuggerProxy &proxy) {
  PCFilter locSave;
  RequestInjectionData &rid = ThreadInfo::s_threadInfo->m_reqInjectionData;
  locSave.swap(rid.m_flowFilter);
  g_context->debuggerSettings.bypassCheck = m_bypassAccessCheck;
  proxy.ExecutePHP(m_body, m_output, m_frame, m_failed,
                   DebuggerProxy::ExecutePHPFlagsAtInterrupt |
                   (!proxy.isLocal() ? DebuggerProxy::ExecutePHPFlagsLog :
                    DebuggerProxy::ExecutePHPFlagsNone));
  g_context->debuggerSettings.bypassCheck = false;
  locSave.swap(rid.m_flowFilter);
  return proxy.sendToClient(this);
}
Пример #14
0
bool CmdPrint::onServer(DebuggerProxy &proxy) {
  PCFilter* locSave = g_vmContext->m_lastLocFilter;
  g_vmContext->m_lastLocFilter = new PCFilter();
  g_vmContext->setDebuggerBypassCheck(m_bypassAccessCheck);
  {
    EvalBreakControl eval(m_noBreak);
    m_ret = DebuggerProxy::ExecutePHP(DebuggerProxy::MakePHPReturn(m_body),
                                      m_output, !proxy.isLocal(), m_frame);
  }
  g_vmContext->setDebuggerBypassCheck(false);
  delete g_vmContext->m_lastLocFilter;
  g_vmContext->m_lastLocFilter = locSave;
  return proxy.sendToClient(this);
}
Пример #15
0
bool CmdVariable::onServer(DebuggerProxy &proxy) {
  if (m_frame < 0) {
    m_variables = g_vmContext->m_globalVarEnv->getDefinedVariables();
    m_global = true;
  } else {
    m_variables = g_vmContext->getLocalDefinedVariables(m_frame);
    m_global = g_vmContext->getVarEnv(m_frame) == g_vmContext->m_globalVarEnv;
  }
  if (m_global) {
    m_variables.remove(s_GLOBALS);
  }
  if (m_version == 1) {
    // Remove the values before sending to client.
    ArrayInit ret(m_variables->size());
    Variant v;
    for (ArrayIter iter(m_variables); iter; ++iter) {
      ret.add(iter.first().toString(), v);
    }
    m_variables = ret.toArray();
    m_version = 2;
  } else if (m_version == 2) {
    // Remove entries that do not match a non empty m_varName.
    if (!m_varName.empty()) {
      ArrayInit ret(1);
      ret.add(m_varName, m_variables[m_varName]);
      m_variables = ret.toArray();
    }
    // Remove entries whose name or contents do not match a non empty m_filter
    if (!m_filter.empty()) {
      ArrayInit ret(1);
      for (ArrayIter iter(m_variables); iter; ++iter) {
        String name = iter.first().toString();
        if (name.find(m_filter, 0, false) < 0) {
          String fullvalue = DebuggerClient::FormatVariable(iter.second(), -1);
          if (fullvalue.find(m_filter, 0, false) < 0) {
            continue;
          }
        }
        ret.add(name, iter.second());
      }
      m_variables = ret.toArray();
    }
  }
  return proxy.sendToClient(this);
}
Пример #16
0
bool CmdExtension::onServer(DebuggerProxy &proxy) {
  if (m_args.size() <= 1) {
    return processList(proxy);
  }

  std::string name = m_args[1];
  Extension *ext = Extension::GetExtension(name);
  if (ext) {
    if (m_args.size() == 2) {
      if (ext->debuggerSupport() & IDebuggable::SupportInfo) {
        IDebuggable::InfoVec info;
        ext->debuggerInfo(info);
        m_out = DebuggerClient::FormatInfoVec(info);
      } else {
        m_err = "Extension doesn't have summary information.";
      }
    } else if (DebuggerClient::Match(m_args[2].c_str(), "dump")) {
      if (ext->debuggerSupport() & IDebuggable::SupportDump) {
        m_out = ext->debuggerDump();
        m_out += "\n";
      } else {
        m_err = "Extension doesn't have detailed dumps.";
      }
    } else {
      if (ext->debuggerSupport() & IDebuggable::SupportVerb) {
        std::string verb = m_args[2];
        std::vector<std::string> args;
        if (m_args.size() > 3) {
          args.insert(args.end(), m_args.begin() + 3, m_args.end());
        }
        m_out = ext->debuggerVerb(verb, args);
        m_out += "\n";
      } else {
        m_err = "Extension doesn't support any debugger actions.";
      }
    }
  } else {
    m_err = "Unable to find the specified extension: ";
    m_err += String(name);
  }
  return proxy.sendToClient(this);
}
Пример #17
0
// Tries to read the contents of the file whose path is specified in m_file.
// If the path cannot be resolved and is relative, the path of the sandbox
// is used to qualify the relative path. If the contents cannot be retrieved
// m_code will be an empty string.
// The function returns false if the reply to the client fails during the
// sending process.
bool CmdList::onServer(DebuggerProxy &proxy) {
  auto savedWarningFrequency = RuntimeOption::WarningFrequency;
  RuntimeOption::WarningFrequency = 0;
  m_code = f_file_get_contents(m_file.c_str());
  if (!proxy.isLocal() && !m_code.toBoolean() && m_file[0] != '/') {
    DSandboxInfo info = proxy.getSandbox();
    if (info.m_path.empty()) {
      raise_warning("path for sandbox %s is not setup, run a web request",
                    info.desc().c_str());
    } else {
      std::string full_path = info.m_path + m_file;
      m_code = f_file_get_contents(full_path.c_str());
    }
  }
  RuntimeOption::WarningFrequency = savedWarningFrequency;
  if (!m_code.toBoolean() && m_file == "systemlib.php") {
    m_code = SystemLib::s_source;
  }
  return proxy.sendToClient((DebuggerCommand*)this);
}
Пример #18
0
bool CmdExtension::processList(DebuggerProxy &proxy) {
  IDebuggable::InfoVec info;

  Array exts = Extension::GetLoadedExtensions();
  typedef std::set<std::string, string_lessi> sorted_iset;
  sorted_iset names;
  for (ArrayIter iter(exts); iter; ++iter) {
    names.insert(iter.second().toString().data());
  }
  for (sorted_iset::const_iterator iter = names.begin();
       iter != names.end(); ++iter) {
    Extension *ext = Extension::GetExtension(*iter);
    assert(ext);
    if (ext) {
      int support = ext->debuggerSupport();
      std::string line;
      line += (support & IDebuggable::SupportInfo) ? "Yes     " : "        ";
      line += (support & IDebuggable::SupportDump) ? "Yes     " : "        ";
      line += (support & IDebuggable::SupportVerb) ? "Yes     " : "        ";
      line += ext->getVersion();
      IDebuggable::Add(info, iter->c_str(), line);
    }
  }
  int nameLen;
  String body = DebuggerClient::FormatInfoVec(info, &nameLen);
  int hrLen = nameLen + 42;
  if (hrLen > DebuggerClient::LineWidth) hrLen = DebuggerClient::LineWidth;

  StringBuffer sb;
  for (int i = 0; i < hrLen; i++) sb.append(BOX_H); sb.append("\n");
  sb.append(StringUtil::Pad("Name\\Support", nameLen));
  sb.append("Info    Dump    Verb    Version\n");
  for (int i = 0; i < hrLen; i++) sb.append(BOX_H); sb.append("\n");
  sb.append(body);
  for (int i = 0; i < hrLen; i++) sb.append(BOX_H); sb.append("\n");

  m_out = sb.detach();
  return proxy.sendToClient(this);
}
Пример #19
0
bool CmdHeaptrace::onServer(DebuggerProxy &proxy) {

  // globals
  std::vector<TypedValue *> roots;
  CArrRef arr = g_vmContext->m_globalVarEnv->getDefinedVariables();
  arr->getChildren(roots);

  // static properties
  for (AllClasses ac; !ac.empty();) {
    Class *c = ac.popFront();
    c->getChildren(roots);
  }

  // locals
  int numFrames = proxy.getRealStackDepth();
  std::vector<Array> locs;
  for (int i = 0; i < numFrames; ++i) {
    locs.push_back(g_vmContext->getLocalDefinedVariables(i));
  }
  for (CArrRef locArr : locs) {
    locArr->getChildren(roots);
  }

  Tracer<Accum>::traceAll(
    roots,
    [](TypedValue *node, Accum &accum) {
      accum.typesMap[(int64_t)node] = (int8_t)node->m_type;
      accum.sizeMap[(int64_t)node] = (int64_t)MemoryProfile::getSizeOfTV(node);
    },
    [](TypedValue *parent, TypedValue *child, Accum &accum) {
      accum.adjacencyList[(int64_t)parent].push_back((int64_t)child);
    },
    m_accum
  );

  return proxy.sendToClient(this);
}
Пример #20
0
bool CmdInterrupt::onServer(DebuggerProxy &proxy) {
  return proxy.sendToClient(this);
}
Пример #21
0
// Sends an acknowledgment back to the client so that
// it can go ahead and terminate. It it were to do so
// before the server has received the command, the pipe
// will be closed and the proxy will carry on as if there
// were a communication failure, which is not as clean
// explicitly quitting.
bool CmdQuit::onServer(DebuggerProxy &proxy) {
  TRACE(2, "CmdQuit::onServer\n");
  return proxy.sendToClient(this);
}
Пример #22
0
bool CmdVariable::onServer(DebuggerProxy &proxy) {
  m_variables = g_vmContext->getLocalDefinedVariables(m_frame);
  return proxy.sendToClient(this);
}
Пример #23
0
bool CmdVariable::onServer(DebuggerProxy &proxy) {
  if (m_type == KindOfVariableAsync) {
    //we only do variable inspection on continuation wait handles
    auto frame = getWaitHandleAtAsyncStackPosition(m_frame);

    if (frame != nullptr) {
      auto fp = frame->actRec();
      if (fp != nullptr) {
        m_variables = getDefinedVariables(fp);
      }
    }
  } else if (m_frame < 0) {
    m_variables = g_context->m_globalVarEnv->getDefinedVariables();
    m_global = true;
  } else {
    m_variables = g_context->getLocalDefinedVariables(m_frame);
    m_global = g_context->hasVarEnv(m_frame) == g_context->m_globalVarEnv;
    auto oThis = g_context->getThis();
    if (nullptr != oThis) {
      TypedValue tvThis;

      tvThis.m_type = KindOfObject;
      tvThis.m_data.pobj = oThis;

      Variant thisName(s_this);
      m_variables.add(thisName, tvAsVariant(&tvThis));
    }
  }

  if (m_global) {
    m_variables.remove(s_GLOBALS);
  }

  // Deprecated IDE uses this, so keep it around for now.  It expects all
  // variable values to be fully serialized across the wire.
  if (m_version == 0) {
    return proxy.sendToClient(this);
  }

  // Version 1 of this command means we want the names of all variables, but we
  // don't care about their values just yet.
  if (m_version == 1) {
    ArrayInit ret(m_variables->size(), ArrayInit::Map{});
    Variant v;
    for (ArrayIter iter(m_variables); iter; ++iter) {
      assert(iter.first().isString());
      ret.add(iter.first().toString(), v);
    }
    m_variables = ret.toArray();
    m_version = 2;
    return proxy.sendToClient(this);
  }

  // Version 2 of this command means we're trying to get the value of a single
  // variable.
  always_assert(m_version == 2);
  always_assert(!m_varName.empty());

  // Variable name might not exist.
  if (!m_variables.exists(m_varName, true /* isKey */)) {
    m_variables = Array::Create();
    return proxy.sendToClient(this);
  }

  auto const value = m_variables[m_varName];
  auto const result = m_formatMaxLen < 0
    ? DebuggerClient::FormatVariable(value)
    : DebuggerClient::FormatVariableWithLimit(value, m_formatMaxLen);
  m_variables = Array::Create(m_varName, result);

  // Remove the entry if its name or context does not match the filter.
  if (!m_filter.empty() && m_varName.find(m_filter, 0, false) < 0) {
    auto const fullvalue = DebuggerClient::FormatVariable(value);
    if (fullvalue.find(m_filter, 0, false) < 0) {
      m_variables = Array::Create();
    }
  }

  return proxy.sendToClient(this);
}
Пример #24
0
bool CmdSignal::onServer(DebuggerProxy &proxy) {
  return proxy.sendToClient(this);
}