michael@0: /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #ifndef nsExceptionHandler_h__ michael@0: #define nsExceptionHandler_h__ michael@0: michael@0: #include michael@0: #include michael@0: #include "nsError.h" michael@0: #include "nsStringGlue.h" michael@0: michael@0: #if defined(XP_WIN32) michael@0: #ifdef WIN32_LEAN_AND_MEAN michael@0: #undef WIN32_LEAN_AND_MEAN michael@0: #endif michael@0: #include michael@0: #endif michael@0: michael@0: #if defined(XP_MACOSX) michael@0: #include michael@0: #endif michael@0: michael@0: #if defined(XP_LINUX) michael@0: #include michael@0: #endif michael@0: michael@0: class nsIFile; michael@0: template class nsDataHashtable; michael@0: class nsCStringHashKey; michael@0: michael@0: namespace CrashReporter { michael@0: nsresult SetExceptionHandler(nsIFile* aXREDirectory, bool force=false); michael@0: nsresult UnsetExceptionHandler(); michael@0: michael@0: /** michael@0: * Tell the crash reporter to recalculate where crash events files should go. michael@0: * michael@0: * This should be called during crash reporter initialization and when a michael@0: * profile is activated or deactivated. michael@0: */ michael@0: void UpdateCrashEventsDir(); michael@0: michael@0: /** michael@0: * Get the path where crash event files should be written. michael@0: */ michael@0: bool GetCrashEventsDir(nsAString& aPath); michael@0: michael@0: bool GetEnabled(); michael@0: bool GetServerURL(nsACString& aServerURL); michael@0: nsresult SetServerURL(const nsACString& aServerURL); michael@0: bool GetMinidumpPath(nsAString& aPath); michael@0: nsresult SetMinidumpPath(const nsAString& aPath); michael@0: michael@0: michael@0: // AnnotateCrashReport and AppendAppNotesToCrashReport may be called from any michael@0: // thread in a chrome process, but may only be called from the main thread in michael@0: // a content process. michael@0: nsresult AnnotateCrashReport(const nsACString& key, const nsACString& data); michael@0: nsresult AppendAppNotesToCrashReport(const nsACString& data); michael@0: michael@0: void AnnotateOOMAllocationSize(size_t size); michael@0: nsresult SetGarbageCollecting(bool collecting); michael@0: void SetEventloopNestingLevel(uint32_t level); michael@0: michael@0: nsresult SetRestartArgs(int argc, char** argv); michael@0: nsresult SetupExtraData(nsIFile* aAppDataDirectory, michael@0: const nsACString& aBuildID); michael@0: bool GetLastRunCrashID(nsAString& id); michael@0: michael@0: // Registers an additional memory region to be included in the minidump michael@0: nsresult RegisterAppMemory(void* ptr, size_t length); michael@0: nsresult UnregisterAppMemory(void* ptr); michael@0: michael@0: // Functions for working with minidumps and .extras michael@0: typedef nsDataHashtable AnnotationTable; michael@0: michael@0: bool GetMinidumpForID(const nsAString& id, nsIFile** minidump); michael@0: bool GetIDFromMinidump(nsIFile* minidump, nsAString& id); michael@0: bool GetExtraFileForID(const nsAString& id, nsIFile** extraFile); michael@0: bool GetExtraFileForMinidump(nsIFile* minidump, nsIFile** extraFile); michael@0: bool AppendExtraData(const nsAString& id, const AnnotationTable& data); michael@0: bool AppendExtraData(nsIFile* extraFile, const AnnotationTable& data); michael@0: void RenameAdditionalHangMinidump(nsIFile* minidump, nsIFile* childMinidump, michael@0: const nsACString& name); michael@0: michael@0: #ifdef XP_WIN32 michael@0: nsresult WriteMinidumpForException(EXCEPTION_POINTERS* aExceptionInfo); michael@0: #endif michael@0: #ifdef XP_LINUX michael@0: bool WriteMinidumpForSigInfo(int signo, siginfo_t* info, void* uc); michael@0: #endif michael@0: #ifdef XP_MACOSX michael@0: nsresult AppendObjCExceptionInfoToAppNotes(void *inException); michael@0: #endif michael@0: nsresult GetSubmitReports(bool* aSubmitReport); michael@0: nsresult SetSubmitReports(bool aSubmitReport); michael@0: michael@0: // Out-of-process crash reporter API. michael@0: michael@0: // Initializes out-of-process crash reporting. This method must be called michael@0: // before the platform-specifi notificationpipe APIs are called. michael@0: void OOPInit(); michael@0: michael@0: // Return true if a dump was found for |childPid|, and return the michael@0: // path in |dump|. The caller owns the last reference to |dump| if it michael@0: // is non-nullptr. The sequence parameter will be filled with an ordinal michael@0: // indicating which remote process crashed first. michael@0: bool TakeMinidumpForChild(uint32_t childPid, michael@0: nsIFile** dump, michael@0: uint32_t* aSequence = nullptr); michael@0: michael@0: #if defined(XP_WIN) michael@0: typedef HANDLE ProcessHandle; michael@0: typedef DWORD ThreadId; michael@0: #elif defined(XP_MACOSX) michael@0: typedef task_t ProcessHandle; michael@0: typedef mach_port_t ThreadId; michael@0: #else michael@0: typedef int ProcessHandle; michael@0: typedef int ThreadId; michael@0: #endif michael@0: michael@0: // Return the current thread's ID. michael@0: // michael@0: // XXX: this is a somewhat out-of-place interface to expose through michael@0: // crashreporter, but it takes significant work to call sys_gettid() michael@0: // correctly on Linux and breakpad has already jumped through those michael@0: // hoops for us. michael@0: ThreadId CurrentThreadId(); michael@0: michael@0: // Create a hang report with two minidumps that are snapshots of the state michael@0: // of this parent process and |childPid|. The "main" minidump will be the michael@0: // child process, and this parent process will have the -browser extension. michael@0: // michael@0: // Returns true on success. If this function fails, it will attempt to delete michael@0: // any files that were created. michael@0: // michael@0: // The .extra information created will not include an additional_minidumps michael@0: // annotation: the caller should annotate additional_minidumps with michael@0: // at least "browser" and perhaps other minidumps attached to this report. michael@0: bool CreatePairedMinidumps(ProcessHandle childPid, michael@0: ThreadId childBlamedThread, michael@0: nsIFile** childDump); michael@0: michael@0: // Create an additional minidump for a child of a process which already has michael@0: // a minidump (|parentMinidump|). michael@0: // The resulting dump will get the id of the parent and use the |name| as michael@0: // an extension. michael@0: bool CreateAdditionalChildMinidump(ProcessHandle childPid, michael@0: ThreadId childBlamedThread, michael@0: nsIFile* parentMinidump, michael@0: const nsACString& name); michael@0: michael@0: # if defined(XP_WIN32) || defined(XP_MACOSX) michael@0: // Parent-side API for children michael@0: const char* GetChildNotificationPipe(); michael@0: michael@0: #ifdef MOZ_CRASHREPORTER_INJECTOR michael@0: // Inject a crash report client into an arbitrary process, and inform the michael@0: // callback object when it crashes. Parent process only. michael@0: michael@0: class InjectorCrashCallback michael@0: { michael@0: public: michael@0: InjectorCrashCallback() { } michael@0: michael@0: /** michael@0: * Inform the callback of a crash. The client code should call michael@0: * TakeMinidumpForChild to remove it from the PID mapping table. michael@0: * michael@0: * The callback will not be fired if the client has already called michael@0: * TakeMinidumpForChild for this process ID. michael@0: */ michael@0: virtual void OnCrash(DWORD processID) = 0; michael@0: }; michael@0: michael@0: // This method implies OOPInit michael@0: void InjectCrashReporterIntoProcess(DWORD processID, InjectorCrashCallback* cb); michael@0: void UnregisterInjectorCallback(DWORD processID); michael@0: #endif michael@0: michael@0: // Child-side API michael@0: bool SetRemoteExceptionHandler(const nsACString& crashPipe); michael@0: michael@0: # elif defined(XP_LINUX) michael@0: // Parent-side API for children michael@0: michael@0: // Set the outparams for crash reporter server's fd (|childCrashFd|) michael@0: // and the magic fd number it should be remapped to michael@0: // (|childCrashRemapFd|) before exec() in the child process. michael@0: // |SetRemoteExceptionHandler()| in the child process expects to find michael@0: // the server at |childCrashRemapFd|. Return true iff successful. michael@0: // michael@0: // If crash reporting is disabled, both outparams will be set to -1 michael@0: // and |true| will be returned. michael@0: bool CreateNotificationPipeForChild(int* childCrashFd, int* childCrashRemapFd); michael@0: michael@0: // Child-side API michael@0: bool SetRemoteExceptionHandler(); michael@0: michael@0: #endif // XP_WIN32 michael@0: michael@0: bool UnsetRemoteExceptionHandler(); michael@0: michael@0: #if defined(MOZ_WIDGET_ANDROID) michael@0: // Android builds use a custom library loader, so /proc//maps michael@0: // will just show anonymous mappings for all the non-system michael@0: // shared libraries. This API is to work around that by providing michael@0: // info about the shared libraries that are mapped into these anonymous michael@0: // mappings. michael@0: void AddLibraryMapping(const char* library_name, michael@0: uintptr_t start_address, michael@0: size_t mapping_length, michael@0: size_t file_offset); michael@0: michael@0: #endif michael@0: } michael@0: michael@0: #endif /* nsExceptionHandler_h__ */