bug 423674 - update to breakpad revision 250. rs=sayrer

This commit is contained in:
ted.mielczarek%gmail.com 2008-03-19 01:48:24 +00:00
Родитель b57e217417
Коммит dbee1effa5
48 изменённых файлов: 6316 добавлений и 1128 удалений

Просмотреть файл

@ -42,12 +42,9 @@
#include "common/solaris/guid_creator.h"
#include "common/solaris/message_output.h"
#include "google_breakpad/common/minidump_format.h"
#include "processor/scoped_ptr.h"
namespace google_breakpad {
static const int kStackSize = 1024 * 1024;
// Signals that we are interested.
static const int kSigTable[] = {
SIGSEGV,
@ -68,10 +65,9 @@ ExceptionHandler::ExceptionHandler(const string &dump_path,
void *callback_context,
bool install_handler)
: filter_(filter),
handler_thread_(0),
handler_return_value_(false),
callback_(callback),
callback_context_(callback_context),
dump_path_(),
installed_handler_(install_handler) {
set_dump_path(dump_path);
@ -79,19 +75,6 @@ ExceptionHandler::ExceptionHandler(const string &dump_path,
SetupHandler();
}
sem_init(&handler_start_semaphore_, 0, 0);
sem_init(&handler_finish_semaphore_, 0, 0);
pthread_attr_t attr;
scoped_array<char> thread_stack;
pthread_attr_init(&attr);
thread_stack.reset(new char[kStackSize]);
pthread_attr_setstackaddr(&attr, thread_stack.get());
pthread_attr_setstacksize(&attr, kStackSize);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
pthread_create(&handler_thread_, &attr, ExceptionHandlerThreadMain, this);
pthread_attr_destroy(&attr);
if (install_handler) {
pthread_mutex_lock(&handler_stack_mutex_);
@ -125,34 +108,11 @@ ExceptionHandler::~ExceptionHandler() {
delete handler_stack_;
handler_stack_ = NULL;
}
pthread_exit((void *)handler_thread_);
sem_destroy(&handler_start_semaphore_);
sem_destroy(&handler_finish_semaphore_);
pthread_mutex_unlock(&handler_stack_mutex_);
}
// static
void* ExceptionHandler::ExceptionHandlerThreadMain(void *lpParameter) {
ExceptionHandler *self = reinterpret_cast<ExceptionHandler *>(lpParameter);
assert(self);
while (true) {
if (!sem_wait(&(self->handler_start_semaphore_))) {
// Perform the requested action.
self->handler_return_value_ = self->InternalWriteMinidump();
// Allow the requesting thread to proceed.
sem_post(&(self->handler_finish_semaphore_));
}
}
// Not reached. This thread will be terminated by ExceptionHandler's
// destructor.
return 0;
}
bool ExceptionHandler::WriteMinidump() {
return WriteMinidumpOnHandlerThread(0);
return InternalWriteMinidump(0, 0, NULL);
}
// static
@ -161,7 +121,7 @@ bool ExceptionHandler::WriteMinidump(const string &dump_path,
void *callback_context) {
ExceptionHandler handler(dump_path, NULL, callback,
callback_context, false);
return handler.WriteMinidumpOnHandlerThread(0);
return handler.InternalWriteMinidump(0, 0, NULL);
}
void ExceptionHandler::SetupHandler() {
@ -204,22 +164,22 @@ void ExceptionHandler::TeardownAllHandlers() {
}
}
bool ExceptionHandler::WriteMinidumpOnHandlerThread(int signo) {
// Set up data to be passed in to the handler thread.
signo_ = signo;
// This causes the handler thread to call InternalWriteMinidump.
sem_post(&handler_start_semaphore_);
// Wait until InternalWriteMinidump is done and collect its return value.
sem_wait(&handler_finish_semaphore_);
bool status = handler_return_value_;
return status;
}
// static
void ExceptionHandler::HandleException(int signo) {
//void ExceptionHandler::HandleException(int signo, siginfo_t *sip, ucontext_t *sig_ctx) {
// The context information about the signal is put on the stack of
// the signal handler frame as value parameter. For some reasons, the
// prototype of the handler doesn't declare this information as parameter, we
// will do it by hand. The stack layout for a signal handler frame is here:
// http://src.opensolaris.org/source/xref/onnv/onnv-gate/usr/src/lib/libproc/common/Pstack.c#81
//
// However, if we are being called by another signal handler passing the
// signal up the chain, then we may not have this random extra parameter,
// so we may have to walk the stack to find it. We do the actual work
// on another thread, where it's a little safer, but we want the ebp
// from this frame to find it.
uintptr_t current_ebp = (uintptr_t)_getfp();
pthread_mutex_lock(&handler_stack_mutex_);
ExceptionHandler *current_handler =
handler_stack_->at(handler_stack_->size() - ++handler_stack_index_);
@ -227,7 +187,10 @@ void ExceptionHandler::HandleException(int signo) {
// Restore original handler.
current_handler->TeardownHandler(signo);
if (current_handler->WriteMinidumpOnHandlerThread(signo)) {
ucontext_t *sig_ctx = NULL;
if (current_handler->InternalWriteMinidump(signo, current_ebp, &sig_ctx)) {
// if (current_handler->InternalWriteMinidump(signo, &sig_ctx)) {
// Fully handled this exception, safe to exit.
exit(EXIT_FAILURE);
} else {
@ -253,7 +216,9 @@ void ExceptionHandler::HandleException(int signo) {
pthread_mutex_unlock(&handler_stack_mutex_);
}
bool ExceptionHandler::InternalWriteMinidump() {
bool ExceptionHandler::InternalWriteMinidump(int signo,
uintptr_t sighandler_ebp,
ucontext_t **sig_ctx) {
if (filter_ && !filter_(callback_context_))
return false;
@ -277,7 +242,8 @@ bool ExceptionHandler::InternalWriteMinidump() {
print_message1(2, "HandleException: failed to block signals.\n");
}
success = minidump_generator_.WriteMinidumpToFile(minidump_path, signo_);
success = minidump_generator_.WriteMinidumpToFile(
minidump_path, signo, sighandler_ebp, sig_ctx);
// Unblock the signals.
if (blocked)

Просмотреть файл

@ -32,9 +32,6 @@
#ifndef CLIENT_SOLARIS_HANDLER_EXCEPTION_HANDLER_H__
#define CLIENT_SOLARIS_HANDLER_EXCEPTION_HANDLER_H__
#include <pthread.h>
#include <semaphore.h>
#include <map>
#include <string>
#include <vector>
@ -119,9 +116,11 @@ class ExceptionHandler {
bool install_handler);
~ExceptionHandler();
// Set the minidump path.
// Get and Set the minidump path.
string dump_path() const { return dump_path_; }
void set_dump_path(const string &dump_path) {
dump_path_c_ = dump_path.c_str();
dump_path_ = dump_path;
dump_path_c_ = dump_path_.c_str();
}
// Writes a minidump immediately. This can be used to capture the
@ -150,36 +149,25 @@ class ExceptionHandler {
// Signal handler.
static void HandleException(int signo);
// Trigger the call to InternalWriteMinidump and wait for the return value.
bool WriteMinidumpOnHandlerThread(int signo);
// Write all the information to the dump file.
bool InternalWriteMinidump();
// If called from a signal handler, sighandler_ebp is the ebp of
// that signal handler's frame, and sig_ctx is an out parameter
// that will be set to point at the ucontext_t that was placed
// on the stack by the kernel. You can pass zero and NULL
// for the second and third parameters if you are not calling
// this from a signal handler.
bool InternalWriteMinidump(int signo, uintptr_t sighandler_ebp,
ucontext_t **sig_ctx);
private:
// Signal number when crash happed. Can be 0 if this is a requested dump.
int signo_;
// The exception handler thread.
pthread_t handler_thread_;
// Semaphores used to move exception handling between the exception thread
// and the handler thread. handler_start_semaphore_ is signalled by the
// exception thread to wake up the handler thread when an exception occurs.
// handler_finish_semaphore_ is signalled by the handler thread to wake up
// the exception thread when handling is complete.
sem_t handler_start_semaphore_;
sem_t handler_finish_semaphore_;
// The return value of the handler, passed from the handler thread back to
// the requesting thread.
bool handler_return_value_;
// The callbacks before and after writing the dump file.
FilterCallback filter_;
MinidumpCallback callback_;
void *callback_context_;
// The directory in which a minidump will be written, set by the dump_path
// argument to the constructor, or set_dump_path.
string dump_path_;
// C style dump path. Keep this when setting dump path, since calling
// c_str() of std::string when crashing may not be safe.
const char *dump_path_c_;

Просмотреть файл

@ -30,12 +30,11 @@
// Author: Alfred Peng
#include <fcntl.h>
#include <pthread.h>
#include <sys/frame.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/utsname.h>
#include <sys/wait.h>
#include <ucontext.h>
#include <unistd.h>
#include <cstdlib>
@ -45,21 +44,98 @@
#include "client/minidump_file_writer-inl.h"
#include "common/solaris/file_id.h"
namespace google_breakpad {
namespace {
MinidumpGenerator::MinidumpGenerator()
: requester_pid_(0),
signo_(0),
lwp_lister_(NULL) {
using namespace google_breakpad;
// Argument for the writer function.
struct WriterArgument {
MinidumpFileWriter *minidump_writer;
// Pid of the lwp who called WriteMinidumpToFile
int requester_pid;
// The stack bottom of the lwp which caused the dump.
// Mainly used to find the lwp id of the crashed lwp since signal
// handler may not be called in the lwp who caused it.
uintptr_t crashed_stack_bottom;
// Id of the crashing lwp.
int crashed_lwpid;
// Signal number when crash happened. Can be 0 if this is a requested dump.
int signo;
// The ebp of the signal handler frame on x86. Can be 0 if this is a
// requested dump.
uintptr_t sighandler_ebp;
// User context when crash happens. Can be NULL if this is a requested dump.
// This is actually an out parameter, but it will be filled in at the start
// of the writer LWP.
ucontext_t *sig_ctx;
// Used to get information about the lwps.
SolarisLwp *lwp_lister;
};
// Holding context information for the callback of finding the crashing lwp.
struct FindCrashLwpContext {
const SolarisLwp *lwp_lister;
uintptr_t crashing_stack_bottom;
int crashing_lwpid;
FindCrashLwpContext() :
lwp_lister(NULL),
crashing_stack_bottom(0UL),
crashing_lwpid(-1) {
}
};
// Callback for list lwps.
// It will compare the stack bottom of the provided lwp with the stack
// bottom of the crashed lwp, it they are eqaul, this lwp is the one
// who crashed.
bool IsLwpCrashedCallback(lwpstatus_t *lsp, void *context) {
FindCrashLwpContext *crashing_context =
static_cast<FindCrashLwpContext *>(context);
const SolarisLwp *lwp_lister = crashing_context->lwp_lister;
const prgregset_t *gregs = &(lsp->pr_reg);
#if TARGET_CPU_SPARC
uintptr_t last_ebp = (*gregs)[R_FP];
#elif TARGET_CPU_X86
uintptr_t last_ebp = (*gregs)[EBP];
#endif
uintptr_t stack_bottom = lwp_lister->GetLwpStackBottom(last_ebp);
if (stack_bottom > last_ebp &&
stack_bottom == crashing_context->crashing_stack_bottom) {
// Got it. Stop iteration.
crashing_context->crashing_lwpid = lsp->pr_lwpid;
return false;
}
return true;
}
MinidumpGenerator::~MinidumpGenerator() {
// Find the crashing lwpid.
// This is done based on stack bottom comparing.
int FindCrashingLwp(uintptr_t crashing_stack_bottom,
int requester_pid,
const SolarisLwp *lwp_lister) {
FindCrashLwpContext context;
context.lwp_lister = lwp_lister;
context.crashing_stack_bottom = crashing_stack_bottom;
CallbackParam<LwpCallback> callback_param(IsLwpCrashedCallback,
&context);
lwp_lister->Lwp_iter_all(lwp_lister->getpid(), &callback_param);
return context.crashing_lwpid;
}
bool MinidumpGenerator::WriteLwpStack(uintptr_t last_esp,
UntypedMDRVA *memory,
MDMemoryDescriptor *loc) {
uintptr_t stack_bottom = lwp_lister_->GetLwpStackBottom(last_esp);
bool WriteLwpStack(const SolarisLwp *lwp_lister,
uintptr_t last_esp,
UntypedMDRVA *memory,
MDMemoryDescriptor *loc) {
uintptr_t stack_bottom = lwp_lister->GetLwpStackBottom(last_esp);
if (stack_bottom >= last_esp) {
int size = stack_bottom - last_esp;
if (size > 0) {
@ -75,29 +151,52 @@ bool MinidumpGenerator::WriteLwpStack(uintptr_t last_esp,
}
#if TARGET_CPU_SPARC
bool MinidumpGenerator::WriteContext(MDRawContextSPARC *context, prgregset_t regs,
prfpregset_t *fp_regs) {
bool WriteContext(MDRawContextSPARC *context, ucontext_t *sig_ctx) {
assert(sig_ctx != NULL);
int* regs = sig_ctx->uc_mcontext.gregs;
context->context_flags = MD_CONTEXT_SPARC_FULL;
context->ccr = (unsigned int)(regs[0]);
context->pc = (unsigned int)(regs[REG_PC]);
context->npc = (unsigned int)(regs[REG_nPC]);
context->y = (unsigned int)(regs[REG_Y]);
context->asi = (unsigned int)(regs[19]);
context->fprs = (unsigned int)(regs[20]);
for ( int i = 0 ; i < 32; ++i ) {
context->g_r[i] = 0;
}
for ( int i = 1 ; i < 16; ++i ) {
context->g_r[i] = (uintptr_t)(sig_ctx->uc_mcontext.gregs[i + 3]);
}
context->g_r[30] = (uintptr_t)(((struct frame *)context->g_r[14])->fr_savfp);
return true;
}
bool WriteContext(MDRawContextSPARC *context, prgregset_t regs,
prfpregset_t *fp_regs) {
if (!context || !regs)
return false;
context->context_flags = MD_CONTEXT_SPARC_FULL;
context->ccr = (unsigned int)(regs[32]);
context->pc = (unsigned int)(regs[R_PC]);
context->npc = (unsigned int)(regs[R_nPC]);
context->y = (unsigned int)(regs[R_Y]);
context->asi = (unsigned int)(regs[36]);
context->fprs = (unsigned int)(regs[37]);
context->ccr = (uintptr_t)(regs[32]);
context->pc = (uintptr_t)(regs[R_PC]);
context->npc = (uintptr_t)(regs[R_nPC]);
context->y = (uintptr_t)(regs[R_Y]);
context->asi = (uintptr_t)(regs[36]);
context->fprs = (uintptr_t)(regs[37]);
for ( int i = 0 ; i < 32 ; ++i ){
context->g_r[i] = (unsigned int)(regs[i]);
context->g_r[i] = (uintptr_t)(regs[i]);
}
return true;
}
#elif TARGET_CPU_X86
bool MinidumpGenerator::WriteContext(MDRawContextX86 *context, prgregset_t regs,
prfpregset_t *fp_regs) {
bool WriteContext(MDRawContextX86 *context, prgregset_t regs,
prfpregset_t *fp_regs) {
if (!context || !regs)
return false;
@ -124,18 +223,67 @@ bool MinidumpGenerator::WriteContext(MDRawContextX86 *context, prgregset_t regs,
}
#endif /* TARGET_CPU_XXX */
bool MinidumpGenerator::WriteLwpStream(lwpstatus_t *lsp, MDRawThread *lwp) {
prfpregset_t fp_regs = lsp->pr_fpreg;
prgregset_t *gregs = &(lsp->pr_reg);
UntypedMDRVA memory(&writer_);
// Write information about a crashed Lwp.
// When a lwp crash, kernel will write something on the stack for processing
// signal. This makes the current stack not reliable, and our stack walker
// won't figure out the whole call stack for this. So we write the stack at the
// time of the crash into the minidump file, not the current stack.
bool WriteCrashedLwpStream(MinidumpFileWriter *minidump_writer,
const WriterArgument *writer_args,
const lwpstatus_t *lsp,
MDRawThread *lwp) {
assert(writer_args->sig_ctx != NULL);
lwp->thread_id = lsp->pr_lwpid;
#if TARGET_CPU_SPARC
if (!WriteLwpStack((*gregs)[R_SP],
UntypedMDRVA memory(minidump_writer);
if (!WriteLwpStack(writer_args->lwp_lister,
writer_args->sig_ctx->uc_mcontext.gregs[REG_O6],
&memory,
&lwp->stack))
return false;
TypedMDRVA<MDRawContextSPARC> context(minidump_writer);
if (!context.Allocate())
return false;
lwp->thread_context = context.location();
memset(context.get(), 0, sizeof(MDRawContextSPARC));
return WriteContext(context.get(), writer_args->sig_ctx);
#elif TARGET_CPU_X86
UntypedMDRVA memory(minidump_writer);
if (!WriteLwpStack(writer_args->lwp_lister,
writer_args->sig_ctx->uc_mcontext.gregs[UESP],
&memory,
&lwp->stack))
return false;
TypedMDRVA<MDRawContextX86> context(minidump_writer);
if (!context.Allocate())
return false;
lwp->thread_context = context.location();
memset(context.get(), 0, sizeof(MDRawContextX86));
return WriteContext(context.get(),
(int *)&writer_args->sig_ctx->uc_mcontext.gregs,
&writer_args->sig_ctx->uc_mcontext.fpregs);
#endif
}
bool WriteLwpStream(MinidumpFileWriter *minidump_writer,
const SolarisLwp *lwp_lister,
const lwpstatus_t *lsp, MDRawThread *lwp) {
prfpregset_t fp_regs = lsp->pr_fpreg;
const prgregset_t *gregs = &(lsp->pr_reg);
UntypedMDRVA memory(minidump_writer);
#if TARGET_CPU_SPARC
if (!WriteLwpStack(lwp_lister,
(*gregs)[R_SP],
&memory,
&lwp->stack))
return false;
// Write context
TypedMDRVA<MDRawContextSPARC> context(&writer_);
TypedMDRVA<MDRawContextSPARC> context(minidump_writer);
if (!context.Allocate())
return false;
// should be the thread_id
@ -143,13 +291,14 @@ bool MinidumpGenerator::WriteLwpStream(lwpstatus_t *lsp, MDRawThread *lwp) {
lwp->thread_context = context.location();
memset(context.get(), 0, sizeof(MDRawContextSPARC));
#elif TARGET_CPU_X86
if (!WriteLwpStack((*gregs)[UESP],
if (!WriteLwpStack(lwp_lister,
(*gregs)[UESP],
&memory,
&lwp->stack))
return false;
// Write context
TypedMDRVA<MDRawContextX86> context(&writer_);
TypedMDRVA<MDRawContextX86> context(minidump_writer);
if (!context.Allocate())
return false;
// should be the thread_id
@ -160,7 +309,7 @@ bool MinidumpGenerator::WriteLwpStream(lwpstatus_t *lsp, MDRawThread *lwp) {
return WriteContext(context.get(), (int *)gregs, &fp_regs);
}
bool MinidumpGenerator::WriteCPUInformation(MDRawSystemInfo *sys_info) {
bool WriteCPUInformation(MDRawSystemInfo *sys_info) {
struct utsname uts;
char *major, *minor, *build;
@ -188,7 +337,8 @@ bool MinidumpGenerator::WriteCPUInformation(MDRawSystemInfo *sys_info) {
return true;
}
bool MinidumpGenerator::WriteOSInformation(MDRawSystemInfo *sys_info) {
bool WriteOSInformation(MinidumpFileWriter *minidump_writer,
MDRawSystemInfo *sys_info) {
sys_info->platform_id = MD_OS_SOLARIS;
struct utsname uts;
@ -220,7 +370,7 @@ bool MinidumpGenerator::WriteOSInformation(MDRawSystemInfo *sys_info) {
}
MDLocationDescriptor location;
if (!writer_.WriteString(os_version, 0, &location))
if (!minidump_writer->WriteString(os_version, 0, &location))
return false;
sys_info->csd_version_rva = location.rva;
}
@ -229,21 +379,34 @@ bool MinidumpGenerator::WriteOSInformation(MDRawSystemInfo *sys_info) {
// Callback context for get writting lwp information.
struct LwpInfoCallbackCtx {
MinidumpGenerator *generator;
MinidumpFileWriter *minidump_writer;
const WriterArgument *writer_args;
TypedMDRVA<MDRawThreadList> *list;
int lwp_index;
};
bool LwpInformationCallback(lwpstatus_t *lsp, void *context) {
bool success = true;
// The current thread is the one to handle the crash. Ignore it.
LwpInfoCallbackCtx *callback_context =
static_cast<LwpInfoCallbackCtx *>(context);
// The current lwp is the one to handle the crash. Ignore it.
if (lsp->pr_lwpid != pthread_self()) {
LwpInfoCallbackCtx *callback_context =
static_cast<LwpInfoCallbackCtx *>(context);
MDRawThread lwp;
memset(&lwp, 0, sizeof(MDRawThread));
success = callback_context->generator->WriteLwpStream(lsp, &lwp);
if (lsp->pr_lwpid != callback_context->writer_args->crashed_lwpid ||
callback_context->writer_args->sig_ctx == NULL) {
success = WriteLwpStream(callback_context->minidump_writer,
callback_context->writer_args->lwp_lister,
lsp, &lwp);
} else {
success = WriteCrashedLwpStream(callback_context->minidump_writer,
callback_context->writer_args,
lsp, &lwp);
}
if (success) {
callback_context->list->CopyIndexAfterObject(
callback_context->lwp_index++,
@ -254,12 +417,15 @@ bool LwpInformationCallback(lwpstatus_t *lsp, void *context) {
return success;
}
bool MinidumpGenerator::WriteLwpListStream(MDRawDirectory *dir) {
bool WriteLwpListStream(MinidumpFileWriter *minidump_writer,
const WriterArgument *writer_args,
MDRawDirectory *dir) {
// Get the lwp information.
int lwp_count = lwp_lister_->GetLwpCount();
const SolarisLwp *lwp_lister = writer_args->lwp_lister;
int lwp_count = lwp_lister->GetLwpCount();
if (lwp_count < 0)
return false;
TypedMDRVA<MDRawThreadList> list(&writer_);
TypedMDRVA<MDRawThreadList> list(minidump_writer);
if (!list.AllocateObjectAndArray(lwp_count - 1, sizeof(MDRawThread)))
return false;
dir->stream_type = MD_THREAD_LIST_STREAM;
@ -267,31 +433,32 @@ bool MinidumpGenerator::WriteLwpListStream(MDRawDirectory *dir) {
list.get()->number_of_threads = lwp_count - 1;
LwpInfoCallbackCtx context;
context.generator = this;
context.minidump_writer = minidump_writer;
context.writer_args = writer_args;
context.list = &list;
context.lwp_index = 0;
CallbackParam<LwpCallback> callback_param(LwpInformationCallback,
&context);
int written =
lwp_lister_->Lwp_iter_all(lwp_lister_->getpid(), &callback_param);
lwp_lister->Lwp_iter_all(lwp_lister->getpid(), &callback_param);
return written == lwp_count;
}
bool MinidumpGenerator::WriteCVRecord(MDRawModule *module,
const char *module_path) {
TypedMDRVA<MDCVInfoPDB70> cv(&writer_);
bool WriteCVRecord(MinidumpFileWriter *minidump_writer,
MDRawModule *module,
const char *module_path,
char *realname) {
TypedMDRVA<MDCVInfoPDB70> cv(minidump_writer);
char path[PATH_MAX];
const char *module_name = module_path ? module_path : "<Unknown>";
snprintf(path, sizeof(path), "/proc/self/object/%s", module_name);
size_t module_name_length = strlen(module_name);
size_t module_name_length = strlen(realname);
if (!cv.AllocateObjectAndArray(module_name_length + 1, sizeof(u_int8_t)))
return false;
if (!cv.CopyIndexAfterObject(0, const_cast<char *>(module_name),
module_name_length)) {
if (!cv.CopyIndexAfterObject(0, realname, module_name_length))
return false;
}
module->cv_record = cv.location();
MDCVInfoPDB70 *cv_ptr = cv.get();
@ -322,8 +489,8 @@ bool MinidumpGenerator::WriteCVRecord(MDRawModule *module,
}
struct ModuleInfoCallbackCtx {
MinidumpGenerator *generator;
MinidumpFileWriter *minidump_writer;
const WriterArgument *writer_args;
TypedMDRVA<MDRawModuleList> *list;
int module_index;
};
@ -338,16 +505,29 @@ bool ModuleInfoCallback(const ModuleInfo &module_info, void *context) {
MDRawModule module;
memset(&module, 0, sizeof(module));
MDLocationDescriptor loc;
if (!callback_context->minidump_writer->WriteString(module_info.name,
0, &loc)) {
char path[PATH_MAX];
char buf[PATH_MAX];
char *realname;
int count;
snprintf(path, sizeof (path), "/proc/self/path/%s", module_info.name);
if ((count = readlink(path, buf, PATH_MAX)) < 0)
return false;
buf[count] = '\0';
if ((realname = strrchr(buf, '/')) == NULL)
return false;
realname++;
if (!callback_context->minidump_writer->WriteString(realname, 0, &loc))
return false;
}
module.base_of_image = (u_int64_t)module_info.start_addr;
module.size_of_image = module_info.size;
module.module_name_rva = loc.rva;
if (!callback_context->generator->WriteCVRecord(&module, module_info.name))
if (!WriteCVRecord(callback_context->minidump_writer, &module,
module_info.name, realname))
return false;
callback_context->list->CopyIndexAfterObject(
@ -355,9 +535,11 @@ bool ModuleInfoCallback(const ModuleInfo &module_info, void *context) {
return true;
}
bool MinidumpGenerator::WriteModuleListStream(MDRawDirectory *dir) {
TypedMDRVA<MDRawModuleList> list(&writer_);
int module_count = lwp_lister_->GetModuleCount();
bool WriteModuleListStream(MinidumpFileWriter *minidump_writer,
const WriterArgument *writer_args,
MDRawDirectory *dir) {
TypedMDRVA<MDRawModuleList> list(minidump_writer);
int module_count = writer_args->lwp_lister->GetModuleCount();
if (module_count <= 0 ||
!list.AllocateObjectAndArray(module_count, MD_MODULE_SIZE)) {
@ -368,16 +550,18 @@ bool MinidumpGenerator::WriteModuleListStream(MDRawDirectory *dir) {
dir->location = list.location();
list.get()->number_of_modules = module_count;
ModuleInfoCallbackCtx context;
context.generator = this;
context.minidump_writer = &writer_;
context.minidump_writer = minidump_writer;
context.writer_args = writer_args;
context.list = &list;
context.module_index = 0;
CallbackParam<ModuleCallback> callback(ModuleInfoCallback, &context);
return lwp_lister_->ListModules(&callback) == module_count;
return writer_args->lwp_lister->ListModules(&callback) == module_count;
}
bool MinidumpGenerator::WriteSystemInfoStream(MDRawDirectory *dir) {
TypedMDRVA<MDRawSystemInfo> sys_info(&writer_);
bool WriteSystemInfoStream(MinidumpFileWriter *minidump_writer,
const WriterArgument *writer_args,
MDRawDirectory *dir) {
TypedMDRVA<MDRawSystemInfo> sys_info(minidump_writer);
if (!sys_info.Allocate())
return false;
@ -386,69 +570,65 @@ bool MinidumpGenerator::WriteSystemInfoStream(MDRawDirectory *dir) {
dir->location = sys_info.location();
return WriteCPUInformation(sys_info.get()) &&
WriteOSInformation(sys_info.get());
WriteOSInformation(minidump_writer, sys_info.get());
}
bool MinidumpGenerator::WriteExceptionStream(MDRawDirectory *dir) {
ucontext_t uc;
gregset_t *gregs;
fpregset_t fp_regs;
if (getcontext(&uc) != 0)
bool WriteExceptionStream(MinidumpFileWriter *minidump_writer,
const WriterArgument *writer_args,
MDRawDirectory *dir) {
// This happenes when this is not a crash, but a requested dump.
if (writer_args->sig_ctx == NULL)
return false;
TypedMDRVA<MDRawExceptionStream> exception(&writer_);
TypedMDRVA<MDRawExceptionStream> exception(minidump_writer);
if (!exception.Allocate())
return false;
dir->stream_type = MD_EXCEPTION_STREAM;
dir->location = exception.location();
exception.get()->thread_id = requester_pid_;
exception.get()->exception_record.exception_code = signo_;
exception.get()->thread_id = writer_args->crashed_lwpid;
exception.get()->exception_record.exception_code = writer_args->signo;
exception.get()->exception_record.exception_flags = 0;
gregs = &(uc.uc_mcontext.gregs);
fp_regs = uc.uc_mcontext.fpregs;
#if TARGET_CPU_SPARC
exception.get()->exception_record.exception_address = ((unsigned int *)gregs)[1];
if (writer_args->sig_ctx != NULL) {
exception.get()->exception_record.exception_address =
writer_args->sig_ctx->uc_mcontext.gregs[REG_PC];
} else {
return true;
}
// Write context of the exception.
TypedMDRVA<MDRawContextSPARC> context(&writer_);
TypedMDRVA<MDRawContextSPARC> context(minidump_writer);
if (!context.Allocate())
return false;
exception.get()->thread_context = context.location();
memset(context.get(), 0, sizeof(MDRawContextSPARC));
// On Solaris i386, gregset_t = prgregset_t, fpregset_t = prfpregset_t
// But on Solaris Sparc are diffrent, see sys/regset.h and sys/procfs_isa.h
context.get()->context_flags = MD_CONTEXT_SPARC_FULL;
context.get()->ccr = ((unsigned int *)gregs)[0];
context.get()->pc = ((unsigned int *)gregs)[1];
context.get()->npc = ((unsigned int *)gregs)[2];
context.get()->y = ((unsigned int *)gregs)[3];
context.get()->asi = ((unsigned int *)gregs)[19];
context.get()->fprs = ((unsigned int *)gregs)[20];
for (int i = 0; i < 32; ++i) {
context.get()->g_r[i] = 0;
}
for (int i = 1; i < 16; ++i) {
context.get()->g_r[i] = ((unsigned int *)gregs)[i + 3];
}
return true;
return WriteContext(context.get(), writer_args->sig_ctx);
#elif TARGET_CPU_X86
exception.get()->exception_record.exception_address = (*gregs)[EIP];
if (writer_args->sig_ctx != NULL) {
exception.get()->exception_record.exception_address =
writer_args->sig_ctx->uc_mcontext.gregs[EIP];
} else {
return true;
}
// Write context of the exception.
TypedMDRVA<MDRawContextX86> context(&writer_);
TypedMDRVA<MDRawContextX86> context(minidump_writer);
if (!context.Allocate())
return false;
exception.get()->thread_context = context.location();
memset(context.get(), 0, sizeof(MDRawContextX86));
return WriteContext(context.get(), (int *)gregs, &fp_regs);
#endif /* TARGET_CPU_XXX */
return WriteContext(context.get(),
(int *)&writer_args->sig_ctx->uc_mcontext.gregs,
NULL);
#endif
}
bool MinidumpGenerator::WriteMiscInfoStream(MDRawDirectory *dir) {
TypedMDRVA<MDRawMiscInfo> info(&writer_);
bool WriteMiscInfoStream(MinidumpFileWriter *minidump_writer,
const WriterArgument *writer_args,
MDRawDirectory *dir) {
TypedMDRVA<MDRawMiscInfo> info(minidump_writer);
if (!info.Allocate())
return false;
@ -457,13 +637,15 @@ bool MinidumpGenerator::WriteMiscInfoStream(MDRawDirectory *dir) {
dir->location = info.location();
info.get()->size_of_info = sizeof(MDRawMiscInfo);
info.get()->flags1 = MD_MISCINFO_FLAGS1_PROCESS_ID;
info.get()->process_id = requester_pid_;
info.get()->process_id = writer_args->requester_pid;
return true;
}
bool MinidumpGenerator::WriteBreakpadInfoStream(MDRawDirectory *dir) {
TypedMDRVA<MDRawBreakpadInfo> info(&writer_);
bool WriteBreakpadInfoStream(MinidumpFileWriter *minidump_writer,
const WriterArgument *writer_args,
MDRawDirectory *dir) {
TypedMDRVA<MDRawBreakpadInfo> info(minidump_writer);
if (!info.Allocate())
return false;
@ -474,7 +656,7 @@ bool MinidumpGenerator::WriteBreakpadInfoStream(MDRawDirectory *dir) {
info.get()->validity = MD_BREAKPAD_INFO_VALID_DUMP_THREAD_ID |
MD_BREAKPAD_INFO_VALID_REQUESTING_THREAD_ID;
info.get()->dump_thread_id = getpid();
info.get()->requesting_thread_id = requester_pid_;
info.get()->requesting_thread_id = writer_args->requester_pid;
return true;
}
@ -486,25 +668,53 @@ class AutoLwpResumer {
SolarisLwp *lwp_;
};
// Will call each writer function in the writers table.
void* MinidumpGenerator::Write() {
// Function table to writer a full minidump.
const WriteStreamFN writers[] = {
&MinidumpGenerator::WriteLwpListStream,
&MinidumpGenerator::WriteModuleListStream,
&MinidumpGenerator::WriteSystemInfoStream,
&MinidumpGenerator::WriteExceptionStream,
&MinidumpGenerator::WriteMiscInfoStream,
&MinidumpGenerator::WriteBreakpadInfoStream,
};
// Prototype of writer functions.
typedef bool (*WriteStreamFN)(MinidumpFileWriter *,
const WriterArgument *,
MDRawDirectory *);
if (!lwp_lister_->ControlAllLwps(true))
// Function table to writer a full minidump.
const WriteStreamFN writers[] = {
WriteLwpListStream,
WriteModuleListStream,
WriteSystemInfoStream,
WriteExceptionStream,
WriteMiscInfoStream,
WriteBreakpadInfoStream,
};
// Will call each writer function in the writers table.
//void* MinidumpGenerator::Write(void *argument) {
void* Write(void *argument) {
WriterArgument *writer_args = static_cast<WriterArgument *>(argument);
if (!writer_args->lwp_lister->ControlAllLwps(true))
return NULL;
AutoLwpResumer lwpResumer(lwp_lister_);
AutoLwpResumer lwpResumer(writer_args->lwp_lister);
TypedMDRVA<MDRawHeader> header(&writer_);
TypedMDRVA<MDRawDirectory> dir(&writer_);
if (writer_args->sighandler_ebp != 0 &&
writer_args->lwp_lister->FindSigContext(writer_args->sighandler_ebp,
&writer_args->sig_ctx)) {
writer_args->crashed_stack_bottom =
writer_args->lwp_lister->GetLwpStackBottom(
#if TARGET_CPU_SPARC
writer_args->sig_ctx->uc_mcontext.gregs[REG_O6]
#elif TARGET_CPU_X86
writer_args->sig_ctx->uc_mcontext.gregs[UESP]
#endif
);
int crashed_lwpid = FindCrashingLwp(writer_args->crashed_stack_bottom,
writer_args->requester_pid,
writer_args->lwp_lister);
if (crashed_lwpid > 0)
writer_args->crashed_lwpid = crashed_lwpid;
}
MinidumpFileWriter *minidump_writer = writer_args->minidump_writer;
TypedMDRVA<MDRawHeader> header(minidump_writer);
TypedMDRVA<MDRawDirectory> dir(minidump_writer);
if (!header.Allocate())
return 0;
@ -521,29 +731,53 @@ void* MinidumpGenerator::Write() {
int dir_index = 0;
MDRawDirectory local_dir;
for (int i = 0; i < writer_count; ++i) {
if ((this->*writers[i])(&local_dir))
if ((*writers[i])(minidump_writer, writer_args, &local_dir))
dir.CopyIndex(dir_index++, &local_dir);
}
return 0;
}
} // namespace
namespace google_breakpad {
MinidumpGenerator::MinidumpGenerator() {
}
MinidumpGenerator::~MinidumpGenerator() {
}
// Write minidump into file.
// It runs in a different thread from the crashing thread.
bool MinidumpGenerator::WriteMinidumpToFile(const char *file_pathname,
int signo) {
int signo,
uintptr_t sighandler_ebp,
ucontext_t **sig_ctx) const {
// The exception handler thread.
pthread_t handler_thread;
assert(file_pathname != NULL);
if (file_pathname == NULL)
return false;
if (writer_.Open(file_pathname)) {
MinidumpFileWriter minidump_writer;
if (minidump_writer.Open(file_pathname)) {
WriterArgument argument;
memset(&argument, 0, sizeof(argument));
SolarisLwp lwp_lister(getpid());
lwp_lister_ = &lwp_lister;
requester_pid_ = getpid();
signo_ = signo;
if (Write())
return true;
argument.lwp_lister = &lwp_lister;
argument.minidump_writer = &minidump_writer;
argument.requester_pid = getpid();
argument.crashed_lwpid = pthread_self();
argument.signo = signo;
argument.sighandler_ebp = sighandler_ebp;
argument.sig_ctx = NULL;
pthread_create(&handler_thread, NULL, Write, (void *)&argument);
pthread_join(handler_thread, NULL);
return true;
}
return false;

Просмотреть файл

@ -32,13 +32,7 @@
#ifndef CLIENT_SOLARIS_HANDLER_MINIDUMP_GENERATOR_H__
#define CLIENT_SOLARIS_HANDLER_MINIDUMP_GENERATOR_H__
#if defined(sparc) || defined(__sparc__)
#define TARGET_CPU_SPARC 1
#elif defined(i386) || defined(__i386__)
#define TARGET_CPU_X86 1
#else
#error "cannot determine cpu type"
#endif
#include <ucontext.h>
#include "client/minidump_file_writer.h"
#include "client/solaris/handler/solaris_lwp.h"
@ -66,59 +60,9 @@ class MinidumpGenerator {
// Write minidump.
bool WriteMinidumpToFile(const char *file_pathname,
int signo);
private:
// Helpers
bool WriteCVRecord(MDRawModule *module, const char *module_path);
// Write the lwp stack information to dump file.
bool WriteLwpStack(uintptr_t last_esp, UntypedMDRVA *memory,
MDMemoryDescriptor *loc);
// Write CPU context based on provided registers.
#if TARGET_CPU_SPARC
bool WriteContext(MDRawContextSPARC *context, prgregset_t regs,
prfpregset_t *fp_regs);
#elif TARGET_CPU_X86
bool WriteContext(MDRawContextX86 *context, prgregset_t regs,
prfpregset_t *fp_regs);
#endif /* TARGET_CPU_XXX */
// Write information about a lwp.
// Only processes lwp running normally at the crash.
bool WriteLwpStream(lwpstatus_t *lsp, MDRawThread *lwp);
// Write the CPU information to the dump file.
bool WriteCPUInformation(MDRawSystemInfo *sys_info);
//Write the OS information to the dump file.
bool WriteOSInformation(MDRawSystemInfo *sys_info);
typedef bool (MinidumpGenerator::*WriteStreamFN)(MDRawDirectory *);
// Write all the information to the dump file.
void *Write();
// Stream writers
bool WriteLwpListStream(MDRawDirectory *dir);
bool WriteModuleListStream(MDRawDirectory *dir);
bool WriteSystemInfoStream(MDRawDirectory *dir);
bool WriteExceptionStream(MDRawDirectory *dir);
bool WriteMiscInfoStream(MDRawDirectory *dir);
bool WriteBreakpadInfoStream(MDRawDirectory *dir);
private:
MinidumpFileWriter writer_;
// Pid of the lwp who called WriteMinidumpToFile
int requester_pid_;
// Signal number when crash happed. Can be 0 if this is a requested dump.
int signo_;
// Used to get information about the lwps.
SolarisLwp *lwp_lister_;
int signo,
uintptr_t sighandler_ebp,
ucontext_t **sig_ctx) const;
};
} // namespace google_breakpad

Просмотреть файл

@ -48,7 +48,7 @@ static void *Reporter(void *) {
snprintf(buffer, sizeof(buffer), "./minidump_test.out");
fprintf(stdout, "Writing %s\n", buffer);
md.WriteMinidumpToFile(buffer, 0);
md.WriteMinidumpToFile(buffer, 0, 0, NULL);
doneWritingReport = true;
return NULL;

Просмотреть файл

@ -30,9 +30,11 @@
// Author: Alfred Peng
#include <dirent.h>
#include <elf.h>
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
#include <sys/frame.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>
@ -56,6 +58,16 @@ uintptr_t stack_base_address = 0;
static const int HEADER_MAX = 2000;
static const int MAP_MAX = 1000;
// Context information for the callbacks when validating address by listing
// modules.
struct AddressValidatingContext {
uintptr_t address;
bool is_mapped;
AddressValidatingContext() : address(0UL), is_mapped(false) {
}
};
// Convert from string to int.
static bool LocalAtoi(char *s, int *r) {
assert(s != NULL);
@ -69,18 +81,19 @@ static bool LocalAtoi(char *s, int *r) {
}
// Callback invoked for each mapped module.
// It use the module's adderss range to validate the address.
// It uses the module's adderss range to validate the address.
static bool AddressNotInModuleCallback(const ModuleInfo &module_info,
void *context) {
uintptr_t addr = reinterpret_cast<uintptr_t>(context);
if ((module_info.start_addr > 0) &&
(addr >= module_info.start_addr) &&
(addr <= module_info.start_addr + module_info.size)) {
AddressValidatingContext *addr =
reinterpret_cast<AddressValidatingContext *>(context);
if (addr->is_mapped = ((module_info.start_addr > 0) &&
(addr->address >= module_info.start_addr) &&
(addr->address <= module_info.start_addr +
module_info.size))) {
stack_base_address = module_info.start_addr + module_info.size;
return false;
}
return true;
return !addr->is_mapped;
}
static int IterateLwpAll(int pid,
@ -114,6 +127,28 @@ static int IterateLwpAll(int pid,
return count;
}
#if defined(__i386) && !defined(NO_FRAME_POINTER)
void *GetNextFrame(void **last_ebp) {
void *sp = *last_ebp;
if ((unsigned long)sp == (unsigned long)last_ebp)
return NULL;
if ((unsigned long)sp & (sizeof(void *) - 1))
return NULL;
if ((unsigned long)sp - (unsigned long)last_ebp > 100000)
return NULL;
return sp;
}
#elif defined(__sparc)
void *GetNextFrame(void *last_ebp) {
return reinterpret_cast<struct frame *>(last_ebp)->fr_savfp;
}
#else
void *GetNextFrame(void **last_ebp) {
return reinterpret_cast<void*>(last_ebp);
}
#endif
class AutoCloser {
public:
AutoCloser(int fd) : fd_(fd) {}
@ -250,8 +285,10 @@ int SolarisLwp::Lwp_iter_all(int pid,
}
uintptr_t SolarisLwp::GetLwpStackBottom(uintptr_t current_esp) const {
AddressValidatingContext addr;
addr.address = current_esp;
CallbackParam<ModuleCallback> callback_param(AddressNotInModuleCallback,
(void *)current_esp);
&addr);
ListModules(&callback_param);
return stack_base_address;
}
@ -313,7 +350,28 @@ int SolarisLwp::ListModules(
memset(&module, 0, sizeof (module));
module.start_addr = _maps->pr_vaddr;
module.size = _maps->pr_size;
if ((strlen(name) > 0) && (strcmp(name, "a.out") != 0)) {
if (strlen(name) > 0) {
int objectfd = 0;
char path[PATH_MAX];
char buf[SELFMAG];
snprintf(path, sizeof (path), "/proc/self/object/%s", name);
if ((objectfd = open(path, O_RDONLY)) < 0) {
print_message1(2, "can't open module file\n");
continue;
}
AutoCloser autocloser(objectfd);
if (read(objectfd, buf, SELFMAG) != SELFMAG) {
print_message1(2, "can't read module file\n");
continue;
}
if (buf[0] != ELFMAG0 || buf[1] != ELFMAG1 ||
buf[2] != ELFMAG2 || buf[3] != ELFMAG3) {
continue;
}
strncpy(module.name, name, sizeof (module.name) - 1);
++module_count;
}
@ -326,4 +384,53 @@ int SolarisLwp::ListModules(
return module_count;
}
// Check if the address is a valid virtual address.
// If the address is in any of the mapped modules, we take it as valid.
// Otherwise it is invalid.
bool SolarisLwp::IsAddressMapped(uintptr_t address) const {
AddressValidatingContext addr;
addr.address = address;
CallbackParam<ModuleCallback> callback_param(AddressNotInModuleCallback,
&addr);
ListModules(&callback_param);
return addr.is_mapped;
}
// We're looking for a ucontext_t as the second parameter
// to a signal handler function call. Luckily, the ucontext_t
// has an ebp(fp on SPARC) member which should match the ebp(fp)
// pointed to by the ebp(fp) of the signal handler frame.
// The Solaris stack looks like this:
// http://src.opensolaris.org/source/xref/onnv/onnv-gate/usr/src/lib/libproc/common/Pstack.c#81
bool SolarisLwp::FindSigContext(uintptr_t sighandler_ebp,
ucontext_t **sig_ctx) {
uintptr_t previous_ebp;
uintptr_t sig_ebp;
const int MAX_STACK_DEPTH = 50;
int depth_counter = 0;
do {
#if TARGET_CPU_SPARC
previous_ebp = reinterpret_cast<uintptr_t>(GetNextFrame(
reinterpret_cast<void*>(sighandler_ebp)));
*sig_ctx = reinterpret_cast<ucontext_t*>(sighandler_ebp + sizeof (struct frame));
uintptr_t sig_esp = (*sig_ctx)->uc_mcontext.gregs[REG_O6];
if (sig_esp < previous_ebp && sig_esp > sighandler_ebp)
sig_ebp = (uintptr_t)(((struct frame *)sig_esp)->fr_savfp);
#elif TARGET_CPU_X86
previous_ebp = reinterpret_cast<uintptr_t>(GetNextFrame(
reinterpret_cast<void**>(sighandler_ebp)));
*sig_ctx = reinterpret_cast<ucontext_t*>(sighandler_ebp + sizeof (struct frame) +
3 * sizeof(uintptr_t));
sig_ebp = (*sig_ctx)->uc_mcontext.gregs[EBP];
#endif
sighandler_ebp = previous_ebp;
depth_counter++;
} while(previous_ebp != sig_ebp && sighandler_ebp != 0 &&
IsAddressMapped(sighandler_ebp) && depth_counter < MAX_STACK_DEPTH);
return previous_ebp == sig_ebp && previous_ebp != 0;
}
} // namespace google_breakpad

Просмотреть файл

@ -32,9 +32,18 @@
#ifndef CLIENT_SOLARIS_HANDLER_SOLARIS_LWP_H__
#define CLIENT_SOLARIS_HANDLER_SOLARIS_LWP_H__
#if defined(sparc) || defined(__sparc)
#define TARGET_CPU_SPARC 1
#elif defined(i386) || defined(__i386)
#define TARGET_CPU_X86 1
#else
#error "cannot determine cpu type"
#endif
#include <signal.h>
#include <stdint.h>
#include <sys/user.h>
#include <ucontext.h>
#ifndef _KERNEL
#define _KERNEL
@ -134,6 +143,13 @@ class SolarisLwp {
// Get the bottom of the stack from esp.
uintptr_t GetLwpStackBottom(uintptr_t current_esp) const;
// Finds a signal context on the stack given the ebp of our signal handler.
bool FindSigContext(uintptr_t sighandler_ebp, ucontext_t **sig_ctx);
private:
// Check if the address is a valid virtual address.
bool IsAddressMapped(uintptr_t address) const;
private:
// The pid of the process we are listing lwps.
int pid_;

Просмотреть файл

@ -2,9 +2,14 @@
Microsoft Visual Studio Solution File, Format Version 9.00
# Visual Studio 2005
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "exception_handler", "handler\exception_handler.vcproj", "{B55CA863-B374-4BAF-95AC-539E4FA4C90C}"
ProjectSection(ProjectDependencies) = postProject
{A820AF62-6239-4693-8430-4F516C1838F4} = {A820AF62-6239-4693-8430-4F516C1838F4}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "crash_report_sender", "sender\crash_report_sender.vcproj", "{9946A048-043B-4F8F-9E07-9297B204714C}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "crash_generation", "crash_generation\crash_generation.vcproj", "{A820AF62-6239-4693-8430-4F516C1838F4}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
@ -29,6 +34,14 @@ Global
{9946A048-043B-4F8F-9E07-9297B204714C}.Release|Win32.Build.0 = Release|Win32
{9946A048-043B-4F8F-9E07-9297B204714C}.ReleaseStaticCRT|Win32.ActiveCfg = ReleaseStaticCRT|Win32
{9946A048-043B-4F8F-9E07-9297B204714C}.ReleaseStaticCRT|Win32.Build.0 = ReleaseStaticCRT|Win32
{A820AF62-6239-4693-8430-4F516C1838F4}.Debug|Win32.ActiveCfg = Debug|Win32
{A820AF62-6239-4693-8430-4F516C1838F4}.Debug|Win32.Build.0 = Debug|Win32
{A820AF62-6239-4693-8430-4F516C1838F4}.DebugStaticCRT|Win32.ActiveCfg = DebugStaticCRT|Win32
{A820AF62-6239-4693-8430-4F516C1838F4}.DebugStaticCRT|Win32.Build.0 = DebugStaticCRT|Win32
{A820AF62-6239-4693-8430-4F516C1838F4}.Release|Win32.ActiveCfg = Release|Win32
{A820AF62-6239-4693-8430-4F516C1838F4}.Release|Win32.Build.0 = Release|Win32
{A820AF62-6239-4693-8430-4F516C1838F4}.ReleaseStaticCRT|Win32.ActiveCfg = ReleaseStaticCRT|Win32
{A820AF62-6239-4693-8430-4F516C1838F4}.ReleaseStaticCRT|Win32.Build.0 = ReleaseStaticCRT|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

Просмотреть файл

@ -0,0 +1,63 @@
// Copyright (c) 2008, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef CLIENT_WINDOWS_COMMON_AUTO_CRITICAL_SECTION_H__
#define CLIENT_WINDOWS_COMMON_AUTO_CRITICAL_SECTION_H__
#include <Windows.h>
namespace google_breakpad {
// Automatically enters the critical section in the constructor and leaves
// the critical section in the destructor.
class AutoCriticalSection {
public:
// Creates a new instance with the given critical section object
// and enters the critical section immediately.
explicit AutoCriticalSection(CRITICAL_SECTION* cs) : cs_(cs) {
assert(cs_);
EnterCriticalSection(cs_);
}
// Destructor: leaves the critical section.
~AutoCriticalSection() {
LeaveCriticalSection(cs_);
}
private:
// Disable copy ctor and operator=.
AutoCriticalSection(const AutoCriticalSection&);
AutoCriticalSection& operator=(const AutoCriticalSection&);
CRITICAL_SECTION* cs_;
};
} // namespace google_breakpad
#endif // CLIENT_WINDOWS_COMMON_AUTO_CRITICAL_SECTION_H__

Просмотреть файл

@ -0,0 +1,122 @@
// Copyright (c) 2008, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef CLIENT_WINDOWS_COMMON_IPC_PROTOCOL_H__
#define CLIENT_WINDOWS_COMMON_IPC_PROTOCOL_H__
#include <Windows.h>
#include <DbgHelp.h>
#include "google_breakpad/common/minidump_format.h"
namespace google_breakpad {
// Constants for the protocol between client and the server.
// Tags sent with each message indicating the purpose of
// the message.
enum MessageTag {
MESSAGE_TAG_NONE = 0,
MESSAGE_TAG_REGISTRATION_REQUEST = 1,
MESSAGE_TAG_REGISTRATION_RESPONSE = 2,
MESSAGE_TAG_REGISTRATION_ACK = 3
};
// Message structure for IPC between crash client and crash server.
struct ProtocolMessage {
ProtocolMessage()
: tag(MESSAGE_TAG_NONE),
pid(0),
dump_type(MiniDumpNormal),
thread_id(0),
exception_pointers(NULL),
assert_info(NULL),
dump_request_handle(NULL),
dump_generated_handle(NULL),
server_alive_handle(NULL) {
}
// Creates an instance with the given parameters.
ProtocolMessage(MessageTag arg_tag,
DWORD arg_pid,
MINIDUMP_TYPE arg_dump_type,
DWORD* arg_thread_id,
EXCEPTION_POINTERS** arg_exception_pointers,
MDRawAssertionInfo* arg_assert_info,
HANDLE arg_dump_request_handle,
HANDLE arg_dump_generated_handle,
HANDLE arg_server_alive)
: tag(arg_tag),
pid(arg_pid),
dump_type(arg_dump_type),
thread_id(arg_thread_id),
exception_pointers(arg_exception_pointers),
assert_info(arg_assert_info),
dump_request_handle(arg_dump_request_handle),
dump_generated_handle(arg_dump_generated_handle),
server_alive_handle(arg_server_alive) {
}
// Tag in the message.
MessageTag tag;
// Process id.
DWORD pid;
// Dump type requested.
MINIDUMP_TYPE dump_type;
// Client thread id pointer.
DWORD* thread_id;
// Exception information.
EXCEPTION_POINTERS** exception_pointers;
// Assert information in case of an invalid parameter or
// pure call failure.
MDRawAssertionInfo* assert_info;
// Handle to signal the crash event.
HANDLE dump_request_handle;
// Handle to check if server is done generating crash.
HANDLE dump_generated_handle;
// Handle to a mutex that becomes signaled (WAIT_ABANDONED)
// if server process goes down.
HANDLE server_alive_handle;
private:
// Disable copy ctor and operator=.
ProtocolMessage(const ProtocolMessage& msg);
ProtocolMessage& operator=(const ProtocolMessage& msg);
};
} // namespace google_breakpad
#endif // CLIENT_WINDOWS_COMMON_IPC_PROTOCOL_H__

Просмотреть файл

@ -0,0 +1,58 @@
=========================================================================
State machine transitions for the Crash Generation Server
=========================================================================
=========================================================================
|
STATE | ACTIONS
|
=========================================================================
ERROR | Clean up resources used to serve clients.
| Always remain in ERROR state.
-------------------------------------------------------------------------
INITIAL | Connect to the pipe asynchronously.
| If connection is successfully queued up asynchronously,
| go into CONNECTING state.
| If connection is done synchronously, go into CONNECTED
| state.
| For any unexpected problems, go into ERROR state.
-------------------------------------------------------------------------
CONNECTING | Get the result of async connection request.
| If I/O is still incomplete, remain in the CONNECTING
| state.
| If connection is complete, go into CONNECTED state.
| For any unexpected problems, go into DISCONNECTING state.
-------------------------------------------------------------------------
CONNECTED | Read from the pipe asynchronously.
| If read request is successfully queued up asynchronously,
| go into READING state.
| For any unexpected problems, go into DISCONNECTING state.
-------------------------------------------------------------------------
READING | Get the result of async read request.
| If read is done, go into READ_DONE state.
| For any unexpected problems, go into DISCONNECTING state.
-------------------------------------------------------------------------
READ_DONE | Register the client, prepare the reply and write the
| reply to the pipe asynchronously.
| If write request is successfully queued up asynchronously,
| go into WRITING state.
| For any unexpected problems, go into DISCONNECTING state.
-------------------------------------------------------------------------
WRITING | Get the result of the async write request.
| If write is done, go into WRITE_DONE state.
| For any unexpected problems, go into DISCONNECTING state.
-------------------------------------------------------------------------
WRITE_DONE | Read from the pipe asynchronously (for an ACK).
| If read request is successfully queued up asynchonously,
| go into READING_ACK state.
| For any unexpected problems, go into DISCONNECTING state.
-------------------------------------------------------------------------
READING_ACK | Get the result of the async read request.
| If read is done, perform action for successful client
| connection.
| Go into DISCONNECTING state.
-------------------------------------------------------------------------
DISCONNECTING | Disconnect from the pipe, reset the event and go into
| INITIAL state and signal the event again. If anything
| fails, go into ERROR state.
=========================================================================

Просмотреть файл

@ -0,0 +1,147 @@
// Copyright (c) 2008, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "client/windows/crash_generation/client_info.h"
namespace google_breakpad {
ClientInfo::ClientInfo(CrashGenerationServer* crash_server,
DWORD pid,
MINIDUMP_TYPE dump_type,
DWORD* thread_id,
EXCEPTION_POINTERS** ex_info,
MDRawAssertionInfo* assert_info)
: crash_server_(crash_server),
pid_(pid),
dump_type_(dump_type),
ex_info_(ex_info),
assert_info_(assert_info),
thread_id_(thread_id),
process_handle_(NULL),
dump_requested_handle_(NULL),
dump_generated_handle_(NULL),
dump_request_wait_handle_(NULL),
process_exit_wait_handle_(NULL) {
}
bool ClientInfo::Initialize() {
process_handle_ = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid_);
if (!process_handle_) {
return false;
}
dump_requested_handle_ = CreateEvent(NULL, // Security attributes.
TRUE, // Manual reset.
FALSE, // Initial state.
NULL); // Name.
if (!dump_requested_handle_) {
return false;
}
dump_generated_handle_ = CreateEvent(NULL, // Security attributes.
TRUE, // Manual reset.
FALSE, // Initial state.
NULL); // Name.
return dump_generated_handle_ != NULL;
}
ClientInfo::~ClientInfo() {
if (process_handle_) {
CloseHandle(process_handle_);
}
if (dump_requested_handle_) {
CloseHandle(dump_requested_handle_);
}
if (dump_generated_handle_) {
CloseHandle(dump_generated_handle_);
}
if (dump_request_wait_handle_) {
// Wait for callbacks that might already be running to finish.
UnregisterWaitEx(dump_request_wait_handle_, INVALID_HANDLE_VALUE);
}
if (process_exit_wait_handle_) {
// Wait for the callback that might already be running to finish.
UnregisterWaitEx(process_exit_wait_handle_, INVALID_HANDLE_VALUE);
}
}
bool ClientInfo::UnregisterWaits() {
bool success = true;
if (dump_request_wait_handle_) {
if (!UnregisterWait(dump_request_wait_handle_)) {
success = false;
} else {
dump_request_wait_handle_ = NULL;
}
}
if (process_exit_wait_handle_) {
if (!UnregisterWait(process_exit_wait_handle_)) {
success = false;
} else {
process_exit_wait_handle_ = NULL;
}
}
return success;
}
bool ClientInfo::GetClientExceptionInfo(
EXCEPTION_POINTERS** ex_info) const {
SIZE_T bytes_count = 0;
if (!ReadProcessMemory(process_handle_,
ex_info_,
ex_info,
sizeof(*ex_info),
&bytes_count)) {
return false;
}
return bytes_count == sizeof(*ex_info);
}
bool ClientInfo::GetClientThreadId(DWORD* thread_id) const {
SIZE_T bytes_count = 0;
if (!ReadProcessMemory(process_handle_,
thread_id_,
thread_id,
sizeof(*thread_id),
&bytes_count)) {
return false;
}
return bytes_count == sizeof(*thread_id);
}
} // namespace google_breakpad

Просмотреть файл

@ -0,0 +1,145 @@
// Copyright (c) 2008, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef CLIENT_WINDOWS_CRASH_GENERATION_CLIENT_INFO_H__
#define CLIENT_WINDOWS_CRASH_GENERATION_CLIENT_INFO_H__
#include <Windows.h>
#include <DbgHelp.h>
#include "google_breakpad/common/minidump_format.h"
namespace google_breakpad {
class CrashGenerationServer;
// Abstraction for a crash client process.
class ClientInfo {
public:
// Creates an instance with the given values. Gets the process
// handle for the given process id and creates necessary event
// objects.
ClientInfo(CrashGenerationServer* crash_server,
DWORD pid,
MINIDUMP_TYPE dump_type,
DWORD* thread_id,
EXCEPTION_POINTERS** ex_info,
MDRawAssertionInfo* assert_info);
~ClientInfo();
CrashGenerationServer* crash_server() const { return crash_server_; }
DWORD pid() const { return pid_; }
MINIDUMP_TYPE dump_type() const { return dump_type_; }
EXCEPTION_POINTERS** ex_info() const { return ex_info_; }
MDRawAssertionInfo* assert_info() const { return assert_info_; }
DWORD* thread_id() const { return thread_id_; }
HANDLE process_handle() const { return process_handle_; }
HANDLE dump_requested_handle() const { return dump_requested_handle_; }
HANDLE dump_generated_handle() const { return dump_generated_handle_; }
HANDLE dump_request_wait_handle() const {
return dump_request_wait_handle_;
}
void set_dump_request_wait_handle(HANDLE value) {
dump_request_wait_handle_ = value;
}
HANDLE process_exit_wait_handle() const {
return process_exit_wait_handle_;
}
void set_process_exit_wait_handle(HANDLE value) {
process_exit_wait_handle_ = value;
}
// Unregister all waits for the client.
bool UnregisterWaits();
bool Initialize();
bool GetClientExceptionInfo(EXCEPTION_POINTERS** ex_info) const;
bool GetClientThreadId(DWORD* thread_id) const;
private:
// Crash generation server.
CrashGenerationServer* crash_server_;
// Client process ID.
DWORD pid_;
// Dump type requested by the client.
MINIDUMP_TYPE dump_type_;
// Address of an EXCEPTION_POINTERS* variable in the client
// process address space that will point to an instance of
// EXCEPTION_POINTERS containing information about crash.
//
// WARNING: Do not dereference these pointers as they are pointers
// in the address space of another process.
EXCEPTION_POINTERS** ex_info_;
// Address of an instance of MDRawAssertionInfo in the client
// process address space that will contain information about
// non-exception related crashes like invalid parameter assertion
// failures and pure calls.
//
// WARNING: Do not dereference these pointers as they are pointers
// in the address space of another process.
MDRawAssertionInfo* assert_info_;
// Address of a variable in the client process address space that
// will contain the thread id of the crashing client thread.
//
// WARNING: Do not dereference these pointers as they are pointers
// in the address space of another process.
DWORD* thread_id_;
// Client process handle.
HANDLE process_handle_;
// Dump request event handle.
HANDLE dump_requested_handle_;
// Dump generated event handle.
HANDLE dump_generated_handle_;
// Wait handle for dump request event.
HANDLE dump_request_wait_handle_;
// Wait handle for process exit event.
HANDLE process_exit_wait_handle_;
// Disallow copy ctor and operator=.
ClientInfo(const ClientInfo& client_info);
ClientInfo& operator=(const ClientInfo& client_info);
};
} // namespace google_breakpad
#endif // CLIENT_WINDOWS_CRASH_GENERATION_CLIENT_INFO_H__

Просмотреть файл

@ -0,0 +1,343 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="8.00"
Name="crash_generation"
ProjectGUID="{A820AF62-6239-4693-8430-4F516C1838F4}"
RootNamespace="CrashGenerationServer"
Keyword="Win32Proj"
>
<Platforms>
<Platform
Name="Win32"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="4"
CharacterSet="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="..\..\.."
PreprocessorDefinitions="WIN32;_DEBUG;_LIB;WIN32_LEAN_AND_MEAN;_WIN32_WINNT=0x0500"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
UsePrecompiledHeader="0"
WarningLevel="4"
Detect64BitPortabilityProblems="true"
DebugInformationFormat="4"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLibrarianTool"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="4"
CharacterSet="1"
WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="..\..\.."
PreprocessorDefinitions="WIN32;NDEBUG;_LIB;WIN32_LEAN_AND_MEAN;_WIN32_WINNT=0x0500"
RuntimeLibrary="2"
UsePrecompiledHeader="0"
WarningLevel="4"
Detect64BitPortabilityProblems="true"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLibrarianTool"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="DebugStaticCRT|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="4"
CharacterSet="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="..\..\.."
PreprocessorDefinitions="WIN32;_DEBUG;_LIB;WIN32_LEAN_AND_MEAN;_WIN32_WINNT=0x0500"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="1"
UsePrecompiledHeader="0"
WarningLevel="4"
Detect64BitPortabilityProblems="true"
DebugInformationFormat="4"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLibrarianTool"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="ReleaseStaticCRT|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="4"
CharacterSet="1"
WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="..\..\.."
PreprocessorDefinitions="WIN32;NDEBUG;_LIB;WIN32_LEAN_AND_MEAN;_WIN32_WINNT=0x0500"
RuntimeLibrary="0"
UsePrecompiledHeader="0"
WarningLevel="4"
Detect64BitPortabilityProblems="true"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLibrarianTool"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="Source Files"
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
>
<File
RelativePath=".\client_info.cc"
>
</File>
<File
RelativePath=".\crash_generation_client.cc"
>
</File>
<File
RelativePath=".\crash_generation_server.cc"
>
</File>
<File
RelativePath="..\..\..\common\windows\guid_string.cc"
>
</File>
<File
RelativePath=".\minidump_generator.cc"
>
</File>
</Filter>
<Filter
Name="Header Files"
Filter="h;hpp;hxx;hm;inl;inc;xsd"
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
>
<File
RelativePath="..\common\auto_critical_section.h"
>
</File>
<File
RelativePath=".\client_info.h"
>
</File>
<File
RelativePath=".\crash_generation_client.h"
>
</File>
<File
RelativePath=".\crash_generation_server.h"
>
</File>
<File
RelativePath="..\common\ipc_protocol.h"
>
</File>
<File
RelativePath="..\..\..\google_breakpad\common\minidump_format.h"
>
</File>
<File
RelativePath=".\minidump_generator.h"
>
</File>
</Filter>
<Filter
Name="Resource Files"
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
>
</Filter>
<File
RelativePath=".\ReadMe.txt"
>
</File>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

Просмотреть файл

@ -0,0 +1,329 @@
// Copyright (c) 2008, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "client/windows/crash_generation/crash_generation_client.h"
#include <cassert>
#include "client/windows/common/ipc_protocol.h"
namespace google_breakpad {
const int kPipeBusyWaitTimeoutMs = 2000;
#ifdef _DEBUG
const DWORD kWaitForServerTimeoutMs = INFINITE;
#else
const DWORD kWaitForServerTimeoutMs = 15000;
#endif
const int kPipeConnectMaxAttempts = 2;
const DWORD kPipeDesiredAccess = FILE_READ_DATA |
FILE_WRITE_DATA |
FILE_WRITE_ATTRIBUTES;
const DWORD kPipeFlagsAndAttributes = SECURITY_IDENTIFICATION |
SECURITY_SQOS_PRESENT;
const DWORD kPipeMode = PIPE_READMODE_MESSAGE;
const size_t kWaitEventCount = 2;
// This function is orphan for production code. It can be used
// for debugging to help repro some scenarios like the client
// is slow in writing to the pipe after connecting, the client
// is slow in reading from the pipe after writing, etc. The parameter
// overlapped below is not used and it is present to match the signature
// of this function to TransactNamedPipe Win32 API. Uncomment if needed
// for debugging.
/**
static bool TransactNamedPipeDebugHelper(HANDLE pipe,
const void* in_buffer,
DWORD in_size,
void* out_buffer,
DWORD out_size,
DWORD* bytes_count,
LPOVERLAPPED) {
// Uncomment the next sleep to create a gap before writing
// to pipe.
// Sleep(5000);
if (!WriteFile(pipe,
in_buffer,
in_size,
bytes_count,
NULL)) {
return false;
}
// Uncomment the next sleep to create a gap between write
// and read.
// Sleep(5000);
return ReadFile(pipe, out_buffer, out_size, bytes_count, NULL) != FALSE;
}
**/
CrashGenerationClient::CrashGenerationClient(const wchar_t* pipe_name,
MINIDUMP_TYPE dump_type)
: pipe_name_(pipe_name),
dump_type_(dump_type),
thread_id_(0),
server_process_id_(0),
crash_event_(NULL),
crash_generated_(NULL),
server_alive_(NULL),
exception_pointers_(NULL) {
memset(&assert_info_, 0, sizeof(assert_info_));
}
CrashGenerationClient::~CrashGenerationClient() {
if (crash_event_) {
CloseHandle(crash_event_);
}
if (crash_generated_) {
CloseHandle(crash_generated_);
}
if (server_alive_) {
CloseHandle(server_alive_);
}
}
// Performs the registration step with the server process.
// The registration step involves communicating with the server
// via a named pipe. The client sends the following pieces of
// data to the server:
//
// * Message tag indicating the client is requesting registration.
// * Process id of the client process.
// * Address of a DWORD variable in the client address space
// that will contain the thread id of the client thread that
// caused the crash.
// * Address of a EXCEPTION_POINTERS* variable in the client
// address space that will point to an instance of EXCEPTION_POINTERS
// when the crash happens.
// * Address of an instance of MDRawAssertionInfo that will contain
// relevant information in case of non-exception crashes like assertion
// failures and pure calls.
//
// In return the client expects the following information from the server:
//
// * Message tag indicating successful registration.
// * Server process id.
// * Handle to an object that client can signal to request dump
// generation from the server.
// * Handle to an object that client can wait on after requesting
// dump generation for the server to finish dump generation.
// * Handle to a mutex object that client can wait on to make sure
// server is still alive.
//
// If any step of the expected behavior mentioned above fails, the
// registration step is not considered successful and hence out-of-process
// dump generation service is not available.
//
// Returns true if the registration is successful; false otherwise.
bool CrashGenerationClient::Register() {
HANDLE pipe = ConnectToServer();
if (!pipe) {
return false;
}
bool success = RegisterClient(pipe);
CloseHandle(pipe);
return success;
}
HANDLE CrashGenerationClient::ConnectToServer() {
HANDLE pipe = ConnectToPipe(pipe_name_.c_str(),
kPipeDesiredAccess,
kPipeFlagsAndAttributes);
if (!pipe) {
return NULL;
}
DWORD mode = kPipeMode;
if (!SetNamedPipeHandleState(pipe, &mode, NULL, NULL)) {
CloseHandle(pipe);
pipe = NULL;
}
return pipe;
}
bool CrashGenerationClient::RegisterClient(HANDLE pipe) {
ProtocolMessage msg(MESSAGE_TAG_REGISTRATION_REQUEST,
GetCurrentProcessId(),
dump_type_,
&thread_id_,
&exception_pointers_,
&assert_info_,
NULL,
NULL,
NULL);
ProtocolMessage reply;
DWORD bytes_count = 0;
// The call to TransactNamedPipe below can be changed to a call
// to TransactNamedPipeDebugHelper to help repro some scenarios.
// For details see comments for TransactNamedPipeDebugHelper.
if (!TransactNamedPipe(pipe,
&msg,
sizeof(msg),
&reply,
sizeof(ProtocolMessage),
&bytes_count,
NULL)) {
return false;
}
if (!ValidateResponse(reply)) {
return false;
}
ProtocolMessage ack_msg;
ack_msg.tag = MESSAGE_TAG_REGISTRATION_ACK;
if (!WriteFile(pipe, &ack_msg, sizeof(ack_msg), &bytes_count, NULL)) {
return false;
}
crash_event_ = reply.dump_request_handle;
crash_generated_ = reply.dump_generated_handle;
server_alive_ = reply.server_alive_handle;
server_process_id_ = reply.pid;
return true;
}
HANDLE CrashGenerationClient::ConnectToPipe(const wchar_t* pipe_name,
DWORD pipe_access,
DWORD flags_attrs) {
for (int i = 0; i < kPipeConnectMaxAttempts; ++i) {
HANDLE pipe = CreateFile(pipe_name,
pipe_access,
0,
NULL,
OPEN_EXISTING,
flags_attrs,
NULL);
if (pipe != INVALID_HANDLE_VALUE) {
return pipe;
}
// Cannot continue retrying if error is something other than
// ERROR_PIPE_BUSY.
if (GetLastError() != ERROR_PIPE_BUSY) {
break;
}
// Cannot continue retrying if wait on pipe fails.
if (!WaitNamedPipe(pipe_name, kPipeBusyWaitTimeoutMs)) {
break;
}
}
return NULL;
}
bool CrashGenerationClient::ValidateResponse(
const ProtocolMessage& msg) const {
return (msg.tag == MESSAGE_TAG_REGISTRATION_RESPONSE) &&
(msg.pid != 0) &&
(msg.dump_request_handle != NULL) &&
(msg.dump_generated_handle != NULL) &&
(msg.server_alive_handle != NULL);
}
bool CrashGenerationClient::IsRegistered() const {
return crash_event_ != NULL;
}
bool CrashGenerationClient::RequestDump(EXCEPTION_POINTERS* ex_info) {
if (!IsRegistered()) {
return false;
}
exception_pointers_ = ex_info;
thread_id_ = GetCurrentThreadId();
assert_info_.line = 0;
assert_info_.type = 0;
assert_info_.expression[0] = 0;
assert_info_.file[0] = 0;
assert_info_.function[0] = 0;
return SignalCrashEventAndWait();
}
bool CrashGenerationClient::RequestDump(MDRawAssertionInfo* assert_info) {
if (!IsRegistered()) {
return false;
}
exception_pointers_ = NULL;
if (assert_info) {
memcpy(&assert_info_, assert_info, sizeof(assert_info_));
} else {
memset(&assert_info_, 0, sizeof(assert_info_));
}
thread_id_ = GetCurrentThreadId();
return SignalCrashEventAndWait();
}
bool CrashGenerationClient::SignalCrashEventAndWait() {
assert(crash_event_);
assert(crash_generated_);
assert(server_alive_);
// Reset the dump generated event before signaling the crash
// event so that the server can set the dump generated event
// once it is done generating the event.
if (!ResetEvent(crash_generated_)) {
return false;
}
if (!SetEvent(crash_event_)) {
return false;
}
HANDLE wait_handles[kWaitEventCount] = {crash_generated_, server_alive_};
DWORD result = WaitForMultipleObjects(kWaitEventCount,
wait_handles,
FALSE,
kWaitForServerTimeoutMs);
// Crash dump was successfully generated only if the server
// signaled the crash generated event.
return result == WAIT_OBJECT_0;
}
} // namespace google_breakpad

Просмотреть файл

@ -0,0 +1,149 @@
// Copyright (c) 2008, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef CLIENT_WINDOWS_CRASH_GENERATION_CRASH_GENERATION_CLIENT_H__
#define CLIENT_WINDOWS_CRASH_GENERATION_CRASH_GENERATION_CLIENT_H__
#include <string>
#include "client/windows/common/ipc_protocol.h"
namespace google_breakpad {
// Abstraction of client-side implementation of out of process
// crash generation.
//
// The process that desires to have out-of-process crash dump
// generation service can use this class in the following way:
//
// * Create an instance.
// * Call Register method so that the client tries to register
// with the server process and check the return value. If
// registration is not successful, out-of-process crash dump
// generation will not be available
// * Request dump generation by calling either of the two
// overloaded RequestDump methods - one in case of exceptions
// and the other in case of assertion failures
//
// Note that it is the responsibility of the client code of
// this class to set the unhandled exception filter with the
// system by calling the SetUnhandledExceptionFilter function
// and the client code should explicitly request dump generation.
class CrashGenerationClient {
public:
CrashGenerationClient(const wchar_t* pipe_name,
MINIDUMP_TYPE dump_type);
~CrashGenerationClient();
// Registers the client process with the crash server.
//
// Returns true if the registration is successful; false otherwise.
bool Register();
// Requests the crash server to generate a dump with the given
// exception information.
//
// Returns true if the dump was successful; false otherwise. Note that
// if the registration step was not performed or it was not successful,
// false will be returned.
bool RequestDump(EXCEPTION_POINTERS* ex_info);
// Requests the crash server to generate a dump with the given
// assertion information.
//
// Returns true if the dump was successful; false otherwise. Note that
// if the registration step was not performed or it was not successful,
// false will be returned.
bool RequestDump(MDRawAssertionInfo* assert_info);
private:
// Connects to the appropriate pipe and sets the pipe handle state.
//
// Returns the pipe handle if everything goes well; otherwise Returns NULL.
HANDLE ConnectToServer();
// Performs a handshake with the server over the given pipe which should be
// already connected to the server.
//
// Returns true if handshake with the server was successful; false otherwise.
bool RegisterClient(HANDLE pipe);
// Validates the given server response.
bool ValidateResponse(const ProtocolMessage& msg) const;
// Returns true if the registration step succeeded; false otherwise.
bool IsRegistered() const;
// Connects to the given named pipe with given parameters.
//
// Returns true if the connection is successful; false otherwise.
HANDLE ConnectToPipe(const wchar_t* pipe_name,
DWORD pipe_access,
DWORD flags_attrs);
// Signals the crash event and wait for the server to generate crash.
bool SignalCrashEventAndWait();
// Pipe name to use to talk to server.
std::wstring pipe_name_;
// Type of dump to generate.
MINIDUMP_TYPE dump_type_;
// Event to signal in case of a crash.
HANDLE crash_event_;
// Handle to wait on after signaling a crash for the server
// to finish generating crash dump.
HANDLE crash_generated_;
// Handle to a mutex that will become signaled with WAIT_ABANDONED
// if the server process goes down.
HANDLE server_alive_;
// Server process id.
DWORD server_process_id_;
// Id of the thread that caused the crash.
DWORD thread_id_;
// Exception pointers for an exception crash.
EXCEPTION_POINTERS* exception_pointers_;
// Assertion info for an invalid parameter or pure call crash.
MDRawAssertionInfo assert_info_;
// Disable copy ctor and operator=.
CrashGenerationClient(const CrashGenerationClient& crash_client);
CrashGenerationClient& operator=(const CrashGenerationClient& crash_client);
};
} // namespace google_breakpad
#endif // CLIENT_WINDOWS_CRASH_GENERATION_CRASH_GENERATION_CLIENT_H__

Просмотреть файл

@ -0,0 +1,825 @@
// Copyright (c) 2008, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "client/windows/crash_generation/crash_generation_server.h"
#include <Windows.h>
#include <cassert>
#include "client/windows/common/auto_critical_section.h"
#include "processor/scoped_ptr.h"
namespace google_breakpad {
// Output buffer size.
const size_t kOutBufferSize = 64;
// Input buffer size.
const size_t kInBufferSize = 64;
// Access flags for the client on the dump request event.
const DWORD kDumpRequestEventAccess = EVENT_MODIFY_STATE;
// Access flags for the client on the dump generated event.
const DWORD kDumpGeneratedEventAccess = EVENT_MODIFY_STATE |
SYNCHRONIZE;
// Access flags for the client on the mutex.
const DWORD kMutexAccess = SYNCHRONIZE;
// Attribute flags for the pipe.
const DWORD kPipeAttr = FILE_FLAG_FIRST_PIPE_INSTANCE |
PIPE_ACCESS_DUPLEX |
FILE_FLAG_OVERLAPPED;
// Mode for the pipe.
const DWORD kPipeMode = PIPE_TYPE_MESSAGE |
PIPE_READMODE_MESSAGE |
PIPE_WAIT;
// For pipe I/O, execute the callback in the wait thread itself,
// since the callback does very little work. The callback executes
// the code for one of the states of the server state machine and
// the code for all of the states perform async I/O and hence
// finish very quickly.
const ULONG kPipeIOThreadFlags = WT_EXECUTEINWAITTHREAD;
// Dump request threads will, most likely, generate dumps. That may
// take some time to finish, so specify WT_EXECUTELONGFUNCTION flag.
const ULONG kDumpRequestThreadFlags = WT_EXECUTEINWAITTHREAD |
WT_EXECUTELONGFUNCTION;
// Maximum delay during server shutdown if some work items
// are still executing.
const int kShutdownDelayMs = 10000;
// Interval for each sleep during server shutdown.
const int kShutdownSleepIntervalMs = 5;
static bool ValidateClientRequest(const ProtocolMessage& msg) {
return msg.tag == MESSAGE_TAG_REGISTRATION_REQUEST &&
msg.pid != 0 &&
msg.thread_id != NULL &&
msg.exception_pointers != NULL &&
msg.assert_info != NULL;
}
CrashGenerationServer::CrashGenerationServer(
const wchar_t* pipe_name,
OnClientConnectedCallback connect_callback,
void* connect_context,
OnClientDumpRequestCallback dump_callback,
void* dump_context,
OnClientExitedCallback exit_callback,
void* exit_context,
bool generate_dumps,
const std::wstring* dump_path)
: pipe_name_(pipe_name),
pipe_(NULL),
pipe_wait_handle_(NULL),
server_alive_handle_(NULL),
connect_callback_(connect_callback),
connect_context_(connect_context),
dump_callback_(dump_callback),
dump_context_(dump_context),
exit_callback_(exit_callback),
exit_context_(exit_context),
generate_dumps_(generate_dumps),
dump_generator_(NULL),
server_state_(IPC_SERVER_STATE_INITIAL),
shutting_down_(false),
overlapped_(),
client_info_(NULL),
cleanup_item_count_(0) {
InitializeCriticalSection(&clients_sync_);
if (dump_path) {
dump_generator_.reset(new MinidumpGenerator(*dump_path));
}
}
CrashGenerationServer::~CrashGenerationServer() {
// Indicate to existing threads that server is shutting down.
shutting_down_ = true;
// Unregister wait on the pipe.
if (pipe_wait_handle_) {
// Wait for already executing callbacks to finish.
UnregisterWaitEx(pipe_wait_handle_, INVALID_HANDLE_VALUE);
}
// Close the pipe to avoid further client connections.
if (pipe_) {
CloseHandle(pipe_);
}
// Request all ClientInfo objects to unregister all waits.
// New scope to hold the lock for the shortest time.
{
AutoCriticalSection lock(&clients_sync_);
std::list<ClientInfo*>::iterator iter;
for (iter = clients_.begin(); iter != clients_.end(); ++iter) {
ClientInfo* client_info = *iter;
client_info->UnregisterWaits();
}
}
// Now that all waits have been unregistered, wait for some time
// for all pending work items to finish.
int total_wait = 0;
while (cleanup_item_count_ > 0) {
Sleep(kShutdownSleepIntervalMs);
total_wait += kShutdownSleepIntervalMs;
if (total_wait >= kShutdownDelayMs) {
break;
}
}
// Clean up all the ClientInfo objects.
// New scope to hold the lock for the shortest time.
{
AutoCriticalSection lock(&clients_sync_);
std::list<ClientInfo*>::iterator iter;
for (iter = clients_.begin(); iter != clients_.end(); ++iter) {
ClientInfo* client_info = *iter;
delete client_info;
}
}
if (server_alive_handle_) {
// Release the mutex before closing the handle so that clients requesting
// dumps wait for a long time for the server to generate a dump.
ReleaseMutex(server_alive_handle_);
CloseHandle(server_alive_handle_);
}
DeleteCriticalSection(&clients_sync_);
}
bool CrashGenerationServer::Start() {
server_state_ = IPC_SERVER_STATE_INITIAL;
server_alive_handle_ = CreateMutex(NULL, TRUE, NULL);
if (!server_alive_handle_) {
return false;
}
// Event to signal the client connection and pipe reads and writes.
overlapped_.hEvent = CreateEvent(NULL, // Security descriptor.
TRUE, // Manual reset.
FALSE, // Initially signaled.
NULL); // Name.
if (!overlapped_.hEvent) {
return false;
}
// Register a callback with the thread pool for the client connection.
RegisterWaitForSingleObject(&pipe_wait_handle_,
overlapped_.hEvent,
OnPipeConnected,
this,
INFINITE,
kPipeIOThreadFlags);
pipe_ = CreateNamedPipe(pipe_name_.c_str(),
kPipeAttr,
kPipeMode,
1,
kOutBufferSize,
kInBufferSize,
0,
NULL);
if (!pipe_) {
return false;
}
// Signal the event to start a separate thread to handle
// client connections.
return SetEvent(overlapped_.hEvent) != FALSE;
}
// If the server thread serving clients ever gets into the
// ERROR state, reset the event, close the pipe and remain
// in the error state forever. Error state means something
// that we didn't account for has happened, and it's dangerous
// to do anything unknowingly.
void CrashGenerationServer::HandleErrorState() {
assert(server_state_ == IPC_SERVER_STATE_ERROR);
// If the server is shutting down anyway, don't clean up
// here since shut down process will clean up.
if (shutting_down_) {
return;
}
if (pipe_wait_handle_) {
UnregisterWait(pipe_wait_handle_);
pipe_wait_handle_ = NULL;
}
if (pipe_) {
CloseHandle(pipe_);
pipe_ = NULL;
}
if (overlapped_.hEvent) {
CloseHandle(overlapped_.hEvent);
overlapped_.hEvent = NULL;
}
}
// When the server thread serving clients is in the INITIAL state,
// try to connect to the pipe asynchronously. If the connection
// finishes synchronously, directly go into the CONNECTED state;
// otherwise go into the CONNECTING state. For any problems, go
// into the ERROR state.
void CrashGenerationServer::HandleInitialState() {
assert(server_state_ == IPC_SERVER_STATE_INITIAL);
if (!ResetEvent(overlapped_.hEvent)) {
server_state_ = IPC_SERVER_STATE_ERROR;
return;
}
bool success;
success = ConnectNamedPipe(pipe_, &overlapped_) != FALSE;
// From MSDN, it is not clear that when ConnectNamedPipe is used
// in an overlapped mode, will it ever return non-zero value, and
// if so, in what cases.
assert(!success);
DWORD error_code = GetLastError();
switch (error_code) {
case ERROR_IO_PENDING:
server_state_ = IPC_SERVER_STATE_CONNECTING;
break;
case ERROR_PIPE_CONNECTED:
if (SetEvent(overlapped_.hEvent)) {
server_state_ = IPC_SERVER_STATE_CONNECTED;
} else {
server_state_ = IPC_SERVER_STATE_ERROR;
}
break;
default:
server_state_ = IPC_SERVER_STATE_ERROR;
break;
}
}
// When the server thread serving the clients is in the CONNECTING state,
// try to get the result of the asynchronous connection request using
// the OVERLAPPED object. If the result indicates the connection is done,
// go into the CONNECTED state. If the result indicates I/O is still
// INCOMPLETE, remain in the CONNECTING state. For any problems,
// go into the DISCONNECTING state.
void CrashGenerationServer::HandleConnectingState() {
assert(server_state_ == IPC_SERVER_STATE_CONNECTING);
DWORD bytes_count = 0;
bool success = GetOverlappedResult(pipe_,
&overlapped_,
&bytes_count,
FALSE) != FALSE;
if (success) {
server_state_ = IPC_SERVER_STATE_CONNECTED;
return;
}
if (GetLastError() != ERROR_IO_INCOMPLETE) {
server_state_ = IPC_SERVER_STATE_DISCONNECTING;
}
}
// When the server thread serving the clients is in the CONNECTED state,
// try to issue an asynchronous read from the pipe. If read completes
// synchronously or if I/O is pending then go into the READING state.
// For any problems, go into the DISCONNECTING state.
void CrashGenerationServer::HandleConnectedState() {
assert(server_state_ == IPC_SERVER_STATE_CONNECTED);
DWORD bytes_count = 0;
memset(&msg_, 0, sizeof(msg_));
bool success = ReadFile(pipe_,
&msg_,
sizeof(msg_),
&bytes_count,
&overlapped_) != FALSE;
// Note that the asynchronous read issued above can finish before the
// code below executes. But, it is okay to change state after issuing
// the asynchronous read. This is because even if the asynchronous read
// is done, the callback for it would not be executed until the current
// thread finishes its execution.
if (success || GetLastError() == ERROR_IO_PENDING) {
server_state_ = IPC_SERVER_STATE_READING;
} else {
server_state_ = IPC_SERVER_STATE_DISCONNECTING;
}
}
// When the server thread serving the clients is in the READING state,
// try to get the result of the async read. If async read is done,
// go into the READ_DONE state. For any problems, go into the
// DISCONNECTING state.
void CrashGenerationServer::HandleReadingState() {
assert(server_state_ == IPC_SERVER_STATE_READING);
DWORD bytes_count = 0;
bool success = GetOverlappedResult(pipe_,
&overlapped_,
&bytes_count,
FALSE) != FALSE;
if (success && bytes_count == sizeof(ProtocolMessage)){
server_state_ = IPC_SERVER_STATE_READ_DONE;
return;
}
DWORD error_code;
error_code = GetLastError();
// We should never get an I/O incomplete since we should not execute this
// unless the Read has finished and the overlapped event is signaled. If
// we do get INCOMPLETE, we have a bug in our code.
assert(error_code != ERROR_IO_INCOMPLETE);
server_state_ = IPC_SERVER_STATE_DISCONNECTING;
}
// When the server thread serving the client is in the READ_DONE state,
// validate the client's request message, register the client by
// creating appropriate objects and prepare the response. Then try to
// write the response to the pipe asynchronously. If that succeeds,
// go into the WRITING state. For any problems, go into the DISCONNECTING
// state.
void CrashGenerationServer::HandleReadDoneState() {
assert(server_state_ == IPC_SERVER_STATE_READ_DONE);
if (!ValidateClientRequest(msg_)) {
server_state_ = IPC_SERVER_STATE_DISCONNECTING;
return;
}
scoped_ptr<ClientInfo> client_info(
new ClientInfo(this,
msg_.pid,
msg_.dump_type,
msg_.thread_id,
msg_.exception_pointers,
msg_.assert_info));
if (!client_info->Initialize()) {
server_state_ = IPC_SERVER_STATE_DISCONNECTING;
return;
}
if (!RespondToClient(client_info.get())) {
server_state_ = IPC_SERVER_STATE_DISCONNECTING;
return;
}
// Note that the asynchronous write issued by RespondToClient function
// can finish before the code below executes. But it is okay to change
// state after issuing the asynchronous write. This is because even if
// the asynchronous write is done, the callback for it would not be
// executed until the current thread finishes its execution.
server_state_ = IPC_SERVER_STATE_WRITING;
client_info_ = client_info.release();
}
// When the server thread serving the clients is in the WRITING state,
// try to get the result of the async write. If the async write is done,
// go into the WRITE_DONE state. For any problems, go into the
// DISONNECTING state.
void CrashGenerationServer::HandleWritingState() {
assert(server_state_ == IPC_SERVER_STATE_WRITING);
DWORD bytes_count = 0;
bool success = GetOverlappedResult(pipe_,
&overlapped_,
&bytes_count,
FALSE) != FALSE;
if (success) {
server_state_ = IPC_SERVER_STATE_WRITE_DONE;
return;
}
DWORD error_code;
error_code = GetLastError();
// We should never get an I/O incomplete since we should not execute this
// unless the Write has finished and the overlapped event is signaled. If
// we do get INCOMPLETE, we have a bug in our code.
assert(error_code != ERROR_IO_INCOMPLETE);
server_state_ = IPC_SERVER_STATE_DISCONNECTING;
}
// When the server thread serving the clients is in the WRITE_DONE state,
// try to issue an async read on the pipe. If the read completes synchronously
// or if I/O is still pending then go into the READING_ACK state. For any
// issues, go into the DISCONNECTING state.
void CrashGenerationServer::HandleWriteDoneState() {
assert(server_state_ == IPC_SERVER_STATE_WRITE_DONE);
server_state_ = IPC_SERVER_STATE_READING_ACK;
DWORD bytes_count = 0;
bool success = ReadFile(pipe_,
&msg_,
sizeof(msg_),
&bytes_count,
&overlapped_) != FALSE;
if (success) {
return;
}
DWORD error_code = GetLastError();
if (error_code != ERROR_IO_PENDING) {
server_state_ = IPC_SERVER_STATE_DISCONNECTING;
}
}
// When the server thread serving the clients is in the READING_ACK state,
// try to get result of async read. Go into the DISCONNECTING state.
void CrashGenerationServer::HandleReadingAckState() {
assert(server_state_ == IPC_SERVER_STATE_READING_ACK);
DWORD bytes_count = 0;
bool success = GetOverlappedResult(pipe_,
&overlapped_,
&bytes_count,
FALSE) != FALSE;
if (success) {
// The connection handshake with the client is now complete; perform
// the callback.
if (connect_callback_) {
connect_callback_(connect_context_, client_info_);
}
} else {
DWORD error_code;
error_code = GetLastError();
// We should never get an I/O incomplete since we should not execute this
// unless the Read has finished and the overlapped event is signaled. If
// we do get INCOMPLETE, we have a bug in our code.
assert(error_code != ERROR_IO_INCOMPLETE);
}
server_state_ = IPC_SERVER_STATE_DISCONNECTING;
}
// When the server thread serving the client is in the DISCONNECTING state,
// disconnect from the pipe and reset the event. If anything fails, go into
// the ERROR state. If it goes well, go into the INITIAL state and set the
// event to start all over again.
void CrashGenerationServer::HandleDisconnectingState() {
assert(server_state_ == IPC_SERVER_STATE_DISCONNECTING);
// Done serving the client.
client_info_ = NULL;
overlapped_.Internal = NULL;
overlapped_.InternalHigh = NULL;
overlapped_.Offset = 0;
overlapped_.OffsetHigh = 0;
overlapped_.Pointer = NULL;
if (!ResetEvent(overlapped_.hEvent)) {
server_state_ = IPC_SERVER_STATE_ERROR;
return;
}
if (!DisconnectNamedPipe(pipe_)) {
server_state_ = IPC_SERVER_STATE_ERROR;
return;
}
// If the server is shutting down do not connect to the
// next client.
if (shutting_down_) {
return;
}
server_state_ = IPC_SERVER_STATE_INITIAL;
if (!SetEvent(overlapped_.hEvent)) {
server_state_ = IPC_SERVER_STATE_ERROR;
}
}
bool CrashGenerationServer::PrepareReply(const ClientInfo& client_info,
ProtocolMessage* reply) const {
reply->tag = MESSAGE_TAG_REGISTRATION_RESPONSE;
reply->pid = GetCurrentProcessId();
if (CreateClientHandles(client_info, reply)) {
return true;
}
if (reply->dump_request_handle) {
CloseHandle(reply->dump_request_handle);
}
if (reply->dump_generated_handle) {
CloseHandle(reply->dump_generated_handle);
}
if (reply->server_alive_handle) {
CloseHandle(reply->server_alive_handle);
}
return false;
}
bool CrashGenerationServer::CreateClientHandles(const ClientInfo& client_info,
ProtocolMessage* reply) const {
HANDLE current_process = GetCurrentProcess();
if (!DuplicateHandle(current_process,
client_info.dump_requested_handle(),
client_info.process_handle(),
&reply->dump_request_handle,
kDumpRequestEventAccess,
FALSE,
0)) {
return false;
}
if (!DuplicateHandle(current_process,
client_info.dump_generated_handle(),
client_info.process_handle(),
&reply->dump_generated_handle,
kDumpGeneratedEventAccess,
FALSE,
0)) {
return false;
}
if (!DuplicateHandle(current_process,
server_alive_handle_,
client_info.process_handle(),
&reply->server_alive_handle,
kMutexAccess,
FALSE,
0)) {
return false;
}
return true;
}
bool CrashGenerationServer::RespondToClient(ClientInfo* client_info) {
ProtocolMessage reply;
if (!PrepareReply(*client_info, &reply)) {
return false;
}
if (!AddClient(client_info)) {
return false;
}
DWORD bytes_count = 0;
bool success = WriteFile(pipe_,
&reply,
sizeof(reply),
&bytes_count,
&overlapped_) != FALSE;
return success || GetLastError() == ERROR_IO_PENDING;
}
// The server thread servicing the clients runs this method. The method
// implements the state machine described in ReadMe.txt along with the
// helper methods HandleXXXState.
void CrashGenerationServer::HandleConnectionRequest() {
switch (server_state_) {
case IPC_SERVER_STATE_ERROR:
HandleErrorState();
break;
case IPC_SERVER_STATE_INITIAL:
HandleInitialState();
break;
case IPC_SERVER_STATE_CONNECTING:
HandleConnectingState();
break;
case IPC_SERVER_STATE_CONNECTED:
HandleConnectedState();
break;
case IPC_SERVER_STATE_READING:
HandleReadingState();
break;
case IPC_SERVER_STATE_READ_DONE:
HandleReadDoneState();
break;
case IPC_SERVER_STATE_WRITING:
HandleWritingState();
break;
case IPC_SERVER_STATE_WRITE_DONE:
HandleWriteDoneState();
break;
case IPC_SERVER_STATE_READING_ACK:
HandleReadingAckState();
break;
case IPC_SERVER_STATE_DISCONNECTING:
HandleDisconnectingState();
break;
default:
assert(false);
// This indicates that we added one more state without
// adding handling code.
server_state_ = IPC_SERVER_STATE_ERROR;
break;
}
}
bool CrashGenerationServer::AddClient(ClientInfo* client_info) {
HANDLE request_wait_handle = NULL;
if (!RegisterWaitForSingleObject(&request_wait_handle,
client_info->dump_requested_handle(),
OnDumpRequest,
client_info,
INFINITE,
kDumpRequestThreadFlags)) {
return false;
}
client_info->set_dump_request_wait_handle(request_wait_handle);
// OnClientEnd will be called when the client process terminates.
HANDLE process_wait_handle = NULL;
if (!RegisterWaitForSingleObject(&process_wait_handle,
client_info->process_handle(),
OnClientEnd,
client_info,
INFINITE,
WT_EXECUTEONLYONCE)) {
return false;
}
client_info->set_process_exit_wait_handle(process_wait_handle);
// New scope to hold the lock for the shortest time.
{
AutoCriticalSection lock(&clients_sync_);
clients_.push_back(client_info);
}
return true;
}
// static
void CALLBACK CrashGenerationServer::OnPipeConnected(void* context, BOOLEAN) {
assert (context);
CrashGenerationServer* obj =
reinterpret_cast<CrashGenerationServer*>(context);
obj->HandleConnectionRequest();
}
// static
void CALLBACK CrashGenerationServer::OnDumpRequest(void* context, BOOLEAN) {
assert(context);
ClientInfo* client_info = reinterpret_cast<ClientInfo*>(context);
CrashGenerationServer* crash_server = client_info->crash_server();
assert(crash_server);
crash_server->HandleDumpRequest(*client_info);
ResetEvent(client_info->dump_requested_handle());
}
// static
void CALLBACK CrashGenerationServer::OnClientEnd(void* context, BOOLEAN) {
assert(context);
ClientInfo* client_info = reinterpret_cast<ClientInfo*>(context);
CrashGenerationServer* crash_server = client_info->crash_server();
assert(crash_server);
InterlockedIncrement(&crash_server->cleanup_item_count_);
if (!QueueUserWorkItem(CleanupClient, context, WT_EXECUTEDEFAULT))
{
InterlockedDecrement(&crash_server->cleanup_item_count_);
}
}
// static
DWORD WINAPI CrashGenerationServer::CleanupClient(void* context) {
assert(context);
ClientInfo* client_info = reinterpret_cast<ClientInfo*>(context);
CrashGenerationServer* crash_server = client_info->crash_server();
assert(crash_server);
if (crash_server->exit_callback_) {
crash_server->exit_callback_(crash_server->exit_context_, client_info);
}
crash_server->DoCleanup(client_info);
InterlockedDecrement(&crash_server->cleanup_item_count_);
return 0;
}
void CrashGenerationServer::DoCleanup(ClientInfo* client_info) {
assert(client_info);
// Start a new scope to release lock automatically.
{
AutoCriticalSection lock(&clients_sync_);
clients_.remove(client_info);
}
delete client_info;
}
void CrashGenerationServer::HandleDumpRequest(const ClientInfo& client_info) {
// Generate the dump only if it's explicitly requested by the
// server application; otherwise the server might want to generate
// dump in the callback.
if (generate_dumps_) {
if (!GenerateDump(client_info)) {
return;
}
}
if (dump_callback_) {
dump_callback_(dump_context_, &client_info);
}
SetEvent(client_info.dump_generated_handle());
}
bool CrashGenerationServer::GenerateDump(const ClientInfo& client) {
assert(client.pid() != 0);
assert(client.process_handle());
// We have to get the address of EXCEPTION_INFORMATION from
// the client process address space.
EXCEPTION_POINTERS* client_ex_info = NULL;
if (!client.GetClientExceptionInfo(&client_ex_info)) {
return false;
}
DWORD client_thread_id = 0;
if (!client.GetClientThreadId(&client_thread_id)) {
return false;
}
return dump_generator_->WriteMinidump(client.process_handle(),
client.pid(),
client_thread_id,
GetCurrentThreadId(),
client_ex_info,
client.assert_info(),
client.dump_type(),
true);
}
} // namespace google_breakpad

Просмотреть файл

@ -0,0 +1,255 @@
// Copyright (c) 2008, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef CLIENT_WINDOWS_CRASH_GENERATION_CRASH_GENERATION_SERVER_H__
#define CLIENT_WINDOWS_CRASH_GENERATION_CRASH_GENERATION_SERVER_H__
#include <list>
#include <string>
#include "client/windows/common/ipc_protocol.h"
#include "client/windows/crash_generation/client_info.h"
#include "client/windows/crash_generation/minidump_generator.h"
#include "processor/scoped_ptr.h"
namespace google_breakpad {
// Abstraction for server side implementation of out-of-process crash
// generation protocol. It generates minidumps (Windows platform) for
// client processes that request dump generation.
class CrashGenerationServer {
public:
typedef void (*OnClientConnectedCallback)(void* context,
const ClientInfo* client_info);
typedef void (*OnClientDumpRequestCallback)(void* context,
const ClientInfo* client_info);
typedef void (*OnClientExitedCallback)(void* context,
const ClientInfo* client_info);
// Creates an instance with the given parameters.
//
// Parameter pipe_name: Name of the pipe
// Parameter connect_callback: Callback for a new client connection.
// Parameter connect_context: Context for client connection callback.
// Parameter crash_callback: Callback for a client crash dump request.
// Parameter crash_context: Context for client crash dump request callback.
// Parameter exit_callback: Callback for client process exit.
// Parameter exit_context: Context for client exit callback.
// Parameter generate_dumps: Whether to automatically generate dumps or not.
// Client code of this class might want to generate dumps explicitly in the
// crash dump request callback. In that case, false can be passed for this
// parameter.
// Parameter dump_path: Path for generating dumps; required only if true is
// passed for generateDumps parameter; NULL can be passed otherwise.
CrashGenerationServer(const wchar_t* pipe_name,
OnClientConnectedCallback connect_callback,
void* connect_context,
OnClientDumpRequestCallback dump_callback,
void* dump_context,
OnClientExitedCallback exit_callback,
void* exit_context,
bool generate_dumps,
const std::wstring* dump_path);
~CrashGenerationServer();
// Performs initialization steps needed to start listening to clients.
//
// Returns true if initialization is successful; false otherwise.
bool Start();
private:
// Various states the client can be in during the handshake with
// the server.
enum IPCServerState {
// Server is in error state and it cannot serve any clients.
IPC_SERVER_STATE_ERROR,
// Server starts in this state.
IPC_SERVER_STATE_INITIAL,
// Server has issued an async connect to the pipe and it is waiting
// for the connection to be established.
IPC_SERVER_STATE_CONNECTING,
// Server is connected successfully.
IPC_SERVER_STATE_CONNECTED,
// Server has issued an async read from the pipe and it is waiting for
// the read to finish.
IPC_SERVER_STATE_READING,
// Server is done reading from the pipe.
IPC_SERVER_STATE_READ_DONE,
// Server has issued an async write to the pipe and it is waiting for
// the write to finish.
IPC_SERVER_STATE_WRITING,
// Server is done writing to the pipe.
IPC_SERVER_STATE_WRITE_DONE,
// Server has issued an async read from the pipe for an ack and it
// is waiting for the read to finish.
IPC_SERVER_STATE_READING_ACK,
// Server is done writing to the pipe and it is now ready to disconnect
// and reconnect.
IPC_SERVER_STATE_DISCONNECTING
};
//
// Helper methods to handle various server IPC states.
//
void HandleErrorState();
void HandleInitialState();
void HandleConnectingState();
void HandleConnectedState();
void HandleReadingState();
void HandleReadDoneState();
void HandleWritingState();
void HandleWriteDoneState();
void HandleReadingAckState();
void HandleDisconnectingState();
// Prepares reply for a client from the given parameters.
bool PrepareReply(const ClientInfo& client_info,
ProtocolMessage* reply) const;
// Duplicates various handles in the ClientInfo object for the client
// process and stores them in the given ProtocolMessage instance. If
// creating any handle fails, ProtocolMessage will contain the handles
// already created successfully, which should be closed by the caller.
bool CreateClientHandles(const ClientInfo& client_info,
ProtocolMessage* reply) const;
// Response to the given client. Return true if all steps of
// responding to the client succeed, false otherwise.
bool RespondToClient(ClientInfo* client_info);
// Handles a connection request from the client.
void HandleConnectionRequest();
// Handles a dump request from the client.
void HandleDumpRequest(const ClientInfo& client_info);
// Callback for pipe connected event.
static void CALLBACK OnPipeConnected(void* context, BOOLEAN timer_or_wait);
// Callback for a dump request.
static void CALLBACK OnDumpRequest(void* context, BOOLEAN timer_or_wait);
// Callback for client process exit event.
static void CALLBACK OnClientEnd(void* context, BOOLEAN timer_or_wait);
// Releases resources for a client.
static DWORD WINAPI CleanupClient(void* context);
// Cleans up for the given client.
void DoCleanup(ClientInfo* client_info);
// Adds the given client to the list of registered clients.
bool AddClient(ClientInfo* client_info);
// Generates dump for the given client.
bool GenerateDump(const ClientInfo& client);
// Sync object for thread-safe access to the shared list of clients.
CRITICAL_SECTION clients_sync_;
// List of clients.
std::list<ClientInfo*> clients_;
// Pipe name.
std::wstring pipe_name_;
// Handle to the pipe used for handshake with clients.
HANDLE pipe_;
// Pipe wait handle.
HANDLE pipe_wait_handle_;
// Handle to server-alive mutex.
HANDLE server_alive_handle_;
// Callback for a successful client connection.
OnClientConnectedCallback connect_callback_;
// Context for client connected callback.
void* connect_context_;
// Callback for a client dump request.
OnClientDumpRequestCallback dump_callback_;
// Context for client dump request callback.
void* dump_context_;
// Callback for client process exit.
OnClientExitedCallback exit_callback_;
// Context for client process exit callback.
void* exit_context_;
// Whether to generate dumps or not.
bool generate_dumps_;
// Instance of a mini dump generator.
scoped_ptr<MinidumpGenerator> dump_generator_;
// State of the server in performing the IPC with the client.
// Note that since we restrict the pipe to one instance, we
// only need to keep one state of the server. Otherwise, server
// would have one state per client it is talking to.
IPCServerState server_state_;
// Whether the server is shutting down.
volatile bool shutting_down_;
// Overlapped instance for async I/O on the pipe.
OVERLAPPED overlapped_;
// Message object used in IPC with the client.
ProtocolMessage msg_;
// Client Info for the client that's connecting to the server.
ClientInfo* client_info_;
// Count of clean-up work items that are currently running or are
// already queued to run.
volatile LONG cleanup_item_count_;
// Disable copy ctor and operator=.
CrashGenerationServer(const CrashGenerationServer& crash_server);
CrashGenerationServer& operator=(const CrashGenerationServer& crash_server);
};
} // namespace google_breakpad
#endif // CLIENT_WINDOWS_CRASH_GENERATION_CRASH_GENERATION_SERVER_H__

Просмотреть файл

@ -0,0 +1,228 @@
// Copyright (c) 2008, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "client/windows/crash_generation/minidump_generator.h"
#include <cassert>
#include "client/windows/common/auto_critical_section.h"
#include "common/windows/guid_string.h"
using std::wstring;
namespace google_breakpad {
MinidumpGenerator::MinidumpGenerator(const wstring& dump_path)
: dbghelp_module_(NULL),
rpcrt4_module_(NULL),
dump_path_(dump_path),
write_dump_(NULL),
create_uuid_(NULL) {
InitializeCriticalSection(&module_load_sync_);
InitializeCriticalSection(&get_proc_address_sync_);
}
MinidumpGenerator::~MinidumpGenerator() {
if (dbghelp_module_) {
FreeLibrary(dbghelp_module_);
}
if (rpcrt4_module_) {
FreeLibrary(rpcrt4_module_);
}
DeleteCriticalSection(&get_proc_address_sync_);
DeleteCriticalSection(&module_load_sync_);
}
bool MinidumpGenerator::WriteMinidump(HANDLE process_handle,
DWORD process_id,
DWORD thread_id,
DWORD requesting_thread_id,
EXCEPTION_POINTERS* exception_pointers,
MDRawAssertionInfo* assert_info,
MINIDUMP_TYPE dump_type,
bool is_client_pointers) {
MiniDumpWriteDumpType write_dump = GetWriteDump();
if (!write_dump) {
return false;
}
wstring dump_file_path;
if (!GenerateDumpFilePath(&dump_file_path)) {
return false;
}
HANDLE dump_file = CreateFile(dump_file_path.c_str(),
GENERIC_WRITE,
0,
NULL,
CREATE_NEW,
FILE_ATTRIBUTE_NORMAL,
NULL);
if (dump_file == INVALID_HANDLE_VALUE) {
return false;
}
MINIDUMP_EXCEPTION_INFORMATION* dump_exception_pointers = NULL;
MINIDUMP_EXCEPTION_INFORMATION dump_exception_info;
// Setup the exception information object only if it's a dump
// due to an exception.
if (exception_pointers) {
dump_exception_pointers = &dump_exception_info;
dump_exception_info.ThreadId = thread_id;
dump_exception_info.ExceptionPointers = exception_pointers;
dump_exception_info.ClientPointers = is_client_pointers;
}
// Add an MDRawBreakpadInfo stream to the minidump, to provide additional
// information about the exception handler to the Breakpad processor.
// The information will help the processor determine which threads are
// relevant. The Breakpad processor does not require this information but
// can function better with Breakpad-generated dumps when it is present.
// The native debugger is not harmed by the presence of this information.
MDRawBreakpadInfo breakpad_info;
breakpad_info.validity = MD_BREAKPAD_INFO_VALID_DUMP_THREAD_ID |
MD_BREAKPAD_INFO_VALID_REQUESTING_THREAD_ID;
breakpad_info.dump_thread_id = thread_id;
breakpad_info.requesting_thread_id = requesting_thread_id;
// Leave room in user_stream_array for a possible assertion info stream.
MINIDUMP_USER_STREAM user_stream_array[2];
user_stream_array[0].Type = MD_BREAKPAD_INFO_STREAM;
user_stream_array[0].BufferSize = sizeof(breakpad_info);
user_stream_array[0].Buffer = &breakpad_info;
MINIDUMP_USER_STREAM_INFORMATION user_streams;
user_streams.UserStreamCount = 1;
user_streams.UserStreamArray = user_stream_array;
MDRawAssertionInfo* actual_assert_info = assert_info;
MDRawAssertionInfo client_assert_info = {0};
if (assert_info) {
// If the assertion info object lives in the client process,
// read the memory of the client process.
if (is_client_pointers) {
SIZE_T bytes_read = 0;
if (!ReadProcessMemory(process_handle,
assert_info,
&client_assert_info,
sizeof(client_assert_info),
&bytes_read)) {
CloseHandle(dump_file);
return false;
}
if (bytes_read != sizeof(client_assert_info)) {
CloseHandle(dump_file);
return false;
}
actual_assert_info = &client_assert_info;
}
user_stream_array[1].Type = MD_ASSERTION_INFO_STREAM;
user_stream_array[1].BufferSize = sizeof(MDRawAssertionInfo);
user_stream_array[1].Buffer = actual_assert_info;
++user_streams.UserStreamCount;
}
bool result = write_dump(process_handle,
process_id,
dump_file,
dump_type,
exception_pointers ? &dump_exception_info : NULL,
&user_streams,
NULL) != FALSE;
CloseHandle(dump_file);
return result;
}
HMODULE MinidumpGenerator::GetDbghelpModule() {
AutoCriticalSection lock(&module_load_sync_);
if (!dbghelp_module_) {
dbghelp_module_ = LoadLibrary(TEXT("dbghelp.dll"));
}
return dbghelp_module_;
}
MinidumpGenerator::MiniDumpWriteDumpType MinidumpGenerator::GetWriteDump() {
AutoCriticalSection lock(&get_proc_address_sync_);
if (!write_dump_) {
HMODULE module = GetDbghelpModule();
if (module) {
FARPROC proc = GetProcAddress(module, "MiniDumpWriteDump");
write_dump_ = reinterpret_cast<MiniDumpWriteDumpType>(proc);
}
}
return write_dump_;
}
HMODULE MinidumpGenerator::GetRpcrt4Module() {
AutoCriticalSection lock(&module_load_sync_);
if (!rpcrt4_module_) {
rpcrt4_module_ = LoadLibrary(TEXT("rpcrt4.dll"));
}
return rpcrt4_module_;
}
MinidumpGenerator::UuidCreateType MinidumpGenerator::GetCreateUuid() {
AutoCriticalSection lock(&module_load_sync_);
if (!create_uuid_) {
HMODULE module = GetRpcrt4Module();
if (module) {
FARPROC proc = GetProcAddress(module, "UuidCreate");
create_uuid_ = reinterpret_cast<UuidCreateType>(proc);
}
}
return create_uuid_;
}
bool MinidumpGenerator::GenerateDumpFilePath(wstring* file_path) {
UUID id = {0};
UuidCreateType create_uuid = GetCreateUuid();
if(!create_uuid) {
return false;
}
create_uuid(&id);
wstring id_str = GUIDString::GUIDToWString(&id);
*file_path = dump_path_ + TEXT("\\") + id_str + TEXT(".dmp");
return true;
}
} // namespace google_breakpad

Просмотреть файл

@ -0,0 +1,118 @@
// Copyright (c) 2008, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef CLIENT_WINDOWS_CRASH_GENERATION_MINIDUMP_GENERATION_H__
#define CLIENT_WINDOWS_CRASH_GENERATION_MINIDUMP_GENERATION_H__
#include <Windows.h>
#include <DbgHelp.h>
#include <list>
#include "google_breakpad/common/minidump_format.h"
namespace google_breakpad {
// Abstraction for various objects and operations needed to generate
// minidump on Windows. This abstraction is useful to hide all the gory
// details for minidump generation and provide a clean interface to
// the clients to generate minidumps.
class MinidumpGenerator {
public:
// Creates an instance with the given dump path.
explicit MinidumpGenerator(const std::wstring& dump_path);
~MinidumpGenerator();
// Writes the minidump with the given parameters.
bool WriteMinidump(HANDLE process_handle,
DWORD process_id,
DWORD thread_id,
DWORD requesting_thread_id,
EXCEPTION_POINTERS* exception_pointers,
MDRawAssertionInfo* assert_info,
MINIDUMP_TYPE dump_type,
bool is_client_pointers);
private:
// Function pointer type for MiniDumpWriteDump, which is looked up
// dynamically.
typedef BOOL (WINAPI* MiniDumpWriteDumpType)(
HANDLE hProcess,
DWORD ProcessId,
HANDLE hFile,
MINIDUMP_TYPE DumpType,
CONST PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam,
CONST PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam,
CONST PMINIDUMP_CALLBACK_INFORMATION CallbackParam);
// Function pointer type for UuidCreate, which is looked up dynamically.
typedef RPC_STATUS (RPC_ENTRY* UuidCreateType)(UUID* Uuid);
// Loads the appropriate DLL lazily in a thread safe way.
HMODULE GetDbghelpModule();
// Loads the appropriate DLL and gets a pointer to the MiniDumpWriteDump
// function lazily and in a thread-safe manner.
MiniDumpWriteDumpType GetWriteDump();
// Loads the appropriate DLL lazily in a thread safe way.
HMODULE GetRpcrt4Module();
// Loads the appropriate DLL and gets a pointer to the UuidCreate
// function lazily and in a thread-safe manner.
UuidCreateType GetCreateUuid();
// Returns the path for the file to write dump to.
bool GenerateDumpFilePath(std::wstring* file_path);
// Handle to dynamically loaded DbgHelp.dll.
HMODULE dbghelp_module_;
// Pointer to the MiniDumpWriteDump function.
MiniDumpWriteDumpType write_dump_;
// Handle to dynamically loaded rpcrt4.dll.
HMODULE rpcrt4_module_;
// Pointer to the UuidCreate function.
UuidCreateType create_uuid_;
// Folder path to store dump files.
std::wstring dump_path_;
// Critical section to sychronize action of loading modules dynamically.
CRITICAL_SECTION module_load_sync_;
// Critical section to synchronize action of dynamically getting function
// addresses from modules.
CRITICAL_SECTION get_proc_address_sync_;
};
} // namespace google_breakpad
#endif // CLIENT_WINDOWS_CRASH_GENERATION_MINIDUMP_GENERATION_H__

Просмотреть файл

@ -0,0 +1,53 @@
// Copyright (c) 2008, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "precompile.h"
namespace google_breakpad {
Base::Base(Derived* derived)
: derived_(derived) {
}
Base::~Base() {
derived_->DoSomething();
}
#pragma warning(push)
#pragma warning(disable:4355)
// Disable warning C4355: 'this' : used in base member initializer list.
Derived::Derived()
: Base(this) { // C4355
}
#pragma warning(pop)
void Derived::DoSomething() {
}
} // namespace google_breakpad

Просмотреть файл

@ -0,0 +1,57 @@
// Copyright (c) 2008, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef CLIENT_WINDOWS_TESTS_CRASH_GENERATION_APP_ABSTRACT_CLASS_H__
#define CLIENT_WINDOWS_TESTS_CRASH_GENERATION_APP_ABSTRACT_CLASS_H__
namespace google_breakpad {
// Dummy classes to help generate a pure call violation.
class Derived;
class Base {
public:
Base(Derived* derived);
virtual ~Base();
virtual void DoSomething() = 0;
private:
Derived* derived_;
};
class Derived : public Base {
public:
Derived();
virtual void DoSomething();
};
} // namespace google_breakpad
#endif // CLIENT_WINDOWS_TESTS_CRASH_GENERATION_APP_CRASH_GENERATION_APP_H__

Просмотреть файл

@ -0,0 +1,467 @@
// Copyright (c) 2008, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// crash_generation_app.cpp : Defines the entry point for the application.
//
#include "precompile.h"
namespace google_breakpad {
const int kMaxLoadString = 100;
const wchar_t kPipeName[] = L"\\\\.\\pipe\\GoogleCrashServices";
const DWORD kEditBoxStyles = WS_CHILD |
WS_VISIBLE |
WS_VSCROLL |
ES_LEFT |
ES_MULTILINE |
ES_AUTOVSCROLL |
ES_READONLY;
// Maximum length of a line in the edit box.
const size_t kMaximumLineLength = 256;
// CS to access edit control in a thread safe way.
static CRITICAL_SECTION* cs_edit = NULL;
// Edit control.
static HWND client_status_edit_box;
HINSTANCE current_instance; // Current instance.
TCHAR title[kMaxLoadString]; // Title bar text.
TCHAR window_class[kMaxLoadString]; // Main window class name.
ATOM MyRegisterClass(HINSTANCE instance);
BOOL InitInstance(HINSTANCE, int);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
INT_PTR CALLBACK About(HWND, UINT, WPARAM, LPARAM);
static ExceptionHandler* handler = NULL;
static CrashGenerationServer* crash_server = NULL;
// Registers the window class.
//
// This function and its usage are only necessary if you want this code
// to be compatible with Win32 systems prior to the 'RegisterClassEx'
// function that was added to Windows 95. It is important to call this
// function so that the application will get 'well formed' small icons
// associated with it.
ATOM MyRegisterClass(HINSTANCE instance) {
WNDCLASSEX wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = instance;
wcex.hIcon = LoadIcon(instance,
MAKEINTRESOURCE(IDI_CRASHGENERATIONAPP));
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = MAKEINTRESOURCE(IDC_CRASHGENERATIONAPP);
wcex.lpszClassName = window_class;
wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));
return RegisterClassEx(&wcex);
}
// Saves instance handle and creates main window
//
// In this function, we save the instance handle in a global variable and
// create and display the main program window.
BOOL InitInstance(HINSTANCE instance, int command_show) {
current_instance = instance;
HWND wnd = CreateWindow(window_class,
title,
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
0,
CW_USEDEFAULT,
0,
NULL,
NULL,
instance,
NULL);
if (!wnd) {
return FALSE;
}
ShowWindow(wnd, command_show);
UpdateWindow(wnd);
return TRUE;
}
static void AppendTextToEditBox(TCHAR* text) {
EnterCriticalSection(cs_edit);
SYSTEMTIME current_time;
GetLocalTime(&current_time);
TCHAR line[kMaximumLineLength];
int result = swprintf_s(line,
kMaximumLineLength,
L"[%.2d-%.2d-%.4d %.2d:%.2d:%.2d] %s",
current_time.wMonth,
current_time.wDay,
current_time.wYear,
current_time.wHour,
current_time.wMinute,
current_time.wSecond,
text);
if (result == -1) {
return;
}
int length = GetWindowTextLength(client_status_edit_box);
SendMessage(client_status_edit_box,
EM_SETSEL,
(WPARAM)length,
(LPARAM)length);
SendMessage(client_status_edit_box,
EM_REPLACESEL,
(WPARAM)FALSE,
(LPARAM)line);
LeaveCriticalSection(cs_edit);
}
static DWORD WINAPI AppendTextWorker(void* context) {
TCHAR* text = reinterpret_cast<TCHAR*>(context);
AppendTextToEditBox(text);
delete[] text;
return 0;
}
bool ShowDumpResults(const wchar_t* dump_path,
const wchar_t* minidump_id,
void* context,
EXCEPTION_POINTERS* exinfo,
MDRawAssertionInfo* assertion,
bool succeeded) {
TCHAR* text = new TCHAR[kMaximumLineLength];
int result = swprintf_s(text,
kMaximumLineLength,
TEXT("Dump generation request %s\r\n"),
succeeded ? TEXT("succeeded") : TEXT("failed"));
if (result == -1) {
delete [] text;
}
AppendTextWorker(text);
return succeeded;
}
static void _cdecl ShowClientConnected(void* context,
const ClientInfo* client_info) {
TCHAR* line = new TCHAR[kMaximumLineLength];
int result = swprintf_s(line,
kMaximumLineLength,
L"Client connected:\t\t%d\r\n",
client_info->pid());
if (result == -1) {
delete[] line;
return;
}
QueueUserWorkItem(AppendTextWorker, line, WT_EXECUTEDEFAULT);
}
static void _cdecl ShowClientCrashed(void* context,
const ClientInfo* client_info) {
TCHAR* line = new TCHAR[kMaximumLineLength];
int result = swprintf_s(line,
kMaximumLineLength,
TEXT("Client requested dump:\t%d\r\n"),
client_info->pid());
if (result == -1) {
delete[] line;
return;
}
QueueUserWorkItem(AppendTextWorker, line, WT_EXECUTEDEFAULT);
}
static void _cdecl ShowClientExited(void* context,
const ClientInfo* client_info) {
TCHAR* line = new TCHAR[kMaximumLineLength];
int result = swprintf_s(line,
kMaximumLineLength,
TEXT("Client exited:\t\t%d\r\n"),
client_info->pid());
if (result == -1) {
delete[] line;
return;
}
QueueUserWorkItem(AppendTextWorker, line, WT_EXECUTEDEFAULT);
}
void CrashServerStart() {
// Do not create another instance of the server.
if (crash_server) {
return;
}
std::wstring dump_path = L"C:\\Dumps\\";
crash_server = new CrashGenerationServer(kPipeName,
ShowClientConnected,
NULL,
ShowClientCrashed,
NULL,
ShowClientExited,
NULL,
true,
&dump_path);
if (!crash_server->Start()) {
MessageBoxW(NULL, L"Unable to start server", L"Dumper", MB_OK);
delete crash_server;
crash_server = NULL;
}
}
void CrashServerStop() {
delete crash_server;
crash_server = NULL;
}
void DerefZeroCrash() {
int* x = 0;
*x = 1;
}
void InvalidParamCrash() {
printf(NULL);
}
void PureCallCrash() {
Derived derived;
}
void RequestDump() {
if (!handler->WriteMinidump()) {
MessageBoxW(NULL, L"Dump request failed", L"Dumper", MB_OK);
}
}
void CleanUp() {
if (cs_edit) {
DeleteCriticalSection(cs_edit);
delete cs_edit;
}
if (handler) {
delete handler;
}
if (crash_server) {
delete crash_server;
}
}
// Processes messages for the main window.
//
// WM_COMMAND - process the application menu.
// WM_PAINT - Paint the main window.
// WM_DESTROY - post a quit message and return.
LRESULT CALLBACK WndProc(HWND wnd,
UINT message,
WPARAM w_param,
LPARAM l_param) {
int message_id;
int message_event;
PAINTSTRUCT ps;
HDC hdc;
#pragma warning(push)
#pragma warning(disable:4312)
// Disable warning C4312: 'type cast' : conversion from 'LONG' to
// 'HINSTANCE' of greater size.
// The value returned by GetwindowLong in the case below returns unsigned.
HINSTANCE instance = (HINSTANCE)GetWindowLong(wnd, GWL_HINSTANCE);
#pragma warning(pop)
switch (message) {
case WM_COMMAND:
// Parse the menu selections.
message_id = LOWORD(w_param);
message_event = HIWORD(w_param);
switch (message_id) {
case IDM_ABOUT:
DialogBox(current_instance,
MAKEINTRESOURCE(IDD_ABOUTBOX),
wnd,
About);
break;
case IDM_EXIT:
DestroyWindow(wnd);
break;
case ID_SERVER_START:
CrashServerStart();
break;
case ID_SERVER_STOP:
CrashServerStop();
break;
case ID_CLIENT_DEREFZERO:
DerefZeroCrash();
break;
case ID_CLIENT_INVALIDPARAM:
InvalidParamCrash();
break;
case ID_CLIENT_PURECALL:
PureCallCrash();
break;
case ID_CLIENT_REQUESTEXPLICITDUMP:
RequestDump();
break;
default:
return DefWindowProc(wnd, message, w_param, l_param);
}
break;
case WM_CREATE:
client_status_edit_box = CreateWindow(TEXT("EDIT"),
NULL,
kEditBoxStyles,
0,
0,
0,
0,
wnd,
NULL,
instance,
NULL);
break;
case WM_SIZE:
// Make the edit control the size of the window's client area.
MoveWindow(client_status_edit_box,
0,
0,
LOWORD(l_param), // width of client area.
HIWORD(l_param), // height of client area.
TRUE); // repaint window.
break;
case WM_SETFOCUS:
SetFocus(client_status_edit_box);
break;
case WM_PAINT:
hdc = BeginPaint(wnd, &ps);
EndPaint(wnd, &ps);
break;
case WM_DESTROY:
CleanUp();
PostQuitMessage(0);
break;
default:
return DefWindowProc(wnd, message, w_param, l_param);
}
return 0;
}
// Message handler for about box.
INT_PTR CALLBACK About(HWND dlg,
UINT message,
WPARAM w_param,
LPARAM l_param) {
UNREFERENCED_PARAMETER(l_param);
switch (message) {
case WM_INITDIALOG:
return (INT_PTR)TRUE;
case WM_COMMAND:
if (LOWORD(w_param) == IDOK || LOWORD(w_param) == IDCANCEL) {
EndDialog(dlg, LOWORD(w_param));
return (INT_PTR)TRUE;
}
break;
}
return (INT_PTR)FALSE;
}
} // namespace google_breakpad
int APIENTRY _tWinMain(HINSTANCE instance,
HINSTANCE previous_instance,
LPTSTR command_line,
int command_show) {
using namespace google_breakpad;
UNREFERENCED_PARAMETER(previous_instance);
UNREFERENCED_PARAMETER(command_line);
cs_edit = new CRITICAL_SECTION();
InitializeCriticalSection(cs_edit);
// This is needed for CRT to not show dialog for invalid param
// failures and instead let the code handle it.
_CrtSetReportMode(_CRT_ASSERT, 0);
handler = new ExceptionHandler(L"C:\\dumps\\",
NULL,
google_breakpad::ShowDumpResults,
NULL,
ExceptionHandler::HANDLER_ALL,
MiniDumpNormal,
kPipeName);
// Initialize global strings.
LoadString(instance, IDS_APP_TITLE, title, kMaxLoadString);
LoadString(instance,
IDC_CRASHGENERATIONAPP,
window_class,
kMaxLoadString);
MyRegisterClass(instance);
// Perform application initialization.
if (!InitInstance (instance, command_show)) {
return FALSE;
}
HACCEL accel_table = LoadAccelerators(
instance,
MAKEINTRESOURCE(IDC_CRASHGENERATIONAPP));
// Main message loop.
MSG msg;
while (GetMessage(&msg, NULL, 0, 0)) {
if (!TranslateAccelerator(msg.hwnd, accel_table, &msg)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return (int)msg.wParam;
}

Просмотреть файл

@ -0,0 +1,35 @@
// Copyright (c) 2008, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef CLIENT_WINDOWS_TESTS_CRASH_GENERATION_APP_CRASH_GENERATION_APP_H__
#define CLIENT_WINDOWS_TESTS_CRASH_GENERATION_APP_CRASH_GENERATION_APP_H__
#include "resource.h"
#endif // CLIENT_WINDOWS_TESTS_CRASH_GENERATION_APP_CRASH_GENERATION_APP_H__

Просмотреть файл

@ -0,0 +1,144 @@
// Microsoft Visual C++ generated resource script.
//
#include "resource.h"
#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#define APSTUDIO_HIDDEN_SYMBOLS
#include "windows.h"
#undef APSTUDIO_HIDDEN_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
// English (U.S.) resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
#ifdef _WIN32
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
#pragma code_page(1252)
#endif //_WIN32
/////////////////////////////////////////////////////////////////////////////
//
// Icon
//
// Icon with lowest ID value placed first to ensure application icon
// remains consistent on all systems.
IDI_CRASHGENERATIONAPP ICON "crash_generation_app.ico"
IDI_SMALL ICON "small.ico"
/////////////////////////////////////////////////////////////////////////////
//
// Menu
//
IDC_CRASHGENERATIONAPP MENU
BEGIN
POPUP "&File"
BEGIN
MENUITEM "E&xit", IDM_EXIT
END
POPUP "&Server"
BEGIN
MENUITEM "&Start", ID_SERVER_START
MENUITEM "S&top", ID_SERVER_STOP
END
POPUP "&Client"
BEGIN
MENUITEM "&Deref Zero", ID_CLIENT_DEREFZERO
MENUITEM "&Invalid Param", ID_CLIENT_INVALIDPARAM
MENUITEM "&Pure Call", ID_CLIENT_PURECALL
MENUITEM "&Request Dump", ID_CLIENT_REQUESTEXPLICITDUMP
END
END
/////////////////////////////////////////////////////////////////////////////
//
// Accelerator
//
IDC_CRASHGENERATIONAPP ACCELERATORS
BEGIN
"?", IDM_ABOUT, ASCII, ALT
"/", IDM_ABOUT, ASCII, ALT
END
/////////////////////////////////////////////////////////////////////////////
//
// Dialog
//
IDD_ABOUTBOX DIALOG 22, 17, 230, 75
STYLE DS_SETFONT | DS_MODALFRAME | WS_CAPTION | WS_SYSMENU
CAPTION "About"
FONT 8, "System"
BEGIN
ICON IDI_CRASHGENERATIONAPP,IDC_MYICON,14,9,16,16
LTEXT "CrashGenerationApp Version 1.0",IDC_STATIC,49,10,119,8,SS_NOPREFIX
LTEXT "Copyright (C) 2008",IDC_STATIC,49,20,119,8
DEFPUSHBUTTON "OK",IDOK,195,6,30,11,WS_GROUP
END
#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//
1 TEXTINCLUDE
BEGIN
"resource.h\0"
END
2 TEXTINCLUDE
BEGIN
"#define APSTUDIO_HIDDEN_SYMBOLS\r\n"
"#include ""windows.h""\r\n"
"#undef APSTUDIO_HIDDEN_SYMBOLS\r\n"
"\0"
END
3 TEXTINCLUDE
BEGIN
"\r\n"
"\0"
END
#endif // APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// String Table
//
STRINGTABLE
BEGIN
IDS_APP_TITLE "CrashGenerationApp"
IDC_CRASHGENERATIONAPP "CRASHGENERATIONAPP"
END
#endif // English (U.S.) resources
/////////////////////////////////////////////////////////////////////////////
#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//
/////////////////////////////////////////////////////////////////////////////
#endif // not APSTUDIO_INVOKED

Просмотреть файл

@ -0,0 +1,26 @@

Microsoft Visual Studio Solution File, Format Version 9.00
# Visual Studio 2005
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "crash_generation_app", "crash_generation_app.vcproj", "{A15674ED-713D-4B37-B1D2-0C29C7E533C8}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
DebugStaticCRT|Win32 = DebugStaticCRT|Win32
Release|Win32 = Release|Win32
ReleaseStaticCRT|Win32 = ReleaseStaticCRT|Win32
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{A15674ED-713D-4B37-B1D2-0C29C7E533C8}.Debug|Win32.ActiveCfg = Debug|Win32
{A15674ED-713D-4B37-B1D2-0C29C7E533C8}.Debug|Win32.Build.0 = Debug|Win32
{A15674ED-713D-4B37-B1D2-0C29C7E533C8}.DebugStaticCRT|Win32.ActiveCfg = DebugStaticCRT|Win32
{A15674ED-713D-4B37-B1D2-0C29C7E533C8}.DebugStaticCRT|Win32.Build.0 = DebugStaticCRT|Win32
{A15674ED-713D-4B37-B1D2-0C29C7E533C8}.Release|Win32.ActiveCfg = Release|Win32
{A15674ED-713D-4B37-B1D2-0C29C7E533C8}.Release|Win32.Build.0 = Release|Win32
{A15674ED-713D-4B37-B1D2-0C29C7E533C8}.ReleaseStaticCRT|Win32.ActiveCfg = ReleaseStaticCRT|Win32
{A15674ED-713D-4B37-B1D2-0C29C7E533C8}.ReleaseStaticCRT|Win32.Build.0 = ReleaseStaticCRT|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

Просмотреть файл

@ -0,0 +1,431 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="8.00"
Name="crash_generation_app"
ProjectGUID="{A15674ED-713D-4B37-B1D2-0C29C7E533C8}"
RootNamespace="CrashGenerationServerApp"
Keyword="Win32Proj"
>
<Platforms>
<Platform
Name="Win32"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="..\..\..\..\"
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
UsePrecompiledHeader="2"
PrecompiledHeaderThrough="PreCompile.h"
WarningLevel="3"
Detect64BitPortabilityProblems="true"
DebugInformationFormat="4"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="exception_handler.lib"
LinkIncremental="2"
AdditionalLibraryDirectories="..\..\$(ConfigurationName)"
GenerateDebugInformation="true"
SubSystem="2"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="1"
WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="..\..\..\..\"
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS"
RuntimeLibrary="2"
UsePrecompiledHeader="2"
PrecompiledHeaderThrough="precompile.h"
WarningLevel="3"
Detect64BitPortabilityProblems="true"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="exception_handler.lib"
LinkIncremental="1"
AdditionalLibraryDirectories="..\..\$(ConfigurationName)"
GenerateDebugInformation="true"
SubSystem="2"
OptimizeReferences="2"
EnableCOMDATFolding="2"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="DebugStaticCRT|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="..\..\..\..\"
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="1"
UsePrecompiledHeader="2"
PrecompiledHeaderThrough="PreCompile.h"
WarningLevel="3"
Detect64BitPortabilityProblems="true"
DebugInformationFormat="4"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="exception_handler.lib"
LinkIncremental="2"
AdditionalLibraryDirectories="..\..\$(ConfigurationName)"
GenerateDebugInformation="true"
SubSystem="2"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="ReleaseStaticCRT|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="1"
WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="..\..\..\..\"
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS"
RuntimeLibrary="0"
UsePrecompiledHeader="2"
PrecompiledHeaderThrough="precompile.h"
WarningLevel="3"
Detect64BitPortabilityProblems="true"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="exception_handler.lib"
LinkIncremental="1"
AdditionalLibraryDirectories="..\..\$(ConfigurationName)"
GenerateDebugInformation="true"
SubSystem="2"
OptimizeReferences="2"
EnableCOMDATFolding="2"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="Source Files"
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
>
<File
RelativePath=".\abstract_class.cc"
>
</File>
<File
RelativePath=".\crash_generation_app.cc"
>
</File>
<File
RelativePath=".\precompile.cc"
>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="1"
/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="1"
/>
</FileConfiguration>
<FileConfiguration
Name="DebugStaticCRT|Win32"
>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="1"
/>
</FileConfiguration>
<FileConfiguration
Name="ReleaseStaticCRT|Win32"
>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="1"
/>
</FileConfiguration>
</File>
</Filter>
<Filter
Name="Header Files"
Filter="h;hpp;hxx;hm;inl;inc;xsd"
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
>
<File
RelativePath=".\abstract_class.h"
>
</File>
<File
RelativePath=".\crash_generation_app.h"
>
</File>
<File
RelativePath=".\precompile.h"
>
</File>
<File
RelativePath=".\Resource.h"
>
</File>
</Filter>
<Filter
Name="Resource Files"
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
>
<File
RelativePath=".\crash_generation_app.ico"
>
</File>
<File
RelativePath=".\crash_generation_app.rc"
>
</File>
<File
RelativePath=".\small.ico"
>
</File>
</Filter>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

Просмотреть файл

@ -0,0 +1,37 @@
// Copyright (c) 2008, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// precompile.cpp : source file that includes just the standard includes
// CrashGenerationApp.pch will be the pre-compiled header
// precompile.obj will contain the pre-compiled type information
#include "precompile.h"
// Reference any additional headers you need in PRECOMPILE.H
// and not in this file.

Просмотреть файл

@ -0,0 +1,89 @@
// Copyright (c) 2008, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// PreCompile.h : include file for standard system include files,
// or project specific include files that are used frequently, but
// are changed infrequently
//
#ifndef CLIENT_WINDOWS_TESTS_CRASH_GENERATION_APP_PRECOMPILE_H__
#define CLIENT_WINDOWS_TESTS_CRASH_GENERATION_APP_PRECOMPILE_H__
// Modify the following defines if you have to target a platform prior to
// the ones specified below. Refer to MSDN for the latest info on
// corresponding values for different platforms.
// Allow use of features specific to Windows XP or later.
#ifndef WINVER
// Change this to the appropriate value to target other versions of Windows.
#define WINVER 0x0501
#endif
// Allow use of features specific to Windows XP or later.
#ifndef _WIN32_WINNT
// Change this to the appropriate value to target other versions of Windows.
#define _WIN32_WINNT 0x0501
#endif
// Allow use of features specific to Windows 98 or later.
#ifndef _WIN32_WINDOWS
// Change this to the appropriate value to target Windows Me or later.
#define _WIN32_WINDOWS 0x0410
#endif
// Allow use of features specific to IE 6.0 or later.
#ifndef _WIN32_IE
// Change this to the appropriate value to target other versions of IE.
#define _WIN32_IE 0x0600
#endif
// Exclude rarely-used stuff from Windows headers
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <DbgHelp.h>
#include <malloc.h>
#include <memory.h>
#include <stdlib.h>
#include <string.h>
#include <tchar.h>
#include <cassert>
#include <list>
#include "client/windows/crash_generation/client_info.h"
#include "client/windows/crash_generation/crash_generation_client.h"
#include "client/windows/crash_generation/crash_generation_server.h"
#include "client/windows/crash_generation/minidump_generator.h"
#include "client/windows/handler/exception_handler.h"
#include "client/windows/tests/crash_generation_app/abstract_class.h"
#include "client/windows/tests/crash_generation_app/crash_generation_app.h"
#include "google_breakpad/common/minidump_format.h"
#endif // CLIENT_WINDOWS_TESTS_CRASH_GENERATION_APP_PRECOMPILE_H__

Просмотреть файл

@ -0,0 +1,73 @@
// Copyright (c) 2008, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// PreCompile.h : include file for standard system include files,
// or project specific include files that are used frequently, but
// are changed infrequently
//
#ifndef CLIENT_WINDOWS_TESTS_CRASH_GENERATION_APP_RESOURCE_H__
#define CLIENT_WINDOWS_TESTS_CRASH_GENERATION_APP_RESOURCE_H__
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by crash_generation_app.rc
//
#define IDC_MYICON 2
#define IDD_CRASHGENERATIONAPP_DIALOG 102
#define IDS_APP_TITLE 103
#define IDD_ABOUTBOX 103
#define IDM_ABOUT 104
#define IDM_EXIT 105
#define IDI_CRASHGENERATIONAPP 107
#define IDI_SMALL 108
#define IDC_CRASHGENERATIONAPP 109
#define IDR_MAINFRAME 128
#define ID_SERVER_START 32771
#define ID_SERVER_STOP 32772
#define ID_CLIENT_INVALIDPARAM 32773
#define ID_CLIENT_ASSERTFAILURE 32774
#define ID_CLIENT_DEREFZERO 32775
#define ID_CLIENT_PURECALL 32777
#define ID_CLIENT_REQUESTEXPLICITDUMP 32778
#define IDC_STATIC -1
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NO_MFC 1
#define _APS_NEXT_RESOURCE_VALUE 129
#define _APS_NEXT_COMMAND_VALUE 32780
#define _APS_NEXT_CONTROL_VALUE 1000
#define _APS_NEXT_SYMED_VALUE 110
#endif
#endif
#endif // CLIENT_WINDOWS_TESTS_CRASH_GENERATION_APP_RESOURCE_H__

Просмотреть файл

@ -40,6 +40,7 @@
#include <unistd.h>
#include <functional>
#include <map>
#include <vector>
#include "common/solaris/dump_symbols.h"
@ -50,7 +51,15 @@
// This namespace contains helper functions.
namespace {
// Symbol table entry for stabs. Sun CC specific.
using std::make_pair;
#if defined(_LP64)
typedef Elf64_Sym Elf_Sym;
#else
typedef Elf32_Sym Elf_Sym;
#endif
// Symbol table entry from stabs. Sun CC specific.
struct slist {
// String table index.
unsigned int n_strx;
@ -61,6 +70,14 @@ struct slist {
unsigned long n_value;
};
// Symbol table entry
struct SymbolEntry {
// Offset from the start of the file.
GElf_Addr offset;
// Function size.
GElf_Word size;
};
// Infomation of a line.
struct LineInfo {
// Offset from start of the function.
@ -107,10 +124,20 @@ struct SourceFileInfo {
std::vector<struct FuncInfo> func_info;
};
struct CompareString {
bool operator()(const char *s1, const char *s2) const {
return strcmp(s1, s2) < 0;
}
};
typedef std::map<const char *, struct SymbolEntry *, CompareString> SymbolMap;
// Information of a symbol table.
// This is the root of all types of symbol.
struct SymbolInfo {
std::vector<struct SourceFileInfo> source_file_info;
// Symbols information.
SymbolMap symbol_entries;
};
// Stab section name.
@ -119,8 +146,32 @@ const char *kStabName = ".stab";
// Stab str section name.
const char *kStabStrName = ".stabstr";
// Symtab section name.
const char *kSymtabName = ".symtab";
// Strtab section name.
const char *kStrtabName = ".strtab";
// Default buffer lenght for demangle.
const int demangleLen = 2000;
const int demangleLen = 20000;
// Offset to the string table.
u_int64_t stringOffset = 0;
// Update the offset to the start of the string index of the next
// object module for every N_ENDM stabs.
inline void RecalculateOffset(struct slist* cur_list, char *stabstr) {
while ((--cur_list)->n_strx == 0) ;
stringOffset += cur_list->n_strx;
char *temp = stabstr + stringOffset;
while (*temp != '\0') {
++stringOffset;
++temp;
}
// Skip the extra '\0'
++stringOffset;
}
// Demangle using demangle library on Solaris.
std::string Demangle(const char *mangled) {
@ -145,18 +196,6 @@ out:
return std::string(mangled);
}
// Find the prefered loading address of the binary.
GElf_Addr GetLoadingAddress(const GElf_Phdr *program_headers, int nheader) {
for (int i = 0; i < nheader; ++i) {
const GElf_Phdr &header = program_headers[i];
// For executable, it is the PT_LOAD segment with offset to zero.
if (header.p_type == PT_LOAD && header.p_offset == 0)
return header.p_vaddr;
}
// For other types of ELF, return 0.
return 0;
}
bool WriteFormat(int fd, const char *fmt, ...) {
va_list list;
char buffer[4096];
@ -226,9 +265,11 @@ int LoadLineInfo(struct slist *list,
do {
// Skip non line information.
while (cur_list < list_end && cur_list->n_type != N_SLINE) {
// Only exit when got another function, or source file.
if (cur_list->n_type == N_FUN || cur_list->n_type == N_SO)
// Only exit when got another function, or source file, or end stab.
if (cur_list->n_type == N_FUN || cur_list->n_type == N_SO ||
cur_list->n_type == N_ENDM) {
return cur_list - list;
}
++cur_list;
}
struct LineInfo line;
@ -248,7 +289,7 @@ int LoadLineInfo(struct slist *list,
int LoadFuncSymbols(struct slist *list,
struct slist *list_end,
const GElf_Shdr *stabstr_section,
char *stabstr,
GElf_Word base,
struct SourceFileInfo *source_file_info) {
struct slist *cur_list = list;
@ -263,18 +304,20 @@ int LoadFuncSymbols(struct slist *list,
return cur_list - list;
}
++cur_list;
if (cur_list->n_type == N_ENDM)
RecalculateOffset(cur_list, stabstr);
continue;
}
while (cur_list->n_type == N_FUN) {
struct FuncInfo func_info;
memset(&func_info, 0, sizeof(func_info));
func_info.name =
reinterpret_cast<char *>(cur_list->n_strx +
stabstr_section->sh_offset + base);
func_info.name = stabstr + cur_list->n_strx + stringOffset;
// The n_value field is always 0 from stab generated by Sun CC.
// TODO(Alfred): Find the correct value.
func_info.addr = cur_list->n_value;
++cur_list;
if (cur_list->n_type == N_ENDM)
RecalculateOffset(cur_list, stabstr);
if (cur_list->n_type != N_ESYM && cur_list->n_type != N_ISYM &&
cur_list->n_type != N_FUN) {
// Stack parameter size.
@ -282,6 +325,8 @@ int LoadFuncSymbols(struct slist *list,
// Line info.
cur_list += LoadLineInfo(cur_list, list_end, &func_info);
}
if (cur_list < list_end && cur_list->n_type == N_ENDM)
RecalculateOffset(cur_list, stabstr);
// Functions in this module should have address bigger than the module
// starting address.
//
@ -296,48 +341,70 @@ int LoadFuncSymbols(struct slist *list,
}
// Compute size and rva information based on symbols loaded from stab section.
bool ComputeSizeAndRVA(GElf_Addr loading_addr, struct SymbolInfo *symbols) {
bool ComputeSizeAndRVA(struct SymbolInfo *symbols) {
std::vector<struct SourceFileInfo> *sorted_files =
&(symbols->source_file_info);
SymbolMap *symbol_entries = &(symbols->symbol_entries);
for (size_t i = 0; i < sorted_files->size(); ++i) {
struct SourceFileInfo &source_file = (*sorted_files)[i];
std::vector<struct FuncInfo> *sorted_functions = &(source_file.func_info);
for (size_t j = 0; j < sorted_functions->size(); ++j) {
int func_size = sorted_functions->size();
for (size_t j = 0; j < func_size; ++j) {
struct FuncInfo &func_info = (*sorted_functions)[j];
assert(func_info.addr >= loading_addr);
func_info.rva_to_base = func_info.addr - loading_addr;
int line_count = func_info.line_info.size();
func_info.size =
(line_count == 0) ? 0 :
func_info.line_info[line_count - 1].rva_to_func;
// Discard the ending part of the name.
std::string func_name(func_info.name);
std::string::size_type last_colon = func_name.find_first_of(':');
if (last_colon != std::string::npos)
func_name = func_name.substr(0, last_colon);
// Fine the symbol offset from the loading address and size by name.
SymbolMap::const_iterator it = symbol_entries->find(func_name.c_str());
if (it->second) {
func_info.rva_to_base = it->second->offset;
func_info.size = (line_count == 0) ? 0 : it->second->size;
} else {
func_info.rva_to_base = 0;
func_info.size = 0;
}
// Compute function and line size.
for (size_t k = 0; k < line_count; ++k) {
struct LineInfo &line_info = func_info.line_info[k];
if (k == 0) {
line_info.size = line_info.rva_to_func;
} else {
line_info.size =
line_info.rva_to_func - func_info.line_info[k - 1].rva_to_func;
}
line_info.rva_to_base = line_info.rva_to_func + func_info.rva_to_base;
if (k == line_count - 1) {
line_info.size = func_info.size - line_info.rva_to_func;
} else {
struct LineInfo &next_line = func_info.line_info[k + 1];
line_info.size = next_line.rva_to_func - line_info.rva_to_func;
}
} // for each line.
} // for each function.
} // for each source file.
for (SymbolMap::iterator it = symbol_entries->begin();
it != symbol_entries->end(); ++it) {
free(it->second);
}
return true;
}
bool LoadAllSymbols(const GElf_Shdr *stab_section,
const GElf_Shdr *stabstr_section,
GElf_Addr loading_addr,
GElf_Word base,
struct SymbolInfo *symbols) {
if (stab_section == NULL || stabstr_section == NULL)
return false;
char *stabstr =
reinterpret_cast<char *>(stabstr_section->sh_offset + base);
struct slist *lists =
reinterpret_cast<struct slist *>(stab_section->sh_offset + base);
int nstab = stab_section->sh_size / sizeof(struct slist);
int source_id = 0;
// First pass, load all symbols from the object file.
for (int i = 0; i < nstab; ) {
int step = 1;
@ -345,9 +412,7 @@ bool LoadAllSymbols(const GElf_Shdr *stab_section,
if (cur_list->n_type == N_SO) {
// FUNC <address> <size> <param_stack_size> <function>
struct SourceFileInfo source_file_info;
source_file_info.name =
reinterpret_cast<char *>(cur_list->n_strx +
stabstr_section->sh_offset + base);
source_file_info.name = stabstr + cur_list->n_strx + stringOffset;
// The n_value field is always 0 from stab generated by Sun CC.
// TODO(Alfred): Find the correct value.
source_file_info.addr = cur_list->n_value;
@ -355,22 +420,19 @@ bool LoadAllSymbols(const GElf_Shdr *stab_section,
source_file_info.source_id = source_id++;
else
source_file_info.source_id = -1;
step = LoadFuncSymbols(cur_list, lists + nstab - 1,
stabstr_section, base, &source_file_info);
step = LoadFuncSymbols(cur_list, lists + nstab - 1, stabstr,
base, &source_file_info);
symbols->source_file_info.push_back(source_file_info);
}
i += step;
}
// Second pass, compute the size of functions and lines.
return ComputeSizeAndRVA(loading_addr, symbols);
return ComputeSizeAndRVA(symbols);
}
bool LoadSymbols(Elf *elf, GElf_Ehdr *elf_header, struct SymbolInfo *symbols,
void *obj_base) {
GElf_Word base = reinterpret_cast<GElf_Word>(obj_base);
GElf_Addr loading_addr = GetLoadingAddress(
reinterpret_cast<GElf_Phdr *>(elf_header->e_phoff + base),
elf_header->e_phnum);
const GElf_Shdr *sections =
reinterpret_cast<GElf_Shdr *>(elf_header->e_shoff + base);
@ -386,9 +448,34 @@ bool LoadSymbols(Elf *elf, GElf_Ehdr *elf_header, struct SymbolInfo *symbols,
fprintf(stderr, "Stabstr section not found.\n");
return false;
}
GElf_Shdr symtab_section;
if (!FindSectionByName(elf, kSymtabName, elf_header->e_shstrndx,
&symtab_section)) {
fprintf(stderr, "Symtab section not found.\n");
return false;
}
GElf_Shdr strtab_section;
if (!FindSectionByName(elf, kStrtabName, elf_header->e_shstrndx,
&strtab_section)) {
fprintf(stderr, "Strtab section not found.\n");
return false;
}
Elf_Sym *symbol = (Elf_Sym *)((char *)base + symtab_section.sh_offset);
for (int i = 0; i < symtab_section.sh_size/symtab_section.sh_entsize; ++i) {
struct SymbolEntry *symbol_entry =
(struct SymbolEntry *)malloc(sizeof(struct SymbolEntry));
const char *name = reinterpret_cast<char *>(
strtab_section.sh_offset + (GElf_Word)base + symbol->st_name);
symbol_entry->offset = symbol->st_value;
symbol_entry->size = symbol->st_size;
symbols->symbol_entries.insert(make_pair(name, symbol_entry));
++symbol;
}
// Load symbols.
return LoadAllSymbols(&stab_section, &stabstr_section, loading_addr, base, symbols);
return LoadAllSymbols(&stab_section, &stabstr_section, base, symbols);
}
bool WriteModuleInfo(int fd, GElf_Half arch, const std::string &obj_file) {
@ -397,8 +484,12 @@ bool WriteModuleInfo(int fd, GElf_Half arch, const std::string &obj_file) {
arch_name = "x86";
else if (arch == EM_X86_64)
arch_name = "x86_64";
else
else if (arch == EM_SPARC32PLUS)
arch_name = "SPARC_32+";
else {
printf("Please add more ARCH support\n");
return false;
}
unsigned char identifier[16];
google_breakpad::FileID file_id(obj_file.c_str());
@ -437,18 +528,20 @@ bool WriteOneFunction(int fd, int source_id,
func_name = func_name.substr(0, last_colon);
func_name = Demangle(func_name.c_str());
if (func_info.size < 0)
if (func_info.size <= 0)
return true;
// rva_to_base could be unsigned long(32 bit) or unsigned long long(64 bit).
if (WriteFormat(fd, "FUNC %llx %d %d %s\n",
if (WriteFormat(fd, "FUNC %llx %x %d %s\n",
(long long)func_info.rva_to_base,
func_info.size,
func_info.stack_param_size,
func_name.c_str())) {
for (size_t i = 0; i < func_info.line_info.size(); ++i) {
const struct LineInfo &line_info = func_info.line_info[i];
if (!WriteFormat(fd, "%llx %d %d %d\n",
if (line_info.line_num == 0)
return true;
if (!WriteFormat(fd, "%llx %x %d %d\n",
(long long)line_info.rva_to_base,
line_info.size,
line_info.line_num,

Просмотреть файл

@ -43,6 +43,10 @@
#ifndef _WIN32
#include <sys/types.h>
#ifndef __STDC_FORMAT_MACROS
#define __STDC_FORMAT_MACROS
#endif /* __STDC_FORMAT_MACROS */
#include <inttypes.h>
#if defined(__SUNPRO_CC) || (defined(__GNUC__) && defined(__sun__))
typedef uint8_t u_int8_t;
@ -69,4 +73,11 @@ typedef struct {
typedef u_int64_t breakpad_time_t;
/* Try to get PRIx64 from inttypes.h, but if it's not defined, fall back to
* llx, which is the format string for "long long" - this is a 64-bit
* integral type on many systems. */
#ifndef PRIx64
#define PRIx64 "llx"
#endif /* !PRIx64 */
#endif /* GOOGLE_BREAKPAD_COMMON_BREAKPAD_TYPES_H__ */

Просмотреть файл

@ -0,0 +1,231 @@
/* Copyright (c) 2006, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
/* minidump_format.h: A cross-platform reimplementation of minidump-related
* portions of DbgHelp.h from the Windows Platform SDK.
*
* (This is C99 source, please don't corrupt it with C++.)
*
* This file contains the necessary definitions to read minidump files
* produced on amd64. These files may be read on any platform provided
* that the alignments of these structures on the processing system are
* identical to the alignments of these structures on the producing system.
* For this reason, precise-sized types are used. The structures defined
* by this file have been laid out to minimize alignment problems by ensuring
* ensuring that all members are aligned on their natural boundaries. In
* In some cases, tail-padding may be significant when different ABIs specify
* different tail-padding behaviors. To avoid problems when reading or
* writing affected structures, MD_*_SIZE macros are provided where needed,
* containing the useful size of the structures without padding.
*
* Structures that are defined by Microsoft to contain a zero-length array
* are instead defined here to contain an array with one element, as
* zero-length arrays are forbidden by standard C and C++. In these cases,
* *_minsize constants are provided to be used in place of sizeof. For a
* cleaner interface to these sizes when using C++, see minidump_size.h.
*
* These structures are also sufficient to populate minidump files.
*
* These definitions may be extended to support handling minidump files
* for other CPUs and other operating systems.
*
* Because precise data type sizes are crucial for this implementation to
* function properly and portably in terms of interoperability with minidumps
* produced by DbgHelp on Windows, a set of primitive types with known sizes
* are used as the basis of each structure defined by this file. DbgHelp
* on Windows is assumed to be the reference implementation; this file
* seeks to provide a cross-platform compatible implementation. To avoid
* collisions with the types and values defined and used by DbgHelp in the
* event that this implementation is used on Windows, each type and value
* defined here is given a new name, beginning with "MD". Names of the
* equivalent types and values in the Windows Platform SDK are given in
* comments.
*
* Author: Mark Mentovai
* Change to split into its own file: Neal Sidhwaney */
#ifndef GOOGLE_BREAKPAD_COMMON_MINIDUMP_CPU_AMD64_H__
#define GOOGLE_BREAKPAD_COMMON_MINIDUMP_CPU_AMD64_H__
/*
* AMD64 support, see WINNT.H
*/
typedef struct {
u_int16_t control_word;
u_int16_t status_word;
u_int8_t tag_word;
u_int8_t reserved1;
u_int16_t error_opcode;
u_int32_t error_offset;
u_int16_t error_selector;
u_int16_t reserved2;
u_int32_t data_offset;
u_int16_t data_selector;
u_int16_t reserved3;
u_int32_t mx_csr;
u_int32_t mx_csr_mask;
u_int128_t float_registers[8];
u_int128_t xmm_registers[16];
u_int8_t reserved4[96];
} MDXmmSaveArea32AMD64; /* XMM_SAVE_AREA32 */
#define MD_CONTEXT_AMD64_VR_COUNT 26
typedef struct {
/*
* Register parameter home addresses.
*/
u_int64_t p1_home;
u_int64_t p2_home;
u_int64_t p3_home;
u_int64_t p4_home;
u_int64_t p5_home;
u_int64_t p6_home;
/* The next field determines the layout of the structure, and which parts
* of it are populated */
u_int32_t context_flags;
u_int32_t mx_csr;
/* The next register is included with MD_CONTEXT_AMD64_CONTROL */
u_int16_t cs;
/* The next 4 registers are included with MD_CONTEXT_AMD64_SEGMENTS */
u_int16_t ds;
u_int16_t es;
u_int16_t fs;
u_int16_t gs;
/* The next 2 registers are included with MD_CONTEXT_AMD64_CONTROL */
u_int16_t ss;
u_int32_t eflags;
/* The next 6 registers are included with MD_CONTEXT_AMD64_DEBUG_REGISTERS */
u_int64_t dr0;
u_int64_t dr1;
u_int64_t dr2;
u_int64_t dr3;
u_int64_t dr6;
u_int64_t dr7;
/* The next 4 registers are included with MD_CONTEXT_AMD64_INTEGER */
u_int64_t rax;
u_int64_t rcx;
u_int64_t rdx;
u_int64_t rbx;
/* The next register is included with MD_CONTEXT_AMD64_CONTROL */
u_int64_t rsp;
/* The next 11 registers are included with MD_CONTEXT_AMD64_INTEGER */
u_int64_t rbp;
u_int64_t rsi;
u_int64_t rdi;
u_int64_t r8;
u_int64_t r9;
u_int64_t r10;
u_int64_t r11;
u_int64_t r12;
u_int64_t r13;
u_int64_t r14;
u_int64_t r15;
/* The next register is included with MD_CONTEXT_AMD64_CONTROL */
u_int64_t rip;
/* The next set of registers are included with
* MD_CONTEXT_AMD64_FLOATING_POINT
*/
union {
MDXmmSaveArea32AMD64 flt_save;
struct {
u_int128_t header[2];
u_int128_t legacy[8];
u_int128_t xmm0;
u_int128_t xmm1;
u_int128_t xmm2;
u_int128_t xmm3;
u_int128_t xmm4;
u_int128_t xmm5;
u_int128_t xmm6;
u_int128_t xmm7;
u_int128_t xmm8;
u_int128_t xmm9;
u_int128_t xmm10;
u_int128_t xmm11;
u_int128_t xmm12;
u_int128_t xmm13;
u_int128_t xmm14;
u_int128_t xmm15;
} sse_registers;
};
u_int128_t vector_register[MD_CONTEXT_AMD64_VR_COUNT];
u_int64_t vector_control;
/* The next 5 registers are included with MD_CONTEXT_AMD64_DEBUG_REGISTERS */
u_int64_t debug_control;
u_int64_t last_branch_to_rip;
u_int64_t last_branch_from_rip;
u_int64_t last_exception_to_rip;
u_int64_t last_exception_from_rip;
} MDRawContextAMD64; /* CONTEXT */
/* For (MDRawContextAMD64).context_flags. These values indicate the type of
* context stored in the structure. The high 26 bits identify the CPU, the
* low 6 bits identify the type of context saved. */
#define MD_CONTEXT_AMD64_CONTROL (MD_CONTEXT_AMD64 | 0x00000001)
/* CONTEXT_CONTROL */
#define MD_CONTEXT_AMD64_INTEGER (MD_CONTEXT_AMD64 | 0x00000002)
/* CONTEXT_INTEGER */
#define MD_CONTEXT_AMD64_SEGMENTS (MD_CONTEXT_AMD64 | 0x00000004)
/* CONTEXT_SEGMENTS */
#define MD_CONTEXT_AMD64_FLOATING_POINT (MD_CONTEXT_AMD64 | 0x00000008)
/* CONTEXT_FLOATING_POINT */
#define MD_CONTEXT_AMD64_DEBUG_REGISTERS (MD_CONTEXT_AMD64 | 0x00000010)
/* CONTEXT_DEBUG_REGISTERS */
/* WinNT.h refers to CONTEXT_MMX_REGISTERS but doesn't appear to define it
* I think it really means CONTEXT_FLOATING_POINT.
*/
#define MD_CONTEXT_AMD64_FULL (MD_CONTEXT_AMD64_CONTROL | \
MD_CONTEXT_AMD64_INTEGER | \
MD_CONTEXT_AMD64_FLOATING_POINT)
/* CONTEXT_FULL */
#define MD_CONTEXT_AMD64_ALL (MD_CONTEXT_AMD64_FULL | \
MD_CONTEXT_AMD64_SEGMENTS | \
MD_CONTEXT_X86_DEBUG_REGISTERS)
/* CONTEXT_ALL */
#endif /* GOOGLE_BREAKPAD_COMMON_MINIDUMP_CPU_AMD64_H__ */

Просмотреть файл

@ -0,0 +1,148 @@
/* Copyright (c) 2006, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
/* minidump_format.h: A cross-platform reimplementation of minidump-related
* portions of DbgHelp.h from the Windows Platform SDK.
*
* (This is C99 source, please don't corrupt it with C++.)
*
* This file contains the necessary definitions to read minidump files
* produced on ppc. These files may be read on any platform provided
* that the alignments of these structures on the processing system are
* identical to the alignments of these structures on the producing system.
* For this reason, precise-sized types are used. The structures defined
* by this file have been laid out to minimize alignment problems by ensuring
* ensuring that all members are aligned on their natural boundaries. In
* In some cases, tail-padding may be significant when different ABIs specify
* different tail-padding behaviors. To avoid problems when reading or
* writing affected structures, MD_*_SIZE macros are provided where needed,
* containing the useful size of the structures without padding.
*
* Structures that are defined by Microsoft to contain a zero-length array
* are instead defined here to contain an array with one element, as
* zero-length arrays are forbidden by standard C and C++. In these cases,
* *_minsize constants are provided to be used in place of sizeof. For a
* cleaner interface to these sizes when using C++, see minidump_size.h.
*
* These structures are also sufficient to populate minidump files.
*
* These definitions may be extended to support handling minidump files
* for other CPUs and other operating systems.
*
* Because precise data type sizes are crucial for this implementation to
* function properly and portably in terms of interoperability with minidumps
* produced by DbgHelp on Windows, a set of primitive types with known sizes
* are used as the basis of each structure defined by this file. DbgHelp
* on Windows is assumed to be the reference implementation; this file
* seeks to provide a cross-platform compatible implementation. To avoid
* collisions with the types and values defined and used by DbgHelp in the
* event that this implementation is used on Windows, each type and value
* defined here is given a new name, beginning with "MD". Names of the
* equivalent types and values in the Windows Platform SDK are given in
* comments.
*
* Author: Mark Mentovai
* Change to split into its own file: Neal Sidhwaney */
/*
* Breakpad minidump extension for PowerPC support. Based on Darwin/Mac OS X'
* mach/ppc/_types.h
*/
#ifndef GOOGLE_BREAKPAD_COMMON_MINIDUMP_CPU_PPC_H__
#define GOOGLE_BREAKPAD_COMMON_MINIDUMP_CPU_PPC_H__
#define MD_FLOATINGSAVEAREA_PPC_FPR_COUNT 32
typedef struct {
/* fpregs is a double[32] in mach/ppc/_types.h, but a u_int64_t is used
* here for precise sizing. */
u_int64_t fpregs[MD_FLOATINGSAVEAREA_PPC_FPR_COUNT];
u_int32_t fpscr_pad;
u_int32_t fpscr; /* Status/control */
} MDFloatingSaveAreaPPC; /* Based on ppc_float_state */
#define MD_VECTORSAVEAREA_PPC_VR_COUNT 32
typedef struct {
/* Vector registers (including vscr) are 128 bits, but mach/ppc/_types.h
* exposes them as four 32-bit quantities. */
u_int128_t save_vr[MD_VECTORSAVEAREA_PPC_VR_COUNT];
u_int128_t save_vscr; /* Status/control */
u_int32_t save_pad5[4];
u_int32_t save_vrvalid; /* Identifies which vector registers are saved */
u_int32_t save_pad6[7];
} MDVectorSaveAreaPPC; /* ppc_vector_state */
#define MD_CONTEXT_PPC_GPR_COUNT 32
typedef struct {
/* context_flags is not present in ppc_thread_state, but it aids
* identification of MDRawContextPPC among other raw context types,
* and it guarantees alignment when we get to float_save. */
u_int32_t context_flags;
u_int32_t srr0; /* Machine status save/restore: stores pc
* (instruction) */
u_int32_t srr1; /* Machine status save/restore: stores msr
* (ps, program/machine state) */
/* ppc_thread_state contains 32 fields, r0 .. r31. Here, an array is
* used for brevity. */
u_int32_t gpr[MD_CONTEXT_PPC_GPR_COUNT];
u_int32_t cr; /* Condition */
u_int32_t xer; /* Integer (fiXed-point) exception */
u_int32_t lr; /* Link */
u_int32_t ctr; /* Count */
u_int32_t mq; /* Multiply/Quotient (PPC 601, POWER only) */
u_int32_t vrsave; /* Vector save */
/* float_save and vector_save aren't present in ppc_thread_state, but
* are represented in separate structures that still define a thread's
* context. */
MDFloatingSaveAreaPPC float_save;
MDVectorSaveAreaPPC vector_save;
} MDRawContextPPC; /* Based on ppc_thread_state */
/* For (MDRawContextPPC).context_flags. These values indicate the type of
* context stored in the structure. MD_CONTEXT_PPC is Breakpad-defined. Its
* value was chosen to avoid likely conflicts with MD_CONTEXT_* for other
* CPUs. */
#define MD_CONTEXT_PPC 0x20000000
#define MD_CONTEXT_PPC_BASE (MD_CONTEXT_PPC | 0x00000001)
#define MD_CONTEXT_PPC_FLOATING_POINT (MD_CONTEXT_PPC | 0x00000008)
#define MD_CONTEXT_PPC_VECTOR (MD_CONTEXT_PPC | 0x00000020)
#define MD_CONTEXT_PPC_FULL MD_CONTEXT_PPC_BASE
#define MD_CONTEXT_PPC_ALL (MD_CONTEXT_PPC_FULL | \
MD_CONTEXT_PPC_FLOATING_POINT | \
MD_CONTEXT_PPC_VECTOR)
#endif /* GOOGLE_BREAKPAD_COMMON_MINIDUMP_CPU_PPC_H__ */

Просмотреть файл

@ -0,0 +1,129 @@
/* Copyright (c) 2008, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
/* minidump_format.h: A cross-platform reimplementation of minidump-related
* portions of DbgHelp.h from the Windows Platform SDK.
*
* (This is C99 source, please don't corrupt it with C++.)
*
* This file contains the necessary definitions to read minidump files
* produced on ppc64. These files may be read on any platform provided
* that the alignments of these structures on the processing system are
* identical to the alignments of these structures on the producing system.
* For this reason, precise-sized types are used. The structures defined
* by this file have been laid out to minimize alignment problems by ensuring
* ensuring that all members are aligned on their natural boundaries. In
* In some cases, tail-padding may be significant when different ABIs specify
* different tail-padding behaviors. To avoid problems when reading or
* writing affected structures, MD_*_SIZE macros are provided where needed,
* containing the useful size of the structures without padding.
*
* Structures that are defined by Microsoft to contain a zero-length array
* are instead defined here to contain an array with one element, as
* zero-length arrays are forbidden by standard C and C++. In these cases,
* *_minsize constants are provided to be used in place of sizeof. For a
* cleaner interface to these sizes when using C++, see minidump_size.h.
*
* These structures are also sufficient to populate minidump files.
*
* These definitions may be extended to support handling minidump files
* for other CPUs and other operating systems.
*
* Because precise data type sizes are crucial for this implementation to
* function properly and portably in terms of interoperability with minidumps
* produced by DbgHelp on Windows, a set of primitive types with known sizes
* are used as the basis of each structure defined by this file. DbgHelp
* on Windows is assumed to be the reference implementation; this file
* seeks to provide a cross-platform compatible implementation. To avoid
* collisions with the types and values defined and used by DbgHelp in the
* event that this implementation is used on Windows, each type and value
* defined here is given a new name, beginning with "MD". Names of the
* equivalent types and values in the Windows Platform SDK are given in
* comments.
*
* Author: Neal Sidhwaney */
/*
* Breakpad minidump extension for PPC64 support. Based on Darwin/Mac OS X'
* mach/ppc/_types.h
*/
#ifndef GOOGLE_BREAKPAD_COMMON_MINIDUMP_CPU_PPC64_H__
#define GOOGLE_BREAKPAD_COMMON_MINIDUMP_CPU_PPC64_H__
#include "minidump_cpu_ppc.h"
// these types are the same in ppc64 & ppc
typedef MDFloatingSaveAreaPPC MDFloatingSaveAreaPPC64;
typedef MDVectorSaveAreaPPC MDVectorSaveAreaPPC64;
#define MD_CONTEXT_PPC64_GPR_COUNT MD_CONTEXT_PPC_GPR_COUNT
typedef struct {
/* context_flags is not present in ppc_thread_state, but it aids
* identification of MDRawContextPPC among other raw context types,
* and it guarantees alignment when we get to float_save. */
u_int64_t context_flags;
u_int64_t srr0; /* Machine status save/restore: stores pc
* (instruction) */
u_int64_t srr1; /* Machine status save/restore: stores msr
* (ps, program/machine state) */
/* ppc_thread_state contains 32 fields, r0 .. r31. Here, an array is
* used for brevity. */
u_int64_t gpr[MD_CONTEXT_PPC64_GPR_COUNT];
u_int64_t cr; /* Condition */
u_int64_t xer; /* Integer (fiXed-point) exception */
u_int64_t lr; /* Link */
u_int64_t ctr; /* Count */
u_int64_t vrsave; /* Vector save */
/* float_save and vector_save aren't present in ppc_thread_state, but
* are represented in separate structures that still define a thread's
* context. */
MDFloatingSaveAreaPPC float_save;
MDVectorSaveAreaPPC vector_save;
} MDRawContextPPC64; /* Based on ppc_thread_state */
/* For (MDRawContextPPC).context_flags. These values indicate the type of
* context stored in the structure. MD_CONTEXT_PPC is Breakpad-defined. Its
* value was chosen to avoid likely conflicts with MD_CONTEXT_* for other
* CPUs. */
#define MD_CONTEXT_PPC 0x20000000
#define MD_CONTEXT_PPC_BASE (MD_CONTEXT_PPC | 0x00000001)
#define MD_CONTEXT_PPC_FLOATING_POINT (MD_CONTEXT_PPC | 0x00000008)
#define MD_CONTEXT_PPC_VECTOR (MD_CONTEXT_PPC | 0x00000020)
#define MD_CONTEXT_PPC_FULL MD_CONTEXT_PPC_BASE
#define MD_CONTEXT_PPC_ALL (MD_CONTEXT_PPC_FULL | \
MD_CONTEXT_PPC_FLOATING_POINT | \
MD_CONTEXT_PPC_VECTOR)
#endif /* GOOGLE_BREAKPAD_COMMON_MINIDUMP_CPU_PPC64_H__ */

Просмотреть файл

@ -0,0 +1,158 @@
/* Copyright (c) 2006, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
/* minidump_format.h: A cross-platform reimplementation of minidump-related
* portions of DbgHelp.h from the Windows Platform SDK.
*
* (This is C99 source, please don't corrupt it with C++.)
*
* This file contains the necessary definitions to read minidump files
* produced on sparc. These files may be read on any platform provided
* that the alignments of these structures on the processing system are
* identical to the alignments of these structures on the producing system.
* For this reason, precise-sized types are used. The structures defined
* by this file have been laid out to minimize alignment problems by ensuring
* ensuring that all members are aligned on their natural boundaries. In
* In some cases, tail-padding may be significant when different ABIs specify
* different tail-padding behaviors. To avoid problems when reading or
* writing affected structures, MD_*_SIZE macros are provided where needed,
* containing the useful size of the structures without padding.
*
* Structures that are defined by Microsoft to contain a zero-length array
* are instead defined here to contain an array with one element, as
* zero-length arrays are forbidden by standard C and C++. In these cases,
* *_minsize constants are provided to be used in place of sizeof. For a
* cleaner interface to these sizes when using C++, see minidump_size.h.
*
* These structures are also sufficient to populate minidump files.
*
* These definitions may be extended to support handling minidump files
* for other CPUs and other operating systems.
*
* Because precise data type sizes are crucial for this implementation to
* function properly and portably in terms of interoperability with minidumps
* produced by DbgHelp on Windows, a set of primitive types with known sizes
* are used as the basis of each structure defined by this file. DbgHelp
* on Windows is assumed to be the reference implementation; this file
* seeks to provide a cross-platform compatible implementation. To avoid
* collisions with the types and values defined and used by DbgHelp in the
* event that this implementation is used on Windows, each type and value
* defined here is given a new name, beginning with "MD". Names of the
* equivalent types and values in the Windows Platform SDK are given in
* comments.
*
* Author: Mark Mentovai
* Change to split into its own file: Neal Sidhwaney */
/*
* SPARC support, see (solaris)sys/procfs_isa.h also
*/
#ifndef GOOGLE_BREAKPAD_COMMON_MINIDUMP_CPU_SPARC_H__
#define GOOGLE_BREAKPAD_COMMON_MINIDUMP_CPU_SPARC_H__
#define MD_FLOATINGSAVEAREA_SPARC_FPR_COUNT 32
typedef struct {
/* FPU floating point regs */
u_int64_t regs[MD_FLOATINGSAVEAREA_SPARC_FPR_COUNT];
u_int64_t filler;
u_int64_t fsr; /* FPU status register */
} MDFloatingSaveAreaSPARC; /* FLOATING_SAVE_AREA */
#define MD_CONTEXT_SPARC_GPR_COUNT 32
typedef struct {
/* The next field determines the layout of the structure, and which parts
* of it are populated
*/
u_int32_t context_flags;
u_int32_t flag_pad;
/*
* General register access (SPARC).
* Don't confuse definitions here with definitions in <sys/regset.h>.
* Registers are 32 bits for ILP32, 64 bits for LP64.
* SPARC V7/V8 is for 32bit, SPARC V9 is for 64bit
*/
/* 32 Integer working registers */
/* g_r[0-7] global registers(g0-g7)
* g_r[8-15] out registers(o0-o7)
* g_r[16-23] local registers(l0-l7)
* g_r[24-31] in registers(i0-i7)
*/
u_int64_t g_r[MD_CONTEXT_SPARC_GPR_COUNT];
/* several control registers */
/* Processor State register(PSR) for SPARC V7/V8
* Condition Code register (CCR) for SPARC V9
*/
u_int64_t ccr;
u_int64_t pc; /* Program Counter register (PC) */
u_int64_t npc; /* Next Program Counter register (nPC) */
u_int64_t y; /* Y register (Y) */
/* Address Space Identifier register (ASI) for SPARC V9
* WIM for SPARC V7/V8
*/
u_int64_t asi;
/* Floating-Point Registers State register (FPRS) for SPARC V9
* TBR for for SPARC V7/V8
*/
u_int64_t fprs;
/* The next field is included with MD_CONTEXT_SPARC_FLOATING_POINT */
MDFloatingSaveAreaSPARC float_save;
} MDRawContextSPARC; /* CONTEXT_SPARC */
/* For (MDRawContextSPARC).context_flags. These values indicate the type of
* context stored in the structure. MD_CONTEXT_SPARC is Breakpad-defined. Its
* value was chosen to avoid likely conflicts with MD_CONTEXT_* for other
* CPUs. */
#define MD_CONTEXT_SPARC 0x10000000
#define MD_CONTEXT_SPARC_CONTROL (MD_CONTEXT_SPARC | 0x00000001)
#define MD_CONTEXT_SPARC_INTEGER (MD_CONTEXT_SPARC | 0x00000002)
#define MD_CONTEXT_SAPARC_FLOATING_POINT (MD_CONTEXT_SPARC | 0x00000004)
#define MD_CONTEXT_SAPARC_EXTRA (MD_CONTEXT_SPARC | 0x00000008)
#define MD_CONTEXT_SPARC_FULL (MD_CONTEXT_SPARC_CONTROL | \
MD_CONTEXT_SPARC_INTEGER)
#define MD_CONTEXT_SPARC_ALL (MD_CONTEXT_SPARC_FULL | \
MD_CONTEXT_SAPARC_FLOATING_POINT | \
MD_CONTEXT_SAPARC_EXTRA)
#endif /* GOOGLE_BREAKPAD_COMMON_MINIDUMP_CPU_SPARC_H__ */

Просмотреть файл

@ -0,0 +1,172 @@
/* Copyright (c) 2006, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
/* minidump_format.h: A cross-platform reimplementation of minidump-related
* portions of DbgHelp.h from the Windows Platform SDK.
*
* (This is C99 source, please don't corrupt it with C++.)
*
* This file contains the necessary definitions to read minidump files
* produced on x86. These files may be read on any platform provided
* that the alignments of these structures on the processing system are
* identical to the alignments of these structures on the producing system.
* For this reason, precise-sized types are used. The structures defined
* by this file have been laid out to minimize alignment problems by ensuring
* ensuring that all members are aligned on their natural boundaries. In
* In some cases, tail-padding may be significant when different ABIs specify
* different tail-padding behaviors. To avoid problems when reading or
* writing affected structures, MD_*_SIZE macros are provided where needed,
* containing the useful size of the structures without padding.
*
* Structures that are defined by Microsoft to contain a zero-length array
* are instead defined here to contain an array with one element, as
* zero-length arrays are forbidden by standard C and C++. In these cases,
* *_minsize constants are provided to be used in place of sizeof. For a
* cleaner interface to these sizes when using C++, see minidump_size.h.
*
* These structures are also sufficient to populate minidump files.
*
* These definitions may be extended to support handling minidump files
* for other CPUs and other operating systems.
*
* Because precise data type sizes are crucial for this implementation to
* function properly and portably in terms of interoperability with minidumps
* produced by DbgHelp on Windows, a set of primitive types with known sizes
* are used as the basis of each structure defined by this file. DbgHelp
* on Windows is assumed to be the reference implementation; this file
* seeks to provide a cross-platform compatible implementation. To avoid
* collisions with the types and values defined and used by DbgHelp in the
* event that this implementation is used on Windows, each type and value
* defined here is given a new name, beginning with "MD". Names of the
* equivalent types and values in the Windows Platform SDK are given in
* comments.
*
* Author: Mark Mentovai */
#ifndef GOOGLE_BREAKPAD_COMMON_MINIDUMP_CPU_X86_H__
#define GOOGLE_BREAKPAD_COMMON_MINIDUMP_CPU_X86_H__
#define MD_FLOATINGSAVEAREA_X86_REGISTERAREA_SIZE 80
/* SIZE_OF_80387_REGISTERS */
typedef struct {
u_int32_t control_word;
u_int32_t status_word;
u_int32_t tag_word;
u_int32_t error_offset;
u_int32_t error_selector;
u_int32_t data_offset;
u_int32_t data_selector;
/* register_area contains eight 80-bit (x87 "long double") quantities for
* floating-point registers %st0 (%mm0) through %st7 (%mm7). */
u_int8_t register_area[MD_FLOATINGSAVEAREA_X86_REGISTERAREA_SIZE];
u_int32_t cr0_npx_state;
} MDFloatingSaveAreaX86; /* FLOATING_SAVE_AREA */
#define MD_CONTEXT_X86_EXTENDED_REGISTERS_SIZE 512
/* MAXIMUM_SUPPORTED_EXTENSION */
typedef struct {
/* The next field determines the layout of the structure, and which parts
* of it are populated */
u_int32_t context_flags;
/* The next 6 registers are included with MD_CONTEXT_X86_DEBUG_REGISTERS */
u_int32_t dr0;
u_int32_t dr1;
u_int32_t dr2;
u_int32_t dr3;
u_int32_t dr6;
u_int32_t dr7;
/* The next field is included with MD_CONTEXT_X86_FLOATING_POINT */
MDFloatingSaveAreaX86 float_save;
/* The next 4 registers are included with MD_CONTEXT_X86_SEGMENTS */
u_int32_t gs;
u_int32_t fs;
u_int32_t es;
u_int32_t ds;
/* The next 6 registers are included with MD_CONTEXT_X86_INTEGER */
u_int32_t edi;
u_int32_t esi;
u_int32_t ebx;
u_int32_t edx;
u_int32_t ecx;
u_int32_t eax;
/* The next 6 registers are included with MD_CONTEXT_X86_CONTROL */
u_int32_t ebp;
u_int32_t eip;
u_int32_t cs; /* WinNT.h says "must be sanitized" */
u_int32_t eflags; /* WinNT.h says "must be sanitized" */
u_int32_t esp;
u_int32_t ss;
/* The next field is included with MD_CONTEXT_X86_EXTENDED_REGISTERS.
* It contains vector (MMX/SSE) registers. It it laid out in the
* format used by the fxsave and fsrstor instructions, so it includes
* a copy of the x87 floating-point registers as well. See FXSAVE in
* "Intel Architecture Software Developer's Manual, Volume 2." */
u_int8_t extended_registers[
MD_CONTEXT_X86_EXTENDED_REGISTERS_SIZE];
} MDRawContextX86; /* CONTEXT */
/* For (MDRawContextX86).context_flags. These values indicate the type of
* context stored in the structure. The high 26 bits identify the CPU, the
* low 6 bits identify the type of context saved. */
#define MD_CONTEXT_X86 0x00010000
/* CONTEXT_i386, CONTEXT_i486: identifies CPU */
#define MD_CONTEXT_X86_CONTROL (MD_CONTEXT_X86 | 0x00000001)
/* CONTEXT_CONTROL */
#define MD_CONTEXT_X86_INTEGER (MD_CONTEXT_X86 | 0x00000002)
/* CONTEXT_INTEGER */
#define MD_CONTEXT_X86_SEGMENTS (MD_CONTEXT_X86 | 0x00000004)
/* CONTEXT_SEGMENTS */
#define MD_CONTEXT_X86_FLOATING_POINT (MD_CONTEXT_X86 | 0x00000008)
/* CONTEXT_FLOATING_POINT */
#define MD_CONTEXT_X86_DEBUG_REGISTERS (MD_CONTEXT_X86 | 0x00000010)
/* CONTEXT_DEBUG_REGISTERS */
#define MD_CONTEXT_X86_EXTENDED_REGISTERS (MD_CONTEXT_X86 | 0x00000020)
/* CONTEXT_EXTENDED_REGISTERS */
#define MD_CONTEXT_X86_FULL (MD_CONTEXT_X86_CONTROL | \
MD_CONTEXT_X86_INTEGER | \
MD_CONTEXT_X86_SEGMENTS)
/* CONTEXT_FULL */
#define MD_CONTEXT_X86_ALL (MD_CONTEXT_X86_FULL | \
MD_CONTEXT_X86_FLOATING_POINT | \
MD_CONTEXT_X86_DEBUG_REGISTERS | \
MD_CONTEXT_X86_EXTENDED_REGISTERS)
/* CONTEXT_ALL */
#endif /* GOOGLE_BREAKPAD_COMMON_MINIDUMP_CPU_X86_H__ */

Просмотреть файл

@ -0,0 +1,85 @@
/* Copyright (c) 2006, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
/* minidump_exception_linux.h: A definition of exception codes for
* Linux
*
* (This is C99 source, please don't corrupt it with C++.)
*
* Author: Mark Mentovai
* Split into its own file: Neal Sidhwaney */
#ifndef GOOGLE_BREAKPAD_COMMON_MINIDUMP_EXCEPTION_LINUX_H__
#define GOOGLE_BREAKPAD_COMMON_MINIDUMP_EXCEPTION_LINUX_H__
#include <stddef.h>
#include "google_breakpad/common/breakpad_types.h"
/* For (MDException).exception_code. These values come from bits/signum.h.
*/
typedef enum {
MD_EXCEPTION_CODE_LIN_SIGHUP = 1, /* Hangup (POSIX) */
MD_EXCEPTION_CODE_LIN_SIGINT = 2, /* Interrupt (ANSI) */
MD_EXCEPTION_CODE_LIN_SIGQUIT = 3, /* Quit (POSIX) */
MD_EXCEPTION_CODE_LIN_SIGILL = 4, /* Illegal instruction (ANSI) */
MD_EXCEPTION_CODE_LIN_SIGTRAP = 5, /* Trace trap (POSIX) */
MD_EXCEPTION_CODE_LIN_SIGABRT = 6, /* Abort (ANSI) */
MD_EXCEPTION_CODE_LIN_SIGBUS = 7, /* BUS error (4.2 BSD) */
MD_EXCEPTION_CODE_LIN_SIGFPE = 8, /* Floating-point exception (ANSI) */
MD_EXCEPTION_CODE_LIN_SIGKILL = 9, /* Kill, unblockable (POSIX) */
MD_EXCEPTION_CODE_LIN_SIGUSR1 = 10, /* User-defined signal 1 (POSIX). */
MD_EXCEPTION_CODE_LIN_SIGSEGV = 11, /* Segmentation violation (ANSI) */
MD_EXCEPTION_CODE_LIN_SIGUSR2 = 12, /* User-defined signal 2 (POSIX) */
MD_EXCEPTION_CODE_LIN_SIGPIPE = 13, /* Broken pipe (POSIX) */
MD_EXCEPTION_CODE_LIN_SIGALRM = 14, /* Alarm clock (POSIX) */
MD_EXCEPTION_CODE_LIN_SIGTERM = 15, /* Termination (ANSI) */
MD_EXCEPTION_CODE_LIN_SIGSTKFLT = 16, /* Stack faultd */
MD_EXCEPTION_CODE_LIN_SIGCHLD = 17, /* Child status has changed (POSIX) */
MD_EXCEPTION_CODE_LIN_SIGCONT = 18, /* Continue (POSIX) */
MD_EXCEPTION_CODE_LIN_SIGSTOP = 19, /* Stop, unblockable (POSIX) */
MD_EXCEPTION_CODE_LIN_SIGTSTP = 20, /* Keyboard stop (POSIX) */
MD_EXCEPTION_CODE_LIN_SIGTTIN = 21, /* Background read from tty (POSIX) */
MD_EXCEPTION_CODE_LIN_SIGTTOU = 22, /* Background write to tty (POSIX) */
MD_EXCEPTION_CODE_LIN_SIGURG = 23,
/* Urgent condition on socket (4.2 BSD) */
MD_EXCEPTION_CODE_LIN_SIGXCPU = 24, /* CPU limit exceeded (4.2 BSD) */
MD_EXCEPTION_CODE_LIN_SIGXFSZ = 25,
/* File size limit exceeded (4.2 BSD) */
MD_EXCEPTION_CODE_LIN_SIGVTALRM = 26, /* Virtual alarm clock (4.2 BSD) */
MD_EXCEPTION_CODE_LIN_SIGPROF = 27, /* Profiling alarm clock (4.2 BSD) */
MD_EXCEPTION_CODE_LIN_SIGWINCH = 28, /* Window size change (4.3 BSD, Sun) */
MD_EXCEPTION_CODE_LIN_SIGIO = 29, /* I/O now possible (4.2 BSD) */
MD_EXCEPTION_CODE_LIN_SIGPWR = 30, /* Power failure restart (System V) */
MD_EXCEPTION_CODE_LIN_SIGSYS = 31 /* Bad system call */
} MDExceptionCodeLinux;
#endif /* GOOGLE_BREAKPAD_COMMON_MINIDUMP_EXCEPTION_LINUX_H__ */

Просмотреть файл

@ -0,0 +1,193 @@
/* Copyright (c) 2006, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
/* minidump_exception_mac.h: A definition of exception codes for Mac
* OS X
*
* (This is C99 source, please don't corrupt it with C++.)
*
* Author: Mark Mentovai
* Split into its own file: Neal Sidhwaney */
#ifndef GOOGLE_BREAKPAD_COMMON_MINIDUMP_EXCEPTION_MAC_H__
#define GOOGLE_BREAKPAD_COMMON_MINIDUMP_EXCEPTION_MAC_H__
#include <stddef.h>
#include "google_breakpad/common/breakpad_types.h"
/* For (MDException).exception_code. Breakpad minidump extension for Mac OS X
* support. Based on Darwin/Mac OS X' mach/exception_types.h. This is
* what Mac OS X calls an "exception", not a "code". */
typedef enum {
/* Exception code. The high 16 bits of exception_code contains one of
* these values. */
MD_EXCEPTION_MAC_BAD_ACCESS = 1, /* code can be a kern_return_t */
/* EXC_BAD_ACCESS */
MD_EXCEPTION_MAC_BAD_INSTRUCTION = 2, /* code is CPU-specific */
/* EXC_BAD_INSTRUCTION */
MD_EXCEPTION_MAC_ARITHMETIC = 3, /* code is CPU-specific */
/* EXC_ARITHMETIC */
MD_EXCEPTION_MAC_EMULATION = 4, /* code is CPU-specific */
/* EXC_EMULATION */
MD_EXCEPTION_MAC_SOFTWARE = 5,
/* EXC_SOFTWARE */
MD_EXCEPTION_MAC_BREAKPOINT = 6, /* code is CPU-specific */
/* EXC_BREAKPOINT */
MD_EXCEPTION_MAC_SYSCALL = 7,
/* EXC_SYSCALL */
MD_EXCEPTION_MAC_MACH_SYSCALL = 8,
/* EXC_MACH_SYSCALL */
MD_EXCEPTION_MAC_RPC_ALERT = 9
/* EXC_RPC_ALERT */
} MDExceptionMac;
/* For (MDException).exception_flags. Breakpad minidump extension for Mac OS X
* support. Based on Darwin/Mac OS X' mach/ppc/exception.h and
* mach/i386/exception.h. This is what Mac OS X calls a "code". */
typedef enum {
/* With MD_EXCEPTION_BAD_ACCESS. These are relevant kern_return_t values
* from mach/kern_return.h. */
MD_EXCEPTION_CODE_MAC_INVALID_ADDRESS = 1,
/* KERN_INVALID_ADDRESS */
MD_EXCEPTION_CODE_MAC_PROTECTION_FAILURE = 2,
/* KERN_PROTECTION_FAILURE */
MD_EXCEPTION_CODE_MAC_NO_ACCESS = 8,
/* KERN_NO_ACCESS */
MD_EXCEPTION_CODE_MAC_MEMORY_FAILURE = 9,
/* KERN_MEMORY_FAILURE */
MD_EXCEPTION_CODE_MAC_MEMORY_ERROR = 10,
/* KERN_MEMORY_ERROR */
/* With MD_EXCEPTION_SOFTWARE */
MD_EXCEPTION_CODE_MAC_BAD_SYSCALL = 0x00010000, /* Mach SIGSYS */
MD_EXCEPTION_CODE_MAC_BAD_PIPE = 0x00010001, /* Mach SIGPIPE */
MD_EXCEPTION_CODE_MAC_ABORT = 0x00010002, /* Mach SIGABRT */
/* With MD_EXCEPTION_MAC_BAD_ACCESS on ppc */
MD_EXCEPTION_CODE_MAC_PPC_VM_PROT_READ = 0x0101,
/* EXC_PPC_VM_PROT_READ */
MD_EXCEPTION_CODE_MAC_PPC_BADSPACE = 0x0102,
/* EXC_PPC_BADSPACE */
MD_EXCEPTION_CODE_MAC_PPC_UNALIGNED = 0x0103,
/* EXC_PPC_UNALIGNED */
/* With MD_EXCEPTION_MAC_BAD_INSTRUCTION on ppc */
MD_EXCEPTION_CODE_MAC_PPC_INVALID_SYSCALL = 1,
/* EXC_PPC_INVALID_SYSCALL */
MD_EXCEPTION_CODE_MAC_PPC_UNIMPLEMENTED_INSTRUCTION = 2,
/* EXC_PPC_UNIPL_INST */
MD_EXCEPTION_CODE_MAC_PPC_PRIVILEGED_INSTRUCTION = 3,
/* EXC_PPC_PRIVINST */
MD_EXCEPTION_CODE_MAC_PPC_PRIVILEGED_REGISTER = 4,
/* EXC_PPC_PRIVREG */
MD_EXCEPTION_CODE_MAC_PPC_TRACE = 5,
/* EXC_PPC_TRACE */
MD_EXCEPTION_CODE_MAC_PPC_PERFORMANCE_MONITOR = 6,
/* EXC_PPC_PERFMON */
/* With MD_EXCEPTION_MAC_ARITHMETIC on ppc */
MD_EXCEPTION_CODE_MAC_PPC_OVERFLOW = 1,
/* EXC_PPC_OVERFLOW */
MD_EXCEPTION_CODE_MAC_PPC_ZERO_DIVIDE = 2,
/* EXC_PPC_ZERO_DIVIDE */
MD_EXCEPTION_CODE_MAC_PPC_FLOAT_INEXACT = 3,
/* EXC_FLT_INEXACT */
MD_EXCEPTION_CODE_MAC_PPC_FLOAT_ZERO_DIVIDE = 4,
/* EXC_PPC_FLT_ZERO_DIVIDE */
MD_EXCEPTION_CODE_MAC_PPC_FLOAT_UNDERFLOW = 5,
/* EXC_PPC_FLT_UNDERFLOW */
MD_EXCEPTION_CODE_MAC_PPC_FLOAT_OVERFLOW = 6,
/* EXC_PPC_FLT_OVERFLOW */
MD_EXCEPTION_CODE_MAC_PPC_FLOAT_NOT_A_NUMBER = 7,
/* EXC_PPC_FLT_NOT_A_NUMBER */
/* With MD_EXCEPTION_MAC_EMULATION on ppc */
MD_EXCEPTION_CODE_MAC_PPC_NO_EMULATION = 8,
/* EXC_PPC_NOEMULATION */
MD_EXCEPTION_CODE_MAC_PPC_ALTIVEC_ASSIST = 9,
/* EXC_PPC_ALTIVECASSIST */
/* With MD_EXCEPTION_MAC_SOFTWARE on ppc */
MD_EXCEPTION_CODE_MAC_PPC_TRAP = 0x00000001, /* EXC_PPC_TRAP */
MD_EXCEPTION_CODE_MAC_PPC_MIGRATE = 0x00010100, /* EXC_PPC_MIGRATE */
/* With MD_EXCEPTION_MAC_BREAKPOINT on ppc */
MD_EXCEPTION_CODE_MAC_PPC_BREAKPOINT = 1, /* EXC_PPC_BREAKPOINT */
/* With MD_EXCEPTION_MAC_BAD_INSTRUCTION on x86, see also x86 interrupt
* values below. */
MD_EXCEPTION_CODE_MAC_X86_INVALID_OPERATION = 1, /* EXC_I386_INVOP */
/* With MD_EXCEPTION_MAC_ARITHMETIC on x86 */
MD_EXCEPTION_CODE_MAC_X86_DIV = 1, /* EXC_I386_DIV */
MD_EXCEPTION_CODE_MAC_X86_INTO = 2, /* EXC_I386_INTO */
MD_EXCEPTION_CODE_MAC_X86_NOEXT = 3, /* EXC_I386_NOEXT */
MD_EXCEPTION_CODE_MAC_X86_EXTOVR = 4, /* EXC_I386_EXTOVR */
MD_EXCEPTION_CODE_MAC_X86_EXTERR = 5, /* EXC_I386_EXTERR */
MD_EXCEPTION_CODE_MAC_X86_EMERR = 6, /* EXC_I386_EMERR */
MD_EXCEPTION_CODE_MAC_X86_BOUND = 7, /* EXC_I386_BOUND */
MD_EXCEPTION_CODE_MAC_X86_SSEEXTERR = 8, /* EXC_I386_SSEEXTERR */
/* With MD_EXCEPTION_MAC_BREAKPOINT on x86 */
MD_EXCEPTION_CODE_MAC_X86_SGL = 1, /* EXC_I386_SGL */
MD_EXCEPTION_CODE_MAC_X86_BPT = 2, /* EXC_I386_BPT */
/* With MD_EXCEPTION_MAC_BAD_INSTRUCTION on x86. These are the raw
* x86 interrupt codes. Most of these are mapped to other Mach
* exceptions and codes, are handled, or should not occur in user space.
* A few of these will do occur with MD_EXCEPTION_MAC_BAD_INSTRUCTION. */
/* EXC_I386_DIVERR = 0: mapped to EXC_ARITHMETIC/EXC_I386_DIV */
/* EXC_I386_SGLSTP = 1: mapped to EXC_BREAKPOINT/EXC_I386_SGL */
/* EXC_I386_NMIFLT = 2: should not occur in user space */
/* EXC_I386_BPTFLT = 3: mapped to EXC_BREAKPOINT/EXC_I386_BPT */
/* EXC_I386_INTOFLT = 4: mapped to EXC_ARITHMETIC/EXC_I386_INTO */
/* EXC_I386_BOUNDFLT = 5: mapped to EXC_ARITHMETIC/EXC_I386_BOUND */
/* EXC_I386_INVOPFLT = 6: mapped to EXC_BAD_INSTRUCTION/EXC_I386_INVOP */
/* EXC_I386_NOEXTFLT = 7: should be handled by the kernel */
/* EXC_I386_DBLFLT = 8: should be handled (if possible) by the kernel */
/* EXC_I386_EXTOVRFLT = 9: mapped to EXC_BAD_ACCESS/(PROT_READ|PROT_EXEC) */
MD_EXCEPTION_CODE_MAC_X86_INVALID_TASK_STATE_SEGMENT = 10,
/* EXC_INVTSSFLT */
MD_EXCEPTION_CODE_MAC_X86_SEGMENT_NOT_PRESENT = 11,
/* EXC_SEGNPFLT */
MD_EXCEPTION_CODE_MAC_X86_STACK_FAULT = 12,
/* EXC_STKFLT */
MD_EXCEPTION_CODE_MAC_X86_GENERAL_PROTECTION_FAULT = 13,
/* EXC_GPFLT */
/* EXC_I386_PGFLT = 14: should not occur in user space */
/* EXC_I386_EXTERRFLT = 16: mapped to EXC_ARITHMETIC/EXC_I386_EXTERR */
MD_EXCEPTION_CODE_MAC_X86_ALIGNMENT_FAULT = 17
/* EXC_ALIGNFLT (for vector operations) */
/* EXC_I386_ENOEXTFLT = 32: should be handled by the kernel */
/* EXC_I386_ENDPERR = 33: should not occur */
} MDExceptionCodeMac;
#endif /* GOOGLE_BREAKPAD_COMMON_MINIDUMP_EXCEPTION_MAC_OSX_H__ */

Просмотреть файл

@ -0,0 +1,94 @@
/* Copyright (c) 2006, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
/* minidump_exception_solaris.h: A definition of exception codes for
* Solaris
*
* (This is C99 source, please don't corrupt it with C++.)
*
* Author: Mark Mentovai
* Split into its own file: Neal Sidhwaney */
#ifndef GOOGLE_BREAKPAD_COMMON_MINIDUMP_EXCEPTION_SOLARIS_H__
#define GOOGLE_BREAKPAD_COMMON_MINIDUMP_EXCEPTION_SOLARIS_H__
#include <stddef.h>
#include "google_breakpad/common/breakpad_types.h"
/* For (MDException).exception_code. These values come from sys/iso/signal_iso.h
*/
typedef enum {
MD_EXCEPTION_CODE_SOL_SIGHUP = 1, /* Hangup */
MD_EXCEPTION_CODE_SOL_SIGINT = 2, /* interrupt (rubout) */
MD_EXCEPTION_CODE_SOL_SIGQUIT = 3, /* quit (ASCII FS) */
MD_EXCEPTION_CODE_SOL_SIGILL = 4, /* illegal instruction (not reset when caught) */
MD_EXCEPTION_CODE_SOL_SIGTRAP = 5, /* trace trap (not reset when caught) */
MD_EXCEPTION_CODE_SOL_SIGIOT = 6, /* IOT instruction */
MD_EXCEPTION_CODE_SOL_SIGABRT = 6, /* used by abort, replace SIGIOT in the future */
MD_EXCEPTION_CODE_SOL_SIGEMT = 7, /* EMT instruction */
MD_EXCEPTION_CODE_SOL_SIGFPE = 8, /* floating point exception */
MD_EXCEPTION_CODE_SOL_SIGKILL = 9, /* kill (cannot be caught or ignored) */
MD_EXCEPTION_CODE_SOL_SIGBUS = 10, /* bus error */
MD_EXCEPTION_CODE_SOL_SIGSEGV = 11, /* segmentation violation */
MD_EXCEPTION_CODE_SOL_SIGSYS = 12, /* bad argument to system call */
MD_EXCEPTION_CODE_SOL_SIGPIPE = 13, /* write on a pipe with no one to read it */
MD_EXCEPTION_CODE_SOL_SIGALRM = 14, /* alarm clock */
MD_EXCEPTION_CODE_SOL_SIGTERM = 15, /* software termination signal from kill */
MD_EXCEPTION_CODE_SOL_SIGUSR1 = 16, /* user defined signal 1 */
MD_EXCEPTION_CODE_SOL_SIGUSR2 = 17, /* user defined signal 2 */
MD_EXCEPTION_CODE_SOL_SIGCLD = 18, /* child status change */
MD_EXCEPTION_CODE_SOL_SIGCHLD = 18, /* child status change alias (POSIX) */
MD_EXCEPTION_CODE_SOL_SIGPWR = 19, /* power-fail restart */
MD_EXCEPTION_CODE_SOL_SIGWINCH = 20, /* window size change */
MD_EXCEPTION_CODE_SOL_SIGURG = 21, /* urgent socket condition */
MD_EXCEPTION_CODE_SOL_SIGPOLL = 22, /* pollable event occured */
MD_EXCEPTION_CODE_SOL_SIGIO = 22, /* socket I/O possible (SIGPOLL alias) */
MD_EXCEPTION_CODE_SOL_SIGSTOP = 23, /* stop (cannot be caught or ignored) */
MD_EXCEPTION_CODE_SOL_SIGTSTP = 24, /* user stop requested from tty */
MD_EXCEPTION_CODE_SOL_SIGCONT = 25, /* stopped process has been continued */
MD_EXCEPTION_CODE_SOL_SIGTTIN = 26, /* background tty read attempted */
MD_EXCEPTION_CODE_SOL_SIGTTOU = 27, /* background tty write attempted */
MD_EXCEPTION_CODE_SOL_SIGVTALRM = 28, /* virtual timer expired */
MD_EXCEPTION_CODE_SOL_SIGPROF = 29, /* profiling timer expired */
MD_EXCEPTION_CODE_SOL_SIGXCPU = 30, /* exceeded cpu limit */
MD_EXCEPTION_CODE_SOL_SIGXFSZ = 31, /* exceeded file size limit */
MD_EXCEPTION_CODE_SOL_SIGWAITING = 32, /* reserved signal no longer used by threading code */
MD_EXCEPTION_CODE_SOL_SIGLWP = 33, /* reserved signal no longer used by threading code */
MD_EXCEPTION_CODE_SOL_SIGFREEZE = 34, /* special signal used by CPR */
MD_EXCEPTION_CODE_SOL_SIGTHAW = 35, /* special signal used by CPR */
MD_EXCEPTION_CODE_SOL_SIGCANCEL = 36, /* reserved signal for thread cancellation */
MD_EXCEPTION_CODE_SOL_SIGLOST = 37, /* resource lost (eg, record-lock lost) */
MD_EXCEPTION_CODE_SOL_SIGXRES = 38, /* resource control exceeded */
MD_EXCEPTION_CODE_SOL_SIGJVM1 = 39, /* reserved signal for Java Virtual Machine */
MD_EXCEPTION_CODE_SOL_SIGJVM2 = 40 /* reserved signal for Java Virtual Machine */
} MDExceptionCodeSolaris;
#endif /* GOOGLE_BREAKPAD_COMMON_MINIDUMP_EXCEPTION_SOLARIS_H__ */

Просмотреть файл

@ -0,0 +1,102 @@
/* Copyright (c) 2006, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
/* minidump_exception_win32.h: Definitions of exception codes for
* Win32 platform
*
* (This is C99 source, please don't corrupt it with C++.)
*
* Author: Mark Mentovai
* Split into its own file: Neal Sidhwaney */
#ifndef GOOGLE_BREAKPAD_COMMON_MINIDUMP_EXCEPTION_WIN32_H__
#define GOOGLE_BREAKPAD_COMMON_MINIDUMP_EXCEPTION_WIN32_H__
#include <stddef.h>
#include "google_breakpad/common/breakpad_types.h"
/* For (MDException).exception_code. These values come from WinBase.h
* and WinNT.h (names beginning with EXCEPTION_ are in WinBase.h,
* they are STATUS_ in WinNT.h). */
typedef enum {
MD_EXCEPTION_CODE_WIN_CONTROL_C = 0x40010005,
/* DBG_CONTROL_C */
MD_EXCEPTION_CODE_WIN_GUARD_PAGE_VIOLATION = 0x80000001,
/* EXCEPTION_GUARD_PAGE */
MD_EXCEPTION_CODE_WIN_DATATYPE_MISALIGNMENT = 0x80000002,
/* EXCEPTION_DATATYPE_MISALIGNMENT */
MD_EXCEPTION_CODE_WIN_BREAKPOINT = 0x80000003,
/* EXCEPTION_BREAKPOINT */
MD_EXCEPTION_CODE_WIN_SINGLE_STEP = 0x80000004,
/* EXCEPTION_SINGLE_STEP */
MD_EXCEPTION_CODE_WIN_ACCESS_VIOLATION = 0xc0000005,
/* EXCEPTION_ACCESS_VIOLATION */
MD_EXCEPTION_CODE_WIN_IN_PAGE_ERROR = 0xc0000006,
/* EXCEPTION_IN_PAGE_ERROR */
MD_EXCEPTION_CODE_WIN_INVALID_HANDLE = 0xc0000008,
/* EXCEPTION_INVALID_HANDLE */
MD_EXCEPTION_CODE_WIN_ILLEGAL_INSTRUCTION = 0xc000001d,
/* EXCEPTION_ILLEGAL_INSTRUCTION */
MD_EXCEPTION_CODE_WIN_NONCONTINUABLE_EXCEPTION = 0xc0000025,
/* EXCEPTION_NONCONTINUABLE_EXCEPTION */
MD_EXCEPTION_CODE_WIN_INVALID_DISPOSITION = 0xc0000026,
/* EXCEPTION_INVALID_DISPOSITION */
MD_EXCEPTION_CODE_WIN_ARRAY_BOUNDS_EXCEEDED = 0xc000008c,
/* EXCEPTION_BOUNDS_EXCEEDED */
MD_EXCEPTION_CODE_WIN_FLOAT_DENORMAL_OPERAND = 0xc000008d,
/* EXCEPTION_FLT_DENORMAL_OPERAND */
MD_EXCEPTION_CODE_WIN_FLOAT_DIVIDE_BY_ZERO = 0xc000008e,
/* EXCEPTION_FLT_DIVIDE_BY_ZERO */
MD_EXCEPTION_CODE_WIN_FLOAT_INEXACT_RESULT = 0xc000008f,
/* EXCEPTION_FLT_INEXACT_RESULT */
MD_EXCEPTION_CODE_WIN_FLOAT_INVALID_OPERATION = 0xc0000090,
/* EXCEPTION_FLT_INVALID_OPERATION */
MD_EXCEPTION_CODE_WIN_FLOAT_OVERFLOW = 0xc0000091,
/* EXCEPTION_FLT_OVERFLOW */
MD_EXCEPTION_CODE_WIN_FLOAT_STACK_CHECK = 0xc0000092,
/* EXCEPTION_FLT_STACK_CHECK */
MD_EXCEPTION_CODE_WIN_FLOAT_UNDERFLOW = 0xc0000093,
/* EXCEPTION_FLT_UNDERFLOW */
MD_EXCEPTION_CODE_WIN_INTEGER_DIVIDE_BY_ZERO = 0xc0000094,
/* EXCEPTION_INT_DIVIDE_BY_ZERO */
MD_EXCEPTION_CODE_WIN_INTEGER_OVERFLOW = 0xc0000095,
/* EXCEPTION_INT_OVERFLOW */
MD_EXCEPTION_CODE_WIN_PRIVILEGED_INSTRUCTION = 0xc0000096,
/* EXCEPTION_PRIV_INSTRUCTION */
MD_EXCEPTION_CODE_WIN_STACK_OVERFLOW = 0xc00000fd,
/* EXCEPTION_STACK_OVERFLOW */
MD_EXCEPTION_CODE_WIN_POSSIBLE_DEADLOCK = 0xc0000194
/* EXCEPTION_POSSIBLE_DEADLOCK */
} MDExceptionCodeWin;
#endif /* GOOGLE_BREAKPAD_COMMON_MINIDUMP_EXCEPTION_WIN32_H__ */

Просмотреть файл

@ -32,18 +32,6 @@
*
* (This is C99 source, please don't corrupt it with C++.)
*
* This file contains the necessary definitions to read minidump files
* produced on win32/x86. These files may be read on any platform provided
* that the alignments of these structures on the processing system are
* identical to the alignments of these structures on the producing system.
* For this reason, precise-sized types are used. The structures defined
* by this file have been laid out to minimize alignment problems by ensuring
* ensuring that all members are aligned on their natural boundaries. In
* In some cases, tail-padding may be significant when different ABIs specify
* different tail-padding behaviors. To avoid problems when reading or
* writing affected structures, MD_*_SIZE macros are provided where needed,
* containing the useful size of the structures without padding.
*
* Structures that are defined by Microsoft to contain a zero-length array
* are instead defined here to contain an array with one element, as
* zero-length arrays are forbidden by standard C and C++. In these cases,
@ -68,7 +56,7 @@
* comments.
*
* Author: Mark Mentovai */
#ifndef GOOGLE_BREAKPAD_COMMON_MINIDUMP_FORMAT_H__
#define GOOGLE_BREAKPAD_COMMON_MINIDUMP_FORMAT_H__
@ -90,7 +78,6 @@
* guiddef.h
*/
typedef struct {
u_int32_t data1;
u_int16_t data2;
@ -103,104 +90,6 @@ typedef struct {
* WinNT.h
*/
#define MD_FLOATINGSAVEAREA_X86_REGISTERAREA_SIZE 80
/* SIZE_OF_80387_REGISTERS */
typedef struct {
u_int32_t control_word;
u_int32_t status_word;
u_int32_t tag_word;
u_int32_t error_offset;
u_int32_t error_selector;
u_int32_t data_offset;
u_int32_t data_selector;
/* register_area contains eight 80-bit (x87 "long double") quantities for
* floating-point registers %st0 (%mm0) through %st7 (%mm7). */
u_int8_t register_area[MD_FLOATINGSAVEAREA_X86_REGISTERAREA_SIZE];
u_int32_t cr0_npx_state;
} MDFloatingSaveAreaX86; /* FLOATING_SAVE_AREA */
#define MD_CONTEXT_X86_EXTENDED_REGISTERS_SIZE 512
/* MAXIMUM_SUPPORTED_EXTENSION */
typedef struct {
/* The next field determines the layout of the structure, and which parts
* of it are populated */
u_int32_t context_flags;
/* The next 6 registers are included with MD_CONTEXT_X86_DEBUG_REGISTERS */
u_int32_t dr0;
u_int32_t dr1;
u_int32_t dr2;
u_int32_t dr3;
u_int32_t dr6;
u_int32_t dr7;
/* The next field is included with MD_CONTEXT_X86_FLOATING_POINT */
MDFloatingSaveAreaX86 float_save;
/* The next 4 registers are included with MD_CONTEXT_X86_SEGMENTS */
u_int32_t gs;
u_int32_t fs;
u_int32_t es;
u_int32_t ds;
/* The next 6 registers are included with MD_CONTEXT_X86_INTEGER */
u_int32_t edi;
u_int32_t esi;
u_int32_t ebx;
u_int32_t edx;
u_int32_t ecx;
u_int32_t eax;
/* The next 6 registers are included with MD_CONTEXT_X86_CONTROL */
u_int32_t ebp;
u_int32_t eip;
u_int32_t cs; /* WinNT.h says "must be sanitized" */
u_int32_t eflags; /* WinNT.h says "must be sanitized" */
u_int32_t esp;
u_int32_t ss;
/* The next field is included with MD_CONTEXT_X86_EXTENDED_REGISTERS.
* It contains vector (MMX/SSE) registers. It it laid out in the
* format used by the fxsave and fsrstor instructions, so it includes
* a copy of the x87 floating-point registers as well. See FXSAVE in
* "Intel Architecture Software Developer's Manual, Volume 2." */
u_int8_t extended_registers[
MD_CONTEXT_X86_EXTENDED_REGISTERS_SIZE];
} MDRawContextX86; /* CONTEXT */
/* For (MDRawContextX86).context_flags. These values indicate the type of
* context stored in the structure. The high 26 bits identify the CPU, the
* low 6 bits identify the type of context saved. */
#define MD_CONTEXT_X86 0x00010000
/* CONTEXT_i386, CONTEXT_i486: identifies CPU */
#define MD_CONTEXT_X86_CONTROL (MD_CONTEXT_X86 | 0x00000001)
/* CONTEXT_CONTROL */
#define MD_CONTEXT_X86_INTEGER (MD_CONTEXT_X86 | 0x00000002)
/* CONTEXT_INTEGER */
#define MD_CONTEXT_X86_SEGMENTS (MD_CONTEXT_X86 | 0x00000004)
/* CONTEXT_SEGMENTS */
#define MD_CONTEXT_X86_FLOATING_POINT (MD_CONTEXT_X86 | 0x00000008)
/* CONTEXT_FLOATING_POINT */
#define MD_CONTEXT_X86_DEBUG_REGISTERS (MD_CONTEXT_X86 | 0x00000010)
/* CONTEXT_DEBUG_REGISTERS */
#define MD_CONTEXT_X86_EXTENDED_REGISTERS (MD_CONTEXT_X86 | 0x00000020)
/* CONTEXT_EXTENDED_REGISTERS */
#define MD_CONTEXT_X86_FULL (MD_CONTEXT_X86_CONTROL | \
MD_CONTEXT_X86_INTEGER | \
MD_CONTEXT_X86_SEGMENTS)
/* CONTEXT_FULL */
#define MD_CONTEXT_X86_ALL (MD_CONTEXT_X86_FULL | \
MD_CONTEXT_X86_FLOATING_POINT | \
MD_CONTEXT_X86_DEBUG_REGISTERS | \
MD_CONTEXT_X86_EXTENDED_REGISTERS)
/* CONTEXT_ALL */
/* Non-x86 CPU identifiers found in the high 26 bits of
* (MDRawContext*).context_flags. These aren't used by Breakpad, but are
* defined here for reference, to avoid assigning values that conflict
@ -215,247 +104,6 @@ typedef struct {
#define MD_CONTEXT_CPU_MASK 0xffffffc0
/*
* AMD64 support, see WINNT.H
*/
typedef struct {
u_int16_t control_word;
u_int16_t status_word;
u_int8_t tag_word;
u_int8_t reserved1;
u_int16_t error_opcode;
u_int32_t error_offset;
u_int16_t error_selector;
u_int16_t reserved2;
u_int32_t data_offset;
u_int16_t data_selector;
u_int16_t reserved3;
u_int32_t mx_csr;
u_int32_t mx_csr_mask;
u_int128_t float_registers[8];
u_int128_t xmm_registers[16];
u_int8_t reserved4[96];
} MDXmmSaveArea32AMD64; /* XMM_SAVE_AREA32 */
#define MD_CONTEXT_AMD64_VR_COUNT 26
typedef struct {
/*
* Register parameter home addresses.
*/
u_int64_t p1_home;
u_int64_t p2_home;
u_int64_t p3_home;
u_int64_t p4_home;
u_int64_t p5_home;
u_int64_t p6_home;
/* The next field determines the layout of the structure, and which parts
* of it are populated */
u_int32_t context_flags;
u_int32_t mx_csr;
/* The next register is included with MD_CONTEXT_AMD64_CONTROL */
u_int16_t cs;
/* The next 4 registers are included with MD_CONTEXT_AMD64_SEGMENTS */
u_int16_t ds;
u_int16_t es;
u_int16_t fs;
u_int16_t gs;
/* The next 2 registers are included with MD_CONTEXT_AMD64_CONTROL */
u_int16_t ss;
u_int32_t eflags;
/* The next 6 registers are included with MD_CONTEXT_AMD64_DEBUG_REGISTERS */
u_int64_t dr0;
u_int64_t dr1;
u_int64_t dr2;
u_int64_t dr3;
u_int64_t dr6;
u_int64_t dr7;
/* The next 4 registers are included with MD_CONTEXT_AMD64_INTEGER */
u_int64_t rax;
u_int64_t rcx;
u_int64_t rdx;
u_int64_t rbx;
/* The next register is included with MD_CONTEXT_AMD64_CONTROL */
u_int64_t rsp;
/* The next 11 registers are included with MD_CONTEXT_AMD64_INTEGER */
u_int64_t rbp;
u_int64_t rsi;
u_int64_t rdi;
u_int64_t r8;
u_int64_t r9;
u_int64_t r10;
u_int64_t r11;
u_int64_t r12;
u_int64_t r13;
u_int64_t r14;
u_int64_t r15;
/* The next register is included with MD_CONTEXT_AMD64_CONTROL */
u_int64_t rip;
/* The next set of registers are included with
* MD_CONTEXT_AMD64_FLOATING_POINT
*/
union {
MDXmmSaveArea32AMD64 flt_save;
struct {
u_int128_t header[2];
u_int128_t legacy[8];
u_int128_t xmm0;
u_int128_t xmm1;
u_int128_t xmm2;
u_int128_t xmm3;
u_int128_t xmm4;
u_int128_t xmm5;
u_int128_t xmm6;
u_int128_t xmm7;
u_int128_t xmm8;
u_int128_t xmm9;
u_int128_t xmm10;
u_int128_t xmm11;
u_int128_t xmm12;
u_int128_t xmm13;
u_int128_t xmm14;
u_int128_t xmm15;
} sse_registers;
};
u_int128_t vector_register[MD_CONTEXT_AMD64_VR_COUNT];
u_int64_t vector_control;
/* The next 5 registers are included with MD_CONTEXT_AMD64_DEBUG_REGISTERS */
u_int64_t debug_control;
u_int64_t last_branch_to_rip;
u_int64_t last_branch_from_rip;
u_int64_t last_exception_to_rip;
u_int64_t last_exception_from_rip;
} MDRawContextAMD64; /* CONTEXT */
/* For (MDRawContextAMD64).context_flags. These values indicate the type of
* context stored in the structure. The high 26 bits identify the CPU, the
* low 6 bits identify the type of context saved. */
#define MD_CONTEXT_AMD64_CONTROL (MD_CONTEXT_AMD64 | 0x00000001)
/* CONTEXT_CONTROL */
#define MD_CONTEXT_AMD64_INTEGER (MD_CONTEXT_AMD64 | 0x00000002)
/* CONTEXT_INTEGER */
#define MD_CONTEXT_AMD64_SEGMENTS (MD_CONTEXT_AMD64 | 0x00000004)
/* CONTEXT_SEGMENTS */
#define MD_CONTEXT_AMD64_FLOATING_POINT (MD_CONTEXT_AMD64 | 0x00000008)
/* CONTEXT_FLOATING_POINT */
#define MD_CONTEXT_AMD64_DEBUG_REGISTERS (MD_CONTEXT_AMD64 | 0x00000010)
/* CONTEXT_DEBUG_REGISTERS */
/* WinNT.h refers to CONTEXT_MMX_REGISTERS but doesn't appear to define it
* I think it really means CONTEXT_FLOATING_POINT.
*/
#define MD_CONTEXT_AMD64_FULL (MD_CONTEXT_AMD64_CONTROL | \
MD_CONTEXT_AMD64_INTEGER | \
MD_CONTEXT_AMD64_FLOATING_POINT)
/* CONTEXT_FULL */
#define MD_CONTEXT_AMD64_ALL (MD_CONTEXT_AMD64_FULL | \
MD_CONTEXT_AMD64_SEGMENTS | \
MD_CONTEXT_X86_DEBUG_REGISTERS)
/* CONTEXT_ALL */
/*
* SPARC support, see (solaris)sys/procfs_isa.h also
*/
#define MD_FLOATINGSAVEAREA_SPARC_FPR_COUNT 32
typedef struct {
/* FPU floating point regs */
u_int64_t regs[MD_FLOATINGSAVEAREA_SPARC_FPR_COUNT];
u_int64_t filler;
u_int64_t fsr; /* FPU status register */
} MDFloatingSaveAreaSPARC; /* FLOATING_SAVE_AREA */
#define MD_CONTEXT_SPARC_GPR_COUNT 32
typedef struct {
/* The next field determines the layout of the structure, and which parts
* of it are populated
*/
u_int32_t context_flags;
u_int32_t flag_pad;
/*
* General register access (SPARC).
* Don't confuse definitions here with definitions in <sys/regset.h>.
* Registers are 32 bits for ILP32, 64 bits for LP64.
* SPARC V7/V8 is for 32bit, SPARC V9 is for 64bit
*/
/* 32 Integer working registers */
/* g_r[0-7] global registers(g0-g7)
* g_r[8-15] out registers(o0-o7)
* g_r[16-23] local registers(l0-l7)
* g_r[24-31] in registers(i0-i7)
*/
u_int64_t g_r[MD_CONTEXT_SPARC_GPR_COUNT];
/* several control registers */
/* Processor State register(PSR) for SPARC V7/V8
* Condition Code register (CCR) for SPARC V9
*/
u_int64_t ccr;
u_int64_t pc; /* Program Counter register (PC) */
u_int64_t npc; /* Next Program Counter register (nPC) */
u_int64_t y; /* Y register (Y) */
/* Address Space Identifier register (ASI) for SPARC V9
* WIM for SPARC V7/V8
*/
u_int64_t asi;
/* Floating-Point Registers State register (FPRS) for SPARC V9
* TBR for for SPARC V7/V8
*/
u_int64_t fprs;
/* The next field is included with MD_CONTEXT_SPARC_FLOATING_POINT */
MDFloatingSaveAreaSPARC float_save;
} MDRawContextSPARC; /* CONTEXT_SPARC */
/* For (MDRawContextSPARC).context_flags. These values indicate the type of
* context stored in the structure. MD_CONTEXT_SPARC is Breakpad-defined. Its
* value was chosen to avoid likely conflicts with MD_CONTEXT_* for other
* CPUs. */
#define MD_CONTEXT_SPARC 0x10000000
#define MD_CONTEXT_SPARC_CONTROL (MD_CONTEXT_SPARC | 0x00000001)
#define MD_CONTEXT_SPARC_INTEGER (MD_CONTEXT_SPARC | 0x00000002)
#define MD_CONTEXT_SAPARC_FLOATING_POINT (MD_CONTEXT_SPARC | 0x00000004)
#define MD_CONTEXT_SAPARC_EXTRA (MD_CONTEXT_SPARC | 0x00000008)
#define MD_CONTEXT_SPARC_FULL (MD_CONTEXT_SPARC_CONTROL | \
MD_CONTEXT_SPARC_INTEGER)
#define MD_CONTEXT_SPARC_ALL (MD_CONTEXT_SPARC_FULL | \
MD_CONTEXT_SAPARC_FLOATING_POINT | \
MD_CONTEXT_SAPARC_EXTRA)
/*
* Breakpad minidump extension for PowerPC support. Based on Darwin/Mac OS X'
* mach/ppc/_types.h
*/
/* This is a base type for MDRawContextX86 and MDRawContextPPC. This
* structure should never be allocated directly. The actual structure type
@ -464,73 +112,11 @@ typedef struct {
u_int32_t context_flags;
} MDRawContextBase;
#define MD_FLOATINGSAVEAREA_PPC_FPR_COUNT 32
typedef struct {
/* fpregs is a double[32] in mach/ppc/_types.h, but a u_int64_t is used
* here for precise sizing. */
u_int64_t fpregs[MD_FLOATINGSAVEAREA_PPC_FPR_COUNT];
u_int32_t fpscr_pad;
u_int32_t fpscr; /* Status/control */
} MDFloatingSaveAreaPPC; /* Based on ppc_float_state */
#define MD_VECTORSAVEAREA_PPC_VR_COUNT 32
typedef struct {
/* Vector registers (including vscr) are 128 bits, but mach/ppc/_types.h
* exposes them as four 32-bit quantities. */
u_int128_t save_vr[MD_VECTORSAVEAREA_PPC_VR_COUNT];
u_int128_t save_vscr; /* Status/control */
u_int32_t save_pad5[4];
u_int32_t save_vrvalid; /* Identifies which vector registers are saved */
u_int32_t save_pad6[7];
} MDVectorSaveAreaPPC; /* ppc_vector_state */
#define MD_CONTEXT_PPC_GPR_COUNT 32
typedef struct {
/* context_flags is not present in ppc_thread_state, but it aids
* identification of MDRawContextPPC among other raw context types,
* and it guarantees alignment when we get to float_save. */
u_int32_t context_flags;
u_int32_t srr0; /* Machine status save/restore: stores pc
* (instruction) */
u_int32_t srr1; /* Machine status save/restore: stores msr
* (ps, program/machine state) */
/* ppc_thread_state contains 32 fields, r0 .. r31. Here, an array is
* used for brevity. */
u_int32_t gpr[MD_CONTEXT_PPC_GPR_COUNT];
u_int32_t cr; /* Condition */
u_int32_t xer; /* Integer (fiXed-point) exception */
u_int32_t lr; /* Link */
u_int32_t ctr; /* Count */
u_int32_t mq; /* Multiply/Quotient (PPC 601, POWER only) */
u_int32_t vrsave; /* Vector save */
/* float_save and vector_save aren't present in ppc_thread_state, but
* are represented in separate structures that still define a thread's
* context. */
MDFloatingSaveAreaPPC float_save;
MDVectorSaveAreaPPC vector_save;
} MDRawContextPPC; /* Based on ppc_thread_state */
/* For (MDRawContextPPC).context_flags. These values indicate the type of
* context stored in the structure. MD_CONTEXT_PPC is Breakpad-defined. Its
* value was chosen to avoid likely conflicts with MD_CONTEXT_* for other
* CPUs. */
#define MD_CONTEXT_PPC 0x20000000
#define MD_CONTEXT_PPC_BASE (MD_CONTEXT_PPC | 0x00000001)
#define MD_CONTEXT_PPC_FLOATING_POINT (MD_CONTEXT_PPC | 0x00000008)
#define MD_CONTEXT_PPC_VECTOR (MD_CONTEXT_PPC | 0x00000020)
#define MD_CONTEXT_PPC_FULL MD_CONTEXT_PPC_BASE
#define MD_CONTEXT_PPC_ALL (MD_CONTEXT_PPC_FULL | \
MD_CONTEXT_PPC_FLOATING_POINT | \
MD_CONTEXT_PPC_VECTOR)
#include "minidump_cpu_sparc.h"
#include "minidump_cpu_x86.h"
#include "minidump_cpu_ppc.h"
#include "minidump_cpu_ppc64.h"
#include "minidump_cpu_amd64.h"
/*
@ -646,7 +232,6 @@ typedef struct {
* MDRawHeader is at offset 0. */
typedef u_int32_t MDRVA; /* RVA */
typedef struct {
u_int32_t data_size;
MDRVA rva;
@ -925,292 +510,10 @@ typedef struct {
u_int64_t exception_information[MD_EXCEPTION_MAXIMUM_PARAMETERS];
} MDException; /* MINIDUMP_EXCEPTION */
/* For (MDException).exception_code. These values come from WinBase.h
* and WinNT.h (names beginning with EXCEPTION_ are in WinBase.h,
* they are STATUS_ in WinNT.h). */
typedef enum {
MD_EXCEPTION_CODE_WIN_CONTROL_C = 0x40010005,
/* DBG_CONTROL_C */
MD_EXCEPTION_CODE_WIN_GUARD_PAGE_VIOLATION = 0x80000001,
/* EXCEPTION_GUARD_PAGE */
MD_EXCEPTION_CODE_WIN_DATATYPE_MISALIGNMENT = 0x80000002,
/* EXCEPTION_DATATYPE_MISALIGNMENT */
MD_EXCEPTION_CODE_WIN_BREAKPOINT = 0x80000003,
/* EXCEPTION_BREAKPOINT */
MD_EXCEPTION_CODE_WIN_SINGLE_STEP = 0x80000004,
/* EXCEPTION_SINGLE_STEP */
MD_EXCEPTION_CODE_WIN_ACCESS_VIOLATION = 0xc0000005,
/* EXCEPTION_ACCESS_VIOLATION */
MD_EXCEPTION_CODE_WIN_IN_PAGE_ERROR = 0xc0000006,
/* EXCEPTION_IN_PAGE_ERROR */
MD_EXCEPTION_CODE_WIN_INVALID_HANDLE = 0xc0000008,
/* EXCEPTION_INVALID_HANDLE */
MD_EXCEPTION_CODE_WIN_ILLEGAL_INSTRUCTION = 0xc000001d,
/* EXCEPTION_ILLEGAL_INSTRUCTION */
MD_EXCEPTION_CODE_WIN_NONCONTINUABLE_EXCEPTION = 0xc0000025,
/* EXCEPTION_NONCONTINUABLE_EXCEPTION */
MD_EXCEPTION_CODE_WIN_INVALID_DISPOSITION = 0xc0000026,
/* EXCEPTION_INVALID_DISPOSITION */
MD_EXCEPTION_CODE_WIN_ARRAY_BOUNDS_EXCEEDED = 0xc000008c,
/* EXCEPTION_BOUNDS_EXCEEDED */
MD_EXCEPTION_CODE_WIN_FLOAT_DENORMAL_OPERAND = 0xc000008d,
/* EXCEPTION_FLT_DENORMAL_OPERAND */
MD_EXCEPTION_CODE_WIN_FLOAT_DIVIDE_BY_ZERO = 0xc000008e,
/* EXCEPTION_FLT_DIVIDE_BY_ZERO */
MD_EXCEPTION_CODE_WIN_FLOAT_INEXACT_RESULT = 0xc000008f,
/* EXCEPTION_FLT_INEXACT_RESULT */
MD_EXCEPTION_CODE_WIN_FLOAT_INVALID_OPERATION = 0xc0000090,
/* EXCEPTION_FLT_INVALID_OPERATION */
MD_EXCEPTION_CODE_WIN_FLOAT_OVERFLOW = 0xc0000091,
/* EXCEPTION_FLT_OVERFLOW */
MD_EXCEPTION_CODE_WIN_FLOAT_STACK_CHECK = 0xc0000092,
/* EXCEPTION_FLT_STACK_CHECK */
MD_EXCEPTION_CODE_WIN_FLOAT_UNDERFLOW = 0xc0000093,
/* EXCEPTION_FLT_UNDERFLOW */
MD_EXCEPTION_CODE_WIN_INTEGER_DIVIDE_BY_ZERO = 0xc0000094,
/* EXCEPTION_INT_DIVIDE_BY_ZERO */
MD_EXCEPTION_CODE_WIN_INTEGER_OVERFLOW = 0xc0000095,
/* EXCEPTION_INT_OVERFLOW */
MD_EXCEPTION_CODE_WIN_PRIVILEGED_INSTRUCTION = 0xc0000096,
/* EXCEPTION_PRIV_INSTRUCTION */
MD_EXCEPTION_CODE_WIN_STACK_OVERFLOW = 0xc00000fd,
/* EXCEPTION_STACK_OVERFLOW */
MD_EXCEPTION_CODE_WIN_POSSIBLE_DEADLOCK = 0xc0000194
/* EXCEPTION_POSSIBLE_DEADLOCK */
} MDExceptionCodeWin;
/* For (MDException).exception_code. Breakpad minidump extension for Mac OS X
* support. Based on Darwin/Mac OS X' mach/exception_types.h. This is
* what Mac OS X calls an "exception", not a "code". */
typedef enum {
/* Exception code. The high 16 bits of exception_code contains one of
* these values. */
MD_EXCEPTION_MAC_BAD_ACCESS = 1, /* code can be a kern_return_t */
/* EXC_BAD_ACCESS */
MD_EXCEPTION_MAC_BAD_INSTRUCTION = 2, /* code is CPU-specific */
/* EXC_BAD_INSTRUCTION */
MD_EXCEPTION_MAC_ARITHMETIC = 3, /* code is CPU-specific */
/* EXC_ARITHMETIC */
MD_EXCEPTION_MAC_EMULATION = 4, /* code is CPU-specific */
/* EXC_EMULATION */
MD_EXCEPTION_MAC_SOFTWARE = 5,
/* EXC_SOFTWARE */
MD_EXCEPTION_MAC_BREAKPOINT = 6, /* code is CPU-specific */
/* EXC_BREAKPOINT */
MD_EXCEPTION_MAC_SYSCALL = 7,
/* EXC_SYSCALL */
MD_EXCEPTION_MAC_MACH_SYSCALL = 8,
/* EXC_MACH_SYSCALL */
MD_EXCEPTION_MAC_RPC_ALERT = 9
/* EXC_RPC_ALERT */
} MDExceptionMac;
/* For (MDException).exception_flags. Breakpad minidump extension for Mac OS X
* support. Based on Darwin/Mac OS X' mach/ppc/exception.h and
* mach/i386/exception.h. This is what Mac OS X calls a "code". */
typedef enum {
/* With MD_EXCEPTION_BAD_ACCESS. These are relevant kern_return_t values
* from mach/kern_return.h. */
MD_EXCEPTION_CODE_MAC_INVALID_ADDRESS = 1,
/* KERN_INVALID_ADDRESS */
MD_EXCEPTION_CODE_MAC_PROTECTION_FAILURE = 2,
/* KERN_PROTECTION_FAILURE */
MD_EXCEPTION_CODE_MAC_NO_ACCESS = 8,
/* KERN_NO_ACCESS */
MD_EXCEPTION_CODE_MAC_MEMORY_FAILURE = 9,
/* KERN_MEMORY_FAILURE */
MD_EXCEPTION_CODE_MAC_MEMORY_ERROR = 10,
/* KERN_MEMORY_ERROR */
/* With MD_EXCEPTION_SOFTWARE */
MD_EXCEPTION_CODE_MAC_BAD_SYSCALL = 0x00010000, /* Mach SIGSYS */
MD_EXCEPTION_CODE_MAC_BAD_PIPE = 0x00010001, /* Mach SIGPIPE */
MD_EXCEPTION_CODE_MAC_ABORT = 0x00010002, /* Mach SIGABRT */
/* With MD_EXCEPTION_MAC_BAD_ACCESS on ppc */
MD_EXCEPTION_CODE_MAC_PPC_VM_PROT_READ = 0x0101,
/* EXC_PPC_VM_PROT_READ */
MD_EXCEPTION_CODE_MAC_PPC_BADSPACE = 0x0102,
/* EXC_PPC_BADSPACE */
MD_EXCEPTION_CODE_MAC_PPC_UNALIGNED = 0x0103,
/* EXC_PPC_UNALIGNED */
/* With MD_EXCEPTION_MAC_BAD_INSTRUCTION on ppc */
MD_EXCEPTION_CODE_MAC_PPC_INVALID_SYSCALL = 1,
/* EXC_PPC_INVALID_SYSCALL */
MD_EXCEPTION_CODE_MAC_PPC_UNIMPLEMENTED_INSTRUCTION = 2,
/* EXC_PPC_UNIPL_INST */
MD_EXCEPTION_CODE_MAC_PPC_PRIVILEGED_INSTRUCTION = 3,
/* EXC_PPC_PRIVINST */
MD_EXCEPTION_CODE_MAC_PPC_PRIVILEGED_REGISTER = 4,
/* EXC_PPC_PRIVREG */
MD_EXCEPTION_CODE_MAC_PPC_TRACE = 5,
/* EXC_PPC_TRACE */
MD_EXCEPTION_CODE_MAC_PPC_PERFORMANCE_MONITOR = 6,
/* EXC_PPC_PERFMON */
/* With MD_EXCEPTION_MAC_ARITHMETIC on ppc */
MD_EXCEPTION_CODE_MAC_PPC_OVERFLOW = 1,
/* EXC_PPC_OVERFLOW */
MD_EXCEPTION_CODE_MAC_PPC_ZERO_DIVIDE = 2,
/* EXC_PPC_ZERO_DIVIDE */
MD_EXCEPTION_CODE_MAC_PPC_FLOAT_INEXACT = 3,
/* EXC_FLT_INEXACT */
MD_EXCEPTION_CODE_MAC_PPC_FLOAT_ZERO_DIVIDE = 4,
/* EXC_PPC_FLT_ZERO_DIVIDE */
MD_EXCEPTION_CODE_MAC_PPC_FLOAT_UNDERFLOW = 5,
/* EXC_PPC_FLT_UNDERFLOW */
MD_EXCEPTION_CODE_MAC_PPC_FLOAT_OVERFLOW = 6,
/* EXC_PPC_FLT_OVERFLOW */
MD_EXCEPTION_CODE_MAC_PPC_FLOAT_NOT_A_NUMBER = 7,
/* EXC_PPC_FLT_NOT_A_NUMBER */
/* With MD_EXCEPTION_MAC_EMULATION on ppc */
MD_EXCEPTION_CODE_MAC_PPC_NO_EMULATION = 8,
/* EXC_PPC_NOEMULATION */
MD_EXCEPTION_CODE_MAC_PPC_ALTIVEC_ASSIST = 9,
/* EXC_PPC_ALTIVECASSIST */
/* With MD_EXCEPTION_MAC_SOFTWARE on ppc */
MD_EXCEPTION_CODE_MAC_PPC_TRAP = 0x00000001, /* EXC_PPC_TRAP */
MD_EXCEPTION_CODE_MAC_PPC_MIGRATE = 0x00010100, /* EXC_PPC_MIGRATE */
/* With MD_EXCEPTION_MAC_BREAKPOINT on ppc */
MD_EXCEPTION_CODE_MAC_PPC_BREAKPOINT = 1, /* EXC_PPC_BREAKPOINT */
/* With MD_EXCEPTION_MAC_BAD_INSTRUCTION on x86, see also x86 interrupt
* values below. */
MD_EXCEPTION_CODE_MAC_X86_INVALID_OPERATION = 1, /* EXC_I386_INVOP */
/* With MD_EXCEPTION_MAC_ARITHMETIC on x86 */
MD_EXCEPTION_CODE_MAC_X86_DIV = 1, /* EXC_I386_DIV */
MD_EXCEPTION_CODE_MAC_X86_INTO = 2, /* EXC_I386_INTO */
MD_EXCEPTION_CODE_MAC_X86_NOEXT = 3, /* EXC_I386_NOEXT */
MD_EXCEPTION_CODE_MAC_X86_EXTOVR = 4, /* EXC_I386_EXTOVR */
MD_EXCEPTION_CODE_MAC_X86_EXTERR = 5, /* EXC_I386_EXTERR */
MD_EXCEPTION_CODE_MAC_X86_EMERR = 6, /* EXC_I386_EMERR */
MD_EXCEPTION_CODE_MAC_X86_BOUND = 7, /* EXC_I386_BOUND */
MD_EXCEPTION_CODE_MAC_X86_SSEEXTERR = 8, /* EXC_I386_SSEEXTERR */
/* With MD_EXCEPTION_MAC_BREAKPOINT on x86 */
MD_EXCEPTION_CODE_MAC_X86_SGL = 1, /* EXC_I386_SGL */
MD_EXCEPTION_CODE_MAC_X86_BPT = 2, /* EXC_I386_BPT */
/* With MD_EXCEPTION_MAC_BAD_INSTRUCTION on x86. These are the raw
* x86 interrupt codes. Most of these are mapped to other Mach
* exceptions and codes, are handled, or should not occur in user space.
* A few of these will do occur with MD_EXCEPTION_MAC_BAD_INSTRUCTION. */
/* EXC_I386_DIVERR = 0: mapped to EXC_ARITHMETIC/EXC_I386_DIV */
/* EXC_I386_SGLSTP = 1: mapped to EXC_BREAKPOINT/EXC_I386_SGL */
/* EXC_I386_NMIFLT = 2: should not occur in user space */
/* EXC_I386_BPTFLT = 3: mapped to EXC_BREAKPOINT/EXC_I386_BPT */
/* EXC_I386_INTOFLT = 4: mapped to EXC_ARITHMETIC/EXC_I386_INTO */
/* EXC_I386_BOUNDFLT = 5: mapped to EXC_ARITHMETIC/EXC_I386_BOUND */
/* EXC_I386_INVOPFLT = 6: mapped to EXC_BAD_INSTRUCTION/EXC_I386_INVOP */
/* EXC_I386_NOEXTFLT = 7: should be handled by the kernel */
/* EXC_I386_DBLFLT = 8: should be handled (if possible) by the kernel */
/* EXC_I386_EXTOVRFLT = 9: mapped to EXC_BAD_ACCESS/(PROT_READ|PROT_EXEC) */
MD_EXCEPTION_CODE_MAC_X86_INVALID_TASK_STATE_SEGMENT = 10,
/* EXC_INVTSSFLT */
MD_EXCEPTION_CODE_MAC_X86_SEGMENT_NOT_PRESENT = 11,
/* EXC_SEGNPFLT */
MD_EXCEPTION_CODE_MAC_X86_STACK_FAULT = 12,
/* EXC_STKFLT */
MD_EXCEPTION_CODE_MAC_X86_GENERAL_PROTECTION_FAULT = 13,
/* EXC_GPFLT */
/* EXC_I386_PGFLT = 14: should not occur in user space */
/* EXC_I386_EXTERRFLT = 16: mapped to EXC_ARITHMETIC/EXC_I386_EXTERR */
MD_EXCEPTION_CODE_MAC_X86_ALIGNMENT_FAULT = 17
/* EXC_ALIGNFLT (for vector operations) */
/* EXC_I386_ENOEXTFLT = 32: should be handled by the kernel */
/* EXC_I386_ENDPERR = 33: should not occur */
} MDExceptionCodeMac;
/* For (MDException).exception_code. These values come from bits/signum.h.
*/
typedef enum {
MD_EXCEPTION_CODE_LIN_SIGHUP = 1, /* Hangup (POSIX) */
MD_EXCEPTION_CODE_LIN_SIGINT = 2, /* Interrupt (ANSI) */
MD_EXCEPTION_CODE_LIN_SIGQUIT = 3, /* Quit (POSIX) */
MD_EXCEPTION_CODE_LIN_SIGILL = 4, /* Illegal instruction (ANSI) */
MD_EXCEPTION_CODE_LIN_SIGTRAP = 5, /* Trace trap (POSIX) */
MD_EXCEPTION_CODE_LIN_SIGABRT = 6, /* Abort (ANSI) */
MD_EXCEPTION_CODE_LIN_SIGBUS = 7, /* BUS error (4.2 BSD) */
MD_EXCEPTION_CODE_LIN_SIGFPE = 8, /* Floating-point exception (ANSI) */
MD_EXCEPTION_CODE_LIN_SIGKILL = 9, /* Kill, unblockable (POSIX) */
MD_EXCEPTION_CODE_LIN_SIGUSR1 = 10, /* User-defined signal 1 (POSIX). */
MD_EXCEPTION_CODE_LIN_SIGSEGV = 11, /* Segmentation violation (ANSI) */
MD_EXCEPTION_CODE_LIN_SIGUSR2 = 12, /* User-defined signal 2 (POSIX) */
MD_EXCEPTION_CODE_LIN_SIGPIPE = 13, /* Broken pipe (POSIX) */
MD_EXCEPTION_CODE_LIN_SIGALRM = 14, /* Alarm clock (POSIX) */
MD_EXCEPTION_CODE_LIN_SIGTERM = 15, /* Termination (ANSI) */
MD_EXCEPTION_CODE_LIN_SIGSTKFLT = 16, /* Stack faultd */
MD_EXCEPTION_CODE_LIN_SIGCHLD = 17, /* Child status has changed (POSIX) */
MD_EXCEPTION_CODE_LIN_SIGCONT = 18, /* Continue (POSIX) */
MD_EXCEPTION_CODE_LIN_SIGSTOP = 19, /* Stop, unblockable (POSIX) */
MD_EXCEPTION_CODE_LIN_SIGTSTP = 20, /* Keyboard stop (POSIX) */
MD_EXCEPTION_CODE_LIN_SIGTTIN = 21, /* Background read from tty (POSIX) */
MD_EXCEPTION_CODE_LIN_SIGTTOU = 22, /* Background write to tty (POSIX) */
MD_EXCEPTION_CODE_LIN_SIGURG = 23,
/* Urgent condition on socket (4.2 BSD) */
MD_EXCEPTION_CODE_LIN_SIGXCPU = 24, /* CPU limit exceeded (4.2 BSD) */
MD_EXCEPTION_CODE_LIN_SIGXFSZ = 25,
/* File size limit exceeded (4.2 BSD) */
MD_EXCEPTION_CODE_LIN_SIGVTALRM = 26, /* Virtual alarm clock (4.2 BSD) */
MD_EXCEPTION_CODE_LIN_SIGPROF = 27, /* Profiling alarm clock (4.2 BSD) */
MD_EXCEPTION_CODE_LIN_SIGWINCH = 28, /* Window size change (4.3 BSD, Sun) */
MD_EXCEPTION_CODE_LIN_SIGIO = 29, /* I/O now possible (4.2 BSD) */
MD_EXCEPTION_CODE_LIN_SIGPWR = 30, /* Power failure restart (System V) */
MD_EXCEPTION_CODE_LIN_SIGSYS = 31 /* Bad system call */
} MDExceptionCodeLinux;
/* For (MDException).exception_code. These values come from sys/iso/signal_iso.h
*/
typedef enum {
MD_EXCEPTION_CODE_SOL_SIGHUP = 1, /* Hangup */
MD_EXCEPTION_CODE_SOL_SIGINT = 2, /* interrupt (rubout) */
MD_EXCEPTION_CODE_SOL_SIGQUIT = 3, /* quit (ASCII FS) */
MD_EXCEPTION_CODE_SOL_SIGILL = 4, /* illegal instruction (not reset when caught) */
MD_EXCEPTION_CODE_SOL_SIGTRAP = 5, /* trace trap (not reset when caught) */
MD_EXCEPTION_CODE_SOL_SIGIOT = 6, /* IOT instruction */
MD_EXCEPTION_CODE_SOL_SIGABRT = 6, /* used by abort, replace SIGIOT in the future */
MD_EXCEPTION_CODE_SOL_SIGEMT = 7, /* EMT instruction */
MD_EXCEPTION_CODE_SOL_SIGFPE = 8, /* floating point exception */
MD_EXCEPTION_CODE_SOL_SIGKILL = 9, /* kill (cannot be caught or ignored) */
MD_EXCEPTION_CODE_SOL_SIGBUS = 10, /* bus error */
MD_EXCEPTION_CODE_SOL_SIGSEGV = 11, /* segmentation violation */
MD_EXCEPTION_CODE_SOL_SIGSYS = 12, /* bad argument to system call */
MD_EXCEPTION_CODE_SOL_SIGPIPE = 13, /* write on a pipe with no one to read it */
MD_EXCEPTION_CODE_SOL_SIGALRM = 14, /* alarm clock */
MD_EXCEPTION_CODE_SOL_SIGTERM = 15, /* software termination signal from kill */
MD_EXCEPTION_CODE_SOL_SIGUSR1 = 16, /* user defined signal 1 */
MD_EXCEPTION_CODE_SOL_SIGUSR2 = 17, /* user defined signal 2 */
MD_EXCEPTION_CODE_SOL_SIGCLD = 18, /* child status change */
MD_EXCEPTION_CODE_SOL_SIGCHLD = 18, /* child status change alias (POSIX) */
MD_EXCEPTION_CODE_SOL_SIGPWR = 19, /* power-fail restart */
MD_EXCEPTION_CODE_SOL_SIGWINCH = 20, /* window size change */
MD_EXCEPTION_CODE_SOL_SIGURG = 21, /* urgent socket condition */
MD_EXCEPTION_CODE_SOL_SIGPOLL = 22, /* pollable event occured */
MD_EXCEPTION_CODE_SOL_SIGIO = 22, /* socket I/O possible (SIGPOLL alias) */
MD_EXCEPTION_CODE_SOL_SIGSTOP = 23, /* stop (cannot be caught or ignored) */
MD_EXCEPTION_CODE_SOL_SIGTSTP = 24, /* user stop requested from tty */
MD_EXCEPTION_CODE_SOL_SIGCONT = 25, /* stopped process has been continued */
MD_EXCEPTION_CODE_SOL_SIGTTIN = 26, /* background tty read attempted */
MD_EXCEPTION_CODE_SOL_SIGTTOU = 27, /* background tty write attempted */
MD_EXCEPTION_CODE_SOL_SIGVTALRM = 28, /* virtual timer expired */
MD_EXCEPTION_CODE_SOL_SIGPROF = 29, /* profiling timer expired */
MD_EXCEPTION_CODE_SOL_SIGXCPU = 30, /* exceeded cpu limit */
MD_EXCEPTION_CODE_SOL_SIGXFSZ = 31, /* exceeded file size limit */
MD_EXCEPTION_CODE_SOL_SIGWAITING = 32, /* reserved signal no longer used by threading code */
MD_EXCEPTION_CODE_SOL_SIGLWP = 33, /* reserved signal no longer used by threading code */
MD_EXCEPTION_CODE_SOL_SIGFREEZE = 34, /* special signal used by CPR */
MD_EXCEPTION_CODE_SOL_SIGTHAW = 35, /* special signal used by CPR */
MD_EXCEPTION_CODE_SOL_SIGCANCEL = 36, /* reserved signal for thread cancellation */
MD_EXCEPTION_CODE_SOL_SIGLOST = 37, /* resource lost (eg, record-lock lost) */
MD_EXCEPTION_CODE_SOL_SIGXRES = 38, /* resource control exceeded */
MD_EXCEPTION_CODE_SOL_SIGJVM1 = 39, /* reserved signal for Java Virtual Machine */
MD_EXCEPTION_CODE_SOL_SIGJVM2 = 40 /* reserved signal for Java Virtual Machine */
} MDExceptionCodeSolaris;
#include "minidump_exception_win32.h"
#include "minidump_exception_mac.h"
#include "minidump_exception_linux.h"
#include "minidump_exception_solaris.h"
typedef struct {
u_int32_t thread_id; /* Thread in which the exception

Просмотреть файл

@ -79,6 +79,7 @@
#ifndef GOOGLE_BREAKPAD_PROCESSOR_MINIDUMP_H__
#define GOOGLE_BREAKPAD_PROCESSOR_MINIDUMP_H__
#include <unistd.h>
#include <map>
#include <string>

Просмотреть файл

@ -128,9 +128,9 @@ struct StackFrameSPARC : public StackFrame {
// to be confirmed
enum ContextValidity {
CONTEXT_VALID_NONE = 0,
CONTEXT_VALID_PC = 0 << 0,
CONTEXT_VALID_SP = 0 << 1,
CONTEXT_VALID_FP = 0 << 2,
CONTEXT_VALID_PC = 1 << 0,
CONTEXT_VALID_SP = 1 << 1,
CONTEXT_VALID_FP = 1 << 2,
CONTEXT_VALID_ALL = -1
};

Просмотреть файл

@ -80,7 +80,7 @@ std::string HexString(u_int32_t number) {
std::string HexString(u_int64_t number) {
char buffer[19];
snprintf(buffer, sizeof(buffer), "0x%llx", number);
snprintf(buffer, sizeof(buffer), "0x%" PRIx64, number);
return std::string(buffer);
}

Просмотреть файл

@ -850,7 +850,7 @@ void MinidumpContext::Print() {
for (unsigned int fpr_index = 0;
fpr_index < MD_FLOATINGSAVEAREA_PPC_FPR_COUNT;
++fpr_index) {
printf(" float_save.fpregs[%2d] = 0x%llx\n",
printf(" float_save.fpregs[%2d] = 0x%" PRIx64 "\n",
fpr_index, context_ppc->float_save.fpregs[fpr_index]);
}
printf(" float_save.fpscr = 0x%x\n",
@ -858,7 +858,7 @@ void MinidumpContext::Print() {
// TODO(mmentovai): print the 128-bit quantities in
// context_ppc->vector_save. This isn't done yet because printf
// doesn't support 128-bit quantities, and printing them using
// %llx as two 64-bit quantities requires knowledge of the CPU's
// PRIx64 as two 64-bit quantities requires knowledge of the CPU's
// byte ordering.
printf(" vector_save.save_vrvalid = 0x%x\n",
context_ppc->vector_save.save_vrvalid);
@ -870,17 +870,17 @@ void MinidumpContext::Print() {
case MD_CONTEXT_AMD64: {
const MDRawContextAMD64* context_amd64 = GetContextAMD64();
printf("MDRawContextAMD64\n");
printf(" p1_home = 0x%llx\n",
printf(" p1_home = 0x%" PRIx64 "\n",
context_amd64->p1_home);
printf(" p2_home = 0x%llx\n",
printf(" p2_home = 0x%" PRIx64 "\n",
context_amd64->p2_home);
printf(" p3_home = 0x%llx\n",
printf(" p3_home = 0x%" PRIx64 "\n",
context_amd64->p3_home);
printf(" p4_home = 0x%llx\n",
printf(" p4_home = 0x%" PRIx64 "\n",
context_amd64->p4_home);
printf(" p5_home = 0x%llx\n",
printf(" p5_home = 0x%" PRIx64 "\n",
context_amd64->p5_home);
printf(" p6_home = 0x%llx\n",
printf(" p6_home = 0x%" PRIx64 "\n",
context_amd64->p6_home);
printf(" context_flags = 0x%x\n",
context_amd64->context_flags);
@ -893,29 +893,29 @@ void MinidumpContext::Print() {
printf(" gs = 0x%x\n", context_amd64->gs);
printf(" ss = 0x%x\n", context_amd64->ss);
printf(" eflags = 0x%x\n", context_amd64->eflags);
printf(" dr0 = 0x%llx\n", context_amd64->dr0);
printf(" dr1 = 0x%llx\n", context_amd64->dr1);
printf(" dr2 = 0x%llx\n", context_amd64->dr2);
printf(" dr3 = 0x%llx\n", context_amd64->dr3);
printf(" dr6 = 0x%llx\n", context_amd64->dr6);
printf(" dr7 = 0x%llx\n", context_amd64->dr7);
printf(" rax = 0x%llx\n", context_amd64->rax);
printf(" rcx = 0x%llx\n", context_amd64->rcx);
printf(" rdx = 0x%llx\n", context_amd64->rdx);
printf(" rbx = 0x%llx\n", context_amd64->rbx);
printf(" rsp = 0x%llx\n", context_amd64->rsp);
printf(" rbp = 0x%llx\n", context_amd64->rbp);
printf(" rsi = 0x%llx\n", context_amd64->rsi);
printf(" rdi = 0x%llx\n", context_amd64->rdi);
printf(" r8 = 0x%llx\n", context_amd64->r8);
printf(" r9 = 0x%llx\n", context_amd64->r9);
printf(" r10 = 0x%llx\n", context_amd64->r10);
printf(" r11 = 0x%llx\n", context_amd64->r11);
printf(" r12 = 0x%llx\n", context_amd64->r12);
printf(" r13 = 0x%llx\n", context_amd64->r13);
printf(" r14 = 0x%llx\n", context_amd64->r14);
printf(" r15 = 0x%llx\n", context_amd64->r15);
printf(" rip = 0x%llx\n", context_amd64->rip);
printf(" dr0 = 0x%" PRIx64 "\n", context_amd64->dr0);
printf(" dr1 = 0x%" PRIx64 "\n", context_amd64->dr1);
printf(" dr2 = 0x%" PRIx64 "\n", context_amd64->dr2);
printf(" dr3 = 0x%" PRIx64 "\n", context_amd64->dr3);
printf(" dr6 = 0x%" PRIx64 "\n", context_amd64->dr6);
printf(" dr7 = 0x%" PRIx64 "\n", context_amd64->dr7);
printf(" rax = 0x%" PRIx64 "\n", context_amd64->rax);
printf(" rcx = 0x%" PRIx64 "\n", context_amd64->rcx);
printf(" rdx = 0x%" PRIx64 "\n", context_amd64->rdx);
printf(" rbx = 0x%" PRIx64 "\n", context_amd64->rbx);
printf(" rsp = 0x%" PRIx64 "\n", context_amd64->rsp);
printf(" rbp = 0x%" PRIx64 "\n", context_amd64->rbp);
printf(" rsi = 0x%" PRIx64 "\n", context_amd64->rsi);
printf(" rdi = 0x%" PRIx64 "\n", context_amd64->rdi);
printf(" r8 = 0x%" PRIx64 "\n", context_amd64->r8);
printf(" r9 = 0x%" PRIx64 "\n", context_amd64->r9);
printf(" r10 = 0x%" PRIx64 "\n", context_amd64->r10);
printf(" r11 = 0x%" PRIx64 "\n", context_amd64->r11);
printf(" r12 = 0x%" PRIx64 "\n", context_amd64->r12);
printf(" r13 = 0x%" PRIx64 "\n", context_amd64->r13);
printf(" r14 = 0x%" PRIx64 "\n", context_amd64->r14);
printf(" r15 = 0x%" PRIx64 "\n", context_amd64->r15);
printf(" rip = 0x%" PRIx64 "\n", context_amd64->rip);
//TODO: print xmm, vector, debug registers
printf("\n");
break;
@ -929,25 +929,25 @@ void MinidumpContext::Print() {
for (unsigned int g_r_index = 0;
g_r_index < MD_CONTEXT_SPARC_GPR_COUNT;
++g_r_index) {
printf(" g_r[%2d] = 0x%llx\n",
printf(" g_r[%2d] = 0x%" PRIx64 "\n",
g_r_index, context_sparc->g_r[g_r_index]);
}
printf(" ccr = 0x%llx\n", context_sparc->ccr);
printf(" pc = 0x%llx\n", context_sparc->pc);
printf(" npc = 0x%llx\n", context_sparc->npc);
printf(" y = 0x%llx\n", context_sparc->y);
printf(" asi = 0x%llx\n", context_sparc->asi);
printf(" fprs = 0x%llx\n", context_sparc->fprs);
printf(" ccr = 0x%" PRIx64 "\n", context_sparc->ccr);
printf(" pc = 0x%" PRIx64 "\n", context_sparc->pc);
printf(" npc = 0x%" PRIx64 "\n", context_sparc->npc);
printf(" y = 0x%" PRIx64 "\n", context_sparc->y);
printf(" asi = 0x%" PRIx64 "\n", context_sparc->asi);
printf(" fprs = 0x%" PRIx64 "\n", context_sparc->fprs);
for (unsigned int fpr_index = 0;
fpr_index < MD_FLOATINGSAVEAREA_SPARC_FPR_COUNT;
++fpr_index) {
printf(" float_save.regs[%2d] = 0x%llx\n",
printf(" float_save.regs[%2d] = 0x%" PRIx64 "\n",
fpr_index, context_sparc->float_save.regs[fpr_index]);
}
printf(" float_save.filler = 0x%llx\n",
printf(" float_save.filler = 0x%" PRIx64 "\n",
context_sparc->float_save.filler);
printf(" float_save.fsr = 0x%llx\n",
printf(" float_save.fsr = 0x%" PRIx64 "\n",
context_sparc->float_save.fsr);
break;
}
@ -1265,8 +1265,8 @@ void MinidumpThread::Print() {
printf(" suspend_count = %d\n", thread_.suspend_count);
printf(" priority_class = 0x%x\n", thread_.priority_class);
printf(" priority = 0x%x\n", thread_.priority);
printf(" teb = 0x%llx\n", thread_.teb);
printf(" stack.start_of_memory_range = 0x%llx\n",
printf(" teb = 0x%" PRIx64 "\n", thread_.teb);
printf(" stack.start_of_memory_range = 0x%" PRIx64 "\n",
thread_.stack.start_of_memory_range);
printf(" stack.memory.data_size = 0x%x\n",
thread_.stack.memory.data_size);
@ -2050,7 +2050,7 @@ void MinidumpModule::Print() {
}
printf("MDRawModule\n");
printf(" base_of_image = 0x%llx\n",
printf(" base_of_image = 0x%" PRIx64 "\n",
module_.base_of_image);
printf(" size_of_image = 0x%x\n",
module_.size_of_image);
@ -2602,7 +2602,7 @@ void MinidumpMemoryList::Print() {
MDMemoryDescriptor* descriptor = &(*descriptors_)[region_index];
printf("region[%d]\n", region_index);
printf("MDMemoryDescriptor\n");
printf(" start_of_memory_range = 0x%llx\n",
printf(" start_of_memory_range = 0x%" PRIx64 "\n",
descriptor->start_of_memory_range);
printf(" memory.data_size = 0x%x\n", descriptor->memory.data_size);
printf(" memory.rva = 0x%x\n", descriptor->memory.rva);
@ -2732,16 +2732,16 @@ void MinidumpException::Print() {
exception_.exception_record.exception_code);
printf(" exception_record.exception_flags = 0x%x\n",
exception_.exception_record.exception_flags);
printf(" exception_record.exception_record = 0x%llx\n",
printf(" exception_record.exception_record = 0x%" PRIx64 "\n",
exception_.exception_record.exception_record);
printf(" exception_record.exception_address = 0x%llx\n",
printf(" exception_record.exception_address = 0x%" PRIx64 "\n",
exception_.exception_record.exception_address);
printf(" exception_record.number_parameters = %d\n",
exception_.exception_record.number_parameters);
for (unsigned int parameterIndex = 0;
parameterIndex < exception_.exception_record.number_parameters;
++parameterIndex) {
printf(" exception_record.exception_information[%2d] = 0x%llx\n",
printf(" exception_record.exception_information[%2d] = 0x%" PRIx64 "\n",
parameterIndex,
exception_.exception_record.exception_information[parameterIndex]);
}
@ -2885,6 +2885,10 @@ string MinidumpSystemInfo::GetCPU() {
cpu = "ppc";
break;
case MD_CPU_ARCHITECTURE_SPARC:
cpu = "sparc";
break;
default:
BPLOG(ERROR) << "MinidumpSystemInfo unknown CPU for architecture " <<
HexString(system_info_.processor_architecture);
@ -3439,7 +3443,7 @@ void Minidump::Print() {
strftime(timestr, 20, "%Y-%m-%d %H:%M:%S", &timestruct);
printf(" time_date_stamp = 0x%x %s\n", header_.time_date_stamp,
timestr);
printf(" flags = 0x%llx\n", header_.flags);
printf(" flags = 0x%" PRIx64 "\n", header_.flags);
printf("\n");
for (unsigned int stream_index = 0;

Просмотреть файл

@ -121,18 +121,19 @@ static void PrintStack(const CallStack *stack, const string &cpu) {
printf("!%s", frame->function_name.c_str());
if (!frame->source_file_name.empty()) {
string source_file = PathnameStripper::File(frame->source_file_name);
printf(" [%s : %d + 0x%llx]", source_file.c_str(),
frame->source_line,
frame->instruction -
frame->source_line_base);
printf(" [%s : %d + 0x%" PRIx64 "]",
source_file.c_str(),
frame->source_line,
frame->instruction - frame->source_line_base);
} else {
printf(" + 0x%llx", frame->instruction - frame->function_base);
printf(" + 0x%" PRIx64, frame->instruction - frame->function_base);
}
} else {
printf(" + 0x%llx", frame->instruction - frame->module->base_address());
printf(" + 0x%" PRIx64,
frame->instruction - frame->module->base_address());
}
} else {
printf("0x%llx", frame->instruction);
printf("0x%" PRIx64, frame->instruction);
}
int sequence = 0;
@ -213,35 +214,36 @@ static void PrintStackMachineReadable(int thread_num, const CallStack *stack) {
printf("%c%s", kOutputSeparator,
StripSeparator(frame->function_name).c_str());
if (!frame->source_file_name.empty()) {
printf("%c%s%c%d%c0x%llx", kOutputSeparator,
StripSeparator(frame->source_file_name)
.c_str(),
kOutputSeparator,
frame->source_line,
kOutputSeparator,
frame->instruction -
frame->source_line_base);
printf("%c%s%c%d%c0x%" PRIx64,
kOutputSeparator,
StripSeparator(frame->source_file_name).c_str(),
kOutputSeparator,
frame->source_line,
kOutputSeparator,
frame->instruction - frame->source_line_base);
} else {
printf("%c%c%c0x%llx", kOutputSeparator, // empty source file
kOutputSeparator, // empty source line
kOutputSeparator,
frame->instruction - frame->function_base);
printf("%c%c%c0x%" PRIx64,
kOutputSeparator, // empty source file
kOutputSeparator, // empty source line
kOutputSeparator,
frame->instruction - frame->function_base);
}
} else {
printf("%c%c%c%c0x%llx", kOutputSeparator, // empty function name
kOutputSeparator, // empty source file
kOutputSeparator, // empty source line
kOutputSeparator,
frame->instruction -
frame->module->base_address());
printf("%c%c%c%c0x%" PRIx64,
kOutputSeparator, // empty function name
kOutputSeparator, // empty source file
kOutputSeparator, // empty source line
kOutputSeparator,
frame->instruction - frame->module->base_address());
}
} else {
// the printf before this prints a trailing separator for module name
printf("%c%c%c%c0x%llx", kOutputSeparator, // empty function name
kOutputSeparator, // empty source file
kOutputSeparator, // empty source line
kOutputSeparator,
frame->instruction);
printf("%c%c%c%c0x%" PRIx64,
kOutputSeparator, // empty function name
kOutputSeparator, // empty source file
kOutputSeparator, // empty source line
kOutputSeparator,
frame->instruction);
}
printf("\n");
}
@ -266,7 +268,7 @@ static void PrintModules(const CodeModules *modules) {
++module_sequence) {
const CodeModule *module = modules->GetModuleAtSequence(module_sequence);
u_int64_t base_address = module->base_address();
printf("0x%08llx - 0x%08llx %s %s%s\n",
printf("0x%08" PRIx64 " - 0x%08" PRIx64 " %s %s%s\n",
base_address, base_address + module->size() - 1,
PathnameStripper::File(module->code_file()).c_str(),
module->version().empty() ? "???" : module->version().c_str(),
@ -296,7 +298,7 @@ static void PrintModulesMachineReadable(const CodeModules *modules) {
++module_sequence) {
const CodeModule *module = modules->GetModuleAtSequence(module_sequence);
u_int64_t base_address = module->base_address();
printf("Module%c%s%c%s%c%s%c%s%c0x%08llx%c0x%08llx%c%d\n",
printf("Module%c%s%c%s%c%s%c%s%c0x%08" PRIx64 "%c0x%08" PRIx64 "%c%d\n",
kOutputSeparator,
StripSeparator(PathnameStripper::File(module->code_file())).c_str(),
kOutputSeparator, StripSeparator(module->version()).c_str(),
@ -331,7 +333,7 @@ static void PrintProcessState(const ProcessState& process_state) {
// Print crash information.
if (process_state.crashed()) {
printf("Crash reason: %s\n", process_state.crash_reason().c_str());
printf("Crash address: 0x%llx\n", process_state.crash_address());
printf("Crash address: 0x%" PRIx64 "\n", process_state.crash_address());
} else {
printf("No crash\n");
}
@ -384,7 +386,7 @@ static void PrintProcessStateMachineReadable(const ProcessState& process_state)
// Crash|{Crash Reason}|{Crash Address}|{Crashed Thread}
printf("Crash%c", kOutputSeparator);
if (process_state.crashed()) {
printf("%s%c0x%llx%c",
printf("%s%c0x%" PRIx64 "%c",
StripSeparator(process_state.crash_reason()).c_str(),
kOutputSeparator, process_state.crash_address(), kOutputSeparator);
} else {

Просмотреть файл

@ -345,7 +345,7 @@ static unsigned int CountCallerFrames() {
frame_index < stack.frames()->size();
++frame_index) {
StackFrame *frame = stack.frames()->at(frame_index);
printf("frame %-3d instruction = 0x%08llx",
printf("frame %-3d instruction = 0x%08" PRIx64,
frame_index, frame->instruction);
#if defined(__i386__)
StackFrameX86 *frame_x86 = reinterpret_cast<StackFrameX86*>(frame);