Bug 1378442 - Move Win64 profiler hooks to profiler_start. r=mstange
authorDavid Major <dmajor@mozilla.com>
Wed, 05 Jul 2017 18:45:31 -0400
changeset 367551 a199c96110ca7116ae45e5f97ddaab7ad8dd10f7
parent 367550 092cf837ffea606ba5c7129566596ce9cb706a30
child 367552 7a401b1e5f9854a1b49f567374d380e3e0e1100a
push id32137
push usercbook@mozilla.com
push dateThu, 06 Jul 2017 09:18:21 +0000
treeherdermozilla-central@018b3829d0a7 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmstange
bugs1378442
milestone56.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 1378442 - Move Win64 profiler hooks to profiler_start. r=mstange
mozglue/build/WindowsDllBlocklist.cpp
tools/profiler/core/platform-win32.cpp
tools/profiler/core/platform.cpp
--- a/mozglue/build/WindowsDllBlocklist.cpp
+++ b/mozglue/build/WindowsDllBlocklist.cpp
@@ -774,48 +774,16 @@ continue_loading:
   // Prevent the stack walker from suspending this thread when LdrLoadDll
   // holds the RtlLookupFunctionEntry lock.
   AutoSuppressStackWalking suppress;
 #endif
 
   return stub_LdrLoadDll(filePath, flags, moduleFileName, handle);
 }
 
-#ifdef _M_AMD64
-typedef NTSTATUS (NTAPI *LdrUnloadDll_func)(HMODULE module);
-static LdrUnloadDll_func stub_LdrUnloadDll;
-
-static NTSTATUS NTAPI
-patched_LdrUnloadDll(HMODULE module)
-{
-  // Prevent the stack walker from suspending this thread when LdrUnloadDll
-  // holds the RtlLookupFunctionEntry lock.
-  AutoSuppressStackWalking suppress;
-  return stub_LdrUnloadDll(module);
-}
-
-// These pointers are disguised as PVOID to avoid pulling in obscure headers
-typedef PVOID (WINAPI *LdrResolveDelayLoadedAPI_func)(PVOID ParentModuleBase,
-  PVOID DelayloadDescriptor, PVOID FailureDllHook, PVOID FailureSystemHook,
-  PVOID ThunkAddress, ULONG Flags);
-static LdrResolveDelayLoadedAPI_func stub_LdrResolveDelayLoadedAPI;
-
-static PVOID WINAPI patched_LdrResolveDelayLoadedAPI(PVOID ParentModuleBase,
-  PVOID DelayloadDescriptor, PVOID FailureDllHook, PVOID FailureSystemHook,
-  PVOID ThunkAddress, ULONG Flags)
-{
-  // Prevent the stack walker from suspending this thread when
-  // LdrResolveDelayLoadAPI holds the RtlLookupFunctionEntry lock.
-  AutoSuppressStackWalking suppress;
-  return stub_LdrResolveDelayLoadedAPI(ParentModuleBase, DelayloadDescriptor,
-                                       FailureDllHook, FailureSystemHook,
-                                       ThunkAddress, Flags);
-}
-#endif
-
 #ifdef _M_IX86
 static bool
 ShouldBlockThread(void* aStartAddress)
 {
   // Allows crashfirefox.exe to continue to work. Also if your threadproc is null, this crash is intentional.
   if (aStartAddress == 0)
     return false;
 
@@ -885,24 +853,16 @@ DllBlocklist_Initialize(uint32_t aInitFl
 #ifdef DEBUG
     printf_stderr("LdrLoadDll hook failed, no dll blocklisting active\n");
 #endif
   }
 
   Kernel32Intercept.Init("kernel32.dll");
 
 #ifdef _M_AMD64
-  NtDllIntercept.AddHook("LdrUnloadDll",
-                         reinterpret_cast<intptr_t>(patched_LdrUnloadDll),
-                         (void**)&stub_LdrUnloadDll);
-  if (IsWin8OrLater()) { // LdrResolveDelayLoadedAPI was introduced in Win8
-    NtDllIntercept.AddHook("LdrResolveDelayLoadedAPI",
-                           reinterpret_cast<intptr_t>(patched_LdrResolveDelayLoadedAPI),
-                           (void**)&stub_LdrResolveDelayLoadedAPI);
-  }
   if (!IsWin8OrLater()) {
     // The crash that this hook works around is only seen on Win7.
     Kernel32Intercept.AddHook("RtlInstallFunctionTableCallback",
                               reinterpret_cast<intptr_t>(patched_RtlInstallFunctionTableCallback),
                               (void**)&stub_RtlInstallFunctionTableCallback);
   }
 #endif
 
--- a/tools/profiler/core/platform-win32.cpp
+++ b/tools/profiler/core/platform-win32.cpp
@@ -27,16 +27,20 @@
 // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 // OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 // SUCH DAMAGE.
 
 #include <windows.h>
 #include <mmsystem.h>
 #include <process.h>
 
+#include "nsWindowsDllInterceptor.h"
+#include "mozilla/StackWalk_windows.h"
+#include "mozilla/WindowsVersion.h"
+
 /* static */ Thread::tid_t
 Thread::GetCurrentId()
 {
   return GetCurrentThreadId();
 }
 
 static void
 PopulateRegsFromContext(Registers& aRegs, CONTEXT* aContext)
@@ -277,8 +281,63 @@ void
 Registers::SyncPopulate()
 {
   CONTEXT context;
   RtlCaptureContext(&context);
   PopulateRegsFromContext(*this, &context);
 }
 #endif
 
+#if defined(GP_PLAT_amd64_windows)
+static WindowsDllInterceptor NtDllIntercept;
+
+typedef NTSTATUS (NTAPI *LdrUnloadDll_func)(HMODULE module);
+static LdrUnloadDll_func stub_LdrUnloadDll;
+
+static NTSTATUS NTAPI
+patched_LdrUnloadDll(HMODULE module)
+{
+  // Prevent the stack walker from suspending this thread when LdrUnloadDll
+  // holds the RtlLookupFunctionEntry lock.
+  AutoSuppressStackWalking suppress;
+  return stub_LdrUnloadDll(module);
+}
+
+// These pointers are disguised as PVOID to avoid pulling in obscure headers
+typedef PVOID (WINAPI *LdrResolveDelayLoadedAPI_func)(PVOID ParentModuleBase,
+  PVOID DelayloadDescriptor, PVOID FailureDllHook, PVOID FailureSystemHook,
+  PVOID ThunkAddress, ULONG Flags);
+static LdrResolveDelayLoadedAPI_func stub_LdrResolveDelayLoadedAPI;
+
+static PVOID WINAPI
+patched_LdrResolveDelayLoadedAPI(PVOID ParentModuleBase,
+  PVOID DelayloadDescriptor, PVOID FailureDllHook, PVOID FailureSystemHook,
+  PVOID ThunkAddress, ULONG Flags)
+{
+  // Prevent the stack walker from suspending this thread when
+  // LdrResolveDelayLoadAPI holds the RtlLookupFunctionEntry lock.
+  AutoSuppressStackWalking suppress;
+  return stub_LdrResolveDelayLoadedAPI(ParentModuleBase, DelayloadDescriptor,
+                                       FailureDllHook, FailureSystemHook,
+                                       ThunkAddress, Flags);
+}
+
+void
+InitializeWin64ProfilerHooks()
+{
+  static bool initialized = false;
+  if (initialized) {
+    return;
+  }
+  initialized = true;
+
+  NtDllIntercept.Init("ntdll.dll");
+  NtDllIntercept.AddHook("LdrUnloadDll",
+                         reinterpret_cast<intptr_t>(patched_LdrUnloadDll),
+                         (void**)&stub_LdrUnloadDll);
+  if (IsWin8OrLater()) { // LdrResolveDelayLoadedAPI was introduced in Win8
+    NtDllIntercept.AddHook("LdrResolveDelayLoadedAPI",
+                           reinterpret_cast<intptr_t>(patched_LdrResolveDelayLoadedAPI),
+                           (void**)&stub_LdrResolveDelayLoadedAPI);
+  }
+}
+#endif // defined(GP_PLAT_amd64_windows)
+
--- a/tools/profiler/core/platform.cpp
+++ b/tools/profiler/core/platform.cpp
@@ -2418,16 +2418,20 @@ locked_profiler_start(PSLockRef aLock, i
 
     for (uint32_t i = 0; i < aFilterCount; i++) {
       LOG("- threads  = %s", aFilters[i]);
     }
   }
 
   MOZ_RELEASE_ASSERT(CorePS::Exists() && !ActivePS::Exists(aLock));
 
+#if defined(GP_PLAT_amd64_windows)
+  InitializeWin64ProfilerHooks();
+#endif
+
   // Fall back to the default values if the passed-in values are unreasonable.
   int entries = aEntries > 0 ? aEntries : PROFILER_DEFAULT_ENTRIES;
   double interval = aInterval > 0 ? aInterval : PROFILER_DEFAULT_INTERVAL;
 
   ActivePS::Create(aLock, entries, interval, aFeatures, aFilters, aFilterCount);
 
   // Set up profiling for each registered thread, if appropriate.
   Thread::tid_t tid = Thread::GetCurrentId();