Bug 1270686. Log all dlls ever loaded. r=aklotz
☠☠ backed out by e15b4b4184eb ☠ ☠
authorJeff Muizelaar <jmuizelaar@mozilla.com>
Wed, 25 May 2016 03:42:08 -0400
changeset 337910 15359139459812abed51ce740a819624f1d8de2d
parent 337909 56b15c2f02c32803d161fe1e7c6b49033ff98a43
child 337911 8465a41d5bff393a45fc3ecae64b06c4f02ae236
push id6249
push userjlund@mozilla.com
push dateMon, 01 Aug 2016 13:59:36 +0000
treeherdermozilla-beta@bad9d4f5bf7e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersaklotz
bugs1270686
milestone49.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 1270686. Log all dlls ever loaded. r=aklotz This is a temporary patch to try to figure out if a dll is being unloaded that we still need.
mozglue/build/WindowsDllBlocklist.cpp
mozglue/build/WindowsDllBlocklist.h
mozglue/build/moz.build
toolkit/crashreporter/nsExceptionHandler.cpp
toolkit/crashreporter/test/unit/test_crashreporter_crash.js
--- a/mozglue/build/WindowsDllBlocklist.cpp
+++ b/mozglue/build/WindowsDllBlocklist.cpp
@@ -12,20 +12,23 @@
 #define MALLOC_DECL(name, return_type, ...) \
   extern "C" MOZ_MEMORY_API return_type name ## _impl(__VA_ARGS__);
 #include "malloc_decls.h"
 #endif
 
 #include <windows.h>
 #include <winternl.h>
 #include <io.h>
+#define PSAPI_VERSION 1
+#include <psapi.h>
 
 #pragma warning( push )
 #pragma warning( disable : 4275 4530 ) // See msvc-stl-wrapper.template.h
 #include <map>
+#include <vector>
 #pragma warning( pop )
 
 #include "nsAutoPtr.h"
 
 #include "nsWindowsDllInterceptor.h"
 #include "mozilla/UniquePtr.h"
 #include "mozilla/WindowsVersion.h"
 #include "nsWindowsHelpers.h"
@@ -538,21 +541,25 @@ static wchar_t* lastslash(wchar_t* s, in
   for (wchar_t* c = s + len - 1; c >= s; --c) {
     if (*c == L'\\' || *c == L'/') {
       return c;
     }
   }
   return nullptr;
 }
 
+#ifdef NIGHTLY_BUILD
+static std::vector<DllLoadInfo> gDllLoadInfos;
+static LoadCallBackFn gLoadInfoCallback;
+#endif
+
 static NTSTATUS NTAPI
 patched_LdrLoadDll (PWCHAR filePath, PULONG flags, PUNICODE_STRING moduleFileName, PHANDLE handle)
 {
   // We have UCS2 (UTF16?), we want ASCII, but we also just want the filename portion
-#define DLLNAME_MAX 128
   char dllName[DLLNAME_MAX+1];
   wchar_t *dll_part;
   char *dot;
   DllBlockInfo *info;
 
   int len = moduleFileName->Length / 2;
   wchar_t *fname = moduleFileName->Buffer;
   UniquePtr<wchar_t[]> full_fname;
@@ -730,24 +737,50 @@ continue_loading:
       return STATUS_DLL_NOT_FOUND;
     }
 
     if (IsVistaOrLater() && !CheckASLR(full_fname.get())) {
       printf_stderr("LdrLoadDll: Blocking load of '%s'.  XPCOM components must support ASLR.\n", dllName);
       return STATUS_DLL_NOT_FOUND;
     }
   }
-
-  return stub_LdrLoadDll(filePath, flags, moduleFileName, handle);
+  NTSTATUS ret = stub_LdrLoadDll(filePath, flags, moduleFileName, handle);
+#ifdef NIGHTLY_BUILD
+  if (!ret) {
+      MODULEINFO moduleInfo;
+      if (GetModuleInformation(GetCurrentProcess(), *(HMODULE*)handle, &moduleInfo, sizeof(moduleInfo))) {
+          DllLoadInfo info;
+          strcpy(info.name, dllName);
+          info.lpBaseOfDll = moduleInfo.lpBaseOfDll;
+          info.SizeOfImage = moduleInfo.SizeOfImage;
+          if (gLoadInfoCallback) {
+            gLoadInfoCallback(info);
+          } else {
+            gDllLoadInfos.push_back(info);
+          }
+      }
+  }
+#endif
+  return ret;
 }
 
 WindowsDllInterceptor NtDllIntercept;
 
 } // namespace
 
+#ifdef NIGHTLY_BUILD
+MFBT_API void
+RegisterDllLoadCallback(LoadCallBackFn aCallback) {
+  gLoadInfoCallback = aCallback;
+  for (DllLoadInfo &info : gDllLoadInfos) {
+    aCallback(info);
+  }
+}
+#endif
+
 MFBT_API void
 DllBlocklist_Initialize()
 {
 #if defined(_MSC_VER) && _MSC_VER < 1900 && defined(_M_X64)
   // The code below is not blocklist-related, but is the best place for it.
   // This is the earliest place where msvcr120.dll is loaded, and this
   // codepath is used by both firefox.exe and plugin-container.exe processes.
 
--- a/mozglue/build/WindowsDllBlocklist.h
+++ b/mozglue/build/WindowsDllBlocklist.h
@@ -29,10 +29,22 @@ class MOZ_RAII AutoSetXPCOMLoadOnMainThr
     ~AutoSetXPCOMLoadOnMainThread() {
       DllBlocklist_SetInXPCOMLoadOnMainThread(false);
     }
 
   private:
     MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
 };
 
+#define DLLNAME_MAX 128
+#ifdef NIGHTLY_BUILD
+struct DllLoadInfo
+{
+  char name[DLLNAME_MAX+1];
+  LPVOID lpBaseOfDll;
+  DWORD SizeOfImage;
+};
+typedef void (*LoadCallBackFn)(DllLoadInfo&);
+MFBT_API void RegisterDllLoadCallback(LoadCallBackFn);
+#endif // NIGHTLY_BUILD
+
 #endif // defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_X64))
 #endif // mozilla_windowsdllblocklist_h
--- a/mozglue/build/moz.build
+++ b/mozglue/build/moz.build
@@ -47,16 +47,17 @@ if not CONFIG['JS_STANDALONE']:
         LOCAL_INCLUDES += [
             '/memory/build',
         ]
         SOURCES += [
             'WindowsDllBlocklist.cpp',
         ]
         DISABLE_STL_WRAPPING = True
         OS_LIBS += [
+            'psapi',
             'version',
         ]
 
     if CONFIG['MOZ_NUWA_PROCESS']:
         EXPORTS.ipc += [
             'Nuwa.h',
         ]
         SOURCES += [
--- a/toolkit/crashreporter/nsExceptionHandler.cpp
+++ b/toolkit/crashreporter/nsExceptionHandler.cpp
@@ -1432,16 +1432,27 @@ ChildFilter(void* context)
 {
   bool result = Filter(context);
   if (result) {
     PrepareChildExceptionTimeAnnotations();
   }
   return result;
 }
 
+#if defined(XP_WIN) && defined(NIGHTLY_BUILD)
+static void DllLoadCallback(DllLoadInfo& info)
+{
+  nsAutoCString note;
+  note.AppendPrintf("%s-%p-%x\n", info.name, info.lpBaseOfDll, info.SizeOfImage);
+
+  CrashReporter::AppendAppNotesToCrashReport(note);
+}
+#endif
+
+
 nsresult SetExceptionHandler(nsIFile* aXREDirectory,
                              bool force/*=false*/)
 {
   if (gExceptionHandler)
     return NS_ERROR_ALREADY_INITIALIZED;
 
 #if !defined(DEBUG) || defined(MOZ_WIDGET_GONK)
   // In non-debug builds, enable the crash reporter by default, and allow
@@ -1669,16 +1680,20 @@ nsresult SetExceptionHandler(nsIFile* aX
                                       library_mappings[i].start_address,
                                       library_mappings[i].length,
                                       library_mappings[i].file_offset);
   }
 #endif
 
   mozalloc_set_oom_abort_handler(AnnotateOOMAllocationSize);
 
+#if defined(XP_WIN) && defined(NIGHTLY_BUILD)
+  RegisterDllLoadCallback(DllLoadCallback);
+#endif
+
   return NS_OK;
 }
 
 bool GetEnabled()
 {
   return gExceptionHandler != nullptr;
 }
 
--- a/toolkit/crashreporter/test/unit/test_crashreporter_crash.js
+++ b/toolkit/crashreporter/test/unit/test_crashreporter_crash.js
@@ -40,12 +40,15 @@ function run_test()
              // TelemetrySession setup will trigger the session annotation
              let scope = {};
              Components.utils.import("resource://gre/modules/TelemetryController.jsm", scope);
              scope.TelemetryController.testSetup();
            },
            function(mdump, extra) {
              do_check_eq(extra.TestKey, "TestValue");
              do_check_eq(extra["\u2665"], "\u{1F4A9}");
-             do_check_eq(extra.Notes, "JunkMoreJunk");
+             // we spam the crash dumps with dlls loading so temporarily disable
+             // this check on windows
+             if (!is_windows)
+               do_check_eq(extra.Notes, "JunkMoreJunk");
              do_check_true(!("TelemetrySessionId" in extra));
            });
 }