mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-24 05:11:16 +00:00
Bug 1307153 - Add stack traces to the crash pings in Fennec; r=jchen,ted.mielczarek
MozReview-Commit-ID: ZJKUwHFsuK --HG-- extra : amend_source : 9a57ff1d2cf15391f1f30fa63585220adbb1a49b
This commit is contained in:
parent
9abec85212
commit
f167c2f3e8
@ -29,6 +29,8 @@ import java.util.zip.GZIPOutputStream;
|
||||
|
||||
import org.mozilla.gecko.AppConstants.Versions;
|
||||
import org.mozilla.gecko.GeckoProfile;
|
||||
import org.mozilla.gecko.mozglue.GeckoLoader;
|
||||
import org.mozilla.gecko.mozglue.MinidumpAnalyzer;
|
||||
import org.mozilla.gecko.telemetry.pingbuilders.TelemetryCrashPingBuilder;
|
||||
import org.mozilla.gecko.telemetry.TelemetryDispatcher;
|
||||
import org.mozilla.gecko.util.INIParser;
|
||||
@ -153,7 +155,20 @@ public class CrashReporter extends AppCompatActivity
|
||||
mPendingExtrasFile = new File(pendingDir, extrasFile.getName());
|
||||
moveFile(extrasFile, mPendingExtrasFile);
|
||||
|
||||
// Compute the minidump hash and generate the stack traces
|
||||
computeMinidumpHash(mPendingExtrasFile, mPendingMinidumpFile);
|
||||
|
||||
try {
|
||||
GeckoLoader.loadMozGlue(this);
|
||||
|
||||
if (!MinidumpAnalyzer.GenerateStacks(mPendingMinidumpFile.getPath(), /* fullStacks */ false)) {
|
||||
Log.e(LOGTAG, "Could not generate stacks for this minidump: " + passedMinidumpPath);
|
||||
}
|
||||
} catch (UnsatisfiedLinkError e) {
|
||||
Log.e(LOGTAG, "Could not load libmozglue.so, stacks for this crash won't be generated");
|
||||
}
|
||||
|
||||
// Extract the annotations from the .extra file
|
||||
mExtrasStringMap = new HashMap<String, String>();
|
||||
readStringsFromFile(mPendingExtrasFile.getPath(), mExtrasStringMap);
|
||||
|
||||
|
@ -0,0 +1,31 @@
|
||||
/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
|
||||
* 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/. */
|
||||
|
||||
package org.mozilla.gecko.mozglue;
|
||||
|
||||
/**
|
||||
* JNI wrapper for accessing the minidump analyzer tool. This is used to
|
||||
* generate stack traces and other process information from a crash minidump.
|
||||
*/
|
||||
public final class MinidumpAnalyzer {
|
||||
private MinidumpAnalyzer() {
|
||||
// prevent instantiation
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate the stacks from the minidump file specified in minidumpPath
|
||||
* and adds the StackTraces annotation to the associated .extra file.
|
||||
* If fullStacks is false then only the stack trace for the crashing thread
|
||||
* will be generated, otherwise stacks will be generated for all threads.
|
||||
*
|
||||
* This JNI method is implemented in mozglue/android/nsGeckoUtils.cpp.
|
||||
*
|
||||
* @param minidumpPath The path to the minidump file to be analyzed.
|
||||
* @param fullStacks Specifies if stacks must be generated for all threads.
|
||||
* @return <code>true</code> if the operation was successful,
|
||||
* <code>false</code> otherwise.
|
||||
*/
|
||||
public static native boolean GenerateStacks(String minidumpPath, boolean fullStacks);
|
||||
}
|
@ -18,6 +18,15 @@ SOURCES += [
|
||||
'SQLiteBridge.cpp',
|
||||
]
|
||||
|
||||
if CONFIG['MOZ_CRASHREPORTER']:
|
||||
USE_LIBS += [
|
||||
'minidump-analyzer',
|
||||
]
|
||||
|
||||
LOCAL_INCLUDES += [
|
||||
'/toolkit/crashreporter/minidump-analyzer',
|
||||
]
|
||||
|
||||
FINAL_LIBRARY = 'mozglue'
|
||||
|
||||
for var in ('ANDROID_PACKAGE_NAME',
|
||||
|
@ -11,6 +11,10 @@
|
||||
#include "Zip.h"
|
||||
#include "mozilla/RefPtr.h"
|
||||
|
||||
#ifdef MOZ_CRASHREPORTER
|
||||
# include "minidump-analyzer.h"
|
||||
#endif
|
||||
|
||||
extern "C"
|
||||
__attribute__ ((visibility("default")))
|
||||
void MOZ_JNICALL
|
||||
@ -138,3 +142,21 @@ Java_org_mozilla_gecko_mozglue_NativeZip__1getInputStream(JNIEnv *jenv, jobject
|
||||
// other Native -> Java call doesn't happen before returning to Java.
|
||||
return jenv->CallObjectMethod(jzip, method, buf, (jint) stream.GetType());
|
||||
}
|
||||
|
||||
#ifdef MOZ_CRASHREPORTER
|
||||
|
||||
extern "C"
|
||||
__attribute__ ((visibility("default")))
|
||||
jboolean MOZ_JNICALL
|
||||
Java_org_mozilla_gecko_mozglue_MinidumpAnalyzer_GenerateStacks(JNIEnv *jenv, jclass, jstring minidumpPath, jboolean fullStacks)
|
||||
{
|
||||
const char* str;
|
||||
str = jenv->GetStringUTFChars(minidumpPath, nullptr);
|
||||
|
||||
bool res = CrashReporter::GenerateStacks(str, fullStacks);
|
||||
|
||||
jenv->ReleaseStringUTFChars(minidumpPath, str);
|
||||
return res;
|
||||
}
|
||||
|
||||
#endif // MOZ_CRASHREPORTER
|
||||
|
@ -125,25 +125,6 @@ UTF8toMBCS(const std::string &inp) {
|
||||
|
||||
#endif // XP_WIN
|
||||
|
||||
// Check if a file exists at the specified path
|
||||
|
||||
static inline bool
|
||||
FileExists(const std::string& aPath)
|
||||
{
|
||||
#if defined(XP_WIN)
|
||||
DWORD attrs = GetFileAttributes(UTF8ToWide(aPath).c_str());
|
||||
return (attrs != INVALID_FILE_ATTRIBUTES);
|
||||
#else // Non-Windows
|
||||
struct stat sb;
|
||||
int ret = stat(aPath.c_str(), &sb);
|
||||
if (ret == -1 || !(sb.st_mode & S_IFREG)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
#endif // XP_WIN
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace CrashReporter
|
||||
|
||||
#endif // MinidumpAnalyzerUtils_h
|
||||
|
@ -3,6 +3,8 @@
|
||||
* 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 "minidump-analyzer.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <fstream>
|
||||
@ -232,7 +234,8 @@ ConvertModulesToJSON(const ProcessState& aProcessState,
|
||||
// crash, the module list and stack traces for every thread
|
||||
|
||||
static void
|
||||
ConvertProcessStateToJSON(const ProcessState& aProcessState, Json::Value& aRoot)
|
||||
ConvertProcessStateToJSON(const ProcessState& aProcessState, Json::Value& aRoot,
|
||||
const bool aFullStacks)
|
||||
{
|
||||
// We use this map to get the index of a module when listed by address
|
||||
OrderedModulesMap orderedModules;
|
||||
@ -249,8 +252,7 @@ ConvertProcessStateToJSON(const ProcessState& aProcessState, Json::Value& aRoot)
|
||||
// Record the crashing thread index only if this is a full minidump
|
||||
// and all threads' stacks are present, otherwise only the crashing
|
||||
// thread stack is written out and this field is set to 0.
|
||||
crashInfo["crashing_thread"] =
|
||||
gMinidumpAnalyzerOptions.fullMinidump ? requestingThread : 0;
|
||||
crashInfo["crashing_thread"] = aFullStacks ? requestingThread : 0;
|
||||
}
|
||||
} else {
|
||||
crashInfo["type"] = Json::Value(Json::nullValue);
|
||||
@ -278,7 +280,7 @@ ConvertProcessStateToJSON(const ProcessState& aProcessState, Json::Value& aRoot)
|
||||
Json::Value threads(Json::arrayValue);
|
||||
int threadCount = aProcessState.threads()->size();
|
||||
|
||||
if (!gMinidumpAnalyzerOptions.fullMinidump && (requestingThread != -1)) {
|
||||
if (!aFullStacks && (requestingThread != -1)) {
|
||||
// Only add the crashing thread
|
||||
Json::Value thread;
|
||||
Json::Value stack(Json::arrayValue);
|
||||
@ -306,7 +308,7 @@ ConvertProcessStateToJSON(const ProcessState& aProcessState, Json::Value& aRoot)
|
||||
// the node specified in |aRoot|
|
||||
|
||||
static bool
|
||||
ProcessMinidump(Json::Value& aRoot, const string& aDumpFile) {
|
||||
ProcessMinidump(Json::Value& aRoot, const string& aDumpFile, const bool aFullStacks) {
|
||||
#if XP_WIN && HAVE_64BIT_BUILD
|
||||
MozStackFrameSymbolizer symbolizer;
|
||||
MinidumpProcessor minidumpProcessor(&symbolizer, false);
|
||||
@ -327,7 +329,7 @@ ProcessMinidump(Json::Value& aRoot, const string& aDumpFile) {
|
||||
rv = minidumpProcessor.Process(&dump, &processState);
|
||||
aRoot["status"] = ResultString(rv);
|
||||
|
||||
ConvertProcessStateToJSON(processState, aRoot);
|
||||
ConvertProcessStateToJSON(processState, aRoot, aFullStacks);
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -356,28 +358,43 @@ OpenAppend(const string& aFilename)
|
||||
// Update the extra data file by adding the StackTraces field holding the
|
||||
// JSON output of this program.
|
||||
|
||||
static void
|
||||
static bool
|
||||
UpdateExtraDataFile(const string &aDumpPath, const Json::Value& aRoot)
|
||||
{
|
||||
string extraDataPath(aDumpPath);
|
||||
int dot = extraDataPath.rfind('.');
|
||||
|
||||
if (dot < 0) {
|
||||
return; // Not a valid dump path
|
||||
return false; // Not a valid dump path
|
||||
}
|
||||
|
||||
extraDataPath.replace(dot, extraDataPath.length() - dot, kExtraDataExtension);
|
||||
ofstream* f = OpenAppend(extraDataPath.c_str());
|
||||
bool res = false;
|
||||
|
||||
if (f->is_open()) {
|
||||
Json::FastWriter writer;
|
||||
|
||||
*f << "StackTraces=" << writer.write(aRoot);
|
||||
res = !f->fail();
|
||||
|
||||
f->close();
|
||||
}
|
||||
|
||||
delete f;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
bool
|
||||
GenerateStacks(const string& aDumpPath, const bool aFullStacks) {
|
||||
Json::Value root;
|
||||
|
||||
if (!ProcessMinidump(root, aDumpPath, aFullStacks)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return UpdateExtraDataFile(aDumpPath , root);
|
||||
}
|
||||
|
||||
} // namespace CrashReporter
|
||||
@ -408,16 +425,9 @@ int main(int argc, char** argv)
|
||||
{
|
||||
ParseArguments(argc, argv);
|
||||
|
||||
if (!FileExists(gMinidumpPath)) {
|
||||
// The dump file does not exist
|
||||
if (!GenerateStacks(gMinidumpPath, gMinidumpAnalyzerOptions.fullMinidump)) {
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
// Try processing the minidump
|
||||
Json::Value root;
|
||||
if (ProcessMinidump(root, gMinidumpPath)) {
|
||||
UpdateExtraDataFile(gMinidumpPath, root);
|
||||
}
|
||||
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
17
toolkit/crashreporter/minidump-analyzer/minidump-analyzer.h
Normal file
17
toolkit/crashreporter/minidump-analyzer/minidump-analyzer.h
Normal file
@ -0,0 +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/. */
|
||||
|
||||
#ifndef MINIDUMP_ANALYZER_H__
|
||||
#define MINIDUMP_ANALYZER_H__
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace CrashReporter {
|
||||
|
||||
bool GenerateStacks(const std::string& aDumpPath, const bool aFullStacks);
|
||||
|
||||
}
|
||||
|
||||
#endif // MINIDUMP_ANALYZER_H__
|
@ -7,37 +7,42 @@
|
||||
if CONFIG['OS_TARGET'] != 'Android':
|
||||
Program('minidump-analyzer')
|
||||
|
||||
DEFINES['UNICODE'] = True
|
||||
DEFINES['_UNICODE'] = True
|
||||
|
||||
UNIFIED_SOURCES += [
|
||||
'minidump-analyzer.cpp',
|
||||
]
|
||||
|
||||
USE_LIBS += [
|
||||
'breakpad_processor',
|
||||
'jsoncpp',
|
||||
]
|
||||
|
||||
LOCAL_INCLUDES += [
|
||||
'/toolkit/components/jsoncpp/include',
|
||||
]
|
||||
|
||||
|
||||
if CONFIG['OS_TARGET'] == 'Darwin':
|
||||
DIST_SUBDIR = 'crashreporter.app/Contents/MacOS'
|
||||
|
||||
if CONFIG['OS_TARGET'] == 'WINNT' and CONFIG['CPU_ARCH'] == 'x86_64':
|
||||
UNIFIED_SOURCES += [
|
||||
'MozStackFrameSymbolizer.cpp',
|
||||
'Win64ModuleUnwindMetadata.cpp',
|
||||
if CONFIG['OS_TARGET'] == 'WINNT':
|
||||
DEFINES['UNICODE'] = True
|
||||
DEFINES['_UNICODE'] = True
|
||||
|
||||
if CONFIG['CPU_ARCH'] == 'x86_64':
|
||||
UNIFIED_SOURCES += [
|
||||
'MozStackFrameSymbolizer.cpp',
|
||||
'Win64ModuleUnwindMetadata.cpp',
|
||||
]
|
||||
|
||||
OS_LIBS += [
|
||||
'Dbghelp',
|
||||
'Imagehlp'
|
||||
]
|
||||
else:
|
||||
Library('minidump-analyzer')
|
||||
|
||||
EXPORTS += [
|
||||
'minidump-analyzer.h',
|
||||
]
|
||||
|
||||
OS_LIBS += [
|
||||
'Dbghelp',
|
||||
'Imagehlp'
|
||||
]
|
||||
UNIFIED_SOURCES += [
|
||||
'minidump-analyzer.cpp',
|
||||
]
|
||||
|
||||
USE_LIBS += [
|
||||
'breakpad_processor',
|
||||
'jsoncpp',
|
||||
]
|
||||
|
||||
LOCAL_INCLUDES += [
|
||||
'/toolkit/components/jsoncpp/include',
|
||||
]
|
||||
|
||||
# Don't use the STL wrappers in the crashreporter clients; they don't
|
||||
# link with -lmozalloc, and it really doesn't matter here anyway.
|
||||
|
Loading…
Reference in New Issue
Block a user