Esempio n. 1
0
void
TelemetryImpl::RecordChromeHang(uint32_t duration,
                                const Telemetry::HangStack &callStack,
                                SharedLibraryInfo &moduleMap)
{
  MOZ_ASSERT(sTelemetry);
  if (!sTelemetry->mCanRecord) {
    return;
  }

  MutexAutoLock hangReportMutex(sTelemetry->mHangReportsMutex);

  // Only report the modules which changed since the first hang report
  if (sTelemetry->mHangReports.Length()) {
    SharedLibraryInfo &firstModuleMap =
      sTelemetry->mHangReports[0].moduleMap;
    for (size_t i = 0; i < moduleMap.GetSize(); ++i) {
      if (firstModuleMap.Contains(moduleMap.GetEntry(i))) {
        moduleMap.RemoveEntries(i, i + 1);
        --i;
      }
    }
  }

  HangReport newReport = { duration, callStack, moduleMap };
  sTelemetry->mHangReports.AppendElement(newReport);
}
Esempio n. 2
0
static void
GetChromeHangReport(Telemetry::HangStack &callStack, SharedLibraryInfo &moduleMap)
{
  MOZ_ASSERT(winMainThreadHandle);

  DWORD ret = ::SuspendThread(winMainThreadHandle);
  if (ret == -1) {
    callStack.Clear();
    moduleMap.Clear();
    return;
  }
  NS_StackWalk(ChromeStackWalker, 0, &callStack,
               reinterpret_cast<uintptr_t>(winMainThreadHandle));
  ret = ::ResumeThread(winMainThreadHandle);
  if (ret == -1) {
    callStack.Clear();
    moduleMap.Clear();
    return;
  }

  moduleMap = SharedLibraryInfo::GetInfoForSelf();
  moduleMap.SortByAddress();

  // Remove all modules not referenced by a PC on the stack
  Telemetry::HangStack sortedStack = callStack;
  sortedStack.Sort();

  size_t moduleIndex = 0;
  size_t stackIndex = 0;
  bool unreferencedModule = true;
  while (stackIndex < sortedStack.Length() && moduleIndex < moduleMap.GetSize()) {
    uintptr_t pc = sortedStack[stackIndex];
    SharedLibrary& module = moduleMap.GetEntry(moduleIndex);
    uintptr_t moduleStart = module.GetStart();
    uintptr_t moduleEnd = module.GetEnd() - 1;
    if (moduleStart <= pc && pc <= moduleEnd) {
      // If the current PC is within the current module, mark module as used
      unreferencedModule = false;
      ++stackIndex;
    } else if (pc > moduleEnd) {
      if (unreferencedModule) {
        // Remove module if no PCs within its address range
        moduleMap.RemoveEntries(moduleIndex, moduleIndex + 1);
      } else {
        // Module was referenced on stack, but current PC belongs to later module
        unreferencedModule = true;
        ++moduleIndex;
      }
    } else {
      // PC does not belong to any module
      ++stackIndex;
    }
  }

  // Clean up remaining unreferenced modules, i.e. module addresses > max(pc)
  if (moduleIndex + 1 < moduleMap.GetSize()) {
    moduleMap.RemoveEntries(moduleIndex + 1, moduleMap.GetSize());
  }
}
 virtual const CodeModule* GetModuleAtIndex(unsigned int aIndex) const
 {
   const SharedLibrary& lib = mLibs.GetEntry(aIndex);
   mModule = new BasicCodeModule(lib.GetStart(), lib.GetEnd() - lib.GetStart(),
                                 lib.GetName(), lib.GetBreakpadId(),
                                 lib.GetName(), lib.GetBreakpadId(), "");
   // Keep mModule valid until the next GetModuleAtIndex call.
   return mModule;
 }
Esempio n. 4
0
std::string
GetSharedLibraryInfoString()
{
  SharedLibraryInfo info = SharedLibraryInfo::GetInfoForSelf();
  if (info.GetSize() == 0)
    return "[]";

  std::ostringstream os;
  os << "[";
  AddSharedLibraryInfoToStream(os, info.GetEntry(0));

  for (size_t i = 1; i < info.GetSize(); i++) {
    os << ",";
    AddSharedLibraryInfoToStream(os, info.GetEntry(i));
  }

  os << "]";
  return os.str();
}