Index: chrome_elf/crash/crash_helper.cc |
diff --git a/chrome_elf/chrome_elf_main.cc b/chrome_elf/crash/crash_helper.cc |
similarity index 52% |
copy from chrome_elf/chrome_elf_main.cc |
copy to chrome_elf/crash/crash_helper.cc |
index 1a125f0cdb6c0cbf061e132a1050f18e1a1fe8bb..21dddcb00931f0248b06b7eb2850b73ee4c08012 100644 |
--- a/chrome_elf/chrome_elf_main.cc |
+++ b/chrome_elf/crash/crash_helper.cc |
@@ -1,39 +1,34 @@ |
-// Copyright 2013 The Chromium Authors. All rights reserved. |
+// Copyright 2016 The Chromium Authors. All rights reserved. |
// Use of this source code is governed by a BSD-style license that can be |
// found in the LICENSE file. |
-#include "chrome_elf/chrome_elf_main.h" |
+#include "chrome_elf/crash/crash_helper.h" |
+#include <assert.h> |
#include <windows.h> |
+ |
#include <algorithm> |
+#include <string> |
+#include <vector> |
-#include "base/lazy_instance.h" |
-#include "base/strings/string16.h" |
-#include "base/win/iat_patch_function.h" |
-#include "build/build_config.h" |
#include "chrome/app/chrome_crash_reporter_client_win.h" |
-#include "chrome/install_static/install_util.h" |
-#include "chrome_elf/blacklist/blacklist.h" |
-#include "chrome_elf/blacklist/crashpad_helper.h" |
-#include "chrome_elf/chrome_elf_constants.h" |
+#include "chrome_elf/hook_util/hook_util.h" |
#include "components/crash/content/app/crashpad.h" |
#include "components/crash/core/common/crash_keys.h" |
+#include "third_party/crashpad/crashpad/client/crashpad_client.h" |
namespace { |
-base::LazyInstance<std::vector<crash_reporter::Report>>::Leaky g_crash_reports = |
- LAZY_INSTANCE_INITIALIZER; |
- |
// Gets the exe name from the full path of the exe. |
-base::string16 GetExeName() { |
+std::wstring GetExeName() { |
wchar_t file_path[MAX_PATH] = {}; |
- if (!::GetModuleFileName(nullptr, file_path, arraysize(file_path))) { |
+ if (!::GetModuleFileNameW(nullptr, file_path, MAX_PATH)) { |
assert(false); |
- return base::string16(); |
+ return std::wstring(); |
} |
- base::string16 file_name_string = file_path; |
+ std::wstring file_name_string = file_path; |
robertshield
2016/08/02 02:38:40
You can save a copy here like this:
std::wstring
penny
2016/08/02 21:07:43
Done.
|
size_t last_slash_pos = file_name_string.find_last_of(L'\\'); |
- if (last_slash_pos != base::string16::npos) { |
+ if (last_slash_pos != std::wstring::npos) { |
file_name_string = file_name_string.substr( |
last_slash_pos + 1, file_name_string.length() - last_slash_pos); |
} |
@@ -42,12 +37,10 @@ base::string16 GetExeName() { |
return file_name_string; |
} |
-void InitializeCrashReportingForProcess() { |
- // We want to initialize crash reporting only in chrome.exe |
- if (GetExeName() != L"chrome.exe") |
- return; |
- ChromeCrashReporterClient::InitializeCrashReportingForProcess(); |
-} |
+// Global pointer to a vector of crash reports. |
+// This structure will be initialized in InitializeCrashReportingForProcess() |
+// and cleaned up in DllDetachCrashReportingCleanup(). |
+std::vector<crash_reporter::Report>* g_crash_reports = nullptr; |
// chrome_elf loads early in the process and initializes Crashpad. That in turn |
// uses the SetUnhandledExceptionFilter API to set a top level exception |
@@ -63,39 +56,84 @@ void InitializeCrashReportingForProcess() { |
// TODO(ananta). |
// Check if it is possible to fix EAT patching or use sidestep patching for |
// 32 bit and 64 bit for this purpose. |
-base::win::IATPatchFunction g_set_unhandled_exception_filter; |
+elf_hook::IATHook g_set_unhandled_exception_filter; |
+// Hook function, which ignores the request to set an unhandled-exception |
+// filter. |
LPTOP_LEVEL_EXCEPTION_FILTER WINAPI |
SetUnhandledExceptionFilterPatch(LPTOP_LEVEL_EXCEPTION_FILTER filter) { |
// Don't set the exception filter. Please see above for comments. |
return nullptr; |
} |
+} // namespace |
+ |
+//------------------------------------------------------------------------------ |
+// Public chrome_elf crash APIs |
+//------------------------------------------------------------------------------ |
+ |
+namespace elf_crash { |
+ |
+void InitializeCrashReportingForProcess() { |
+ // We want to initialize crash reporting only in chrome.exe |
+ if (GetExeName() != L"chrome.exe") { |
+#ifdef _DEBUG |
+ assert(false); |
+#endif // _DEBUG |
+ return; |
+ } |
+ |
robertshield
2016/08/02 02:38:40
Could you also assert in debug mode that g_crash_r
penny
2016/08/02 21:07:43
Done.
|
+ // No global objects with destructors, so using a global pointer. |
+ // DllMain on detach will clean this up. |
+ g_crash_reports = new std::vector<crash_reporter::Report>; |
+ |
+ ChromeCrashReporterClient::InitializeCrashReportingForProcess(); |
+} |
+ |
+// NOTE: This function will be called from DllMain during DLL_PROCESS_DETACH |
+// (while we have the loader lock), so do not misbehave. |
robertshield
2016/08/02 02:38:40
This comment also applies to InitializeCrashReport
penny
2016/08/02 21:07:43
Done.
|
+void DllDetachCrashReportingCleanup() { |
+ if (g_crash_reports != nullptr) { |
+ g_crash_reports->clear(); |
+ delete g_crash_reports; |
+ } |
+} |
+ |
// Please refer above to more information about why we intercept the |
robertshield
2016/08/02 02:38:40
specify to refer to the comment on g_set_unhandled
penny
2016/08/02 21:07:43
Done.
|
// SetUnhandledExceptionFilter API. |
void DisableSetUnhandledExceptionFilter() { |
- DWORD patched = g_set_unhandled_exception_filter.PatchFromModule( |
- GetModuleHandle(nullptr), "kernel32.dll", "SetUnhandledExceptionFilter", |
- SetUnhandledExceptionFilterPatch); |
- CHECK(patched == 0); |
+ if (g_set_unhandled_exception_filter.Hook( |
+ GetModuleHandle(nullptr), "kernel32.dll", |
+ "SetUnhandledExceptionFilter", |
+ SetUnhandledExceptionFilterPatch) != NO_ERROR) { |
+#ifdef _DEBUG |
+ assert(false); |
+#endif //_DEBUG |
+ } |
} |
-} // namespace |
- |
-void SignalChromeElf() { |
- blacklist::ResetBeacon(); |
+int GenerateCrashDump(EXCEPTION_POINTERS* exception_pointers) { |
+ crashpad::CrashpadClient::DumpWithoutCrash( |
+ *(exception_pointers->ContextRecord)); |
+ return EXCEPTION_CONTINUE_SEARCH; |
} |
+} // namespace elf_crash |
+ |
+//------------------------------------------------------------------------------ |
+// Exported crash APIs for the rest of the process. |
+//------------------------------------------------------------------------------ |
+ |
// This helper is invoked by code in chrome.dll to retrieve the crash reports. |
-// See CrashUploadListCrashpad. Note that we do not pass an std::vector here, |
+// See CrashUploadListCrashpad. Note that we do not pass a std::vector here, |
// because we do not want to allocate/free in different modules. The returned |
// pointer is read-only. |
extern "C" __declspec(dllexport) void GetCrashReportsImpl( |
const crash_reporter::Report** reports, |
size_t* report_count) { |
- crash_reporter::GetReports(g_crash_reports.Pointer()); |
- *reports = g_crash_reports.Pointer()->data(); |
- *report_count = g_crash_reports.Pointer()->size(); |
+ crash_reporter::GetReports(g_crash_reports); |
+ *reports = g_crash_reports->data(); |
+ *report_count = g_crash_reports->size(); |
} |
// This helper is invoked by debugging code in chrome to register the client |
@@ -105,21 +143,3 @@ extern "C" __declspec(dllexport) void SetMetricsClientId( |
if (client_id) |
crash_keys::SetMetricsClientIdFromGUID(client_id); |
} |
- |
-BOOL APIENTRY DllMain(HMODULE module, DWORD reason, LPVOID reserved) { |
- if (reason == DLL_PROCESS_ATTACH) { |
- InitializeCrashReportingForProcess(); |
- // CRT on initialization installs an exception filter which calls |
- // TerminateProcess. We need to hook CRT's attempt to set an exception |
- // handler and ignore it. |
- DisableSetUnhandledExceptionFilter(); |
- |
- install_static::InitializeProcessType(); |
- |
- __try { |
- blacklist::Initialize(false); // Don't force, abort if beacon is present. |
- } __except(GenerateCrashDump(GetExceptionInformation())) { |
- } |
- } |
- return TRUE; |
-} |