Bug 1196381 - Eliminate breakpad dependency in ThreadStackHelper; r=nfroyd r=snorp
authorJim Chen <nchen@mozilla.com>
Fri, 18 Sep 2015 09:17:10 -0400
changeset 263241 5e86358d4ec223fbaa00177add41c9f33055f827
parent 263240 b2956e60f8255e24a0f5686f19d6cefae382abf4
child 263242 007b7970b6c8e67cdfe88e0a1f75f9e7b6735ce6
push id65250
push usernchen@mozilla.com
push dateFri, 18 Sep 2015 13:17:38 +0000
treeherdermozilla-inbound@e13fd468953b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnfroyd, snorp
bugs1196381, 1069556
milestone43.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1196381 - Eliminate breakpad dependency in ThreadStackHelper; r=nfroyd r=snorp The breakpad dependency in ThreadStackHelper is preventing us from upgrading our in-tree copy to a newer version (bug 1069556). This patch gets rid of that dependency. This makes native stack frames not work for BHR, but because of the ftp.m.o decommissioning, native symbolication was already broken and naive stack frames already don't work, so we don't really lose anything from this patch. Eventually we want to make ThreadStackHelper use other means of unwinding, such as LUL for Linux I added | #if 0 | around the code to fill the thread context, but left the code in because I think we'll evenually want to reuse some of that code.
xpcom/threads/ThreadStackHelper.cpp
xpcom/threads/ThreadStackHelper.h
--- a/xpcom/threads/ThreadStackHelper.cpp
+++ b/xpcom/threads/ThreadStackHelper.cpp
@@ -17,32 +17,16 @@
 #include "mozilla/Attributes.h"
 #include "mozilla/IntegerPrintfMacros.h"
 #include "mozilla/Move.h"
 #include "mozilla/Scoped.h"
 #include "mozilla/UniquePtr.h"
 #include "mozilla/MemoryChecking.h"
 #include "mozilla/Snprintf.h"
 
-#ifdef MOZ_THREADSTACKHELPER_NATIVE
-#include "google_breakpad/processor/call_stack.h"
-#include "google_breakpad/processor/basic_source_line_resolver.h"
-#include "google_breakpad/processor/stack_frame_cpu.h"
-#include "processor/basic_code_module.h"
-#include "processor/basic_code_modules.h"
-#endif
-
-#if defined(MOZ_THREADSTACKHELPER_X86)
-#include "processor/stackwalker_x86.h"
-#elif defined(MOZ_THREADSTACKHELPER_X64)
-#include "processor/stackwalker_amd64.h"
-#elif defined(MOZ_THREADSTACKHELPER_ARM)
-#include "processor/stackwalker_arm.h"
-#endif
-
 #if defined(MOZ_VALGRIND)
 # include <valgrind/valgrind.h>
 #endif
 
 #include <string.h>
 #include <vector>
 #include <cstdlib>
 
@@ -282,77 +266,22 @@ ThreadStackHelper::GetStack(Stack& aStac
   FillThreadContext();
 
   MOZ_ALWAYS_TRUE(::thread_resume(mThreadID) == KERN_SUCCESS);
 
 #endif
 }
 
 #ifdef MOZ_THREADSTACKHELPER_NATIVE
-class ThreadStackHelper::CodeModulesProvider
-  : public google_breakpad::CodeModules
-{
-private:
-  typedef google_breakpad::CodeModule CodeModule;
-  typedef google_breakpad::BasicCodeModule BasicCodeModule;
-
-  const SharedLibraryInfo mLibs;
-  mutable ScopedDeletePtr<BasicCodeModule> mModule;
-
-public:
-  CodeModulesProvider() : mLibs(SharedLibraryInfo::GetInfoForSelf()) {}
-  virtual ~CodeModulesProvider() {}
-
-  virtual unsigned int module_count() const
-  {
-    return mLibs.GetSize();
-  }
-
-  virtual const CodeModule* GetModuleForAddress(uint64_t aAddress) const
-  {
-    MOZ_CRASH("Not implemented");
-  }
-
-  virtual const CodeModule* GetMainModule() const
-  {
-    return nullptr;
-  }
-
-  virtual const CodeModule* GetModuleAtSequence(unsigned int aSequence) const
-  {
-    MOZ_CRASH("Not implemented");
-  }
-
-  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;
-  }
-
-  virtual const CodeModules* Copy() const
-  {
-    MOZ_CRASH("Not implemented");
-  }
-};
-
 class ThreadStackHelper::ThreadContext final
-  : public google_breakpad::MemoryRegion
 {
 public:
-#if defined(MOZ_THREADSTACKHELPER_X86)
-  typedef MDRawContextX86 Context;
-#elif defined(MOZ_THREADSTACKHELPER_X64)
-  typedef MDRawContextAMD64 Context;
-#elif defined(MOZ_THREADSTACKHELPER_ARM)
-  typedef MDRawContextARM Context;
-#endif
+  // TODO: provide per-platform definition of Context.
+  typedef struct {} Context;
+
   // Limit copied stack to 4kB
   static const size_t kMaxStackSize = 0x1000;
   // Limit unwound stack to 32 frames
   static const unsigned int kMaxStackFrames = 32;
   // Whether this structure contains valid data
   bool mValid;
   // Processor context
   Context mContext;
@@ -365,121 +294,33 @@ public:
   // End of stack area
   const void* mStackEnd;
 
   ThreadContext()
     : mValid(false)
     , mStackBase(0)
     , mStackSize(0)
     , mStackEnd(nullptr) {}
-  virtual ~ThreadContext() {}
-
-  virtual uint64_t GetBase() const { return uint64_t(mStackBase); }
-  virtual uint32_t GetSize() const { return mStackSize; }
-  virtual bool GetMemoryAtAddress(uint64_t aAddress, uint8_t* aValue) const
-  {
-    return GetMemoryAtAddressInternal(aAddress, aValue);
-  }
-  virtual bool GetMemoryAtAddress(uint64_t aAddress, uint16_t* aValue) const
-  {
-    return GetMemoryAtAddressInternal(aAddress, aValue);
-  }
-  virtual bool GetMemoryAtAddress(uint64_t aAddress, uint32_t* aValue) const
-  {
-    return GetMemoryAtAddressInternal(aAddress, aValue);
-  }
-  virtual bool GetMemoryAtAddress(uint64_t aAddress, uint64_t* aValue) const
-  {
-    return GetMemoryAtAddressInternal(aAddress, aValue);
-  }
-
-private:
-  template<typename T>
-  bool GetMemoryAtAddressInternal(uint64_t aAddress, T* aValue) const
-  {
-    const intptr_t offset = intptr_t(aAddress) - intptr_t(GetBase());
-    if (offset < 0 || uintptr_t(offset) > (GetSize() - sizeof(T))) {
-      return false;
-    }
-    *aValue = *reinterpret_cast<const T*>(&mStack[offset]);
-    return true;
-  }
 };
 #endif // MOZ_THREADSTACKHELPER_NATIVE
 
 void
 ThreadStackHelper::GetNativeStack(Stack& aStack)
 {
 #ifdef MOZ_THREADSTACKHELPER_NATIVE
   ThreadContext context;
   context.mStack = MakeUnique<uint8_t[]>(ThreadContext::kMaxStackSize);
 
   ScopedSetPtr<ThreadContext> contextPtr(mContextToFill, &context);
 
   // Get pseudostack first and fill the thread context.
   GetStack(aStack);
   NS_ENSURE_TRUE_VOID(context.mValid);
 
-  CodeModulesProvider modulesProvider;
-  google_breakpad::BasicCodeModules modules(&modulesProvider);
-  google_breakpad::BasicSourceLineResolver resolver;
-  google_breakpad::StackFrameSymbolizer symbolizer(nullptr, &resolver);
-
-#if defined(MOZ_THREADSTACKHELPER_X86)
-  google_breakpad::StackwalkerX86 stackWalker(
-    nullptr, &context.mContext, &context, &modules, &symbolizer);
-#elif defined(MOZ_THREADSTACKHELPER_X64)
-  google_breakpad::StackwalkerAMD64 stackWalker(
-    nullptr, &context.mContext, &context, &modules, &symbolizer);
-#elif defined(MOZ_THREADSTACKHELPER_ARM)
-  google_breakpad::StackwalkerARM stackWalker(
-    nullptr, &context.mContext, -1, &context, &modules, &symbolizer);
-#else
-  #error "Unsupported architecture"
-#endif
-
-  google_breakpad::CallStack callStack;
-  std::vector<const google_breakpad::CodeModule*> modules_without_symbols;
-
-  google_breakpad::Stackwalker::set_max_frames(ThreadContext::kMaxStackFrames);
-  google_breakpad::Stackwalker::
-    set_max_frames_scanned(ThreadContext::kMaxStackFrames);
-
-  NS_ENSURE_TRUE_VOID(stackWalker.Walk(&callStack, &modules_without_symbols));
-
-  const std::vector<google_breakpad::StackFrame*>& frames(*callStack.frames());
-  for (intptr_t i = frames.size() - 1; i >= 0; i--) {
-    const google_breakpad::StackFrame& frame = *frames[i];
-    if (!frame.module) {
-      continue;
-    }
-    const string& module = frame.module->code_file();
-#if defined(XP_LINUX) || defined(XP_MACOSX)
-    const char PATH_SEP = '/';
-#elif defined(XP_WIN)
-    const char PATH_SEP = '\\';
-#endif
-    const char* const module_basename = strrchr(module.c_str(), PATH_SEP);
-    const char* const module_name = module_basename ?
-                                    module_basename + 1 : module.c_str();
-
-    char buffer[0x100];
-    size_t len = 0;
-    if (!frame.function_name.empty()) {
-      len = snprintf_literal(buffer, "%s:%s",
-                             module_name, frame.function_name.c_str());
-    } else {
-      len = snprintf_literal(buffer, "%s:0x%p", module_name,
-                             (intptr_t)(frame.instruction -
-                                          frame.module->base_address()));
-    }
-    if (len) {
-      aStack.AppendViaBuffer(buffer, len);
-    }
-  }
+  // TODO: walk the saved stack frames.
 #endif // MOZ_THREADSTACKHELPER_NATIVE
 }
 
 #ifdef XP_LINUX
 
 int ThreadStackHelper::sInitialized;
 int ThreadStackHelper::sFillStackSignum;
 
@@ -702,16 +543,17 @@ ThreadStackHelper::FillStackBuffer()
 MOZ_ASAN_BLACKLIST void
 ThreadStackHelper::FillThreadContext(void* aContext)
 {
 #ifdef MOZ_THREADSTACKHELPER_NATIVE
   if (!mContextToFill) {
     return;
   }
 
+#if 0 // TODO: remove dependency on Breakpad structs.
 #if defined(XP_LINUX)
   const ucontext_t& context = *reinterpret_cast<ucontext_t*>(aContext);
 #if defined(MOZ_THREADSTACKHELPER_X86)
   mContextToFill->mContext.context_flags = MD_CONTEXT_X86_FULL;
   mContextToFill->mContext.edi = context.uc_mcontext.gregs[REG_EDI];
   mContextToFill->mContext.esi = context.uc_mcontext.gregs[REG_ESI];
   mContextToFill->mContext.ebx = context.uc_mcontext.gregs[REG_EBX];
   mContextToFill->mContext.edx = context.uc_mcontext.gregs[REG_EDX];
@@ -859,12 +701,13 @@ ThreadStackHelper::FillThreadContext(voi
   for (intptr_t len = stackSize; len > 0; len -= sizeof(*src)) {
     *(dst++) = *(src++);
   }
 #endif
 
   mContextToFill->mStackBase = uintptr_t(sp);
   mContextToFill->mStackSize = stackSize;
   mContextToFill->mValid = true;
+#endif
 #endif // MOZ_THREADSTACKHELPER_NATIVE
 }
 
 } // namespace mozilla
--- a/xpcom/threads/ThreadStackHelper.h
+++ b/xpcom/threads/ThreadStackHelper.h
@@ -61,17 +61,16 @@ class ThreadStackHelper
 public:
   typedef Telemetry::HangStack Stack;
 
 private:
   Stack* mStackToFill;
 #ifdef MOZ_THREADSTACKHELPER_PSEUDO
   const PseudoStack* const mPseudoStack;
 #ifdef MOZ_THREADSTACKHELPER_NATIVE
-  class CodeModulesProvider;
   class ThreadContext;
   // Set to non-null if GetStack should get the thread context.
   ThreadContext* mContextToFill;
   intptr_t mThreadStackBase;
 #endif
   size_t mMaxStackSize;
   size_t mMaxBufferSize;
 #endif