| OLD | NEW | 
|---|
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be | 
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. | 
| 4 | 4 | 
| 5 #include "chrome_elf/chrome_elf_main.h" | 5 #include "chrome_elf/chrome_elf_main.h" | 
| 6 | 6 | 
|  | 7 #include <assert.h> | 
| 7 #include <windows.h> | 8 #include <windows.h> | 
| 8 #include <algorithm> |  | 
| 9 | 9 | 
| 10 #include "base/lazy_instance.h" |  | 
| 11 #include "base/strings/string16.h" |  | 
| 12 #include "base/win/iat_patch_function.h" |  | 
| 13 #include "build/build_config.h" |  | 
| 14 #include "chrome/app/chrome_crash_reporter_client_win.h" |  | 
| 15 #include "chrome/install_static/install_util.h" | 10 #include "chrome/install_static/install_util.h" | 
| 16 #include "chrome_elf/blacklist/blacklist.h" | 11 #include "chrome_elf/blacklist/blacklist.h" | 
| 17 #include "chrome_elf/blacklist/crashpad_helper.h" | 12 #include "chrome_elf/crash/crash_helper.h" | 
| 18 #include "chrome_elf/chrome_elf_constants.h" |  | 
| 19 #include "components/crash/content/app/crashpad.h" |  | 
| 20 #include "components/crash/core/common/crash_keys.h" |  | 
| 21 |  | 
| 22 namespace { |  | 
| 23 |  | 
| 24 base::LazyInstance<std::vector<crash_reporter::Report>>::Leaky g_crash_reports = |  | 
| 25     LAZY_INSTANCE_INITIALIZER; |  | 
| 26 |  | 
| 27 #if !defined(ADDRESS_SANITIZER) |  | 
| 28 // chrome_elf loads early in the process and initializes Crashpad. That in turn |  | 
| 29 // uses the SetUnhandledExceptionFilter API to set a top level exception |  | 
| 30 // handler for the process. When the process eventually initializes, CRT sets |  | 
| 31 // an exception handler which calls TerminateProcess which effectively bypasses |  | 
| 32 // us. Ideally we want to be at the top of the unhandled exception filter |  | 
| 33 // chain. However we don't have a good way of intercepting the |  | 
| 34 // SetUnhandledExceptionFilter API in the sandbox. EAT patching kernel32 or |  | 
| 35 // kernelbase should ideally work. However the kernel32 kernelbase dlls are |  | 
| 36 // prebound which causes EAT patching to not work. Sidestep works. However it |  | 
| 37 // is only supported for 32 bit. For now we use IAT patching for the |  | 
| 38 // executable. |  | 
| 39 // TODO(ananta). |  | 
| 40 // Check if it is possible to fix EAT patching or use sidestep patching for |  | 
| 41 // 32 bit and 64 bit for this purpose. |  | 
| 42 base::win::IATPatchFunction g_set_unhandled_exception_filter; |  | 
| 43 |  | 
| 44 LPTOP_LEVEL_EXCEPTION_FILTER WINAPI |  | 
| 45 SetUnhandledExceptionFilterPatch(LPTOP_LEVEL_EXCEPTION_FILTER filter) { |  | 
| 46   // Don't set the exception filter. Please see above for comments. |  | 
| 47   return nullptr; |  | 
| 48 } |  | 
| 49 |  | 
| 50 // Please refer above to more information about why we intercept the |  | 
| 51 // SetUnhandledExceptionFilter API. |  | 
| 52 void DisableSetUnhandledExceptionFilter() { |  | 
| 53   DWORD patched = g_set_unhandled_exception_filter.PatchFromModule( |  | 
| 54       GetModuleHandle(nullptr), "kernel32.dll", "SetUnhandledExceptionFilter", |  | 
| 55       SetUnhandledExceptionFilterPatch); |  | 
| 56   CHECK(patched == 0); |  | 
| 57 } |  | 
| 58 #endif // !defined(ADDRESS_SANITIZER) |  | 
| 59 |  | 
| 60 }  // namespace |  | 
| 61 | 13 | 
| 62 void SignalChromeElf() { | 14 void SignalChromeElf() { | 
| 63   blacklist::ResetBeacon(); | 15   blacklist::ResetBeacon(); | 
| 64 } | 16 } | 
| 65 | 17 | 
| 66 // This helper is invoked by code in chrome.dll to retrieve the crash reports. |  | 
| 67 // See CrashUploadListCrashpad. Note that we do not pass an std::vector here, |  | 
| 68 // because we do not want to allocate/free in different modules. The returned |  | 
| 69 // pointer is read-only. |  | 
| 70 extern "C" __declspec(dllexport) void GetCrashReportsImpl( |  | 
| 71     const crash_reporter::Report** reports, |  | 
| 72     size_t* report_count) { |  | 
| 73   crash_reporter::GetReports(g_crash_reports.Pointer()); |  | 
| 74   *reports = g_crash_reports.Pointer()->data(); |  | 
| 75   *report_count = g_crash_reports.Pointer()->size(); |  | 
| 76 } |  | 
| 77 |  | 
| 78 // This helper is invoked by debugging code in chrome to register the client |  | 
| 79 // id. |  | 
| 80 extern "C" __declspec(dllexport) void SetMetricsClientId( |  | 
| 81     const char* client_id) { |  | 
| 82   if (client_id) |  | 
| 83     crash_keys::SetMetricsClientIdFromGUID(client_id); |  | 
| 84 } |  | 
| 85 |  | 
| 86 BOOL APIENTRY DllMain(HMODULE module, DWORD reason, LPVOID reserved) { | 18 BOOL APIENTRY DllMain(HMODULE module, DWORD reason, LPVOID reserved) { | 
| 87   if (reason == DLL_PROCESS_ATTACH) { | 19   if (reason == DLL_PROCESS_ATTACH) { | 
| 88     ChromeCrashReporterClient::InitializeCrashReportingForProcess(); | 20     if (!elf_crash::InitializeCrashReporting()) { | 
| 89     // CRT on initialization installs an exception filter which calls | 21 #ifdef _DEBUG | 
| 90     // TerminateProcess. We need to hook CRT's attempt to set an exception | 22       assert(false); | 
| 91     // handler and ignore it. Don't do this when ASan is present, or ASan will | 23 #endif  // _DEBUG | 
| 92     // fail to install its own unhandled exception filter. | 24     } | 
|  | 25 // CRT on initialization installs an exception filter which calls | 
|  | 26 // TerminateProcess. We need to hook CRT's attempt to set an exception. | 
|  | 27 // NOTE: Do not hook if ASan is present, or ASan will fail to install | 
|  | 28 // its own unhandled exception filter. | 
| 93 #if !defined(ADDRESS_SANITIZER) | 29 #if !defined(ADDRESS_SANITIZER) | 
| 94     DisableSetUnhandledExceptionFilter(); | 30     elf_crash::DisableSetUnhandledExceptionFilter(); | 
| 95 #endif | 31 #endif  // !defined (ADDRESS_SANITIZER) | 
| 96 | 32 | 
| 97     install_static::InitializeProcessType(); | 33     install_static::InitializeProcessType(); | 
| 98 | 34 | 
| 99     __try { | 35     __try { | 
| 100       blacklist::Initialize(false);  // Don't force, abort if beacon is present. | 36       blacklist::Initialize(false);  // Don't force, abort if beacon is present. | 
| 101     } __except(GenerateCrashDump(GetExceptionInformation())) { | 37     } __except (elf_crash::GenerateCrashDump(GetExceptionInformation())) { | 
| 102     } | 38     } | 
|  | 39   } else if (reason == DLL_PROCESS_DETACH) { | 
|  | 40     elf_crash::ShutdownCrashReporting(); | 
| 103   } | 41   } | 
| 104   return TRUE; | 42   return TRUE; | 
| 105 } | 43 } | 
| OLD | NEW | 
|---|