Пример #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
void HphpdHook::onDefClass(const Class* cls) {
  // Make sure we have a proxy
  DebuggerProxy* proxy = Debugger::GetProxy().get();
  if (proxy == nullptr) return;

  // If the proxy has enabled breakpoints that match entry into methods of
  // the given class, arrange for the VM to stop execution and notify the
  // debugger whenever execution enters one of these matched method.
  // This function is called once, when a class is first loaded, so it is not
  // performance critical.
  size_t numFuncs = cls->numMethods();
  if (numFuncs == 0) return;
  auto clsName = cls->name();
  std::vector<BreakPointInfoPtr> bps;
  proxy->getBreakPoints(bps);
  for (unsigned int i = 0; i < bps.size(); i++) {
    BreakPointInfoPtr bp = bps[i];
    if (bp->m_state == BreakPointInfo::Disabled) continue;
    // TODO: check name space separately
    if (bp->getClass() != clsName->data()) continue;
    bp->m_bindState = BreakPointInfo::KnownToBeInvalid;
    for (size_t i = 0; i < numFuncs; ++i) {
      auto f = cls->getMethod(i);
      if (!matchFunctionName(bp->getFunction(), f)) continue;
      bp->m_bindState = BreakPointInfo::KnownToBeValid;
      phpAddBreakPointFuncEntry(f);
    }
  }
}
Пример #3
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);
}
Пример #4
0
    DWORD    DebuggerProxy::DebugPollProc( void* param )
    {
        _ASSERT( param != NULL );

        DebuggerProxy*    pThis = (DebuggerProxy*) param;

        CoInitializeEx( NULL, COINIT_MULTITHREADED );
        HRESULT hr = pThis->PollLoop();
        CoUninitialize();

        return hr;
    }
Пример #5
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);
}
Пример #6
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);
}
Пример #7
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);
}
Пример #8
0
void CmdOut::onBeginInterrupt(DebuggerProxy &proxy, CmdInterrupt &interrupt) {
  TRACE(2, "CmdNext::onBeginInterrupt\n");
  assert(!m_complete); // Complete cmds should not be asked to do work.
  if (interrupt.getInterruptType() == ExceptionThrown) {
    // If an exception is thrown we turn interrupts on to ensure we stop when
    // control reaches the first catch clause.
    removeLocationFilter();
    m_needsVMInterrupt = true;
    return;
  }

  int currentVMDepth = g_vmContext->m_nesting;
  int currentStackDepth = proxy.getStackDepth();

  // Deeper or same depth? Keep running.
  if ((currentVMDepth > m_vmDepth) ||
      ((currentVMDepth == m_vmDepth) && (currentStackDepth >= m_stackDepth))) {
    return;
  }

  TRACE(2, "CmdOut: shallower stack depth, done.\n");
  cleanupStepOuts();
  m_complete = (decCount() == 0);
  if (!m_complete) {
    TRACE(2, "CmdOut: not complete, step out again.\n");
    onSetup(proxy, interrupt);
  }
  m_needsVMInterrupt = false;
}
Пример #9
0
bool CmdWhere::onServer(DebuggerProxy &proxy) {
  m_stacktrace = g_vmContext->debugBacktrace(false, true, false);
  if (!m_stackArgs) {
    processStackTrace();
  }
  return proxy.sendToClient(this);
}
Пример #10
0
void HphpdHook::onFileLoad(Unit* unit) {
  DebuggerProxy* proxy = Debugger::GetProxy().get();
  if (proxy == nullptr) return;

  // Look up the proxy's breakpoints and add needed breakpoints to the passed
  // unit
  std::vector<BreakPointInfoPtr> bps;
  proxy->getBreakPoints(bps);
  for (unsigned int i = 0; i < bps.size(); i++) {
    BreakPointInfoPtr bp = bps[i];
    if (BreakPointInfo::MatchFile(bp->m_file,
                                        unit->filepath()->toCppString())) {
      addBreakPointInUnit(bp, unit);
    }
  }
}
Пример #11
0
void CmdOut::onBeginInterrupt(DebuggerProxy &proxy, CmdInterrupt &interrupt) {
  TRACE(2, "CmdNext::onBeginInterrupt\n");
  assert(!m_complete); // Complete cmds should not be asked to do work.
  if (interrupt.getInterruptType() == ExceptionThrown) {
    // If an exception is thrown we turn interrupts on to ensure we stop when
    // control reaches the first catch clause.
    removeLocationFilter();
    m_needsVMInterrupt = true;
    return;
  }

  int currentVMDepth = g_vmContext->m_nesting;
  int currentStackDepth = proxy.getStackDepth();
  if (currentVMDepth < m_vmDepth) {
    // Cut corner here, just break when cross VM boundary no matter how
    // many levels we want to go out of
    TRACE(2, "CmdOut: shallower VM depth, done.\n");
    cleanupStepOuts();
    m_complete = true;
  } else if ((currentVMDepth == m_vmDepth) &&
             (currentStackDepth < m_stackDepth)) {
    TRACE(2, "CmdOut: same VM depth, shallower stack depth, done.\n");
    cleanupStepOuts();
    m_complete = (decCount() == 0);
    if (!m_complete) {
      TRACE(2, "CmdOut: not complete, step out again.\n");
      setupStepOuts();
    }
  }
  m_needsVMInterrupt = false;
}
Пример #12
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);
}
Пример #13
0
void CmdOut::onSetup(DebuggerProxy &proxy, CmdInterrupt &interrupt) {
  TRACE(2, "CmdOut::onSetup\n");
  assert(!m_complete); // Complete cmds should not be asked to do work.
  m_stackDepth = proxy.getStackDepth();
  m_vmDepth = g_context->m_nesting;

  // Simply setup a "step out breakpoint" and let the program run.
  setupStepOuts();
}
Пример #14
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);
}
Пример #15
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);
}
Пример #16
0
void CmdInstrument::validateAndWriteToTable(DebuggerProxy &proxy) {
  if (!proxy.getInjTables()) {
    proxy.setInjTables(new InjectionTables());
  }
  InjectionTableInt64* tablePC = nullptr;
  InjectionTableSD* tableFEntry = nullptr;

  for (int i = 0; i < (int)m_ips.size(); i++) {
    InstPointInfoPtr ipi = m_ips[i];
    const Injection* inj =
      InjectionCache::GetInjection(ipi->m_code, ipi->m_desc);
    if (!inj) { // error in the code
      continue;
    }
    if (ipi->m_locType == InstPointInfo::LocHere ||
        ipi->m_locType == InstPointInfo::LocFileLine) {
      // bytecode address
      const uchar *pc = ipi->lookupPC();
      if (pc == nullptr) {
        continue;
      }
      if (tablePC == nullptr) {
        tablePC = new InjectionTableInt64();
      }
      ipi->m_valid = true;
      (*tablePC)[(int64_t)pc] = inj;
    }
    if (ipi->m_locType == InstPointInfo::LocFuncEntry) {
      StackStringData sd(ipi->m_func.c_str(), ipi->m_func.size(), AttachLiteral);
      const StringData* sdCache = InjectionCache::GetStringData(&sd);
      if (tableFEntry == nullptr) {
        tableFEntry = new InjectionTableSD();
      }
      ipi->m_valid = true;
      (*tableFEntry)[sdCache] = inj;
    }
  }

  proxy.getInjTables()->setInt64Table(InstHookTypeBCPC, tablePC);
  proxy.getInjTables()->setSDTable(InstHookTypeFuncEntry, tableFEntry);

  proxy.writeInjTablesToThread();
}
Пример #17
0
void CmdInstrument::readFromTable(DebuggerProxy &proxy) {
  proxy.readInjTablesFromThread();
  m_ips.clear();
  if (!proxy.getInjTables()) {
    // nothing there
    return;
  }
  // Bytecode address
  InjectionTableInt64* tablePC =
    proxy.getInjTables()->getInt64Table(InstHookTypeBCPC);
  if (tablePC) {
    for (InjectionTableInt64::const_iterator it = tablePC->begin();
         it != tablePC->end(); ++it) {
      const Injection* inj = it->second;
      InstPointInfoPtr ipi(new InstPointInfo());
      ipi->m_valid = true;
      if (inj->m_desc) {
        ipi->m_desc = inj->m_desc->data();
      }
      ipi->m_locType = InstPointInfo::LocFileLine;
      // TODO use pc to figure out m_file and m_line
      // uchar* pc = (uchar*)it->first;
      m_ips.push_back(ipi);
    }
  }
  InjectionTableSD* tableFEntry =
    proxy.getInjTables()->getSDTable(InstHookTypeFuncEntry);
  if (tableFEntry) {
    for (InjectionTableSD::const_iterator it = tableFEntry->begin();
         it != tableFEntry->end(); ++it) {
      const Injection* inj = it->second;
      InstPointInfoPtr ipi(new InstPointInfo());
      ipi->m_valid = true;
      if (inj->m_desc) {
        ipi->m_desc = inj->m_desc->data();
      }
      ipi->m_func = it->first->data();
      ipi->m_locType = InstPointInfo::LocFuncEntry;
      m_ips.push_back(ipi);
    }
  }
}
Пример #18
0
void CmdNext::onSetup(DebuggerProxy& proxy, CmdInterrupt& interrupt) {
  TRACE(2, "CmdNext::onSetup\n");
  assert(!m_complete); // Complete cmds should not be asked to do work.
  m_stackDepth = proxy.getStackDepth();
  m_vmDepth = g_vmContext->m_nesting;
  m_loc = interrupt.getFileLine();
  ActRec *fp = g_vmContext->getFP();
  assert(fp); // All interrupts which reach a flow cmd have an AR.
  PC pc = g_vmContext->getPC();
  stepCurrentLine(interrupt, fp, pc);
}
Пример #19
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);
}
Пример #20
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);
}
Пример #21
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);
}
Пример #22
0
void CmdNext::onSetup(DebuggerProxy &proxy, CmdInterrupt &interrupt) {
  TRACE(2, "CmdNext::onSetup\n");
  assert(!m_complete); // Complete cmds should not be asked to do work.
  CmdFlowControl::onSetup(proxy, interrupt);
  m_stackDepth = proxy.getStackDepth();
  m_vmDepth = g_vmContext->m_nesting;
  m_loc = interrupt.getFileLine();

  // Start by single-stepping the current line.
  installLocationFilterForLine(interrupt.getSite());
  m_needsVMInterrupt = true;
}
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);
}
Пример #24
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);
}
Пример #25
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);
}
Пример #26
0
void CmdOut::onBeginInterrupt(DebuggerProxy &proxy, CmdInterrupt &interrupt) {
  TRACE(2, "CmdOut::onBeginInterrupt\n");
  assert(!m_complete); // Complete cmds should not be asked to do work.

  m_needsVMInterrupt = false;

  if (m_skippingOverPopR) {
    m_complete = true;
    return;
  }

  int currentVMDepth = g_context->m_nesting;
  int currentStackDepth = proxy.getStackDepth();

  // Deeper or same depth? Keep running.
  if ((currentVMDepth > m_vmDepth) ||
      ((currentVMDepth == m_vmDepth) && (currentStackDepth >= m_stackDepth))) {
    TRACE(2, "CmdOut: deeper, keep running...\n");
    return;
  }

  if (interrupt.getInterruptType() == ExceptionHandler) {
    // If we're about to enter an exception handler we turn interrupts on to
    // ensure we stop when control reaches the handler. The normal logic below
    // will decide if we're done at that point or not.
    TRACE(2, "CmdOut: exception thrown\n");
    removeLocationFilter();
    m_needsVMInterrupt = true;
    return;
  }

  TRACE(2, "CmdOut: shallower stack depth, done.\n");
  cleanupStepOuts();
  int depth = decCount();
  if (depth == 0) {
    PC pc = g_context->getPC();
    // Step over PopR following a call
    if (toOp(*pc) == OpPopR) {
      m_skippingOverPopR = true;
      m_needsVMInterrupt = true;
    } else {
      m_complete = true;
    }
    return;
  } else {
    TRACE(2, "CmdOut: not complete, step out again.\n");
    onSetup(proxy, interrupt);
  }
}
Пример #27
0
void CmdNext::onSetup(DebuggerProxy& proxy, CmdInterrupt& interrupt) {
  TRACE(2, "CmdNext::onSetup\n");
  assertx(!m_complete); // Complete cmds should not be asked to do work.
  m_stackDepth = proxy.getStackDepth();
  m_vmDepth = g_context->m_nesting;
  m_loc = interrupt.getFileLine();
  ActRec *fp = vmfp();
  if (!fp) {
    // If we have no frame just wait for the next instruction to be interpreted.
    m_needsVMInterrupt = true;
    return;
  }
  PC pc = vmpc();
  stepCurrentLine(interrupt, fp, pc);
}
Пример #28
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;
}
Пример #29
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);
}
Пример #30
0
void CmdNext::onBeginInterrupt(DebuggerProxy &proxy, CmdInterrupt &interrupt) {
  TRACE(2, "CmdNext::onBeginInterrupt\n");
  assert(!m_complete); // Complete cmds should not be asked to do work.
  if (interrupt.getInterruptType() == ExceptionThrown) {
    // If an exception is thrown we turn interrupts on to ensure we stop when
    // control reaches the first catch clause.
    removeLocationFilter();
    m_needsVMInterrupt = true;
    return;
  }

  int currentVMDepth = g_vmContext->m_nesting;
  int currentStackDepth = proxy.getStackDepth();

  if ((currentVMDepth < m_vmDepth) ||
      ((currentVMDepth == m_vmDepth) && (currentStackDepth <= m_stackDepth))) {
    // We're at the same depth as when we started, or perhaps even shallower, so
    // there's no need for any step out breakpoint anymore.
    cleanupStepOut();

    if (m_loc != interrupt.getFileLine()) {
      TRACE(2, "CmdNext: same depth, off original line.\n");
      m_complete = (decCount() == 0);
    }
    if (!m_complete) {
      TRACE(2, "CmdNext: not complete, filter new line and keep stepping.\n");
      m_loc = interrupt.getFileLine();
      installLocationFilterForLine(interrupt.getSite());
      m_needsVMInterrupt = true;
    }
  } else {
    // Deeper, so let's setup a step out operation and turn interrupts off.
    if (!m_stepOutUnit) {
      // We can nuke the entire location filter here since we'll re-install it
      // when we get back to the old level. Keeping it installed may be more
      // efficient if we were on a large line, but there is a penalty for every
      // opcode executed while it's installed and that's bad if there's a lot of
      // code called from that line.
      removeLocationFilter();
      setupStepOut();
    }
    m_needsVMInterrupt = false;
  }
}