mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Merge mozilla-central into moizilla-inbound
This commit is contained in:
commit
910d058e01
@ -9,11 +9,13 @@ VPATH = @srcdir@
|
|||||||
|
|
||||||
include $(DEPTH)/config/autoconf.mk
|
include $(DEPTH)/config/autoconf.mk
|
||||||
|
|
||||||
DIRS = chrome components locales app
|
DIRS = chrome components locales
|
||||||
|
|
||||||
ifeq ($(OS_ARCH),WINNT)
|
ifeq ($(OS_ARCH),WINNT)
|
||||||
DIRS += $(DEPTH)/xulrunner/tools/redit
|
DIRS += $(DEPTH)/xulrunner/tools/redit
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
DIRS += app
|
||||||
|
|
||||||
include $(topsrcdir)/config/rules.mk
|
include $(topsrcdir)/config/rules.mk
|
||||||
include $(topsrcdir)/testing/testsuite-targets.mk
|
include $(topsrcdir)/testing/testsuite-targets.mk
|
||||||
|
@ -1,23 +0,0 @@
|
|||||||
#GONK_TOOLCHAIN_VERSION=0
|
|
||||||
#TOOLCHAIN_HOST=linux-x86
|
|
||||||
#export GONK_PRODUCT=generic
|
|
||||||
#gonk="/home/cjones/mozilla/gonk-toolchain-$GONK_TOOLCHAIN_VERSION"
|
|
||||||
|
|
||||||
mk_add_options MOZ_OBJDIR=@TOPSRCDIR@/obj-b2g
|
|
||||||
|
|
||||||
mk_add_options MOZ_MAKE_FLAGS="-j8"
|
|
||||||
|
|
||||||
ac_add_options --enable-application=b2g
|
|
||||||
|
|
||||||
ac_add_options --target=arm-android-eabi
|
|
||||||
ac_add_options --with-gonk="$gonk"
|
|
||||||
ac_add_options --with-gonk-toolchain-prefix="$gonk/prebuilt/$TOOLCHAIN_HOST/toolchain/arm-eabi-4.4.3/bin/arm-eabi-"
|
|
||||||
ac_add_options --with-endian=little
|
|
||||||
ac_add_options --disable-elf-hack
|
|
||||||
ac_add_options --enable-debug-symbols
|
|
||||||
ac_add_options --enable-profiling
|
|
||||||
ac_add_options --with-ccache
|
|
||||||
ac_add_options --enable-marionette
|
|
||||||
|
|
||||||
# Enable dump() from JS.
|
|
||||||
export CXXFLAGS=-DMOZ_ENABLE_JS_DUMP
|
|
@ -1,23 +0,0 @@
|
|||||||
#GONK_TOOLCHAIN_VERSION=0
|
|
||||||
#TOOLCHAIN_HOST=linux-x86
|
|
||||||
#export GONK_PRODUCT=generic
|
|
||||||
#gonk="/home/cjones/mozilla/gonk-toolchain-$GONK_TOOLCHAIN_VERSION"
|
|
||||||
|
|
||||||
mk_add_options MOZ_OBJDIR=@TOPSRCDIR@/obj-b2g
|
|
||||||
|
|
||||||
mk_add_options MOZ_MAKE_FLAGS="-j8"
|
|
||||||
|
|
||||||
ac_add_options --enable-application=b2g
|
|
||||||
|
|
||||||
ac_add_options --target=arm-android-eabi
|
|
||||||
ac_add_options --with-gonk="$gonk"
|
|
||||||
ac_add_options --with-gonk-toolchain-prefix="$gonk/prebuilt/$TOOLCHAIN_HOST/toolchain/arm-eabi-4.4.3/bin/arm-eabi-"
|
|
||||||
ac_add_options --with-endian=little
|
|
||||||
ac_add_options --disable-elf-hack
|
|
||||||
ac_add_options --enable-debug-symbols
|
|
||||||
ac_add_options --enable-profiling
|
|
||||||
ac_add_options --with-ccache
|
|
||||||
ac_add_options --enable-marionette
|
|
||||||
|
|
||||||
# Enable dump() from JS.
|
|
||||||
export CXXFLAGS=-DMOZ_ENABLE_JS_DUMP
|
|
@ -6,8 +6,6 @@ ac_add_options --enable-signmar
|
|||||||
# Nightlies only since this has a cost in performance
|
# Nightlies only since this has a cost in performance
|
||||||
#ac_add_options --enable-js-diagnostics
|
#ac_add_options --enable-js-diagnostics
|
||||||
|
|
||||||
. $topsrcdir/build/unix/mozconfig.linux
|
|
||||||
|
|
||||||
# Avoid dependency on libstdc++ 4.5
|
# Avoid dependency on libstdc++ 4.5
|
||||||
ac_add_options --enable-stdcxx-compat
|
ac_add_options --enable-stdcxx-compat
|
||||||
|
|
@ -661,6 +661,9 @@ bin/libfreebl_32int64_3.so
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
@BINPATH@/crashreporter-override.ini
|
@BINPATH@/crashreporter-override.ini
|
||||||
|
#ifdef MOZ_CRASHREPORTER_INJECTOR
|
||||||
|
@BINPATH@/breakpadinjector.dll
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
; [Extensions]
|
; [Extensions]
|
||||||
|
@ -155,6 +155,7 @@ LIBJPEG_TURBO_ARM_ASM = @LIBJPEG_TURBO_ARM_ASM@
|
|||||||
NS_PRINTING = @NS_PRINTING@
|
NS_PRINTING = @NS_PRINTING@
|
||||||
MOZ_PDF_PRINTING = @MOZ_PDF_PRINTING@
|
MOZ_PDF_PRINTING = @MOZ_PDF_PRINTING@
|
||||||
MOZ_CRASHREPORTER = @MOZ_CRASHREPORTER@
|
MOZ_CRASHREPORTER = @MOZ_CRASHREPORTER@
|
||||||
|
MOZ_CRASHREPORTER_INJECTOR = @MOZ_CRASHREPORTER_INJECTOR@
|
||||||
MOZ_HELP_VIEWER = @MOZ_HELP_VIEWER@
|
MOZ_HELP_VIEWER = @MOZ_HELP_VIEWER@
|
||||||
MOC = @MOC@
|
MOC = @MOC@
|
||||||
RCC = @RCC@
|
RCC = @RCC@
|
||||||
|
@ -5858,6 +5858,11 @@ if test -n "$MOZ_CRASHREPORTER"; then
|
|||||||
if (test "$OS_ARCH" != "$HOST_OS_ARCH"); then
|
if (test "$OS_ARCH" != "$HOST_OS_ARCH"); then
|
||||||
AC_MSG_ERROR([Breakpad tools do not support compiling on $HOST_OS_ARCH while targeting $OS_ARCH. Use --disable-crashreporter.])
|
AC_MSG_ERROR([Breakpad tools do not support compiling on $HOST_OS_ARCH while targeting $OS_ARCH. Use --disable-crashreporter.])
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if test "$OS_ARCH" == "WINNT" -a -z "$HAVE_64BIT_OS"; then
|
||||||
|
MOZ_CRASHREPORTER_INJECTOR=1
|
||||||
|
AC_DEFINE(MOZ_CRASHREPORTER_INJECTOR)
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
MOZ_ARG_WITH_STRING(crashreporter-enable-percent,
|
MOZ_ARG_WITH_STRING(crashreporter-enable-percent,
|
||||||
@ -8327,6 +8332,7 @@ AC_SUBST(MOZ_SPELLCHECK)
|
|||||||
AC_SUBST(MOZ_JAVA_COMPOSITOR)
|
AC_SUBST(MOZ_JAVA_COMPOSITOR)
|
||||||
AC_SUBST(MOZ_ONLY_TOUCH_EVENTS)
|
AC_SUBST(MOZ_ONLY_TOUCH_EVENTS)
|
||||||
AC_SUBST(MOZ_CRASHREPORTER)
|
AC_SUBST(MOZ_CRASHREPORTER)
|
||||||
|
AC_SUBST(MOZ_CRASHREPORTER_INJECTOR)
|
||||||
AC_SUBST(MOZ_MAINTENANCE_SERVICE)
|
AC_SUBST(MOZ_MAINTENANCE_SERVICE)
|
||||||
AC_SUBST(MOZ_VERIFY_MAR_SIGNATURE)
|
AC_SUBST(MOZ_VERIFY_MAR_SIGNATURE)
|
||||||
AC_SUBST(MOZ_ENABLE_SIGNMAR)
|
AC_SUBST(MOZ_ENABLE_SIGNMAR)
|
||||||
|
@ -102,6 +102,10 @@ PluginModuleParent::PluginModuleParent(const char* aFilePath)
|
|||||||
, mNPNIface(NULL)
|
, mNPNIface(NULL)
|
||||||
, mPlugin(NULL)
|
, mPlugin(NULL)
|
||||||
, mTaskFactory(this)
|
, mTaskFactory(this)
|
||||||
|
#ifdef MOZ_CRASHREPORTER_INJECTOR
|
||||||
|
, mFlashProcess1(0)
|
||||||
|
, mFlashProcess2(0)
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
NS_ASSERTION(mSubprocess, "Out of memory!");
|
NS_ASSERTION(mSubprocess, "Out of memory!");
|
||||||
|
|
||||||
@ -127,6 +131,13 @@ PluginModuleParent::~PluginModuleParent()
|
|||||||
mSubprocess = nsnull;
|
mSubprocess = nsnull;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef MOZ_CRASHREPORTER_INJECTOR
|
||||||
|
if (mFlashProcess1)
|
||||||
|
CrashReporter::UnregisterInjectorCallback(mFlashProcess1);
|
||||||
|
if (mFlashProcess2)
|
||||||
|
CrashReporter::UnregisterInjectorCallback(mFlashProcess2);
|
||||||
|
#endif
|
||||||
|
|
||||||
Preferences::UnregisterCallback(TimeoutChanged, kChildTimeoutPref, this);
|
Preferences::UnregisterCallback(TimeoutChanged, kChildTimeoutPref, this);
|
||||||
Preferences::UnregisterCallback(TimeoutChanged, kParentTimeoutPref, this);
|
Preferences::UnregisterCallback(TimeoutChanged, kParentTimeoutPref, this);
|
||||||
}
|
}
|
||||||
@ -151,9 +162,12 @@ PluginModuleParent::WriteExtraDataForMinidump(CrashReporter::AnnotationTable& no
|
|||||||
notes.Put(CS("PluginName"), CS(""));
|
notes.Put(CS("PluginName"), CS(""));
|
||||||
notes.Put(CS("PluginVersion"), CS(""));
|
notes.Put(CS("PluginVersion"), CS(""));
|
||||||
|
|
||||||
const nsString& hangID = CrashReporter()->HangID();
|
CrashReporterParent* crashReporter = CrashReporter();
|
||||||
if (!hangID.IsEmpty())
|
if (crashReporter) {
|
||||||
notes.Put(CS("HangID"), NS_ConvertUTF16toUTF8(hangID));
|
const nsString& hangID = crashReporter->HangID();
|
||||||
|
if (!hangID.IsEmpty())
|
||||||
|
notes.Put(CS("HangID"), NS_ConvertUTF16toUTF8(hangID));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif // MOZ_CRASHREPORTER
|
#endif // MOZ_CRASHREPORTER
|
||||||
|
|
||||||
@ -186,17 +200,19 @@ bool
|
|||||||
PluginModuleParent::ShouldContinueFromReplyTimeout()
|
PluginModuleParent::ShouldContinueFromReplyTimeout()
|
||||||
{
|
{
|
||||||
#ifdef MOZ_CRASHREPORTER
|
#ifdef MOZ_CRASHREPORTER
|
||||||
CrashReporterParent* crashReporter = CrashReporter();
|
if (mPluginDumpID.IsEmpty()) {
|
||||||
if (crashReporter->GeneratePairedMinidump(this)) {
|
CrashReporterParent* crashReporter = CrashReporter();
|
||||||
mBrowserDumpID = crashReporter->ParentDumpID();
|
if (crashReporter->GeneratePairedMinidump(this)) {
|
||||||
mPluginDumpID = crashReporter->ChildDumpID();
|
mBrowserDumpID = crashReporter->ParentDumpID();
|
||||||
PLUGIN_LOG_DEBUG(
|
mPluginDumpID = crashReporter->ChildDumpID();
|
||||||
("generated paired browser/plugin minidumps: %s/%s (ID=%s)",
|
PLUGIN_LOG_DEBUG(
|
||||||
NS_ConvertUTF16toUTF8(mBrowserDumpID).get(),
|
("generated paired browser/plugin minidumps: %s/%s (ID=%s)",
|
||||||
NS_ConvertUTF16toUTF8(mPluginDumpID).get(),
|
NS_ConvertUTF16toUTF8(mBrowserDumpID).get(),
|
||||||
NS_ConvertUTF16toUTF8(crashReporter->HangID()).get()));
|
NS_ConvertUTF16toUTF8(mPluginDumpID).get(),
|
||||||
} else {
|
NS_ConvertUTF16toUTF8(crashReporter->HangID()).get()));
|
||||||
NS_WARNING("failed to capture paired minidumps from hang");
|
} else {
|
||||||
|
NS_WARNING("failed to capture paired minidumps from hang");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -217,7 +233,6 @@ PluginModuleParent::ShouldContinueFromReplyTimeout()
|
|||||||
CrashReporterParent*
|
CrashReporterParent*
|
||||||
PluginModuleParent::CrashReporter()
|
PluginModuleParent::CrashReporter()
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(ManagedPCrashReporterParent().Length() > 0);
|
|
||||||
return static_cast<CrashReporterParent*>(ManagedPCrashReporterParent()[0]);
|
return static_cast<CrashReporterParent*>(ManagedPCrashReporterParent()[0]);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -234,14 +249,18 @@ PluginModuleParent::ActorDestroy(ActorDestroyReason why)
|
|||||||
notes.Init(4);
|
notes.Init(4);
|
||||||
WriteExtraDataForMinidump(notes);
|
WriteExtraDataForMinidump(notes);
|
||||||
|
|
||||||
if (crashReporter->GenerateCrashReport(this, ¬es)) {
|
if (!mPluginDumpID.IsEmpty() && !mBrowserDumpID.IsEmpty()) {
|
||||||
|
crashReporter->GenerateHangCrashReport(¬es);
|
||||||
|
}
|
||||||
|
else if (!mPluginDumpID.IsEmpty()) {
|
||||||
|
// Nothing to do, we've already written this minidump in
|
||||||
|
// PluginModuleParent::OnCrash
|
||||||
|
}
|
||||||
|
else if (crashReporter->GenerateCrashReport(this, ¬es)) {
|
||||||
mPluginDumpID = crashReporter->ChildDumpID();
|
mPluginDumpID = crashReporter->ChildDumpID();
|
||||||
PLUGIN_LOG_DEBUG(("got child minidump: %s",
|
PLUGIN_LOG_DEBUG(("got child minidump: %s",
|
||||||
NS_ConvertUTF16toUTF8(mPluginDumpID).get()));
|
NS_ConvertUTF16toUTF8(mPluginDumpID).get()));
|
||||||
}
|
}
|
||||||
else if (!mPluginDumpID.IsEmpty() && !mBrowserDumpID.IsEmpty()) {
|
|
||||||
crashReporter->GenerateHangCrashReport(¬es);
|
|
||||||
}
|
|
||||||
else {
|
else {
|
||||||
NS_WARNING("[PluginModuleParent::ActorDestroy] abnormal shutdown without minidump!");
|
NS_WARNING("[PluginModuleParent::ActorDestroy] abnormal shutdown without minidump!");
|
||||||
}
|
}
|
||||||
@ -761,6 +780,10 @@ PluginModuleParent::NP_Initialize(NPNetscapeFuncs* bFuncs, NPError* error)
|
|||||||
unused << SendSetAudioSessionData(id, sessionName, iconPath);
|
unused << SendSetAudioSessionData(id, sessionName, iconPath);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef MOZ_CRASHREPORTER_INJECTOR
|
||||||
|
InitializeInjector();
|
||||||
|
#endif
|
||||||
|
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -1162,3 +1185,102 @@ PluginModuleParent::RecvNPN_ReloadPlugins(const bool& aReloadPages)
|
|||||||
mozilla::plugins::parent::_reloadplugins(aReloadPages);
|
mozilla::plugins::parent::_reloadplugins(aReloadPages);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef MOZ_CRASHREPORTER_INJECTOR
|
||||||
|
|
||||||
|
// We only add the crash reporter to subprocess which have the filename
|
||||||
|
// FlashPlayerPlugin*
|
||||||
|
#define FLASH_PROCESS_PREFIX "FLASHPLAYERPLUGIN"
|
||||||
|
|
||||||
|
static DWORD
|
||||||
|
GetFlashChildOfPID(DWORD pid, HANDLE snapshot)
|
||||||
|
{
|
||||||
|
PROCESSENTRY32 entry = {
|
||||||
|
sizeof(entry)
|
||||||
|
};
|
||||||
|
for (BOOL ok = Process32First(snapshot, &entry);
|
||||||
|
ok;
|
||||||
|
ok = Process32Next(snapshot, &entry)) {
|
||||||
|
if (entry.th32ParentProcessID == pid) {
|
||||||
|
nsString name(entry.szExeFile);
|
||||||
|
ToUpperCase(name);
|
||||||
|
if (StringBeginsWith(name, NS_LITERAL_STRING(FLASH_PROCESS_PREFIX))) {
|
||||||
|
return entry.th32ProcessID;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We only look for child processes of the Flash plugin, NPSWF*
|
||||||
|
#define FLASH_PLUGIN_PREFIX "NPSWF"
|
||||||
|
|
||||||
|
void
|
||||||
|
PluginModuleParent::InitializeInjector()
|
||||||
|
{
|
||||||
|
if (!Preferences::GetBool("dom.ipc.plugins.flash.subprocess.crashreporter.enabled", false))
|
||||||
|
return;
|
||||||
|
|
||||||
|
nsCString path(Process()->GetPluginFilePath().c_str());
|
||||||
|
ToUpperCase(path);
|
||||||
|
PRInt32 lastSlash = path.RFindCharInSet("\\/");
|
||||||
|
if (kNotFound == lastSlash)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!StringBeginsWith(Substring(path, lastSlash + 1),
|
||||||
|
NS_LITERAL_CSTRING(FLASH_PLUGIN_PREFIX)))
|
||||||
|
return;
|
||||||
|
|
||||||
|
HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
|
||||||
|
if (INVALID_HANDLE_VALUE == snapshot)
|
||||||
|
return;
|
||||||
|
|
||||||
|
DWORD pluginProcessPID = GetProcessId(Process()->GetChildProcessHandle());
|
||||||
|
mFlashProcess1 = GetFlashChildOfPID(pluginProcessPID, snapshot);
|
||||||
|
if (mFlashProcess1) {
|
||||||
|
InjectCrashReporterIntoProcess(mFlashProcess1, this);
|
||||||
|
|
||||||
|
mFlashProcess2 = GetFlashChildOfPID(mFlashProcess1, snapshot);
|
||||||
|
if (mFlashProcess2) {
|
||||||
|
InjectCrashReporterIntoProcess(mFlashProcess2, this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
PluginModuleParent::OnCrash(DWORD processID, const nsAString& aDumpID)
|
||||||
|
{
|
||||||
|
if (!mPluginDumpID.IsEmpty()) {
|
||||||
|
// One process has already crashed: we assume that the first-to-crash
|
||||||
|
// is the interesting one
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
mPluginDumpID = aDumpID;
|
||||||
|
|
||||||
|
CrashReporter::AnnotationTable notes;
|
||||||
|
notes.Init(4);
|
||||||
|
WriteExtraDataForMinidump(notes);
|
||||||
|
notes.Put(NS_LITERAL_CSTRING("ProcessType"), NS_LITERAL_CSTRING("plugin"));
|
||||||
|
if (processID == mFlashProcess1) {
|
||||||
|
notes.Put(NS_LITERAL_CSTRING("FlashProcessDump"),
|
||||||
|
NS_LITERAL_CSTRING("Broker"));
|
||||||
|
}
|
||||||
|
else if (processID == mFlashProcess2) {
|
||||||
|
notes.Put(NS_LITERAL_CSTRING("FlashProcessDump"),
|
||||||
|
NS_LITERAL_CSTRING("Sandbox"));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
NS_ERROR("Got minidump for Flash process neither broker nor sandbox.");
|
||||||
|
}
|
||||||
|
|
||||||
|
CrashReporter::AppendExtraData(aDumpID, notes);
|
||||||
|
MessageLoop::current()->PostTask(
|
||||||
|
FROM_HERE,
|
||||||
|
mTaskFactory.NewRunnableMethod(
|
||||||
|
&PluginModuleParent::CleanupFromTimeout));
|
||||||
|
|
||||||
|
KillProcess(OtherProcess(), 1, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // MOZ_CRASHREPORTER_INJECTOR
|
||||||
|
@ -30,6 +30,10 @@
|
|||||||
#include "nsHashKeys.h"
|
#include "nsHashKeys.h"
|
||||||
#include "nsIFileStreams.h"
|
#include "nsIFileStreams.h"
|
||||||
|
|
||||||
|
#ifdef MOZ_CRASHREPORTER
|
||||||
|
#include "nsExceptionHandler.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
namespace dom {
|
namespace dom {
|
||||||
class PCrashReporterParent;
|
class PCrashReporterParent;
|
||||||
@ -52,7 +56,12 @@ class BrowserStreamParent;
|
|||||||
* child process needs to make these calls back into Gecko proper.
|
* child process needs to make these calls back into Gecko proper.
|
||||||
* This class is responsible for "actually" making those function calls.
|
* This class is responsible for "actually" making those function calls.
|
||||||
*/
|
*/
|
||||||
class PluginModuleParent : public PPluginModuleParent, PluginLibrary
|
class PluginModuleParent
|
||||||
|
: public PPluginModuleParent
|
||||||
|
, public PluginLibrary
|
||||||
|
#ifdef MOZ_CRASHREPORTER_INJECTOR
|
||||||
|
, public CrashReporter::InjectorCrashCallback
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
typedef mozilla::PluginLibrary PluginLibrary;
|
typedef mozilla::PluginLibrary PluginLibrary;
|
||||||
@ -306,6 +315,15 @@ private:
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
friend class mozilla::dom::CrashReporterParent;
|
friend class mozilla::dom::CrashReporterParent;
|
||||||
|
|
||||||
|
#ifdef MOZ_CRASHREPORTER_INJECTOR
|
||||||
|
void InitializeInjector();
|
||||||
|
|
||||||
|
NS_OVERRIDE void OnCrash(DWORD processID, const nsAString& aDumpID);
|
||||||
|
|
||||||
|
DWORD mFlashProcess1;
|
||||||
|
DWORD mFlashProcess2;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace plugins
|
} // namespace plugins
|
||||||
|
@ -1630,6 +1630,8 @@ pref("dom.ipc.plugins.parentTimeoutSecs", 0);
|
|||||||
// conflicts with our implementation, at least on Windows).
|
// conflicts with our implementation, at least on Windows).
|
||||||
pref("dom.ipc.plugins.java.enabled", false);
|
pref("dom.ipc.plugins.java.enabled", false);
|
||||||
|
|
||||||
|
pref("dom.ipc.plugins.flash.subprocess.crashreporter.enabled", true);
|
||||||
|
|
||||||
#ifndef ANDROID
|
#ifndef ANDROID
|
||||||
#ifndef XP_MACOSX
|
#ifndef XP_MACOSX
|
||||||
#ifdef XP_UNIX
|
#ifdef XP_UNIX
|
||||||
|
84
toolkit/crashreporter/InjectCrashReporter.cpp
Normal file
84
toolkit/crashreporter/InjectCrashReporter.cpp
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
/* -*- Mode: C++; tab-width: 8; 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 "InjectCrashReporter.h"
|
||||||
|
#include "nsDirectoryServiceUtils.h"
|
||||||
|
#include "nsDirectoryServiceDefs.h"
|
||||||
|
#include "client/windows/crash_generation/crash_generation_client.h"
|
||||||
|
#include "nsExceptionHandler.h"
|
||||||
|
#include "LoadLibraryRemote.h"
|
||||||
|
#include "nsWindowsHelpers.h"
|
||||||
|
|
||||||
|
using google_breakpad::CrashGenerationClient;
|
||||||
|
using CrashReporter::GetChildNotificationPipe;
|
||||||
|
|
||||||
|
namespace mozilla {
|
||||||
|
|
||||||
|
InjectCrashRunnable::InjectCrashRunnable(DWORD pid)
|
||||||
|
: mPID(pid)
|
||||||
|
{
|
||||||
|
nsCOMPtr<nsIFile> dll;
|
||||||
|
nsresult rv = NS_GetSpecialDirectory(NS_GRE_DIR, getter_AddRefs(dll));
|
||||||
|
if (NS_SUCCEEDED(rv)) {
|
||||||
|
dll->Append(NS_LITERAL_STRING("breakpadinjector.dll"));
|
||||||
|
dll->GetPath(mInjectorPath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
InjectCrashRunnable::Run()
|
||||||
|
{
|
||||||
|
if (mInjectorPath.IsEmpty())
|
||||||
|
return NS_OK;
|
||||||
|
|
||||||
|
nsAutoHandle hProcess(
|
||||||
|
OpenProcess(PROCESS_CREATE_THREAD |
|
||||||
|
PROCESS_QUERY_INFORMATION |
|
||||||
|
PROCESS_DUP_HANDLE |
|
||||||
|
PROCESS_VM_OPERATION |
|
||||||
|
PROCESS_VM_WRITE |
|
||||||
|
PROCESS_VM_READ, FALSE, mPID));
|
||||||
|
if (!hProcess) {
|
||||||
|
NS_WARNING("Unable to open remote process handle for crashreporter injection.");
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
void* proc = LoadRemoteLibraryAndGetAddress(hProcess, mInjectorPath.get(),
|
||||||
|
"Start");
|
||||||
|
if (!proc) {
|
||||||
|
NS_WARNING("Unable to inject crashreporter DLL.");
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
HANDLE hRemotePipe =
|
||||||
|
CrashGenerationClient::DuplicatePipeToClientProcess(
|
||||||
|
NS_ConvertASCIItoUTF16(GetChildNotificationPipe()).get(),
|
||||||
|
hProcess);
|
||||||
|
if (INVALID_HANDLE_VALUE == hRemotePipe) {
|
||||||
|
NS_WARNING("Unable to duplicate crash reporter pipe to process.");
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsAutoHandle hThread(CreateRemoteThread(hProcess, NULL, 0,
|
||||||
|
(LPTHREAD_START_ROUTINE) proc,
|
||||||
|
(void*) hRemotePipe, 0, NULL));
|
||||||
|
if (!hThread) {
|
||||||
|
NS_WARNING("Unable to CreateRemoteThread");
|
||||||
|
|
||||||
|
// We have to close the remote pipe or else our crash generation client
|
||||||
|
// will be stuck unable to accept other remote requests.
|
||||||
|
HANDLE toClose = INVALID_HANDLE_VALUE;
|
||||||
|
if (DuplicateHandle(hProcess, hRemotePipe, ::GetCurrentProcess(),
|
||||||
|
&toClose, 0, FALSE,
|
||||||
|
DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS)) {
|
||||||
|
CloseHandle(toClose);
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace mozilla
|
23
toolkit/crashreporter/InjectCrashReporter.h
Normal file
23
toolkit/crashreporter/InjectCrashReporter.h
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
/* -*- Mode: C++; tab-width: 8; 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 "nsThreadUtils.h"
|
||||||
|
#include <windows.h>
|
||||||
|
|
||||||
|
namespace mozilla {
|
||||||
|
|
||||||
|
class InjectCrashRunnable : public nsRunnable
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
InjectCrashRunnable(DWORD pid);
|
||||||
|
|
||||||
|
NS_IMETHOD Run();
|
||||||
|
|
||||||
|
private:
|
||||||
|
DWORD mPID;
|
||||||
|
nsString mInjectorPath;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // Namespace mozilla
|
440
toolkit/crashreporter/LoadLibraryRemote.cpp
Normal file
440
toolkit/crashreporter/LoadLibraryRemote.cpp
Normal file
@ -0,0 +1,440 @@
|
|||||||
|
/* 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 __GNUC__
|
||||||
|
// disable warnings about pointer <-> DWORD conversions
|
||||||
|
#pragma warning( disable : 4311 4312 )
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef _WIN64
|
||||||
|
#define POINTER_TYPE ULONGLONG
|
||||||
|
#else
|
||||||
|
#define POINTER_TYPE DWORD
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <windows.h>
|
||||||
|
#include <winnt.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#ifdef DEBUG_OUTPUT
|
||||||
|
#include <stdio.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "nsWindowsHelpers.h"
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
typedef const unsigned char* FileView;
|
||||||
|
|
||||||
|
template<>
|
||||||
|
class nsAutoRefTraits<FileView>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef FileView RawRef;
|
||||||
|
static FileView Void()
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void Release(RawRef aView)
|
||||||
|
{
|
||||||
|
if (NULL != aView)
|
||||||
|
UnmapViewOfFile(aView);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // anonymous namespace
|
||||||
|
|
||||||
|
#ifndef IMAGE_SIZEOF_BASE_RELOCATION
|
||||||
|
// Vista SDKs no longer define IMAGE_SIZEOF_BASE_RELOCATION!?
|
||||||
|
#define IMAGE_SIZEOF_BASE_RELOCATION (sizeof(IMAGE_BASE_RELOCATION))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "LoadLibraryRemote.h"
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
PIMAGE_NT_HEADERS headers;
|
||||||
|
unsigned char *localCodeBase;
|
||||||
|
unsigned char *remoteCodeBase;
|
||||||
|
HMODULE *modules;
|
||||||
|
int numModules;
|
||||||
|
} MEMORYMODULE, *PMEMORYMODULE;
|
||||||
|
|
||||||
|
typedef BOOL (WINAPI *DllEntryProc)(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved);
|
||||||
|
|
||||||
|
#define GET_HEADER_DICTIONARY(module, idx) &(module)->headers->OptionalHeader.DataDirectory[idx]
|
||||||
|
|
||||||
|
#ifdef DEBUG_OUTPUT
|
||||||
|
static void
|
||||||
|
OutputLastError(const char *msg)
|
||||||
|
{
|
||||||
|
char* tmp;
|
||||||
|
char *tmpmsg;
|
||||||
|
FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||||
|
NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR) &tmp, 0, NULL);
|
||||||
|
tmpmsg = (char *)LocalAlloc(LPTR, strlen(msg) + strlen(tmp) + 3);
|
||||||
|
sprintf(tmpmsg, "%s: %s", msg, tmp);
|
||||||
|
OutputDebugStringA(tmpmsg);
|
||||||
|
LocalFree(tmpmsg);
|
||||||
|
LocalFree(tmp);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static void
|
||||||
|
CopySections(const unsigned char *data, PIMAGE_NT_HEADERS old_headers, PMEMORYMODULE module)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
unsigned char *codeBase = module->localCodeBase;
|
||||||
|
unsigned char *dest;
|
||||||
|
PIMAGE_SECTION_HEADER section = IMAGE_FIRST_SECTION(module->headers);
|
||||||
|
for (i=0; i<module->headers->FileHeader.NumberOfSections; i++, section++) {
|
||||||
|
dest = codeBase + section->VirtualAddress;
|
||||||
|
memset(dest, 0, section->Misc.VirtualSize);
|
||||||
|
if (section->SizeOfRawData) {
|
||||||
|
memcpy(dest, data + section->PointerToRawData, section->SizeOfRawData);
|
||||||
|
}
|
||||||
|
// section->Misc.PhysicalAddress = (POINTER_TYPE) module->remoteCodeBase + section->VirtualAddress;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Protection flags for memory pages (Executable, Readable, Writeable)
|
||||||
|
static int ProtectionFlags[2][2][2] = {
|
||||||
|
{
|
||||||
|
// not executable
|
||||||
|
{PAGE_NOACCESS, PAGE_WRITECOPY},
|
||||||
|
{PAGE_READONLY, PAGE_READWRITE},
|
||||||
|
}, {
|
||||||
|
// executable
|
||||||
|
{PAGE_EXECUTE, PAGE_EXECUTE_WRITECOPY},
|
||||||
|
{PAGE_EXECUTE_READ, PAGE_EXECUTE_READWRITE},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
static bool
|
||||||
|
FinalizeSections(PMEMORYMODULE module, HANDLE hRemoteProcess)
|
||||||
|
{
|
||||||
|
#ifdef DEBUG_OUTPUT
|
||||||
|
fprintf(stderr, "Finalizing sections: local base %p, remote base %p\n",
|
||||||
|
module->localCodeBase, module->remoteCodeBase);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int i;
|
||||||
|
PIMAGE_SECTION_HEADER section = IMAGE_FIRST_SECTION(module->headers);
|
||||||
|
|
||||||
|
// loop through all sections and change access flags
|
||||||
|
for (i=0; i<module->headers->FileHeader.NumberOfSections; i++, section++) {
|
||||||
|
DWORD protect, oldProtect, size;
|
||||||
|
int executable = (section->Characteristics & IMAGE_SCN_MEM_EXECUTE) != 0;
|
||||||
|
int readable = (section->Characteristics & IMAGE_SCN_MEM_READ) != 0;
|
||||||
|
int writeable = (section->Characteristics & IMAGE_SCN_MEM_WRITE) != 0;
|
||||||
|
|
||||||
|
// determine protection flags based on characteristics
|
||||||
|
protect = ProtectionFlags[executable][readable][writeable];
|
||||||
|
if (section->Characteristics & IMAGE_SCN_MEM_NOT_CACHED) {
|
||||||
|
protect |= PAGE_NOCACHE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// determine size of region
|
||||||
|
size = section->Misc.VirtualSize;
|
||||||
|
if (size > 0) {
|
||||||
|
void* remoteAddress = module->remoteCodeBase + section->VirtualAddress;
|
||||||
|
void* localAddress = module->localCodeBase + section->VirtualAddress;
|
||||||
|
|
||||||
|
#ifdef DEBUG_OUTPUT
|
||||||
|
fprintf(stderr, "Copying section %s to %p, size %x, executable %i readable %i writeable %i\n",
|
||||||
|
section->Name, remoteAddress, size, executable, readable, writeable);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Copy the data from local->remote and set the memory protection
|
||||||
|
if (!VirtualAllocEx(hRemoteProcess, remoteAddress, size, MEM_COMMIT, PAGE_READWRITE))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!WriteProcessMemory(hRemoteProcess,
|
||||||
|
remoteAddress,
|
||||||
|
localAddress,
|
||||||
|
size,
|
||||||
|
NULL)) {
|
||||||
|
#ifdef DEBUG_OUTPUT
|
||||||
|
OutputLastError("Error writing remote memory.\n");
|
||||||
|
#endif
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (VirtualProtectEx(hRemoteProcess, remoteAddress, size, protect, &oldProtect) == 0) {
|
||||||
|
#ifdef DEBUG_OUTPUT
|
||||||
|
OutputLastError("Error protecting memory page");
|
||||||
|
#endif
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
PerformBaseRelocation(PMEMORYMODULE module, SIZE_T delta)
|
||||||
|
{
|
||||||
|
DWORD i;
|
||||||
|
unsigned char *codeBase = module->localCodeBase;
|
||||||
|
|
||||||
|
PIMAGE_DATA_DIRECTORY directory = GET_HEADER_DICTIONARY(module, IMAGE_DIRECTORY_ENTRY_BASERELOC);
|
||||||
|
if (directory->Size > 0) {
|
||||||
|
PIMAGE_BASE_RELOCATION relocation = (PIMAGE_BASE_RELOCATION) (codeBase + directory->VirtualAddress);
|
||||||
|
for (; relocation->VirtualAddress > 0; ) {
|
||||||
|
unsigned char *dest = codeBase + relocation->VirtualAddress;
|
||||||
|
unsigned short *relInfo = (unsigned short *)((unsigned char *)relocation + IMAGE_SIZEOF_BASE_RELOCATION);
|
||||||
|
for (i=0; i<((relocation->SizeOfBlock-IMAGE_SIZEOF_BASE_RELOCATION) / 2); i++, relInfo++) {
|
||||||
|
DWORD *patchAddrHL;
|
||||||
|
#ifdef _WIN64
|
||||||
|
ULONGLONG *patchAddr64;
|
||||||
|
#endif
|
||||||
|
int type, offset;
|
||||||
|
|
||||||
|
// the upper 4 bits define the type of relocation
|
||||||
|
type = *relInfo >> 12;
|
||||||
|
// the lower 12 bits define the offset
|
||||||
|
offset = *relInfo & 0xfff;
|
||||||
|
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case IMAGE_REL_BASED_ABSOLUTE:
|
||||||
|
// skip relocation
|
||||||
|
break;
|
||||||
|
|
||||||
|
case IMAGE_REL_BASED_HIGHLOW:
|
||||||
|
// change complete 32 bit address
|
||||||
|
patchAddrHL = (DWORD *) (dest + offset);
|
||||||
|
*patchAddrHL += delta;
|
||||||
|
break;
|
||||||
|
|
||||||
|
#ifdef _WIN64
|
||||||
|
case IMAGE_REL_BASED_DIR64:
|
||||||
|
patchAddr64 = (ULONGLONG *) (dest + offset);
|
||||||
|
*patchAddr64 += delta;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
default:
|
||||||
|
//printf("Unknown relocation: %d\n", type);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// advance to next relocation block
|
||||||
|
relocation = (PIMAGE_BASE_RELOCATION) (((char *) relocation) + relocation->SizeOfBlock);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
BuildImportTable(PMEMORYMODULE module)
|
||||||
|
{
|
||||||
|
int result=1;
|
||||||
|
unsigned char *codeBase = module->localCodeBase;
|
||||||
|
|
||||||
|
PIMAGE_DATA_DIRECTORY directory = GET_HEADER_DICTIONARY(module, IMAGE_DIRECTORY_ENTRY_IMPORT);
|
||||||
|
if (directory->Size > 0) {
|
||||||
|
PIMAGE_IMPORT_DESCRIPTOR importDesc = (PIMAGE_IMPORT_DESCRIPTOR) (codeBase + directory->VirtualAddress);
|
||||||
|
PIMAGE_IMPORT_DESCRIPTOR importEnd = (PIMAGE_IMPORT_DESCRIPTOR) (codeBase + directory->VirtualAddress + directory->Size);
|
||||||
|
|
||||||
|
for (; importDesc < importEnd && importDesc->Name; importDesc++) {
|
||||||
|
POINTER_TYPE *thunkRef;
|
||||||
|
FARPROC *funcRef;
|
||||||
|
HMODULE handle = GetModuleHandleA((LPCSTR) (codeBase + importDesc->Name));
|
||||||
|
if (handle == NULL) {
|
||||||
|
#if DEBUG_OUTPUT
|
||||||
|
OutputLastError("Can't load library");
|
||||||
|
#endif
|
||||||
|
result = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
module->modules = (HMODULE *)realloc(module->modules, (module->numModules+1)*(sizeof(HMODULE)));
|
||||||
|
if (module->modules == NULL) {
|
||||||
|
result = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
module->modules[module->numModules++] = handle;
|
||||||
|
if (importDesc->OriginalFirstThunk) {
|
||||||
|
thunkRef = (POINTER_TYPE *) (codeBase + importDesc->OriginalFirstThunk);
|
||||||
|
funcRef = (FARPROC *) (codeBase + importDesc->FirstThunk);
|
||||||
|
} else {
|
||||||
|
// no hint table
|
||||||
|
thunkRef = (POINTER_TYPE *) (codeBase + importDesc->FirstThunk);
|
||||||
|
funcRef = (FARPROC *) (codeBase + importDesc->FirstThunk);
|
||||||
|
}
|
||||||
|
for (; *thunkRef; thunkRef++, funcRef++) {
|
||||||
|
if (IMAGE_SNAP_BY_ORDINAL(*thunkRef)) {
|
||||||
|
*funcRef = (FARPROC)GetProcAddress(handle, (LPCSTR)IMAGE_ORDINAL(*thunkRef));
|
||||||
|
} else {
|
||||||
|
PIMAGE_IMPORT_BY_NAME thunkData = (PIMAGE_IMPORT_BY_NAME) (codeBase + (*thunkRef));
|
||||||
|
*funcRef = (FARPROC)GetProcAddress(handle, (LPCSTR)&thunkData->Name);
|
||||||
|
}
|
||||||
|
if (*funcRef == 0) {
|
||||||
|
result = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!result) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void* MemoryGetProcAddress(PMEMORYMODULE module, const char *name);
|
||||||
|
|
||||||
|
void* LoadRemoteLibraryAndGetAddress(HANDLE hRemoteProcess,
|
||||||
|
const WCHAR* library,
|
||||||
|
const char* symbol)
|
||||||
|
{
|
||||||
|
// Map the DLL into memory
|
||||||
|
nsAutoHandle hLibrary(
|
||||||
|
CreateFile(library, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING,
|
||||||
|
FILE_ATTRIBUTE_NORMAL, NULL));
|
||||||
|
if (INVALID_HANDLE_VALUE == hLibrary) {
|
||||||
|
#if DEBUG_OUTPUT
|
||||||
|
OutputLastError("Couldn't CreateFile the library.\n");
|
||||||
|
#endif
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsAutoHandle hMapping(
|
||||||
|
CreateFileMapping(hLibrary, NULL, PAGE_READONLY, 0, 0, NULL));
|
||||||
|
if (!hMapping) {
|
||||||
|
#if DEBUG_OUTPUT
|
||||||
|
OutputLastError("Couldn't CreateFileMapping.\n");
|
||||||
|
#endif
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsAutoRef<FileView> data(
|
||||||
|
(const unsigned char*) MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0));
|
||||||
|
if (!data) {
|
||||||
|
#if DEBUG_OUTPUT
|
||||||
|
OutputLastError("Couldn't MapViewOfFile.\n");
|
||||||
|
#endif
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
SIZE_T locationDelta;
|
||||||
|
|
||||||
|
PIMAGE_DOS_HEADER dos_header = (PIMAGE_DOS_HEADER)data.get();
|
||||||
|
if (dos_header->e_magic != IMAGE_DOS_SIGNATURE) {
|
||||||
|
#if DEBUG_OUTPUT
|
||||||
|
OutputDebugStringA("Not a valid executable file.\n");
|
||||||
|
#endif
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
PIMAGE_NT_HEADERS old_header = (PIMAGE_NT_HEADERS)(data + dos_header->e_lfanew);
|
||||||
|
if (old_header->Signature != IMAGE_NT_SIGNATURE) {
|
||||||
|
#if DEBUG_OUTPUT
|
||||||
|
OutputDebugStringA("No PE header found.\n");
|
||||||
|
#endif
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// reserve memory for image of library in this process and the target process
|
||||||
|
unsigned char* localCode = (unsigned char*) VirtualAlloc(NULL,
|
||||||
|
old_header->OptionalHeader.SizeOfImage,
|
||||||
|
MEM_RESERVE | MEM_COMMIT,
|
||||||
|
PAGE_READWRITE);
|
||||||
|
if (!localCode) {
|
||||||
|
#if DEBUG_OUTPUT
|
||||||
|
OutputLastError("Can't reserve local memory.");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char* remoteCode = (unsigned char*) VirtualAllocEx(hRemoteProcess, NULL,
|
||||||
|
old_header->OptionalHeader.SizeOfImage,
|
||||||
|
MEM_RESERVE,
|
||||||
|
PAGE_EXECUTE_READ);
|
||||||
|
if (!remoteCode) {
|
||||||
|
#if DEBUG_OUTPUT
|
||||||
|
OutputLastError("Can't reserve remote memory.");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
MEMORYMODULE result;
|
||||||
|
result.localCodeBase = localCode;
|
||||||
|
result.remoteCodeBase = remoteCode;
|
||||||
|
result.numModules = 0;
|
||||||
|
result.modules = NULL;
|
||||||
|
|
||||||
|
// copy PE header to code
|
||||||
|
memcpy(localCode, dos_header, dos_header->e_lfanew + old_header->OptionalHeader.SizeOfHeaders);
|
||||||
|
result.headers = reinterpret_cast<PIMAGE_NT_HEADERS>(localCode + dos_header->e_lfanew);
|
||||||
|
|
||||||
|
// update position
|
||||||
|
result.headers->OptionalHeader.ImageBase = (POINTER_TYPE)remoteCode;
|
||||||
|
|
||||||
|
// copy sections from DLL file block to new memory location
|
||||||
|
CopySections(data, old_header, &result);
|
||||||
|
|
||||||
|
// adjust base address of imported data
|
||||||
|
locationDelta = (SIZE_T)(remoteCode - old_header->OptionalHeader.ImageBase);
|
||||||
|
if (locationDelta != 0) {
|
||||||
|
PerformBaseRelocation(&result, locationDelta);
|
||||||
|
}
|
||||||
|
|
||||||
|
// load required dlls and adjust function table of imports
|
||||||
|
if (!BuildImportTable(&result)) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// mark memory pages depending on section headers and release
|
||||||
|
// sections that are marked as "discardable"
|
||||||
|
if (!FinalizeSections(&result, hRemoteProcess)) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return MemoryGetProcAddress(&result, symbol);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void* MemoryGetProcAddress(PMEMORYMODULE module, const char *name)
|
||||||
|
{
|
||||||
|
unsigned char *localCodeBase = module->localCodeBase;
|
||||||
|
int idx=-1;
|
||||||
|
DWORD i, *nameRef;
|
||||||
|
WORD *ordinal;
|
||||||
|
PIMAGE_EXPORT_DIRECTORY exports;
|
||||||
|
PIMAGE_DATA_DIRECTORY directory = GET_HEADER_DICTIONARY(module, IMAGE_DIRECTORY_ENTRY_EXPORT);
|
||||||
|
if (directory->Size == 0) {
|
||||||
|
// no export table found
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
exports = (PIMAGE_EXPORT_DIRECTORY) (localCodeBase + directory->VirtualAddress);
|
||||||
|
if (exports->NumberOfNames == 0 || exports->NumberOfFunctions == 0) {
|
||||||
|
// DLL doesn't export anything
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// search function name in list of exported names
|
||||||
|
nameRef = (DWORD *) (localCodeBase + exports->AddressOfNames);
|
||||||
|
ordinal = (WORD *) (localCodeBase + exports->AddressOfNameOrdinals);
|
||||||
|
for (i=0; i<exports->NumberOfNames; i++, nameRef++, ordinal++) {
|
||||||
|
if (stricmp(name, (const char *) (localCodeBase + (*nameRef))) == 0) {
|
||||||
|
idx = *ordinal;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (idx == -1) {
|
||||||
|
// exported symbol not found
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((DWORD)idx > exports->NumberOfFunctions) {
|
||||||
|
// name <-> ordinal number don't match
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddressOfFunctions contains the RVAs to the "real" functions
|
||||||
|
return (FARPROC) (module->remoteCodeBase + (*(DWORD *) (localCodeBase + exports->AddressOfFunctions + (idx*4))));
|
||||||
|
}
|
24
toolkit/crashreporter/LoadLibraryRemote.h
Normal file
24
toolkit/crashreporter/LoadLibraryRemote.h
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
/* 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 LoadLibraryRemote_h
|
||||||
|
#define LoadLibraryRemote_h
|
||||||
|
|
||||||
|
#include <windows.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Inject a library into a remote process. This injection has the following
|
||||||
|
* restrictions:
|
||||||
|
*
|
||||||
|
* - The DLL being injected must only depend on kernel32 and user32.
|
||||||
|
* - The entry point of the DLL is not run. If the DLL uses the CRT, it is
|
||||||
|
* the responsibility of the caller to make sure that _CRT_INIT is called.
|
||||||
|
* - There is no support for unloading a library once it has been loaded.
|
||||||
|
* - The symbol must be a named symbol and not an ordinal.
|
||||||
|
*/
|
||||||
|
void* LoadRemoteLibraryAndGetAddress(HANDLE hRemoteProcess,
|
||||||
|
const WCHAR* library,
|
||||||
|
const char* symbol);
|
||||||
|
|
||||||
|
#endif // LoadLibraryRemote_h
|
@ -14,12 +14,10 @@ LIBXUL_LIBRARY = 1
|
|||||||
LIBRARY_NAME = exception_handler_s
|
LIBRARY_NAME = exception_handler_s
|
||||||
|
|
||||||
ifeq ($(OS_ARCH),WINNT)
|
ifeq ($(OS_ARCH),WINNT)
|
||||||
DIRS += \
|
DIRS += breakpad-windows-libxul
|
||||||
google-breakpad/src/common/windows \
|
ifdef MOZ_CRASHREPORTER_INJECTOR
|
||||||
google-breakpad/src/client/windows/handler \
|
DIRS += breakpad-windows-standalone
|
||||||
google-breakpad/src/client/windows/sender \
|
endif
|
||||||
google-breakpad/src/client/windows/crash_generation \
|
|
||||||
$(NULL)
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(OS_ARCH),Darwin)
|
ifeq ($(OS_ARCH),Darwin)
|
||||||
@ -74,6 +72,10 @@ endif
|
|||||||
|
|
||||||
DIRS += client
|
DIRS += client
|
||||||
|
|
||||||
|
ifdef MOZ_CRASHREPORTER_INJECTOR
|
||||||
|
DIRS += injector
|
||||||
|
endif
|
||||||
|
|
||||||
LOCAL_INCLUDES = -I$(srcdir)/google-breakpad/src
|
LOCAL_INCLUDES = -I$(srcdir)/google-breakpad/src
|
||||||
DEFINES += -DUNICODE -D_UNICODE
|
DEFINES += -DUNICODE -D_UNICODE
|
||||||
|
|
||||||
@ -85,6 +87,13 @@ CPPSRCS = \
|
|||||||
nsExceptionHandler.cpp \
|
nsExceptionHandler.cpp \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
|
|
||||||
|
ifdef MOZ_CRASHREPORTER_INJECTOR
|
||||||
|
CPPSRCS += \
|
||||||
|
LoadLibraryRemote.cpp \
|
||||||
|
InjectCrashReporter.cpp \
|
||||||
|
$(NULL)
|
||||||
|
endif
|
||||||
|
|
||||||
FORCE_STATIC_LIB = 1
|
FORCE_STATIC_LIB = 1
|
||||||
|
|
||||||
EXTRA_JS_MODULES = \
|
EXTRA_JS_MODULES = \
|
||||||
|
41
toolkit/crashreporter/breakpad-windows-libxul/Makefile.in
Normal file
41
toolkit/crashreporter/breakpad-windows-libxul/Makefile.in
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
# 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/.
|
||||||
|
|
||||||
|
DEPTH = ../../..
|
||||||
|
topsrcdir = @top_srcdir@
|
||||||
|
srcdir = @srcdir@
|
||||||
|
VPATH = @srcdir@
|
||||||
|
|
||||||
|
include $(DEPTH)/config/autoconf.mk
|
||||||
|
|
||||||
|
LIBRARY_NAME = google_breakpad_libxul_s
|
||||||
|
FORCE_STATIC_LIB = 1
|
||||||
|
|
||||||
|
STL_FLAGS =
|
||||||
|
|
||||||
|
LOCAL_INCLUDES = -I$(topsrcdir)/toolkit/crashreporter/google-breakpad/src
|
||||||
|
|
||||||
|
include $(topsrcdir)/toolkit/crashreporter/google-breakpad/src/common/windows/objs.mk
|
||||||
|
include $(topsrcdir)/toolkit/crashreporter/google-breakpad/src/client/windows/handler/objs.mk
|
||||||
|
include $(topsrcdir)/toolkit/crashreporter/google-breakpad/src/client/windows/sender/objs.mk
|
||||||
|
include $(topsrcdir)/toolkit/crashreporter/google-breakpad/src/client/windows/crash_generation/objs.mk
|
||||||
|
|
||||||
|
VPATH += \
|
||||||
|
$(topsrcdir)/toolkit/crashreporter/google-breakpad/src/common/windows \
|
||||||
|
$(topsrcdir)/toolkit/crashreporter/google-breakpad/src/client/windows/handler \
|
||||||
|
$(topsrcdir)/toolkit/crashreporter/google-breakpad/src/client/windows/sender \
|
||||||
|
$(topsrcdir)/toolkit/crashreporter/google-breakpad/src/client/windows/crash_generation \
|
||||||
|
$(NULL)
|
||||||
|
|
||||||
|
CPPSRCS = \
|
||||||
|
$(objs_common) \
|
||||||
|
$(objs_handler) \
|
||||||
|
$(objs_sender) \
|
||||||
|
$(objs_crash_generation) \
|
||||||
|
http_upload.cc \ # required for the libxul version but not standalone
|
||||||
|
$(NULL)
|
||||||
|
|
||||||
|
DEFINES += -DUNICODE -DUNICODE_ -DBREAKPAD_NO_TERMINATE_THREAD -DNOMINMAX
|
||||||
|
|
||||||
|
include $(topsrcdir)/config/rules.mk
|
@ -0,0 +1,39 @@
|
|||||||
|
# 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/.
|
||||||
|
|
||||||
|
DEPTH = ../../..
|
||||||
|
topsrcdir = @top_srcdir@
|
||||||
|
srcdir = @srcdir@
|
||||||
|
VPATH = @srcdir@
|
||||||
|
|
||||||
|
include $(DEPTH)/config/autoconf.mk
|
||||||
|
|
||||||
|
LIBRARY_NAME = google_breakpad_standalone_s
|
||||||
|
FORCE_STATIC_LIB = 1
|
||||||
|
USE_STATIC_LIBS = 1
|
||||||
|
MOZ_GLUE_LDFLAGS =
|
||||||
|
|
||||||
|
STL_FLAGS =
|
||||||
|
|
||||||
|
LOCAL_INCLUDES = -I$(topsrcdir)/toolkit/crashreporter/google-breakpad/src
|
||||||
|
|
||||||
|
include $(topsrcdir)/toolkit/crashreporter/google-breakpad/src/common/windows/objs.mk
|
||||||
|
include $(topsrcdir)/toolkit/crashreporter/google-breakpad/src/client/windows/handler/objs.mk
|
||||||
|
include $(topsrcdir)/toolkit/crashreporter/google-breakpad/src/client/windows/crash_generation/objs.mk
|
||||||
|
|
||||||
|
VPATH += \
|
||||||
|
$(topsrcdir)/toolkit/crashreporter/google-breakpad/src/common/windows \
|
||||||
|
$(topsrcdir)/toolkit/crashreporter/google-breakpad/src/client/windows/handler \
|
||||||
|
$(topsrcdir)/toolkit/crashreporter/google-breakpad/src/client/windows/crash_generation \
|
||||||
|
$(NULL)
|
||||||
|
|
||||||
|
CPPSRCS = \
|
||||||
|
$(objs_common) \
|
||||||
|
$(objs_handler) \
|
||||||
|
$(objs_crash_generation) \
|
||||||
|
$(NULL)
|
||||||
|
|
||||||
|
DEFINES += -DUNICODE -DUNICODE_ -DBREAKPAD_NO_TERMINATE_THREAD -DNOMINMAX
|
||||||
|
|
||||||
|
include $(topsrcdir)/config/rules.mk
|
@ -37,8 +37,7 @@ CPPSRCS = \
|
|||||||
ifeq ($(OS_ARCH),WINNT)
|
ifeq ($(OS_ARCH),WINNT)
|
||||||
CPPSRCS += crashreporter_win.cpp
|
CPPSRCS += crashreporter_win.cpp
|
||||||
LIBS += \
|
LIBS += \
|
||||||
$(DEPTH)/toolkit/crashreporter/google-breakpad/src/client/windows/sender/$(LIB_PREFIX)crash_report_sender_s.$(LIB_SUFFIX) \
|
$(DEPTH)/toolkit/crashreporter/breakpad-windows-libxul/$(LIB_PREFIX)google_breakpad_libxul_s.$(LIB_SUFFIX)
|
||||||
$(DEPTH)/toolkit/crashreporter/google-breakpad/src/common/windows/$(LIB_PREFIX)breakpad_windows_common_s.$(LIB_SUFFIX) \
|
|
||||||
$(NULL)
|
$(NULL)
|
||||||
LOCAL_INCLUDES += -I$(srcdir)
|
LOCAL_INCLUDES += -I$(srcdir)
|
||||||
RCINCLUDE = crashreporter.rc
|
RCINCLUDE = crashreporter.rc
|
||||||
|
@ -1,28 +0,0 @@
|
|||||||
# 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/.
|
|
||||||
|
|
||||||
DEPTH = ../../../../../../..
|
|
||||||
topsrcdir = @top_srcdir@
|
|
||||||
srcdir = @srcdir@
|
|
||||||
VPATH = @srcdir@
|
|
||||||
|
|
||||||
include $(DEPTH)/config/autoconf.mk
|
|
||||||
|
|
||||||
MODULE = crash_generation
|
|
||||||
LIBRARY_NAME = crash_generation_s
|
|
||||||
|
|
||||||
LOCAL_INCLUDES = -I$(topsrcdir)/toolkit/crashreporter/google-breakpad/src
|
|
||||||
DEFINES += -DUNICODE -D_UNICODE
|
|
||||||
|
|
||||||
CPPSRCS = \
|
|
||||||
client_info.cc \
|
|
||||||
crash_generation_client.cc \
|
|
||||||
crash_generation_server.cc \
|
|
||||||
minidump_generator.cc \
|
|
||||||
$(NULL)
|
|
||||||
|
|
||||||
# need static lib
|
|
||||||
FORCE_STATIC_LIB = 1
|
|
||||||
|
|
||||||
include $(topsrcdir)/config/rules.mk
|
|
@ -95,6 +95,27 @@ CrashGenerationClient::CrashGenerationClient(
|
|||||||
MINIDUMP_TYPE dump_type,
|
MINIDUMP_TYPE dump_type,
|
||||||
const CustomClientInfo* custom_info)
|
const CustomClientInfo* custom_info)
|
||||||
: pipe_name_(pipe_name),
|
: pipe_name_(pipe_name),
|
||||||
|
pipe_handle_(NULL),
|
||||||
|
dump_type_(dump_type),
|
||||||
|
thread_id_(0),
|
||||||
|
server_process_id_(0),
|
||||||
|
crash_event_(NULL),
|
||||||
|
crash_generated_(NULL),
|
||||||
|
server_alive_(NULL),
|
||||||
|
exception_pointers_(NULL),
|
||||||
|
custom_info_() {
|
||||||
|
memset(&assert_info_, 0, sizeof(assert_info_));
|
||||||
|
if (custom_info) {
|
||||||
|
custom_info_ = *custom_info;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CrashGenerationClient::CrashGenerationClient(
|
||||||
|
HANDLE pipe_handle,
|
||||||
|
MINIDUMP_TYPE dump_type,
|
||||||
|
const CustomClientInfo* custom_info)
|
||||||
|
: pipe_name_(),
|
||||||
|
pipe_handle_(pipe_handle),
|
||||||
dump_type_(dump_type),
|
dump_type_(dump_type),
|
||||||
thread_id_(0),
|
thread_id_(0),
|
||||||
server_process_id_(0),
|
server_process_id_(0),
|
||||||
@ -231,6 +252,12 @@ bool CrashGenerationClient::RegisterClient(HANDLE pipe) {
|
|||||||
HANDLE CrashGenerationClient::ConnectToPipe(const wchar_t* pipe_name,
|
HANDLE CrashGenerationClient::ConnectToPipe(const wchar_t* pipe_name,
|
||||||
DWORD pipe_access,
|
DWORD pipe_access,
|
||||||
DWORD flags_attrs) {
|
DWORD flags_attrs) {
|
||||||
|
if (pipe_handle_) {
|
||||||
|
HANDLE t = pipe_handle_;
|
||||||
|
pipe_handle_ = NULL;
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
for (int i = 0; i < kPipeConnectMaxAttempts; ++i) {
|
for (int i = 0; i < kPipeConnectMaxAttempts; ++i) {
|
||||||
HANDLE pipe = CreateFile(pipe_name,
|
HANDLE pipe = CreateFile(pipe_name,
|
||||||
pipe_access,
|
pipe_access,
|
||||||
@ -325,4 +352,33 @@ bool CrashGenerationClient::SignalCrashEventAndWait() {
|
|||||||
return result == WAIT_OBJECT_0;
|
return result == WAIT_OBJECT_0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
HANDLE CrashGenerationClient::DuplicatePipeToClientProcess(const wchar_t* pipe_name,
|
||||||
|
HANDLE hProcess) {
|
||||||
|
for (int i = 0; i < kPipeConnectMaxAttempts; ++i) {
|
||||||
|
HANDLE local_pipe = CreateFile(pipe_name, kPipeDesiredAccess,
|
||||||
|
0, NULL, OPEN_EXISTING,
|
||||||
|
kPipeFlagsAndAttributes, NULL);
|
||||||
|
if (local_pipe != INVALID_HANDLE_VALUE) {
|
||||||
|
HANDLE remotePipe = INVALID_HANDLE_VALUE;
|
||||||
|
if (DuplicateHandle(GetCurrentProcess(), local_pipe,
|
||||||
|
hProcess, &remotePipe, 0, FALSE,
|
||||||
|
DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS)) {
|
||||||
|
return remotePipe;
|
||||||
|
} else {
|
||||||
|
return INVALID_HANDLE_VALUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cannot continue retrying if the error wasn't a busy pipe.
|
||||||
|
if (GetLastError() != ERROR_PIPE_BUSY) {
|
||||||
|
return INVALID_HANDLE_VALUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!WaitNamedPipe(pipe_name, kPipeBusyWaitTimeoutMs)) {
|
||||||
|
return INVALID_HANDLE_VALUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return INVALID_HANDLE_VALUE;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace google_breakpad
|
} // namespace google_breakpad
|
||||||
|
@ -66,6 +66,10 @@ class CrashGenerationClient {
|
|||||||
MINIDUMP_TYPE dump_type,
|
MINIDUMP_TYPE dump_type,
|
||||||
const CustomClientInfo* custom_info);
|
const CustomClientInfo* custom_info);
|
||||||
|
|
||||||
|
CrashGenerationClient(HANDLE pipe_handle,
|
||||||
|
MINIDUMP_TYPE dump_type,
|
||||||
|
const CustomClientInfo* custom_info);
|
||||||
|
|
||||||
~CrashGenerationClient();
|
~CrashGenerationClient();
|
||||||
|
|
||||||
// Registers the client process with the crash server.
|
// Registers the client process with the crash server.
|
||||||
@ -92,6 +96,14 @@ class CrashGenerationClient {
|
|||||||
// false will be returned.
|
// false will be returned.
|
||||||
bool RequestDump(MDRawAssertionInfo* assert_info);
|
bool RequestDump(MDRawAssertionInfo* assert_info);
|
||||||
|
|
||||||
|
// If the crash generation client is running in a sandbox that prevents it
|
||||||
|
// from opening the named pipe directly, the server process may open the
|
||||||
|
// handle and duplicate it into the client process with this helper method.
|
||||||
|
// Returns INVALID_HANDLE_VALUE on failure. The process must have been opened
|
||||||
|
// with the PROCESS_DUP_HANDLE access right.
|
||||||
|
static HANDLE DuplicatePipeToClientProcess(const wchar_t* pipe_name,
|
||||||
|
HANDLE hProcess);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Connects to the appropriate pipe and sets the pipe handle state.
|
// Connects to the appropriate pipe and sets the pipe handle state.
|
||||||
//
|
//
|
||||||
@ -123,6 +135,10 @@ class CrashGenerationClient {
|
|||||||
// Pipe name to use to talk to server.
|
// Pipe name to use to talk to server.
|
||||||
std::wstring pipe_name_;
|
std::wstring pipe_name_;
|
||||||
|
|
||||||
|
// Pipe handle duplicated from server process. Only valid before
|
||||||
|
// Register is called.
|
||||||
|
HANDLE pipe_handle_;
|
||||||
|
|
||||||
// Custom client information
|
// Custom client information
|
||||||
CustomClientInfo custom_info_;
|
CustomClientInfo custom_info_;
|
||||||
|
|
||||||
|
@ -0,0 +1,6 @@
|
|||||||
|
objs_crash_generation = \
|
||||||
|
client_info.cc \
|
||||||
|
crash_generation_client.cc \
|
||||||
|
crash_generation_server.cc \
|
||||||
|
minidump_generator.cc \
|
||||||
|
$(NULL)
|
@ -1,26 +0,0 @@
|
|||||||
# 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/.
|
|
||||||
|
|
||||||
DEPTH = ../../../../../../..
|
|
||||||
topsrcdir = @top_srcdir@
|
|
||||||
srcdir = @srcdir@
|
|
||||||
VPATH = @srcdir@
|
|
||||||
|
|
||||||
include $(DEPTH)/config/autoconf.mk
|
|
||||||
|
|
||||||
MODULE = handler
|
|
||||||
LIBRARY_NAME = exception_handler_s
|
|
||||||
XPI_NAME = crashreporter
|
|
||||||
|
|
||||||
LOCAL_INCLUDES = -I$(topsrcdir)/toolkit/crashreporter/google-breakpad/src
|
|
||||||
DEFINES += -DUNICODE -D_UNICODE -DBREAKPAD_NO_TERMINATE_THREAD -DNOMINMAX
|
|
||||||
|
|
||||||
CPPSRCS = \
|
|
||||||
exception_handler.cc \
|
|
||||||
$(NULL)
|
|
||||||
|
|
||||||
# need static lib
|
|
||||||
FORCE_STATIC_LIB = 1
|
|
||||||
|
|
||||||
include $(topsrcdir)/config/rules.mk
|
|
@ -156,9 +156,29 @@ ExceptionHandler::ExceptionHandler(const wstring& dump_path,
|
|||||||
handler_types,
|
handler_types,
|
||||||
dump_type,
|
dump_type,
|
||||||
pipe_name,
|
pipe_name,
|
||||||
|
NULL,
|
||||||
custom_info);
|
custom_info);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ExceptionHandler::ExceptionHandler(const wstring& dump_path,
|
||||||
|
FilterCallback filter,
|
||||||
|
MinidumpCallback callback,
|
||||||
|
void* callback_context,
|
||||||
|
int handler_types,
|
||||||
|
MINIDUMP_TYPE dump_type,
|
||||||
|
HANDLE pipe_handle,
|
||||||
|
const CustomClientInfo* custom_info) {
|
||||||
|
Initialize(dump_path,
|
||||||
|
filter,
|
||||||
|
callback,
|
||||||
|
callback_context,
|
||||||
|
handler_types,
|
||||||
|
dump_type,
|
||||||
|
NULL,
|
||||||
|
pipe_handle,
|
||||||
|
custom_info);
|
||||||
|
}
|
||||||
|
|
||||||
ExceptionHandler::ExceptionHandler(const wstring &dump_path,
|
ExceptionHandler::ExceptionHandler(const wstring &dump_path,
|
||||||
FilterCallback filter,
|
FilterCallback filter,
|
||||||
MinidumpCallback callback,
|
MinidumpCallback callback,
|
||||||
@ -171,6 +191,7 @@ ExceptionHandler::ExceptionHandler(const wstring &dump_path,
|
|||||||
handler_types,
|
handler_types,
|
||||||
MiniDumpNormal,
|
MiniDumpNormal,
|
||||||
NULL,
|
NULL,
|
||||||
|
NULL,
|
||||||
NULL);
|
NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -181,6 +202,7 @@ void ExceptionHandler::Initialize(const wstring& dump_path,
|
|||||||
int handler_types,
|
int handler_types,
|
||||||
MINIDUMP_TYPE dump_type,
|
MINIDUMP_TYPE dump_type,
|
||||||
const wchar_t* pipe_name,
|
const wchar_t* pipe_name,
|
||||||
|
HANDLE pipe_handle,
|
||||||
const CustomClientInfo* custom_info) {
|
const CustomClientInfo* custom_info) {
|
||||||
LONG instance_count = InterlockedIncrement(&instance_count_);
|
LONG instance_count = InterlockedIncrement(&instance_count_);
|
||||||
filter_ = filter;
|
filter_ = filter;
|
||||||
@ -210,12 +232,22 @@ void ExceptionHandler::Initialize(const wstring& dump_path,
|
|||||||
handler_return_value_ = false;
|
handler_return_value_ = false;
|
||||||
handle_debug_exceptions_ = false;
|
handle_debug_exceptions_ = false;
|
||||||
|
|
||||||
// Attempt to use out-of-process if user has specified pipe name.
|
// Attempt to use out-of-process if user has specified a pipe.
|
||||||
if (pipe_name != NULL) {
|
if (pipe_name != NULL || pipe_handle != NULL) {
|
||||||
scoped_ptr<CrashGenerationClient> client(
|
assert(!(pipe_name && pipe_handle));
|
||||||
|
|
||||||
|
scoped_ptr<CrashGenerationClient> client;
|
||||||
|
if (pipe_name) {
|
||||||
|
client.reset(
|
||||||
new CrashGenerationClient(pipe_name,
|
new CrashGenerationClient(pipe_name,
|
||||||
dump_type_,
|
dump_type_,
|
||||||
custom_info));
|
custom_info));
|
||||||
|
} else {
|
||||||
|
client.reset(
|
||||||
|
new CrashGenerationClient(pipe_handle,
|
||||||
|
dump_type_,
|
||||||
|
custom_info));
|
||||||
|
}
|
||||||
|
|
||||||
// If successful in registering with the monitoring process,
|
// If successful in registering with the monitoring process,
|
||||||
// there is no need to setup in-process crash generation.
|
// there is no need to setup in-process crash generation.
|
||||||
|
@ -164,7 +164,7 @@ class ExceptionHandler {
|
|||||||
void* callback_context,
|
void* callback_context,
|
||||||
int handler_types);
|
int handler_types);
|
||||||
|
|
||||||
// Creates a new ExcetpionHandler instance that can attempt to perform
|
// Creates a new ExceptionHandler instance that can attempt to perform
|
||||||
// out-of-process dump generation if pipe_name is not NULL. If pipe_name is
|
// out-of-process dump generation if pipe_name is not NULL. If pipe_name is
|
||||||
// NULL, or if out-of-process dump generation registration step fails,
|
// NULL, or if out-of-process dump generation registration step fails,
|
||||||
// in-process dump generation will be used. This also allows specifying
|
// in-process dump generation will be used. This also allows specifying
|
||||||
@ -178,6 +178,17 @@ class ExceptionHandler {
|
|||||||
const wchar_t* pipe_name,
|
const wchar_t* pipe_name,
|
||||||
const CustomClientInfo* custom_info);
|
const CustomClientInfo* custom_info);
|
||||||
|
|
||||||
|
// As above, creates a new ExceptionHandler instance to perform
|
||||||
|
// out-of-process dump generation if the given pipe_handle is not NULL.
|
||||||
|
ExceptionHandler(const wstring& dump_path,
|
||||||
|
FilterCallback filter,
|
||||||
|
MinidumpCallback callback,
|
||||||
|
void* callback_context,
|
||||||
|
int handler_types,
|
||||||
|
MINIDUMP_TYPE dump_type,
|
||||||
|
HANDLE pipe_handle,
|
||||||
|
const CustomClientInfo* custom_info);
|
||||||
|
|
||||||
~ExceptionHandler();
|
~ExceptionHandler();
|
||||||
|
|
||||||
// Get and set the minidump path.
|
// Get and set the minidump path.
|
||||||
@ -253,6 +264,7 @@ class ExceptionHandler {
|
|||||||
int handler_types,
|
int handler_types,
|
||||||
MINIDUMP_TYPE dump_type,
|
MINIDUMP_TYPE dump_type,
|
||||||
const wchar_t* pipe_name,
|
const wchar_t* pipe_name,
|
||||||
|
HANDLE pipe_handle,
|
||||||
const CustomClientInfo* custom_info);
|
const CustomClientInfo* custom_info);
|
||||||
|
|
||||||
// Function pointer type for MiniDumpWriteDump, which is looked up
|
// Function pointer type for MiniDumpWriteDump, which is looked up
|
||||||
|
@ -0,0 +1 @@
|
|||||||
|
objs_handler = exception_handler.cc
|
@ -1,26 +0,0 @@
|
|||||||
# 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/.
|
|
||||||
|
|
||||||
DEPTH = ../../../../../../..
|
|
||||||
topsrcdir = @top_srcdir@
|
|
||||||
srcdir = @srcdir@
|
|
||||||
VPATH = @srcdir@
|
|
||||||
|
|
||||||
include $(DEPTH)/config/autoconf.mk
|
|
||||||
|
|
||||||
MODULE = sender
|
|
||||||
LIBRARY_NAME = crash_report_sender_s
|
|
||||||
|
|
||||||
LOCAL_INCLUDES = -I$(srcdir)/../../..
|
|
||||||
DEFINES += -DUNICODE -D_UNICODE
|
|
||||||
STL_FLAGS =
|
|
||||||
|
|
||||||
CPPSRCS = \
|
|
||||||
crash_report_sender.cc \
|
|
||||||
$(NULL)
|
|
||||||
|
|
||||||
# need static lib
|
|
||||||
FORCE_STATIC_LIB = 1
|
|
||||||
|
|
||||||
include $(topsrcdir)/config/rules.mk
|
|
@ -0,0 +1 @@
|
|||||||
|
objs_sender = crash_report_sender.cc
|
@ -1,28 +0,0 @@
|
|||||||
# 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/.
|
|
||||||
|
|
||||||
DEPTH = ../../../../../..
|
|
||||||
topsrcdir = @top_srcdir@
|
|
||||||
srcdir = @srcdir@
|
|
||||||
VPATH = @srcdir@
|
|
||||||
|
|
||||||
include $(DEPTH)/config/autoconf.mk
|
|
||||||
|
|
||||||
MODULE = breakpad_windows_common
|
|
||||||
LIBRARY_NAME = breakpad_windows_common_s
|
|
||||||
|
|
||||||
LOCAL_INCLUDES = -I$(srcdir)/../..
|
|
||||||
DEFINES += -DUNICODE -D_UNICODE
|
|
||||||
STL_FLAGS =
|
|
||||||
|
|
||||||
CPPSRCS = \
|
|
||||||
guid_string.cc \
|
|
||||||
http_upload.cc \
|
|
||||||
string_utils.cc \
|
|
||||||
$(NULL)
|
|
||||||
|
|
||||||
# need static lib
|
|
||||||
FORCE_STATIC_LIB = 1
|
|
||||||
|
|
||||||
include $(topsrcdir)/config/rules.mk
|
|
@ -0,0 +1,4 @@
|
|||||||
|
objs_common = \
|
||||||
|
guid_string.cc \
|
||||||
|
string_utils.cc \
|
||||||
|
$(NULL)
|
27
toolkit/crashreporter/injector/Makefile.in
Normal file
27
toolkit/crashreporter/injector/Makefile.in
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
# 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/.
|
||||||
|
|
||||||
|
DEPTH = ../../..
|
||||||
|
topsrcdir = @top_srcdir@
|
||||||
|
srcdir = @srcdir@
|
||||||
|
VPATH = @srcdir@
|
||||||
|
|
||||||
|
include $(DEPTH)/config/autoconf.mk
|
||||||
|
|
||||||
|
LIBRARY_NAME = breakpadinjector
|
||||||
|
FORCE_SHARED_LIB = 1
|
||||||
|
USE_STATIC_LIBS = 1
|
||||||
|
STL_FLAGS =
|
||||||
|
MOZ_GLUE_LDFLAGS =
|
||||||
|
|
||||||
|
CPPSRCS = injector.cpp
|
||||||
|
|
||||||
|
SHARED_LIBRARY_LIBS += ../breakpad-windows-standalone/$(LIB_PREFIX)google_breakpad_standalone_s.$(LIB_SUFFIX)
|
||||||
|
|
||||||
|
include $(topsrcdir)/config/config.mk
|
||||||
|
include $(topsrcdir)/ipc/chromium/chromium-config.mk
|
||||||
|
include $(topsrcdir)/config/rules.mk
|
||||||
|
|
||||||
|
LOCAL_INCLUDES += -I$(topsrcdir)/toolkit/crashreporter/google-breakpad/src
|
||||||
|
LDFLAGS += -ENTRY:DummyEntryPoint
|
40
toolkit/crashreporter/injector/injector.cpp
Normal file
40
toolkit/crashreporter/injector/injector.cpp
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
/* 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 "client/windows/handler/exception_handler.h"
|
||||||
|
|
||||||
|
using google_breakpad::ExceptionHandler;
|
||||||
|
using std::wstring;
|
||||||
|
|
||||||
|
BOOL WINAPI DummyEntryPoint(HINSTANCE instance,
|
||||||
|
DWORD reason,
|
||||||
|
void* reserved)
|
||||||
|
{
|
||||||
|
__debugbreak();
|
||||||
|
|
||||||
|
return FALSE; // We're being loaded remotely, this shouldn't happen!
|
||||||
|
}
|
||||||
|
|
||||||
|
// support.microsoft.com/kb/94248
|
||||||
|
extern "C" BOOL WINAPI _CRT_INIT(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved);
|
||||||
|
|
||||||
|
extern "C"
|
||||||
|
__declspec(dllexport) DWORD Start(void* context)
|
||||||
|
{
|
||||||
|
// Because the remote DLL injector does not call DllMain, we have to
|
||||||
|
// initialize the CRT manually
|
||||||
|
_CRT_INIT(NULL, DLL_PROCESS_ATTACH, NULL);
|
||||||
|
|
||||||
|
HANDLE hCrashPipe = reinterpret_cast<HANDLE>(context);
|
||||||
|
|
||||||
|
ExceptionHandler* e = new (std::nothrow)
|
||||||
|
ExceptionHandler(wstring(), NULL, NULL, NULL,
|
||||||
|
ExceptionHandler::HANDLER_ALL,
|
||||||
|
MiniDumpNormal, hCrashPipe, NULL);
|
||||||
|
if (e)
|
||||||
|
e->set_handle_debug_exceptions(true);
|
||||||
|
return 1;
|
||||||
|
}
|
@ -62,6 +62,11 @@
|
|||||||
#error "Not yet implemented for this platform"
|
#error "Not yet implemented for this platform"
|
||||||
#endif // defined(XP_WIN32)
|
#endif // defined(XP_WIN32)
|
||||||
|
|
||||||
|
#ifdef MOZ_CRASHREPORTER_INJECTOR
|
||||||
|
#include "InjectCrashReporter.h"
|
||||||
|
using mozilla::InjectCrashRunnable;
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <prenv.h>
|
#include <prenv.h>
|
||||||
@ -219,6 +224,23 @@ static Mutex* dumpMapLock;
|
|||||||
typedef nsInterfaceHashtable<nsUint32HashKey, nsIFile> ChildMinidumpMap;
|
typedef nsInterfaceHashtable<nsUint32HashKey, nsIFile> ChildMinidumpMap;
|
||||||
static ChildMinidumpMap* pidToMinidump;
|
static ChildMinidumpMap* pidToMinidump;
|
||||||
|
|
||||||
|
#ifdef MOZ_CRASHREPORTER_INJECTOR
|
||||||
|
static nsIThread* sInjectorThread;
|
||||||
|
typedef nsDataHashtable<nsUint32HashKey, InjectorCrashCallback*> InjectorPIDMap;
|
||||||
|
static InjectorPIDMap* pidToInjectorCallback;
|
||||||
|
|
||||||
|
class ReportInjectedCrash : public nsRunnable
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ReportInjectedCrash(PRUint32 pid) : mPID(pid) { }
|
||||||
|
|
||||||
|
NS_IMETHOD Run();
|
||||||
|
|
||||||
|
private:
|
||||||
|
PRUint32 mPID;
|
||||||
|
};
|
||||||
|
#endif // MOZ_CRASHREPORTER_INJECTOR
|
||||||
|
|
||||||
// Crashreporter annotations that we don't send along in subprocess
|
// Crashreporter annotations that we don't send along in subprocess
|
||||||
// reports
|
// reports
|
||||||
static const char* kSubprocessBlacklist[] = {
|
static const char* kSubprocessBlacklist[] = {
|
||||||
@ -808,7 +830,7 @@ nsresult SetExceptionHandler(nsIFile* aXREDirectory,
|
|||||||
#if defined(XP_WIN32)
|
#if defined(XP_WIN32)
|
||||||
google_breakpad::ExceptionHandler::HANDLER_ALL,
|
google_breakpad::ExceptionHandler::HANDLER_ALL,
|
||||||
minidump_type,
|
minidump_type,
|
||||||
NULL,
|
(const wchar_t*) NULL,
|
||||||
NULL);
|
NULL);
|
||||||
#else
|
#else
|
||||||
true
|
true
|
||||||
@ -1911,8 +1933,13 @@ OnChildProcessDumpRequested(void* aContext,
|
|||||||
aClientInfo->pid();
|
aClientInfo->pid();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
MutexAutoLock lock(*dumpMapLock);
|
{
|
||||||
pidToMinidump->Put(pid, minidump);
|
MutexAutoLock lock(*dumpMapLock);
|
||||||
|
pidToMinidump->Put(pid, minidump);
|
||||||
|
}
|
||||||
|
#ifdef MOZ_CRASHREPORTER_INJECTOR
|
||||||
|
NS_DispatchToMainThread(new ReportInjectedCrash(pid));
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2002,6 +2029,16 @@ OOPDeinit()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef MOZ_CRASHREPORTER_INJECTOR
|
||||||
|
if (sInjectorThread) {
|
||||||
|
sInjectorThread->Shutdown();
|
||||||
|
NS_RELEASE(sInjectorThread);
|
||||||
|
}
|
||||||
|
|
||||||
|
delete pidToInjectorCallback;
|
||||||
|
pidToInjectorCallback = NULL;
|
||||||
|
#endif
|
||||||
|
|
||||||
delete crashServer;
|
delete crashServer;
|
||||||
crashServer = NULL;
|
crashServer = NULL;
|
||||||
|
|
||||||
@ -2032,6 +2069,67 @@ GetChildNotificationPipe()
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef MOZ_CRASHREPORTER_INJECTOR
|
||||||
|
void
|
||||||
|
InjectCrashReporterIntoProcess(DWORD processID, InjectorCrashCallback* cb)
|
||||||
|
{
|
||||||
|
if (!GetEnabled())
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!OOPInitialized())
|
||||||
|
OOPInit();
|
||||||
|
|
||||||
|
if (!pidToInjectorCallback) {
|
||||||
|
pidToInjectorCallback = new InjectorPIDMap;
|
||||||
|
pidToInjectorCallback->Init();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!sInjectorThread) {
|
||||||
|
if (NS_FAILED(NS_NewThread(&sInjectorThread)))
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
pidToInjectorCallback->Put(processID, cb);
|
||||||
|
|
||||||
|
nsCOMPtr<nsIRunnable> r = new InjectCrashRunnable(processID);
|
||||||
|
sInjectorThread->Dispatch(r, nsIEventTarget::DISPATCH_NORMAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
ReportInjectedCrash::Run()
|
||||||
|
{
|
||||||
|
// Crash reporting may have been disabled after this method was dispatched
|
||||||
|
if (!pidToInjectorCallback)
|
||||||
|
return NS_OK;
|
||||||
|
|
||||||
|
InjectorCrashCallback* cb = pidToInjectorCallback->Get(mPID);
|
||||||
|
if (!cb)
|
||||||
|
return NS_OK;
|
||||||
|
|
||||||
|
nsCOMPtr<nsIFile> minidump;
|
||||||
|
if (!TakeMinidumpForChild(mPID, getter_AddRefs(minidump))) {
|
||||||
|
NS_WARNING("No minidump for crash notification.");
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsString id;
|
||||||
|
GetIDFromMinidump(minidump, id);
|
||||||
|
|
||||||
|
cb->OnCrash(mPID, id);
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
UnregisterInjectorCallback(DWORD processID)
|
||||||
|
{
|
||||||
|
if (!OOPInitialized())
|
||||||
|
return;
|
||||||
|
|
||||||
|
pidToInjectorCallback->Remove(processID);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // MOZ_CRASHREPORTER_INJECTOR
|
||||||
|
|
||||||
#if defined(XP_WIN)
|
#if defined(XP_WIN)
|
||||||
// Child-side API
|
// Child-side API
|
||||||
bool
|
bool
|
||||||
|
@ -111,6 +111,22 @@ bool CreatePairedMinidumps(ProcessHandle childPid,
|
|||||||
// Parent-side API for children
|
// Parent-side API for children
|
||||||
const char* GetChildNotificationPipe();
|
const char* GetChildNotificationPipe();
|
||||||
|
|
||||||
|
#ifdef MOZ_CRASHREPORTER_INJECTOR
|
||||||
|
// Inject a crash report client into an arbitrary process, and inform the
|
||||||
|
// callback object when it crashes. Parent process only.
|
||||||
|
|
||||||
|
class InjectorCrashCallback
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
InjectorCrashCallback() { }
|
||||||
|
|
||||||
|
virtual void OnCrash(DWORD processID, const nsAString& aDumpID) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
void InjectCrashReporterIntoProcess(DWORD processID, InjectorCrashCallback* cb);
|
||||||
|
void UnregisterInjectorCallback(DWORD processID);
|
||||||
|
#endif
|
||||||
|
|
||||||
// Child-side API
|
// Child-side API
|
||||||
bool SetRemoteExceptionHandler(const nsACString& crashPipe);
|
bool SetRemoteExceptionHandler(const nsACString& crashPipe);
|
||||||
|
|
||||||
|
@ -1148,10 +1148,9 @@ if [ "$MOZ_CRASHREPORTER" ]; then
|
|||||||
"
|
"
|
||||||
if [ "$OS_ARCH" = "WINNT" ]; then
|
if [ "$OS_ARCH" = "WINNT" ]; then
|
||||||
add_makefiles "
|
add_makefiles "
|
||||||
toolkit/crashreporter/google-breakpad/src/client/windows/crash_generation/Makefile
|
toolkit/crashreporter/breakpad-windows-libxul/Makefile
|
||||||
toolkit/crashreporter/google-breakpad/src/client/windows/handler/Makefile
|
toolkit/crashreporter/breakpad-windows-standalone/Makefile
|
||||||
toolkit/crashreporter/google-breakpad/src/client/windows/sender/Makefile
|
toolkit/crashreporter/injector/Makefile
|
||||||
toolkit/crashreporter/google-breakpad/src/common/windows/Makefile
|
|
||||||
"
|
"
|
||||||
elif [ "$OS_ARCH" = "Darwin" ]; then
|
elif [ "$OS_ARCH" = "Darwin" ]; then
|
||||||
add_makefiles "
|
add_makefiles "
|
||||||
|
@ -128,9 +128,7 @@ ifdef MOZ_CRASHREPORTER
|
|||||||
SHARED_LIBRARY_LIBS += $(DEPTH)/toolkit/crashreporter/$(LIB_PREFIX)exception_handler_s.$(LIB_SUFFIX)
|
SHARED_LIBRARY_LIBS += $(DEPTH)/toolkit/crashreporter/$(LIB_PREFIX)exception_handler_s.$(LIB_SUFFIX)
|
||||||
ifeq ($(OS_ARCH),WINNT)
|
ifeq ($(OS_ARCH),WINNT)
|
||||||
SHARED_LIBRARY_LIBS += \
|
SHARED_LIBRARY_LIBS += \
|
||||||
$(DEPTH)/toolkit/crashreporter/google-breakpad/src/client/windows/handler/$(LIB_PREFIX)exception_handler_s.$(LIB_SUFFIX) \
|
$(DEPTH)/toolkit/crashreporter/breakpad-windows-libxul/$(LIB_PREFIX)google_breakpad_libxul_s.$(LIB_SUFFIX)
|
||||||
$(DEPTH)/toolkit/crashreporter/google-breakpad/src/client/windows/crash_generation/$(LIB_PREFIX)crash_generation_s.$(LIB_SUFFIX) \
|
|
||||||
$(DEPTH)/toolkit/crashreporter/google-breakpad/src/common/windows/$(LIB_PREFIX)breakpad_windows_common_s.$(LIB_SUFFIX)
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(OS_ARCH),Darwin)
|
ifeq ($(OS_ARCH),Darwin)
|
||||||
|
Loading…
Reference in New Issue
Block a user