コード例 #1
0
ファイル: cmd_where.cpp プロジェクト: tony2001/hiphop-php
void CmdWhere::onClientImpl(DebuggerClient &client) {
    if (DebuggerCommand::displayedHelp(client)) return;
    if (client.argCount() > 1) {
        help(client);
        return;
    }

    Array st = fetchStackTrace(client);
    if (st.empty()) {
        client.info("(no stacktrace to display or in global scope)");
        client.info("if you hit serialization limit, consider do "
                    "\"set sa off\" and then get the stack without args");
        return;
    }

    // so list command can default to current frame
    client.moveToFrame(client.getFrame(), false);

    if (client.argCount() == 0) {
        int i = 0;
        for (ArrayIter iter(st); iter; ++iter) {
            client.printFrame(i, iter.second().toArray());
            ++i;
            if (!client.isApiMode() &&
                    i % DebuggerClient::ScrollBlockSize == 0 &&
                    client.ask("There are %zd more frames. Continue? [Y/n]",
                               st.size() - i) == 'n') {
                break;
            }
        }
    } else {
        string snum = client.argValue(1);
        int num = atoi(snum.c_str());
        if (snum[0] == '-') {
            snum = snum.substr(1);
        }
        if (!DebuggerClient::IsValidNumber(snum)) {
            client.error("The argument, if specified, has to be numeric.");
            return;
        }
        if (num > 0) {
            for (int i = 0; i < num && i < st.size(); i++) {
                client.printFrame(i, st[i].toArray());
            }
        } else if (num < 0) {
            for (int i = st.size() + num; i < st.size(); i++) {
                client.printFrame(i, st[i].toArray());
            }
        } else {
            client.error("0 was specified for the number of frames");
            client.tutorial(
                "The optional argument is the number of frames to print out. "
                "Use a positive number to print out innermost frames. Use a negative "
                "number to print out outermost frames."
            );
        }
    }
}
コード例 #2
0
ファイル: cmd_machine.cpp プロジェクト: MarkTseng/hiphop-php
bool CmdMachine::processList(DebuggerClient &client,
                             bool output /* = true */) {
  m_body = "list";
  CmdMachinePtr res = client.xend<CmdMachine>(this);
  client.updateSandboxes(res->m_sandboxes);
  if (!output) return true;

  if (res->m_sandboxes.empty()) {
    client.info("(no sandbox was found)");
    client.tutorial(
      "Please hit the sandbox from browser at least once. Then run "
      "'[m]achine [l]ist' again."
    );
  } else {
    for (int i = 0; i < (int)res->m_sandboxes.size(); i++) {
      client.print("  %d\t%s", i + 1,
                    res->m_sandboxes[i]->desc().c_str());
    }
    client.tutorial(
      "Use '[m]achine [a]ttach {index}' to attach to one sandbox. For "
      "example, 'm a 1'. If desired sandbox is not on the list, please "
      "hit the sandbox from browser once. Then run '[m]achine [l]ist' "
      "again."
    );
  }

  return true;
}
コード例 #3
0
ファイル: cmd_machine.cpp プロジェクト: MarkTseng/hiphop-php
bool CmdMachine::AttachSandbox(DebuggerClient &client,
                               DSandboxInfoPtr sandbox,
                               bool force /* = false */) {
  if (client.isLocal()) {
    client.error("Local script doesn't have sandbox to attach to.");
    return false;
  }

  CmdMachine cmd;
  cmd.m_body = "attach";
  cmd.m_sandboxes.push_back(sandbox);
  cmd.m_force = force;

  client.info("Attaching to %s and pre-loading, please wait...",
               sandbox->desc().c_str());
  CmdMachinePtr cmdMachine = client.xend<CmdMachine>(&cmd);
  if (cmdMachine->m_succeed) {
    client.playMacro("startup");
  } else {
    // Note: it would be nice to give them more info about the process we think
    // is debugging this sandbox: what machine it's on, what it's pid is, etc.
    // Unfortunately, we don't have any of that data. We'd need a protocol
    // change to have the client give us more info when it attaches.
    client.error(
      "Failed to attach to the sandbox. Maybe another client is debugging, \n"
      "or a client failed to detach cleanly.\n"
      "You can attach to another sandbox, or exit the other attached client, \n"
      "or force this client to take over the sandbox with: \n"
      "\n"
      "\t[m]achine [a]ttach [f]orce %s %s"
      "\n",
      sandbox->m_user.c_str(), sandbox->m_name.c_str());
  }
  return cmdMachine->m_succeed;
}
コード例 #4
0
ファイル: cmd_variable.cpp プロジェクト: Fininvest/hhvm
void CmdVariable::onClient(DebuggerClient &client) {
  if (DebuggerCommand::displayedHelp(client)) return;

  String text;
  if (client.argCount() == 1) {
    text = client.argValue(1);
  } else if (client.argCount() != 0) {
    help(client);
    return;
  }

  if (client.isStackTraceAsync()) {
    m_type = KindOfVariableAsync;
  }

  m_frame = client.getFrame();

  auto cmd = client.xend<CmdVariable>(this);
  if (cmd->m_variables.empty()) {
    client.info("(no variable was defined)");
  } else {
    PrintVariables(client, cmd->m_variables, cmd->m_global ? -1 : m_frame,
        text, cmd->m_version);
  }
}
コード例 #5
0
bool CmdMachine::AttachSandbox(DebuggerClient &client,
                               DSandboxInfoPtr sandbox,
                               bool force /* = false */) {
  if (client.isLocal()) {
    client.error("Local script doesn't have sandbox to attach to.");
    return false;
  }

  CmdMachine cmd;
  cmd.m_body = "attach";
  cmd.m_sandboxes.push_back(sandbox);
  cmd.m_force = force;

  client.info("Attaching to %s and pre-loading, please wait...",
               sandbox->desc().c_str());
  CmdMachinePtr cmdMachine = client.xend<CmdMachine>(&cmd);
  if (cmdMachine->m_succeed) {
    client.playMacro("startup");
  } else {
    client.error("failed to attach to sandbox, maybe another client is "
                  "debugging, \nattach to another sandbox, exit the "
                  "attached hphpd client, or try \n"
                  "[m]achine [a]ttach [f]orce [%s] [%s]",
                  sandbox->m_user.c_str(), sandbox->m_name.c_str());
  }
  return cmdMachine->m_succeed;
}
コード例 #6
0
void CmdInternalTesting::onClientImpl(DebuggerClient &client) {
  TRACE(2, "CmdInternalTesting::onClientImpl\n");
  if (DebuggerCommand::displayedHelp(client)) return;
  if (client.argCount() == 0) {
    help(client);
    return;
  }

  client.info("Executing internal test...");
  m_arg = client.argValue(1);

  if (client.arg(1, "badcmdtypesend")) {
    // Give the cmd a bad type and send it over. This should cause the proxy to
    // disconnect from us.
    m_type = KindOfInternalTestingBad;
    client.sendToServer(this);
    // Spin here and wait for the client to be marked as stopped
    // before going back to the event loop. This will give the local
    // proxy time to recgonize the bad cmd, terminate, and wait for
    // the client to stop. This will ensure that we always exit on the
    // same path on both proxy and client threads, and remove any
    // spurious output form ths test case.
    while (!client.internalTestingIsClientStopped()) {
      sleep(1);
    }
    throw DebuggerConsoleExitException(); // Expect no response
  } else if (client.arg(1, "badcmdtypereceive")) {
    client.xend<CmdInternalTesting>(this);
    return;
  } else if (client.arg(1, "shortcmdsend")) {
    m_arg = "shortcmd"; // Force send to drop a field.
    client.sendToServer(this);
    // See note above about this wait.
    while (!client.internalTestingIsClientStopped()) {
      sleep(1);
    }
    throw DebuggerConsoleExitException(); // Expect no response
  } else if (client.arg(1, "shortcmdreceive")) {
    client.xend<CmdInternalTesting>(this);
    return;
  } else if (client.arg(1, "segfaultClient")) {
    int *px = nullptr;
    *px = 42;
  } else if (client.arg(1, "segfaultServer")) {
    client.xend<CmdInternalTesting>(this);
    return;
  }

  help(client);
}
コード例 #7
0
void CmdZend::onClientImpl(DebuggerClient &client) {
  if (DebuggerCommand::displayedHelp(client)) return;

  if (client.argCount() == 0) {
    const std::string &code = client.getCode();
    if (!code.empty()) {
      const std::string zendExe = client.getZendExecutable();
      client.info("Executing last PHP block with \"%s\"...", zendExe.c_str());
      string out;
      Process::Exec(zendExe.c_str(), nullptr, code.c_str(), out, &out, true);
      client.print(out);
      return;
    }
  }
  help(client);
}
コード例 #8
0
ファイル: cmd_global.cpp プロジェクト: KOgames/hhvm
void CmdGlobal::onClient(DebuggerClient &client) {
  if (DebuggerCommand::displayedHelp(client)) return;

  String text;
  if (client.argCount() == 1) {
    text = client.argValue(1);
  } else if (client.argCount() != 0) {
    help(client);
    return;
  }

  auto cmd = client.xend<CmdGlobal>(this);
  if (cmd->m_globals.empty()) {
    client.info("(no global variable was found)");
  } else {
    CmdVariable::PrintVariables(client, cmd->m_globals, -1,
        text, cmd->m_version);
  }
}
コード例 #9
0
ファイル: cmd_variable.cpp プロジェクト: Barbayar/hiphop-php
void CmdVariable::onClient(DebuggerClient &client) {
  if (DebuggerCommand::displayedHelp(client)) return;

  String text;
  if (client.argCount() == 1) {
    text = client.argValue(1);
  } else if (client.argCount() != 0) {
    help(client);
    return;
  }

  m_frame = client.getFrame();
  CmdVariablePtr cmd = client.xend<CmdVariable>(this);
  if (cmd->m_variables.empty()) {
    client.info("(no variable was defined)");
  } else {
    m_variables = cmd->m_variables;
    PrintVariables(client, cmd->m_variables, cmd->m_global, text);
  }
}
コード例 #10
0
ファイル: cmd_variable.cpp プロジェクト: Barbayar/hiphop-php
void CmdVariable::PrintVariables(DebuggerClient &client, CArrRef variables,
                                 bool global, CStrRef text) {
  bool system = true;
  int i = 0;
  bool found = false;
  for (ArrayIter iter(variables); iter; ++iter) {
    String name = iter.first().toString();
    String value = DebuggerClient::FormatVariable(iter.second(), 200);
    if (!text.empty()) {
      String fullvalue = DebuggerClient::FormatVariable(iter.second(), -1);
      if (name.find(text, 0, false) >= 0 ||
          fullvalue.find(text, 0, false) >= 0) {
        client.print("%s = %s", name.data(), value.data());
        found = true;
      }
    } else {
      if (global && system) {
        client.print("$%s = %s", name.data(), value.data());
      } else {
        client.output("$%s = %s", name.data(), value.data());
      }

      // we knew this is the last system global
      if (global && name == "http_response_header") {
        client.output("%s", "");
        system = false;
      }

      ++i;
      if (i % DebuggerClient::ScrollBlockSize == 0 &&
          client.ask("There are %zd more variables. Continue? [Y/n]",
                      variables.size() - i) == 'n') {
        break;
      }
    }
  }

  if (!text.empty() && !found) {
    client.info("(unable to find specified text in any variables)");
  }
}
コード例 #11
0
ファイル: cmd_list.cpp プロジェクト: bd808/hhvm
// Sends this list command to the server to retrieve the source to be listed
// and then displays the source on the client. The client's current line
// is then updated to point to the last listed line.
// Returns false if the server was unable to return source for this command.
bool CmdList::listFileRange(DebuggerClient &client,
                            int lineFocus0, int charFocus0,
                            int lineFocus1, int charFocus1) {
  if (m_line1 <= 0) m_line1 = 1;
  if (m_line2 <= 0) m_line2 = 1;
  if (m_line1 > m_line2) {
    int32_t tmp = m_line1;
    m_line1 = m_line2;
    m_line2 = tmp;
  }

  auto res = client.xend<CmdList>(this);
  if (res->m_code.isString()) {
    if (!client.code(res->m_code.toString(), m_line1, m_line2,
                     lineFocus0, charFocus0, lineFocus1, charFocus1)) {
      client.info("No more lines in %s to display.", m_file.c_str());
    }
    client.setListLocation(m_file, m_line2, false);
    return true;
  }
  return false;
}
コード例 #12
0
ファイル: cmd_print.cpp プロジェクト: 360buyliulei/hiphop-php
void CmdPrint::processClear(DebuggerClient &client) {
  DebuggerClient::WatchPtrVec &watches = client.getWatches();
  if (watches.empty()) {
    client.error("There is no watch expression to clear.");
    client.tutorial(
      "Use '[p]rint [a]lways ...' to set new watch expressions. "
      "Use '[p]rint ?|[h]elp' to read how to set them. "
    );
    return;
  }

  if (client.arg(2, "all")) {
    watches.clear();
    client.info("All watch expressions are cleared.");
    return;
  }

  string snum = client.argValue(2);
  if (!DebuggerClient::IsValidNumber(snum)) {
    client.error("'[p]rint [c]lear' needs an {index} argument.");
    client.tutorial(
      "You will have to run '[p]rint [l]ist' first to see a list of valid "
      "numbers or indices to specify."
    );
    return;
  }

  int num = atoi(snum.c_str()) - 1;
  if (num < 0 || num >= (int)watches.size()) {
    client.error("\"%s\" is not a valid index. Choose one from this list:",
                  snum.c_str());
    processList(client);
    return;
  }

  watches.erase(watches.begin() + num);
}
コード例 #13
0
ファイル: cmd_where.cpp プロジェクト: stone54321277/hhvm
void CmdWhere::onClient(DebuggerClient &client) {
  if (DebuggerCommand::displayedHelp(client)) return;
  if (client.argCount() > 2) {
    help(client);
    return;
  }
  int argBase = 1;
  if ((client.argCount() > 0) && client.arg(argBase, "async")) {
    // We use a different command type for an async stack trace, so we
    // can both send and receive different data and still keep the
    // existing Where command unchanged. This ensures that old clients
    // can still get a stack trace from a newer server, and vice
    // versa.
    m_type = KindOfWhereAsync;
    argBase++;
    client.info("Fetching async stacktrace...");
  }

  Array st = fetchStackTrace(client);
  if (st.empty()) {
    if (m_type != KindOfWhereAsync) {
      client.info("(no stacktrace to display or in global scope)");
      client.info("If you hit the serialization limit, try "
                  "\"set sa off\" to get the stack without args");
    } else {
      client.info("(no async stacktrace to display)");
    }
    return;
  }

  // so list command can default to current frame
  client.moveToFrame(client.getFrame(), false);

  if (client.argCount() < argBase) {
    int i = 0;
    for (ArrayIter iter(st); iter; ++iter) {
      client.printFrame(i, iter.second().toArray());
      ++i;
      if (i % DebuggerClient::ScrollBlockSize == 0 &&
          client.ask("There are %zd more frames. Continue? [Y/n]",
                      st.size() - i) == 'n') {
        break;
      }
    }
  } else {
    std::string snum = client.argValue(argBase);
    int num = atoi(snum.c_str());
    if (snum[0] == '-') {
      snum = snum.substr(1);
    }
    if (!DebuggerClient::IsValidNumber(snum)) {
      client.error("The argument, if specified, has to be numeric.");
      return;
    }
    if (num > 0) {
      for (int i = 0; i < num && i < st.size(); i++) {
        client.printFrame(i, st[i].toArray());
      }
    } else if (num < 0) {
      for (int i = st.size() + num; i < st.size(); i++) {
        client.printFrame(i, st[i].toArray());
      }
    } else {
      client.error("0 was specified for the number of frames");
      client.tutorial(
        "The optional argument is the number of frames to print out. "
        "Use a positive number to print out innermost frames. Use a negative "
        "number to print out outermost frames."
      );
    }
  }
}
コード例 #14
0
void CmdVariable::PrintVariables(DebuggerClient &client, CArrRef variables,
                                 int frame, const String& text, int version) {
  bool global = frame == -1; // I.e. we were called from CmdGlobal, or the
  //client's current frame is the global frame, according to OnServer
  bool system = true;
  int i = 0;
  bool found = false;
  for (ArrayIter iter(variables); iter; ++iter) {
    String name = iter.first().toString();
    String value;
    if (version == 2) {
      // Using the new protocol, so variables contain only names.
      // Fetch the value separately.
      CmdVariable cmd;
      cmd.m_frame = frame;
      cmd.m_variables = null_array;
      cmd.m_varName = name;
      cmd.m_filter = text;
      cmd.m_version = 2;
      auto rcmd = client.xend<CmdVariable>(&cmd);
      if (!rcmd->m_variables.empty()) {
        value = DebuggerClient::FormatVariable(rcmd->m_variables[name], 200);
        found = true;
      } else if (text.empty()) {
        // Not missing because filtered out, assume the value is too large.
        value = s_omitted;
        found = true;
      } else {
        if (name.find(text, 0, false) >= 0) {
          // Server should have matched it.
          // Assume missing because value is too large.
          value = s_omitted;
          found = true;
        } else {
          // The variable was filtered out on the server, using text.
          // Or it was just too large. Either way we let skip over it.
          continue;
        }
      }
    } else {
      value = DebuggerClient::FormatVariable(iter.second(), 200);
    }
    if (version == 0 && !text.empty()) {
      if (name.find(text, 0, false) >= 0) {
        client.print("%s = %s", name.data(), value.data());
        found = true;
      } else {
        String fullvalue = DebuggerClient::FormatVariable(value, -1);
        if (fullvalue.find(text, 0, false) >= 0) {
          client.print("%s = %s", name.data(), value.data());
          found = true;
        }
      }
    } else {
      if (global && system) {
        client.print("$%s = %s", name.data(), value.data());
      } else {
        client.output("$%s = %s", name.data(), value.data());
      }

      // we know s_http_response_header is the last system global
      if (global && name == s_http_response_header) {
        client.output("%s", "");
        system = false;
      }

      ++i;
      if (i % DebuggerClient::ScrollBlockSize == 0 &&
          client.ask("There are %zd more variables. Continue? [Y/n]",
                      variables.size() - i) == 'n') {
        break;
      }
    }
  }

  if (!text.empty() && !found) {
    client.info("(unable to find specified text in any variables)");
  }
}
コード例 #15
0
ファイル: cmd_thread.cpp プロジェクト: 191919/hhvm
void CmdThread::onClient(DebuggerClient &client) {
  if (DebuggerCommand::displayedHelp(client)) return;
  if (client.argCount() > 1) {
    help(client);
    return;
  }

  if (client.argCount() == 0) {
    m_body = "info";
    auto res = client.xend<CmdThread>(this);
    client.print(res->m_out);
  } else if (client.arg(1, "list")) {
    processList(client);
  } else if (client.arg(1, "normal")) {
    m_body = "normal";
    client.sendToServer(this);
    client.info("Thread is running in normal mode now. Other threads will "
                 "interleave when they hit breakpoints as well.");
  } else if (client.arg(1, "sticky")) {
    m_body = "sticky";
    client.sendToServer(this);
    client.info("Thread is running in sticky mode now. All other threads "
                 "will wait until this thread finishes, when they hit "
                 "breakpoints.");
  } else if (client.arg(1, "exclusive")) {
    m_body = "exclusive";
    client.sendToServer(this);
    client.info("Thread is running in exclusive mode now. All other threads "
                 "will not break, even when they hit breakpoints.");
  } else {
    std::string snum = client.argValue(1);
    if (!DebuggerClient::IsValidNumber(snum)) {
      client.error("'[t]hread {index}' needs a numeric argument.");
      client.tutorial(
        "You will have to run '[t]hread [l]ist' first to see a list of valid "
        "numbers or indices to specify. Thread 1 is always your current "
        "thread. If that's the only thread on the list, you do not have "
        "another thread at break to switch to."
      );
      return;
    }

    int num = atoi(snum.c_str());
    DThreadInfoPtr thread = client.getThread(num);
    if (!thread) {
      processList(client, false);
      thread = client.getThread(num);
      if (!thread) {
        client.error("\"%s\" is not a valid thread index. Choose one from "
                      "this list:", snum.c_str());
        processList(client);
        return;
      }
    }

    if (thread->m_id == client.getCurrentThreadId()) {
      client.info("This is your current thread already.");
      return;
    }

    m_body = "switch";
    m_threads.push_back(thread);
    client.sendToServer(this);
    throw DebuggerConsoleExitException();
  }
}
コード例 #16
0
ファイル: cmd_list.cpp プロジェクト: bd808/hhvm
// Checks the command arguments, report errors and returning as appropriate.
// Then communicates with the server to retrieve source information. Also
// retrieves and updates location information stored in the client.
void CmdList::onClient(DebuggerClient &client) {
  if (DebuggerCommand::displayedHelp(client)) return;
  if (client.argCount() > 1) {
    help(client);
    return;
  }

  int line = 0;
  m_line1 = m_line2 = 0;
  if (client.argCount() == 1) {
    std::string arg = client.argValue(1);
    if (DebuggerClient::IsValidNumber(arg)) {
      line = atoi(arg.c_str());
      if (line <= 0) {
        client.error("A line number has to be a positive integer.");
        help(client);
        return;
      }
      m_line1 = line - DebuggerClient::CodeBlockSize/2;
      m_line2 = m_line1 + DebuggerClient::CodeBlockSize;
    } else if (arg.find("::") != std::string::npos) {
      if (!listFunctionOrClass(client)) {
        client.error("Unable to read specified method.");
      }
      return;
    } else {
      size_t pos = arg.find(':');
      if (pos != std::string::npos) {
        m_file = arg.substr(0, pos);
        if (m_file.empty()) {
          client.error("File name cannot be empty.");
          help(client);
          return;
        }
        arg = arg.substr(pos + 1);
      }
      pos = arg.find('-');
      if (pos != std::string::npos) {
        std::string line1 = arg.substr(0, pos);
        std::string line2 = arg.substr(pos + 1);
        if (!DebuggerClient::IsValidNumber(line1) ||
            !DebuggerClient::IsValidNumber(line2)) {
          if (m_file.empty()) {
            m_file = arg;
            m_line1 = 1;
            m_line2 = DebuggerClient::CodeBlockSize;
          } else {
            client.error("Line numbers have to be integers.");
            help(client);
            return;
          }
        } else {
          m_line1 = atoi(line1.c_str());
          m_line2 = atoi(line2.c_str());
          if (line1.empty()) {
            m_line1 = m_line2 - DebuggerClient::CodeBlockSize;
          }
          if (line2.empty()) {
            m_line2 = m_line1 + DebuggerClient::CodeBlockSize;
          }
          if (m_line1 <= 0 || m_line2 <= 0) {
            client.error("Line numbers have to be positive integers.");
            help(client);
            return;
          }
        }
      } else {
        if (!DebuggerClient::IsValidNumber(arg)) {
          if (m_file.empty()) {
            if (client.argCount() == 1 && listFunctionOrClass(client)) {
              return;
            }
            m_file = arg;
            m_line1 = 1;
            m_line2 = DebuggerClient::CodeBlockSize;
          } else {
            client.error("A line number has to be an integer.");
            help(client);
            return;
          }
        } else {
          int line = atoi(arg.c_str());
          if (line <= 0) {
            client.error("A line number has to be a positive integer.");
            help(client);
            return;
          }
          m_line1 = line - DebuggerClient::CodeBlockSize/2;
          m_line2 = m_line1 + DebuggerClient::CodeBlockSize;
        }
      }
    }
  }

  int charFocus0 = 0;
  int lineFocus1 = 0;
  int charFocus1 = 0;

  if (m_file.empty()) {
    getListLocation(client, line, charFocus0, lineFocus1, charFocus1);
    if (m_file.empty()) {
      listEvalCode(client);
      return;
    }
  } else if (m_file[0] == '/') {
    struct stat sb;
    stat(m_file.c_str(), &sb);
    if ((sb.st_mode & S_IFMT) == S_IFDIR) {
      client.setSourceRoot(m_file);
      client.info("PHP source root directory is set to %s", m_file.c_str());
      return;
    }
  }

   if (!listFileRange(client, line, charFocus0, lineFocus1, charFocus1)) {
     client.error(
       "Unable to read specified function, class or source file location.");
  }
}
コード例 #17
0
ファイル: cmd_variable.cpp プロジェクト: Globalcherry/hhvm
void CmdVariable::PrintVariables(DebuggerClient &client, const Array& variables,
                                 int frame, const String& text, int version) {
  bool global = frame == -1; // I.e. we were called from CmdGlobal, or the
  //client's current frame is the global frame, according to OnServer
  bool system = true;
  int i = 0;
  bool found = false;

  always_assert(version == 2);

  for (ArrayIter iter(variables); iter; ++iter) {
    auto const name = iter.first().toString();
    String value;

    // Using the new protocol, so variables contain only names.  Fetch the value
    // separately.
    CmdVariable cmd(client.isStackTraceAsync()
                    ? KindOfVariableAsync : KindOfVariable);
    cmd.m_frame = frame;
    cmd.m_variables.reset();
    cmd.m_varName = name;
    cmd.m_filter = text;
    cmd.m_formatMaxLen = 200;
    cmd.m_version = 2;
    auto rcmd = client.xend<CmdVariable>(&cmd);
    if (!rcmd->m_variables.empty()) {
      assert(rcmd->m_variables[name].isString());
      value = rcmd->m_variables[name].toString();
      found = true;
    } else if (text.empty()) {
      // Not missing because filtered out, assume the value is too large.
      value = s_omitted;
      found = true;
    } else if (name.find(text, 0, false) >= 0) {
      // Server should have matched it.  Assume missing because value is too
      // large.
      value = s_omitted;
      found = true;
    } else {
      // The variable was filtered out on the server, using text.  Or it was
      // just too large.  Either way we skip over it.
      continue;
    }

    if (global && system) {
      client.print("$%s = %s", name.data(), value.data());
    } else {
      client.output("$%s = %s", name.data(), value.data());
    }

    // We know s_HTTP_RAW_POST_DATA is the last system global.
    if (global && name == s_HTTP_RAW_POST_DATA) {
      client.output("%s", "");
      system = false;
    }

    ++i;
    if (i % DebuggerClient::ScrollBlockSize == 0 &&
        client.ask("There are %zd more variables. Continue? [Y/n]",
                   variables.size() - i) == 'n') {
      break;
    }
  }

  if (!text.empty() && !found) {
    client.info("(unable to find specified text in any variables)");
  }
}
コード例 #18
0
ファイル: cmd_interrupt.cpp プロジェクト: 191919/hhvm
void CmdInterrupt::onClient(DebuggerClient &client) {
  client.setCurrentLocation(m_threadId, m_bpi);
  if (!client.getDebuggerClientSmallStep()) {
    // Adjust line and char if it's not small stepping
    if (m_bpi->m_line1 == m_bpi->m_line2) {
      m_bpi->m_char1 = 1;
      m_bpi->m_char2 = 100;
    }
  }
  client.setMatchedBreakPoints(m_matched);

  switch (m_interrupt) {
    case SessionStarted:
      if (!m_program.empty()) {
        client.info("Program %s loaded. Type '[r]un' or '[c]ontinue' to go.",
                     m_program.c_str());
        m_bpi->m_file = m_program;
      }
      break;
    case SessionEnded:
      if (!m_program.empty()) {
        client.info("Program %s exited normally.", m_program.c_str());
      }
      break;
    case RequestStarted:
      if (!m_program.empty()) {
        client.info("Web request %s started.", m_program.c_str());
      }
      break;
    case RequestEnded:
      if (!m_program.empty()) {
        client.info("Web request %s ended.", m_program.c_str());
      }
      break;
    case PSPEnded:
      if (!m_program.empty()) {
        client.info("Post-Send Processing for %s was ended.",
                     m_program.c_str());
      }
      break;
    case HardBreakPoint:
    case BreakPointReached:
    case ExceptionThrown: {
      bool found = false;
      bool toggled = false;
      auto *bps = client.getBreakPoints();
      for (unsigned int i = 0; i < m_matched.size(); i++) {
        BreakPointInfoPtr bpm = m_matched[i];
        BreakPointInfoPtr bp;
        int index = 0;
        for (; index < (int)bps->size(); index++) {
          if (bpm->same((*bps)[index])) {
            bp = (*bps)[index];
            break;
          }
        }
        if (bp) {
          found = true;
          if (bp->m_state == BreakPointInfo::Once) {
            bp->m_state = BreakPointInfo::Disabled;
            toggled = true;
          }
          if (m_interrupt == BreakPointReached ||
              m_interrupt == HardBreakPoint) {
            client.info("Breakpoint %d reached %s", bp->index(),
                         m_bpi->site().c_str());
            client.shortCode(m_bpi);
          } else {
            if (m_bpi->m_exceptionClass == BreakPointInfo::ErrorClassName) {
              client.info("Breakpoint %d reached: An error occurred %s",
                           bp->index(), m_bpi->site().c_str());
              client.shortCode(m_bpi);
              client.error("Error Message: %s",
                            m_bpi->m_exceptionObject.c_str());
            } else {
              client.info("Breakpoint %d reached: Throwing %s %s",
                           bp->index(),
                           m_bpi->m_exceptionClass.c_str(),
                           m_bpi->site().c_str());
              client.shortCode(m_bpi);
              if (client.getLogFileHandler()) {
                client.output(m_bpi->m_exceptionObject);
              }
            }
          }
          if (!bpm->m_output.empty()) {
            client.print(bpm->m_output);
          }
        }
      }
      if (toggled) {
        CmdBreak::SendClientBreakpointListToServer(client);
      }
      if (!found) {
        if (m_interrupt == HardBreakPoint) {
          // for HardBreakPoint, default the frame to the caller
          client.setFrame(1);
        }
        client.info("Break %s", m_bpi->site().c_str());
        client.shortCode(m_bpi);
      }
      break;
    }
  }

  if (!m_errorMsg.empty()) {
    client.error(m_errorMsg);
  }

  // watches
  switch (m_interrupt) {
    case SessionStarted:
    case RequestStarted:
      break;
    default: {
      DebuggerClient::WatchPtrVec &watches = client.getWatches();
      for (int i = 0; i < (int)watches.size(); i++) {
        if (i > 0) client.output("%s", "");
        client.info("Watch %d: %s =", i + 1, watches[i]->second.c_str());
        Variant v = CmdPrint().processWatch(client, watches[i]->first,
                                            watches[i]->second);
        client.output(CmdPrint::FormatResult(watches[i]->first, v));
      }
    }
  }
}