Bug 775378 - Trap exception handling calls to __abi_FailFast made by winrt delegate wrapper code. r=ted
authorJim Mathies <jmathies@mozilla.com>
Mon, 23 Jul 2012 16:11:45 -0500
changeset 100226 b4571293e6bd9fb35d71e9e806ca81b269bab74a
parent 100225 f872ba0b17cab118c8218a1371e957bc65bae273
child 100227 d42b966e4262266231d470445e1256d4efe5ef6f
push id12387
push userjmathies@mozilla.com
push dateMon, 23 Jul 2012 21:11:53 +0000
treeherdermozilla-inbound@b4571293e6bd [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersted
bugs775378
milestone17.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 775378 - Trap exception handling calls to __abi_FailFast made by winrt delegate wrapper code. r=ted
toolkit/library/nsDllMain.cpp
--- a/toolkit/library/nsDllMain.cpp
+++ b/toolkit/library/nsDllMain.cpp
@@ -1,16 +1,17 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  
 #include <windows.h>
 #include <delayimp.h>
 #include "nsToolkit.h"
+#include "mozilla/Assertions.h"
 
 #if defined(__GNUC__)
 // If DllMain gets name mangled, it won't be seen.
 extern "C" {
 #endif
 
 BOOL APIENTRY DllMain(  
                       HINSTANCE hModule, 
@@ -46,16 +47,26 @@ BOOL APIENTRY DllMain(
  * the compiler bakes auto-generated code into our binary, including a c init-
  * ializer which inits the winrt library through a call into the winrt standard
  * lib 'vccorlib'. Vccorlib in turn has system dll dependencies which are only
  * available on Win8 (currently API-MS-WIN-CORE-WINRT and
  * API-MS-WIN-CORE-WINRT-STRING), which prevent xul.dll from loading on os <=
  * Win7. To get around this we generate a dummy vccore lib with the three entry
  * points the initializer needs and load it in place of the real vccorlib. We
  * also have to add vccorlib and the system dlls to the delay load list.
+ *
+ * In addition to setting up dummyvccorlib, we also have additional checks for
+ * for unexpected behavior, specifically:
+ * - trap attempts to load entry points in dummyvccorlib. This is not expected
+ *   to happen in release code. It can happen during development if winrt apis
+ *   are accessed when running on the desktop, or when winrt objects are
+ *   accidentially placed in the global scope.
+ * - trap and handle calls to vccorlib's __abi_FailFast in a breakpad compatible
+ *   way. __abi_FailFast is called by exception handling code generated by the
+ *   compiler for delegate events.
  */
 static bool IsWin8OrHigher()
 {
   static PRInt32 version = 0;
 
   if (version) {
     return (version >= 0x602);
   }
@@ -66,39 +77,57 @@ static bool IsWin8OrHigher()
   ::GetVersionEx((OSVERSIONINFO*)&osInfo);
   version =
     (osInfo.dwMajorVersion & 0xff) << 8 | (osInfo.dwMinorVersion & 0xff);
   return (version >= 0x602);
 }
 
 const char* kvccorlib = "vccorlib";
 const char* kwinrtprelim = "api-ms-win-core-winrt";
+const char* kfailfast = "?__abi_FailFast";
+
+static bool IsWinRTDLLNotPresent(PDelayLoadInfo pdli, const char* aLibToken)
+{
+  return (!IsWin8OrHigher() && pdli->szDll &&
+          !strnicmp(pdli->szDll, aLibToken, strlen(aLibToken)));
+}
 
 static bool IsWinRTDLLPresent(PDelayLoadInfo pdli, const char* aLibToken)
 {
-  return (!IsWin8OrHigher() && pdli->szDll &&
+  return (IsWin8OrHigher() && pdli->szDll &&
           !strnicmp(pdli->szDll, aLibToken, strlen(aLibToken)));
 }
 
+void __stdcall __abi_MozFailFast()
+{
+  MOZ_CRASH();
+}
+
 FARPROC WINAPI DelayDllLoadHook(unsigned dliNotify, PDelayLoadInfo pdli)
 {
   if (dliNotify == dliNotePreLoadLibrary) {
-    if (IsWinRTDLLPresent(pdli, kvccorlib)) {
+    if (IsWinRTDLLNotPresent(pdli, kvccorlib)) {
       return (FARPROC)LoadLibraryA("dummyvccorlib.dll");
     }
-    NS_ASSERTION(!IsWinRTDLLPresent(pdli, kwinrtprelim),
+    NS_ASSERTION(!IsWinRTDLLNotPresent(pdli, kwinrtprelim),
       "Attempting to load winrt libs in non-metro environment. "
       "(Winrt variable type placed in global scope?)");
   }
-  if (dliNotify == dliFailGetProc && IsWinRTDLLPresent(pdli, kvccorlib)) {
+  if (dliNotify == dliFailGetProc && IsWinRTDLLNotPresent(pdli, kvccorlib)) {
     NS_WARNING("Attempting to access winrt vccorlib entry point in non-metro environment.");
     NS_WARNING(pdli->szDll);
     NS_WARNING(pdli->dlp.szProcName);
     NS_ABORT();
   }
+  if (dliNotify == dliNotePreGetProcAddress &&
+      IsWinRTDLLPresent(pdli, kvccorlib) &&
+      pdli->dlp.szProcName &&
+      !strnicmp(pdli->dlp.szProcName, kfailfast, strlen(kfailfast))) {
+    return (FARPROC)__abi_MozFailFast;
+  }
   return NULL;
 }
 
 ExternC PfnDliHook __pfnDliNotifyHook2 = DelayDllLoadHook;
 ExternC PfnDliHook __pfnDliFailureHook2 = DelayDllLoadHook;
 
 #endif // MOZ_METRO