Bug 1286802 - Part 3: Add empty set_include_context_heap() implementation to ExceptionHandler and CrashGenerationServer. r?ted draft
authorCervantes Yu <cyu@mozilla.com>
Thu, 30 Mar 2017 17:56:08 +0800
changeset 580336 c21afd250116ccdd8bcd486475a07837b556bf31
parent 580335 fafe58b23541df4d76494cfea60a168ac4fc4d3a
child 580337 726c57c2a35b6a3d1efc0ee7196de4ae259e2b8d
push id59519
push usercyu@mozilla.com
push dateThu, 18 May 2017 11:09:20 +0000
reviewersted
bugs1286802
milestone55.0a1
Bug 1286802 - Part 3: Add empty set_include_context_heap() implementation to ExceptionHandler and CrashGenerationServer. r?ted MozReview-Commit-ID: 5GBzvyvNPDa
modules/libpref/init/all.js
toolkit/crashreporter/breakpad-client/windows/crash_generation/crash_generation_server.cc
toolkit/crashreporter/breakpad-client/windows/crash_generation/crash_generation_server.h
toolkit/crashreporter/breakpad-client/windows/handler/exception_handler.cc
toolkit/crashreporter/breakpad-client/windows/handler/exception_handler.h
toolkit/crashreporter/nsExceptionHandler.cpp
toolkit/crashreporter/nsExceptionHandler.h
toolkit/xre/nsAppRunner.cpp
--- a/modules/libpref/init/all.js
+++ b/modules/libpref/init/all.js
@@ -5713,8 +5713,16 @@ pref("fuzzing.enabled", false);
 // to do that.
 pref("layers.advanced.border-layers", 2);
 pref("layers.advanced.boxshadow-inset-layers", 2);
 pref("layers.advanced.boxshadow-outer-layers", 2);
 pref("layers.advanced.caret-layers", 2);
 pref("layers.advanced.displaybuttonborder-layers", 2);
 pref("layers.advanced.outline-layers", 2);
 pref("layers.advanced.solid-color-layers", 2);
+
+// When a crash happens, whether to include heap regions of the crash context
+// in the minidump. Enabled by default on nightly and aurora.
+#ifdef RELEASE_OR_BETA
+pref("toolkit.crashreporter.include_context_heap", false);
+#else
+pref("toolkit.crashreporter.include_context_heap", true);
+#endif
--- a/toolkit/crashreporter/breakpad-client/windows/crash_generation/crash_generation_server.cc
+++ b/toolkit/crashreporter/breakpad-client/windows/crash_generation/crash_generation_server.cc
@@ -121,17 +121,18 @@ CrashGenerationServer::CrashGenerationSe
       upload_request_callback_(upload_request_callback),
       upload_context_(upload_context),
       generate_dumps_(generate_dumps),
       pre_fetch_custom_info_(true),
       dump_path_(dump_path ? *dump_path : L""),
       server_state_(IPC_SERVER_STATE_UNINITIALIZED),
       shutting_down_(false),
       overlapped_(),
-      client_info_(NULL) {
+      client_info_(NULL),
+      include_context_heap_(false) {
   InitializeCriticalSection(&sync_);
 }
 
 // This should never be called from the OnPipeConnected callback.
 // Otherwise the UnregisterWaitEx call below will cause a deadlock.
 CrashGenerationServer::~CrashGenerationServer() {
   // New scope to release the lock automatically.
   {
@@ -891,16 +892,21 @@ void CrashGenerationServer::HandleDumpRe
   if (dump_callback_ && execute_callback) {
     std::wstring* ptr_dump_path = (dump_path == L"") ? NULL : &dump_path;
     dump_callback_(dump_context_, &client_info, ptr_dump_path);
   }
 
   SetEvent(client_info.dump_generated_handle());
 }
 
+void CrashGenerationServer::set_include_context_heap(bool enabled) {
+
+  include_context_heap_ = enabled;
+}
+
 bool CrashGenerationServer::GenerateDump(const ClientInfo& client,
                                          std::wstring* dump_path) {
   assert(client.pid() != 0);
   assert(client.process_handle());
 
   // We have to get the address of EXCEPTION_INFORMATION from
   // the client process address space.
   EXCEPTION_POINTERS* client_ex_info = NULL;
--- a/toolkit/crashreporter/breakpad-client/windows/crash_generation/crash_generation_server.h
+++ b/toolkit/crashreporter/breakpad-client/windows/crash_generation/crash_generation_server.h
@@ -101,16 +101,21 @@ class CrashGenerationServer {
   //
   // Returns true if initialization is successful; false otherwise.
   bool Start();
 
   void pre_fetch_custom_info(bool do_pre_fetch) {
     pre_fetch_custom_info_ = do_pre_fetch;
   }
 
+  // Calling set_include_context_heap(true) causes heap regions to be included
+  // in the minidump when a crash happens. The heap regions are from the
+  // register values of the client crashing context.
+  void set_include_context_heap(bool enabled);
+
  private:
   // Various states the client can be in during the handshake with
   // the server.
   enum IPCServerState {
     // Server starts in this state.
     IPC_SERVER_STATE_UNINITIALIZED,
 
     // Server is in error state and it cannot serve any clients.
@@ -284,16 +289,19 @@ class CrashGenerationServer {
   OVERLAPPED overlapped_;
 
   // Message object used in IPC with the client.
   ProtocolMessage msg_;
 
   // Client Info for the client that's connecting to the server.
   ClientInfo* client_info_;
 
+  // Whether to include heap regions of the crashing context.
+  bool include_context_heap_;
+
   // Disable copy ctor and operator=.
   CrashGenerationServer(const CrashGenerationServer& crash_server);
   CrashGenerationServer& operator=(const CrashGenerationServer& crash_server);
 };
 
 }  // namespace google_breakpad
 
 #endif  // CLIENT_WINDOWS_CRASH_GENERATION_CRASH_GENERATION_SERVER_H__
--- a/toolkit/crashreporter/breakpad-client/windows/handler/exception_handler.cc
+++ b/toolkit/crashreporter/breakpad-client/windows/handler/exception_handler.cc
@@ -274,16 +274,18 @@ void ExceptionHandler::Initialize(
       previous_iph_ = _set_invalid_parameter_handler(HandleInvalidParameter);
 #endif  // _MSC_VER >= 1400
 
     if (handler_types & HANDLER_PURECALL)
       previous_pch_ = _set_purecall_handler(HandlePureVirtualCall);
 
     LeaveCriticalSection(&handler_stack_critical_section_);
   }
+
+  include_context_heap_ = false;
 }
 
 ExceptionHandler::~ExceptionHandler() {
   if (dbghelp_module_) {
     FreeLibrary(dbghelp_module_);
   }
 
   if (rpcrt4_module_) {
@@ -1021,9 +1023,13 @@ void ExceptionHandler::RegisterAppMemory
 void ExceptionHandler::UnregisterAppMemory(void* ptr) {
   AppMemoryList::iterator iter =
     std::find(app_memory_info_.begin(), app_memory_info_.end(), ptr);
   if (iter != app_memory_info_.end()) {
     app_memory_info_.erase(iter);
   }
 }
 
+void ExceptionHandler::set_include_context_heap(bool enabled) {
+  include_context_heap_ = enabled;
+}
+
 }  // namespace google_breakpad
--- a/toolkit/crashreporter/breakpad-client/windows/handler/exception_handler.h
+++ b/toolkit/crashreporter/breakpad-client/windows/handler/exception_handler.h
@@ -262,16 +262,21 @@ class ExceptionHandler {
   // Returns whether out-of-process dump generation is used or not.
   bool IsOutOfProcess() const { return crash_generation_client_.get() != NULL; }
 
   // Calling RegisterAppMemory(p, len) causes len bytes starting
   // at address p to be copied to the minidump when a crash happens.
   void RegisterAppMemory(void* ptr, size_t length);
   void UnregisterAppMemory(void* ptr);
 
+  // Calling set_include_context_heap(true) causes heap regions to be included
+  // in the minidump when a crash happens. The heap regions are from the
+  // register values of the crashing context.
+  void set_include_context_heap(bool enabled);
+
  private:
   friend class AutoExceptionHandler;
 
   // Initializes the instance with given values.
   void Initialize(const wstring& dump_path,
                   FilterCallback filter,
                   MinidumpCallback callback,
                   void* callback_context,
@@ -485,16 +490,18 @@ class ExceptionHandler {
   // handler_stack_critical_section_ guards operations on handler_stack_ and
   // handler_stack_index_. The critical section is initialized by the
   // first instance of the class and destroyed by the last instance of it.
   static CRITICAL_SECTION handler_stack_critical_section_;
 
   // The number of instances of this class.
   static volatile LONG instance_count_;
 
+  bool include_context_heap_;
+
   // disallow copy ctor and operator=
   explicit ExceptionHandler(const ExceptionHandler &);
   void operator=(const ExceptionHandler &);
 };
 
 }  // namespace google_breakpad
 
 #pragma warning(pop)
--- a/toolkit/crashreporter/nsExceptionHandler.cpp
+++ b/toolkit/crashreporter/nsExceptionHandler.cpp
@@ -255,16 +255,19 @@ static nsCString* crashEventAPIData = nu
 static nsCString* notesField = nullptr;
 static bool isGarbageCollecting;
 static uint32_t eventloopNestingLevel = 0;
 
 // Avoid a race during application termination.
 static Mutex* dumpSafetyLock;
 static bool isSafeToDump = false;
 
+// Whether to include heap regions of the crash context.
+static bool sIncludeContextHeap = false;
+
 // OOP crash reporting
 static CrashGenerationServer* crashServer; // chrome process has this
 
 static std::terminate_handler oldTerminateHandler = nullptr;
 
 #if (defined(XP_MACOSX) || defined(XP_WIN))
 // This field is valid in both chrome and content processes.
 static xpstring* childProcessTmpDir = nullptr;
@@ -1803,16 +1806,19 @@ nsresult SetExceptionHandler(nsIFile* aX
 #endif // XP_WIN32
 
   if (!gExceptionHandler)
     return NS_ERROR_OUT_OF_MEMORY;
 
 #ifdef XP_WIN
   gExceptionHandler->set_handle_debug_exceptions(true);
 
+  // Initially set sIncludeContextHeap to true for debugging startup crashes
+  // even if the controlling pref value is false.
+  SetIncludeContextHeap(true);
 #ifdef _WIN64
   // Tell JS about the new filter before we disable SetUnhandledExceptionFilter
   SetJitExceptionHandler();
 #endif
 
   // protect the crash reporter from being unloaded
   gBlockUnhandledExceptionFilter = true;
   gKernel32Intercept.Init("kernel32.dll");
@@ -2470,16 +2476,27 @@ nsresult UnregisterAppMemory(void* ptr)
 #if defined(XP_LINUX) || defined(XP_WIN32)
   gExceptionHandler->UnregisterAppMemory(ptr);
   return NS_OK;
 #else
   return NS_ERROR_NOT_IMPLEMENTED;
 #endif
 }
 
+void SetIncludeContextHeap(bool aValue)
+{
+  sIncludeContextHeap = aValue;
+
+#ifdef XP_WIN
+  if (gExceptionHandler) {
+    gExceptionHandler->set_include_context_heap(sIncludeContextHeap);
+  }
+#endif
+}
+
 bool GetServerURL(nsACString& aServerURL)
 {
   if (!gExceptionHandler)
     return false;
 
   return GetAnnotation(NS_LITERAL_CSTRING("ServerURL"), aServerURL);
 }
 
@@ -3548,16 +3565,20 @@ OOPInit()
     nullptr,                    // default security attributes
     nullptr, nullptr,           // we don't care about process connect here
     OnChildProcessDumpRequested, nullptr,
     nullptr, nullptr,           // we don't care about process exit here
     nullptr, nullptr,           // we don't care about upload request here
     true,                       // automatically generate dumps
     &dumpPath);
 
+  if (sIncludeContextHeap) {
+    crashServer->set_include_context_heap(sIncludeContextHeap);
+  }
+
 #elif defined(XP_LINUX)
   if (!CrashGenerationServer::CreateReportChannel(&serverSocketFd,
                                                   &clientSocketFd))
     MOZ_CRASH("can't create crash reporter socketpair()");
 
   const std::string dumpPath =
       gExceptionHandler->minidump_descriptor().directory();
   crashServer = new CrashGenerationServer(
--- a/toolkit/crashreporter/nsExceptionHandler.h
+++ b/toolkit/crashreporter/nsExceptionHandler.h
@@ -88,16 +88,19 @@ nsresult SetRestartArgs(int argc, char**
 nsresult SetupExtraData(nsIFile* aAppDataDirectory,
                         const nsACString& aBuildID);
 bool GetLastRunCrashID(nsAString& id);
 
 // Registers an additional memory region to be included in the minidump
 nsresult RegisterAppMemory(void* ptr, size_t length);
 nsresult UnregisterAppMemory(void* ptr);
 
+// Include heap regions of the crash context.
+void SetIncludeContextHeap(bool aValue);
+
 // Functions for working with minidumps and .extras
 typedef nsDataHashtable<nsCStringHashKey, nsCString> AnnotationTable;
 
 void DeleteMinidumpFilesForID(const nsAString& id);
 bool GetMinidumpForID(const nsAString& id, nsIFile** minidump);
 bool GetIDFromMinidump(nsIFile* minidump, nsAString& id);
 bool GetExtraFileForID(const nsAString& id, nsIFile** extraFile);
 bool GetExtraFileForMinidump(nsIFile* minidump, nsIFile** extraFile);
--- a/toolkit/xre/nsAppRunner.cpp
+++ b/toolkit/xre/nsAppRunner.cpp
@@ -4257,16 +4257,20 @@ XREMain::XRE_mainRun()
     }
   }
   // Needs to be set after xpcom initialization.
   CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("FramePoisonBase"),
                                      nsPrintfCString("%.16" PRIu64, uint64_t(gMozillaPoisonBase)));
   CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("FramePoisonSize"),
                                      nsPrintfCString("%" PRIu32, uint32_t(gMozillaPoisonSize)));
 
+  bool includeContextHeap =
+    Preferences::GetBool("toolkit.crashreporter.include_context_heap", false);
+  CrashReporter::SetIncludeContextHeap(includeContextHeap);
+
 #ifdef XP_WIN
   PR_CreateThread(PR_USER_THREAD, AnnotateSystemManufacturer_ThreadStart, 0,
                   PR_PRIORITY_LOW, PR_GLOBAL_THREAD, PR_UNJOINABLE_THREAD, 0);
 #endif
 
 #if defined(XP_LINUX) && !defined(ANDROID)
   PR_CreateThread(PR_USER_THREAD, AnnotateLSBRelease, 0, PR_PRIORITY_LOW,
                   PR_GLOBAL_THREAD, PR_UNJOINABLE_THREAD, 0);