mirror of
https://git.suyu.dev/suyu/breakpad.git
synced 2026-01-11 08:58:13 +01:00
Allow adding extra memory regions to minidump on linux/windows
A=Bill McCloskey <wmccloskey@mozilla.com>, ted, original patch from https://bugzilla.mozilla.org/show_bug.cgi?id=662646 R=mark at https://breakpad.appspot.com/450002/ git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@1041 4c0a9323-5329-0410-9bdc-e9ce6186880e
This commit is contained in:
parent
3682b31cbe
commit
61d9b9ff96
10 changed files with 447 additions and 37 deletions
|
|
@ -46,9 +46,8 @@ static const int kExceptionHandlerThreadInitialStackSize = 64 * 1024;
|
|||
|
||||
// This is passed as the context to the MinidumpWriteDump callback.
|
||||
typedef struct {
|
||||
ULONG64 memory_base;
|
||||
ULONG memory_size;
|
||||
bool finished;
|
||||
AppMemoryList::const_iterator iter;
|
||||
AppMemoryList::const_iterator end;
|
||||
} MinidumpCallbackContext;
|
||||
|
||||
vector<ExceptionHandler*>* ExceptionHandler::handler_stack_ = NULL;
|
||||
|
|
@ -220,6 +219,12 @@ void ExceptionHandler::Initialize(const wstring& dump_path,
|
|||
set_dump_path(dump_path);
|
||||
}
|
||||
|
||||
// Reserve one element for the instruction memory
|
||||
AppMemory instruction_memory;
|
||||
instruction_memory.ptr = NULL;
|
||||
instruction_memory.length = 0;
|
||||
app_memory_info_.push_back(instruction_memory);
|
||||
|
||||
// There is a race condition here. If the first instance has not yet
|
||||
// initialized the critical section, the second (and later) instances may
|
||||
// try to use uninitialized critical section object. The feature of multiple
|
||||
|
|
@ -795,9 +800,6 @@ bool ExceptionHandler::WriteMinidumpWithException(
|
|||
++user_streams.UserStreamCount;
|
||||
}
|
||||
|
||||
MINIDUMP_CALLBACK_INFORMATION callback;
|
||||
MinidumpCallbackContext context;
|
||||
MINIDUMP_CALLBACK_INFORMATION* callback_pointer = NULL;
|
||||
// Older versions of DbgHelp.dll don't correctly put the memory around
|
||||
// the faulting instruction pointer into the minidump. This
|
||||
// callback will ensure that it gets included.
|
||||
|
|
@ -822,23 +824,34 @@ bool ExceptionHandler::WriteMinidumpWithException(
|
|||
// pointer, but settle for whatever's available up to the
|
||||
// boundaries of the memory region.
|
||||
const ULONG64 kIPMemorySize = 256;
|
||||
context.memory_base =
|
||||
ULONG64 base =
|
||||
(std::max)(reinterpret_cast<ULONG64>(info.BaseAddress),
|
||||
instruction_pointer - (kIPMemorySize / 2));
|
||||
ULONG64 end_of_range =
|
||||
(std::min)(instruction_pointer + (kIPMemorySize / 2),
|
||||
reinterpret_cast<ULONG64>(info.BaseAddress)
|
||||
+ info.RegionSize);
|
||||
context.memory_size =
|
||||
static_cast<ULONG>(end_of_range - context.memory_base);
|
||||
ULONG size = static_cast<ULONG>(end_of_range - base);
|
||||
|
||||
context.finished = false;
|
||||
callback.CallbackRoutine = MinidumpWriteDumpCallback;
|
||||
callback.CallbackParam = reinterpret_cast<void*>(&context);
|
||||
callback_pointer = &callback;
|
||||
AppMemory& elt = app_memory_info_.front();
|
||||
elt.ptr = base;
|
||||
elt.length = size;
|
||||
}
|
||||
}
|
||||
|
||||
MinidumpCallbackContext context;
|
||||
context.iter = app_memory_info_.begin();
|
||||
context.end = app_memory_info_.end();
|
||||
|
||||
// Skip the reserved element if there was no instruction memory
|
||||
if (context.iter->ptr == 0) {
|
||||
context.iter++;
|
||||
}
|
||||
|
||||
MINIDUMP_CALLBACK_INFORMATION callback;
|
||||
callback.CallbackRoutine = MinidumpWriteDumpCallback;
|
||||
callback.CallbackParam = reinterpret_cast<void*>(&context);
|
||||
|
||||
// The explicit comparison to TRUE avoids a warning (C4800).
|
||||
success = (minidump_write_dump_(GetCurrentProcess(),
|
||||
GetCurrentProcessId(),
|
||||
|
|
@ -846,7 +859,7 @@ bool ExceptionHandler::WriteMinidumpWithException(
|
|||
dump_type_,
|
||||
exinfo ? &except_info : NULL,
|
||||
&user_streams,
|
||||
callback_pointer) == TRUE);
|
||||
&callback) == TRUE);
|
||||
|
||||
CloseHandle(dump_file);
|
||||
}
|
||||
|
|
@ -874,13 +887,13 @@ BOOL CALLBACK ExceptionHandler::MinidumpWriteDumpCallback(
|
|||
case MemoryCallback: {
|
||||
MinidumpCallbackContext* callback_context =
|
||||
reinterpret_cast<MinidumpCallbackContext*>(context);
|
||||
if (callback_context->finished)
|
||||
if (callback_context->iter == callback_context->end)
|
||||
return FALSE;
|
||||
|
||||
// Include the specified memory region.
|
||||
callback_output->MemoryBase = callback_context->memory_base;
|
||||
callback_output->MemorySize = callback_context->memory_size;
|
||||
callback_context->finished = true;
|
||||
callback_output->MemoryBase = callback_context->iter->ptr;
|
||||
callback_output->MemorySize = callback_context->iter->length;
|
||||
callback_context->iter++;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
|
@ -924,4 +937,26 @@ void ExceptionHandler::UpdateNextID() {
|
|||
next_minidump_path_c_ = next_minidump_path_.c_str();
|
||||
}
|
||||
|
||||
void ExceptionHandler::RegisterAppMemory(void* ptr, size_t length) {
|
||||
AppMemoryList::iterator iter =
|
||||
std::find(app_memory_info_.begin(), app_memory_info_.end(), ptr);
|
||||
if (iter != app_memory_info_.end()) {
|
||||
// Don't allow registering the same pointer twice.
|
||||
return;
|
||||
}
|
||||
|
||||
AppMemory app_memory;
|
||||
app_memory.ptr = reinterpret_cast<ULONG64>(ptr);
|
||||
app_memory.length = static_cast<ULONG>(length);
|
||||
app_memory_info_.push_back(app_memory);
|
||||
}
|
||||
|
||||
void ExceptionHandler::UnregisterAppMemory(void* ptr) {
|
||||
AppMemoryList::iterator iter =
|
||||
std::find(app_memory_info_.begin(), app_memory_info_.end(), ptr);
|
||||
if (iter != app_memory_info_.end()) {
|
||||
app_memory_info_.erase(iter);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace google_breakpad
|
||||
|
|
|
|||
|
|
@ -65,6 +65,7 @@
|
|||
// Disable exception handler warnings.
|
||||
#pragma warning( disable : 4530 )
|
||||
|
||||
#include <list>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
|
|
@ -78,6 +79,22 @@ namespace google_breakpad {
|
|||
using std::vector;
|
||||
using std::wstring;
|
||||
|
||||
// These entries store a list of memory regions that the client wants included
|
||||
// in the minidump.
|
||||
struct AppMemory {
|
||||
ULONG64 ptr;
|
||||
ULONG length;
|
||||
|
||||
bool operator==(const struct AppMemory& other) const {
|
||||
return ptr == other.ptr;
|
||||
}
|
||||
|
||||
bool operator==(const void* other) const {
|
||||
return ptr == reinterpret_cast<ULONG64>(other);
|
||||
}
|
||||
};
|
||||
typedef std::list<AppMemory> AppMemoryList;
|
||||
|
||||
class ExceptionHandler {
|
||||
public:
|
||||
// A callback function to run before Breakpad performs any substantial
|
||||
|
|
@ -219,6 +236,11 @@ class ExceptionHandler {
|
|||
// Returns whether out-of-process dump generation is used or not.
|
||||
bool IsOutOfProcess() const { return crash_generation_client_.get() != NULL; }
|
||||
|
||||
// Calling RegisterAppMemory(p, len) causes len bytes starting
|
||||
// at address p to be copied to the minidump when a crash happens.
|
||||
void RegisterAppMemory(void* ptr, size_t length);
|
||||
void UnregisterAppMemory(void* ptr);
|
||||
|
||||
private:
|
||||
friend class AutoExceptionHandler;
|
||||
|
||||
|
|
@ -404,6 +426,10 @@ class ExceptionHandler {
|
|||
// to not interfere with debuggers.
|
||||
bool handle_debug_exceptions_;
|
||||
|
||||
// Callers can request additional memory regions to be included in
|
||||
// the dump.
|
||||
AppMemoryList app_memory_info_;
|
||||
|
||||
// A stack of ExceptionHandler objects that have installed unhandled
|
||||
// exception filters. This vector is used by HandleException to determine
|
||||
// which ExceptionHandler object to route an exception to. When an
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue