forked from chromium/chromium
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathaw_microdump_crash_reporter.cc
153 lines (127 loc) · 5.07 KB
/
aw_microdump_crash_reporter.cc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
// Copyright 2015 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 "android_webview/crash_reporter/aw_microdump_crash_reporter.h"
#include "android_webview/common/aw_version_info_values.h"
#include "base/debug/dump_without_crashing.h"
#include "base/files/file_path.h"
#include "base/lazy_instance.h"
#include "base/scoped_native_library.h"
#include "base/synchronization/lock.h"
#include "build/build_config.h"
#include "components/crash/content/app/breakpad_linux.h"
#include "components/crash/content/app/crash_reporter_client.h"
#include "content/public/common/content_switches.h"
namespace android_webview {
namespace crash_reporter {
namespace {
class AwCrashReporterClient : public ::crash_reporter::CrashReporterClient {
public:
AwCrashReporterClient() : dump_fd_(-1), crash_signal_fd_(-1) {}
// Does not use lock, can only be called immediately after creation.
void set_crash_signal_fd(int fd) { crash_signal_fd_ = fd; }
// crash_reporter::CrashReporterClient implementation.
bool IsRunningUnattended() override { return false; }
bool GetCollectStatsConsent() override { return false; }
void GetProductNameAndVersion(const char** product_name,
const char** version) override {
*product_name = "WebView";
*version = PRODUCT_VERSION;
}
// Microdumps are always enabled in WebView builds, conversely to what happens
// in the case of the other Chrome for Android builds (where they are enabled
// only when NO_UNWIND_TABLES == 1).
bool ShouldEnableBreakpadMicrodumps() override { return true; }
int GetAndroidMinidumpDescriptor() override { return dump_fd_; }
int GetAndroidCrashSignalFD() override { return crash_signal_fd_; }
bool DumpWithoutCrashingToFd(int fd) {
DCHECK(dump_fd_ == -1);
base::AutoLock lock(dump_lock_);
dump_fd_ = fd;
base::debug::DumpWithoutCrashing();
dump_fd_ = -1;
return true;
}
private:
int dump_fd_;
int crash_signal_fd_;
base::Lock dump_lock_;
DISALLOW_COPY_AND_ASSIGN(AwCrashReporterClient);
};
base::LazyInstance<AwCrashReporterClient>::Leaky g_crash_reporter_client =
LAZY_INSTANCE_INITIALIZER;
bool g_enabled = false;
#if defined(ARCH_CPU_X86_FAMILY)
bool SafeToUseSignalHandler() {
// On X86/64 there are binary translators that handle SIGSEGV in userspace and
// may get chained after our handler - see http://crbug.com/477444
// We attempt to detect this to work out when it's safe to install breakpad.
// If anything doesn't seem right we assume it's not safe.
// type and mangled name of android::NativeBridgeInitialized
typedef bool (*InitializedFunc)();
const char kInitializedSymbol[] = "_ZN7android23NativeBridgeInitializedEv";
// type and mangled name of android::NativeBridgeGetVersion
typedef uint32_t (*VersionFunc)();
const char kVersionSymbol[] = "_ZN7android22NativeBridgeGetVersionEv";
base::ScopedNativeLibrary lib_native_bridge(
base::FilePath("libnativebridge.so"));
if (!lib_native_bridge.is_valid()) {
DLOG(WARNING) << "Couldn't load libnativebridge";
return false;
}
InitializedFunc NativeBridgeInitialized = reinterpret_cast<InitializedFunc>(
lib_native_bridge.GetFunctionPointer(kInitializedSymbol));
if (NativeBridgeInitialized == nullptr) {
DLOG(WARNING) << "Couldn't tell if native bridge initialized";
return false;
}
if (!NativeBridgeInitialized()) {
// Native process, safe to use breakpad.
return true;
}
VersionFunc NativeBridgeGetVersion = reinterpret_cast<VersionFunc>(
lib_native_bridge.GetFunctionPointer(kVersionSymbol));
if (NativeBridgeGetVersion == nullptr) {
DLOG(WARNING) << "Couldn't get native bridge version";
return false;
}
uint32_t version = NativeBridgeGetVersion();
if (version >= 2) {
// Native bridge at least version 2, safe to use breakpad.
return true;
} else {
DLOG(WARNING) << "Native bridge ver=" << version << "; too low";
return false;
}
}
#endif
} // namespace
void EnableMicrodumpCrashReporter(const std::string& process_type,
int crash_signal_fd) {
if (g_enabled) {
NOTREACHED() << "EnableMicrodumpCrashReporter called more than once";
return;
}
#if defined(ARCH_CPU_X86_FAMILY)
if (!SafeToUseSignalHandler()) {
LOG(WARNING) << "Can't use breakpad to handle WebView crashes";
return;
}
#endif
AwCrashReporterClient* client = g_crash_reporter_client.Pointer();
if (process_type == switches::kRendererProcess && crash_signal_fd != -1) {
client->set_crash_signal_fd(crash_signal_fd);
}
::crash_reporter::SetCrashReporterClient(client);
breakpad::InitMicrodumpCrashHandlerIfNecessary(process_type);
g_enabled = true;
}
void AddGpuFingerprintToMicrodumpCrashHandler(
const std::string& gpu_fingerprint) {
breakpad::AddGpuFingerprintToMicrodumpCrashHandler(gpu_fingerprint);
}
bool DumpWithoutCrashingToFd(int fd) {
return g_crash_reporter_client.Pointer()->DumpWithoutCrashingToFd(fd);
}
} // namespace crash_reporter
} // namespace android_webview